Steve Reinhardt | ba2eae5 | 2006-05-22 14:29:33 -0400 | [diff] [blame] | 1 | /* |
| 2 | * tcp.h |
| 3 | * |
| 4 | * Transmission Control Protocol (RFC 793). |
| 5 | * |
| 6 | * Copyright (c) 2000 Dug Song <dugsong@monkey.org> |
| 7 | * |
| 8 | * $Id: tcp.h,v 1.17 2004/02/23 10:02:11 dugsong Exp $ |
| 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 */ |