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