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