Daiki Kato / mbed-os-lychee

Dependents:   mbed-os-example-blinky-gr-lychee GR-Boads_Camera_sample GR-Boards_Audio_Recoder GR-Boads_Camera_DisplayApp ... more

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