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