12632SN/A/*
22632SN/A * tcp.h
32632SN/A *
42632SN/A * Transmission Control Protocol (RFC 793).
52632SN/A *
62632SN/A * Copyright (c) 2000 Dug Song <dugsong@monkey.org>
72632SN/A *
82632SN/A * $Id: tcp.h,v 1.17 2004/02/23 10:02:11 dugsong Exp $
92632SN/A */
102632SN/A
112632SN/A#ifndef DNET_TCP_H
122632SN/A#define DNET_TCP_H
132632SN/A
142632SN/A#define TCP_HDR_LEN	20		/* base TCP header length */
152632SN/A#define TCP_OPT_LEN	2		/* base TCP option length */
162632SN/A#define TCP_OPT_LEN_MAX	40
172632SN/A#define TCP_HDR_LEN_MAX	(TCP_HDR_LEN + TCP_OPT_LEN_MAX)
182632SN/A
192632SN/A#ifndef __GNUC__
202632SN/A# define __attribute__(x)
212632SN/A# pragma pack(1)
222632SN/A#endif
232632SN/A
242632SN/A/*
252632SN/A * TCP header, without options
262632SN/A */
272632SN/Astruct tcp_hdr {
282632SN/A        uint16_t	th_sport;	/* source port */
292632SN/A        uint16_t	th_dport;	/* destination port */
302632SN/A        uint32_t	th_seq;		/* sequence number */
312632SN/A        uint32_t	th_ack;		/* acknowledgment number */
322632SN/A#if DNET_BYTESEX == DNET_BIG_ENDIAN
332632SN/A        uint8_t		th_off:4,	/* data offset */
342632SN/A                        th_x2:4;	/* (unused) */
352632SN/A#elif DNET_BYTESEX == DNET_LIL_ENDIAN
362632SN/A        uint8_t		th_x2:4,
372632SN/A                        th_off:4;
382632SN/A#else
392632SN/A# error "need to include <dnet.h>"
402632SN/A#endif
412632SN/A        uint8_t		th_flags;	/* control flags */
422632SN/A        uint16_t	th_win;		/* window */
432632SN/A        uint16_t	th_sum;		/* checksum */
442632SN/A        uint16_t	th_urp;		/* urgent pointer */
452632SN/A};
462632SN/A
472632SN/A/*
482632SN/A * TCP control flags (th_flags)
492632SN/A */
502632SN/A#define TH_FIN		0x01		/* end of data */
512632SN/A#define TH_SYN		0x02		/* synchronize sequence numbers */
522632SN/A#define TH_RST		0x04		/* reset connection */
532632SN/A#define TH_PUSH		0x08		/* push */
542632SN/A#define TH_ACK		0x10		/* acknowledgment number set */
552632SN/A#define TH_URG		0x20		/* urgent pointer set */
562632SN/A#define TH_ECE		0x40		/* ECN echo, RFC 3168 */
572632SN/A#define TH_CWR		0x80		/* congestion window reduced */
582632SN/A
592632SN/A#define TCP_PORT_MAX	65535		/* maximum port */
602632SN/A#define TCP_WIN_MAX	65535		/* maximum (unscaled) window */
612632SN/A
622632SN/A/*
632632SN/A * Sequence number comparison macros
642632SN/A */
652632SN/A#define TCP_SEQ_LT(a,b)		((int)((a)-(b)) < 0)
662632SN/A#define TCP_SEQ_LEQ(a,b)	((int)((a)-(b)) <= 0)
672632SN/A#define TCP_SEQ_GT(a,b)		((int)((a)-(b)) > 0)
682632SN/A#define TCP_SEQ_GEQ(a,b)	((int)((a)-(b)) >= 0)
692632SN/A
702632SN/A/*
712632SN/A * TCP FSM states
722632SN/A */
732632SN/A#define TCP_STATE_CLOSED	0	/* closed */
742632SN/A#define TCP_STATE_LISTEN	1	/* listening from connection */
752632SN/A#define TCP_STATE_SYN_SENT	2	/* active, have sent SYN */
762632SN/A#define TCP_STATE_SYN_RECEIVED	3	/* have sent and received SYN */
772632SN/A
782632SN/A#define TCP_STATE_ESTABLISHED	4	/* established */
792632SN/A#define TCP_STATE_CLOSE_WAIT	5	/* rcvd FIN, waiting for close */
802632SN/A
812632SN/A#define TCP_STATE_FIN_WAIT_1	6	/* have closed, sent FIN */
822632SN/A#define TCP_STATE_CLOSING	7	/* closed xchd FIN, await FIN-ACK */
832632SN/A#define TCP_STATE_LAST_ACK	8	/* had FIN and close, await FIN-ACK */
842632SN/A
852632SN/A#define TCP_STATE_FIN_WAIT_2	9	/* have closed, FIN is acked */
862632SN/A#define TCP_STATE_TIME_WAIT	10	/* in 2*MSL quiet wait after close */
872632SN/A#define TCP_STATE_MAX		11
882632SN/A
892632SN/A/*
902632SN/A * Options (opt_type) - http://www.iana.org/assignments/tcp-parameters
912632SN/A */
922632SN/A#define TCP_OPT_EOL		0	/* end of option list */
932632SN/A#define TCP_OPT_NOP		1	/* no operation */
942632SN/A#define TCP_OPT_MSS		2	/* maximum segment size */
952632SN/A#define TCP_OPT_WSCALE		3	/* window scale factor, RFC 1072 */
962632SN/A#define TCP_OPT_SACKOK		4	/* SACK permitted, RFC 2018 */
972632SN/A#define TCP_OPT_SACK		5	/* SACK, RFC 2018 */
982632SN/A#define TCP_OPT_ECHO		6	/* echo (obsolete), RFC 1072 */
992632SN/A#define TCP_OPT_ECHOREPLY	7	/* echo reply (obsolete), RFC 1072 */
1002632SN/A#define TCP_OPT_TIMESTAMP	8	/* timestamp, RFC 1323 */
1012632SN/A#define TCP_OPT_POCONN		9	/* partial order conn, RFC 1693 */
1022632SN/A#define TCP_OPT_POSVC		10	/* partial order service, RFC 1693 */
1032632SN/A#define TCP_OPT_CC		11	/* connection count, RFC 1644 */
1042632SN/A#define TCP_OPT_CCNEW		12	/* CC.NEW, RFC 1644 */
1052632SN/A#define TCP_OPT_CCECHO		13	/* CC.ECHO, RFC 1644 */
1062632SN/A#define TCP_OPT_ALTSUM		14	/* alt checksum request, RFC 1146 */
1072632SN/A#define TCP_OPT_ALTSUMDATA	15	/* alt checksum data, RFC 1146 */
1082632SN/A#define TCP_OPT_SKEETER		16	/* Skeeter */
1092632SN/A#define TCP_OPT_BUBBA		17	/* Bubba */
1102632SN/A#define TCP_OPT_TRAILSUM	18	/* trailer checksum */
1112632SN/A#define TCP_OPT_MD5		19	/* MD5 signature, RFC 2385 */
1122632SN/A#define TCP_OPT_SCPS		20	/* SCPS capabilities */
1132632SN/A#define TCP_OPT_SNACK		21	/* selective negative acks */
1142632SN/A#define TCP_OPT_REC		22	/* record boundaries */
1152632SN/A#define TCP_OPT_CORRUPT		23	/* corruption experienced */
1162632SN/A#define TCP_OPT_SNAP		24	/* SNAP */
1172632SN/A#define TCP_OPT_TCPCOMP		26	/* TCP compression filter */
1182632SN/A#define TCP_OPT_MAX		27
1192632SN/A
1202632SN/A#define TCP_OPT_TYPEONLY(type)	\
1212632SN/A        ((type) == TCP_OPT_EOL || (type) == TCP_OPT_NOP)
1222632SN/A
1232632SN/A/*
1242632SN/A * TCP option (following TCP header)
1252632SN/A */
1262632SN/Astruct tcp_opt {
1272632SN/A        uint8_t		opt_type;	/* option type */
1282632SN/A        uint8_t		opt_len;	/* option length >= TCP_OPT_LEN */
1292632SN/A        union tcp_opt_data {
1302632SN/A                uint16_t	mss;		/* TCP_OPT_MSS */
1312632SN/A                uint8_t		wscale;		/* TCP_OPT_WSCALE */
1322632SN/A                uint16_t	sack[19];	/* TCP_OPT_SACK */
1332632SN/A                uint32_t	echo;		/* TCP_OPT_ECHO{REPLY} */
1342632SN/A                uint32_t	timestamp[2];	/* TCP_OPT_TIMESTAMP */
1352632SN/A                uint32_t	cc;		/* TCP_OPT_CC{NEW,ECHO} */
1362632SN/A                uint8_t		cksum;		/* TCP_OPT_ALTSUM */
1372632SN/A                uint8_t		md5[16];	/* TCP_OPT_MD5 */
1382632SN/A                uint8_t		data8[TCP_OPT_LEN_MAX - TCP_OPT_LEN];
1392632SN/A        } opt_data;
1402632SN/A} __attribute__((__packed__));
1412632SN/A
1422632SN/A#ifndef __GNUC__
1432632SN/A# pragma pack()
1442632SN/A#endif
1452632SN/A
1462632SN/A#define tcp_pack_hdr(hdr, sport, dport, seq, ack, flags, win, urp) do {	\
1472632SN/A        struct tcp_hdr *tcp_pack_p = (struct tcp_hdr *)(hdr);		\
1482632SN/A        tcp_pack_p->th_sport = htons(sport);				\
1492632SN/A        tcp_pack_p->th_dport = htons(dport);				\
1502632SN/A        tcp_pack_p->th_seq = htonl(seq);				\
1512632SN/A        tcp_pack_p->th_ack = htonl(ack);				\
1522632SN/A        tcp_pack_p->th_x2 = 0; tcp_pack_p->th_off = 5;			\
1532632SN/A        tcp_pack_p->th_flags = flags;					\
1542632SN/A        tcp_pack_p->th_win = htons(win);				\
1552632SN/A        tcp_pack_p->th_urp = htons(urp);				\
1562632SN/A} while (0)
1572632SN/A
1582632SN/A#endif /* DNET_TCP_H */
159