1 /*
2  * tcp.h
3  *
4  * Transmission Control Protocol (RFC 793).
5  *
6  * Copyright (c) 2000 Dug Song <dugsong@monkey.org>
7  *
8  * $Id$
9  */
10 
11 #ifndef DNET_TCP_H
12 #define DNET_TCP_H
13 
14 #define TCP_HDR_LEN	20		/* base TCP header length */
15 #define TCP_OPT_LEN	2		/* base TCP option length */
16 #define TCP_OPT_LEN_MAX	40
17 #define TCP_HDR_LEN_MAX	(TCP_HDR_LEN + TCP_OPT_LEN_MAX)
18 
19 #ifndef __GNUC__
20 # define __attribute__(x)
21 # pragma pack(1)
22 #endif
23 
24 /*
25  * TCP header, without options
26  */
27 struct tcp_hdr {
28 	uint16_t	th_sport;	/* source port */
29 	uint16_t	th_dport;	/* destination port */
30 	uint32_t	th_seq;		/* sequence number */
31 	uint32_t	th_ack;		/* acknowledgment number */
32 #if DNET_BYTESEX == DNET_BIG_ENDIAN
33 	uint8_t		th_off:4,	/* data offset */
34 			th_x2:4;	/* (unused) */
35 #elif DNET_BYTESEX == DNET_LIL_ENDIAN
36 	uint8_t		th_x2:4,
37 			th_off:4;
38 #else
39 # error "need to include <dnet.h>"
40 #endif
41 	uint8_t		th_flags;	/* control flags */
42 	uint16_t	th_win;		/* window */
43 	uint16_t	th_sum;		/* checksum */
44 	uint16_t	th_urp;		/* urgent pointer */
45 };
46 
47 /*
48  * TCP control flags (th_flags)
49  */
50 #define TH_FIN		0x01		/* end of data */
51 #define TH_SYN		0x02		/* synchronize sequence numbers */
52 #define TH_RST		0x04		/* reset connection */
53 #define TH_PUSH		0x08		/* push */
54 #define TH_ACK		0x10		/* acknowledgment number set */
55 #define TH_URG		0x20		/* urgent pointer set */
56 #define TH_ECE		0x40		/* ECN echo, RFC 3168 */
57 #define TH_CWR		0x80		/* congestion window reduced */
58 
59 #define TCP_PORT_MAX	65535		/* maximum port */
60 #define TCP_WIN_MAX	65535		/* maximum (unscaled) window */
61 
62 /*
63  * Sequence number comparison macros
64  */
65 #define TCP_SEQ_LT(a,b)		((int)((a)-(b)) < 0)
66 #define TCP_SEQ_LEQ(a,b)	((int)((a)-(b)) <= 0)
67 #define TCP_SEQ_GT(a,b)		((int)((a)-(b)) > 0)
68 #define TCP_SEQ_GEQ(a,b)	((int)((a)-(b)) >= 0)
69 
70 /*
71  * TCP FSM states
72  */
73 #define TCP_STATE_CLOSED	0	/* closed */
74 #define TCP_STATE_LISTEN	1	/* listening from connection */
75 #define TCP_STATE_SYN_SENT	2	/* active, have sent SYN */
76 #define TCP_STATE_SYN_RECEIVED	3	/* have sent and received SYN */
77 
78 #define TCP_STATE_ESTABLISHED	4	/* established */
79 #define TCP_STATE_CLOSE_WAIT	5	/* rcvd FIN, waiting for close */
80 
81 #define TCP_STATE_FIN_WAIT_1	6	/* have closed, sent FIN */
82 #define TCP_STATE_CLOSING	7	/* closed xchd FIN, await FIN-ACK */
83 #define TCP_STATE_LAST_ACK	8	/* had FIN and close, await FIN-ACK */
84 
85 #define TCP_STATE_FIN_WAIT_2	9	/* have closed, FIN is acked */
86 #define TCP_STATE_TIME_WAIT	10	/* in 2*MSL quiet wait after close */
87 #define TCP_STATE_MAX		11
88 
89 /*
90  * Options (opt_type) - http://www.iana.org/assignments/tcp-parameters
91  */
92 #define TCP_OPT_EOL		0	/* end of option list */
93 #define TCP_OPT_NOP		1	/* no operation */
94 #define TCP_OPT_MSS		2	/* maximum segment size */
95 #define TCP_OPT_WSCALE		3	/* window scale factor, RFC 1072 */
96 #define TCP_OPT_SACKOK		4	/* SACK permitted, RFC 2018 */
97 #define TCP_OPT_SACK		5	/* SACK, RFC 2018 */
98 #define TCP_OPT_ECHO		6	/* echo (obsolete), RFC 1072 */
99 #define TCP_OPT_ECHOREPLY	7	/* echo reply (obsolete), RFC 1072 */
100 #define TCP_OPT_TIMESTAMP	8	/* timestamp, RFC 1323 */
101 #define TCP_OPT_POCONN		9	/* partial order conn, RFC 1693 */
102 #define TCP_OPT_POSVC		10	/* partial order service, RFC 1693 */
103 #define TCP_OPT_CC		11	/* connection count, RFC 1644 */
104 #define TCP_OPT_CCNEW		12	/* CC.NEW, RFC 1644 */
105 #define TCP_OPT_CCECHO		13	/* CC.ECHO, RFC 1644 */
106 #define TCP_OPT_ALTSUM		14	/* alt checksum request, RFC 1146 */
107 #define TCP_OPT_ALTSUMDATA	15	/* alt checksum data, RFC 1146 */
108 #define TCP_OPT_SKEETER		16	/* Skeeter */
109 #define TCP_OPT_BUBBA		17	/* Bubba */
110 #define TCP_OPT_TRAILSUM	18	/* trailer checksum */
111 #define TCP_OPT_MD5		19	/* MD5 signature, RFC 2385 */
112 #define TCP_OPT_SCPS		20	/* SCPS capabilities */
113 #define TCP_OPT_SNACK		21	/* selective negative acks */
114 #define TCP_OPT_REC		22	/* record boundaries */
115 #define TCP_OPT_CORRUPT		23	/* corruption experienced */
116 #define TCP_OPT_SNAP		24	/* SNAP */
117 #define TCP_OPT_TCPCOMP		26	/* TCP compression filter */
118 #define TCP_OPT_MAX		27
119 
120 #define TCP_OPT_TYPEONLY(type)	\
121 	((type) == TCP_OPT_EOL || (type) == TCP_OPT_NOP)
122 
123 /*
124  * TCP option (following TCP header)
125  */
126 struct tcp_opt {
127 	uint8_t		opt_type;	/* option type */
128 	uint8_t		opt_len;	/* option length >= TCP_OPT_LEN */
129 	union tcp_opt_data {
130 		uint16_t	mss;		/* TCP_OPT_MSS */
131 		uint8_t		wscale;		/* TCP_OPT_WSCALE */
132 		uint16_t	sack[19];	/* TCP_OPT_SACK */
133 		uint32_t	echo;		/* TCP_OPT_ECHO{REPLY} */
134 		uint32_t	timestamp[2];	/* TCP_OPT_TIMESTAMP */
135 		uint32_t	cc;		/* TCP_OPT_CC{NEW,ECHO} */
136 		uint8_t		cksum;		/* TCP_OPT_ALTSUM */
137 		uint8_t		md5[16];	/* TCP_OPT_MD5 */
138 		uint8_t		data8[TCP_OPT_LEN_MAX - TCP_OPT_LEN];
139 	} opt_data;
140 } __attribute__((__packed__));
141 
142 #ifndef __GNUC__
143 # pragma pack()
144 #endif
145 
146 #define tcp_pack_hdr(hdr, sport, dport, seq, ack, flags, win, urp) do {	\
147 	struct tcp_hdr *tcp_pack_p = (struct tcp_hdr *)(hdr);		\
148 	tcp_pack_p->th_sport = htons(sport);				\
149 	tcp_pack_p->th_dport = htons(dport);				\
150 	tcp_pack_p->th_seq = htonl(seq);				\
151 	tcp_pack_p->th_ack = htonl(ack);				\
152 	tcp_pack_p->th_x2 = 0; tcp_pack_p->th_off = 5;			\
153 	tcp_pack_p->th_flags = flags;					\
154 	tcp_pack_p->th_win = htons(win);				\
155 	tcp_pack_p->th_urp = htons(urp);				\
156 } while (0)
157 
158 #endif /* DNET_TCP_H */
159