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