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