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).
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
38 * This file is part of the lwIP TCP/IP stack.
40 * Author: Adam Dunkels <adam@sics.se>
46 #if LWIP_TCP /* don't build if not configured for use in lwipopts.h */
48 #include "lwip/tcp_impl.h"
50 #include "lwip/ip_addr.h"
51 #include "lwip/netif.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 #include "lwip/ip6_addr.h"
60 #include "lwip/inet_chksum.h"
61 #if LWIP_ND6_TCP_REACHABILITY_HINTS
63 #endif /* LWIP_ND6_TCP_REACHABILITY_HINTS */
65 /* These variables are global to all functions involved in the input
66 processing of TCP segments. They are set by the tcp_input()
68 static struct tcp_seg inseg;
69 static struct tcp_hdr *tcphdr;
70 static u32_t seqno, ackno;
74 static u8_t recv_flags;
75 static struct pbuf *recv_data;
77 struct tcp_pcb *tcp_input_pcb;
79 /* Forward declarations. */
80 static err_t tcp_process(struct tcp_pcb *pcb);
81 static void tcp_receive(struct tcp_pcb *pcb);
82 static void tcp_parseopt(struct tcp_pcb *pcb);
84 static err_t tcp_listen_input(struct tcp_pcb_listen *pcb);
85 static err_t tcp_timewait_input(struct tcp_pcb *pcb);
88 * The initial input processing of TCP. It verifies the TCP header, demultiplexes
89 * the segment between the PCBs and passes it on to tcp_process(), which implements
90 * the TCP finite state machine. This function is called by the IP layer (in
93 * @param p received TCP segment to process (p->payload pointing to the TCP header)
94 * @param inp network interface on which this segment was received
97 tcp_input(struct pbuf *p, struct netif *inp)
99 struct tcp_pcb *pcb, *prev;
100 struct tcp_pcb_listen *lpcb;
102 struct tcp_pcb *lpcb_prev = NULL;
103 struct tcp_pcb_listen *lpcb_any = NULL;
104 #endif /* SO_REUSE */
107 #if CHECKSUM_CHECK_TCP
109 #endif /* CHECKSUM_CHECK_TCP */
113 TCP_STATS_INC(tcp.recv);
114 snmp_inc_tcpinsegs();
116 tcphdr = (struct tcp_hdr *)p->payload;
119 tcp_debug_print(tcphdr);
122 /* Check that TCP header fits in payload */
123 if (p->len < sizeof(struct tcp_hdr)) {
124 /* drop short packets */
125 LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: short packet (%"U16_F" bytes) discarded\n", p->tot_len));
126 TCP_STATS_INC(tcp.lenerr);
130 /* Don't even process incoming broadcasts/multicasts. */
131 if ((!ip_current_is_v6() && ip_addr_isbroadcast(ip_current_dest_addr(), inp)) ||
132 ipX_addr_ismulticast(ip_current_is_v6(), ipX_current_dest_addr())) {
133 TCP_STATS_INC(tcp.proterr);
137 #if CHECKSUM_CHECK_TCP
138 /* Verify TCP checksum. */
139 chksum = ipX_chksum_pseudo(ip_current_is_v6(), p, IP_PROTO_TCP, p->tot_len,
140 ipX_current_src_addr(), ipX_current_dest_addr());
142 LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: packet discarded due to failing checksum 0x%04"X16_F"\n",
144 tcp_debug_print(tcphdr);
145 TCP_STATS_INC(tcp.chkerr);
148 #endif /* CHECKSUM_CHECK_TCP */
150 /* Move the payload pointer in the pbuf so that it points to the
151 TCP data instead of the TCP header. */
152 hdrlen = TCPH_HDRLEN(tcphdr);
153 if(pbuf_header(p, -(hdrlen * 4))){
154 /* drop short packets */
155 LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: short packet\n"));
156 TCP_STATS_INC(tcp.lenerr);
160 /* Convert fields in TCP header to host byte order. */
161 tcphdr->src = ntohs(tcphdr->src);
162 tcphdr->dest = ntohs(tcphdr->dest);
163 seqno = tcphdr->seqno = ntohl(tcphdr->seqno);
164 ackno = tcphdr->ackno = ntohl(tcphdr->ackno);
165 tcphdr->wnd = ntohs(tcphdr->wnd);
167 flags = TCPH_FLAGS(tcphdr);
168 tcplen = p->tot_len + ((flags & (TCP_FIN | TCP_SYN)) ? 1 : 0);
170 /* Demultiplex an incoming segment. First, we check if it is destined
171 for an active connection. */
175 for(pcb = tcp_active_pcbs; pcb != NULL; pcb = pcb->next) {
176 LWIP_ASSERT("tcp_input: active pcb->state != CLOSED", pcb->state != CLOSED);
177 LWIP_ASSERT("tcp_input: active pcb->state != TIME-WAIT", pcb->state != TIME_WAIT);
178 LWIP_ASSERT("tcp_input: active pcb->state != LISTEN", pcb->state != LISTEN);
179 if (pcb->remote_port == tcphdr->src &&
180 pcb->local_port == tcphdr->dest &&
181 IP_PCB_IPVER_INPUT_MATCH(pcb) &&
182 ipX_addr_cmp(ip_current_is_v6(), &pcb->remote_ip, ipX_current_src_addr()) &&
183 ipX_addr_cmp(ip_current_is_v6(),&pcb->local_ip, ipX_current_dest_addr())) {
184 /* Move this PCB to the front of the list so that subsequent
185 lookups will be faster (we exploit locality in TCP segment
187 LWIP_ASSERT("tcp_input: pcb->next != pcb (before cache)", pcb->next != pcb);
189 prev->next = pcb->next;
190 pcb->next = tcp_active_pcbs;
191 tcp_active_pcbs = pcb;
193 LWIP_ASSERT("tcp_input: pcb->next != pcb (after cache)", pcb->next != pcb);
200 /* If it did not go to an active connection, we check the connections
201 in the TIME-WAIT state. */
202 for(pcb = tcp_tw_pcbs; pcb != NULL; pcb = pcb->next) {
203 LWIP_ASSERT("tcp_input: TIME-WAIT pcb->state == TIME-WAIT", pcb->state == TIME_WAIT);
204 if (pcb->remote_port == tcphdr->src &&
205 pcb->local_port == tcphdr->dest &&
206 IP_PCB_IPVER_INPUT_MATCH(pcb) &&
207 ipX_addr_cmp(ip_current_is_v6(), &pcb->remote_ip, ipX_current_src_addr()) &&
208 ipX_addr_cmp(ip_current_is_v6(),&pcb->local_ip, ipX_current_dest_addr())) {
209 /* We don't really care enough to move this PCB to the front
210 of the list since we are not very likely to receive that
211 many segments for connections in TIME-WAIT. */
212 LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: packed for TIME_WAITing connection.\n"));
213 tcp_timewait_input(pcb);
219 /* Finally, if we still did not get a match, we check all PCBs that
220 are LISTENing for incoming connections. */
222 for(lpcb = tcp_listen_pcbs.listen_pcbs; lpcb != NULL; lpcb = lpcb->next) {
223 if (lpcb->local_port == tcphdr->dest) {
225 if (lpcb->accept_any_ip_version) {
226 /* found an ANY-match */
232 #endif /* SO_REUSE */
234 #endif /* LWIP_IPV6 */
235 if (IP_PCB_IPVER_INPUT_MATCH(lpcb)) {
236 if (ipX_addr_cmp(ip_current_is_v6(), &lpcb->local_ip, ipX_current_dest_addr())) {
237 /* found an exact match */
239 } else if (ipX_addr_isany(ip_current_is_v6(), &lpcb->local_ip)) {
240 /* found an ANY-match */
246 #endif /* SO_REUSE */
250 prev = (struct tcp_pcb *)lpcb;
253 /* first try specific local IP */
255 /* only pass to ANY if no specific local IP has been found */
259 #endif /* SO_REUSE */
261 /* Move this PCB to the front of the list so that subsequent
262 lookups will be faster (we exploit locality in TCP segment
265 ((struct tcp_pcb_listen *)prev)->next = lpcb->next;
266 /* our successor is the remainder of the listening list */
267 lpcb->next = tcp_listen_pcbs.listen_pcbs;
268 /* put this listening pcb at the head of the listening list */
269 tcp_listen_pcbs.listen_pcbs = lpcb;
272 LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: packed for LISTENing connection.\n"));
273 tcp_listen_input(lpcb);
280 LWIP_DEBUGF(TCP_INPUT_DEBUG, ("+-+-+-+-+-+-+-+-+-+-+-+-+-+- tcp_input: flags "));
281 tcp_debug_print_flags(TCPH_FLAGS(tcphdr));
282 LWIP_DEBUGF(TCP_INPUT_DEBUG, ("-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n"));
283 #endif /* TCP_INPUT_DEBUG */
287 /* The incoming segment belongs to a connection. */
290 tcp_debug_print_state(pcb->state);
291 #endif /* TCP_DEBUG */
292 #endif /* TCP_INPUT_DEBUG */
294 /* Set up a tcp_seg structure. */
296 inseg.len = p->tot_len;
298 inseg.tcphdr = tcphdr;
303 if (flags & TCP_PSH) {
304 p->flags |= PBUF_FLAG_PUSH;
307 /* If there is data which was previously "refused" by upper layer */
308 if (pcb->refused_data != NULL) {
309 /* Notify again application with data previously received. */
310 LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: notify kept packet\n"));
311 TCP_EVENT_RECV(pcb, pcb->refused_data, ERR_OK, err);
313 pcb->refused_data = NULL;
314 } else if ((err == ERR_ABRT) || (tcplen > 0)) {
315 /* if err == ERR_ABRT, 'pcb' is already deallocated */
316 /* Drop incoming packets because pcb is "full" (only if the incoming
317 segment contains data). */
318 LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: drop incoming packets, because pcb is \"full\"\n"));
323 err = tcp_process(pcb);
324 /* A return value of ERR_ABRT means that tcp_abort() was called
325 and that the pcb has been freed. If so, we don't do anything. */
326 if (err != ERR_ABRT) {
327 if (recv_flags & TF_RESET) {
328 /* TF_RESET means that the connection was reset by the other
329 end. We then call the error callback to inform the
330 application that the connection is dead before we
331 deallocate the PCB. */
332 TCP_EVENT_ERR(pcb->errf, pcb->callback_arg, ERR_RST);
333 tcp_pcb_remove(&tcp_active_pcbs, pcb);
334 memp_free(MEMP_TCP_PCB, pcb);
335 } else if (recv_flags & TF_CLOSED) {
336 /* The connection has been closed and we will deallocate the
338 tcp_pcb_remove(&tcp_active_pcbs, pcb);
339 memp_free(MEMP_TCP_PCB, pcb);
342 /* If the application has registered a "sent" function to be
343 called when new send buffer space is available, we call it
345 if (pcb->acked > 0) {
346 TCP_EVENT_SENT(pcb, pcb->acked, err);
347 if (err == ERR_ABRT) {
352 if (recv_data != NULL) {
353 LWIP_ASSERT("pcb->refused_data == NULL", pcb->refused_data == NULL);
354 if (pcb->flags & TF_RXCLOSED) {
355 /* received data although already closed -> abort (send RST) to
356 notify the remote host that not all data has been processed */
357 pbuf_free(recv_data);
362 /* Notify application that data has been received. */
363 TCP_EVENT_RECV(pcb, recv_data, ERR_OK, err);
364 if (err == ERR_ABRT) {
368 /* If the upper layer can't receive this data, store it */
370 pcb->refused_data = recv_data;
371 LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: keep incoming packet, because pcb is \"full\"\n"));
375 /* If a FIN segment was received, we call the callback
376 function with a NULL buffer to indicate EOF. */
377 if (recv_flags & TF_GOT_FIN) {
378 /* correct rcv_wnd as the application won't call tcp_recved()
379 for the FIN's seqno */
380 if (pcb->rcv_wnd != TCP_WND) {
383 TCP_EVENT_CLOSED(pcb, err);
384 if (err == ERR_ABRT) {
389 tcp_input_pcb = NULL;
390 /* Try to send something out. */
394 tcp_debug_print_state(pcb->state);
395 #endif /* TCP_DEBUG */
396 #endif /* TCP_INPUT_DEBUG */
399 /* Jump target if pcb has been aborted in a callback (by calling tcp_abort()).
400 Below this line, 'pcb' may not be dereferenced! */
402 tcp_input_pcb = NULL;
405 /* give up our reference to inseg.p */
413 /* If no matching PCB was found, send a TCP RST (reset) to the
415 LWIP_DEBUGF(TCP_RST_DEBUG, ("tcp_input: no PCB match found, resetting.\n"));
416 if (!(TCPH_FLAGS(tcphdr) & TCP_RST)) {
417 TCP_STATS_INC(tcp.proterr);
418 TCP_STATS_INC(tcp.drop);
419 tcp_rst(ackno, seqno + tcplen, ipX_current_dest_addr(),
420 ipX_current_src_addr(), tcphdr->dest, tcphdr->src, ip_current_is_v6());
425 LWIP_ASSERT("tcp_input: tcp_pcbs_sane()", tcp_pcbs_sane());
426 PERF_STOP("tcp_input");
429 TCP_STATS_INC(tcp.drop);
430 snmp_inc_tcpinerrs();
435 * Called by tcp_input() when a segment arrives for a listening
436 * connection (from tcp_input()).
438 * @param pcb the tcp_pcb_listen for which a segment arrived
439 * @return ERR_OK if the segment was processed
440 * another err_t on error
442 * @note the return value is not (yet?) used in tcp_input()
443 * @note the segment which arrived is saved in global variables, therefore only the pcb
444 * involved is passed as a parameter to this function
447 tcp_listen_input(struct tcp_pcb_listen *pcb)
449 struct tcp_pcb *npcb;
452 if (flags & TCP_RST) {
453 /* An incoming RST should be ignored. Return. */
457 /* In the LISTEN state, we check for incoming SYN segments,
458 creates a new PCB, and responds with a SYN|ACK. */
459 if (flags & TCP_ACK) {
460 /* For incoming segments with the ACK flag set, respond with a
462 LWIP_DEBUGF(TCP_RST_DEBUG, ("tcp_listen_input: ACK in LISTEN, sending reset\n"));
463 tcp_rst(ackno, seqno + tcplen, ipX_current_dest_addr(),
464 ipX_current_src_addr(), tcphdr->dest, tcphdr->src, ip_current_is_v6());
465 } else if (flags & TCP_SYN) {
466 LWIP_DEBUGF(TCP_DEBUG, ("TCP connection request %"U16_F" -> %"U16_F".\n", tcphdr->src, tcphdr->dest));
467 #if TCP_LISTEN_BACKLOG
468 if (pcb->accepts_pending >= pcb->backlog) {
469 LWIP_DEBUGF(TCP_DEBUG, ("tcp_listen_input: listen backlog exceeded for port %"U16_F"\n", tcphdr->dest));
472 #endif /* TCP_LISTEN_BACKLOG */
473 npcb = tcp_alloc(pcb->prio);
474 /* If a new PCB could not be created (probably due to lack of memory),
475 we don't do anything, but rely on the sender will retransmit the
476 SYN at a time when we have more memory available. */
478 LWIP_DEBUGF(TCP_DEBUG, ("tcp_listen_input: could not allocate PCB\n"));
479 TCP_STATS_INC(tcp.memerr);
482 #if TCP_LISTEN_BACKLOG
483 pcb->accepts_pending++;
484 #endif /* TCP_LISTEN_BACKLOG */
485 /* Set up the new PCB. */
487 PCB_ISIPV6(npcb) = ip_current_is_v6();
488 #endif /* LWIP_IPV6 */
489 ipX_addr_copy(ip_current_is_v6(), npcb->local_ip, *ipX_current_dest_addr());
490 ipX_addr_copy(ip_current_is_v6(), npcb->remote_ip, *ipX_current_src_addr());
491 npcb->local_port = pcb->local_port;
492 npcb->remote_port = tcphdr->src;
493 npcb->state = SYN_RCVD;
494 npcb->rcv_nxt = seqno + 1;
495 npcb->rcv_ann_right_edge = npcb->rcv_nxt;
496 npcb->snd_wnd = tcphdr->wnd;
497 npcb->ssthresh = npcb->snd_wnd;
498 npcb->snd_wl1 = seqno - 1;/* initialise to seqno-1 to force window update */
499 npcb->callback_arg = pcb->callback_arg;
500 #if LWIP_CALLBACK_API
501 npcb->accept = pcb->accept;
502 #endif /* LWIP_CALLBACK_API */
503 /* inherit socket options */
504 npcb->so_options = pcb->so_options & SOF_INHERITED;
505 /* Register the new PCB so that we can begin receiving segments
507 TCP_REG(&tcp_active_pcbs, npcb);
509 /* Parse any options in the SYN. */
511 #if TCP_CALCULATE_EFF_SEND_MSS
512 npcb->mss = tcp_eff_send_mss(npcb->mss, &npcb->local_ip,
513 &npcb->remote_ip, PCB_ISIPV6(npcb));
514 #endif /* TCP_CALCULATE_EFF_SEND_MSS */
516 snmp_inc_tcppassiveopens();
518 /* Send a SYN|ACK together with the MSS option. */
519 rc = tcp_enqueue_flags(npcb, TCP_SYN | TCP_ACK);
521 tcp_abandon(npcb, 0);
524 return tcp_output(npcb);
530 * Called by tcp_input() when a segment arrives for a connection in
533 * @param pcb the tcp_pcb for which a segment arrived
535 * @note the segment which arrived is saved in global variables, therefore only the pcb
536 * involved is passed as a parameter to this function
539 tcp_timewait_input(struct tcp_pcb *pcb)
541 /* RFC 1337: in TIME_WAIT, ignore RST and ACK FINs + any 'acceptable' segments */
542 /* RFC 793 3.9 Event Processing - Segment Arrives:
543 * - first check sequence number - we skip that one in TIME_WAIT (always
544 * acceptable since we only send ACKs)
545 * - second check the RST bit (... return) */
546 if (flags & TCP_RST) {
549 /* - fourth, check the SYN bit, */
550 if (flags & TCP_SYN) {
551 /* If an incoming segment is not acceptable, an acknowledgment
552 should be sent in reply */
553 if (TCP_SEQ_BETWEEN(seqno, pcb->rcv_nxt, pcb->rcv_nxt+pcb->rcv_wnd)) {
554 /* If the SYN is in the window it is an error, send a reset */
555 tcp_rst(ackno, seqno + tcplen, ipX_current_dest_addr(),
556 ipX_current_src_addr(), tcphdr->dest, tcphdr->src, ip_current_is_v6());
559 } else if (flags & TCP_FIN) {
560 /* - eighth, check the FIN bit: Remain in the TIME-WAIT state.
561 Restart the 2 MSL time-wait timeout.*/
562 pcb->tmr = tcp_ticks;
566 /* Acknowledge data, FIN or out-of-window SYN */
567 pcb->flags |= TF_ACK_NOW;
568 return tcp_output(pcb);
574 * Implements the TCP state machine. Called by tcp_input. In some
575 * states tcp_receive() is called to receive data. The tcp_seg
576 * argument will be freed by the caller (tcp_input()) unless the
577 * recv_data pointer in the pcb is set.
579 * @param pcb the tcp_pcb for which a segment arrived
581 * @note the segment which arrived is saved in global variables, therefore only the pcb
582 * involved is passed as a parameter to this function
585 tcp_process(struct tcp_pcb *pcb)
587 struct tcp_seg *rseg;
593 /* Process incoming RST segments. */
594 if (flags & TCP_RST) {
595 /* First, determine if the reset is acceptable. */
596 if (pcb->state == SYN_SENT) {
597 if (ackno == pcb->snd_nxt) {
601 if (TCP_SEQ_BETWEEN(seqno, pcb->rcv_nxt,
602 pcb->rcv_nxt+pcb->rcv_wnd)) {
608 LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_process: Connection RESET\n"));
609 LWIP_ASSERT("tcp_input: pcb->state != CLOSED", pcb->state != CLOSED);
610 recv_flags |= TF_RESET;
611 pcb->flags &= ~TF_ACK_DELAY;
614 LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_process: unacceptable reset seqno %"U32_F" rcv_nxt %"U32_F"\n",
615 seqno, pcb->rcv_nxt));
616 LWIP_DEBUGF(TCP_DEBUG, ("tcp_process: unacceptable reset seqno %"U32_F" rcv_nxt %"U32_F"\n",
617 seqno, pcb->rcv_nxt));
622 if ((flags & TCP_SYN) && (pcb->state != SYN_SENT && pcb->state != SYN_RCVD)) {
623 /* Cope with new connection attempt after remote end crashed */
628 if ((pcb->flags & TF_RXCLOSED) == 0) {
629 /* Update the PCB (in)activity timer unless rx is closed (see tcp_shutdown) */
630 pcb->tmr = tcp_ticks;
632 pcb->keep_cnt_sent = 0;
636 /* Do different things depending on the TCP state. */
637 switch (pcb->state) {
639 LWIP_DEBUGF(TCP_INPUT_DEBUG, ("SYN-SENT: ackno %"U32_F" pcb->snd_nxt %"U32_F" unacked %"U32_F"\n", ackno,
640 pcb->snd_nxt, ntohl(pcb->unacked->tcphdr->seqno)));
641 /* received SYN ACK with expected sequence number? */
642 if ((flags & TCP_ACK) && (flags & TCP_SYN)
643 && ackno == ntohl(pcb->unacked->tcphdr->seqno) + 1) {
645 pcb->rcv_nxt = seqno + 1;
646 pcb->rcv_ann_right_edge = pcb->rcv_nxt;
647 pcb->lastack = ackno;
648 pcb->snd_wnd = tcphdr->wnd;
649 pcb->snd_wl1 = seqno - 1; /* initialise to seqno - 1 to force window update */
650 pcb->state = ESTABLISHED;
652 #if TCP_CALCULATE_EFF_SEND_MSS
653 pcb->mss = tcp_eff_send_mss(pcb->mss, &pcb->local_ip, &pcb->remote_ip,
655 #endif /* TCP_CALCULATE_EFF_SEND_MSS */
657 /* Set ssthresh again after changing pcb->mss (already set in tcp_connect
658 * but for the default value of pcb->mss) */
659 pcb->ssthresh = pcb->mss * 10;
661 pcb->cwnd = ((pcb->cwnd == 1) ? (pcb->mss * 2) : pcb->mss);
662 LWIP_ASSERT("pcb->snd_queuelen > 0", (pcb->snd_queuelen > 0));
664 LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_process: SYN-SENT --queuelen %"U16_F"\n", (u16_t)pcb->snd_queuelen));
666 pcb->unacked = rseg->next;
668 /* If there's nothing left to acknowledge, stop the retransmit
669 timer, otherwise reset it to start again */
670 if(pcb->unacked == NULL)
679 /* Call the user specified function to call when sucessfully
681 TCP_EVENT_CONNECTED(pcb, ERR_OK, err);
682 if (err == ERR_ABRT) {
687 /* received ACK? possibly a half-open connection */
688 else if (flags & TCP_ACK) {
689 /* send a RST to bring the other side in a non-synchronized state. */
690 tcp_rst(ackno, seqno + tcplen, ipX_current_dest_addr(),
691 ipX_current_src_addr(), tcphdr->dest, tcphdr->src, ip_current_is_v6());
695 if (flags & TCP_ACK) {
696 /* expected ACK number? */
697 if (TCP_SEQ_BETWEEN(ackno, pcb->lastack+1, pcb->snd_nxt)) {
699 pcb->state = ESTABLISHED;
700 LWIP_DEBUGF(TCP_DEBUG, ("TCP connection established %"U16_F" -> %"U16_F".\n", inseg.tcphdr->src, inseg.tcphdr->dest));
701 #if LWIP_CALLBACK_API
702 LWIP_ASSERT("pcb->accept != NULL", pcb->accept != NULL);
704 /* Call the accept function. */
705 TCP_EVENT_ACCEPT(pcb, ERR_OK, err);
707 /* If the accept function returns with an error, we abort
709 /* Already aborted? */
710 if (err != ERR_ABRT) {
715 old_cwnd = pcb->cwnd;
716 /* If there was any data contained within this ACK,
717 * we'd better pass it on to the application as well. */
720 /* Prevent ACK for SYN to generate a sent event */
721 if (pcb->acked != 0) {
725 pcb->cwnd = ((old_cwnd == 1) ? (pcb->mss * 2) : pcb->mss);
727 if (recv_flags & TF_GOT_FIN) {
729 pcb->state = CLOSE_WAIT;
732 /* incorrect ACK number, send RST */
733 tcp_rst(ackno, seqno + tcplen, ipX_current_dest_addr(),
734 ipX_current_src_addr(), tcphdr->dest, tcphdr->src, ip_current_is_v6());
736 } else if ((flags & TCP_SYN) && (seqno == pcb->rcv_nxt - 1)) {
737 /* Looks like another copy of the SYN - retransmit our SYN-ACK */
745 if (recv_flags & TF_GOT_FIN) { /* passive close */
747 pcb->state = CLOSE_WAIT;
752 if (recv_flags & TF_GOT_FIN) {
753 if ((flags & TCP_ACK) && (ackno == pcb->snd_nxt)) {
754 LWIP_DEBUGF(TCP_DEBUG,
755 ("TCP connection closed: FIN_WAIT_1 %"U16_F" -> %"U16_F".\n", inseg.tcphdr->src, inseg.tcphdr->dest));
758 TCP_RMV(&tcp_active_pcbs, pcb);
759 pcb->state = TIME_WAIT;
760 TCP_REG(&tcp_tw_pcbs, pcb);
763 pcb->state = CLOSING;
765 } else if ((flags & TCP_ACK) && (ackno == pcb->snd_nxt)) {
766 pcb->state = FIN_WAIT_2;
771 if (recv_flags & TF_GOT_FIN) {
772 LWIP_DEBUGF(TCP_DEBUG, ("TCP connection closed: FIN_WAIT_2 %"U16_F" -> %"U16_F".\n", inseg.tcphdr->src, inseg.tcphdr->dest));
775 TCP_RMV(&tcp_active_pcbs, pcb);
776 pcb->state = TIME_WAIT;
777 TCP_REG(&tcp_tw_pcbs, pcb);
782 if (flags & TCP_ACK && ackno == pcb->snd_nxt) {
783 LWIP_DEBUGF(TCP_DEBUG, ("TCP connection closed: CLOSING %"U16_F" -> %"U16_F".\n", inseg.tcphdr->src, inseg.tcphdr->dest));
785 TCP_RMV(&tcp_active_pcbs, pcb);
786 pcb->state = TIME_WAIT;
787 TCP_REG(&tcp_tw_pcbs, pcb);
792 if (flags & TCP_ACK && ackno == pcb->snd_nxt) {
793 LWIP_DEBUGF(TCP_DEBUG, ("TCP connection closed: LAST_ACK %"U16_F" -> %"U16_F".\n", inseg.tcphdr->src, inseg.tcphdr->dest));
794 /* bugfix #21699: don't set pcb->state to CLOSED here or we risk leaking segments */
795 recv_flags |= TF_CLOSED;
806 * Insert segment into the list (segments covered with new one will be deleted)
808 * Called from tcp_receive()
811 tcp_oos_insert_segment(struct tcp_seg *cseg, struct tcp_seg *next)
813 struct tcp_seg *old_seg;
815 if (TCPH_FLAGS(cseg->tcphdr) & TCP_FIN) {
816 /* received segment overlaps all following segments */
821 /* delete some following segments
822 oos queue may have segments with FIN flag */
824 TCP_SEQ_GEQ((seqno + cseg->len),
825 (next->tcphdr->seqno + next->len))) {
826 /* cseg with FIN already processed */
827 if (TCPH_FLAGS(next->tcphdr) & TCP_FIN) {
828 TCPH_SET_FLAG(cseg->tcphdr, TCP_FIN);
832 tcp_seg_free(old_seg);
835 TCP_SEQ_GT(seqno + cseg->len, next->tcphdr->seqno)) {
836 /* We need to trim the incoming segment. */
837 cseg->len = (u16_t)(next->tcphdr->seqno - seqno);
838 pbuf_realloc(cseg->p, cseg->len);
843 #endif /* TCP_QUEUE_OOSEQ */
846 * Called by tcp_process. Checks if the given segment is an ACK for outstanding
847 * data, and if so frees the memory of the buffered data. Next, is places the
848 * segment on any of the receive queues (pcb->recved or pcb->ooseq). If the segment
849 * is buffered, the pbuf is referenced by pbuf_ref so that it will not be freed until
850 * i it has been removed from the buffer.
852 * If the incoming segment constitutes an ACK for a segment that was used for RTT
853 * estimation, the RTT is estimated here as well.
855 * Called from tcp_process().
858 tcp_receive(struct tcp_pcb *pcb)
860 struct tcp_seg *next;
862 struct tcp_seg *prev, *cseg;
863 #endif /* TCP_QUEUE_OOSEQ */
867 u32_t right_wnd_edge;
869 int found_dupack = 0;
871 if (flags & TCP_ACK) {
872 right_wnd_edge = pcb->snd_wnd + pcb->snd_wl2;
875 if (TCP_SEQ_LT(pcb->snd_wl1, seqno) ||
876 (pcb->snd_wl1 == seqno && TCP_SEQ_LT(pcb->snd_wl2, ackno)) ||
877 (pcb->snd_wl2 == ackno && tcphdr->wnd > pcb->snd_wnd)) {
878 pcb->snd_wnd = tcphdr->wnd;
879 pcb->snd_wl1 = seqno;
880 pcb->snd_wl2 = ackno;
881 if (pcb->snd_wnd > 0 && pcb->persist_backoff > 0) {
882 pcb->persist_backoff = 0;
884 LWIP_DEBUGF(TCP_WND_DEBUG, ("tcp_receive: window update %"U16_F"\n", pcb->snd_wnd));
887 if (pcb->snd_wnd != tcphdr->wnd) {
888 LWIP_DEBUGF(TCP_WND_DEBUG,
889 ("tcp_receive: no window update lastack %"U32_F" ackno %"
890 U32_F" wl1 %"U32_F" seqno %"U32_F" wl2 %"U32_F"\n",
891 pcb->lastack, ackno, pcb->snd_wl1, seqno, pcb->snd_wl2));
893 #endif /* TCP_WND_DEBUG */
896 /* (From Stevens TCP/IP Illustrated Vol II, p970.) Its only a
898 * 1) It doesn't ACK new data
899 * 2) length of received packet is zero (i.e. no payload)
900 * 3) the advertised window hasn't changed
901 * 4) There is outstanding unacknowledged data (retransmission timer running)
902 * 5) The ACK is == biggest ACK sequence number so far seen (snd_una)
904 * If it passes all five, should process as a dupack:
905 * a) dupacks < 3: do nothing
906 * b) dupacks == 3: fast retransmit
907 * c) dupacks > 3: increase cwnd
909 * If it only passes 1-3, should reset dupack counter (and add to
910 * stats, which we don't do in lwIP)
912 * If it only passes 1, should reset dupack counter
917 if (TCP_SEQ_LEQ(ackno, pcb->lastack)) {
922 if (pcb->snd_wl2 + pcb->snd_wnd == right_wnd_edge){
924 if (pcb->rtime >= 0) {
926 if (pcb->lastack == ackno) {
928 if (pcb->dupacks + 1 > pcb->dupacks)
930 if (pcb->dupacks > 3) {
931 /* Inflate the congestion window, but not if it means that
932 the value overflows. */
933 if ((u16_t)(pcb->cwnd + pcb->mss) > pcb->cwnd) {
934 pcb->cwnd += pcb->mss;
936 } else if (pcb->dupacks == 3) {
937 /* Do fast retransmit */
938 tcp_rexmit_fast(pcb);
944 /* If Clause (1) or more is true, but not a duplicate ack, reset
945 * count of consecutive duplicate acks */
949 } else if (TCP_SEQ_BETWEEN(ackno, pcb->lastack+1, pcb->snd_nxt)){
950 /* We come here when the ACK acknowledges new data. */
952 /* Reset the "IN Fast Retransmit" flag, since we are no longer
953 in fast retransmit. Also reset the congestion window to the
954 slow start threshold. */
955 if (pcb->flags & TF_INFR) {
956 pcb->flags &= ~TF_INFR;
957 pcb->cwnd = pcb->ssthresh;
960 /* Reset the number of retransmissions. */
963 /* Reset the retransmission time-out. */
964 pcb->rto = (pcb->sa >> 3) + pcb->sv;
966 /* Update the send buffer space. Diff between the two can never exceed 64K? */
967 pcb->acked = (u16_t)(ackno - pcb->lastack);
969 pcb->snd_buf += pcb->acked;
971 /* Reset the fast retransmit variables. */
973 pcb->lastack = ackno;
975 /* Update the congestion control variables (cwnd and
977 if (pcb->state >= ESTABLISHED) {
978 if (pcb->cwnd < pcb->ssthresh) {
979 if ((u16_t)(pcb->cwnd + pcb->mss) > pcb->cwnd) {
980 pcb->cwnd += pcb->mss;
982 LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_receive: slow start cwnd %"U16_F"\n", pcb->cwnd));
984 u16_t new_cwnd = (pcb->cwnd + pcb->mss * pcb->mss / pcb->cwnd);
985 if (new_cwnd > pcb->cwnd) {
986 pcb->cwnd = new_cwnd;
988 LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_receive: congestion avoidance cwnd %"U16_F"\n", pcb->cwnd));
991 LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: ACK for %"U32_F", unacked->seqno %"U32_F":%"U32_F"\n",
993 pcb->unacked != NULL?
994 ntohl(pcb->unacked->tcphdr->seqno): 0,
995 pcb->unacked != NULL?
996 ntohl(pcb->unacked->tcphdr->seqno) + TCP_TCPLEN(pcb->unacked): 0));
998 /* Remove segment from the unacknowledged list if the incoming
999 ACK acknowlegdes them. */
1000 while (pcb->unacked != NULL &&
1001 TCP_SEQ_LEQ(ntohl(pcb->unacked->tcphdr->seqno) +
1002 TCP_TCPLEN(pcb->unacked), ackno)) {
1003 LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: removing %"U32_F":%"U32_F" from pcb->unacked\n",
1004 ntohl(pcb->unacked->tcphdr->seqno),
1005 ntohl(pcb->unacked->tcphdr->seqno) +
1006 TCP_TCPLEN(pcb->unacked)));
1008 next = pcb->unacked;
1009 pcb->unacked = pcb->unacked->next;
1011 LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_receive: queuelen %"U16_F" ... ", (u16_t)pcb->snd_queuelen));
1012 LWIP_ASSERT("pcb->snd_queuelen >= pbuf_clen(next->p)", (pcb->snd_queuelen >= pbuf_clen(next->p)));
1013 /* Prevent ACK for FIN to generate a sent event */
1014 if ((pcb->acked != 0) && ((TCPH_FLAGS(next->tcphdr) & TCP_FIN) != 0)) {
1018 pcb->snd_queuelen -= pbuf_clen(next->p);
1021 LWIP_DEBUGF(TCP_QLEN_DEBUG, ("%"U16_F" (after freeing unacked)\n", (u16_t)pcb->snd_queuelen));
1022 if (pcb->snd_queuelen != 0) {
1023 LWIP_ASSERT("tcp_receive: valid queue length", pcb->unacked != NULL ||
1024 pcb->unsent != NULL);
1028 /* If there's nothing left to acknowledge, stop the retransmit
1029 timer, otherwise reset it to start again */
1030 if(pcb->unacked == NULL)
1037 #if LWIP_IPV6 && LWIP_ND6_TCP_REACHABILITY_HINTS
1038 if (PCB_ISIPV6(pcb)) {
1039 /* Inform neighbor reachability of forward progress. */
1040 nd6_reachability_hint(ip6_current_src_addr());
1042 #endif /* LWIP_IPV6 && LWIP_ND6_TCP_REACHABILITY_HINTS*/
1044 /* Fix bug bug #21582: out of sequence ACK, didn't really ack anything */
1048 /* We go through the ->unsent list to see if any of the segments
1049 on the list are acknowledged by the ACK. This may seem
1050 strange since an "unsent" segment shouldn't be acked. The
1051 rationale is that lwIP puts all outstanding segments on the
1052 ->unsent list after a retransmission, so these segments may
1053 in fact have been sent once. */
1054 while (pcb->unsent != NULL &&
1055 TCP_SEQ_BETWEEN(ackno, ntohl(pcb->unsent->tcphdr->seqno) +
1056 TCP_TCPLEN(pcb->unsent), pcb->snd_nxt)) {
1057 LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: removing %"U32_F":%"U32_F" from pcb->unsent\n",
1058 ntohl(pcb->unsent->tcphdr->seqno), ntohl(pcb->unsent->tcphdr->seqno) +
1059 TCP_TCPLEN(pcb->unsent)));
1062 pcb->unsent = pcb->unsent->next;
1063 LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_receive: queuelen %"U16_F" ... ", (u16_t)pcb->snd_queuelen));
1064 LWIP_ASSERT("pcb->snd_queuelen >= pbuf_clen(next->p)", (pcb->snd_queuelen >= pbuf_clen(next->p)));
1065 /* Prevent ACK for FIN to generate a sent event */
1066 if ((pcb->acked != 0) && ((TCPH_FLAGS(next->tcphdr) & TCP_FIN) != 0)) {
1069 pcb->snd_queuelen -= pbuf_clen(next->p);
1071 LWIP_DEBUGF(TCP_QLEN_DEBUG, ("%"U16_F" (after freeing unsent)\n", (u16_t)pcb->snd_queuelen));
1072 if (pcb->snd_queuelen != 0) {
1073 LWIP_ASSERT("tcp_receive: valid queue length",
1074 pcb->unacked != NULL || pcb->unsent != NULL);
1077 /* End of ACK for new data processing. */
1079 LWIP_DEBUGF(TCP_RTO_DEBUG, ("tcp_receive: pcb->rttest %"U32_F" rtseq %"U32_F" ackno %"U32_F"\n",
1080 pcb->rttest, pcb->rtseq, ackno));
1082 /* RTT estimation calculations. This is done by checking if the
1083 incoming segment acknowledges the segment we use to take a
1084 round-trip time measurement. */
1085 if (pcb->rttest && TCP_SEQ_LT(pcb->rtseq, ackno)) {
1086 /* diff between this shouldn't exceed 32K since this are tcp timer ticks
1087 and a round-trip shouldn't be that long... */
1088 m = (s16_t)(tcp_ticks - pcb->rttest);
1090 LWIP_DEBUGF(TCP_RTO_DEBUG, ("tcp_receive: experienced rtt %"U16_F" ticks (%"U16_F" msec).\n",
1091 m, m * TCP_SLOW_INTERVAL));
1093 /* This is taken directly from VJs original code in his paper */
1094 m = m - (pcb->sa >> 3);
1099 m = m - (pcb->sv >> 2);
1101 pcb->rto = (pcb->sa >> 3) + pcb->sv;
1103 LWIP_DEBUGF(TCP_RTO_DEBUG, ("tcp_receive: RTO %"U16_F" (%"U16_F" milliseconds)\n",
1104 pcb->rto, pcb->rto * TCP_SLOW_INTERVAL));
1110 /* If the incoming segment contains data, we must process it
1113 /* This code basically does three things:
1115 +) If the incoming segment contains data that is the next
1116 in-sequence data, this data is passed to the application. This
1117 might involve trimming the first edge of the data. The rcv_nxt
1118 variable and the advertised window are adjusted.
1120 +) If the incoming segment has data that is above the next
1121 sequence number expected (->rcv_nxt), the segment is placed on
1122 the ->ooseq queue. This is done by finding the appropriate
1123 place in the ->ooseq queue (which is ordered by sequence
1124 number) and trim the segment in both ends if needed. An
1125 immediate ACK is sent to indicate that we received an
1126 out-of-sequence segment.
1128 +) Finally, we check if the first segment on the ->ooseq queue
1129 now is in sequence (i.e., if rcv_nxt >= ooseq->seqno). If
1130 rcv_nxt > ooseq->seqno, we must trim the first edge of the
1131 segment on ->ooseq before we adjust rcv_nxt. The data in the
1132 segments that are now on sequence are chained onto the
1133 incoming segment so that we only need to call the application
1137 /* First, we check if we must trim the first edge. We have to do
1138 this if the sequence number of the incoming segment is less
1139 than rcv_nxt, and the sequence number plus the length of the
1140 segment is larger than rcv_nxt. */
1141 /* if (TCP_SEQ_LT(seqno, pcb->rcv_nxt)){
1142 if (TCP_SEQ_LT(pcb->rcv_nxt, seqno + tcplen)) {*/
1143 if (TCP_SEQ_BETWEEN(pcb->rcv_nxt, seqno + 1, seqno + tcplen - 1)){
1144 /* Trimming the first edge is done by pushing the payload
1145 pointer in the pbuf downwards. This is somewhat tricky since
1146 we do not want to discard the full contents of the pbuf up to
1147 the new starting point of the data since we have to keep the
1148 TCP header which is present in the first pbuf in the chain.
1150 What is done is really quite a nasty hack: the first pbuf in
1151 the pbuf chain is pointed to by inseg.p. Since we need to be
1152 able to deallocate the whole pbuf, we cannot change this
1153 inseg.p pointer to point to any of the later pbufs in the
1154 chain. Instead, we point the ->payload pointer in the first
1155 pbuf to data in one of the later pbufs. We also set the
1156 inseg.data pointer to point to the right place. This way, the
1157 ->p pointer will still point to the first pbuf, but the
1158 ->p->payload pointer will point to data in another pbuf.
1160 After we are done with adjusting the pbuf pointers we must
1161 adjust the ->data pointer in the seg and the segment
1164 off = pcb->rcv_nxt - seqno;
1166 LWIP_ASSERT("inseg.p != NULL", inseg.p);
1167 LWIP_ASSERT("insane offset!", (off < 0x7fff));
1168 if (inseg.p->len < off) {
1169 LWIP_ASSERT("pbuf too short!", (((s32_t)inseg.p->tot_len) >= off));
1170 new_tot_len = (u16_t)(inseg.p->tot_len - off);
1171 while (p->len < off) {
1173 /* KJM following line changed (with addition of new_tot_len var)
1175 inseg.p->tot_len -= p->len; */
1176 p->tot_len = new_tot_len;
1180 if(pbuf_header(p, (s16_t)-off)) {
1181 /* Do we need to cope with this failing? Assert for now */
1182 LWIP_ASSERT("pbuf_header failed", 0);
1185 if(pbuf_header(inseg.p, (s16_t)-off)) {
1186 /* Do we need to cope with this failing? Assert for now */
1187 LWIP_ASSERT("pbuf_header failed", 0);
1190 inseg.len -= (u16_t)(pcb->rcv_nxt - seqno);
1191 inseg.tcphdr->seqno = seqno = pcb->rcv_nxt;
1194 if (TCP_SEQ_LT(seqno, pcb->rcv_nxt)){
1195 /* the whole segment is < rcv_nxt */
1196 /* must be a duplicate of a packet that has already been correctly handled */
1198 LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: duplicate seqno %"U32_F"\n", seqno));
1203 /* The sequence number must be within the window (above rcv_nxt
1204 and below rcv_nxt + rcv_wnd) in order to be further
1206 if (TCP_SEQ_BETWEEN(seqno, pcb->rcv_nxt,
1207 pcb->rcv_nxt + pcb->rcv_wnd - 1)){
1208 if (pcb->rcv_nxt == seqno) {
1209 /* The incoming segment is the next in sequence. We check if
1210 we have to trim the end of the segment and update rcv_nxt
1211 and pass the data to the application. */
1212 tcplen = TCP_TCPLEN(&inseg);
1214 if (tcplen > pcb->rcv_wnd) {
1215 LWIP_DEBUGF(TCP_INPUT_DEBUG,
1216 ("tcp_receive: other end overran receive window"
1217 "seqno %"U32_F" len %"U16_F" right edge %"U32_F"\n",
1218 seqno, tcplen, pcb->rcv_nxt + pcb->rcv_wnd));
1219 if (TCPH_FLAGS(inseg.tcphdr) & TCP_FIN) {
1220 /* Must remove the FIN from the header as we're trimming
1221 * that byte of sequence-space from the packet */
1222 TCPH_FLAGS_SET(inseg.tcphdr, TCPH_FLAGS(inseg.tcphdr) &~ TCP_FIN);
1224 /* Adjust length of segment to fit in the window. */
1225 inseg.len = pcb->rcv_wnd;
1226 if (TCPH_FLAGS(inseg.tcphdr) & TCP_SYN) {
1229 pbuf_realloc(inseg.p, inseg.len);
1230 tcplen = TCP_TCPLEN(&inseg);
1231 LWIP_ASSERT("tcp_receive: segment not trimmed correctly to rcv_wnd\n",
1232 (seqno + tcplen) == (pcb->rcv_nxt + pcb->rcv_wnd));
1235 /* Received in-sequence data, adjust ooseq data if:
1236 - FIN has been received or
1237 - inseq overlaps with ooseq */
1238 if (pcb->ooseq != NULL) {
1239 if (TCPH_FLAGS(inseg.tcphdr) & TCP_FIN) {
1240 LWIP_DEBUGF(TCP_INPUT_DEBUG,
1241 ("tcp_receive: received in-order FIN, binning ooseq queue\n"));
1242 /* Received in-order FIN means anything that was received
1243 * out of order must now have been received in-order, so
1244 * bin the ooseq queue */
1245 while (pcb->ooseq != NULL) {
1246 struct tcp_seg *old_ooseq = pcb->ooseq;
1247 pcb->ooseq = pcb->ooseq->next;
1248 tcp_seg_free(old_ooseq);
1253 /* Remove all segments on ooseq that are covered by inseg already.
1254 * FIN is copied from ooseq to inseg if present. */
1256 TCP_SEQ_GEQ(seqno + tcplen,
1257 next->tcphdr->seqno + next->len)) {
1258 /* inseg cannot have FIN here (already processed above) */
1259 if (TCPH_FLAGS(next->tcphdr) & TCP_FIN &&
1260 (TCPH_FLAGS(inseg.tcphdr) & TCP_SYN) == 0) {
1261 TCPH_SET_FLAG(inseg.tcphdr, TCP_FIN);
1262 tcplen = TCP_TCPLEN(&inseg);
1268 /* Now trim right side of inseg if it overlaps with the first
1269 * segment on ooseq */
1271 TCP_SEQ_GT(seqno + tcplen,
1272 next->tcphdr->seqno)) {
1273 /* inseg cannot have FIN here (already processed above) */
1274 inseg.len = (u16_t)(next->tcphdr->seqno - seqno);
1275 if (TCPH_FLAGS(inseg.tcphdr) & TCP_SYN) {
1278 pbuf_realloc(inseg.p, inseg.len);
1279 tcplen = TCP_TCPLEN(&inseg);
1280 LWIP_ASSERT("tcp_receive: segment not trimmed correctly to ooseq queue\n",
1281 (seqno + tcplen) == next->tcphdr->seqno);
1286 #endif /* TCP_QUEUE_OOSEQ */
1288 pcb->rcv_nxt = seqno + tcplen;
1290 /* Update the receiver's (our) window. */
1291 LWIP_ASSERT("tcp_receive: tcplen > rcv_wnd\n", pcb->rcv_wnd >= tcplen);
1292 pcb->rcv_wnd -= tcplen;
1294 tcp_update_rcv_ann_wnd(pcb);
1296 /* If there is data in the segment, we make preparations to
1297 pass this up to the application. The ->recv_data variable
1298 is used for holding the pbuf that goes to the
1299 application. The code for reassembling out-of-sequence data
1300 chains its data on this pbuf as well.
1302 If the segment was a FIN, we set the TF_GOT_FIN flag that will
1303 be used to indicate to the application that the remote side has
1304 closed its end of the connection. */
1305 if (inseg.p->tot_len > 0) {
1306 recv_data = inseg.p;
1307 /* Since this pbuf now is the responsibility of the
1308 application, we delete our reference to it so that we won't
1309 (mistakingly) deallocate it. */
1312 if (TCPH_FLAGS(inseg.tcphdr) & TCP_FIN) {
1313 LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: received FIN.\n"));
1314 recv_flags |= TF_GOT_FIN;
1318 /* We now check if we have segments on the ->ooseq queue that
1319 are now in sequence. */
1320 while (pcb->ooseq != NULL &&
1321 pcb->ooseq->tcphdr->seqno == pcb->rcv_nxt) {
1324 seqno = pcb->ooseq->tcphdr->seqno;
1326 pcb->rcv_nxt += TCP_TCPLEN(cseg);
1327 LWIP_ASSERT("tcp_receive: ooseq tcplen > rcv_wnd\n",
1328 pcb->rcv_wnd >= TCP_TCPLEN(cseg));
1329 pcb->rcv_wnd -= TCP_TCPLEN(cseg);
1331 tcp_update_rcv_ann_wnd(pcb);
1333 if (cseg->p->tot_len > 0) {
1334 /* Chain this pbuf onto the pbuf that we will pass to
1337 pbuf_cat(recv_data, cseg->p);
1339 recv_data = cseg->p;
1343 if (TCPH_FLAGS(cseg->tcphdr) & TCP_FIN) {
1344 LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: dequeued FIN.\n"));
1345 recv_flags |= TF_GOT_FIN;
1346 if (pcb->state == ESTABLISHED) { /* force passive close or we can move to active close */
1347 pcb->state = CLOSE_WAIT;
1351 pcb->ooseq = cseg->next;
1354 #endif /* TCP_QUEUE_OOSEQ */
1357 /* Acknowledge the segment(s). */
1360 #if LWIP_IPV6 && LWIP_ND6_TCP_REACHABILITY_HINTS
1361 if (PCB_ISIPV6(pcb)) {
1362 /* Inform neighbor reachability of forward progress. */
1363 nd6_reachability_hint(ip6_current_src_addr());
1365 #endif /* LWIP_IPV6 && LWIP_ND6_TCP_REACHABILITY_HINTS*/
1368 /* We get here if the incoming segment is out-of-sequence. */
1369 tcp_send_empty_ack(pcb);
1371 /* We queue the segment on the ->ooseq queue. */
1372 if (pcb->ooseq == NULL) {
1373 pcb->ooseq = tcp_seg_copy(&inseg);
1375 /* If the queue is not empty, we walk through the queue and
1376 try to find a place where the sequence number of the
1377 incoming segment is between the sequence numbers of the
1378 previous and the next segment on the ->ooseq queue. That is
1379 the place where we put the incoming segment. If needed, we
1380 trim the second edges of the previous and the incoming
1381 segment so that it will fit into the sequence.
1383 If the incoming segment has the same sequence number as a
1384 segment on the ->ooseq queue, we discard the segment that
1385 contains less data. */
1388 for(next = pcb->ooseq; next != NULL; next = next->next) {
1389 if (seqno == next->tcphdr->seqno) {
1390 /* The sequence number of the incoming segment is the
1391 same as the sequence number of the segment on
1392 ->ooseq. We check the lengths to see which one to
1394 if (inseg.len > next->len) {
1395 /* The incoming segment is larger than the old
1396 segment. We replace some segments with the new
1398 cseg = tcp_seg_copy(&inseg);
1405 tcp_oos_insert_segment(cseg, next);
1409 /* Either the lenghts are the same or the incoming
1410 segment was smaller than the old one; in either
1411 case, we ditch the incoming segment. */
1416 if (TCP_SEQ_LT(seqno, next->tcphdr->seqno)) {
1417 /* The sequence number of the incoming segment is lower
1418 than the sequence number of the first segment on the
1419 queue. We put the incoming segment first on the
1421 cseg = tcp_seg_copy(&inseg);
1424 tcp_oos_insert_segment(cseg, next);
1429 /*if (TCP_SEQ_LT(prev->tcphdr->seqno, seqno) &&
1430 TCP_SEQ_LT(seqno, next->tcphdr->seqno)) {*/
1431 if (TCP_SEQ_BETWEEN(seqno, prev->tcphdr->seqno+1, next->tcphdr->seqno-1)) {
1432 /* The sequence number of the incoming segment is in
1433 between the sequence numbers of the previous and
1434 the next segment on ->ooseq. We trim trim the previous
1435 segment, delete next segments that included in received segment
1436 and trim received, if needed. */
1437 cseg = tcp_seg_copy(&inseg);
1439 if (TCP_SEQ_GT(prev->tcphdr->seqno + prev->len, seqno)) {
1440 /* We need to trim the prev segment. */
1441 prev->len = (u16_t)(seqno - prev->tcphdr->seqno);
1442 pbuf_realloc(prev->p, prev->len);
1445 tcp_oos_insert_segment(cseg, next);
1450 /* If the "next" segment is the last segment on the
1451 ooseq queue, we add the incoming segment to the end
1453 if (next->next == NULL &&
1454 TCP_SEQ_GT(seqno, next->tcphdr->seqno)) {
1455 if (TCPH_FLAGS(next->tcphdr) & TCP_FIN) {
1456 /* segment "next" already contains all data */
1459 next->next = tcp_seg_copy(&inseg);
1460 if (next->next != NULL) {
1461 if (TCP_SEQ_GT(next->tcphdr->seqno + next->len, seqno)) {
1462 /* We need to trim the last segment. */
1463 next->len = (u16_t)(seqno - next->tcphdr->seqno);
1464 pbuf_realloc(next->p, next->len);
1466 /* check if the remote side overruns our receive window */
1467 if ((u32_t)tcplen + seqno > pcb->rcv_nxt + (u32_t)pcb->rcv_wnd) {
1468 LWIP_DEBUGF(TCP_INPUT_DEBUG,
1469 ("tcp_receive: other end overran receive window"
1470 "seqno %"U32_F" len %"U16_F" right edge %"U32_F"\n",
1471 seqno, tcplen, pcb->rcv_nxt + pcb->rcv_wnd));
1472 if (TCPH_FLAGS(next->next->tcphdr) & TCP_FIN) {
1473 /* Must remove the FIN from the header as we're trimming
1474 * that byte of sequence-space from the packet */
1475 TCPH_FLAGS_SET(next->next->tcphdr, TCPH_FLAGS(next->next->tcphdr) &~ TCP_FIN);
1477 /* Adjust length of segment to fit in the window. */
1478 next->next->len = pcb->rcv_nxt + pcb->rcv_wnd - seqno;
1479 pbuf_realloc(next->next->p, next->next->len);
1480 tcplen = TCP_TCPLEN(next->next);
1481 LWIP_ASSERT("tcp_receive: segment not trimmed correctly to rcv_wnd\n",
1482 (seqno + tcplen) == (pcb->rcv_nxt + pcb->rcv_wnd));
1491 #endif /* TCP_QUEUE_OOSEQ */
1495 /* The incoming segment is not withing the window. */
1496 tcp_send_empty_ack(pcb);
1499 /* Segments with length 0 is taken care of here. Segments that
1500 fall out of the window are ACKed. */
1501 /*if (TCP_SEQ_GT(pcb->rcv_nxt, seqno) ||
1502 TCP_SEQ_GEQ(seqno, pcb->rcv_nxt + pcb->rcv_wnd)) {*/
1503 if(!TCP_SEQ_BETWEEN(seqno, pcb->rcv_nxt, pcb->rcv_nxt + pcb->rcv_wnd-1)){
1510 * Parses the options contained in the incoming segment.
1512 * Called from tcp_listen_input() and tcp_process().
1513 * Currently, only the MSS option is supported!
1515 * @param pcb the tcp_pcb for which a segment arrived
1518 tcp_parseopt(struct tcp_pcb *pcb)
1523 #if LWIP_TCP_TIMESTAMPS
1527 opts = (u8_t *)tcphdr + TCP_HLEN;
1529 /* Parse the TCP MSS option, if present. */
1530 if(TCPH_HDRLEN(tcphdr) > 0x5) {
1531 max_c = (TCPH_HDRLEN(tcphdr) - 5) << 2;
1532 for (c = 0; c < max_c; ) {
1536 /* End of options. */
1537 LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: EOL\n"));
1542 LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: NOP\n"));
1545 LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: MSS\n"));
1546 if (opts[c + 1] != 0x04 || c + 0x04 > max_c) {
1548 LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: bad length\n"));
1551 /* An MSS option with the right option length. */
1552 mss = (opts[c + 2] << 8) | opts[c + 3];
1553 /* Limit the mss to the configured TCP_MSS and prevent division by zero */
1554 pcb->mss = ((mss > TCP_MSS) || (mss == 0)) ? TCP_MSS : mss;
1555 /* Advance to next option */
1558 #if LWIP_TCP_TIMESTAMPS
1560 LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: TS\n"));
1561 if (opts[c + 1] != 0x0A || c + 0x0A > max_c) {
1563 LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: bad length\n"));
1566 /* TCP timestamp option with valid length */
1567 tsval = (opts[c+2]) | (opts[c+3] << 8) |
1568 (opts[c+4] << 16) | (opts[c+5] << 24);
1569 if (flags & TCP_SYN) {
1570 pcb->ts_recent = ntohl(tsval);
1571 pcb->flags |= TF_TIMESTAMP;
1572 } else if (TCP_SEQ_BETWEEN(pcb->ts_lastacksent, seqno, seqno+tcplen)) {
1573 pcb->ts_recent = ntohl(tsval);
1575 /* Advance to next option */
1580 LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: other\n"));
1581 if (opts[c + 1] == 0) {
1582 LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: bad length\n"));
1583 /* If the length field is zero, the options are malformed
1584 and we don't process them further. */
1587 /* All other options have a length field, so that we easily
1588 can skip past them. */
1595 #endif /* LWIP_TCP */