ON Semiconductor / mbed-os

Dependents:   mbed-TFT-example-NCS36510 mbed-Accelerometer-example-NCS36510 mbed-Accelerometer-example-NCS36510

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers lwip_ip6.c Source File

lwip_ip6.c

Go to the documentation of this file.
00001 /**
00002  * @file
00003  *
00004  * IPv6 layer.
00005  */
00006 
00007 /*
00008  * Copyright (c) 2010 Inico Technologies Ltd.
00009  * All rights reserved.
00010  *
00011  * Redistribution and use in source and binary forms, with or without modification,
00012  * are permitted provided that the following conditions are met:
00013  *
00014  * 1. Redistributions of source code must retain the above copyright notice,
00015  *    this list of conditions and the following disclaimer.
00016  * 2. Redistributions in binary form must reproduce the above copyright notice,
00017  *    this list of conditions and the following disclaimer in the documentation
00018  *    and/or other materials provided with the distribution.
00019  * 3. The name of the author may not be used to endorse or promote products
00020  *    derived from this software without specific prior written permission.
00021  *
00022  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
00023  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
00024  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
00025  * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
00026  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
00027  * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
00028  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
00029  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
00030  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
00031  * OF SUCH DAMAGE.
00032  *
00033  * This file is part of the lwIP TCP/IP stack.
00034  *
00035  * Author: Ivan Delamer <delamer@inicotech.com>
00036  *
00037  *
00038  * Please coordinate changes and requests with Ivan Delamer
00039  * <delamer@inicotech.com>
00040  */
00041 
00042 #include "lwip/opt.h"
00043 
00044 #if LWIP_IPV6  /* don't build if not configured for use in lwipopts.h */
00045 
00046 #include "lwip/def.h"
00047 #include "lwip/mem.h"
00048 #include "lwip/netif.h"
00049 #include "lwip/ip6.h"
00050 #include "lwip/ip6_addr.h"
00051 #include "lwip/ip6_frag.h"
00052 #include "lwip/icmp6.h"
00053 #include "lwip/raw.h"
00054 #include "lwip/udp.h"
00055 #include "lwip/priv/tcp_priv.h"
00056 #include "lwip/dhcp6.h"
00057 #include "lwip/nd6.h"
00058 #include "lwip/mld6.h"
00059 #include "lwip/debug.h"
00060 #include "lwip/stats.h"
00061 
00062 /**
00063  * Finds the appropriate network interface for a given IPv6 address. It tries to select
00064  * a netif following a sequence of heuristics:
00065  * 1) if there is only 1 netif, return it
00066  * 2) if the destination is a link-local address, try to match the src address to a netif.
00067  *    this is a tricky case because with multiple netifs, link-local addresses only have
00068  *    meaning within a particular subnet/link.
00069  * 3) tries to match the destination subnet to a configured address
00070  * 4) tries to find a router
00071  * 5) tries to match the source address to the netif
00072  * 6) returns the default netif, if configured
00073  *
00074  * @param src the source IPv6 address, if known
00075  * @param dest the destination IPv6 address for which to find the route
00076  * @return the netif on which to send to reach dest
00077  */
00078 struct netif *
00079 ip6_route(const ip6_addr_t *src, const ip6_addr_t *dest)
00080 {
00081   struct netif *netif;
00082   s8_t i;
00083 
00084   /* If single netif configuration, fast return. */
00085   if ((netif_list != NULL) && (netif_list->next == NULL)) {
00086     if (!netif_is_up(netif_list) || !netif_is_link_up(netif_list)) {
00087       return NULL;
00088     }
00089     return netif_list;
00090   }
00091 
00092   /* Special processing for link-local addresses. */
00093   if (ip6_addr_islinklocal(dest)) {
00094     if (ip6_addr_isany(src)) {
00095       /* Use default netif, if Up. */
00096       if (!netif_is_up(netif_default) || !netif_is_link_up(netif_default)) {
00097         return NULL;
00098       }
00099       return netif_default;
00100     }
00101 
00102     /* Try to find the netif for the source address, checking that link is up. */
00103     for (netif = netif_list; netif != NULL; netif = netif->next) {
00104       if (!netif_is_up(netif) || !netif_is_link_up(netif)) {
00105         continue;
00106       }
00107       for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) {
00108         if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i)) &&
00109             ip6_addr_cmp(src, netif_ip6_addr(netif, i))) {
00110           return netif;
00111         }
00112       }
00113     }
00114 
00115     /* netif not found, use default netif, if up */
00116     if (!netif_is_up(netif_default) || !netif_is_link_up(netif_default)) {
00117       return NULL;
00118     }
00119     return netif_default;
00120   }
00121 
00122   /* we come here for non-link-local addresses */
00123 #ifdef LWIP_HOOK_IP6_ROUTE
00124   netif = LWIP_HOOK_IP6_ROUTE(src, dest);
00125   if (netif != NULL) {
00126     return netif;
00127   }
00128 #endif
00129 
00130   /* See if the destination subnet matches a configured address. */
00131   for (netif = netif_list; netif != NULL; netif = netif->next) {
00132     if (!netif_is_up(netif) || !netif_is_link_up(netif)) {
00133       continue;
00134     }
00135     for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) {
00136       if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i)) &&
00137           ip6_addr_netcmp(dest, netif_ip6_addr(netif, i))) {
00138         return netif;
00139       }
00140     }
00141   }
00142 
00143   /* Get the netif for a suitable router. */
00144   i = nd6_select_router(dest, NULL);
00145   if (i >= 0) {
00146     if (default_router_list[i].neighbor_entry != NULL) {
00147       if (default_router_list[i].neighbor_entry->netif != NULL) {
00148         if (netif_is_up(default_router_list[i].neighbor_entry->netif) && netif_is_link_up(default_router_list[i].neighbor_entry->netif)) {
00149           return default_router_list[i].neighbor_entry->netif;
00150         }
00151       }
00152     }
00153   }
00154 
00155   /* try with the netif that matches the source address. */
00156   if (!ip6_addr_isany(src)) {
00157     for (netif = netif_list; netif != NULL; netif = netif->next) {
00158       if (!netif_is_up(netif) || !netif_is_link_up(netif)) {
00159         continue;
00160       }
00161       for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) {
00162         if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i)) &&
00163             ip6_addr_cmp(src, netif_ip6_addr(netif, i))) {
00164           return netif;
00165         }
00166       }
00167     }
00168   }
00169 
00170 #if LWIP_NETIF_LOOPBACK && !LWIP_HAVE_LOOPIF
00171   /* loopif is disabled, loopback traffic is passed through any netif */
00172   if (ip6_addr_isloopback(dest)) {
00173     /* don't check for link on loopback traffic */
00174     if (netif_is_up(netif_default)) {
00175       return netif_default;
00176     }
00177     /* default netif is not up, just use any netif for loopback traffic */
00178     for (netif = netif_list; netif != NULL; netif = netif->next) {
00179       if (netif_is_up(netif)) {
00180         return netif;
00181       }
00182     }
00183     return NULL;
00184   }
00185 #endif /* LWIP_NETIF_LOOPBACK && !LWIP_HAVE_LOOPIF */
00186 
00187   /* no matching netif found, use default netif, if up */
00188   if ((netif_default == NULL) || !netif_is_up(netif_default) || !netif_is_link_up(netif_default)) {
00189     return NULL;
00190   }
00191   return netif_default;
00192 }
00193 
00194 /**
00195  * Select the best IPv6 source address for a given destination
00196  * IPv6 address. Loosely follows RFC 3484. "Strong host" behavior
00197  * is assumed.
00198  *
00199  * @param netif the netif on which to send a packet
00200  * @param dest the destination we are trying to reach
00201  * @return the most suitable source address to use, or NULL if no suitable
00202  *         source address is found
00203  */
00204 const ip_addr_t *
00205 ip6_select_source_address(struct netif *netif, const ip6_addr_t * dest)
00206 {
00207   const ip_addr_t *src = NULL;
00208   u8_t i;
00209 
00210   /* If dest is link-local, choose a link-local source. */
00211   if (ip6_addr_islinklocal(dest) || ip6_addr_ismulticast_linklocal(dest) || ip6_addr_ismulticast_iflocal(dest)) {
00212     for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) {
00213       if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i)) &&
00214           ip6_addr_islinklocal(netif_ip6_addr(netif, i))) {
00215         return netif_ip_addr6(netif, i);
00216       }
00217     }
00218   }
00219 
00220   /* Choose a site-local with matching prefix. */
00221   if (ip6_addr_issitelocal(dest) || ip6_addr_ismulticast_sitelocal(dest)) {
00222     for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) {
00223       if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i)) &&
00224           ip6_addr_issitelocal(netif_ip6_addr(netif, i)) &&
00225           ip6_addr_netcmp(dest, netif_ip6_addr(netif, i))) {
00226         return netif_ip_addr6(netif, i);
00227       }
00228     }
00229   }
00230 
00231   /* Choose a unique-local with matching prefix. */
00232   if (ip6_addr_isuniquelocal(dest) || ip6_addr_ismulticast_orglocal(dest)) {
00233     for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) {
00234       if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i)) &&
00235           ip6_addr_isuniquelocal(netif_ip6_addr(netif, i)) &&
00236           ip6_addr_netcmp(dest, netif_ip6_addr(netif, i))) {
00237         return netif_ip_addr6(netif, i);
00238       }
00239     }
00240   }
00241 
00242   /* Choose a global with best matching prefix. */
00243   if (ip6_addr_isglobal(dest) || ip6_addr_ismulticast_global(dest)) {
00244     for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) {
00245       if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i)) &&
00246           ip6_addr_isglobal(netif_ip6_addr(netif, i))) {
00247         if (src == NULL) {
00248           src = netif_ip_addr6(netif, i);
00249         }
00250         else {
00251           /* Replace src only if we find a prefix match. */
00252           /* @todo find longest matching prefix. */
00253           if ((!(ip6_addr_netcmp(ip_2_ip6(src), dest))) &&
00254               ip6_addr_netcmp(netif_ip6_addr(netif, i), dest)) {
00255             src = netif_ip_addr6(netif, i);
00256           }
00257         }
00258       }
00259     }
00260     if (src != NULL) {
00261       return src;
00262     }
00263   }
00264 
00265   /* Last resort: see if arbitrary prefix matches. */
00266   for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) {
00267     if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i)) &&
00268         ip6_addr_netcmp(dest, netif_ip6_addr(netif, i))) {
00269       return netif_ip_addr6(netif, i);
00270     }
00271   }
00272 
00273   return NULL;
00274 }
00275 
00276 #if LWIP_IPV6_FORWARD
00277 /**
00278  * Forwards an IPv6 packet. It finds an appropriate route for the
00279  * packet, decrements the HL value of the packet, and outputs
00280  * the packet on the appropriate interface.
00281  *
00282  * @param p the packet to forward (p->payload points to IP header)
00283  * @param iphdr the IPv6 header of the input packet
00284  * @param inp the netif on which this packet was received
00285  */
00286 static void
00287 ip6_forward(struct pbuf *p, struct ip6_hdr *iphdr, struct netif *inp)
00288 {
00289   struct netif *netif;
00290 
00291   /* do not forward link-local addresses */
00292   if (ip6_addr_islinklocal(ip6_current_dest_addr())) {
00293     LWIP_DEBUGF(IP6_DEBUG, ("ip6_forward: not forwarding link-local address.\n"));
00294     IP6_STATS_INC(ip6.rterr);
00295     IP6_STATS_INC(ip6.drop);
00296     return;
00297   }
00298 
00299   /* Find network interface where to forward this IP packet to. */
00300   netif = ip6_route(IP6_ADDR_ANY6, ip6_current_dest_addr());
00301   if (netif == NULL) {
00302     LWIP_DEBUGF(IP6_DEBUG, ("ip6_forward: no route for %"X16_F":%"X16_F":%"X16_F":%"X16_F":%"X16_F":%"X16_F":%"X16_F":%"X16_F"\n",
00303         IP6_ADDR_BLOCK1(ip6_current_dest_addr()),
00304         IP6_ADDR_BLOCK2(ip6_current_dest_addr()),
00305         IP6_ADDR_BLOCK3(ip6_current_dest_addr()),
00306         IP6_ADDR_BLOCK4(ip6_current_dest_addr()),
00307         IP6_ADDR_BLOCK5(ip6_current_dest_addr()),
00308         IP6_ADDR_BLOCK6(ip6_current_dest_addr()),
00309         IP6_ADDR_BLOCK7(ip6_current_dest_addr()),
00310         IP6_ADDR_BLOCK8(ip6_current_dest_addr())));
00311 #if LWIP_ICMP6
00312     /* Don't send ICMP messages in response to ICMP messages */
00313     if (IP6H_NEXTH(iphdr) != IP6_NEXTH_ICMP6) {
00314       icmp6_dest_unreach(p, ICMP6_DUR_NO_ROUTE);
00315     }
00316 #endif /* LWIP_ICMP6 */
00317     IP6_STATS_INC(ip6.rterr);
00318     IP6_STATS_INC(ip6.drop);
00319     return;
00320   }
00321   /* Do not forward packets onto the same network interface on which
00322    * they arrived. */
00323   if (netif == inp) {
00324     LWIP_DEBUGF(IP6_DEBUG, ("ip6_forward: not bouncing packets back on incoming interface.\n"));
00325     IP6_STATS_INC(ip6.rterr);
00326     IP6_STATS_INC(ip6.drop);
00327     return;
00328   }
00329 
00330   /* decrement HL */
00331   IP6H_HOPLIM_SET(iphdr, IP6H_HOPLIM(iphdr) - 1);
00332   /* send ICMP6 if HL == 0 */
00333   if (IP6H_HOPLIM(iphdr) == 0) {
00334 #if LWIP_ICMP6
00335     /* Don't send ICMP messages in response to ICMP messages */
00336     if (IP6H_NEXTH(iphdr) != IP6_NEXTH_ICMP6) {
00337       icmp6_time_exceeded(p, ICMP6_TE_HL);
00338     }
00339 #endif /* LWIP_ICMP6 */
00340     IP6_STATS_INC(ip6.drop);
00341     return;
00342   }
00343 
00344   if (netif->mtu && (p->tot_len > netif->mtu)) {
00345 #if LWIP_ICMP6
00346     /* Don't send ICMP messages in response to ICMP messages */
00347     if (IP6H_NEXTH(iphdr) != IP6_NEXTH_ICMP6) {
00348       icmp6_packet_too_big(p, netif->mtu);
00349     }
00350 #endif /* LWIP_ICMP6 */
00351     IP6_STATS_INC(ip6.drop);
00352     return;
00353   }
00354 
00355   LWIP_DEBUGF(IP6_DEBUG, ("ip6_forward: forwarding packet to %"X16_F":%"X16_F":%"X16_F":%"X16_F":%"X16_F":%"X16_F":%"X16_F":%"X16_F"\n",
00356       IP6_ADDR_BLOCK1(ip6_current_dest_addr()),
00357       IP6_ADDR_BLOCK2(ip6_current_dest_addr()),
00358       IP6_ADDR_BLOCK3(ip6_current_dest_addr()),
00359       IP6_ADDR_BLOCK4(ip6_current_dest_addr()),
00360       IP6_ADDR_BLOCK5(ip6_current_dest_addr()),
00361       IP6_ADDR_BLOCK6(ip6_current_dest_addr()),
00362       IP6_ADDR_BLOCK7(ip6_current_dest_addr()),
00363       IP6_ADDR_BLOCK8(ip6_current_dest_addr())));
00364 
00365   /* transmit pbuf on chosen interface */
00366   netif->output_ip6(netif, p, ip6_current_dest_addr());
00367   IP6_STATS_INC(ip6.fw);
00368   IP6_STATS_INC(ip6.xmit);
00369   return;
00370 }
00371 #endif /* LWIP_IPV6_FORWARD */
00372 
00373 /**
00374  * This function is called by the network interface device driver when
00375  * an IPv6 packet is received. The function does the basic checks of the
00376  * IP header such as packet size being at least larger than the header
00377  * size etc. If the packet was not destined for us, the packet is
00378  * forwarded (using ip6_forward).
00379  *
00380  * Finally, the packet is sent to the upper layer protocol input function.
00381  *
00382  * @param p the received IPv6 packet (p->payload points to IPv6 header)
00383  * @param inp the netif on which this packet was received
00384  * @return ERR_OK if the packet was processed (could return ERR_* if it wasn't
00385  *         processed, but currently always returns ERR_OK)
00386  */
00387 err_t
00388 ip6_input(struct pbuf *p, struct netif *inp)
00389 {
00390   struct ip6_hdr *ip6hdr;
00391   struct netif *netif;
00392   u8_t nexth;
00393   u16_t hlen; /* the current header length */
00394   u8_t i;
00395 #if 0 /*IP_ACCEPT_LINK_LAYER_ADDRESSING*/
00396   @todo
00397   int check_ip_src=1;
00398 #endif /* IP_ACCEPT_LINK_LAYER_ADDRESSING */
00399 
00400   IP6_STATS_INC(ip6.recv);
00401 
00402   /* identify the IP header */
00403   ip6hdr = (struct ip6_hdr *)p->payload;
00404   if (IP6H_V(ip6hdr) != 6) {
00405     LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_LEVEL_WARNING, ("IPv6 packet dropped due to bad version number %"U32_F"\n",
00406         IP6H_V(ip6hdr)));
00407     pbuf_free(p);
00408     IP6_STATS_INC(ip6.err);
00409     IP6_STATS_INC(ip6.drop);
00410     return ERR_OK;
00411   }
00412 
00413 #ifdef LWIP_HOOK_IP6_INPUT
00414   if (LWIP_HOOK_IP6_INPUT(p, inp)) {
00415     /* the packet has been eaten */
00416     return ERR_OK;
00417   }
00418 #endif
00419 
00420   /* header length exceeds first pbuf length, or ip length exceeds total pbuf length? */
00421   if ((IP6_HLEN > p->len) || ((IP6H_PLEN(ip6hdr) + IP6_HLEN) > p->tot_len)) {
00422     if (IP6_HLEN > p->len) {
00423       LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_LEVEL_SERIOUS,
00424         ("IPv6 header (len %"U16_F") does not fit in first pbuf (len %"U16_F"), IP packet dropped.\n",
00425             (u16_t)IP6_HLEN, p->len));
00426     }
00427     if ((IP6H_PLEN(ip6hdr) + IP6_HLEN) > p->tot_len) {
00428       LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_LEVEL_SERIOUS,
00429         ("IPv6 (plen %"U16_F") is longer than pbuf (len %"U16_F"), IP packet dropped.\n",
00430             (u16_t)(IP6H_PLEN(ip6hdr) + IP6_HLEN), p->tot_len));
00431     }
00432     /* free (drop) packet pbufs */
00433     pbuf_free(p);
00434     IP6_STATS_INC(ip6.lenerr);
00435     IP6_STATS_INC(ip6.drop);
00436     return ERR_OK;
00437   }
00438 
00439   /* Trim pbuf. This should have been done at the netif layer,
00440    * but we'll do it anyway just to be sure that its done. */
00441   pbuf_realloc(p, IP6_HLEN + IP6H_PLEN(ip6hdr));
00442 
00443   /* copy IP addresses to aligned ip6_addr_t */
00444   ip_addr_copy_from_ip6(ip_data.current_iphdr_dest, ip6hdr->dest);
00445   ip_addr_copy_from_ip6(ip_data.current_iphdr_src, ip6hdr->src);
00446 
00447   /* Don't accept virtual IPv6 mapped IPv4 addresses */
00448   if (ip6_addr_isipv6mappedipv4(ip_2_ip6(&ip_data.current_iphdr_dest)) ||
00449      ip6_addr_isipv6mappedipv4(ip_2_ip6(&ip_data.current_iphdr_src))     ) {
00450     IP6_STATS_INC(ip6.err);
00451     IP6_STATS_INC(ip6.drop);
00452     return ERR_OK;
00453   }
00454   
00455   /* current header pointer. */
00456   ip_data.current_ip6_header = ip6hdr;
00457 
00458   /* In netif, used in case we need to send ICMPv6 packets back. */
00459   ip_data.current_netif = inp;
00460   ip_data.current_input_netif = inp;
00461 
00462   /* match packet against an interface, i.e. is this packet for us? */
00463   if (ip6_addr_ismulticast(ip6_current_dest_addr())) {
00464     /* Always joined to multicast if-local and link-local all-nodes group. */
00465     if (ip6_addr_isallnodes_iflocal(ip6_current_dest_addr()) ||
00466         ip6_addr_isallnodes_linklocal(ip6_current_dest_addr())) {
00467       netif = inp;
00468     }
00469 #if LWIP_IPV6_MLD
00470     else if (mld6_lookfor_group(inp, ip6_current_dest_addr())) {
00471       netif = inp;
00472     }
00473 #else /* LWIP_IPV6_MLD */
00474     else if (ip6_addr_issolicitednode(ip6_current_dest_addr())) {
00475       /* Filter solicited node packets when MLD is not enabled
00476        * (for Neighbor discovery). */
00477       netif = NULL;
00478       for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) {
00479         if (ip6_addr_isvalid(netif_ip6_addr_state(inp, i)) &&
00480             ip6_addr_cmp_solicitednode(ip6_current_dest_addr(), netif_ip6_addr(inp, i))) {
00481           netif = inp;
00482           LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: solicited node packet accepted on interface %c%c\n",
00483               netif->name[0], netif->name[1]));
00484           break;
00485         }
00486       }
00487     }
00488 #endif /* LWIP_IPV6_MLD */
00489     else {
00490       netif = NULL;
00491     }
00492   } else {
00493     /* start trying with inp. if that's not acceptable, start walking the
00494        list of configured netifs.
00495        'first' is used as a boolean to mark whether we started walking the list */
00496     int first = 1;
00497     netif = inp;
00498     do {
00499       /* interface is up? */
00500       if (netif_is_up(netif)) {
00501         /* unicast to this interface address? address configured? */
00502         for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) {
00503           if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i)) &&
00504               ip6_addr_cmp(ip6_current_dest_addr(), netif_ip6_addr(netif, i))) {
00505             /* exit outer loop */
00506             goto netif_found;
00507           }
00508         }
00509       }
00510       if (ip6_addr_islinklocal(ip6_current_dest_addr())) {
00511         /* Do not match link-local addresses to other netifs. */
00512         netif = NULL;
00513         break;
00514       }
00515       if (first) {
00516         first = 0;
00517         netif = netif_list;
00518       } else {
00519         netif = netif->next;
00520       }
00521       if (netif == inp) {
00522         netif = netif->next;
00523       }
00524     } while (netif != NULL);
00525 netif_found:
00526     LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: packet accepted on interface %c%c\n",
00527         netif ? netif->name[0] : 'X', netif? netif->name[1] : 'X'));
00528   }
00529 
00530   /* "::" packet source address? (used in duplicate address detection) */
00531   if (ip6_addr_isany(ip6_current_src_addr()) &&
00532       (!ip6_addr_issolicitednode(ip6_current_dest_addr()))) {
00533     /* packet source is not valid */
00534     /* free (drop) packet pbufs */
00535     LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: packet with src ANY_ADDRESS dropped\n"));
00536     pbuf_free(p);
00537     IP6_STATS_INC(ip6.drop);
00538     goto ip6_input_cleanup;
00539   }
00540 
00541   /* packet not for us? */
00542   if (netif == NULL) {
00543     /* packet not for us, route or discard */
00544     LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_TRACE, ("ip6_input: packet not for us.\n"));
00545 #if LWIP_IPV6_FORWARD
00546     /* non-multicast packet? */
00547     if (!ip6_addr_ismulticast(ip6_current_dest_addr())) {
00548       /* try to forward IP packet on (other) interfaces */
00549       ip6_forward(p, ip6hdr, inp);
00550     }
00551 #endif /* LWIP_IPV6_FORWARD */
00552     pbuf_free(p);
00553     goto ip6_input_cleanup;
00554   }
00555 
00556   /* current netif pointer. */
00557   ip_data.current_netif = netif;
00558 
00559   /* Save next header type. */
00560   nexth = IP6H_NEXTH(ip6hdr);
00561 
00562   /* Init header length. */
00563   hlen = ip_data.current_ip_header_tot_len = IP6_HLEN;
00564 
00565   /* Move to payload. */
00566   pbuf_header(p, -IP6_HLEN);
00567 
00568   /* Process known option extension headers, if present. */
00569   while (nexth != IP6_NEXTH_NONE)
00570   {
00571     switch (nexth) {
00572     case IP6_NEXTH_HOPBYHOP:
00573       LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: packet with Hop-by-Hop options header\n"));
00574       /* Get next header type. */
00575       nexth = *((u8_t *)p->payload);
00576 
00577       /* Get the header length. */
00578       hlen = 8 * (1 + *((u8_t *)p->payload + 1));
00579       ip_data.current_ip_header_tot_len += hlen;
00580 
00581       /* Skip over this header. */
00582       if (hlen > p->len) {
00583         LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_LEVEL_SERIOUS,
00584           ("IPv6 options header (hlen %"U16_F") does not fit in first pbuf (len %"U16_F"), IPv6 packet dropped.\n",
00585               hlen, p->len));
00586         /* free (drop) packet pbufs */
00587         pbuf_free(p);
00588         IP6_STATS_INC(ip6.lenerr);
00589         IP6_STATS_INC(ip6.drop);
00590         goto ip6_input_cleanup;
00591       }
00592 
00593       pbuf_header(p, -(s16_t)hlen);
00594       break;
00595     case IP6_NEXTH_DESTOPTS:
00596       LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: packet with Destination options header\n"));
00597       /* Get next header type. */
00598       nexth = *((u8_t *)p->payload);
00599 
00600       /* Get the header length. */
00601       hlen = 8 * (1 + *((u8_t *)p->payload + 1));
00602       ip_data.current_ip_header_tot_len += hlen;
00603 
00604       /* Skip over this header. */
00605       if (hlen > p->len) {
00606         LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_LEVEL_SERIOUS,
00607           ("IPv6 options header (hlen %"U16_F") does not fit in first pbuf (len %"U16_F"), IPv6 packet dropped.\n",
00608               hlen, p->len));
00609         /* free (drop) packet pbufs */
00610         pbuf_free(p);
00611         IP6_STATS_INC(ip6.lenerr);
00612         IP6_STATS_INC(ip6.drop);
00613         goto ip6_input_cleanup;
00614       }
00615 
00616       pbuf_header(p, -(s16_t)hlen);
00617       break;
00618     case IP6_NEXTH_ROUTING:
00619       LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: packet with Routing header\n"));
00620       /* Get next header type. */
00621       nexth = *((u8_t *)p->payload);
00622 
00623       /* Get the header length. */
00624       hlen = 8 * (1 + *((u8_t *)p->payload + 1));
00625       ip_data.current_ip_header_tot_len += hlen;
00626 
00627       /* Skip over this header. */
00628       if (hlen > p->len) {
00629         LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_LEVEL_SERIOUS,
00630           ("IPv6 options header (hlen %"U16_F") does not fit in first pbuf (len %"U16_F"), IPv6 packet dropped.\n",
00631               hlen, p->len));
00632         /* free (drop) packet pbufs */
00633         pbuf_free(p);
00634         IP6_STATS_INC(ip6.lenerr);
00635         IP6_STATS_INC(ip6.drop);
00636         goto ip6_input_cleanup;
00637       }
00638 
00639       pbuf_header(p, -(s16_t)hlen);
00640       break;
00641 
00642     case IP6_NEXTH_FRAGMENT:
00643     {
00644       struct ip6_frag_hdr * frag_hdr;
00645       LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: packet with Fragment header\n"));
00646 
00647       frag_hdr = (struct ip6_frag_hdr *)p->payload;
00648 
00649       /* Get next header type. */
00650       nexth = frag_hdr->_nexth;
00651 
00652       /* Fragment Header length. */
00653       hlen = 8;
00654       ip_data.current_ip_header_tot_len += hlen;
00655 
00656       /* Make sure this header fits in current pbuf. */
00657       if (hlen > p->len) {
00658         LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_LEVEL_SERIOUS,
00659           ("IPv6 options header (hlen %"U16_F") does not fit in first pbuf (len %"U16_F"), IPv6 packet dropped.\n",
00660               hlen, p->len));
00661         /* free (drop) packet pbufs */
00662         pbuf_free(p);
00663         IP6_FRAG_STATS_INC(ip6_frag.lenerr);
00664         IP6_FRAG_STATS_INC(ip6_frag.drop);
00665         goto ip6_input_cleanup;
00666       }
00667 
00668       /* Offset == 0 and more_fragments == 0? */
00669       if ((frag_hdr->_fragment_offset &
00670            PP_HTONS(IP6_FRAG_OFFSET_MASK | IP6_FRAG_MORE_FLAG)) == 0) {
00671         /* This is a 1-fragment packet, usually a packet that we have
00672          * already reassembled. Skip this header anc continue. */
00673         pbuf_header(p, -(s16_t)hlen);
00674       } else {
00675 #if LWIP_IPV6_REASS
00676 
00677         /* reassemble the packet */
00678         p = ip6_reass(p);
00679         /* packet not fully reassembled yet? */
00680         if (p == NULL) {
00681           goto ip6_input_cleanup;
00682         }
00683 
00684         /* Returned p point to IPv6 header.
00685          * Update all our variables and pointers and continue. */
00686         ip6hdr = (struct ip6_hdr *)p->payload;
00687         nexth = IP6H_NEXTH(ip6hdr);
00688         hlen = ip_data.current_ip_header_tot_len = IP6_HLEN;
00689         pbuf_header(p, -IP6_HLEN);
00690 
00691 #else /* LWIP_IPV6_REASS */
00692         /* free (drop) packet pbufs */
00693         LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: packet with Fragment header dropped (with LWIP_IPV6_REASS==0)\n"));
00694         pbuf_free(p);
00695         IP6_STATS_INC(ip6.opterr);
00696         IP6_STATS_INC(ip6.drop);
00697         goto ip6_input_cleanup;
00698 #endif /* LWIP_IPV6_REASS */
00699       }
00700       break;
00701     }
00702     default:
00703       goto options_done;
00704       break;
00705     }
00706   }
00707 options_done:
00708 
00709   /* p points to IPv6 header again. */
00710   pbuf_header_force(p, ip_data.current_ip_header_tot_len);
00711 
00712   /* send to upper layers */
00713   LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: \n"));
00714   ip6_debug_print(p);
00715   LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: p->len %"U16_F" p->tot_len %"U16_F"\n", p->len, p->tot_len));
00716 
00717 #if LWIP_RAW
00718   /* raw input did not eat the packet? */
00719   if (raw_input(p, inp) == 0)
00720 #endif /* LWIP_RAW */
00721   {
00722     switch (nexth) {
00723     case IP6_NEXTH_NONE:
00724       pbuf_free(p);
00725       break;
00726 #if LWIP_UDP
00727     case IP6_NEXTH_UDP:
00728 #if LWIP_UDPLITE
00729     case IP6_NEXTH_UDPLITE:
00730 #endif /* LWIP_UDPLITE */
00731       /* Point to payload. */
00732       pbuf_header(p, -(s16_t)ip_data.current_ip_header_tot_len);
00733       udp_input(p, inp);
00734       break;
00735 #endif /* LWIP_UDP */
00736 #if LWIP_TCP
00737     case IP6_NEXTH_TCP:
00738       /* Point to payload. */
00739       pbuf_header(p, -(s16_t)ip_data.current_ip_header_tot_len);
00740       tcp_input(p, inp);
00741       break;
00742 #endif /* LWIP_TCP */
00743 #if LWIP_ICMP6
00744     case IP6_NEXTH_ICMP6:
00745       /* Point to payload. */
00746       pbuf_header(p, -(s16_t)ip_data.current_ip_header_tot_len);
00747       icmp6_input(p, inp);
00748       break;
00749 #endif /* LWIP_ICMP */
00750     default:
00751 #if LWIP_ICMP6
00752       /* send ICMP parameter problem unless it was a multicast or ICMPv6 */
00753       if ((!ip6_addr_ismulticast(ip6_current_dest_addr())) &&
00754           (IP6H_NEXTH(ip6hdr) != IP6_NEXTH_ICMP6)) {
00755         icmp6_param_problem(p, ICMP6_PP_HEADER, ip_data.current_ip_header_tot_len - hlen);
00756       }
00757 #endif /* LWIP_ICMP */
00758       LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("ip6_input: Unsupported transport protocol %"U16_F"\n", (u16_t)IP6H_NEXTH(ip6hdr)));
00759       pbuf_free(p);
00760       IP6_STATS_INC(ip6.proterr);
00761       IP6_STATS_INC(ip6.drop);
00762       break;
00763     }
00764   }
00765 
00766 ip6_input_cleanup:
00767   ip_data.current_netif = NULL;
00768   ip_data.current_input_netif = NULL;
00769   ip_data.current_ip6_header = NULL;
00770   ip_data.current_ip_header_tot_len = 0;
00771   ip6_addr_set_zero(ip6_current_src_addr());
00772   ip6_addr_set_zero(ip6_current_dest_addr());
00773 
00774   return ERR_OK;
00775 }
00776 
00777 
00778 /**
00779  * Sends an IPv6 packet on a network interface. This function constructs
00780  * the IPv6 header. If the source IPv6 address is NULL, the IPv6 "ANY" address is
00781  * used as source (usually during network startup). If the source IPv6 address it
00782  * IP6_ADDR_ANY, the most appropriate IPv6 address of the outgoing network
00783  * interface is filled in as source address. If the destination IPv6 address is
00784  * IP_HDRINCL, p is assumed to already include an IPv6 header and p->payload points
00785  * to it instead of the data.
00786  *
00787  * @param p the packet to send (p->payload points to the data, e.g. next
00788             protocol header; if dest == IP_HDRINCL, p already includes an
00789             IPv6 header and p->payload points to that IPv6 header)
00790  * @param src the source IPv6 address to send from (if src == IP6_ADDR_ANY, an
00791  *         IP address of the netif is selected and used as source address.
00792  *         if src == NULL, IP6_ADDR_ANY is used as source)
00793  * @param dest the destination IPv6 address to send the packet to
00794  * @param hl the Hop Limit value to be set in the IPv6 header
00795  * @param tc the Traffic Class value to be set in the IPv6 header
00796  * @param nexth the Next Header to be set in the IPv6 header
00797  * @param netif the netif on which to send this packet
00798  * @return ERR_OK if the packet was sent OK
00799  *         ERR_BUF if p doesn't have enough space for IPv6/LINK headers
00800  *         returns errors returned by netif->output
00801  */
00802 err_t
00803 ip6_output_if(struct pbuf *p, const ip6_addr_t *src, const ip6_addr_t *dest,
00804              u8_t hl, u8_t tc,
00805              u8_t nexth, struct netif *netif)
00806 {
00807   const ip6_addr_t *src_used = src;
00808   if (dest != IP_HDRINCL) {
00809     if (src != NULL && ip6_addr_isany(src)) {
00810       src = ip_2_ip6(ip6_select_source_address(netif, dest));
00811       if ((src == NULL) || ip6_addr_isany(src)) {
00812         /* No appropriate source address was found for this packet. */
00813         LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("ip6_output: No suitable source address for packet.\n"));
00814         IP6_STATS_INC(ip6.rterr);
00815         return ERR_RTE;
00816       }
00817     }
00818   }
00819   return ip6_output_if_src(p, src_used, dest, hl, tc, nexth, netif);
00820 }
00821 
00822 /**
00823  * Same as ip6_output_if() but 'src' address is not replaced by netif address
00824  * when it is 'any'.
00825  */
00826 err_t
00827 ip6_output_if_src(struct pbuf *p, const ip6_addr_t *src, const ip6_addr_t *dest,
00828              u8_t hl, u8_t tc,
00829              u8_t nexth, struct netif *netif)
00830 {
00831   struct ip6_hdr *ip6hdr;
00832   ip6_addr_t dest_addr;
00833 
00834   LWIP_IP_CHECK_PBUF_REF_COUNT_FOR_TX(p);
00835 
00836   /* Should the IPv6 header be generated or is it already included in p? */
00837   if (dest != IP_HDRINCL) {
00838     /* generate IPv6 header */
00839     if (pbuf_header(p, IP6_HLEN)) {
00840       LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("ip6_output: not enough room for IPv6 header in pbuf\n"));
00841       IP6_STATS_INC(ip6.err);
00842       return ERR_BUF;
00843     }
00844 
00845     ip6hdr = (struct ip6_hdr *)p->payload;
00846     LWIP_ASSERT("check that first pbuf can hold struct ip6_hdr",
00847                (p->len >= sizeof(struct ip6_hdr)));
00848 
00849     IP6H_HOPLIM_SET(ip6hdr, hl);
00850     IP6H_NEXTH_SET(ip6hdr, nexth);
00851 
00852     /* dest cannot be NULL here */
00853     ip6_addr_copy(ip6hdr->dest, *dest);
00854 
00855     IP6H_VTCFL_SET(ip6hdr, 6, tc, 0);
00856     IP6H_PLEN_SET(ip6hdr, p->tot_len - IP6_HLEN);
00857 
00858     if (src == NULL) {
00859       src = IP6_ADDR_ANY6;
00860     }
00861     /* src cannot be NULL here */
00862     ip6_addr_copy(ip6hdr->src, *src);
00863 
00864   } else {
00865     /* IP header already included in p */
00866     ip6hdr = (struct ip6_hdr *)p->payload;
00867     ip6_addr_copy(dest_addr, ip6hdr->dest);
00868     dest = &dest_addr;
00869   }
00870 
00871   IP6_STATS_INC(ip6.xmit);
00872 
00873   LWIP_DEBUGF(IP6_DEBUG, ("ip6_output_if: %c%c%"U16_F"\n", netif->name[0], netif->name[1], (u16_t)netif->num));
00874   ip6_debug_print(p);
00875 
00876 #if ENABLE_LOOPBACK
00877   {
00878     int i;
00879 #if !LWIP_HAVE_LOOPIF
00880     if (ip6_addr_isloopback(dest)) {
00881       return netif_loop_output(netif, p);
00882     }
00883 #endif /* !LWIP_HAVE_LOOPIF */
00884     for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) {
00885       if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i)) &&
00886           ip6_addr_cmp(dest, netif_ip6_addr(netif, i))) {
00887         /* Packet to self, enqueue it for loopback */
00888         LWIP_DEBUGF(IP6_DEBUG, ("netif_loop_output()\n"));
00889         return netif_loop_output(netif, p);
00890       }
00891     }
00892   }
00893 #endif /* ENABLE_LOOPBACK */
00894 #if LWIP_IPV6_FRAG
00895   /* don't fragment if interface has mtu set to 0 [loopif] */
00896   if (netif->mtu && (p->tot_len > nd6_get_destination_mtu(dest, netif))) {
00897     return ip6_frag(p, netif, dest);
00898   }
00899 #endif /* LWIP_IPV6_FRAG */
00900 
00901   LWIP_DEBUGF(IP6_DEBUG, ("netif->output_ip6()\n"));
00902   return netif->output_ip6(netif, p, dest);
00903 }
00904 
00905 /**
00906  * Simple interface to ip6_output_if. It finds the outgoing network
00907  * interface and calls upon ip6_output_if to do the actual work.
00908  *
00909  * @param p the packet to send (p->payload points to the data, e.g. next
00910             protocol header; if dest == IP_HDRINCL, p already includes an
00911             IPv6 header and p->payload points to that IPv6 header)
00912  * @param src the source IPv6 address to send from (if src == IP6_ADDR_ANY, an
00913  *         IP address of the netif is selected and used as source address.
00914  *         if src == NULL, IP6_ADDR_ANY is used as source)
00915  * @param dest the destination IPv6 address to send the packet to
00916  * @param hl the Hop Limit value to be set in the IPv6 header
00917  * @param tc the Traffic Class value to be set in the IPv6 header
00918  * @param nexth the Next Header to be set in the IPv6 header
00919  *
00920  * @return ERR_RTE if no route is found
00921  *         see ip_output_if() for more return values
00922  */
00923 err_t
00924 ip6_output(struct pbuf *p, const ip6_addr_t *src, const ip6_addr_t *dest,
00925           u8_t hl, u8_t tc, u8_t nexth)
00926 {
00927   struct netif *netif;
00928   struct ip6_hdr *ip6hdr;
00929   ip6_addr_t src_addr, dest_addr;
00930 
00931   LWIP_IP_CHECK_PBUF_REF_COUNT_FOR_TX(p);
00932 
00933   if (dest != IP_HDRINCL) {
00934     netif = ip6_route(src, dest);
00935   } else {
00936     /* IP header included in p, read addresses. */
00937     ip6hdr = (struct ip6_hdr *)p->payload;
00938     ip6_addr_copy(src_addr, ip6hdr->src);
00939     ip6_addr_copy(dest_addr, ip6hdr->dest);
00940     netif = ip6_route(&src_addr, &dest_addr);
00941   }
00942 
00943   if (netif == NULL) {
00944     LWIP_DEBUGF(IP6_DEBUG, ("ip6_output: no route for %"X16_F":%"X16_F":%"X16_F":%"X16_F":%"X16_F":%"X16_F":%"X16_F":%"X16_F"\n",
00945         IP6_ADDR_BLOCK1(dest),
00946         IP6_ADDR_BLOCK2(dest),
00947         IP6_ADDR_BLOCK3(dest),
00948         IP6_ADDR_BLOCK4(dest),
00949         IP6_ADDR_BLOCK5(dest),
00950         IP6_ADDR_BLOCK6(dest),
00951         IP6_ADDR_BLOCK7(dest),
00952         IP6_ADDR_BLOCK8(dest)));
00953     IP6_STATS_INC(ip6.rterr);
00954     return ERR_RTE;
00955   }
00956 
00957   return ip6_output_if(p, src, dest, hl, tc, nexth, netif);
00958 }
00959 
00960 
00961 #if LWIP_NETIF_HWADDRHINT
00962 /** Like ip6_output, but takes and addr_hint pointer that is passed on to netif->addr_hint
00963  *  before calling ip6_output_if.
00964  *
00965  * @param p the packet to send (p->payload points to the data, e.g. next
00966             protocol header; if dest == IP_HDRINCL, p already includes an
00967             IPv6 header and p->payload points to that IPv6 header)
00968  * @param src the source IPv6 address to send from (if src == IP6_ADDR_ANY, an
00969  *         IP address of the netif is selected and used as source address.
00970  *         if src == NULL, IP6_ADDR_ANY is used as source)
00971  * @param dest the destination IPv6 address to send the packet to
00972  * @param hl the Hop Limit value to be set in the IPv6 header
00973  * @param tc the Traffic Class value to be set in the IPv6 header
00974  * @param nexth the Next Header to be set in the IPv6 header
00975  * @param addr_hint address hint pointer set to netif->addr_hint before
00976  *        calling ip_output_if()
00977  *
00978  * @return ERR_RTE if no route is found
00979  *         see ip_output_if() for more return values
00980  */
00981 err_t
00982 ip6_output_hinted(struct pbuf *p, const ip6_addr_t *src, const ip6_addr_t *dest,
00983           u8_t hl, u8_t tc, u8_t nexth, u8_t *addr_hint)
00984 {
00985   struct netif *netif;
00986   struct ip6_hdr *ip6hdr;
00987   ip6_addr_t src_addr, dest_addr;
00988   err_t err;
00989 
00990   LWIP_IP_CHECK_PBUF_REF_COUNT_FOR_TX(p);
00991 
00992   if (dest != IP_HDRINCL) {
00993     netif = ip6_route(src, dest);
00994   } else {
00995     /* IP header included in p, read addresses. */
00996     ip6hdr = (struct ip6_hdr *)p->payload;
00997     ip6_addr_copy(src_addr, ip6hdr->src);
00998     ip6_addr_copy(dest_addr, ip6hdr->dest);
00999     netif = ip6_route(&src_addr, &dest_addr);
01000   }
01001 
01002   if (netif == NULL) {
01003     LWIP_DEBUGF(IP6_DEBUG, ("ip6_output: no route for %"X16_F":%"X16_F":%"X16_F":%"X16_F":%"X16_F":%"X16_F":%"X16_F":%"X16_F"\n",
01004         IP6_ADDR_BLOCK1(dest),
01005         IP6_ADDR_BLOCK2(dest),
01006         IP6_ADDR_BLOCK3(dest),
01007         IP6_ADDR_BLOCK4(dest),
01008         IP6_ADDR_BLOCK5(dest),
01009         IP6_ADDR_BLOCK6(dest),
01010         IP6_ADDR_BLOCK7(dest),
01011         IP6_ADDR_BLOCK8(dest)));
01012     IP6_STATS_INC(ip6.rterr);
01013     return ERR_RTE;
01014   }
01015 
01016   NETIF_SET_HWADDRHINT(netif, addr_hint);
01017   err = ip6_output_if(p, src, dest, hl, tc, nexth, netif);
01018   NETIF_SET_HWADDRHINT(netif, NULL);
01019 
01020   return err;
01021 }
01022 #endif /* LWIP_NETIF_HWADDRHINT*/
01023 
01024 #if LWIP_IPV6_MLD
01025 /**
01026  * Add a hop-by-hop options header with a router alert option and padding.
01027  *
01028  * Used by MLD when sending a Multicast listener report/done message.
01029  *
01030  * @param p the packet to which we will prepend the options header
01031  * @param nexth the next header protocol number (e.g. IP6_NEXTH_ICMP6)
01032  * @param value the value of the router alert option data (e.g. IP6_ROUTER_ALERT_VALUE_MLD)
01033  * @return ERR_OK if hop-by-hop header was added, ERR_* otherwise
01034  */
01035 err_t
01036 ip6_options_add_hbh_ra(struct pbuf * p, u8_t nexth, u8_t value)
01037 {
01038   struct ip6_hbh_hdr * hbh_hdr;
01039 
01040   /* Move pointer to make room for hop-by-hop options header. */
01041   if (pbuf_header(p, sizeof(struct ip6_hbh_hdr))) {
01042     LWIP_DEBUGF(IP6_DEBUG, ("ip6_options: no space for options header\n"));
01043     IP6_STATS_INC(ip6.err);
01044     return ERR_BUF;
01045   }
01046 
01047   hbh_hdr = (struct ip6_hbh_hdr *)p->payload;
01048 
01049   /* Set fields. */
01050   hbh_hdr->_nexth = nexth;
01051   hbh_hdr->_hlen = 0;
01052   hbh_hdr->_ra_opt_type = IP6_ROUTER_ALERT_OPTION;
01053   hbh_hdr->_ra_opt_dlen = 2;
01054   hbh_hdr->_ra_opt_data = value;
01055   hbh_hdr->_padn_opt_type = IP6_PADN_ALERT_OPTION;
01056   hbh_hdr->_padn_opt_dlen = 0;
01057 
01058   return ERR_OK;
01059 }
01060 #endif /* LWIP_IPV6_MLD */
01061 
01062 #if IP6_DEBUG
01063 /* Print an IPv6 header by using LWIP_DEBUGF
01064  * @param p an IPv6 packet, p->payload pointing to the IPv6 header
01065  */
01066 void
01067 ip6_debug_print(struct pbuf *p)
01068 {
01069   struct ip6_hdr *ip6hdr = (struct ip6_hdr *)p->payload;
01070 
01071   LWIP_DEBUGF(IP6_DEBUG, ("IPv6 header:\n"));
01072   LWIP_DEBUGF(IP6_DEBUG, ("+-------------------------------+\n"));
01073   LWIP_DEBUGF(IP6_DEBUG, ("| %2"U16_F" |  %3"U16_F"  |      %7"U32_F"     | (ver, class, flow)\n",
01074                     IP6H_V(ip6hdr),
01075                     IP6H_TC(ip6hdr),
01076                     IP6H_FL(ip6hdr)));
01077   LWIP_DEBUGF(IP6_DEBUG, ("+-------------------------------+\n"));
01078   LWIP_DEBUGF(IP6_DEBUG, ("|     %5"U16_F"     |  %3"U16_F"  |  %3"U16_F"  | (plen, nexth, hopl)\n",
01079                     IP6H_PLEN(ip6hdr),
01080                     IP6H_NEXTH(ip6hdr),
01081                     IP6H_HOPLIM(ip6hdr)));
01082   LWIP_DEBUGF(IP6_DEBUG, ("+-------------------------------+\n"));
01083   LWIP_DEBUGF(IP6_DEBUG, ("|  %4"X32_F" |  %4"X32_F" |  %4"X32_F" |  %4"X32_F" | (src)\n",
01084                     IP6_ADDR_BLOCK1(&(ip6hdr->src)),
01085                     IP6_ADDR_BLOCK2(&(ip6hdr->src)),
01086                     IP6_ADDR_BLOCK3(&(ip6hdr->src)),
01087                     IP6_ADDR_BLOCK4(&(ip6hdr->src))));
01088   LWIP_DEBUGF(IP6_DEBUG, ("|  %4"X32_F" |  %4"X32_F" |  %4"X32_F" |  %4"X32_F" |\n",
01089                     IP6_ADDR_BLOCK5(&(ip6hdr->src)),
01090                     IP6_ADDR_BLOCK6(&(ip6hdr->src)),
01091                     IP6_ADDR_BLOCK7(&(ip6hdr->src)),
01092                     IP6_ADDR_BLOCK8(&(ip6hdr->src))));
01093   LWIP_DEBUGF(IP6_DEBUG, ("+-------------------------------+\n"));
01094   LWIP_DEBUGF(IP6_DEBUG, ("|  %4"X32_F" |  %4"X32_F" |  %4"X32_F" |  %4"X32_F" | (dest)\n",
01095                     IP6_ADDR_BLOCK1(&(ip6hdr->dest)),
01096                     IP6_ADDR_BLOCK2(&(ip6hdr->dest)),
01097                     IP6_ADDR_BLOCK3(&(ip6hdr->dest)),
01098                     IP6_ADDR_BLOCK4(&(ip6hdr->dest))));
01099   LWIP_DEBUGF(IP6_DEBUG, ("|  %4"X32_F" |  %4"X32_F" |  %4"X32_F" |  %4"X32_F" |\n",
01100                     IP6_ADDR_BLOCK5(&(ip6hdr->dest)),
01101                     IP6_ADDR_BLOCK6(&(ip6hdr->dest)),
01102                     IP6_ADDR_BLOCK7(&(ip6hdr->dest)),
01103                     IP6_ADDR_BLOCK8(&(ip6hdr->dest))));
01104   LWIP_DEBUGF(IP6_DEBUG, ("+-------------------------------+\n"));
01105 }
01106 #endif /* IP6_DEBUG */
01107 
01108 #endif /* LWIP_IPV6 */