Darran Shepherd
/
AutoIpNetStack
Net stack with AutoIP enabled
Embed:
(wiki syntax)
Show/hide line numbers
tcp_in.c
Go to the documentation of this file.
00001 /** 00002 * @file 00003 * Transmission Control Protocol, incoming traffic 00004 * 00005 * The input processing functions of the TCP layer. 00006 * 00007 * These functions are generally called in the order (ip_input() ->) 00008 * tcp_input() -> * tcp_process() -> tcp_receive() (-> application). 00009 * 00010 */ 00011 00012 /* 00013 * Copyright (c) 2001-2004 Swedish Institute of Computer Science. 00014 * All rights reserved. 00015 * 00016 * Redistribution and use in source and binary forms, with or without modification, 00017 * are permitted provided that the following conditions are met: 00018 * 00019 * 1. Redistributions of source code must retain the above copyright notice, 00020 * this list of conditions and the following disclaimer. 00021 * 2. Redistributions in binary form must reproduce the above copyright notice, 00022 * this list of conditions and the following disclaimer in the documentation 00023 * and/or other materials provided with the distribution. 00024 * 3. The name of the author may not be used to endorse or promote products 00025 * derived from this software without specific prior written permission. 00026 * 00027 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 00028 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 00029 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 00030 * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 00031 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 00032 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 00033 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 00034 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 00035 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 00036 * OF SUCH DAMAGE. 00037 * 00038 * This file is part of the lwIP TCP/IP stack. 00039 * 00040 * Author: Adam Dunkels <adam@sics.se> 00041 * 00042 */ 00043 00044 #include "lwip/opt.h" 00045 00046 #if LWIP_TCP /* don't build if not configured for use in lwipopts.h */ 00047 00048 #include "lwip/tcp_impl.h" 00049 #include "lwip/def.h" 00050 #include "lwip/ip_addr.h" 00051 #include "lwip/netif.h" 00052 #include "lwip/mem.h" 00053 #include "lwip/memp.h" 00054 #include "lwip/inet_chksum.h" 00055 #include "lwip/stats.h" 00056 #include "lwip/snmp.h" 00057 #include "arch/perf.h" 00058 00059 /* These variables are global to all functions involved in the input 00060 processing of TCP segments. They are set by the tcp_input() 00061 function. */ 00062 static struct tcp_seg inseg; 00063 static struct tcp_hdr *tcphdr; 00064 static struct ip_hdr *iphdr; 00065 static u32_t seqno, ackno; 00066 static u8_t flags; 00067 static u16_t tcplen; 00068 00069 static u8_t recv_flags; 00070 static struct pbuf *recv_data; 00071 00072 struct tcp_pcb *tcp_input_pcb; 00073 00074 /* Forward declarations. */ 00075 static err_t tcp_process(struct tcp_pcb *pcb); 00076 static void tcp_receive(struct tcp_pcb *pcb); 00077 static void tcp_parseopt(struct tcp_pcb *pcb); 00078 00079 static err_t tcp_listen_input(struct tcp_pcb_listen *pcb); 00080 static err_t tcp_timewait_input(struct tcp_pcb *pcb); 00081 00082 /** 00083 * The initial input processing of TCP. It verifies the TCP header, demultiplexes 00084 * the segment between the PCBs and passes it on to tcp_process(), which implements 00085 * the TCP finite state machine. This function is called by the IP layer (in 00086 * ip_input()). 00087 * 00088 * @param p received TCP segment to process (p->payload pointing to the IP header) 00089 * @param inp network interface on which this segment was received 00090 */ 00091 void 00092 tcp_input(struct pbuf *p, struct netif *inp) 00093 { 00094 struct tcp_pcb *pcb, *prev; 00095 struct tcp_pcb_listen *lpcb; 00096 u8_t hdrlen; 00097 err_t err; 00098 00099 PERF_START; 00100 00101 TCP_STATS_INC(tcp.recv); 00102 snmp_inc_tcpinsegs(); 00103 00104 iphdr = (struct ip_hdr *)p->payload; 00105 tcphdr = (struct tcp_hdr *)((u8_t *)p->payload + IPH_HL(iphdr) * 4); 00106 00107 #if TCP_INPUT_DEBUG 00108 tcp_debug_print(tcphdr); 00109 #endif 00110 00111 /* remove header from payload */ 00112 if (pbuf_header(p, -((s16_t)(IPH_HL(iphdr) * 4))) || (p->tot_len < sizeof(struct tcp_hdr))) { 00113 /* drop short packets */ 00114 LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: short packet (%"U16_F" bytes) discarded\n", p->tot_len)); 00115 TCP_STATS_INC(tcp.lenerr); 00116 TCP_STATS_INC(tcp.drop); 00117 snmp_inc_tcpinerrs(); 00118 pbuf_free(p); 00119 return; 00120 } 00121 00122 /* Don't even process incoming broadcasts/multicasts. */ 00123 if (ip_addr_isbroadcast(&(iphdr->dest), inp) || 00124 ip_addr_ismulticast(&(iphdr->dest))) { 00125 TCP_STATS_INC(tcp.proterr); 00126 TCP_STATS_INC(tcp.drop); 00127 snmp_inc_tcpinerrs(); 00128 pbuf_free(p); 00129 return; 00130 } 00131 00132 #if CHECKSUM_CHECK_TCP 00133 /* Verify TCP checksum. */ 00134 if (inet_chksum_pseudo(p, &iphdr->src, &iphdr->dest, 00135 IP_PROTO_TCP, p->tot_len) != 0) { 00136 LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: packet discarded due to failing checksum 0x%04"X16_F"\n", 00137 inet_chksum_pseudo(p, &iphdr->src, &iphdr->dest, 00138 IP_PROTO_TCP, p->tot_len))); 00139 #if TCP_DEBUG 00140 tcp_debug_print(tcphdr); 00141 #endif /* TCP_DEBUG */ 00142 TCP_STATS_INC(tcp.chkerr); 00143 TCP_STATS_INC(tcp.drop); 00144 snmp_inc_tcpinerrs(); 00145 pbuf_free(p); 00146 return; 00147 } 00148 #endif 00149 00150 /* Move the payload pointer in the pbuf so that it points to the 00151 TCP data instead of the TCP header. */ 00152 hdrlen = TCPH_HDRLEN(tcphdr); 00153 if(pbuf_header(p, -(hdrlen * 4))){ 00154 /* drop short packets */ 00155 LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: short packet\n")); 00156 TCP_STATS_INC(tcp.lenerr); 00157 TCP_STATS_INC(tcp.drop); 00158 snmp_inc_tcpinerrs(); 00159 pbuf_free(p); 00160 return; 00161 } 00162 00163 /* Convert fields in TCP header to host byte order. */ 00164 tcphdr->src = ntohs(tcphdr->src); 00165 tcphdr->dest = ntohs(tcphdr->dest); 00166 seqno = tcphdr->seqno = ntohl(tcphdr->seqno); 00167 ackno = tcphdr->ackno = ntohl(tcphdr->ackno); 00168 tcphdr->wnd = ntohs(tcphdr->wnd); 00169 00170 flags = TCPH_FLAGS(tcphdr); 00171 tcplen = p->tot_len + ((flags & (TCP_FIN | TCP_SYN)) ? 1 : 0); 00172 00173 /* Demultiplex an incoming segment. First, we check if it is destined 00174 for an active connection. */ 00175 prev = NULL; 00176 00177 00178 for(pcb = tcp_active_pcbs; pcb != NULL; pcb = pcb->next) { 00179 LWIP_ASSERT("tcp_input: active pcb->state != CLOSED", pcb->state != CLOSED); 00180 LWIP_ASSERT("tcp_input: active pcb->state != TIME-WAIT", pcb->state != TIME_WAIT); 00181 LWIP_ASSERT("tcp_input: active pcb->state != LISTEN", pcb->state != LISTEN); 00182 if (pcb->remote_port == tcphdr->src && 00183 pcb->local_port == tcphdr->dest && 00184 ip_addr_cmp(&(pcb->remote_ip), &(iphdr->src)) && 00185 ip_addr_cmp(&(pcb->local_ip), &(iphdr->dest))) { 00186 00187 /* Move this PCB to the front of the list so that subsequent 00188 lookups will be faster (we exploit locality in TCP segment 00189 arrivals). */ 00190 LWIP_ASSERT("tcp_input: pcb->next != pcb (before cache)", pcb->next != pcb); 00191 if (prev != NULL) { 00192 prev->next = pcb->next; 00193 pcb->next = tcp_active_pcbs; 00194 tcp_active_pcbs = pcb; 00195 } 00196 LWIP_ASSERT("tcp_input: pcb->next != pcb (after cache)", pcb->next != pcb); 00197 break; 00198 } 00199 prev = pcb; 00200 } 00201 00202 if (pcb == NULL) { 00203 /* If it did not go to an active connection, we check the connections 00204 in the TIME-WAIT state. */ 00205 for(pcb = tcp_tw_pcbs; pcb != NULL; pcb = pcb->next) { 00206 LWIP_ASSERT("tcp_input: TIME-WAIT pcb->state == TIME-WAIT", pcb->state == TIME_WAIT); 00207 if (pcb->remote_port == tcphdr->src && 00208 pcb->local_port == tcphdr->dest && 00209 ip_addr_cmp(&(pcb->remote_ip), &(iphdr->src)) && 00210 ip_addr_cmp(&(pcb->local_ip), &(iphdr->dest))) { 00211 /* We don't really care enough to move this PCB to the front 00212 of the list since we are not very likely to receive that 00213 many segments for connections in TIME-WAIT. */ 00214 LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: packed for TIME_WAITing connection.\n")); 00215 tcp_timewait_input(pcb); 00216 pbuf_free(p); 00217 return; 00218 } 00219 } 00220 00221 /* Finally, if we still did not get a match, we check all PCBs that 00222 are LISTENing for incoming connections. */ 00223 prev = NULL; 00224 for(lpcb = tcp_listen_pcbs.listen_pcbs; lpcb != NULL; lpcb = lpcb->next) { 00225 if ((ip_addr_isany(&(lpcb->local_ip)) || 00226 ip_addr_cmp(&(lpcb->local_ip), &(iphdr->dest))) && 00227 lpcb->local_port == tcphdr->dest) { 00228 /* Move this PCB to the front of the list so that subsequent 00229 lookups will be faster (we exploit locality in TCP segment 00230 arrivals). */ 00231 if (prev != NULL) { 00232 ((struct tcp_pcb_listen *)prev)->next = lpcb->next; 00233 /* our successor is the remainder of the listening list */ 00234 lpcb->next = tcp_listen_pcbs.listen_pcbs; 00235 /* put this listening pcb at the head of the listening list */ 00236 tcp_listen_pcbs.listen_pcbs = lpcb; 00237 } 00238 00239 LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: packed for LISTENing connection.\n")); 00240 tcp_listen_input(lpcb); 00241 pbuf_free(p); 00242 return; 00243 } 00244 prev = (struct tcp_pcb *)lpcb; 00245 } 00246 } 00247 00248 #if TCP_INPUT_DEBUG 00249 LWIP_DEBUGF(TCP_INPUT_DEBUG, ("+-+-+-+-+-+-+-+-+-+-+-+-+-+- tcp_input: flags ")); 00250 tcp_debug_print_flags(TCPH_FLAGS(tcphdr)); 00251 LWIP_DEBUGF(TCP_INPUT_DEBUG, ("-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n")); 00252 #endif /* TCP_INPUT_DEBUG */ 00253 00254 00255 if (pcb != NULL) { 00256 /* The incoming segment belongs to a connection. */ 00257 #if TCP_INPUT_DEBUG 00258 #if TCP_DEBUG 00259 tcp_debug_print_state(pcb->state); 00260 #endif /* TCP_DEBUG */ 00261 #endif /* TCP_INPUT_DEBUG */ 00262 00263 /* Set up a tcp_seg structure. */ 00264 inseg.next = NULL; 00265 inseg.len = p->tot_len; 00266 inseg.dataptr = p->payload; 00267 inseg.p = p; 00268 inseg.tcphdr = tcphdr; 00269 00270 recv_data = NULL; 00271 recv_flags = 0; 00272 00273 /* If there is data which was previously "refused" by upper layer */ 00274 if (pcb->refused_data != NULL) { 00275 /* Notify again application with data previously received. */ 00276 LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: notify kept packet\n")); 00277 TCP_EVENT_RECV(pcb, pcb->refused_data, ERR_OK, err); 00278 if (err == ERR_OK) { 00279 pcb->refused_data = NULL; 00280 } else { 00281 /* if err == ERR_ABRT, 'pcb' is already deallocated */ 00282 /* drop incoming packets, because pcb is "full" */ 00283 LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: drop incoming packets, because pcb is \"full\"\n")); 00284 TCP_STATS_INC(tcp.drop); 00285 snmp_inc_tcpinerrs(); 00286 pbuf_free(p); 00287 return; 00288 } 00289 } 00290 tcp_input_pcb = pcb; 00291 err = tcp_process(pcb); 00292 /* A return value of ERR_ABRT means that tcp_abort() was called 00293 and that the pcb has been freed. If so, we don't do anything. */ 00294 if (err != ERR_ABRT) { 00295 if (recv_flags & TF_RESET) { 00296 /* TF_RESET means that the connection was reset by the other 00297 end. We then call the error callback to inform the 00298 application that the connection is dead before we 00299 deallocate the PCB. */ 00300 TCP_EVENT_ERR(pcb->errf, pcb->callback_arg, ERR_RST); 00301 tcp_pcb_remove(&tcp_active_pcbs, pcb); 00302 memp_free(MEMP_TCP_PCB, pcb); 00303 } else if (recv_flags & TF_CLOSED) { 00304 /* The connection has been closed and we will deallocate the 00305 PCB. */ 00306 tcp_pcb_remove(&tcp_active_pcbs, pcb); 00307 memp_free(MEMP_TCP_PCB, pcb); 00308 } else { 00309 err = ERR_OK; 00310 /* If the application has registered a "sent" function to be 00311 called when new send buffer space is available, we call it 00312 now. */ 00313 if (pcb->acked > 0) { 00314 TCP_EVENT_SENT(pcb, pcb->acked, err); 00315 if (err == ERR_ABRT) { 00316 goto aborted; 00317 } 00318 } 00319 00320 if (recv_data != NULL) { 00321 if(flags & TCP_PSH) { 00322 recv_data->flags |= PBUF_FLAG_PUSH; 00323 } 00324 00325 /* Notify application that data has been received. */ 00326 TCP_EVENT_RECV(pcb, recv_data, ERR_OK, err); 00327 if (err == ERR_ABRT) { 00328 goto aborted; 00329 } 00330 00331 /* If the upper layer can't receive this data, store it */ 00332 if (err != ERR_OK) { 00333 pcb->refused_data = recv_data; 00334 LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: keep incoming packet, because pcb is \"full\"\n")); 00335 } 00336 } 00337 00338 /* If a FIN segment was received, we call the callback 00339 function with a NULL buffer to indicate EOF. */ 00340 if (recv_flags & TF_GOT_FIN) { 00341 /* correct rcv_wnd as the application won't call tcp_recved() 00342 for the FIN's seqno */ 00343 if (pcb->rcv_wnd != TCP_WND) { 00344 pcb->rcv_wnd++; 00345 } 00346 TCP_EVENT_RECV(pcb, NULL, ERR_OK, err); 00347 if (err == ERR_ABRT) { 00348 goto aborted; 00349 } 00350 } 00351 00352 tcp_input_pcb = NULL; 00353 /* Try to send something out. */ 00354 tcp_output(pcb); 00355 #if TCP_INPUT_DEBUG 00356 #if TCP_DEBUG 00357 tcp_debug_print_state(pcb->state); 00358 #endif /* TCP_DEBUG */ 00359 #endif /* TCP_INPUT_DEBUG */ 00360 } 00361 } 00362 /* Jump target if pcb has been aborted in a callback (by calling tcp_abort()). 00363 Below this line, 'pcb' may not be dereferenced! */ 00364 aborted: 00365 tcp_input_pcb = NULL; 00366 00367 00368 /* give up our reference to inseg.p */ 00369 if (inseg.p != NULL) 00370 { 00371 pbuf_free(inseg.p); 00372 inseg.p = NULL; 00373 } 00374 } else { 00375 00376 /* If no matching PCB was found, send a TCP RST (reset) to the 00377 sender. */ 00378 LWIP_DEBUGF(TCP_RST_DEBUG, ("tcp_input: no PCB match found, resetting.\n")); 00379 if (!(TCPH_FLAGS(tcphdr) & TCP_RST)) { 00380 TCP_STATS_INC(tcp.proterr); 00381 TCP_STATS_INC(tcp.drop); 00382 tcp_rst(ackno, seqno + tcplen, 00383 &(iphdr->dest), &(iphdr->src), 00384 tcphdr->dest, tcphdr->src); 00385 } 00386 pbuf_free(p); 00387 } 00388 00389 LWIP_ASSERT("tcp_input: tcp_pcbs_sane()", tcp_pcbs_sane()); 00390 PERF_STOP("tcp_input"); 00391 } 00392 00393 /** 00394 * Called by tcp_input() when a segment arrives for a listening 00395 * connection (from tcp_input()). 00396 * 00397 * @param pcb the tcp_pcb_listen for which a segment arrived 00398 * @return ERR_OK if the segment was processed 00399 * another err_t on error 00400 * 00401 * @note the return value is not (yet?) used in tcp_input() 00402 * @note the segment which arrived is saved in global variables, therefore only the pcb 00403 * involved is passed as a parameter to this function 00404 */ 00405 static err_t 00406 tcp_listen_input(struct tcp_pcb_listen *pcb) 00407 { 00408 struct tcp_pcb *npcb; 00409 err_t rc; 00410 00411 /* In the LISTEN state, we check for incoming SYN segments, 00412 creates a new PCB, and responds with a SYN|ACK. */ 00413 if (flags & TCP_ACK) { 00414 /* For incoming segments with the ACK flag set, respond with a 00415 RST. */ 00416 LWIP_DEBUGF(TCP_RST_DEBUG, ("tcp_listen_input: ACK in LISTEN, sending reset\n")); 00417 tcp_rst(ackno + 1, seqno + tcplen, 00418 &(iphdr->dest), &(iphdr->src), 00419 tcphdr->dest, tcphdr->src); 00420 } else if (flags & TCP_SYN) { 00421 LWIP_DEBUGF(TCP_DEBUG, ("TCP connection request %"U16_F" -> %"U16_F".\n", tcphdr->src, tcphdr->dest)); 00422 #if TCP_LISTEN_BACKLOG 00423 if (pcb->accepts_pending >= pcb->backlog) { 00424 LWIP_DEBUGF(TCP_DEBUG, ("tcp_listen_input: listen backlog exceeded for port %"U16_F"\n", tcphdr->dest)); 00425 return ERR_ABRT; 00426 } 00427 #endif /* TCP_LISTEN_BACKLOG */ 00428 npcb = tcp_alloc(pcb->prio); 00429 /* If a new PCB could not be created (probably due to lack of memory), 00430 we don't do anything, but rely on the sender will retransmit the 00431 SYN at a time when we have more memory available. */ 00432 if (npcb == NULL) { 00433 LWIP_DEBUGF(TCP_DEBUG, ("tcp_listen_input: could not allocate PCB\n")); 00434 TCP_STATS_INC(tcp.memerr); 00435 return ERR_MEM; 00436 } 00437 #if TCP_LISTEN_BACKLOG 00438 pcb->accepts_pending++; 00439 #endif /* TCP_LISTEN_BACKLOG */ 00440 /* Set up the new PCB. */ 00441 ip_addr_copy(npcb->local_ip, iphdr->dest); 00442 npcb->local_port = pcb->local_port; 00443 ip_addr_copy(npcb->remote_ip, iphdr->src); 00444 npcb->remote_port = tcphdr->src; 00445 npcb->state = SYN_RCVD; 00446 npcb->rcv_nxt = seqno + 1; 00447 npcb->rcv_ann_right_edge = npcb->rcv_nxt; 00448 npcb->snd_wnd = tcphdr->wnd; 00449 npcb->ssthresh = npcb->snd_wnd; 00450 npcb->snd_wl1 = seqno - 1;/* initialise to seqno-1 to force window update */ 00451 npcb->callback_arg = pcb->callback_arg; 00452 #if LWIP_CALLBACK_API 00453 npcb->accept = pcb->accept; 00454 #endif /* LWIP_CALLBACK_API */ 00455 /* inherit socket options */ 00456 npcb->so_options = pcb->so_options & (SOF_DEBUG|SOF_DONTROUTE|SOF_KEEPALIVE|SOF_OOBINLINE|SOF_LINGER); 00457 /* Register the new PCB so that we can begin receiving segments 00458 for it. */ 00459 TCP_REG(&tcp_active_pcbs, npcb); 00460 00461 /* Parse any options in the SYN. */ 00462 tcp_parseopt(npcb); 00463 #if TCP_CALCULATE_EFF_SEND_MSS 00464 npcb->mss = tcp_eff_send_mss(npcb->mss, &(npcb->remote_ip)); 00465 #endif /* TCP_CALCULATE_EFF_SEND_MSS */ 00466 00467 snmp_inc_tcppassiveopens(); 00468 00469 /* Send a SYN|ACK together with the MSS option. */ 00470 rc = tcp_enqueue_flags(npcb, TCP_SYN | TCP_ACK); 00471 if (rc != ERR_OK) { 00472 tcp_abandon(npcb, 0); 00473 return rc; 00474 } 00475 return tcp_output(npcb); 00476 } 00477 return ERR_OK; 00478 } 00479 00480 /** 00481 * Called by tcp_input() when a segment arrives for a connection in 00482 * TIME_WAIT. 00483 * 00484 * @param pcb the tcp_pcb for which a segment arrived 00485 * 00486 * @note the segment which arrived is saved in global variables, therefore only the pcb 00487 * involved is passed as a parameter to this function 00488 */ 00489 static err_t 00490 tcp_timewait_input(struct tcp_pcb *pcb) 00491 { 00492 /* RFC 1337: in TIME_WAIT, ignore RST and ACK FINs + any 'acceptable' segments */ 00493 /* RFC 793 3.9 Event Processing - Segment Arrives: 00494 * - first check sequence number - we skip that one in TIME_WAIT (always 00495 * acceptable since we only send ACKs) 00496 * - second check the RST bit (... return) */ 00497 if (flags & TCP_RST) { 00498 return ERR_OK; 00499 } 00500 /* - fourth, check the SYN bit, */ 00501 if (flags & TCP_SYN) { 00502 /* If an incoming segment is not acceptable, an acknowledgment 00503 should be sent in reply */ 00504 if (TCP_SEQ_BETWEEN(seqno, pcb->rcv_nxt, pcb->rcv_nxt+pcb->rcv_wnd)) { 00505 /* If the SYN is in the window it is an error, send a reset */ 00506 tcp_rst(ackno, seqno + tcplen, &(iphdr->dest), &(iphdr->src), 00507 tcphdr->dest, tcphdr->src); 00508 return ERR_OK; 00509 } 00510 } else if (flags & TCP_FIN) { 00511 /* - eighth, check the FIN bit: Remain in the TIME-WAIT state. 00512 Restart the 2 MSL time-wait timeout.*/ 00513 pcb->tmr = tcp_ticks; 00514 } 00515 00516 if ((tcplen > 0)) { 00517 /* Acknowledge data, FIN or out-of-window SYN */ 00518 pcb->flags |= TF_ACK_NOW; 00519 return tcp_output(pcb); 00520 } 00521 return ERR_OK; 00522 } 00523 00524 /** 00525 * Implements the TCP state machine. Called by tcp_input. In some 00526 * states tcp_receive() is called to receive data. The tcp_seg 00527 * argument will be freed by the caller (tcp_input()) unless the 00528 * recv_data pointer in the pcb is set. 00529 * 00530 * @param pcb the tcp_pcb for which a segment arrived 00531 * 00532 * @note the segment which arrived is saved in global variables, therefore only the pcb 00533 * involved is passed as a parameter to this function 00534 */ 00535 static err_t 00536 tcp_process(struct tcp_pcb *pcb) 00537 { 00538 struct tcp_seg *rseg; 00539 u8_t acceptable = 0; 00540 err_t err; 00541 00542 err = ERR_OK; 00543 00544 /* Process incoming RST segments. */ 00545 if (flags & TCP_RST) { 00546 /* First, determine if the reset is acceptable. */ 00547 if (pcb->state == SYN_SENT) { 00548 if (ackno == pcb->snd_nxt) { 00549 acceptable = 1; 00550 } 00551 } else { 00552 if (TCP_SEQ_BETWEEN(seqno, pcb->rcv_nxt, 00553 pcb->rcv_nxt+pcb->rcv_wnd)) { 00554 acceptable = 1; 00555 } 00556 } 00557 00558 if (acceptable) { 00559 LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_process: Connection RESET\n")); 00560 LWIP_ASSERT("tcp_input: pcb->state != CLOSED", pcb->state != CLOSED); 00561 recv_flags |= TF_RESET; 00562 pcb->flags &= ~TF_ACK_DELAY; 00563 return ERR_RST; 00564 } else { 00565 LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_process: unacceptable reset seqno %"U32_F" rcv_nxt %"U32_F"\n", 00566 seqno, pcb->rcv_nxt)); 00567 LWIP_DEBUGF(TCP_DEBUG, ("tcp_process: unacceptable reset seqno %"U32_F" rcv_nxt %"U32_F"\n", 00568 seqno, pcb->rcv_nxt)); 00569 return ERR_OK; 00570 } 00571 } 00572 00573 if ((flags & TCP_SYN) && (pcb->state != SYN_SENT && pcb->state != SYN_RCVD)) { 00574 /* Cope with new connection attempt after remote end crashed */ 00575 tcp_ack_now(pcb); 00576 return ERR_OK; 00577 } 00578 00579 if ((pcb->flags & TF_RXCLOSED) == 0) { 00580 /* Update the PCB (in)activity timer unless rx is closed (see tcp_shutdown) */ 00581 pcb->tmr = tcp_ticks; 00582 } 00583 pcb->keep_cnt_sent = 0; 00584 00585 tcp_parseopt(pcb); 00586 00587 /* Do different things depending on the TCP state. */ 00588 switch (pcb->state) { 00589 case SYN_SENT: 00590 LWIP_DEBUGF(TCP_INPUT_DEBUG, ("SYN-SENT: ackno %"U32_F" pcb->snd_nxt %"U32_F" unacked %"U32_F"\n", ackno, 00591 pcb->snd_nxt, ntohl(pcb->unacked->tcphdr->seqno))); 00592 /* received SYN ACK with expected sequence number? */ 00593 if ((flags & TCP_ACK) && (flags & TCP_SYN) 00594 && ackno == ntohl(pcb->unacked->tcphdr->seqno) + 1) { 00595 pcb->snd_buf++; 00596 pcb->rcv_nxt = seqno + 1; 00597 pcb->rcv_ann_right_edge = pcb->rcv_nxt; 00598 pcb->lastack = ackno; 00599 pcb->snd_wnd = tcphdr->wnd; 00600 pcb->snd_wl1 = seqno - 1; /* initialise to seqno - 1 to force window update */ 00601 pcb->state = ESTABLISHED; 00602 00603 #if TCP_CALCULATE_EFF_SEND_MSS 00604 pcb->mss = tcp_eff_send_mss(pcb->mss, &(pcb->remote_ip)); 00605 #endif /* TCP_CALCULATE_EFF_SEND_MSS */ 00606 00607 /* Set ssthresh again after changing pcb->mss (already set in tcp_connect 00608 * but for the default value of pcb->mss) */ 00609 pcb->ssthresh = pcb->mss * 10; 00610 00611 pcb->cwnd = ((pcb->cwnd == 1) ? (pcb->mss * 2) : pcb->mss); 00612 LWIP_ASSERT("pcb->snd_queuelen > 0", (pcb->snd_queuelen > 0)); 00613 --pcb->snd_queuelen; 00614 LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_process: SYN-SENT --queuelen %"U16_F"\n", (u16_t)pcb->snd_queuelen)); 00615 rseg = pcb->unacked; 00616 pcb->unacked = rseg->next; 00617 00618 /* If there's nothing left to acknowledge, stop the retransmit 00619 timer, otherwise reset it to start again */ 00620 if(pcb->unacked == NULL) 00621 pcb->rtime = -1; 00622 else { 00623 pcb->rtime = 0; 00624 pcb->nrtx = 0; 00625 } 00626 00627 tcp_seg_free(rseg); 00628 00629 /* Call the user specified function to call when sucessfully 00630 * connected. */ 00631 TCP_EVENT_CONNECTED(pcb, ERR_OK, err); 00632 if (err == ERR_ABRT) { 00633 return ERR_ABRT; 00634 } 00635 tcp_ack_now(pcb); 00636 } 00637 /* received ACK? possibly a half-open connection */ 00638 else if (flags & TCP_ACK) { 00639 /* send a RST to bring the other side in a non-synchronized state. */ 00640 tcp_rst(ackno, seqno + tcplen, &(iphdr->dest), &(iphdr->src), 00641 tcphdr->dest, tcphdr->src); 00642 } 00643 break; 00644 case SYN_RCVD: 00645 if (flags & TCP_ACK) { 00646 /* expected ACK number? */ 00647 if (TCP_SEQ_BETWEEN(ackno, pcb->lastack+1, pcb->snd_nxt)) { 00648 u16_t old_cwnd; 00649 pcb->state = ESTABLISHED; 00650 LWIP_DEBUGF(TCP_DEBUG, ("TCP connection established %"U16_F" -> %"U16_F".\n", inseg.tcphdr->src, inseg.tcphdr->dest)); 00651 #if LWIP_CALLBACK_API 00652 LWIP_ASSERT("pcb->accept != NULL", pcb->accept != NULL); 00653 #endif 00654 /* Call the accept function. */ 00655 TCP_EVENT_ACCEPT(pcb, ERR_OK, err); 00656 if (err != ERR_OK) { 00657 /* If the accept function returns with an error, we abort 00658 * the connection. */ 00659 /* Already aborted? */ 00660 if (err != ERR_ABRT) { 00661 tcp_abort(pcb); 00662 } 00663 return ERR_ABRT; 00664 } 00665 old_cwnd = pcb->cwnd; 00666 /* If there was any data contained within this ACK, 00667 * we'd better pass it on to the application as well. */ 00668 tcp_receive(pcb); 00669 00670 /* Prevent ACK for SYN to generate a sent event */ 00671 if (pcb->acked != 0) { 00672 pcb->acked--; 00673 } 00674 00675 pcb->cwnd = ((old_cwnd == 1) ? (pcb->mss * 2) : pcb->mss); 00676 00677 if (recv_flags & TF_GOT_FIN) { 00678 tcp_ack_now(pcb); 00679 pcb->state = CLOSE_WAIT; 00680 } 00681 } else { 00682 /* incorrect ACK number, send RST */ 00683 tcp_rst(ackno, seqno + tcplen, &(iphdr->dest), &(iphdr->src), 00684 tcphdr->dest, tcphdr->src); 00685 } 00686 } else if ((flags & TCP_SYN) && (seqno == pcb->rcv_nxt - 1)) { 00687 /* Looks like another copy of the SYN - retransmit our SYN-ACK */ 00688 tcp_rexmit(pcb); 00689 } 00690 break; 00691 case CLOSE_WAIT: 00692 /* FALLTHROUGH */ 00693 case ESTABLISHED: 00694 tcp_receive(pcb); 00695 if (recv_flags & TF_GOT_FIN) { /* passive close */ 00696 tcp_ack_now(pcb); 00697 pcb->state = CLOSE_WAIT; 00698 } 00699 break; 00700 case FIN_WAIT_1: 00701 tcp_receive(pcb); 00702 if (recv_flags & TF_GOT_FIN) { 00703 if ((flags & TCP_ACK) && (ackno == pcb->snd_nxt)) { 00704 LWIP_DEBUGF(TCP_DEBUG, 00705 ("TCP connection closed: FIN_WAIT_1 %"U16_F" -> %"U16_F".\n", inseg.tcphdr->src, inseg.tcphdr->dest)); 00706 tcp_ack_now(pcb); 00707 tcp_pcb_purge(pcb); 00708 TCP_RMV(&tcp_active_pcbs, pcb); 00709 pcb->state = TIME_WAIT; 00710 TCP_REG(&tcp_tw_pcbs, pcb); 00711 } else { 00712 tcp_ack_now(pcb); 00713 pcb->state = CLOSING; 00714 } 00715 } else if ((flags & TCP_ACK) && (ackno == pcb->snd_nxt)) { 00716 pcb->state = FIN_WAIT_2; 00717 } 00718 break; 00719 case FIN_WAIT_2: 00720 tcp_receive(pcb); 00721 if (recv_flags & TF_GOT_FIN) { 00722 LWIP_DEBUGF(TCP_DEBUG, ("TCP connection closed: FIN_WAIT_2 %"U16_F" -> %"U16_F".\n", inseg.tcphdr->src, inseg.tcphdr->dest)); 00723 tcp_ack_now(pcb); 00724 tcp_pcb_purge(pcb); 00725 TCP_RMV(&tcp_active_pcbs, pcb); 00726 pcb->state = TIME_WAIT; 00727 TCP_REG(&tcp_tw_pcbs, pcb); 00728 } 00729 break; 00730 case CLOSING: 00731 tcp_receive(pcb); 00732 if (flags & TCP_ACK && ackno == pcb->snd_nxt) { 00733 LWIP_DEBUGF(TCP_DEBUG, ("TCP connection closed: CLOSING %"U16_F" -> %"U16_F".\n", inseg.tcphdr->src, inseg.tcphdr->dest)); 00734 tcp_pcb_purge(pcb); 00735 TCP_RMV(&tcp_active_pcbs, pcb); 00736 pcb->state = TIME_WAIT; 00737 TCP_REG(&tcp_tw_pcbs, pcb); 00738 } 00739 break; 00740 case LAST_ACK: 00741 tcp_receive(pcb); 00742 if (flags & TCP_ACK && ackno == pcb->snd_nxt) { 00743 LWIP_DEBUGF(TCP_DEBUG, ("TCP connection closed: LAST_ACK %"U16_F" -> %"U16_F".\n", inseg.tcphdr->src, inseg.tcphdr->dest)); 00744 /* bugfix #21699: don't set pcb->state to CLOSED here or we risk leaking segments */ 00745 recv_flags |= TF_CLOSED; 00746 } 00747 break; 00748 default: 00749 break; 00750 } 00751 return ERR_OK; 00752 } 00753 00754 #if TCP_QUEUE_OOSEQ 00755 /** 00756 * Insert segment into the list (segments covered with new one will be deleted) 00757 * 00758 * Called from tcp_receive() 00759 */ 00760 static void 00761 tcp_oos_insert_segment(struct tcp_seg *cseg, struct tcp_seg *next) 00762 { 00763 struct tcp_seg *old_seg; 00764 00765 if (TCPH_FLAGS(cseg->tcphdr) & TCP_FIN) { 00766 /* received segment overlaps all following segments */ 00767 tcp_segs_free(next); 00768 next = NULL; 00769 } 00770 else { 00771 /* delete some following segments 00772 oos queue may have segments with FIN flag */ 00773 while (next && 00774 TCP_SEQ_GEQ((seqno + cseg->len), 00775 (next->tcphdr->seqno + next->len))) { 00776 /* cseg with FIN already processed */ 00777 if (TCPH_FLAGS(next->tcphdr) & TCP_FIN) { 00778 TCPH_SET_FLAG(cseg->tcphdr, TCP_FIN); 00779 } 00780 old_seg = next; 00781 next = next->next; 00782 tcp_seg_free(old_seg); 00783 } 00784 if (next && 00785 TCP_SEQ_GT(seqno + cseg->len, next->tcphdr->seqno)) { 00786 /* We need to trim the incoming segment. */ 00787 cseg->len = (u16_t)(next->tcphdr->seqno - seqno); 00788 pbuf_realloc(cseg->p, cseg->len); 00789 } 00790 } 00791 cseg->next = next; 00792 } 00793 #endif /* TCP_QUEUE_OOSEQ */ 00794 00795 /** 00796 * Called by tcp_process. Checks if the given segment is an ACK for outstanding 00797 * data, and if so frees the memory of the buffered data. Next, is places the 00798 * segment on any of the receive queues (pcb->recved or pcb->ooseq). If the segment 00799 * is buffered, the pbuf is referenced by pbuf_ref so that it will not be freed until 00800 * i it has been removed from the buffer. 00801 * 00802 * If the incoming segment constitutes an ACK for a segment that was used for RTT 00803 * estimation, the RTT is estimated here as well. 00804 * 00805 * Called from tcp_process(). 00806 */ 00807 static void 00808 tcp_receive(struct tcp_pcb *pcb) 00809 { 00810 struct tcp_seg *next; 00811 #if TCP_QUEUE_OOSEQ 00812 struct tcp_seg *prev, *cseg; 00813 #endif /* TCP_QUEUE_OOSEQ */ 00814 struct pbuf *p; 00815 s32_t off; 00816 s16_t m; 00817 u32_t right_wnd_edge; 00818 u16_t new_tot_len; 00819 int found_dupack = 0; 00820 00821 if (flags & TCP_ACK) { 00822 right_wnd_edge = pcb->snd_wnd + pcb->snd_wl2; 00823 00824 /* Update window. */ 00825 if (TCP_SEQ_LT(pcb->snd_wl1, seqno) || 00826 (pcb->snd_wl1 == seqno && TCP_SEQ_LT(pcb->snd_wl2, ackno)) || 00827 (pcb->snd_wl2 == ackno && tcphdr->wnd > pcb->snd_wnd)) { 00828 pcb->snd_wnd = tcphdr->wnd; 00829 pcb->snd_wl1 = seqno; 00830 pcb->snd_wl2 = ackno; 00831 if (pcb->snd_wnd > 0 && pcb->persist_backoff > 0) { 00832 pcb->persist_backoff = 0; 00833 } 00834 LWIP_DEBUGF(TCP_WND_DEBUG, ("tcp_receive: window update %"U16_F"\n", pcb->snd_wnd)); 00835 #if TCP_WND_DEBUG 00836 } else { 00837 if (pcb->snd_wnd != tcphdr->wnd) { 00838 LWIP_DEBUGF(TCP_WND_DEBUG, 00839 ("tcp_receive: no window update lastack %"U32_F" ackno %" 00840 U32_F" wl1 %"U32_F" seqno %"U32_F" wl2 %"U32_F"\n", 00841 pcb->lastack, ackno, pcb->snd_wl1, seqno, pcb->snd_wl2)); 00842 } 00843 #endif /* TCP_WND_DEBUG */ 00844 } 00845 00846 /* (From Stevens TCP/IP Illustrated Vol II, p970.) Its only a 00847 * duplicate ack if: 00848 * 1) It doesn't ACK new data 00849 * 2) length of received packet is zero (i.e. no payload) 00850 * 3) the advertised window hasn't changed 00851 * 4) There is outstanding unacknowledged data (retransmission timer running) 00852 * 5) The ACK is == biggest ACK sequence number so far seen (snd_una) 00853 * 00854 * If it passes all five, should process as a dupack: 00855 * a) dupacks < 3: do nothing 00856 * b) dupacks == 3: fast retransmit 00857 * c) dupacks > 3: increase cwnd 00858 * 00859 * If it only passes 1-3, should reset dupack counter (and add to 00860 * stats, which we don't do in lwIP) 00861 * 00862 * If it only passes 1, should reset dupack counter 00863 * 00864 */ 00865 00866 /* Clause 1 */ 00867 if (TCP_SEQ_LEQ(ackno, pcb->lastack)) { 00868 pcb->acked = 0; 00869 /* Clause 2 */ 00870 if (tcplen == 0) { 00871 /* Clause 3 */ 00872 if (pcb->snd_wl2 + pcb->snd_wnd == right_wnd_edge){ 00873 /* Clause 4 */ 00874 if (pcb->rtime >= 0) { 00875 /* Clause 5 */ 00876 if (pcb->lastack == ackno) { 00877 found_dupack = 1; 00878 if (pcb->dupacks + 1 > pcb->dupacks) 00879 ++pcb->dupacks; 00880 if (pcb->dupacks > 3) { 00881 /* Inflate the congestion window, but not if it means that 00882 the value overflows. */ 00883 if ((u16_t)(pcb->cwnd + pcb->mss) > pcb->cwnd) { 00884 pcb->cwnd += pcb->mss; 00885 } 00886 } else if (pcb->dupacks == 3) { 00887 /* Do fast retransmit */ 00888 tcp_rexmit_fast(pcb); 00889 } 00890 } 00891 } 00892 } 00893 } 00894 /* If Clause (1) or more is true, but not a duplicate ack, reset 00895 * count of consecutive duplicate acks */ 00896 if (!found_dupack) { 00897 pcb->dupacks = 0; 00898 } 00899 } else if (TCP_SEQ_BETWEEN(ackno, pcb->lastack+1, pcb->snd_nxt)){ 00900 /* We come here when the ACK acknowledges new data. */ 00901 00902 /* Reset the "IN Fast Retransmit" flag, since we are no longer 00903 in fast retransmit. Also reset the congestion window to the 00904 slow start threshold. */ 00905 if (pcb->flags & TF_INFR) { 00906 pcb->flags &= ~TF_INFR; 00907 pcb->cwnd = pcb->ssthresh; 00908 } 00909 00910 /* Reset the number of retransmissions. */ 00911 pcb->nrtx = 0; 00912 00913 /* Reset the retransmission time-out. */ 00914 pcb->rto = (pcb->sa >> 3) + pcb->sv; 00915 00916 /* Update the send buffer space. Diff between the two can never exceed 64K? */ 00917 pcb->acked = (u16_t)(ackno - pcb->lastack); 00918 00919 pcb->snd_buf += pcb->acked; 00920 00921 /* Reset the fast retransmit variables. */ 00922 pcb->dupacks = 0; 00923 pcb->lastack = ackno; 00924 00925 /* Update the congestion control variables (cwnd and 00926 ssthresh). */ 00927 if (pcb->state >= ESTABLISHED) { 00928 if (pcb->cwnd < pcb->ssthresh) { 00929 if ((u16_t)(pcb->cwnd + pcb->mss) > pcb->cwnd) { 00930 pcb->cwnd += pcb->mss; 00931 } 00932 LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_receive: slow start cwnd %"U16_F"\n", pcb->cwnd)); 00933 } else { 00934 u16_t new_cwnd = (pcb->cwnd + pcb->mss * pcb->mss / pcb->cwnd); 00935 if (new_cwnd > pcb->cwnd) { 00936 pcb->cwnd = new_cwnd; 00937 } 00938 LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_receive: congestion avoidance cwnd %"U16_F"\n", pcb->cwnd)); 00939 } 00940 } 00941 LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: ACK for %"U32_F", unacked->seqno %"U32_F":%"U32_F"\n", 00942 ackno, 00943 pcb->unacked != NULL? 00944 ntohl(pcb->unacked->tcphdr->seqno): 0, 00945 pcb->unacked != NULL? 00946 ntohl(pcb->unacked->tcphdr->seqno) + TCP_TCPLEN(pcb->unacked): 0)); 00947 00948 /* Remove segment from the unacknowledged list if the incoming 00949 ACK acknowlegdes them. */ 00950 while (pcb->unacked != NULL && 00951 TCP_SEQ_LEQ(ntohl(pcb->unacked->tcphdr->seqno) + 00952 TCP_TCPLEN(pcb->unacked), ackno)) { 00953 LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: removing %"U32_F":%"U32_F" from pcb->unacked\n", 00954 ntohl(pcb->unacked->tcphdr->seqno), 00955 ntohl(pcb->unacked->tcphdr->seqno) + 00956 TCP_TCPLEN(pcb->unacked))); 00957 00958 next = pcb->unacked; 00959 pcb->unacked = pcb->unacked->next; 00960 00961 LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_receive: queuelen %"U16_F" ... ", (u16_t)pcb->snd_queuelen)); 00962 LWIP_ASSERT("pcb->snd_queuelen >= pbuf_clen(next->p)", (pcb->snd_queuelen >= pbuf_clen(next->p))); 00963 /* Prevent ACK for FIN to generate a sent event */ 00964 if ((pcb->acked != 0) && ((TCPH_FLAGS(next->tcphdr) & TCP_FIN) != 0)) { 00965 pcb->acked--; 00966 } 00967 00968 pcb->snd_queuelen -= pbuf_clen(next->p); 00969 tcp_seg_free(next); 00970 00971 LWIP_DEBUGF(TCP_QLEN_DEBUG, ("%"U16_F" (after freeing unacked)\n", (u16_t)pcb->snd_queuelen)); 00972 if (pcb->snd_queuelen != 0) { 00973 LWIP_ASSERT("tcp_receive: valid queue length", pcb->unacked != NULL || 00974 pcb->unsent != NULL); 00975 } 00976 } 00977 00978 /* If there's nothing left to acknowledge, stop the retransmit 00979 timer, otherwise reset it to start again */ 00980 if(pcb->unacked == NULL) 00981 pcb->rtime = -1; 00982 else 00983 pcb->rtime = 0; 00984 00985 pcb->polltmr = 0; 00986 } else { 00987 /* Fix bug bug #21582: out of sequence ACK, didn't really ack anything */ 00988 pcb->acked = 0; 00989 } 00990 00991 /* We go through the ->unsent list to see if any of the segments 00992 on the list are acknowledged by the ACK. This may seem 00993 strange since an "unsent" segment shouldn't be acked. The 00994 rationale is that lwIP puts all outstanding segments on the 00995 ->unsent list after a retransmission, so these segments may 00996 in fact have been sent once. */ 00997 while (pcb->unsent != NULL && 00998 TCP_SEQ_BETWEEN(ackno, ntohl(pcb->unsent->tcphdr->seqno) + 00999 TCP_TCPLEN(pcb->unsent), pcb->snd_nxt)) { 01000 LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: removing %"U32_F":%"U32_F" from pcb->unsent\n", 01001 ntohl(pcb->unsent->tcphdr->seqno), ntohl(pcb->unsent->tcphdr->seqno) + 01002 TCP_TCPLEN(pcb->unsent))); 01003 01004 next = pcb->unsent; 01005 pcb->unsent = pcb->unsent->next; 01006 LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_receive: queuelen %"U16_F" ... ", (u16_t)pcb->snd_queuelen)); 01007 LWIP_ASSERT("pcb->snd_queuelen >= pbuf_clen(next->p)", (pcb->snd_queuelen >= pbuf_clen(next->p))); 01008 /* Prevent ACK for FIN to generate a sent event */ 01009 if ((pcb->acked != 0) && ((TCPH_FLAGS(next->tcphdr) & TCP_FIN) != 0)) { 01010 pcb->acked--; 01011 } 01012 pcb->snd_queuelen -= pbuf_clen(next->p); 01013 tcp_seg_free(next); 01014 LWIP_DEBUGF(TCP_QLEN_DEBUG, ("%"U16_F" (after freeing unsent)\n", (u16_t)pcb->snd_queuelen)); 01015 if (pcb->snd_queuelen != 0) { 01016 LWIP_ASSERT("tcp_receive: valid queue length", 01017 pcb->unacked != NULL || pcb->unsent != NULL); 01018 } 01019 } 01020 /* End of ACK for new data processing. */ 01021 01022 LWIP_DEBUGF(TCP_RTO_DEBUG, ("tcp_receive: pcb->rttest %"U32_F" rtseq %"U32_F" ackno %"U32_F"\n", 01023 pcb->rttest, pcb->rtseq, ackno)); 01024 01025 /* RTT estimation calculations. This is done by checking if the 01026 incoming segment acknowledges the segment we use to take a 01027 round-trip time measurement. */ 01028 if (pcb->rttest && TCP_SEQ_LT(pcb->rtseq, ackno)) { 01029 /* diff between this shouldn't exceed 32K since this are tcp timer ticks 01030 and a round-trip shouldn't be that long... */ 01031 m = (s16_t)(tcp_ticks - pcb->rttest); 01032 01033 LWIP_DEBUGF(TCP_RTO_DEBUG, ("tcp_receive: experienced rtt %"U16_F" ticks (%"U16_F" msec).\n", 01034 m, m * TCP_SLOW_INTERVAL)); 01035 01036 /* This is taken directly from VJs original code in his paper */ 01037 m = m - (pcb->sa >> 3); 01038 pcb->sa += m; 01039 if (m < 0) { 01040 m = -m; 01041 } 01042 m = m - (pcb->sv >> 2); 01043 pcb->sv += m; 01044 pcb->rto = (pcb->sa >> 3) + pcb->sv; 01045 01046 LWIP_DEBUGF(TCP_RTO_DEBUG, ("tcp_receive: RTO %"U16_F" (%"U16_F" milliseconds)\n", 01047 pcb->rto, pcb->rto * TCP_SLOW_INTERVAL)); 01048 01049 pcb->rttest = 0; 01050 } 01051 } 01052 01053 /* If the incoming segment contains data, we must process it 01054 further. */ 01055 if (tcplen > 0) { 01056 /* This code basically does three things: 01057 01058 +) If the incoming segment contains data that is the next 01059 in-sequence data, this data is passed to the application. This 01060 might involve trimming the first edge of the data. The rcv_nxt 01061 variable and the advertised window are adjusted. 01062 01063 +) If the incoming segment has data that is above the next 01064 sequence number expected (->rcv_nxt), the segment is placed on 01065 the ->ooseq queue. This is done by finding the appropriate 01066 place in the ->ooseq queue (which is ordered by sequence 01067 number) and trim the segment in both ends if needed. An 01068 immediate ACK is sent to indicate that we received an 01069 out-of-sequence segment. 01070 01071 +) Finally, we check if the first segment on the ->ooseq queue 01072 now is in sequence (i.e., if rcv_nxt >= ooseq->seqno). If 01073 rcv_nxt > ooseq->seqno, we must trim the first edge of the 01074 segment on ->ooseq before we adjust rcv_nxt. The data in the 01075 segments that are now on sequence are chained onto the 01076 incoming segment so that we only need to call the application 01077 once. 01078 */ 01079 01080 /* First, we check if we must trim the first edge. We have to do 01081 this if the sequence number of the incoming segment is less 01082 than rcv_nxt, and the sequence number plus the length of the 01083 segment is larger than rcv_nxt. */ 01084 /* if (TCP_SEQ_LT(seqno, pcb->rcv_nxt)){ 01085 if (TCP_SEQ_LT(pcb->rcv_nxt, seqno + tcplen)) {*/ 01086 if (TCP_SEQ_BETWEEN(pcb->rcv_nxt, seqno + 1, seqno + tcplen - 1)){ 01087 /* Trimming the first edge is done by pushing the payload 01088 pointer in the pbuf downwards. This is somewhat tricky since 01089 we do not want to discard the full contents of the pbuf up to 01090 the new starting point of the data since we have to keep the 01091 TCP header which is present in the first pbuf in the chain. 01092 01093 What is done is really quite a nasty hack: the first pbuf in 01094 the pbuf chain is pointed to by inseg.p. Since we need to be 01095 able to deallocate the whole pbuf, we cannot change this 01096 inseg.p pointer to point to any of the later pbufs in the 01097 chain. Instead, we point the ->payload pointer in the first 01098 pbuf to data in one of the later pbufs. We also set the 01099 inseg.data pointer to point to the right place. This way, the 01100 ->p pointer will still point to the first pbuf, but the 01101 ->p->payload pointer will point to data in another pbuf. 01102 01103 After we are done with adjusting the pbuf pointers we must 01104 adjust the ->data pointer in the seg and the segment 01105 length.*/ 01106 01107 off = pcb->rcv_nxt - seqno; 01108 p = inseg.p; 01109 LWIP_ASSERT("inseg.p != NULL", inseg.p); 01110 LWIP_ASSERT("insane offset!", (off < 0x7fff)); 01111 if (inseg.p->len < off) { 01112 LWIP_ASSERT("pbuf too short!", (((s32_t)inseg.p->tot_len) >= off)); 01113 new_tot_len = (u16_t)(inseg.p->tot_len - off); 01114 while (p->len < off) { 01115 off -= p->len; 01116 /* KJM following line changed (with addition of new_tot_len var) 01117 to fix bug #9076 01118 inseg.p->tot_len -= p->len; */ 01119 p->tot_len = new_tot_len; 01120 p->len = 0; 01121 p = p->next; 01122 } 01123 if(pbuf_header(p, (s16_t)-off)) { 01124 /* Do we need to cope with this failing? Assert for now */ 01125 LWIP_ASSERT("pbuf_header failed", 0); 01126 } 01127 } else { 01128 if(pbuf_header(inseg.p, (s16_t)-off)) { 01129 /* Do we need to cope with this failing? Assert for now */ 01130 LWIP_ASSERT("pbuf_header failed", 0); 01131 } 01132 } 01133 /* KJM following line changed to use p->payload rather than inseg->p->payload 01134 to fix bug #9076 */ 01135 inseg.dataptr = p->payload; 01136 inseg.len -= (u16_t)(pcb->rcv_nxt - seqno); 01137 inseg.tcphdr->seqno = seqno = pcb->rcv_nxt; 01138 } 01139 else { 01140 if (TCP_SEQ_LT(seqno, pcb->rcv_nxt)){ 01141 /* the whole segment is < rcv_nxt */ 01142 /* must be a duplicate of a packet that has already been correctly handled */ 01143 01144 LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: duplicate seqno %"U32_F"\n", seqno)); 01145 tcp_ack_now(pcb); 01146 } 01147 } 01148 01149 /* The sequence number must be within the window (above rcv_nxt 01150 and below rcv_nxt + rcv_wnd) in order to be further 01151 processed. */ 01152 if (TCP_SEQ_BETWEEN(seqno, pcb->rcv_nxt, 01153 pcb->rcv_nxt + pcb->rcv_wnd - 1)){ 01154 if (pcb->rcv_nxt == seqno) { 01155 /* The incoming segment is the next in sequence. We check if 01156 we have to trim the end of the segment and update rcv_nxt 01157 and pass the data to the application. */ 01158 tcplen = TCP_TCPLEN(&inseg); 01159 01160 if (tcplen > pcb->rcv_wnd) { 01161 LWIP_DEBUGF(TCP_INPUT_DEBUG, 01162 ("tcp_receive: other end overran receive window" 01163 "seqno %"U32_F" len %"U16_F" right edge %"U32_F"\n", 01164 seqno, tcplen, pcb->rcv_nxt + pcb->rcv_wnd)); 01165 if (TCPH_FLAGS(inseg.tcphdr) & TCP_FIN) { 01166 /* Must remove the FIN from the header as we're trimming 01167 * that byte of sequence-space from the packet */ 01168 TCPH_FLAGS_SET(inseg.tcphdr, TCPH_FLAGS(inseg.tcphdr) &~ TCP_FIN); 01169 } 01170 /* Adjust length of segment to fit in the window. */ 01171 inseg.len = pcb->rcv_wnd; 01172 if (TCPH_FLAGS(inseg.tcphdr) & TCP_SYN) { 01173 inseg.len -= 1; 01174 } 01175 pbuf_realloc(inseg.p, inseg.len); 01176 tcplen = TCP_TCPLEN(&inseg); 01177 LWIP_ASSERT("tcp_receive: segment not trimmed correctly to rcv_wnd\n", 01178 (seqno + tcplen) == (pcb->rcv_nxt + pcb->rcv_wnd)); 01179 } 01180 #if TCP_QUEUE_OOSEQ 01181 /* Received in-sequence data, adjust ooseq data if: 01182 - FIN has been received or 01183 - inseq overlaps with ooseq */ 01184 if (pcb->ooseq != NULL) { 01185 if (TCPH_FLAGS(inseg.tcphdr) & TCP_FIN) { 01186 LWIP_DEBUGF(TCP_INPUT_DEBUG, 01187 ("tcp_receive: received in-order FIN, binning ooseq queue\n")); 01188 /* Received in-order FIN means anything that was received 01189 * out of order must now have been received in-order, so 01190 * bin the ooseq queue */ 01191 while (pcb->ooseq != NULL) { 01192 struct tcp_seg *old_ooseq = pcb->ooseq; 01193 pcb->ooseq = pcb->ooseq->next; 01194 tcp_seg_free(old_ooseq); 01195 } 01196 } 01197 else { 01198 next = pcb->ooseq; 01199 /* Remove all segments on ooseq that are covered by inseg already. 01200 * FIN is copied from ooseq to inseg if present. */ 01201 while (next && 01202 TCP_SEQ_GEQ(seqno + tcplen, 01203 next->tcphdr->seqno + next->len)) { 01204 /* inseg cannot have FIN here (already processed above) */ 01205 if (TCPH_FLAGS(next->tcphdr) & TCP_FIN && 01206 (TCPH_FLAGS(inseg.tcphdr) & TCP_SYN) == 0) { 01207 TCPH_SET_FLAG(inseg.tcphdr, TCP_FIN); 01208 tcplen = TCP_TCPLEN(&inseg); 01209 } 01210 prev = next; 01211 next = next->next; 01212 tcp_seg_free(prev); 01213 } 01214 /* Now trim right side of inseg if it overlaps with the first 01215 * segment on ooseq */ 01216 if (next && 01217 TCP_SEQ_GT(seqno + tcplen, 01218 next->tcphdr->seqno)) { 01219 /* inseg cannot have FIN here (already processed above) */ 01220 inseg.len = (u16_t)(next->tcphdr->seqno - seqno); 01221 if (TCPH_FLAGS(inseg.tcphdr) & TCP_SYN) { 01222 inseg.len -= 1; 01223 } 01224 pbuf_realloc(inseg.p, inseg.len); 01225 tcplen = TCP_TCPLEN(&inseg); 01226 LWIP_ASSERT("tcp_receive: segment not trimmed correctly to ooseq queue\n", 01227 (seqno + tcplen) == next->tcphdr->seqno); 01228 } 01229 pcb->ooseq = next; 01230 } 01231 } 01232 #endif /* TCP_QUEUE_OOSEQ */ 01233 01234 pcb->rcv_nxt = seqno + tcplen; 01235 01236 /* Update the receiver's (our) window. */ 01237 LWIP_ASSERT("tcp_receive: tcplen > rcv_wnd\n", pcb->rcv_wnd >= tcplen); 01238 pcb->rcv_wnd -= tcplen; 01239 01240 tcp_update_rcv_ann_wnd(pcb); 01241 01242 /* If there is data in the segment, we make preparations to 01243 pass this up to the application. The ->recv_data variable 01244 is used for holding the pbuf that goes to the 01245 application. The code for reassembling out-of-sequence data 01246 chains its data on this pbuf as well. 01247 01248 If the segment was a FIN, we set the TF_GOT_FIN flag that will 01249 be used to indicate to the application that the remote side has 01250 closed its end of the connection. */ 01251 if (inseg.p->tot_len > 0) { 01252 recv_data = inseg.p; 01253 /* Since this pbuf now is the responsibility of the 01254 application, we delete our reference to it so that we won't 01255 (mistakingly) deallocate it. */ 01256 inseg.p = NULL; 01257 } 01258 if (TCPH_FLAGS(inseg.tcphdr) & TCP_FIN) { 01259 LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: received FIN.\n")); 01260 recv_flags |= TF_GOT_FIN; 01261 } 01262 01263 #if TCP_QUEUE_OOSEQ 01264 /* We now check if we have segments on the ->ooseq queue that 01265 are now in sequence. */ 01266 while (pcb->ooseq != NULL && 01267 pcb->ooseq->tcphdr->seqno == pcb->rcv_nxt) { 01268 01269 cseg = pcb->ooseq; 01270 seqno = pcb->ooseq->tcphdr->seqno; 01271 01272 pcb->rcv_nxt += TCP_TCPLEN(cseg); 01273 LWIP_ASSERT("tcp_receive: ooseq tcplen > rcv_wnd\n", 01274 pcb->rcv_wnd >= TCP_TCPLEN(cseg)); 01275 pcb->rcv_wnd -= TCP_TCPLEN(cseg); 01276 01277 tcp_update_rcv_ann_wnd(pcb); 01278 01279 if (cseg->p->tot_len > 0) { 01280 /* Chain this pbuf onto the pbuf that we will pass to 01281 the application. */ 01282 if (recv_data) { 01283 pbuf_cat(recv_data, cseg->p); 01284 } else { 01285 recv_data = cseg->p; 01286 } 01287 cseg->p = NULL; 01288 } 01289 if (TCPH_FLAGS(cseg->tcphdr) & TCP_FIN) { 01290 LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: dequeued FIN.\n")); 01291 recv_flags |= TF_GOT_FIN; 01292 if (pcb->state == ESTABLISHED) { /* force passive close or we can move to active close */ 01293 pcb->state = CLOSE_WAIT; 01294 } 01295 } 01296 01297 pcb->ooseq = cseg->next; 01298 tcp_seg_free(cseg); 01299 } 01300 #endif /* TCP_QUEUE_OOSEQ */ 01301 01302 01303 /* Acknowledge the segment(s). */ 01304 tcp_ack(pcb); 01305 01306 } else { 01307 /* We get here if the incoming segment is out-of-sequence. */ 01308 tcp_send_empty_ack(pcb); 01309 #if TCP_QUEUE_OOSEQ 01310 /* We queue the segment on the ->ooseq queue. */ 01311 if (pcb->ooseq == NULL) { 01312 pcb->ooseq = tcp_seg_copy(&inseg); 01313 } else { 01314 /* If the queue is not empty, we walk through the queue and 01315 try to find a place where the sequence number of the 01316 incoming segment is between the sequence numbers of the 01317 previous and the next segment on the ->ooseq queue. That is 01318 the place where we put the incoming segment. If needed, we 01319 trim the second edges of the previous and the incoming 01320 segment so that it will fit into the sequence. 01321 01322 If the incoming segment has the same sequence number as a 01323 segment on the ->ooseq queue, we discard the segment that 01324 contains less data. */ 01325 01326 prev = NULL; 01327 for(next = pcb->ooseq; next != NULL; next = next->next) { 01328 if (seqno == next->tcphdr->seqno) { 01329 /* The sequence number of the incoming segment is the 01330 same as the sequence number of the segment on 01331 ->ooseq. We check the lengths to see which one to 01332 discard. */ 01333 if (inseg.len > next->len) { 01334 /* The incoming segment is larger than the old 01335 segment. We replace some segments with the new 01336 one. */ 01337 cseg = tcp_seg_copy(&inseg); 01338 if (cseg != NULL) { 01339 if (prev != NULL) { 01340 prev->next = cseg; 01341 } else { 01342 pcb->ooseq = cseg; 01343 } 01344 tcp_oos_insert_segment(cseg, next); 01345 } 01346 break; 01347 } else { 01348 /* Either the lenghts are the same or the incoming 01349 segment was smaller than the old one; in either 01350 case, we ditch the incoming segment. */ 01351 break; 01352 } 01353 } else { 01354 if (prev == NULL) { 01355 if (TCP_SEQ_LT(seqno, next->tcphdr->seqno)) { 01356 /* The sequence number of the incoming segment is lower 01357 than the sequence number of the first segment on the 01358 queue. We put the incoming segment first on the 01359 queue. */ 01360 cseg = tcp_seg_copy(&inseg); 01361 if (cseg != NULL) { 01362 pcb->ooseq = cseg; 01363 tcp_oos_insert_segment(cseg, next); 01364 } 01365 break; 01366 } 01367 } else { 01368 /*if (TCP_SEQ_LT(prev->tcphdr->seqno, seqno) && 01369 TCP_SEQ_LT(seqno, next->tcphdr->seqno)) {*/ 01370 if (TCP_SEQ_BETWEEN(seqno, prev->tcphdr->seqno+1, next->tcphdr->seqno-1)) { 01371 /* The sequence number of the incoming segment is in 01372 between the sequence numbers of the previous and 01373 the next segment on ->ooseq. We trim trim the previous 01374 segment, delete next segments that included in received segment 01375 and trim received, if needed. */ 01376 cseg = tcp_seg_copy(&inseg); 01377 if (cseg != NULL) { 01378 if (TCP_SEQ_GT(prev->tcphdr->seqno + prev->len, seqno)) { 01379 /* We need to trim the prev segment. */ 01380 prev->len = (u16_t)(seqno - prev->tcphdr->seqno); 01381 pbuf_realloc(prev->p, prev->len); 01382 } 01383 prev->next = cseg; 01384 tcp_oos_insert_segment(cseg, next); 01385 } 01386 break; 01387 } 01388 } 01389 /* If the "next" segment is the last segment on the 01390 ooseq queue, we add the incoming segment to the end 01391 of the list. */ 01392 if (next->next == NULL && 01393 TCP_SEQ_GT(seqno, next->tcphdr->seqno)) { 01394 if (TCPH_FLAGS(next->tcphdr) & TCP_FIN) { 01395 /* segment "next" already contains all data */ 01396 break; 01397 } 01398 next->next = tcp_seg_copy(&inseg); 01399 if (next->next != NULL) { 01400 if (TCP_SEQ_GT(next->tcphdr->seqno + next->len, seqno)) { 01401 /* We need to trim the last segment. */ 01402 next->len = (u16_t)(seqno - next->tcphdr->seqno); 01403 pbuf_realloc(next->p, next->len); 01404 } 01405 } 01406 break; 01407 } 01408 } 01409 prev = next; 01410 } 01411 } 01412 #endif /* TCP_QUEUE_OOSEQ */ 01413 01414 } 01415 } else { 01416 /* The incoming segment is not withing the window. */ 01417 tcp_send_empty_ack(pcb); 01418 } 01419 } else { 01420 /* Segments with length 0 is taken care of here. Segments that 01421 fall out of the window are ACKed. */ 01422 /*if (TCP_SEQ_GT(pcb->rcv_nxt, seqno) || 01423 TCP_SEQ_GEQ(seqno, pcb->rcv_nxt + pcb->rcv_wnd)) {*/ 01424 if(!TCP_SEQ_BETWEEN(seqno, pcb->rcv_nxt, pcb->rcv_nxt + pcb->rcv_wnd-1)){ 01425 tcp_ack_now(pcb); 01426 } 01427 } 01428 } 01429 01430 /** 01431 * Parses the options contained in the incoming segment. 01432 * 01433 * Called from tcp_listen_input() and tcp_process(). 01434 * Currently, only the MSS option is supported! 01435 * 01436 * @param pcb the tcp_pcb for which a segment arrived 01437 */ 01438 static void 01439 tcp_parseopt(struct tcp_pcb *pcb) 01440 { 01441 u16_t c, max_c; 01442 u16_t mss; 01443 u8_t *opts, opt; 01444 #if LWIP_TCP_TIMESTAMPS 01445 u32_t tsval; 01446 #endif 01447 01448 opts = (u8_t *)tcphdr + TCP_HLEN; 01449 01450 /* Parse the TCP MSS option, if present. */ 01451 if(TCPH_HDRLEN(tcphdr) > 0x5) { 01452 max_c = (TCPH_HDRLEN(tcphdr) - 5) << 2; 01453 for (c = 0; c < max_c; ) { 01454 opt = opts[c]; 01455 switch (opt) { 01456 case 0x00: 01457 /* End of options. */ 01458 LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: EOL\n")); 01459 return; 01460 case 0x01: 01461 /* NOP option. */ 01462 ++c; 01463 LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: NOP\n")); 01464 break; 01465 case 0x02: 01466 LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: MSS\n")); 01467 if (opts[c + 1] != 0x04 || c + 0x04 > max_c) { 01468 /* Bad length */ 01469 LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: bad length\n")); 01470 return; 01471 } 01472 /* An MSS option with the right option length. */ 01473 mss = (opts[c + 2] << 8) | opts[c + 3]; 01474 /* Limit the mss to the configured TCP_MSS and prevent division by zero */ 01475 pcb->mss = ((mss > TCP_MSS) || (mss == 0)) ? TCP_MSS : mss; 01476 /* Advance to next option */ 01477 c += 0x04; 01478 break; 01479 #if LWIP_TCP_TIMESTAMPS 01480 case 0x08: 01481 LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: TS\n")); 01482 if (opts[c + 1] != 0x0A || c + 0x0A > max_c) { 01483 /* Bad length */ 01484 LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: bad length\n")); 01485 return; 01486 } 01487 /* TCP timestamp option with valid length */ 01488 tsval = (opts[c+2]) | (opts[c+3] << 8) | 01489 (opts[c+4] << 16) | (opts[c+5] << 24); 01490 if (flags & TCP_SYN) { 01491 pcb->ts_recent = ntohl(tsval); 01492 pcb->flags |= TF_TIMESTAMP; 01493 } else if (TCP_SEQ_BETWEEN(pcb->ts_lastacksent, seqno, seqno+tcplen)) { 01494 pcb->ts_recent = ntohl(tsval); 01495 } 01496 /* Advance to next option */ 01497 c += 0x0A; 01498 break; 01499 #endif 01500 default: 01501 LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: other\n")); 01502 if (opts[c + 1] == 0) { 01503 LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: bad length\n")); 01504 /* If the length field is zero, the options are malformed 01505 and we don't process them further. */ 01506 return; 01507 } 01508 /* All other options have a length field, so that we easily 01509 can skip past them. */ 01510 c += opts[c + 1]; 01511 } 01512 } 01513 } 01514 } 01515 01516 #endif /* LWIP_TCP */
Generated on Tue Jul 12 2022 15:37:05 by 1.7.2