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/tcp_impl.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/snmp.h"
57 #include "arch/perf.h"
58 
59 /* These variables are global to all functions involved in the input
60    processing of TCP segments. They are set by the tcp_input()
61    function. */
62 static struct tcp_seg inseg;
63 static struct tcp_hdr *tcphdr;
64 static struct ip_hdr *iphdr;
65 static u32_t seqno, ackno;
66 static u8_t flags;
67 static u16_t tcplen;
68 
69 static u8_t recv_flags;
70 static struct pbuf *recv_data;
71 
72 struct tcp_pcb *tcp_input_pcb;
73 
74 /* Forward declarations. */
75 static err_t tcp_process(struct tcp_pcb *pcb);
76 static void tcp_receive(struct tcp_pcb *pcb);
77 static void tcp_parseopt(struct tcp_pcb *pcb);
78 
79 static err_t tcp_listen_input(struct tcp_pcb_listen *pcb);
80 static err_t tcp_timewait_input(struct tcp_pcb *pcb);
81 
82 /**
83  * The initial input processing of TCP. It verifies the TCP header, demultiplexes
84  * the segment between the PCBs and passes it on to tcp_process(), which implements
85  * the TCP finite state machine. This function is called by the IP layer (in
86  * ip_input()).
87  *
88  * @param p received TCP segment to process (p->payload pointing to the IP header)
89  * @param inp network interface on which this segment was received
90  */
91 void
tcp_input(struct pbuf * p,struct netif * inp)92 tcp_input(struct pbuf *p, struct netif *inp)
93 {
94   struct tcp_pcb *pcb, *prev;
95   struct tcp_pcb_listen *lpcb;
96 #if SO_REUSE
97   struct tcp_pcb *lpcb_prev = NULL;
98   struct tcp_pcb_listen *lpcb_any = NULL;
99 #endif /* SO_REUSE */
100   u8_t hdrlen;
101   err_t err;
102 
103   PERF_START;
104 
105   TCP_STATS_INC(tcp.recv);
106   snmp_inc_tcpinsegs();
107 
108   iphdr = (struct ip_hdr *)p->payload;
109   tcphdr = (struct tcp_hdr *)((u8_t *)p->payload + IPH_HL(iphdr) * 4);
110 
111 #if TCP_INPUT_DEBUG
112   tcp_debug_print(tcphdr);
113 #endif
114 
115   /* remove header from payload */
116   if (pbuf_header(p, -((s16_t)(IPH_HL(iphdr) * 4))) || (p->tot_len < sizeof(struct tcp_hdr))) {
117     /* drop short packets */
118     LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: short packet (%"U16_F" bytes) discarded\n", p->tot_len));
119     TCP_STATS_INC(tcp.lenerr);
120     goto dropped;
121   }
122 
123   /* Don't even process incoming broadcasts/multicasts. */
124   if (ip_addr_isbroadcast(&current_iphdr_dest, inp) ||
125       ip_addr_ismulticast(&current_iphdr_dest)) {
126     TCP_STATS_INC(tcp.proterr);
127     goto dropped;
128   }
129 
130 #if CHECKSUM_CHECK_TCP
131   /* Verify TCP checksum. */
132   if (inet_chksum_pseudo(p, ip_current_src_addr(), ip_current_dest_addr(),
133       IP_PROTO_TCP, p->tot_len) != 0) {
134       LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: packet discarded due to failing checksum 0x%04"X16_F"\n",
135         inet_chksum_pseudo(p, ip_current_src_addr(), ip_current_dest_addr(),
136       IP_PROTO_TCP, p->tot_len)));
137 #if TCP_DEBUG
138     tcp_debug_print(tcphdr);
139 #endif /* TCP_DEBUG */
140     TCP_STATS_INC(tcp.chkerr);
141     goto dropped;
142   }
143 #endif
144 
145   /* Move the payload pointer in the pbuf so that it points to the
146      TCP data instead of the TCP header. */
147   hdrlen = TCPH_HDRLEN(tcphdr);
148   if(pbuf_header(p, -(hdrlen * 4))){
149     /* drop short packets */
150     LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: short packet\n"));
151     TCP_STATS_INC(tcp.lenerr);
152     goto dropped;
153   }
154 
155   /* Convert fields in TCP header to host byte order. */
156   tcphdr->src = ntohs(tcphdr->src);
157   tcphdr->dest = ntohs(tcphdr->dest);
158   seqno = tcphdr->seqno = ntohl(tcphdr->seqno);
159   ackno = tcphdr->ackno = ntohl(tcphdr->ackno);
160   tcphdr->wnd = ntohs(tcphdr->wnd);
161 
162   flags = TCPH_FLAGS(tcphdr);
163   tcplen = p->tot_len + ((flags & (TCP_FIN | TCP_SYN)) ? 1 : 0);
164 
165   /* Demultiplex an incoming segment. First, we check if it is destined
166      for an active connection. */
167   prev = NULL;
168 
169 
170   for(pcb = tcp_active_pcbs; pcb != NULL; pcb = pcb->next) {
171     LWIP_ASSERT("tcp_input: active pcb->state != CLOSED", pcb->state != CLOSED);
172     LWIP_ASSERT("tcp_input: active pcb->state != TIME-WAIT", pcb->state != TIME_WAIT);
173     LWIP_ASSERT("tcp_input: active pcb->state != LISTEN", pcb->state != LISTEN);
174     if (pcb->remote_port == tcphdr->src &&
175        pcb->local_port == tcphdr->dest &&
176        ip_addr_cmp(&(pcb->remote_ip), &current_iphdr_src) &&
177        ip_addr_cmp(&(pcb->local_ip), &current_iphdr_dest)) {
178 
179       /* Move this PCB to the front of the list so that subsequent
180          lookups will be faster (we exploit locality in TCP segment
181          arrivals). */
182       LWIP_ASSERT("tcp_input: pcb->next != pcb (before cache)", pcb->next != pcb);
183       if (prev != NULL) {
184         prev->next = pcb->next;
185         pcb->next = tcp_active_pcbs;
186         tcp_active_pcbs = pcb;
187       }
188       LWIP_ASSERT("tcp_input: pcb->next != pcb (after cache)", pcb->next != pcb);
189       break;
190     }
191     prev = pcb;
192   }
193 
194   if (pcb == NULL) {
195     /* If it did not go to an active connection, we check the connections
196        in the TIME-WAIT state. */
197     for(pcb = tcp_tw_pcbs; pcb != NULL; pcb = pcb->next) {
198       LWIP_ASSERT("tcp_input: TIME-WAIT pcb->state == TIME-WAIT", pcb->state == TIME_WAIT);
199       if (pcb->remote_port == tcphdr->src &&
200          pcb->local_port == tcphdr->dest &&
201          ip_addr_cmp(&(pcb->remote_ip), &current_iphdr_src) &&
202          ip_addr_cmp(&(pcb->local_ip), &current_iphdr_dest)) {
203         /* We don't really care enough to move this PCB to the front
204            of the list since we are not very likely to receive that
205            many segments for connections in TIME-WAIT. */
206         LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: packed for TIME_WAITing connection.\n"));
207         tcp_timewait_input(pcb);
208         pbuf_free(p);
209         return;
210       }
211     }
212 
213     /* Finally, if we still did not get a match, we check all PCBs that
214        are LISTENing for incoming connections. */
215     prev = NULL;
216     for(lpcb = tcp_listen_pcbs.listen_pcbs; lpcb != NULL; lpcb = lpcb->next) {
217       if (lpcb->local_port == tcphdr->dest) {
218 #if SO_REUSE
219         if (ip_addr_cmp(&(lpcb->local_ip), &current_iphdr_dest)) {
220           /* found an exact match */
221           break;
222         } else if(ip_addr_isany(&(lpcb->local_ip))) {
223           /* found an ANY-match */
224           lpcb_any = lpcb;
225           lpcb_prev = prev;
226         }
227 #else /* SO_REUSE */
228         if (ip_addr_cmp(&(lpcb->local_ip), &current_iphdr_dest) ||
229             ip_addr_isany(&(lpcb->local_ip))) {
230           /* found a match */
231           break;
232         }
233 #endif /* SO_REUSE */
234       }
235       prev = (struct tcp_pcb *)lpcb;
236     }
237 #if SO_REUSE
238     /* first try specific local IP */
239     if (lpcb == NULL) {
240       /* only pass to ANY if no specific local IP has been found */
241       lpcb = lpcb_any;
242       prev = lpcb_prev;
243     }
244 #endif /* SO_REUSE */
245     if (lpcb != NULL) {
246       /* Move this PCB to the front of the list so that subsequent
247          lookups will be faster (we exploit locality in TCP segment
248          arrivals). */
249       if (prev != NULL) {
250         ((struct tcp_pcb_listen *)prev)->next = lpcb->next;
251               /* our successor is the remainder of the listening list */
252         lpcb->next = tcp_listen_pcbs.listen_pcbs;
253               /* put this listening pcb at the head of the listening list */
254         tcp_listen_pcbs.listen_pcbs = lpcb;
255       }
256 
257       LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: packed for LISTENing connection.\n"));
258       tcp_listen_input(lpcb);
259       pbuf_free(p);
260       return;
261     }
262   }
263 
264 #if TCP_INPUT_DEBUG
265   LWIP_DEBUGF(TCP_INPUT_DEBUG, ("+-+-+-+-+-+-+-+-+-+-+-+-+-+- tcp_input: flags "));
266   tcp_debug_print_flags(TCPH_FLAGS(tcphdr));
267   LWIP_DEBUGF(TCP_INPUT_DEBUG, ("-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n"));
268 #endif /* TCP_INPUT_DEBUG */
269 
270 
271   if (pcb != NULL) {
272     /* The incoming segment belongs to a connection. */
273 #if TCP_INPUT_DEBUG
274 #if TCP_DEBUG
275     tcp_debug_print_state(pcb->state);
276 #endif /* TCP_DEBUG */
277 #endif /* TCP_INPUT_DEBUG */
278 
279     /* Set up a tcp_seg structure. */
280     inseg.next = NULL;
281     inseg.len = p->tot_len;
282     inseg.p = p;
283     inseg.tcphdr = tcphdr;
284 
285     recv_data = NULL;
286     recv_flags = 0;
287 
288     if (flags & TCP_PSH) {
289       p->flags |= PBUF_FLAG_PUSH;
290     }
291 
292     /* If there is data which was previously "refused" by upper layer */
293     if (pcb->refused_data != NULL) {
294       if ((tcp_process_refused_data(pcb) == ERR_ABRT) ||
295         ((pcb->refused_data != NULL) && (tcplen > 0))) {
296         /* pcb has been aborted or refused data is still refused and the new
297            segment contains data */
298         TCP_STATS_INC(tcp.drop);
299         snmp_inc_tcpinerrs();
300         goto aborted;
301       }
302     }
303     tcp_input_pcb = pcb;
304     err = tcp_process(pcb);
305     /* A return value of ERR_ABRT means that tcp_abort() was called
306        and that the pcb has been freed. If so, we don't do anything. */
307     if (err != ERR_ABRT) {
308       if (recv_flags & TF_RESET) {
309         /* TF_RESET means that the connection was reset by the other
310            end. We then call the error callback to inform the
311            application that the connection is dead before we
312            deallocate the PCB. */
313         TCP_EVENT_ERR(pcb->errf, pcb->callback_arg, ERR_RST);
314         tcp_pcb_remove(&tcp_active_pcbs, pcb);
315         memp_free(MEMP_TCP_PCB, pcb);
316       } else if (recv_flags & TF_CLOSED) {
317         /* The connection has been closed and we will deallocate the
318            PCB. */
319         if (!(pcb->flags & TF_RXCLOSED)) {
320           /* Connection closed although the application has only shut down the
321              tx side: call the PCB's err callback and indicate the closure to
322              ensure the application doesn't continue using the PCB. */
323           TCP_EVENT_ERR(pcb->errf, pcb->callback_arg, ERR_CLSD);
324         }
325         tcp_pcb_remove(&tcp_active_pcbs, pcb);
326         memp_free(MEMP_TCP_PCB, pcb);
327       } else {
328         err = ERR_OK;
329         /* If the application has registered a "sent" function to be
330            called when new send buffer space is available, we call it
331            now. */
332         if (pcb->acked > 0) {
333           TCP_EVENT_SENT(pcb, pcb->acked, err);
334           if (err == ERR_ABRT) {
335             goto aborted;
336           }
337         }
338 
339         if (recv_data != NULL) {
340           LWIP_ASSERT("pcb->refused_data == NULL", pcb->refused_data == NULL);
341           if (pcb->flags & TF_RXCLOSED) {
342             /* received data although already closed -> abort (send RST) to
343                notify the remote host that not all data has been processed */
344             pbuf_free(recv_data);
345             tcp_abort(pcb);
346             goto aborted;
347           }
348 
349           /* Notify application that data has been received. */
350           TCP_EVENT_RECV(pcb, recv_data, ERR_OK, err);
351           if (err == ERR_ABRT) {
352             goto aborted;
353           }
354 
355           /* If the upper layer can't receive this data, store it */
356           if (err != ERR_OK) {
357             pcb->refused_data = recv_data;
358             LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: keep incoming packet, because pcb is \"full\"\n"));
359           }
360         }
361 
362         /* If a FIN segment was received, we call the callback
363            function with a NULL buffer to indicate EOF. */
364         if (recv_flags & TF_GOT_FIN) {
365           if (pcb->refused_data != NULL) {
366             /* Delay this if we have refused data. */
367             pcb->refused_data->flags |= PBUF_FLAG_TCP_FIN;
368           } else {
369             /* correct rcv_wnd as the application won't call tcp_recved()
370                for the FIN's seqno */
371             if (pcb->rcv_wnd != TCP_WND) {
372               pcb->rcv_wnd++;
373             }
374             TCP_EVENT_CLOSED(pcb, err);
375             if (err == ERR_ABRT) {
376               goto aborted;
377             }
378           }
379         }
380 
381         tcp_input_pcb = NULL;
382         /* Try to send something out. */
383         tcp_output(pcb);
384 #if TCP_INPUT_DEBUG
385 #if TCP_DEBUG
386         tcp_debug_print_state(pcb->state);
387 #endif /* TCP_DEBUG */
388 #endif /* TCP_INPUT_DEBUG */
389       }
390     }
391     /* Jump target if pcb has been aborted in a callback (by calling tcp_abort()).
392        Below this line, 'pcb' may not be dereferenced! */
393 aborted:
394     tcp_input_pcb = NULL;
395     recv_data = NULL;
396 
397     /* give up our reference to inseg.p */
398     if (inseg.p != NULL)
399     {
400       pbuf_free(inseg.p);
401       inseg.p = NULL;
402     }
403   } else {
404 
405     /* If no matching PCB was found, send a TCP RST (reset) to the
406        sender. */
407     LWIP_DEBUGF(TCP_RST_DEBUG, ("tcp_input: no PCB match found, resetting.\n"));
408     if (!(TCPH_FLAGS(tcphdr) & TCP_RST)) {
409       TCP_STATS_INC(tcp.proterr);
410       TCP_STATS_INC(tcp.drop);
411       tcp_rst(ackno, seqno + tcplen,
412         ip_current_dest_addr(), ip_current_src_addr(),
413         tcphdr->dest, tcphdr->src);
414     }
415     pbuf_free(p);
416   }
417 
418   LWIP_ASSERT("tcp_input: tcp_pcbs_sane()", tcp_pcbs_sane());
419   PERF_STOP("tcp_input");
420   return;
421 dropped:
422   TCP_STATS_INC(tcp.drop);
423   snmp_inc_tcpinerrs();
424   pbuf_free(p);
425 }
426 
427 /**
428  * Called by tcp_input() when a segment arrives for a listening
429  * connection (from tcp_input()).
430  *
431  * @param pcb the tcp_pcb_listen for which a segment arrived
432  * @return ERR_OK if the segment was processed
433  *         another err_t on error
434  *
435  * @note the return value is not (yet?) used in tcp_input()
436  * @note the segment which arrived is saved in global variables, therefore only the pcb
437  *       involved is passed as a parameter to this function
438  */
439 static err_t
tcp_listen_input(struct tcp_pcb_listen * pcb)440 tcp_listen_input(struct tcp_pcb_listen *pcb)
441 {
442   struct tcp_pcb *npcb;
443   err_t rc;
444 
445   if (flags & TCP_RST) {
446     /* An incoming RST should be ignored. Return. */
447     return ERR_OK;
448   }
449 
450   /* In the LISTEN state, we check for incoming SYN segments,
451      creates a new PCB, and responds with a SYN|ACK. */
452   if (flags & TCP_ACK) {
453     /* For incoming segments with the ACK flag set, respond with a
454        RST. */
455     LWIP_DEBUGF(TCP_RST_DEBUG, ("tcp_listen_input: ACK in LISTEN, sending reset\n"));
456     tcp_rst(ackno, seqno + tcplen, ip_current_dest_addr(),
457       ip_current_src_addr(), tcphdr->dest, tcphdr->src);
458   } else if (flags & TCP_SYN) {
459     LWIP_DEBUGF(TCP_DEBUG, ("TCP connection request %"U16_F" -> %"U16_F".\n", tcphdr->src, tcphdr->dest));
460 #if TCP_LISTEN_BACKLOG
461     if (pcb->accepts_pending >= pcb->backlog) {
462       LWIP_DEBUGF(TCP_DEBUG, ("tcp_listen_input: listen backlog exceeded for port %"U16_F"\n", tcphdr->dest));
463       return ERR_ABRT;
464     }
465 #endif /* TCP_LISTEN_BACKLOG */
466     npcb = tcp_alloc(pcb->prio);
467     /* If a new PCB could not be created (probably due to lack of memory),
468        we don't do anything, but rely on the sender will retransmit the
469        SYN at a time when we have more memory available. */
470     if (npcb == NULL) {
471       LWIP_DEBUGF(TCP_DEBUG, ("tcp_listen_input: could not allocate PCB\n"));
472       TCP_STATS_INC(tcp.memerr);
473       return ERR_MEM;
474     }
475 #if TCP_LISTEN_BACKLOG
476     pcb->accepts_pending++;
477 #endif /* TCP_LISTEN_BACKLOG */
478     /* Set up the new PCB. */
479     ip_addr_copy(npcb->local_ip, current_iphdr_dest);
480     npcb->local_port = pcb->local_port;
481     ip_addr_copy(npcb->remote_ip, current_iphdr_src);
482     npcb->remote_port = tcphdr->src;
483     npcb->state = SYN_RCVD;
484     npcb->rcv_nxt = seqno + 1;
485     npcb->rcv_ann_right_edge = npcb->rcv_nxt;
486     npcb->snd_wnd = tcphdr->wnd;
487     npcb->snd_wnd_max = tcphdr->wnd;
488     npcb->ssthresh = npcb->snd_wnd;
489     npcb->snd_wl1 = seqno - 1;/* initialise to seqno-1 to force window update */
490     npcb->callback_arg = pcb->callback_arg;
491 #if LWIP_CALLBACK_API
492     npcb->accept = pcb->accept;
493 #endif /* LWIP_CALLBACK_API */
494     /* inherit socket options */
495     npcb->so_options = pcb->so_options & SOF_INHERITED;
496     /* Register the new PCB so that we can begin receiving segments
497        for it. */
498     TCP_REG_ACTIVE(npcb);
499 
500     /* Parse any options in the SYN. */
501     tcp_parseopt(npcb);
502 #if TCP_CALCULATE_EFF_SEND_MSS
503     npcb->mss = tcp_eff_send_mss(npcb->mss, &(npcb->remote_ip));
504 #endif /* TCP_CALCULATE_EFF_SEND_MSS */
505 
506     snmp_inc_tcppassiveopens();
507 
508     /* Send a SYN|ACK together with the MSS option. */
509     rc = tcp_enqueue_flags(npcb, TCP_SYN | TCP_ACK);
510     if (rc != ERR_OK) {
511       tcp_abandon(npcb, 0);
512       return rc;
513     }
514     return tcp_output(npcb);
515   }
516   return ERR_OK;
517 }
518 
519 /**
520  * Called by tcp_input() when a segment arrives for a connection in
521  * TIME_WAIT.
522  *
523  * @param pcb the tcp_pcb for which a segment arrived
524  *
525  * @note the segment which arrived is saved in global variables, therefore only the pcb
526  *       involved is passed as a parameter to this function
527  */
528 static err_t
tcp_timewait_input(struct tcp_pcb * pcb)529 tcp_timewait_input(struct tcp_pcb *pcb)
530 {
531   /* RFC 1337: in TIME_WAIT, ignore RST and ACK FINs + any 'acceptable' segments */
532   /* RFC 793 3.9 Event Processing - Segment Arrives:
533    * - first check sequence number - we skip that one in TIME_WAIT (always
534    *   acceptable since we only send ACKs)
535    * - second check the RST bit (... return) */
536   if (flags & TCP_RST)  {
537     return ERR_OK;
538   }
539   /* - fourth, check the SYN bit, */
540   if (flags & TCP_SYN) {
541     /* If an incoming segment is not acceptable, an acknowledgment
542        should be sent in reply */
543     if (TCP_SEQ_BETWEEN(seqno, pcb->rcv_nxt, pcb->rcv_nxt+pcb->rcv_wnd)) {
544       /* If the SYN is in the window it is an error, send a reset */
545       tcp_rst(ackno, seqno + tcplen, ip_current_dest_addr(), ip_current_src_addr(),
546         tcphdr->dest, tcphdr->src);
547       return ERR_OK;
548     }
549   } else if (flags & TCP_FIN) {
550     /* - eighth, check the FIN bit: Remain in the TIME-WAIT state.
551          Restart the 2 MSL time-wait timeout.*/
552     pcb->tmr = tcp_ticks;
553   }
554 
555   if ((tcplen > 0))  {
556     /* Acknowledge data, FIN or out-of-window SYN */
557     pcb->flags |= TF_ACK_NOW;
558     return tcp_output(pcb);
559   }
560   return ERR_OK;
561 }
562 
563 /**
564  * Implements the TCP state machine. Called by tcp_input. In some
565  * states tcp_receive() is called to receive data. The tcp_seg
566  * argument will be freed by the caller (tcp_input()) unless the
567  * recv_data pointer in the pcb is set.
568  *
569  * @param pcb the tcp_pcb for which a segment arrived
570  *
571  * @note the segment which arrived is saved in global variables, therefore only the pcb
572  *       involved is passed as a parameter to this function
573  */
574 static err_t
tcp_process(struct tcp_pcb * pcb)575 tcp_process(struct tcp_pcb *pcb)
576 {
577   struct tcp_seg *rseg;
578   u8_t acceptable = 0;
579   err_t err;
580 
581   err = ERR_OK;
582 
583   /* Process incoming RST segments. */
584   if (flags & TCP_RST) {
585     /* First, determine if the reset is acceptable. */
586     if (pcb->state == SYN_SENT) {
587       /* "In the SYN-SENT state (a RST received in response to an initial SYN),
588           the RST is acceptable if the ACK field acknowledges the SYN." */
589       if (ackno == pcb->snd_nxt) {
590         acceptable = 1;
591       }
592     } else {
593       /* "In all states except SYN-SENT, all reset (RST) segments are validated
594       		by checking their SEQ-fields." */
595       if (seqno == pcb->rcv_nxt) {
596         acceptable = 1;
597       } else if (TCP_SEQ_BETWEEN(seqno, pcb->rcv_nxt, pcb->rcv_nxt + pcb->rcv_wnd)) {
598         /* If the sequence number is inside the window, we only send an ACK
599         and wait for a re-send with matching sequence number.
600         This violates RFC 793, but is required to protection against
601         CVE-2004-0230 (RST spoofing attack). */
602         tcp_ack_now(pcb);
603     }
604 
605     if (acceptable) {
606       LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_process: Connection RESET\n"));
607       LWIP_ASSERT("tcp_input: pcb->state != CLOSED", pcb->state != CLOSED);
608       recv_flags |= TF_RESET;
609       pcb->flags &= ~TF_ACK_DELAY;
610       return ERR_RST;
611     } else {
612       LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_process: unacceptable reset seqno %"U32_F" rcv_nxt %"U32_F"\n",
613        seqno, pcb->rcv_nxt));
614       LWIP_DEBUGF(TCP_DEBUG, ("tcp_process: unacceptable reset seqno %"U32_F" rcv_nxt %"U32_F"\n",
615        seqno, pcb->rcv_nxt));
616       return ERR_OK;
617     }
618   }
619 
620   if ((flags & TCP_SYN) && (pcb->state != SYN_SENT && pcb->state != SYN_RCVD)) {
621     /* Cope with new connection attempt after remote end crashed */
622     tcp_ack_now(pcb);
623     return ERR_OK;
624   }
625 
626   if ((pcb->flags & TF_RXCLOSED) == 0) {
627     /* Update the PCB (in)activity timer unless rx is closed (see tcp_shutdown) */
628     pcb->tmr = tcp_ticks;
629   }
630   pcb->keep_cnt_sent = 0;
631 
632   tcp_parseopt(pcb);
633 
634   /* Do different things depending on the TCP state. */
635   switch (pcb->state) {
636   case SYN_SENT:
637     LWIP_DEBUGF(TCP_INPUT_DEBUG, ("SYN-SENT: ackno %"U32_F" pcb->snd_nxt %"U32_F" unacked %"U32_F"\n", ackno,
638      pcb->snd_nxt, ntohl(pcb->unacked->tcphdr->seqno)));
639     /* received SYN ACK with expected sequence number? */
640     if ((flags & TCP_ACK) && (flags & TCP_SYN)
641         && ackno == ntohl(pcb->unacked->tcphdr->seqno) + 1) {
642       pcb->snd_buf++;
643       pcb->rcv_nxt = seqno + 1;
644       pcb->rcv_ann_right_edge = pcb->rcv_nxt;
645       pcb->lastack = ackno;
646       pcb->snd_wnd = tcphdr->wnd;
647       pcb->snd_wnd_max = tcphdr->wnd;
648       pcb->snd_wl1 = seqno - 1; /* initialise to seqno - 1 to force window update */
649       pcb->state = ESTABLISHED;
650 
651 #if TCP_CALCULATE_EFF_SEND_MSS
652       pcb->mss = tcp_eff_send_mss(pcb->mss, &(pcb->remote_ip));
653 #endif /* TCP_CALCULATE_EFF_SEND_MSS */
654 
655       /* Set ssthresh again after changing pcb->mss (already set in tcp_connect
656        * but for the default value of pcb->mss) */
657       pcb->ssthresh = pcb->mss * 10;
658 
659       pcb->cwnd = ((pcb->cwnd == 1) ? (pcb->mss * 2) : pcb->mss);
660       LWIP_ASSERT("pcb->snd_queuelen > 0", (pcb->snd_queuelen > 0));
661       --pcb->snd_queuelen;
662       LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_process: SYN-SENT --queuelen %"U16_F"\n", (u16_t)pcb->snd_queuelen));
663       rseg = pcb->unacked;
664       pcb->unacked = rseg->next;
665       tcp_seg_free(rseg);
666 
667       /* If there's nothing left to acknowledge, stop the retransmit
668          timer, otherwise reset it to start again */
669       if(pcb->unacked == NULL)
670         pcb->rtime = -1;
671       else {
672         pcb->rtime = 0;
673         pcb->nrtx = 0;
674       }
675 
676       /* Call the user specified function to call when sucessfully
677        * connected. */
678       TCP_EVENT_CONNECTED(pcb, ERR_OK, err);
679       if (err == ERR_ABRT) {
680         return ERR_ABRT;
681       }
682       tcp_ack_now(pcb);
683     }
684     /* received ACK? possibly a half-open connection */
685     else if (flags & TCP_ACK) {
686       /* send a RST to bring the other side in a non-synchronized state. */
687       tcp_rst(ackno, seqno + tcplen, ip_current_dest_addr(), ip_current_src_addr(),
688         tcphdr->dest, tcphdr->src);
689     }
690     break;
691   case SYN_RCVD:
692     if (flags & TCP_ACK) {
693       /* expected ACK number? */
694       if (TCP_SEQ_BETWEEN(ackno, pcb->lastack+1, pcb->snd_nxt)) {
695         u16_t old_cwnd;
696         pcb->state = ESTABLISHED;
697         LWIP_DEBUGF(TCP_DEBUG, ("TCP connection established %"U16_F" -> %"U16_F".\n", inseg.tcphdr->src, inseg.tcphdr->dest));
698 #if LWIP_CALLBACK_API
699         LWIP_ASSERT("pcb->accept != NULL", pcb->accept != NULL);
700 #endif
701         /* Call the accept function. */
702         TCP_EVENT_ACCEPT(pcb, ERR_OK, err);
703         if (err != ERR_OK) {
704           /* If the accept function returns with an error, we abort
705            * the connection. */
706           /* Already aborted? */
707           if (err != ERR_ABRT) {
708             tcp_abort(pcb);
709           }
710           return ERR_ABRT;
711         }
712         old_cwnd = pcb->cwnd;
713         /* If there was any data contained within this ACK,
714          * we'd better pass it on to the application as well. */
715         tcp_receive(pcb);
716 
717         /* Prevent ACK for SYN to generate a sent event */
718         if (pcb->acked != 0) {
719           pcb->acked--;
720         }
721 
722         pcb->cwnd = ((old_cwnd == 1) ? (pcb->mss * 2) : pcb->mss);
723 
724         if (recv_flags & TF_GOT_FIN) {
725           tcp_ack_now(pcb);
726           pcb->state = CLOSE_WAIT;
727         }
728       } else {
729         /* incorrect ACK number, send RST */
730         tcp_rst(ackno, seqno + tcplen, ip_current_dest_addr(), ip_current_src_addr(),
731                 tcphdr->dest, tcphdr->src);
732       }
733     } else if ((flags & TCP_SYN) && (seqno == pcb->rcv_nxt - 1)) {
734       /* Looks like another copy of the SYN - retransmit our SYN-ACK */
735       tcp_rexmit(pcb);
736     }
737     break;
738   case CLOSE_WAIT:
739     /* FALLTHROUGH */
740   case ESTABLISHED:
741     tcp_receive(pcb);
742     if (recv_flags & TF_GOT_FIN) { /* passive close */
743       tcp_ack_now(pcb);
744       pcb->state = CLOSE_WAIT;
745     }
746     break;
747   case FIN_WAIT_1:
748     tcp_receive(pcb);
749     if (recv_flags & TF_GOT_FIN) {
750       if ((flags & TCP_ACK) && (ackno == pcb->snd_nxt)) {
751         LWIP_DEBUGF(TCP_DEBUG,
752           ("TCP connection closed: FIN_WAIT_1 %"U16_F" -> %"U16_F".\n", inseg.tcphdr->src, inseg.tcphdr->dest));
753         tcp_ack_now(pcb);
754         tcp_pcb_purge(pcb);
755         TCP_RMV_ACTIVE(pcb);
756         pcb->state = TIME_WAIT;
757         TCP_REG(&tcp_tw_pcbs, pcb);
758       } else {
759         tcp_ack_now(pcb);
760         pcb->state = CLOSING;
761       }
762     } else if ((flags & TCP_ACK) && (ackno == pcb->snd_nxt)) {
763       pcb->state = FIN_WAIT_2;
764     }
765     break;
766   case FIN_WAIT_2:
767     tcp_receive(pcb);
768     if (recv_flags & TF_GOT_FIN) {
769       LWIP_DEBUGF(TCP_DEBUG, ("TCP connection closed: FIN_WAIT_2 %"U16_F" -> %"U16_F".\n", inseg.tcphdr->src, inseg.tcphdr->dest));
770       tcp_ack_now(pcb);
771       tcp_pcb_purge(pcb);
772       TCP_RMV_ACTIVE(pcb);
773       pcb->state = TIME_WAIT;
774       TCP_REG(&tcp_tw_pcbs, pcb);
775     }
776     break;
777   case CLOSING:
778     tcp_receive(pcb);
779     if (flags & TCP_ACK && ackno == pcb->snd_nxt) {
780       LWIP_DEBUGF(TCP_DEBUG, ("TCP connection closed: CLOSING %"U16_F" -> %"U16_F".\n", inseg.tcphdr->src, inseg.tcphdr->dest));
781       tcp_pcb_purge(pcb);
782       TCP_RMV_ACTIVE(pcb);
783       pcb->state = TIME_WAIT;
784       TCP_REG(&tcp_tw_pcbs, pcb);
785     }
786     break;
787   case LAST_ACK:
788     tcp_receive(pcb);
789     if (flags & TCP_ACK && ackno == pcb->snd_nxt) {
790       LWIP_DEBUGF(TCP_DEBUG, ("TCP connection closed: LAST_ACK %"U16_F" -> %"U16_F".\n", inseg.tcphdr->src, inseg.tcphdr->dest));
791       /* bugfix #21699: don't set pcb->state to CLOSED here or we risk leaking segments */
792       recv_flags |= TF_CLOSED;
793     }
794     break;
795   default:
796     break;
797   }
798   return ERR_OK;
799 }
800 
801 #if TCP_QUEUE_OOSEQ
802 /**
803  * Insert segment into the list (segments covered with new one will be deleted)
804  *
805  * Called from tcp_receive()
806  */
807 static void
808 tcp_oos_insert_segment(struct tcp_seg *cseg, struct tcp_seg *next)
809 {
810   struct tcp_seg *old_seg;
811 
812   if (TCPH_FLAGS(cseg->tcphdr) & TCP_FIN) {
813     /* received segment overlaps all following segments */
814     tcp_segs_free(next);
815     next = NULL;
816   }
817   else {
818     /* delete some following segments
819        oos queue may have segments with FIN flag */
820     while (next &&
821            TCP_SEQ_GEQ((seqno + cseg->len),
822                       (next->tcphdr->seqno + next->len))) {
823       /* cseg with FIN already processed */
824       if (TCPH_FLAGS(next->tcphdr) & TCP_FIN) {
825         TCPH_SET_FLAG(cseg->tcphdr, TCP_FIN);
826       }
827       old_seg = next;
828       next = next->next;
829       tcp_seg_free(old_seg);
830     }
831     if (next &&
832         TCP_SEQ_GT(seqno + cseg->len, next->tcphdr->seqno)) {
833       /* We need to trim the incoming segment. */
834       cseg->len = (u16_t)(next->tcphdr->seqno - seqno);
835       pbuf_realloc(cseg->p, cseg->len);
836     }
837   }
838   cseg->next = next;
839 }
840 #endif /* TCP_QUEUE_OOSEQ */
841 
842 /**
843  * Called by tcp_process. Checks if the given segment is an ACK for outstanding
844  * data, and if so frees the memory of the buffered data. Next, is places the
845  * segment on any of the receive queues (pcb->recved or pcb->ooseq). If the segment
846  * is buffered, the pbuf is referenced by pbuf_ref so that it will not be freed until
847  * it has been removed from the buffer.
848  *
849  * If the incoming segment constitutes an ACK for a segment that was used for RTT
850  * estimation, the RTT is estimated here as well.
851  *
852  * Called from tcp_process().
853  */
854 static void
855 tcp_receive(struct tcp_pcb *pcb)
856 {
857   struct tcp_seg *next;
858 #if TCP_QUEUE_OOSEQ
859   struct tcp_seg *prev, *cseg;
860 #endif /* TCP_QUEUE_OOSEQ */
861   struct pbuf *p;
862   s32_t off;
863   s16_t m;
864   u32_t right_wnd_edge;
865   u16_t new_tot_len;
866   int found_dupack = 0;
867 #if TCP_OOSEQ_MAX_BYTES || TCP_OOSEQ_MAX_PBUFS
868   u32_t ooseq_blen;
869   u16_t ooseq_qlen;
870 #endif /* TCP_OOSEQ_MAX_BYTES || TCP_OOSEQ_MAX_PBUFS */
871 
872   LWIP_ASSERT("tcp_receive: wrong state", pcb->state >= ESTABLISHED);
873 
874   if (flags & TCP_ACK) {
875     right_wnd_edge = pcb->snd_wnd + pcb->snd_wl2;
876 
877     /* Update window. */
878     if (TCP_SEQ_LT(pcb->snd_wl1, seqno) ||
879        (pcb->snd_wl1 == seqno && TCP_SEQ_LT(pcb->snd_wl2, ackno)) ||
880        (pcb->snd_wl2 == ackno && tcphdr->wnd > pcb->snd_wnd)) {
881       pcb->snd_wnd = tcphdr->wnd;
882       /* keep track of the biggest window announced by the remote host to calculate
883          the maximum segment size */
884       if (pcb->snd_wnd_max < tcphdr->wnd) {
885         pcb->snd_wnd_max = tcphdr->wnd;
886       }
887       pcb->snd_wl1 = seqno;
888       pcb->snd_wl2 = ackno;
889       if (pcb->snd_wnd == 0) {
890         if (pcb->persist_backoff == 0) {
891           /* start persist timer */
892           pcb->persist_cnt = 0;
893           pcb->persist_backoff = 1;
894         }
895       } else if (pcb->persist_backoff > 0) {
896         /* stop persist timer */
897           pcb->persist_backoff = 0;
898       }
899       LWIP_DEBUGF(TCP_WND_DEBUG, ("tcp_receive: window update %"U16_F"\n", pcb->snd_wnd));
900 #if TCP_WND_DEBUG
901     } else {
902       if (pcb->snd_wnd != tcphdr->wnd) {
903         LWIP_DEBUGF(TCP_WND_DEBUG,
904                     ("tcp_receive: no window update lastack %"U32_F" ackno %"
905                      U32_F" wl1 %"U32_F" seqno %"U32_F" wl2 %"U32_F"\n",
906                      pcb->lastack, ackno, pcb->snd_wl1, seqno, pcb->snd_wl2));
907       }
908 #endif /* TCP_WND_DEBUG */
909     }
910 
911     /* (From Stevens TCP/IP Illustrated Vol II, p970.) Its only a
912      * duplicate ack if:
913      * 1) It doesn't ACK new data
914      * 2) length of received packet is zero (i.e. no payload)
915      * 3) the advertised window hasn't changed
916      * 4) There is outstanding unacknowledged data (retransmission timer running)
917      * 5) The ACK is == biggest ACK sequence number so far seen (snd_una)
918      *
919      * If it passes all five, should process as a dupack:
920      * a) dupacks < 3: do nothing
921      * b) dupacks == 3: fast retransmit
922      * c) dupacks > 3: increase cwnd
923      *
924      * If it only passes 1-3, should reset dupack counter (and add to
925      * stats, which we don't do in lwIP)
926      *
927      * If it only passes 1, should reset dupack counter
928      *
929      */
930 
931     /* Clause 1 */
932     if (TCP_SEQ_LEQ(ackno, pcb->lastack)) {
933       pcb->acked = 0;
934       /* Clause 2 */
935       if (tcplen == 0) {
936         /* Clause 3 */
937         if (pcb->snd_wl2 + pcb->snd_wnd == right_wnd_edge){
938           /* Clause 4 */
939           if (pcb->rtime >= 0) {
940             /* Clause 5 */
941             if (pcb->lastack == ackno) {
942               found_dupack = 1;
943               if ((u8_t)(pcb->dupacks + 1) > pcb->dupacks) {
944                 ++pcb->dupacks;
945               }
946               if (pcb->dupacks > 3) {
947                 /* Inflate the congestion window, but not if it means that
948                    the value overflows. */
949                 if ((u16_t)(pcb->cwnd + pcb->mss) > pcb->cwnd) {
950                   pcb->cwnd += pcb->mss;
951                 }
952               } else if (pcb->dupacks == 3) {
953                 /* Do fast retransmit */
954                 tcp_rexmit_fast(pcb);
955               }
956             }
957           }
958         }
959       }
960       /* If Clause (1) or more is true, but not a duplicate ack, reset
961        * count of consecutive duplicate acks */
962       if (!found_dupack) {
963         pcb->dupacks = 0;
964       }
965     } else if (TCP_SEQ_BETWEEN(ackno, pcb->lastack+1, pcb->snd_nxt)){
966       /* We come here when the ACK acknowledges new data. */
967 
968       /* Reset the "IN Fast Retransmit" flag, since we are no longer
969          in fast retransmit. Also reset the congestion window to the
970          slow start threshold. */
971       if (pcb->flags & TF_INFR) {
972         pcb->flags &= ~TF_INFR;
973         pcb->cwnd = pcb->ssthresh;
974       }
975 
976       /* Reset the number of retransmissions. */
977       pcb->nrtx = 0;
978 
979       /* Reset the retransmission time-out. */
980       pcb->rto = (pcb->sa >> 3) + pcb->sv;
981 
982       /* Update the send buffer space. Diff between the two can never exceed 64K? */
983       pcb->acked = (u16_t)(ackno - pcb->lastack);
984 
985       pcb->snd_buf += pcb->acked;
986 
987       /* Reset the fast retransmit variables. */
988       pcb->dupacks = 0;
989       pcb->lastack = ackno;
990 
991       /* Update the congestion control variables (cwnd and
992          ssthresh). */
993       if (pcb->state >= ESTABLISHED) {
994         if (pcb->cwnd < pcb->ssthresh) {
995           if ((u16_t)(pcb->cwnd + pcb->mss) > pcb->cwnd) {
996             pcb->cwnd += pcb->mss;
997           }
998           LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_receive: slow start cwnd %"U16_F"\n", pcb->cwnd));
999         } else {
1000           u16_t new_cwnd = (pcb->cwnd + pcb->mss * pcb->mss / pcb->cwnd);
1001           if (new_cwnd > pcb->cwnd) {
1002             pcb->cwnd = new_cwnd;
1003           }
1004           LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_receive: congestion avoidance cwnd %"U16_F"\n", pcb->cwnd));
1005         }
1006       }
1007       LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: ACK for %"U32_F", unacked->seqno %"U32_F":%"U32_F"\n",
1008                                     ackno,
1009                                     pcb->unacked != NULL?
1010                                     ntohl(pcb->unacked->tcphdr->seqno): 0,
1011                                     pcb->unacked != NULL?
1012                                     ntohl(pcb->unacked->tcphdr->seqno) + TCP_TCPLEN(pcb->unacked): 0));
1013 
1014       /* Remove segment from the unacknowledged list if the incoming
1015          ACK acknowlegdes them. */
1016       while (pcb->unacked != NULL &&
1017              TCP_SEQ_LEQ(ntohl(pcb->unacked->tcphdr->seqno) +
1018                          TCP_TCPLEN(pcb->unacked), ackno)) {
1019         LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: removing %"U32_F":%"U32_F" from pcb->unacked\n",
1020                                       ntohl(pcb->unacked->tcphdr->seqno),
1021                                       ntohl(pcb->unacked->tcphdr->seqno) +
1022                                       TCP_TCPLEN(pcb->unacked)));
1023 
1024         next = pcb->unacked;
1025         pcb->unacked = pcb->unacked->next;
1026 
1027         LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_receive: queuelen %"U16_F" ... ", (u16_t)pcb->snd_queuelen));
1028         LWIP_ASSERT("pcb->snd_queuelen >= pbuf_clen(next->p)", (pcb->snd_queuelen >= pbuf_clen(next->p)));
1029         /* Prevent ACK for FIN to generate a sent event */
1030         if ((pcb->acked != 0) && ((TCPH_FLAGS(next->tcphdr) & TCP_FIN) != 0)) {
1031           pcb->acked--;
1032         }
1033 
1034         pcb->snd_queuelen -= pbuf_clen(next->p);
1035         tcp_seg_free(next);
1036 
1037         LWIP_DEBUGF(TCP_QLEN_DEBUG, ("%"U16_F" (after freeing unacked)\n", (u16_t)pcb->snd_queuelen));
1038         if (pcb->snd_queuelen != 0) {
1039           LWIP_ASSERT("tcp_receive: valid queue length", pcb->unacked != NULL ||
1040                       pcb->unsent != NULL);
1041         }
1042       }
1043 
1044       /* If there's nothing left to acknowledge, stop the retransmit
1045          timer, otherwise reset it to start again */
1046       if(pcb->unacked == NULL)
1047         pcb->rtime = -1;
1048       else
1049         pcb->rtime = 0;
1050 
1051       pcb->polltmr = 0;
1052     } else {
1053       /* Fix bug bug #21582: out of sequence ACK, didn't really ack anything */
1054       pcb->acked = 0;
1055     }
1056 
1057     /* We go through the ->unsent list to see if any of the segments
1058        on the list are acknowledged by the ACK. This may seem
1059        strange since an "unsent" segment shouldn't be acked. The
1060        rationale is that lwIP puts all outstanding segments on the
1061        ->unsent list after a retransmission, so these segments may
1062        in fact have been sent once. */
1063     while (pcb->unsent != NULL &&
1064            TCP_SEQ_BETWEEN(ackno, ntohl(pcb->unsent->tcphdr->seqno) +
1065                            TCP_TCPLEN(pcb->unsent), pcb->snd_nxt)) {
1066       LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: removing %"U32_F":%"U32_F" from pcb->unsent\n",
1067                                     ntohl(pcb->unsent->tcphdr->seqno), ntohl(pcb->unsent->tcphdr->seqno) +
1068                                     TCP_TCPLEN(pcb->unsent)));
1069 
1070       next = pcb->unsent;
1071       pcb->unsent = pcb->unsent->next;
1072 #if TCP_OVERSIZE
1073       if (pcb->unsent == NULL) {
1074         pcb->unsent_oversize = 0;
1075       }
1076 #endif /* TCP_OVERSIZE */
1077       LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_receive: queuelen %"U16_F" ... ", (u16_t)pcb->snd_queuelen));
1078       LWIP_ASSERT("pcb->snd_queuelen >= pbuf_clen(next->p)", (pcb->snd_queuelen >= pbuf_clen(next->p)));
1079       /* Prevent ACK for FIN to generate a sent event */
1080       if ((pcb->acked != 0) && ((TCPH_FLAGS(next->tcphdr) & TCP_FIN) != 0)) {
1081         pcb->acked--;
1082       }
1083       pcb->snd_queuelen -= pbuf_clen(next->p);
1084       tcp_seg_free(next);
1085       LWIP_DEBUGF(TCP_QLEN_DEBUG, ("%"U16_F" (after freeing unsent)\n", (u16_t)pcb->snd_queuelen));
1086       if (pcb->snd_queuelen != 0) {
1087         LWIP_ASSERT("tcp_receive: valid queue length",
1088           pcb->unacked != NULL || pcb->unsent != NULL);
1089       }
1090     }
1091     /* End of ACK for new data processing. */
1092 
1093     LWIP_DEBUGF(TCP_RTO_DEBUG, ("tcp_receive: pcb->rttest %"U32_F" rtseq %"U32_F" ackno %"U32_F"\n",
1094                                 pcb->rttest, pcb->rtseq, ackno));
1095 
1096     /* RTT estimation calculations. This is done by checking if the
1097        incoming segment acknowledges the segment we use to take a
1098        round-trip time measurement. */
1099     if (pcb->rttest && TCP_SEQ_LT(pcb->rtseq, ackno)) {
1100       /* diff between this shouldn't exceed 32K since this are tcp timer ticks
1101          and a round-trip shouldn't be that long... */
1102       m = (s16_t)(tcp_ticks - pcb->rttest);
1103 
1104       LWIP_DEBUGF(TCP_RTO_DEBUG, ("tcp_receive: experienced rtt %"U16_F" ticks (%"U16_F" msec).\n",
1105                                   m, m * TCP_SLOW_INTERVAL));
1106 
1107       /* This is taken directly from VJs original code in his paper */
1108       m = m - (pcb->sa >> 3);
1109       pcb->sa += m;
1110       if (m < 0) {
1111         m = -m;
1112       }
1113       m = m - (pcb->sv >> 2);
1114       pcb->sv += m;
1115       pcb->rto = (pcb->sa >> 3) + pcb->sv;
1116 
1117       LWIP_DEBUGF(TCP_RTO_DEBUG, ("tcp_receive: RTO %"U16_F" (%"U16_F" milliseconds)\n",
1118                                   pcb->rto, pcb->rto * TCP_SLOW_INTERVAL));
1119 
1120       pcb->rttest = 0;
1121     }
1122   }
1123 
1124   /* If the incoming segment contains data, we must process it
1125      further unless the pcb already received a FIN.
1126      (RFC 793, chapeter 3.9, "SEGMENT ARRIVES" in states CLOSE-WAIT, CLOSING,
1127      LAST-ACK and TIME-WAIT: "Ignore the segment text.") */
1128   if ((tcplen > 0) && (pcb->state < CLOSE_WAIT)) {
1129     /* This code basically does three things:
1130 
1131     +) If the incoming segment contains data that is the next
1132     in-sequence data, this data is passed to the application. This
1133     might involve trimming the first edge of the data. The rcv_nxt
1134     variable and the advertised window are adjusted.
1135 
1136     +) If the incoming segment has data that is above the next
1137     sequence number expected (->rcv_nxt), the segment is placed on
1138     the ->ooseq queue. This is done by finding the appropriate
1139     place in the ->ooseq queue (which is ordered by sequence
1140     number) and trim the segment in both ends if needed. An
1141     immediate ACK is sent to indicate that we received an
1142     out-of-sequence segment.
1143 
1144     +) Finally, we check if the first segment on the ->ooseq queue
1145     now is in sequence (i.e., if rcv_nxt >= ooseq->seqno). If
1146     rcv_nxt > ooseq->seqno, we must trim the first edge of the
1147     segment on ->ooseq before we adjust rcv_nxt. The data in the
1148     segments that are now on sequence are chained onto the
1149     incoming segment so that we only need to call the application
1150     once.
1151     */
1152 
1153     /* First, we check if we must trim the first edge. We have to do
1154        this if the sequence number of the incoming segment is less
1155        than rcv_nxt, and the sequence number plus the length of the
1156        segment is larger than rcv_nxt. */
1157     /*    if (TCP_SEQ_LT(seqno, pcb->rcv_nxt)){
1158           if (TCP_SEQ_LT(pcb->rcv_nxt, seqno + tcplen)) {*/
1159     if (TCP_SEQ_BETWEEN(pcb->rcv_nxt, seqno + 1, seqno + tcplen - 1)){
1160       /* Trimming the first edge is done by pushing the payload
1161          pointer in the pbuf downwards. This is somewhat tricky since
1162          we do not want to discard the full contents of the pbuf up to
1163          the new starting point of the data since we have to keep the
1164          TCP header which is present in the first pbuf in the chain.
1165 
1166          What is done is really quite a nasty hack: the first pbuf in
1167          the pbuf chain is pointed to by inseg.p. Since we need to be
1168          able to deallocate the whole pbuf, we cannot change this
1169          inseg.p pointer to point to any of the later pbufs in the
1170          chain. Instead, we point the ->payload pointer in the first
1171          pbuf to data in one of the later pbufs. We also set the
1172          inseg.data pointer to point to the right place. This way, the
1173          ->p pointer will still point to the first pbuf, but the
1174          ->p->payload pointer will point to data in another pbuf.
1175 
1176          After we are done with adjusting the pbuf pointers we must
1177          adjust the ->data pointer in the seg and the segment
1178          length.*/
1179 
1180       off = pcb->rcv_nxt - seqno;
1181       p = inseg.p;
1182       LWIP_ASSERT("inseg.p != NULL", inseg.p);
1183       LWIP_ASSERT("insane offset!", (off < 0x7fff));
1184       if (inseg.p->len < off) {
1185         LWIP_ASSERT("pbuf too short!", (((s32_t)inseg.p->tot_len) >= off));
1186         new_tot_len = (u16_t)(inseg.p->tot_len - off);
1187         while (p->len < off) {
1188           off -= p->len;
1189           /* KJM following line changed (with addition of new_tot_len var)
1190              to fix bug #9076
1191              inseg.p->tot_len -= p->len; */
1192           p->tot_len = new_tot_len;
1193           p->len = 0;
1194           p = p->next;
1195         }
1196         if(pbuf_header(p, (s16_t)-off)) {
1197           /* Do we need to cope with this failing?  Assert for now */
1198           LWIP_ASSERT("pbuf_header failed", 0);
1199         }
1200       } else {
1201         if(pbuf_header(inseg.p, (s16_t)-off)) {
1202           /* Do we need to cope with this failing?  Assert for now */
1203           LWIP_ASSERT("pbuf_header failed", 0);
1204         }
1205       }
1206       inseg.len -= (u16_t)(pcb->rcv_nxt - seqno);
1207       inseg.tcphdr->seqno = seqno = pcb->rcv_nxt;
1208     }
1209     else {
1210       if (TCP_SEQ_LT(seqno, pcb->rcv_nxt)){
1211         /* the whole segment is < rcv_nxt */
1212         /* must be a duplicate of a packet that has already been correctly handled */
1213 
1214         LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: duplicate seqno %"U32_F"\n", seqno));
1215         tcp_ack_now(pcb);
1216       }
1217     }
1218 
1219     /* The sequence number must be within the window (above rcv_nxt
1220        and below rcv_nxt + rcv_wnd) in order to be further
1221        processed. */
1222     if (TCP_SEQ_BETWEEN(seqno, pcb->rcv_nxt,
1223                         pcb->rcv_nxt + pcb->rcv_wnd - 1)){
1224       if (pcb->rcv_nxt == seqno) {
1225         /* The incoming segment is the next in sequence. We check if
1226            we have to trim the end of the segment and update rcv_nxt
1227            and pass the data to the application. */
1228         tcplen = TCP_TCPLEN(&inseg);
1229 
1230         if (tcplen > pcb->rcv_wnd) {
1231           LWIP_DEBUGF(TCP_INPUT_DEBUG,
1232                       ("tcp_receive: other end overran receive window"
1233                        "seqno %"U32_F" len %"U16_F" right edge %"U32_F"\n",
1234                        seqno, tcplen, pcb->rcv_nxt + pcb->rcv_wnd));
1235           if (TCPH_FLAGS(inseg.tcphdr) & TCP_FIN) {
1236             /* Must remove the FIN from the header as we're trimming
1237              * that byte of sequence-space from the packet */
1238             TCPH_FLAGS_SET(inseg.tcphdr, TCPH_FLAGS(inseg.tcphdr) &~ TCP_FIN);
1239           }
1240           /* Adjust length of segment to fit in the window. */
1241           inseg.len = pcb->rcv_wnd;
1242           if (TCPH_FLAGS(inseg.tcphdr) & TCP_SYN) {
1243             inseg.len -= 1;
1244           }
1245           pbuf_realloc(inseg.p, inseg.len);
1246           tcplen = TCP_TCPLEN(&inseg);
1247           LWIP_ASSERT("tcp_receive: segment not trimmed correctly to rcv_wnd\n",
1248                       (seqno + tcplen) == (pcb->rcv_nxt + pcb->rcv_wnd));
1249         }
1250 #if TCP_QUEUE_OOSEQ
1251         /* Received in-sequence data, adjust ooseq data if:
1252            - FIN has been received or
1253            - inseq overlaps with ooseq */
1254         if (pcb->ooseq != NULL) {
1255           if (TCPH_FLAGS(inseg.tcphdr) & TCP_FIN) {
1256             LWIP_DEBUGF(TCP_INPUT_DEBUG,
1257                         ("tcp_receive: received in-order FIN, binning ooseq queue\n"));
1258             /* Received in-order FIN means anything that was received
1259              * out of order must now have been received in-order, so
1260              * bin the ooseq queue */
1261             while (pcb->ooseq != NULL) {
1262               struct tcp_seg *old_ooseq = pcb->ooseq;
1263               pcb->ooseq = pcb->ooseq->next;
1264               tcp_seg_free(old_ooseq);
1265             }
1266           } else {
1267             next = pcb->ooseq;
1268             /* Remove all segments on ooseq that are covered by inseg already.
1269              * FIN is copied from ooseq to inseg if present. */
1270             while (next &&
1271                    TCP_SEQ_GEQ(seqno + tcplen,
1272                                next->tcphdr->seqno + next->len)) {
1273               /* inseg cannot have FIN here (already processed above) */
1274               if (TCPH_FLAGS(next->tcphdr) & TCP_FIN &&
1275                   (TCPH_FLAGS(inseg.tcphdr) & TCP_SYN) == 0) {
1276                 TCPH_SET_FLAG(inseg.tcphdr, TCP_FIN);
1277                 tcplen = TCP_TCPLEN(&inseg);
1278               }
1279               prev = next;
1280               next = next->next;
1281               tcp_seg_free(prev);
1282             }
1283             /* Now trim right side of inseg if it overlaps with the first
1284              * segment on ooseq */
1285             if (next &&
1286                 TCP_SEQ_GT(seqno + tcplen,
1287                            next->tcphdr->seqno)) {
1288               /* inseg cannot have FIN here (already processed above) */
1289               inseg.len = (u16_t)(next->tcphdr->seqno - seqno);
1290               if (TCPH_FLAGS(inseg.tcphdr) & TCP_SYN) {
1291                 inseg.len -= 1;
1292               }
1293               pbuf_realloc(inseg.p, inseg.len);
1294               tcplen = TCP_TCPLEN(&inseg);
1295               LWIP_ASSERT("tcp_receive: segment not trimmed correctly to ooseq queue\n",
1296                           (seqno + tcplen) == next->tcphdr->seqno);
1297             }
1298             pcb->ooseq = next;
1299           }
1300         }
1301 #endif /* TCP_QUEUE_OOSEQ */
1302 
1303         pcb->rcv_nxt = seqno + tcplen;
1304 
1305         /* Update the receiver's (our) window. */
1306         LWIP_ASSERT("tcp_receive: tcplen > rcv_wnd\n", pcb->rcv_wnd >= tcplen);
1307         pcb->rcv_wnd -= tcplen;
1308 
1309         tcp_update_rcv_ann_wnd(pcb);
1310 
1311         /* If there is data in the segment, we make preparations to
1312            pass this up to the application. The ->recv_data variable
1313            is used for holding the pbuf that goes to the
1314            application. The code for reassembling out-of-sequence data
1315            chains its data on this pbuf as well.
1316 
1317            If the segment was a FIN, we set the TF_GOT_FIN flag that will
1318            be used to indicate to the application that the remote side has
1319            closed its end of the connection. */
1320         if (inseg.p->tot_len > 0) {
1321           recv_data = inseg.p;
1322           /* Since this pbuf now is the responsibility of the
1323              application, we delete our reference to it so that we won't
1324              (mistakingly) deallocate it. */
1325           inseg.p = NULL;
1326         }
1327         if (TCPH_FLAGS(inseg.tcphdr) & TCP_FIN) {
1328           LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: received FIN.\n"));
1329           recv_flags |= TF_GOT_FIN;
1330         }
1331 
1332 #if TCP_QUEUE_OOSEQ
1333         /* We now check if we have segments on the ->ooseq queue that
1334            are now in sequence. */
1335         while (pcb->ooseq != NULL &&
1336                pcb->ooseq->tcphdr->seqno == pcb->rcv_nxt) {
1337 
1338           cseg = pcb->ooseq;
1339           seqno = pcb->ooseq->tcphdr->seqno;
1340 
1341           pcb->rcv_nxt += TCP_TCPLEN(cseg);
1342           LWIP_ASSERT("tcp_receive: ooseq tcplen > rcv_wnd\n",
1343                       pcb->rcv_wnd >= TCP_TCPLEN(cseg));
1344           pcb->rcv_wnd -= TCP_TCPLEN(cseg);
1345 
1346           tcp_update_rcv_ann_wnd(pcb);
1347 
1348           if (cseg->p->tot_len > 0) {
1349             /* Chain this pbuf onto the pbuf that we will pass to
1350                the application. */
1351             if (recv_data) {
1352               pbuf_cat(recv_data, cseg->p);
1353             } else {
1354               recv_data = cseg->p;
1355             }
1356             cseg->p = NULL;
1357           }
1358           if (TCPH_FLAGS(cseg->tcphdr) & TCP_FIN) {
1359             LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: dequeued FIN.\n"));
1360             recv_flags |= TF_GOT_FIN;
1361             if (pcb->state == ESTABLISHED) { /* force passive close or we can move to active close */
1362               pcb->state = CLOSE_WAIT;
1363             }
1364           }
1365 
1366           pcb->ooseq = cseg->next;
1367           tcp_seg_free(cseg);
1368         }
1369 #endif /* TCP_QUEUE_OOSEQ */
1370 
1371 
1372         /* Acknowledge the segment(s). */
1373         tcp_ack(pcb);
1374 
1375       } else {
1376         /* We get here if the incoming segment is out-of-sequence. */
1377         tcp_send_empty_ack(pcb);
1378 #if TCP_QUEUE_OOSEQ
1379         /* We queue the segment on the ->ooseq queue. */
1380         if (pcb->ooseq == NULL) {
1381           pcb->ooseq = tcp_seg_copy(&inseg);
1382         } else {
1383           /* If the queue is not empty, we walk through the queue and
1384              try to find a place where the sequence number of the
1385              incoming segment is between the sequence numbers of the
1386              previous and the next segment on the ->ooseq queue. That is
1387              the place where we put the incoming segment. If needed, we
1388              trim the second edges of the previous and the incoming
1389              segment so that it will fit into the sequence.
1390 
1391              If the incoming segment has the same sequence number as a
1392              segment on the ->ooseq queue, we discard the segment that
1393              contains less data. */
1394 
1395           prev = NULL;
1396           for(next = pcb->ooseq; next != NULL; next = next->next) {
1397             if (seqno == next->tcphdr->seqno) {
1398               /* The sequence number of the incoming segment is the
1399                  same as the sequence number of the segment on
1400                  ->ooseq. We check the lengths to see which one to
1401                  discard. */
1402               if (inseg.len > next->len) {
1403                 /* The incoming segment is larger than the old
1404                    segment. We replace some segments with the new
1405                    one. */
1406                 cseg = tcp_seg_copy(&inseg);
1407                 if (cseg != NULL) {
1408                   if (prev != NULL) {
1409                     prev->next = cseg;
1410                   } else {
1411                     pcb->ooseq = cseg;
1412                   }
1413                   tcp_oos_insert_segment(cseg, next);
1414                 }
1415                 break;
1416               } else {
1417                 /* Either the lenghts are the same or the incoming
1418                    segment was smaller than the old one; in either
1419                    case, we ditch the incoming segment. */
1420                 break;
1421               }
1422             } else {
1423               if (prev == NULL) {
1424                 if (TCP_SEQ_LT(seqno, next->tcphdr->seqno)) {
1425                   /* The sequence number of the incoming segment is lower
1426                      than the sequence number of the first segment on the
1427                      queue. We put the incoming segment first on the
1428                      queue. */
1429                   cseg = tcp_seg_copy(&inseg);
1430                   if (cseg != NULL) {
1431                     pcb->ooseq = cseg;
1432                     tcp_oos_insert_segment(cseg, next);
1433                   }
1434                   break;
1435                 }
1436               } else {
1437                 /*if (TCP_SEQ_LT(prev->tcphdr->seqno, seqno) &&
1438                   TCP_SEQ_LT(seqno, next->tcphdr->seqno)) {*/
1439                 if (TCP_SEQ_BETWEEN(seqno, prev->tcphdr->seqno+1, next->tcphdr->seqno-1)) {
1440                   /* The sequence number of the incoming segment is in
1441                      between the sequence numbers of the previous and
1442                      the next segment on ->ooseq. We trim trim the previous
1443                      segment, delete next segments that included in received segment
1444                      and trim received, if needed. */
1445                   cseg = tcp_seg_copy(&inseg);
1446                   if (cseg != NULL) {
1447                     if (TCP_SEQ_GT(prev->tcphdr->seqno + prev->len, seqno)) {
1448                       /* We need to trim the prev segment. */
1449                       prev->len = (u16_t)(seqno - prev->tcphdr->seqno);
1450                       pbuf_realloc(prev->p, prev->len);
1451                     }
1452                     prev->next = cseg;
1453                     tcp_oos_insert_segment(cseg, next);
1454                   }
1455                   break;
1456                 }
1457               }
1458               /* If the "next" segment is the last segment on the
1459                  ooseq queue, we add the incoming segment to the end
1460                  of the list. */
1461               if (next->next == NULL &&
1462                   TCP_SEQ_GT(seqno, next->tcphdr->seqno)) {
1463                 if (TCPH_FLAGS(next->tcphdr) & TCP_FIN) {
1464                   /* segment "next" already contains all data */
1465                   break;
1466                 }
1467                 next->next = tcp_seg_copy(&inseg);
1468                 if (next->next != NULL) {
1469                   if (TCP_SEQ_GT(next->tcphdr->seqno + next->len, seqno)) {
1470                     /* We need to trim the last segment. */
1471                     next->len = (u16_t)(seqno - next->tcphdr->seqno);
1472                     pbuf_realloc(next->p, next->len);
1473                   }
1474                   /* check if the remote side overruns our receive window */
1475                   if ((u32_t)tcplen + seqno > pcb->rcv_nxt + (u32_t)pcb->rcv_wnd) {
1476                     LWIP_DEBUGF(TCP_INPUT_DEBUG,
1477                                 ("tcp_receive: other end overran receive window"
1478                                  "seqno %"U32_F" len %"U16_F" right edge %"U32_F"\n",
1479                                  seqno, tcplen, pcb->rcv_nxt + pcb->rcv_wnd));
1480                     if (TCPH_FLAGS(next->next->tcphdr) & TCP_FIN) {
1481                       /* Must remove the FIN from the header as we're trimming
1482                        * that byte of sequence-space from the packet */
1483                       TCPH_FLAGS_SET(next->next->tcphdr, TCPH_FLAGS(next->next->tcphdr) &~ TCP_FIN);
1484                     }
1485                     /* Adjust length of segment to fit in the window. */
1486                     next->next->len = pcb->rcv_nxt + pcb->rcv_wnd - seqno;
1487                     pbuf_realloc(next->next->p, next->next->len);
1488                     tcplen = TCP_TCPLEN(next->next);
1489                     LWIP_ASSERT("tcp_receive: segment not trimmed correctly to rcv_wnd\n",
1490                                 (seqno + tcplen) == (pcb->rcv_nxt + pcb->rcv_wnd));
1491                   }
1492                 }
1493                 break;
1494               }
1495             }
1496             prev = next;
1497           }
1498         }
1499 #if TCP_OOSEQ_MAX_BYTES || TCP_OOSEQ_MAX_PBUFS
1500         /* Check that the data on ooseq doesn't exceed one of the limits
1501            and throw away everything above that limit. */
1502         ooseq_blen = 0;
1503         ooseq_qlen = 0;
1504         prev = NULL;
1505         for(next = pcb->ooseq; next != NULL; prev = next, next = next->next) {
1506           struct pbuf *p = next->p;
1507           ooseq_blen += p->tot_len;
1508           ooseq_qlen += pbuf_clen(p);
1509           if ((ooseq_blen > TCP_OOSEQ_MAX_BYTES) ||
1510               (ooseq_qlen > TCP_OOSEQ_MAX_PBUFS)) {
1511              /* too much ooseq data, dump this and everything after it */
1512              tcp_segs_free(next);
1513              if (prev == NULL) {
1514                /* first ooseq segment is too much, dump the whole queue */
1515                pcb->ooseq = NULL;
1516              } else {
1517                /* just dump 'next' and everything after it */
1518                prev->next = NULL;
1519              }
1520              break;
1521           }
1522         }
1523 #endif /* TCP_OOSEQ_MAX_BYTES || TCP_OOSEQ_MAX_PBUFS */
1524 #endif /* TCP_QUEUE_OOSEQ */
1525       }
1526     } else {
1527       /* The incoming segment is not withing the window. */
1528       tcp_send_empty_ack(pcb);
1529     }
1530   } else {
1531     /* Segments with length 0 is taken care of here. Segments that
1532        fall out of the window are ACKed. */
1533     /*if (TCP_SEQ_GT(pcb->rcv_nxt, seqno) ||
1534       TCP_SEQ_GEQ(seqno, pcb->rcv_nxt + pcb->rcv_wnd)) {*/
1535     if(!TCP_SEQ_BETWEEN(seqno, pcb->rcv_nxt, pcb->rcv_nxt + pcb->rcv_wnd-1)){
1536       tcp_ack_now(pcb);
1537     }
1538   }
1539 }
1540 
1541 /**
1542  * Parses the options contained in the incoming segment.
1543  *
1544  * Called from tcp_listen_input() and tcp_process().
1545  * Currently, only the MSS option is supported!
1546  *
1547  * @param pcb the tcp_pcb for which a segment arrived
1548  */
1549 static void
1550 tcp_parseopt(struct tcp_pcb *pcb)
1551 {
1552   u16_t c, max_c;
1553   u16_t mss;
1554   u8_t *opts, opt;
1555 #if LWIP_TCP_TIMESTAMPS
1556   u32_t tsval;
1557 #endif
1558 
1559   opts = (u8_t *)tcphdr + TCP_HLEN;
1560 
1561   /* Parse the TCP MSS option, if present. */
1562   if(TCPH_HDRLEN(tcphdr) > 0x5) {
1563     max_c = (TCPH_HDRLEN(tcphdr) - 5) << 2;
1564     for (c = 0; c < max_c; ) {
1565       opt = opts[c];
1566       switch (opt) {
1567       case 0x00:
1568         /* End of options. */
1569         LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: EOL\n"));
1570         return;
1571       case 0x01:
1572         /* NOP option. */
1573         ++c;
1574         LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: NOP\n"));
1575         break;
1576       case 0x02:
1577         LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: MSS\n"));
1578         if (opts[c + 1] != 0x04 || c + 0x04 > max_c) {
1579           /* Bad length */
1580           LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: bad length\n"));
1581           return;
1582         }
1583         /* An MSS option with the right option length. */
1584         mss = (opts[c + 2] << 8) | opts[c + 3];
1585         /* Limit the mss to the configured TCP_MSS and prevent division by zero */
1586         pcb->mss = ((mss > TCP_MSS) || (mss == 0)) ? TCP_MSS : mss;
1587         /* Advance to next option */
1588         c += 0x04;
1589         break;
1590 #if LWIP_TCP_TIMESTAMPS
1591       case 0x08:
1592         LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: TS\n"));
1593         if (opts[c + 1] != 0x0A || c + 0x0A > max_c) {
1594           /* Bad length */
1595           LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: bad length\n"));
1596           return;
1597         }
1598         /* TCP timestamp option with valid length */
1599         tsval = (opts[c+2]) | (opts[c+3] << 8) |
1600           (opts[c+4] << 16) | (opts[c+5] << 24);
1601         if (flags & TCP_SYN) {
1602           pcb->ts_recent = ntohl(tsval);
1603           pcb->flags |= TF_TIMESTAMP;
1604         } else if (TCP_SEQ_BETWEEN(pcb->ts_lastacksent, seqno, seqno+tcplen)) {
1605           pcb->ts_recent = ntohl(tsval);
1606         }
1607         /* Advance to next option */
1608         c += 0x0A;
1609         break;
1610 #endif
1611       default:
1612         LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: other\n"));
1613         if (opts[c + 1] == 0) {
1614           LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: bad length\n"));
1615           /* If the length field is zero, the options are malformed
1616              and we don't process them further. */
1617           return;
1618         }
1619         /* All other options have a length field, so that we easily
1620            can skip past them. */
1621         c += opts[c + 1];
1622       }
1623     }
1624   }
1625 }
1626 
1627 #endif /* LWIP_TCP */
1628