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