ReactOS 0.4.16-dev-570-g1868985
ip6.c
Go to the documentation of this file.
1
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
85struct netif *
86ip6_route(const ip6_addr_t *src, const ip6_addr_t *dest)
87{
88#if LWIP_SINGLE_NETIF
91#else /* LWIP_SINGLE_NETIF */
92 struct netif *netif;
93 s8_t i;
94
96
97 /* If single netif configuration, fast return. */
98 if ((netif_list != NULL) && (netif_list->next == NULL)) {
100 (ip6_addr_has_zone(dest) && !ip6_addr_test_zone(dest, netif_list))) {
101 return NULL;
102 }
103 return netif_list;
104 }
105
106#if LWIP_IPV6_SCOPES
107 /* Special processing for zoned destination addresses. This includes link-
108 * local unicast addresses and interface/link-local multicast addresses. Use
109 * the zone to find a matching netif. If the address is not zoned, then there
110 * is technically no "wrong" netif to choose, and we leave routing to other
111 * rules; in most cases this should be the scoped-source rule below. */
112 if (ip6_addr_has_zone(dest)) {
113 IP6_ADDR_ZONECHECK(dest);
114 /* Find a netif based on the zone. For custom mappings, one zone may map
115 * to multiple netifs, so find one that can actually send a packet. */
117 if (ip6_addr_test_zone(dest, netif) &&
119 return netif;
120 }
121 }
122 /* No matching netif found. Do no try to route to a different netif,
123 * as that would be a zone violation, resulting in any packets sent to
124 * that netif being dropped on output. */
125 return NULL;
126 }
127#endif /* LWIP_IPV6_SCOPES */
128
129 /* Special processing for scoped source and destination addresses. If we get
130 * here, the destination address does not have a zone, so either way we need
131 * to look at the source address, which may or may not have a zone. If it
132 * does, the zone is restrictive: there is (typically) only one matching
133 * netif for it, and we should avoid routing to any other netif as that would
134 * result in guaranteed zone violations. For scoped source addresses that do
135 * not have a zone, use (only) a netif that has that source address locally
136 * assigned. This case also applies to the loopback source address, which has
137 * an implied link-local scope. If only the destination address is scoped
138 * (but, again, not zoned), we still want to use only the source address to
139 * determine its zone because that's most likely what the user/application
140 * wants, regardless of whether the source address is scoped. Finally, some
141 * of this story also applies if scoping is disabled altogether. */
142#if LWIP_IPV6_SCOPES
143 if (ip6_addr_has_scope(dest, IP6_UNKNOWN) ||
144 ip6_addr_has_scope(src, IP6_UNICAST) ||
145#else /* LWIP_IPV6_SCOPES */
146 if (ip6_addr_islinklocal(dest) || ip6_addr_ismulticast_iflocal(dest) ||
147 ip6_addr_ismulticast_linklocal(dest) || ip6_addr_islinklocal(src) ||
148#endif /* LWIP_IPV6_SCOPES */
149 ip6_addr_isloopback(src)) {
150#if LWIP_IPV6_SCOPES
151 if (ip6_addr_has_zone(src)) {
152 /* Find a netif matching the source zone (relatively cheap). */
155 ip6_addr_test_zone(src, netif)) {
156 return netif;
157 }
158 }
159 } else
160#endif /* LWIP_IPV6_SCOPES */
161 {
162 /* Find a netif matching the source address (relatively expensive). */
165 continue;
166 }
167 for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) {
168 if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i)) &&
169 ip6_addr_zoneless_eq(src, netif_ip6_addr(netif, i))) {
170 return netif;
171 }
172 }
173 }
174 }
175 /* Again, do not use any other netif in this case, as that could result in
176 * zone boundary violations. */
177 return NULL;
178 }
179
180 /* We come here only if neither source nor destination is scoped. */
181 IP6_ADDR_ZONECHECK(src);
182
183#ifdef LWIP_HOOK_IP6_ROUTE
184 netif = LWIP_HOOK_IP6_ROUTE(src, dest);
185 if (netif != NULL) {
186 return netif;
187 }
188#endif
189
190 /* See if the destination subnet matches a configured address. In accordance
191 * with RFC 5942, dynamically configured addresses do not have an implied
192 * local subnet, and thus should be considered /128 assignments. However, as
193 * such, the destination address may still match a local address, and so we
194 * still need to check for exact matches here. By (lwIP) policy, statically
195 * configured addresses do always have an implied local /64 subnet. */
198 continue;
199 }
200 for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) {
201 if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i)) &&
202 ip6_addr_net_eq(dest, netif_ip6_addr(netif, i)) &&
203 (netif_ip6_addr_isstatic(netif, i) ||
204 ip6_addr_nethost_eq(dest, netif_ip6_addr(netif, i)))) {
205 return netif;
206 }
207 }
208 }
209
210 /* Get the netif for a suitable router-announced route. */
211 netif = nd6_find_route(dest);
212 if (netif != NULL) {
213 return netif;
214 }
215
216 /* Try with the netif that matches the source address. Given the earlier rule
217 * for scoped source addresses, this applies to unscoped addresses only. */
218 if (!ip6_addr_isany(src)) {
221 continue;
222 }
223 for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) {
224 if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i)) &&
225 ip6_addr_eq(src, netif_ip6_addr(netif, i))) {
226 return netif;
227 }
228 }
229 }
230 }
231
232#if LWIP_NETIF_LOOPBACK && !LWIP_HAVE_LOOPIF
233 /* loopif is disabled, loopback traffic is passed through any netif */
234 if (ip6_addr_isloopback(dest)) {
235 /* don't check for link on loopback traffic */
237 return netif_default;
238 }
239 /* default netif is not up, just use any netif for loopback traffic */
241 if (netif_is_up(netif)) {
242 return netif;
243 }
244 }
245 return NULL;
246 }
247#endif /* LWIP_NETIF_LOOPBACK && !LWIP_HAVE_LOOPIF */
248#endif /* !LWIP_SINGLE_NETIF */
249
250 /* no matching netif found, use default netif, if up */
252 return NULL;
253 }
254 return netif_default;
255}
256
282const ip_addr_t *
283ip6_select_source_address(struct netif *netif, const ip6_addr_t *dest)
284{
285 const ip_addr_t *best_addr;
286 const ip6_addr_t *cand_addr;
287 s8_t dest_scope, cand_scope;
288 s8_t best_scope = IP6_MULTICAST_SCOPE_RESERVED;
289 u8_t i, cand_pref, cand_bits;
290 u8_t best_pref = 0;
291 u8_t best_bits = 0;
292
293 /* Start by determining the scope of the given destination address. These
294 * tests are hopefully (roughly) in order of likeliness to match. */
295 if (ip6_addr_isglobal(dest)) {
296 dest_scope = IP6_MULTICAST_SCOPE_GLOBAL;
297 } else if (ip6_addr_islinklocal(dest) || ip6_addr_isloopback(dest)) {
298 dest_scope = IP6_MULTICAST_SCOPE_LINK_LOCAL;
299 } else if (ip6_addr_isuniquelocal(dest)) {
300 dest_scope = IP6_MULTICAST_SCOPE_ORGANIZATION_LOCAL;
301 } else if (ip6_addr_ismulticast(dest)) {
302 dest_scope = ip6_addr_multicast_scope(dest);
303 } else if (ip6_addr_issitelocal(dest)) {
304 dest_scope = IP6_MULTICAST_SCOPE_SITE_LOCAL;
305 } else {
306 /* no match, consider scope global */
307 dest_scope = IP6_MULTICAST_SCOPE_GLOBAL;
308 }
309
310 best_addr = NULL;
311
312 for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) {
313 /* Consider only valid (= preferred and deprecated) addresses. */
314 if (!ip6_addr_isvalid(netif_ip6_addr_state(netif, i))) {
315 continue;
316 }
317 /* Determine the scope of this candidate address. Same ordering idea. */
318 cand_addr = netif_ip6_addr(netif, i);
319 if (ip6_addr_isglobal(cand_addr)) {
320 cand_scope = IP6_MULTICAST_SCOPE_GLOBAL;
321 } else if (ip6_addr_islinklocal(cand_addr)) {
322 cand_scope = IP6_MULTICAST_SCOPE_LINK_LOCAL;
323 } else if (ip6_addr_isuniquelocal(cand_addr)) {
324 cand_scope = IP6_MULTICAST_SCOPE_ORGANIZATION_LOCAL;
325 } else if (ip6_addr_issitelocal(cand_addr)) {
326 cand_scope = IP6_MULTICAST_SCOPE_SITE_LOCAL;
327 } else {
328 /* no match, treat as low-priority global scope */
329 cand_scope = IP6_MULTICAST_SCOPE_RESERVEDF;
330 }
331 cand_pref = ip6_addr_ispreferred(netif_ip6_addr_state(netif, i));
332 /* @todo compute the actual common bits, for longest matching prefix. */
333 /* We cannot count on the destination address having a proper zone
334 * assignment, so do not compare zones in this case. */
335 cand_bits = ip6_addr_net_zoneless_eq(cand_addr, dest); /* just 1 or 0 for now */
336 if (cand_bits && ip6_addr_nethost_eq(cand_addr, dest)) {
337 return netif_ip_addr6(netif, i); /* Rule 1 */
338 }
339 if ((best_addr == NULL) || /* no alternative yet */
340 ((cand_scope < best_scope) && (cand_scope >= dest_scope)) ||
341 ((cand_scope > best_scope) && (best_scope < dest_scope)) || /* Rule 2 */
342 ((cand_scope == best_scope) && ((cand_pref > best_pref) || /* Rule 3 */
343 ((cand_pref == best_pref) && (cand_bits > best_bits))))) { /* Rule 8 */
344 /* We found a new "winning" candidate. */
345 best_addr = netif_ip_addr6(netif, i);
346 best_scope = cand_scope;
347 best_pref = cand_pref;
348 best_bits = cand_bits;
349 }
350 }
351
352 return best_addr; /* may be NULL */
353}
354
355#if LWIP_IPV6_FORWARD
365static void
366ip6_forward(struct pbuf *p, struct ip6_hdr *iphdr, struct netif *inp)
367{
368 struct netif *netif;
369
370 /* do not forward link-local or loopback addresses */
371 if (ip6_addr_islinklocal(ip6_current_dest_addr()) ||
372 ip6_addr_isloopback(ip6_current_dest_addr())) {
373 LWIP_DEBUGF(IP6_DEBUG, ("ip6_forward: not forwarding link-local address.\n"));
374 IP6_STATS_INC(ip6.rterr);
375 IP6_STATS_INC(ip6.drop);
376 return;
377 }
378
379 /* Find network interface where to forward this IP packet to. */
380 netif = ip6_route(IP6_ADDR_ANY6, ip6_current_dest_addr());
381 if (netif == NULL) {
382 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",
383 IP6_ADDR_BLOCK1(ip6_current_dest_addr()),
384 IP6_ADDR_BLOCK2(ip6_current_dest_addr()),
385 IP6_ADDR_BLOCK3(ip6_current_dest_addr()),
386 IP6_ADDR_BLOCK4(ip6_current_dest_addr()),
387 IP6_ADDR_BLOCK5(ip6_current_dest_addr()),
388 IP6_ADDR_BLOCK6(ip6_current_dest_addr()),
389 IP6_ADDR_BLOCK7(ip6_current_dest_addr()),
390 IP6_ADDR_BLOCK8(ip6_current_dest_addr())));
391#if LWIP_ICMP6
392 /* Don't send ICMP messages in response to ICMP messages */
393 if (IP6H_NEXTH(iphdr) != IP6_NEXTH_ICMP6) {
394 icmp6_dest_unreach(p, ICMP6_DUR_NO_ROUTE);
395 }
396#endif /* LWIP_ICMP6 */
397 IP6_STATS_INC(ip6.rterr);
398 IP6_STATS_INC(ip6.drop);
399 return;
400 }
401#if LWIP_IPV6_SCOPES
402 /* Do not forward packets with a zoned (e.g., link-local) source address
403 * outside of their zone. We determined the zone a bit earlier, so we know
404 * that the address is properly zoned here, so we can safely use has_zone.
405 * Also skip packets with a loopback source address (link-local implied). */
406 if ((ip6_addr_has_zone(ip6_current_src_addr()) &&
407 !ip6_addr_test_zone(ip6_current_src_addr(), netif)) ||
408 ip6_addr_isloopback(ip6_current_src_addr())) {
409 LWIP_DEBUGF(IP6_DEBUG, ("ip6_forward: not forwarding packet beyond its source address zone.\n"));
410 IP6_STATS_INC(ip6.rterr);
411 IP6_STATS_INC(ip6.drop);
412 return;
413 }
414#endif /* LWIP_IPV6_SCOPES */
415 /* Do not forward packets onto the same network interface on which
416 * they arrived. */
417 if (netif == inp) {
418 LWIP_DEBUGF(IP6_DEBUG, ("ip6_forward: not bouncing packets back on incoming interface.\n"));
419 IP6_STATS_INC(ip6.rterr);
420 IP6_STATS_INC(ip6.drop);
421 return;
422 }
423
424 /* decrement HL */
425 IP6H_HOPLIM_SET(iphdr, IP6H_HOPLIM(iphdr) - 1);
426 /* send ICMP6 if HL == 0 */
427 if (IP6H_HOPLIM(iphdr) == 0) {
428#if LWIP_ICMP6
429 /* Don't send ICMP messages in response to ICMP messages */
430 if (IP6H_NEXTH(iphdr) != IP6_NEXTH_ICMP6) {
431 icmp6_time_exceeded(p, ICMP6_TE_HL);
432 }
433#endif /* LWIP_ICMP6 */
434 IP6_STATS_INC(ip6.drop);
435 return;
436 }
437
438 if (netif->mtu && (p->tot_len > netif->mtu)) {
439#if LWIP_ICMP6
440 /* Don't send ICMP messages in response to ICMP messages */
441 if (IP6H_NEXTH(iphdr) != IP6_NEXTH_ICMP6) {
442 icmp6_packet_too_big(p, netif->mtu);
443 }
444#endif /* LWIP_ICMP6 */
445 IP6_STATS_INC(ip6.drop);
446 return;
447 }
448
449 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",
450 IP6_ADDR_BLOCK1(ip6_current_dest_addr()),
451 IP6_ADDR_BLOCK2(ip6_current_dest_addr()),
452 IP6_ADDR_BLOCK3(ip6_current_dest_addr()),
453 IP6_ADDR_BLOCK4(ip6_current_dest_addr()),
454 IP6_ADDR_BLOCK5(ip6_current_dest_addr()),
455 IP6_ADDR_BLOCK6(ip6_current_dest_addr()),
456 IP6_ADDR_BLOCK7(ip6_current_dest_addr()),
457 IP6_ADDR_BLOCK8(ip6_current_dest_addr())));
458
459 /* transmit pbuf on chosen interface */
460 netif->output_ip6(netif, p, ip6_current_dest_addr());
461 IP6_STATS_INC(ip6.fw);
462 IP6_STATS_INC(ip6.xmit);
463 return;
464}
465#endif /* LWIP_IPV6_FORWARD */
466
468static int
469ip6_input_accept(struct netif *netif)
470{
471 /* interface is up? */
472 if (netif_is_up(netif)) {
473 u8_t i;
474 /* unicast to this interface address? address configured? */
475 /* If custom scopes are used, the destination zone will be tested as
476 * part of the local-address comparison, but we need to test the source
477 * scope as well (e.g., is this interface on the same link?). */
478 for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) {
479 if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i)) &&
480 ip6_addr_eq(ip6_current_dest_addr(), netif_ip6_addr(netif, i))
481#if IPV6_CUSTOM_SCOPES
482 && (!ip6_addr_has_zone(ip6_current_src_addr()) ||
483 ip6_addr_test_zone(ip6_current_src_addr(), netif))
484#endif /* IPV6_CUSTOM_SCOPES */
485 ) {
486 /* accept on this netif */
487 return 1;
488 }
489 }
490 }
491 return 0;
492}
493
508err_t
509ip6_input(struct pbuf *p, struct netif *inp)
510{
511 struct ip6_hdr *ip6hdr;
512 struct netif *netif;
513 const u8_t *nexth;
514 u16_t hlen, hlen_tot; /* the current header length */
515#if 0 /*IP_ACCEPT_LINK_LAYER_ADDRESSING*/
516 @todo
517 int check_ip_src=1;
518#endif /* IP_ACCEPT_LINK_LAYER_ADDRESSING */
519#if LWIP_RAW
520 raw_input_state_t raw_status;
521#endif /* LWIP_RAW */
522
524
525 IP6_STATS_INC(ip6.recv);
526
527 /* identify the IP header */
528 ip6hdr = (struct ip6_hdr *)p->payload;
529 if (IP6H_V(ip6hdr) != 6) {
530 LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_LEVEL_WARNING, ("IPv6 packet dropped due to bad version number %"U32_F"\n",
531 IP6H_V(ip6hdr)));
532 pbuf_free(p);
533 IP6_STATS_INC(ip6.err);
534 IP6_STATS_INC(ip6.drop);
535 return ERR_OK;
536 }
537
538#ifdef LWIP_HOOK_IP6_INPUT
539 if (LWIP_HOOK_IP6_INPUT(p, inp)) {
540 /* the packet has been eaten */
541 return ERR_OK;
542 }
543#endif
544
545 /* header length exceeds first pbuf length, or ip length exceeds total pbuf length? */
546 if ((IP6_HLEN > p->len) || (IP6H_PLEN(ip6hdr) > (p->tot_len - IP6_HLEN))) {
547 if (IP6_HLEN > p->len) {
549 ("IPv6 header (len %"U16_F") does not fit in first pbuf (len %"U16_F"), IP packet dropped.\n",
550 (u16_t)IP6_HLEN, p->len));
551 }
552 if ((IP6H_PLEN(ip6hdr) + IP6_HLEN) > p->tot_len) {
554 ("IPv6 (plen %"U16_F") is longer than pbuf (len %"U16_F"), IP packet dropped.\n",
555 (u16_t)(IP6H_PLEN(ip6hdr) + IP6_HLEN), p->tot_len));
556 }
557 /* free (drop) packet pbufs */
558 pbuf_free(p);
559 IP6_STATS_INC(ip6.lenerr);
560 IP6_STATS_INC(ip6.drop);
561 return ERR_OK;
562 }
563
564 /* Trim pbuf. This should have been done at the netif layer,
565 * but we'll do it anyway just to be sure that its done. */
566 pbuf_realloc(p, (u16_t)(IP6_HLEN + IP6H_PLEN(ip6hdr)));
567
568 /* copy IP addresses to aligned ip6_addr_t */
569 ip_addr_copy_from_ip6_packed(ip_data.current_iphdr_dest, ip6hdr->dest);
570 ip_addr_copy_from_ip6_packed(ip_data.current_iphdr_src, ip6hdr->src);
571
572 /* Don't accept virtual IPv4 mapped IPv6 addresses.
573 * Don't accept multicast source addresses. */
574 if (ip6_addr_isipv4mappedipv6(ip_2_ip6(&ip_data.current_iphdr_dest)) ||
575 ip6_addr_isipv4mappedipv6(ip_2_ip6(&ip_data.current_iphdr_src)) ||
576 ip6_addr_ismulticast(ip_2_ip6(&ip_data.current_iphdr_src))) {
577 /* free (drop) packet pbufs */
578 pbuf_free(p);
579 IP6_STATS_INC(ip6.err);
580 IP6_STATS_INC(ip6.drop);
581 return ERR_OK;
582 }
583
584 /* Set the appropriate zone identifier on the addresses. */
585 ip6_addr_assign_zone(ip_2_ip6(&ip_data.current_iphdr_dest), IP6_UNKNOWN, inp);
586 ip6_addr_assign_zone(ip_2_ip6(&ip_data.current_iphdr_src), IP6_UNICAST, inp);
587
588 /* current header pointer. */
589 ip_data.current_ip6_header = ip6hdr;
590
591 /* In netif, used in case we need to send ICMPv6 packets back. */
592 ip_data.current_netif = inp;
593 ip_data.current_input_netif = inp;
594
595 /* match packet against an interface, i.e. is this packet for us? */
596 if (ip6_addr_ismulticast(ip6_current_dest_addr())) {
597 /* Always joined to multicast if-local and link-local all-nodes group. */
598 if (ip6_addr_isallnodes_iflocal(ip6_current_dest_addr()) ||
599 ip6_addr_isallnodes_linklocal(ip6_current_dest_addr())) {
600 netif = inp;
601 }
602#if LWIP_IPV6_MLD
603 else if (mld6_lookfor_group(inp, ip6_current_dest_addr())) {
604 netif = inp;
605 }
606#else /* LWIP_IPV6_MLD */
607 else if (ip6_addr_issolicitednode(ip6_current_dest_addr())) {
608 u8_t i;
609 /* Filter solicited node packets when MLD is not enabled
610 * (for Neighbor discovery). */
611 netif = NULL;
612 for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) {
613 if (ip6_addr_isvalid(netif_ip6_addr_state(inp, i)) &&
614 ip6_addr_solicitednode_eq(ip6_current_dest_addr(), netif_ip6_addr(inp, i))) {
615 netif = inp;
616 LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: solicited node packet accepted on interface %c%c\n",
617 netif->name[0], netif->name[1]));
618 break;
619 }
620 }
621 }
622#endif /* LWIP_IPV6_MLD */
623 else {
624 netif = NULL;
625 }
626 } else {
627 /* start trying with inp. if that's not acceptable, start walking the
628 list of configured netifs. */
629 if (ip6_input_accept(inp)) {
630 netif = inp;
631 } else {
632 netif = NULL;
633#if !IPV6_CUSTOM_SCOPES
634 /* Shortcut: stop looking for other interfaces if either the source or
635 * the destination has a scope constrained to this interface. Custom
636 * scopes may break the 1:1 link/interface mapping, however. */
637 if (ip6_addr_islinklocal(ip6_current_dest_addr()) ||
638 ip6_addr_islinklocal(ip6_current_src_addr())) {
639 goto netif_found;
640 }
641#endif /* !IPV6_CUSTOM_SCOPES */
642#if !LWIP_NETIF_LOOPBACK || LWIP_HAVE_LOOPIF
643 /* The loopback address is to be considered link-local. Packets to it
644 * should be dropped on other interfaces, as per RFC 4291 Sec. 2.5.3.
645 * Its implied scope means packets *from* the loopback address should
646 * not be accepted on other interfaces, either. These requirements
647 * cannot be implemented in the case that loopback traffic is sent
648 * across a non-loopback interface, however. */
649 if (ip6_addr_isloopback(ip6_current_dest_addr()) ||
650 ip6_addr_isloopback(ip6_current_src_addr())) {
651 goto netif_found;
652 }
653#endif /* !LWIP_NETIF_LOOPBACK || LWIP_HAVE_LOOPIF */
654#if !LWIP_SINGLE_NETIF
656 if (netif == inp) {
657 /* we checked that before already */
658 continue;
659 }
660 if (ip6_input_accept(netif)) {
661 break;
662 }
663 }
664#endif /* !LWIP_SINGLE_NETIF */
665 }
666netif_found:
667 LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: packet accepted on interface %c%c\n",
668 netif ? netif->name[0] : 'X', netif? netif->name[1] : 'X'));
669 }
670
671 /* "::" packet source address? (used in duplicate address detection) */
672 if (ip6_addr_isany(ip6_current_src_addr()) &&
673 (!ip6_addr_issolicitednode(ip6_current_dest_addr()))) {
674 /* packet source is not valid */
675 /* free (drop) packet pbufs */
676 LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: packet with src ANY_ADDRESS dropped\n"));
677 pbuf_free(p);
678 IP6_STATS_INC(ip6.drop);
679 goto ip6_input_cleanup;
680 }
681
682 /* packet not for us? */
683 if (netif == NULL) {
684 /* packet not for us, route or discard */
685 LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_TRACE, ("ip6_input: packet not for us.\n"));
686#if LWIP_IPV6_FORWARD
687 /* non-multicast packet? */
688 if (!ip6_addr_ismulticast(ip6_current_dest_addr())) {
689 /* try to forward IP packet on (other) interfaces */
690 ip6_forward(p, ip6hdr, inp);
691 }
692#endif /* LWIP_IPV6_FORWARD */
693 pbuf_free(p);
694 goto ip6_input_cleanup;
695 }
696
697 /* current netif pointer. */
698 ip_data.current_netif = netif;
699
700 /* Save next header type. */
701 nexth = &IP6H_NEXTH(ip6hdr);
702
703 /* Init header length. */
704 hlen = hlen_tot = IP6_HLEN;
705
706 LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: \n"));
707 ip6_debug_print(p);
708 LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: p->len %"U16_F" p->tot_len %"U16_F"\n", p->len, p->tot_len));
709
710 /* Move to payload. */
712
713 /* Process known option extension headers, if present. */
714 while (*nexth != IP6_NEXTH_NONE)
715 {
716 switch (*nexth) {
718 {
719 s32_t opt_offset;
720 struct ip6_hbh_hdr *hbh_hdr;
721 struct ip6_opt_hdr *opt_hdr;
722 LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: packet with Hop-by-Hop options header\n"));
723
724 /* Get and check the header length, while staying in packet bounds. */
725 hbh_hdr = (struct ip6_hbh_hdr *)p->payload;
726
727 /* Get next header type. */
728 nexth = &IP6_HBH_NEXTH(hbh_hdr);
729
730 /* Get the header length. */
731 hlen = (u16_t)(8 * (1 + hbh_hdr->_hlen));
732
733 if ((p->len < 8) || (hlen > p->len)) {
735 ("IPv6 options header (hlen %"U16_F") does not fit in first pbuf (len %"U16_F"), IPv6 packet dropped.\n",
736 hlen, p->len));
737 /* free (drop) packet pbufs */
738 pbuf_free(p);
739 IP6_STATS_INC(ip6.lenerr);
740 IP6_STATS_INC(ip6.drop);
741 goto ip6_input_cleanup;
742 }
743
744 hlen_tot = (u16_t)(hlen_tot + hlen);
745
746 /* The extended option header starts right after Hop-by-Hop header. */
747 opt_offset = IP6_HBH_HLEN;
748 while (opt_offset < hlen)
749 {
750 s32_t opt_dlen = 0;
751
752 opt_hdr = (struct ip6_opt_hdr *)((u8_t *)hbh_hdr + opt_offset);
753
754 switch (IP6_OPT_TYPE(opt_hdr)) {
755 /* @todo: process IPV6 Hop-by-Hop option data */
756 case IP6_PAD1_OPTION:
757 /* PAD1 option doesn't have length and value field */
758 opt_dlen = -1;
759 break;
760 case IP6_PADN_OPTION:
761 opt_dlen = IP6_OPT_DLEN(opt_hdr);
762 break;
764 opt_dlen = IP6_OPT_DLEN(opt_hdr);
765 break;
766 case IP6_JUMBO_OPTION:
767 opt_dlen = IP6_OPT_DLEN(opt_hdr);
768 break;
769 default:
770 /* Check 2 MSB of Hop-by-Hop header type. */
771 switch (IP6_OPT_TYPE_ACTION(opt_hdr)) {
772 case 1:
773 /* Discard the packet. */
774 LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: packet with invalid Hop-by-Hop option type dropped.\n"));
775 pbuf_free(p);
776 IP6_STATS_INC(ip6.drop);
777 goto ip6_input_cleanup;
778 case 2:
779 /* Send ICMP Parameter Problem */
780 icmp6_param_problem(p, ICMP6_PP_OPTION, opt_hdr);
781 LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: packet with invalid Hop-by-Hop option type dropped.\n"));
782 pbuf_free(p);
783 IP6_STATS_INC(ip6.drop);
784 goto ip6_input_cleanup;
785 case 3:
786 /* Send ICMP Parameter Problem if destination address is not a multicast address */
787 if (!ip6_addr_ismulticast(ip6_current_dest_addr())) {
788 icmp6_param_problem(p, ICMP6_PP_OPTION, opt_hdr);
789 }
790 LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: packet with invalid Hop-by-Hop option type dropped.\n"));
791 pbuf_free(p);
792 IP6_STATS_INC(ip6.drop);
793 goto ip6_input_cleanup;
794 default:
795 /* Skip over this option. */
796 opt_dlen = IP6_OPT_DLEN(opt_hdr);
797 break;
798 }
799 break;
800 }
801
802 /* Adjust the offset to move to the next extended option header */
803 opt_offset = opt_offset + IP6_OPT_HLEN + opt_dlen;
804 }
805 pbuf_remove_header(p, hlen);
806 break;
807 }
809 {
810 s32_t opt_offset;
811 struct ip6_dest_hdr *dest_hdr;
812 struct ip6_opt_hdr *opt_hdr;
813 LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: packet with Destination options header\n"));
814
815 dest_hdr = (struct ip6_dest_hdr *)p->payload;
816
817 /* Get next header type. */
818 nexth = &IP6_DEST_NEXTH(dest_hdr);
819
820 /* Get the header length. */
821 hlen = 8 * (1 + dest_hdr->_hlen);
822 if ((p->len < 8) || (hlen > p->len)) {
824 ("IPv6 options header (hlen %"U16_F") does not fit in first pbuf (len %"U16_F"), IPv6 packet dropped.\n",
825 hlen, p->len));
826 /* free (drop) packet pbufs */
827 pbuf_free(p);
828 IP6_STATS_INC(ip6.lenerr);
829 IP6_STATS_INC(ip6.drop);
830 goto ip6_input_cleanup;
831 }
832
833 hlen_tot = (u16_t)(hlen_tot + hlen);
834
835 /* The extended option header starts right after Destination header. */
836 opt_offset = IP6_DEST_HLEN;
837 while (opt_offset < hlen)
838 {
839 s32_t opt_dlen = 0;
840
841 opt_hdr = (struct ip6_opt_hdr *)((u8_t *)dest_hdr + opt_offset);
842
843 switch (IP6_OPT_TYPE(opt_hdr))
844 {
845 /* @todo: process IPV6 Destination option data */
846 case IP6_PAD1_OPTION:
847 /* PAD1 option deosn't have length and value field */
848 opt_dlen = -1;
849 break;
850 case IP6_PADN_OPTION:
851 opt_dlen = IP6_OPT_DLEN(opt_hdr);
852 break;
854 opt_dlen = IP6_OPT_DLEN(opt_hdr);
855 break;
856 case IP6_JUMBO_OPTION:
857 opt_dlen = IP6_OPT_DLEN(opt_hdr);
858 break;
860 opt_dlen = IP6_OPT_DLEN(opt_hdr);
861 break;
862 default:
863 /* Check 2 MSB of Destination header type. */
864 switch (IP6_OPT_TYPE_ACTION(opt_hdr))
865 {
866 case 1:
867 /* Discard the packet. */
868 LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: packet with invalid destination option type dropped.\n"));
869 pbuf_free(p);
870 IP6_STATS_INC(ip6.drop);
871 goto ip6_input_cleanup;
872 case 2:
873 /* Send ICMP Parameter Problem */
874 icmp6_param_problem(p, ICMP6_PP_OPTION, opt_hdr);
875 LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: packet with invalid destination option type dropped.\n"));
876 pbuf_free(p);
877 IP6_STATS_INC(ip6.drop);
878 goto ip6_input_cleanup;
879 case 3:
880 /* Send ICMP Parameter Problem if destination address is not a multicast address */
881 if (!ip6_addr_ismulticast(ip6_current_dest_addr())) {
882 icmp6_param_problem(p, ICMP6_PP_OPTION, opt_hdr);
883 }
884 LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: packet with invalid destination option type dropped.\n"));
885 pbuf_free(p);
886 IP6_STATS_INC(ip6.drop);
887 goto ip6_input_cleanup;
888 default:
889 /* Skip over this option. */
890 opt_dlen = IP6_OPT_DLEN(opt_hdr);
891 break;
892 }
893 break;
894 }
895
896 /* Adjust the offset to move to the next extended option header */
897 opt_offset = opt_offset + IP6_OPT_HLEN + opt_dlen;
898 }
899
900 pbuf_remove_header(p, hlen);
901 break;
902 }
904 {
905 struct ip6_rout_hdr *rout_hdr;
906 LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: packet with Routing header\n"));
907
908 rout_hdr = (struct ip6_rout_hdr *)p->payload;
909
910 /* Get next header type. */
911 nexth = &IP6_ROUT_NEXTH(rout_hdr);
912
913 /* Get the header length. */
914 hlen = 8 * (1 + rout_hdr->_hlen);
915
916 if ((p->len < 8) || (hlen > p->len)) {
918 ("IPv6 options header (hlen %"U16_F") does not fit in first pbuf (len %"U16_F"), IPv6 packet dropped.\n",
919 hlen, p->len));
920 /* free (drop) packet pbufs */
921 pbuf_free(p);
922 IP6_STATS_INC(ip6.lenerr);
923 IP6_STATS_INC(ip6.drop);
924 goto ip6_input_cleanup;
925 }
926
927 /* Skip over this header. */
928 hlen_tot = (u16_t)(hlen_tot + hlen);
929
930 /* if segment left value is 0 in routing header, ignore the option */
931 if (IP6_ROUT_SEG_LEFT(rout_hdr)) {
932 /* The length field of routing option header must be even */
933 if (rout_hdr->_hlen & 0x1) {
934 /* Discard and send parameter field error */
935 icmp6_param_problem(p, ICMP6_PP_FIELD, &rout_hdr->_hlen);
936 LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: packet with invalid routing type dropped\n"));
937 pbuf_free(p);
938 IP6_STATS_INC(ip6.drop);
939 goto ip6_input_cleanup;
940 }
941
942 switch (IP6_ROUT_TYPE(rout_hdr))
943 {
944 /* TODO: process routing by the type */
945 case IP6_ROUT_TYPE2:
946 break;
947 case IP6_ROUT_RPL:
948 break;
949 default:
950 /* Discard unrecognized routing type and send parameter field error */
951 icmp6_param_problem(p, ICMP6_PP_FIELD, &IP6_ROUT_TYPE(rout_hdr));
952 LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: packet with invalid routing type dropped\n"));
953 pbuf_free(p);
954 IP6_STATS_INC(ip6.drop);
955 goto ip6_input_cleanup;
956 }
957 }
958
959 pbuf_remove_header(p, hlen);
960 break;
961 }
963 {
964 struct ip6_frag_hdr *frag_hdr;
965 LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: packet with Fragment header\n"));
966
967 frag_hdr = (struct ip6_frag_hdr *)p->payload;
968
969 /* Get next header type. */
970 nexth = &IP6_FRAG_NEXTH(frag_hdr);
971
972 /* Fragment Header length. */
973 hlen = 8;
974
975 /* Make sure this header fits in current pbuf. */
976 if (hlen > p->len) {
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);
984 goto ip6_input_cleanup;
985 }
986
987 hlen_tot = (u16_t)(hlen_tot + hlen);
988
989 /* check payload length is multiple of 8 octets when mbit is set */
990 if (IP6_FRAG_MBIT(frag_hdr) && (IP6H_PLEN(ip6hdr) & 0x7)) {
991 /* ipv6 payload length is not multiple of 8 octets */
992 icmp6_param_problem(p, ICMP6_PP_FIELD, LWIP_PACKED_CAST(const void *, &ip6hdr->_plen));
993 LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: packet with invalid payload length dropped\n"));
994 pbuf_free(p);
995 IP6_STATS_INC(ip6.drop);
996 goto ip6_input_cleanup;
997 }
998
999 /* Offset == 0 and more_fragments == 0? */
1000 if ((frag_hdr->_fragment_offset &
1002 /* This is a 1-fragment packet. Skip this header and continue. */
1003 pbuf_remove_header(p, hlen);
1004 } else {
1005#if LWIP_IPV6_REASS
1006 /* reassemble the packet */
1007 ip_data.current_ip_header_tot_len = hlen_tot;
1008 p = ip6_reass(p);
1009 /* packet not fully reassembled yet? */
1010 if (p == NULL) {
1011 goto ip6_input_cleanup;
1012 }
1013
1014 /* Returned p point to IPv6 header.
1015 * Update all our variables and pointers and continue. */
1016 ip6hdr = (struct ip6_hdr *)p->payload;
1017 nexth = &IP6H_NEXTH(ip6hdr);
1018 hlen = hlen_tot = IP6_HLEN;
1020
1021#else /* LWIP_IPV6_REASS */
1022 /* free (drop) packet pbufs */
1023 LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: packet with Fragment header dropped (with LWIP_IPV6_REASS==0)\n"));
1024 pbuf_free(p);
1025 IP6_STATS_INC(ip6.opterr);
1026 IP6_STATS_INC(ip6.drop);
1027 goto ip6_input_cleanup;
1028#endif /* LWIP_IPV6_REASS */
1029 }
1030 break;
1031 }
1032 default:
1033 goto options_done;
1034 }
1035
1036 if (*nexth == IP6_NEXTH_HOPBYHOP) {
1037 /* Hop-by-Hop header comes only as a first option */
1038 icmp6_param_problem(p, ICMP6_PP_HEADER, nexth);
1039 LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: packet with Hop-by-Hop options header dropped (only valid as a first option)\n"));
1040 pbuf_free(p);
1041 IP6_STATS_INC(ip6.drop);
1042 goto ip6_input_cleanup;
1043 }
1044 }
1045
1046options_done:
1047
1048 /* send to upper layers */
1049 ip_data.current_ip_header_tot_len = hlen_tot;
1050
1051#if LWIP_RAW
1052 /* p points to IPv6 header again for raw_input. */
1053 pbuf_add_header_force(p, hlen_tot);
1054 /* raw input did not eat the packet? */
1055 raw_status = raw_input(p, inp);
1056 if (raw_status != RAW_INPUT_EATEN)
1057 {
1058 /* Point to payload. */
1059 pbuf_remove_header(p, hlen_tot);
1060#else /* LWIP_RAW */
1061 {
1062#endif /* LWIP_RAW */
1063 switch (*nexth) {
1064 case IP6_NEXTH_NONE:
1065 pbuf_free(p);
1066 break;
1067#if LWIP_UDP
1068 case IP6_NEXTH_UDP:
1069#if LWIP_UDPLITE
1070 case IP6_NEXTH_UDPLITE:
1071#endif /* LWIP_UDPLITE */
1072 udp_input(p, inp);
1073 break;
1074#endif /* LWIP_UDP */
1075#if LWIP_TCP
1076 case IP6_NEXTH_TCP:
1077 tcp_input(p, inp);
1078 break;
1079#endif /* LWIP_TCP */
1080#if LWIP_ICMP6
1081 case IP6_NEXTH_ICMP6:
1082 icmp6_input(p, inp);
1083 break;
1084#endif /* LWIP_ICMP */
1085 default:
1086#if LWIP_RAW
1087 if (raw_status == RAW_INPUT_DELIVERED) {
1088 /* @todo: ipv6 mib in-delivers? */
1089 } else
1090#endif /* LWIP_RAW */
1091 {
1092#if LWIP_ICMP6
1093 /* p points to IPv6 header again for raw_input. */
1094 pbuf_add_header_force(p, hlen_tot);
1095 /* send ICMP parameter problem unless it was a multicast or ICMPv6 */
1096 if ((!ip6_addr_ismulticast(ip6_current_dest_addr())) &&
1097 (IP6H_NEXTH(ip6hdr) != IP6_NEXTH_ICMP6)) {
1098 icmp6_param_problem(p, ICMP6_PP_HEADER, nexth);
1099 }
1100#endif /* LWIP_ICMP */
1101 LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("ip6_input: Unsupported transport protocol %"U16_F"\n", (u16_t)IP6H_NEXTH(ip6hdr)));
1102 IP6_STATS_INC(ip6.proterr);
1103 IP6_STATS_INC(ip6.drop);
1104 }
1105 pbuf_free(p);
1106 break;
1107 }
1108 }
1109
1110ip6_input_cleanup:
1111 ip_data.current_netif = NULL;
1112 ip_data.current_input_netif = NULL;
1113 ip_data.current_ip6_header = NULL;
1114 ip_data.current_ip_header_tot_len = 0;
1115 ip6_addr_set_zero(ip6_current_src_addr());
1116 ip6_addr_set_zero(ip6_current_dest_addr());
1117
1118 return ERR_OK;
1119}
1120
1121
1148err_t
1149ip6_output_if(struct pbuf *p, const ip6_addr_t *src, const ip6_addr_t *dest,
1150 u8_t hl, u8_t tc,
1151 u8_t nexth, struct netif *netif)
1152{
1153 const ip6_addr_t *src_used = src;
1154 if (dest != LWIP_IP_HDRINCL) {
1155 if (src != NULL && ip6_addr_isany(src)) {
1156 src_used = ip_2_ip6(ip6_select_source_address(netif, dest));
1157 if ((src_used == NULL) || ip6_addr_isany(src_used)) {
1158 /* No appropriate source address was found for this packet. */
1159 LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("ip6_output: No suitable source address for packet.\n"));
1160 IP6_STATS_INC(ip6.rterr);
1161 return ERR_RTE;
1162 }
1163 }
1164 }
1165 return ip6_output_if_src(p, src_used, dest, hl, tc, nexth, netif);
1166}
1167
1172err_t
1173ip6_output_if_src(struct pbuf *p, const ip6_addr_t *src, const ip6_addr_t *dest,
1174 u8_t hl, u8_t tc,
1175 u8_t nexth, struct netif *netif)
1176{
1177 struct ip6_hdr *ip6hdr;
1178 ip6_addr_t dest_addr;
1179
1182
1183 /* Should the IPv6 header be generated or is it already included in p? */
1184 if (dest != LWIP_IP_HDRINCL) {
1185#if LWIP_IPV6_SCOPES
1186 /* If the destination address is scoped but lacks a zone, add a zone now,
1187 * based on the outgoing interface. The lower layers (e.g., nd6) absolutely
1188 * require addresses to be properly zoned for correctness. In some cases,
1189 * earlier attempts will have been made to add a zone to the destination,
1190 * but this function is the only one that is called in all (other) cases,
1191 * so we must do this here. */
1192 if (ip6_addr_lacks_zone(dest, IP6_UNKNOWN)) {
1193 ip6_addr_copy(dest_addr, *dest);
1194 ip6_addr_assign_zone(&dest_addr, IP6_UNKNOWN, netif);
1195 dest = &dest_addr;
1196 }
1197#endif /* LWIP_IPV6_SCOPES */
1198
1199 /* generate IPv6 header */
1200 if (pbuf_add_header(p, IP6_HLEN)) {
1201 LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("ip6_output: not enough room for IPv6 header in pbuf\n"));
1202 IP6_STATS_INC(ip6.err);
1203 return ERR_BUF;
1204 }
1205
1206 ip6hdr = (struct ip6_hdr *)p->payload;
1207 LWIP_ASSERT("check that first pbuf can hold struct ip6_hdr",
1208 (p->len >= sizeof(struct ip6_hdr)));
1209
1210 IP6H_HOPLIM_SET(ip6hdr, hl);
1211 IP6H_NEXTH_SET(ip6hdr, nexth);
1212
1213 /* dest cannot be NULL here */
1214 ip6_addr_copy_to_packed(ip6hdr->dest, *dest);
1215
1216 IP6H_VTCFL_SET(ip6hdr, 6, tc, 0);
1217 IP6H_PLEN_SET(ip6hdr, (u16_t)(p->tot_len - IP6_HLEN));
1218
1219 if (src == NULL) {
1220 src = IP6_ADDR_ANY6;
1221 }
1222 /* src cannot be NULL here */
1223 ip6_addr_copy_to_packed(ip6hdr->src, *src);
1224
1225 } else {
1226 /* IP header already included in p */
1227 ip6hdr = (struct ip6_hdr *)p->payload;
1228 ip6_addr_copy_from_packed(dest_addr, ip6hdr->dest);
1229 ip6_addr_assign_zone(&dest_addr, IP6_UNKNOWN, netif);
1230 dest = &dest_addr;
1231 }
1232
1233 IP6_STATS_INC(ip6.xmit);
1234
1235 LWIP_DEBUGF(IP6_DEBUG, ("ip6_output_if: %c%c%"U16_F"\n", netif->name[0], netif->name[1], (u16_t)netif->num));
1236 ip6_debug_print(p);
1237
1238#if ENABLE_LOOPBACK
1239 {
1240 int i;
1241#if !LWIP_HAVE_LOOPIF
1242 if (ip6_addr_isloopback(dest)) {
1243 return netif_loop_output(netif, p);
1244 }
1245#endif /* !LWIP_HAVE_LOOPIF */
1246 for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) {
1247 if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i)) &&
1248 ip6_addr_eq(dest, netif_ip6_addr(netif, i))) {
1249 /* Packet to self, enqueue it for loopback */
1250 LWIP_DEBUGF(IP6_DEBUG, ("netif_loop_output()\n"));
1251 return netif_loop_output(netif, p);
1252 }
1253 }
1254 }
1255#if LWIP_MULTICAST_TX_OPTIONS
1256 if ((p->flags & PBUF_FLAG_MCASTLOOP) != 0) {
1257 netif_loop_output(netif, p);
1258 }
1259#endif /* LWIP_MULTICAST_TX_OPTIONS */
1260#endif /* ENABLE_LOOPBACK */
1261#if LWIP_IPV6_FRAG
1262 /* don't fragment if interface has mtu set to 0 [loopif] */
1263 if (netif_mtu6(netif) && (p->tot_len > nd6_get_destination_mtu(dest, netif))) {
1264 return ip6_frag(p, netif, dest);
1265 }
1266#endif /* LWIP_IPV6_FRAG */
1267
1268 LWIP_DEBUGF(IP6_DEBUG, ("netif->output_ip6()\n"));
1269 return netif->output_ip6(netif, p, dest);
1270}
1271
1290err_t
1291ip6_output(struct pbuf *p, const ip6_addr_t *src, const ip6_addr_t *dest,
1292 u8_t hl, u8_t tc, u8_t nexth)
1293{
1294 struct netif *netif;
1295 struct ip6_hdr *ip6hdr;
1296 ip6_addr_t src_addr, dest_addr;
1297
1299
1300 if (dest != LWIP_IP_HDRINCL) {
1301 netif = ip6_route(src, dest);
1302 } else {
1303 /* IP header included in p, read addresses. */
1304 ip6hdr = (struct ip6_hdr *)p->payload;
1305 ip6_addr_copy_from_packed(src_addr, ip6hdr->src);
1306 ip6_addr_copy_from_packed(dest_addr, ip6hdr->dest);
1307 netif = ip6_route(&src_addr, &dest_addr);
1308 dest = &dest_addr;
1309 }
1310
1311 if (netif == NULL) {
1312 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",
1313 IP6_ADDR_BLOCK1(dest),
1314 IP6_ADDR_BLOCK2(dest),
1315 IP6_ADDR_BLOCK3(dest),
1316 IP6_ADDR_BLOCK4(dest),
1317 IP6_ADDR_BLOCK5(dest),
1318 IP6_ADDR_BLOCK6(dest),
1319 IP6_ADDR_BLOCK7(dest),
1320 IP6_ADDR_BLOCK8(dest)));
1321 IP6_STATS_INC(ip6.rterr);
1322 return ERR_RTE;
1323 }
1324
1325 return ip6_output_if(p, src, dest, hl, tc, nexth, netif);
1326}
1327
1328
1329#if LWIP_NETIF_USE_HINTS
1349err_t
1350ip6_output_hinted(struct pbuf *p, const ip6_addr_t *src, const ip6_addr_t *dest,
1351 u8_t hl, u8_t tc, u8_t nexth, struct netif_hint *netif_hint)
1352{
1353 struct netif *netif;
1354 struct ip6_hdr *ip6hdr;
1355 ip6_addr_t src_addr, dest_addr;
1356 err_t err;
1357
1359
1360 if (dest != LWIP_IP_HDRINCL) {
1361 netif = ip6_route(src, dest);
1362 } else {
1363 /* IP header included in p, read addresses. */
1364 ip6hdr = (struct ip6_hdr *)p->payload;
1365 ip6_addr_copy_from_packed(src_addr, ip6hdr->src);
1366 ip6_addr_copy_from_packed(dest_addr, ip6hdr->dest);
1367 netif = ip6_route(&src_addr, &dest_addr);
1368 dest = &dest_addr;
1369 }
1370
1371 if (netif == NULL) {
1372 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",
1373 IP6_ADDR_BLOCK1(dest),
1374 IP6_ADDR_BLOCK2(dest),
1375 IP6_ADDR_BLOCK3(dest),
1376 IP6_ADDR_BLOCK4(dest),
1377 IP6_ADDR_BLOCK5(dest),
1378 IP6_ADDR_BLOCK6(dest),
1379 IP6_ADDR_BLOCK7(dest),
1380 IP6_ADDR_BLOCK8(dest)));
1381 IP6_STATS_INC(ip6.rterr);
1382 return ERR_RTE;
1383 }
1384
1385 NETIF_SET_HINTS(netif, netif_hint);
1386 err = ip6_output_if(p, src, dest, hl, tc, nexth, netif);
1388
1389 return err;
1390}
1391#endif /* LWIP_NETIF_USE_HINTS*/
1392
1393#if LWIP_IPV6_MLD
1404err_t
1405ip6_options_add_hbh_ra(struct pbuf *p, u8_t nexth, u8_t value)
1406{
1407 u8_t *opt_data;
1408 u32_t offset = 0;
1409 struct ip6_hbh_hdr *hbh_hdr;
1410 struct ip6_opt_hdr *opt_hdr;
1411
1412 /* fixed 4 bytes for router alert option and 2 bytes padding */
1413 const u8_t hlen = (sizeof(struct ip6_opt_hdr) * 2) + IP6_ROUTER_ALERT_DLEN;
1414 /* Move pointer to make room for hop-by-hop options header. */
1415 if (pbuf_add_header(p, sizeof(struct ip6_hbh_hdr) + hlen)) {
1416 LWIP_DEBUGF(IP6_DEBUG, ("ip6_options: no space for options header\n"));
1417 IP6_STATS_INC(ip6.err);
1418 return ERR_BUF;
1419 }
1420
1421 /* Set fields of Hop-by-Hop header */
1422 hbh_hdr = (struct ip6_hbh_hdr *)p->payload;
1423 IP6_HBH_NEXTH(hbh_hdr) = nexth;
1424 hbh_hdr->_hlen = 0;
1426
1427 /* Set router alert options to Hop-by-Hop extended option header */
1428 opt_hdr = (struct ip6_opt_hdr *)((u8_t *)hbh_hdr + offset);
1432
1433 /* Set router alert option data */
1434 opt_data = (u8_t *)hbh_hdr + offset;
1435 opt_data[0] = value;
1436 opt_data[1] = 0;
1437 offset += IP6_OPT_DLEN(opt_hdr);
1438
1439 /* add 2 bytes padding to make 8 bytes Hop-by-Hop header length */
1440 opt_hdr = (struct ip6_opt_hdr *)((u8_t *)hbh_hdr + offset);
1441 IP6_OPT_TYPE(opt_hdr) = IP6_PADN_OPTION;
1442 IP6_OPT_DLEN(opt_hdr) = 0;
1443
1444 return ERR_OK;
1445}
1446#endif /* LWIP_IPV6_MLD */
1447
1448#if IP6_DEBUG
1449/* Print an IPv6 header by using LWIP_DEBUGF
1450 * @param p an IPv6 packet, p->payload pointing to the IPv6 header
1451 */
1452void
1453ip6_debug_print(struct pbuf *p)
1454{
1455 struct ip6_hdr *ip6hdr = (struct ip6_hdr *)p->payload;
1456
1457 LWIP_DEBUGF(IP6_DEBUG, ("IPv6 header:\n"));
1458 LWIP_DEBUGF(IP6_DEBUG, ("+-------------------------------+\n"));
1459 LWIP_DEBUGF(IP6_DEBUG, ("| %2"U16_F" | %3"U16_F" | %7"U32_F" | (ver, class, flow)\n",
1460 IP6H_V(ip6hdr),
1461 IP6H_TC(ip6hdr),
1462 IP6H_FL(ip6hdr)));
1463 LWIP_DEBUGF(IP6_DEBUG, ("+-------------------------------+\n"));
1464 LWIP_DEBUGF(IP6_DEBUG, ("| %5"U16_F" | %3"U16_F" | %3"U16_F" | (plen, nexth, hopl)\n",
1465 IP6H_PLEN(ip6hdr),
1466 IP6H_NEXTH(ip6hdr),
1467 IP6H_HOPLIM(ip6hdr)));
1468 LWIP_DEBUGF(IP6_DEBUG, ("+-------------------------------+\n"));
1469 LWIP_DEBUGF(IP6_DEBUG, ("| %4"X32_F" | %4"X32_F" | %4"X32_F" | %4"X32_F" | (src)\n",
1470 IP6_ADDR_BLOCK1(&(ip6hdr->src)),
1471 IP6_ADDR_BLOCK2(&(ip6hdr->src)),
1472 IP6_ADDR_BLOCK3(&(ip6hdr->src)),
1473 IP6_ADDR_BLOCK4(&(ip6hdr->src))));
1474 LWIP_DEBUGF(IP6_DEBUG, ("| %4"X32_F" | %4"X32_F" | %4"X32_F" | %4"X32_F" |\n",
1475 IP6_ADDR_BLOCK5(&(ip6hdr->src)),
1476 IP6_ADDR_BLOCK6(&(ip6hdr->src)),
1477 IP6_ADDR_BLOCK7(&(ip6hdr->src)),
1478 IP6_ADDR_BLOCK8(&(ip6hdr->src))));
1479 LWIP_DEBUGF(IP6_DEBUG, ("+-------------------------------+\n"));
1480 LWIP_DEBUGF(IP6_DEBUG, ("| %4"X32_F" | %4"X32_F" | %4"X32_F" | %4"X32_F" | (dest)\n",
1481 IP6_ADDR_BLOCK1(&(ip6hdr->dest)),
1482 IP6_ADDR_BLOCK2(&(ip6hdr->dest)),
1483 IP6_ADDR_BLOCK3(&(ip6hdr->dest)),
1484 IP6_ADDR_BLOCK4(&(ip6hdr->dest))));
1485 LWIP_DEBUGF(IP6_DEBUG, ("| %4"X32_F" | %4"X32_F" | %4"X32_F" | %4"X32_F" |\n",
1486 IP6_ADDR_BLOCK5(&(ip6hdr->dest)),
1487 IP6_ADDR_BLOCK6(&(ip6hdr->dest)),
1488 IP6_ADDR_BLOCK7(&(ip6hdr->dest)),
1489 IP6_ADDR_BLOCK8(&(ip6hdr->dest))));
1490 LWIP_DEBUGF(IP6_DEBUG, ("+-------------------------------+\n"));
1491}
1492#endif /* IP6_DEBUG */
1493
1494#endif /* LWIP_IPV6 */
#define PP_HTONS(x)
Definition: def.h:90
#define NULL
Definition: types.h:112
#define X16_F
Definition: cc.h:21
#define U16_F
Definition: cc.h:19
#define X32_F
Definition: cc.h:24
#define U32_F
Definition: cc.h:22
#define LWIP_DEBUGF(debug, message)
Definition: debug.h:158
#define LWIP_ASSERT(message, assertion)
Definition: debug.h:116
#define LWIP_IP_HDRINCL
Definition: ip.h:58
#define LWIP_IP_CHECK_PBUF_REF_COUNT_FOR_TX(p)
Definition: ip.h:63
struct ip_globals ip_data
GLenum src
Definition: glext.h:6340
GLintptr offset
Definition: glext.h:5920
const GLfloat * tc
Definition: glext.h:8925
GLfloat GLfloat p
Definition: glext.h:8902
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
int32_t s32_t
Definition: arch.h:130
#define LWIP_PACKED_CAST(target_type, val)
Definition: arch.h:257
uint32_t u32_t
Definition: arch.h:129
uint8_t u8_t
Definition: arch.h:125
#define LWIP_UNUSED_ARG(x)
Definition: arch.h:373
uint16_t u16_t
Definition: arch.h:127
int8_t s8_t
Definition: arch.h:126
#define LWIP_DBG_LEVEL_SERIOUS
Definition: debug.h:57
#define LWIP_DBG_LEVEL_WARNING
Definition: debug.h:55
#define LWIP_DBG_TRACE
Definition: debug.h:83
s8_t err_t
Definition: err.h:96
@ ERR_BUF
Definition: err.h:59
@ ERR_RTE
Definition: err.h:63
@ ERR_OK
Definition: err.h:55
#define IP6_DEBUG
Definition: opt.h:3554
#define LWIP_IPV6_NUM_ADDRESSES
Definition: opt.h:2487
#define LWIP_ASSERT_CORE_LOCKED()
Definition: opt.h:227
#define netif_is_up(netif)
Definition: netif.h:479
void pbuf_realloc(struct pbuf *p, u16_t new_len)
Definition: pbuf.c:402
u8_t pbuf_free(struct pbuf *p)
Definition: pbuf.c:727
#define ip_2_ip6(ipaddr)
Definition: ip_addr.h:356
#define ip_addr_copy_from_ip6_packed(dest, src)
Definition: ip_addr.h:362
ip6_addr_t ip_addr_t
Definition: ip_addr.h:344
if(dx< 0)
Definition: linetemp.h:194
BOOL todo
Definition: filedlg.c:313
static char * dest
Definition: rtl.c:135
struct netif * netif_list
Definition: netif.c:113
struct netif * netif_default
Definition: netif.c:115
#define netif_is_link_up(netif)
Definition: netif.h:491
#define NETIF_FOREACH(netif)
Definition: netif.h:424
#define NETIF_RESET_HINTS(netif)
Definition: netif.h:570
#define NETIF_SET_HINTS(netif, netifhint)
Definition: netif.h:569
#define ip6_frag
Definition: netiodef.h:210
u8_t pbuf_add_header(struct pbuf *p, size_t header_size_increment)
Definition: pbuf.c:554
u8_t pbuf_remove_header(struct pbuf *p, size_t header_size_decrement)
Definition: pbuf.c:585
u8_t pbuf_add_header_force(struct pbuf *p, size_t header_size_increment)
Definition: pbuf.c:564
#define PBUF_FLAG_MCASTLOOP
Definition: pbuf.h:177
@ ICMP6_DUR_NO_ROUTE
Definition: icmp6.h:100
@ ICMP6_PP_FIELD
Definition: icmp6.h:126
@ ICMP6_PP_OPTION
Definition: icmp6.h:130
@ ICMP6_PP_HEADER
Definition: icmp6.h:128
@ ICMP6_TE_HL
Definition: icmp6.h:118
#define IP6_NEXTH_UDP
Definition: ip6.h:68
#define IP6_ROUTER_ALERT_OPTION
Definition: ip6.h:114
#define IP6H_TC(hdr)
Definition: ip6.h:100
#define IP6_HOME_ADDRESS_OPTION
Definition: ip6.h:116
#define IP6_DEST_NEXTH(hdr)
Definition: ip6.h:176
#define IP6_HBH_NEXTH(hdr)
Definition: ip6.h:157
#define IP6_ROUT_TYPE2
Definition: ip6.h:179
#define IP6H_NEXTH(hdr)
Definition: ip6.h:103
#define IP6_FRAG_MBIT(hdr)
Definition: ip6.h:228
#define IP6_ROUTER_ALERT_DLEN
Definition: ip6.h:117
#define IP6_NEXTH_FRAGMENT
Definition: ip6.h:71
#define IP6_OPT_HLEN
Definition: ip6.h:134
#define IP6_NEXTH_HOPBYHOP
Definition: ip6.h:66
#define IP6H_PLEN_SET(hdr, plen)
Definition: ip6.h:107
#define IP6_PADN_OPTION
Definition: ip6.h:113
#define IP6_HBH_HLEN
Definition: ip6.h:141
#define IP6_ROUT_SEG_LEFT(hdr)
Definition: ip6.h:202
#define IP6_FRAG_OFFSET_MASK
Definition: ip6.h:206
#define IP6_NEXTH_ROUTING
Definition: ip6.h:70
#define IP6_FRAG_MORE_FLAG
Definition: ip6.h:207
#define IP6H_HOPLIM(hdr)
Definition: ip6.h:105
#define IP6_JUMBO_OPTION
Definition: ip6.h:115
#define IP6_OPT_TYPE(hdr)
Definition: ip6.h:137
#define IP6_NEXTH_NONE
Definition: ip6.h:73
#define IP6_NEXTH_UDPLITE
Definition: ip6.h:75
#define IP6_DEST_HLEN
Definition: ip6.h:160
#define IP6_NEXTH_TCP
Definition: ip6.h:67
#define IP6_OPT_TYPE_ACTION(hdr)
Definition: ip6.h:135
#define IP6_ROUT_NEXTH(hdr)
Definition: ip6.h:200
#define IP6_ROUT_RPL
Definition: ip6.h:180
#define IP6_PAD1_OPTION
Definition: ip6.h:112
#define IP6H_NEXTH_SET(hdr, nexth)
Definition: ip6.h:108
#define IP6H_V(hdr)
Definition: ip6.h:99
#define IP6H_VTCFL_SET(hdr, v, tc, fl)
Definition: ip6.h:106
#define IP6_FRAG_NEXTH(hdr)
Definition: ip6.h:227
#define IP6H_HOPLIM_SET(hdr, hl)
Definition: ip6.h:109
#define IP6_OPT_DLEN(hdr)
Definition: ip6.h:138
#define IP6_NEXTH_ICMP6
Definition: ip6.h:72
#define IP6H_PLEN(hdr)
Definition: ip6.h:102
#define IP6H_FL(hdr)
Definition: ip6.h:101
#define IP6_ROUT_TYPE(hdr)
Definition: ip6.h:201
#define IP6_NEXTH_DESTOPTS
Definition: ip6.h:74
#define IP6_HLEN
Definition: ip6.h:64
#define err(...)
#define IP6_FRAG_STATS_INC(x)
Definition: stats.h:444
#define IP6_STATS_INC(x)
Definition: stats.h:428
Definition: ip6.h:82
Definition: netif.h:269
char name[2]
Definition: netif.h:356
u8_t num
Definition: netif.h:359
u16_t mtu
Definition: netif.h:344
Definition: pbuf.h:186
Definition: pdh_main.c:94