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