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