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 / ipv4 / ip.c
1 /**
2  * @file
3  * This is the IPv4 layer implementation for incoming and outgoing IP traffic.
4  * 
5  * @see ip_frag.c
6  *
7  */
8
9 /*
10  * Copyright (c) 2001-2004 Swedish Institute of Computer Science.
11  * All rights reserved.
12  *
13  * Redistribution and use in source and binary forms, with or without modification,
14  * are permitted provided that the following conditions are met:
15  *
16  * 1. Redistributions of source code must retain the above copyright notice,
17  *    this list of conditions and the following disclaimer.
18  * 2. Redistributions in binary form must reproduce the above copyright notice,
19  *    this list of conditions and the following disclaimer in the documentation
20  *    and/or other materials provided with the distribution.
21  * 3. The name of the author may not be used to endorse or promote products
22  *    derived from this software without specific prior written permission.
23  *
24  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
25  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
26  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
27  * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
28  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
29  * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
30  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
31  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
32  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
33  * OF SUCH DAMAGE.
34  *
35  * This file is part of the lwIP TCP/IP stack.
36  *
37  * Author: Adam Dunkels <adam@sics.se>
38  *
39  */
40
41 #include "lwip/opt.h"
42 #include "lwip/ip.h"
43 #include "lwip/def.h"
44 #include "lwip/mem.h"
45 #include "lwip/ip_frag.h"
46 #include "lwip/inet.h"
47 #include "lwip/inet_chksum.h"
48 #include "lwip/netif.h"
49 #include "lwip/icmp.h"
50 #include "lwip/igmp.h"
51 #include "lwip/raw.h"
52 #include "lwip/udp.h"
53 #include "lwip/tcp.h"
54 #include "lwip/snmp.h"
55 #include "lwip/dhcp.h"
56 #include "lwip/stats.h"
57 #include "arch/perf.h"
58
59 /**
60  * Finds the appropriate network interface for a given IP address. It
61  * searches the list of network interfaces linearly. A match is found
62  * if the masked IP address of the network interface equals the masked
63  * IP address given to the function.
64  *
65  * @param dest the destination IP address for which to find the route
66  * @return the netif on which to send to reach dest
67  */
68 struct netif *
69 ip_route(struct ip_addr *dest)
70 {
71   struct netif *netif;
72
73   /* iterate through netifs */
74   for(netif = netif_list; netif != NULL; netif = netif->next) {
75     /* network mask matches? */
76     if (netif_is_up(netif)) {
77       if (ip_addr_netcmp(dest, &(netif->ip_addr), &(netif->netmask))) {
78         /* return netif on which to forward IP packet */
79         return netif;
80       }
81     }
82   }
83   if ((netif_default == NULL) || (!netif_is_up(netif_default))) {
84     LWIP_DEBUGF(IP_DEBUG | 2, ("ip_route: No route to 0x%"X32_F"\n", dest->addr));
85     IP_STATS_INC(ip.rterr);
86     snmp_inc_ipoutnoroutes();
87     return NULL;
88   }
89   /* no matching netif found, use default netif */
90   return netif_default;
91 }
92
93 #if IP_FORWARD
94 /**
95  * Forwards an IP packet. It finds an appropriate route for the
96  * packet, decrements the TTL value of the packet, adjusts the
97  * checksum and outputs the packet on the appropriate interface.
98  *
99  * @param p the packet to forward (p->payload points to IP header)
100  * @param iphdr the IP header of the input packet
101  * @param inp the netif on which this packet was received
102  * @return the netif on which the packet was sent (NULL if it wasn't sent)
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_ipoutnoroutes();
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_ipoutnoroutes();
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     snmp_inc_ipinhdrerrors();
131 #if LWIP_ICMP
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 #endif /* LWIP_ICMP */
137     return (struct netif *)NULL;
138   }
139
140   /* Incrementally update the IP checksum. */
141   if (IPH_CHKSUM(iphdr) >= htons(0xffff - 0x100)) {
142     IPH_CHKSUM_SET(iphdr, IPH_CHKSUM(iphdr) + htons(0x100) + 1);
143   } else {
144     IPH_CHKSUM_SET(iphdr, IPH_CHKSUM(iphdr) + htons(0x100));
145   }
146
147   LWIP_DEBUGF(IP_DEBUG, ("ip_forward: forwarding packet to 0x%"X32_F"\n",
148                     iphdr->dest.addr));
149
150   IP_STATS_INC(ip.fw);
151   IP_STATS_INC(ip.xmit);
152   snmp_inc_ipforwdatagrams();
153
154   PERF_STOP("ip_forward");
155   /* transmit pbuf on chosen interface */
156   netif->output(netif, p, (struct ip_addr *)&(iphdr->dest));
157   return netif;
158 }
159 #endif /* IP_FORWARD */
160
161 /**
162  * This function is called by the network interface device driver when
163  * an IP packet is received. The function does the basic checks of the
164  * IP header such as packet size being at least larger than the header
165  * size etc. If the packet was not destined for us, the packet is
166  * forwarded (using ip_forward). The IP checksum is always checked.
167  *
168  * Finally, the packet is sent to the upper layer protocol input function.
169  * 
170  * @param p the received IP packet (p->payload points to IP header)
171  * @param inp the netif on which this packet was received
172  * @return ERR_OK if the packet was processed (could return ERR_* if it wasn't
173  *         processed, but currently always returns ERR_OK)
174  */
175 err_t
176 ip_input(struct pbuf *p, struct netif *inp)
177 {
178   struct ip_hdr *iphdr;
179   struct netif *netif;
180   u16_t iphdr_hlen;
181   u16_t iphdr_len;
182 #if LWIP_DHCP
183   int check_ip_src=1;
184 #endif /* LWIP_DHCP */
185
186   IP_STATS_INC(ip.recv);
187   snmp_inc_ipinreceives();
188
189   /* identify the IP header */
190   iphdr = p->payload;
191   if (IPH_V(iphdr) != 4) {
192     LWIP_DEBUGF(IP_DEBUG | 1, ("IP packet dropped due to bad version number %"U16_F"\n", IPH_V(iphdr)));
193     ip_debug_print(p);
194     pbuf_free(p);
195     IP_STATS_INC(ip.err);
196     IP_STATS_INC(ip.drop);
197     snmp_inc_ipinhdrerrors();
198     return ERR_OK;
199   }
200
201   /* obtain IP header length in number of 32-bit words */
202   iphdr_hlen = IPH_HL(iphdr);
203   /* calculate IP header length in bytes */
204   iphdr_hlen *= 4;
205   /* obtain ip length in bytes */
206   iphdr_len = ntohs(IPH_LEN(iphdr));
207
208   /* header length exceeds first pbuf length, or ip length exceeds total pbuf length? */
209   if ((iphdr_hlen > p->len) || (iphdr_len > p->tot_len)) {
210     if (iphdr_hlen > p->len)
211     LWIP_DEBUGF(IP_DEBUG | 2, ("IP header (len %"U16_F") does not fit in first pbuf (len %"U16_F"), IP packet dropped.\n",
212                                iphdr_hlen, p->len));
213     if (iphdr_len > p->tot_len)
214     LWIP_DEBUGF(IP_DEBUG | 2, ("IP (len %"U16_F") is longer than pbuf (len %"U16_F"), "
215                                "IP packet dropped.\n",
216                                iphdr_len, p->tot_len));
217     /* free (drop) packet pbufs */
218     pbuf_free(p);
219     IP_STATS_INC(ip.lenerr);
220     IP_STATS_INC(ip.drop);
221     snmp_inc_ipindiscards();
222     return ERR_OK;
223   }
224
225   /* verify checksum */
226 #if CHECKSUM_CHECK_IP
227   if (inet_chksum(iphdr, iphdr_hlen) != 0) {
228
229     LWIP_DEBUGF(IP_DEBUG | 2, ("Checksum (0x%"X16_F") failed, IP packet dropped.\n", inet_chksum(iphdr, iphdr_hlen)));
230     ip_debug_print(p);
231     pbuf_free(p);
232     IP_STATS_INC(ip.chkerr);
233     IP_STATS_INC(ip.drop);
234     snmp_inc_ipinhdrerrors();
235     return ERR_OK;
236   }
237 #endif
238
239   /* Trim pbuf. This should have been done at the netif layer,
240    * but we'll do it anyway just to be sure that its done. */
241   pbuf_realloc(p, iphdr_len);
242
243   /* match packet against an interface, i.e. is this packet for us? */
244 #if LWIP_IGMP
245   if (ip_addr_ismulticast(&(iphdr->dest))) {
246     if ((inp->flags & NETIF_FLAG_IGMP) && (igmp_lookfor_group(inp, &(iphdr->dest)))) {
247       netif = inp;
248     } else {
249       netif = NULL;
250     }
251   } else
252 #endif /* LWIP_IGMP */
253   {
254     /* start trying with inp. if that's not acceptable, start walking the
255        list of configured netifs.
256        'first' is used as a boolean to mark whether we started walking the list */
257     int first = 1;
258     netif = inp;
259     do {
260       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",
261           iphdr->dest.addr, netif->ip_addr.addr,
262           iphdr->dest.addr & netif->netmask.addr,
263           netif->ip_addr.addr & netif->netmask.addr,
264           iphdr->dest.addr & ~(netif->netmask.addr)));
265
266       /* interface is up and configured? */
267       if ((netif_is_up(netif)) && (!ip_addr_isany(&(netif->ip_addr)))) {
268         /* unicast to this interface address? */
269         if (ip_addr_cmp(&(iphdr->dest), &(netif->ip_addr)) ||
270             /* or broadcast on this interface network address? */
271             ip_addr_isbroadcast(&(iphdr->dest), netif)) {
272           LWIP_DEBUGF(IP_DEBUG, ("ip_input: packet accepted on interface %c%c\n",
273               netif->name[0], netif->name[1]));
274           /* break out of for loop */
275           break;
276         }
277       }
278       if (first) {
279         first = 0;
280         netif = netif_list;
281       } else {
282         netif = netif->next;
283       }
284       if (netif == inp) {
285         netif = netif->next;
286       }
287     } while(netif != NULL);
288   }
289
290 #if LWIP_DHCP
291   /* Pass DHCP messages regardless of destination address. DHCP traffic is addressed
292    * using link layer addressing (such as Ethernet MAC) so we must not filter on IP.
293    * According to RFC 1542 section 3.1.1, referred by RFC 2131).
294    */
295   if (netif == NULL) {
296     /* remote port is DHCP server? */
297     if (IPH_PROTO(iphdr) == IP_PROTO_UDP) {
298       LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_TRACE | 1, ("ip_input: UDP packet to DHCP client port %"U16_F"\n",
299         ntohs(((struct udp_hdr *)((u8_t *)iphdr + iphdr_hlen))->dest)));
300       if (ntohs(((struct udp_hdr *)((u8_t *)iphdr + iphdr_hlen))->dest) == DHCP_CLIENT_PORT) {
301         LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_TRACE | 1, ("ip_input: DHCP packet accepted.\n"));
302         netif = inp;
303         check_ip_src = 0;
304       }
305     }
306   }
307 #endif /* LWIP_DHCP */
308
309   /* broadcast or multicast packet source address? Compliant with RFC 1122: 3.2.1.3 */
310 #if LWIP_DHCP
311   if (check_ip_src)
312 #endif /* LWIP_DHCP */
313   {  if ((ip_addr_isbroadcast(&(iphdr->src), inp)) ||
314          (ip_addr_ismulticast(&(iphdr->src)))) {
315       /* packet source is not valid */
316       LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_TRACE | 1, ("ip_input: packet source is not valid.\n"));
317       /* free (drop) packet pbufs */
318       pbuf_free(p);
319       IP_STATS_INC(ip.drop);
320       snmp_inc_ipinaddrerrors();
321       snmp_inc_ipindiscards();
322       return ERR_OK;
323     }
324   }
325
326   /* packet not for us? */
327   if (netif == NULL) {
328     /* packet not for us, route or discard */
329     LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_TRACE | 1, ("ip_input: packet not for us.\n"));
330 #if IP_FORWARD
331     /* non-broadcast packet? */
332     if (!ip_addr_isbroadcast(&(iphdr->dest), inp)) {
333       /* try to forward IP packet on (other) interfaces */
334       ip_forward(p, iphdr, inp);
335     } else
336 #endif /* IP_FORWARD */
337     {
338       snmp_inc_ipinaddrerrors();
339       snmp_inc_ipindiscards();
340     }
341     pbuf_free(p);
342     return ERR_OK;
343   }
344   /* packet consists of multiple fragments? */
345   if ((IPH_OFFSET(iphdr) & htons(IP_OFFMASK | IP_MF)) != 0) {
346 #if IP_REASSEMBLY /* packet fragment reassembly code present? */
347     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",
348       ntohs(IPH_ID(iphdr)), p->tot_len, ntohs(IPH_LEN(iphdr)), !!(IPH_OFFSET(iphdr) & htons(IP_MF)), (ntohs(IPH_OFFSET(iphdr)) & IP_OFFMASK)*8));
349     /* reassemble the packet*/
350     p = ip_reass(p);
351     /* packet not fully reassembled yet? */
352     if (p == NULL) {
353       return ERR_OK;
354     }
355     iphdr = p->payload;
356 #else /* IP_REASSEMBLY == 0, no packet fragment reassembly code present */
357     pbuf_free(p);
358     LWIP_DEBUGF(IP_DEBUG | 2, ("IP packet dropped since it was fragmented (0x%"X16_F") (while IP_REASSEMBLY == 0).\n",
359       ntohs(IPH_OFFSET(iphdr))));
360     IP_STATS_INC(ip.opterr);
361     IP_STATS_INC(ip.drop);
362     /* unsupported protocol feature */
363     snmp_inc_ipinunknownprotos();
364     return ERR_OK;
365 #endif /* IP_REASSEMBLY */
366   }
367
368 #if IP_OPTIONS_ALLOWED == 0 /* no support for IP options in the IP header? */
369
370 #if LWIP_IGMP
371   /* there is an extra "router alert" option in IGMP messages which we allow for but do not police */
372   if((iphdr_hlen > IP_HLEN &&  (IPH_PROTO(iphdr) != IP_PROTO_IGMP)) {
373 #else
374   if (iphdr_hlen > IP_HLEN) {
375 #endif /* LWIP_IGMP */
376     LWIP_DEBUGF(IP_DEBUG | 2, ("IP packet dropped since there were IP options (while IP_OPTIONS_ALLOWED == 0).\n"));
377     pbuf_free(p);
378     IP_STATS_INC(ip.opterr);
379     IP_STATS_INC(ip.drop);
380     /* unsupported protocol feature */
381     snmp_inc_ipinunknownprotos();
382     return ERR_OK;
383   }
384 #endif /* IP_OPTIONS_ALLOWED == 0 */
385
386   /* send to upper layers */
387   LWIP_DEBUGF(IP_DEBUG, ("ip_input: \n"));
388   ip_debug_print(p);
389   LWIP_DEBUGF(IP_DEBUG, ("ip_input: p->len %"U16_F" p->tot_len %"U16_F"\n", p->len, p->tot_len));
390
391 #if LWIP_RAW
392   /* raw input did not eat the packet? */
393   if (raw_input(p, inp) == 0)
394 #endif /* LWIP_RAW */
395   {
396
397     switch (IPH_PROTO(iphdr)) {
398 #if LWIP_UDP
399     case IP_PROTO_UDP:
400 #if LWIP_UDPLITE
401     case IP_PROTO_UDPLITE:
402 #endif /* LWIP_UDPLITE */
403       snmp_inc_ipindelivers();
404       udp_input(p, inp);
405       break;
406 #endif /* LWIP_UDP */
407 #if LWIP_TCP
408     case IP_PROTO_TCP:
409       snmp_inc_ipindelivers();
410       tcp_input(p, inp);
411       break;
412 #endif /* LWIP_TCP */
413 #if LWIP_ICMP
414     case IP_PROTO_ICMP:
415       snmp_inc_ipindelivers();
416       icmp_input(p, inp);
417       break;
418 #endif /* LWIP_ICMP */
419 #if LWIP_IGMP
420     case IP_PROTO_IGMP:
421       igmp_input(p,inp,&(iphdr->dest));
422       break;
423 #endif /* LWIP_IGMP */
424     default:
425 #if LWIP_ICMP
426       /* send ICMP destination protocol unreachable unless is was a broadcast */
427       if (!ip_addr_isbroadcast(&(iphdr->dest), inp) &&
428           !ip_addr_ismulticast(&(iphdr->dest))) {
429         p->payload = iphdr;
430         icmp_dest_unreach(p, ICMP_DUR_PROTO);
431       }
432 #endif /* LWIP_ICMP */
433       pbuf_free(p);
434
435       LWIP_DEBUGF(IP_DEBUG | 2, ("Unsupported transport protocol %"U16_F"\n", IPH_PROTO(iphdr)));
436
437       IP_STATS_INC(ip.proterr);
438       IP_STATS_INC(ip.drop);
439       snmp_inc_ipinunknownprotos();
440     }
441   }
442
443   return ERR_OK;
444 }
445
446 /**
447  * Sends an IP packet on a network interface. This function constructs
448  * the IP header and calculates the IP header checksum. If the source
449  * IP address is NULL, the IP address of the outgoing network
450  * interface is filled in as source address.
451  * If the destination IP address is IP_HDRINCL, p is assumed to already
452  * include an IP header and p->payload points to it instead of the data.
453  *
454  * @param p the packet to send (p->payload points to the data, e.g. next
455             protocol header; if dest == IP_HDRINCL, p already includes an IP
456             header and p->payload points to that IP header)
457  * @param src the source IP address to send from (if src == IP_ADDR_ANY, the
458  *         IP  address of the netif used to send is used as source address)
459  * @param dest the destination IP address to send the packet to
460  * @param ttl the TTL value to be set in the IP header
461  * @param tos the TOS value to be set in the IP header
462  * @param proto the PROTOCOL to be set in the IP header
463  * @param netif the netif on which to send this packet
464  * @return ERR_OK if the packet was sent OK
465  *         ERR_BUF if p doesn't have enough space for IP/LINK headers
466  *         returns errors returned by netif->output
467  *
468  * @note ip_id: RFC791 "some host may be able to simply use
469  *  unique identifiers independent of destination"
470  */
471 err_t
472 ip_output_if(struct pbuf *p, struct ip_addr *src, struct ip_addr *dest,
473              u8_t ttl, u8_t tos,
474              u8_t proto, struct netif *netif)
475 {
476   struct ip_hdr *iphdr;
477   static u16_t ip_id = 0;
478
479   snmp_inc_ipoutrequests();
480
481   /* Should the IP header be generated or is it already included in p? */
482   if (dest != IP_HDRINCL) {
483     /* generate IP header */
484     if (pbuf_header(p, IP_HLEN)) {
485       LWIP_DEBUGF(IP_DEBUG | 2, ("ip_output: not enough room for IP header in pbuf\n"));
486
487       IP_STATS_INC(ip.err);
488       snmp_inc_ipoutdiscards();
489       return ERR_BUF;
490     }
491
492     iphdr = p->payload;
493     LWIP_ASSERT("check that first pbuf can hold struct ip_hdr",
494                (p->len >= sizeof(struct ip_hdr)));
495
496     IPH_TTL_SET(iphdr, ttl);
497     IPH_PROTO_SET(iphdr, proto);
498
499     ip_addr_set(&(iphdr->dest), dest);
500
501     IPH_VHLTOS_SET(iphdr, 4, IP_HLEN / 4, tos);
502     IPH_LEN_SET(iphdr, htons(p->tot_len));
503     IPH_OFFSET_SET(iphdr, 0);
504     IPH_ID_SET(iphdr, htons(ip_id));
505     ++ip_id;
506
507     if (ip_addr_isany(src)) {
508       ip_addr_set(&(iphdr->src), &(netif->ip_addr));
509     } else {
510       ip_addr_set(&(iphdr->src), src);
511     }
512
513     IPH_CHKSUM_SET(iphdr, 0);
514 #if CHECKSUM_GEN_IP
515     IPH_CHKSUM_SET(iphdr, inet_chksum(iphdr, IP_HLEN));
516 #endif
517   } else {
518     /* IP header already included in p */
519     iphdr = p->payload;
520     dest = &(iphdr->dest);
521   }
522
523 #if IP_FRAG
524   /* don't fragment if interface has mtu set to 0 [loopif] */
525   if (netif->mtu && (p->tot_len > netif->mtu))
526     return ip_frag(p,netif,dest);
527 #endif
528
529   IP_STATS_INC(ip.xmit);
530
531   LWIP_DEBUGF(IP_DEBUG, ("ip_output_if: %c%c%"U16_F"\n", netif->name[0], netif->name[1], netif->num));
532   ip_debug_print(p);
533
534   LWIP_DEBUGF(IP_DEBUG, ("netif->output()"));
535
536   return netif->output(netif, p, dest);
537 }
538
539 /**
540  * Simple interface to ip_output_if. It finds the outgoing network
541  * interface and calls upon ip_output_if to do the actual work.
542  *
543  * @param p the packet to send (p->payload points to the data, e.g. next
544             protocol header; if dest == IP_HDRINCL, p already includes an IP
545             header and p->payload points to that IP header)
546  * @param src the source IP address to send from (if src == IP_ADDR_ANY, the
547  *         IP  address of the netif used to send is used as source address)
548  * @param dest the destination IP address to send the packet to
549  * @param ttl the TTL value to be set in the IP header
550  * @param tos the TOS value to be set in the IP header
551  * @param proto the PROTOCOL to be set in the IP header
552  *
553  * @return ERR_RTE if no route is found
554  *         see ip_output_if() for more return values
555  */
556 err_t
557 ip_output(struct pbuf *p, struct ip_addr *src, struct ip_addr *dest,
558           u8_t ttl, u8_t tos, u8_t proto)
559 {
560   struct netif *netif;
561
562   if ((netif = ip_route(dest)) == NULL) {
563     return ERR_RTE;
564   }
565
566   return ip_output_if(p, src, dest, ttl, tos, proto, netif);
567 }
568
569 #if IP_DEBUG
570 /* Print an IP header by using LWIP_DEBUGF
571  * @param p an IP packet, p->payload pointing to the IP header
572  */
573 void
574 ip_debug_print(struct pbuf *p)
575 {
576   struct ip_hdr *iphdr = p->payload;
577   u8_t *payload;
578
579   payload = (u8_t *)iphdr + IP_HLEN;
580
581   LWIP_DEBUGF(IP_DEBUG, ("IP header:\n"));
582   LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n"));
583   LWIP_DEBUGF(IP_DEBUG, ("|%2"S16_F" |%2"S16_F" |  0x%02"X16_F" |     %5"U16_F"     | (v, hl, tos, len)\n",
584                     IPH_V(iphdr),
585                     IPH_HL(iphdr),
586                     IPH_TOS(iphdr),
587                     ntohs(IPH_LEN(iphdr))));
588   LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n"));
589   LWIP_DEBUGF(IP_DEBUG, ("|    %5"U16_F"      |%"U16_F"%"U16_F"%"U16_F"|    %4"U16_F"   | (id, flags, offset)\n",
590                     ntohs(IPH_ID(iphdr)),
591                     ntohs(IPH_OFFSET(iphdr)) >> 15 & 1,
592                     ntohs(IPH_OFFSET(iphdr)) >> 14 & 1,
593                     ntohs(IPH_OFFSET(iphdr)) >> 13 & 1,
594                     ntohs(IPH_OFFSET(iphdr)) & IP_OFFMASK));
595   LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n"));
596   LWIP_DEBUGF(IP_DEBUG, ("|  %3"U16_F"  |  %3"U16_F"  |    0x%04"X16_F"     | (ttl, proto, chksum)\n",
597                     IPH_TTL(iphdr),
598                     IPH_PROTO(iphdr),
599                     ntohs(IPH_CHKSUM(iphdr))));
600   LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n"));
601   LWIP_DEBUGF(IP_DEBUG, ("|  %3"U16_F"  |  %3"U16_F"  |  %3"U16_F"  |  %3"U16_F"  | (src)\n",
602                     ip4_addr1(&iphdr->src),
603                     ip4_addr2(&iphdr->src),
604                     ip4_addr3(&iphdr->src),
605                     ip4_addr4(&iphdr->src)));
606   LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n"));
607   LWIP_DEBUGF(IP_DEBUG, ("|  %3"U16_F"  |  %3"U16_F"  |  %3"U16_F"  |  %3"U16_F"  | (dest)\n",
608                     ip4_addr1(&iphdr->dest),
609                     ip4_addr2(&iphdr->dest),
610                     ip4_addr3(&iphdr->dest),
611                     ip4_addr4(&iphdr->dest)));
612   LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n"));
613 }
614 #endif /* IP_DEBUG */