Palacios Public Git Repository

To checkout Palacios execute

  git clone http://v3vee.org/palacios/palacios.web/palacios.git
This will give you the master branch. You probably want the devel branch or one of the release branches. To switch to the devel branch, simply execute
  cd palacios
  git checkout --track -b devel origin/devel
The other branches are similar.


Release 1.0
[palacios.git] / geekos / src / lwip / core / ipv6 / ip6.c
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
62 void
63 ip_init(void)
64 {
65 }
66
67 /* ip_route:
68  *
69  * Finds the appropriate network interface for a given IP address. It searches the
70  * list of network interfaces linearly. A match is found if the masked IP address of
71  * the network interface equals the masked IP address given to the function.
72  */
73
74 struct netif *
75 ip_route(struct ip_addr *dest)
76 {
77   struct netif *netif;
78
79   for(netif = netif_list; netif != NULL; netif = netif->next) {
80     if (ip_addr_netcmp(dest, &(netif->ip_addr), &(netif->netmask))) {
81       return netif;
82     }
83   }
84
85   return netif_default;
86 }
87
88 /* ip_forward:
89  *
90  * Forwards an IP packet. It finds an appropriate route for the packet, decrements
91  * the TTL value of the packet, adjusts the checksum and outputs the packet on the
92  * appropriate interface.
93  */
94
95 static void
96 ip_forward(struct pbuf *p, struct ip_hdr *iphdr)
97 {
98   struct netif *netif;
99
100   PERF_START;
101
102   if ((netif = ip_route((struct ip_addr *)&(iphdr->dest))) == NULL) {
103
104     LWIP_DEBUGF(IP_DEBUG, ("ip_input: no forwarding route found for "));
105 #if IP_DEBUG
106     ip_addr_debug_print(IP_DEBUG, ((struct ip_addr *)&(iphdr->dest)));
107 #endif /* IP_DEBUG */
108     LWIP_DEBUGF(IP_DEBUG, ("\n"));
109     pbuf_free(p);
110     return;
111   }
112   /* Decrement TTL and send ICMP if ttl == 0. */
113   if (--iphdr->hoplim == 0) {
114 #if LWIP_ICMP
115     /* Don't send ICMP messages in response to ICMP messages */
116     if (iphdr->nexthdr != IP_PROTO_ICMP) {
117       icmp_time_exceeded(p, ICMP_TE_TTL);
118     }
119 #endif /* LWIP_ICMP */
120     pbuf_free(p);
121     return;
122   }
123
124   /* Incremental update of the IP checksum. */
125   /*  if (iphdr->chksum >= htons(0xffff - 0x100)) {
126     iphdr->chksum += htons(0x100) + 1;
127   } else {
128     iphdr->chksum += htons(0x100);
129     }*/
130
131
132   LWIP_DEBUGF(IP_DEBUG, ("ip_forward: forwarding packet to "));
133 #if IP_DEBUG
134   ip_addr_debug_print(IP_DEBUG, ((struct ip_addr *)&(iphdr->dest)));
135 #endif /* IP_DEBUG */
136   LWIP_DEBUGF(IP_DEBUG, ("\n"));
137
138   IP_STATS_INC(ip.fw);
139   IP_STATS_INC(ip.xmit);
140
141   PERF_STOP("ip_forward");
142
143   netif->output(netif, p, (struct ip_addr *)&(iphdr->dest));
144 }
145
146 /* ip_input:
147  *
148  * This function is called by the network interface device driver when an IP packet is
149  * received. The function does the basic checks of the IP header such as packet size
150  * being at least larger than the header size etc. If the packet was not destined for
151  * us, the packet is forwarded (using ip_forward). The IP checksum is always checked.
152  *
153  * Finally, the packet is sent to the upper layer protocol input function.
154  */
155
156 void
157 ip_input(struct pbuf *p, struct netif *inp) {
158   struct ip_hdr *iphdr;
159   struct netif *netif;
160
161
162   PERF_START;
163
164 #if IP_DEBUG
165   ip_debug_print(p);
166 #endif /* IP_DEBUG */
167
168
169   IP_STATS_INC(ip.recv);
170
171   /* identify the IP header */
172   iphdr = p->payload;
173
174
175   if (iphdr->v != 6) {
176     LWIP_DEBUGF(IP_DEBUG, ("IP packet dropped due to bad version number\n"));
177 #if IP_DEBUG
178     ip_debug_print(p);
179 #endif /* IP_DEBUG */
180     pbuf_free(p);
181     IP_STATS_INC(ip.err);
182     IP_STATS_INC(ip.drop);
183     return;
184   }
185
186   /* is this packet for us? */
187   for(netif = netif_list; netif != NULL; netif = netif->next) {
188 #if IP_DEBUG
189     LWIP_DEBUGF(IP_DEBUG, ("ip_input: iphdr->dest "));
190     ip_addr_debug_print(IP_DEBUG, ((struct ip_addr *)&(iphdr->dest)));
191     LWIP_DEBUGF(IP_DEBUG, ("netif->ip_addr "));
192     ip_addr_debug_print(IP_DEBUG, ((struct ip_addr *)&(iphdr->dest)));
193     LWIP_DEBUGF(IP_DEBUG, ("\n"));
194 #endif /* IP_DEBUG */
195     if (ip_addr_cmp(&(iphdr->dest), &(netif->ip_addr))) {
196       break;
197     }
198   }
199
200
201   if (netif == NULL) {
202     /* packet not for us, route or discard */
203 #if IP_FORWARD
204     ip_forward(p, iphdr);
205 #endif
206     pbuf_free(p);
207     return;
208   }
209
210   pbuf_realloc(p, IP_HLEN + ntohs(iphdr->len));
211
212   /* send to upper layers */
213 #if IP_DEBUG
214   /*  LWIP_DEBUGF("ip_input: \n");
215   ip_debug_print(p);
216   LWIP_DEBUGF("ip_input: p->len %"U16_F" p->tot_len %"U16_F"\n", p->len, p->tot_len);*/
217 #endif /* IP_DEBUG */
218
219   if(pbuf_header(p, -IP_HLEN)) {
220     LWIP_ASSERT("Can't move over header in packet", 0);
221     return;
222   }
223
224   switch (iphdr->nexthdr) {
225   case IP_PROTO_UDP:
226     udp_input(p, inp);
227     break;
228   case IP_PROTO_TCP:
229     tcp_input(p, inp);
230     break;
231 #if LWIP_ICMP
232   case IP_PROTO_ICMP:
233     icmp_input(p, inp);
234     break;
235 #endif /* LWIP_ICMP */
236   default:
237 #if LWIP_ICMP
238     /* send ICMP destination protocol unreachable */
239     icmp_dest_unreach(p, ICMP_DUR_PROTO);
240 #endif /* LWIP_ICMP */
241     pbuf_free(p);
242     LWIP_DEBUGF(IP_DEBUG, ("Unsupported transport protocol %"U16_F"\n",
243           iphdr->nexthdr));
244
245     IP_STATS_INC(ip.proterr);
246     IP_STATS_INC(ip.drop);
247   }
248   PERF_STOP("ip_input");
249 }
250
251
252 /* ip_output_if:
253  *
254  * Sends an IP packet on a network interface. This function constructs the IP header
255  * and calculates the IP header checksum. If the source IP address is NULL,
256  * the IP address of the outgoing network interface is filled in as source address.
257  */
258
259 err_t
260 ip_output_if (struct pbuf *p, struct ip_addr *src, struct ip_addr *dest,
261        u8_t ttl,
262        u8_t proto, struct netif *netif)
263 {
264   struct ip_hdr *iphdr;
265
266   PERF_START;
267
268   LWIP_DEBUGF(IP_DEBUG, ("len %"U16_F" tot_len %"U16_F"\n", p->len, p->tot_len));
269   if (pbuf_header(p, IP_HLEN)) {
270     LWIP_DEBUGF(IP_DEBUG, ("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, ("len %"U16_F" tot_len %"U16_F"\n", p->len, p->tot_len));
276
277   iphdr = p->payload;
278
279
280   if (dest != IP_HDRINCL) {
281     LWIP_DEBUGF(IP_DEBUG, ("!IP_HDRLINCL\n"));
282     iphdr->hoplim = ttl;
283     iphdr->nexthdr = proto;
284     iphdr->len = htons(p->tot_len - IP_HLEN);
285     ip_addr_set(&(iphdr->dest), dest);
286
287     iphdr->v = 6;
288
289     if (ip_addr_isany(src)) {
290       ip_addr_set(&(iphdr->src), &(netif->ip_addr));
291     } else {
292       ip_addr_set(&(iphdr->src), src);
293     }
294
295   } else {
296     dest = &(iphdr->dest);
297   }
298
299   IP_STATS_INC(ip.xmit);
300
301   LWIP_DEBUGF(IP_DEBUG, ("ip_output_if: %c%c (len %"U16_F")\n", netif->name[0], netif->name[1], p->tot_len));
302 #if IP_DEBUG
303   ip_debug_print(p);
304 #endif /* IP_DEBUG */
305
306   PERF_STOP("ip_output_if");
307   return netif->output(netif, p, dest);
308 }
309
310 /* ip_output:
311  *
312  * Simple interface to ip_output_if. It finds the outgoing network interface and
313  * calls upon ip_output_if to do the actual work.
314  */
315
316 err_t
317 ip_output(struct pbuf *p, struct ip_addr *src, struct ip_addr *dest,
318     u8_t ttl, u8_t proto)
319 {
320   struct netif *netif;
321   if ((netif = ip_route(dest)) == NULL) {
322     LWIP_DEBUGF(IP_DEBUG, ("ip_output: No route to 0x%"X32_F"\n", dest->addr));
323     IP_STATS_INC(ip.rterr);
324     return ERR_RTE;
325   }
326
327   return ip_output_if (p, src, dest, ttl, proto, netif);
328 }
329
330 #if IP_DEBUG
331 void
332 ip_debug_print(struct pbuf *p)
333 {
334   struct ip_hdr *iphdr = p->payload;
335
336   LWIP_DEBUGF(IP_DEBUG, ("IP header:\n"));
337   LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n"));
338   LWIP_DEBUGF(IP_DEBUG, ("|%2"S16_F" |  %"X16_F"%"X16_F"  |      %"X16_F"%"X16_F"           | (v, traffic class, flow label)\n",
339         iphdr->v,
340         iphdr->tclass1, iphdr->tclass2,
341         iphdr->flow1, iphdr->flow2));
342   LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n"));
343   LWIP_DEBUGF(IP_DEBUG, ("|    %5"U16_F"      | %2"U16_F"  |  %2"U16_F"   | (len, nexthdr, hoplim)\n",
344         ntohs(iphdr->len),
345         iphdr->nexthdr,
346         iphdr->hoplim));
347   LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n"));
348   LWIP_DEBUGF(IP_DEBUG, ("|       %4"X32_F"      |       %4"X32_F"     | (src)\n",
349         (ntohl(iphdr->src.addr[0]) >> 16) & 0xffff,
350         ntohl(iphdr->src.addr[0]) & 0xffff));
351   LWIP_DEBUGF(IP_DEBUG, ("|       %4"X32_F"      |       %4"X32_F"     | (src)\n",
352         (ntohl(iphdr->src.addr[1]) >> 16) & 0xffff,
353         ntohl(iphdr->src.addr[1]) & 0xffff));
354   LWIP_DEBUGF(IP_DEBUG, ("|       %4"X32_F"      |       %4"X32_F"     | (src)\n",
355         (ntohl(iphdr->src.addr[2]) >> 16) & 0xffff,
356         ntohl(iphdr->src.addr[2]) & 0xffff));
357   LWIP_DEBUGF(IP_DEBUG, ("|       %4"X32_F"      |       %4"X32_F"     | (src)\n",
358         (ntohl(iphdr->src.addr[3]) >> 16) & 0xffff,
359         ntohl(iphdr->src.addr[3]) & 0xffff));
360   LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n"));
361   LWIP_DEBUGF(IP_DEBUG, ("|       %4"X32_F"      |       %4"X32_F"     | (dest)\n",
362         (ntohl(iphdr->dest.addr[0]) >> 16) & 0xffff,
363         ntohl(iphdr->dest.addr[0]) & 0xffff));
364   LWIP_DEBUGF(IP_DEBUG, ("|       %4"X32_F"      |       %4"X32_F"     | (dest)\n",
365         (ntohl(iphdr->dest.addr[1]) >> 16) & 0xffff,
366         ntohl(iphdr->dest.addr[1]) & 0xffff));
367   LWIP_DEBUGF(IP_DEBUG, ("|       %4"X32_F"      |       %4"X32_F"     | (dest)\n",
368         (ntohl(iphdr->dest.addr[2]) >> 16) & 0xffff,
369         ntohl(iphdr->dest.addr[2]) & 0xffff));
370   LWIP_DEBUGF(IP_DEBUG, ("|       %4"X32_F"      |       %4"X32_F"     | (dest)\n",
371         (ntohl(iphdr->dest.addr[3]) >> 16) & 0xffff,
372         ntohl(iphdr->dest.addr[3]) & 0xffff));
373   LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n"));
374 }
375 #endif /* IP_DEBUG */