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