Main Page | Alphabetical List | Data Structures | File List | Data Fields | Globals | Related Pages

ip6.c

Go to the documentation of this file.
00001 /*
00002  * Copyright (c) 2001-2003 Swedish Institute of Computer Science.
00003  * All rights reserved. 
00004  * 
00005  * Redistribution and use in source and binary forms, with or without modification, 
00006  * are permitted provided that the following conditions are met:
00007  *
00008  * 1. Redistributions of source code must retain the above copyright notice,
00009  *    this list of conditions and the following disclaimer.
00010  * 2. Redistributions in binary form must reproduce the above copyright notice,
00011  *    this list of conditions and the following disclaimer in the documentation
00012  *    and/or other materials provided with the distribution.
00013  * 3. The name of the author may not be used to endorse or promote products
00014  *    derived from this software without specific prior written permission. 
00015  *
00016  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 
00017  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 
00018  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 
00019  * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 
00020  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 
00021  * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
00022  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
00023  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 
00024  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 
00025  * OF SUCH DAMAGE.
00026  *
00027  * This file is part of the lwIP TCP/IP stack.
00028  * 
00029  * Author: Adam Dunkels <adam@sics.se>
00030  *
00031  */
00032 
00033 
00034 /*-----------------------------------------------------------------------------------*/
00035 /* ip.c
00036  *
00037  * This is the code for the IP layer for IPv6.
00038  *
00039  */   
00040 /*-----------------------------------------------------------------------------------*/
00041 
00042 #include "lwip/opt.h"
00043 
00044 #include "lwip/def.h"
00045 #include "lwip/mem.h"
00046 #include "lwip/ip.h"
00047 #include "lwip/inet.h"
00048 #include "lwip/netif.h"
00049 #include "lwip/icmp.h"
00050 #include "lwip/udp.h"
00051 #include "lwip/tcp.h"
00052 
00053 #include "lwip/stats.h"
00054 
00055 #include "arch/perf.h"
00056 /*-----------------------------------------------------------------------------------*/
00057 /* ip_init:
00058  *
00059  * Initializes the IP layer.
00060  */
00061 /*-----------------------------------------------------------------------------------*/
00062 void
00063 ip_init(void)
00064 {
00065 }
00066 /*-----------------------------------------------------------------------------------*/
00067 /* ip_route:
00068  *
00069  * Finds the appropriate network interface for a given IP address. It searches the
00070  * list of network interfaces linearly. A match is found if the masked IP address of
00071  * the network interface equals the masked IP address given to the function.
00072  */
00073 /*-----------------------------------------------------------------------------------*/
00074 struct netif *
00075 ip_route(struct ip_addr *dest)
00076 {
00077   struct netif *netif;
00078   
00079   for(netif = netif_list; netif != NULL; netif = netif->next) {
00080     if(ip_addr_maskcmp(dest, &(netif->ip_addr), &(netif->netmask))) {
00081       return netif;
00082     }
00083   }
00084 
00085   return netif_default;
00086 }
00087 /*-----------------------------------------------------------------------------------*/
00088 /* ip_forward:
00089  *
00090  * Forwards an IP packet. It finds an appropriate route for the packet, decrements
00091  * the TTL value of the packet, adjusts the checksum and outputs the packet on the
00092  * appropriate interface.
00093  */
00094 /*-----------------------------------------------------------------------------------*/
00095 static void
00096 ip_forward(struct pbuf *p, struct ip_hdr *iphdr)
00097 {
00098   struct netif *netif;
00099   
00100   PERF_START;
00101   
00102   if((netif = ip_route((struct ip_addr *)&(iphdr->dest))) == NULL) {
00103 
00104     DEBUGF(IP_DEBUG, ("ip_input: no forwarding route found for "));
00105 #if IP_DEBUG
00106     ip_addr_debug_print(&(iphdr->dest));
00107 #endif /* IP_DEBUG */
00108     DEBUGF(IP_DEBUG, ("\n"));
00109     pbuf_free(p);
00110     return;
00111   }
00112   /* Decrement TTL and send ICMP if ttl == 0. */
00113   if(--iphdr->hoplim == 0) {
00114     /* Don't send ICMP messages in response to ICMP messages */
00115     if(iphdr->nexthdr != IP_PROTO_ICMP) {
00116       icmp_time_exceeded(p, ICMP_TE_TTL);
00117     }
00118     pbuf_free(p);
00119     return;       
00120   }
00121   
00122   /* Incremental update of the IP checksum. */
00123   /*  if (iphdr->chksum >= htons(0xffff - 0x100)) {
00124     iphdr->chksum += htons(0x100) + 1;
00125   } else {
00126     iphdr->chksum += htons(0x100);
00127     }*/
00128   
00129 
00130   DEBUGF(IP_DEBUG, ("ip_forward: forwarding packet to "));
00131 #if IP_DEBUG
00132   ip_addr_debug_print(&(iphdr->dest));
00133 #endif /* IP_DEBUG */
00134   DEBUGF(IP_DEBUG, ("\n"));
00135 
00136 #ifdef IP_STATS
00137   ++lwip_stats.ip.fw;
00138   ++lwip_stats.ip.xmit;
00139 #endif /* IP_STATS */
00140 
00141   PERF_STOP("ip_forward");
00142   
00143   netif->output(netif, p, (struct ip_addr *)&(iphdr->dest));
00144 }
00145 /*-----------------------------------------------------------------------------------*/
00146 /* ip_input:
00147  *
00148  * This function is called by the network interface device driver when an IP packet is
00149  * received. The function does the basic checks of the IP header such as packet size
00150  * being at least larger than the header size etc. If the packet was not destined for
00151  * us, the packet is forwarded (using ip_forward). The IP checksum is always checked.
00152  *
00153  * Finally, the packet is sent to the upper layer protocol input function.
00154  */
00155 /*-----------------------------------------------------------------------------------*/
00156 void
00157 ip_input(struct pbuf *p, struct netif *inp) {
00158   struct ip_hdr *iphdr;
00159   struct netif *netif;
00160 
00161   
00162   PERF_START;
00163 
00164 #if IP_DEBUG
00165   ip_debug_print(p);
00166 #endif /* IP_DEBUG */
00167 
00168   
00169 #ifdef IP_STATS
00170   ++lwip_stats.ip.recv;
00171 #endif /* IP_STATS */
00172   
00173   /* identify the IP header */
00174   iphdr = p->payload;
00175 
00176   
00177   if(iphdr->v != 6) {
00178     DEBUGF(IP_DEBUG, ("IP packet dropped due to bad version number\n"));
00179 #if IP_DEBUG
00180     ip_debug_print(p);
00181 #endif /* IP_DEBUG */
00182     pbuf_free(p);
00183 #ifdef IP_STATS
00184     ++lwip_stats.ip.err;
00185     ++lwip_stats.ip.drop;
00186 #endif /* IP_STATS */
00187     return;
00188   }
00189   
00190   /* is this packet for us? */
00191   for(netif = netif_list; netif != NULL; netif = netif->next) {
00192 #if IP_DEBUG
00193     DEBUGF(IP_DEBUG, ("ip_input: iphdr->dest "));
00194     ip_addr_debug_print(&(iphdr->dest));
00195     DEBUGF(IP_DEBUG, ("netif->ip_addr "));
00196     ip_addr_debug_print(&(netif->ip_addr));
00197     DEBUGF(IP_DEBUG, ("\n"));
00198 #endif /* IP_DEBUG */
00199     if(ip_addr_cmp(&(iphdr->dest), &(netif->ip_addr))) {
00200       break;
00201     }
00202   }
00203 
00204   
00205   if(netif == NULL) {
00206     /* packet not for us, route or discard */
00207 #ifdef IP_FORWARD
00208     ip_forward(p, iphdr);
00209 #endif
00210     pbuf_free(p);
00211     return;
00212   }
00213 
00214   pbuf_realloc(p, IP_HLEN + ntohs(iphdr->len));
00215   
00216   /* send to upper layers */
00217 #if IP_DEBUG
00218   /*  DEBUGF("ip_input: \n");
00219   ip_debug_print(p);
00220   DEBUGF("ip_input: p->len %u p->tot_len %u\n", p->len, p->tot_len);*/
00221 #endif /* IP_DEBUG */
00222    
00223 
00224   pbuf_header(p, -IP_HLEN);
00225 
00226   switch(iphdr->nexthdr) {
00227   case IP_PROTO_UDP:
00228     udp_input(p);
00229     break;
00230   case IP_PROTO_TCP:
00231     tcp_input(p);
00232     break;
00233   case IP_PROTO_ICMP:
00234     icmp_input(p, inp);
00235     break;
00236   default:
00237     /* send ICMP destination protocol unreachable */
00238     icmp_dest_unreach(p, ICMP_DUR_PROTO);
00239     pbuf_free(p);
00240     DEBUGF(IP_DEBUG, ("Unsupported transportation protocol %u\n",
00241                       iphdr->nexthdr));
00242 
00243 #ifdef IP_STATS
00244     ++lwip_stats.ip.proterr;
00245     ++lwip_stats.ip.drop;
00246 #endif /* IP_STATS */
00247 
00248   }
00249   PERF_STOP("ip_input");
00250 }
00251 
00252 /*-----------------------------------------------------------------------------------*/
00253 /* ip_output_if:
00254  *
00255  * Sends an IP packet on a network interface. This function constructs the IP header
00256  * and calculates the IP header checksum. If the source IP address is NULL,
00257  * the IP address of the outgoing network interface is filled in as source address.
00258  */
00259 /*-----------------------------------------------------------------------------------*/
00260 err_t
00261 ip_output_if(struct pbuf *p, struct ip_addr *src, struct ip_addr *dest,
00262              u8_t ttl,
00263              u8_t proto, struct netif *netif)
00264 {
00265   struct ip_hdr *iphdr;
00266 
00267   PERF_START;
00268 
00269   printf("len %u tot_len %u\n", p->len, p->tot_len);
00270   if(pbuf_header(p, IP_HLEN)) {
00271     DEBUGF(IP_DEBUG, ("ip_output: not enough room for IP header in pbuf\n"));
00272 #ifdef IP_STATS
00273     ++lwip_stats.ip.err;
00274 #endif /* IP_STATS */
00275 
00276     return ERR_BUF;
00277   }
00278   printf("len %u tot_len %u\n", p->len, p->tot_len);
00279   
00280   iphdr = p->payload;
00281   
00282 
00283   if(dest != IP_HDRINCL) {
00284     printf("!IP_HDRLINCL\n");
00285     iphdr->hoplim = ttl;
00286     iphdr->nexthdr = proto;
00287     iphdr->len = htons(p->tot_len - IP_HLEN);
00288     ip_addr_set(&(iphdr->dest), dest);
00289 
00290     iphdr->v = 6;
00291 
00292     if(ip_addr_isany(src)) {
00293       ip_addr_set(&(iphdr->src), &(netif->ip_addr));
00294     } else {
00295       ip_addr_set(&(iphdr->src), src);
00296     }
00297     
00298   } else {
00299     dest = &(iphdr->dest);
00300   }
00301 
00302 #ifdef IP_STATS
00303   ++lwip_stats.ip.xmit;
00304 #endif /* IP_STATS */
00305 
00306   DEBUGF(IP_DEBUG, ("ip_output_if: %c%c (len %u)\n", netif->name[0], netif->name[1], p->tot_len));
00307 #if IP_DEBUG
00308   ip_debug_print(p);
00309 #endif /* IP_DEBUG */
00310 
00311   PERF_STOP("ip_output_if");
00312   return netif->output(netif, p, dest);  
00313 }
00314 /*-----------------------------------------------------------------------------------*/
00315 /* ip_output:
00316  *
00317  * Simple interface to ip_output_if. It finds the outgoing network interface and
00318  * calls upon ip_output_if to do the actual work.
00319  */
00320 /*-----------------------------------------------------------------------------------*/
00321 err_t
00322 ip_output(struct pbuf *p, struct ip_addr *src, struct ip_addr *dest,
00323           u8_t ttl, u8_t proto)
00324 {
00325   struct netif *netif;
00326   if((netif = ip_route(dest)) == NULL) {
00327     DEBUGF(IP_DEBUG, ("ip_output: No route to 0x%lx\n", dest->addr));
00328 #ifdef IP_STATS
00329     ++lwip_stats.ip.rterr;
00330 #endif /* IP_STATS */
00331     return ERR_RTE;
00332   }
00333 
00334   return ip_output_if(p, src, dest, ttl, proto, netif);
00335 }
00336 /*-----------------------------------------------------------------------------------*/
00337 #if IP_DEBUG
00338 void
00339 ip_debug_print(struct pbuf *p)
00340 {
00341   struct ip_hdr *iphdr = p->payload;
00342   char *payload;
00343 
00344   payload = (char *)iphdr + IP_HLEN;
00345   
00346   DEBUGF(IP_DEBUG, ("IP header:\n"));
00347   DEBUGF(IP_DEBUG, ("+-------------------------------+\n"));
00348   DEBUGF(IP_DEBUG, ("|%2d |  %x%x  |      %x%x           | (v, traffic class, flow label)\n",
00349                     iphdr->v,
00350                     iphdr->tclass1, iphdr->tclass2,
00351                     iphdr->flow1, iphdr->flow2));
00352   DEBUGF(IP_DEBUG, ("+-------------------------------+\n"));
00353   DEBUGF(IP_DEBUG, ("|    %5u      | %2u  |  %2u   | (len, nexthdr, hoplim)\n",
00354                     ntohs(iphdr->len),
00355                     iphdr->nexthdr,
00356                     iphdr->hoplim));
00357   DEBUGF(IP_DEBUG, ("+-------------------------------+\n"));
00358   DEBUGF(IP_DEBUG, ("|       %4lx      |       %4lx     | (src)\n",
00359                     ntohl(iphdr->src.addr[0]) >> 16 & 0xffff,
00360                     ntohl(iphdr->src.addr[0]) & 0xffff));
00361   DEBUGF(IP_DEBUG, ("|       %4lx      |       %4lx     | (src)\n",
00362                     ntohl(iphdr->src.addr[1]) >> 16 & 0xffff,
00363                     ntohl(iphdr->src.addr[1]) & 0xffff));
00364   DEBUGF(IP_DEBUG, ("|       %4lx      |       %4lx     | (src)\n",
00365                     ntohl(iphdr->src.addr[2]) >> 16 & 0xffff,
00366                     ntohl(iphdr->src.addr[2]) & 0xffff));
00367   DEBUGF(IP_DEBUG, ("|       %4lx      |       %4lx     | (src)\n",
00368                     ntohl(iphdr->src.addr[3]) >> 16 & 0xffff,
00369                     ntohl(iphdr->src.addr[3]) & 0xffff));
00370   DEBUGF(IP_DEBUG, ("+-------------------------------+\n"));
00371   DEBUGF(IP_DEBUG, ("|       %4lx      |       %4lx     | (dest)\n",
00372                     ntohl(iphdr->dest.addr[0]) >> 16 & 0xffff,
00373                     ntohl(iphdr->dest.addr[0]) & 0xffff));
00374   DEBUGF(IP_DEBUG, ("|       %4lx      |       %4lx     | (dest)\n",
00375                     ntohl(iphdr->dest.addr[1]) >> 16 & 0xffff,
00376                     ntohl(iphdr->dest.addr[1]) & 0xffff));
00377   DEBUGF(IP_DEBUG, ("|       %4lx      |       %4lx     | (dest)\n",
00378                     ntohl(iphdr->dest.addr[2]) >> 16 & 0xffff,
00379                     ntohl(iphdr->dest.addr[2]) & 0xffff));
00380   DEBUGF(IP_DEBUG, ("|       %4lx      |       %4lx     | (dest)\n",
00381                     ntohl(iphdr->dest.addr[3]) >> 16 & 0xffff,
00382                     ntohl(iphdr->dest.addr[3]) & 0xffff));
00383   DEBUGF(IP_DEBUG, ("+-------------------------------+\n"));
00384 }
00385 #endif /* IP_DEBUG */
00386 /*-----------------------------------------------------------------------------------*/

Generated on Wed Jan 14 12:58:56 2004 for RTL-lwIP-0.4 by doxygen 1.3.4