]> Git Repo - J-u-boot.git/blame - net/tcp.c
Merge tag 'u-boot-imx-master-20250127' of https://gitlab.denx.de/u-boot/custodians...
[J-u-boot.git] / net / tcp.c
CommitLineData
a3bf193b
YCLP
1// SPDX-License-Identifier: GPL-2.0
2/*
3 * Copyright 2017 Duncan Hare, all rights reserved.
4 */
5
6/*
7 * General Desription:
8 *
9 * TCP support for the wget command, for fast file downloading.
10 *
11 * HTTP/TCP Receiver:
12 *
13 * Prerequisites: - own ethernet address
14 * - own IP address
15 * - Server IP address
16 * - Server with TCP
17 * - TCP application (eg wget)
18 * Next Step HTTPS?
19 */
a3bf193b
YCLP
20#include <command.h>
21#include <console.h>
22#include <env_internal.h>
23#include <errno.h>
24#include <net.h>
25#include <net/tcp.h>
26
bf962de9
MK
27/*
28 * The start sequence number increment for the two sequently created
29 * connections within the same timer tick. This number must be:
30 * - prime (to increase the time before the same number will be generated)
31 * - larger than typical MTU (to avoid similar numbers for two sequently
32 * created connections)
33 */
34#define TCP_START_SEQ_INC 2153 /* just large prime number */
35
36#define TCP_SEND_RETRY 3
37#define TCP_SEND_TIMEOUT 2000UL
38#define TCP_RX_INACTIVE_TIMEOUT 30000UL
0eff9208
MK
39#if PKTBUFSRX != 0
40 #define TCP_RCV_WND_SIZE (PKTBUFSRX * TCP_MSS)
41#else
42 #define TCP_RCV_WND_SIZE (4 * TCP_MSS)
43#endif
bf962de9
MK
44
45#define TCP_PACKET_OK 0
46#define TCP_PACKET_DROP 1
47
ddedfe1c 48static struct tcp_stream tcp_stream;
bf962de9
MK
49
50static int (*tcp_stream_on_create)(struct tcp_stream *tcp);
a3bf193b 51
a3bf193b
YCLP
52/*
53 * TCP lengths are stored as a rounded up number of 32 bit words.
54 * Add 3 to length round up, rounded, then divided into the
55 * length in 32 bit words.
56 */
57#define LEN_B_TO_DW(x) ((x) >> 2)
58#define ROUND_TCPHDR_LEN(x) (LEN_B_TO_DW((x) + 3))
bf962de9 59#define ROUND_TCPHDR_BYTES(x) (((x) + 3) & ~3)
a3bf193b
YCLP
60#define SHIFT_TO_TCPHDRLEN_FIELD(x) ((x) << 4)
61#define GET_TCP_HDR_LEN_IN_BYTES(x) ((x) >> 2)
62
2b177498
MK
63#define RANDOM_PORT_START 1024
64#define RANDOM_PORT_RANGE 0x4000
65
66/**
67 * random_port() - make port a little random (1024-17407)
68 *
69 * Return: random port number from 1024 to 17407
70 *
71 * This keeps the math somewhat trivial to compute, and seems to work with
72 * all supported protocols/clients/servers
73 */
74static uint random_port(void)
75{
76 return RANDOM_PORT_START + (get_timer(0) % RANDOM_PORT_RANGE);
77}
78
40d3d655
MK
79static inline s32 tcp_seq_cmp(u32 a, u32 b)
80{
81 return (s32)(a - b);
82}
83
bf962de9
MK
84static inline u32 tcp_get_start_seq(void)
85{
86 static u32 tcp_seq_inc;
87 u32 tcp_seq;
88
89 tcp_seq = (get_timer(0) & 0xffffffff) + tcp_seq_inc;
90 tcp_seq_inc += TCP_START_SEQ_INC;
91
92 return tcp_seq;
93}
94
95static inline ulong msec_to_ticks(ulong msec)
96{
97 return msec * CONFIG_SYS_HZ / 1000;
98}
99
a3bf193b 100/**
2b177498 101 * tcp_stream_get_state() - get TCP stream state
ddedfe1c 102 * @tcp: tcp stream
a3bf193b 103 *
ddedfe1c 104 * Return: TCP stream state
a3bf193b 105 */
2b177498 106enum tcp_state tcp_stream_get_state(struct tcp_stream *tcp)
a3bf193b 107{
ddedfe1c 108 return tcp->state;
a3bf193b
YCLP
109}
110
111/**
2b177498 112 * tcp_stream_set_state() - set TCP stream state
ddedfe1c 113 * @tcp: tcp stream
a3bf193b
YCLP
114 * @new_state: new TCP state
115 */
2b177498
MK
116static void tcp_stream_set_state(struct tcp_stream *tcp,
117 enum tcp_state new_state)
a3bf193b 118{
ddedfe1c
MK
119 tcp->state = new_state;
120}
121
bf962de9
MK
122/**
123 * tcp_stream_get_status() - get TCP stream status
124 * @tcp: tcp stream
125 *
126 * Return: TCP stream status
127 */
128enum tcp_status tcp_stream_get_status(struct tcp_stream *tcp)
2b177498 129{
bf962de9 130 return tcp->status;
2b177498
MK
131}
132
bf962de9
MK
133/**
134 * tcp_stream_set_status() - set TCP stream state
135 * @tcp: tcp stream
136 * @new_satus: new TCP stream status
137 */
138static void tcp_stream_set_status(struct tcp_stream *tcp,
139 enum tcp_status new_status)
2b177498 140{
bf962de9 141 tcp->status = new_status;
2b177498
MK
142}
143
bf962de9 144void tcp_stream_restart_rx_timer(struct tcp_stream *tcp)
2b177498 145{
bf962de9
MK
146 tcp->time_last_rx = get_timer(0);
147}
2b177498 148
bf962de9
MK
149static void tcp_stream_init(struct tcp_stream *tcp,
150 struct in_addr rhost, u16 rport, u16 lport)
151{
2b177498
MK
152 memset(tcp, 0, sizeof(struct tcp_stream));
153 tcp->rhost.s_addr = rhost.s_addr;
154 tcp->rport = rport;
155 tcp->lport = lport;
156 tcp->state = TCP_CLOSED;
157 tcp->lost.len = TCP_OPT_LEN_2;
bf962de9
MK
158 tcp->rcv_wnd = TCP_RCV_WND_SIZE;
159 tcp->max_retry_count = TCP_SEND_RETRY;
160 tcp->initial_timeout = TCP_SEND_TIMEOUT;
161 tcp->rx_inactiv_timeout = TCP_RX_INACTIVE_TIMEOUT;
162 tcp_stream_restart_rx_timer(tcp);
163}
164
165static void tcp_stream_destroy(struct tcp_stream *tcp)
166{
167 if (tcp->on_closed)
168 tcp->on_closed(tcp);
169 memset(tcp, 0, sizeof(struct tcp_stream));
170}
171
172void tcp_init(void)
173{
174 static int initialized;
175 struct tcp_stream *tcp = &tcp_stream;
176
177 tcp_stream_on_create = NULL;
178 if (!initialized) {
179 initialized = 1;
180 memset(tcp, 0, sizeof(struct tcp_stream));
181 }
182
183 tcp_stream_set_state(tcp, TCP_CLOSED);
184 tcp_stream_set_status(tcp, TCP_ERR_RST);
185 tcp_stream_destroy(tcp);
186}
187
188void tcp_stream_set_on_create_handler(int (*on_create)(struct tcp_stream *))
189{
190 tcp_stream_on_create = on_create;
191}
192
193static struct tcp_stream *tcp_stream_add(struct in_addr rhost,
194 u16 rport, u16 lport)
195{
196 struct tcp_stream *tcp = &tcp_stream;
197
198 if (!tcp_stream_on_create ||
199 tcp->state != TCP_CLOSED)
200 return NULL;
201
202 tcp_stream_init(tcp, rhost, rport, lport);
203 if (!tcp_stream_on_create(tcp))
204 return NULL;
205
2b177498
MK
206 return tcp;
207}
208
209struct tcp_stream *tcp_stream_get(int is_new, struct in_addr rhost,
210 u16 rport, u16 lport)
ddedfe1c 211{
2b177498
MK
212 struct tcp_stream *tcp = &tcp_stream;
213
214 if (tcp->rhost.s_addr == rhost.s_addr &&
215 tcp->rport == rport &&
216 tcp->lport == lport)
217 return tcp;
218
bf962de9
MK
219 return is_new ? tcp_stream_add(rhost, rport, lport) : NULL;
220}
2b177498 221
bf962de9
MK
222void tcp_stream_put(struct tcp_stream *tcp)
223{
224 if (tcp->state == TCP_CLOSED)
225 tcp_stream_destroy(tcp);
a3bf193b
YCLP
226}
227
bf962de9 228u32 tcp_stream_rx_offs(struct tcp_stream *tcp)
a3bf193b 229{
bf962de9
MK
230 u32 ret;
231
232 switch (tcp->state) {
233 case TCP_CLOSED:
234 case TCP_SYN_SENT:
235 case TCP_SYN_RECEIVED:
236 return 0;
237 default:
238 break;
239 }
240
241 ret = tcp->rcv_nxt - tcp->irs - 1;
242 if (tcp->fin_rx && tcp->rcv_nxt == tcp->fin_rx_seq)
243 ret--;
244
245 return ret;
a3bf193b
YCLP
246}
247
bf962de9
MK
248u32 tcp_stream_tx_offs(struct tcp_stream *tcp)
249{
250 u32 ret;
251
252 switch (tcp->state) {
253 case TCP_CLOSED:
254 case TCP_SYN_SENT:
255 case TCP_SYN_RECEIVED:
256 return 0;
257 default:
258 break;
259 }
260
261 ret = tcp->snd_una - tcp->iss - 1;
262 if (tcp->fin_tx && tcp->snd_una == tcp->fin_tx_seq + 1)
263 ret--;
264
265 return ret;
266}
267
268static void tcp_stream_set_time_handler(struct tcp_stream *tcp, ulong msec,
269 void (*handler)(struct tcp_stream *))
270{
271 if (!msec) {
272 tcp->time_handler = NULL;
273 return;
274 }
275
276 tcp->time_handler = handler;
277 tcp->time_start = get_timer(0);
278 tcp->time_delta = msec_to_ticks(msec);
279}
280
281static void tcp_send_packet(struct tcp_stream *tcp, u8 action,
282 u32 tcp_seq_num, u32 tcp_ack_num, u32 tx_len)
283{
284 tcp->tx_packets++;
285 net_send_tcp_packet(tx_len, tcp->rhost, tcp->rport,
286 tcp->lport, action, tcp_seq_num,
287 tcp_ack_num);
288}
289
290static void tcp_send_repeat(struct tcp_stream *tcp)
291{
292 uchar *ptr;
293 u32 tcp_opts_size;
294 int ret;
295
296 if (!tcp->retry_cnt) {
297 puts("\nTCP: send retry counter exceeded\n");
298 tcp_send_packet(tcp, TCP_RST, tcp->retry_seq_num,
299 tcp->rcv_nxt, 0);
300 tcp_stream_set_status(tcp, TCP_ERR_TOUT);
301 tcp_stream_set_state(tcp, TCP_CLOSED);
302 tcp_stream_destroy(tcp);
303 return;
304 }
305 tcp->retry_cnt--;
306 tcp->retry_timeout += tcp->initial_timeout;
307
308 if (tcp->retry_tx_len > 0) {
309 tcp_opts_size = ROUND_TCPHDR_BYTES(TCP_TSOPT_SIZE +
310 tcp->lost.len);
311 ptr = net_tx_packet + net_eth_hdr_size() +
312 IP_TCP_HDR_SIZE + tcp_opts_size;
313
314 if (tcp->retry_tx_len > TCP_MSS - tcp_opts_size)
315 tcp->retry_tx_len = TCP_MSS - tcp_opts_size;
316
317 /* refill packet data */
318 ret = tcp->tx(tcp, tcp->retry_tx_offs, ptr, tcp->retry_tx_len);
319 if (ret < 0) {
320 puts("\nTCP: send failure\n");
321 tcp_send_packet(tcp, TCP_RST, tcp->retry_seq_num,
322 tcp->rcv_nxt, 0);
323 tcp_stream_set_status(tcp, TCP_ERR_IO);
324 tcp_stream_set_state(tcp, TCP_CLOSED);
325 tcp_stream_destroy(tcp);
326 return;
327 }
328 }
329 tcp_send_packet(tcp, tcp->retry_action, tcp->retry_seq_num,
330 tcp->rcv_nxt, tcp->retry_tx_len);
331
332 tcp_stream_set_time_handler(tcp, tcp->retry_timeout, tcp_send_repeat);
333}
334
335static void tcp_send_packet_with_retry(struct tcp_stream *tcp, u8 action,
336 u32 tcp_seq_num, u32 tx_len, u32 tx_offs)
337{
338 tcp->retry_cnt = tcp->max_retry_count;
339 tcp->retry_timeout = tcp->initial_timeout;
340 tcp->retry_action = action;
341 tcp->retry_seq_num = tcp_seq_num;
342 tcp->retry_tx_len = tx_len;
343 tcp->retry_tx_offs = tx_offs;
344
345 tcp_send_packet(tcp, action, tcp_seq_num, tcp->rcv_nxt, tx_len);
346 tcp_stream_set_time_handler(tcp, tcp->retry_timeout, tcp_send_repeat);
347}
348
349static inline u8 tcp_stream_fin_needed(struct tcp_stream *tcp, u32 tcp_seq_num)
350{
351 return (tcp->fin_tx && (tcp_seq_num == tcp->fin_tx_seq)) ? TCP_FIN : 0;
352}
353
354static void tcp_steam_tx_try(struct tcp_stream *tcp)
a3bf193b 355{
bf962de9
MK
356 uchar *ptr;
357 int tx_len;
358 u32 tx_offs, tcp_opts_size;
359
360 if (tcp->state != TCP_ESTABLISHED ||
361 tcp->time_handler ||
362 !tcp->tx)
363 return;
364
365 tcp_opts_size = ROUND_TCPHDR_BYTES(TCP_TSOPT_SIZE + tcp->lost.len);
366 tx_len = TCP_MSS - tcp_opts_size;
367 if (tcp->fin_tx) {
368 /* do not try to send beyonds FIN packet limits */
369 if (tcp_seq_cmp(tcp->snd_una, tcp->fin_tx_seq) >= 0)
370 return;
371
372 tx_len = tcp->fin_tx_seq - tcp->snd_una;
373 if (tx_len > TCP_MSS - tcp_opts_size)
374 tx_len = TCP_MSS - tcp_opts_size;
375 }
376
377 tx_offs = tcp_stream_tx_offs(tcp);
378 ptr = net_tx_packet + net_eth_hdr_size() +
379 IP_TCP_HDR_SIZE + tcp_opts_size;
380
381 /* fill packet data and adjust size */
382 tx_len = tcp->tx(tcp, tx_offs, ptr, tx_len);
383 if (tx_len < 0) {
384 puts("\nTCP: send failure\n");
385 tcp_send_packet(tcp, TCP_RST, tcp->retry_seq_num,
386 tcp->rcv_nxt, 0);
387 tcp_stream_set_status(tcp, TCP_ERR_IO);
388 tcp_stream_set_state(tcp, TCP_CLOSED);
389 tcp_stream_destroy(tcp);
390 return;
391 }
392 if (!tx_len)
393 return;
394
395 if (tcp_seq_cmp(tcp->snd_una + tx_len, tcp->snd_nxt) > 0)
396 tcp->snd_nxt = tcp->snd_una + tx_len;
397
398 tcp_send_packet_with_retry(tcp, TCP_ACK | TCP_PUSH,
399 tcp->snd_una, tx_len, tx_offs);
400}
401
402static void tcp_stream_poll(struct tcp_stream *tcp, ulong time)
403{
404 ulong delta;
405 void (*handler)(struct tcp_stream *tcp);
406
407 if (tcp->state == TCP_CLOSED)
408 return;
409
410 /* handle rx inactivity timeout */
411 delta = msec_to_ticks(tcp->rx_inactiv_timeout);
412 if (time - tcp->time_last_rx >= delta) {
413 puts("\nTCP: rx inactivity timeout exceeded\n");
414 tcp_stream_reset(tcp);
415 tcp_stream_set_status(tcp, TCP_ERR_TOUT);
416 tcp_stream_destroy(tcp);
417 return;
418 }
419
420 /* handle retransmit timeout */
421 if (tcp->time_handler &&
422 time - tcp->time_start >= tcp->time_delta) {
423 handler = tcp->time_handler;
424 tcp->time_handler = NULL;
425 handler(tcp);
426 }
427
428 tcp_steam_tx_try(tcp);
429}
430
431void tcp_streams_poll(void)
432{
433 ulong time;
434 struct tcp_stream *tcp;
435
436 time = get_timer(0);
437 tcp = &tcp_stream;
438 tcp_stream_poll(tcp, time);
a3bf193b
YCLP
439}
440
441/**
442 * tcp_set_pseudo_header() - set TCP pseudo header
443 * @pkt: the packet
444 * @src: source IP address
445 * @dest: destinaion IP address
446 * @tcp_len: tcp length
447 * @pkt_len: packet length
448 *
449 * Return: the checksum of the packet
450 */
451u16 tcp_set_pseudo_header(uchar *pkt, struct in_addr src, struct in_addr dest,
452 int tcp_len, int pkt_len)
453{
454 union tcp_build_pkt *b = (union tcp_build_pkt *)pkt;
455 int checksum_len;
456
457 /*
458 * Pseudo header
459 *
460 * Zero the byte after the last byte so that the header checksum
461 * will always work.
462 */
463 pkt[pkt_len] = 0;
464
465 net_copy_ip((void *)&b->ph.p_src, &src);
466 net_copy_ip((void *)&b->ph.p_dst, &dest);
467 b->ph.rsvd = 0;
468 b->ph.p = IPPROTO_TCP;
469 b->ph.len = htons(tcp_len);
470 checksum_len = tcp_len + PSEUDO_HDR_SIZE;
471
472 debug_cond(DEBUG_DEV_PKT,
473 "TCP Pesudo Header (to=%pI4, from=%pI4, Len=%d)\n",
474 &b->ph.p_dst, &b->ph.p_src, checksum_len);
475
476 return compute_ip_checksum(pkt + PSEUDO_PAD_SIZE, checksum_len);
477}
478
479/**
480 * net_set_ack_options() - set TCP options in acknowledge packets
ddedfe1c 481 * @tcp: tcp stream
a3bf193b
YCLP
482 * @b: the packet
483 *
484 * Return: TCP header length
485 */
ddedfe1c 486int net_set_ack_options(struct tcp_stream *tcp, union tcp_build_pkt *b)
a3bf193b
YCLP
487{
488 b->sack.hdr.tcp_hlen = SHIFT_TO_TCPHDRLEN_FIELD(LEN_B_TO_DW(TCP_HDR_SIZE));
489
490 b->sack.t_opt.kind = TCP_O_TS;
491 b->sack.t_opt.len = TCP_OPT_LEN_A;
ddedfe1c
MK
492 b->sack.t_opt.t_snd = htons(tcp->loc_timestamp);
493 b->sack.t_opt.t_rcv = tcp->rmt_timestamp;
a3bf193b
YCLP
494 b->sack.sack_v.kind = TCP_1_NOP;
495 b->sack.sack_v.len = 0;
496
497 if (IS_ENABLED(CONFIG_PROT_TCP_SACK)) {
ddedfe1c 498 if (tcp->lost.len > TCP_OPT_LEN_2) {
a3bf193b 499 debug_cond(DEBUG_DEV_PKT, "TCP ack opt lost.len %x\n",
ddedfe1c
MK
500 tcp->lost.len);
501 b->sack.sack_v.len = tcp->lost.len;
a3bf193b 502 b->sack.sack_v.kind = TCP_V_SACK;
ddedfe1c
MK
503 b->sack.sack_v.hill[0].l = htonl(tcp->lost.hill[0].l);
504 b->sack.sack_v.hill[0].r = htonl(tcp->lost.hill[0].r);
a3bf193b
YCLP
505
506 /*
507 * These SACK structures are initialized with NOPs to
508 * provide TCP header alignment padding. There are 4
509 * SACK structures used for both header padding and
510 * internally.
511 */
ddedfe1c
MK
512 b->sack.sack_v.hill[1].l = htonl(tcp->lost.hill[1].l);
513 b->sack.sack_v.hill[1].r = htonl(tcp->lost.hill[1].r);
514 b->sack.sack_v.hill[2].l = htonl(tcp->lost.hill[2].l);
515 b->sack.sack_v.hill[2].r = htonl(tcp->lost.hill[2].r);
a3bf193b
YCLP
516 b->sack.sack_v.hill[3].l = TCP_O_NOP;
517 b->sack.sack_v.hill[3].r = TCP_O_NOP;
518 }
519
520 b->sack.hdr.tcp_hlen = SHIFT_TO_TCPHDRLEN_FIELD(ROUND_TCPHDR_LEN(TCP_HDR_SIZE +
521 TCP_TSOPT_SIZE +
ddedfe1c 522 tcp->lost.len));
a3bf193b
YCLP
523 } else {
524 b->sack.sack_v.kind = 0;
525 b->sack.hdr.tcp_hlen = SHIFT_TO_TCPHDRLEN_FIELD(ROUND_TCPHDR_LEN(TCP_HDR_SIZE +
526 TCP_TSOPT_SIZE));
527 }
528
529 /*
530 * This returns the actual rounded up length of the
531 * TCP header to add to the total packet length
532 */
a3bf193b
YCLP
533 return GET_TCP_HDR_LEN_IN_BYTES(b->sack.hdr.tcp_hlen);
534}
535
536/**
ddedfe1c
MK
537 * net_set_syn_options() - set TCP options in SYN packets
538 * @tcp: tcp stream
a3bf193b
YCLP
539 * @b: the packet
540 */
ddedfe1c 541void net_set_syn_options(struct tcp_stream *tcp, union tcp_build_pkt *b)
a3bf193b
YCLP
542{
543 if (IS_ENABLED(CONFIG_PROT_TCP_SACK))
ddedfe1c 544 tcp->lost.len = 0;
a3bf193b
YCLP
545
546 b->ip.hdr.tcp_hlen = 0xa0;
547
548 b->ip.mss.kind = TCP_O_MSS;
549 b->ip.mss.len = TCP_OPT_LEN_4;
550 b->ip.mss.mss = htons(TCP_MSS);
551 b->ip.scale.kind = TCP_O_SCL;
552 b->ip.scale.scale = TCP_SCALE;
553 b->ip.scale.len = TCP_OPT_LEN_3;
554 if (IS_ENABLED(CONFIG_PROT_TCP_SACK)) {
555 b->ip.sack_p.kind = TCP_P_SACK;
556 b->ip.sack_p.len = TCP_OPT_LEN_2;
557 } else {
558 b->ip.sack_p.kind = TCP_1_NOP;
559 b->ip.sack_p.len = TCP_1_NOP;
560 }
561 b->ip.t_opt.kind = TCP_O_TS;
562 b->ip.t_opt.len = TCP_OPT_LEN_A;
ddedfe1c
MK
563 tcp->loc_timestamp = get_ticks();
564 tcp->rmt_timestamp = 0;
a3bf193b
YCLP
565 b->ip.t_opt.t_snd = 0;
566 b->ip.t_opt.t_rcv = 0;
567 b->ip.end = TCP_O_END;
568}
569
3a44b8ba
MK
570const char *tcpflags_to_str(char tcpflags, char *buf, int size)
571{
572 int i;
573 static const struct {
574 int bit;
575 const char *name;
576 } desc[] = {{TCP_RST, "RST"}, {TCP_SYN, "SYN"}, {TCP_PUSH, "PSH"},
577 {TCP_FIN, "FIN"}, {TCP_ACK, "ACK"}};
578
579 *buf = '\0';
580 for (i = 0; i < ARRAY_SIZE(desc); i++) {
581 if (!(tcpflags & desc[i].bit))
582 continue;
583
584 if (*buf)
585 strlcat(buf, ",", size);
586 strlcat(buf, desc[i].name, size);
587 }
588
589 return buf;
590}
591
2b177498 592int tcp_set_tcp_header(struct tcp_stream *tcp, uchar *pkt, int payload_len,
a3bf193b
YCLP
593 u8 action, u32 tcp_seq_num, u32 tcp_ack_num)
594{
595 union tcp_build_pkt *b = (union tcp_build_pkt *)pkt;
3a44b8ba 596 char buf[24];
a3bf193b
YCLP
597 int pkt_hdr_len;
598 int pkt_len;
599 int tcp_len;
600
601 /*
602 * Header: 5 32 bit words. 4 bits TCP header Length,
603 * 4 bits reserved options
604 */
605 b->ip.hdr.tcp_flags = action;
a3bf193b
YCLP
606 b->ip.hdr.tcp_hlen = SHIFT_TO_TCPHDRLEN_FIELD(LEN_B_TO_DW(TCP_HDR_SIZE));
607
608 switch (action) {
609 case TCP_SYN:
610 debug_cond(DEBUG_DEV_PKT,
3a44b8ba
MK
611 "TCP Hdr:%s (%pI4, %pI4, s=%u, a=%u)\n",
612 tcpflags_to_str(action, buf, sizeof(buf)),
613 &tcp->rhost, &net_ip, tcp_seq_num, tcp_ack_num);
ddedfe1c 614 net_set_syn_options(tcp, b);
a3bf193b 615 pkt_hdr_len = IP_TCP_O_SIZE;
a3bf193b 616 break;
08fb8da3
DM
617 case TCP_RST | TCP_ACK:
618 case TCP_RST:
619 debug_cond(DEBUG_DEV_PKT,
3a44b8ba
MK
620 "TCP Hdr:%s (%pI4, %pI4, s=%u, a=%u)\n",
621 tcpflags_to_str(action, buf, sizeof(buf)),
2b177498 622 &tcp->rhost, &net_ip, tcp_seq_num, tcp_ack_num);
3a44b8ba 623 pkt_hdr_len = IP_TCP_HDR_SIZE;
08fb8da3 624 break;
a3bf193b 625 default:
ddedfe1c 626 pkt_hdr_len = IP_HDR_SIZE + net_set_ack_options(tcp, b);
a3bf193b 627 debug_cond(DEBUG_DEV_PKT,
3a44b8ba
MK
628 "TCP Hdr:%s (%pI4, %pI4, s=%u, a=%u)\n",
629 tcpflags_to_str(action, buf, sizeof(buf)),
630 &tcp->rhost, &net_ip, tcp_seq_num, tcp_ack_num);
631 break;
a3bf193b
YCLP
632 }
633
634 pkt_len = pkt_hdr_len + payload_len;
635 tcp_len = pkt_len - IP_HDR_SIZE;
636
82bf3aaf 637 tcp->rcv_nxt = tcp_ack_num;
a3bf193b 638 /* TCP Header */
82bf3aaf 639 b->ip.hdr.tcp_ack = htonl(tcp->rcv_nxt);
2b177498
MK
640 b->ip.hdr.tcp_src = htons(tcp->lport);
641 b->ip.hdr.tcp_dst = htons(tcp->rport);
a3bf193b 642 b->ip.hdr.tcp_seq = htonl(tcp_seq_num);
a3bf193b
YCLP
643
644 /*
645 * TCP window size - TCP header variable tcp_win.
646 * Change tcp_win only if you have an understanding of network
647 * overrun, congestion, TCP segment sizes, TCP windows, TCP scale,
648 * queuing theory and packet buffering. If there are too few buffers,
649 * there will be data loss, recovery may work or the sending TCP,
650 * the server, could abort the stream transmission.
651 * MSS is governed by maximum Ethernet frame length.
652 * The number of buffers is governed by the desire to have a queue of
653 * full buffers to be processed at the destination to maximize
654 * throughput. Temporary memory use for the boot phase on modern
655 * SOCs is may not be considered a constraint to buffer space, if
656 * it is, then the u-boot tftp or nfs kernel netboot should be
657 * considered.
658 */
bf962de9 659 b->ip.hdr.tcp_win = htons(tcp->rcv_wnd >> TCP_SCALE);
a3bf193b
YCLP
660
661 b->ip.hdr.tcp_xsum = 0;
662 b->ip.hdr.tcp_ugr = 0;
663
2b177498 664 b->ip.hdr.tcp_xsum = tcp_set_pseudo_header(pkt, net_ip, tcp->rhost,
a3bf193b
YCLP
665 tcp_len, pkt_len);
666
2b177498 667 net_set_ip_header((uchar *)&b->ip, tcp->rhost, net_ip,
a3bf193b
YCLP
668 pkt_len, IPPROTO_TCP);
669
670 return pkt_hdr_len;
671}
672
82bf3aaf 673static void tcp_update_rcv_nxt(struct tcp_stream *tcp)
40d3d655 674{
82bf3aaf
MK
675 if (tcp_seq_cmp(tcp->rcv_nxt, tcp->lost.hill[0].l) >= 0) {
676 tcp->rcv_nxt = tcp->lost.hill[0].r;
40d3d655 677
ddedfe1c 678 memmove(&tcp->lost.hill[0], &tcp->lost.hill[1],
40d3d655
MK
679 (TCP_SACK_HILLS - 1) * sizeof(struct sack_edges));
680
ddedfe1c
MK
681 tcp->lost.len -= TCP_OPT_LEN_8;
682 tcp->lost.hill[TCP_SACK_HILLS - 1].l = TCP_O_NOP;
683 tcp->lost.hill[TCP_SACK_HILLS - 1].r = TCP_O_NOP;
40d3d655
MK
684 }
685}
686
a3bf193b
YCLP
687/**
688 * tcp_hole() - Selective Acknowledgment (Essential for fast stream transfer)
ddedfe1c 689 * @tcp: tcp stream
a3bf193b
YCLP
690 * @tcp_seq_num: TCP sequence start number
691 * @len: the length of sequence numbers
a3bf193b 692 */
ddedfe1c 693void tcp_hole(struct tcp_stream *tcp, u32 tcp_seq_num, u32 len)
a3bf193b 694{
40d3d655 695 int i, j, cnt, cnt_move;
a3bf193b 696
ddedfe1c 697 cnt = (tcp->lost.len - TCP_OPT_LEN_2) / TCP_OPT_LEN_8;
40d3d655 698 for (i = 0; i < cnt; i++) {
ddedfe1c 699 if (tcp_seq_cmp(tcp->lost.hill[i].r, tcp_seq_num) < 0)
40d3d655 700 continue;
ddedfe1c 701 if (tcp_seq_cmp(tcp->lost.hill[i].l, tcp_seq_num + len) > 0)
40d3d655 702 break;
a3bf193b 703
ddedfe1c
MK
704 if (tcp_seq_cmp(tcp->lost.hill[i].l, tcp_seq_num) > 0)
705 tcp->lost.hill[i].l = tcp_seq_num;
706 if (tcp_seq_cmp(tcp->lost.hill[i].l, tcp_seq_num) < 0) {
707 len += tcp_seq_num - tcp->lost.hill[i].l;
708 tcp_seq_num = tcp->lost.hill[i].l;
40d3d655 709 }
ddedfe1c 710 if (tcp_seq_cmp(tcp->lost.hill[i].r, tcp_seq_num + len) >= 0) {
82bf3aaf 711 tcp_update_rcv_nxt(tcp);
40d3d655
MK
712 return;
713 }
a3bf193b 714
40d3d655
MK
715 /* check overlapping with next hills */
716 cnt_move = 0;
ddedfe1c 717 tcp->lost.hill[i].r = tcp_seq_num + len;
40d3d655 718 for (j = i + 1; j < cnt; j++) {
ddedfe1c 719 if (tcp_seq_cmp(tcp->lost.hill[j].l, tcp->lost.hill[i].r) > 0)
a3bf193b 720 break;
40d3d655 721
ddedfe1c 722 tcp->lost.hill[i].r = tcp->lost.hill[j].r;
40d3d655
MK
723 cnt_move++;
724 }
725
726 if (cnt_move > 0) {
727 if (cnt > i + cnt_move + 1)
ddedfe1c
MK
728 memmove(&tcp->lost.hill[i + 1],
729 &tcp->lost.hill[i + cnt_move + 1],
40d3d655
MK
730 cnt_move * sizeof(struct sack_edges));
731
732 cnt -= cnt_move;
ddedfe1c 733 tcp->lost.len = TCP_OPT_LEN_2 + cnt * TCP_OPT_LEN_8;
40d3d655 734 for (j = cnt; j < TCP_SACK_HILLS; j++) {
ddedfe1c
MK
735 tcp->lost.hill[j].l = TCP_O_NOP;
736 tcp->lost.hill[j].r = TCP_O_NOP;
a3bf193b 737 }
a3bf193b 738 }
40d3d655 739
82bf3aaf 740 tcp_update_rcv_nxt(tcp);
40d3d655 741 return;
a3bf193b 742 }
40d3d655
MK
743
744 if (i == TCP_SACK_HILLS) {
82bf3aaf 745 tcp_update_rcv_nxt(tcp);
40d3d655
MK
746 return;
747 }
748
749 if (cnt < TCP_SACK_HILLS) {
750 cnt_move = cnt - i;
751 cnt++;
752 } else {
753 cnt = TCP_SACK_HILLS;
754 cnt_move = TCP_SACK_HILLS - i;
755 }
756
757 if (cnt_move > 0)
ddedfe1c
MK
758 memmove(&tcp->lost.hill[i + 1],
759 &tcp->lost.hill[i],
40d3d655
MK
760 cnt_move * sizeof(struct sack_edges));
761
ddedfe1c
MK
762 tcp->lost.hill[i].l = tcp_seq_num;
763 tcp->lost.hill[i].r = tcp_seq_num + len;
764 tcp->lost.len = TCP_OPT_LEN_2 + cnt * TCP_OPT_LEN_8;
40d3d655 765
82bf3aaf 766 tcp_update_rcv_nxt(tcp);
40d3d655 767};
a3bf193b
YCLP
768
769/**
770 * tcp_parse_options() - parsing TCP options
ddedfe1c 771 * @tcp: tcp stream
a3bf193b
YCLP
772 * @o: pointer to the option field.
773 * @o_len: length of the option field.
774 */
ddedfe1c 775void tcp_parse_options(struct tcp_stream *tcp, uchar *o, int o_len)
a3bf193b
YCLP
776{
777 struct tcp_t_opt *tsopt;
bf962de9 778 struct tcp_scale *wsopt;
a3bf193b
YCLP
779 uchar *p = o;
780
781 /*
782 * NOPs are options with a zero length, and thus are special.
783 * All other options have length fields.
784 */
77da29b8 785 for (p = o; p < (o + o_len); ) {
a3bf193b
YCLP
786 if (!p[1])
787 return; /* Finished processing options */
788
789 switch (p[0]) {
790 case TCP_O_END:
791 return;
792 case TCP_O_MSS:
a3bf193b
YCLP
793 case TCP_P_SACK:
794 case TCP_V_SACK:
795 break;
bf962de9
MK
796 case TCP_O_SCL:
797 wsopt = (struct tcp_scale *)p;
798 tcp->rmt_win_scale = wsopt->scale;
799 break;
a3bf193b
YCLP
800 case TCP_O_TS:
801 tsopt = (struct tcp_t_opt *)p;
ddedfe1c 802 tcp->rmt_timestamp = tsopt->t_snd;
77da29b8 803 break;
a3bf193b
YCLP
804 }
805
806 /* Process optional NOPs */
807 if (p[0] == TCP_O_NOP)
808 p++;
77da29b8
MK
809 else
810 p += p[1];
a3bf193b
YCLP
811 }
812}
813
bf962de9
MK
814static int tcp_seg_in_wnd(struct tcp_stream *tcp,
815 u32 tcp_seq_num, int payload_len)
a3bf193b 816{
bf962de9
MK
817 if (!payload_len && !tcp->rcv_wnd) {
818 if (tcp_seq_num == tcp->rcv_nxt)
819 return 1;
820 }
821 if (!payload_len && tcp->rcv_wnd > 0) {
822 if (tcp_seq_cmp(tcp->rcv_nxt, tcp_seq_num) <= 0 &&
823 tcp_seq_cmp(tcp_seq_num, tcp->rcv_nxt + tcp->rcv_wnd) < 0)
824 return 1;
825 }
826 if (payload_len > 0 && tcp->rcv_wnd > 0) {
827 if (tcp_seq_cmp(tcp->rcv_nxt, tcp_seq_num) <= 0 &&
828 tcp_seq_cmp(tcp_seq_num, tcp->rcv_nxt + tcp->rcv_wnd) < 0)
829 return 1;
830 tcp_seq_num += payload_len - 1;
831 if (tcp_seq_cmp(tcp->rcv_nxt, tcp_seq_num) <= 0 &&
832 tcp_seq_cmp(tcp_seq_num, tcp->rcv_nxt + tcp->rcv_wnd) < 0)
833 return 1;
834 }
835
836 return 0;
837}
838
839static int tcp_rx_check_ack_num(struct tcp_stream *tcp, u32 tcp_seq_num,
840 u32 tcp_ack_num, u32 tcp_win_size)
841{
842 u32 old_offs, new_offs;
843 u8 action;
844
845 switch (tcp->state) {
846 case TCP_SYN_RECEIVED:
847 if (tcp_seq_cmp(tcp->snd_una, tcp_ack_num) >= 0 ||
848 tcp_seq_cmp(tcp_ack_num, tcp->snd_nxt) > 0) {
849 // segment acknowledgment is not acceptable
850 tcp_send_packet(tcp, TCP_RST, tcp_ack_num, 0, 0);
851 return TCP_PACKET_DROP;
852 }
a3bf193b 853
bf962de9
MK
854 tcp_stream_set_state(tcp, TCP_ESTABLISHED);
855 tcp->snd_wnd = tcp_win_size;
856 tcp->snd_wl1 = tcp_seq_num;
857 tcp->snd_wl2 = tcp_ack_num;
858
859 if (tcp->on_established)
860 tcp->on_established(tcp);
861
862 fallthrough;
863
864 case TCP_ESTABLISHED:
865 case TCP_FIN_WAIT_1:
866 case TCP_FIN_WAIT_2:
867 case TCP_CLOSE_WAIT:
868 case TCP_CLOSING:
869 if (tcp_seq_cmp(tcp_ack_num, tcp->snd_nxt) > 0) {
870 // ACK acks something not yet sent
871 action = tcp_stream_fin_needed(tcp, tcp->snd_una) | TCP_ACK;
872 tcp_send_packet(tcp, action, tcp->snd_una, tcp->rcv_nxt, 0);
873 return TCP_PACKET_DROP;
874 }
875
876 if (tcp_seq_cmp(tcp->snd_una, tcp_ack_num) < 0) {
877 old_offs = tcp_stream_tx_offs(tcp);
878 tcp->snd_una = tcp_ack_num;
879 new_offs = tcp_stream_tx_offs(tcp);
880 if (tcp->time_handler &&
881 tcp_seq_cmp(tcp->snd_una, tcp->retry_seq_num) > 0) {
882 tcp_stream_set_time_handler(tcp, 0, NULL);
883 }
884 if (tcp->on_snd_una_update &&
885 old_offs != new_offs)
886 tcp->on_snd_una_update(tcp, new_offs);
887 }
888
889 if (tcp_seq_cmp(tcp->snd_una, tcp_ack_num) <= 0) {
890 if (tcp_seq_cmp(tcp->snd_wl1, tcp_seq_num) < 0 ||
891 (tcp->snd_wl1 == tcp_seq_num &&
892 tcp_seq_cmp(tcp->snd_wl2, tcp_seq_num) <= 0)) {
893 tcp->snd_wnd = tcp_win_size;
894 tcp->snd_wl1 = tcp_seq_num;
895 tcp->snd_wl2 = tcp_ack_num;
896 }
897 }
898
899 if (tcp->state == TCP_FIN_WAIT_1) {
900 if (tcp->snd_una == tcp->snd_nxt)
901 tcp_stream_set_state(tcp, TCP_FIN_WAIT_2);
902 }
903
904 if (tcp->state == TCP_CLOSING) {
905 if (tcp->snd_una == tcp->snd_nxt)
906 tcp_stream_set_state(tcp, TCP_CLOSED);
907 }
908 return TCP_PACKET_OK;
909
910 case TCP_LAST_ACK:
911 if (tcp_ack_num == tcp->snd_nxt)
912 tcp_stream_set_state(tcp, TCP_CLOSED);
913 return TCP_PACKET_OK;
914
915 default:
916 return TCP_PACKET_DROP;
917 }
918}
919
920static int tcp_rx_user_data(struct tcp_stream *tcp, u32 tcp_seq_num,
921 char *buf, int len)
922{
923 int tmp_len;
924 u32 buf_offs, old_offs, new_offs;
925 u8 action;
926
927 if (!len)
928 return TCP_PACKET_OK;
929
930 switch (tcp->state) {
931 case TCP_ESTABLISHED:
932 case TCP_FIN_WAIT_1:
933 case TCP_FIN_WAIT_2:
934 break;
935 default:
936 return TCP_PACKET_DROP;
937 }
938
939 tmp_len = len;
940 old_offs = tcp_stream_rx_offs(tcp);
941 buf_offs = tcp_seq_num - tcp->irs - 1;
942 if (tcp->rx) {
943 tmp_len = tcp->rx(tcp, buf_offs, buf, len);
944 if (tmp_len < 0) {
945 puts("\nTCP: receive failure\n");
946 tcp_send_packet(tcp, TCP_RST, tcp->snd_una,
947 tcp->rcv_nxt, 0);
948 tcp_stream_set_status(tcp, TCP_ERR_IO);
949 tcp_stream_set_state(tcp, TCP_CLOSED);
950 tcp_stream_destroy(tcp);
951 return TCP_PACKET_DROP;
952 }
953 }
954 if (tmp_len)
955 tcp_hole(tcp, tcp_seq_num, tmp_len);
956
957 new_offs = tcp_stream_rx_offs(tcp);
958 if (tcp->on_rcv_nxt_update && old_offs != new_offs)
959 tcp->on_rcv_nxt_update(tcp, new_offs);
960
961 action = tcp_stream_fin_needed(tcp, tcp->snd_una) | TCP_ACK;
962 tcp_send_packet(tcp, action, tcp->snd_una, tcp->rcv_nxt, 0);
963
964 return TCP_PACKET_OK;
965}
966
967void tcp_rx_state_machine(struct tcp_stream *tcp,
968 union tcp_build_pkt *b, unsigned int pkt_len)
969{
970 int tcp_len = pkt_len - IP_HDR_SIZE;
971 u32 tcp_seq_num, tcp_ack_num, tcp_win_size;
972 int tcp_hdr_len, payload_len;
973 u8 tcp_flags, action;
974
975 tcp_hdr_len = GET_TCP_HDR_LEN_IN_BYTES(b->ip.hdr.tcp_hlen);
976 payload_len = tcp_len - tcp_hdr_len;
977
978 if (tcp_hdr_len > TCP_HDR_SIZE)
979 tcp_parse_options(tcp, (uchar *)b + IP_TCP_HDR_SIZE,
980 tcp_hdr_len - TCP_HDR_SIZE);
a3bf193b 981 /*
bf962de9
MK
982 * Incoming sequence and ack numbers are server's view of the numbers.
983 * The app must swap the numbers when responding.
a3bf193b 984 */
bf962de9
MK
985 tcp_seq_num = ntohl(b->ip.hdr.tcp_seq);
986 tcp_ack_num = ntohl(b->ip.hdr.tcp_ack);
987 tcp_win_size = ntohs(b->ip.hdr.tcp_win) << tcp->rmt_win_scale;
a3bf193b 988
bf962de9
MK
989 tcp_flags = b->ip.hdr.tcp_flags;
990
991// printf("pkt: seq=%d, ack=%d, flags=%x, len=%d\n",
992// tcp_seq_num - tcp->irs, tcp_ack_num - tcp->iss, tcp_flags, pkt_len);
993// printf("tcp: rcv_nxt=%d, snd_una=%d, snd_nxt=%d\n\n",
994// tcp->rcv_nxt - tcp->irs, tcp->snd_una - tcp->iss, tcp->snd_nxt - tcp->iss);
995
996 switch (tcp->state) {
a3bf193b 997 case TCP_CLOSED:
bf962de9
MK
998 if (tcp_flags & TCP_RST)
999 return;
1000
1001 if (tcp_flags & TCP_ACK) {
1002 tcp_send_packet(tcp, TCP_RST, tcp_ack_num, 0, 0);
1003 return;
08fb8da3 1004 }
bf962de9
MK
1005
1006 if (!(tcp_flags & TCP_SYN))
1007 return;
1008
1009 tcp->irs = tcp_seq_num;
1010 tcp->rcv_nxt = tcp->irs + 1;
1011
1012 tcp->iss = tcp_get_start_seq();
1013 tcp->snd_una = tcp->iss;
1014 tcp->snd_nxt = tcp->iss + 1;
1015 tcp->snd_wnd = tcp_win_size;
1016
1017 tcp_stream_restart_rx_timer(tcp);
1018
1019 tcp_stream_set_state(tcp, TCP_SYN_RECEIVED);
1020 tcp_send_packet_with_retry(tcp, TCP_SYN | TCP_ACK,
1021 tcp->iss, 0, 0);
1022 return;
1023
a3bf193b 1024 case TCP_SYN_SENT:
bf962de9
MK
1025 if (!(tcp_flags & TCP_ACK))
1026 return;
1027
1028 if (tcp_seq_cmp(tcp_ack_num, tcp->iss) <= 0 ||
1029 tcp_seq_cmp(tcp_ack_num, tcp->snd_nxt) > 0) {
1030 if (!(tcp_flags & TCP_RST))
1031 tcp_send_packet(tcp, TCP_RST, tcp_ack_num, 0, 0);
1032 return;
a3bf193b 1033 }
bf962de9
MK
1034
1035 if (tcp_flags & TCP_RST) {
1036 tcp_stream_set_status(tcp, TCP_ERR_RST);
1037 tcp_stream_set_state(tcp, TCP_CLOSED);
1038 return;
1039 }
1040
1041 if (!(tcp_flags & TCP_SYN))
1042 return;
1043
1044 /* stop retransmit of SYN */
1045 tcp_stream_set_time_handler(tcp, 0, NULL);
1046
1047 tcp->irs = tcp_seq_num;
1048 tcp->rcv_nxt = tcp->irs + 1;
1049 tcp->snd_una = tcp_ack_num;
1050
1051 tcp_stream_restart_rx_timer(tcp);
1052
1053 /* our SYN has been ACKed */
1054 tcp_stream_set_state(tcp, TCP_ESTABLISHED);
1055
1056 if (tcp->on_established)
1057 tcp->on_established(tcp);
1058
1059 action = tcp_stream_fin_needed(tcp, tcp->snd_una) | TCP_ACK;
1060 tcp_send_packet(tcp, action, tcp->snd_una, tcp->rcv_nxt, 0);
1061 tcp_rx_user_data(tcp, tcp_seq_num,
1062 ((char *)b) + pkt_len - payload_len,
1063 payload_len);
1064 return;
1065
1066 case TCP_SYN_RECEIVED:
a3bf193b 1067 case TCP_ESTABLISHED:
bf962de9
MK
1068 case TCP_FIN_WAIT_1:
1069 case TCP_FIN_WAIT_2:
1070 case TCP_CLOSE_WAIT:
1071 case TCP_CLOSING:
1072 case TCP_LAST_ACK:
1073 if (!tcp_seg_in_wnd(tcp, tcp_seq_num, payload_len)) {
1074 if (tcp_flags & TCP_RST)
1075 return;
1076 action = tcp_stream_fin_needed(tcp, tcp->snd_una) | TCP_ACK;
1077 tcp_send_packet(tcp, action, tcp->snd_una, tcp->rcv_nxt, 0);
1078 return;
a3bf193b
YCLP
1079 }
1080
bf962de9
MK
1081 tcp_stream_restart_rx_timer(tcp);
1082
1083 if (tcp_flags & TCP_RST) {
1084 tcp_stream_set_status(tcp, TCP_ERR_RST);
1085 tcp_stream_set_state(tcp, TCP_CLOSED);
1086 return;
a3bf193b
YCLP
1087 }
1088
bf962de9
MK
1089 if (tcp_flags & TCP_SYN) {
1090 tcp_send_packet(tcp, TCP_RST, tcp_ack_num, 0, 0);
1091 tcp_stream_set_status(tcp, TCP_ERR_RST);
1092 tcp_stream_set_state(tcp, TCP_CLOSED);
1093 return;
a3bf193b 1094 }
bf962de9
MK
1095
1096 if (!(tcp_flags & TCP_ACK))
1097 return;
1098
1099 if (tcp_rx_check_ack_num(tcp, tcp_seq_num, tcp_ack_num,
1100 tcp_win_size) == TCP_PACKET_DROP) {
1101 return;
a3bf193b 1102 }
bf962de9
MK
1103
1104 if (tcp_rx_user_data(tcp, tcp_seq_num,
1105 ((char *)b) + pkt_len - payload_len,
1106 payload_len) == TCP_PACKET_DROP) {
1107 return;
1108 }
1109
1110 if (tcp_flags & TCP_FIN) {
1111 tcp->fin_rx = 1;
1112 tcp->fin_rx_seq = tcp_seq_num + payload_len + 1;
1113 tcp_hole(tcp, tcp_seq_num + payload_len, 1);
1114 action = tcp_stream_fin_needed(tcp, tcp->snd_una) | TCP_ACK;
1115 tcp_send_packet(tcp, action, tcp->snd_una, tcp->rcv_nxt, 0);
1116 }
1117
1118 if (tcp->fin_rx &&
1119 tcp->fin_rx_seq == tcp->rcv_nxt) {
1120 /* all rx data were processed */
1121 switch (tcp->state) {
1122 case TCP_ESTABLISHED:
1123 tcp_stream_set_state(tcp, TCP_LAST_ACK);
1124 tcp_send_packet_with_retry(tcp, TCP_ACK | TCP_FIN,
1125 tcp->snd_nxt, 0, 0);
1126 tcp->snd_nxt++;
1127 break;
1128
1129 case TCP_FIN_WAIT_1:
1130 if (tcp_ack_num == tcp->snd_nxt)
1131 tcp_stream_set_state(tcp, TCP_CLOSED);
1132 else
1133 tcp_stream_set_state(tcp, TCP_CLOSING);
1134 break;
1135
1136 case TCP_FIN_WAIT_2:
1137 tcp_stream_set_state(tcp, TCP_CLOSED);
1138 break;
1139
1140 default:
1141 break;
1142 }
1143 }
1144
1145 if (tcp->state == TCP_FIN_WAIT_1 &&
1146 tcp_stream_fin_needed(tcp, tcp->snd_una)) {
1147 /* all tx data were acknowledged */
1148 tcp_send_packet_with_retry(tcp, TCP_ACK | TCP_FIN,
1149 tcp->snd_una, 0, 0);
a3bf193b 1150 }
a3bf193b 1151 }
a3bf193b
YCLP
1152}
1153
1154/**
1155 * rxhand_tcp_f() - process receiving data and call data handler.
1156 * @b: the packet
1157 * @pkt_len: the length of packet.
1158 */
1159void rxhand_tcp_f(union tcp_build_pkt *b, unsigned int pkt_len)
1160{
1161 int tcp_len = pkt_len - IP_HDR_SIZE;
1162 u16 tcp_rx_xsum = b->ip.hdr.ip_sum;
ddedfe1c 1163 struct tcp_stream *tcp;
2b177498 1164 struct in_addr src;
a3bf193b
YCLP
1165
1166 /* Verify IP header */
1167 debug_cond(DEBUG_DEV_PKT,
1168 "TCP RX in RX Sum (to=%pI4, from=%pI4, len=%d)\n",
1169 &b->ip.hdr.ip_src, &b->ip.hdr.ip_dst, pkt_len);
1170
2b177498
MK
1171 /*
1172 * src IP address will be destroyed by TCP checksum verification
1173 * algorithm (see tcp_set_pseudo_header()), so remember it before
1174 * it was garbaged.
1175 */
1176 src.s_addr = b->ip.hdr.ip_src.s_addr;
1177
a3bf193b
YCLP
1178 b->ip.hdr.ip_dst = net_ip;
1179 b->ip.hdr.ip_sum = 0;
1180 if (tcp_rx_xsum != compute_ip_checksum(b, IP_HDR_SIZE)) {
1181 debug_cond(DEBUG_DEV_PKT,
1182 "TCP RX IP xSum Error (%pI4, =%pI4, len=%d)\n",
2b177498 1183 &net_ip, &src, pkt_len);
a3bf193b
YCLP
1184 return;
1185 }
1186
1187 /* Build pseudo header and verify TCP header */
1188 tcp_rx_xsum = b->ip.hdr.tcp_xsum;
1189 b->ip.hdr.tcp_xsum = 0;
1190 if (tcp_rx_xsum != tcp_set_pseudo_header((uchar *)b, b->ip.hdr.ip_src,
1191 b->ip.hdr.ip_dst, tcp_len,
1192 pkt_len)) {
1193 debug_cond(DEBUG_DEV_PKT,
1194 "TCP RX TCP xSum Error (%pI4, %pI4, len=%d)\n",
2b177498 1195 &net_ip, &src, tcp_len);
a3bf193b
YCLP
1196 return;
1197 }
1198
2b177498
MK
1199 tcp = tcp_stream_get(b->ip.hdr.tcp_flags & TCP_SYN,
1200 src,
1201 ntohs(b->ip.hdr.tcp_src),
1202 ntohs(b->ip.hdr.tcp_dst));
ddedfe1c
MK
1203 if (!tcp)
1204 return;
1205
bf962de9
MK
1206 tcp->rx_packets++;
1207 tcp_rx_state_machine(tcp, b, pkt_len);
1208 tcp_stream_put(tcp);
1209}
a3bf193b 1210
bf962de9
MK
1211struct tcp_stream *tcp_stream_connect(struct in_addr rhost, u16 rport)
1212{
1213 struct tcp_stream *tcp;
a3bf193b 1214
bf962de9
MK
1215 tcp = tcp_stream_add(rhost, rport, random_port());
1216 if (!tcp)
1217 return NULL;
a3bf193b 1218
bf962de9
MK
1219 tcp->iss = tcp_get_start_seq();
1220 tcp->snd_una = tcp->iss;
1221 tcp->snd_nxt = tcp->iss + 1;
a3bf193b 1222
bf962de9
MK
1223 tcp_stream_set_state(tcp, TCP_SYN_SENT);
1224 tcp_send_packet_with_retry(tcp, TCP_SYN, tcp->snd_una, 0, 0);
a3bf193b 1225
bf962de9
MK
1226 return tcp;
1227}
a3bf193b 1228
bf962de9
MK
1229void tcp_stream_reset(struct tcp_stream *tcp)
1230{
1231 if (tcp->state == TCP_CLOSED)
1232 return;
1233
1234 tcp_stream_set_time_handler(tcp, 0, NULL);
1235 tcp_send_packet(tcp, TCP_RST, tcp->snd_una, 0, 0);
1236 tcp_stream_set_status(tcp, TCP_ERR_RST);
1237 tcp_stream_set_state(tcp, TCP_CLOSED);
a3bf193b 1238}
2b177498 1239
bf962de9 1240void tcp_stream_close(struct tcp_stream *tcp)
2b177498 1241{
bf962de9
MK
1242 switch (tcp->state) {
1243 case TCP_SYN_SENT:
1244 tcp_stream_reset(tcp);
1245 break;
1246 case TCP_SYN_RECEIVED:
1247 case TCP_ESTABLISHED:
1248 tcp->fin_tx = 1;
1249 tcp->fin_tx_seq = tcp->snd_nxt;
1250 if (tcp_stream_fin_needed(tcp, tcp->snd_una)) {
1251 /* all tx data were acknowledged */
1252 tcp_send_packet_with_retry(tcp, TCP_ACK | TCP_FIN,
1253 tcp->snd_una, 0, 0);
1254 }
1255 tcp_stream_set_state(tcp, TCP_FIN_WAIT_1);
1256 tcp->snd_nxt++;
1257 break;
1258 default:
1259 break;
1260 }
2b177498 1261}
This page took 0.285926 seconds and 5 git commands to generate.