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