1/* 2 * Copyright (c) 2001-2004 Swedish Institute of Computer Science. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without modification, 6 * are permitted provided that the following conditions are met: 7 * 8 * 1. Redistributions of source code must retain the above copyright notice, 9 * this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright notice, 11 * this list of conditions and the following disclaimer in the documentation 12 * and/or other materials provided with the distribution. 13 * 3. The name of the author may not be used to endorse or promote products 14 * derived from this software without specific prior written permission. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 18 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 19 * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 20 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 21 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 22 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 23 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 24 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 25 * OF SUCH DAMAGE. 26 * 27 * This file is part of the lwIP TCP/IP stack. 28 * 29 * Author: Adam Dunkels <adam@sics.se> 30 * 31 */ 32 33 34 35/* ip.c 36 * 37 * This is the code for the IP layer for IPv6. 38 * 39 */ 40 41 42#include "lwip/opt.h" 43 44#include "lwip/def.h" 45#include "lwip/mem.h" 46#include "lwip/ip.h" 47#include "lwip/inet.h" 48#include "lwip/netif.h" 49#include "lwip/icmp.h" 50#include "lwip/udp.h" 51#include "lwip/tcp.h" 52 53#include "lwip/stats.h" 54 55#include "arch/perf.h" 56 57/* ip_init: 58 * 59 * Initializes the IP layer. 60 */ 61 62void ip_init(void) 63{ 64} 65 66/* ip_route: 67 * 68 * Finds the appropriate network interface for a given IP address. It searches the 69 * list of network interfaces linearly. A match is found if the masked IP address of 70 * the network interface equals the masked IP address given to the function. 71 */ 72 73struct netif *ip_route(struct ip_addr *dest) 74{ 75 struct netif *netif; 76 77 for (netif = netif_list; netif != NULL; netif = netif->next) { 78 if (ip_addr_netcmp(dest, &(netif->ip_addr), &(netif->netmask))) { 79 return netif; 80 } 81 } 82 83 return netif_default; 84} 85 86/* ip_forward: 87 * 88 * Forwards an IP packet. It finds an appropriate route for the packet, decrements 89 * the TTL value of the packet, adjusts the checksum and outputs the packet on the 90 * appropriate interface. 91 */ 92 93static void ip_forward(struct pbuf *p, struct ip_hdr *iphdr) 94{ 95 struct netif *netif; 96 97 PERF_START; 98 99 if ((netif = ip_route((struct ip_addr *) &(iphdr->dest))) == NULL) { 100 101 LWIP_DEBUGF(IP_DEBUG, ("ip_input: no forwarding route found for ")); 102#if IP_DEBUG 103 ip_addr_debug_print(IP_DEBUG, ((struct ip_addr *) &(iphdr->dest))); 104#endif /* IP_DEBUG */ 105 LWIP_DEBUGF(IP_DEBUG, ("\n")); 106 pbuf_free(p); 107 return; 108 } 109 /* Decrement TTL and send ICMP if ttl == 0. */ 110 if (--iphdr->hoplim == 0) { 111#if LWIP_ICMP 112 /* Don't send ICMP messages in response to ICMP messages */ 113 if (iphdr->nexthdr != IP_PROTO_ICMP) { 114 icmp_time_exceeded(p, ICMP_TE_TTL); 115 } 116#endif /* LWIP_ICMP */ 117 pbuf_free(p); 118 return; 119 } 120 121 /* Incremental update of the IP checksum. */ 122 /* if (iphdr->chksum >= htons(0xffff - 0x100)) { 123 iphdr->chksum += htons(0x100) + 1; 124 } else { 125 iphdr->chksum += htons(0x100); 126 } */ 127 128 129 LWIP_DEBUGF(IP_DEBUG, ("ip_forward: forwarding packet to ")); 130#if IP_DEBUG 131 ip_addr_debug_print(IP_DEBUG, ((struct ip_addr *) &(iphdr->dest))); 132#endif /* IP_DEBUG */ 133 LWIP_DEBUGF(IP_DEBUG, ("\n")); 134 135 IP_STATS_INC(ip.fw); 136 IP_STATS_INC(ip.xmit); 137 138 PERF_STOP("ip_forward"); 139 140 netif->output(netif, p, (struct ip_addr *) &(iphdr->dest)); 141} 142 143/* ip_input: 144 * 145 * This function is called by the network interface device driver when an IP packet is 146 * received. The function does the basic checks of the IP header such as packet size 147 * being at least larger than the header size etc. If the packet was not destined for 148 * us, the packet is forwarded (using ip_forward). The IP checksum is always checked. 149 * 150 * Finally, the packet is sent to the upper layer protocol input function. 151 */ 152 153void ip_input(struct pbuf *p, struct netif *inp) 154{ 155 struct ip_hdr *iphdr; 156 struct netif *netif; 157 158 159 PERF_START; 160 161#if IP_DEBUG 162 ip_debug_print(p); 163#endif /* IP_DEBUG */ 164 165 166 IP_STATS_INC(ip.recv); 167 168 /* identify the IP header */ 169 iphdr = p->payload; 170 171 172 if (iphdr->v != 6) { 173 LWIP_DEBUGF(IP_DEBUG, 174 ("IP packet dropped due to bad version number\n")); 175#if IP_DEBUG 176 ip_debug_print(p); 177#endif /* IP_DEBUG */ 178 pbuf_free(p); 179 IP_STATS_INC(ip.err); 180 IP_STATS_INC(ip.drop); 181 return; 182 } 183 184 /* is this packet for us? */ 185 for (netif = netif_list; netif != NULL; netif = netif->next) { 186#if IP_DEBUG 187 LWIP_DEBUGF(IP_DEBUG, ("ip_input: iphdr->dest ")); 188 ip_addr_debug_print(IP_DEBUG, ((struct ip_addr *) &(iphdr->dest))); 189 LWIP_DEBUGF(IP_DEBUG, ("netif->ip_addr ")); 190 ip_addr_debug_print(IP_DEBUG, ((struct ip_addr *) &(iphdr->dest))); 191 LWIP_DEBUGF(IP_DEBUG, ("\n")); 192#endif /* IP_DEBUG */ 193 if (ip_addr_cmp(&(iphdr->dest), &(netif->ip_addr))) { 194 break; 195 } 196 } 197 198 199 if (netif == NULL) { 200 /* packet not for us, route or discard */ 201#if IP_FORWARD 202 ip_forward(p, iphdr); 203#endif 204 pbuf_free(p); 205 return; 206 } 207 208 pbuf_realloc(p, IP_HLEN + ntohs(iphdr->len)); 209 210 /* send to upper layers */ 211#if IP_DEBUG 212 /* LWIP_DEBUGF("ip_input: \n"); 213 ip_debug_print(p); 214 LWIP_DEBUGF("ip_input: p->len %"U16_F" p->tot_len %"U16_F"\n", p->len, p->tot_len); */ 215#endif /* IP_DEBUG */ 216 217 if (pbuf_header(p, -IP_HLEN)) { 218 LWIP_ASSERT("Can't move over header in packet", 0); 219 return; 220 } 221 222 switch (iphdr->nexthdr) { 223 case IP_PROTO_UDP: 224 udp_input(p, inp); 225 break; 226 case IP_PROTO_TCP: 227 tcp_input(p, inp); 228 break; 229#if LWIP_ICMP 230 case IP_PROTO_ICMP: 231 icmp_input(p, inp); 232 break; 233#endif /* LWIP_ICMP */ 234 default: 235#if LWIP_ICMP 236 /* send ICMP destination protocol unreachable */ 237 icmp_dest_unreach(p, ICMP_DUR_PROTO); 238#endif /* LWIP_ICMP */ 239 pbuf_free(p); 240 LWIP_DEBUGF(IP_DEBUG, 241 ("Unsupported transport protocol %" U16_F "\n", 242 iphdr->nexthdr)); 243 244 IP_STATS_INC(ip.proterr); 245 IP_STATS_INC(ip.drop); 246 } 247 PERF_STOP("ip_input"); 248} 249 250 251/* ip_output_if: 252 * 253 * Sends an IP packet on a network interface. This function constructs the IP header 254 * and calculates the IP header checksum. If the source IP address is NULL, 255 * the IP address of the outgoing network interface is filled in as source address. 256 */ 257 258err_t 259ip_output_if(struct pbuf *p, struct ip_addr *src, struct ip_addr *dest, 260 u8_t ttl, u8_t proto, struct netif *netif) 261{ 262 struct ip_hdr *iphdr; 263 264 PERF_START; 265 266 LWIP_DEBUGF(IP_DEBUG, 267 ("len %" U16_F " tot_len %" U16_F "\n", p->len, p->tot_len)); 268 if (pbuf_header(p, IP_HLEN)) { 269 LWIP_DEBUGF(IP_DEBUG, 270 ("ip_output: not enough room for IP header in pbuf\n")); 271 IP_STATS_INC(ip.err); 272 273 return ERR_BUF; 274 } 275 LWIP_DEBUGF(IP_DEBUG, 276 ("len %" U16_F " tot_len %" U16_F "\n", p->len, p->tot_len)); 277 278 iphdr = p->payload; 279 280 281 if (dest != IP_HDRINCL) { 282 LWIP_DEBUGF(IP_DEBUG, ("!IP_HDRLINCL\n")); 283 iphdr->hoplim = ttl; 284 iphdr->nexthdr = proto; 285 iphdr->len = htons(p->tot_len - IP_HLEN); 286 ip_addr_set(&(iphdr->dest), dest); 287 288 iphdr->v = 6; 289 290 if (ip_addr_isany(src)) { 291 ip_addr_set(&(iphdr->src), &(netif->ip_addr)); 292 } else { 293 ip_addr_set(&(iphdr->src), src); 294 } 295 296 } else { 297 dest = &(iphdr->dest); 298 } 299 300 IP_STATS_INC(ip.xmit); 301 302 LWIP_DEBUGF(IP_DEBUG, 303 ("ip_output_if: %c%c (len %" U16_F ")\n", netif->name[0], 304 netif->name[1], p->tot_len)); 305#if IP_DEBUG 306 ip_debug_print(p); 307#endif /* IP_DEBUG */ 308 309 PERF_STOP("ip_output_if"); 310 return netif->output(netif, p, dest); 311} 312 313/* ip_output: 314 * 315 * Simple interface to ip_output_if. It finds the outgoing network interface and 316 * calls upon ip_output_if to do the actual work. 317 */ 318 319err_t 320ip_output(struct pbuf * p, struct ip_addr * src, struct ip_addr * dest, 321 u8_t ttl, u8_t proto) 322{ 323 struct netif *netif; 324 325 if ((netif = ip_route(dest)) == NULL) { 326 LWIP_DEBUGF(IP_DEBUG, 327 ("ip_output: No route to 0x%" X32_F "\n", dest->addr)); 328 IP_STATS_INC(ip.rterr); 329 return ERR_RTE; 330 } 331 332 return ip_output_if(p, src, dest, ttl, proto, netif); 333} 334 335#if LWIP_NETIF_HWADDRHINT 336err_t 337ip_output_hinted(struct pbuf * p, struct ip_addr * src, struct ip_addr * dest, 338 u8_t ttl, u8_t tos, u8_t proto, u8_t * addr_hint) 339{ 340 struct netif *netif; 341 err_t err; 342 343 if ((netif = ip_route(dest)) == NULL) { 344 LWIP_DEBUGF(IP_DEBUG, 345 ("ip_output: No route to 0x%" X32_F "\n", dest->addr)); 346 IP_STATS_INC(ip.rterr); 347 return ERR_RTE; 348 } 349 350 netif->addr_hint = addr_hint; 351 err = ip_output_if(p, src, dest, ttl, tos, proto, netif); 352 netif->addr_hint = NULL; 353 354 return err; 355} 356#endif /* LWIP_NETIF_HWADDRHINT */ 357 358#if IP_DEBUG 359void ip_debug_print(struct pbuf *p) 360{ 361 struct ip_hdr *iphdr = p->payload; 362 363 LWIP_DEBUGF(IP_DEBUG, ("IP header:\n")); 364 LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n")); 365 LWIP_DEBUGF(IP_DEBUG, 366 ("|%2" S16_F " | %" X16_F "%" X16_F " | %" X16_F "%" 367 X16_F " | (v, traffic class, flow label)\n", 368 iphdr->v, iphdr->tclass1, iphdr->tclass2, iphdr->flow1, 369 iphdr->flow2)); 370 LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n")); 371 LWIP_DEBUGF(IP_DEBUG, 372 ("| %5" U16_F " | %2" U16_F " | %2" U16_F 373 " | (len, nexthdr, hoplim)\n", ntohs(iphdr->len), 374 iphdr->nexthdr, iphdr->hoplim)); 375 LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n")); 376 LWIP_DEBUGF(IP_DEBUG, 377 ("| %4" X32_F " | %4" X32_F " | (src)\n", 378 (ntohl(iphdr->src.addr[0]) >> 16) & 0xffff, 379 ntohl(iphdr->src.addr[0]) & 0xffff)); 380 LWIP_DEBUGF(IP_DEBUG, 381 ("| %4" X32_F " | %4" X32_F " | (src)\n", 382 (ntohl(iphdr->src.addr[1]) >> 16) & 0xffff, 383 ntohl(iphdr->src.addr[1]) & 0xffff)); 384 LWIP_DEBUGF(IP_DEBUG, 385 ("| %4" X32_F " | %4" X32_F " | (src)\n", 386 (ntohl(iphdr->src.addr[2]) >> 16) & 0xffff, 387 ntohl(iphdr->src.addr[2]) & 0xffff)); 388 LWIP_DEBUGF(IP_DEBUG, 389 ("| %4" X32_F " | %4" X32_F " | (src)\n", 390 (ntohl(iphdr->src.addr[3]) >> 16) & 0xffff, 391 ntohl(iphdr->src.addr[3]) & 0xffff)); 392 LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n")); 393 LWIP_DEBUGF(IP_DEBUG, 394 ("| %4" X32_F " | %4" X32_F " | (dest)\n", 395 (ntohl(iphdr->dest.addr[0]) >> 16) & 0xffff, 396 ntohl(iphdr->dest.addr[0]) & 0xffff)); 397 LWIP_DEBUGF(IP_DEBUG, 398 ("| %4" X32_F " | %4" X32_F " | (dest)\n", 399 (ntohl(iphdr->dest.addr[1]) >> 16) & 0xffff, 400 ntohl(iphdr->dest.addr[1]) & 0xffff)); 401 LWIP_DEBUGF(IP_DEBUG, 402 ("| %4" X32_F " | %4" X32_F " | (dest)\n", 403 (ntohl(iphdr->dest.addr[2]) >> 16) & 0xffff, 404 ntohl(iphdr->dest.addr[2]) & 0xffff)); 405 LWIP_DEBUGF(IP_DEBUG, 406 ("| %4" X32_F " | %4" X32_F " | (dest)\n", 407 (ntohl(iphdr->dest.addr[3]) >> 16) & 0xffff, 408 ntohl(iphdr->dest.addr[3]) & 0xffff)); 409 LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n")); 410} 411#endif /* IP_DEBUG */ 412