ban4jp -
/
uIP-1-0_webserver
uIP 1.0 based webserver for LPC1114 + ENC28J60
Embed:
(wiki syntax)
Show/hide line numbers
uip-fw.c
Go to the documentation of this file.
00001 /* 00002 * Copyright (c) 2004, Swedish Institute of Computer Science. 00003 * All rights reserved. 00004 * 00005 * Redistribution and use in source and binary forms, with or without 00006 * modification, are permitted provided that the following conditions 00007 * are met: 00008 * 1. Redistributions of source code must retain the above copyright 00009 * notice, this list of conditions and the following disclaimer. 00010 * 2. Redistributions in binary form must reproduce the above copyright 00011 * notice, this list of conditions and the following disclaimer in the 00012 * documentation and/or other materials provided with the distribution. 00013 * 3. Neither the name of the Institute nor the names of its contributors 00014 * may be used to endorse or promote products derived from this software 00015 * without specific prior written permission. 00016 * 00017 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 00018 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 00019 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 00020 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 00021 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 00022 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 00023 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 00024 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 00025 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 00026 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 00027 * SUCH DAMAGE. 00028 * 00029 * This file is part of the Contiki operating system. 00030 * 00031 * Author: Adam Dunkels <adam@sics.se> 00032 * 00033 */ 00034 /** 00035 * \addtogroup uip 00036 * @{ 00037 */ 00038 00039 /** 00040 * \defgroup uipfw uIP packet forwarding 00041 * @{ 00042 * 00043 */ 00044 00045 /** 00046 * \file 00047 * uIP packet forwarding. 00048 * \author Adam Dunkels <adam@sics.se> 00049 * 00050 * This file implements a number of simple functions which do packet 00051 * forwarding over multiple network interfaces with uIP. 00052 * 00053 */ 00054 00055 #include <string.h> 00056 00057 #include "uip-conf.h" 00058 00059 #include "uip.h" 00060 #include "uip_arch.h" 00061 #include "uip-fw.h" 00062 #ifdef AODV_COMPLIANCE 00063 #include "uaodv-def.h" 00064 #endif 00065 00066 /* 00067 * The list of registered network interfaces. 00068 */ 00069 static struct uip_fw_netif *netifs = NULL; 00070 00071 /* 00072 * A pointer to the default network interface. 00073 */ 00074 static struct uip_fw_netif *defaultnetif = NULL; 00075 00076 struct tcpip_hdr { 00077 /* IP header. */ 00078 uint8_t vhl, 00079 tos; 00080 uint16_t len, 00081 ipid, 00082 ipoffset; 00083 uint8_t ttl, 00084 proto; 00085 uint16_t ipchksum; 00086 uip_ipaddr_t srcipaddr, destipaddr; 00087 00088 /* TCP header. */ 00089 uint16_t srcport, 00090 destport; 00091 uint8_t seqno[4], 00092 ackno[4], 00093 tcpoffset, 00094 flags, 00095 wnd[2]; 00096 uint16_t tcpchksum; 00097 uint8_t urgp[2]; 00098 uint8_t optdata[4]; 00099 }; 00100 00101 struct icmpip_hdr { 00102 /* IP header. */ 00103 uint8_t vhl, 00104 tos, 00105 len[2], 00106 ipid[2], 00107 ipoffset[2], 00108 ttl, 00109 proto; 00110 uint16_t ipchksum; 00111 uip_ipaddr_t srcipaddr, destipaddr; 00112 /* ICMP (echo) header. */ 00113 uint8_t type, icode; 00114 uint16_t icmpchksum; 00115 uint16_t id, seqno; 00116 uint8_t payload[1]; 00117 }; 00118 00119 /* ICMP ECHO. */ 00120 #define ICMP_ECHO 8 00121 00122 /* ICMP TIME-EXCEEDED. */ 00123 #define ICMP_TE 11 00124 00125 /* 00126 * Pointer to the TCP/IP headers of the packet in the uip_buf buffer. 00127 */ 00128 #define BUF ((struct tcpip_hdr *)&uip_buf[UIP_LLH_LEN]) 00129 00130 /* 00131 * Pointer to the ICMP/IP headers of the packet in the uip_buf buffer. 00132 */ 00133 #define ICMPBUF ((struct icmpip_hdr *)&uip_buf[UIP_LLH_LEN]) 00134 00135 /* 00136 * Certain fields of an IP packet that are used for identifying 00137 * duplicate packets. 00138 */ 00139 struct fwcache_entry { 00140 uint16_t timer; 00141 00142 uip_ipaddr_t srcipaddr; 00143 uip_ipaddr_t destipaddr; 00144 uint16_t ipid; 00145 uint8_t proto; 00146 uint8_t unused; 00147 00148 #if notdef 00149 uint16_t payload[2]; 00150 #endif 00151 00152 #if UIP_REASSEMBLY > 0 00153 uint16_t len, offset; 00154 #endif 00155 }; 00156 00157 /* 00158 * The number of packets to remember when looking for duplicates. 00159 */ 00160 #ifdef UIP_CONF_FWCACHE_SIZE 00161 #define FWCACHE_SIZE UIP_CONF_FWCACHE_SIZE 00162 #else 00163 #define FWCACHE_SIZE 2 00164 #endif 00165 00166 00167 /* 00168 * A cache of packet header fields which are used for 00169 * identifying duplicate packets. 00170 */ 00171 static struct fwcache_entry fwcache[FWCACHE_SIZE]; 00172 00173 /** 00174 * \internal 00175 * The time that a packet cache is active. 00176 */ 00177 #define FW_TIME 20 00178 00179 /*------------------------------------------------------------------------------*/ 00180 /** 00181 * Initialize the uIP packet forwarding module. 00182 */ 00183 /*------------------------------------------------------------------------------*/ 00184 void 00185 uip_fw_init(void) 00186 { 00187 struct uip_fw_netif *t; 00188 defaultnetif = NULL; 00189 while(netifs != NULL) { 00190 t = netifs; 00191 netifs = netifs->next; 00192 t->next = NULL; 00193 } 00194 } 00195 /*------------------------------------------------------------------------------*/ 00196 /** 00197 * \internal 00198 * Check if an IP address is within the network defined by an IP 00199 * address and a netmask. 00200 * 00201 * \param ipaddr The IP address to be checked. 00202 * \param netipaddr The IP address of the network. 00203 * \param netmask The netmask of the network. 00204 * 00205 * \return Non-zero if IP address is in network, zero otherwise. 00206 */ 00207 /*------------------------------------------------------------------------------*/ 00208 static unsigned char 00209 ipaddr_maskcmp(uip_ipaddr_t *ipaddr, 00210 uip_ipaddr_t *netipaddr, 00211 uip_ipaddr_t *netmask) 00212 { 00213 return (ipaddr->u16[0] & netmask->u16[0]) == (netipaddr->u16[0] & netmask->u16[0]) && 00214 (ipaddr->u16[1] & netmask->u16[1]) == (netipaddr->u16[1] & netmask->u16[1]); 00215 } 00216 /*------------------------------------------------------------------------------*/ 00217 /** 00218 * \internal 00219 * Send out an ICMP TIME-EXCEEDED message. 00220 * 00221 * This function replaces the packet in the uip_buf buffer with the 00222 * ICMP packet. 00223 */ 00224 /*------------------------------------------------------------------------------*/ 00225 static void 00226 time_exceeded(void) 00227 { 00228 00229 /* We don't send out ICMP errors for ICMP messages (unless they are pings). */ 00230 if(ICMPBUF->proto == UIP_PROTO_ICMP && 00231 ICMPBUF->type != ICMP_ECHO) { 00232 uip_len = 0; 00233 return; 00234 } 00235 /* Copy fields from packet header into payload of this ICMP packet. */ 00236 memcpy(&(ICMPBUF->payload[0]), ICMPBUF, UIP_IPH_LEN + 8); 00237 00238 /* Set the ICMP type and code. */ 00239 ICMPBUF->type = ICMP_TE; 00240 ICMPBUF->icode = 0; 00241 00242 /* Calculate the ICMP checksum. */ 00243 ICMPBUF->icmpchksum = 0; 00244 ICMPBUF->icmpchksum = ~uip_chksum((uint16_t *)&(ICMPBUF->type), 36); 00245 00246 /* Set the IP destination address to be the source address of the 00247 original packet. */ 00248 uip_ipaddr_copy(&BUF->destipaddr, &BUF->srcipaddr); 00249 00250 /* Set our IP address as the source address. */ 00251 uip_ipaddr_copy(&BUF->srcipaddr, &uip_hostaddr); 00252 00253 /* The size of the ICMP time exceeded packet is 36 + the size of the 00254 IP header (20) = 56. */ 00255 uip_len = 56; 00256 ICMPBUF->len[0] = 0; 00257 ICMPBUF->len[1] = (uint8_t)uip_len; 00258 00259 /* Fill in the other fields in the IP header. */ 00260 ICMPBUF->vhl = 0x45; 00261 ICMPBUF->tos = 0; 00262 ICMPBUF->ipoffset[0] = ICMPBUF->ipoffset[1] = 0; 00263 ICMPBUF->ttl = UIP_TTL; 00264 ICMPBUF->proto = UIP_PROTO_ICMP; 00265 00266 /* Calculate IP checksum. */ 00267 ICMPBUF->ipchksum = 0; 00268 ICMPBUF->ipchksum = ~(uip_ipchksum()); 00269 00270 00271 } 00272 /*------------------------------------------------------------------------------*/ 00273 /** 00274 * \internal 00275 * Register a packet in the forwarding cache so that it won't be 00276 * forwarded again. 00277 */ 00278 /*------------------------------------------------------------------------------*/ 00279 static void 00280 fwcache_register(void) 00281 { 00282 struct fwcache_entry *fw; 00283 int i, oldest; 00284 00285 oldest = FW_TIME; 00286 fw = NULL; 00287 00288 /* Find the oldest entry in the cache. */ 00289 for(i = 0; i < FWCACHE_SIZE; ++i) { 00290 if(fwcache[i].timer == 0) { 00291 fw = &fwcache[i]; 00292 break; 00293 } else if(fwcache[i].timer <= oldest) { 00294 fw = &fwcache[i]; 00295 oldest = fwcache[i].timer; 00296 } 00297 } 00298 00299 fw->timer = FW_TIME; 00300 fw->ipid = BUF->ipid; 00301 uip_ipaddr_copy(&fw->srcipaddr, &BUF->srcipaddr); 00302 uip_ipaddr_copy(&fw->destipaddr, &BUF->destipaddr); 00303 fw->proto = BUF->proto; 00304 #if notdef 00305 fw->payload[0] = BUF->srcport; 00306 fw->payload[1] = BUF->destport; 00307 #endif 00308 #if UIP_REASSEMBLY > 0 00309 fw->len = BUF->len; 00310 fw->offset = BUF->ipoffset; 00311 #endif 00312 } 00313 /*------------------------------------------------------------------------------*/ 00314 /** 00315 * \internal 00316 * Find a network interface for the IP packet in uip_buf. 00317 */ 00318 /*------------------------------------------------------------------------------*/ 00319 static struct uip_fw_netif * 00320 find_netif(void) 00321 { 00322 struct uip_fw_netif *netif; 00323 00324 /* Walk through every network interface to check for a match. */ 00325 for(netif = netifs; netif != NULL; netif = netif->next) { 00326 if(ipaddr_maskcmp(&BUF->destipaddr, &netif->ipaddr, 00327 &netif->netmask)) { 00328 /* If there was a match, we break the loop. */ 00329 return netif; 00330 } 00331 } 00332 00333 /* If no matching netif was found, we use default netif. */ 00334 return defaultnetif; 00335 } 00336 /*------------------------------------------------------------------------------*/ 00337 /** 00338 * Output an IP packet on the correct network interface. 00339 * 00340 * The IP packet should be present in the uip_buf buffer and its 00341 * length in the global uip_len variable. 00342 * 00343 * \retval UIP_FW_ZEROLEN Indicates that a zero-length packet 00344 * transmission was attempted and that no packet was sent. 00345 * 00346 * \retval UIP_FW_NOROUTE No suitable network interface could be found 00347 * for the outbound packet, and the packet was not sent. 00348 * 00349 * \return The return value from the actual network interface output 00350 * function is passed unmodified as a return value. 00351 */ 00352 /*------------------------------------------------------------------------------*/ 00353 uint8_t 00354 uip_fw_output(void) 00355 { 00356 struct uip_fw_netif *netif; 00357 #if UIP_BROADCAST 00358 const struct uip_udpip_hdr *udp = (void *)BUF; 00359 #endif /* UIP_BROADCAST */ 00360 00361 if(uip_len == 0) { 00362 return UIP_FW_ZEROLEN; 00363 } 00364 00365 fwcache_register(); 00366 00367 #if UIP_BROADCAST 00368 /* Link local broadcasts go out on all interfaces. */ 00369 if(uip_ipaddr_cmp(&udp->destipaddr, &uip_broadcast_addr)) { 00370 if(defaultnetif != NULL) { 00371 defaultnetif->output(); 00372 } 00373 for(netif = netifs; netif != NULL; netif = netif->next) { 00374 netif->output(); 00375 } 00376 return UIP_FW_OK; 00377 } 00378 #endif /* UIP_BROADCAST */ 00379 00380 netif = find_netif(); 00381 /* printf("uip_fw_output: netif %p ->output %p len %d\n", netif, 00382 netif->output, 00383 uip_len);*/ 00384 00385 if(netif == NULL) { 00386 return UIP_FW_NOROUTE; 00387 } 00388 /* If we now have found a suitable network interface, we call its 00389 output function to send out the packet. */ 00390 return netif->output(); 00391 } 00392 /*------------------------------------------------------------------------------*/ 00393 /** 00394 * Forward an IP packet in the uip_buf buffer. 00395 * 00396 * 00397 * 00398 * \return UIP_FW_FORWARDED if the packet was forwarded, UIP_FW_LOCAL if 00399 * the packet should be processed locally. 00400 */ 00401 /*------------------------------------------------------------------------------*/ 00402 uint8_t 00403 uip_fw_forward(void) 00404 { 00405 struct fwcache_entry *fw; 00406 00407 /* First check if the packet is destined for ourselves and return 0 00408 to indicate that the packet should be processed locally. */ 00409 if(uip_ipaddr_cmp(&BUF->destipaddr, &uip_hostaddr)) { 00410 return UIP_FW_LOCAL; 00411 } 00412 00413 #ifdef AODV_COMPLIANCE 00414 #define udp ((struct uip_udpip_hdr *)&uip_buf[UIP_LLH_LEN]) 00415 if(udp->proto == UIP_PROTO_UDP && udp->destport == UIP_HTONS(UAODV_UDPPORT)) { 00416 return UIP_FW_LOCAL; 00417 } 00418 #endif 00419 00420 /* If we use ping IP address configuration, and our IP address is 00421 not yet configured, we should intercept all ICMP echo packets. */ 00422 #if UIP_PINGADDRCONF 00423 if(uip_ipaddr_cmp(&uip_hostaddr, &uip_all_zeroes_addr) && 00424 BUF->proto == UIP_PROTO_ICMP && 00425 ICMPBUF->type == ICMP_ECHO) { 00426 return UIP_FW_LOCAL; 00427 } 00428 #endif /* UIP_PINGADDRCONF */ 00429 00430 /* Check if the packet is in the forwarding cache already, and if so 00431 we drop it. */ 00432 00433 for(fw = fwcache; fw < &fwcache[FWCACHE_SIZE]; ++fw) { 00434 if(fw->timer != 0 && 00435 #if UIP_REASSEMBLY > 0 00436 fw->len == BUF->len && 00437 fw->offset == BUF->ipoffset && 00438 #endif 00439 fw->ipid == BUF->ipid && 00440 uip_ipaddr_cmp(&fw->srcipaddr, &BUF->srcipaddr) && 00441 uip_ipaddr_cmp(&fw->destipaddr, &BUF->destipaddr) && 00442 #if notdef 00443 fw->payload[0] == BUF->srcport && 00444 fw->payload[1] == BUF->destport && 00445 #endif 00446 fw->proto == BUF->proto) { 00447 /* Drop packet. */ 00448 return UIP_FW_FORWARDED; 00449 } 00450 } 00451 00452 /* If the TTL reaches zero we produce an ICMP time exceeded message 00453 in the uip_buf buffer and forward that packet back to the sender 00454 of the packet. */ 00455 00456 if(BUF->ttl <= 1) { 00457 /* No time exceeded for broadcasts and multicasts! */ 00458 if(uip_ipaddr_cmp(&BUF->destipaddr, &uip_broadcast_addr)) { 00459 return UIP_FW_LOCAL; 00460 } 00461 time_exceeded(); 00462 } 00463 00464 /* Decrement the TTL (time-to-live) value in the IP header */ 00465 BUF->ttl = BUF->ttl - 1; 00466 00467 /* Update the IP checksum. */ 00468 if(BUF->ipchksum >= UIP_HTONS(0xffff - 0x0100)) { 00469 BUF->ipchksum = BUF->ipchksum + UIP_HTONS(0x0100) + 1; 00470 } else { 00471 BUF->ipchksum = BUF->ipchksum + UIP_HTONS(0x0100); 00472 } 00473 00474 if(uip_len > 0) { 00475 uip_appdata = &uip_buf[UIP_LLH_LEN + UIP_TCPIP_HLEN]; 00476 uip_fw_output(); 00477 } 00478 00479 #if UIP_BROADCAST 00480 if(uip_ipaddr_cmp(&BUF->destipaddr, &uip_broadcast_addr)) { 00481 return UIP_FW_LOCAL; 00482 } 00483 #endif /* UIP_BROADCAST */ 00484 00485 /* Return non-zero to indicate that the packet was forwarded and that no 00486 other processing should be made. */ 00487 return UIP_FW_FORWARDED; 00488 } 00489 /*------------------------------------------------------------------------------*/ 00490 /** 00491 * Register a network interface with the forwarding module. 00492 * 00493 * \param netif A pointer to the network interface that is to be 00494 * registered. 00495 */ 00496 /*------------------------------------------------------------------------------*/ 00497 void 00498 uip_fw_register(struct uip_fw_netif *netif) 00499 { 00500 netif->next = netifs; 00501 netifs = netif; 00502 } 00503 /*------------------------------------------------------------------------------*/ 00504 /** 00505 * Register a default network interface. 00506 * 00507 * All packets that don't go out on any of the other interfaces will 00508 * be routed to the default interface. 00509 * 00510 * \param netif A pointer to the network interface that is to be 00511 * registered. 00512 */ 00513 /*------------------------------------------------------------------------------*/ 00514 void 00515 uip_fw_default(struct uip_fw_netif *netif) 00516 { 00517 defaultnetif = netif; 00518 } 00519 /*------------------------------------------------------------------------------*/ 00520 /** 00521 * Perform periodic processing. 00522 */ 00523 /*------------------------------------------------------------------------------*/ 00524 void 00525 uip_fw_periodic(void) 00526 { 00527 struct fwcache_entry *fw; 00528 for(fw = fwcache; fw < &fwcache[FWCACHE_SIZE]; ++fw) { 00529 if(fw->timer > 0) { 00530 --fw->timer; 00531 } 00532 } 00533 } 00534 /*------------------------------------------------------------------------------*/ 00535 /** @} */ 00536 /** @} */
Generated on Tue Jul 12 2022 12:52:12 by 1.7.2