]> git.sur5r.net Git - freertos/blob - Demo/lwIP_MCF5235_GCC/lwip/src/core/ipv4/ip.c
Add PIC24, dsPIC and Coldfire files.
[freertos] / Demo / lwIP_MCF5235_GCC / lwip / src / core / ipv4 / ip.c
1 /* @file
2  *
3  * This is the IP layer implementation for incoming and outgoing IP traffic.
4  * 
5  * @see ip_frag.c
6  *
7  */
8 /*
9  * Copyright (c) 2001-2004 Swedish Institute of Computer Science.
10  * All rights reserved.
11  *
12  * Redistribution and use in source and binary forms, with or without modification,
13  * are permitted provided that the following conditions are met:
14  *
15  * 1. Redistributions of source code must retain the above copyright notice,
16  *    this list of conditions and the following disclaimer.
17  * 2. Redistributions in binary form must reproduce the above copyright notice,
18  *    this list of conditions and the following disclaimer in the documentation
19  *    and/or other materials provided with the distribution.
20  * 3. The name of the author may not be used to endorse or promote products
21  *    derived from this software without specific prior written permission.
22  *
23  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
24  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
25  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
26  * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
27  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
28  * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
29  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
30  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
31  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
32  * OF SUCH DAMAGE.
33  *
34  * This file is part of the lwIP TCP/IP stack.
35  *
36  * Author: Adam Dunkels <adam@sics.se>
37  *
38  */
39
40 #include "lwip/opt.h"
41
42 #include "lwip/def.h"
43 #include "lwip/mem.h"
44 #include "lwip/ip.h"
45 #include "lwip/ip_frag.h"
46 #include "lwip/inet.h"
47 #include "lwip/netif.h"
48 #include "lwip/icmp.h"
49 #include "lwip/raw.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 #include "lwip/snmp.h"
58 #if LWIP_DHCP
59 #  include "lwip/dhcp.h"
60 #endif /* LWIP_DHCP */
61
62
63 /**
64  * Initializes the IP layer.
65  */
66
67 void
68 ip_init(void)
69 {
70   /* no initializations as of yet */
71 }
72
73 /**
74  * Finds the appropriate network interface for a given IP address. It
75  * searches the list of network interfaces linearly. A match is found
76  * if the masked IP address of the network interface equals the masked
77  * IP address given to the function.
78  */
79
80 struct netif *
81 ip_route(struct ip_addr *dest)
82 {
83   struct netif *netif;
84
85   /* iterate through netifs */
86   for(netif = netif_list; netif != NULL; netif = netif->next) {
87     /* network mask matches? */
88     if (ip_addr_netcmp(dest, &(netif->ip_addr), &(netif->netmask))) {
89       /* return netif on which to forward IP packet */
90       return netif;
91     }
92   }
93   /* no matching netif found, use default netif */
94   return netif_default;
95 }
96 #if IP_FORWARD
97
98 /**
99  * Forwards an IP packet. It finds an appropriate route for the
100  * packet, decrements the TTL value of the packet, adjusts the
101  * checksum and outputs the packet on the appropriate interface.
102  */
103
104 static struct netif *
105 ip_forward(struct pbuf *p, struct ip_hdr *iphdr, struct netif *inp)
106 {
107   struct netif *netif;
108
109   PERF_START;
110   /* Find network interface where to forward this IP packet to. */
111   netif = ip_route((struct ip_addr *)&(iphdr->dest));
112   if (netif == NULL) {
113     LWIP_DEBUGF(IP_DEBUG, ("ip_forward: no forwarding route for 0x%"X32_F" found\n",
114                       iphdr->dest.addr));
115     snmp_inc_ipnoroutes();
116     return (struct netif *)NULL;
117   }
118   /* Do not forward packets onto the same network interface on which
119    * they arrived. */
120   if (netif == inp) {
121     LWIP_DEBUGF(IP_DEBUG, ("ip_forward: not bouncing packets back on incoming interface.\n"));
122     snmp_inc_ipnoroutes();
123     return (struct netif *)NULL;
124   }
125
126   /* decrement TTL */
127   IPH_TTL_SET(iphdr, IPH_TTL(iphdr) - 1);
128   /* send ICMP if TTL == 0 */
129   if (IPH_TTL(iphdr) == 0) {
130     /* Don't send ICMP messages in response to ICMP messages */
131     if (IPH_PROTO(iphdr) != IP_PROTO_ICMP) {
132       icmp_time_exceeded(p, ICMP_TE_TTL);
133       snmp_inc_icmpouttimeexcds();
134     }
135     return (struct netif *)NULL;
136   }
137
138   /* Incrementally update the IP checksum. */
139   if (IPH_CHKSUM(iphdr) >= htons(0xffff - 0x100)) {
140     IPH_CHKSUM_SET(iphdr, IPH_CHKSUM(iphdr) + htons(0x100) + 1);
141   } else {
142     IPH_CHKSUM_SET(iphdr, IPH_CHKSUM(iphdr) + htons(0x100));
143   }
144
145   LWIP_DEBUGF(IP_DEBUG, ("ip_forward: forwarding packet to 0x%"X32_F"\n",
146                     iphdr->dest.addr));
147
148   IP_STATS_INC(ip.fw);
149   IP_STATS_INC(ip.xmit);
150     snmp_inc_ipforwdatagrams();
151
152   PERF_STOP("ip_forward");
153   /* transmit pbuf on chosen interface */
154   netif->output(netif, p, (struct ip_addr *)&(iphdr->dest));
155   return netif;
156 }
157 #endif /* IP_FORWARD */
158
159 /**
160  * This function is called by the network interface device driver when
161  * an IP packet is received. The function does the basic checks of the
162  * IP header such as packet size being at least larger than the header
163  * size etc. If the packet was not destined for us, the packet is
164  * forwarded (using ip_forward). The IP checksum is always checked.
165  *
166  * Finally, the packet is sent to the upper layer protocol input function.
167  * 
168  * 
169  * 
170  */
171
172 err_t
173 ip_input(struct pbuf *p, struct netif *inp) {
174   struct ip_hdr *iphdr;
175   struct netif *netif;
176   u16_t iphdrlen;
177
178   IP_STATS_INC(ip.recv);
179   snmp_inc_ipinreceives();
180
181   /* identify the IP header */
182   iphdr = p->payload;
183   if (IPH_V(iphdr) != 4) {
184     LWIP_DEBUGF(IP_DEBUG | 1, ("IP packet dropped due to bad version number %"U16_F"\n", IPH_V(iphdr)));
185     ip_debug_print(p);
186     pbuf_free(p);
187     IP_STATS_INC(ip.err);
188     IP_STATS_INC(ip.drop);
189     snmp_inc_ipunknownprotos();
190     return ERR_OK;
191   }
192   /* obtain IP header length in number of 32-bit words */
193   iphdrlen = IPH_HL(iphdr);
194   /* calculate IP header length in bytes */
195   iphdrlen *= 4;
196
197   /* header length exceeds first pbuf length? */
198   if (iphdrlen > p->len) {
199     LWIP_DEBUGF(IP_DEBUG | 2, ("IP header (len %"U16_F") does not fit in first pbuf (len %"U16_F"), IP packet droppped.\n",
200       iphdrlen, p->len));
201     /* free (drop) packet pbufs */
202     pbuf_free(p);
203     IP_STATS_INC(ip.lenerr);
204     IP_STATS_INC(ip.drop);
205     snmp_inc_ipindiscards();
206     return ERR_OK;
207   }
208
209   /* verify checksum */
210 #if CHECKSUM_CHECK_IP
211   if (inet_chksum(iphdr, iphdrlen) != 0) {
212
213     LWIP_DEBUGF(IP_DEBUG | 2, ("Checksum (0x%"X16_F") failed, IP packet dropped.\n", inet_chksum(iphdr, iphdrlen)));
214     ip_debug_print(p);
215     pbuf_free(p);
216     IP_STATS_INC(ip.chkerr);
217     IP_STATS_INC(ip.drop);
218     snmp_inc_ipindiscards();
219     return ERR_OK;
220   }
221 #endif
222
223   /* Trim pbuf. This should have been done at the netif layer,
224    * but we'll do it anyway just to be sure that its done. */
225   pbuf_realloc(p, ntohs(IPH_LEN(iphdr)));
226
227   /* match packet against an interface, i.e. is this packet for us? */
228   for (netif = netif_list; netif != NULL; netif = netif->next) {
229
230     LWIP_DEBUGF(IP_DEBUG, ("ip_input: iphdr->dest 0x%"X32_F" netif->ip_addr 0x%"X32_F" (0x%"X32_F", 0x%"X32_F", 0x%"X32_F")\n",
231       iphdr->dest.addr, netif->ip_addr.addr,
232       iphdr->dest.addr & netif->netmask.addr,
233       netif->ip_addr.addr & netif->netmask.addr,
234       iphdr->dest.addr & ~(netif->netmask.addr)));
235
236     /* interface is up and configured? */
237     if ((netif_is_up(netif)) && (!ip_addr_isany(&(netif->ip_addr))))
238     {
239       /* unicast to this interface address? */
240       if (ip_addr_cmp(&(iphdr->dest), &(netif->ip_addr)) ||
241          /* or broadcast on this interface network address? */
242          ip_addr_isbroadcast(&(iphdr->dest), netif)) {
243         LWIP_DEBUGF(IP_DEBUG, ("ip_input: packet accepted on interface %c%c\n",
244           netif->name[0], netif->name[1]));
245         /* break out of for loop */
246         break;
247       }
248     }
249   }
250 #if LWIP_DHCP
251   /* Pass DHCP messages regardless of destination address. DHCP traffic is addressed
252    * using link layer addressing (such as Ethernet MAC) so we must not filter on IP.
253    * According to RFC 1542 section 3.1.1, referred by RFC 2131).
254    */
255   if (netif == NULL) {
256     /* remote port is DHCP server? */
257     if (IPH_PROTO(iphdr) == IP_PROTO_UDP) {
258       LWIP_DEBUGF(IP_DEBUG | DBG_TRACE | 1, ("ip_input: UDP packet to DHCP client port %"U16_F"\n",
259         ntohs(((struct udp_hdr *)((u8_t *)iphdr + iphdrlen))->dest)));
260       if (ntohs(((struct udp_hdr *)((u8_t *)iphdr + iphdrlen))->dest) == DHCP_CLIENT_PORT) {
261         LWIP_DEBUGF(IP_DEBUG | DBG_TRACE | 1, ("ip_input: DHCP packet accepted.\n"));
262         netif = inp;
263       }
264     }
265   }
266 #endif /* LWIP_DHCP */
267   /* packet not for us? */
268   if (netif == NULL) {
269     /* packet not for us, route or discard */
270     LWIP_DEBUGF(IP_DEBUG | DBG_TRACE | 1, ("ip_input: packet not for us.\n"));
271 #if IP_FORWARD
272     /* non-broadcast packet? */
273     if (!ip_addr_isbroadcast(&(iphdr->dest), inp)) {
274       /* try to forward IP packet on (other) interfaces */
275       ip_forward(p, iphdr, inp);
276     }
277     else
278 #endif /* IP_FORWARD */
279     {
280       snmp_inc_ipindiscards();
281     }
282     pbuf_free(p);
283     return ERR_OK;
284   }
285   /* packet consists of multiple fragments? */
286   if ((IPH_OFFSET(iphdr) & htons(IP_OFFMASK | IP_MF)) != 0) {
287 #if IP_REASSEMBLY /* packet fragment reassembly code present? */
288     LWIP_DEBUGF(IP_DEBUG, ("IP packet is a fragment (id=0x%04"X16_F" tot_len=%"U16_F" len=%"U16_F" MF=%"U16_F" offset=%"U16_F"), calling ip_reass()\n",
289       ntohs(IPH_ID(iphdr)), p->tot_len, ntohs(IPH_LEN(iphdr)), !!(IPH_OFFSET(iphdr) & htons(IP_MF)), (ntohs(IPH_OFFSET(iphdr)) & IP_OFFMASK)*8));
290     /* reassemble the packet*/
291     p = ip_reass(p);
292     /* packet not fully reassembled yet? */
293     if (p == NULL) {
294       return ERR_OK;
295     }
296     iphdr = p->payload;
297 #else /* IP_REASSEMBLY == 0, no packet fragment reassembly code present */
298     pbuf_free(p);
299     LWIP_DEBUGF(IP_DEBUG | 2, ("IP packet dropped since it was fragmented (0x%"X16_F") (while IP_REASSEMBLY == 0).\n",
300       ntohs(IPH_OFFSET(iphdr))));
301     IP_STATS_INC(ip.opterr);
302     IP_STATS_INC(ip.drop);
303     snmp_inc_ipunknownprotos();
304     return ERR_OK;
305 #endif /* IP_REASSEMBLY */
306   }
307
308 #if IP_OPTIONS == 0 /* no support for IP options in the IP header? */
309   if (iphdrlen > IP_HLEN) {
310     LWIP_DEBUGF(IP_DEBUG | 2, ("IP packet dropped since there were IP options (while IP_OPTIONS == 0).\n"));
311     pbuf_free(p);
312     IP_STATS_INC(ip.opterr);
313     IP_STATS_INC(ip.drop);
314     snmp_inc_ipunknownprotos();
315     return ERR_OK;
316   }
317 #endif /* IP_OPTIONS == 0 */
318
319   /* send to upper layers */
320   LWIP_DEBUGF(IP_DEBUG, ("ip_input: \n"));
321   ip_debug_print(p);
322   LWIP_DEBUGF(IP_DEBUG, ("ip_input: p->len %"U16_F" p->tot_len %"U16_F"\n", p->len, p->tot_len));
323
324 #if LWIP_RAW
325   /* raw input did not eat the packet? */
326   if (raw_input(p, inp) == 0) {
327 #endif /* LWIP_RAW */
328
329   switch (IPH_PROTO(iphdr)) {
330 #if LWIP_UDP
331   case IP_PROTO_UDP:
332   case IP_PROTO_UDPLITE:
333     snmp_inc_ipindelivers();
334     udp_input(p, inp);
335     break;
336 #endif /* LWIP_UDP */
337 #if LWIP_TCP
338   case IP_PROTO_TCP:
339     snmp_inc_ipindelivers();
340     tcp_input(p, inp);
341     break;
342 #endif /* LWIP_TCP */
343   case IP_PROTO_ICMP:
344     snmp_inc_ipindelivers();
345     icmp_input(p, inp);
346     break;
347   default:
348     /* send ICMP destination protocol unreachable unless is was a broadcast */
349     if (!ip_addr_isbroadcast(&(iphdr->dest), inp) &&
350         !ip_addr_ismulticast(&(iphdr->dest))) {
351       p->payload = iphdr;
352       icmp_dest_unreach(p, ICMP_DUR_PROTO);
353     }
354     pbuf_free(p);
355
356     LWIP_DEBUGF(IP_DEBUG | 2, ("Unsupported transport protocol %"U16_F"\n", IPH_PROTO(iphdr)));
357
358     IP_STATS_INC(ip.proterr);
359     IP_STATS_INC(ip.drop);
360     snmp_inc_ipunknownprotos();
361   }
362 #if LWIP_RAW
363   } /* LWIP_RAW */
364 #endif
365   return ERR_OK;
366 }
367
368 /**
369  * Sends an IP packet on a network interface. This function constructs
370  * the IP header and calculates the IP header checksum. If the source
371  * IP address is NULL, the IP address of the outgoing network
372  * interface is filled in as source address.
373  */
374
375 err_t
376 ip_output_if(struct pbuf *p, struct ip_addr *src, struct ip_addr *dest,
377              u8_t ttl, u8_t tos,
378              u8_t proto, struct netif *netif)
379 {
380   struct ip_hdr *iphdr;
381   u16_t ip_id = 0;
382
383   snmp_inc_ipoutrequests();
384
385   if (dest != IP_HDRINCL) {
386     if (pbuf_header(p, IP_HLEN)) {
387       LWIP_DEBUGF(IP_DEBUG | 2, ("ip_output: not enough room for IP header in pbuf\n"));
388
389       IP_STATS_INC(ip.err);
390       snmp_inc_ipoutdiscards();
391       return ERR_BUF;
392     }
393
394     iphdr = p->payload;
395
396     IPH_TTL_SET(iphdr, ttl);
397     IPH_PROTO_SET(iphdr, proto);
398
399     ip_addr_set(&(iphdr->dest), dest);
400
401     IPH_VHLTOS_SET(iphdr, 4, IP_HLEN / 4, tos);
402     IPH_LEN_SET(iphdr, htons(p->tot_len));
403     IPH_OFFSET_SET(iphdr, htons(IP_DF));
404     IPH_ID_SET(iphdr, htons(ip_id));
405     ++ip_id;
406
407     if (ip_addr_isany(src)) {
408       ip_addr_set(&(iphdr->src), &(netif->ip_addr));
409     } else {
410       ip_addr_set(&(iphdr->src), src);
411     }
412
413     IPH_CHKSUM_SET(iphdr, 0);
414 #if CHECKSUM_GEN_IP
415     IPH_CHKSUM_SET(iphdr, inet_chksum(iphdr, IP_HLEN));
416 #endif
417   } else {
418     iphdr = p->payload;
419     dest = &(iphdr->dest);
420   }
421
422 #if IP_FRAG
423   /* don't fragment if interface has mtu set to 0 [loopif] */
424   if (netif->mtu && (p->tot_len > netif->mtu))
425     return ip_frag(p,netif,dest);
426 #endif
427
428   IP_STATS_INC(ip.xmit);
429
430   LWIP_DEBUGF(IP_DEBUG, ("ip_output_if: %c%c%"U16_F"\n", netif->name[0], netif->name[1], netif->num));
431   ip_debug_print(p);
432
433   LWIP_DEBUGF(IP_DEBUG, ("netif->output()"));
434
435   return netif->output(netif, p, dest);
436 }
437
438 /**
439  * Simple interface to ip_output_if. It finds the outgoing network
440  * interface and calls upon ip_output_if to do the actual work.
441  */
442
443 err_t
444 ip_output(struct pbuf *p, struct ip_addr *src, struct ip_addr *dest,
445           u8_t ttl, u8_t tos, u8_t proto)
446 {
447   struct netif *netif;
448
449   if ((netif = ip_route(dest)) == NULL) {
450     LWIP_DEBUGF(IP_DEBUG | 2, ("ip_output: No route to 0x%"X32_F"\n", dest->addr));
451
452     IP_STATS_INC(ip.rterr);
453     snmp_inc_ipoutdiscards();
454     return ERR_RTE;
455   }
456
457   return ip_output_if(p, src, dest, ttl, tos, proto, netif);
458 }
459
460 #if IP_DEBUG
461 void
462 ip_debug_print(struct pbuf *p)
463 {
464   struct ip_hdr *iphdr = p->payload;
465   u8_t *payload;
466
467   payload = (u8_t *)iphdr + IP_HLEN;
468
469   LWIP_DEBUGF(IP_DEBUG, ("IP header:\n"));
470   LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n"));
471   LWIP_DEBUGF(IP_DEBUG, ("|%2"S16_F" |%2"S16_F" |  0x%02"X16_F" |     %5"U16_F"     | (v, hl, tos, len)\n",
472                     IPH_V(iphdr),
473                     IPH_HL(iphdr),
474                     IPH_TOS(iphdr),
475                     ntohs(IPH_LEN(iphdr))));
476   LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n"));
477   LWIP_DEBUGF(IP_DEBUG, ("|    %5"U16_F"      |%"U16_F"%"U16_F"%"U16_F"|    %4"U16_F"   | (id, flags, offset)\n",
478                     ntohs(IPH_ID(iphdr)),
479                     ntohs(IPH_OFFSET(iphdr)) >> 15 & 1,
480                     ntohs(IPH_OFFSET(iphdr)) >> 14 & 1,
481                     ntohs(IPH_OFFSET(iphdr)) >> 13 & 1,
482                     ntohs(IPH_OFFSET(iphdr)) & IP_OFFMASK));
483   LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n"));
484   LWIP_DEBUGF(IP_DEBUG, ("|  %3"U16_F"  |  %3"U16_F"  |    0x%04"X16_F"     | (ttl, proto, chksum)\n",
485                     IPH_TTL(iphdr),
486                     IPH_PROTO(iphdr),
487                     ntohs(IPH_CHKSUM(iphdr))));
488   LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n"));
489   LWIP_DEBUGF(IP_DEBUG, ("|  %3"U16_F"  |  %3"U16_F"  |  %3"U16_F"  |  %3"U16_F"  | (src)\n",
490                     ip4_addr1(&iphdr->src),
491                     ip4_addr2(&iphdr->src),
492                     ip4_addr3(&iphdr->src),
493                     ip4_addr4(&iphdr->src)));
494   LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n"));
495   LWIP_DEBUGF(IP_DEBUG, ("|  %3"U16_F"  |  %3"U16_F"  |  %3"U16_F"  |  %3"U16_F"  | (dest)\n",
496                     ip4_addr1(&iphdr->dest),
497                     ip4_addr2(&iphdr->dest),
498                     ip4_addr3(&iphdr->dest),
499                     ip4_addr4(&iphdr->dest)));
500   LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n"));
501 }
502 #endif /* IP_DEBUG */
503
504
505
506
507
508