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_cmp_zoneless(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_netcmp(dest, netif_ip6_addr(netif, i)) &&
233 (netif_ip6_addr_isstatic(netif, i) ||
234 ip6_addr_nethostcmp(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_cmp(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_netcmp_zoneless(cand_addr, dest); /* just 1 or 0 for now */
388 if (cand_bits && ip6_addr_nethostcmp(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_cmp(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_cmp_solicitednode(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 /* Move to payload. */
767 pbuf_remove_header(p, IP6_HLEN);
768
769 /* Process known option extension headers, if present. */
770 while (*nexth != IP6_NEXTH_NONE)
771 {
772 switch (*nexth) {
773 case IP6_NEXTH_HOPBYHOP:
774 {
775 s32_t opt_offset;
776 struct ip6_hbh_hdr *hbh_hdr;
777 struct ip6_opt_hdr *opt_hdr;
778 LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: packet with Hop-by-Hop options header\n"));
779
780 /* Get and check the header length, while staying in packet bounds. */
781 hbh_hdr = (struct ip6_hbh_hdr *)p->payload;
782
783 /* Get next header type. */
784 nexth = &IP6_HBH_NEXTH(hbh_hdr);
785
786 /* Get the header length. */
787 hlen = (u16_t)(8 * (1 + hbh_hdr->_hlen));
788
789 if ((p->len < 8) || (hlen > p->len)) {
790 LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_LEVEL_SERIOUS,
791 ("IPv6 options header (hlen %"U16_F") does not fit in first pbuf (len %"U16_F"), IPv6 packet dropped.\n",
792 hlen, p->len));
793 /* free (drop) packet pbufs */
794 pbuf_free(p);
795 IP6_STATS_INC(ip6.lenerr);
796 IP6_STATS_INC(ip6.drop);
797 goto ip6_input_cleanup;
798 }
799
800 hlen_tot = (u16_t)(hlen_tot + hlen);
801
802 /* The extended option header starts right after Hop-by-Hop header. */
803 opt_offset = IP6_HBH_HLEN;
804 while (opt_offset < hlen)
805 {
806 s32_t opt_dlen = 0;
807
808 opt_hdr = (struct ip6_opt_hdr *)((u8_t *)hbh_hdr + opt_offset);
809
810 switch (IP6_OPT_TYPE(opt_hdr)) {
811 /* @todo: process IPV6 Hop-by-Hop option data */
812 case IP6_PAD1_OPTION:
813 /* PAD1 option doesn't have length and value field */
814 opt_dlen = -1;
815 break;
816 case IP6_PADN_OPTION:
817 opt_dlen = IP6_OPT_DLEN(opt_hdr);
818 break;
819 case IP6_ROUTER_ALERT_OPTION:
820 opt_dlen = IP6_OPT_DLEN(opt_hdr);
821 break;
822 case IP6_JUMBO_OPTION:
823 opt_dlen = IP6_OPT_DLEN(opt_hdr);
824 break;
825 default:
826 /* Check 2 MSB of Hop-by-Hop header type. */
827 switch (IP6_OPT_TYPE_ACTION(opt_hdr)) {
828 case 1:
829 /* Discard the packet. */
830 LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: packet with invalid Hop-by-Hop option type dropped.\n"));
831 pbuf_free(p);
832 IP6_STATS_INC(ip6.drop);
833 goto ip6_input_cleanup;
834 case 2:
835 /* Send ICMP Parameter Problem */
836 icmp6_param_problem(p, ICMP6_PP_OPTION, opt_hdr);
837 LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: packet with invalid Hop-by-Hop option type dropped.\n"));
838 pbuf_free(p);
839 IP6_STATS_INC(ip6.drop);
840 goto ip6_input_cleanup;
841 case 3:
842 /* Send ICMP Parameter Problem if destination address is not a multicast address */
843 if (!ip6_addr_ismulticast(ip6_current_dest_addr())) {
844 icmp6_param_problem(p, ICMP6_PP_OPTION, opt_hdr);
845 }
846 LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: packet with invalid Hop-by-Hop option type dropped.\n"));
847 pbuf_free(p);
848 IP6_STATS_INC(ip6.drop);
849 goto ip6_input_cleanup;
850 default:
851 /* Skip over this option. */
852 opt_dlen = IP6_OPT_DLEN(opt_hdr);
853 break;
854 }
855 break;
856 }
857
858 /* Adjust the offset to move to the next extended option header */
859 opt_offset = opt_offset + IP6_OPT_HLEN + opt_dlen;
860 }
861 pbuf_remove_header(p, hlen);
862 break;
863 }
864 case IP6_NEXTH_DESTOPTS:
865 {
866 s32_t opt_offset;
867 struct ip6_dest_hdr *dest_hdr;
868 struct ip6_opt_hdr *opt_hdr;
869 LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: packet with Destination options header\n"));
870
871 dest_hdr = (struct ip6_dest_hdr *)p->payload;
872
873 /* Get next header type. */
874 nexth = &IP6_DEST_NEXTH(dest_hdr);
875
876 /* Get the header length. */
877 hlen = 8 * (1 + dest_hdr->_hlen);
878 if ((p->len < 8) || (hlen > p->len)) {
879 LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_LEVEL_SERIOUS,
880 ("IPv6 options header (hlen %"U16_F") does not fit in first pbuf (len %"U16_F"), IPv6 packet dropped.\n",
881 hlen, p->len));
882 /* free (drop) packet pbufs */
883 pbuf_free(p);
884 IP6_STATS_INC(ip6.lenerr);
885 IP6_STATS_INC(ip6.drop);
886 goto ip6_input_cleanup;
887 }
888
889 hlen_tot = (u16_t)(hlen_tot + hlen);
890
891 /* The extended option header starts right after Destination header. */
892 opt_offset = IP6_DEST_HLEN;
893 while (opt_offset < hlen)
894 {
895 s32_t opt_dlen = 0;
896
897 opt_hdr = (struct ip6_opt_hdr *)((u8_t *)dest_hdr + opt_offset);
898
899 switch (IP6_OPT_TYPE(opt_hdr))
900 {
901 /* @todo: process IPV6 Destination option data */
902 case IP6_PAD1_OPTION:
903 /* PAD1 option deosn't have length and value field */
904 opt_dlen = -1;
905 break;
906 case IP6_PADN_OPTION:
907 opt_dlen = IP6_OPT_DLEN(opt_hdr);
908 break;
909 case IP6_ROUTER_ALERT_OPTION:
910 opt_dlen = IP6_OPT_DLEN(opt_hdr);
911 break;
912 case IP6_JUMBO_OPTION:
913 opt_dlen = IP6_OPT_DLEN(opt_hdr);
914 break;
915 case IP6_HOME_ADDRESS_OPTION:
916 opt_dlen = IP6_OPT_DLEN(opt_hdr);
917 break;
918 default:
919 /* Check 2 MSB of Destination header type. */
920 switch (IP6_OPT_TYPE_ACTION(opt_hdr))
921 {
922 case 1:
923 /* Discard the packet. */
924 LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: packet with invalid destination option type dropped.\n"));
925 pbuf_free(p);
926 IP6_STATS_INC(ip6.drop);
927 goto ip6_input_cleanup;
928 case 2:
929 /* Send ICMP Parameter Problem */
930 icmp6_param_problem(p, ICMP6_PP_OPTION, opt_hdr);
931 LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: packet with invalid destination option type dropped.\n"));
932 pbuf_free(p);
933 IP6_STATS_INC(ip6.drop);
934 goto ip6_input_cleanup;
935 case 3:
936 /* Send ICMP Parameter Problem if destination address is not a multicast address */
937 if (!ip6_addr_ismulticast(ip6_current_dest_addr())) {
938 icmp6_param_problem(p, ICMP6_PP_OPTION, opt_hdr);
939 }
940 LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: packet with invalid destination option type dropped.\n"));
941 pbuf_free(p);
942 IP6_STATS_INC(ip6.drop);
943 goto ip6_input_cleanup;
944 default:
945 /* Skip over this option. */
946 opt_dlen = IP6_OPT_DLEN(opt_hdr);
947 break;
948 }
949 break;
950 }
951
952 /* Adjust the offset to move to the next extended option header */
953 opt_offset = opt_offset + IP6_OPT_HLEN + opt_dlen;
954 }
955
956 pbuf_remove_header(p, hlen);
957 break;
958 }
959 case IP6_NEXTH_ROUTING:
960 {
961 struct ip6_rout_hdr *rout_hdr;
962 LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: packet with Routing header\n"));
963
964 rout_hdr = (struct ip6_rout_hdr *)p->payload;
965
966 /* Get next header type. */
967 nexth = &IP6_ROUT_NEXTH(rout_hdr);
968
969 /* Get the header length. */
970 hlen = 8 * (1 + rout_hdr->_hlen);
971
972 if ((p->len < 8) || (hlen > p->len)) {
973 LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_LEVEL_SERIOUS,
974 ("IPv6 options header (hlen %"U16_F") does not fit in first pbuf (len %"U16_F"), IPv6 packet dropped.\n",
975 hlen, p->len));
976 /* free (drop) packet pbufs */
977 pbuf_free(p);
978 IP6_STATS_INC(ip6.lenerr);
979 IP6_STATS_INC(ip6.drop);
980 goto ip6_input_cleanup;
981 }
982
983 /* Skip over this header. */
984 hlen_tot = (u16_t)(hlen_tot + hlen);
985
986 /* if segment left value is 0 in routing header, ignore the option */
987 if (IP6_ROUT_SEG_LEFT(rout_hdr)) {
988 /* The length field of routing option header must be even */
989 if (rout_hdr->_hlen & 0x1) {
990 /* Discard and send parameter field error */
991 icmp6_param_problem(p, ICMP6_PP_FIELD, &rout_hdr->_hlen);
992 LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: packet with invalid routing type dropped\n"));
993 pbuf_free(p);
994 IP6_STATS_INC(ip6.drop);
995 goto ip6_input_cleanup;
996 }
997
998 switch (IP6_ROUT_TYPE(rout_hdr))
999 {
1000 /* TODO: process routing by the type */
1001 case IP6_ROUT_TYPE2:
1002 break;
1003 case IP6_ROUT_RPL:
1004 break;
1005 default:
1006 /* Discard unrecognized routing type and send parameter field error */
1007 icmp6_param_problem(p, ICMP6_PP_FIELD, &IP6_ROUT_TYPE(rout_hdr));
1008 LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: packet with invalid routing type dropped\n"));
1009 pbuf_free(p);
1010 IP6_STATS_INC(ip6.drop);
1011 goto ip6_input_cleanup;
1012 }
1013 }
1014
1015 pbuf_remove_header(p, hlen);
1016 break;
1017 }
1018 case IP6_NEXTH_FRAGMENT:
1019 {
1020 struct ip6_frag_hdr *frag_hdr;
1021 LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: packet with Fragment header\n"));
1022
1023 frag_hdr = (struct ip6_frag_hdr *)p->payload;
1024
1025 /* Get next header type. */
1026 nexth = &IP6_FRAG_NEXTH(frag_hdr);
1027
1028 /* Fragment Header length. */
1029 hlen = 8;
1030
1031 /* Make sure this header fits in current pbuf. */
1032 if (hlen > p->len) {
1033 LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_LEVEL_SERIOUS,
1034 ("IPv6 options header (hlen %"U16_F") does not fit in first pbuf (len %"U16_F"), IPv6 packet dropped.\n",
1035 hlen, p->len));
1036 /* free (drop) packet pbufs */
1037 pbuf_free(p);
1038 IP6_FRAG_STATS_INC(ip6_frag.lenerr);
1039 IP6_FRAG_STATS_INC(ip6_frag.drop);
1040 goto ip6_input_cleanup;
1041 }
1042
1043 hlen_tot = (u16_t)(hlen_tot + hlen);
1044
1045 /* check payload length is multiple of 8 octets when mbit is set */
1046 if (IP6_FRAG_MBIT(frag_hdr) && (IP6H_PLEN(ip6hdr) & 0x7)) {
1047 /* ipv6 payload length is not multiple of 8 octets */
1048 icmp6_param_problem(p, ICMP6_PP_FIELD, LWIP_PACKED_CAST(const void *, &ip6hdr->_plen));
1049 LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: packet with invalid payload length dropped\n"));
1050 pbuf_free(p);
1051 IP6_STATS_INC(ip6.drop);
1052 goto ip6_input_cleanup;
1053 }
1054
1055 /* Offset == 0 and more_fragments == 0? */
1056 if ((frag_hdr->_fragment_offset &
1057 PP_HTONS(IP6_FRAG_OFFSET_MASK | IP6_FRAG_MORE_FLAG)) == 0) {
1058 /* This is a 1-fragment packet. Skip this header and continue. */
1059 pbuf_remove_header(p, hlen);
1060 } else {
1061 #if LWIP_IPV6_REASS
1062 /* reassemble the packet */
1063 ip_data.current_ip_header_tot_len = hlen_tot;
1064 p = ip6_reass(p);
1065 /* packet not fully reassembled yet? */
1066 if (p == NULL) {
1067 goto ip6_input_cleanup;
1068 }
1069
1070 /* Returned p point to IPv6 header.
1071 * Update all our variables and pointers and continue. */
1072 ip6hdr = (struct ip6_hdr *)p->payload;
1073 nexth = &IP6H_NEXTH(ip6hdr);
1074 hlen = hlen_tot = IP6_HLEN;
1075 pbuf_remove_header(p, IP6_HLEN);
1076
1077 #else /* LWIP_IPV6_REASS */
1078 /* free (drop) packet pbufs */
1079 LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: packet with Fragment header dropped (with LWIP_IPV6_REASS==0)\n"));
1080 pbuf_free(p);
1081 IP6_STATS_INC(ip6.opterr);
1082 IP6_STATS_INC(ip6.drop);
1083 goto ip6_input_cleanup;
1084 #endif /* LWIP_IPV6_REASS */
1085 }
1086 break;
1087 }
1088 default:
1089 goto options_done;
1090 }
1091
1092 if (*nexth == IP6_NEXTH_HOPBYHOP) {
1093 /* Hop-by-Hop header comes only as a first option */
1094 icmp6_param_problem(p, ICMP6_PP_HEADER, nexth);
1095 LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: packet with Hop-by-Hop options header dropped (only valid as a first option)\n"));
1096 pbuf_free(p);
1097 IP6_STATS_INC(ip6.drop);
1098 goto ip6_input_cleanup;
1099 }
1100 }
1101
1102 options_done:
1103
1104 /* send to upper layers */
1105 LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: \n"));
1106 ip6_debug_print(p);
1107 LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: p->len %"U16_F" p->tot_len %"U16_F"\n", p->len, p->tot_len));
1108
1109 ip_data.current_ip_header_tot_len = hlen_tot;
1110
1111 #if LWIP_RAW
1112 /* p points to IPv6 header again for raw_input. */
1113 pbuf_add_header_force(p, hlen_tot);
1114 /* raw input did not eat the packet? */
1115 raw_status = raw_input(p, inp);
1116 if (raw_status != RAW_INPUT_EATEN)
1117 {
1118 /* Point to payload. */
1119 pbuf_remove_header(p, hlen_tot);
1120 #else /* LWIP_RAW */
1121 {
1122 #endif /* LWIP_RAW */
1123 switch (*nexth) {
1124 case IP6_NEXTH_NONE:
1125 pbuf_free(p);
1126 break;
1127 #if LWIP_UDP
1128 case IP6_NEXTH_UDP:
1129 #if LWIP_UDPLITE
1130 case IP6_NEXTH_UDPLITE:
1131 #endif /* LWIP_UDPLITE */
1132 udp_input(p, inp);
1133 break;
1134 #endif /* LWIP_UDP */
1135 #if LWIP_TCP
1136 case IP6_NEXTH_TCP:
1137 tcp_input(p, inp);
1138 break;
1139 #endif /* LWIP_TCP */
1140 #if LWIP_ICMP6
1141 case IP6_NEXTH_ICMP6:
1142 icmp6_input(p, inp);
1143 break;
1144 #endif /* LWIP_ICMP */
1145 default:
1146 #if LWIP_RAW
1147 if (raw_status == RAW_INPUT_DELIVERED) {
1148 /* @todo: ipv6 mib in-delivers? */
1149 } else
1150 #endif /* LWIP_RAW */
1151 {
1152 #if LWIP_ICMP6
1153 /* p points to IPv6 header again for raw_input. */
1154 pbuf_add_header_force(p, hlen_tot);
1155 /* send ICMP parameter problem unless it was a multicast or ICMPv6 */
1156 if ((!ip6_addr_ismulticast(ip6_current_dest_addr())) &&
1157 (IP6H_NEXTH(ip6hdr) != IP6_NEXTH_ICMP6)) {
1158 icmp6_param_problem(p, ICMP6_PP_HEADER, nexth);
1159 }
1160 #endif /* LWIP_ICMP */
1161 LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("ip6_input: Unsupported transport protocol %"U16_F"\n", (u16_t)IP6H_NEXTH(ip6hdr)));
1162 IP6_STATS_INC(ip6.proterr);
1163 IP6_STATS_INC(ip6.drop);
1164 }
1165 pbuf_free(p);
1166 break;
1167 }
1168 }
1169
1170 ip6_input_cleanup:
1171 ip_data.current_netif = NULL;
1172 ip_data.current_input_netif = NULL;
1173 ip_data.current_ip6_header = NULL;
1174 ip_data.current_ip_header_tot_len = 0;
1175 ip6_addr_set_zero(ip6_current_src_addr());
1176 ip6_addr_set_zero(ip6_current_dest_addr());
1177
1178 return ERR_OK;
1179 }
1180
1181
1182 /**
1183 * Sends an IPv6 packet on a network interface. This function constructs
1184 * the IPv6 header. If the source IPv6 address is NULL, the IPv6 "ANY" address is
1185 * used as source (usually during network startup). If the source IPv6 address it
1186 * IP6_ADDR_ANY, the most appropriate IPv6 address of the outgoing network
1187 * interface is filled in as source address. If the destination IPv6 address is
1188 * LWIP_IP_HDRINCL, p is assumed to already include an IPv6 header and
1189 * p->payload points to it instead of the data.
1190 *
1191 * @param p the packet to send (p->payload points to the data, e.g. next
1192 protocol header; if dest == LWIP_IP_HDRINCL, p already includes an
1193 IPv6 header and p->payload points to that IPv6 header)
1194 * @param src the source IPv6 address to send from (if src == IP6_ADDR_ANY, an
1195 * IP address of the netif is selected and used as source address.
1196 * if src == NULL, IP6_ADDR_ANY is used as source) (src is possibly not
1197 * properly zoned)
1198 * @param dest the destination IPv6 address to send the packet to (possibly not
1199 * properly zoned)
1200 * @param hl the Hop Limit value to be set in the IPv6 header
1201 * @param tc the Traffic Class value to be set in the IPv6 header
1202 * @param nexth the Next Header to be set in the IPv6 header
1203 * @param netif the netif on which to send this packet
1204 * @return ERR_OK if the packet was sent OK
1205 * ERR_BUF if p doesn't have enough space for IPv6/LINK headers
1206 * returns errors returned by netif->output_ip6
1207 */
1208 err_t
1209 ip6_output_if(struct pbuf *p, const ip6_addr_t *src, const ip6_addr_t *dest,
1210 u8_t hl, u8_t tc,
1211 u8_t nexth, struct netif *netif)
1212 {
1213 const ip6_addr_t *src_used = src;
1214 if (dest != LWIP_IP_HDRINCL) {
1215 if (src != NULL && ip6_addr_isany(src)) {
1216 src_used = ip_2_ip6(ip6_select_source_address(netif, dest));
1217 if ((src_used == NULL) || ip6_addr_isany(src_used)) {
1218 /* No appropriate source address was found for this packet. */
1219 LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("ip6_output: No suitable source address for packet.\n"));
1220 IP6_STATS_INC(ip6.rterr);
1221 return ERR_RTE;
1222 }
1223 }
1224 }
1225 return ip6_output_if_src(p, src_used, dest, hl, tc, nexth, netif);
1226 }
1227
1228 /**
1229 * Same as ip6_output_if() but 'src' address is not replaced by netif address
1230 * when it is 'any'.
1231 */
1232 err_t
1233 ip6_output_if_src(struct pbuf *p, const ip6_addr_t *src, const ip6_addr_t *dest,
1234 u8_t hl, u8_t tc,
1235 u8_t nexth, struct netif *netif)
1236 {
1237 struct ip6_hdr *ip6hdr;
1238 ip6_addr_t dest_addr;
1239
1240 LWIP_ASSERT_CORE_LOCKED();
1241 LWIP_IP_CHECK_PBUF_REF_COUNT_FOR_TX(p);
1242
1243 /* Should the IPv6 header be generated or is it already included in p? */
1244 if (dest != LWIP_IP_HDRINCL) {
1245 #if LWIP_IPV6_SCOPES
1246 /* If the destination address is scoped but lacks a zone, add a zone now,
1247 * based on the outgoing interface. The lower layers (e.g., nd6) absolutely
1248 * require addresses to be properly zoned for correctness. In some cases,
1249 * earlier attempts will have been made to add a zone to the destination,
1250 * but this function is the only one that is called in all (other) cases,
1251 * so we must do this here. */
1252 if (ip6_addr_lacks_zone(dest, IP6_UNKNOWN)) {
1253 ip6_addr_copy(dest_addr, *dest);
1254 ip6_addr_assign_zone(&dest_addr, IP6_UNKNOWN, netif);
1255 dest = &dest_addr;
1256 }
1257 #endif /* LWIP_IPV6_SCOPES */
1258
1259 /* generate IPv6 header */
1260 if (pbuf_add_header(p, IP6_HLEN)) {
1261 LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("ip6_output: not enough room for IPv6 header in pbuf\n"));
1262 IP6_STATS_INC(ip6.err);
1263 return ERR_BUF;
1264 }
1265
1266 ip6hdr = (struct ip6_hdr *)p->payload;
1267 LWIP_ASSERT("check that first pbuf can hold struct ip6_hdr",
1268 (p->len >= sizeof(struct ip6_hdr)));
1269
1270 IP6H_HOPLIM_SET(ip6hdr, hl);
1271 IP6H_NEXTH_SET(ip6hdr, nexth);
1272
1273 /* dest cannot be NULL here */
1274 ip6_addr_copy_to_packed(ip6hdr->dest, *dest);
1275
1276 IP6H_VTCFL_SET(ip6hdr, 6, tc, 0);
1277 IP6H_PLEN_SET(ip6hdr, (u16_t)(p->tot_len - IP6_HLEN));
1278
1279 if (src == NULL) {
1280 src = IP6_ADDR_ANY6;
1281 }
1282 /* src cannot be NULL here */
1283 ip6_addr_copy_to_packed(ip6hdr->src, *src);
1284
1285 } else {
1286 /* IP header already included in p */
1287 ip6hdr = (struct ip6_hdr *)p->payload;
1288 ip6_addr_copy_from_packed(dest_addr, ip6hdr->dest);
1289 ip6_addr_assign_zone(&dest_addr, IP6_UNKNOWN, netif);
1290 dest = &dest_addr;
1291 }
1292
1293 IP6_STATS_INC(ip6.xmit);
1294
1295 LWIP_DEBUGF(IP6_DEBUG, ("ip6_output_if: %c%c%"U16_F"\n", netif->name[0], netif->name[1], (u16_t)netif->num));
1296 ip6_debug_print(p);
1297
1298 #if ENABLE_LOOPBACK
1299 {
1300 int i;
1301 #if !LWIP_HAVE_LOOPIF
1302 if (ip6_addr_isloopback(dest)) {
1303 return netif_loop_output(netif, p);
1304 }
1305 #endif /* !LWIP_HAVE_LOOPIF */
1306 for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) {
1307 if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i)) &&
1308 ip6_addr_cmp(dest, netif_ip6_addr(netif, i))) {
1309 /* Packet to self, enqueue it for loopback */
1310 LWIP_DEBUGF(IP6_DEBUG, ("netif_loop_output()\n"));
1311 return netif_loop_output(netif, p);
1312 }
1313 }
1314 }
1315 #if LWIP_MULTICAST_TX_OPTIONS
1316 if ((p->flags & PBUF_FLAG_MCASTLOOP) != 0) {
1317 netif_loop_output(netif, p);
1318 }
1319 #endif /* LWIP_MULTICAST_TX_OPTIONS */
1320 #endif /* ENABLE_LOOPBACK */
1321 #if LWIP_IPV6_FRAG
1322 /* don't fragment if interface has mtu set to 0 [loopif] */
1323 if (netif_mtu6(netif) && (p->tot_len > nd6_get_destination_mtu(dest, netif))) {
1324 return ip6_frag(p, netif, dest);
1325 }
1326 #endif /* LWIP_IPV6_FRAG */
1327
1328 LWIP_DEBUGF(IP6_DEBUG, ("netif->output_ip6()\n"));
1329 return netif->output_ip6(netif, p, dest);
1330 }
1331
1332 /**
1333 * Simple interface to ip6_output_if. It finds the outgoing network
1334 * interface and calls upon ip6_output_if to do the actual work.
1335 *
1336 * @param p the packet to send (p->payload points to the data, e.g. next
1337 protocol header; if dest == LWIP_IP_HDRINCL, p already includes an
1338 IPv6 header and p->payload points to that IPv6 header)
1339 * @param src the source IPv6 address to send from (if src == IP6_ADDR_ANY, an
1340 * IP address of the netif is selected and used as source address.
1341 * if src == NULL, IP6_ADDR_ANY is used as source)
1342 * @param dest the destination IPv6 address to send the packet to
1343 * @param hl the Hop Limit value to be set in the IPv6 header
1344 * @param tc the Traffic Class value to be set in the IPv6 header
1345 * @param nexth the Next Header to be set in the IPv6 header
1346 *
1347 * @return ERR_RTE if no route is found
1348 * see ip_output_if() for more return values
1349 */
1350 err_t
1351 ip6_output(struct pbuf *p, const ip6_addr_t *src, const ip6_addr_t *dest,
1352 u8_t hl, u8_t tc, u8_t nexth)
1353 {
1354 struct netif *netif;
1355 struct ip6_hdr *ip6hdr;
1356 ip6_addr_t src_addr, dest_addr;
1357
1358 LWIP_IP_CHECK_PBUF_REF_COUNT_FOR_TX(p);
1359
1360 #ifdef LOSCFG_NET_CONTAINER
1361 struct net_group *group = get_curr_process_net_group();
1362 #endif
1363
1364 if (dest != LWIP_IP_HDRINCL) {
1365 #ifdef LOSCFG_NET_CONTAINER
1366 netif = ip6_route(src, dest, group);
1367 #else
1368 netif = ip6_route(src, dest);
1369 #endif
1370 } else {
1371 /* IP header included in p, read addresses. */
1372 ip6hdr = (struct ip6_hdr *)p->payload;
1373 ip6_addr_copy_from_packed(src_addr, ip6hdr->src);
1374 ip6_addr_copy_from_packed(dest_addr, ip6hdr->dest);
1375 #ifdef LOSCFG_NET_CONTAINER
1376 netif = ip6_route(&src_addr, &dest_addr, group);
1377 #else
1378 netif = ip6_route(&src_addr, &dest_addr);
1379 #endif
1380 dest = &dest_addr;
1381 }
1382
1383 if (netif == NULL) {
1384 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",
1385 IP6_ADDR_BLOCK1(dest),
1386 IP6_ADDR_BLOCK2(dest),
1387 IP6_ADDR_BLOCK3(dest),
1388 IP6_ADDR_BLOCK4(dest),
1389 IP6_ADDR_BLOCK5(dest),
1390 IP6_ADDR_BLOCK6(dest),
1391 IP6_ADDR_BLOCK7(dest),
1392 IP6_ADDR_BLOCK8(dest)));
1393 IP6_STATS_INC(ip6.rterr);
1394 return ERR_RTE;
1395 }
1396
1397 return ip6_output_if(p, src, dest, hl, tc, nexth, netif);
1398 }
1399
1400
1401 #if LWIP_NETIF_USE_HINTS
1402 /** Like ip6_output, but takes and addr_hint pointer that is passed on to netif->addr_hint
1403 * before calling ip6_output_if.
1404 *
1405 * @param p the packet to send (p->payload points to the data, e.g. next
1406 protocol header; if dest == LWIP_IP_HDRINCL, p already includes an
1407 IPv6 header and p->payload points to that IPv6 header)
1408 * @param src the source IPv6 address to send from (if src == IP6_ADDR_ANY, an
1409 * IP address of the netif is selected and used as source address.
1410 * if src == NULL, IP6_ADDR_ANY is used as source)
1411 * @param dest the destination IPv6 address to send the packet to
1412 * @param hl the Hop Limit value to be set in the IPv6 header
1413 * @param tc the Traffic Class value to be set in the IPv6 header
1414 * @param nexth the Next Header to be set in the IPv6 header
1415 * @param netif_hint netif output hint pointer set to netif->hint before
1416 * calling ip_output_if()
1417 *
1418 * @return ERR_RTE if no route is found
1419 * see ip_output_if() for more return values
1420 */
1421 err_t
1422 ip6_output_hinted(struct pbuf *p, const ip6_addr_t *src, const ip6_addr_t *dest,
1423 u8_t hl, u8_t tc, u8_t nexth, struct netif_hint *netif_hint)
1424 {
1425 struct netif *netif;
1426 struct ip6_hdr *ip6hdr;
1427 ip6_addr_t src_addr, dest_addr;
1428 err_t err;
1429
1430 LWIP_IP_CHECK_PBUF_REF_COUNT_FOR_TX(p);
1431
1432 if (dest != LWIP_IP_HDRINCL) {
1433 netif = ip6_route(src, dest);
1434 } else {
1435 /* IP header included in p, read addresses. */
1436 ip6hdr = (struct ip6_hdr *)p->payload;
1437 ip6_addr_copy_from_packed(src_addr, ip6hdr->src);
1438 ip6_addr_copy_from_packed(dest_addr, ip6hdr->dest);
1439 netif = ip6_route(&src_addr, &dest_addr);
1440 dest = &dest_addr;
1441 }
1442
1443 if (netif == NULL) {
1444 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",
1445 IP6_ADDR_BLOCK1(dest),
1446 IP6_ADDR_BLOCK2(dest),
1447 IP6_ADDR_BLOCK3(dest),
1448 IP6_ADDR_BLOCK4(dest),
1449 IP6_ADDR_BLOCK5(dest),
1450 IP6_ADDR_BLOCK6(dest),
1451 IP6_ADDR_BLOCK7(dest),
1452 IP6_ADDR_BLOCK8(dest)));
1453 IP6_STATS_INC(ip6.rterr);
1454 return ERR_RTE;
1455 }
1456
1457 NETIF_SET_HINTS(netif, netif_hint);
1458 err = ip6_output_if(p, src, dest, hl, tc, nexth, netif);
1459 NETIF_RESET_HINTS(netif);
1460
1461 return err;
1462 }
1463 #endif /* LWIP_NETIF_USE_HINTS*/
1464
1465 #if LWIP_IPV6_MLD
1466 /**
1467 * Add a hop-by-hop options header with a router alert option and padding.
1468 *
1469 * Used by MLD when sending a Multicast listener report/done message.
1470 *
1471 * @param p the packet to which we will prepend the options header
1472 * @param nexth the next header protocol number (e.g. IP6_NEXTH_ICMP6)
1473 * @param value the value of the router alert option data (e.g. IP6_ROUTER_ALERT_VALUE_MLD)
1474 * @return ERR_OK if hop-by-hop header was added, ERR_* otherwise
1475 */
1476 err_t
1477 ip6_options_add_hbh_ra(struct pbuf *p, u8_t nexth, u8_t value)
1478 {
1479 u8_t *opt_data;
1480 u32_t offset = 0;
1481 struct ip6_hbh_hdr *hbh_hdr;
1482 struct ip6_opt_hdr *opt_hdr;
1483
1484 /* fixed 4 bytes for router alert option and 2 bytes padding */
1485 const u8_t hlen = (sizeof(struct ip6_opt_hdr) * 2) + IP6_ROUTER_ALERT_DLEN;
1486 /* Move pointer to make room for hop-by-hop options header. */
1487 if (pbuf_add_header(p, sizeof(struct ip6_hbh_hdr) + hlen)) {
1488 LWIP_DEBUGF(IP6_DEBUG, ("ip6_options: no space for options header\n"));
1489 IP6_STATS_INC(ip6.err);
1490 return ERR_BUF;
1491 }
1492
1493 /* Set fields of Hop-by-Hop header */
1494 hbh_hdr = (struct ip6_hbh_hdr *)p->payload;
1495 IP6_HBH_NEXTH(hbh_hdr) = nexth;
1496 hbh_hdr->_hlen = 0;
1497 offset = IP6_HBH_HLEN;
1498
1499 /* Set router alert options to Hop-by-Hop extended option header */
1500 opt_hdr = (struct ip6_opt_hdr *)((u8_t *)hbh_hdr + offset);
1501 IP6_OPT_TYPE(opt_hdr) = IP6_ROUTER_ALERT_OPTION;
1502 IP6_OPT_DLEN(opt_hdr) = IP6_ROUTER_ALERT_DLEN;
1503 offset += IP6_OPT_HLEN;
1504
1505 /* Set router alert option data */
1506 opt_data = (u8_t *)hbh_hdr + offset;
1507 opt_data[0] = value;
1508 opt_data[1] = 0;
1509 offset += IP6_OPT_DLEN(opt_hdr);
1510
1511 /* add 2 bytes padding to make 8 bytes Hop-by-Hop header length */
1512 opt_hdr = (struct ip6_opt_hdr *)((u8_t *)hbh_hdr + offset);
1513 IP6_OPT_TYPE(opt_hdr) = IP6_PADN_OPTION;
1514 IP6_OPT_DLEN(opt_hdr) = 0;
1515
1516 return ERR_OK;
1517 }
1518 #endif /* LWIP_IPV6_MLD */
1519
1520 #if IP6_DEBUG
1521 /* Print an IPv6 header by using LWIP_DEBUGF
1522 * @param p an IPv6 packet, p->payload pointing to the IPv6 header
1523 */
1524 void
1525 ip6_debug_print(struct pbuf *p)
1526 {
1527 struct ip6_hdr *ip6hdr = (struct ip6_hdr *)p->payload;
1528
1529 LWIP_DEBUGF(IP6_DEBUG, ("IPv6 header:\n"));
1530 LWIP_DEBUGF(IP6_DEBUG, ("+-------------------------------+\n"));
1531 LWIP_DEBUGF(IP6_DEBUG, ("| %2"U16_F" | %3"U16_F" | %7"U32_F" | (ver, class, flow)\n",
1532 IP6H_V(ip6hdr),
1533 IP6H_TC(ip6hdr),
1534 IP6H_FL(ip6hdr)));
1535 LWIP_DEBUGF(IP6_DEBUG, ("+-------------------------------+\n"));
1536 LWIP_DEBUGF(IP6_DEBUG, ("| %5"U16_F" | %3"U16_F" | %3"U16_F" | (plen, nexth, hopl)\n",
1537 IP6H_PLEN(ip6hdr),
1538 IP6H_NEXTH(ip6hdr),
1539 IP6H_HOPLIM(ip6hdr)));
1540 LWIP_DEBUGF(IP6_DEBUG, ("+-------------------------------+\n"));
1541 LWIP_DEBUGF(IP6_DEBUG, ("| %4"X32_F" | %4"X32_F" | %4"X32_F" | %4"X32_F" | (src)\n",
1542 IP6_ADDR_BLOCK1(&(ip6hdr->src)),
1543 IP6_ADDR_BLOCK2(&(ip6hdr->src)),
1544 IP6_ADDR_BLOCK3(&(ip6hdr->src)),
1545 IP6_ADDR_BLOCK4(&(ip6hdr->src))));
1546 LWIP_DEBUGF(IP6_DEBUG, ("| %4"X32_F" | %4"X32_F" | %4"X32_F" | %4"X32_F" |\n",
1547 IP6_ADDR_BLOCK5(&(ip6hdr->src)),
1548 IP6_ADDR_BLOCK6(&(ip6hdr->src)),
1549 IP6_ADDR_BLOCK7(&(ip6hdr->src)),
1550 IP6_ADDR_BLOCK8(&(ip6hdr->src))));
1551 LWIP_DEBUGF(IP6_DEBUG, ("+-------------------------------+\n"));
1552 LWIP_DEBUGF(IP6_DEBUG, ("| %4"X32_F" | %4"X32_F" | %4"X32_F" | %4"X32_F" | (dest)\n",
1553 IP6_ADDR_BLOCK1(&(ip6hdr->dest)),
1554 IP6_ADDR_BLOCK2(&(ip6hdr->dest)),
1555 IP6_ADDR_BLOCK3(&(ip6hdr->dest)),
1556 IP6_ADDR_BLOCK4(&(ip6hdr->dest))));
1557 LWIP_DEBUGF(IP6_DEBUG, ("| %4"X32_F" | %4"X32_F" | %4"X32_F" | %4"X32_F" |\n",
1558 IP6_ADDR_BLOCK5(&(ip6hdr->dest)),
1559 IP6_ADDR_BLOCK6(&(ip6hdr->dest)),
1560 IP6_ADDR_BLOCK7(&(ip6hdr->dest)),
1561 IP6_ADDR_BLOCK8(&(ip6hdr->dest))));
1562 LWIP_DEBUGF(IP6_DEBUG, ("+-------------------------------+\n"));
1563 }
1564 #endif /* IP6_DEBUG */
1565
1566 #endif /* LWIP_IPV6 */
1567