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/priv/tcp_priv.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"
57 #include "lwip/ip6_addr.h"
58 #if LWIP_ND6_TCP_REACHABILITY_HINTS
60 #endif /* LWIP_ND6_TCP_REACHABILITY_HINTS */
62 /** Initial CWND calculation as defined RFC 2581 */
63 #define LWIP_TCP_CALC_INITIAL_CWND(mss) LWIP_MIN((4U * (mss)), LWIP_MAX((2U * (mss)), 4380U));
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 u16_t tcphdr_optlen
;
71 static u16_t tcphdr_opt1len
;
72 static u8_t
* tcphdr_opt2
;
73 static u16_t tcp_optidx
;
74 static u32_t seqno
, ackno
;
75 static tcpwnd_size_t recv_acked
;
79 static u8_t recv_flags
;
80 static struct pbuf
*recv_data
;
82 struct tcp_pcb
*tcp_input_pcb
;
84 /* Forward declarations. */
85 static err_t
tcp_process(struct tcp_pcb
*pcb
);
86 static void tcp_receive(struct tcp_pcb
*pcb
);
87 static void tcp_parseopt(struct tcp_pcb
*pcb
);
89 static void tcp_listen_input(struct tcp_pcb_listen
*pcb
);
90 static void tcp_timewait_input(struct tcp_pcb
*pcb
);
93 * The initial input processing of TCP. It verifies the TCP header, demultiplexes
94 * the segment between the PCBs and passes it on to tcp_process(), which implements
95 * the TCP finite state machine. This function is called by the IP layer (in
98 * @param p received TCP segment to process (p->payload pointing to the TCP header)
99 * @param inp network interface on which this segment was received
102 tcp_input(struct pbuf
*p
, struct netif
*inp
)
104 struct tcp_pcb
*pcb
, *prev
;
105 struct tcp_pcb_listen
*lpcb
;
107 struct tcp_pcb
*lpcb_prev
= NULL
;
108 struct tcp_pcb_listen
*lpcb_any
= NULL
;
109 #endif /* SO_REUSE */
113 LWIP_UNUSED_ARG(inp
);
117 TCP_STATS_INC(tcp
.recv
);
118 MIB2_STATS_INC(mib2
.tcpinsegs
);
120 tcphdr
= (struct tcp_hdr
*)p
->payload
;
123 tcp_debug_print(tcphdr
);
126 /* Check that TCP header fits in payload */
127 if (p
->len
< TCP_HLEN
) {
128 /* drop short packets */
129 LWIP_DEBUGF(TCP_INPUT_DEBUG
, ("tcp_input: short packet (%"U16_F
" bytes) discarded\n", p
->tot_len
));
130 TCP_STATS_INC(tcp
.lenerr
);
134 /* Don't even process incoming broadcasts/multicasts. */
135 if (ip_addr_isbroadcast(ip_current_dest_addr(), ip_current_netif()) ||
136 ip_addr_ismulticast(ip_current_dest_addr())) {
137 TCP_STATS_INC(tcp
.proterr
);
141 #if CHECKSUM_CHECK_TCP
142 IF__NETIF_CHECKSUM_ENABLED(inp
, NETIF_CHECKSUM_CHECK_TCP
) {
143 /* Verify TCP checksum. */
144 u16_t chksum
= ip_chksum_pseudo(p
, IP_PROTO_TCP
, p
->tot_len
,
145 ip_current_src_addr(), ip_current_dest_addr());
147 LWIP_DEBUGF(TCP_INPUT_DEBUG
, ("tcp_input: packet discarded due to failing checksum 0x%04"X16_F
"\n",
149 tcp_debug_print(tcphdr
);
150 TCP_STATS_INC(tcp
.chkerr
);
154 #endif /* CHECKSUM_CHECK_TCP */
156 /* sanity-check header length */
157 hdrlen_bytes
= TCPH_HDRLEN(tcphdr
) * 4;
158 if ((hdrlen_bytes
< TCP_HLEN
) || (hdrlen_bytes
> p
->tot_len
)) {
159 LWIP_DEBUGF(TCP_INPUT_DEBUG
, ("tcp_input: invalid header length (%"U16_F
")\n", (u16_t
)hdrlen_bytes
));
160 TCP_STATS_INC(tcp
.lenerr
);
164 /* Move the payload pointer in the pbuf so that it points to the
165 TCP data instead of the TCP header. */
166 tcphdr_optlen
= hdrlen_bytes
- TCP_HLEN
;
168 if (p
->len
>= hdrlen_bytes
) {
169 /* all options are in the first pbuf */
170 tcphdr_opt1len
= tcphdr_optlen
;
171 pbuf_header(p
, -(s16_t
)hdrlen_bytes
); /* cannot fail */
174 /* TCP header fits into first pbuf, options don't - data is in the next pbuf */
175 /* there must be a next pbuf, due to hdrlen_bytes sanity check above */
176 LWIP_ASSERT("p->next != NULL", p
->next
!= NULL
);
178 /* advance over the TCP header (cannot fail) */
179 pbuf_header(p
, -TCP_HLEN
);
181 /* determine how long the first and second parts of the options are */
182 tcphdr_opt1len
= p
->len
;
183 opt2len
= tcphdr_optlen
- tcphdr_opt1len
;
185 /* options continue in the next pbuf: set p to zero length and hide the
186 options in the next pbuf (adjusting p->tot_len) */
187 pbuf_header(p
, -(s16_t
)tcphdr_opt1len
);
189 /* check that the options fit in the second pbuf */
190 if (opt2len
> p
->next
->len
) {
191 /* drop short packets */
192 LWIP_DEBUGF(TCP_INPUT_DEBUG
, ("tcp_input: options overflow second pbuf (%"U16_F
" bytes)\n", p
->next
->len
));
193 TCP_STATS_INC(tcp
.lenerr
);
197 /* remember the pointer to the second part of the options */
198 tcphdr_opt2
= (u8_t
*)p
->next
->payload
;
200 /* advance p->next to point after the options, and manually
201 adjust p->tot_len to keep it consistent with the changed p->next */
202 pbuf_header(p
->next
, -(s16_t
)opt2len
);
203 p
->tot_len
-= opt2len
;
205 LWIP_ASSERT("p->len == 0", p
->len
== 0);
206 LWIP_ASSERT("p->tot_len == p->next->tot_len", p
->tot_len
== p
->next
->tot_len
);
209 /* Convert fields in TCP header to host byte order. */
210 tcphdr
->src
= lwip_ntohs(tcphdr
->src
);
211 tcphdr
->dest
= lwip_ntohs(tcphdr
->dest
);
212 seqno
= tcphdr
->seqno
= lwip_ntohl(tcphdr
->seqno
);
213 ackno
= tcphdr
->ackno
= lwip_ntohl(tcphdr
->ackno
);
214 tcphdr
->wnd
= lwip_ntohs(tcphdr
->wnd
);
216 flags
= TCPH_FLAGS(tcphdr
);
217 tcplen
= p
->tot_len
+ ((flags
& (TCP_FIN
| TCP_SYN
)) ? 1 : 0);
219 /* Demultiplex an incoming segment. First, we check if it is destined
220 for an active connection. */
223 for (pcb
= tcp_active_pcbs
; pcb
!= NULL
; pcb
= pcb
->next
) {
224 LWIP_ASSERT("tcp_input: active pcb->state != CLOSED", pcb
->state
!= CLOSED
);
225 LWIP_ASSERT("tcp_input: active pcb->state != TIME-WAIT", pcb
->state
!= TIME_WAIT
);
226 LWIP_ASSERT("tcp_input: active pcb->state != LISTEN", pcb
->state
!= LISTEN
);
227 if (pcb
->remote_port
== tcphdr
->src
&&
228 pcb
->local_port
== tcphdr
->dest
&&
229 ip_addr_cmp(&pcb
->remote_ip
, ip_current_src_addr()) &&
230 ip_addr_cmp(&pcb
->local_ip
, ip_current_dest_addr())) {
231 /* Move this PCB to the front of the list so that subsequent
232 lookups will be faster (we exploit locality in TCP segment
234 LWIP_ASSERT("tcp_input: pcb->next != pcb (before cache)", pcb
->next
!= pcb
);
236 prev
->next
= pcb
->next
;
237 pcb
->next
= tcp_active_pcbs
;
238 tcp_active_pcbs
= pcb
;
240 TCP_STATS_INC(tcp
.cachehit
);
242 LWIP_ASSERT("tcp_input: pcb->next != pcb (after cache)", pcb
->next
!= pcb
);
249 /* If it did not go to an active connection, we check the connections
250 in the TIME-WAIT state. */
251 for (pcb
= tcp_tw_pcbs
; pcb
!= NULL
; pcb
= pcb
->next
) {
252 LWIP_ASSERT("tcp_input: TIME-WAIT pcb->state == TIME-WAIT", pcb
->state
== TIME_WAIT
);
253 if (pcb
->remote_port
== tcphdr
->src
&&
254 pcb
->local_port
== tcphdr
->dest
&&
255 ip_addr_cmp(&pcb
->remote_ip
, ip_current_src_addr()) &&
256 ip_addr_cmp(&pcb
->local_ip
, ip_current_dest_addr())) {
257 /* We don't really care enough to move this PCB to the front
258 of the list since we are not very likely to receive that
259 many segments for connections in TIME-WAIT. */
260 LWIP_DEBUGF(TCP_INPUT_DEBUG
, ("tcp_input: packed for TIME_WAITing connection.\n"));
261 tcp_timewait_input(pcb
);
267 /* Finally, if we still did not get a match, we check all PCBs that
268 are LISTENing for incoming connections. */
270 for (lpcb
= tcp_listen_pcbs
.listen_pcbs
; lpcb
!= NULL
; lpcb
= lpcb
->next
) {
271 if (lpcb
->local_port
== tcphdr
->dest
) {
272 if (IP_IS_ANY_TYPE_VAL(lpcb
->local_ip
)) {
273 /* found an ANY TYPE (IPv4/IPv6) match */
279 #endif /* SO_REUSE */
280 } else if (IP_ADDR_PCB_VERSION_MATCH_EXACT(lpcb
, ip_current_dest_addr())) {
281 if (ip_addr_cmp(&lpcb
->local_ip
, ip_current_dest_addr())) {
282 /* found an exact match */
284 } else if (ip_addr_isany(&lpcb
->local_ip
)) {
285 /* found an ANY-match */
291 #endif /* SO_REUSE */
295 prev
= (struct tcp_pcb
*)lpcb
;
298 /* first try specific local IP */
300 /* only pass to ANY if no specific local IP has been found */
304 #endif /* SO_REUSE */
306 /* Move this PCB to the front of the list so that subsequent
307 lookups will be faster (we exploit locality in TCP segment
310 ((struct tcp_pcb_listen
*)prev
)->next
= lpcb
->next
;
311 /* our successor is the remainder of the listening list */
312 lpcb
->next
= tcp_listen_pcbs
.listen_pcbs
;
313 /* put this listening pcb at the head of the listening list */
314 tcp_listen_pcbs
.listen_pcbs
= lpcb
;
316 TCP_STATS_INC(tcp
.cachehit
);
319 LWIP_DEBUGF(TCP_INPUT_DEBUG
, ("tcp_input: packed for LISTENing connection.\n"));
320 tcp_listen_input(lpcb
);
327 LWIP_DEBUGF(TCP_INPUT_DEBUG
, ("+-+-+-+-+-+-+-+-+-+-+-+-+-+- tcp_input: flags "));
328 tcp_debug_print_flags(TCPH_FLAGS(tcphdr
));
329 LWIP_DEBUGF(TCP_INPUT_DEBUG
, ("-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n"));
330 #endif /* TCP_INPUT_DEBUG */
334 /* The incoming segment belongs to a connection. */
336 tcp_debug_print_state(pcb
->state
);
337 #endif /* TCP_INPUT_DEBUG */
339 /* Set up a tcp_seg structure. */
341 inseg
.len
= p
->tot_len
;
343 inseg
.tcphdr
= tcphdr
;
349 if (flags
& TCP_PSH
) {
350 p
->flags
|= PBUF_FLAG_PUSH
;
353 /* If there is data which was previously "refused" by upper layer */
354 if (pcb
->refused_data
!= NULL
) {
355 if ((tcp_process_refused_data(pcb
) == ERR_ABRT
) ||
356 ((pcb
->refused_data
!= NULL
) && (tcplen
> 0))) {
357 /* pcb has been aborted or refused data is still refused and the new
358 segment contains data */
359 if (pcb
->rcv_ann_wnd
== 0) {
360 /* this is a zero-window probe, we respond to it with current RCV.NXT
361 and drop the data segment */
362 tcp_send_empty_ack(pcb
);
364 TCP_STATS_INC(tcp
.drop
);
365 MIB2_STATS_INC(mib2
.tcpinerrs
);
370 err
= tcp_process(pcb
);
371 /* A return value of ERR_ABRT means that tcp_abort() was called
372 and that the pcb has been freed. If so, we don't do anything. */
373 if (err
!= ERR_ABRT
) {
374 if (recv_flags
& TF_RESET
) {
375 /* TF_RESET means that the connection was reset by the other
376 end. We then call the error callback to inform the
377 application that the connection is dead before we
378 deallocate the PCB. */
379 TCP_EVENT_ERR(pcb
->state
, pcb
->errf
, pcb
->callback_arg
, ERR_RST
);
380 tcp_pcb_remove(&tcp_active_pcbs
, pcb
);
381 memp_free(MEMP_TCP_PCB
, pcb
);
384 /* If the application has registered a "sent" function to be
385 called when new send buffer space is available, we call it
387 if (recv_acked
> 0) {
390 /* recv_acked is u32_t but the sent callback only takes a u16_t,
391 so we might have to call it multiple times. */
392 u32_t acked
= recv_acked
;
394 acked16
= (u16_t
)LWIP_MIN(acked
, 0xffffu
);
398 acked16
= recv_acked
;
400 TCP_EVENT_SENT(pcb
, (u16_t
)acked16
, err
);
401 if (err
== ERR_ABRT
) {
407 if (recv_flags
& TF_CLOSED
) {
408 /* The connection has been closed and we will deallocate the
410 if (!(pcb
->flags
& TF_RXCLOSED
)) {
411 /* Connection closed although the application has only shut down the
412 tx side: call the PCB's err callback and indicate the closure to
413 ensure the application doesn't continue using the PCB. */
414 TCP_EVENT_ERR(pcb
->state
, pcb
->errf
, pcb
->callback_arg
, ERR_CLSD
);
416 tcp_pcb_remove(&tcp_active_pcbs
, pcb
);
417 memp_free(MEMP_TCP_PCB
, pcb
);
420 #if TCP_QUEUE_OOSEQ && LWIP_WND_SCALE
421 while (recv_data
!= NULL
) {
422 struct pbuf
*rest
= NULL
;
423 pbuf_split_64k(recv_data
, &rest
);
424 #else /* TCP_QUEUE_OOSEQ && LWIP_WND_SCALE */
425 if (recv_data
!= NULL
) {
426 #endif /* TCP_QUEUE_OOSEQ && LWIP_WND_SCALE */
428 LWIP_ASSERT("pcb->refused_data == NULL", pcb
->refused_data
== NULL
);
429 if (pcb
->flags
& TF_RXCLOSED
) {
430 /* received data although already closed -> abort (send RST) to
431 notify the remote host that not all data has been processed */
432 pbuf_free(recv_data
);
433 #if TCP_QUEUE_OOSEQ && LWIP_WND_SCALE
437 #endif /* TCP_QUEUE_OOSEQ && LWIP_WND_SCALE */
442 /* Notify application that data has been received. */
443 TCP_EVENT_RECV(pcb
, recv_data
, ERR_OK
, err
);
444 if (err
== ERR_ABRT
) {
445 #if TCP_QUEUE_OOSEQ && LWIP_WND_SCALE
449 #endif /* TCP_QUEUE_OOSEQ && LWIP_WND_SCALE */
453 /* If the upper layer can't receive this data, store it */
455 #if TCP_QUEUE_OOSEQ && LWIP_WND_SCALE
457 pbuf_cat(recv_data
, rest
);
459 #endif /* TCP_QUEUE_OOSEQ && LWIP_WND_SCALE */
460 pcb
->refused_data
= recv_data
;
461 LWIP_DEBUGF(TCP_INPUT_DEBUG
, ("tcp_input: keep incoming packet, because pcb is \"full\"\n"));
462 #if TCP_QUEUE_OOSEQ && LWIP_WND_SCALE
465 /* Upper layer received the data, go on with the rest if > 64K */
467 #endif /* TCP_QUEUE_OOSEQ && LWIP_WND_SCALE */
471 /* If a FIN segment was received, we call the callback
472 function with a NULL buffer to indicate EOF. */
473 if (recv_flags
& TF_GOT_FIN
) {
474 if (pcb
->refused_data
!= NULL
) {
475 /* Delay this if we have refused data. */
476 pcb
->refused_data
->flags
|= PBUF_FLAG_TCP_FIN
;
478 /* correct rcv_wnd as the application won't call tcp_recved()
479 for the FIN's seqno */
480 if (pcb
->rcv_wnd
!= TCP_WND_MAX(pcb
)) {
483 TCP_EVENT_CLOSED(pcb
, err
);
484 if (err
== ERR_ABRT
) {
490 tcp_input_pcb
= NULL
;
491 /* Try to send something out. */
495 tcp_debug_print_state(pcb
->state
);
496 #endif /* TCP_DEBUG */
497 #endif /* TCP_INPUT_DEBUG */
500 /* Jump target if pcb has been aborted in a callback (by calling tcp_abort()).
501 Below this line, 'pcb' may not be dereferenced! */
503 tcp_input_pcb
= NULL
;
506 /* give up our reference to inseg.p */
514 /* If no matching PCB was found, send a TCP RST (reset) to the
516 LWIP_DEBUGF(TCP_RST_DEBUG
, ("tcp_input: no PCB match found, resetting.\n"));
517 if (!(TCPH_FLAGS(tcphdr
) & TCP_RST
)) {
518 TCP_STATS_INC(tcp
.proterr
);
519 TCP_STATS_INC(tcp
.drop
);
520 tcp_rst(ackno
, seqno
+ tcplen
, ip_current_dest_addr(),
521 ip_current_src_addr(), tcphdr
->dest
, tcphdr
->src
);
526 LWIP_ASSERT("tcp_input: tcp_pcbs_sane()", tcp_pcbs_sane());
527 PERF_STOP("tcp_input");
530 TCP_STATS_INC(tcp
.drop
);
531 MIB2_STATS_INC(mib2
.tcpinerrs
);
536 * Called by tcp_input() when a segment arrives for a listening
537 * connection (from tcp_input()).
539 * @param pcb the tcp_pcb_listen for which a segment arrived
541 * @note the segment which arrived is saved in global variables, therefore only the pcb
542 * involved is passed as a parameter to this function
545 tcp_listen_input(struct tcp_pcb_listen
*pcb
)
547 struct tcp_pcb
*npcb
;
551 if (flags
& TCP_RST
) {
552 /* An incoming RST should be ignored. Return. */
556 /* In the LISTEN state, we check for incoming SYN segments,
557 creates a new PCB, and responds with a SYN|ACK. */
558 if (flags
& TCP_ACK
) {
559 /* For incoming segments with the ACK flag set, respond with a
561 LWIP_DEBUGF(TCP_RST_DEBUG
, ("tcp_listen_input: ACK in LISTEN, sending reset\n"));
562 tcp_rst(ackno
, seqno
+ tcplen
, ip_current_dest_addr(),
563 ip_current_src_addr(), tcphdr
->dest
, tcphdr
->src
);
564 } else if (flags
& TCP_SYN
) {
565 LWIP_DEBUGF(TCP_DEBUG
, ("TCP connection request %"U16_F
" -> %"U16_F
".\n", tcphdr
->src
, tcphdr
->dest
));
566 #if TCP_LISTEN_BACKLOG
567 if (pcb
->accepts_pending
>= pcb
->backlog
) {
568 LWIP_DEBUGF(TCP_DEBUG
, ("tcp_listen_input: listen backlog exceeded for port %"U16_F
"\n", tcphdr
->dest
));
571 #endif /* TCP_LISTEN_BACKLOG */
572 npcb
= tcp_alloc(pcb
->prio
);
573 /* If a new PCB could not be created (probably due to lack of memory),
574 we don't do anything, but rely on the sender will retransmit the
575 SYN at a time when we have more memory available. */
578 LWIP_DEBUGF(TCP_DEBUG
, ("tcp_listen_input: could not allocate PCB\n"));
579 TCP_STATS_INC(tcp
.memerr
);
580 TCP_EVENT_ACCEPT(pcb
, NULL
, pcb
->callback_arg
, ERR_MEM
, err
);
581 LWIP_UNUSED_ARG(err
); /* err not useful here */
584 #if TCP_LISTEN_BACKLOG
585 pcb
->accepts_pending
++;
586 npcb
->flags
|= TF_BACKLOGPEND
;
587 #endif /* TCP_LISTEN_BACKLOG */
588 /* Set up the new PCB. */
589 ip_addr_copy(npcb
->local_ip
, *ip_current_dest_addr());
590 ip_addr_copy(npcb
->remote_ip
, *ip_current_src_addr());
591 npcb
->local_port
= pcb
->local_port
;
592 npcb
->remote_port
= tcphdr
->src
;
593 npcb
->state
= SYN_RCVD
;
594 npcb
->rcv_nxt
= seqno
+ 1;
595 npcb
->rcv_ann_right_edge
= npcb
->rcv_nxt
;
596 iss
= tcp_next_iss(npcb
);
601 npcb
->snd_wl1
= seqno
- 1;/* initialise to seqno-1 to force window update */
602 npcb
->callback_arg
= pcb
->callback_arg
;
603 #if LWIP_CALLBACK_API || TCP_LISTEN_BACKLOG
604 npcb
->listener
= pcb
;
605 #endif /* LWIP_CALLBACK_API || TCP_LISTEN_BACKLOG */
606 /* inherit socket options */
607 npcb
->so_options
= pcb
->so_options
& SOF_INHERITED
;
608 /* Register the new PCB so that we can begin receiving segments
610 TCP_REG_ACTIVE(npcb
);
612 /* Parse any options in the SYN. */
614 npcb
->snd_wnd
= tcphdr
->wnd
;
615 npcb
->snd_wnd_max
= npcb
->snd_wnd
;
617 #if TCP_CALCULATE_EFF_SEND_MSS
618 npcb
->mss
= tcp_eff_send_mss(npcb
->mss
, &npcb
->local_ip
, &npcb
->remote_ip
);
619 #endif /* TCP_CALCULATE_EFF_SEND_MSS */
621 MIB2_STATS_INC(mib2
.tcppassiveopens
);
623 /* Send a SYN|ACK together with the MSS option. */
624 rc
= tcp_enqueue_flags(npcb
, TCP_SYN
| TCP_ACK
);
626 tcp_abandon(npcb
, 0);
635 * Called by tcp_input() when a segment arrives for a connection in
638 * @param pcb the tcp_pcb for which a segment arrived
640 * @note the segment which arrived is saved in global variables, therefore only the pcb
641 * involved is passed as a parameter to this function
644 tcp_timewait_input(struct tcp_pcb
*pcb
)
646 /* RFC 1337: in TIME_WAIT, ignore RST and ACK FINs + any 'acceptable' segments */
647 /* RFC 793 3.9 Event Processing - Segment Arrives:
648 * - first check sequence number - we skip that one in TIME_WAIT (always
649 * acceptable since we only send ACKs)
650 * - second check the RST bit (... return) */
651 if (flags
& TCP_RST
) {
654 /* - fourth, check the SYN bit, */
655 if (flags
& TCP_SYN
) {
656 /* If an incoming segment is not acceptable, an acknowledgment
657 should be sent in reply */
658 if (TCP_SEQ_BETWEEN(seqno
, pcb
->rcv_nxt
, pcb
->rcv_nxt
+ pcb
->rcv_wnd
)) {
659 /* If the SYN is in the window it is an error, send a reset */
660 tcp_rst(ackno
, seqno
+ tcplen
, ip_current_dest_addr(),
661 ip_current_src_addr(), tcphdr
->dest
, tcphdr
->src
);
664 } else if (flags
& TCP_FIN
) {
665 /* - eighth, check the FIN bit: Remain in the TIME-WAIT state.
666 Restart the 2 MSL time-wait timeout.*/
667 pcb
->tmr
= tcp_ticks
;
671 /* Acknowledge data, FIN or out-of-window SYN */
672 pcb
->flags
|= TF_ACK_NOW
;
679 * Implements the TCP state machine. Called by tcp_input. In some
680 * states tcp_receive() is called to receive data. The tcp_seg
681 * argument will be freed by the caller (tcp_input()) unless the
682 * recv_data pointer in the pcb is set.
684 * @param pcb the tcp_pcb for which a segment arrived
686 * @note the segment which arrived is saved in global variables, therefore only the pcb
687 * involved is passed as a parameter to this function
690 tcp_process(struct tcp_pcb
*pcb
)
692 struct tcp_seg
*rseg
;
698 /* Process incoming RST segments. */
699 if (flags
& TCP_RST
) {
700 /* First, determine if the reset is acceptable. */
701 if (pcb
->state
== SYN_SENT
) {
702 /* "In the SYN-SENT state (a RST received in response to an initial SYN),
703 the RST is acceptable if the ACK field acknowledges the SYN." */
704 if (ackno
== pcb
->snd_nxt
) {
708 /* "In all states except SYN-SENT, all reset (RST) segments are validated
709 by checking their SEQ-fields." */
710 if (seqno
== pcb
->rcv_nxt
) {
712 } else if (TCP_SEQ_BETWEEN(seqno
, pcb
->rcv_nxt
,
713 pcb
->rcv_nxt
+ pcb
->rcv_wnd
)) {
714 /* If the sequence number is inside the window, we only send an ACK
715 and wait for a re-send with matching sequence number.
716 This violates RFC 793, but is required to protection against
717 CVE-2004-0230 (RST spoofing attack). */
723 LWIP_DEBUGF(TCP_INPUT_DEBUG
, ("tcp_process: Connection RESET\n"));
724 LWIP_ASSERT("tcp_input: pcb->state != CLOSED", pcb
->state
!= CLOSED
);
725 recv_flags
|= TF_RESET
;
726 pcb
->flags
&= ~TF_ACK_DELAY
;
729 LWIP_DEBUGF(TCP_INPUT_DEBUG
, ("tcp_process: unacceptable reset seqno %"U32_F
" rcv_nxt %"U32_F
"\n",
730 seqno
, pcb
->rcv_nxt
));
731 LWIP_DEBUGF(TCP_DEBUG
, ("tcp_process: unacceptable reset seqno %"U32_F
" rcv_nxt %"U32_F
"\n",
732 seqno
, pcb
->rcv_nxt
));
737 if ((flags
& TCP_SYN
) && (pcb
->state
!= SYN_SENT
&& pcb
->state
!= SYN_RCVD
)) {
738 /* Cope with new connection attempt after remote end crashed */
743 if ((pcb
->flags
& TF_RXCLOSED
) == 0) {
744 /* Update the PCB (in)activity timer unless rx is closed (see tcp_shutdown) */
745 pcb
->tmr
= tcp_ticks
;
747 pcb
->keep_cnt_sent
= 0;
751 /* Do different things depending on the TCP state. */
752 switch (pcb
->state
) {
754 LWIP_DEBUGF(TCP_INPUT_DEBUG
, ("SYN-SENT: ackno %"U32_F
" pcb->snd_nxt %"U32_F
" unacked %"U32_F
"\n", ackno
,
755 pcb
->snd_nxt
, lwip_ntohl(pcb
->unacked
->tcphdr
->seqno
)));
756 /* received SYN ACK with expected sequence number? */
757 if ((flags
& TCP_ACK
) && (flags
& TCP_SYN
)
758 && (ackno
== pcb
->lastack
+ 1)) {
759 pcb
->rcv_nxt
= seqno
+ 1;
760 pcb
->rcv_ann_right_edge
= pcb
->rcv_nxt
;
761 pcb
->lastack
= ackno
;
762 pcb
->snd_wnd
= tcphdr
->wnd
;
763 pcb
->snd_wnd_max
= pcb
->snd_wnd
;
764 pcb
->snd_wl1
= seqno
- 1; /* initialise to seqno - 1 to force window update */
765 pcb
->state
= ESTABLISHED
;
767 #if TCP_CALCULATE_EFF_SEND_MSS
768 pcb
->mss
= tcp_eff_send_mss(pcb
->mss
, &pcb
->local_ip
, &pcb
->remote_ip
);
769 #endif /* TCP_CALCULATE_EFF_SEND_MSS */
771 pcb
->cwnd
= LWIP_TCP_CALC_INITIAL_CWND(pcb
->mss
);
772 LWIP_DEBUGF(TCP_CWND_DEBUG
, ("tcp_process (SENT): cwnd %"TCPWNDSIZE_F
773 " ssthresh %"TCPWNDSIZE_F
"\n",
774 pcb
->cwnd
, pcb
->ssthresh
));
775 LWIP_ASSERT("pcb->snd_queuelen > 0", (pcb
->snd_queuelen
> 0));
777 LWIP_DEBUGF(TCP_QLEN_DEBUG
, ("tcp_process: SYN-SENT --queuelen %"TCPWNDSIZE_F
"\n", (tcpwnd_size_t
)pcb
->snd_queuelen
));
780 /* might happen if tcp_output fails in tcp_rexmit_rto()
781 in which case the segment is on the unsent list */
783 LWIP_ASSERT("no segment to free", rseg
!= NULL
);
784 pcb
->unsent
= rseg
->next
;
786 pcb
->unacked
= rseg
->next
;
790 /* If there's nothing left to acknowledge, stop the retransmit
791 timer, otherwise reset it to start again */
792 if (pcb
->unacked
== NULL
) {
799 /* Call the user specified function to call when successfully
801 TCP_EVENT_CONNECTED(pcb
, ERR_OK
, err
);
802 if (err
== ERR_ABRT
) {
807 /* received ACK? possibly a half-open connection */
808 else if (flags
& TCP_ACK
) {
809 /* send a RST to bring the other side in a non-synchronized state. */
810 tcp_rst(ackno
, seqno
+ tcplen
, ip_current_dest_addr(),
811 ip_current_src_addr(), tcphdr
->dest
, tcphdr
->src
);
812 /* Resend SYN immediately (don't wait for rto timeout) to establish
813 connection faster, but do not send more SYNs than we otherwise would
814 have, or we might get caught in a loop on loopback interfaces. */
815 if (pcb
->nrtx
< TCP_SYNMAXRTX
) {
822 if (flags
& TCP_ACK
) {
823 /* expected ACK number? */
824 if (TCP_SEQ_BETWEEN(ackno
, pcb
->lastack
+1, pcb
->snd_nxt
)) {
825 pcb
->state
= ESTABLISHED
;
826 LWIP_DEBUGF(TCP_DEBUG
, ("TCP connection established %"U16_F
" -> %"U16_F
".\n", inseg
.tcphdr
->src
, inseg
.tcphdr
->dest
));
827 #if LWIP_CALLBACK_API || TCP_LISTEN_BACKLOG
828 if (pcb
->listener
== NULL
) {
829 /* listen pcb might be closed by now */
832 #endif /* LWIP_CALLBACK_API || TCP_LISTEN_BACKLOG */
834 #if LWIP_CALLBACK_API
835 LWIP_ASSERT("pcb->listener->accept != NULL", pcb
->listener
->accept
!= NULL
);
837 tcp_backlog_accepted(pcb
);
838 /* Call the accept function. */
839 TCP_EVENT_ACCEPT(pcb
->listener
, pcb
, pcb
->callback_arg
, ERR_OK
, err
);
842 /* If the accept function returns with an error, we abort
844 /* Already aborted? */
845 if (err
!= ERR_ABRT
) {
850 /* If there was any data contained within this ACK,
851 * we'd better pass it on to the application as well. */
854 /* Prevent ACK for SYN to generate a sent event */
855 if (recv_acked
!= 0) {
859 pcb
->cwnd
= LWIP_TCP_CALC_INITIAL_CWND(pcb
->mss
);
860 LWIP_DEBUGF(TCP_CWND_DEBUG
, ("tcp_process (SYN_RCVD): cwnd %"TCPWNDSIZE_F
861 " ssthresh %"TCPWNDSIZE_F
"\n",
862 pcb
->cwnd
, pcb
->ssthresh
));
864 if (recv_flags
& TF_GOT_FIN
) {
866 pcb
->state
= CLOSE_WAIT
;
869 /* incorrect ACK number, send RST */
870 tcp_rst(ackno
, seqno
+ tcplen
, ip_current_dest_addr(),
871 ip_current_src_addr(), tcphdr
->dest
, tcphdr
->src
);
873 } else if ((flags
& TCP_SYN
) && (seqno
== pcb
->rcv_nxt
- 1)) {
874 /* Looks like another copy of the SYN - retransmit our SYN-ACK */
882 if (recv_flags
& TF_GOT_FIN
) { /* passive close */
884 pcb
->state
= CLOSE_WAIT
;
889 if (recv_flags
& TF_GOT_FIN
) {
890 if ((flags
& TCP_ACK
) && (ackno
== pcb
->snd_nxt
) &&
891 pcb
->unsent
== NULL
) {
892 LWIP_DEBUGF(TCP_DEBUG
,
893 ("TCP connection closed: FIN_WAIT_1 %"U16_F
" -> %"U16_F
".\n", inseg
.tcphdr
->src
, inseg
.tcphdr
->dest
));
897 pcb
->state
= TIME_WAIT
;
898 TCP_REG(&tcp_tw_pcbs
, pcb
);
901 pcb
->state
= CLOSING
;
903 } else if ((flags
& TCP_ACK
) && (ackno
== pcb
->snd_nxt
) &&
904 pcb
->unsent
== NULL
) {
905 pcb
->state
= FIN_WAIT_2
;
910 if (recv_flags
& TF_GOT_FIN
) {
911 LWIP_DEBUGF(TCP_DEBUG
, ("TCP connection closed: FIN_WAIT_2 %"U16_F
" -> %"U16_F
".\n", inseg
.tcphdr
->src
, inseg
.tcphdr
->dest
));
915 pcb
->state
= TIME_WAIT
;
916 TCP_REG(&tcp_tw_pcbs
, pcb
);
921 if ((flags
& TCP_ACK
) && ackno
== pcb
->snd_nxt
&& pcb
->unsent
== NULL
) {
922 LWIP_DEBUGF(TCP_DEBUG
, ("TCP connection closed: CLOSING %"U16_F
" -> %"U16_F
".\n", inseg
.tcphdr
->src
, inseg
.tcphdr
->dest
));
925 pcb
->state
= TIME_WAIT
;
926 TCP_REG(&tcp_tw_pcbs
, pcb
);
931 if ((flags
& TCP_ACK
) && ackno
== pcb
->snd_nxt
&& pcb
->unsent
== NULL
) {
932 LWIP_DEBUGF(TCP_DEBUG
, ("TCP connection closed: LAST_ACK %"U16_F
" -> %"U16_F
".\n", inseg
.tcphdr
->src
, inseg
.tcphdr
->dest
));
933 /* bugfix #21699: don't set pcb->state to CLOSED here or we risk leaking segments */
934 recv_flags
|= TF_CLOSED
;
945 * Insert segment into the list (segments covered with new one will be deleted)
947 * Called from tcp_receive()
950 tcp_oos_insert_segment(struct tcp_seg
*cseg
, struct tcp_seg
*next
)
952 struct tcp_seg
*old_seg
;
954 if (TCPH_FLAGS(cseg
->tcphdr
) & TCP_FIN
) {
955 /* received segment overlaps all following segments */
959 /* delete some following segments
960 oos queue may have segments with FIN flag */
962 TCP_SEQ_GEQ((seqno
+ cseg
->len
),
963 (next
->tcphdr
->seqno
+ next
->len
))) {
964 /* cseg with FIN already processed */
965 if (TCPH_FLAGS(next
->tcphdr
) & TCP_FIN
) {
966 TCPH_SET_FLAG(cseg
->tcphdr
, TCP_FIN
);
970 tcp_seg_free(old_seg
);
973 TCP_SEQ_GT(seqno
+ cseg
->len
, next
->tcphdr
->seqno
)) {
974 /* We need to trim the incoming segment. */
975 cseg
->len
= (u16_t
)(next
->tcphdr
->seqno
- seqno
);
976 pbuf_realloc(cseg
->p
, cseg
->len
);
981 #endif /* TCP_QUEUE_OOSEQ */
984 * Called by tcp_process. Checks if the given segment is an ACK for outstanding
985 * data, and if so frees the memory of the buffered data. Next, it places the
986 * segment on any of the receive queues (pcb->recved or pcb->ooseq). If the segment
987 * is buffered, the pbuf is referenced by pbuf_ref so that it will not be freed until
988 * it has been removed from the buffer.
990 * If the incoming segment constitutes an ACK for a segment that was used for RTT
991 * estimation, the RTT is estimated here as well.
993 * Called from tcp_process().
996 tcp_receive(struct tcp_pcb
*pcb
)
998 struct tcp_seg
*next
;
1000 struct tcp_seg
*prev
, *cseg
;
1001 #endif /* TCP_QUEUE_OOSEQ */
1004 u32_t right_wnd_edge
;
1006 int found_dupack
= 0;
1007 #if TCP_OOSEQ_MAX_BYTES || TCP_OOSEQ_MAX_PBUFS
1010 #endif /* TCP_OOSEQ_MAX_BYTES || TCP_OOSEQ_MAX_PBUFS */
1012 LWIP_ASSERT("tcp_receive: wrong state", pcb
->state
>= ESTABLISHED
);
1014 if (flags
& TCP_ACK
) {
1015 right_wnd_edge
= pcb
->snd_wnd
+ pcb
->snd_wl2
;
1017 /* Update window. */
1018 if (TCP_SEQ_LT(pcb
->snd_wl1
, seqno
) ||
1019 (pcb
->snd_wl1
== seqno
&& TCP_SEQ_LT(pcb
->snd_wl2
, ackno
)) ||
1020 (pcb
->snd_wl2
== ackno
&& (u32_t
)SND_WND_SCALE(pcb
, tcphdr
->wnd
) > pcb
->snd_wnd
)) {
1021 pcb
->snd_wnd
= SND_WND_SCALE(pcb
, tcphdr
->wnd
);
1022 /* keep track of the biggest window announced by the remote host to calculate
1023 the maximum segment size */
1024 if (pcb
->snd_wnd_max
< pcb
->snd_wnd
) {
1025 pcb
->snd_wnd_max
= pcb
->snd_wnd
;
1027 pcb
->snd_wl1
= seqno
;
1028 pcb
->snd_wl2
= ackno
;
1029 if (pcb
->snd_wnd
== 0) {
1030 if (pcb
->persist_backoff
== 0) {
1031 /* start persist timer */
1032 pcb
->persist_cnt
= 0;
1033 pcb
->persist_backoff
= 1;
1035 } else if (pcb
->persist_backoff
> 0) {
1036 /* stop persist timer */
1037 pcb
->persist_backoff
= 0;
1039 LWIP_DEBUGF(TCP_WND_DEBUG
, ("tcp_receive: window update %"TCPWNDSIZE_F
"\n", pcb
->snd_wnd
));
1042 if (pcb
->snd_wnd
!= (tcpwnd_size_t
)SND_WND_SCALE(pcb
, tcphdr
->wnd
)) {
1043 LWIP_DEBUGF(TCP_WND_DEBUG
,
1044 ("tcp_receive: no window update lastack %"U32_F
" ackno %"
1045 U32_F
" wl1 %"U32_F
" seqno %"U32_F
" wl2 %"U32_F
"\n",
1046 pcb
->lastack
, ackno
, pcb
->snd_wl1
, seqno
, pcb
->snd_wl2
));
1048 #endif /* TCP_WND_DEBUG */
1051 /* (From Stevens TCP/IP Illustrated Vol II, p970.) Its only a
1053 * 1) It doesn't ACK new data
1054 * 2) length of received packet is zero (i.e. no payload)
1055 * 3) the advertised window hasn't changed
1056 * 4) There is outstanding unacknowledged data (retransmission timer running)
1057 * 5) The ACK is == biggest ACK sequence number so far seen (snd_una)
1059 * If it passes all five, should process as a dupack:
1060 * a) dupacks < 3: do nothing
1061 * b) dupacks == 3: fast retransmit
1062 * c) dupacks > 3: increase cwnd
1064 * If it only passes 1-3, should reset dupack counter (and add to
1065 * stats, which we don't do in lwIP)
1067 * If it only passes 1, should reset dupack counter
1072 if (TCP_SEQ_LEQ(ackno
, pcb
->lastack
)) {
1076 if (pcb
->snd_wl2
+ pcb
->snd_wnd
== right_wnd_edge
) {
1078 if (pcb
->rtime
>= 0) {
1080 if (pcb
->lastack
== ackno
) {
1082 if ((u8_t
)(pcb
->dupacks
+ 1) > pcb
->dupacks
) {
1085 if (pcb
->dupacks
> 3) {
1086 /* Inflate the congestion window, but not if it means that
1087 the value overflows. */
1088 if ((tcpwnd_size_t
)(pcb
->cwnd
+ pcb
->mss
) > pcb
->cwnd
) {
1089 pcb
->cwnd
+= pcb
->mss
;
1091 } else if (pcb
->dupacks
== 3) {
1092 /* Do fast retransmit */
1093 tcp_rexmit_fast(pcb
);
1099 /* If Clause (1) or more is true, but not a duplicate ack, reset
1100 * count of consecutive duplicate acks */
1101 if (!found_dupack
) {
1104 } else if (TCP_SEQ_BETWEEN(ackno
, pcb
->lastack
+1, pcb
->snd_nxt
)) {
1105 /* We come here when the ACK acknowledges new data. */
1107 /* Reset the "IN Fast Retransmit" flag, since we are no longer
1108 in fast retransmit. Also reset the congestion window to the
1109 slow start threshold. */
1110 if (pcb
->flags
& TF_INFR
) {
1111 pcb
->flags
&= ~TF_INFR
;
1112 pcb
->cwnd
= pcb
->ssthresh
;
1115 /* Reset the number of retransmissions. */
1118 /* Reset the retransmission time-out. */
1119 pcb
->rto
= (pcb
->sa
>> 3) + pcb
->sv
;
1121 /* Reset the fast retransmit variables. */
1123 pcb
->lastack
= ackno
;
1125 /* Update the congestion control variables (cwnd and
1127 if (pcb
->state
>= ESTABLISHED
) {
1128 if (pcb
->cwnd
< pcb
->ssthresh
) {
1129 if ((tcpwnd_size_t
)(pcb
->cwnd
+ pcb
->mss
) > pcb
->cwnd
) {
1130 pcb
->cwnd
+= pcb
->mss
;
1132 LWIP_DEBUGF(TCP_CWND_DEBUG
, ("tcp_receive: slow start cwnd %"TCPWNDSIZE_F
"\n", pcb
->cwnd
));
1134 tcpwnd_size_t new_cwnd
= (pcb
->cwnd
+ pcb
->mss
* pcb
->mss
/ pcb
->cwnd
);
1135 if (new_cwnd
> pcb
->cwnd
) {
1136 pcb
->cwnd
= new_cwnd
;
1138 LWIP_DEBUGF(TCP_CWND_DEBUG
, ("tcp_receive: congestion avoidance cwnd %"TCPWNDSIZE_F
"\n", pcb
->cwnd
));
1141 LWIP_DEBUGF(TCP_INPUT_DEBUG
, ("tcp_receive: ACK for %"U32_F
", unacked->seqno %"U32_F
":%"U32_F
"\n",
1143 pcb
->unacked
!= NULL
?
1144 lwip_ntohl(pcb
->unacked
->tcphdr
->seqno
): 0,
1145 pcb
->unacked
!= NULL
?
1146 lwip_ntohl(pcb
->unacked
->tcphdr
->seqno
) + TCP_TCPLEN(pcb
->unacked
): 0));
1148 /* Remove segment from the unacknowledged list if the incoming
1149 ACK acknowledges them. */
1150 while (pcb
->unacked
!= NULL
&&
1151 TCP_SEQ_LEQ(lwip_ntohl(pcb
->unacked
->tcphdr
->seqno
) +
1152 TCP_TCPLEN(pcb
->unacked
), ackno
)) {
1153 LWIP_DEBUGF(TCP_INPUT_DEBUG
, ("tcp_receive: removing %"U32_F
":%"U32_F
" from pcb->unacked\n",
1154 lwip_ntohl(pcb
->unacked
->tcphdr
->seqno
),
1155 lwip_ntohl(pcb
->unacked
->tcphdr
->seqno
) +
1156 TCP_TCPLEN(pcb
->unacked
)));
1158 next
= pcb
->unacked
;
1159 pcb
->unacked
= pcb
->unacked
->next
;
1161 LWIP_DEBUGF(TCP_QLEN_DEBUG
, ("tcp_receive: queuelen %"TCPWNDSIZE_F
" ... ", (tcpwnd_size_t
)pcb
->snd_queuelen
));
1162 LWIP_ASSERT("pcb->snd_queuelen >= pbuf_clen(next->p)", (pcb
->snd_queuelen
>= pbuf_clen(next
->p
)));
1164 pcb
->snd_queuelen
-= pbuf_clen(next
->p
);
1165 recv_acked
+= next
->len
;
1168 LWIP_DEBUGF(TCP_QLEN_DEBUG
, ("%"TCPWNDSIZE_F
" (after freeing unacked)\n", (tcpwnd_size_t
)pcb
->snd_queuelen
));
1169 if (pcb
->snd_queuelen
!= 0) {
1170 LWIP_ASSERT("tcp_receive: valid queue length", pcb
->unacked
!= NULL
||
1171 pcb
->unsent
!= NULL
);
1175 /* If there's nothing left to acknowledge, stop the retransmit
1176 timer, otherwise reset it to start again */
1177 if (pcb
->unacked
== NULL
) {
1185 #if LWIP_IPV6 && LWIP_ND6_TCP_REACHABILITY_HINTS
1186 if (ip_current_is_v6()) {
1187 /* Inform neighbor reachability of forward progress. */
1188 nd6_reachability_hint(ip6_current_src_addr());
1190 #endif /* LWIP_IPV6 && LWIP_ND6_TCP_REACHABILITY_HINTS*/
1192 /* Out of sequence ACK, didn't really ack anything */
1193 tcp_send_empty_ack(pcb
);
1196 /* We go through the ->unsent list to see if any of the segments
1197 on the list are acknowledged by the ACK. This may seem
1198 strange since an "unsent" segment shouldn't be acked. The
1199 rationale is that lwIP puts all outstanding segments on the
1200 ->unsent list after a retransmission, so these segments may
1201 in fact have been sent once. */
1202 while (pcb
->unsent
!= NULL
&&
1203 TCP_SEQ_BETWEEN(ackno
, lwip_ntohl(pcb
->unsent
->tcphdr
->seqno
) +
1204 TCP_TCPLEN(pcb
->unsent
), pcb
->snd_nxt
)) {
1205 LWIP_DEBUGF(TCP_INPUT_DEBUG
, ("tcp_receive: removing %"U32_F
":%"U32_F
" from pcb->unsent\n",
1206 lwip_ntohl(pcb
->unsent
->tcphdr
->seqno
), lwip_ntohl(pcb
->unsent
->tcphdr
->seqno
) +
1207 TCP_TCPLEN(pcb
->unsent
)));
1210 pcb
->unsent
= pcb
->unsent
->next
;
1212 if (pcb
->unsent
== NULL
) {
1213 pcb
->unsent_oversize
= 0;
1215 #endif /* TCP_OVERSIZE */
1216 LWIP_DEBUGF(TCP_QLEN_DEBUG
, ("tcp_receive: queuelen %"TCPWNDSIZE_F
" ... ", (tcpwnd_size_t
)pcb
->snd_queuelen
));
1217 LWIP_ASSERT("pcb->snd_queuelen >= pbuf_clen(next->p)", (pcb
->snd_queuelen
>= pbuf_clen(next
->p
)));
1218 /* Prevent ACK for FIN to generate a sent event */
1219 pcb
->snd_queuelen
-= pbuf_clen(next
->p
);
1220 recv_acked
+= next
->len
;
1222 LWIP_DEBUGF(TCP_QLEN_DEBUG
, ("%"TCPWNDSIZE_F
" (after freeing unsent)\n", (tcpwnd_size_t
)pcb
->snd_queuelen
));
1223 if (pcb
->snd_queuelen
!= 0) {
1224 LWIP_ASSERT("tcp_receive: valid queue length",
1225 pcb
->unacked
!= NULL
|| pcb
->unsent
!= NULL
);
1228 pcb
->snd_buf
+= recv_acked
;
1229 /* End of ACK for new data processing. */
1231 LWIP_DEBUGF(TCP_RTO_DEBUG
, ("tcp_receive: pcb->rttest %"U32_F
" rtseq %"U32_F
" ackno %"U32_F
"\n",
1232 pcb
->rttest
, pcb
->rtseq
, ackno
));
1234 /* RTT estimation calculations. This is done by checking if the
1235 incoming segment acknowledges the segment we use to take a
1236 round-trip time measurement. */
1237 if (pcb
->rttest
&& TCP_SEQ_LT(pcb
->rtseq
, ackno
)) {
1238 /* diff between this shouldn't exceed 32K since this are tcp timer ticks
1239 and a round-trip shouldn't be that long... */
1240 m
= (s16_t
)(tcp_ticks
- pcb
->rttest
);
1242 LWIP_DEBUGF(TCP_RTO_DEBUG
, ("tcp_receive: experienced rtt %"U16_F
" ticks (%"U16_F
" msec).\n",
1243 m
, (u16_t
)(m
* TCP_SLOW_INTERVAL
)));
1245 /* This is taken directly from VJs original code in his paper */
1246 m
= m
- (pcb
->sa
>> 3);
1251 m
= m
- (pcb
->sv
>> 2);
1253 pcb
->rto
= (pcb
->sa
>> 3) + pcb
->sv
;
1255 LWIP_DEBUGF(TCP_RTO_DEBUG
, ("tcp_receive: RTO %"U16_F
" (%"U16_F
" milliseconds)\n",
1256 pcb
->rto
, (u16_t
)(pcb
->rto
* TCP_SLOW_INTERVAL
)));
1262 /* If the incoming segment contains data, we must process it
1263 further unless the pcb already received a FIN.
1264 (RFC 793, chapter 3.9, "SEGMENT ARRIVES" in states CLOSE-WAIT, CLOSING,
1265 LAST-ACK and TIME-WAIT: "Ignore the segment text.") */
1266 if ((tcplen
> 0) && (pcb
->state
< CLOSE_WAIT
)) {
1267 /* This code basically does three things:
1269 +) If the incoming segment contains data that is the next
1270 in-sequence data, this data is passed to the application. This
1271 might involve trimming the first edge of the data. The rcv_nxt
1272 variable and the advertised window are adjusted.
1274 +) If the incoming segment has data that is above the next
1275 sequence number expected (->rcv_nxt), the segment is placed on
1276 the ->ooseq queue. This is done by finding the appropriate
1277 place in the ->ooseq queue (which is ordered by sequence
1278 number) and trim the segment in both ends if needed. An
1279 immediate ACK is sent to indicate that we received an
1280 out-of-sequence segment.
1282 +) Finally, we check if the first segment on the ->ooseq queue
1283 now is in sequence (i.e., if rcv_nxt >= ooseq->seqno). If
1284 rcv_nxt > ooseq->seqno, we must trim the first edge of the
1285 segment on ->ooseq before we adjust rcv_nxt. The data in the
1286 segments that are now on sequence are chained onto the
1287 incoming segment so that we only need to call the application
1291 /* First, we check if we must trim the first edge. We have to do
1292 this if the sequence number of the incoming segment is less
1293 than rcv_nxt, and the sequence number plus the length of the
1294 segment is larger than rcv_nxt. */
1295 /* if (TCP_SEQ_LT(seqno, pcb->rcv_nxt)) {
1296 if (TCP_SEQ_LT(pcb->rcv_nxt, seqno + tcplen)) {*/
1297 if (TCP_SEQ_BETWEEN(pcb
->rcv_nxt
, seqno
+ 1, seqno
+ tcplen
- 1)) {
1298 /* Trimming the first edge is done by pushing the payload
1299 pointer in the pbuf downwards. This is somewhat tricky since
1300 we do not want to discard the full contents of the pbuf up to
1301 the new starting point of the data since we have to keep the
1302 TCP header which is present in the first pbuf in the chain.
1304 What is done is really quite a nasty hack: the first pbuf in
1305 the pbuf chain is pointed to by inseg.p. Since we need to be
1306 able to deallocate the whole pbuf, we cannot change this
1307 inseg.p pointer to point to any of the later pbufs in the
1308 chain. Instead, we point the ->payload pointer in the first
1309 pbuf to data in one of the later pbufs. We also set the
1310 inseg.data pointer to point to the right place. This way, the
1311 ->p pointer will still point to the first pbuf, but the
1312 ->p->payload pointer will point to data in another pbuf.
1314 After we are done with adjusting the pbuf pointers we must
1315 adjust the ->data pointer in the seg and the segment
1318 struct pbuf
*p
= inseg
.p
;
1319 off
= pcb
->rcv_nxt
- seqno
;
1320 LWIP_ASSERT("inseg.p != NULL", inseg
.p
);
1321 LWIP_ASSERT("insane offset!", (off
< 0x7fff));
1322 if (inseg
.p
->len
< off
) {
1323 LWIP_ASSERT("pbuf too short!", (((s32_t
)inseg
.p
->tot_len
) >= off
));
1324 new_tot_len
= (u16_t
)(inseg
.p
->tot_len
- off
);
1325 while (p
->len
< off
) {
1327 /* KJM following line changed (with addition of new_tot_len var)
1329 inseg.p->tot_len -= p->len; */
1330 p
->tot_len
= new_tot_len
;
1334 if (pbuf_header(p
, (s16_t
)-off
)) {
1335 /* Do we need to cope with this failing? Assert for now */
1336 LWIP_ASSERT("pbuf_header failed", 0);
1339 if (pbuf_header(inseg
.p
, (s16_t
)-off
)) {
1340 /* Do we need to cope with this failing? Assert for now */
1341 LWIP_ASSERT("pbuf_header failed", 0);
1344 inseg
.len
-= (u16_t
)(pcb
->rcv_nxt
- seqno
);
1345 inseg
.tcphdr
->seqno
= seqno
= pcb
->rcv_nxt
;
1348 if (TCP_SEQ_LT(seqno
, pcb
->rcv_nxt
)) {
1349 /* the whole segment is < rcv_nxt */
1350 /* must be a duplicate of a packet that has already been correctly handled */
1352 LWIP_DEBUGF(TCP_INPUT_DEBUG
, ("tcp_receive: duplicate seqno %"U32_F
"\n", seqno
));
1357 /* The sequence number must be within the window (above rcv_nxt
1358 and below rcv_nxt + rcv_wnd) in order to be further
1360 if (TCP_SEQ_BETWEEN(seqno
, pcb
->rcv_nxt
,
1361 pcb
->rcv_nxt
+ pcb
->rcv_wnd
- 1)) {
1362 if (pcb
->rcv_nxt
== seqno
) {
1363 /* The incoming segment is the next in sequence. We check if
1364 we have to trim the end of the segment and update rcv_nxt
1365 and pass the data to the application. */
1366 tcplen
= TCP_TCPLEN(&inseg
);
1368 if (tcplen
> pcb
->rcv_wnd
) {
1369 LWIP_DEBUGF(TCP_INPUT_DEBUG
,
1370 ("tcp_receive: other end overran receive window"
1371 "seqno %"U32_F
" len %"U16_F
" right edge %"U32_F
"\n",
1372 seqno
, tcplen
, pcb
->rcv_nxt
+ pcb
->rcv_wnd
));
1373 if (TCPH_FLAGS(inseg
.tcphdr
) & TCP_FIN
) {
1374 /* Must remove the FIN from the header as we're trimming
1375 * that byte of sequence-space from the packet */
1376 TCPH_FLAGS_SET(inseg
.tcphdr
, TCPH_FLAGS(inseg
.tcphdr
) & ~(unsigned int)TCP_FIN
);
1378 /* Adjust length of segment to fit in the window. */
1379 TCPWND_CHECK16(pcb
->rcv_wnd
);
1380 inseg
.len
= (u16_t
)pcb
->rcv_wnd
;
1381 if (TCPH_FLAGS(inseg
.tcphdr
) & TCP_SYN
) {
1384 pbuf_realloc(inseg
.p
, inseg
.len
);
1385 tcplen
= TCP_TCPLEN(&inseg
);
1386 LWIP_ASSERT("tcp_receive: segment not trimmed correctly to rcv_wnd\n",
1387 (seqno
+ tcplen
) == (pcb
->rcv_nxt
+ pcb
->rcv_wnd
));
1390 /* Received in-sequence data, adjust ooseq data if:
1391 - FIN has been received or
1392 - inseq overlaps with ooseq */
1393 if (pcb
->ooseq
!= NULL
) {
1394 if (TCPH_FLAGS(inseg
.tcphdr
) & TCP_FIN
) {
1395 LWIP_DEBUGF(TCP_INPUT_DEBUG
,
1396 ("tcp_receive: received in-order FIN, binning ooseq queue\n"));
1397 /* Received in-order FIN means anything that was received
1398 * out of order must now have been received in-order, so
1399 * bin the ooseq queue */
1400 while (pcb
->ooseq
!= NULL
) {
1401 struct tcp_seg
*old_ooseq
= pcb
->ooseq
;
1402 pcb
->ooseq
= pcb
->ooseq
->next
;
1403 tcp_seg_free(old_ooseq
);
1407 /* Remove all segments on ooseq that are covered by inseg already.
1408 * FIN is copied from ooseq to inseg if present. */
1410 TCP_SEQ_GEQ(seqno
+ tcplen
,
1411 next
->tcphdr
->seqno
+ next
->len
)) {
1412 /* inseg cannot have FIN here (already processed above) */
1413 if ((TCPH_FLAGS(next
->tcphdr
) & TCP_FIN
) != 0 &&
1414 (TCPH_FLAGS(inseg
.tcphdr
) & TCP_SYN
) == 0) {
1415 TCPH_SET_FLAG(inseg
.tcphdr
, TCP_FIN
);
1416 tcplen
= TCP_TCPLEN(&inseg
);
1422 /* Now trim right side of inseg if it overlaps with the first
1423 * segment on ooseq */
1425 TCP_SEQ_GT(seqno
+ tcplen
,
1426 next
->tcphdr
->seqno
)) {
1427 /* inseg cannot have FIN here (already processed above) */
1428 inseg
.len
= (u16_t
)(next
->tcphdr
->seqno
- seqno
);
1429 if (TCPH_FLAGS(inseg
.tcphdr
) & TCP_SYN
) {
1432 pbuf_realloc(inseg
.p
, inseg
.len
);
1433 tcplen
= TCP_TCPLEN(&inseg
);
1434 LWIP_ASSERT("tcp_receive: segment not trimmed correctly to ooseq queue\n",
1435 (seqno
+ tcplen
) == next
->tcphdr
->seqno
);
1440 #endif /* TCP_QUEUE_OOSEQ */
1442 pcb
->rcv_nxt
= seqno
+ tcplen
;
1444 /* Update the receiver's (our) window. */
1445 LWIP_ASSERT("tcp_receive: tcplen > rcv_wnd\n", pcb
->rcv_wnd
>= tcplen
);
1446 pcb
->rcv_wnd
-= tcplen
;
1448 tcp_update_rcv_ann_wnd(pcb
);
1450 /* If there is data in the segment, we make preparations to
1451 pass this up to the application. The ->recv_data variable
1452 is used for holding the pbuf that goes to the
1453 application. The code for reassembling out-of-sequence data
1454 chains its data on this pbuf as well.
1456 If the segment was a FIN, we set the TF_GOT_FIN flag that will
1457 be used to indicate to the application that the remote side has
1458 closed its end of the connection. */
1459 if (inseg
.p
->tot_len
> 0) {
1460 recv_data
= inseg
.p
;
1461 /* Since this pbuf now is the responsibility of the
1462 application, we delete our reference to it so that we won't
1463 (mistakingly) deallocate it. */
1466 if (TCPH_FLAGS(inseg
.tcphdr
) & TCP_FIN
) {
1467 LWIP_DEBUGF(TCP_INPUT_DEBUG
, ("tcp_receive: received FIN.\n"));
1468 recv_flags
|= TF_GOT_FIN
;
1472 /* We now check if we have segments on the ->ooseq queue that
1473 are now in sequence. */
1474 while (pcb
->ooseq
!= NULL
&&
1475 pcb
->ooseq
->tcphdr
->seqno
== pcb
->rcv_nxt
) {
1478 seqno
= pcb
->ooseq
->tcphdr
->seqno
;
1480 pcb
->rcv_nxt
+= TCP_TCPLEN(cseg
);
1481 LWIP_ASSERT("tcp_receive: ooseq tcplen > rcv_wnd\n",
1482 pcb
->rcv_wnd
>= TCP_TCPLEN(cseg
));
1483 pcb
->rcv_wnd
-= TCP_TCPLEN(cseg
);
1485 tcp_update_rcv_ann_wnd(pcb
);
1487 if (cseg
->p
->tot_len
> 0) {
1488 /* Chain this pbuf onto the pbuf that we will pass to
1490 /* With window scaling, this can overflow recv_data->tot_len, but
1491 that's not a problem since we explicitly fix that before passing
1492 recv_data to the application. */
1494 pbuf_cat(recv_data
, cseg
->p
);
1496 recv_data
= cseg
->p
;
1500 if (TCPH_FLAGS(cseg
->tcphdr
) & TCP_FIN
) {
1501 LWIP_DEBUGF(TCP_INPUT_DEBUG
, ("tcp_receive: dequeued FIN.\n"));
1502 recv_flags
|= TF_GOT_FIN
;
1503 if (pcb
->state
== ESTABLISHED
) { /* force passive close or we can move to active close */
1504 pcb
->state
= CLOSE_WAIT
;
1508 pcb
->ooseq
= cseg
->next
;
1511 #endif /* TCP_QUEUE_OOSEQ */
1514 /* Acknowledge the segment(s). */
1517 #if LWIP_IPV6 && LWIP_ND6_TCP_REACHABILITY_HINTS
1518 if (ip_current_is_v6()) {
1519 /* Inform neighbor reachability of forward progress. */
1520 nd6_reachability_hint(ip6_current_src_addr());
1522 #endif /* LWIP_IPV6 && LWIP_ND6_TCP_REACHABILITY_HINTS*/
1525 /* We get here if the incoming segment is out-of-sequence. */
1526 tcp_send_empty_ack(pcb
);
1528 /* We queue the segment on the ->ooseq queue. */
1529 if (pcb
->ooseq
== NULL
) {
1530 pcb
->ooseq
= tcp_seg_copy(&inseg
);
1532 /* If the queue is not empty, we walk through the queue and
1533 try to find a place where the sequence number of the
1534 incoming segment is between the sequence numbers of the
1535 previous and the next segment on the ->ooseq queue. That is
1536 the place where we put the incoming segment. If needed, we
1537 trim the second edges of the previous and the incoming
1538 segment so that it will fit into the sequence.
1540 If the incoming segment has the same sequence number as a
1541 segment on the ->ooseq queue, we discard the segment that
1542 contains less data. */
1545 for (next
= pcb
->ooseq
; next
!= NULL
; next
= next
->next
) {
1546 if (seqno
== next
->tcphdr
->seqno
) {
1547 /* The sequence number of the incoming segment is the
1548 same as the sequence number of the segment on
1549 ->ooseq. We check the lengths to see which one to
1551 if (inseg
.len
> next
->len
) {
1552 /* The incoming segment is larger than the old
1553 segment. We replace some segments with the new
1555 cseg
= tcp_seg_copy(&inseg
);
1562 tcp_oos_insert_segment(cseg
, next
);
1566 /* Either the lengths are the same or the incoming
1567 segment was smaller than the old one; in either
1568 case, we ditch the incoming segment. */
1573 if (TCP_SEQ_LT(seqno
, next
->tcphdr
->seqno
)) {
1574 /* The sequence number of the incoming segment is lower
1575 than the sequence number of the first segment on the
1576 queue. We put the incoming segment first on the
1578 cseg
= tcp_seg_copy(&inseg
);
1581 tcp_oos_insert_segment(cseg
, next
);
1586 /*if (TCP_SEQ_LT(prev->tcphdr->seqno, seqno) &&
1587 TCP_SEQ_LT(seqno, next->tcphdr->seqno)) {*/
1588 if (TCP_SEQ_BETWEEN(seqno
, prev
->tcphdr
->seqno
+1, next
->tcphdr
->seqno
-1)) {
1589 /* The sequence number of the incoming segment is in
1590 between the sequence numbers of the previous and
1591 the next segment on ->ooseq. We trim trim the previous
1592 segment, delete next segments that included in received segment
1593 and trim received, if needed. */
1594 cseg
= tcp_seg_copy(&inseg
);
1596 if (TCP_SEQ_GT(prev
->tcphdr
->seqno
+ prev
->len
, seqno
)) {
1597 /* We need to trim the prev segment. */
1598 prev
->len
= (u16_t
)(seqno
- prev
->tcphdr
->seqno
);
1599 pbuf_realloc(prev
->p
, prev
->len
);
1602 tcp_oos_insert_segment(cseg
, next
);
1607 /* If the "next" segment is the last segment on the
1608 ooseq queue, we add the incoming segment to the end
1610 if (next
->next
== NULL
&&
1611 TCP_SEQ_GT(seqno
, next
->tcphdr
->seqno
)) {
1612 if (TCPH_FLAGS(next
->tcphdr
) & TCP_FIN
) {
1613 /* segment "next" already contains all data */
1616 next
->next
= tcp_seg_copy(&inseg
);
1617 if (next
->next
!= NULL
) {
1618 if (TCP_SEQ_GT(next
->tcphdr
->seqno
+ next
->len
, seqno
)) {
1619 /* We need to trim the last segment. */
1620 next
->len
= (u16_t
)(seqno
- next
->tcphdr
->seqno
);
1621 pbuf_realloc(next
->p
, next
->len
);
1623 /* check if the remote side overruns our receive window */
1624 if (TCP_SEQ_GT((u32_t
)tcplen
+ seqno
, pcb
->rcv_nxt
+ (u32_t
)pcb
->rcv_wnd
)) {
1625 LWIP_DEBUGF(TCP_INPUT_DEBUG
,
1626 ("tcp_receive: other end overran receive window"
1627 "seqno %"U32_F
" len %"U16_F
" right edge %"U32_F
"\n",
1628 seqno
, tcplen
, pcb
->rcv_nxt
+ pcb
->rcv_wnd
));
1629 if (TCPH_FLAGS(next
->next
->tcphdr
) & TCP_FIN
) {
1630 /* Must remove the FIN from the header as we're trimming
1631 * that byte of sequence-space from the packet */
1632 TCPH_FLAGS_SET(next
->next
->tcphdr
, TCPH_FLAGS(next
->next
->tcphdr
) & ~TCP_FIN
);
1634 /* Adjust length of segment to fit in the window. */
1635 next
->next
->len
= (u16_t
)(pcb
->rcv_nxt
+ pcb
->rcv_wnd
- seqno
);
1636 pbuf_realloc(next
->next
->p
, next
->next
->len
);
1637 tcplen
= TCP_TCPLEN(next
->next
);
1638 LWIP_ASSERT("tcp_receive: segment not trimmed correctly to rcv_wnd\n",
1639 (seqno
+ tcplen
) == (pcb
->rcv_nxt
+ pcb
->rcv_wnd
));
1648 #if TCP_OOSEQ_MAX_BYTES || TCP_OOSEQ_MAX_PBUFS
1649 /* Check that the data on ooseq doesn't exceed one of the limits
1650 and throw away everything above that limit. */
1654 for (next
= pcb
->ooseq
; next
!= NULL
; prev
= next
, next
= next
->next
) {
1655 struct pbuf
*p
= next
->p
;
1656 ooseq_blen
+= p
->tot_len
;
1657 ooseq_qlen
+= pbuf_clen(p
);
1658 if ((ooseq_blen
> TCP_OOSEQ_MAX_BYTES
) ||
1659 (ooseq_qlen
> TCP_OOSEQ_MAX_PBUFS
)) {
1660 /* too much ooseq data, dump this and everything after it */
1661 tcp_segs_free(next
);
1663 /* first ooseq segment is too much, dump the whole queue */
1666 /* just dump 'next' and everything after it */
1672 #endif /* TCP_OOSEQ_MAX_BYTES || TCP_OOSEQ_MAX_PBUFS */
1673 #endif /* TCP_QUEUE_OOSEQ */
1676 /* The incoming segment is not within the window. */
1677 tcp_send_empty_ack(pcb
);
1680 /* Segments with length 0 is taken care of here. Segments that
1681 fall out of the window are ACKed. */
1682 if (!TCP_SEQ_BETWEEN(seqno
, pcb
->rcv_nxt
, pcb
->rcv_nxt
+ pcb
->rcv_wnd
- 1)) {
1689 tcp_getoptbyte(void)
1691 if ((tcphdr_opt2
== NULL
) || (tcp_optidx
< tcphdr_opt1len
)) {
1692 u8_t
* opts
= (u8_t
*)tcphdr
+ TCP_HLEN
;
1693 return opts
[tcp_optidx
++];
1695 u8_t idx
= (u8_t
)(tcp_optidx
++ - tcphdr_opt1len
);
1696 return tcphdr_opt2
[idx
];
1701 * Parses the options contained in the incoming segment.
1703 * Called from tcp_listen_input() and tcp_process().
1704 * Currently, only the MSS option is supported!
1706 * @param pcb the tcp_pcb for which a segment arrived
1709 tcp_parseopt(struct tcp_pcb
*pcb
)
1713 #if LWIP_TCP_TIMESTAMPS
1717 /* Parse the TCP MSS option, if present. */
1718 if (tcphdr_optlen
!= 0) {
1719 for (tcp_optidx
= 0; tcp_optidx
< tcphdr_optlen
; ) {
1720 u8_t opt
= tcp_getoptbyte();
1722 case LWIP_TCP_OPT_EOL
:
1723 /* End of options. */
1724 LWIP_DEBUGF(TCP_INPUT_DEBUG
, ("tcp_parseopt: EOL\n"));
1726 case LWIP_TCP_OPT_NOP
:
1728 LWIP_DEBUGF(TCP_INPUT_DEBUG
, ("tcp_parseopt: NOP\n"));
1730 case LWIP_TCP_OPT_MSS
:
1731 LWIP_DEBUGF(TCP_INPUT_DEBUG
, ("tcp_parseopt: MSS\n"));
1732 if (tcp_getoptbyte() != LWIP_TCP_OPT_LEN_MSS
|| (tcp_optidx
- 2 + LWIP_TCP_OPT_LEN_MSS
) > tcphdr_optlen
) {
1734 LWIP_DEBUGF(TCP_INPUT_DEBUG
, ("tcp_parseopt: bad length\n"));
1737 /* An MSS option with the right option length. */
1738 mss
= (tcp_getoptbyte() << 8);
1739 mss
|= tcp_getoptbyte();
1740 /* Limit the mss to the configured TCP_MSS and prevent division by zero */
1741 pcb
->mss
= ((mss
> TCP_MSS
) || (mss
== 0)) ? TCP_MSS
: mss
;
1744 case LWIP_TCP_OPT_WS
:
1745 LWIP_DEBUGF(TCP_INPUT_DEBUG
, ("tcp_parseopt: WND_SCALE\n"));
1746 if (tcp_getoptbyte() != LWIP_TCP_OPT_LEN_WS
|| (tcp_optidx
- 2 + LWIP_TCP_OPT_LEN_WS
) > tcphdr_optlen
) {
1748 LWIP_DEBUGF(TCP_INPUT_DEBUG
, ("tcp_parseopt: bad length\n"));
1751 /* If syn was received with wnd scale option,
1752 activate wnd scale opt, but only if this is not a retransmission */
1753 if ((flags
& TCP_SYN
) && !(pcb
->flags
& TF_WND_SCALE
)) {
1754 /* An WND_SCALE option with the right option length. */
1755 data
= tcp_getoptbyte();
1756 pcb
->snd_scale
= data
;
1757 if (pcb
->snd_scale
> 14U) {
1758 pcb
->snd_scale
= 14U;
1760 pcb
->rcv_scale
= TCP_RCV_SCALE
;
1761 pcb
->flags
|= TF_WND_SCALE
;
1762 /* window scaling is enabled, we can use the full receive window */
1763 LWIP_ASSERT("window not at default value", pcb
->rcv_wnd
== TCPWND_MIN16(TCP_WND
));
1764 LWIP_ASSERT("window not at default value", pcb
->rcv_ann_wnd
== TCPWND_MIN16(TCP_WND
));
1765 pcb
->rcv_wnd
= pcb
->rcv_ann_wnd
= TCP_WND
;
1769 #if LWIP_TCP_TIMESTAMPS
1770 case LWIP_TCP_OPT_TS
:
1771 LWIP_DEBUGF(TCP_INPUT_DEBUG
, ("tcp_parseopt: TS\n"));
1772 if (tcp_getoptbyte() != LWIP_TCP_OPT_LEN_TS
|| (tcp_optidx
- 2 + LWIP_TCP_OPT_LEN_TS
) > tcphdr_optlen
) {
1774 LWIP_DEBUGF(TCP_INPUT_DEBUG
, ("tcp_parseopt: bad length\n"));
1777 /* TCP timestamp option with valid length */
1778 tsval
= tcp_getoptbyte();
1779 tsval
|= (tcp_getoptbyte() << 8);
1780 tsval
|= (tcp_getoptbyte() << 16);
1781 tsval
|= (tcp_getoptbyte() << 24);
1782 if (flags
& TCP_SYN
) {
1783 pcb
->ts_recent
= lwip_ntohl(tsval
);
1784 /* Enable sending timestamps in every segment now that we know
1785 the remote host supports it. */
1786 pcb
->flags
|= TF_TIMESTAMP
;
1787 } else if (TCP_SEQ_BETWEEN(pcb
->ts_lastacksent
, seqno
, seqno
+tcplen
)) {
1788 pcb
->ts_recent
= lwip_ntohl(tsval
);
1790 /* Advance to next option (6 bytes already read) */
1791 tcp_optidx
+= LWIP_TCP_OPT_LEN_TS
- 6;
1795 LWIP_DEBUGF(TCP_INPUT_DEBUG
, ("tcp_parseopt: other\n"));
1796 data
= tcp_getoptbyte();
1798 LWIP_DEBUGF(TCP_INPUT_DEBUG
, ("tcp_parseopt: bad length\n"));
1799 /* If the length field is zero, the options are malformed
1800 and we don't process them further. */
1803 /* All other options have a length field, so that we easily
1804 can skip past them. */
1805 tcp_optidx
+= data
- 2;
1812 tcp_trigger_input_pcb_close(void)
1814 recv_flags
|= TF_CLOSED
;
1817 #endif /* LWIP_TCP */