1 /* SPDX-License-Identifier: BSD-2-Clause */
3 * dhcpcd - IPv6 ND handling
4 * Copyright (c) 2006-2019 Roy Marples <roy@marples.name>
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 #include <sys/ioctl.h>
30 #include <sys/param.h>
31 #include <sys/socket.h>
33 #include <net/route.h>
34 #include <netinet/in.h>
35 #include <netinet/ip6.h>
36 #include <netinet/icmp6.h>
49 #include "dhcp-common.h"
59 /* Debugging Router Solicitations is a lot of spam, so disable it */
63 #define ND_OPT_RDNSS 25
64 struct nd_opt_rdnss { /* RDNSS option RFC 6106 */
65 uint8_t nd_opt_rdnss_type;
66 uint8_t nd_opt_rdnss_len;
67 uint16_t nd_opt_rdnss_reserved;
68 uint32_t nd_opt_rdnss_lifetime;
69 /* followed by list of IP prefixes */
71 __CTASSERT(sizeof(struct nd_opt_rdnss) == 8);
75 #define ND_OPT_DNSSL 31
76 struct nd_opt_dnssl { /* DNSSL option RFC 6106 */
77 uint8_t nd_opt_dnssl_type;
78 uint8_t nd_opt_dnssl_len;
79 uint16_t nd_opt_dnssl_reserved;
80 uint32_t nd_opt_dnssl_lifetime;
81 /* followed by list of DNS servers */
83 __CTASSERT(sizeof(struct nd_opt_rdnss) == 8);
86 /* Impossible options, so we can easily add extras */
87 #define _ND_OPT_PREFIX_ADDR 255 + 1
89 /* Minimal IPv6 MTU */
91 #define IPV6_MMTU 1280
94 #ifndef ND_RA_FLAG_RTPREF_HIGH
95 #define ND_RA_FLAG_RTPREF_MASK 0x18
96 #define ND_RA_FLAG_RTPREF_HIGH 0x08
97 #define ND_RA_FLAG_RTPREF_MEDIUM 0x00
98 #define ND_RA_FLAG_RTPREF_LOW 0x18
99 #define ND_RA_FLAG_RTPREF_RSV 0x10
102 /* RTPREF_MEDIUM has to be 0! */
103 #define RTPREF_HIGH 1
104 #define RTPREF_MEDIUM 0
105 #define RTPREF_LOW (-1)
106 #define RTPREF_RESERVED (-2)
107 #define RTPREF_INVALID (-3) /* internal */
109 #define EXPIRED_MAX 5 /* Remember 5 expired routers to avoid
112 #define MIN_RANDOM_FACTOR 500 /* millisecs */
113 #define MAX_RANDOM_FACTOR 1500 /* millisecs */
114 #define MIN_RANDOM_FACTOR_U MIN_RANDOM_FACTOR * 1000 /* usecs */
115 #define MAX_RANDOM_FACTOR_U MAX_RANDOM_FACTOR * 1000 /* usecs */
117 #if BYTE_ORDER == BIG_ENDIAN
118 #define IPV6_ADDR_INT32_ONE 1
119 #define IPV6_ADDR_INT16_MLL 0xff02
120 #elif BYTE_ORDER == LITTLE_ENDIAN
121 #define IPV6_ADDR_INT32_ONE 0x01000000
122 #define IPV6_ADDR_INT16_MLL 0x02ff
125 /* Debugging Neighbor Solicitations is a lot of spam, so disable it */
129 static void ipv6nd_handledata(void *);
132 * Android ships buggy ICMP6 filter headers.
133 * Supply our own until they fix their shit.
135 * https://android-review.googlesource.com/#/c/58438/
136 * http://code.google.com/p/android/issues/original?id=32621&seq=24
139 #undef ICMP6_FILTER_WILLPASS
140 #undef ICMP6_FILTER_WILLBLOCK
141 #undef ICMP6_FILTER_SETPASS
142 #undef ICMP6_FILTER_SETBLOCK
143 #undef ICMP6_FILTER_SETPASSALL
144 #undef ICMP6_FILTER_SETBLOCKALL
145 #define ICMP6_FILTER_WILLPASS(type, filterp) \
146 ((((filterp)->icmp6_filt[(type) >> 5]) & (1 << ((type) & 31))) == 0)
147 #define ICMP6_FILTER_WILLBLOCK(type, filterp) \
148 ((((filterp)->icmp6_filt[(type) >> 5]) & (1 << ((type) & 31))) != 0)
149 #define ICMP6_FILTER_SETPASS(type, filterp) \
150 ((((filterp)->icmp6_filt[(type) >> 5]) &= ~(1 << ((type) & 31))))
151 #define ICMP6_FILTER_SETBLOCK(type, filterp) \
152 ((((filterp)->icmp6_filt[(type) >> 5]) |= (1 << ((type) & 31))))
153 #define ICMP6_FILTER_SETPASSALL(filterp) \
154 memset(filterp, 0, sizeof(struct icmp6_filter));
155 #define ICMP6_FILTER_SETBLOCKALL(filterp) \
156 memset(filterp, 0xff, sizeof(struct icmp6_filter));
159 /* Support older systems with different defines */
160 #if !defined(IPV6_RECVHOPLIMIT) && defined(IPV6_HOPLIMIT)
161 #define IPV6_RECVHOPLIMIT IPV6_HOPLIMIT
163 #if !defined(IPV6_RECVPKTINFO) && defined(IPV6_PKTINFO)
164 #define IPV6_RECVPKTINFO IPV6_PKTINFO
168 #define ipv6nd_free_ra(ra) ipv6nd_freedrop_ra((ra), 0)
169 #define ipv6nd_drop_ra(ra) ipv6nd_freedrop_ra((ra), 1)
172 ipv6nd_printoptions(const struct dhcpcd_ctx *ctx,
173 const struct dhcp_opt *opts, size_t opts_len)
176 const struct dhcp_opt *opt, *opt2;
179 for (i = 0, opt = ctx->nd_opts;
180 i < ctx->nd_opts_len; i++, opt++)
182 for (j = 0, opt2 = opts; j < opts_len; j++, opt2++)
183 if (opt2->option == opt->option)
186 cols = printf("%03d %s", opt->option, opt->var);
187 dhcp_print_option_encoding(opt, cols);
190 for (i = 0, opt = opts; i < opts_len; i++, opt++) {
191 cols = printf("%03d %s", opt->option, opt->var);
192 dhcp_print_option_encoding(opt, cols);
200 struct icmp6_filter filt;
202 #define SOCK_FLAGS SOCK_CLOEXEC | SOCK_NONBLOCK
203 s = xsocket(PF_INET6, SOCK_RAW | SOCK_FLAGS, IPPROTO_ICMPV6);
210 if (setsockopt(s, IPPROTO_IPV6, IPV6_MULTICAST_HOPS,
211 &on, sizeof(on)) == -1)
215 if (setsockopt(s, IPPROTO_IPV6, IPV6_RECVHOPLIMIT,
216 &on, sizeof(on)) == -1)
219 ICMP6_FILTER_SETBLOCKALL(&filt);
220 ICMP6_FILTER_SETPASS(ND_ROUTER_ADVERT, &filt);
221 if (setsockopt(s, IPPROTO_ICMPV6, ICMP6_FILTER,
222 &filt, sizeof(filt)) == -1)
234 ipv6nd_open(struct interface *ifp)
237 struct ipv6_mreq mreq = {
238 .ipv6mr_multiaddr = IN6ADDR_LINKLOCAL_ALLNODES_INIT,
239 .ipv6mr_interface = ifp->index
241 struct rs_state *state = RS_STATE(ifp);
242 uint_t ifindex = ifp->index;
244 if (state->nd_fd != -1)
251 if (setsockopt(s, IPPROTO_IPV6, IPV6_BOUND_IF,
252 &ifindex, sizeof(ifindex)) == -1)
258 if (setsockopt(s, IPPROTO_IPV6, IPV6_JOIN_GROUP,
259 &mreq, sizeof(mreq)) == -1)
266 eloop_event_add(ifp->ctx->eloop, s, ipv6nd_handledata, ifp);
271 ipv6nd_open(struct dhcpcd_ctx *ctx)
275 if (ctx->nd_fd != -1)
283 if (setsockopt(s, IPPROTO_IPV6, IPV6_RECVPKTINFO,
284 &on, sizeof(on)) == -1)
291 eloop_event_add(ctx->eloop, s, ipv6nd_handledata, ctx);
297 ipv6nd_makersprobe(struct interface *ifp)
299 struct rs_state *state;
300 struct nd_router_solicit *rs;
302 state = RS_STATE(ifp);
304 state->rslen = sizeof(*rs);
306 state->rslen += (size_t)ROUNDUP8(ifp->hwlen + 2);
307 state->rs = calloc(1, state->rslen);
308 if (state->rs == NULL)
311 rs->nd_rs_type = ND_ROUTER_SOLICIT;
312 //rs->nd_rs_code = 0;
313 //rs->nd_rs_cksum = 0;
314 //rs->nd_rs_reserved = 0;
316 if (ifp->hwlen != 0) {
317 struct nd_opt_hdr *nd;
319 nd = (struct nd_opt_hdr *)(state->rs + 1);
320 nd->nd_opt_type = ND_OPT_SOURCE_LINKADDR;
321 nd->nd_opt_len = (uint8_t)((ROUNDUP8(ifp->hwlen + 2)) >> 3);
322 memcpy(nd + 1, ifp->hwaddr, ifp->hwlen);
328 ipv6nd_sendrsprobe(void *arg)
330 struct interface *ifp = arg;
331 struct rs_state *state = RS_STATE(ifp);
332 struct sockaddr_in6 dst = {
333 .sin6_family = AF_INET6,
334 .sin6_addr = IN6ADDR_LINKLOCAL_ALLROUTERS_INIT,
335 .sin6_scope_id = ifp->index,
337 struct iovec iov = { .iov_base = state->rs, .iov_len = state->rslen };
338 unsigned char ctl[CMSG_SPACE(sizeof(struct in6_pktinfo))] = { 0 };
339 struct msghdr msg = {
340 .msg_name = &dst, .msg_namelen = sizeof(dst),
341 .msg_iov = &iov, .msg_iovlen = 1,
342 .msg_control = ctl, .msg_controllen = sizeof(ctl),
345 struct in6_pktinfo pi = { .ipi6_ifindex = ifp->index };
348 if (ipv6_linklocal(ifp) == NULL) {
349 logdebugx("%s: delaying Router Solicitation for LL address",
351 ipv6_addlinklocalcallback(ifp, ipv6nd_sendrsprobe, ifp);
356 dst.sin6_len = sizeof(dst);
359 /* Set the outbound interface */
360 cm = CMSG_FIRSTHDR(&msg);
361 if (cm == NULL) /* unlikely */
363 cm->cmsg_level = IPPROTO_IPV6;
364 cm->cmsg_type = IPV6_PKTINFO;
365 cm->cmsg_len = CMSG_LEN(sizeof(pi));
366 memcpy(CMSG_DATA(cm), &pi, sizeof(pi));
368 logdebugx("%s: sending Router Solicitation", ifp->name);
374 if (sendmsg(s, &msg, 0) == -1) {
376 /* Allow IPv6ND to continue .... at most a few errors
378 * Generally the error is ENOBUFS when struggling to
379 * associate with an access point. */
382 if (state->rsprobes++ < MAX_RTR_SOLICITATIONS)
383 eloop_timeout_add_sec(ifp->ctx->eloop,
384 RTR_SOLICITATION_INTERVAL, ipv6nd_sendrsprobe, ifp);
386 logwarnx("%s: no IPv6 Routers available", ifp->name);
393 ipv6nd_sendadvertisement(void *arg)
395 struct ipv6_addr *ia = arg;
396 struct interface *ifp = ia->iface;
397 struct dhcpcd_ctx *ctx = ifp->ctx;
398 struct sockaddr_in6 dst = {
399 .sin6_family = AF_INET6,
400 .sin6_addr = IN6ADDR_LINKLOCAL_ALLNODES_INIT,
401 .sin6_scope_id = ifp->index,
403 struct iovec iov = { .iov_base = ia->na, .iov_len = ia->na_len };
404 unsigned char ctl[CMSG_SPACE(sizeof(struct in6_pktinfo))] = { 0 };
405 struct msghdr msg = {
406 .msg_name = &dst, .msg_namelen = sizeof(dst),
407 .msg_iov = &iov, .msg_iovlen = 1,
408 .msg_control = ctl, .msg_controllen = sizeof(ctl),
411 struct in6_pktinfo pi = { .ipi6_ifindex = ifp->index };
412 const struct rs_state *state = RS_CSTATE(ifp);
415 if (state == NULL || ifp->carrier <= LINK_DOWN)
419 dst.sin6_len = sizeof(dst);
422 /* Set the outbound interface. */
423 cm = CMSG_FIRSTHDR(&msg);
425 cm->cmsg_level = IPPROTO_IPV6;
426 cm->cmsg_type = IPV6_PKTINFO;
427 cm->cmsg_len = CMSG_LEN(sizeof(pi));
428 memcpy(CMSG_DATA(cm), &pi, sizeof(pi));
429 logdebugx("%s: sending NA for %s", ifp->name, ia->saddr);
435 if (sendmsg(s, &msg, 0) == -1)
438 if (++ia->na_count < MAX_NEIGHBOR_ADVERTISEMENT) {
439 eloop_timeout_add_sec(ctx->eloop,
440 state->retrans / 1000, ipv6nd_sendadvertisement, ia);
451 ipv6nd_advertise(struct ipv6_addr *ia)
453 struct dhcpcd_ctx *ctx;
454 struct interface *ifp;
455 struct ipv6_state *state;
456 struct ipv6_addr *iap, *iaf;
457 struct nd_neighbor_advert *na;
459 if (IN6_IS_ADDR_MULTICAST(&ia->addr))
463 if (!(ia->flags & IPV6_AF_AUTOCONF) && ia->flags & IPV6_AF_RAPFX)
467 ctx = ia->iface->ctx;
468 /* Find the most preferred address to advertise. */
470 TAILQ_FOREACH(ifp, ctx->ifaces, next) {
471 state = IPV6_STATE(ifp);
472 if (state == NULL || ifp->carrier <= LINK_DOWN)
475 TAILQ_FOREACH(iap, &state->addrs, next) {
476 if (!IN6_ARE_ADDR_EQUAL(&iap->addr, &ia->addr))
479 /* Cancel any current advertisement. */
480 eloop_timeout_delete(ctx->eloop,
481 ipv6nd_sendadvertisement, iap);
483 /* Don't advertise what we can't use. */
484 if (iap->prefix_vltime == 0 ||
485 iap->addr_flags & IN6_IFF_NOTUSEABLE)
489 iaf->iface->metric > iap->iface->metric)
496 /* Make the packet. */
498 iaf->na_len = sizeof(*na);
500 iaf->na_len += (size_t)ROUNDUP8(ifp->hwlen + 2);
501 na = calloc(1, iaf->na_len);
507 na->nd_na_type = ND_NEIGHBOR_ADVERT;
508 na->nd_na_flags_reserved = ND_NA_FLAG_OVERRIDE;
509 if (ip6_forwarding(ifp->name) == 1)
510 na->nd_na_flags_reserved |= ND_NA_FLAG_ROUTER;
511 na->nd_na_target = ia->addr;
513 if (ifp->hwlen != 0) {
514 struct nd_opt_hdr *opt;
516 opt = (struct nd_opt_hdr *)(na + 1);
517 opt->nd_opt_type = ND_OPT_TARGET_LINKADDR;
518 opt->nd_opt_len = (uint8_t)((ROUNDUP8(ifp->hwlen + 2)) >> 3);
519 memcpy(opt + 1, ifp->hwaddr, ifp->hwlen);
525 eloop_timeout_delete(ctx->eloop, ipv6nd_sendadvertisement, iaf);
526 ipv6nd_sendadvertisement(iaf);
528 #elif !defined(SMALL)
529 #warning kernel does not support userland sending ND6 advertisements
530 #endif /* ND6_ADVERTISE */
533 ipv6nd_expire(void *arg)
535 struct interface *ifp = arg;
537 struct ipv6_addr *ia;
538 struct timespec now = { .tv_sec = 1 };
540 if (ifp->ctx->ra_routers == NULL)
543 TAILQ_FOREACH(rap, ifp->ctx->ra_routers, next) {
544 if (rap->iface == ifp)
547 TAILQ_FOREACH(ia, &rap->addrs, next) {
551 ipv6nd_expirera(ifp);
555 ipv6nd_startexpire(struct interface *ifp)
558 eloop_timeout_add_sec(ifp->ctx->eloop, RTR_CARRIER_EXPIRE,
563 * Neighbour reachability.
565 * RFC 4681 6.2.5 says when a node is no longer a router it MUST
566 * send a RA with a zero lifetime.
567 * All OS's I know of set the NA router flag if they are a router
568 * or not and disregard that they are actively advertising or
569 * shutting down. If the interface is disabled, it cant't send a NA at all.
571 * As such we CANNOT rely on the NA Router flag and MUST use
572 * unreachability or receive a RA with a lifetime of zero to remove
573 * the node as a default router.
576 ipv6nd_neighbour(struct dhcpcd_ctx *ctx, struct in6_addr *addr, bool reachable)
578 struct ra *rap, *rapr;
580 if (ctx->ra_routers == NULL)
583 TAILQ_FOREACH(rap, ctx->ra_routers, next) {
584 if (IN6_ARE_ADDR_EQUAL(&rap->from, addr))
588 if (rap == NULL || rap->expired)
592 if (rap->isreachable)
594 loginfox("%s: %s is reachable again",
595 rap->iface->name, rap->sfrom);
596 rap->isreachable = true;
599 if (!rap->isreachable)
601 logwarnx("%s: %s is unreachable",
602 rap->iface->name, rap->sfrom);
603 rap->isreachable = false;
606 /* If we have no reachable default routers, try and solicit one. */
607 TAILQ_FOREACH(rapr, ctx->ra_routers, next) {
608 if (rap == rapr || rap->iface != rapr->iface)
610 if (rapr->isreachable && !rapr->expired && rapr->lifetime)
615 ipv6nd_startrs(rap->iface);
618 const struct ipv6_addr *
619 ipv6nd_iffindaddr(const struct interface *ifp, const struct in6_addr *addr,
623 struct ipv6_addr *ap;
625 if (ifp->ctx->ra_routers == NULL)
628 TAILQ_FOREACH(rap, ifp->ctx->ra_routers, next) {
629 if (rap->iface != ifp)
631 TAILQ_FOREACH(ap, &rap->addrs, next) {
632 if (ipv6_findaddrmatch(ap, addr, flags))
640 ipv6nd_findaddr(struct dhcpcd_ctx *ctx, const struct in6_addr *addr,
644 struct ipv6_addr *ap;
646 if (ctx->ra_routers == NULL)
649 TAILQ_FOREACH(rap, ctx->ra_routers, next) {
650 TAILQ_FOREACH(ap, &rap->addrs, next) {
651 if (ipv6_findaddrmatch(ap, addr, flags))
659 ipv6nd_removefreedrop_ra(struct ra *rap, int remove_ra, int drop_ra)
662 eloop_timeout_delete(rap->iface->ctx->eloop, NULL, rap->iface);
663 eloop_timeout_delete(rap->iface->ctx->eloop, NULL, rap);
665 TAILQ_REMOVE(rap->iface->ctx->ra_routers, rap, next);
666 ipv6_freedrop_addrs(&rap->addrs, drop_ra, NULL);
672 ipv6nd_freedrop_ra(struct ra *rap, int drop)
675 ipv6nd_removefreedrop_ra(rap, 1, drop);
679 ipv6nd_free(struct interface *ifp)
681 struct rs_state *state;
682 struct ra *rap, *ran;
683 struct dhcpcd_ctx *ctx;
686 state = RS_STATE(ifp);
692 eloop_event_delete(ctx->eloop, state->nd_fd);
697 ifp->if_data[IF_DATA_IPV6ND] = NULL;
699 TAILQ_FOREACH_SAFE(rap, ifp->ctx->ra_routers, next, ran) {
700 if (rap->iface == ifp) {
707 /* If we don't have any more IPv6 enabled interfaces,
708 * close the global socket and release resources */
709 TAILQ_FOREACH(ifp, ctx->ifaces, next) {
714 if (ctx->nd_fd != -1) {
715 eloop_event_delete(ctx->eloop, ctx->nd_fd);
726 rtpref(struct ra *rap)
729 switch (rap->flags & ND_RA_FLAG_RTPREF_MASK) {
730 case ND_RA_FLAG_RTPREF_HIGH:
731 return (RTPREF_HIGH);
732 case ND_RA_FLAG_RTPREF_MEDIUM:
733 case ND_RA_FLAG_RTPREF_RSV:
734 return (RTPREF_MEDIUM);
735 case ND_RA_FLAG_RTPREF_LOW:
738 logerrx("rtpref: impossible RA flag %x", rap->flags);
739 return (RTPREF_INVALID);
745 add_router(struct dhcpcd_ctx *ctx, struct ra *router)
749 TAILQ_FOREACH(rap, ctx->ra_routers, next) {
750 if (router->iface->metric < rap->iface->metric ||
751 (router->iface->metric == rap->iface->metric &&
752 rtpref(router) > rtpref(rap)))
754 TAILQ_INSERT_BEFORE(rap, router, next);
758 TAILQ_INSERT_TAIL(ctx->ra_routers, router, next);
762 ipv6nd_scriptrun(struct ra *rap)
764 int hasdns, hasaddress, pid;
765 struct ipv6_addr *ap;
768 /* If all addresses have completed DAD run the script */
769 TAILQ_FOREACH(ap, &rap->addrs, next) {
770 if ((ap->flags & (IPV6_AF_AUTOCONF | IPV6_AF_ADDED)) ==
771 (IPV6_AF_AUTOCONF | IPV6_AF_ADDED))
774 if (!(ap->flags & IPV6_AF_DADCOMPLETED) &&
775 ipv6_iffindaddr(ap->iface, &ap->addr,
777 ap->flags |= IPV6_AF_DADCOMPLETED;
778 if ((ap->flags & IPV6_AF_DADCOMPLETED) == 0) {
779 logdebugx("%s: waiting for Router Advertisement"
787 /* If we don't require RDNSS then set hasdns = 1 so we fork */
788 if (!(rap->iface->options->options & DHCPCD_IPV6RA_REQRDNSS))
791 hasdns = rap->hasdns;
794 script_runreason(rap->iface, "ROUTERADVERT");
796 if (hasdns && (hasaddress ||
797 !(rap->flags & (ND_RA_FLAG_MANAGED | ND_RA_FLAG_OTHER))))
798 pid = dhcpcd_daemonise(rap->iface->ctx);
800 else if (options & DHCPCD_DAEMONISE &&
801 !(options & DHCPCD_DAEMONISED) && new_data)
802 logwarnx("%s: did not fork due to an absent"
803 " RDNSS option in the RA",
811 ipv6nd_addaddr(void *arg)
813 struct ipv6_addr *ap = arg;
815 ipv6_addaddr(ap, NULL);
819 ipv6nd_dadcompleted(const struct interface *ifp)
821 const struct ra *rap;
822 const struct ipv6_addr *ap;
824 TAILQ_FOREACH(rap, ifp->ctx->ra_routers, next) {
825 if (rap->iface != ifp)
827 TAILQ_FOREACH(ap, &rap->addrs, next) {
828 if (ap->flags & IPV6_AF_AUTOCONF &&
829 ap->flags & IPV6_AF_ADDED &&
830 !(ap->flags & IPV6_AF_DADCOMPLETED))
838 ipv6nd_dadcallback(void *arg)
840 struct ipv6_addr *ia = arg, *rapap;
841 struct interface *ifp;
843 int wascompleted, found;
845 char buf[INET6_ADDRSTRLEN];
850 wascompleted = (ia->flags & IPV6_AF_DADCOMPLETED);
851 ia->flags |= IPV6_AF_DADCOMPLETED;
852 if (ia->flags & IPV6_AF_DUPLICATED) {
854 logwarnx("%s: DAD detected %s", ifp->name, ia->saddr);
856 /* Try and make another stable private address.
857 * Because ap->dadcounter is always increamented,
858 * a different address is generated. */
859 /* XXX Cache DAD counter per prefix/id/ssid? */
860 if (ifp->options->options & DHCPCD_SLAACPRIVATE) {
861 if (ia->dadcounter >= IDGEN_RETRIES) {
862 logerrx("%s: unable to obtain a"
863 " stable private address",
867 loginfox("%s: deleting address %s",
868 ifp->name, ia->saddr);
869 if (if_address6(RTM_DELADDR, ia) == -1 &&
870 errno != EADDRNOTAVAIL && errno != ENXIO)
872 dadcounter = ia->dadcounter;
873 if (ipv6_makestableprivate(&ia->addr,
874 &ia->prefix, ia->prefix_len,
875 ifp, &dadcounter) == -1)
877 logerr("ipv6_makestableprivate");
880 ia->dadcounter = dadcounter;
881 ia->flags &= ~(IPV6_AF_ADDED | IPV6_AF_DADCOMPLETED);
882 ia->flags |= IPV6_AF_NEW;
883 p = inet_ntop(AF_INET6, &ia->addr, buf, sizeof(buf));
892 tv.tv_nsec = (suseconds_t)
893 arc4random_uniform(IDGEN_DELAY * NSEC_PER_SEC);
895 eloop_timeout_add_tv(ifp->ctx->eloop, &tv,
903 TAILQ_FOREACH(rap, ifp->ctx->ra_routers, next) {
904 if (rap->iface != ifp)
908 TAILQ_FOREACH(rapap, &rap->addrs, next) {
909 if (rapap->flags & IPV6_AF_AUTOCONF &&
910 rapap->flags & IPV6_AF_ADDED &&
911 (rapap->flags & IPV6_AF_DADCOMPLETED) == 0)
920 if (wascompleted && found) {
921 logdebugx("%s: Router Advertisement DAD "
924 if (ipv6nd_scriptrun(rap))
929 ipv6nd_advertise(ia);
935 /* If DHCPv6 is compiled out, supply a shim to provide an error message
936 * if IPv6RA requests DHCPv6. */
942 dhcp6_start(__unused struct interface *ifp, __unused enum DH6S init_state)
951 ipv6nd_handlera(struct dhcpcd_ctx *ctx,
952 const struct sockaddr_in6 *from, const char *sfrom,
953 struct interface *ifp, struct icmp6_hdr *icp, size_t len, int hoplimit)
956 struct nd_router_advert *nd_ra;
957 struct nd_opt_hdr ndo;
958 struct nd_opt_prefix_info pi;
959 struct nd_opt_mtu mtu;
960 struct nd_opt_rdnss rdnss;
963 struct in6_addr pi_prefix;
964 struct ipv6_addr *ap;
965 struct dhcp_opt *dho;
966 bool new_rap, new_data, has_address;
967 uint32_t old_lifetime;
968 __printflike(1, 2) void (*logfunc)(const char *, ...);
969 #ifdef IPV6_MANAGETEMPADDR
975 logdebugx("RA for unexpected interface from %s", sfrom);
980 if (len < sizeof(struct nd_router_advert)) {
981 logerrx("IPv6 RA packet too short from %s", sfrom);
986 if (hoplimit != 255) {
987 logerrx("invalid hoplimit(%d) in RA from %s", hoplimit, sfrom);
990 if (!IN6_IS_ADDR_LINKLOCAL(&from->sin6_addr)) {
991 logerrx("RA from non local address %s", sfrom);
995 if (!(ifp->options->options & DHCPCD_IPV6RS)) {
997 logerrx("%s: unexpected RA from %s", ifp->name, sfrom);
1002 /* We could receive a RA before we sent a RS*/
1003 if (ipv6_linklocal(ifp) == NULL) {
1005 logdebugx("%s: received RA from %s (no link-local)",
1011 if (ipv6_iffindaddr(ifp, &from->sin6_addr, IN6_IFF_TENTATIVE)) {
1012 logdebugx("%s: ignoring RA from ourself %s",
1017 TAILQ_FOREACH(rap, ctx->ra_routers, next) {
1018 if (ifp == rap->iface &&
1019 IN6_ARE_ADDR_EQUAL(&rap->from, &from->sin6_addr))
1023 nd_ra = (struct nd_router_advert *)icp;
1025 /* We don't want to spam the log with the fact we got an RA every
1026 * 30 seconds or so, so only spam the log if it's different. */
1027 if (rap == NULL || (rap->data_len != len ||
1028 memcmp(rap->data, (unsigned char *)icp, rap->data_len) != 0))
1038 rap = calloc(1, sizeof(*rap));
1044 rap->from = from->sin6_addr;
1045 strlcpy(rap->sfrom, sfrom, sizeof(rap->sfrom));
1046 TAILQ_INIT(&rap->addrs);
1048 rap->isreachable = true;
1051 if (rap->data_len == 0) {
1052 rap->data = malloc(len);
1053 if (rap->data == NULL) {
1059 memcpy(rap->data, icp, len);
1060 rap->data_len = len;
1063 /* We could change the debug level based on new_data, but some
1064 * routers like to decrease the advertised valid and preferred times
1065 * in accordance with the own prefix times which would result in too
1066 * much needless log spam. */
1067 logfunc = new_data || !rap->isreachable ? loginfox : logdebugx,
1068 logfunc("%s: Router Advertisement from %s", ifp->name, rap->sfrom);
1070 clock_gettime(CLOCK_MONOTONIC, &rap->acquired);
1071 rap->flags = nd_ra->nd_ra_flags_reserved;
1072 old_lifetime = rap->lifetime;
1073 rap->lifetime = ntohs(nd_ra->nd_ra_router_lifetime);
1074 if (!new_rap && rap->lifetime == 0 && old_lifetime != 0)
1075 logwarnx("%s: %s: no longer a default router",
1076 ifp->name, rap->sfrom);
1077 if (nd_ra->nd_ra_reachable) {
1078 rap->reachable = ntohl(nd_ra->nd_ra_reachable);
1079 if (rap->reachable > MAX_REACHABLE_TIME)
1082 if (nd_ra->nd_ra_retransmit) {
1083 struct rs_state *state = RS_STATE(ifp);
1085 state->retrans = rap->retrans = ntohl(nd_ra->nd_ra_retransmit);
1087 rap->expired = false;
1088 rap->hasdns = false;
1089 rap->isreachable = true;
1090 has_address = false;
1092 #ifdef IPV6_AF_TEMPORARY
1093 ipv6_markaddrsstale(ifp, IPV6_AF_TEMPORARY);
1095 TAILQ_FOREACH(ap, &rap->addrs, next) {
1096 ap->flags |= IPV6_AF_STALE;
1099 len -= sizeof(struct nd_router_advert);
1100 p = ((uint8_t *)icp) + sizeof(struct nd_router_advert);
1101 for (; len > 0; p += olen, len -= olen) {
1102 if (len < sizeof(ndo)) {
1103 logerrx("%s: short option", ifp->name);
1106 memcpy(&ndo, p, sizeof(ndo));
1107 olen = (size_t)ndo.nd_opt_len * 8;
1109 logerrx("%s: zero length option", ifp->name);
1113 logerrx("%s: option length exceeds message",
1118 if (has_option_mask(ifp->options->rejectmasknd,
1121 for (i = 0, dho = ctx->nd_opts;
1122 i < ctx->nd_opts_len;
1125 if (dho->option == ndo.nd_opt_type)
1129 logwarnx("%s: reject RA (option %s) from %s",
1130 ifp->name, dho->var, rap->sfrom);
1132 logwarnx("%s: reject RA (option %d) from %s",
1133 ifp->name, ndo.nd_opt_type, rap->sfrom);
1135 ipv6nd_removefreedrop_ra(rap, 0, 0);
1137 ipv6nd_free_ra(rap);
1141 if (has_option_mask(ifp->options->nomasknd, ndo.nd_opt_type))
1144 switch (ndo.nd_opt_type) {
1145 case ND_OPT_PREFIX_INFORMATION:
1146 logfunc = new_data ? logerrx : logdebugx;
1147 if (ndo.nd_opt_len != 4) {
1148 logfunc("%s: invalid option len for prefix",
1152 memcpy(&pi, p, sizeof(pi));
1153 if (pi.nd_opt_pi_prefix_len > 128) {
1154 logfunc("%s: invalid prefix len", ifp->name);
1157 /* nd_opt_pi_prefix is not aligned. */
1158 memcpy(&pi_prefix, &pi.nd_opt_pi_prefix,
1160 if (IN6_IS_ADDR_MULTICAST(&pi_prefix) ||
1161 IN6_IS_ADDR_LINKLOCAL(&pi_prefix))
1163 logfunc("%s: invalid prefix in RA", ifp->name);
1166 if (ntohl(pi.nd_opt_pi_preferred_time) >
1167 ntohl(pi.nd_opt_pi_valid_time))
1169 logfunc("%s: pltime > vltime", ifp->name);
1172 TAILQ_FOREACH(ap, &rap->addrs, next)
1173 if (ap->prefix_len ==pi.nd_opt_pi_prefix_len &&
1174 IN6_ARE_ADDR_EQUAL(&ap->prefix, &pi_prefix))
1179 flags = IPV6_AF_RAPFX;
1180 if (pi.nd_opt_pi_flags_reserved &
1181 ND_OPT_PI_FLAG_AUTO &&
1182 rap->iface->options->options &
1183 DHCPCD_IPV6RA_AUTOCONF)
1184 flags |= IPV6_AF_AUTOCONF;
1186 ap = ipv6_newaddr(rap->iface,
1187 &pi_prefix, pi.nd_opt_pi_prefix_len, flags);
1190 ap->prefix = pi_prefix;
1191 if (flags & IPV6_AF_AUTOCONF)
1192 ap->dadcallback = ipv6nd_dadcallback;
1193 ap->created = ap->acquired = rap->acquired;
1194 TAILQ_INSERT_TAIL(&rap->addrs, ap, next);
1196 #ifdef IPV6_MANAGETEMPADDR
1197 /* New address to dhcpcd RA handling.
1198 * If the address already exists and a valid
1199 * temporary address also exists then
1200 * extend the existing one rather than
1201 * create a new one */
1202 if (flags & IPV6_AF_AUTOCONF &&
1203 ipv6_iffindaddr(ifp, &ap->addr,
1204 IN6_IFF_NOTUSEABLE) &&
1205 ipv6_settemptime(ap, 0))
1211 #ifdef IPV6_MANAGETEMPADDR
1214 ap->flags &= ~IPV6_AF_STALE;
1215 ap->acquired = rap->acquired;
1217 if (pi.nd_opt_pi_flags_reserved &
1218 ND_OPT_PI_FLAG_ONLINK)
1219 ap->flags |= IPV6_AF_ONLINK;
1221 ntohl(pi.nd_opt_pi_valid_time);
1223 ntohl(pi.nd_opt_pi_preferred_time);
1224 if (ap->prefix_vltime != 0 &&
1225 ap->flags & IPV6_AF_AUTOCONF)
1228 #ifdef IPV6_MANAGETEMPADDR
1229 /* RFC4941 Section 3.3.3 */
1230 if (ap->flags & IPV6_AF_AUTOCONF &&
1231 ip6_use_tempaddr(ap->iface->name))
1234 if (ipv6_settemptime(ap, 1) == NULL)
1237 if (new_ap && ap->prefix_pltime) {
1238 if (ipv6_createtempaddr(ap,
1239 &ap->acquired) == NULL)
1240 logerr("ipv6_createtempaddr");
1247 if (len < sizeof(mtu)) {
1248 logerrx("%s: short MTU option", ifp->name);
1251 memcpy(&mtu, p, sizeof(mtu));
1252 mtu.nd_opt_mtu_mtu = ntohl(mtu.nd_opt_mtu_mtu);
1253 if (mtu.nd_opt_mtu_mtu < IPV6_MMTU) {
1254 logerrx("%s: invalid MTU %d",
1255 ifp->name, mtu.nd_opt_mtu_mtu);
1258 rap->mtu = mtu.nd_opt_mtu_mtu;
1262 if (len < sizeof(rdnss)) {
1263 logerrx("%s: short RDNSS option", ifp->name);
1266 memcpy(&rdnss, p, sizeof(rdnss));
1267 if (rdnss.nd_opt_rdnss_lifetime &&
1268 rdnss.nd_opt_rdnss_len > 1)
1276 for (i = 0, dho = ctx->nd_opts;
1277 i < ctx->nd_opts_len;
1280 if (has_option_mask(ifp->options->requiremasknd,
1283 logwarnx("%s: reject RA (no option %s) from %s",
1284 ifp->name, dho->var, rap->sfrom);
1286 ipv6nd_removefreedrop_ra(rap, 0, 0);
1288 ipv6nd_free_ra(rap);
1293 if (new_data && !has_address && rap->lifetime && !ipv6_ifanyglobal(ifp))
1294 logwarnx("%s: no global addresses for default route",
1298 add_router(ifp->ctx, rap);
1300 if (ifp->ctx->options & DHCPCD_TEST) {
1301 script_runreason(ifp, "TEST");
1304 ipv6_addaddrs(&rap->addrs);
1305 #ifdef IPV6_MANAGETEMPADDR
1306 ipv6_addtempaddrs(ifp, &rap->acquired);
1309 rt_build(ifp->ctx, AF_INET6);
1310 if (ipv6nd_scriptrun(rap))
1313 eloop_timeout_delete(ifp->ctx->eloop, NULL, ifp);
1314 eloop_timeout_delete(ifp->ctx->eloop, NULL, rap); /* reachable timer */
1317 if (!(ifp->options->options & DHCPCD_DHCP6))
1319 /* Only log a DHCPv6 start error if compiled in or debugging is enabled. */
1321 #define LOG_DHCP6 logerr
1323 #define LOG_DHCP6 logdebug
1325 if (rap->flags & ND_RA_FLAG_MANAGED) {
1326 if (new_data && dhcp6_start(ifp, DH6S_REQUEST) == -1)
1327 LOG_DHCP6("dhcp6_start: %s", ifp->name);
1328 } else if (rap->flags & ND_RA_FLAG_OTHER) {
1329 if (new_data && dhcp6_start(ifp, DH6S_INFORM) == -1)
1330 LOG_DHCP6("dhcp6_start: %s", ifp->name);
1334 logdebugx("%s: No DHCPv6 instruction in RA", ifp->name);
1337 if (ifp->ctx->options & DHCPCD_TEST) {
1338 eloop_exit(ifp->ctx->eloop, EXIT_SUCCESS);
1343 /* Expire should be called last as the rap object could be destroyed */
1344 ipv6nd_expirera(ifp);
1348 ipv6nd_hasralifetime(const struct interface *ifp, bool lifetime)
1350 const struct ra *rap;
1352 if (ifp->ctx->ra_routers) {
1353 TAILQ_FOREACH(rap, ifp->ctx->ra_routers, next)
1354 if (rap->iface == ifp && !rap->expired &&
1355 (!lifetime ||rap->lifetime))
1362 ipv6nd_hasradhcp(const struct interface *ifp)
1364 const struct ra *rap;
1366 if (ifp->ctx->ra_routers) {
1367 TAILQ_FOREACH(rap, ifp->ctx->ra_routers, next) {
1368 if (rap->iface == ifp &&
1370 (rap->flags &(ND_RA_FLAG_MANAGED|ND_RA_FLAG_OTHER)))
1377 static const uint8_t *
1378 ipv6nd_getoption(struct dhcpcd_ctx *ctx,
1379 size_t *os, unsigned int *code, size_t *len,
1380 const uint8_t *od, size_t ol, struct dhcp_opt **oopt)
1382 struct nd_opt_hdr ndo;
1384 struct dhcp_opt *opt;
1392 memcpy(&ndo, od, sizeof(ndo));
1393 i = (size_t)(ndo.nd_opt_len * 8);
1399 *code = ndo.nd_opt_type;
1402 for (i = 0, opt = ctx->nd_opts;
1403 i < ctx->nd_opts_len; i++, opt++)
1405 if (opt->option == *code) {
1412 return od + sizeof(ndo);
1417 ipv6nd_env(FILE *fp, const struct interface *ifp)
1419 size_t i, j, n, len, olen;
1422 struct dhcp_opt *opt;
1424 struct nd_opt_hdr ndo;
1425 struct ipv6_addr *ia;
1426 struct timespec now;
1428 clock_gettime(CLOCK_MONOTONIC, &now);
1430 TAILQ_FOREACH(rap, ifp->ctx->ra_routers, next) {
1431 if (rap->iface != ifp || rap->expired)
1434 snprintf(ndprefix, sizeof(ndprefix), "nd%zu", i);
1435 if (efprintf(fp, "%s_from=%s", ndprefix, rap->sfrom) == -1)
1437 if (efprintf(fp, "%s_acquired=%lld", ndprefix,
1438 (long long)rap->acquired.tv_sec) == -1)
1440 if (efprintf(fp, "%s_now=%lld", ndprefix,
1441 (long long)now.tv_sec) == -1)
1444 /* Zero our indexes */
1445 for (j = 0, opt = rap->iface->ctx->nd_opts;
1446 j < rap->iface->ctx->nd_opts_len;
1448 dhcp_zero_index(opt);
1449 for (j = 0, opt = rap->iface->options->nd_override;
1450 j < rap->iface->options->nd_override_len;
1452 dhcp_zero_index(opt);
1454 /* Unlike DHCP, ND6 options *may* occur more than once.
1455 * There is also no provision for option concatenation
1457 len = rap->data_len - sizeof(struct nd_router_advert);
1458 for (p = rap->data + sizeof(struct nd_router_advert);
1460 p += olen, len -= olen)
1462 memcpy(&ndo, p, sizeof(ndo));
1463 olen = (size_t)(ndo.nd_opt_len * 8);
1468 if (has_option_mask(rap->iface->options->nomasknd,
1471 for (j = 0, opt = rap->iface->options->nd_override;
1472 j < rap->iface->options->nd_override_len;
1474 if (opt->option == ndo.nd_opt_type)
1476 if (j == rap->iface->options->nd_override_len) {
1477 for (j = 0, opt = rap->iface->ctx->nd_opts;
1478 j < rap->iface->ctx->nd_opts_len;
1480 if (opt->option == ndo.nd_opt_type)
1482 if (j == rap->iface->ctx->nd_opts_len)
1487 dhcp_envoption(rap->iface->ctx, fp,
1488 ndprefix, rap->iface->name,
1489 opt, ipv6nd_getoption,
1490 p + sizeof(ndo), olen - sizeof(ndo));
1493 /* We need to output the addresses we actually made
1494 * from the prefix information options as well. */
1496 TAILQ_FOREACH(ia, &rap->addrs, next) {
1497 if (!(ia->flags & IPV6_AF_AUTOCONF) ||
1498 #ifdef IPV6_AF_TEMPORARY
1499 ia->flags & IPV6_AF_TEMPORARY ||
1501 !(ia->flags & IPV6_AF_ADDED) ||
1502 ia->prefix_vltime == 0)
1504 if (efprintf(fp, "%s_addr%zu=%s",
1505 ndprefix, j++, ia->saddr) == -1)
1513 ipv6nd_handleifa(int cmd, struct ipv6_addr *addr, pid_t pid)
1517 /* IPv6 init may not have happened yet if we are learning
1518 * existing addresses when dhcpcd starts. */
1519 if (addr->iface->ctx->ra_routers == NULL)
1522 TAILQ_FOREACH(rap, addr->iface->ctx->ra_routers, next) {
1523 if (rap->iface != addr->iface)
1525 ipv6_handleifa_addrs(cmd, &rap->addrs, addr, pid);
1530 ipv6nd_expirera(void *arg)
1532 struct interface *ifp;
1533 struct ra *rap, *ran;
1534 struct timespec now, lt, expire, next;
1535 bool expired, valid;
1536 struct ipv6_addr *ia;
1539 struct nd_opt_hdr ndo;
1541 struct nd_opt_prefix_info pi;
1543 struct nd_opt_dnssl dnssl;
1544 struct nd_opt_rdnss rdnss;
1546 size_t nexpired = 0;
1549 clock_gettime(CLOCK_MONOTONIC, &now);
1551 timespecclear(&next);
1553 TAILQ_FOREACH_SAFE(rap, ifp->ctx->ra_routers, next, ran) {
1554 if (rap->iface != ifp || rap->expired)
1557 if (rap->lifetime) {
1558 lt.tv_sec = (time_t)rap->lifetime;
1560 timespecadd(&rap->acquired, <, &expire);
1561 if (timespeccmp(&now, &expire, >)) {
1562 if (!rap->expired) {
1563 logwarnx("%s: %s: router expired",
1564 ifp->name, rap->sfrom);
1570 timespecsub(&expire, &now, <);
1571 if (!timespecisset(&next) ||
1572 timespeccmp(&next, <, >))
1577 /* Not every prefix is tied to an address which
1578 * the kernel can expire, so we need to handle it ourself.
1579 * Also, some OS don't support address lifetimes (Solaris). */
1580 TAILQ_FOREACH(ia, &rap->addrs, next) {
1581 if (ia->prefix_vltime == 0)
1583 if (ia->prefix_vltime == ND6_INFINITE_LIFETIME) {
1587 lt.tv_sec = (time_t)ia->prefix_vltime;
1589 timespecadd(&ia->acquired, <, &expire);
1590 if (timespeccmp(&now, &expire, >)) {
1591 if (ia->flags & IPV6_AF_ADDED) {
1592 logwarnx("%s: expired address %s",
1593 ia->iface->name, ia->saddr);
1594 if (if_address6(RTM_DELADDR, ia)== -1 &&
1595 errno != EADDRNOTAVAIL &&
1599 ia->prefix_vltime = ia->prefix_pltime = 0;
1601 ~(IPV6_AF_ADDED | IPV6_AF_DADCOMPLETED);
1604 timespecsub(&expire, &now, <);
1605 if (!timespecisset(&next) ||
1606 timespeccmp(&next, <, >))
1612 /* Work out expiry for ND options */
1613 len = rap->data_len - sizeof(struct nd_router_advert);
1614 for (p = rap->data + sizeof(struct nd_router_advert);
1616 p += olen, len -= olen)
1618 memcpy(&ndo, p, sizeof(ndo));
1619 olen = (size_t)(ndo.nd_opt_len * 8);
1625 if (has_option_mask(rap->iface->options->nomasknd,
1629 switch (ndo.nd_opt_type) {
1630 /* Prefix info is already checked in the above loop. */
1632 case ND_OPT_PREFIX_INFORMATION:
1633 if (len < sizeof(pi))
1635 memcpy(&pi, p, sizeof(pi));
1636 ltime = pi.nd_opt_pi_valid_time;
1640 if (len < sizeof(dnssl))
1642 memcpy(&dnssl, p, sizeof(dnssl));
1643 ltime = dnssl.nd_opt_dnssl_lifetime;
1646 if (len < sizeof(rdnss))
1648 memcpy(&rdnss, p, sizeof(rdnss));
1649 ltime = rdnss.nd_opt_rdnss_lifetime;
1657 if (ltime == ND6_INFINITE_LIFETIME) {
1662 lt.tv_sec = (time_t)ntohl(ltime);
1664 timespecadd(&rap->acquired, <, &expire);
1665 if (timespeccmp(&now, &expire, >)) {
1670 timespecsub(&expire, &now, <);
1671 if (!timespecisset(&next) ||
1672 timespeccmp(&next, <, >))
1682 /* Router has expired. Let's not keep a lot of them. */
1683 rap->expired = true;
1684 if (++nexpired > EXPIRED_MAX)
1685 ipv6nd_free_ra(rap);
1688 if (timespecisset(&next))
1689 eloop_timeout_add_tv(ifp->ctx->eloop,
1690 &next, ipv6nd_expirera, ifp);
1692 logwarnx("%s: part of Router Advertisement expired", ifp->name);
1693 rt_build(ifp->ctx, AF_INET6);
1694 script_runreason(ifp, "ROUTERADVERT");
1699 ipv6nd_drop(struct interface *ifp)
1701 struct ra *rap, *ran;
1702 bool expired = false;
1704 if (ifp->ctx->ra_routers == NULL)
1707 eloop_timeout_delete(ifp->ctx->eloop, NULL, ifp);
1708 TAILQ_FOREACH_SAFE(rap, ifp->ctx->ra_routers, next, ran) {
1709 if (rap->iface == ifp) {
1710 rap->expired = expired = true;
1711 ipv6nd_drop_ra(rap);
1715 rt_build(ifp->ctx, AF_INET6);
1716 if ((ifp->options->options & DHCPCD_NODROP) != DHCPCD_NODROP)
1717 script_runreason(ifp, "ROUTERADVERT");
1722 ipv6nd_handledata(void *arg)
1724 struct dhcpcd_ctx *ctx;
1726 struct sockaddr_in6 from;
1727 unsigned char buf[64 * 1024]; /* Maximum ICMPv6 size */
1728 struct iovec iov = {
1730 .iov_len = sizeof(buf),
1732 unsigned char ctl[CMSG_SPACE(sizeof(struct in6_pktinfo)) + CMSG_SPACE(sizeof(int))] = { 0 };
1733 struct msghdr msg = {
1734 .msg_name = &from, .msg_namelen = sizeof(from),
1735 .msg_iov = &iov, .msg_iovlen = 1,
1736 .msg_control = ctl, .msg_controllen = sizeof(ctl),
1739 char sfrom[INET6_ADDRSTRLEN];
1741 struct icmp6_hdr *icp;
1742 struct interface *ifp;
1745 struct rs_state *state;
1748 state = RS_STATE(ifp);
1755 len = recvmsg(s, &msg, 0);
1760 inet_ntop(AF_INET6, &from.sin6_addr, sfrom, sizeof(sfrom));
1761 if ((size_t)len < sizeof(struct icmp6_hdr)) {
1762 logerrx("IPv6 ICMP packet too short from %s", sfrom);
1767 if_findifpfromcmsg(ctx, &msg, &hoplimit);
1769 ifp = if_findifpfromcmsg(ctx, &msg, &hoplimit);
1776 /* Don't do anything if the user hasn't configured it. */
1777 if (ifp->active != IF_ACTIVE_USER ||
1778 !(ifp->options->options & DHCPCD_IPV6))
1781 icp = (struct icmp6_hdr *)buf;
1782 if (icp->icmp6_code == 0) {
1783 switch(icp->icmp6_type) {
1784 case ND_ROUTER_ADVERT:
1785 ipv6nd_handlera(ctx, &from, sfrom,
1786 ifp, icp, (size_t)len, hoplimit);
1791 logerrx("invalid IPv6 type %d or code %d from %s",
1792 icp->icmp6_type, icp->icmp6_code, sfrom);
1796 ipv6nd_startrs1(void *arg)
1798 struct interface *ifp = arg;
1799 struct rs_state *state;
1801 loginfox("%s: soliciting an IPv6 router", ifp->name);
1802 state = RS_STATE(ifp);
1803 if (state == NULL) {
1804 ifp->if_data[IF_DATA_IPV6ND] = calloc(1, sizeof(*state));
1805 state = RS_STATE(ifp);
1806 if (state == NULL) {
1816 if (ipv6nd_open(ifp) == -1) {
1821 if (ipv6nd_open(ifp->ctx) == -1) {
1827 /* Always make a new probe as the underlying hardware
1828 * address could have changed. */
1829 ipv6nd_makersprobe(ifp);
1830 if (state->rs == NULL) {
1835 state->retrans = RETRANS_TIMER;
1836 state->rsprobes = 0;
1837 ipv6nd_sendrsprobe(ifp);
1841 ipv6nd_startrs(struct interface *ifp)
1845 eloop_timeout_delete(ifp->ctx->eloop, NULL, ifp);
1846 if (!(ifp->options->options & DHCPCD_INITIAL_DELAY)) {
1847 ipv6nd_startrs1(ifp);
1852 tv.tv_nsec = (suseconds_t)arc4random_uniform(
1853 MAX_RTR_SOLICITATION_DELAY * NSEC_PER_SEC);
1855 logdebugx("%s: delaying IPv6 router solicitation for %0.1f seconds",
1856 ifp->name, timespec_to_double(&tv));
1857 eloop_timeout_add_tv(ifp->ctx->eloop, &tv, ipv6nd_startrs1, ifp);