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