1/* SPDX-License-Identifier: GPL-2.0 */ 2/* 3 * TCP Support with SACK for file transfer. 4 * 5 * Copyright 2017 Duncan Hare, All rights reserved. 6 */ 7 8#define TCP_ACTIVITY 127 /* Number of packets received */ 9 /* before console progress mark */ 10/** 11 * struct ip_tcp_hdr - IP and TCP header 12 * @ip_hl_v: header length and version 13 * @ip_tos: type of service 14 * @ip_len: total length 15 * @ip_id: identification 16 * @ip_off: fragment offset field 17 * @ip_ttl: time to live 18 * @ip_p: protocol 19 * @ip_sum: checksum 20 * @ip_src: Source IP address 21 * @ip_dst: Destination IP address 22 * @tcp_src: TCP source port 23 * @tcp_dst: TCP destination port 24 * @tcp_seq: TCP sequence number 25 * @tcp_ack: TCP Acknowledgment number 26 * @tcp_hlen: 4 bits TCP header Length/4, 4 bits reserved, 2 more bits reserved 27 * @tcp_flag: flags of TCP 28 * @tcp_win: TCP windows size 29 * @tcp_xsum: Checksum 30 * @tcp_ugr: Pointer to urgent data 31 */ 32struct ip_tcp_hdr { 33 u8 ip_hl_v; 34 u8 ip_tos; 35 u16 ip_len; 36 u16 ip_id; 37 u16 ip_off; 38 u8 ip_ttl; 39 u8 ip_p; 40 u16 ip_sum; 41 struct in_addr ip_src; 42 struct in_addr ip_dst; 43 u16 tcp_src; 44 u16 tcp_dst; 45 u32 tcp_seq; 46 u32 tcp_ack; 47 u8 tcp_hlen; 48 u8 tcp_flags; 49 u16 tcp_win; 50 u16 tcp_xsum; 51 u16 tcp_ugr; 52} __packed; 53 54#define IP_TCP_HDR_SIZE (sizeof(struct ip_tcp_hdr)) 55#define TCP_HDR_SIZE (IP_TCP_HDR_SIZE - IP_HDR_SIZE) 56 57#define TCP_DATA 0x00 /* Data Packet - internal use only */ 58#define TCP_FIN 0x01 /* Finish flag */ 59#define TCP_SYN 0x02 /* Synch (start) flag */ 60#define TCP_RST 0x04 /* reset flag */ 61#define TCP_PUSH 0x08 /* Push - Notify app */ 62#define TCP_ACK 0x10 /* Acknowledgment of data received */ 63#define TCP_URG 0x20 /* Urgent */ 64#define TCP_ECE 0x40 /* Congestion control */ 65#define TCP_CWR 0x80 /* Congestion Control */ 66 67/* 68 * TCP header options, Seq, MSS, and SACK 69 */ 70 71#define TCP_SACK 32 /* Number of packets analyzed */ 72 /* on leading edge of stream */ 73 74#define TCP_O_END 0x00 /* End of option list */ 75#define TCP_1_NOP 0x01 /* Single padding NOP */ 76#define TCP_O_NOP 0x01010101 /* NOPs pad to 32 bit boundary */ 77#define TCP_O_MSS 0x02 /* MSS Size option */ 78#define TCP_O_SCL 0x03 /* Window Scale option */ 79#define TCP_P_SACK 0x04 /* SACK permitted */ 80#define TCP_V_SACK 0x05 /* SACK values */ 81#define TCP_O_TS 0x08 /* Timestamp option */ 82#define TCP_OPT_LEN_2 0x02 83#define TCP_OPT_LEN_3 0x03 84#define TCP_OPT_LEN_4 0x04 85#define TCP_OPT_LEN_6 0x06 86#define TCP_OPT_LEN_8 0x08 87#define TCP_OPT_LEN_A 0x0a /* Timestamp Length */ 88#define TCP_MSS 1460 /* Max segment size */ 89#define TCP_SCALE 0x01 /* Scale */ 90 91/** 92 * struct tcp_mss - TCP option structure for MSS (Max segment size) 93 * @kind: Field ID 94 * @len: Field length 95 * @mss: Segment size value 96 */ 97struct tcp_mss { 98 u8 kind; 99 u8 len; 100 u16 mss; 101} __packed; 102 103/** 104 * struct tcp_scale - TCP option structure for Windows scale 105 * @kind: Field ID 106 * @len: Field length 107 * @scale: windows shift value used for networks with many hops. 108 * Typically 4 or more hops 109 */ 110struct tcp_scale { 111 u8 kind; 112 u8 len; 113 u8 scale; 114} __packed; 115 116/** 117 * struct tcp_sack_p - TCP option structure for SACK permitted 118 * @kind: Field ID 119 * @len: Field length 120 */ 121struct tcp_sack_p { 122 u8 kind; 123 u8 len; 124} __packed; 125 126/** 127 * struct sack_edges - structure for SACK edges 128 * @l: Left edge of stream 129 * @r: right edge of stream 130 */ 131struct sack_edges { 132 u32 l; 133 u32 r; 134} __packed; 135 136#define TCP_SACK_SIZE (sizeof(struct sack_edges)) 137 138/* 139 * A TCP stream has holes when packets are missing or disordered. 140 * A hill is the inverse of a hole, and is data received. 141 * TCP received hills (a sequence of data), and inferrs Holes 142 * from the "hills" or packets received. 143 */ 144 145#define TCP_SACK_HILLS 4 146 147/** 148 * struct tcp_sack_v - TCP option structure for SACK 149 * @kind: Field ID 150 * @len: Field length 151 * @hill: L & R window edges 152 */ 153struct tcp_sack_v { 154 u8 kind; 155 u8 len; 156 struct sack_edges hill[TCP_SACK_HILLS]; 157} __packed; 158 159/** 160 * struct tcp_t_opt - TCP option structure for time stamps 161 * @kind: Field ID 162 * @len: Field length 163 * @t_snd: Sender timestamp 164 * @t_rcv: Receiver timestamp 165 */ 166struct tcp_t_opt { 167 u8 kind; 168 u8 len; 169 u32 t_snd; 170 u32 t_rcv; 171} __packed; 172 173#define TCP_TSOPT_SIZE (sizeof(struct tcp_t_opt)) 174 175/* 176 * ip tcp structure with options 177 */ 178 179/** 180 * struct ip_tcp_hdr_o - IP + TCP header + TCP options 181 * @hdr: IP + TCP header 182 * @mss: TCP MSS Option 183 * @scale: TCP Windows Scale Option 184 * @sack_p: TCP Sack-Permitted Option 185 * @t_opt: TCP Timestamp Option 186 * @end: end of options 187 */ 188struct ip_tcp_hdr_o { 189 struct ip_tcp_hdr hdr; 190 struct tcp_mss mss; 191 struct tcp_scale scale; 192 struct tcp_sack_p sack_p; 193 struct tcp_t_opt t_opt; 194 u8 end; 195} __packed; 196 197#define IP_TCP_O_SIZE (sizeof(struct ip_tcp_hdr_o)) 198 199/** 200 * struct ip_tcp_hdr_s - IP + TCP header + TCP options 201 * @hdr: IP + TCP header 202 * @t_opt: TCP Timestamp Option 203 * @sack_v: TCP SACK Option 204 * @end: end of options 205 */ 206struct ip_tcp_hdr_s { 207 struct ip_tcp_hdr hdr; 208 struct tcp_t_opt t_opt; 209 struct tcp_sack_v sack_v; 210 u8 end; 211} __packed; 212 213#define IP_TCP_SACK_SIZE (sizeof(struct ip_tcp_hdr_s)) 214 215/* 216 * TCP pseudo header definitions 217 */ 218#define PSEUDO_PAD_SIZE 8 219 220/** 221 * struct pseudo_hdr - Pseudo Header 222 * @padding: pseudo hdr size = ip_tcp hdr size 223 * @p_src: Source IP address 224 * @p_dst: Destination IP address 225 * @rsvd: reserved 226 * @p: protocol 227 * @len: length of header 228 */ 229struct pseudo_hdr { 230 u8 padding[PSEUDO_PAD_SIZE]; 231 struct in_addr p_src; 232 struct in_addr p_dst; 233 u8 rsvd; 234 u8 p; 235 u16 len; 236} __packed; 237 238#define PSEUDO_HDR_SIZE (sizeof(struct pseudo_hdr)) - PSEUDO_PAD_SIZE 239 240/** 241 * union tcp_build_pkt - union for building TCP/IP packet. 242 * @ph: pseudo header 243 * @ip: IP and TCP header plus TCP options 244 * @sack: IP and TCP header plus SACK options 245 * @raw: buffer 246 * 247 * Build Pseudo header in packed buffer 248 * first, calculate TCP checksum, then build IP header in packed buffer. 249 * 250 */ 251union tcp_build_pkt { 252 struct pseudo_hdr ph; 253 struct ip_tcp_hdr_o ip; 254 struct ip_tcp_hdr_s sack; 255 uchar raw[1600]; 256} __packed; 257 258/** 259 * enum tcp_state - TCP State machine states for connection 260 * @TCP_CLOSED: Need to send SYN to connect 261 * @TCP_SYN_SENT: Trying to connect, waiting for SYN ACK 262 * @TCP_SYN_RECEIVED: Initial SYN received, waiting for ACK 263 * @TCP_ESTABLISHED: both server & client have a connection 264 * @TCP_CLOSE_WAIT: Rec FIN, passed to app for FIN, ACK rsp 265 * @TCP_CLOSING: Rec FIN, sent FIN, ACK waiting for ACK 266 * @TCP_FIN_WAIT_1: Sent FIN waiting for response 267 * @TCP_FIN_WAIT_2: Rec ACK from FIN sent, waiting for FIN 268 */ 269enum tcp_state { 270 TCP_CLOSED, 271 TCP_SYN_SENT, 272 TCP_SYN_RECEIVED, 273 TCP_ESTABLISHED, 274 TCP_CLOSE_WAIT, 275 TCP_CLOSING, 276 TCP_FIN_WAIT_1, 277 TCP_FIN_WAIT_2 278}; 279 280enum tcp_state tcp_get_tcp_state(void); 281void tcp_set_tcp_state(enum tcp_state new_state); 282int tcp_set_tcp_header(uchar *pkt, int dport, int sport, int payload_len, 283 u8 action, u32 tcp_seq_num, u32 tcp_ack_num); 284 285/** 286 * rxhand_tcp() - An incoming packet handler. 287 * @pkt: pointer to the application packet 288 * @dport: destination TCP port 289 * @sip: source IP address 290 * @sport: source TCP port 291 * @tcp_seq_num: TCP sequential number 292 * @tcp_ack_num: TCP acknowledgment number 293 * @action: TCP action (SYN, ACK, FIN, etc) 294 * @len: packet length 295 */ 296typedef void rxhand_tcp(uchar *pkt, u16 dport, 297 struct in_addr sip, u16 sport, 298 u32 tcp_seq_num, u32 tcp_ack_num, 299 u8 action, unsigned int len); 300void tcp_set_tcp_handler(rxhand_tcp *f); 301 302void rxhand_tcp_f(union tcp_build_pkt *b, unsigned int len); 303 304u16 tcp_set_pseudo_header(uchar *pkt, struct in_addr src, struct in_addr dest, 305 int tcp_len, int pkt_len); 306