/[lwip]/lwip/src/core/tcp_in.c
ViewVC logotype

Annotation of /lwip/src/core/tcp_in.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.150 - (hide annotations) (download)
Sat May 28 09:28:18 2011 UTC (12 years, 6 months ago) by goldsimon
Branch: MAIN
CVS Tags: cvs-repository-moved-to-git, HEAD
Changes since 1.149: +5 -5 lines
File MIME type: text/plain
use PCB_IS_IPV6(pcb) instead of pcb->isipv6 everywhere

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

savannah-hackers-public@gnu.org
ViewVC Help
Powered by ViewVC 1.1.26