source: azure_iot_hub_f767zi/trunk/asp_baseplatform/lwip/lwip-2.1.2/src/core/tcp_in.c@ 457

Last change on this file since 457 was 457, checked in by coas-nagasima, 4 years ago

ファイルを追加

  • Property svn:eol-style set to native
  • Property svn:mime-type set to text/x-csrc;charset=UTF-8
File size: 81.4 KB
Line 
1/**
2 * @file
3 * Transmission Control Protocol, incoming traffic
4 *
5 * The input processing functions of the TCP layer.
6 *
7 * These functions are generally called in the order (ip_input() ->)
8 * tcp_input() -> * tcp_process() -> tcp_receive() (-> application).
9 *
10 */
11
12/*
13 * Copyright (c) 2001-2004 Swedish Institute of Computer Science.
14 * All rights reserved.
15 *
16 * Redistribution and use in source and binary forms, with or without modification,
17 * are permitted provided that the following conditions are met:
18 *
19 * 1. Redistributions of source code must retain the above copyright notice,
20 * this list of conditions and the following disclaimer.
21 * 2. Redistributions in binary form must reproduce the above copyright notice,
22 * this list of conditions and the following disclaimer in the documentation
23 * and/or other materials provided with the distribution.
24 * 3. The name of the author may not be used to endorse or promote products
25 * derived from this software without specific prior written permission.
26 *
27 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
28 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
29 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
30 * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
31 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
32 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
35 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
36 * OF SUCH DAMAGE.
37 *
38 * This file is part of the lwIP TCP/IP stack.
39 *
40 * Author: Adam Dunkels <adam@sics.se>
41 *
42 */
43
44#include "lwip/opt.h"
45
46#if LWIP_TCP /* don't build if not configured for use in lwipopts.h */
47
48#include "lwip/priv/tcp_priv.h"
49#include "lwip/def.h"
50#include "lwip/ip_addr.h"
51#include "lwip/netif.h"
52#include "lwip/mem.h"
53#include "lwip/memp.h"
54#include "lwip/inet_chksum.h"
55#include "lwip/stats.h"
56#include "lwip/ip6.h"
57#include "lwip/ip6_addr.h"
58#if LWIP_ND6_TCP_REACHABILITY_HINTS
59#include "lwip/nd6.h"
60#endif /* LWIP_ND6_TCP_REACHABILITY_HINTS */
61
62#include <string.h>
63
64#ifdef LWIP_HOOK_FILENAME
65#include LWIP_HOOK_FILENAME
66#endif
67
68/** Initial CWND calculation as defined RFC 2581 */
69#define LWIP_TCP_CALC_INITIAL_CWND(mss) ((tcpwnd_size_t)LWIP_MIN((4U * (mss)), LWIP_MAX((2U * (mss)), 4380U)))
70
71/* These variables are global to all functions involved in the input
72 processing of TCP segments. They are set by the tcp_input()
73 function. */
74static struct tcp_seg inseg;
75static struct tcp_hdr *tcphdr;
76static u16_t tcphdr_optlen;
77static u16_t tcphdr_opt1len;
78static u8_t *tcphdr_opt2;
79static u16_t tcp_optidx;
80static u32_t seqno, ackno;
81static tcpwnd_size_t recv_acked;
82static u16_t tcplen;
83static u8_t flags;
84
85static u8_t recv_flags;
86static struct pbuf *recv_data;
87
88struct tcp_pcb *tcp_input_pcb;
89
90/* Forward declarations. */
91static err_t tcp_process(struct tcp_pcb *pcb);
92static void tcp_receive(struct tcp_pcb *pcb);
93static void tcp_parseopt(struct tcp_pcb *pcb);
94
95static void tcp_listen_input(struct tcp_pcb_listen *pcb);
96static void tcp_timewait_input(struct tcp_pcb *pcb);
97
98static int tcp_input_delayed_close(struct tcp_pcb *pcb);
99
100#if LWIP_TCP_SACK_OUT
101static void tcp_add_sack(struct tcp_pcb *pcb, u32_t left, u32_t right);
102static void tcp_remove_sacks_lt(struct tcp_pcb *pcb, u32_t seq);
103#if defined(TCP_OOSEQ_BYTES_LIMIT) || defined(TCP_OOSEQ_PBUFS_LIMIT)
104static void tcp_remove_sacks_gt(struct tcp_pcb *pcb, u32_t seq);
105#endif /* TCP_OOSEQ_BYTES_LIMIT || TCP_OOSEQ_PBUFS_LIMIT */
106#endif /* LWIP_TCP_SACK_OUT */
107
108/**
109 * The initial input processing of TCP. It verifies the TCP header, demultiplexes
110 * the segment between the PCBs and passes it on to tcp_process(), which implements
111 * the TCP finite state machine. This function is called by the IP layer (in
112 * ip_input()).
113 *
114 * @param p received TCP segment to process (p->payload pointing to the TCP header)
115 * @param inp network interface on which this segment was received
116 */
117void
118tcp_input(struct pbuf *p, struct netif *inp)
119{
120 struct tcp_pcb *pcb, *prev;
121 struct tcp_pcb_listen *lpcb;
122#if SO_REUSE
123 struct tcp_pcb *lpcb_prev = NULL;
124 struct tcp_pcb_listen *lpcb_any = NULL;
125#endif /* SO_REUSE */
126 u8_t hdrlen_bytes;
127 err_t err;
128
129 LWIP_UNUSED_ARG(inp);
130 LWIP_ASSERT_CORE_LOCKED();
131 LWIP_ASSERT("tcp_input: invalid pbuf", p != NULL);
132
133 PERF_START;
134
135 TCP_STATS_INC(tcp.recv);
136 MIB2_STATS_INC(mib2.tcpinsegs);
137
138 tcphdr = (struct tcp_hdr *)p->payload;
139
140#if TCP_INPUT_DEBUG
141 tcp_debug_print(tcphdr);
142#endif
143
144 /* Check that TCP header fits in payload */
145 if (p->len < TCP_HLEN) {
146 /* drop short packets */
147 LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: short packet (%"U16_F" bytes) discarded\n", p->tot_len));
148 TCP_STATS_INC(tcp.lenerr);
149 goto dropped;
150 }
151
152 /* Don't even process incoming broadcasts/multicasts. */
153 if (ip_addr_isbroadcast(ip_current_dest_addr(), ip_current_netif()) ||
154 ip_addr_ismulticast(ip_current_dest_addr())) {
155 TCP_STATS_INC(tcp.proterr);
156 goto dropped;
157 }
158
159#if CHECKSUM_CHECK_TCP
160 IF__NETIF_CHECKSUM_ENABLED(inp, NETIF_CHECKSUM_CHECK_TCP) {
161 /* Verify TCP checksum. */
162 u16_t chksum = ip_chksum_pseudo(p, IP_PROTO_TCP, p->tot_len,
163 ip_current_src_addr(), ip_current_dest_addr());
164 if (chksum != 0) {
165 LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: packet discarded due to failing checksum 0x%04"X16_F"\n",
166 chksum));
167 tcp_debug_print(tcphdr);
168 TCP_STATS_INC(tcp.chkerr);
169 goto dropped;
170 }
171 }
172#endif /* CHECKSUM_CHECK_TCP */
173
174 /* sanity-check header length */
175 hdrlen_bytes = TCPH_HDRLEN_BYTES(tcphdr);
176 if ((hdrlen_bytes < TCP_HLEN) || (hdrlen_bytes > p->tot_len)) {
177 LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: invalid header length (%"U16_F")\n", (u16_t)hdrlen_bytes));
178 TCP_STATS_INC(tcp.lenerr);
179 goto dropped;
180 }
181
182 /* Move the payload pointer in the pbuf so that it points to the
183 TCP data instead of the TCP header. */
184 tcphdr_optlen = (u16_t)(hdrlen_bytes - TCP_HLEN);
185 tcphdr_opt2 = NULL;
186 if (p->len >= hdrlen_bytes) {
187 /* all options are in the first pbuf */
188 tcphdr_opt1len = tcphdr_optlen;
189 pbuf_remove_header(p, hdrlen_bytes); /* cannot fail */
190 } else {
191 u16_t opt2len;
192 /* TCP header fits into first pbuf, options don't - data is in the next pbuf */
193 /* there must be a next pbuf, due to hdrlen_bytes sanity check above */
194 LWIP_ASSERT("p->next != NULL", p->next != NULL);
195
196 /* advance over the TCP header (cannot fail) */
197 pbuf_remove_header(p, TCP_HLEN);
198
199 /* determine how long the first and second parts of the options are */
200 tcphdr_opt1len = p->len;
201 opt2len = (u16_t)(tcphdr_optlen - tcphdr_opt1len);
202
203 /* options continue in the next pbuf: set p to zero length and hide the
204 options in the next pbuf (adjusting p->tot_len) */
205 pbuf_remove_header(p, tcphdr_opt1len);
206
207 /* check that the options fit in the second pbuf */
208 if (opt2len > p->next->len) {
209 /* drop short packets */
210 LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: options overflow second pbuf (%"U16_F" bytes)\n", p->next->len));
211 TCP_STATS_INC(tcp.lenerr);
212 goto dropped;
213 }
214
215 /* remember the pointer to the second part of the options */
216 tcphdr_opt2 = (u8_t *)p->next->payload;
217
218 /* advance p->next to point after the options, and manually
219 adjust p->tot_len to keep it consistent with the changed p->next */
220 pbuf_remove_header(p->next, opt2len);
221 p->tot_len = (u16_t)(p->tot_len - opt2len);
222
223 LWIP_ASSERT("p->len == 0", p->len == 0);
224 LWIP_ASSERT("p->tot_len == p->next->tot_len", p->tot_len == p->next->tot_len);
225 }
226
227 /* Convert fields in TCP header to host byte order. */
228 tcphdr->src = lwip_ntohs(tcphdr->src);
229 tcphdr->dest = lwip_ntohs(tcphdr->dest);
230 seqno = tcphdr->seqno = lwip_ntohl(tcphdr->seqno);
231 ackno = tcphdr->ackno = lwip_ntohl(tcphdr->ackno);
232 tcphdr->wnd = lwip_ntohs(tcphdr->wnd);
233
234 flags = TCPH_FLAGS(tcphdr);
235 tcplen = p->tot_len;
236 if (flags & (TCP_FIN | TCP_SYN)) {
237 tcplen++;
238 if (tcplen < p->tot_len) {
239 /* u16_t overflow, cannot handle this */
240 LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: length u16_t overflow, cannot handle this\n"));
241 TCP_STATS_INC(tcp.lenerr);
242 goto dropped;
243 }
244 }
245
246 /* Demultiplex an incoming segment. First, we check if it is destined
247 for an active connection. */
248 prev = NULL;
249
250 for (pcb = tcp_active_pcbs; pcb != NULL; pcb = pcb->next) {
251 LWIP_ASSERT("tcp_input: active pcb->state != CLOSED", pcb->state != CLOSED);
252 LWIP_ASSERT("tcp_input: active pcb->state != TIME-WAIT", pcb->state != TIME_WAIT);
253 LWIP_ASSERT("tcp_input: active pcb->state != LISTEN", pcb->state != LISTEN);
254
255 /* check if PCB is bound to specific netif */
256 if ((pcb->netif_idx != NETIF_NO_INDEX) &&
257 (pcb->netif_idx != netif_get_index(ip_data.current_input_netif))) {
258 prev = pcb;
259 continue;
260 }
261
262 if (pcb->remote_port == tcphdr->src &&
263 pcb->local_port == tcphdr->dest &&
264 ip_addr_cmp(&pcb->remote_ip, ip_current_src_addr()) &&
265 ip_addr_cmp(&pcb->local_ip, ip_current_dest_addr())) {
266 /* Move this PCB to the front of the list so that subsequent
267 lookups will be faster (we exploit locality in TCP segment
268 arrivals). */
269 LWIP_ASSERT("tcp_input: pcb->next != pcb (before cache)", pcb->next != pcb);
270 if (prev != NULL) {
271 prev->next = pcb->next;
272 pcb->next = tcp_active_pcbs;
273 tcp_active_pcbs = pcb;
274 } else {
275 TCP_STATS_INC(tcp.cachehit);
276 }
277 LWIP_ASSERT("tcp_input: pcb->next != pcb (after cache)", pcb->next != pcb);
278 break;
279 }
280 prev = pcb;
281 }
282
283 if (pcb == NULL) {
284 /* If it did not go to an active connection, we check the connections
285 in the TIME-WAIT state. */
286 for (pcb = tcp_tw_pcbs; pcb != NULL; pcb = pcb->next) {
287 LWIP_ASSERT("tcp_input: TIME-WAIT pcb->state == TIME-WAIT", pcb->state == TIME_WAIT);
288
289 /* check if PCB is bound to specific netif */
290 if ((pcb->netif_idx != NETIF_NO_INDEX) &&
291 (pcb->netif_idx != netif_get_index(ip_data.current_input_netif))) {
292 continue;
293 }
294
295 if (pcb->remote_port == tcphdr->src &&
296 pcb->local_port == tcphdr->dest &&
297 ip_addr_cmp(&pcb->remote_ip, ip_current_src_addr()) &&
298 ip_addr_cmp(&pcb->local_ip, ip_current_dest_addr())) {
299 /* We don't really care enough to move this PCB to the front
300 of the list since we are not very likely to receive that
301 many segments for connections in TIME-WAIT. */
302 LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: packed for TIME_WAITing connection.\n"));
303#ifdef LWIP_HOOK_TCP_INPACKET_PCB
304 if (LWIP_HOOK_TCP_INPACKET_PCB(pcb, tcphdr, tcphdr_optlen, tcphdr_opt1len,
305 tcphdr_opt2, p) == ERR_OK)
306#endif
307 {
308 tcp_timewait_input(pcb);
309 }
310 pbuf_free(p);
311 return;
312 }
313 }
314
315 /* Finally, if we still did not get a match, we check all PCBs that
316 are LISTENing for incoming connections. */
317 prev = NULL;
318 for (lpcb = tcp_listen_pcbs.listen_pcbs; lpcb != NULL; lpcb = lpcb->next) {
319 /* check if PCB is bound to specific netif */
320 if ((lpcb->netif_idx != NETIF_NO_INDEX) &&
321 (lpcb->netif_idx != netif_get_index(ip_data.current_input_netif))) {
322 prev = (struct tcp_pcb *)lpcb;
323 continue;
324 }
325
326 if (lpcb->local_port == tcphdr->dest) {
327 if (IP_IS_ANY_TYPE_VAL(lpcb->local_ip)) {
328 /* found an ANY TYPE (IPv4/IPv6) match */
329#if SO_REUSE
330 lpcb_any = lpcb;
331 lpcb_prev = prev;
332#else /* SO_REUSE */
333 break;
334#endif /* SO_REUSE */
335 } else if (IP_ADDR_PCB_VERSION_MATCH_EXACT(lpcb, ip_current_dest_addr())) {
336 if (ip_addr_cmp(&lpcb->local_ip, ip_current_dest_addr())) {
337 /* found an exact match */
338 break;
339 } else if (ip_addr_isany(&lpcb->local_ip)) {
340 /* found an ANY-match */
341#if SO_REUSE
342 lpcb_any = lpcb;
343 lpcb_prev = prev;
344#else /* SO_REUSE */
345 break;
346#endif /* SO_REUSE */
347 }
348 }
349 }
350 prev = (struct tcp_pcb *)lpcb;
351 }
352#if SO_REUSE
353 /* first try specific local IP */
354 if (lpcb == NULL) {
355 /* only pass to ANY if no specific local IP has been found */
356 lpcb = lpcb_any;
357 prev = lpcb_prev;
358 }
359#endif /* SO_REUSE */
360 if (lpcb != NULL) {
361 /* Move this PCB to the front of the list so that subsequent
362 lookups will be faster (we exploit locality in TCP segment
363 arrivals). */
364 if (prev != NULL) {
365 ((struct tcp_pcb_listen *)prev)->next = lpcb->next;
366 /* our successor is the remainder of the listening list */
367 lpcb->next = tcp_listen_pcbs.listen_pcbs;
368 /* put this listening pcb at the head of the listening list */
369 tcp_listen_pcbs.listen_pcbs = lpcb;
370 } else {
371 TCP_STATS_INC(tcp.cachehit);
372 }
373
374 LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: packed for LISTENing connection.\n"));
375#ifdef LWIP_HOOK_TCP_INPACKET_PCB
376 if (LWIP_HOOK_TCP_INPACKET_PCB((struct tcp_pcb *)lpcb, tcphdr, tcphdr_optlen,
377 tcphdr_opt1len, tcphdr_opt2, p) == ERR_OK)
378#endif
379 {
380 tcp_listen_input(lpcb);
381 }
382 pbuf_free(p);
383 return;
384 }
385 }
386
387#if TCP_INPUT_DEBUG
388 LWIP_DEBUGF(TCP_INPUT_DEBUG, ("+-+-+-+-+-+-+-+-+-+-+-+-+-+- tcp_input: flags "));
389 tcp_debug_print_flags(TCPH_FLAGS(tcphdr));
390 LWIP_DEBUGF(TCP_INPUT_DEBUG, ("-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n"));
391#endif /* TCP_INPUT_DEBUG */
392
393
394#ifdef LWIP_HOOK_TCP_INPACKET_PCB
395 if ((pcb != NULL) && LWIP_HOOK_TCP_INPACKET_PCB(pcb, tcphdr, tcphdr_optlen,
396 tcphdr_opt1len, tcphdr_opt2, p) != ERR_OK) {
397 pbuf_free(p);
398 return;
399 }
400#endif
401 if (pcb != NULL) {
402 /* The incoming segment belongs to a connection. */
403#if TCP_INPUT_DEBUG
404 tcp_debug_print_state(pcb->state);
405#endif /* TCP_INPUT_DEBUG */
406
407 /* Set up a tcp_seg structure. */
408 inseg.next = NULL;
409 inseg.len = p->tot_len;
410 inseg.p = p;
411 inseg.tcphdr = tcphdr;
412
413 recv_data = NULL;
414 recv_flags = 0;
415 recv_acked = 0;
416
417 if (flags & TCP_PSH) {
418 p->flags |= PBUF_FLAG_PUSH;
419 }
420
421 /* If there is data which was previously "refused" by upper layer */
422 if (pcb->refused_data != NULL) {
423 if ((tcp_process_refused_data(pcb) == ERR_ABRT) ||
424 ((pcb->refused_data != NULL) && (tcplen > 0))) {
425 /* pcb has been aborted or refused data is still refused and the new
426 segment contains data */
427 if (pcb->rcv_ann_wnd == 0) {
428 /* this is a zero-window probe, we respond to it with current RCV.NXT
429 and drop the data segment */
430 tcp_send_empty_ack(pcb);
431 }
432 TCP_STATS_INC(tcp.drop);
433 MIB2_STATS_INC(mib2.tcpinerrs);
434 goto aborted;
435 }
436 }
437 tcp_input_pcb = pcb;
438 err = tcp_process(pcb);
439 /* A return value of ERR_ABRT means that tcp_abort() was called
440 and that the pcb has been freed. If so, we don't do anything. */
441 if (err != ERR_ABRT) {
442 if (recv_flags & TF_RESET) {
443 /* TF_RESET means that the connection was reset by the other
444 end. We then call the error callback to inform the
445 application that the connection is dead before we
446 deallocate the PCB. */
447 TCP_EVENT_ERR(pcb->state, pcb->errf, pcb->callback_arg, ERR_RST);
448 tcp_pcb_remove(&tcp_active_pcbs, pcb);
449 tcp_free(pcb);
450 } else {
451 err = ERR_OK;
452 /* If the application has registered a "sent" function to be
453 called when new send buffer space is available, we call it
454 now. */
455 if (recv_acked > 0) {
456 u16_t acked16;
457#if LWIP_WND_SCALE
458 /* recv_acked is u32_t but the sent callback only takes a u16_t,
459 so we might have to call it multiple times. */
460 u32_t acked = recv_acked;
461 while (acked > 0) {
462 acked16 = (u16_t)LWIP_MIN(acked, 0xffffu);
463 acked -= acked16;
464#else
465 {
466 acked16 = recv_acked;
467#endif
468 TCP_EVENT_SENT(pcb, (u16_t)acked16, err);
469 if (err == ERR_ABRT) {
470 goto aborted;
471 }
472 }
473 recv_acked = 0;
474 }
475 if (tcp_input_delayed_close(pcb)) {
476 goto aborted;
477 }
478#if TCP_QUEUE_OOSEQ && LWIP_WND_SCALE
479 while (recv_data != NULL) {
480 struct pbuf *rest = NULL;
481 pbuf_split_64k(recv_data, &rest);
482#else /* TCP_QUEUE_OOSEQ && LWIP_WND_SCALE */
483 if (recv_data != NULL) {
484#endif /* TCP_QUEUE_OOSEQ && LWIP_WND_SCALE */
485
486 LWIP_ASSERT("pcb->refused_data == NULL", pcb->refused_data == NULL);
487 if (pcb->flags & TF_RXCLOSED) {
488 /* received data although already closed -> abort (send RST) to
489 notify the remote host that not all data has been processed */
490 pbuf_free(recv_data);
491#if TCP_QUEUE_OOSEQ && LWIP_WND_SCALE
492 if (rest != NULL) {
493 pbuf_free(rest);
494 }
495#endif /* TCP_QUEUE_OOSEQ && LWIP_WND_SCALE */
496 tcp_abort(pcb);
497 goto aborted;
498 }
499
500 /* Notify application that data has been received. */
501 TCP_EVENT_RECV(pcb, recv_data, ERR_OK, err);
502 if (err == ERR_ABRT) {
503#if TCP_QUEUE_OOSEQ && LWIP_WND_SCALE
504 if (rest != NULL) {
505 pbuf_free(rest);
506 }
507#endif /* TCP_QUEUE_OOSEQ && LWIP_WND_SCALE */
508 goto aborted;
509 }
510
511 /* If the upper layer can't receive this data, store it */
512 if (err != ERR_OK) {
513#if TCP_QUEUE_OOSEQ && LWIP_WND_SCALE
514 if (rest != NULL) {
515 pbuf_cat(recv_data, rest);
516 }
517#endif /* TCP_QUEUE_OOSEQ && LWIP_WND_SCALE */
518 pcb->refused_data = recv_data;
519 LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: keep incoming packet, because pcb is \"full\"\n"));
520#if TCP_QUEUE_OOSEQ && LWIP_WND_SCALE
521 break;
522 } else {
523 /* Upper layer received the data, go on with the rest if > 64K */
524 recv_data = rest;
525#endif /* TCP_QUEUE_OOSEQ && LWIP_WND_SCALE */
526 }
527 }
528
529 /* If a FIN segment was received, we call the callback
530 function with a NULL buffer to indicate EOF. */
531 if (recv_flags & TF_GOT_FIN) {
532 if (pcb->refused_data != NULL) {
533 /* Delay this if we have refused data. */
534 pcb->refused_data->flags |= PBUF_FLAG_TCP_FIN;
535 } else {
536 /* correct rcv_wnd as the application won't call tcp_recved()
537 for the FIN's seqno */
538 if (pcb->rcv_wnd != TCP_WND_MAX(pcb)) {
539 pcb->rcv_wnd++;
540 }
541 TCP_EVENT_CLOSED(pcb, err);
542 if (err == ERR_ABRT) {
543 goto aborted;
544 }
545 }
546 }
547
548 tcp_input_pcb = NULL;
549 if (tcp_input_delayed_close(pcb)) {
550 goto aborted;
551 }
552 /* Try to send something out. */
553 tcp_output(pcb);
554#if TCP_INPUT_DEBUG
555#if TCP_DEBUG
556 tcp_debug_print_state(pcb->state);
557#endif /* TCP_DEBUG */
558#endif /* TCP_INPUT_DEBUG */
559 }
560 }
561 /* Jump target if pcb has been aborted in a callback (by calling tcp_abort()).
562 Below this line, 'pcb' may not be dereferenced! */
563aborted:
564 tcp_input_pcb = NULL;
565 recv_data = NULL;
566
567 /* give up our reference to inseg.p */
568 if (inseg.p != NULL) {
569 pbuf_free(inseg.p);
570 inseg.p = NULL;
571 }
572 } else {
573 /* If no matching PCB was found, send a TCP RST (reset) to the
574 sender. */
575 LWIP_DEBUGF(TCP_RST_DEBUG, ("tcp_input: no PCB match found, resetting.\n"));
576 if (!(TCPH_FLAGS(tcphdr) & TCP_RST)) {
577 TCP_STATS_INC(tcp.proterr);
578 TCP_STATS_INC(tcp.drop);
579 tcp_rst(NULL, ackno, seqno + tcplen, ip_current_dest_addr(),
580 ip_current_src_addr(), tcphdr->dest, tcphdr->src);
581 }
582 pbuf_free(p);
583 }
584
585 LWIP_ASSERT("tcp_input: tcp_pcbs_sane()", tcp_pcbs_sane());
586 PERF_STOP("tcp_input");
587 return;
588dropped:
589 TCP_STATS_INC(tcp.drop);
590 MIB2_STATS_INC(mib2.tcpinerrs);
591 pbuf_free(p);
592}
593
594/** Called from tcp_input to check for TF_CLOSED flag. This results in closing
595 * and deallocating a pcb at the correct place to ensure noone references it
596 * any more.
597 * @returns 1 if the pcb has been closed and deallocated, 0 otherwise
598 */
599static int
600tcp_input_delayed_close(struct tcp_pcb *pcb)
601{
602 LWIP_ASSERT("tcp_input_delayed_close: invalid pcb", pcb != NULL);
603
604 if (recv_flags & TF_CLOSED) {
605 /* The connection has been closed and we will deallocate the
606 PCB. */
607 if (!(pcb->flags & TF_RXCLOSED)) {
608 /* Connection closed although the application has only shut down the
609 tx side: call the PCB's err callback and indicate the closure to
610 ensure the application doesn't continue using the PCB. */
611 TCP_EVENT_ERR(pcb->state, pcb->errf, pcb->callback_arg, ERR_CLSD);
612 }
613 tcp_pcb_remove(&tcp_active_pcbs, pcb);
614 tcp_free(pcb);
615 return 1;
616 }
617 return 0;
618}
619
620/**
621 * Called by tcp_input() when a segment arrives for a listening
622 * connection (from tcp_input()).
623 *
624 * @param pcb the tcp_pcb_listen for which a segment arrived
625 *
626 * @note the segment which arrived is saved in global variables, therefore only the pcb
627 * involved is passed as a parameter to this function
628 */
629static void
630tcp_listen_input(struct tcp_pcb_listen *pcb)
631{
632 struct tcp_pcb *npcb;
633 u32_t iss;
634 err_t rc;
635
636 if (flags & TCP_RST) {
637 /* An incoming RST should be ignored. Return. */
638 return;
639 }
640
641 LWIP_ASSERT("tcp_listen_input: invalid pcb", pcb != NULL);
642
643 /* In the LISTEN state, we check for incoming SYN segments,
644 creates a new PCB, and responds with a SYN|ACK. */
645 if (flags & TCP_ACK) {
646 /* For incoming segments with the ACK flag set, respond with a
647 RST. */
648 LWIP_DEBUGF(TCP_RST_DEBUG, ("tcp_listen_input: ACK in LISTEN, sending reset\n"));
649 tcp_rst((const struct tcp_pcb *)pcb, ackno, seqno + tcplen, ip_current_dest_addr(),
650 ip_current_src_addr(), tcphdr->dest, tcphdr->src);
651 } else if (flags & TCP_SYN) {
652 LWIP_DEBUGF(TCP_DEBUG, ("TCP connection request %"U16_F" -> %"U16_F".\n", tcphdr->src, tcphdr->dest));
653#if TCP_LISTEN_BACKLOG
654 if (pcb->accepts_pending >= pcb->backlog) {
655 LWIP_DEBUGF(TCP_DEBUG, ("tcp_listen_input: listen backlog exceeded for port %"U16_F"\n", tcphdr->dest));
656 return;
657 }
658#endif /* TCP_LISTEN_BACKLOG */
659 npcb = tcp_alloc(pcb->prio);
660 /* If a new PCB could not be created (probably due to lack of memory),
661 we don't do anything, but rely on the sender will retransmit the
662 SYN at a time when we have more memory available. */
663 if (npcb == NULL) {
664 err_t err;
665 LWIP_DEBUGF(TCP_DEBUG, ("tcp_listen_input: could not allocate PCB\n"));
666 TCP_STATS_INC(tcp.memerr);
667 TCP_EVENT_ACCEPT(pcb, NULL, pcb->callback_arg, ERR_MEM, err);
668 LWIP_UNUSED_ARG(err); /* err not useful here */
669 return;
670 }
671#if TCP_LISTEN_BACKLOG
672 pcb->accepts_pending++;
673 tcp_set_flags(npcb, TF_BACKLOGPEND);
674#endif /* TCP_LISTEN_BACKLOG */
675 /* Set up the new PCB. */
676 ip_addr_copy(npcb->local_ip, *ip_current_dest_addr());
677 ip_addr_copy(npcb->remote_ip, *ip_current_src_addr());
678 npcb->local_port = pcb->local_port;
679 npcb->remote_port = tcphdr->src;
680 npcb->state = SYN_RCVD;
681 npcb->rcv_nxt = seqno + 1;
682 npcb->rcv_ann_right_edge = npcb->rcv_nxt;
683 iss = tcp_next_iss(npcb);
684 npcb->snd_wl2 = iss;
685 npcb->snd_nxt = iss;
686 npcb->lastack = iss;
687 npcb->snd_lbb = iss;
688 npcb->snd_wl1 = seqno - 1;/* initialise to seqno-1 to force window update */
689 npcb->callback_arg = pcb->callback_arg;
690#if LWIP_CALLBACK_API || TCP_LISTEN_BACKLOG
691 npcb->listener = pcb;
692#endif /* LWIP_CALLBACK_API || TCP_LISTEN_BACKLOG */
693 /* inherit socket options */
694 npcb->so_options = pcb->so_options & SOF_INHERITED;
695 npcb->netif_idx = pcb->netif_idx;
696 /* Register the new PCB so that we can begin receiving segments
697 for it. */
698 TCP_REG_ACTIVE(npcb);
699
700 /* Parse any options in the SYN. */
701 tcp_parseopt(npcb);
702 npcb->snd_wnd = tcphdr->wnd;
703 npcb->snd_wnd_max = npcb->snd_wnd;
704
705#if TCP_CALCULATE_EFF_SEND_MSS
706 npcb->mss = tcp_eff_send_mss(npcb->mss, &npcb->local_ip, &npcb->remote_ip);
707#endif /* TCP_CALCULATE_EFF_SEND_MSS */
708
709 MIB2_STATS_INC(mib2.tcppassiveopens);
710
711#if LWIP_TCP_PCB_NUM_EXT_ARGS
712 if (tcp_ext_arg_invoke_callbacks_passive_open(pcb, npcb) != ERR_OK) {
713 tcp_abandon(npcb, 0);
714 return;
715 }
716#endif
717
718 /* Send a SYN|ACK together with the MSS option. */
719 rc = tcp_enqueue_flags(npcb, TCP_SYN | TCP_ACK);
720 if (rc != ERR_OK) {
721 tcp_abandon(npcb, 0);
722 return;
723 }
724 tcp_output(npcb);
725 }
726 return;
727}
728
729/**
730 * Called by tcp_input() when a segment arrives for a connection in
731 * TIME_WAIT.
732 *
733 * @param pcb the tcp_pcb for which a segment arrived
734 *
735 * @note the segment which arrived is saved in global variables, therefore only the pcb
736 * involved is passed as a parameter to this function
737 */
738static void
739tcp_timewait_input(struct tcp_pcb *pcb)
740{
741 /* RFC 1337: in TIME_WAIT, ignore RST and ACK FINs + any 'acceptable' segments */
742 /* RFC 793 3.9 Event Processing - Segment Arrives:
743 * - first check sequence number - we skip that one in TIME_WAIT (always
744 * acceptable since we only send ACKs)
745 * - second check the RST bit (... return) */
746 if (flags & TCP_RST) {
747 return;
748 }
749
750 LWIP_ASSERT("tcp_timewait_input: invalid pcb", pcb != NULL);
751
752 /* - fourth, check the SYN bit, */
753 if (flags & TCP_SYN) {
754 /* If an incoming segment is not acceptable, an acknowledgment
755 should be sent in reply */
756 if (TCP_SEQ_BETWEEN(seqno, pcb->rcv_nxt, pcb->rcv_nxt + pcb->rcv_wnd)) {
757 /* If the SYN is in the window it is an error, send a reset */
758 tcp_rst(pcb, ackno, seqno + tcplen, ip_current_dest_addr(),
759 ip_current_src_addr(), tcphdr->dest, tcphdr->src);
760 return;
761 }
762 } else if (flags & TCP_FIN) {
763 /* - eighth, check the FIN bit: Remain in the TIME-WAIT state.
764 Restart the 2 MSL time-wait timeout.*/
765 pcb->tmr = tcp_ticks;
766 }
767
768 if ((tcplen > 0)) {
769 /* Acknowledge data, FIN or out-of-window SYN */
770 tcp_ack_now(pcb);
771 tcp_output(pcb);
772 }
773 return;
774}
775
776/**
777 * Implements the TCP state machine. Called by tcp_input. In some
778 * states tcp_receive() is called to receive data. The tcp_seg
779 * argument will be freed by the caller (tcp_input()) unless the
780 * recv_data pointer in the pcb is set.
781 *
782 * @param pcb the tcp_pcb for which a segment arrived
783 *
784 * @note the segment which arrived is saved in global variables, therefore only the pcb
785 * involved is passed as a parameter to this function
786 */
787static err_t
788tcp_process(struct tcp_pcb *pcb)
789{
790 struct tcp_seg *rseg;
791 u8_t acceptable = 0;
792 err_t err;
793
794 err = ERR_OK;
795
796 LWIP_ASSERT("tcp_process: invalid pcb", pcb != NULL);
797
798 /* Process incoming RST segments. */
799 if (flags & TCP_RST) {
800 /* First, determine if the reset is acceptable. */
801 if (pcb->state == SYN_SENT) {
802 /* "In the SYN-SENT state (a RST received in response to an initial SYN),
803 the RST is acceptable if the ACK field acknowledges the SYN." */
804 if (ackno == pcb->snd_nxt) {
805 acceptable = 1;
806 }
807 } else {
808 /* "In all states except SYN-SENT, all reset (RST) segments are validated
809 by checking their SEQ-fields." */
810 if (seqno == pcb->rcv_nxt) {
811 acceptable = 1;
812 } else if (TCP_SEQ_BETWEEN(seqno, pcb->rcv_nxt,
813 pcb->rcv_nxt + pcb->rcv_wnd)) {
814 /* If the sequence number is inside the window, we send a challenge ACK
815 and wait for a re-send with matching sequence number.
816 This follows RFC 5961 section 3.2 and addresses CVE-2004-0230
817 (RST spoofing attack), which is present in RFC 793 RST handling. */
818 tcp_ack_now(pcb);
819 }
820 }
821
822 if (acceptable) {
823 LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_process: Connection RESET\n"));
824 LWIP_ASSERT("tcp_input: pcb->state != CLOSED", pcb->state != CLOSED);
825 recv_flags |= TF_RESET;
826 tcp_clear_flags(pcb, TF_ACK_DELAY);
827 return ERR_RST;
828 } else {
829 LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_process: unacceptable reset seqno %"U32_F" rcv_nxt %"U32_F"\n",
830 seqno, pcb->rcv_nxt));
831 LWIP_DEBUGF(TCP_DEBUG, ("tcp_process: unacceptable reset seqno %"U32_F" rcv_nxt %"U32_F"\n",
832 seqno, pcb->rcv_nxt));
833 return ERR_OK;
834 }
835 }
836
837 if ((flags & TCP_SYN) && (pcb->state != SYN_SENT && pcb->state != SYN_RCVD)) {
838 /* Cope with new connection attempt after remote end crashed */
839 tcp_ack_now(pcb);
840 return ERR_OK;
841 }
842
843 if ((pcb->flags & TF_RXCLOSED) == 0) {
844 /* Update the PCB (in)activity timer unless rx is closed (see tcp_shutdown) */
845 pcb->tmr = tcp_ticks;
846 }
847 pcb->keep_cnt_sent = 0;
848 pcb->persist_probe = 0;
849
850 tcp_parseopt(pcb);
851
852 /* Do different things depending on the TCP state. */
853 switch (pcb->state) {
854 case SYN_SENT:
855 LWIP_DEBUGF(TCP_INPUT_DEBUG, ("SYN-SENT: ackno %"U32_F" pcb->snd_nxt %"U32_F" unacked %"U32_F"\n", ackno,
856 pcb->snd_nxt, lwip_ntohl(pcb->unacked->tcphdr->seqno)));
857 /* received SYN ACK with expected sequence number? */
858 if ((flags & TCP_ACK) && (flags & TCP_SYN)
859 && (ackno == pcb->lastack + 1)) {
860 pcb->rcv_nxt = seqno + 1;
861 pcb->rcv_ann_right_edge = pcb->rcv_nxt;
862 pcb->lastack = ackno;
863 pcb->snd_wnd = tcphdr->wnd;
864 pcb->snd_wnd_max = pcb->snd_wnd;
865 pcb->snd_wl1 = seqno - 1; /* initialise to seqno - 1 to force window update */
866 pcb->state = ESTABLISHED;
867
868#if TCP_CALCULATE_EFF_SEND_MSS
869 pcb->mss = tcp_eff_send_mss(pcb->mss, &pcb->local_ip, &pcb->remote_ip);
870#endif /* TCP_CALCULATE_EFF_SEND_MSS */
871
872 pcb->cwnd = LWIP_TCP_CALC_INITIAL_CWND(pcb->mss);
873 LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_process (SENT): cwnd %"TCPWNDSIZE_F
874 " ssthresh %"TCPWNDSIZE_F"\n",
875 pcb->cwnd, pcb->ssthresh));
876 LWIP_ASSERT("pcb->snd_queuelen > 0", (pcb->snd_queuelen > 0));
877 --pcb->snd_queuelen;
878 LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_process: SYN-SENT --queuelen %"TCPWNDSIZE_F"\n", (tcpwnd_size_t)pcb->snd_queuelen));
879 rseg = pcb->unacked;
880 if (rseg == NULL) {
881 /* might happen if tcp_output fails in tcp_rexmit_rto()
882 in which case the segment is on the unsent list */
883 rseg = pcb->unsent;
884 LWIP_ASSERT("no segment to free", rseg != NULL);
885 pcb->unsent = rseg->next;
886 } else {
887 pcb->unacked = rseg->next;
888 }
889 tcp_seg_free(rseg);
890
891 /* If there's nothing left to acknowledge, stop the retransmit
892 timer, otherwise reset it to start again */
893 if (pcb->unacked == NULL) {
894 pcb->rtime = -1;
895 } else {
896 pcb->rtime = 0;
897 pcb->nrtx = 0;
898 }
899
900 /* Call the user specified function to call when successfully
901 * connected. */
902 TCP_EVENT_CONNECTED(pcb, ERR_OK, err);
903 if (err == ERR_ABRT) {
904 return ERR_ABRT;
905 }
906 tcp_ack_now(pcb);
907 }
908 /* received ACK? possibly a half-open connection */
909 else if (flags & TCP_ACK) {
910 /* send a RST to bring the other side in a non-synchronized state. */
911 tcp_rst(pcb, ackno, seqno + tcplen, ip_current_dest_addr(),
912 ip_current_src_addr(), tcphdr->dest, tcphdr->src);
913 /* Resend SYN immediately (don't wait for rto timeout) to establish
914 connection faster, but do not send more SYNs than we otherwise would
915 have, or we might get caught in a loop on loopback interfaces. */
916 if (pcb->nrtx < TCP_SYNMAXRTX) {
917 pcb->rtime = 0;
918 tcp_rexmit_rto(pcb);
919 }
920 }
921 break;
922 case SYN_RCVD:
923 if (flags & TCP_ACK) {
924 /* expected ACK number? */
925 if (TCP_SEQ_BETWEEN(ackno, pcb->lastack + 1, pcb->snd_nxt)) {
926 pcb->state = ESTABLISHED;
927 LWIP_DEBUGF(TCP_DEBUG, ("TCP connection established %"U16_F" -> %"U16_F".\n", inseg.tcphdr->src, inseg.tcphdr->dest));
928#if LWIP_CALLBACK_API || TCP_LISTEN_BACKLOG
929 if (pcb->listener == NULL) {
930 /* listen pcb might be closed by now */
931 err = ERR_VAL;
932 } else
933#endif /* LWIP_CALLBACK_API || TCP_LISTEN_BACKLOG */
934 {
935#if LWIP_CALLBACK_API
936 LWIP_ASSERT("pcb->listener->accept != NULL", pcb->listener->accept != NULL);
937#endif
938 tcp_backlog_accepted(pcb);
939 /* Call the accept function. */
940 TCP_EVENT_ACCEPT(pcb->listener, pcb, pcb->callback_arg, ERR_OK, err);
941 }
942 if (err != ERR_OK) {
943 /* If the accept function returns with an error, we abort
944 * the connection. */
945 /* Already aborted? */
946 if (err != ERR_ABRT) {
947 tcp_abort(pcb);
948 }
949 return ERR_ABRT;
950 }
951 /* If there was any data contained within this ACK,
952 * we'd better pass it on to the application as well. */
953 tcp_receive(pcb);
954
955 /* Prevent ACK for SYN to generate a sent event */
956 if (recv_acked != 0) {
957 recv_acked--;
958 }
959
960 pcb->cwnd = LWIP_TCP_CALC_INITIAL_CWND(pcb->mss);
961 LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_process (SYN_RCVD): cwnd %"TCPWNDSIZE_F
962 " ssthresh %"TCPWNDSIZE_F"\n",
963 pcb->cwnd, pcb->ssthresh));
964
965 if (recv_flags & TF_GOT_FIN) {
966 tcp_ack_now(pcb);
967 pcb->state = CLOSE_WAIT;
968 }
969 } else {
970 /* incorrect ACK number, send RST */
971 tcp_rst(pcb, ackno, seqno + tcplen, ip_current_dest_addr(),
972 ip_current_src_addr(), tcphdr->dest, tcphdr->src);
973 }
974 } else if ((flags & TCP_SYN) && (seqno == pcb->rcv_nxt - 1)) {
975 /* Looks like another copy of the SYN - retransmit our SYN-ACK */
976 tcp_rexmit(pcb);
977 }
978 break;
979 case CLOSE_WAIT:
980 /* FALLTHROUGH */
981 case ESTABLISHED:
982 tcp_receive(pcb);
983 if (recv_flags & TF_GOT_FIN) { /* passive close */
984 tcp_ack_now(pcb);
985 pcb->state = CLOSE_WAIT;
986 }
987 break;
988 case FIN_WAIT_1:
989 tcp_receive(pcb);
990 if (recv_flags & TF_GOT_FIN) {
991 if ((flags & TCP_ACK) && (ackno == pcb->snd_nxt) &&
992 pcb->unsent == NULL) {
993 LWIP_DEBUGF(TCP_DEBUG,
994 ("TCP connection closed: FIN_WAIT_1 %"U16_F" -> %"U16_F".\n", inseg.tcphdr->src, inseg.tcphdr->dest));
995 tcp_ack_now(pcb);
996 tcp_pcb_purge(pcb);
997 TCP_RMV_ACTIVE(pcb);
998 pcb->state = TIME_WAIT;
999 TCP_REG(&tcp_tw_pcbs, pcb);
1000 } else {
1001 tcp_ack_now(pcb);
1002 pcb->state = CLOSING;
1003 }
1004 } else if ((flags & TCP_ACK) && (ackno == pcb->snd_nxt) &&
1005 pcb->unsent == NULL) {
1006 pcb->state = FIN_WAIT_2;
1007 }
1008 break;
1009 case FIN_WAIT_2:
1010 tcp_receive(pcb);
1011 if (recv_flags & TF_GOT_FIN) {
1012 LWIP_DEBUGF(TCP_DEBUG, ("TCP connection closed: FIN_WAIT_2 %"U16_F" -> %"U16_F".\n", inseg.tcphdr->src, inseg.tcphdr->dest));
1013 tcp_ack_now(pcb);
1014 tcp_pcb_purge(pcb);
1015 TCP_RMV_ACTIVE(pcb);
1016 pcb->state = TIME_WAIT;
1017 TCP_REG(&tcp_tw_pcbs, pcb);
1018 }
1019 break;
1020 case CLOSING:
1021 tcp_receive(pcb);
1022 if ((flags & TCP_ACK) && ackno == pcb->snd_nxt && pcb->unsent == NULL) {
1023 LWIP_DEBUGF(TCP_DEBUG, ("TCP connection closed: CLOSING %"U16_F" -> %"U16_F".\n", inseg.tcphdr->src, inseg.tcphdr->dest));
1024 tcp_pcb_purge(pcb);
1025 TCP_RMV_ACTIVE(pcb);
1026 pcb->state = TIME_WAIT;
1027 TCP_REG(&tcp_tw_pcbs, pcb);
1028 }
1029 break;
1030 case LAST_ACK:
1031 tcp_receive(pcb);
1032 if ((flags & TCP_ACK) && ackno == pcb->snd_nxt && pcb->unsent == NULL) {
1033 LWIP_DEBUGF(TCP_DEBUG, ("TCP connection closed: LAST_ACK %"U16_F" -> %"U16_F".\n", inseg.tcphdr->src, inseg.tcphdr->dest));
1034 /* bugfix #21699: don't set pcb->state to CLOSED here or we risk leaking segments */
1035 recv_flags |= TF_CLOSED;
1036 }
1037 break;
1038 default:
1039 break;
1040 }
1041 return ERR_OK;
1042}
1043
1044#if TCP_QUEUE_OOSEQ
1045/**
1046 * Insert segment into the list (segments covered with new one will be deleted)
1047 *
1048 * Called from tcp_receive()
1049 */
1050static void
1051tcp_oos_insert_segment(struct tcp_seg *cseg, struct tcp_seg *next)
1052{
1053 struct tcp_seg *old_seg;
1054
1055 LWIP_ASSERT("tcp_oos_insert_segment: invalid cseg", cseg != NULL);
1056
1057 if (TCPH_FLAGS(cseg->tcphdr) & TCP_FIN) {
1058 /* received segment overlaps all following segments */
1059 tcp_segs_free(next);
1060 next = NULL;
1061 } else {
1062 /* delete some following segments
1063 oos queue may have segments with FIN flag */
1064 while (next &&
1065 TCP_SEQ_GEQ((seqno + cseg->len),
1066 (next->tcphdr->seqno + next->len))) {
1067 /* cseg with FIN already processed */
1068 if (TCPH_FLAGS(next->tcphdr) & TCP_FIN) {
1069 TCPH_SET_FLAG(cseg->tcphdr, TCP_FIN);
1070 }
1071 old_seg = next;
1072 next = next->next;
1073 tcp_seg_free(old_seg);
1074 }
1075 if (next &&
1076 TCP_SEQ_GT(seqno + cseg->len, next->tcphdr->seqno)) {
1077 /* We need to trim the incoming segment. */
1078 cseg->len = (u16_t)(next->tcphdr->seqno - seqno);
1079 pbuf_realloc(cseg->p, cseg->len);
1080 }
1081 }
1082 cseg->next = next;
1083}
1084#endif /* TCP_QUEUE_OOSEQ */
1085
1086/** Remove segments from a list if the incoming ACK acknowledges them */
1087static struct tcp_seg *
1088tcp_free_acked_segments(struct tcp_pcb *pcb, struct tcp_seg *seg_list, const char *dbg_list_name,
1089 struct tcp_seg *dbg_other_seg_list)
1090{
1091 struct tcp_seg *next;
1092 u16_t clen;
1093
1094 LWIP_UNUSED_ARG(dbg_list_name);
1095 LWIP_UNUSED_ARG(dbg_other_seg_list);
1096
1097 while (seg_list != NULL &&
1098 TCP_SEQ_LEQ(lwip_ntohl(seg_list->tcphdr->seqno) +
1099 TCP_TCPLEN(seg_list), ackno)) {
1100 LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: removing %"U32_F":%"U32_F" from pcb->%s\n",
1101 lwip_ntohl(seg_list->tcphdr->seqno),
1102 lwip_ntohl(seg_list->tcphdr->seqno) + TCP_TCPLEN(seg_list),
1103 dbg_list_name));
1104
1105 next = seg_list;
1106 seg_list = seg_list->next;
1107
1108 clen = pbuf_clen(next->p);
1109 LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_receive: queuelen %"TCPWNDSIZE_F" ... ",
1110 (tcpwnd_size_t)pcb->snd_queuelen));
1111 LWIP_ASSERT("pcb->snd_queuelen >= pbuf_clen(next->p)", (pcb->snd_queuelen >= clen));
1112
1113 pcb->snd_queuelen = (u16_t)(pcb->snd_queuelen - clen);
1114 recv_acked = (tcpwnd_size_t)(recv_acked + next->len);
1115 tcp_seg_free(next);
1116
1117 LWIP_DEBUGF(TCP_QLEN_DEBUG, ("%"TCPWNDSIZE_F" (after freeing %s)\n",
1118 (tcpwnd_size_t)pcb->snd_queuelen,
1119 dbg_list_name));
1120 if (pcb->snd_queuelen != 0) {
1121 LWIP_ASSERT("tcp_receive: valid queue length",
1122 seg_list != NULL || dbg_other_seg_list != NULL);
1123 }
1124 }
1125 return seg_list;
1126}
1127
1128/**
1129 * Called by tcp_process. Checks if the given segment is an ACK for outstanding
1130 * data, and if so frees the memory of the buffered data. Next, it places the
1131 * segment on any of the receive queues (pcb->recved or pcb->ooseq). If the segment
1132 * is buffered, the pbuf is referenced by pbuf_ref so that it will not be freed until
1133 * it has been removed from the buffer.
1134 *
1135 * If the incoming segment constitutes an ACK for a segment that was used for RTT
1136 * estimation, the RTT is estimated here as well.
1137 *
1138 * Called from tcp_process().
1139 */
1140static void
1141tcp_receive(struct tcp_pcb *pcb)
1142{
1143 s16_t m;
1144 u32_t right_wnd_edge;
1145 int found_dupack = 0;
1146
1147 LWIP_ASSERT("tcp_receive: invalid pcb", pcb != NULL);
1148 LWIP_ASSERT("tcp_receive: wrong state", pcb->state >= ESTABLISHED);
1149
1150 if (flags & TCP_ACK) {
1151 right_wnd_edge = pcb->snd_wnd + pcb->snd_wl2;
1152
1153 /* Update window. */
1154 if (TCP_SEQ_LT(pcb->snd_wl1, seqno) ||
1155 (pcb->snd_wl1 == seqno && TCP_SEQ_LT(pcb->snd_wl2, ackno)) ||
1156 (pcb->snd_wl2 == ackno && (u32_t)SND_WND_SCALE(pcb, tcphdr->wnd) > pcb->snd_wnd)) {
1157 pcb->snd_wnd = SND_WND_SCALE(pcb, tcphdr->wnd);
1158 /* keep track of the biggest window announced by the remote host to calculate
1159 the maximum segment size */
1160 if (pcb->snd_wnd_max < pcb->snd_wnd) {
1161 pcb->snd_wnd_max = pcb->snd_wnd;
1162 }
1163 pcb->snd_wl1 = seqno;
1164 pcb->snd_wl2 = ackno;
1165 LWIP_DEBUGF(TCP_WND_DEBUG, ("tcp_receive: window update %"TCPWNDSIZE_F"\n", pcb->snd_wnd));
1166#if TCP_WND_DEBUG
1167 } else {
1168 if (pcb->snd_wnd != (tcpwnd_size_t)SND_WND_SCALE(pcb, tcphdr->wnd)) {
1169 LWIP_DEBUGF(TCP_WND_DEBUG,
1170 ("tcp_receive: no window update lastack %"U32_F" ackno %"
1171 U32_F" wl1 %"U32_F" seqno %"U32_F" wl2 %"U32_F"\n",
1172 pcb->lastack, ackno, pcb->snd_wl1, seqno, pcb->snd_wl2));
1173 }
1174#endif /* TCP_WND_DEBUG */
1175 }
1176
1177 /* (From Stevens TCP/IP Illustrated Vol II, p970.) Its only a
1178 * duplicate ack if:
1179 * 1) It doesn't ACK new data
1180 * 2) length of received packet is zero (i.e. no payload)
1181 * 3) the advertised window hasn't changed
1182 * 4) There is outstanding unacknowledged data (retransmission timer running)
1183 * 5) The ACK is == biggest ACK sequence number so far seen (snd_una)
1184 *
1185 * If it passes all five, should process as a dupack:
1186 * a) dupacks < 3: do nothing
1187 * b) dupacks == 3: fast retransmit
1188 * c) dupacks > 3: increase cwnd
1189 *
1190 * If it only passes 1-3, should reset dupack counter (and add to
1191 * stats, which we don't do in lwIP)
1192 *
1193 * If it only passes 1, should reset dupack counter
1194 *
1195 */
1196
1197 /* Clause 1 */
1198 if (TCP_SEQ_LEQ(ackno, pcb->lastack)) {
1199 /* Clause 2 */
1200 if (tcplen == 0) {
1201 /* Clause 3 */
1202 if (pcb->snd_wl2 + pcb->snd_wnd == right_wnd_edge) {
1203 /* Clause 4 */
1204 if (pcb->rtime >= 0) {
1205 /* Clause 5 */
1206 if (pcb->lastack == ackno) {
1207 found_dupack = 1;
1208 if ((u8_t)(pcb->dupacks + 1) > pcb->dupacks) {
1209 ++pcb->dupacks;
1210 }
1211 if (pcb->dupacks > 3) {
1212 /* Inflate the congestion window */
1213 TCP_WND_INC(pcb->cwnd, pcb->mss);
1214 }
1215 if (pcb->dupacks >= 3) {
1216 /* Do fast retransmit (checked via TF_INFR, not via dupacks count) */
1217 tcp_rexmit_fast(pcb);
1218 }
1219 }
1220 }
1221 }
1222 }
1223 /* If Clause (1) or more is true, but not a duplicate ack, reset
1224 * count of consecutive duplicate acks */
1225 if (!found_dupack) {
1226 pcb->dupacks = 0;
1227 }
1228 } else if (TCP_SEQ_BETWEEN(ackno, pcb->lastack + 1, pcb->snd_nxt)) {
1229 /* We come here when the ACK acknowledges new data. */
1230 tcpwnd_size_t acked;
1231
1232 /* Reset the "IN Fast Retransmit" flag, since we are no longer
1233 in fast retransmit. Also reset the congestion window to the
1234 slow start threshold. */
1235 if (pcb->flags & TF_INFR) {
1236 tcp_clear_flags(pcb, TF_INFR);
1237 pcb->cwnd = pcb->ssthresh;
1238 pcb->bytes_acked = 0;
1239 }
1240
1241 /* Reset the number of retransmissions. */
1242 pcb->nrtx = 0;
1243
1244 /* Reset the retransmission time-out. */
1245 pcb->rto = (s16_t)((pcb->sa >> 3) + pcb->sv);
1246
1247 /* Record how much data this ACK acks */
1248 acked = (tcpwnd_size_t)(ackno - pcb->lastack);
1249
1250 /* Reset the fast retransmit variables. */
1251 pcb->dupacks = 0;
1252 pcb->lastack = ackno;
1253
1254 /* Update the congestion control variables (cwnd and
1255 ssthresh). */
1256 if (pcb->state >= ESTABLISHED) {
1257 if (pcb->cwnd < pcb->ssthresh) {
1258 tcpwnd_size_t increase;
1259 /* limit to 1 SMSS segment during period following RTO */
1260 u8_t num_seg = (pcb->flags & TF_RTO) ? 1 : 2;
1261 /* RFC 3465, section 2.2 Slow Start */
1262 increase = LWIP_MIN(acked, (tcpwnd_size_t)(num_seg * pcb->mss));
1263 TCP_WND_INC(pcb->cwnd, increase);
1264 LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_receive: slow start cwnd %"TCPWNDSIZE_F"\n", pcb->cwnd));
1265 } else {
1266 /* RFC 3465, section 2.1 Congestion Avoidance */
1267 TCP_WND_INC(pcb->bytes_acked, acked);
1268 if (pcb->bytes_acked >= pcb->cwnd) {
1269 pcb->bytes_acked = (tcpwnd_size_t)(pcb->bytes_acked - pcb->cwnd);
1270 TCP_WND_INC(pcb->cwnd, pcb->mss);
1271 }
1272 LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_receive: congestion avoidance cwnd %"TCPWNDSIZE_F"\n", pcb->cwnd));
1273 }
1274 }
1275 LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: ACK for %"U32_F", unacked->seqno %"U32_F":%"U32_F"\n",
1276 ackno,
1277 pcb->unacked != NULL ?
1278 lwip_ntohl(pcb->unacked->tcphdr->seqno) : 0,
1279 pcb->unacked != NULL ?
1280 lwip_ntohl(pcb->unacked->tcphdr->seqno) + TCP_TCPLEN(pcb->unacked) : 0));
1281
1282 /* Remove segment from the unacknowledged list if the incoming
1283 ACK acknowledges them. */
1284 pcb->unacked = tcp_free_acked_segments(pcb, pcb->unacked, "unacked", pcb->unsent);
1285 /* We go through the ->unsent list to see if any of the segments
1286 on the list are acknowledged by the ACK. This may seem
1287 strange since an "unsent" segment shouldn't be acked. The
1288 rationale is that lwIP puts all outstanding segments on the
1289 ->unsent list after a retransmission, so these segments may
1290 in fact have been sent once. */
1291 pcb->unsent = tcp_free_acked_segments(pcb, pcb->unsent, "unsent", pcb->unacked);
1292
1293 /* If there's nothing left to acknowledge, stop the retransmit
1294 timer, otherwise reset it to start again */
1295 if (pcb->unacked == NULL) {
1296 pcb->rtime = -1;
1297 } else {
1298 pcb->rtime = 0;
1299 }
1300
1301 pcb->polltmr = 0;
1302
1303#if TCP_OVERSIZE
1304 if (pcb->unsent == NULL) {
1305 pcb->unsent_oversize = 0;
1306 }
1307#endif /* TCP_OVERSIZE */
1308
1309#if LWIP_IPV6 && LWIP_ND6_TCP_REACHABILITY_HINTS
1310 if (ip_current_is_v6()) {
1311 /* Inform neighbor reachability of forward progress. */
1312 nd6_reachability_hint(ip6_current_src_addr());
1313 }
1314#endif /* LWIP_IPV6 && LWIP_ND6_TCP_REACHABILITY_HINTS*/
1315
1316 pcb->snd_buf = (tcpwnd_size_t)(pcb->snd_buf + recv_acked);
1317 /* check if this ACK ends our retransmission of in-flight data */
1318 if (pcb->flags & TF_RTO) {
1319 /* RTO is done if
1320 1) both queues are empty or
1321 2) unacked is empty and unsent head contains data not part of RTO or
1322 3) unacked head contains data not part of RTO */
1323 if (pcb->unacked == NULL) {
1324 if ((pcb->unsent == NULL) ||
1325 (TCP_SEQ_LEQ(pcb->rto_end, lwip_ntohl(pcb->unsent->tcphdr->seqno)))) {
1326 tcp_clear_flags(pcb, TF_RTO);
1327 }
1328 } else if (TCP_SEQ_LEQ(pcb->rto_end, lwip_ntohl(pcb->unacked->tcphdr->seqno))) {
1329 tcp_clear_flags(pcb, TF_RTO);
1330 }
1331 }
1332 /* End of ACK for new data processing. */
1333 } else {
1334 /* Out of sequence ACK, didn't really ack anything */
1335 tcp_send_empty_ack(pcb);
1336 }
1337
1338 LWIP_DEBUGF(TCP_RTO_DEBUG, ("tcp_receive: pcb->rttest %"U32_F" rtseq %"U32_F" ackno %"U32_F"\n",
1339 pcb->rttest, pcb->rtseq, ackno));
1340
1341 /* RTT estimation calculations. This is done by checking if the
1342 incoming segment acknowledges the segment we use to take a
1343 round-trip time measurement. */
1344 if (pcb->rttest && TCP_SEQ_LT(pcb->rtseq, ackno)) {
1345 /* diff between this shouldn't exceed 32K since this are tcp timer ticks
1346 and a round-trip shouldn't be that long... */
1347 m = (s16_t)(tcp_ticks - pcb->rttest);
1348
1349 LWIP_DEBUGF(TCP_RTO_DEBUG, ("tcp_receive: experienced rtt %"U16_F" ticks (%"U16_F" msec).\n",
1350 m, (u16_t)(m * TCP_SLOW_INTERVAL)));
1351
1352 /* This is taken directly from VJs original code in his paper */
1353 m = (s16_t)(m - (pcb->sa >> 3));
1354 pcb->sa = (s16_t)(pcb->sa + m);
1355 if (m < 0) {
1356 m = (s16_t) - m;
1357 }
1358 m = (s16_t)(m - (pcb->sv >> 2));
1359 pcb->sv = (s16_t)(pcb->sv + m);
1360 pcb->rto = (s16_t)((pcb->sa >> 3) + pcb->sv);
1361
1362 LWIP_DEBUGF(TCP_RTO_DEBUG, ("tcp_receive: RTO %"U16_F" (%"U16_F" milliseconds)\n",
1363 pcb->rto, (u16_t)(pcb->rto * TCP_SLOW_INTERVAL)));
1364
1365 pcb->rttest = 0;
1366 }
1367 }
1368
1369 /* If the incoming segment contains data, we must process it
1370 further unless the pcb already received a FIN.
1371 (RFC 793, chapter 3.9, "SEGMENT ARRIVES" in states CLOSE-WAIT, CLOSING,
1372 LAST-ACK and TIME-WAIT: "Ignore the segment text.") */
1373 if ((tcplen > 0) && (pcb->state < CLOSE_WAIT)) {
1374 /* This code basically does three things:
1375
1376 +) If the incoming segment contains data that is the next
1377 in-sequence data, this data is passed to the application. This
1378 might involve trimming the first edge of the data. The rcv_nxt
1379 variable and the advertised window are adjusted.
1380
1381 +) If the incoming segment has data that is above the next
1382 sequence number expected (->rcv_nxt), the segment is placed on
1383 the ->ooseq queue. This is done by finding the appropriate
1384 place in the ->ooseq queue (which is ordered by sequence
1385 number) and trim the segment in both ends if needed. An
1386 immediate ACK is sent to indicate that we received an
1387 out-of-sequence segment.
1388
1389 +) Finally, we check if the first segment on the ->ooseq queue
1390 now is in sequence (i.e., if rcv_nxt >= ooseq->seqno). If
1391 rcv_nxt > ooseq->seqno, we must trim the first edge of the
1392 segment on ->ooseq before we adjust rcv_nxt. The data in the
1393 segments that are now on sequence are chained onto the
1394 incoming segment so that we only need to call the application
1395 once.
1396 */
1397
1398 /* First, we check if we must trim the first edge. We have to do
1399 this if the sequence number of the incoming segment is less
1400 than rcv_nxt, and the sequence number plus the length of the
1401 segment is larger than rcv_nxt. */
1402 /* if (TCP_SEQ_LT(seqno, pcb->rcv_nxt)) {
1403 if (TCP_SEQ_LT(pcb->rcv_nxt, seqno + tcplen)) {*/
1404 if (TCP_SEQ_BETWEEN(pcb->rcv_nxt, seqno + 1, seqno + tcplen - 1)) {
1405 /* Trimming the first edge is done by pushing the payload
1406 pointer in the pbuf downwards. This is somewhat tricky since
1407 we do not want to discard the full contents of the pbuf up to
1408 the new starting point of the data since we have to keep the
1409 TCP header which is present in the first pbuf in the chain.
1410
1411 What is done is really quite a nasty hack: the first pbuf in
1412 the pbuf chain is pointed to by inseg.p. Since we need to be
1413 able to deallocate the whole pbuf, we cannot change this
1414 inseg.p pointer to point to any of the later pbufs in the
1415 chain. Instead, we point the ->payload pointer in the first
1416 pbuf to data in one of the later pbufs. We also set the
1417 inseg.data pointer to point to the right place. This way, the
1418 ->p pointer will still point to the first pbuf, but the
1419 ->p->payload pointer will point to data in another pbuf.
1420
1421 After we are done with adjusting the pbuf pointers we must
1422 adjust the ->data pointer in the seg and the segment
1423 length.*/
1424
1425 struct pbuf *p = inseg.p;
1426 u32_t off32 = pcb->rcv_nxt - seqno;
1427 u16_t new_tot_len, off;
1428 LWIP_ASSERT("inseg.p != NULL", inseg.p);
1429 LWIP_ASSERT("insane offset!", (off32 < 0xffff));
1430 off = (u16_t)off32;
1431 LWIP_ASSERT("pbuf too short!", (((s32_t)inseg.p->tot_len) >= off));
1432 inseg.len -= off;
1433 new_tot_len = (u16_t)(inseg.p->tot_len - off);
1434 while (p->len < off) {
1435 off -= p->len;
1436 /* all pbufs up to and including this one have len==0, so tot_len is equal */
1437 p->tot_len = new_tot_len;
1438 p->len = 0;
1439 p = p->next;
1440 }
1441 /* cannot fail... */
1442 pbuf_remove_header(p, off);
1443 inseg.tcphdr->seqno = seqno = pcb->rcv_nxt;
1444 } else {
1445 if (TCP_SEQ_LT(seqno, pcb->rcv_nxt)) {
1446 /* the whole segment is < rcv_nxt */
1447 /* must be a duplicate of a packet that has already been correctly handled */
1448
1449 LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: duplicate seqno %"U32_F"\n", seqno));
1450 tcp_ack_now(pcb);
1451 }
1452 }
1453
1454 /* The sequence number must be within the window (above rcv_nxt
1455 and below rcv_nxt + rcv_wnd) in order to be further
1456 processed. */
1457 if (TCP_SEQ_BETWEEN(seqno, pcb->rcv_nxt,
1458 pcb->rcv_nxt + pcb->rcv_wnd - 1)) {
1459 if (pcb->rcv_nxt == seqno) {
1460 /* The incoming segment is the next in sequence. We check if
1461 we have to trim the end of the segment and update rcv_nxt
1462 and pass the data to the application. */
1463 tcplen = TCP_TCPLEN(&inseg);
1464
1465 if (tcplen > pcb->rcv_wnd) {
1466 LWIP_DEBUGF(TCP_INPUT_DEBUG,
1467 ("tcp_receive: other end overran receive window"
1468 "seqno %"U32_F" len %"U16_F" right edge %"U32_F"\n",
1469 seqno, tcplen, pcb->rcv_nxt + pcb->rcv_wnd));
1470 if (TCPH_FLAGS(inseg.tcphdr) & TCP_FIN) {
1471 /* Must remove the FIN from the header as we're trimming
1472 * that byte of sequence-space from the packet */
1473 TCPH_FLAGS_SET(inseg.tcphdr, TCPH_FLAGS(inseg.tcphdr) & ~(unsigned int)TCP_FIN);
1474 }
1475 /* Adjust length of segment to fit in the window. */
1476 TCPWND_CHECK16(pcb->rcv_wnd);
1477 inseg.len = (u16_t)pcb->rcv_wnd;
1478 if (TCPH_FLAGS(inseg.tcphdr) & TCP_SYN) {
1479 inseg.len -= 1;
1480 }
1481 pbuf_realloc(inseg.p, inseg.len);
1482 tcplen = TCP_TCPLEN(&inseg);
1483 LWIP_ASSERT("tcp_receive: segment not trimmed correctly to rcv_wnd\n",
1484 (seqno + tcplen) == (pcb->rcv_nxt + pcb->rcv_wnd));
1485 }
1486#if TCP_QUEUE_OOSEQ
1487 /* Received in-sequence data, adjust ooseq data if:
1488 - FIN has been received or
1489 - inseq overlaps with ooseq */
1490 if (pcb->ooseq != NULL) {
1491 if (TCPH_FLAGS(inseg.tcphdr) & TCP_FIN) {
1492 LWIP_DEBUGF(TCP_INPUT_DEBUG,
1493 ("tcp_receive: received in-order FIN, binning ooseq queue\n"));
1494 /* Received in-order FIN means anything that was received
1495 * out of order must now have been received in-order, so
1496 * bin the ooseq queue */
1497 while (pcb->ooseq != NULL) {
1498 struct tcp_seg *old_ooseq = pcb->ooseq;
1499 pcb->ooseq = pcb->ooseq->next;
1500 tcp_seg_free(old_ooseq);
1501 }
1502 } else {
1503 struct tcp_seg *next = pcb->ooseq;
1504 /* Remove all segments on ooseq that are covered by inseg already.
1505 * FIN is copied from ooseq to inseg if present. */
1506 while (next &&
1507 TCP_SEQ_GEQ(seqno + tcplen,
1508 next->tcphdr->seqno + next->len)) {
1509 struct tcp_seg *tmp;
1510 /* inseg cannot have FIN here (already processed above) */
1511 if ((TCPH_FLAGS(next->tcphdr) & TCP_FIN) != 0 &&
1512 (TCPH_FLAGS(inseg.tcphdr) & TCP_SYN) == 0) {
1513 TCPH_SET_FLAG(inseg.tcphdr, TCP_FIN);
1514 tcplen = TCP_TCPLEN(&inseg);
1515 }
1516 tmp = next;
1517 next = next->next;
1518 tcp_seg_free(tmp);
1519 }
1520 /* Now trim right side of inseg if it overlaps with the first
1521 * segment on ooseq */
1522 if (next &&
1523 TCP_SEQ_GT(seqno + tcplen,
1524 next->tcphdr->seqno)) {
1525 /* inseg cannot have FIN here (already processed above) */
1526 inseg.len = (u16_t)(next->tcphdr->seqno - seqno);
1527 if (TCPH_FLAGS(inseg.tcphdr) & TCP_SYN) {
1528 inseg.len -= 1;
1529 }
1530 pbuf_realloc(inseg.p, inseg.len);
1531 tcplen = TCP_TCPLEN(&inseg);
1532 LWIP_ASSERT("tcp_receive: segment not trimmed correctly to ooseq queue\n",
1533 (seqno + tcplen) == next->tcphdr->seqno);
1534 }
1535 pcb->ooseq = next;
1536 }
1537 }
1538#endif /* TCP_QUEUE_OOSEQ */
1539
1540 pcb->rcv_nxt = seqno + tcplen;
1541
1542 /* Update the receiver's (our) window. */
1543 LWIP_ASSERT("tcp_receive: tcplen > rcv_wnd\n", pcb->rcv_wnd >= tcplen);
1544 pcb->rcv_wnd -= tcplen;
1545
1546 tcp_update_rcv_ann_wnd(pcb);
1547
1548 /* If there is data in the segment, we make preparations to
1549 pass this up to the application. The ->recv_data variable
1550 is used for holding the pbuf that goes to the
1551 application. The code for reassembling out-of-sequence data
1552 chains its data on this pbuf as well.
1553
1554 If the segment was a FIN, we set the TF_GOT_FIN flag that will
1555 be used to indicate to the application that the remote side has
1556 closed its end of the connection. */
1557 if (inseg.p->tot_len > 0) {
1558 recv_data = inseg.p;
1559 /* Since this pbuf now is the responsibility of the
1560 application, we delete our reference to it so that we won't
1561 (mistakingly) deallocate it. */
1562 inseg.p = NULL;
1563 }
1564 if (TCPH_FLAGS(inseg.tcphdr) & TCP_FIN) {
1565 LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: received FIN.\n"));
1566 recv_flags |= TF_GOT_FIN;
1567 }
1568
1569#if TCP_QUEUE_OOSEQ
1570 /* We now check if we have segments on the ->ooseq queue that
1571 are now in sequence. */
1572 while (pcb->ooseq != NULL &&
1573 pcb->ooseq->tcphdr->seqno == pcb->rcv_nxt) {
1574
1575 struct tcp_seg *cseg = pcb->ooseq;
1576 seqno = pcb->ooseq->tcphdr->seqno;
1577
1578 pcb->rcv_nxt += TCP_TCPLEN(cseg);
1579 LWIP_ASSERT("tcp_receive: ooseq tcplen > rcv_wnd\n",
1580 pcb->rcv_wnd >= TCP_TCPLEN(cseg));
1581 pcb->rcv_wnd -= TCP_TCPLEN(cseg);
1582
1583 tcp_update_rcv_ann_wnd(pcb);
1584
1585 if (cseg->p->tot_len > 0) {
1586 /* Chain this pbuf onto the pbuf that we will pass to
1587 the application. */
1588 /* With window scaling, this can overflow recv_data->tot_len, but
1589 that's not a problem since we explicitly fix that before passing
1590 recv_data to the application. */
1591 if (recv_data) {
1592 pbuf_cat(recv_data, cseg->p);
1593 } else {
1594 recv_data = cseg->p;
1595 }
1596 cseg->p = NULL;
1597 }
1598 if (TCPH_FLAGS(cseg->tcphdr) & TCP_FIN) {
1599 LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: dequeued FIN.\n"));
1600 recv_flags |= TF_GOT_FIN;
1601 if (pcb->state == ESTABLISHED) { /* force passive close or we can move to active close */
1602 pcb->state = CLOSE_WAIT;
1603 }
1604 }
1605
1606 pcb->ooseq = cseg->next;
1607 tcp_seg_free(cseg);
1608 }
1609#if LWIP_TCP_SACK_OUT
1610 if (pcb->flags & TF_SACK) {
1611 if (pcb->ooseq != NULL) {
1612 /* Some segments may have been removed from ooseq, let's remove all SACKs that
1613 describe anything before the new beginning of that list. */
1614 tcp_remove_sacks_lt(pcb, pcb->ooseq->tcphdr->seqno);
1615 } else if (LWIP_TCP_SACK_VALID(pcb, 0)) {
1616 /* ooseq has been cleared. Nothing to SACK */
1617 memset(pcb->rcv_sacks, 0, sizeof(pcb->rcv_sacks));
1618 }
1619 }
1620#endif /* LWIP_TCP_SACK_OUT */
1621#endif /* TCP_QUEUE_OOSEQ */
1622
1623
1624 /* Acknowledge the segment(s). */
1625 tcp_ack(pcb);
1626
1627#if LWIP_TCP_SACK_OUT
1628 if (LWIP_TCP_SACK_VALID(pcb, 0)) {
1629 /* Normally the ACK for the data received could be piggy-backed on a data packet,
1630 but lwIP currently does not support including SACKs in data packets. So we force
1631 it to respond with an empty ACK packet (only if there is at least one SACK to be sent).
1632 NOTE: tcp_send_empty_ack() on success clears the ACK flags (set by tcp_ack()) */
1633 tcp_send_empty_ack(pcb);
1634 }
1635#endif /* LWIP_TCP_SACK_OUT */
1636
1637#if LWIP_IPV6 && LWIP_ND6_TCP_REACHABILITY_HINTS
1638 if (ip_current_is_v6()) {
1639 /* Inform neighbor reachability of forward progress. */
1640 nd6_reachability_hint(ip6_current_src_addr());
1641 }
1642#endif /* LWIP_IPV6 && LWIP_ND6_TCP_REACHABILITY_HINTS*/
1643
1644 } else {
1645 /* We get here if the incoming segment is out-of-sequence. */
1646
1647#if TCP_QUEUE_OOSEQ
1648 /* We queue the segment on the ->ooseq queue. */
1649 if (pcb->ooseq == NULL) {
1650 pcb->ooseq = tcp_seg_copy(&inseg);
1651#if LWIP_TCP_SACK_OUT
1652 if (pcb->flags & TF_SACK) {
1653 /* All the SACKs should be invalid, so we can simply store the most recent one: */
1654 pcb->rcv_sacks[0].left = seqno;
1655 pcb->rcv_sacks[0].right = seqno + inseg.len;
1656 }
1657#endif /* LWIP_TCP_SACK_OUT */
1658 } else {
1659 /* If the queue is not empty, we walk through the queue and
1660 try to find a place where the sequence number of the
1661 incoming segment is between the sequence numbers of the
1662 previous and the next segment on the ->ooseq queue. That is
1663 the place where we put the incoming segment. If needed, we
1664 trim the second edges of the previous and the incoming
1665 segment so that it will fit into the sequence.
1666
1667 If the incoming segment has the same sequence number as a
1668 segment on the ->ooseq queue, we discard the segment that
1669 contains less data. */
1670
1671#if LWIP_TCP_SACK_OUT
1672 /* This is the left edge of the lowest possible SACK range.
1673 It may start before the newly received segment (possibly adjusted below). */
1674 u32_t sackbeg = TCP_SEQ_LT(seqno, pcb->ooseq->tcphdr->seqno) ? seqno : pcb->ooseq->tcphdr->seqno;
1675#endif /* LWIP_TCP_SACK_OUT */
1676 struct tcp_seg *next, *prev = NULL;
1677 for (next = pcb->ooseq; next != NULL; next = next->next) {
1678 if (seqno == next->tcphdr->seqno) {
1679 /* The sequence number of the incoming segment is the
1680 same as the sequence number of the segment on
1681 ->ooseq. We check the lengths to see which one to
1682 discard. */
1683 if (inseg.len > next->len) {
1684 /* The incoming segment is larger than the old
1685 segment. We replace some segments with the new
1686 one. */
1687 struct tcp_seg *cseg = tcp_seg_copy(&inseg);
1688 if (cseg != NULL) {
1689 if (prev != NULL) {
1690 prev->next = cseg;
1691 } else {
1692 pcb->ooseq = cseg;
1693 }
1694 tcp_oos_insert_segment(cseg, next);
1695 }
1696 break;
1697 } else {
1698 /* Either the lengths are the same or the incoming
1699 segment was smaller than the old one; in either
1700 case, we ditch the incoming segment. */
1701 break;
1702 }
1703 } else {
1704 if (prev == NULL) {
1705 if (TCP_SEQ_LT(seqno, next->tcphdr->seqno)) {
1706 /* The sequence number of the incoming segment is lower
1707 than the sequence number of the first segment on the
1708 queue. We put the incoming segment first on the
1709 queue. */
1710 struct tcp_seg *cseg = tcp_seg_copy(&inseg);
1711 if (cseg != NULL) {
1712 pcb->ooseq = cseg;
1713 tcp_oos_insert_segment(cseg, next);
1714 }
1715 break;
1716 }
1717 } else {
1718 /*if (TCP_SEQ_LT(prev->tcphdr->seqno, seqno) &&
1719 TCP_SEQ_LT(seqno, next->tcphdr->seqno)) {*/
1720 if (TCP_SEQ_BETWEEN(seqno, prev->tcphdr->seqno + 1, next->tcphdr->seqno - 1)) {
1721 /* The sequence number of the incoming segment is in
1722 between the sequence numbers of the previous and
1723 the next segment on ->ooseq. We trim trim the previous
1724 segment, delete next segments that included in received segment
1725 and trim received, if needed. */
1726 struct tcp_seg *cseg = tcp_seg_copy(&inseg);
1727 if (cseg != NULL) {
1728 if (TCP_SEQ_GT(prev->tcphdr->seqno + prev->len, seqno)) {
1729 /* We need to trim the prev segment. */
1730 prev->len = (u16_t)(seqno - prev->tcphdr->seqno);
1731 pbuf_realloc(prev->p, prev->len);
1732 }
1733 prev->next = cseg;
1734 tcp_oos_insert_segment(cseg, next);
1735 }
1736 break;
1737 }
1738 }
1739
1740#if LWIP_TCP_SACK_OUT
1741 /* The new segment goes after the 'next' one. If there is a "hole" in sequence numbers
1742 between 'prev' and the beginning of 'next', we want to move sackbeg. */
1743 if (prev != NULL && prev->tcphdr->seqno + prev->len != next->tcphdr->seqno) {
1744 sackbeg = next->tcphdr->seqno;
1745 }
1746#endif /* LWIP_TCP_SACK_OUT */
1747
1748 /* We don't use 'prev' below, so let's set it to current 'next'.
1749 This way even if we break the loop below, 'prev' will be pointing
1750 at the segment right in front of the newly added one. */
1751 prev = next;
1752
1753 /* If the "next" segment is the last segment on the
1754 ooseq queue, we add the incoming segment to the end
1755 of the list. */
1756 if (next->next == NULL &&
1757 TCP_SEQ_GT(seqno, next->tcphdr->seqno)) {
1758 if (TCPH_FLAGS(next->tcphdr) & TCP_FIN) {
1759 /* segment "next" already contains all data */
1760 break;
1761 }
1762 next->next = tcp_seg_copy(&inseg);
1763 if (next->next != NULL) {
1764 if (TCP_SEQ_GT(next->tcphdr->seqno + next->len, seqno)) {
1765 /* We need to trim the last segment. */
1766 next->len = (u16_t)(seqno - next->tcphdr->seqno);
1767 pbuf_realloc(next->p, next->len);
1768 }
1769 /* check if the remote side overruns our receive window */
1770 if (TCP_SEQ_GT((u32_t)tcplen + seqno, pcb->rcv_nxt + (u32_t)pcb->rcv_wnd)) {
1771 LWIP_DEBUGF(TCP_INPUT_DEBUG,
1772 ("tcp_receive: other end overran receive window"
1773 "seqno %"U32_F" len %"U16_F" right edge %"U32_F"\n",
1774 seqno, tcplen, pcb->rcv_nxt + pcb->rcv_wnd));
1775 if (TCPH_FLAGS(next->next->tcphdr) & TCP_FIN) {
1776 /* Must remove the FIN from the header as we're trimming
1777 * that byte of sequence-space from the packet */
1778 TCPH_FLAGS_SET(next->next->tcphdr, TCPH_FLAGS(next->next->tcphdr) & ~TCP_FIN);
1779 }
1780 /* Adjust length of segment to fit in the window. */
1781 next->next->len = (u16_t)(pcb->rcv_nxt + pcb->rcv_wnd - seqno);
1782 pbuf_realloc(next->next->p, next->next->len);
1783 tcplen = TCP_TCPLEN(next->next);
1784 LWIP_ASSERT("tcp_receive: segment not trimmed correctly to rcv_wnd\n",
1785 (seqno + tcplen) == (pcb->rcv_nxt + pcb->rcv_wnd));
1786 }
1787 }
1788 break;
1789 }
1790 }
1791 }
1792
1793#if LWIP_TCP_SACK_OUT
1794 if (pcb->flags & TF_SACK) {
1795 if (prev == NULL) {
1796 /* The new segment is at the beginning. sackbeg should already be set properly.
1797 We need to find the right edge. */
1798 next = pcb->ooseq;
1799 } else if (prev->next != NULL) {
1800 /* The new segment was added after 'prev'. If there is a "hole" between 'prev' and 'prev->next',
1801 we need to move sackbeg. After that we should find the right edge. */
1802 next = prev->next;
1803 if (prev->tcphdr->seqno + prev->len != next->tcphdr->seqno) {
1804 sackbeg = next->tcphdr->seqno;
1805 }
1806 } else {
1807 next = NULL;
1808 }
1809 if (next != NULL) {
1810 u32_t sackend = next->tcphdr->seqno;
1811 for ( ; (next != NULL) && (sackend == next->tcphdr->seqno); next = next->next) {
1812 sackend += next->len;
1813 }
1814 tcp_add_sack(pcb, sackbeg, sackend);
1815 }
1816 }
1817#endif /* LWIP_TCP_SACK_OUT */
1818 }
1819#if defined(TCP_OOSEQ_BYTES_LIMIT) || defined(TCP_OOSEQ_PBUFS_LIMIT)
1820 {
1821 /* Check that the data on ooseq doesn't exceed one of the limits
1822 and throw away everything above that limit. */
1823#ifdef TCP_OOSEQ_BYTES_LIMIT
1824 const u32_t ooseq_max_blen = TCP_OOSEQ_BYTES_LIMIT(pcb);
1825 u32_t ooseq_blen = 0;
1826#endif
1827#ifdef TCP_OOSEQ_PBUFS_LIMIT
1828 const u16_t ooseq_max_qlen = TCP_OOSEQ_PBUFS_LIMIT(pcb);
1829 u16_t ooseq_qlen = 0;
1830#endif
1831 struct tcp_seg *next, *prev = NULL;
1832 for (next = pcb->ooseq; next != NULL; prev = next, next = next->next) {
1833 struct pbuf *p = next->p;
1834 int stop_here = 0;
1835#ifdef TCP_OOSEQ_BYTES_LIMIT
1836 ooseq_blen += p->tot_len;
1837 if (ooseq_blen > ooseq_max_blen) {
1838 stop_here = 1;
1839 }
1840#endif
1841#ifdef TCP_OOSEQ_PBUFS_LIMIT
1842 ooseq_qlen += pbuf_clen(p);
1843 if (ooseq_qlen > ooseq_max_qlen) {
1844 stop_here = 1;
1845 }
1846#endif
1847 if (stop_here) {
1848#if LWIP_TCP_SACK_OUT
1849 if (pcb->flags & TF_SACK) {
1850 /* Let's remove all SACKs from next's seqno up. */
1851 tcp_remove_sacks_gt(pcb, next->tcphdr->seqno);
1852 }
1853#endif /* LWIP_TCP_SACK_OUT */
1854 /* too much ooseq data, dump this and everything after it */
1855 tcp_segs_free(next);
1856 if (prev == NULL) {
1857 /* first ooseq segment is too much, dump the whole queue */
1858 pcb->ooseq = NULL;
1859 } else {
1860 /* just dump 'next' and everything after it */
1861 prev->next = NULL;
1862 }
1863 break;
1864 }
1865 }
1866 }
1867#endif /* TCP_OOSEQ_BYTES_LIMIT || TCP_OOSEQ_PBUFS_LIMIT */
1868#endif /* TCP_QUEUE_OOSEQ */
1869
1870 /* We send the ACK packet after we've (potentially) dealt with SACKs,
1871 so they can be included in the acknowledgment. */
1872 tcp_send_empty_ack(pcb);
1873 }
1874 } else {
1875 /* The incoming segment is not within the window. */
1876 tcp_send_empty_ack(pcb);
1877 }
1878 } else {
1879 /* Segments with length 0 is taken care of here. Segments that
1880 fall out of the window are ACKed. */
1881 if (!TCP_SEQ_BETWEEN(seqno, pcb->rcv_nxt, pcb->rcv_nxt + pcb->rcv_wnd - 1)) {
1882 tcp_ack_now(pcb);
1883 }
1884 }
1885}
1886
1887static u8_t
1888tcp_get_next_optbyte(void)
1889{
1890 u16_t optidx = tcp_optidx++;
1891 if ((tcphdr_opt2 == NULL) || (optidx < tcphdr_opt1len)) {
1892 u8_t *opts = (u8_t *)tcphdr + TCP_HLEN;
1893 return opts[optidx];
1894 } else {
1895 u8_t idx = (u8_t)(optidx - tcphdr_opt1len);
1896 return tcphdr_opt2[idx];
1897 }
1898}
1899
1900/**
1901 * Parses the options contained in the incoming segment.
1902 *
1903 * Called from tcp_listen_input() and tcp_process().
1904 * Currently, only the MSS option is supported!
1905 *
1906 * @param pcb the tcp_pcb for which a segment arrived
1907 */
1908static void
1909tcp_parseopt(struct tcp_pcb *pcb)
1910{
1911 u8_t data;
1912 u16_t mss;
1913#if LWIP_TCP_TIMESTAMPS
1914 u32_t tsval;
1915#endif
1916
1917 LWIP_ASSERT("tcp_parseopt: invalid pcb", pcb != NULL);
1918
1919 /* Parse the TCP MSS option, if present. */
1920 if (tcphdr_optlen != 0) {
1921 for (tcp_optidx = 0; tcp_optidx < tcphdr_optlen; ) {
1922 u8_t opt = tcp_get_next_optbyte();
1923 switch (opt) {
1924 case LWIP_TCP_OPT_EOL:
1925 /* End of options. */
1926 LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: EOL\n"));
1927 return;
1928 case LWIP_TCP_OPT_NOP:
1929 /* NOP option. */
1930 LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: NOP\n"));
1931 break;
1932 case LWIP_TCP_OPT_MSS:
1933 LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: MSS\n"));
1934 if (tcp_get_next_optbyte() != LWIP_TCP_OPT_LEN_MSS || (tcp_optidx - 2 + LWIP_TCP_OPT_LEN_MSS) > tcphdr_optlen) {
1935 /* Bad length */
1936 LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: bad length\n"));
1937 return;
1938 }
1939 /* An MSS option with the right option length. */
1940 mss = (u16_t)(tcp_get_next_optbyte() << 8);
1941 mss |= tcp_get_next_optbyte();
1942 /* Limit the mss to the configured TCP_MSS and prevent division by zero */
1943 pcb->mss = ((mss > TCP_MSS) || (mss == 0)) ? TCP_MSS : mss;
1944 break;
1945#if LWIP_WND_SCALE
1946 case LWIP_TCP_OPT_WS:
1947 LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: WND_SCALE\n"));
1948 if (tcp_get_next_optbyte() != LWIP_TCP_OPT_LEN_WS || (tcp_optidx - 2 + LWIP_TCP_OPT_LEN_WS) > tcphdr_optlen) {
1949 /* Bad length */
1950 LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: bad length\n"));
1951 return;
1952 }
1953 /* An WND_SCALE option with the right option length. */
1954 data = tcp_get_next_optbyte();
1955 /* If syn was received with wnd scale option,
1956 activate wnd scale opt, but only if this is not a retransmission */
1957 if ((flags & TCP_SYN) && !(pcb->flags & TF_WND_SCALE)) {
1958 pcb->snd_scale = data;
1959 if (pcb->snd_scale > 14U) {
1960 pcb->snd_scale = 14U;
1961 }
1962 pcb->rcv_scale = TCP_RCV_SCALE;
1963 tcp_set_flags(pcb, TF_WND_SCALE);
1964 /* window scaling is enabled, we can use the full receive window */
1965 LWIP_ASSERT("window not at default value", pcb->rcv_wnd == TCPWND_MIN16(TCP_WND));
1966 LWIP_ASSERT("window not at default value", pcb->rcv_ann_wnd == TCPWND_MIN16(TCP_WND));
1967 pcb->rcv_wnd = pcb->rcv_ann_wnd = TCP_WND;
1968 }
1969 break;
1970#endif /* LWIP_WND_SCALE */
1971#if LWIP_TCP_TIMESTAMPS
1972 case LWIP_TCP_OPT_TS:
1973 LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: TS\n"));
1974 if (tcp_get_next_optbyte() != LWIP_TCP_OPT_LEN_TS || (tcp_optidx - 2 + LWIP_TCP_OPT_LEN_TS) > tcphdr_optlen) {
1975 /* Bad length */
1976 LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: bad length\n"));
1977 return;
1978 }
1979 /* TCP timestamp option with valid length */
1980 tsval = tcp_get_next_optbyte();
1981 tsval |= (tcp_get_next_optbyte() << 8);
1982 tsval |= (tcp_get_next_optbyte() << 16);
1983 tsval |= (tcp_get_next_optbyte() << 24);
1984 if (flags & TCP_SYN) {
1985 pcb->ts_recent = lwip_ntohl(tsval);
1986 /* Enable sending timestamps in every segment now that we know
1987 the remote host supports it. */
1988 tcp_set_flags(pcb, TF_TIMESTAMP);
1989 } else if (TCP_SEQ_BETWEEN(pcb->ts_lastacksent, seqno, seqno + tcplen)) {
1990 pcb->ts_recent = lwip_ntohl(tsval);
1991 }
1992 /* Advance to next option (6 bytes already read) */
1993 tcp_optidx += LWIP_TCP_OPT_LEN_TS - 6;
1994 break;
1995#endif /* LWIP_TCP_TIMESTAMPS */
1996#if LWIP_TCP_SACK_OUT
1997 case LWIP_TCP_OPT_SACK_PERM:
1998 LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: SACK_PERM\n"));
1999 if (tcp_get_next_optbyte() != LWIP_TCP_OPT_LEN_SACK_PERM || (tcp_optidx - 2 + LWIP_TCP_OPT_LEN_SACK_PERM) > tcphdr_optlen) {
2000 /* Bad length */
2001 LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: bad length\n"));
2002 return;
2003 }
2004 /* TCP SACK_PERM option with valid length */
2005 if (flags & TCP_SYN) {
2006 /* We only set it if we receive it in a SYN (or SYN+ACK) packet */
2007 tcp_set_flags(pcb, TF_SACK);
2008 }
2009 break;
2010#endif /* LWIP_TCP_SACK_OUT */
2011 default:
2012 LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: other\n"));
2013 data = tcp_get_next_optbyte();
2014 if (data < 2) {
2015 LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: bad length\n"));
2016 /* If the length field is zero, the options are malformed
2017 and we don't process them further. */
2018 return;
2019 }
2020 /* All other options have a length field, so that we easily
2021 can skip past them. */
2022 tcp_optidx += data - 2;
2023 }
2024 }
2025 }
2026}
2027
2028void
2029tcp_trigger_input_pcb_close(void)
2030{
2031 recv_flags |= TF_CLOSED;
2032}
2033
2034#if LWIP_TCP_SACK_OUT
2035/**
2036 * Called by tcp_receive() to add new SACK entry.
2037 *
2038 * The new SACK entry will be placed at the beginning of rcv_sacks[], as the newest one.
2039 * Existing SACK entries will be "pushed back", to preserve their order.
2040 * This is the behavior described in RFC 2018, section 4.
2041 *
2042 * @param pcb the tcp_pcb for which a segment arrived
2043 * @param left the left side of the SACK (the first sequence number)
2044 * @param right the right side of the SACK (the first sequence number past this SACK)
2045 */
2046static void
2047tcp_add_sack(struct tcp_pcb *pcb, u32_t left, u32_t right)
2048{
2049 u8_t i;
2050 u8_t unused_idx;
2051
2052 if ((pcb->flags & TF_SACK) == 0 || !TCP_SEQ_LT(left, right)) {
2053 return;
2054 }
2055
2056 /* First, let's remove all SACKs that are no longer needed (because they overlap with the newest one),
2057 while moving all other SACKs forward.
2058 We run this loop for all entries, until we find the first invalid one.
2059 There is no point checking after that. */
2060 for (i = unused_idx = 0; (i < LWIP_TCP_MAX_SACK_NUM) && LWIP_TCP_SACK_VALID(pcb, i); ++i) {
2061 /* We only want to use SACK at [i] if it doesn't overlap with left:right range.
2062 It does not overlap if its right side is before the newly added SACK,
2063 or if its left side is after the newly added SACK.
2064 NOTE: The equality should not really happen, but it doesn't hurt. */
2065 if (TCP_SEQ_LEQ(pcb->rcv_sacks[i].right, left) || TCP_SEQ_LEQ(right, pcb->rcv_sacks[i].left)) {
2066 if (unused_idx != i) {
2067 /* We don't need to copy if it's already in the right spot */
2068 pcb->rcv_sacks[unused_idx] = pcb->rcv_sacks[i];
2069 }
2070 ++unused_idx;
2071 }
2072 }
2073
2074 /* Now 'unused_idx' is the index of the first invalid SACK entry,
2075 anywhere between 0 (no valid entries) and LWIP_TCP_MAX_SACK_NUM (all entries are valid).
2076 We want to clear this and all following SACKs.
2077 However, we will be adding another one in the front (and shifting everything else back).
2078 So let's just iterate from the back, and set each entry to the one to the left if it's valid,
2079 or to 0 if it is not. */
2080 for (i = LWIP_TCP_MAX_SACK_NUM - 1; i > 0; --i) {
2081 /* [i] is the index we are setting, and the value should be at index [i-1],
2082 or 0 if that index is unused (>= unused_idx). */
2083 if (i - 1 >= unused_idx) {
2084 /* [i-1] is unused. Let's clear [i]. */
2085 pcb->rcv_sacks[i].left = pcb->rcv_sacks[i].right = 0;
2086 } else {
2087 pcb->rcv_sacks[i] = pcb->rcv_sacks[i - 1];
2088 }
2089 }
2090
2091 /* And now we can store the newest SACK */
2092 pcb->rcv_sacks[0].left = left;
2093 pcb->rcv_sacks[0].right = right;
2094}
2095
2096/**
2097 * Called to remove a range of SACKs.
2098 *
2099 * SACK entries will be removed or adjusted to not acknowledge any sequence
2100 * numbers that are less than 'seq' passed. It not only invalidates entries,
2101 * but also moves all entries that are still valid to the beginning.
2102 *
2103 * @param pcb the tcp_pcb to modify
2104 * @param seq the lowest sequence number to keep in SACK entries
2105 */
2106static void
2107tcp_remove_sacks_lt(struct tcp_pcb *pcb, u32_t seq)
2108{
2109 u8_t i;
2110 u8_t unused_idx;
2111
2112 /* We run this loop for all entries, until we find the first invalid one.
2113 There is no point checking after that. */
2114 for (i = unused_idx = 0; (i < LWIP_TCP_MAX_SACK_NUM) && LWIP_TCP_SACK_VALID(pcb, i); ++i) {
2115 /* We only want to use SACK at index [i] if its right side is > 'seq'. */
2116 if (TCP_SEQ_GT(pcb->rcv_sacks[i].right, seq)) {
2117 if (unused_idx != i) {
2118 /* We only copy it if it's not in the right spot already. */
2119 pcb->rcv_sacks[unused_idx] = pcb->rcv_sacks[i];
2120 }
2121 /* NOTE: It is possible that its left side is < 'seq', in which case we should adjust it. */
2122 if (TCP_SEQ_LT(pcb->rcv_sacks[unused_idx].left, seq)) {
2123 pcb->rcv_sacks[unused_idx].left = seq;
2124 }
2125 ++unused_idx;
2126 }
2127 }
2128
2129 /* We also need to invalidate everything from 'unused_idx' till the end */
2130 for (i = unused_idx; i < LWIP_TCP_MAX_SACK_NUM; ++i) {
2131 pcb->rcv_sacks[i].left = pcb->rcv_sacks[i].right = 0;
2132 }
2133}
2134
2135#if defined(TCP_OOSEQ_BYTES_LIMIT) || defined(TCP_OOSEQ_PBUFS_LIMIT)
2136/**
2137 * Called to remove a range of SACKs.
2138 *
2139 * SACK entries will be removed or adjusted to not acknowledge any sequence
2140 * numbers that are greater than (or equal to) 'seq' passed. It not only invalidates entries,
2141 * but also moves all entries that are still valid to the beginning.
2142 *
2143 * @param pcb the tcp_pcb to modify
2144 * @param seq the highest sequence number to keep in SACK entries
2145 */
2146static void
2147tcp_remove_sacks_gt(struct tcp_pcb *pcb, u32_t seq)
2148{
2149 u8_t i;
2150 u8_t unused_idx;
2151
2152 /* We run this loop for all entries, until we find the first invalid one.
2153 There is no point checking after that. */
2154 for (i = unused_idx = 0; (i < LWIP_TCP_MAX_SACK_NUM) && LWIP_TCP_SACK_VALID(pcb, i); ++i) {
2155 /* We only want to use SACK at index [i] if its left side is < 'seq'. */
2156 if (TCP_SEQ_LT(pcb->rcv_sacks[i].left, seq)) {
2157 if (unused_idx != i) {
2158 /* We only copy it if it's not in the right spot already. */
2159 pcb->rcv_sacks[unused_idx] = pcb->rcv_sacks[i];
2160 }
2161 /* NOTE: It is possible that its right side is > 'seq', in which case we should adjust it. */
2162 if (TCP_SEQ_GT(pcb->rcv_sacks[unused_idx].right, seq)) {
2163 pcb->rcv_sacks[unused_idx].right = seq;
2164 }
2165 ++unused_idx;
2166 }
2167 }
2168
2169 /* We also need to invalidate everything from 'unused_idx' till the end */
2170 for (i = unused_idx; i < LWIP_TCP_MAX_SACK_NUM; ++i) {
2171 pcb->rcv_sacks[i].left = pcb->rcv_sacks[i].right = 0;
2172 }
2173}
2174#endif /* TCP_OOSEQ_BYTES_LIMIT || TCP_OOSEQ_PBUFS_LIMIT */
2175
2176#endif /* LWIP_TCP_SACK_OUT */
2177
2178#endif /* LWIP_TCP */
Note: See TracBrowser for help on using the repository browser.