Mbed library for ENC28J60 Ethernet modules. Full support for TCP/IP and UDP Server, Client and HTTP server (webserver). DHCP and DNS is included.
Dependents: mBuino_ENC28_MQTT Nucleo_Web_ENC28J60 Nucleo_Web_ENC28J60_ADC Serial_over_Ethernet ... more
uip.c
00001 #define DEBUG_PRINTF(...) /*printf(__VA_ARGS__)*/ 00002 00003 /** 00004 * \defgroup uip The UIP TCP/IP stack 00005 * @{ 00006 * 00007 * UIP is an implementation of the TCP/IP protocol stack intended for 00008 * small 8-bit and 16-bit microcontrollers. 00009 * 00010 * UIP provides the necessary protocols for Internet communication, 00011 * with a very small code footprint and RAM requirements - the UIP 00012 * code size is on the order of a few kilobytes and RAM usage is on 00013 * the order of a few hundred bytes. 00014 */ 00015 00016 /** 00017 * \file 00018 * The UIP TCP/IP stack code. 00019 * \author Adam Dunkels <adam@dunkels.com> 00020 */ 00021 /* 00022 * Copyright (c) 2001-2003, Adam Dunkels. 00023 * All rights reserved. 00024 * 00025 * Redistribution and use in source and binary forms, with or without 00026 * modification, are permitted provided that the following conditions 00027 * are met: 00028 * 1. Redistributions of source code must retain the above copyright 00029 * notice, this list of conditions and the following disclaimer. 00030 * 2. Redistributions in binary form must reproduce the above copyright 00031 * notice, this list of conditions and the following disclaimer in the 00032 * documentation and/or other materials provided with the distribution. 00033 * 3. The name of the author may not be used to endorse or promote 00034 * products derived from this software without specific prior 00035 * written permission. 00036 * 00037 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS 00038 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 00039 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 00040 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 00041 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 00042 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 00043 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 00044 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 00045 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 00046 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 00047 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00048 * 00049 * This file is part of the UIP TCP/IP stack. 00050 * 00051 * $Id: uip.c,v 1.65 2006/06/11 21:46:39 adam Exp $ 00052 * 00053 */ 00054 /* 00055 * UIP is a small implementation of the IP, UDP and TCP protocols (as 00056 * well as some basic ICMP stuff). The implementation couples the IP, 00057 * UDP, TCP and the application layers very tightly. To keep the size 00058 * of the compiled code down, this code frequently uses the goto 00059 * statement. While it would be possible to break the uip_process() 00060 * function into many smaller functions, this would increase the code 00061 * size because of the overhead of parameter passing and the fact that 00062 * the optimier would not be as efficient. 00063 * 00064 * The principle is that we have a small buffer, called the uip_buf, 00065 * in which the device driver puts an incoming packet. The TCP/IP 00066 * stack parses the headers in the packet, and calls the 00067 * application. If the remote host has sent data to the application, 00068 * this data is present in the uip_buf and the application read the 00069 * data from there. It is up to the application to put this data into 00070 * a byte stream if needed. The application will not be fed with data 00071 * that is out of sequence. 00072 * 00073 * If the application whishes to send data to the peer, it should put 00074 * its data into the uip_buf. The uip_appdata pointer points to the 00075 * first available byte. The TCP/IP stack will calculate the 00076 * checksums, and fill in the necessary header fields and finally send 00077 * the packet back to the peer. 00078 */ 00079 #include "uip.h" 00080 #include "uipopt.h" 00081 #include "uip_arch.h" 00082 00083 #if UIP_CONF_IPV6 00084 #include "uip-neighbor.h" 00085 #endif /* UIP_CONF_IPV6 */ 00086 00087 #include <string.h> 00088 00089 /*---------------------------------------------------------------------------*/ 00090 00091 /* Variable definitions. */ 00092 /* The IP address of this host. If it is defined to be fixed (by 00093 setting UIP_FIXEDADDR to 1 in uipopt.h), the address is set 00094 here. Otherwise, the address */ 00095 #if UIP_FIXEDADDR > 0 00096 const uip_ipaddr_t uip_hostaddr = { HTONS((UIP_IPADDR0 << 8) | UIP_IPADDR1), HTONS 00097 ((UIP_IPADDR2 << 8) | UIP_IPADDR3) }; 00098 const uip_ipaddr_t uip_draddr = 00099 { 00100 HTONS((UIP_DRIPADDR0 << 8) | UIP_DRIPADDR1), 00101 HTONS((UIP_DRIPADDR2 << 8) | UIP_DRIPADDR3) 00102 }; 00103 const uip_ipaddr_t uip_netmask = 00104 { 00105 HTONS((UIP_NETMASK0 << 8) | UIP_NETMASK1), 00106 HTONS((UIP_NETMASK2 << 8) | UIP_NETMASK3) 00107 }; 00108 #else 00109 uip_ipaddr_t uip_hostaddr, uip_draddr, uip_netmask; 00110 #endif /* UIP_FIXEDADDR */ 00111 00112 static const uip_ipaddr_t all_ones_addr = 00113 #if UIP_CONF_IPV6 00114 { 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff }; 00115 #else /* UIP_CONF_IPV6 */ 00116 { 00117 0xffff, 0xffff 00118 }; 00119 #endif /* UIP_CONF_IPV6 */ 00120 static const uip_ipaddr_t all_zeroes_addr = 00121 #if UIP_CONF_IPV6 00122 { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 }; 00123 #else /* UIP_CONF_IPV6 */ 00124 { 00125 0x0000, 0x0000 00126 }; 00127 #endif /* UIP_CONF_IPV6 */ 00128 00129 #if UIP_FIXEDETHADDR 00130 const struct uip_eth_addr uip_ethaddr = 00131 { 00132 { UIP_ETHADDR0, UIP_ETHADDR1, UIP_ETHADDR2, UIP_ETHADDR3, UIP_ETHADDR4, UIP_ETHADDR5 } 00133 }; 00134 #else 00135 struct uip_eth_addr uip_ethaddr = { { 0, 0, 0, 0, 0, 0 } }; 00136 #endif 00137 #ifndef UIP_CONF_EXTERNAL_BUFFER 00138 u8_t uip_buf[UIP_BUFSIZE + 2]; /* The packet buffer that contains 00139 incoming packets. */ 00140 #endif /* UIP_CONF_EXTERNAL_BUFFER */ 00141 00142 void* uip_appdata; /* The uip_appdata pointer points to 00143 application data. */ 00144 void* uip_sappdata; /* The uip_appdata pointer points to 00145 the application data which is to 00146 be sent. */ 00147 #if UIP_URGDATA > 0 00148 void* uip_urgdata; /* The uip_urgdata pointer points to 00149 urgent data (out-of-band data), if 00150 present. */ 00151 u16_t uip_urglen, uip_surglen; 00152 #endif /* UIP_URGDATA > 0 */ 00153 00154 u16_t uip_len, uip_slen; 00155 00156 /* The uip_len is either 8 or 16 bits, 00157 depending on the maximum packet 00158 size. */ 00159 u8_t uip_flags; /* The uip_flags variable is used for 00160 communication between the TCP/IP stack 00161 and the application program. */ 00162 struct uip_conn* uip_conn; /* uip_conn always points to the current 00163 connection. */ 00164 00165 struct uip_conn uip_conns[UIP_CONNS]; 00166 00167 /* The uip_conns array holds all TCP 00168 connections. */ 00169 u16_t uip_listenports[UIP_LISTENPORTS]; 00170 00171 /* The uip_listenports list all currently 00172 listning ports. */ 00173 #if UIP_UDP 00174 struct uip_udp_conn* uip_udp_conn; 00175 struct uip_udp_conn uip_udp_conns[UIP_UDP_CONNS]; 00176 #endif /* UIP_UDP */ 00177 00178 static u16_t ipid; /* Ths ipid variable is an increasing 00179 number that is used for the IP ID 00180 field. */ 00181 00182 /** 00183 * @brief 00184 * @note 00185 * @param 00186 * @retval 00187 */ 00188 void uip_setipid(u16_t id) { 00189 ipid = id; 00190 } 00191 00192 static u8_t iss[4]; /* The iss variable is used for the TCP 00193 initial sequence number. */ 00194 00195 #if UIP_ACTIVE_OPEN 00196 static u16_t lastport; /* Keeps track of the last port used for 00197 a new connection. */ 00198 #endif /* UIP_ACTIVE_OPEN */ 00199 00200 /* Temporary variables. */ 00201 00202 u8_t uip_acc32[4]; 00203 static u8_t c, opt; 00204 static u16_t tmp16; 00205 00206 /* Structures and definitions. */ 00207 00208 #define TCP_FIN 0x01 00209 #define TCP_SYN 0x02 00210 #define TCP_RST 0x04 00211 #define TCP_PSH 0x08 00212 #define TCP_ACK 0x10 00213 #define TCP_URG 0x20 00214 #define TCP_CTL 0x3f 00215 00216 #define TCP_OPT_END 0 /* End of TCP options list */ 00217 00218 #define TCP_OPT_NOOP 1 /* "No-operation" TCP option */ 00219 00220 #define TCP_OPT_MSS 2 /* Maximum segment size TCP option */ 00221 00222 #define TCP_OPT_MSS_LEN 4 /* Length of TCP MSS option. */ 00223 00224 #define ICMP_ECHO_REPLY 0 00225 #define ICMP_ECHO 8 00226 00227 #define ICMP6_ECHO_REPLY 129 00228 #define ICMP6_ECHO 128 00229 #define ICMP6_NEIGHBOR_SOLICITATION 135 00230 #define ICMP6_NEIGHBOR_ADVERTISEMENT 136 00231 00232 #define ICMP6_FLAG_S (1 << 6) 00233 #define ICMP6_OPTION_SOURCE_LINK_ADDRESS 1 00234 #define ICMP6_OPTION_TARGET_LINK_ADDRESS 2 00235 00236 /* Macros. */ 00237 00238 #define BUF ((struct uip_tcpip_hdr*) &uip_buf[UIP_LLH_LEN]) 00239 #define FBUF ((struct uip_tcpip_hdr*) &uip_reassbuf[0]) 00240 #define ICMPBUF ((struct uip_icmpip_hdr*) &uip_buf[UIP_LLH_LEN]) 00241 #define UDPBUF ((struct uip_udpip_hdr*) &uip_buf[UIP_LLH_LEN]) 00242 #if UIP_STATISTICS == 1 00243 struct uip_stats uip_stat; 00244 #define UIP_STAT(s) s 00245 #else 00246 #define UIP_STAT(s) 00247 #endif /* UIP_STATISTICS == 1 */ 00248 00249 #if UIP_LOGGING == 1 00250 #include <stdio.h> 00251 void uip_log(char* msg); 00252 #define UIP_LOG(m) uip_log(m) 00253 #else 00254 #define UIP_LOG(m) 00255 #endif /* UIP_LOGGING == 1 */ 00256 00257 #if !UIP_ARCH_ADD32 00258 00259 /** 00260 * @brief 00261 * @note 00262 * @param 00263 * @retval 00264 */ 00265 void uip_add32(u8_t* op32, u16_t op16) { 00266 uip_acc32[3] = op32[3] + (op16 & 0xff); 00267 uip_acc32[2] = op32[2] + (op16 >> 8); 00268 uip_acc32[1] = op32[1]; 00269 uip_acc32[0] = op32[0]; 00270 00271 if (uip_acc32[2] < (op16 >> 8)) { 00272 ++uip_acc32[1]; 00273 if (uip_acc32[1] == 0) { 00274 ++uip_acc32[0]; 00275 } 00276 } 00277 00278 if (uip_acc32[3] < (op16 & 0xff)) { 00279 ++uip_acc32[2]; 00280 if (uip_acc32[2] == 0) { 00281 ++uip_acc32[1]; 00282 if (uip_acc32[1] == 0) { 00283 ++uip_acc32[0]; 00284 } 00285 } 00286 } 00287 } 00288 #endif /* UIP_ARCH_ADD32 */ 00289 00290 #if !UIP_ARCH_CHKSUM 00291 00292 /*---------------------------------------------------------------------------*/ 00293 static u16_t chksum(u16_t sum, const u8_t* data, u16_t len) { 00294 u16_t t; 00295 const u8_t* dataptr; 00296 const u8_t* last_byte; 00297 00298 dataptr = data; 00299 last_byte = data + len - 1; 00300 00301 while (dataptr < last_byte) { 00302 00303 /* At least two more bytes */ 00304 t = (dataptr[0] << 8) + dataptr[1]; 00305 sum += t; 00306 if (sum < t) { 00307 sum++; /* carry */ 00308 } 00309 00310 dataptr += 2; 00311 } 00312 00313 if (dataptr == last_byte) { 00314 t = (dataptr[0] << 8) + 0; 00315 sum += t; 00316 if (sum < t) { 00317 sum++; /* carry */ 00318 } 00319 } 00320 00321 /* Return sum in host byte order. */ 00322 return sum; 00323 } 00324 00325 /*---------------------------------------------------------------------------*/ 00326 u16_t uip_chksum(u16_t* data, u16_t len) { 00327 return htons(chksum(0, (u8_t*)data, len)); 00328 } 00329 00330 /*---------------------------------------------------------------------------*/ 00331 #ifndef UIP_ARCH_IPCHKSUM 00332 00333 /** 00334 * @brief 00335 * @note 00336 * @param 00337 * @retval 00338 */ 00339 u16_t uip_ipchksum(void) { 00340 u16_t sum; 00341 00342 sum = chksum(0, &uip_buf[UIP_LLH_LEN], UIP_IPH_LEN); 00343 DEBUG_PRINTF("uip_ipchksum: sum 0x%04x\n", sum); 00344 return(sum == 0) ? 0xffff : htons(sum); 00345 } 00346 #endif 00347 00348 /*---------------------------------------------------------------------------*/ 00349 static u16_t upper_layer_chksum(u8_t proto) { 00350 u16_t upper_layer_len; 00351 u16_t sum; 00352 00353 #if UIP_CONF_IPV6 00354 upper_layer_len = (((u16_t) (BUF->len[0]) << 8) + BUF->len[1]); 00355 #else /* UIP_CONF_IPV6 */ 00356 upper_layer_len = (((u16_t) (BUF->len[0]) << 8) + BUF->len[1]) - UIP_IPH_LEN; 00357 #endif /* UIP_CONF_IPV6 */ 00358 00359 /* First sum pseudoheader. */ 00360 00361 /* IP protocol and length fields. This addition cannot carry. */ 00362 sum = upper_layer_len + proto; 00363 00364 /* Sum IP source and destination addresses. */ 00365 sum = chksum(sum, (u8_t*) &BUF->srcipaddr[0], 2 * sizeof(uip_ipaddr_t)); 00366 00367 /* Sum TCP header and data. */ 00368 sum = chksum(sum, &uip_buf[UIP_IPH_LEN + UIP_LLH_LEN], upper_layer_len); 00369 00370 return(sum == 0) ? 0xffff : htons(sum); 00371 } 00372 00373 /*---------------------------------------------------------------------------*/ 00374 #if UIP_CONF_IPV6 00375 00376 /** 00377 * @brief 00378 * @note 00379 * @param 00380 * @retval 00381 */ 00382 u16_t uip_icmp6chksum (void) { 00383 return upper_layer_chksum(UIP_PROTO_ICMP6); 00384 } 00385 #endif /* UIP_CONF_IPV6 */ 00386 00387 /*---------------------------------------------------------------------------*/ 00388 u16_t uip_tcpchksum(void) { 00389 return upper_layer_chksum(UIP_PROTO_TCP); 00390 } 00391 00392 /*---------------------------------------------------------------------------*/ 00393 #if UIP_UDP_CHECKSUMS 00394 00395 /** 00396 * @brief 00397 * @note 00398 * @param 00399 * @retval 00400 */ 00401 u16_t uip_udpchksum(void) { 00402 return upper_layer_chksum(UIP_PROTO_UDP); 00403 } 00404 #endif /* UIP_UDP_CHECKSUMS */ 00405 #endif /* UIP_ARCH_CHKSUM */ 00406 00407 /*---------------------------------------------------------------------------*/ 00408 void uip_init(void) { 00409 for (c = 0; c < UIP_LISTENPORTS; ++c) { 00410 uip_listenports[c] = 0; 00411 } 00412 00413 for (c = 0; c < UIP_CONNS; ++c) { 00414 uip_conns[c].tcpstateflags = UIP_CLOSED; 00415 } 00416 00417 #if UIP_ACTIVE_OPEN 00418 lastport = 1024; 00419 #endif /* UIP_ACTIVE_OPEN */ 00420 00421 #if UIP_UDP 00422 for (c = 0; c < UIP_UDP_CONNS; ++c) { 00423 uip_udp_conns[c].lport = 0; 00424 } 00425 #endif /* UIP_UDP */ 00426 00427 /* IPv4 initialization. */ 00428 00429 #if UIP_FIXEDADDR == 0 00430 /* uip_hostaddr[0] = uip_hostaddr[1] = 0;*/ 00431 #endif /* UIP_FIXEDADDR */ 00432 } 00433 00434 /*---------------------------------------------------------------------------*/ 00435 #if UIP_ACTIVE_OPEN 00436 00437 /** 00438 * @brief 00439 * @note 00440 * @param 00441 * @retval 00442 */ 00443 struct uip_conn* uip_connect(uip_ipaddr_t* ripaddr, u16_t rport) { 00444 register struct uip_conn* conn, *cconn; 00445 00446 /* Find an unused local port. */ 00447 00448 again: 00449 ++lastport; 00450 00451 if (lastport >= 32000) { 00452 lastport = 4096; 00453 } 00454 00455 /* Check if this port is already in use, and if so try to find 00456 another one. */ 00457 for (c = 0; c < UIP_CONNS; ++c) { 00458 conn = &uip_conns[c]; 00459 if (conn->tcpstateflags != UIP_CLOSED && conn->lport == htons(lastport)) { 00460 goto again; 00461 } 00462 } 00463 00464 conn = 0; 00465 for (c = 0; c < UIP_CONNS; ++c) { 00466 cconn = &uip_conns[c]; 00467 if (cconn->tcpstateflags == UIP_CLOSED) { 00468 conn = cconn; 00469 break; 00470 } 00471 00472 if (cconn->tcpstateflags == UIP_TIME_WAIT) { 00473 if (conn == 0 || cconn->timer > conn->timer) { 00474 conn = cconn; 00475 } 00476 } 00477 } 00478 00479 if (conn == 0) { 00480 return 0; 00481 } 00482 00483 conn->tcpstateflags = UIP_SYN_SENT; 00484 00485 conn->snd_nxt[0] = iss[0]; 00486 conn->snd_nxt[1] = iss[1]; 00487 conn->snd_nxt[2] = iss[2]; 00488 conn->snd_nxt[3] = iss[3]; 00489 00490 conn->initialmss = conn->mss = UIP_TCP_MSS; 00491 00492 conn->len = 1; /* TCP length of the SYN is one. */ 00493 conn->nrtx = 0; 00494 conn->timer = 1; /* Send the SYN next time around. */ 00495 conn->rto = UIP_RTO; 00496 conn->sa = 0; 00497 conn->sv = 16; /* Initial value of the RTT variance. */ 00498 conn->lport = htons(lastport); 00499 conn->rport = rport; 00500 uip_ipaddr_copy(&conn->ripaddr, ripaddr); 00501 00502 return conn; 00503 } 00504 #endif /* UIP_ACTIVE_OPEN */ 00505 00506 /*---------------------------------------------------------------------------*/ 00507 00508 #if UIP_UDP 00509 00510 /** 00511 * @brief 00512 * @note 00513 * @param 00514 * @retval 00515 */ 00516 struct uip_udp_conn* uip_udp_new(uip_ipaddr_t* ripaddr, u16_t rport) { 00517 register struct uip_udp_conn* conn; 00518 00519 /* Find an unused local port. */ 00520 00521 again: 00522 ++lastport; 00523 00524 if (lastport >= 32000) { 00525 lastport = 4096; 00526 } 00527 00528 for (c = 0; c < UIP_UDP_CONNS; ++c) { 00529 if (uip_udp_conns[c].lport == htons(lastport)) { 00530 goto again; 00531 } 00532 } 00533 00534 conn = 0; 00535 for (c = 0; c < UIP_UDP_CONNS; ++c) { 00536 if (uip_udp_conns[c].lport == 0) { 00537 conn = &uip_udp_conns[c]; 00538 break; 00539 } 00540 } 00541 00542 if (conn == 0) { 00543 return 0; 00544 } 00545 00546 conn->lport = HTONS(lastport); 00547 conn->rport = rport; 00548 if (ripaddr == NULL) { 00549 memset(conn->ripaddr, 0, sizeof(uip_ipaddr_t)); 00550 } 00551 else { 00552 uip_ipaddr_copy(&conn->ripaddr, ripaddr); 00553 } 00554 00555 conn->ttl = UIP_TTL; 00556 00557 return conn; 00558 } 00559 #endif /* UIP_UDP */ 00560 00561 /*---------------------------------------------------------------------------*/ 00562 void uip_unlisten(u16_t port) { 00563 for (c = 0; c < UIP_LISTENPORTS; ++c) { 00564 if (uip_listenports[c] == port) { 00565 uip_listenports[c] = 0; 00566 return; 00567 } 00568 } 00569 } 00570 00571 /*---------------------------------------------------------------------------*/ 00572 void uip_listen(u16_t port) { 00573 for (c = 0; c < UIP_LISTENPORTS; ++c) { 00574 if (uip_listenports[c] == 0) { 00575 uip_listenports[c] = port; 00576 return; 00577 } 00578 } 00579 } 00580 00581 /*---------------------------------------------------------------------------*/ 00582 /* XXX: IP fragment reassembly: not well-tested. */ 00583 #if UIP_REASSEMBLY && !UIP_CONF_IPV6 00584 #define UIP_REASS_BUFSIZE (UIP_BUFSIZE - UIP_LLH_LEN) 00585 static u8_t uip_reassbuf[UIP_REASS_BUFSIZE]; 00586 static u8_t uip_reassbitmap[UIP_REASS_BUFSIZE / (8 * 8)]; 00587 static const u8_t bitmap_bits[8] = { 0xff, 0x7f, 0x3f, 0x1f, 0x0f, 0x07, 0x03, 0x01 }; 00588 static u16_t uip_reasslen; 00589 static u8_t uip_reassflags; 00590 #define UIP_REASS_FLAG_LASTFRAG 0x01 00591 static u8_t uip_reasstmr; 00592 00593 #define IP_MF 0x20 00594 00595 /** 00596 * @brief 00597 * @note 00598 * @param 00599 * @retval 00600 */ 00601 static u8_t uip_reass (void) { 00602 u16_t offset, len; 00603 u16_t i; 00604 00605 /* If ip_reasstmr is zero, no packet is present in the buffer, so we 00606 write the IP header of the fragment into the reassembly 00607 buffer. The timer is updated with the maximum age. */ 00608 00609 if (uip_reasstmr == 0) { 00610 memcpy(uip_reassbuf, &BUF->vhl, UIP_IPH_LEN); 00611 uip_reasstmr = UIP_REASS_MAXAGE; 00612 uip_reassflags = 0; 00613 00614 /* Clear the bitmap. */ 00615 memset(uip_reassbitmap, 0, sizeof(uip_reassbitmap)); 00616 } 00617 00618 /* Check if the incoming fragment matches the one currently present 00619 in the reasembly buffer. If so, we proceed with copying the 00620 fragment into the buffer. */ 00621 if 00622 ( 00623 BUF->srcipaddr[0] == FBUF->srcipaddr[0] 00624 && BUF->srcipaddr[1] == FBUF->srcipaddr[1] 00625 && BUF->destipaddr[0] == FBUF->destipaddr[0] 00626 && BUF->destipaddr[1] == FBUF->destipaddr[1] 00627 && BUF->ipid[0] == FBUF->ipid[0] 00628 && BUF->ipid[1] == FBUF->ipid[1] 00629 ) { 00630 len = (BUF->len[0] << 8) + BUF->len[1] - (BUF->vhl & 0x0f) * 4; 00631 offset = (((BUF->ipoffset[0] & 0x3f) << 8) + BUF->ipoffset[1]) * 8; 00632 00633 /* If the offset or the offset + fragment length overflows the 00634 reassembly buffer, we discard the entire packet. */ 00635 if (offset > UIP_REASS_BUFSIZE || offset + len > UIP_REASS_BUFSIZE) { 00636 uip_reasstmr = 0; 00637 goto nullreturn; 00638 } 00639 00640 /* Copy the fragment into the reassembly buffer, at the right 00641 offset. */ 00642 memcpy(&uip_reassbuf[UIP_IPH_LEN + offset], (char*)BUF + (int)((BUF->vhl & 0x0f) * 4), len); 00643 00644 /* Update the bitmap. */ 00645 if (offset / (8 * 8) == (offset + len) / (8 * 8)) { 00646 00647 /* If the two endpoints are in the same byte, we only update 00648 that byte. */ 00649 uip_reassbitmap[offset / (8 * 8)] |= bitmap_bits[(offset / 8) & 7] &~bitmap_bits[((offset + len) / 8) & 7]; 00650 } 00651 else { 00652 00653 /* If the two endpoints are in different bytes, we update the 00654 bytes in the endpoints and fill the stuff inbetween with 00655 0xff. */ 00656 uip_reassbitmap[offset / (8 * 8)] |= bitmap_bits[(offset / 8) & 7]; 00657 for (i = 1 + offset / (8 * 8); i < (offset + len) / (8 * 8); ++i) { 00658 uip_reassbitmap[i] = 0xff; 00659 } 00660 00661 uip_reassbitmap[(offset + len) / (8 * 8)] |= ~bitmap_bits[((offset + len) / 8) & 7]; 00662 } 00663 00664 /* If this fragment has the More Fragments flag set to zero, we 00665 know that this is the last fragment, so we can calculate the 00666 size of the entire packet. We also set the 00667 IP_REASS_FLAG_LASTFRAG flag to indicate that we have received 00668 the final fragment. */ 00669 if ((BUF->ipoffset[0] & IP_MF) == 0) { 00670 uip_reassflags |= UIP_REASS_FLAG_LASTFRAG; 00671 uip_reasslen = offset + len; 00672 } 00673 00674 /* Finally, we check if we have a full packet in the buffer. We do 00675 this by checking if we have the last fragment and if all bits 00676 in the bitmap are set. */ 00677 if (uip_reassflags & UIP_REASS_FLAG_LASTFRAG) { 00678 00679 /* Check all bytes up to and including all but the last byte in 00680 the bitmap. */ 00681 for (i = 0; i < uip_reasslen / (8 * 8) - 1; ++i) { 00682 if (uip_reassbitmap[i] != 0xff) { 00683 goto nullreturn; 00684 } 00685 } 00686 00687 /* Check the last byte in the bitmap. It should contain just the 00688 right amount of bits. */ 00689 if (uip_reassbitmap[uip_reasslen / (8 * 8)] != (u8_t)~bitmap_bits[uip_reasslen / 8 & 7]) { 00690 goto nullreturn; 00691 } 00692 00693 /* If we have come this far, we have a full packet in the 00694 buffer, so we allocate a pbuf and copy the packet into it. We 00695 also reset the timer. */ 00696 uip_reasstmr = 0; 00697 memcpy(BUF, FBUF, uip_reasslen); 00698 00699 /* Pretend to be a "normal" (i.e., not fragmented) IP packet 00700 from now on. */ 00701 BUF->ipoffset[0] = BUF->ipoffset[1] = 0; 00702 BUF->len[0] = uip_reasslen >> 8; 00703 BUF->len[1] = uip_reasslen & 0xff; 00704 BUF->ipchksum = 0; 00705 BUF->ipchksum = ~(uip_ipchksum()); 00706 00707 return uip_reasslen; 00708 } 00709 } 00710 00711 nullreturn: 00712 return 0; 00713 } 00714 #endif /* UIP_REASSEMBLY */ 00715 00716 /*---------------------------------------------------------------------------*/ 00717 static void uip_add_rcv_nxt(u16_t n) { 00718 uip_add32(uip_conn->rcv_nxt, n); 00719 uip_conn->rcv_nxt[0] = uip_acc32[0]; 00720 uip_conn->rcv_nxt[1] = uip_acc32[1]; 00721 uip_conn->rcv_nxt[2] = uip_acc32[2]; 00722 uip_conn->rcv_nxt[3] = uip_acc32[3]; 00723 } 00724 00725 /*---------------------------------------------------------------------------*/ 00726 void uip_process(u8_t flag) { 00727 register struct uip_conn* uip_connr = uip_conn; 00728 00729 #if UIP_UDP 00730 if (flag == UIP_UDP_SEND_CONN) { 00731 goto udp_send; 00732 } 00733 #endif /* UIP_UDP */ 00734 00735 uip_sappdata = uip_appdata = &uip_buf[UIP_IPTCPH_LEN + UIP_LLH_LEN]; 00736 00737 /* Check if we were invoked because of a poll request for a 00738 particular connection. */ 00739 if (flag == UIP_POLL_REQUEST) { 00740 if ((uip_connr->tcpstateflags & UIP_TS_MASK) == UIP_ESTABLISHED && !uip_outstanding(uip_connr)) { 00741 uip_flags = UIP_POLL; 00742 UIP_APPCALL(); 00743 goto appsend; 00744 } 00745 00746 goto drop; 00747 00748 /* Check if we were invoked because of the perodic timer fireing. */ 00749 } 00750 else 00751 if (flag == UIP_TIMER) 00752 { 00753 #if UIP_REASSEMBLY 00754 if (uip_reasstmr != 0) { 00755 --uip_reasstmr; 00756 } 00757 #endif /* UIP_REASSEMBLY */ 00758 00759 /* Increase the initial sequence number. */ 00760 00761 if (++iss[3] == 0) { 00762 if (++iss[2] == 0) { 00763 if (++iss[1] == 0) { 00764 ++iss[0]; 00765 } 00766 } 00767 } 00768 00769 /* Reset the length variables. */ 00770 uip_len = 0; 00771 uip_slen = 0; 00772 00773 /* Check if the connection is in a state in which we simply wait 00774 for the connection to time out. If so, we increase the 00775 connection's timer and remove the connection if it times 00776 out. */ 00777 if (uip_connr->tcpstateflags == UIP_TIME_WAIT || uip_connr->tcpstateflags == UIP_FIN_WAIT_2) { 00778 ++(uip_connr->timer); 00779 if (uip_connr->timer == UIP_TIME_WAIT_TIMEOUT) { 00780 uip_connr->tcpstateflags = UIP_CLOSED; 00781 } 00782 } 00783 else 00784 if (uip_connr->tcpstateflags != UIP_CLOSED) { 00785 00786 /* If the connection has outstanding data, we increase the 00787 connection's timer and see if it has reached the RTO value 00788 in which case we retransmit. */ 00789 if (uip_outstanding(uip_connr)) { 00790 if (uip_connr->timer-- == 0) { 00791 if 00792 ( 00793 uip_connr->nrtx == UIP_MAXRTX 00794 || ( 00795 (uip_connr->tcpstateflags == UIP_SYN_SENT || uip_connr->tcpstateflags == UIP_SYN_RCVD) 00796 && uip_connr->nrtx == UIP_MAXSYNRTX 00797 ) 00798 ) { 00799 uip_connr->tcpstateflags = UIP_CLOSED; 00800 00801 /* We call UIP_APPCALL() with uip_flags set to 00802 UIP_TIMEDOUT to inform the application that the 00803 connection has timed out. */ 00804 uip_flags = UIP_TIMEDOUT; 00805 UIP_APPCALL(); 00806 00807 /* We also send a reset packet to the remote host. */ 00808 BUF->flags = TCP_RST | TCP_ACK; 00809 goto tcp_send_nodata; 00810 } 00811 00812 /* Exponential backoff. */ 00813 uip_connr->timer = UIP_RTO << (uip_connr->nrtx > 4 ? 4 : uip_connr->nrtx); 00814 ++(uip_connr->nrtx); 00815 00816 /* Ok, so we need to retransmit. We do this differently 00817 depending on which state we are in. In ESTABLISHED, we 00818 call upon the application so that it may prepare the 00819 data for the retransmit. In SYN_RCVD, we resend the 00820 SYNACK that we sent earlier and in LAST_ACK we have to 00821 retransmit our FINACK. */ 00822 UIP_STAT(++uip_stat.tcp.rexmit); 00823 switch (uip_connr->tcpstateflags & UIP_TS_MASK) { 00824 case UIP_SYN_RCVD: 00825 /* In the SYN_RCVD state, we should retransmit our 00826 SYNACK. */ 00827 goto tcp_send_synack; 00828 00829 #if UIP_ACTIVE_OPEN 00830 00831 case UIP_SYN_SENT: 00832 /* In the SYN_SENT state, we retransmit out SYN. */ 00833 BUF->flags = 0; 00834 goto tcp_send_syn; 00835 #endif /* UIP_ACTIVE_OPEN */ 00836 00837 case UIP_ESTABLISHED: 00838 /* In the ESTABLISHED state, we call upon the application 00839 to do the actual retransmit after which we jump into 00840 the code for sending out the packet (the apprexmit 00841 label). */ 00842 uip_flags = UIP_REXMIT; 00843 UIP_APPCALL(); 00844 goto apprexmit; 00845 00846 case UIP_FIN_WAIT_1: 00847 case UIP_CLOSING: 00848 case UIP_LAST_ACK: 00849 /* In all these states we should retransmit a FINACK. */ 00850 goto tcp_send_finack; 00851 } 00852 } 00853 } 00854 else 00855 if ((uip_connr->tcpstateflags & UIP_TS_MASK) == UIP_ESTABLISHED) { 00856 00857 /* If there was no need for a retransmission, we poll the 00858 application for new data. */ 00859 uip_flags = UIP_POLL; 00860 UIP_APPCALL(); 00861 goto appsend; 00862 } 00863 } 00864 00865 goto drop; 00866 } 00867 00868 #if UIP_UDP 00869 if (flag == UIP_UDP_TIMER) { 00870 if (uip_udp_conn->lport != 0) { 00871 uip_conn = NULL; 00872 uip_sappdata = uip_appdata = &uip_buf[UIP_LLH_LEN + UIP_IPUDPH_LEN]; 00873 uip_len = uip_slen = 0; 00874 uip_flags = UIP_POLL; 00875 UIP_UDP_APPCALL(); 00876 goto udp_send; 00877 } 00878 else { 00879 goto drop; 00880 } 00881 } 00882 #endif 00883 /* This is where the input processing starts. */ 00884 00885 UIP_STAT(++uip_stat.ip.recv); 00886 00887 /* Start of IP input header processing code. */ 00888 #if UIP_CONF_IPV6 00889 /* Check validity of the IP header. */ 00890 00891 if ((BUF->vtc & 0xf0) != 0x60) { 00892 00893 /* IP version and header length. */ 00894 UIP_STAT(++uip_stat.ip.drop); 00895 UIP_STAT(++uip_stat.ip.vhlerr); 00896 UIP_LOG("ipv6: invalid version."); 00897 goto drop; 00898 } 00899 00900 #else /* UIP_CONF_IPV6 */ 00901 /* Check validity of the IP header. */ 00902 00903 if (BUF->vhl != 0x45) { 00904 00905 /* IP version and header length. */ 00906 UIP_STAT(++uip_stat.ip.drop); 00907 UIP_STAT(++uip_stat.ip.vhlerr); 00908 UIP_LOG("ip: invalid version or header length."); 00909 goto drop; 00910 } 00911 #endif /* UIP_CONF_IPV6 */ 00912 00913 /* Check the size of the packet. If the size reported to us in 00914 uip_len is smaller the size reported in the IP header, we assume 00915 that the packet has been corrupted in transit. If the size of 00916 uip_len is larger than the size reported in the IP packet header, 00917 the packet has been padded and we set uip_len to the correct 00918 value.. */ 00919 00920 if ((BUF->len[0] << 8) + BUF->len[1] <= uip_len) { 00921 uip_len = (BUF->len[0] << 8) + BUF->len[1]; 00922 #if UIP_CONF_IPV6 00923 uip_len += 40; /* The length reported in the IPv6 header is the 00924 length of the payload that follows the 00925 header. However, UIP uses the uip_len variable 00926 for holding the size of the entire packet, 00927 including the IP header. For IPv4 this is not a 00928 problem as the length field in the IPv4 header 00929 contains the length of the entire packet. But 00930 for IPv6 we need to add the size of the IPv6 00931 header (40 bytes). */ 00932 #endif /* UIP_CONF_IPV6 */ 00933 } 00934 else { 00935 UIP_LOG("ip: packet shorter than reported in IP header."); 00936 goto drop; 00937 } 00938 00939 #if !UIP_CONF_IPV6 00940 /* Check the fragment flag. */ 00941 00942 if ((BUF->ipoffset[0] & 0x3f) != 0 || BUF->ipoffset[1] != 0) 00943 { 00944 #if UIP_REASSEMBLY 00945 uip_len = uip_reass (); 00946 if (uip_len == 0) { 00947 goto drop; 00948 } 00949 00950 #else /* UIP_REASSEMBLY */ 00951 UIP_STAT(++uip_stat.ip.drop); 00952 UIP_STAT(++uip_stat.ip.fragerr); 00953 UIP_LOG("ip: fragment dropped."); 00954 goto drop; 00955 #endif /* UIP_REASSEMBLY */ 00956 } 00957 #endif /* UIP_CONF_IPV6 */ 00958 00959 if (uip_ipaddr_cmp(uip_hostaddr, all_zeroes_addr)) 00960 { 00961 /* If we are configured to use ping IP address configuration and 00962 hasn't been assigned an IP address yet, we accept all ICMP 00963 packets. */ 00964 #if UIP_PINGADDRCONF && !UIP_CONF_IPV6 00965 if (BUF->proto == UIP_PROTO_ICMP) { 00966 UIP_LOG("ip: possible ping config packet received."); 00967 goto icmp_input; 00968 } 00969 else { 00970 UIP_LOG("ip: packet dropped since no address assigned."); 00971 goto drop; 00972 } 00973 #endif /* UIP_PINGADDRCONF */ 00974 } 00975 else 00976 { 00977 /* If IP broadcast support is configured, we check for a broadcast 00978 UDP packet, which may be destined to us. */ 00979 #if UIP_BROADCAST 00980 DEBUG_PRINTF("UDP IP checksum 0x%04x\n", uip_ipchksum()); 00981 if 00982 ( 00983 BUF->proto == UIP_PROTO_UDP 00984 && uip_ipaddr_cmp(BUF->destipaddr, all_ones_addr) /*&& 00985 uip_ipchksum() == 0xffff*/ 00986 ) { 00987 goto udp_input; 00988 } 00989 #endif /* UIP_BROADCAST */ 00990 00991 /* Check if the packet is destined for our IP address. */ 00992 00993 #if !UIP_CONF_IPV6 00994 if (!uip_ipaddr_cmp(BUF->destipaddr, uip_hostaddr)) { 00995 UIP_STAT(++uip_stat.ip.drop); 00996 goto drop; 00997 } 00998 00999 #else /* UIP_CONF_IPV6 */ 01000 /* For IPv6, packet reception is a little trickier as we need to 01001 make sure that we listen to certain multicast addresses (all 01002 hosts multicast address, and the solicited-node multicast 01003 address) as well. However, we will cheat here and accept all 01004 multicast packets that are sent to the ff02::/16 addresses. */ 01005 01006 if (!uip_ipaddr_cmp(BUF->destipaddr, uip_hostaddr) && BUF->destipaddr[0] != HTONS(0xff02)) { 01007 UIP_STAT(++uip_stat.ip.drop); 01008 goto drop; 01009 } 01010 #endif /* UIP_CONF_IPV6 */ 01011 } 01012 01013 #if !UIP_CONF_IPV6 01014 if (uip_ipchksum() != 0xffff) { 01015 01016 /* Compute and check the IP header 01017 checksum. */ 01018 UIP_STAT(++uip_stat.ip.drop); 01019 UIP_STAT(++uip_stat.ip.chkerr); 01020 UIP_LOG("ip: bad checksum."); 01021 goto drop; 01022 } 01023 #endif /* UIP_CONF_IPV6 */ 01024 01025 if (BUF->proto == UIP_PROTO_TCP) { 01026 01027 /* Check for TCP packet. If so, 01028 proceed with TCP input 01029 processing. */ 01030 goto tcp_input; 01031 } 01032 01033 #if UIP_UDP 01034 if (BUF->proto == UIP_PROTO_UDP) { 01035 goto udp_input; 01036 } 01037 #endif /* UIP_UDP */ 01038 01039 #if !UIP_CONF_IPV6 01040 /* ICMPv4 processing code follows. */ 01041 01042 if (BUF->proto != UIP_PROTO_ICMP) { 01043 01044 /* We only allow ICMP packets from 01045 here. */ 01046 UIP_STAT(++uip_stat.ip.drop); 01047 UIP_STAT(++uip_stat.ip.protoerr); 01048 UIP_LOG("ip: neither tcp nor icmp."); 01049 goto drop; 01050 } 01051 01052 #if UIP_PINGADDRCONF 01053 icmp_input : 01054 #endif /* UIP_PINGADDRCONF */ 01055 01056 UIP_STAT(++uip_stat.icmp.recv); 01057 01058 /* ICMP echo (i.e., ping) processing. This is simple, we only change 01059 the ICMP type from ECHO to ECHO_REPLY and adjust the ICMP 01060 checksum before we return the packet. */ 01061 if (ICMPBUF->type != ICMP_ECHO) { 01062 UIP_STAT(++uip_stat.icmp.drop); 01063 UIP_STAT(++uip_stat.icmp.typeerr); 01064 UIP_LOG("icmp: not icmp echo."); 01065 goto drop; 01066 } 01067 01068 /* If we are configured to use ping IP address assignment, we use 01069 the destination IP address of this ping packet and assign it to 01070 ourself. */ 01071 #if UIP_PINGADDRCONF 01072 if ((uip_hostaddr[0] | uip_hostaddr[1]) == 0) { 01073 uip_hostaddr[0] = BUF->destipaddr[0]; 01074 uip_hostaddr[1] = BUF->destipaddr[1]; 01075 } 01076 #endif /* UIP_PINGADDRCONF */ 01077 01078 ICMPBUF->type = ICMP_ECHO_REPLY; 01079 01080 if (ICMPBUF->icmpchksum >= HTONS(0xffff - (ICMP_ECHO << 8))) { 01081 ICMPBUF->icmpchksum += HTONS(ICMP_ECHO << 8) + 1; 01082 } 01083 else { 01084 ICMPBUF->icmpchksum += HTONS(ICMP_ECHO << 8); 01085 } 01086 01087 /* Swap IP addresses. */ 01088 uip_ipaddr_copy(BUF->destipaddr, BUF->srcipaddr); 01089 uip_ipaddr_copy(BUF->srcipaddr, uip_hostaddr); 01090 01091 UIP_STAT(++uip_stat.icmp.sent); 01092 goto send; 01093 01094 /* End of IPv4 input header processing code. */ 01095 #else /* !UIP_CONF_IPV6 */ 01096 /* This is IPv6 ICMPv6 processing code. */ 01097 01098 DEBUG_PRINTF("icmp6_input: length %d\n", uip_len); 01099 01100 if (BUF->proto != UIP_PROTO_ICMP6) { 01101 01102 /* We only allow ICMPv6 packets from 01103 here. */ 01104 UIP_STAT(++uip_stat.ip.drop); 01105 UIP_STAT(++uip_stat.ip.protoerr); 01106 UIP_LOG("ip: neither tcp nor icmp6."); 01107 goto drop; 01108 } 01109 01110 UIP_STAT(++uip_stat.icmp.recv); 01111 01112 /* If we get a neighbor solicitation for our address we should send 01113 a neighbor advertisement message back. */ 01114 if (ICMPBUF->type == ICMP6_NEIGHBOR_SOLICITATION) { 01115 if (uip_ipaddr_cmp(ICMPBUF->icmp6data, uip_hostaddr)) { 01116 if (ICMPBUF->options[0] == ICMP6_OPTION_SOURCE_LINK_ADDRESS) { 01117 01118 /* Save the sender's address in our neighbor list. */ 01119 uip_neighbor_add(ICMPBUF->srcipaddr, &(ICMPBUF->options[2])); 01120 } 01121 01122 /* We should now send a neighbor advertisement back to where the 01123 neighbor solicication came from. */ 01124 ICMPBUF->type = ICMP6_NEIGHBOR_ADVERTISEMENT; 01125 ICMPBUF->flags = ICMP6_FLAG_S; /* Solicited flag. */ 01126 01127 ICMPBUF->reserved1 = ICMPBUF->reserved2 = ICMPBUF->reserved3 = 0; 01128 01129 uip_ipaddr_copy(ICMPBUF->destipaddr, ICMPBUF->srcipaddr); 01130 uip_ipaddr_copy(ICMPBUF->srcipaddr, uip_hostaddr); 01131 ICMPBUF->options[0] = ICMP6_OPTION_TARGET_LINK_ADDRESS; 01132 ICMPBUF->options[1] = 1; /* Options length, 1 = 8 bytes. */ 01133 memcpy(&(ICMPBUF->options[2]), &uip_ethaddr, sizeof(uip_ethaddr)); 01134 ICMPBUF->icmpchksum = 0; 01135 ICMPBUF->icmpchksum = ~uip_icmp6chksum (); 01136 goto send; 01137 } 01138 01139 goto drop; 01140 } 01141 else 01142 if (ICMPBUF->type == ICMP6_ECHO) { 01143 01144 /* ICMP echo (i.e., ping) processing. This is simple, we only 01145 change the ICMP type from ECHO to ECHO_REPLY and update the 01146 ICMP checksum before we return the packet. */ 01147 ICMPBUF->type = ICMP6_ECHO_REPLY; 01148 01149 uip_ipaddr_copy(BUF->destipaddr, BUF->srcipaddr); 01150 uip_ipaddr_copy(BUF->srcipaddr, uip_hostaddr); 01151 ICMPBUF->icmpchksum = 0; 01152 ICMPBUF->icmpchksum = ~uip_icmp6chksum (); 01153 01154 UIP_STAT(++uip_stat.icmp.sent); 01155 goto send; 01156 } 01157 else { 01158 DEBUG_PRINTF("Unknown icmp6 message type %d\n", ICMPBUF->type); 01159 UIP_STAT(++uip_stat.icmp.drop); 01160 UIP_STAT(++uip_stat.icmp.typeerr); 01161 UIP_LOG("icmp: unknown ICMP message."); 01162 goto drop; 01163 } 01164 01165 /* End of IPv6 ICMP processing. */ 01166 #endif /* !UIP_CONF_IPV6 */ 01167 01168 #if UIP_UDP 01169 /* UDP input processing. */ 01170 01171 udp_input : 01172 /* UDP processing is really just a hack. We don't do anything to the 01173 UDP/IP headers, but let the UDP application do all the hard 01174 work. If the application sets uip_slen, it has a packet to 01175 send. */ 01176 #if UIP_UDP_CHECKSUMS 01177 uip_len = uip_len - UIP_IPUDPH_LEN; 01178 uip_appdata = &uip_buf[UIP_LLH_LEN + UIP_IPUDPH_LEN]; 01179 if (UDPBUF->udpchksum != 0 && uip_udpchksum() != 0xffff) { 01180 UIP_STAT(++uip_stat.udp.drop); 01181 UIP_STAT(++uip_stat.udp.chkerr); 01182 UIP_LOG("udp: bad checksum."); 01183 goto drop; 01184 } 01185 01186 #else /* UIP_UDP_CHECKSUMS */ 01187 uip_len = uip_len - UIP_IPUDPH_LEN; 01188 #endif /* UIP_UDP_CHECKSUMS */ 01189 01190 /* Demultiplex this UDP packet between the UDP "connections". */ 01191 01192 for (uip_udp_conn = &uip_udp_conns[0]; uip_udp_conn < &uip_udp_conns[UIP_UDP_CONNS]; ++uip_udp_conn) { 01193 01194 /* If the local UDP port is non-zero, the connection is considered 01195 to be used. If so, the local port number is checked against the 01196 destination port number in the received packet. If the two port 01197 numbers match, the remote port number is checked if the 01198 connection is bound to a remote port. Finally, if the 01199 connection is bound to a remote IP address, the source IP 01200 address of the packet is checked. */ 01201 if 01202 ( 01203 uip_udp_conn->lport != 0 01204 && UDPBUF->destport == uip_udp_conn->lport 01205 && (uip_udp_conn->rport == 0 || UDPBUF->srcport == uip_udp_conn->rport) 01206 && ( 01207 uip_ipaddr_cmp(uip_udp_conn->ripaddr, all_zeroes_addr) 01208 || uip_ipaddr_cmp(uip_udp_conn->ripaddr, all_ones_addr) 01209 || uip_ipaddr_cmp(BUF->srcipaddr, uip_udp_conn->ripaddr) 01210 ) 01211 ) { 01212 goto udp_found; 01213 } 01214 } 01215 01216 UIP_LOG("udp: no matching connection found"); 01217 goto drop; 01218 01219 udp_found: 01220 uip_conn = NULL; 01221 uip_flags = UIP_NEWDATA; 01222 uip_sappdata = uip_appdata = &uip_buf[UIP_LLH_LEN + UIP_IPUDPH_LEN]; 01223 uip_slen = 0; 01224 UIP_UDP_APPCALL(); 01225 udp_send: 01226 if (uip_slen == 0) { 01227 goto drop; 01228 } 01229 01230 uip_len = uip_slen + UIP_IPUDPH_LEN; 01231 01232 #if UIP_CONF_IPV6 01233 /* For IPv6, the IP length field does not include the IPv6 IP header 01234 length. */ 01235 01236 BUF->len[0] = ((uip_len - UIP_IPH_LEN) >> 8); 01237 BUF->len[1] = ((uip_len - UIP_IPH_LEN) & 0xff); 01238 #else /* UIP_CONF_IPV6 */ 01239 BUF->len[0] = (uip_len >> 8); 01240 BUF->len[1] = (uip_len & 0xff); 01241 #endif /* UIP_CONF_IPV6 */ 01242 01243 BUF->ttl = uip_udp_conn->ttl; 01244 BUF->proto = UIP_PROTO_UDP; 01245 01246 UDPBUF->udplen = HTONS(uip_slen + UIP_UDPH_LEN); 01247 UDPBUF->udpchksum = 0; 01248 01249 BUF->srcport = uip_udp_conn->lport; 01250 BUF->destport = uip_udp_conn->rport; 01251 01252 uip_ipaddr_copy(BUF->srcipaddr, uip_hostaddr); 01253 uip_ipaddr_copy(BUF->destipaddr, uip_udp_conn->ripaddr); 01254 01255 uip_appdata = &uip_buf[UIP_LLH_LEN + UIP_IPTCPH_LEN]; 01256 01257 #if UIP_UDP_CHECKSUMS 01258 /* Calculate UDP checksum. */ 01259 01260 UDPBUF->udpchksum = ~(uip_udpchksum()); 01261 if (UDPBUF->udpchksum == 0) { 01262 UDPBUF->udpchksum = 0xffff; 01263 } 01264 #endif /* UIP_UDP_CHECKSUMS */ 01265 01266 goto ip_send_nolen; 01267 #endif /* UIP_UDP */ 01268 01269 /* TCP input processing. */ 01270 01271 tcp_input : UIP_STAT(++uip_stat.tcp.recv); 01272 01273 /* Start of TCP input header processing code. */ 01274 if (uip_tcpchksum() != 0xffff) { 01275 01276 /* Compute and check the TCP 01277 checksum. */ 01278 UIP_STAT(++uip_stat.tcp.drop); 01279 UIP_STAT(++uip_stat.tcp.chkerr); 01280 UIP_LOG("tcp: bad checksum."); 01281 goto drop; 01282 } 01283 01284 /* Demultiplex this segment. */ 01285 /* First check any active connections. */ 01286 for (uip_connr = &uip_conns[0]; uip_connr <= &uip_conns[UIP_CONNS - 1]; ++uip_connr) { 01287 if 01288 ( 01289 uip_connr->tcpstateflags != UIP_CLOSED 01290 && BUF->destport == uip_connr->lport 01291 && BUF->srcport == uip_connr->rport 01292 && uip_ipaddr_cmp(BUF->srcipaddr, uip_connr->ripaddr) 01293 ) { 01294 goto found; 01295 } 01296 } 01297 01298 /* If we didn't find and active connection that expected the packet, 01299 either this packet is an old duplicate, or this is a SYN packet 01300 destined for a connection in LISTEN. If the SYN flag isn't set, 01301 it is an old packet and we send a RST. */ 01302 if ((BUF->flags & TCP_CTL) != TCP_SYN) { 01303 goto reset; 01304 } 01305 01306 tmp16 = BUF->destport; 01307 01308 /* Next, check listening connections. */ 01309 for (c = 0; c < UIP_LISTENPORTS; ++c) { 01310 if (tmp16 == uip_listenports[c]) 01311 goto found_listen; 01312 } 01313 01314 /* No matching connection found, so we send a RST packet. */ 01315 UIP_STAT(++uip_stat.tcp.synrst); 01316 reset: 01317 /* We do not send resets in response to resets. */ 01318 if (BUF->flags & TCP_RST) { 01319 goto drop; 01320 } 01321 01322 UIP_STAT(++uip_stat.tcp.rst); 01323 01324 BUF->flags = TCP_RST | TCP_ACK; 01325 uip_len = UIP_IPTCPH_LEN; 01326 BUF->tcpoffset = 5 << 4; 01327 01328 /* Flip the seqno and ackno fields in the TCP header. */ 01329 c = BUF->seqno[3]; 01330 BUF->seqno[3] = BUF->ackno[3]; 01331 BUF->ackno[3] = c; 01332 01333 c = BUF->seqno[2]; 01334 BUF->seqno[2] = BUF->ackno[2]; 01335 BUF->ackno[2] = c; 01336 01337 c = BUF->seqno[1]; 01338 BUF->seqno[1] = BUF->ackno[1]; 01339 BUF->ackno[1] = c; 01340 01341 c = BUF->seqno[0]; 01342 BUF->seqno[0] = BUF->ackno[0]; 01343 BUF->ackno[0] = c; 01344 01345 /* We also have to increase the sequence number we are 01346 acknowledging. If the least significant byte overflowed, we need 01347 to propagate the carry to the other bytes as well. */ 01348 if (++BUF->ackno[3] == 0) { 01349 if (++BUF->ackno[2] == 0) { 01350 if (++BUF->ackno[1] == 0) { 01351 ++BUF->ackno[0]; 01352 } 01353 } 01354 } 01355 01356 /* Swap port numbers. */ 01357 tmp16 = BUF->srcport; 01358 BUF->srcport = BUF->destport; 01359 BUF->destport = tmp16; 01360 01361 /* Swap IP addresses. */ 01362 uip_ipaddr_copy(BUF->destipaddr, BUF->srcipaddr); 01363 uip_ipaddr_copy(BUF->srcipaddr, uip_hostaddr); 01364 01365 /* And send out the RST packet! */ 01366 goto tcp_send_noconn; 01367 01368 /* This label will be jumped to if we matched the incoming packet 01369 with a connection in LISTEN. In that case, we should create a new 01370 connection and send a SYNACK in return. */ 01371 found_listen: 01372 /* First we check if there are any connections avaliable. Unused 01373 connections are kept in the same table as used connections, but 01374 unused ones have the tcpstate set to CLOSED. Also, connections in 01375 TIME_WAIT are kept track of and we'll use the oldest one if no 01376 CLOSED connections are found. Thanks to Eddie C. Dost for a very 01377 nice algorithm for the TIME_WAIT search. */ 01378 uip_connr = 0; 01379 for (c = 0; c < UIP_CONNS; ++c) { 01380 if (uip_conns[c].tcpstateflags == UIP_CLOSED) { 01381 uip_connr = &uip_conns[c]; 01382 break; 01383 } 01384 01385 if (uip_conns[c].tcpstateflags == UIP_TIME_WAIT) { 01386 if (uip_connr == 0 || uip_conns[c].timer > uip_connr->timer) { 01387 uip_connr = &uip_conns[c]; 01388 } 01389 } 01390 } 01391 01392 if (uip_connr == 0) { 01393 01394 /* All connections are used already, we drop packet and hope that 01395 the remote end will retransmit the packet at a time when we 01396 have more spare connections. */ 01397 UIP_STAT(++uip_stat.tcp.syndrop); 01398 UIP_LOG("tcp: found no unused connections."); 01399 goto drop; 01400 } 01401 01402 uip_conn = uip_connr; 01403 01404 /* Fill in the necessary fields for the new connection. */ 01405 uip_connr->rto = uip_connr->timer = UIP_RTO; 01406 uip_connr->sa = 0; 01407 uip_connr->sv = 4; 01408 uip_connr->nrtx = 0; 01409 uip_connr->lport = BUF->destport; 01410 uip_connr->rport = BUF->srcport; 01411 uip_ipaddr_copy(uip_connr->ripaddr, BUF->srcipaddr); 01412 uip_connr->tcpstateflags = UIP_SYN_RCVD; 01413 01414 uip_connr->snd_nxt[0] = iss[0]; 01415 uip_connr->snd_nxt[1] = iss[1]; 01416 uip_connr->snd_nxt[2] = iss[2]; 01417 uip_connr->snd_nxt[3] = iss[3]; 01418 uip_connr->len = 1; 01419 01420 /* rcv_nxt should be the seqno from the incoming packet + 1. */ 01421 uip_connr->rcv_nxt[3] = BUF->seqno[3]; 01422 uip_connr->rcv_nxt[2] = BUF->seqno[2]; 01423 uip_connr->rcv_nxt[1] = BUF->seqno[1]; 01424 uip_connr->rcv_nxt[0] = BUF->seqno[0]; 01425 uip_add_rcv_nxt(1); 01426 01427 /* Parse the TCP MSS option, if present. */ 01428 if ((BUF->tcpoffset & 0xf0) > 0x50) { 01429 for (c = 0; c < ((BUF->tcpoffset >> 4) - 5) << 2;) { 01430 opt = uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + c]; 01431 if (opt == TCP_OPT_END) { 01432 01433 /* End of options. */ 01434 break; 01435 } 01436 else 01437 if (opt == TCP_OPT_NOOP) { 01438 ++c; 01439 01440 /* NOP option. */ 01441 } 01442 else 01443 if (opt == TCP_OPT_MSS && uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c] == TCP_OPT_MSS_LEN) { 01444 01445 /* An MSS option with the right option length. */ 01446 tmp16 = ((u16_t) uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 2 + c] << 8) | (u16_t) uip_buf[UIP_IPTCPH_LEN + UIP_LLH_LEN + 3 + c]; 01447 uip_connr->initialmss = uip_connr->mss = tmp16 > UIP_TCP_MSS ? UIP_TCP_MSS : tmp16; 01448 01449 /* And we are done processing options. */ 01450 break; 01451 } 01452 else { 01453 01454 /* All other options have a length field, so that we easily 01455 can skip past them. */ 01456 if (uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c] == 0) { 01457 01458 /* If the length field is zero, the options are malformed 01459 and we don't process them further. */ 01460 break; 01461 } 01462 01463 c += uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c]; 01464 } 01465 } 01466 } 01467 01468 /* Our response will be a SYNACK. */ 01469 #if UIP_ACTIVE_OPEN 01470 tcp_send_synack : BUF->flags = TCP_ACK; 01471 01472 tcp_send_syn: 01473 BUF->flags |= TCP_SYN; 01474 #else /* UIP_ACTIVE_OPEN */ 01475 tcp_send_synack : BUF->flags = TCP_SYN | TCP_ACK; 01476 #endif /* UIP_ACTIVE_OPEN */ 01477 01478 /* We send out the TCP Maximum Segment Size option with our 01479 SYNACK. */ 01480 01481 BUF->optdata[0] = TCP_OPT_MSS; 01482 BUF->optdata[1] = TCP_OPT_MSS_LEN; 01483 BUF->optdata[2] = (UIP_TCP_MSS) / 256; 01484 BUF->optdata[3] = (UIP_TCP_MSS) & 255; 01485 uip_len = UIP_IPTCPH_LEN + TCP_OPT_MSS_LEN; 01486 BUF->tcpoffset = ((UIP_TCPH_LEN + TCP_OPT_MSS_LEN) / 4) << 4; 01487 goto tcp_send; 01488 01489 /* This label will be jumped to if we found an active connection. */ 01490 found: 01491 uip_conn = uip_connr; 01492 uip_flags = 0; 01493 01494 /* We do a very naive form of TCP reset processing; we just accept 01495 any RST and kill our connection. We should in fact check if the 01496 sequence number of this reset is wihtin our advertised window 01497 before we accept the reset. */ 01498 if (BUF->flags & TCP_RST) { 01499 uip_connr->tcpstateflags = UIP_CLOSED; 01500 UIP_LOG("tcp: got reset, aborting connection."); 01501 uip_flags = UIP_ABORT; 01502 UIP_APPCALL(); 01503 goto drop; 01504 } 01505 01506 /* Calculated the length of the data, if the application has sent 01507 any data to us. */ 01508 c = (BUF->tcpoffset >> 4) << 2; 01509 01510 /* uip_len will contain the length of the actual TCP data. This is 01511 calculated by subtracing the length of the TCP header (in 01512 c) and the length of the IP header (20 bytes). */ 01513 uip_len = uip_len - c - UIP_IPH_LEN; 01514 01515 /* First, check if the sequence number of the incoming packet is 01516 what we're expecting next. If not, we send out an ACK with the 01517 correct numbers in. */ 01518 if 01519 ( 01520 !(((uip_connr->tcpstateflags & UIP_TS_MASK) == UIP_SYN_SENT) 01521 && ((BUF->flags & TCP_CTL) == (TCP_SYN | TCP_ACK)) 01522 ) 01523 ) { 01524 if 01525 ( 01526 (uip_len > 0 || ((BUF->flags & (TCP_SYN | TCP_FIN)) != 0)) 01527 && ( 01528 BUF->seqno[0] != uip_connr->rcv_nxt[0] 01529 || BUF->seqno[1] != uip_connr->rcv_nxt[1] 01530 || BUF->seqno[2] != uip_connr->rcv_nxt[2] 01531 || BUF->seqno[3] != uip_connr->rcv_nxt[3] 01532 ) 01533 ) { 01534 goto tcp_send_ack; 01535 } 01536 } 01537 01538 /* Next, check if the incoming segment acknowledges any outstanding 01539 data. If so, we update the sequence number, reset the length of 01540 the outstanding data, calculate RTT estimations, and reset the 01541 retransmission timer. */ 01542 if ((BUF->flags & TCP_ACK) && uip_outstanding(uip_connr)) { 01543 uip_add32(uip_connr->snd_nxt, uip_connr->len); 01544 01545 if 01546 ( 01547 BUF->ackno[0] == uip_acc32[0] 01548 && BUF->ackno[1] == uip_acc32[1] 01549 && BUF->ackno[2] == uip_acc32[2] 01550 && BUF->ackno[3] == uip_acc32[3] 01551 ) { 01552 01553 /* Update sequence number. */ 01554 uip_connr->snd_nxt[0] = uip_acc32[0]; 01555 uip_connr->snd_nxt[1] = uip_acc32[1]; 01556 uip_connr->snd_nxt[2] = uip_acc32[2]; 01557 uip_connr->snd_nxt[3] = uip_acc32[3]; 01558 01559 /* Do RTT estimation, unless we have done retransmissions. */ 01560 if (uip_connr->nrtx == 0) { 01561 signed char m; 01562 m = uip_connr->rto - uip_connr->timer; 01563 01564 /* This is taken directly from VJs original code in his paper */ 01565 m = m - (uip_connr->sa >> 3); 01566 uip_connr->sa += m; 01567 if (m < 0) { 01568 m = -m; 01569 } 01570 01571 m = m - (uip_connr->sv >> 2); 01572 uip_connr->sv += m; 01573 uip_connr->rto = (uip_connr->sa >> 3) + uip_connr->sv; 01574 } 01575 01576 /* Set the acknowledged flag. */ 01577 uip_flags = UIP_ACKDATA; 01578 01579 /* Reset the retransmission timer. */ 01580 uip_connr->timer = uip_connr->rto; 01581 01582 /* Reset length of outstanding data. */ 01583 uip_connr->len = 0; 01584 } 01585 } 01586 01587 /* Do different things depending on in what state the connection is. */ 01588 switch (uip_connr->tcpstateflags & UIP_TS_MASK) { 01589 /* CLOSED and LISTEN are not handled here. CLOSE_WAIT is not 01590 implemented, since we force the application to close when the 01591 peer sends a FIN (hence the application goes directly from 01592 ESTABLISHED to LAST_ACK). */ 01593 case UIP_SYN_RCVD: 01594 /* In SYN_RCVD we have sent out a SYNACK in response to a SYN, and 01595 we are waiting for an ACK that acknowledges the data we sent 01596 out the last time. Therefore, we want to have the UIP_ACKDATA 01597 flag set. If so, we enter the ESTABLISHED state. */ 01598 if (uip_flags & UIP_ACKDATA) { 01599 uip_connr->tcpstateflags = UIP_ESTABLISHED; 01600 uip_flags = UIP_CONNECTED; 01601 uip_connr->len = 0; 01602 if (uip_len > 0) { 01603 uip_flags |= UIP_NEWDATA; 01604 uip_add_rcv_nxt(uip_len); 01605 } 01606 01607 uip_slen = 0; 01608 UIP_APPCALL(); 01609 goto appsend; 01610 } 01611 01612 goto drop; 01613 #if UIP_ACTIVE_OPEN 01614 01615 case UIP_SYN_SENT: 01616 /* In SYN_SENT, we wait for a SYNACK that is sent in response to 01617 our SYN. The rcv_nxt is set to sequence number in the SYNACK 01618 plus one, and we send an ACK. We move into the ESTABLISHED 01619 state. */ 01620 if ((uip_flags & UIP_ACKDATA) && (BUF->flags & TCP_CTL) == (TCP_SYN | TCP_ACK)) { 01621 01622 /* Parse the TCP MSS option, if present. */ 01623 if ((BUF->tcpoffset & 0xf0) > 0x50) { 01624 for (c = 0; c < ((BUF->tcpoffset >> 4) - 5) << 2;) { 01625 opt = uip_buf[UIP_IPTCPH_LEN + UIP_LLH_LEN + c]; 01626 if (opt == TCP_OPT_END) { 01627 01628 /* End of options. */ 01629 break; 01630 } 01631 else 01632 if (opt == TCP_OPT_NOOP) { 01633 ++c; 01634 01635 /* NOP option. */ 01636 } 01637 else 01638 if (opt == TCP_OPT_MSS && uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c] == TCP_OPT_MSS_LEN) { 01639 01640 /* An MSS option with the right option length. */ 01641 tmp16 = (uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 2 + c] << 8) | uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 3 + c]; 01642 uip_connr->initialmss = uip_connr->mss = tmp16 > UIP_TCP_MSS ? UIP_TCP_MSS : tmp16; 01643 01644 /* And we are done processing options. */ 01645 break; 01646 } 01647 else { 01648 01649 /* All other options have a length field, so that we easily 01650 can skip past them. */ 01651 if (uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c] == 0) { 01652 01653 /* If the length field is zero, the options are malformed 01654 and we don't process them further. */ 01655 break; 01656 } 01657 01658 c += uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c]; 01659 } 01660 } 01661 } 01662 01663 uip_connr->tcpstateflags = UIP_ESTABLISHED; 01664 uip_connr->rcv_nxt[0] = BUF->seqno[0]; 01665 uip_connr->rcv_nxt[1] = BUF->seqno[1]; 01666 uip_connr->rcv_nxt[2] = BUF->seqno[2]; 01667 uip_connr->rcv_nxt[3] = BUF->seqno[3]; 01668 uip_add_rcv_nxt(1); 01669 uip_flags = UIP_CONNECTED | UIP_NEWDATA; 01670 uip_connr->len = 0; 01671 uip_len = 0; 01672 uip_slen = 0; 01673 UIP_APPCALL(); 01674 goto appsend; 01675 } 01676 01677 /* Inform the application that the connection failed */ 01678 uip_flags = UIP_ABORT; 01679 UIP_APPCALL(); 01680 01681 /* The connection is closed after we send the RST */ 01682 uip_conn->tcpstateflags = UIP_CLOSED; 01683 goto reset; 01684 #endif /* UIP_ACTIVE_OPEN */ 01685 01686 case UIP_ESTABLISHED: 01687 /* In the ESTABLISHED state, we call upon the application to feed 01688 data into the uip_buf. If the UIP_ACKDATA flag is set, the 01689 application should put new data into the buffer, otherwise we are 01690 retransmitting an old segment, and the application should put that 01691 data into the buffer. 01692 01693 If the incoming packet is a FIN, we should close the connection on 01694 this side as well, and we send out a FIN and enter the LAST_ACK 01695 state. We require that there is no outstanding data; otherwise the 01696 sequence numbers will be screwed up. */ 01697 if (BUF->flags & TCP_FIN && !(uip_connr->tcpstateflags & UIP_STOPPED)) { 01698 if (uip_outstanding(uip_connr)) { 01699 goto drop; 01700 } 01701 01702 uip_add_rcv_nxt(1 + uip_len); 01703 uip_flags |= UIP_CLOSE; 01704 if (uip_len > 0) { 01705 uip_flags |= UIP_NEWDATA; 01706 } 01707 01708 UIP_APPCALL(); 01709 uip_connr->len = 1; 01710 uip_connr->tcpstateflags = UIP_LAST_ACK; 01711 uip_connr->nrtx = 0; 01712 tcp_send_finack: 01713 BUF->flags = TCP_FIN | TCP_ACK; 01714 goto tcp_send_nodata; 01715 } 01716 01717 /* Check the URG flag. If this is set, the segment carries urgent 01718 data that we must pass to the application. */ 01719 if ((BUF->flags & TCP_URG) != 0) 01720 { 01721 #if UIP_URGDATA > 0 01722 uip_urglen = (BUF->urgp[0] << 8) | BUF->urgp[1]; 01723 if (uip_urglen > uip_len) { 01724 01725 /* There is more urgent data in the next segment to come. */ 01726 uip_urglen = uip_len; 01727 } 01728 01729 uip_add_rcv_nxt(uip_urglen); 01730 uip_len -= uip_urglen; 01731 uip_urgdata = uip_appdata; 01732 uip_appdata += uip_urglen; 01733 } 01734 else { 01735 uip_urglen = 0; 01736 #else /* UIP_URGDATA > 0 */ 01737 uip_appdata = ((char*)uip_appdata) + ((BUF->urgp[0] << 8) | BUF->urgp[1]); 01738 uip_len -= (BUF->urgp[0] << 8) | BUF->urgp[1]; 01739 #endif /* UIP_URGDATA > 0 */ 01740 } 01741 01742 /* If uip_len > 0 we have TCP data in the packet, and we flag this 01743 by setting the UIP_NEWDATA flag and update the sequence number 01744 we acknowledge. If the application has stopped the dataflow 01745 using uip_stop(), we must not accept any data packets from the 01746 remote host. */ 01747 if (uip_len > 0 && !(uip_connr->tcpstateflags & UIP_STOPPED)) { 01748 uip_flags |= UIP_NEWDATA; 01749 uip_add_rcv_nxt(uip_len); 01750 } 01751 01752 /* Check if the available buffer space advertised by the other end 01753 is smaller than the initial MSS for this connection. If so, we 01754 set the current MSS to the window size to ensure that the 01755 application does not send more data than the other end can 01756 handle. 01757 01758 If the remote host advertises a zero window, we set the MSS to 01759 the initial MSS so that the application will send an entire MSS 01760 of data. This data will not be acknowledged by the receiver, 01761 and the application will retransmit it. This is called the 01762 "persistent timer" and uses the retransmission mechanim. 01763 */ 01764 tmp16 = ((u16_t) BUF->wnd[0] << 8) + (u16_t) BUF->wnd[1]; 01765 if (tmp16 > uip_connr->initialmss || tmp16 == 0) { 01766 tmp16 = uip_connr->initialmss; 01767 } 01768 01769 uip_connr->mss = tmp16; 01770 01771 /* If this packet constitutes an ACK for outstanding data (flagged 01772 by the UIP_ACKDATA flag, we should call the application since it 01773 might want to send more data. If the incoming packet had data 01774 from the peer (as flagged by the UIP_NEWDATA flag), the 01775 application must also be notified. 01776 01777 When the application is called, the global variable uip_len 01778 contains the length of the incoming data. The application can 01779 access the incoming data through the global pointer 01780 uip_appdata, which usually points UIP_IPTCPH_LEN + UIP_LLH_LEN 01781 bytes into the uip_buf array. 01782 01783 If the application wishes to send any data, this data should be 01784 put into the uip_appdata and the length of the data should be 01785 put into uip_len. If the application don't have any data to 01786 send, uip_len must be set to 0. */ 01787 if (uip_flags & (UIP_NEWDATA | UIP_ACKDATA)) { 01788 uip_slen = 0; 01789 UIP_APPCALL(); 01790 01791 appsend: 01792 if (uip_flags & UIP_ABORT) { 01793 uip_slen = 0; 01794 uip_connr->tcpstateflags = UIP_CLOSED; 01795 BUF->flags = TCP_RST | TCP_ACK; 01796 goto tcp_send_nodata; 01797 } 01798 01799 if (uip_flags & UIP_CLOSE) { 01800 uip_slen = 0; 01801 uip_connr->len = 1; 01802 uip_connr->tcpstateflags = UIP_FIN_WAIT_1; 01803 uip_connr->nrtx = 0; 01804 BUF->flags = TCP_FIN | TCP_ACK; 01805 goto tcp_send_nodata; 01806 } 01807 01808 /* If uip_slen > 0, the application has data to be sent. */ 01809 if (uip_slen > 0) { 01810 01811 /* If the connection has acknowledged data, the contents of 01812 the ->len variable should be discarded. */ 01813 if ((uip_flags & UIP_ACKDATA) != 0) { 01814 uip_connr->len = 0; 01815 } 01816 01817 /* If the ->len variable is non-zero the connection has 01818 already data in transit and cannot send anymore right 01819 now. */ 01820 if (uip_connr->len == 0) { 01821 01822 /* The application cannot send more than what is allowed by 01823 the mss (the minumum of the MSS and the available 01824 window). */ 01825 if (uip_slen > uip_connr->mss) { 01826 uip_slen = uip_connr->mss; 01827 } 01828 01829 /* Remember how much data we send out now so that we know 01830 when everything has been acknowledged. */ 01831 uip_connr->len = uip_slen; 01832 } 01833 else { 01834 01835 /* If the application already had unacknowledged data, we 01836 make sure that the application does not send (i.e., 01837 retransmit) out more than it previously sent out. */ 01838 uip_slen = uip_connr->len; 01839 } 01840 } 01841 01842 uip_connr->nrtx = 0; 01843 apprexmit: 01844 uip_appdata = uip_sappdata; 01845 01846 /* If the application has data to be sent, or if the incoming 01847 packet had new data in it, we must send out a packet. */ 01848 if (uip_slen > 0 && uip_connr->len > 0) { 01849 01850 /* Add the length of the IP and TCP headers. */ 01851 uip_len = uip_connr->len + UIP_TCPIP_HLEN; 01852 01853 /* We always set the ACK flag in response packets. */ 01854 BUF->flags = TCP_ACK | TCP_PSH; 01855 01856 /* Send the packet. */ 01857 goto tcp_send_noopts; 01858 } 01859 01860 /* If there is no data to send, just send out a pure ACK if 01861 there is newdata. */ 01862 if (uip_flags & UIP_NEWDATA) { 01863 uip_len = UIP_TCPIP_HLEN; 01864 BUF->flags = TCP_ACK; 01865 goto tcp_send_noopts; 01866 } 01867 } 01868 01869 goto drop; 01870 01871 case UIP_LAST_ACK: 01872 /* We can close this connection if the peer has acknowledged our 01873 FIN. This is indicated by the UIP_ACKDATA flag. */ 01874 if (uip_flags & UIP_ACKDATA) { 01875 uip_connr->tcpstateflags = UIP_CLOSED; 01876 uip_flags = UIP_CLOSE; 01877 UIP_APPCALL(); 01878 } 01879 break; 01880 01881 case UIP_FIN_WAIT_1: 01882 /* The application has closed the connection, but the remote host 01883 hasn't closed its end yet. Thus we do nothing but wait for a 01884 FIN from the other side. */ 01885 if (uip_len > 0) { 01886 uip_add_rcv_nxt(uip_len); 01887 } 01888 01889 if (BUF->flags & TCP_FIN) { 01890 if (uip_flags & UIP_ACKDATA) { 01891 uip_connr->tcpstateflags = UIP_TIME_WAIT; 01892 uip_connr->timer = 0; 01893 uip_connr->len = 0; 01894 } 01895 else { 01896 uip_connr->tcpstateflags = UIP_CLOSING; 01897 } 01898 01899 uip_add_rcv_nxt(1); 01900 uip_flags = UIP_CLOSE; 01901 UIP_APPCALL(); 01902 goto tcp_send_ack; 01903 } 01904 else 01905 if (uip_flags & UIP_ACKDATA) { 01906 uip_connr->tcpstateflags = UIP_FIN_WAIT_2; 01907 uip_connr->len = 0; 01908 goto drop; 01909 } 01910 01911 if (uip_len > 0) { 01912 goto tcp_send_ack; 01913 } 01914 01915 goto drop; 01916 01917 case UIP_FIN_WAIT_2: 01918 if (uip_len > 0) { 01919 uip_add_rcv_nxt(uip_len); 01920 } 01921 01922 if (BUF->flags & TCP_FIN) { 01923 uip_connr->tcpstateflags = UIP_TIME_WAIT; 01924 uip_connr->timer = 0; 01925 uip_add_rcv_nxt(1); 01926 uip_flags = UIP_CLOSE; 01927 UIP_APPCALL(); 01928 goto tcp_send_ack; 01929 } 01930 01931 if (uip_len > 0) { 01932 goto tcp_send_ack; 01933 } 01934 01935 goto drop; 01936 01937 case UIP_TIME_WAIT: 01938 goto tcp_send_ack; 01939 01940 case UIP_CLOSING: 01941 if (uip_flags & UIP_ACKDATA) { 01942 uip_connr->tcpstateflags = UIP_TIME_WAIT; 01943 uip_connr->timer = 0; 01944 } 01945 } 01946 01947 goto drop; 01948 01949 /* We jump here when we are ready to send the packet, and just want 01950 to set the appropriate TCP sequence numbers in the TCP header. */ 01951 tcp_send_ack: 01952 BUF->flags = TCP_ACK; 01953 tcp_send_nodata: 01954 uip_len = UIP_IPTCPH_LEN; 01955 tcp_send_noopts: 01956 BUF->tcpoffset = (UIP_TCPH_LEN / 4) << 4; 01957 tcp_send: 01958 /* We're done with the input processing. We are now ready to send a 01959 reply. Our job is to fill in all the fields of the TCP and IP 01960 headers before calculating the checksum and finally send the 01961 packet. */ 01962 BUF->ackno[0] = uip_connr->rcv_nxt[0]; 01963 BUF->ackno[1] = uip_connr->rcv_nxt[1]; 01964 BUF->ackno[2] = uip_connr->rcv_nxt[2]; 01965 BUF->ackno[3] = uip_connr->rcv_nxt[3]; 01966 01967 BUF->seqno[0] = uip_connr->snd_nxt[0]; 01968 BUF->seqno[1] = uip_connr->snd_nxt[1]; 01969 BUF->seqno[2] = uip_connr->snd_nxt[2]; 01970 BUF->seqno[3] = uip_connr->snd_nxt[3]; 01971 01972 BUF->proto = UIP_PROTO_TCP; 01973 01974 BUF->srcport = uip_connr->lport; 01975 BUF->destport = uip_connr->rport; 01976 01977 uip_ipaddr_copy(BUF->srcipaddr, uip_hostaddr); 01978 uip_ipaddr_copy(BUF->destipaddr, uip_connr->ripaddr); 01979 01980 if (uip_connr->tcpstateflags & UIP_STOPPED) { 01981 01982 /* If the connection has issued uip_stop(), we advertise a zero 01983 window so that the remote host will stop sending data. */ 01984 BUF->wnd[0] = BUF->wnd[1] = 0; 01985 } 01986 else { 01987 BUF->wnd[0] = ((UIP_RECEIVE_WINDOW) >> 8); 01988 BUF->wnd[1] = ((UIP_RECEIVE_WINDOW) & 0xff); 01989 } 01990 01991 tcp_send_noconn: 01992 BUF->ttl = UIP_TTL; 01993 #if UIP_CONF_IPV6 01994 /* For IPv6, the IP length field does not include the IPv6 IP header 01995 length. */ 01996 01997 BUF->len[0] = ((uip_len - UIP_IPH_LEN) >> 8); 01998 BUF->len[1] = ((uip_len - UIP_IPH_LEN) & 0xff); 01999 #else /* UIP_CONF_IPV6 */ 02000 BUF->len[0] = (uip_len >> 8); 02001 BUF->len[1] = (uip_len & 0xff); 02002 #endif /* UIP_CONF_IPV6 */ 02003 02004 BUF->urgp[0] = BUF->urgp[1] = 0; 02005 02006 /* Calculate TCP checksum. */ 02007 BUF->tcpchksum = 0; 02008 BUF->tcpchksum = ~(uip_tcpchksum()); 02009 02010 ip_send_nolen: 02011 #if UIP_CONF_IPV6 02012 BUF->vtc = 0x60; 02013 BUF->tcflow = 0x00; 02014 BUF->flow = 0x00; 02015 #else /* UIP_CONF_IPV6 */ 02016 BUF->vhl = 0x45; 02017 BUF->tos = 0; 02018 BUF->ipoffset[0] = BUF->ipoffset[1] = 0; 02019 ++ipid; 02020 BUF->ipid[0] = ipid >> 8; 02021 BUF->ipid[1] = ipid & 0xff; 02022 02023 /* Calculate IP checksum. */ 02024 BUF->ipchksum = 0; 02025 BUF->ipchksum = ~(uip_ipchksum()); 02026 DEBUG_PRINTF("uip ip_send_nolen: chkecum 0x%04x\n", uip_ipchksum()); 02027 #endif /* UIP_CONF_IPV6 */ 02028 02029 UIP_STAT(++uip_stat.tcp.sent); 02030 send: 02031 DEBUG_PRINTF("Sending packet with length %d (%d)\n", uip_len, (BUF->len[0] << 8) | BUF->len[1]); 02032 02033 UIP_STAT(++uip_stat.ip.sent); 02034 02035 /* Return and let the caller do the actual transmission. */ 02036 uip_flags = 0; 02037 return; 02038 drop: 02039 uip_len = 0; 02040 uip_flags = 0; 02041 return; 02042 } 02043 02044 /*---------------------------------------------------------------------------*/ 02045 u16_t htons(u16_t val) { 02046 return HTONS(val); 02047 } 02048 02049 /*---------------------------------------------------------------------------*/ 02050 void uip_send(const void* data, int len) { 02051 uip_slen = len; 02052 if (len > 0) { 02053 if (data != uip_sappdata) { 02054 memcpy(uip_sappdata, (data), uip_slen); 02055 } 02056 } 02057 } 02058 02059 /** @} */
Generated on Tue Jul 12 2022 18:48:00 by 1.7.2