• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * @file
3  *
4  * IPv6 layer.
5  */
6 
7 /*
8  * Copyright (c) 2010 Inico Technologies Ltd.
9  * All rights reserved.
10  *
11  * Redistribution and use in source and binary forms, with or without modification,
12  * are permitted provided that the following conditions are met:
13  *
14  * 1. Redistributions of source code must retain the above copyright notice,
15  *    this list of conditions and the following disclaimer.
16  * 2. Redistributions in binary form must reproduce the above copyright notice,
17  *    this list of conditions and the following disclaimer in the documentation
18  *    and/or other materials provided with the distribution.
19  * 3. The name of the author may not be used to endorse or promote products
20  *    derived from this software without specific prior written permission.
21  *
22  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
23  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
24  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
25  * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
26  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
27  * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
30  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
31  * OF SUCH DAMAGE.
32  *
33  * This file is part of the lwIP TCP/IP stack.
34  *
35  * Author: Ivan Delamer <delamer@inicotech.com>
36  *
37  *
38  * Please coordinate changes and requests with Ivan Delamer
39  * <delamer@inicotech.com>
40  */
41 
42 #include "lwip/opt.h"
43 
44 #if LWIP_IPV6  /* don't build if not configured for use in lwipopts.h */
45 
46 #include "lwip/def.h"
47 #include "lwip/mem.h"
48 #include "lwip/netif.h"
49 #include "lwip/ip.h"
50 #include "lwip/ip6.h"
51 #include "lwip/ip6_addr.h"
52 #include "lwip/ip6_frag.h"
53 #include "lwip/icmp6.h"
54 #include "lwip/priv/raw_priv.h"
55 #include "lwip/udp.h"
56 #include "lwip/priv/tcp_priv.h"
57 #include "lwip/dhcp6.h"
58 #include "lwip/nd6.h"
59 #include "lwip/mld6.h"
60 #include "lwip/debug.h"
61 #include "lwip/stats.h"
62 
63 #ifdef LWIP_HOOK_FILENAME
64 #include LWIP_HOOK_FILENAME
65 #endif
66 
67 /**
68  * Finds the appropriate network interface for a given IPv6 address. It tries to select
69  * a netif following a sequence of heuristics:
70  * 1) if there is only 1 netif, return it
71  * 2) if the destination is a zoned address, match its zone to a netif
72  * 3) if the either the source or destination address is a scoped address,
73  *    match the source address's zone (if set) or address (if not) to a netif
74  * 4) tries to match the destination subnet to a configured address
75  * 5) tries to find a router-announced route
76  * 6) tries to match the (unscoped) source address to the netif
77  * 7) returns the default netif, if configured
78  *
79  * Note that each of the two given addresses may or may not be properly zoned.
80  *
81  * @param src the source IPv6 address, if known
82  * @param dest the destination IPv6 address for which to find the route
83  * @return the netif on which to send to reach dest
84  */
85 struct netif *
86 #ifdef LOSCFG_NET_CONTAINER
ip6_route(const ip6_addr_t * src,const ip6_addr_t * dest,struct net_group * group)87 ip6_route(const ip6_addr_t *src, const ip6_addr_t *dest, struct net_group *group)
88 #else
89 ip6_route(const ip6_addr_t *src, const ip6_addr_t *dest)
90 #endif
91 {
92 #if LWIP_SINGLE_NETIF
93   LWIP_UNUSED_ARG(src);
94   LWIP_UNUSED_ARG(dest);
95 #else /* LWIP_SINGLE_NETIF */
96   struct netif *netif;
97   s8_t i;
98 
99   LWIP_ASSERT_CORE_LOCKED();
100 
101   /* If single netif configuration, fast return. */
102 #ifdef LOSCFG_NET_CONTAINER
103   if ((group->netif_list != NULL) && (group->netif_list->next == NULL)) {
104     if (!netif_is_up(group->netif_list) || !netif_is_link_up(group->netif_list) ||
105         (ip6_addr_has_zone(dest) && !ip6_addr_test_zone(dest, group->netif_list))) {
106 #else
107   if ((netif_list != NULL) && (netif_list->next == NULL)) {
108     if (!netif_is_up(netif_list) || !netif_is_link_up(netif_list) ||
109         (ip6_addr_has_zone(dest) && !ip6_addr_test_zone(dest, netif_list))) {
110 #endif
111       return NULL;
112     }
113 #ifdef LOSCFG_NET_CONTAINER
114     return group->netif_list;
115 #else
116     return netif_list;
117 #endif
118   }
119 
120 #if LWIP_IPV6_SCOPES
121   /* Special processing for zoned destination addresses. This includes link-
122    * local unicast addresses and interface/link-local multicast addresses. Use
123    * the zone to find a matching netif. If the address is not zoned, then there
124    * is technically no "wrong" netif to choose, and we leave routing to other
125    * rules; in most cases this should be the scoped-source rule below. */
126   if (ip6_addr_has_zone(dest)) {
127     IP6_ADDR_ZONECHECK(dest);
128     /* Find a netif based on the zone. For custom mappings, one zone may map
129      * to multiple netifs, so find one that can actually send a packet. */
130 #ifdef LOSCFG_NET_CONTAINER
131     NETIF_FOREACH(netif, group) {
132 #else
133     NETIF_FOREACH(netif) {
134 #endif
135       if (ip6_addr_test_zone(dest, netif) &&
136           netif_is_up(netif) && netif_is_link_up(netif)) {
137         return netif;
138       }
139     }
140     /* No matching netif found. Do no try to route to a different netif,
141      * as that would be a zone violation, resulting in any packets sent to
142      * that netif being dropped on output. */
143     return NULL;
144   }
145 #endif /* LWIP_IPV6_SCOPES */
146 
147   /* Special processing for scoped source and destination addresses. If we get
148    * here, the destination address does not have a zone, so either way we need
149    * to look at the source address, which may or may not have a zone. If it
150    * does, the zone is restrictive: there is (typically) only one matching
151    * netif for it, and we should avoid routing to any other netif as that would
152    * result in guaranteed zone violations. For scoped source addresses that do
153    * not have a zone, use (only) a netif that has that source address locally
154    * assigned. This case also applies to the loopback source address, which has
155    * an implied link-local scope. If only the destination address is scoped
156    * (but, again, not zoned), we still want to use only the source address to
157    * determine its zone because that's most likely what the user/application
158    * wants, regardless of whether the source address is scoped. Finally, some
159    * of this story also applies if scoping is disabled altogether. */
160 #if LWIP_IPV6_SCOPES
161   if (ip6_addr_has_scope(dest, IP6_UNKNOWN) ||
162       ip6_addr_has_scope(src, IP6_UNICAST) ||
163 #else /* LWIP_IPV6_SCOPES */
164   if (ip6_addr_islinklocal(dest) || ip6_addr_ismulticast_iflocal(dest) ||
165       ip6_addr_ismulticast_linklocal(dest) || ip6_addr_islinklocal(src) ||
166 #endif /* LWIP_IPV6_SCOPES */
167       ip6_addr_isloopback(src)) {
168 #if LWIP_IPV6_SCOPES
169     if (ip6_addr_has_zone(src)) {
170       /* Find a netif matching the source zone (relatively cheap). */
171 #ifdef LOSCFG_NET_CONTAINER
172       NETIF_FOREACH(netif, group) {
173 #else
174       NETIF_FOREACH(netif) {
175 #endif
176         if (netif_is_up(netif) && netif_is_link_up(netif) &&
177             ip6_addr_test_zone(src, netif)) {
178           return netif;
179         }
180       }
181     } else
182 #endif /* LWIP_IPV6_SCOPES */
183     {
184       /* Find a netif matching the source address (relatively expensive). */
185 #ifdef LOSCFG_NET_CONTAINER
186       NETIF_FOREACH(netif, group) {
187 #else
188       NETIF_FOREACH(netif) {
189 #endif
190         if (!netif_is_up(netif) || !netif_is_link_up(netif)) {
191           continue;
192         }
193         for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) {
194           if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i)) &&
195               ip6_addr_zoneless_eq(src, netif_ip6_addr(netif, i))) {
196             return netif;
197           }
198         }
199       }
200     }
201     /* Again, do not use any other netif in this case, as that could result in
202      * zone boundary violations. */
203     return NULL;
204   }
205 
206   /* We come here only if neither source nor destination is scoped. */
207   IP6_ADDR_ZONECHECK(src);
208 
209 #ifdef LWIP_HOOK_IP6_ROUTE
210   netif = LWIP_HOOK_IP6_ROUTE(src, dest);
211   if (netif != NULL) {
212     return netif;
213   }
214 #endif
215 
216   /* See if the destination subnet matches a configured address. In accordance
217    * with RFC 5942, dynamically configured addresses do not have an implied
218    * local subnet, and thus should be considered /128 assignments. However, as
219    * such, the destination address may still match a local address, and so we
220    * still need to check for exact matches here. By (lwIP) policy, statically
221    * configured addresses do always have an implied local /64 subnet. */
222 #ifdef LOSCFG_NET_CONTAINER
223   NETIF_FOREACH(netif, group) {
224 #else
225   NETIF_FOREACH(netif) {
226 #endif
227     if (!netif_is_up(netif) || !netif_is_link_up(netif)) {
228       continue;
229     }
230     for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) {
231       if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i)) &&
232           ip6_addr_net_eq(dest, netif_ip6_addr(netif, i)) &&
233           (netif_ip6_addr_isstatic(netif, i) ||
234           ip6_addr_nethost_eq(dest, netif_ip6_addr(netif, i)))) {
235         return netif;
236       }
237     }
238   }
239 
240   /* Get the netif for a suitable router-announced route. */
241   netif = nd6_find_route(dest);
242   if (netif != NULL) {
243     return netif;
244   }
245 
246   /* Try with the netif that matches the source address. Given the earlier rule
247    * for scoped source addresses, this applies to unscoped addresses only. */
248   if (!ip6_addr_isany(src)) {
249 #ifdef LOSCFG_NET_CONTAINER
250     NETIF_FOREACH(netif, group) {
251 #else
252     NETIF_FOREACH(netif) {
253 #endif
254       if (!netif_is_up(netif) || !netif_is_link_up(netif)) {
255         continue;
256       }
257       for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) {
258         if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i)) &&
259             ip6_addr_eq(src, netif_ip6_addr(netif, i))) {
260           return netif;
261         }
262       }
263     }
264   }
265 
266 #if LWIP_NETIF_LOOPBACK && !LWIP_HAVE_LOOPIF
267   /* loopif is disabled, loopback traffic is passed through any netif */
268   if (ip6_addr_isloopback(dest)) {
269     /* don't check for link on loopback traffic */
270 #ifdef LOSCFG_NET_CONTAINER
271     if (group->netif_default != NULL && netif_is_up(group->netif_default)) {
272       return group->netif_default;
273 #else
274     if (netif_default != NULL && netif_is_up(netif_default)) {
275       return netif_default;
276 #endif
277     }
278     /* default netif is not up, just use any netif for loopback traffic */
279 #ifdef LOSCFG_NET_CONTAINER
280     NETIF_FOREACH(netif, group) {
281 #else
282     NETIF_FOREACH(netif) {
283 #endif
284       if (netif_is_up(netif)) {
285         return netif;
286       }
287     }
288     return NULL;
289   }
290 #endif /* LWIP_NETIF_LOOPBACK && !LWIP_HAVE_LOOPIF */
291 #endif /* !LWIP_SINGLE_NETIF */
292 
293   /* no matching netif found, use default netif, if up */
294 #ifdef LOSCFG_NET_CONTAINER
295   if ((group->netif_default == NULL) || !netif_is_up(group->netif_default) ||
296     !netif_is_link_up(group->netif_default)) {
297 #else
298   if ((netif_default == NULL) || !netif_is_up(netif_default) || !netif_is_link_up(netif_default)) {
299 #endif
300     return NULL;
301   }
302 #ifdef LOSCFG_NET_CONTAINER
303   return group->netif_default;
304 #else
305   return netif_default;
306 #endif
307 }
308 
309 /**
310  * @ingroup ip6
311  * Select the best IPv6 source address for a given destination IPv6 address.
312  *
313  * This implementation follows RFC 6724 Sec. 5 to the following extent:
314  * - Rules 1, 2, 3: fully implemented
315  * - Rules 4, 5, 5.5: not applicable
316  * - Rule 6: not implemented
317  * - Rule 7: not applicable
318  * - Rule 8: limited to "prefer /64 subnet match over non-match"
319  *
320  * For Rule 2, we deliberately deviate from RFC 6724 Sec. 3.1 by considering
321  * ULAs to be of smaller scope than global addresses, to avoid that a preferred
322  * ULA is picked over a deprecated global address when given a global address
323  * as destination, as that would likely result in broken two-way communication.
324  *
325  * As long as temporary addresses are not supported (as used in Rule 7), a
326  * proper implementation of Rule 8 would obviate the need to implement Rule 6.
327  *
328  * @param netif the netif on which to send a packet
329  * @param dest the destination we are trying to reach (possibly not properly
330  *             zoned)
331  * @return the most suitable source address to use, or NULL if no suitable
332  *         source address is found
333  */
334 const ip_addr_t *
335 ip6_select_source_address(struct netif *netif, const ip6_addr_t *dest)
336 {
337   const ip_addr_t *best_addr;
338   const ip6_addr_t *cand_addr;
339   s8_t dest_scope, cand_scope;
340   s8_t best_scope = IP6_MULTICAST_SCOPE_RESERVED;
341   u8_t i, cand_pref, cand_bits;
342   u8_t best_pref = 0;
343   u8_t best_bits = 0;
344 
345   /* Start by determining the scope of the given destination address. These
346    * tests are hopefully (roughly) in order of likeliness to match. */
347   if (ip6_addr_isglobal(dest)) {
348     dest_scope = IP6_MULTICAST_SCOPE_GLOBAL;
349   } else if (ip6_addr_islinklocal(dest) || ip6_addr_isloopback(dest)) {
350     dest_scope = IP6_MULTICAST_SCOPE_LINK_LOCAL;
351   } else if (ip6_addr_isuniquelocal(dest)) {
352     dest_scope = IP6_MULTICAST_SCOPE_ORGANIZATION_LOCAL;
353   } else if (ip6_addr_ismulticast(dest)) {
354     dest_scope = ip6_addr_multicast_scope(dest);
355   } else if (ip6_addr_issitelocal(dest)) {
356     dest_scope = IP6_MULTICAST_SCOPE_SITE_LOCAL;
357   } else {
358     /* no match, consider scope global */
359     dest_scope = IP6_MULTICAST_SCOPE_GLOBAL;
360   }
361 
362   best_addr = NULL;
363 
364   for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) {
365     /* Consider only valid (= preferred and deprecated) addresses. */
366     if (!ip6_addr_isvalid(netif_ip6_addr_state(netif, i))) {
367       continue;
368     }
369     /* Determine the scope of this candidate address. Same ordering idea. */
370     cand_addr = netif_ip6_addr(netif, i);
371     if (ip6_addr_isglobal(cand_addr)) {
372       cand_scope = IP6_MULTICAST_SCOPE_GLOBAL;
373     } else if (ip6_addr_islinklocal(cand_addr)) {
374       cand_scope = IP6_MULTICAST_SCOPE_LINK_LOCAL;
375     } else if (ip6_addr_isuniquelocal(cand_addr)) {
376       cand_scope = IP6_MULTICAST_SCOPE_ORGANIZATION_LOCAL;
377     } else if (ip6_addr_issitelocal(cand_addr)) {
378       cand_scope = IP6_MULTICAST_SCOPE_SITE_LOCAL;
379     } else {
380       /* no match, treat as low-priority global scope */
381       cand_scope = IP6_MULTICAST_SCOPE_RESERVEDF;
382     }
383     cand_pref = ip6_addr_ispreferred(netif_ip6_addr_state(netif, i));
384     /* @todo compute the actual common bits, for longest matching prefix. */
385     /* We cannot count on the destination address having a proper zone
386      * assignment, so do not compare zones in this case. */
387     cand_bits = ip6_addr_net_zoneless_eq(cand_addr, dest); /* just 1 or 0 for now */
388     if (cand_bits && ip6_addr_nethost_eq(cand_addr, dest)) {
389       return netif_ip_addr6(netif, i); /* Rule 1 */
390     }
391     if ((best_addr == NULL) || /* no alternative yet */
392         ((cand_scope < best_scope) && (cand_scope >= dest_scope)) ||
393         ((cand_scope > best_scope) && (best_scope < dest_scope)) || /* Rule 2 */
394         ((cand_scope == best_scope) && ((cand_pref > best_pref) || /* Rule 3 */
395         ((cand_pref == best_pref) && (cand_bits > best_bits))))) { /* Rule 8 */
396       /* We found a new "winning" candidate. */
397       best_addr = netif_ip_addr6(netif, i);
398       best_scope = cand_scope;
399       best_pref = cand_pref;
400       best_bits = cand_bits;
401     }
402   }
403 
404   return best_addr; /* may be NULL */
405 }
406 
407 #if LWIP_IPV6_FORWARD
408 /**
409  * Forwards an IPv6 packet. It finds an appropriate route for the
410  * packet, decrements the HL value of the packet, and outputs
411  * the packet on the appropriate interface.
412  *
413  * @param p the packet to forward (p->payload points to IP header)
414  * @param iphdr the IPv6 header of the input packet
415  * @param inp the netif on which this packet was received
416  */
417 static void
418 ip6_forward(struct pbuf *p, struct ip6_hdr *iphdr, struct netif *inp)
419 {
420   struct netif *netif;
421 
422   /* do not forward link-local or loopback addresses */
423   if (ip6_addr_islinklocal(ip6_current_dest_addr()) ||
424       ip6_addr_isloopback(ip6_current_dest_addr())) {
425     LWIP_DEBUGF(IP6_DEBUG, ("ip6_forward: not forwarding link-local address.\n"));
426     IP6_STATS_INC(ip6.rterr);
427     IP6_STATS_INC(ip6.drop);
428     return;
429   }
430 
431   /* Find network interface where to forward this IP packet to. */
432   netif = ip6_route(IP6_ADDR_ANY6, ip6_current_dest_addr());
433   if (netif == NULL) {
434     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",
435         IP6_ADDR_BLOCK1(ip6_current_dest_addr()),
436         IP6_ADDR_BLOCK2(ip6_current_dest_addr()),
437         IP6_ADDR_BLOCK3(ip6_current_dest_addr()),
438         IP6_ADDR_BLOCK4(ip6_current_dest_addr()),
439         IP6_ADDR_BLOCK5(ip6_current_dest_addr()),
440         IP6_ADDR_BLOCK6(ip6_current_dest_addr()),
441         IP6_ADDR_BLOCK7(ip6_current_dest_addr()),
442         IP6_ADDR_BLOCK8(ip6_current_dest_addr())));
443 #if LWIP_ICMP6
444     /* Don't send ICMP messages in response to ICMP messages */
445     if (IP6H_NEXTH(iphdr) != IP6_NEXTH_ICMP6) {
446       icmp6_dest_unreach(p, ICMP6_DUR_NO_ROUTE);
447     }
448 #endif /* LWIP_ICMP6 */
449     IP6_STATS_INC(ip6.rterr);
450     IP6_STATS_INC(ip6.drop);
451     return;
452   }
453 #if LWIP_IPV6_SCOPES
454   /* Do not forward packets with a zoned (e.g., link-local) source address
455    * outside of their zone. We determined the zone a bit earlier, so we know
456    * that the address is properly zoned here, so we can safely use has_zone.
457    * Also skip packets with a loopback source address (link-local implied). */
458   if ((ip6_addr_has_zone(ip6_current_src_addr()) &&
459       !ip6_addr_test_zone(ip6_current_src_addr(), netif)) ||
460       ip6_addr_isloopback(ip6_current_src_addr())) {
461     LWIP_DEBUGF(IP6_DEBUG, ("ip6_forward: not forwarding packet beyond its source address zone.\n"));
462     IP6_STATS_INC(ip6.rterr);
463     IP6_STATS_INC(ip6.drop);
464     return;
465   }
466 #endif /* LWIP_IPV6_SCOPES */
467   /* Do not forward packets onto the same network interface on which
468    * they arrived. */
469   if (netif == inp) {
470     LWIP_DEBUGF(IP6_DEBUG, ("ip6_forward: not bouncing packets back on incoming interface.\n"));
471     IP6_STATS_INC(ip6.rterr);
472     IP6_STATS_INC(ip6.drop);
473     return;
474   }
475 
476   /* decrement HL */
477   IP6H_HOPLIM_SET(iphdr, IP6H_HOPLIM(iphdr) - 1);
478   /* send ICMP6 if HL == 0 */
479   if (IP6H_HOPLIM(iphdr) == 0) {
480 #if LWIP_ICMP6
481     /* Don't send ICMP messages in response to ICMP messages */
482     if (IP6H_NEXTH(iphdr) != IP6_NEXTH_ICMP6) {
483       icmp6_time_exceeded(p, ICMP6_TE_HL);
484     }
485 #endif /* LWIP_ICMP6 */
486     IP6_STATS_INC(ip6.drop);
487     return;
488   }
489 
490   if (netif->mtu && (p->tot_len > netif->mtu)) {
491 #if LWIP_ICMP6
492     /* Don't send ICMP messages in response to ICMP messages */
493     if (IP6H_NEXTH(iphdr) != IP6_NEXTH_ICMP6) {
494       icmp6_packet_too_big(p, netif->mtu);
495     }
496 #endif /* LWIP_ICMP6 */
497     IP6_STATS_INC(ip6.drop);
498     return;
499   }
500 
501   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",
502       IP6_ADDR_BLOCK1(ip6_current_dest_addr()),
503       IP6_ADDR_BLOCK2(ip6_current_dest_addr()),
504       IP6_ADDR_BLOCK3(ip6_current_dest_addr()),
505       IP6_ADDR_BLOCK4(ip6_current_dest_addr()),
506       IP6_ADDR_BLOCK5(ip6_current_dest_addr()),
507       IP6_ADDR_BLOCK6(ip6_current_dest_addr()),
508       IP6_ADDR_BLOCK7(ip6_current_dest_addr()),
509       IP6_ADDR_BLOCK8(ip6_current_dest_addr())));
510 
511   /* transmit pbuf on chosen interface */
512   netif->output_ip6(netif, p, ip6_current_dest_addr());
513   IP6_STATS_INC(ip6.fw);
514   IP6_STATS_INC(ip6.xmit);
515   return;
516 }
517 #endif /* LWIP_IPV6_FORWARD */
518 
519 /** Return true if the current input packet should be accepted on this netif */
520 static int
521 ip6_input_accept(struct netif *netif)
522 {
523   /* interface is up? */
524   if (netif_is_up(netif)) {
525     u8_t i;
526     /* unicast to this interface address? address configured? */
527     /* If custom scopes are used, the destination zone will be tested as
528       * part of the local-address comparison, but we need to test the source
529       * scope as well (e.g., is this interface on the same link?). */
530     for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) {
531       if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i)) &&
532           ip6_addr_eq(ip6_current_dest_addr(), netif_ip6_addr(netif, i))
533 #if IPV6_CUSTOM_SCOPES
534           && (!ip6_addr_has_zone(ip6_current_src_addr()) ||
535               ip6_addr_test_zone(ip6_current_src_addr(), netif))
536 #endif /* IPV6_CUSTOM_SCOPES */
537       ) {
538         /* accept on this netif */
539         return 1;
540       }
541     }
542   }
543   return 0;
544 }
545 
546 /**
547  * This function is called by the network interface device driver when
548  * an IPv6 packet is received. The function does the basic checks of the
549  * IP header such as packet size being at least larger than the header
550  * size etc. If the packet was not destined for us, the packet is
551  * forwarded (using ip6_forward).
552  *
553  * Finally, the packet is sent to the upper layer protocol input function.
554  *
555  * @param p the received IPv6 packet (p->payload points to IPv6 header)
556  * @param inp the netif on which this packet was received
557  * @return ERR_OK if the packet was processed (could return ERR_* if it wasn't
558  *         processed, but currently always returns ERR_OK)
559  */
560 err_t
561 ip6_input(struct pbuf *p, struct netif *inp)
562 {
563   struct ip6_hdr *ip6hdr;
564   struct netif *netif;
565   const u8_t *nexth;
566   u16_t hlen, hlen_tot; /* the current header length */
567 #if 0 /*IP_ACCEPT_LINK_LAYER_ADDRESSING*/
568   @todo
569   int check_ip_src=1;
570 #endif /* IP_ACCEPT_LINK_LAYER_ADDRESSING */
571 #if LWIP_RAW
572   raw_input_state_t raw_status;
573 #endif /* LWIP_RAW */
574 
575   LWIP_ASSERT_CORE_LOCKED();
576 
577   IP6_STATS_INC(ip6.recv);
578 
579 #ifdef LOSCFG_NET_CONTAINER
580   struct net_group *group = get_net_group_from_netif(inp);
581 #endif
582 
583   /* identify the IP header */
584   ip6hdr = (struct ip6_hdr *)p->payload;
585   if (IP6H_V(ip6hdr) != 6) {
586     LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_LEVEL_WARNING, ("IPv6 packet dropped due to bad version number %"U32_F"\n",
587         IP6H_V(ip6hdr)));
588     pbuf_free(p);
589     IP6_STATS_INC(ip6.err);
590     IP6_STATS_INC(ip6.drop);
591     return ERR_OK;
592   }
593 
594 #ifdef LWIP_HOOK_IP6_INPUT
595   if (LWIP_HOOK_IP6_INPUT(p, inp)) {
596     /* the packet has been eaten */
597     return ERR_OK;
598   }
599 #endif
600 
601   /* header length exceeds first pbuf length, or ip length exceeds total pbuf length? */
602   if ((IP6_HLEN > p->len) || (IP6H_PLEN(ip6hdr) > (p->tot_len - IP6_HLEN))) {
603     if (IP6_HLEN > p->len) {
604       LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_LEVEL_SERIOUS,
605         ("IPv6 header (len %"U16_F") does not fit in first pbuf (len %"U16_F"), IP packet dropped.\n",
606             (u16_t)IP6_HLEN, p->len));
607     }
608     if ((IP6H_PLEN(ip6hdr) + IP6_HLEN) > p->tot_len) {
609       LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_LEVEL_SERIOUS,
610         ("IPv6 (plen %"U16_F") is longer than pbuf (len %"U16_F"), IP packet dropped.\n",
611             (u16_t)(IP6H_PLEN(ip6hdr) + IP6_HLEN), p->tot_len));
612     }
613     /* free (drop) packet pbufs */
614     pbuf_free(p);
615     IP6_STATS_INC(ip6.lenerr);
616     IP6_STATS_INC(ip6.drop);
617     return ERR_OK;
618   }
619 
620   /* Trim pbuf. This should have been done at the netif layer,
621    * but we'll do it anyway just to be sure that its done. */
622   pbuf_realloc(p, (u16_t)(IP6_HLEN + IP6H_PLEN(ip6hdr)));
623 
624   /* copy IP addresses to aligned ip6_addr_t */
625   ip_addr_copy_from_ip6_packed(ip_data.current_iphdr_dest, ip6hdr->dest);
626   ip_addr_copy_from_ip6_packed(ip_data.current_iphdr_src, ip6hdr->src);
627 
628   /* Don't accept virtual IPv4 mapped IPv6 addresses.
629    * Don't accept multicast source addresses. */
630   if (ip6_addr_isipv4mappedipv6(ip_2_ip6(&ip_data.current_iphdr_dest)) ||
631      ip6_addr_isipv4mappedipv6(ip_2_ip6(&ip_data.current_iphdr_src)) ||
632      ip6_addr_ismulticast(ip_2_ip6(&ip_data.current_iphdr_src))) {
633     /* free (drop) packet pbufs */
634     pbuf_free(p);
635     IP6_STATS_INC(ip6.err);
636     IP6_STATS_INC(ip6.drop);
637     return ERR_OK;
638   }
639 
640   /* Set the appropriate zone identifier on the addresses. */
641   ip6_addr_assign_zone(ip_2_ip6(&ip_data.current_iphdr_dest), IP6_UNKNOWN, inp);
642   ip6_addr_assign_zone(ip_2_ip6(&ip_data.current_iphdr_src), IP6_UNICAST, inp);
643 
644   /* current header pointer. */
645   ip_data.current_ip6_header = ip6hdr;
646 
647   /* In netif, used in case we need to send ICMPv6 packets back. */
648   ip_data.current_netif = inp;
649   ip_data.current_input_netif = inp;
650 
651   /* match packet against an interface, i.e. is this packet for us? */
652   if (ip6_addr_ismulticast(ip6_current_dest_addr())) {
653     /* Always joined to multicast if-local and link-local all-nodes group. */
654     if (ip6_addr_isallnodes_iflocal(ip6_current_dest_addr()) ||
655         ip6_addr_isallnodes_linklocal(ip6_current_dest_addr())) {
656       netif = inp;
657     }
658 #if LWIP_IPV6_MLD
659     else if (mld6_lookfor_group(inp, ip6_current_dest_addr())) {
660       netif = inp;
661     }
662 #else /* LWIP_IPV6_MLD */
663     else if (ip6_addr_issolicitednode(ip6_current_dest_addr())) {
664       u8_t i;
665       /* Filter solicited node packets when MLD is not enabled
666        * (for Neighbor discovery). */
667       netif = NULL;
668       for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) {
669         if (ip6_addr_isvalid(netif_ip6_addr_state(inp, i)) &&
670             ip6_addr_solicitednode_eq(ip6_current_dest_addr(), netif_ip6_addr(inp, i))) {
671           netif = inp;
672           LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: solicited node packet accepted on interface %c%c\n",
673               netif->name[0], netif->name[1]));
674           break;
675         }
676       }
677     }
678 #endif /* LWIP_IPV6_MLD */
679     else {
680       netif = NULL;
681     }
682   } else {
683     /* start trying with inp. if that's not acceptable, start walking the
684        list of configured netifs. */
685     if (ip6_input_accept(inp)) {
686       netif = inp;
687     } else {
688       netif = NULL;
689 #if !IPV6_CUSTOM_SCOPES
690       /* Shortcut: stop looking for other interfaces if either the source or
691         * the destination has a scope constrained to this interface. Custom
692         * scopes may break the 1:1 link/interface mapping, however. */
693       if (ip6_addr_islinklocal(ip6_current_dest_addr()) ||
694           ip6_addr_islinklocal(ip6_current_src_addr())) {
695         goto netif_found;
696       }
697 #endif /* !IPV6_CUSTOM_SCOPES */
698 #if !LWIP_NETIF_LOOPBACK || LWIP_HAVE_LOOPIF
699       /* The loopback address is to be considered link-local. Packets to it
700         * should be dropped on other interfaces, as per RFC 4291 Sec. 2.5.3.
701         * Its implied scope means packets *from* the loopback address should
702         * not be accepted on other interfaces, either. These requirements
703         * cannot be implemented in the case that loopback traffic is sent
704         * across a non-loopback interface, however. */
705       if (ip6_addr_isloopback(ip6_current_dest_addr()) ||
706           ip6_addr_isloopback(ip6_current_src_addr())) {
707         goto netif_found;
708       }
709 #endif /* !LWIP_NETIF_LOOPBACK || LWIP_HAVE_LOOPIF */
710 #if !LWIP_SINGLE_NETIF
711 #ifdef LOSCFG_NET_CONTAINER
712       NETIF_FOREACH(netif, group) {
713 #else
714       NETIF_FOREACH(netif) {
715 #endif
716         if (netif == inp) {
717           /* we checked that before already */
718           continue;
719         }
720         if (ip6_input_accept(netif)) {
721           break;
722         }
723       }
724 #endif /* !LWIP_SINGLE_NETIF */
725     }
726 netif_found:
727     LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: packet accepted on interface %c%c\n",
728         netif ? netif->name[0] : 'X', netif? netif->name[1] : 'X'));
729   }
730 
731   /* "::" packet source address? (used in duplicate address detection) */
732   if (ip6_addr_isany(ip6_current_src_addr()) &&
733       (!ip6_addr_issolicitednode(ip6_current_dest_addr()))) {
734     /* packet source is not valid */
735     /* free (drop) packet pbufs */
736     LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: packet with src ANY_ADDRESS dropped\n"));
737     pbuf_free(p);
738     IP6_STATS_INC(ip6.drop);
739     goto ip6_input_cleanup;
740   }
741 
742   /* packet not for us? */
743   if (netif == NULL) {
744     /* packet not for us, route or discard */
745     LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_TRACE, ("ip6_input: packet not for us.\n"));
746 #if LWIP_IPV6_FORWARD
747     /* non-multicast packet? */
748     if (!ip6_addr_ismulticast(ip6_current_dest_addr())) {
749       /* try to forward IP packet on (other) interfaces */
750       ip6_forward(p, ip6hdr, inp);
751     }
752 #endif /* LWIP_IPV6_FORWARD */
753     pbuf_free(p);
754     goto ip6_input_cleanup;
755   }
756 
757   /* current netif pointer. */
758   ip_data.current_netif = netif;
759 
760   /* Save next header type. */
761   nexth = &IP6H_NEXTH(ip6hdr);
762 
763   /* Init header length. */
764   hlen = hlen_tot = IP6_HLEN;
765 
766   LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: \n"));
767   ip6_debug_print(p);
768   LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: p->len %"U16_F" p->tot_len %"U16_F"\n", p->len, p->tot_len));
769 
770   /* Move to payload. */
771   pbuf_remove_header(p, IP6_HLEN);
772 
773   /* Process known option extension headers, if present. */
774   while (*nexth != IP6_NEXTH_NONE)
775   {
776     switch (*nexth) {
777     case IP6_NEXTH_HOPBYHOP:
778     {
779       s32_t opt_offset;
780       struct ip6_hbh_hdr *hbh_hdr;
781       struct ip6_opt_hdr *opt_hdr;
782       LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: packet with Hop-by-Hop options header\n"));
783 
784       /* Get and check the header length, while staying in packet bounds. */
785       hbh_hdr = (struct ip6_hbh_hdr *)p->payload;
786 
787       /* Get next header type. */
788       nexth = &IP6_HBH_NEXTH(hbh_hdr);
789 
790       /* Get the header length. */
791       hlen = (u16_t)(8 * (1 + hbh_hdr->_hlen));
792 
793       if ((p->len < 8) || (hlen > p->len)) {
794         LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_LEVEL_SERIOUS,
795           ("IPv6 options header (hlen %"U16_F") does not fit in first pbuf (len %"U16_F"), IPv6 packet dropped.\n",
796               hlen, p->len));
797         /* free (drop) packet pbufs */
798         pbuf_free(p);
799         IP6_STATS_INC(ip6.lenerr);
800         IP6_STATS_INC(ip6.drop);
801         goto ip6_input_cleanup;
802       }
803 
804       hlen_tot = (u16_t)(hlen_tot + hlen);
805 
806       /* The extended option header starts right after Hop-by-Hop header. */
807       opt_offset = IP6_HBH_HLEN;
808       while (opt_offset < hlen)
809       {
810         s32_t opt_dlen = 0;
811 
812         opt_hdr = (struct ip6_opt_hdr *)((u8_t *)hbh_hdr + opt_offset);
813 
814         switch (IP6_OPT_TYPE(opt_hdr)) {
815         /* @todo: process IPV6 Hop-by-Hop option data */
816         case IP6_PAD1_OPTION:
817           /* PAD1 option doesn't have length and value field */
818           opt_dlen = -1;
819           break;
820         case IP6_PADN_OPTION:
821           opt_dlen = IP6_OPT_DLEN(opt_hdr);
822           break;
823         case IP6_ROUTER_ALERT_OPTION:
824           opt_dlen = IP6_OPT_DLEN(opt_hdr);
825           break;
826         case IP6_JUMBO_OPTION:
827           opt_dlen = IP6_OPT_DLEN(opt_hdr);
828           break;
829         default:
830           /* Check 2 MSB of Hop-by-Hop header type. */
831           switch (IP6_OPT_TYPE_ACTION(opt_hdr)) {
832           case 1:
833             /* Discard the packet. */
834             LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: packet with invalid Hop-by-Hop option type dropped.\n"));
835             pbuf_free(p);
836             IP6_STATS_INC(ip6.drop);
837             goto ip6_input_cleanup;
838           case 2:
839             /* Send ICMP Parameter Problem */
840             icmp6_param_problem(p, ICMP6_PP_OPTION, opt_hdr);
841             LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: packet with invalid Hop-by-Hop option type dropped.\n"));
842             pbuf_free(p);
843             IP6_STATS_INC(ip6.drop);
844             goto ip6_input_cleanup;
845           case 3:
846             /* Send ICMP Parameter Problem if destination address is not a multicast address */
847             if (!ip6_addr_ismulticast(ip6_current_dest_addr())) {
848               icmp6_param_problem(p, ICMP6_PP_OPTION, opt_hdr);
849             }
850             LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: packet with invalid Hop-by-Hop option type dropped.\n"));
851             pbuf_free(p);
852             IP6_STATS_INC(ip6.drop);
853             goto ip6_input_cleanup;
854           default:
855             /* Skip over this option. */
856             opt_dlen = IP6_OPT_DLEN(opt_hdr);
857             break;
858           }
859           break;
860         }
861 
862         /* Adjust the offset to move to the next extended option header */
863         opt_offset = opt_offset + IP6_OPT_HLEN + opt_dlen;
864       }
865       pbuf_remove_header(p, hlen);
866       break;
867     }
868     case IP6_NEXTH_DESTOPTS:
869     {
870       s32_t opt_offset;
871       struct ip6_dest_hdr *dest_hdr;
872       struct ip6_opt_hdr *opt_hdr;
873       LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: packet with Destination options header\n"));
874 
875       dest_hdr = (struct ip6_dest_hdr *)p->payload;
876 
877       /* Get next header type. */
878       nexth = &IP6_DEST_NEXTH(dest_hdr);
879 
880       /* Get the header length. */
881       hlen = 8 * (1 + dest_hdr->_hlen);
882       if ((p->len < 8) || (hlen > p->len)) {
883         LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_LEVEL_SERIOUS,
884           ("IPv6 options header (hlen %"U16_F") does not fit in first pbuf (len %"U16_F"), IPv6 packet dropped.\n",
885               hlen, p->len));
886         /* free (drop) packet pbufs */
887         pbuf_free(p);
888         IP6_STATS_INC(ip6.lenerr);
889         IP6_STATS_INC(ip6.drop);
890         goto ip6_input_cleanup;
891       }
892 
893       hlen_tot = (u16_t)(hlen_tot + hlen);
894 
895       /* The extended option header starts right after Destination header. */
896       opt_offset = IP6_DEST_HLEN;
897       while (opt_offset < hlen)
898       {
899         s32_t opt_dlen = 0;
900 
901         opt_hdr = (struct ip6_opt_hdr *)((u8_t *)dest_hdr + opt_offset);
902 
903         switch (IP6_OPT_TYPE(opt_hdr))
904         {
905         /* @todo: process IPV6 Destination option data */
906         case IP6_PAD1_OPTION:
907           /* PAD1 option deosn't have length and value field */
908           opt_dlen = -1;
909           break;
910         case IP6_PADN_OPTION:
911           opt_dlen = IP6_OPT_DLEN(opt_hdr);
912           break;
913         case IP6_ROUTER_ALERT_OPTION:
914           opt_dlen = IP6_OPT_DLEN(opt_hdr);
915           break;
916         case IP6_JUMBO_OPTION:
917           opt_dlen = IP6_OPT_DLEN(opt_hdr);
918           break;
919         case IP6_HOME_ADDRESS_OPTION:
920           opt_dlen = IP6_OPT_DLEN(opt_hdr);
921           break;
922         default:
923           /* Check 2 MSB of Destination header type. */
924           switch (IP6_OPT_TYPE_ACTION(opt_hdr))
925           {
926           case 1:
927             /* Discard the packet. */
928             LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: packet with invalid destination option type dropped.\n"));
929             pbuf_free(p);
930             IP6_STATS_INC(ip6.drop);
931             goto ip6_input_cleanup;
932           case 2:
933             /* Send ICMP Parameter Problem */
934             icmp6_param_problem(p, ICMP6_PP_OPTION, opt_hdr);
935             LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: packet with invalid destination option type dropped.\n"));
936             pbuf_free(p);
937             IP6_STATS_INC(ip6.drop);
938             goto ip6_input_cleanup;
939           case 3:
940             /* Send ICMP Parameter Problem if destination address is not a multicast address */
941             if (!ip6_addr_ismulticast(ip6_current_dest_addr())) {
942               icmp6_param_problem(p, ICMP6_PP_OPTION, opt_hdr);
943             }
944             LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: packet with invalid destination option type dropped.\n"));
945             pbuf_free(p);
946             IP6_STATS_INC(ip6.drop);
947             goto ip6_input_cleanup;
948           default:
949             /* Skip over this option. */
950             opt_dlen = IP6_OPT_DLEN(opt_hdr);
951             break;
952           }
953           break;
954         }
955 
956         /* Adjust the offset to move to the next extended option header */
957         opt_offset = opt_offset + IP6_OPT_HLEN + opt_dlen;
958       }
959 
960       pbuf_remove_header(p, hlen);
961       break;
962     }
963     case IP6_NEXTH_ROUTING:
964     {
965       struct ip6_rout_hdr *rout_hdr;
966       LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: packet with Routing header\n"));
967 
968       rout_hdr = (struct ip6_rout_hdr *)p->payload;
969 
970       /* Get next header type. */
971       nexth = &IP6_ROUT_NEXTH(rout_hdr);
972 
973       /* Get the header length. */
974       hlen = 8 * (1 + rout_hdr->_hlen);
975 
976       if ((p->len < 8) || (hlen > p->len)) {
977         LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_LEVEL_SERIOUS,
978           ("IPv6 options header (hlen %"U16_F") does not fit in first pbuf (len %"U16_F"), IPv6 packet dropped.\n",
979               hlen, p->len));
980         /* free (drop) packet pbufs */
981         pbuf_free(p);
982         IP6_STATS_INC(ip6.lenerr);
983         IP6_STATS_INC(ip6.drop);
984         goto ip6_input_cleanup;
985       }
986 
987       /* Skip over this header. */
988       hlen_tot = (u16_t)(hlen_tot + hlen);
989 
990       /* if segment left value is 0 in routing header, ignore the option */
991       if (IP6_ROUT_SEG_LEFT(rout_hdr)) {
992         /* The length field of routing option header must be even */
993         if (rout_hdr->_hlen & 0x1) {
994           /* Discard and send parameter field error */
995           icmp6_param_problem(p, ICMP6_PP_FIELD, &rout_hdr->_hlen);
996           LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: packet with invalid routing type dropped\n"));
997           pbuf_free(p);
998           IP6_STATS_INC(ip6.drop);
999           goto ip6_input_cleanup;
1000         }
1001 
1002         switch (IP6_ROUT_TYPE(rout_hdr))
1003         {
1004         /* TODO: process routing by the type */
1005         case IP6_ROUT_TYPE2:
1006           break;
1007         case IP6_ROUT_RPL:
1008           break;
1009         default:
1010           /* Discard unrecognized routing type and send parameter field error */
1011           icmp6_param_problem(p, ICMP6_PP_FIELD, &IP6_ROUT_TYPE(rout_hdr));
1012           LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: packet with invalid routing type dropped\n"));
1013           pbuf_free(p);
1014           IP6_STATS_INC(ip6.drop);
1015           goto ip6_input_cleanup;
1016         }
1017       }
1018 
1019       pbuf_remove_header(p, hlen);
1020       break;
1021     }
1022     case IP6_NEXTH_FRAGMENT:
1023     {
1024       struct ip6_frag_hdr *frag_hdr;
1025       LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: packet with Fragment header\n"));
1026 
1027       frag_hdr = (struct ip6_frag_hdr *)p->payload;
1028 
1029       /* Get next header type. */
1030       nexth = &IP6_FRAG_NEXTH(frag_hdr);
1031 
1032       /* Fragment Header length. */
1033       hlen = 8;
1034 
1035       /* Make sure this header fits in current pbuf. */
1036       if (hlen > p->len) {
1037         LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_LEVEL_SERIOUS,
1038           ("IPv6 options header (hlen %"U16_F") does not fit in first pbuf (len %"U16_F"), IPv6 packet dropped.\n",
1039               hlen, p->len));
1040         /* free (drop) packet pbufs */
1041         pbuf_free(p);
1042         IP6_FRAG_STATS_INC(ip6_frag.lenerr);
1043         IP6_FRAG_STATS_INC(ip6_frag.drop);
1044         goto ip6_input_cleanup;
1045       }
1046 
1047       hlen_tot = (u16_t)(hlen_tot + hlen);
1048 
1049       /* check payload length is multiple of 8 octets when mbit is set */
1050       if (IP6_FRAG_MBIT(frag_hdr) && (IP6H_PLEN(ip6hdr) & 0x7)) {
1051         /* ipv6 payload length is not multiple of 8 octets */
1052         icmp6_param_problem(p, ICMP6_PP_FIELD, LWIP_PACKED_CAST(const void *, &ip6hdr->_plen));
1053         LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: packet with invalid payload length dropped\n"));
1054         pbuf_free(p);
1055         IP6_STATS_INC(ip6.drop);
1056         goto ip6_input_cleanup;
1057       }
1058 
1059       /* Offset == 0 and more_fragments == 0? */
1060       if ((frag_hdr->_fragment_offset &
1061            PP_HTONS(IP6_FRAG_OFFSET_MASK | IP6_FRAG_MORE_FLAG)) == 0) {
1062         /* This is a 1-fragment packet. Skip this header and continue. */
1063         pbuf_remove_header(p, hlen);
1064       } else {
1065 #if LWIP_IPV6_REASS
1066         /* reassemble the packet */
1067         ip_data.current_ip_header_tot_len = hlen_tot;
1068         p = ip6_reass(p);
1069         /* packet not fully reassembled yet? */
1070         if (p == NULL) {
1071           goto ip6_input_cleanup;
1072         }
1073 
1074         /* Returned p points to IPv6 header.
1075          * Update all our variables and pointers and continue. */
1076         ip6hdr = (struct ip6_hdr *)p->payload;
1077         ip_data.current_ip6_header = ip6hdr;
1078         nexth = &IP6H_NEXTH(ip6hdr);
1079         hlen = hlen_tot = IP6_HLEN;
1080         pbuf_remove_header(p, IP6_HLEN);
1081 
1082 #else /* LWIP_IPV6_REASS */
1083         /* free (drop) packet pbufs */
1084         LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: packet with Fragment header dropped (with LWIP_IPV6_REASS==0)\n"));
1085         pbuf_free(p);
1086         IP6_STATS_INC(ip6.opterr);
1087         IP6_STATS_INC(ip6.drop);
1088         goto ip6_input_cleanup;
1089 #endif /* LWIP_IPV6_REASS */
1090       }
1091       break;
1092     }
1093     default:
1094       goto options_done;
1095     }
1096 
1097     if (*nexth == IP6_NEXTH_HOPBYHOP) {
1098       /* Hop-by-Hop header comes only as a first option */
1099       icmp6_param_problem(p, ICMP6_PP_HEADER, nexth);
1100       LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: packet with Hop-by-Hop options header dropped (only valid as a first option)\n"));
1101       pbuf_free(p);
1102       IP6_STATS_INC(ip6.drop);
1103       goto ip6_input_cleanup;
1104     }
1105   }
1106 
1107 options_done:
1108 
1109   /* send to upper layers */
1110   ip_data.current_ip_header_tot_len = hlen_tot;
1111 
1112 #if LWIP_RAW
1113   /* p points to IPv6 header again for raw_input. */
1114   pbuf_add_header_force(p, hlen_tot);
1115   /* raw input did not eat the packet? */
1116   raw_status = raw_input(p, inp);
1117   if (raw_status != RAW_INPUT_EATEN)
1118   {
1119     /* Point to payload. */
1120     pbuf_remove_header(p, hlen_tot);
1121 #else /* LWIP_RAW */
1122   {
1123 #endif /* LWIP_RAW */
1124     switch (*nexth) {
1125     case IP6_NEXTH_NONE:
1126       pbuf_free(p);
1127       break;
1128 #if LWIP_UDP
1129     case IP6_NEXTH_UDP:
1130 #if LWIP_UDPLITE
1131     case IP6_NEXTH_UDPLITE:
1132 #endif /* LWIP_UDPLITE */
1133       udp_input(p, inp);
1134       break;
1135 #endif /* LWIP_UDP */
1136 #if LWIP_TCP
1137     case IP6_NEXTH_TCP:
1138       tcp_input(p, inp);
1139       break;
1140 #endif /* LWIP_TCP */
1141 #if LWIP_ICMP6
1142     case IP6_NEXTH_ICMP6:
1143       icmp6_input(p, inp);
1144       break;
1145 #endif /* LWIP_ICMP */
1146     default:
1147 #if LWIP_RAW
1148         if (raw_status == RAW_INPUT_DELIVERED) {
1149           /* @todo: ipv6 mib in-delivers? */
1150         } else
1151 #endif /* LWIP_RAW */
1152         {
1153 #if LWIP_ICMP6
1154         /* p points to IPv6 header again for raw_input. */
1155         pbuf_add_header_force(p, hlen_tot);
1156         /* send ICMP parameter problem unless it was a multicast or ICMPv6 */
1157         if ((!ip6_addr_ismulticast(ip6_current_dest_addr())) &&
1158             (IP6H_NEXTH(ip6hdr) != IP6_NEXTH_ICMP6)) {
1159           icmp6_param_problem(p, ICMP6_PP_HEADER, nexth);
1160         }
1161 #endif /* LWIP_ICMP */
1162         LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("ip6_input: Unsupported transport protocol %"U16_F"\n", (u16_t)IP6H_NEXTH(ip6hdr)));
1163         IP6_STATS_INC(ip6.proterr);
1164         IP6_STATS_INC(ip6.drop);
1165       }
1166       pbuf_free(p);
1167       break;
1168     }
1169   }
1170 
1171 ip6_input_cleanup:
1172   ip_data.current_netif = NULL;
1173   ip_data.current_input_netif = NULL;
1174   ip_data.current_ip6_header = NULL;
1175   ip_data.current_ip_header_tot_len = 0;
1176   ip6_addr_set_zero(ip6_current_src_addr());
1177   ip6_addr_set_zero(ip6_current_dest_addr());
1178 
1179   return ERR_OK;
1180 }
1181 
1182 
1183 /**
1184  * Sends an IPv6 packet on a network interface. This function constructs
1185  * the IPv6 header. If the source IPv6 address is NULL, the IPv6 "ANY" address is
1186  * used as source (usually during network startup). If the source IPv6 address it
1187  * IP6_ADDR_ANY, the most appropriate IPv6 address of the outgoing network
1188  * interface is filled in as source address. If the destination IPv6 address is
1189  * LWIP_IP_HDRINCL, p is assumed to already include an IPv6 header and
1190  * p->payload points to it instead of the data.
1191  *
1192  * @param p the packet to send (p->payload points to the data, e.g. next
1193             protocol header; if dest == LWIP_IP_HDRINCL, p already includes an
1194             IPv6 header and p->payload points to that IPv6 header)
1195  * @param src the source IPv6 address to send from (if src == IP6_ADDR_ANY, an
1196  *         IP address of the netif is selected and used as source address.
1197  *         if src == NULL, IP6_ADDR_ANY is used as source) (src is possibly not
1198  *         properly zoned)
1199  * @param dest the destination IPv6 address to send the packet to (possibly not
1200  *             properly zoned)
1201  * @param hl the Hop Limit value to be set in the IPv6 header
1202  * @param tc the Traffic Class value to be set in the IPv6 header
1203  * @param nexth the Next Header to be set in the IPv6 header
1204  * @param netif the netif on which to send this packet
1205  * @return ERR_OK if the packet was sent OK
1206  *         ERR_BUF if p doesn't have enough space for IPv6/LINK headers
1207  *         returns errors returned by netif->output_ip6
1208  */
1209 err_t
1210 ip6_output_if(struct pbuf *p, const ip6_addr_t *src, const ip6_addr_t *dest,
1211              u8_t hl, u8_t tc,
1212              u8_t nexth, struct netif *netif)
1213 {
1214   const ip6_addr_t *src_used = src;
1215   if (dest != LWIP_IP_HDRINCL) {
1216     if (src != NULL && ip6_addr_isany(src)) {
1217       src_used = ip_2_ip6(ip6_select_source_address(netif, dest));
1218       if ((src_used == NULL) || ip6_addr_isany(src_used)) {
1219         /* No appropriate source address was found for this packet. */
1220         LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("ip6_output: No suitable source address for packet.\n"));
1221         IP6_STATS_INC(ip6.rterr);
1222         return ERR_RTE;
1223       }
1224     }
1225   }
1226   return ip6_output_if_src(p, src_used, dest, hl, tc, nexth, netif);
1227 }
1228 
1229 /**
1230  * Same as ip6_output_if() but 'src' address is not replaced by netif address
1231  * when it is 'any'.
1232  */
1233 err_t
1234 ip6_output_if_src(struct pbuf *p, const ip6_addr_t *src, const ip6_addr_t *dest,
1235              u8_t hl, u8_t tc,
1236              u8_t nexth, struct netif *netif)
1237 {
1238   struct ip6_hdr *ip6hdr;
1239   ip6_addr_t dest_addr;
1240 
1241   LWIP_ASSERT_CORE_LOCKED();
1242   LWIP_IP_CHECK_PBUF_REF_COUNT_FOR_TX(p);
1243 
1244   /* Should the IPv6 header be generated or is it already included in p? */
1245   if (dest != LWIP_IP_HDRINCL) {
1246 #if LWIP_IPV6_SCOPES
1247     /* If the destination address is scoped but lacks a zone, add a zone now,
1248      * based on the outgoing interface. The lower layers (e.g., nd6) absolutely
1249      * require addresses to be properly zoned for correctness. In some cases,
1250      * earlier attempts will have been made to add a zone to the destination,
1251      * but this function is the only one that is called in all (other) cases,
1252      * so we must do this here. */
1253     if (ip6_addr_lacks_zone(dest, IP6_UNKNOWN)) {
1254       ip6_addr_copy(dest_addr, *dest);
1255       ip6_addr_assign_zone(&dest_addr, IP6_UNKNOWN, netif);
1256       dest = &dest_addr;
1257     }
1258 #endif /* LWIP_IPV6_SCOPES */
1259 
1260     /* generate IPv6 header */
1261     if (pbuf_add_header(p, IP6_HLEN)) {
1262       LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("ip6_output: not enough room for IPv6 header in pbuf\n"));
1263       IP6_STATS_INC(ip6.err);
1264       return ERR_BUF;
1265     }
1266 
1267     ip6hdr = (struct ip6_hdr *)p->payload;
1268     LWIP_ASSERT("check that first pbuf can hold struct ip6_hdr",
1269                (p->len >= sizeof(struct ip6_hdr)));
1270 
1271     IP6H_HOPLIM_SET(ip6hdr, hl);
1272     IP6H_NEXTH_SET(ip6hdr, nexth);
1273 
1274     /* dest cannot be NULL here */
1275     ip6_addr_copy_to_packed(ip6hdr->dest, *dest);
1276 
1277     IP6H_VTCFL_SET(ip6hdr, 6, tc, 0);
1278     IP6H_PLEN_SET(ip6hdr, (u16_t)(p->tot_len - IP6_HLEN));
1279 
1280     if (src == NULL) {
1281       src = IP6_ADDR_ANY6;
1282     }
1283     /* src cannot be NULL here */
1284     ip6_addr_copy_to_packed(ip6hdr->src, *src);
1285 
1286   } else {
1287     /* IP header already included in p */
1288     ip6hdr = (struct ip6_hdr *)p->payload;
1289     ip6_addr_copy_from_packed(dest_addr, ip6hdr->dest);
1290     ip6_addr_assign_zone(&dest_addr, IP6_UNKNOWN, netif);
1291     dest = &dest_addr;
1292   }
1293 
1294   IP6_STATS_INC(ip6.xmit);
1295 
1296   LWIP_DEBUGF(IP6_DEBUG, ("ip6_output_if: %c%c%"U16_F"\n", netif->name[0], netif->name[1], (u16_t)netif->num));
1297   ip6_debug_print(p);
1298 
1299 #if ENABLE_LOOPBACK
1300   {
1301     int i;
1302 #if !LWIP_HAVE_LOOPIF
1303     if (ip6_addr_isloopback(dest)) {
1304       return netif_loop_output(netif, p);
1305     }
1306 #endif /* !LWIP_HAVE_LOOPIF */
1307     for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) {
1308       if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i)) &&
1309           ip6_addr_eq(dest, netif_ip6_addr(netif, i))) {
1310         /* Packet to self, enqueue it for loopback */
1311         LWIP_DEBUGF(IP6_DEBUG, ("netif_loop_output()\n"));
1312         return netif_loop_output(netif, p);
1313       }
1314     }
1315   }
1316 #if LWIP_MULTICAST_TX_OPTIONS
1317   if ((p->flags & PBUF_FLAG_MCASTLOOP) != 0) {
1318     netif_loop_output(netif, p);
1319   }
1320 #endif /* LWIP_MULTICAST_TX_OPTIONS */
1321 #endif /* ENABLE_LOOPBACK */
1322 #if LWIP_IPV6_FRAG
1323   /* don't fragment if interface has mtu set to 0 [loopif] */
1324   if (netif_mtu6(netif) && (p->tot_len > nd6_get_destination_mtu(dest, netif))) {
1325     return ip6_frag(p, netif, dest);
1326   }
1327 #endif /* LWIP_IPV6_FRAG */
1328 
1329   LWIP_DEBUGF(IP6_DEBUG, ("netif->output_ip6()\n"));
1330   return netif->output_ip6(netif, p, dest);
1331 }
1332 
1333 /**
1334  * Simple interface to ip6_output_if. It finds the outgoing network
1335  * interface and calls upon ip6_output_if to do the actual work.
1336  *
1337  * @param p the packet to send (p->payload points to the data, e.g. next
1338             protocol header; if dest == LWIP_IP_HDRINCL, p already includes an
1339             IPv6 header and p->payload points to that IPv6 header)
1340  * @param src the source IPv6 address to send from (if src == IP6_ADDR_ANY, an
1341  *         IP address of the netif is selected and used as source address.
1342  *         if src == NULL, IP6_ADDR_ANY is used as source)
1343  * @param dest the destination IPv6 address to send the packet to
1344  * @param hl the Hop Limit value to be set in the IPv6 header
1345  * @param tc the Traffic Class value to be set in the IPv6 header
1346  * @param nexth the Next Header to be set in the IPv6 header
1347  *
1348  * @return ERR_RTE if no route is found
1349  *         see ip_output_if() for more return values
1350  */
1351 err_t
1352 ip6_output(struct pbuf *p, const ip6_addr_t *src, const ip6_addr_t *dest,
1353           u8_t hl, u8_t tc, u8_t nexth)
1354 {
1355   struct netif *netif;
1356   struct ip6_hdr *ip6hdr;
1357   ip6_addr_t src_addr, dest_addr;
1358 
1359   LWIP_IP_CHECK_PBUF_REF_COUNT_FOR_TX(p);
1360 
1361 #ifdef LOSCFG_NET_CONTAINER
1362   struct net_group *group = get_curr_process_net_group();
1363 #endif
1364 
1365   if (dest != LWIP_IP_HDRINCL) {
1366 #ifdef LOSCFG_NET_CONTAINER
1367     netif = ip6_route(src, dest, group);
1368 #else
1369     netif = ip6_route(src, dest);
1370 #endif
1371   } else {
1372     /* IP header included in p, read addresses. */
1373     ip6hdr = (struct ip6_hdr *)p->payload;
1374     ip6_addr_copy_from_packed(src_addr, ip6hdr->src);
1375     ip6_addr_copy_from_packed(dest_addr, ip6hdr->dest);
1376 #ifdef LOSCFG_NET_CONTAINER
1377     netif = ip6_route(&src_addr, &dest_addr, group);
1378 #else
1379     netif = ip6_route(&src_addr, &dest_addr);
1380 #endif
1381     dest = &dest_addr;
1382   }
1383 
1384   if (netif == NULL) {
1385     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",
1386         IP6_ADDR_BLOCK1(dest),
1387         IP6_ADDR_BLOCK2(dest),
1388         IP6_ADDR_BLOCK3(dest),
1389         IP6_ADDR_BLOCK4(dest),
1390         IP6_ADDR_BLOCK5(dest),
1391         IP6_ADDR_BLOCK6(dest),
1392         IP6_ADDR_BLOCK7(dest),
1393         IP6_ADDR_BLOCK8(dest)));
1394     IP6_STATS_INC(ip6.rterr);
1395     return ERR_RTE;
1396   }
1397 
1398   return ip6_output_if(p, src, dest, hl, tc, nexth, netif);
1399 }
1400 
1401 
1402 #if LWIP_NETIF_USE_HINTS
1403 /** Like ip6_output, but takes and addr_hint pointer that is passed on to netif->addr_hint
1404  *  before calling ip6_output_if.
1405  *
1406  * @param p the packet to send (p->payload points to the data, e.g. next
1407             protocol header; if dest == LWIP_IP_HDRINCL, p already includes an
1408             IPv6 header and p->payload points to that IPv6 header)
1409  * @param src the source IPv6 address to send from (if src == IP6_ADDR_ANY, an
1410  *         IP address of the netif is selected and used as source address.
1411  *         if src == NULL, IP6_ADDR_ANY is used as source)
1412  * @param dest the destination IPv6 address to send the packet to
1413  * @param hl the Hop Limit value to be set in the IPv6 header
1414  * @param tc the Traffic Class value to be set in the IPv6 header
1415  * @param nexth the Next Header to be set in the IPv6 header
1416  * @param netif_hint netif output hint pointer set to netif->hint before
1417  *        calling ip_output_if()
1418  *
1419  * @return ERR_RTE if no route is found
1420  *         see ip_output_if() for more return values
1421  */
1422 err_t
1423 ip6_output_hinted(struct pbuf *p, const ip6_addr_t *src, const ip6_addr_t *dest,
1424           u8_t hl, u8_t tc, u8_t nexth, struct netif_hint *netif_hint)
1425 {
1426   struct netif *netif;
1427   struct ip6_hdr *ip6hdr;
1428   ip6_addr_t src_addr, dest_addr;
1429   err_t err;
1430 
1431   LWIP_IP_CHECK_PBUF_REF_COUNT_FOR_TX(p);
1432 
1433   if (dest != LWIP_IP_HDRINCL) {
1434     netif = ip6_route(src, dest);
1435   } else {
1436     /* IP header included in p, read addresses. */
1437     ip6hdr = (struct ip6_hdr *)p->payload;
1438     ip6_addr_copy_from_packed(src_addr, ip6hdr->src);
1439     ip6_addr_copy_from_packed(dest_addr, ip6hdr->dest);
1440     netif = ip6_route(&src_addr, &dest_addr);
1441     dest = &dest_addr;
1442   }
1443 
1444   if (netif == NULL) {
1445     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",
1446         IP6_ADDR_BLOCK1(dest),
1447         IP6_ADDR_BLOCK2(dest),
1448         IP6_ADDR_BLOCK3(dest),
1449         IP6_ADDR_BLOCK4(dest),
1450         IP6_ADDR_BLOCK5(dest),
1451         IP6_ADDR_BLOCK6(dest),
1452         IP6_ADDR_BLOCK7(dest),
1453         IP6_ADDR_BLOCK8(dest)));
1454     IP6_STATS_INC(ip6.rterr);
1455     return ERR_RTE;
1456   }
1457 
1458   NETIF_SET_HINTS(netif, netif_hint);
1459   err = ip6_output_if(p, src, dest, hl, tc, nexth, netif);
1460   NETIF_RESET_HINTS(netif);
1461 
1462   return err;
1463 }
1464 #endif /* LWIP_NETIF_USE_HINTS*/
1465 
1466 #if LWIP_IPV6_MLD
1467 /**
1468  * Add a hop-by-hop options header with a router alert option and padding.
1469  *
1470  * Used by MLD when sending a Multicast listener report/done message.
1471  *
1472  * @param p the packet to which we will prepend the options header
1473  * @param nexth the next header protocol number (e.g. IP6_NEXTH_ICMP6)
1474  * @param value the value of the router alert option data (e.g. IP6_ROUTER_ALERT_VALUE_MLD)
1475  * @return ERR_OK if hop-by-hop header was added, ERR_* otherwise
1476  */
1477 err_t
1478 ip6_options_add_hbh_ra(struct pbuf *p, u8_t nexth, u8_t value)
1479 {
1480   u8_t *opt_data;
1481   u32_t offset = 0;
1482   struct ip6_hbh_hdr *hbh_hdr;
1483   struct ip6_opt_hdr *opt_hdr;
1484 
1485   /* fixed 4 bytes for router alert option and 2 bytes padding */
1486   const u8_t hlen = (sizeof(struct ip6_opt_hdr) * 2) + IP6_ROUTER_ALERT_DLEN;
1487   /* Move pointer to make room for hop-by-hop options header. */
1488   if (pbuf_add_header(p, sizeof(struct ip6_hbh_hdr) + hlen)) {
1489     LWIP_DEBUGF(IP6_DEBUG, ("ip6_options: no space for options header\n"));
1490     IP6_STATS_INC(ip6.err);
1491     return ERR_BUF;
1492   }
1493 
1494   /* Set fields of Hop-by-Hop header */
1495   hbh_hdr = (struct ip6_hbh_hdr *)p->payload;
1496   IP6_HBH_NEXTH(hbh_hdr) = nexth;
1497   hbh_hdr->_hlen = 0;
1498   offset = IP6_HBH_HLEN;
1499 
1500   /* Set router alert options to Hop-by-Hop extended option header */
1501   opt_hdr = (struct ip6_opt_hdr *)((u8_t *)hbh_hdr + offset);
1502   IP6_OPT_TYPE(opt_hdr) = IP6_ROUTER_ALERT_OPTION;
1503   IP6_OPT_DLEN(opt_hdr) = IP6_ROUTER_ALERT_DLEN;
1504   offset += IP6_OPT_HLEN;
1505 
1506   /* Set router alert option data */
1507   opt_data = (u8_t *)hbh_hdr + offset;
1508   opt_data[0] = value;
1509   opt_data[1] = 0;
1510   offset += IP6_OPT_DLEN(opt_hdr);
1511 
1512   /* add 2 bytes padding to make 8 bytes Hop-by-Hop header length */
1513   opt_hdr = (struct ip6_opt_hdr *)((u8_t *)hbh_hdr + offset);
1514   IP6_OPT_TYPE(opt_hdr) = IP6_PADN_OPTION;
1515   IP6_OPT_DLEN(opt_hdr) = 0;
1516 
1517   return ERR_OK;
1518 }
1519 #endif /* LWIP_IPV6_MLD */
1520 
1521 #if IP6_DEBUG
1522 /* Print an IPv6 header by using LWIP_DEBUGF
1523  * @param p an IPv6 packet, p->payload pointing to the IPv6 header
1524  */
1525 void
1526 ip6_debug_print(struct pbuf *p)
1527 {
1528   struct ip6_hdr *ip6hdr = (struct ip6_hdr *)p->payload;
1529 
1530   LWIP_DEBUGF(IP6_DEBUG, ("IPv6 header:\n"));
1531   LWIP_DEBUGF(IP6_DEBUG, ("+-------------------------------+\n"));
1532   LWIP_DEBUGF(IP6_DEBUG, ("| %2"U16_F" |  %3"U16_F"  |      %7"U32_F"     | (ver, class, flow)\n",
1533                     IP6H_V(ip6hdr),
1534                     IP6H_TC(ip6hdr),
1535                     IP6H_FL(ip6hdr)));
1536   LWIP_DEBUGF(IP6_DEBUG, ("+-------------------------------+\n"));
1537   LWIP_DEBUGF(IP6_DEBUG, ("|     %5"U16_F"     |  %3"U16_F"  |  %3"U16_F"  | (plen, nexth, hopl)\n",
1538                     IP6H_PLEN(ip6hdr),
1539                     IP6H_NEXTH(ip6hdr),
1540                     IP6H_HOPLIM(ip6hdr)));
1541   LWIP_DEBUGF(IP6_DEBUG, ("+-------------------------------+\n"));
1542   LWIP_DEBUGF(IP6_DEBUG, ("|  %4"X32_F" |  %4"X32_F" |  %4"X32_F" |  %4"X32_F" | (src)\n",
1543                     IP6_ADDR_BLOCK1(&(ip6hdr->src)),
1544                     IP6_ADDR_BLOCK2(&(ip6hdr->src)),
1545                     IP6_ADDR_BLOCK3(&(ip6hdr->src)),
1546                     IP6_ADDR_BLOCK4(&(ip6hdr->src))));
1547   LWIP_DEBUGF(IP6_DEBUG, ("|  %4"X32_F" |  %4"X32_F" |  %4"X32_F" |  %4"X32_F" |\n",
1548                     IP6_ADDR_BLOCK5(&(ip6hdr->src)),
1549                     IP6_ADDR_BLOCK6(&(ip6hdr->src)),
1550                     IP6_ADDR_BLOCK7(&(ip6hdr->src)),
1551                     IP6_ADDR_BLOCK8(&(ip6hdr->src))));
1552   LWIP_DEBUGF(IP6_DEBUG, ("+-------------------------------+\n"));
1553   LWIP_DEBUGF(IP6_DEBUG, ("|  %4"X32_F" |  %4"X32_F" |  %4"X32_F" |  %4"X32_F" | (dest)\n",
1554                     IP6_ADDR_BLOCK1(&(ip6hdr->dest)),
1555                     IP6_ADDR_BLOCK2(&(ip6hdr->dest)),
1556                     IP6_ADDR_BLOCK3(&(ip6hdr->dest)),
1557                     IP6_ADDR_BLOCK4(&(ip6hdr->dest))));
1558   LWIP_DEBUGF(IP6_DEBUG, ("|  %4"X32_F" |  %4"X32_F" |  %4"X32_F" |  %4"X32_F" |\n",
1559                     IP6_ADDR_BLOCK5(&(ip6hdr->dest)),
1560                     IP6_ADDR_BLOCK6(&(ip6hdr->dest)),
1561                     IP6_ADDR_BLOCK7(&(ip6hdr->dest)),
1562                     IP6_ADDR_BLOCK8(&(ip6hdr->dest))));
1563   LWIP_DEBUGF(IP6_DEBUG, ("+-------------------------------+\n"));
1564 }
1565 #endif /* IP6_DEBUG */
1566 
1567 #endif /* LWIP_IPV6 */
1568