Update to dhcpcd-9.2.0 with the following changes:
[dragonfly.git] / contrib / dhcpcd / src / ipv6nd.c
blobd1cc4efab7732e17500f4823352b45fdabaa8019
1 /* SPDX-License-Identifier: BSD-2-Clause */
2 /*
3 * dhcpcd - IPv6 ND handling
4 * Copyright (c) 2006-2020 Roy Marples <roy@marples.name>
5 * All rights reserved
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
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
26 * SUCH DAMAGE.
29 #include <sys/ioctl.h>
30 #include <sys/param.h>
31 #include <sys/socket.h>
32 #include <net/if.h>
33 #include <net/route.h>
34 #include <netinet/in.h>
35 #include <netinet/ip6.h>
36 #include <netinet/icmp6.h>
38 #include <assert.h>
39 #include <errno.h>
40 #include <fcntl.h>
41 #include <stddef.h>
42 #include <stdlib.h>
43 #include <string.h>
44 #include <syslog.h>
45 #include <unistd.h>
47 #define ELOOP_QUEUE ELOOP_IPV6ND
48 #include "common.h"
49 #include "dhcpcd.h"
50 #include "dhcp-common.h"
51 #include "dhcp6.h"
52 #include "eloop.h"
53 #include "if.h"
54 #include "ipv6.h"
55 #include "ipv6nd.h"
56 #include "logerr.h"
57 #include "privsep.h"
58 #include "route.h"
59 #include "script.h"
61 /* Debugging Router Solicitations is a lot of spam, so disable it */
62 //#define DEBUG_RS
64 #ifndef ND_RA_FLAG_HOME_AGENT
65 #define ND_RA_FLAG_HOME_AGENT 0x20 /* Home Agent flag in RA */
66 #endif
67 #ifndef ND_RA_FLAG_PROXY
68 #define ND_RA_FLAG_PROXY 0x04 /* Proxy */
69 #endif
70 #ifndef ND_OPT_PI_FLAG_ROUTER
71 #define ND_OPT_PI_FLAG_ROUTER 0x20 /* Router flag in PI */
72 #endif
74 #ifndef ND_OPT_RDNSS
75 #define ND_OPT_RDNSS 25
76 struct nd_opt_rdnss { /* RDNSS option RFC 6106 */
77 uint8_t nd_opt_rdnss_type;
78 uint8_t nd_opt_rdnss_len;
79 uint16_t nd_opt_rdnss_reserved;
80 uint32_t nd_opt_rdnss_lifetime;
81 /* followed by list of IP prefixes */
83 __CTASSERT(sizeof(struct nd_opt_rdnss) == 8);
84 #endif
86 #ifndef ND_OPT_DNSSL
87 #define ND_OPT_DNSSL 31
88 struct nd_opt_dnssl { /* DNSSL option RFC 6106 */
89 uint8_t nd_opt_dnssl_type;
90 uint8_t nd_opt_dnssl_len;
91 uint16_t nd_opt_dnssl_reserved;
92 uint32_t nd_opt_dnssl_lifetime;
93 /* followed by list of DNS servers */
95 __CTASSERT(sizeof(struct nd_opt_rdnss) == 8);
96 #endif
98 /* Impossible options, so we can easily add extras */
99 #define _ND_OPT_PREFIX_ADDR 255 + 1
101 /* Minimal IPv6 MTU */
102 #ifndef IPV6_MMTU
103 #define IPV6_MMTU 1280
104 #endif
106 #ifndef ND_RA_FLAG_RTPREF_HIGH
107 #define ND_RA_FLAG_RTPREF_MASK 0x18
108 #define ND_RA_FLAG_RTPREF_HIGH 0x08
109 #define ND_RA_FLAG_RTPREF_MEDIUM 0x00
110 #define ND_RA_FLAG_RTPREF_LOW 0x18
111 #define ND_RA_FLAG_RTPREF_RSV 0x10
112 #endif
114 #define EXPIRED_MAX 5 /* Remember 5 expired routers to avoid
115 logspam. */
117 #define MIN_RANDOM_FACTOR 500 /* millisecs */
118 #define MAX_RANDOM_FACTOR 1500 /* millisecs */
119 #define MIN_RANDOM_FACTOR_U MIN_RANDOM_FACTOR * 1000 /* usecs */
120 #define MAX_RANDOM_FACTOR_U MAX_RANDOM_FACTOR * 1000 /* usecs */
122 #if BYTE_ORDER == BIG_ENDIAN
123 #define IPV6_ADDR_INT32_ONE 1
124 #define IPV6_ADDR_INT16_MLL 0xff02
125 #elif BYTE_ORDER == LITTLE_ENDIAN
126 #define IPV6_ADDR_INT32_ONE 0x01000000
127 #define IPV6_ADDR_INT16_MLL 0x02ff
128 #endif
130 /* Debugging Neighbor Solicitations is a lot of spam, so disable it */
131 //#define DEBUG_NS
134 static void ipv6nd_handledata(void *);
137 * Android ships buggy ICMP6 filter headers.
138 * Supply our own until they fix their shit.
139 * References:
140 * https://android-review.googlesource.com/#/c/58438/
141 * http://code.google.com/p/android/issues/original?id=32621&seq=24
143 #ifdef __ANDROID__
144 #undef ICMP6_FILTER_WILLPASS
145 #undef ICMP6_FILTER_WILLBLOCK
146 #undef ICMP6_FILTER_SETPASS
147 #undef ICMP6_FILTER_SETBLOCK
148 #undef ICMP6_FILTER_SETPASSALL
149 #undef ICMP6_FILTER_SETBLOCKALL
150 #define ICMP6_FILTER_WILLPASS(type, filterp) \
151 ((((filterp)->icmp6_filt[(type) >> 5]) & (1 << ((type) & 31))) == 0)
152 #define ICMP6_FILTER_WILLBLOCK(type, filterp) \
153 ((((filterp)->icmp6_filt[(type) >> 5]) & (1 << ((type) & 31))) != 0)
154 #define ICMP6_FILTER_SETPASS(type, filterp) \
155 ((((filterp)->icmp6_filt[(type) >> 5]) &= ~(1 << ((type) & 31))))
156 #define ICMP6_FILTER_SETBLOCK(type, filterp) \
157 ((((filterp)->icmp6_filt[(type) >> 5]) |= (1 << ((type) & 31))))
158 #define ICMP6_FILTER_SETPASSALL(filterp) \
159 memset(filterp, 0, sizeof(struct icmp6_filter));
160 #define ICMP6_FILTER_SETBLOCKALL(filterp) \
161 memset(filterp, 0xff, sizeof(struct icmp6_filter));
162 #endif
164 /* Support older systems with different defines */
165 #if !defined(IPV6_RECVHOPLIMIT) && defined(IPV6_HOPLIMIT)
166 #define IPV6_RECVHOPLIMIT IPV6_HOPLIMIT
167 #endif
168 #if !defined(IPV6_RECVPKTINFO) && defined(IPV6_PKTINFO)
169 #define IPV6_RECVPKTINFO IPV6_PKTINFO
170 #endif
172 /* Handy defines */
173 #define ipv6nd_free_ra(ra) ipv6nd_freedrop_ra((ra), 0)
174 #define ipv6nd_drop_ra(ra) ipv6nd_freedrop_ra((ra), 1)
176 void
177 ipv6nd_printoptions(const struct dhcpcd_ctx *ctx,
178 const struct dhcp_opt *opts, size_t opts_len)
180 size_t i, j;
181 const struct dhcp_opt *opt, *opt2;
182 int cols;
184 for (i = 0, opt = ctx->nd_opts;
185 i < ctx->nd_opts_len; i++, opt++)
187 for (j = 0, opt2 = opts; j < opts_len; j++, opt2++)
188 if (opt2->option == opt->option)
189 break;
190 if (j == opts_len) {
191 cols = printf("%03d %s", opt->option, opt->var);
192 dhcp_print_option_encoding(opt, cols);
195 for (i = 0, opt = opts; i < opts_len; i++, opt++) {
196 cols = printf("%03d %s", opt->option, opt->var);
197 dhcp_print_option_encoding(opt, cols);
202 ipv6nd_open(bool recv)
204 int fd, on;
205 struct icmp6_filter filt;
207 fd = xsocket(PF_INET6, SOCK_RAW | SOCK_CXNB, IPPROTO_ICMPV6);
208 if (fd == -1)
209 return -1;
211 ICMP6_FILTER_SETBLOCKALL(&filt);
213 /* RFC4861 4.1 */
214 on = 255;
215 if (setsockopt(fd, IPPROTO_IPV6, IPV6_MULTICAST_HOPS,
216 &on, sizeof(on)) == -1)
217 goto eexit;
219 if (recv) {
220 on = 1;
221 if (setsockopt(fd, IPPROTO_IPV6, IPV6_RECVPKTINFO,
222 &on, sizeof(on)) == -1)
223 goto eexit;
225 on = 1;
226 if (setsockopt(fd, IPPROTO_IPV6, IPV6_RECVHOPLIMIT,
227 &on, sizeof(on)) == -1)
228 goto eexit;
230 ICMP6_FILTER_SETPASS(ND_ROUTER_ADVERT, &filt);
232 #ifdef SO_RERROR
233 on = 1;
234 if (setsockopt(fd, SOL_SOCKET, SO_RERROR,
235 &on, sizeof(on)) == -1)
236 goto eexit;
237 #endif
240 if (setsockopt(fd, IPPROTO_ICMPV6, ICMP6_FILTER,
241 &filt, sizeof(filt)) == -1)
242 goto eexit;
244 return fd;
246 eexit:
247 close(fd);
248 return -1;
251 #ifdef __sun
253 ipv6nd_openif(struct interface *ifp)
255 int fd;
256 struct ipv6_mreq mreq = {
257 .ipv6mr_multiaddr = IN6ADDR_LINKLOCAL_ALLNODES_INIT,
258 .ipv6mr_interface = ifp->index
260 struct rs_state *state = RS_STATE(ifp);
261 uint_t ifindex = ifp->index;
263 if (state->nd_fd != -1)
264 return state->nd_fd;
266 fd = ipv6nd_open(true);
267 if (fd == -1)
268 return -1;
270 if (setsockopt(fd, IPPROTO_IPV6, IPV6_BOUND_IF,
271 &ifindex, sizeof(ifindex)) == -1)
273 close(fd);
274 return -1;
277 if (setsockopt(fd, IPPROTO_IPV6, IPV6_JOIN_GROUP,
278 &mreq, sizeof(mreq)) == -1)
280 close(fd);
281 return -1;
284 state->nd_fd = fd;
285 eloop_event_add(ifp->ctx->eloop, fd, ipv6nd_handledata, ifp);
286 return fd;
288 #endif
290 static int
291 ipv6nd_makersprobe(struct interface *ifp)
293 struct rs_state *state;
294 struct nd_router_solicit *rs;
296 state = RS_STATE(ifp);
297 free(state->rs);
298 state->rslen = sizeof(*rs);
299 if (ifp->hwlen != 0)
300 state->rslen += (size_t)ROUNDUP8(ifp->hwlen + 2);
301 state->rs = calloc(1, state->rslen);
302 if (state->rs == NULL)
303 return -1;
304 rs = state->rs;
305 rs->nd_rs_type = ND_ROUTER_SOLICIT;
306 //rs->nd_rs_code = 0;
307 //rs->nd_rs_cksum = 0;
308 //rs->nd_rs_reserved = 0;
310 if (ifp->hwlen != 0) {
311 struct nd_opt_hdr *nd;
313 nd = (struct nd_opt_hdr *)(state->rs + 1);
314 nd->nd_opt_type = ND_OPT_SOURCE_LINKADDR;
315 nd->nd_opt_len = (uint8_t)((ROUNDUP8(ifp->hwlen + 2)) >> 3);
316 memcpy(nd + 1, ifp->hwaddr, ifp->hwlen);
318 return 0;
321 static void
322 ipv6nd_sendrsprobe(void *arg)
324 struct interface *ifp = arg;
325 struct rs_state *state = RS_STATE(ifp);
326 struct sockaddr_in6 dst = {
327 .sin6_family = AF_INET6,
328 .sin6_addr = IN6ADDR_LINKLOCAL_ALLROUTERS_INIT,
329 .sin6_scope_id = ifp->index,
331 struct iovec iov = { .iov_base = state->rs, .iov_len = state->rslen };
332 union {
333 struct cmsghdr hdr;
334 uint8_t buf[CMSG_SPACE(sizeof(struct in6_pktinfo))];
335 } cmsgbuf = { .buf = { 0 } };
336 struct msghdr msg = {
337 .msg_name = &dst, .msg_namelen = sizeof(dst),
338 .msg_iov = &iov, .msg_iovlen = 1,
339 .msg_control = cmsgbuf.buf, .msg_controllen = sizeof(cmsgbuf.buf),
341 struct cmsghdr *cm;
342 struct in6_pktinfo pi = { .ipi6_ifindex = ifp->index };
343 int s;
344 #ifndef __sun
345 struct dhcpcd_ctx *ctx = ifp->ctx;
346 #endif
348 if (ipv6_linklocal(ifp) == NULL) {
349 logdebugx("%s: delaying Router Solicitation for LL address",
350 ifp->name);
351 ipv6_addlinklocalcallback(ifp, ipv6nd_sendrsprobe, ifp);
352 return;
355 #ifdef HAVE_SA_LEN
356 dst.sin6_len = sizeof(dst);
357 #endif
359 /* Set the outbound interface */
360 cm = CMSG_FIRSTHDR(&msg);
361 if (cm == NULL) /* unlikely */
362 return;
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);
369 #ifdef PRIVSEP
370 if (IN_PRIVSEP(ifp->ctx)) {
371 if (ps_inet_sendnd(ifp, &msg) == -1)
372 logerr(__func__);
373 goto sent;
375 #endif
376 #ifdef __sun
377 if (state->nd_fd == -1) {
378 if (ipv6nd_openif(ifp) == -1) {
379 logerr(__func__);
380 return;
383 s = state->nd_fd;
384 #else
385 if (ctx->nd_fd == -1) {
386 ctx->nd_fd = ipv6nd_open(true);
387 if (ctx->nd_fd == -1) {
388 logerr(__func__);
389 return;
391 eloop_event_add(ctx->eloop, ctx->nd_fd, ipv6nd_handledata, ctx);
393 s = ifp->ctx->nd_fd;
394 #endif
395 if (sendmsg(s, &msg, 0) == -1) {
396 logerr(__func__);
397 /* Allow IPv6ND to continue .... at most a few errors
398 * would be logged.
399 * Generally the error is ENOBUFS when struggling to
400 * associate with an access point. */
403 #ifdef PRIVSEP
404 sent:
405 #endif
406 if (state->rsprobes++ < MAX_RTR_SOLICITATIONS)
407 eloop_timeout_add_sec(ifp->ctx->eloop,
408 RTR_SOLICITATION_INTERVAL, ipv6nd_sendrsprobe, ifp);
409 else
410 logwarnx("%s: no IPv6 Routers available", ifp->name);
413 #ifdef ND6_ADVERTISE
414 static void
415 ipv6nd_sendadvertisement(void *arg)
417 struct ipv6_addr *ia = arg;
418 struct interface *ifp = ia->iface;
419 struct dhcpcd_ctx *ctx = ifp->ctx;
420 struct sockaddr_in6 dst = {
421 .sin6_family = AF_INET6,
422 .sin6_addr = IN6ADDR_LINKLOCAL_ALLNODES_INIT,
423 .sin6_scope_id = ifp->index,
425 struct iovec iov = { .iov_base = ia->na, .iov_len = ia->na_len };
426 union {
427 struct cmsghdr hdr;
428 uint8_t buf[CMSG_SPACE(sizeof(struct in6_pktinfo))];
429 } cmsgbuf = { .buf = { 0 } };
430 struct msghdr msg = {
431 .msg_name = &dst, .msg_namelen = sizeof(dst),
432 .msg_iov = &iov, .msg_iovlen = 1,
433 .msg_control = cmsgbuf.buf, .msg_controllen = sizeof(cmsgbuf.buf),
435 struct cmsghdr *cm;
436 struct in6_pktinfo pi = { .ipi6_ifindex = ifp->index };
437 const struct rs_state *state = RS_CSTATE(ifp);
438 int s;
440 if (state == NULL || ifp->carrier <= LINK_DOWN)
441 goto freeit;
443 #ifdef SIN6_LEN
444 dst.sin6_len = sizeof(dst);
445 #endif
447 /* Set the outbound interface. */
448 cm = CMSG_FIRSTHDR(&msg);
449 assert(cm != NULL);
450 cm->cmsg_level = IPPROTO_IPV6;
451 cm->cmsg_type = IPV6_PKTINFO;
452 cm->cmsg_len = CMSG_LEN(sizeof(pi));
453 memcpy(CMSG_DATA(cm), &pi, sizeof(pi));
454 logdebugx("%s: sending NA for %s", ifp->name, ia->saddr);
456 #ifdef PRIVSEP
457 if (IN_PRIVSEP(ifp->ctx)) {
458 if (ps_inet_sendnd(ifp, &msg) == -1)
459 logerr(__func__);
460 goto sent;
462 #endif
463 #ifdef __sun
464 s = state->nd_fd;
465 #else
466 s = ctx->nd_fd;
467 #endif
468 if (sendmsg(s, &msg, 0) == -1)
469 logerr(__func__);
471 #ifdef PRIVSEP
472 sent:
473 #endif
474 if (++ia->na_count < MAX_NEIGHBOR_ADVERTISEMENT) {
475 eloop_timeout_add_sec(ctx->eloop,
476 state->retrans / 1000, ipv6nd_sendadvertisement, ia);
477 return;
480 freeit:
481 free(ia->na);
482 ia->na = NULL;
483 ia->na_count = 0;
486 void
487 ipv6nd_advertise(struct ipv6_addr *ia)
489 struct dhcpcd_ctx *ctx;
490 struct interface *ifp;
491 struct ipv6_state *state;
492 struct ipv6_addr *iap, *iaf;
493 struct nd_neighbor_advert *na;
495 if (IN6_IS_ADDR_MULTICAST(&ia->addr))
496 return;
498 #ifdef __sun
499 if (!(ia->flags & IPV6_AF_AUTOCONF) && ia->flags & IPV6_AF_RAPFX)
500 return;
501 #endif
503 ctx = ia->iface->ctx;
504 /* Find the most preferred address to advertise. */
505 iaf = NULL;
506 TAILQ_FOREACH(ifp, ctx->ifaces, next) {
507 state = IPV6_STATE(ifp);
508 if (state == NULL || ifp->carrier <= LINK_DOWN)
509 continue;
511 TAILQ_FOREACH(iap, &state->addrs, next) {
512 if (!IN6_ARE_ADDR_EQUAL(&iap->addr, &ia->addr))
513 continue;
515 /* Cancel any current advertisement. */
516 eloop_timeout_delete(ctx->eloop,
517 ipv6nd_sendadvertisement, iap);
519 /* Don't advertise what we can't use. */
520 if (iap->prefix_vltime == 0 ||
521 iap->addr_flags & IN6_IFF_NOTUSEABLE)
522 continue;
524 if (iaf == NULL ||
525 iaf->iface->metric > iap->iface->metric)
526 iaf = iap;
529 if (iaf == NULL)
530 return;
532 /* Make the packet. */
533 ifp = iaf->iface;
534 iaf->na_len = sizeof(*na);
535 if (ifp->hwlen != 0)
536 iaf->na_len += (size_t)ROUNDUP8(ifp->hwlen + 2);
537 na = calloc(1, iaf->na_len);
538 if (na == NULL) {
539 logerr(__func__);
540 return;
543 na->nd_na_type = ND_NEIGHBOR_ADVERT;
544 na->nd_na_flags_reserved = ND_NA_FLAG_OVERRIDE;
545 #if defined(PRIVSEP) && (defined(__linux__) || defined(HAVE_PLEDGE))
546 if (IN_PRIVSEP(ctx)) {
547 if (ps_root_ip6forwarding(ctx, ifp->name) != 0)
548 na->nd_na_flags_reserved |= ND_NA_FLAG_ROUTER;
549 } else
550 #endif
551 if (ip6_forwarding(ifp->name) != 0)
552 na->nd_na_flags_reserved |= ND_NA_FLAG_ROUTER;
553 na->nd_na_target = ia->addr;
555 if (ifp->hwlen != 0) {
556 struct nd_opt_hdr *opt;
558 opt = (struct nd_opt_hdr *)(na + 1);
559 opt->nd_opt_type = ND_OPT_TARGET_LINKADDR;
560 opt->nd_opt_len = (uint8_t)((ROUNDUP8(ifp->hwlen + 2)) >> 3);
561 memcpy(opt + 1, ifp->hwaddr, ifp->hwlen);
564 iaf->na_count = 0;
565 free(iaf->na);
566 iaf->na = na;
567 eloop_timeout_delete(ctx->eloop, ipv6nd_sendadvertisement, iaf);
568 ipv6nd_sendadvertisement(iaf);
570 #elif !defined(SMALL)
571 #warning kernel does not support userland sending ND6 advertisements
572 #endif /* ND6_ADVERTISE */
574 static void
575 ipv6nd_expire(void *arg)
577 struct interface *ifp = arg;
578 struct ra *rap;
580 if (ifp->ctx->ra_routers == NULL)
581 return;
583 TAILQ_FOREACH(rap, ifp->ctx->ra_routers, next) {
584 if (rap->iface == ifp && rap->willexpire)
585 rap->doexpire = true;
587 ipv6nd_expirera(ifp);
590 void
591 ipv6nd_startexpire(struct interface *ifp)
593 struct ra *rap;
595 if (ifp->ctx->ra_routers == NULL)
596 return;
598 TAILQ_FOREACH(rap, ifp->ctx->ra_routers, next) {
599 if (rap->iface == ifp)
600 rap->willexpire = true;
602 eloop_q_timeout_add_sec(ifp->ctx->eloop, ELOOP_IPV6RA_EXPIRE,
603 RTR_CARRIER_EXPIRE, ipv6nd_expire, ifp);
607 ipv6nd_rtpref(struct ra *rap)
610 switch (rap->flags & ND_RA_FLAG_RTPREF_MASK) {
611 case ND_RA_FLAG_RTPREF_HIGH:
612 return RTPREF_HIGH;
613 case ND_RA_FLAG_RTPREF_MEDIUM:
614 case ND_RA_FLAG_RTPREF_RSV:
615 return RTPREF_MEDIUM;
616 case ND_RA_FLAG_RTPREF_LOW:
617 return RTPREF_LOW;
618 default:
619 logerrx("%s: impossible RA flag %x", __func__, rap->flags);
620 return RTPREF_INVALID;
622 /* NOTREACHED */
625 static void
626 ipv6nd_sortrouters(struct dhcpcd_ctx *ctx)
628 struct ra_head sorted_routers = TAILQ_HEAD_INITIALIZER(sorted_routers);
629 struct ra *ra1, *ra2;
631 while ((ra1 = TAILQ_FIRST(ctx->ra_routers)) != NULL) {
632 TAILQ_REMOVE(ctx->ra_routers, ra1, next);
633 TAILQ_FOREACH(ra2, &sorted_routers, next) {
634 if (ra1->iface->metric > ra2->iface->metric)
635 continue;
636 if (ra1->expired && !ra2->expired)
637 continue;
638 if (ra1->willexpire && !ra2->willexpire)
639 continue;
640 if (ra1->lifetime == 0 && ra2->lifetime != 0)
641 continue;
642 if (!ra1->isreachable && ra2->reachable)
643 continue;
644 if (ipv6nd_rtpref(ra1) <= ipv6nd_rtpref(ra2))
645 continue;
646 /* All things being equal, prefer older routers. */
647 /* We don't need to check time, becase newer
648 * routers are always added to the tail and then
649 * sorted. */
650 TAILQ_INSERT_BEFORE(ra2, ra1, next);
651 break;
653 if (ra2 == NULL)
654 TAILQ_INSERT_TAIL(&sorted_routers, ra1, next);
657 TAILQ_CONCAT(ctx->ra_routers, &sorted_routers, next);
660 static void
661 ipv6nd_applyra(struct interface *ifp)
663 struct ra *rap;
664 struct rs_state *state = RS_STATE(ifp);
665 struct ra defra = {
666 .iface = ifp,
667 .hoplimit = IPV6_DEFHLIM ,
668 .reachable = REACHABLE_TIME,
669 .retrans = RETRANS_TIMER,
672 TAILQ_FOREACH(rap, ifp->ctx->ra_routers, next) {
673 if (rap->iface == ifp)
674 break;
677 /* If we have no Router Advertisement, then set default values. */
678 if (rap == NULL || rap->expired || rap->willexpire)
679 rap = &defra;
681 state->retrans = rap->retrans;
682 if (if_applyra(rap) == -1 && errno != ENOENT)
683 logerr(__func__);
687 * Neighbour reachability.
689 * RFC 4681 6.2.5 says when a node is no longer a router it MUST
690 * send a RA with a zero lifetime.
691 * All OS's I know of set the NA router flag if they are a router
692 * or not and disregard that they are actively advertising or
693 * shutting down. If the interface is disabled, it cant't send a NA at all.
695 * As such we CANNOT rely on the NA Router flag and MUST use
696 * unreachability or receive a RA with a lifetime of zero to remove
697 * the node as a default router.
699 void
700 ipv6nd_neighbour(struct dhcpcd_ctx *ctx, struct in6_addr *addr, bool reachable)
702 struct ra *rap, *rapr;
704 if (ctx->ra_routers == NULL)
705 return;
707 TAILQ_FOREACH(rap, ctx->ra_routers, next) {
708 if (IN6_ARE_ADDR_EQUAL(&rap->from, addr))
709 break;
712 if (rap == NULL || rap->expired || rap->isreachable == reachable)
713 return;
715 rap->isreachable = reachable;
716 loginfox("%s: %s is %s", rap->iface->name, rap->sfrom,
717 reachable ? "reachable again" : "unreachable");
719 /* See if we can install a reachable default router. */
720 ipv6nd_sortrouters(ctx);
721 ipv6nd_applyra(rap->iface);
722 rt_build(ctx, AF_INET6);
724 if (reachable)
725 return;
727 /* If we have no reachable default routers, try and solicit one. */
728 TAILQ_FOREACH(rapr, ctx->ra_routers, next) {
729 if (rap == rapr || rap->iface != rapr->iface)
730 continue;
731 if (rapr->isreachable && !rapr->expired && rapr->lifetime)
732 break;
735 if (rapr == NULL)
736 ipv6nd_startrs(rap->iface);
739 const struct ipv6_addr *
740 ipv6nd_iffindaddr(const struct interface *ifp, const struct in6_addr *addr,
741 unsigned int flags)
743 struct ra *rap;
744 struct ipv6_addr *ap;
746 if (ifp->ctx->ra_routers == NULL)
747 return NULL;
749 TAILQ_FOREACH(rap, ifp->ctx->ra_routers, next) {
750 if (rap->iface != ifp)
751 continue;
752 TAILQ_FOREACH(ap, &rap->addrs, next) {
753 if (ipv6_findaddrmatch(ap, addr, flags))
754 return ap;
757 return NULL;
760 struct ipv6_addr *
761 ipv6nd_findaddr(struct dhcpcd_ctx *ctx, const struct in6_addr *addr,
762 unsigned int flags)
764 struct ra *rap;
765 struct ipv6_addr *ap;
767 if (ctx->ra_routers == NULL)
768 return NULL;
770 TAILQ_FOREACH(rap, ctx->ra_routers, next) {
771 TAILQ_FOREACH(ap, &rap->addrs, next) {
772 if (ipv6_findaddrmatch(ap, addr, flags))
773 return ap;
776 return NULL;
779 static struct ipv6_addr *
780 ipv6nd_rapfindprefix(struct ra *rap,
781 const struct in6_addr *pfx, uint8_t pfxlen)
783 struct ipv6_addr *ia;
785 TAILQ_FOREACH(ia, &rap->addrs, next) {
786 if (ia->prefix_vltime == 0)
787 continue;
788 if (ia->prefix_len == pfxlen &&
789 IN6_ARE_ADDR_EQUAL(&ia->prefix, pfx))
790 break;
792 return ia;
795 struct ipv6_addr *
796 ipv6nd_iffindprefix(struct interface *ifp,
797 const struct in6_addr *pfx, uint8_t pfxlen)
799 struct ra *rap;
800 struct ipv6_addr *ia;
802 ia = NULL;
803 TAILQ_FOREACH(rap, ifp->ctx->ra_routers, next) {
804 if (rap->iface != ifp)
805 continue;
806 ia = ipv6nd_rapfindprefix(rap, pfx, pfxlen);
807 if (ia != NULL)
808 break;
810 return ia;
813 static void
814 ipv6nd_removefreedrop_ra(struct ra *rap, int remove_ra, int drop_ra)
817 eloop_timeout_delete(rap->iface->ctx->eloop, NULL, rap->iface);
818 eloop_timeout_delete(rap->iface->ctx->eloop, NULL, rap);
819 if (remove_ra)
820 TAILQ_REMOVE(rap->iface->ctx->ra_routers, rap, next);
821 ipv6_freedrop_addrs(&rap->addrs, drop_ra, NULL);
822 free(rap->data);
823 free(rap);
826 static void
827 ipv6nd_freedrop_ra(struct ra *rap, int drop)
830 ipv6nd_removefreedrop_ra(rap, 1, drop);
833 ssize_t
834 ipv6nd_free(struct interface *ifp)
836 struct rs_state *state;
837 struct ra *rap, *ran;
838 struct dhcpcd_ctx *ctx;
839 ssize_t n;
841 state = RS_STATE(ifp);
842 if (state == NULL)
843 return 0;
845 ctx = ifp->ctx;
846 #ifdef __sun
847 eloop_event_delete(ctx->eloop, state->nd_fd);
848 close(state->nd_fd);
849 #endif
850 free(state->rs);
851 free(state);
852 ifp->if_data[IF_DATA_IPV6ND] = NULL;
853 n = 0;
854 TAILQ_FOREACH_SAFE(rap, ifp->ctx->ra_routers, next, ran) {
855 if (rap->iface == ifp) {
856 ipv6nd_free_ra(rap);
857 n++;
861 #ifndef __sun
862 /* If we don't have any more IPv6 enabled interfaces,
863 * close the global socket and release resources */
864 TAILQ_FOREACH(ifp, ctx->ifaces, next) {
865 if (RS_STATE(ifp))
866 break;
868 if (ifp == NULL) {
869 if (ctx->nd_fd != -1) {
870 eloop_event_delete(ctx->eloop, ctx->nd_fd);
871 close(ctx->nd_fd);
872 ctx->nd_fd = -1;
875 #endif
877 return n;
880 static void
881 ipv6nd_scriptrun(struct ra *rap)
883 int hasdns, hasaddress;
884 struct ipv6_addr *ap;
886 hasaddress = 0;
887 /* If all addresses have completed DAD run the script */
888 TAILQ_FOREACH(ap, &rap->addrs, next) {
889 if ((ap->flags & (IPV6_AF_AUTOCONF | IPV6_AF_ADDED)) ==
890 (IPV6_AF_AUTOCONF | IPV6_AF_ADDED))
892 hasaddress = 1;
893 if (!(ap->flags & IPV6_AF_DADCOMPLETED) &&
894 ipv6_iffindaddr(ap->iface, &ap->addr,
895 IN6_IFF_TENTATIVE))
896 ap->flags |= IPV6_AF_DADCOMPLETED;
897 if ((ap->flags & IPV6_AF_DADCOMPLETED) == 0) {
898 logdebugx("%s: waiting for Router Advertisement"
899 " DAD to complete",
900 rap->iface->name);
901 return;
906 /* If we don't require RDNSS then set hasdns = 1 so we fork */
907 if (!(rap->iface->options->options & DHCPCD_IPV6RA_REQRDNSS))
908 hasdns = 1;
909 else {
910 hasdns = rap->hasdns;
913 script_runreason(rap->iface, "ROUTERADVERT");
914 if (hasdns && (hasaddress ||
915 !(rap->flags & (ND_RA_FLAG_MANAGED | ND_RA_FLAG_OTHER))))
916 dhcpcd_daemonise(rap->iface->ctx);
917 #if 0
918 else if (options & DHCPCD_DAEMONISE &&
919 !(options & DHCPCD_DAEMONISED) && new_data)
920 logwarnx("%s: did not fork due to an absent"
921 " RDNSS option in the RA",
922 ifp->name);
923 #endif
926 static void
927 ipv6nd_addaddr(void *arg)
929 struct ipv6_addr *ap = arg;
931 ipv6_addaddr(ap, NULL);
935 ipv6nd_dadcompleted(const struct interface *ifp)
937 const struct ra *rap;
938 const struct ipv6_addr *ap;
940 TAILQ_FOREACH(rap, ifp->ctx->ra_routers, next) {
941 if (rap->iface != ifp)
942 continue;
943 TAILQ_FOREACH(ap, &rap->addrs, next) {
944 if (ap->flags & IPV6_AF_AUTOCONF &&
945 ap->flags & IPV6_AF_ADDED &&
946 !(ap->flags & IPV6_AF_DADCOMPLETED))
947 return 0;
950 return 1;
953 static void
954 ipv6nd_dadcallback(void *arg)
956 struct ipv6_addr *ia = arg, *rapap;
957 struct interface *ifp;
958 struct ra *rap;
959 int wascompleted, found;
960 char buf[INET6_ADDRSTRLEN];
961 const char *p;
962 int dadcounter;
964 ifp = ia->iface;
965 wascompleted = (ia->flags & IPV6_AF_DADCOMPLETED);
966 ia->flags |= IPV6_AF_DADCOMPLETED;
967 if (ia->addr_flags & IN6_IFF_DUPLICATED) {
968 ia->dadcounter++;
969 logwarnx("%s: DAD detected %s", ifp->name, ia->saddr);
971 /* Try and make another stable private address.
972 * Because ap->dadcounter is always increamented,
973 * a different address is generated. */
974 /* XXX Cache DAD counter per prefix/id/ssid? */
975 if (ifp->options->options & DHCPCD_SLAACPRIVATE &&
976 IA6_CANAUTOCONF(ia))
978 unsigned int delay;
980 if (ia->dadcounter >= IDGEN_RETRIES) {
981 logerrx("%s: unable to obtain a"
982 " stable private address",
983 ifp->name);
984 goto try_script;
986 loginfox("%s: deleting address %s",
987 ifp->name, ia->saddr);
988 if (if_address6(RTM_DELADDR, ia) == -1 &&
989 errno != EADDRNOTAVAIL && errno != ENXIO)
990 logerr(__func__);
991 dadcounter = ia->dadcounter;
992 if (ipv6_makestableprivate(&ia->addr,
993 &ia->prefix, ia->prefix_len,
994 ifp, &dadcounter) == -1)
996 logerr("ipv6_makestableprivate");
997 return;
999 ia->dadcounter = dadcounter;
1000 ia->flags &= ~(IPV6_AF_ADDED | IPV6_AF_DADCOMPLETED);
1001 ia->flags |= IPV6_AF_NEW;
1002 p = inet_ntop(AF_INET6, &ia->addr, buf, sizeof(buf));
1003 if (p)
1004 snprintf(ia->saddr,
1005 sizeof(ia->saddr),
1006 "%s/%d",
1007 p, ia->prefix_len);
1008 else
1009 ia->saddr[0] = '\0';
1010 delay = arc4random_uniform(IDGEN_DELAY * MSEC_PER_SEC);
1011 eloop_timeout_add_msec(ifp->ctx->eloop, delay,
1012 ipv6nd_addaddr, ia);
1013 return;
1017 try_script:
1018 if (!wascompleted) {
1019 TAILQ_FOREACH(rap, ifp->ctx->ra_routers, next) {
1020 if (rap->iface != ifp)
1021 continue;
1022 wascompleted = 1;
1023 found = 0;
1024 TAILQ_FOREACH(rapap, &rap->addrs, next) {
1025 if (rapap->flags & IPV6_AF_AUTOCONF &&
1026 rapap->flags & IPV6_AF_ADDED &&
1027 (rapap->flags & IPV6_AF_DADCOMPLETED) == 0)
1029 wascompleted = 0;
1030 break;
1032 if (rapap == ia)
1033 found = 1;
1036 if (wascompleted && found) {
1037 logdebugx("%s: Router Advertisement DAD "
1038 "completed",
1039 rap->iface->name);
1040 ipv6nd_scriptrun(rap);
1043 #ifdef ND6_ADVERTISE
1044 ipv6nd_advertise(ia);
1045 #endif
1049 static struct ipv6_addr *
1050 ipv6nd_findmarkstale(struct ra *rap, struct ipv6_addr *ia, bool mark)
1052 struct dhcpcd_ctx *ctx = ia->iface->ctx;
1053 struct ra *rap2;
1054 struct ipv6_addr *ia2;
1056 TAILQ_FOREACH(rap2, ctx->ra_routers, next) {
1057 if (rap2 == rap ||
1058 rap2->iface != rap->iface ||
1059 rap2->expired)
1060 continue;
1061 TAILQ_FOREACH(ia2, &rap2->addrs, next) {
1062 if (!IN6_ARE_ADDR_EQUAL(&ia->prefix, &ia2->prefix))
1063 continue;
1064 if (!(ia2->flags & IPV6_AF_STALE))
1065 return ia2;
1066 if (mark)
1067 ia2->prefix_pltime = 0;
1070 return NULL;
1073 #ifndef DHCP6
1074 /* If DHCPv6 is compiled out, supply a shim to provide an error message
1075 * if IPv6RA requests DHCPv6. */
1076 enum DH6S {
1077 DH6S_REQUEST,
1078 DH6S_INFORM,
1080 static int
1081 dhcp6_start(__unused struct interface *ifp, __unused enum DH6S init_state)
1084 errno = ENOTSUP;
1085 return -1;
1087 #endif
1089 static void
1090 ipv6nd_handlera(struct dhcpcd_ctx *ctx,
1091 const struct sockaddr_in6 *from, const char *sfrom,
1092 struct interface *ifp, struct icmp6_hdr *icp, size_t len, int hoplimit)
1094 size_t i, olen;
1095 struct nd_router_advert *nd_ra;
1096 struct nd_opt_hdr ndo;
1097 struct nd_opt_prefix_info pi;
1098 struct nd_opt_mtu mtu;
1099 struct nd_opt_rdnss rdnss;
1100 uint8_t *p;
1101 struct ra *rap;
1102 struct in6_addr pi_prefix;
1103 struct ipv6_addr *ia;
1104 struct dhcp_opt *dho;
1105 bool new_rap, new_data, has_address;
1106 uint32_t old_lifetime;
1107 int ifmtu;
1108 int loglevel;
1109 unsigned int flags;
1110 #ifdef IPV6_MANAGETEMPADDR
1111 bool new_ia;
1112 #endif
1114 if (ifp == NULL || RS_STATE(ifp) == NULL) {
1115 #ifdef DEBUG_RS
1116 logdebugx("RA for unexpected interface from %s", sfrom);
1117 #endif
1118 return;
1121 if (len < sizeof(struct nd_router_advert)) {
1122 logerrx("IPv6 RA packet too short from %s", sfrom);
1123 return;
1126 /* RFC 4861 7.1.2 */
1127 if (hoplimit != 255) {
1128 logerrx("invalid hoplimit(%d) in RA from %s", hoplimit, sfrom);
1129 return;
1131 if (!IN6_IS_ADDR_LINKLOCAL(&from->sin6_addr)) {
1132 logerrx("RA from non local address %s", sfrom);
1133 return;
1136 if (!(ifp->options->options & DHCPCD_IPV6RS)) {
1137 #ifdef DEBUG_RS
1138 logerrx("%s: unexpected RA from %s", ifp->name, sfrom);
1139 #endif
1140 return;
1143 /* We could receive a RA before we sent a RS*/
1144 if (ipv6_linklocal(ifp) == NULL) {
1145 #ifdef DEBUG_RS
1146 logdebugx("%s: received RA from %s (no link-local)",
1147 ifp->name, sfrom);
1148 #endif
1149 return;
1152 if (ipv6_iffindaddr(ifp, &from->sin6_addr, IN6_IFF_TENTATIVE)) {
1153 logdebugx("%s: ignoring RA from ourself %s",
1154 ifp->name, sfrom);
1155 return;
1158 #ifdef NOCARRIER_PRESERVE_IP
1160 * Because we preserve RA's and expire them quickly after
1161 * carrier up, it's important to reset the kernels notion of
1162 * reachable timers back to default values before applying
1163 * new RA values.
1165 TAILQ_FOREACH(rap, ctx->ra_routers, next) {
1166 if (ifp == rap->iface)
1167 break;
1169 if (rap != NULL && rap->willexpire)
1170 ipv6nd_applyra(ifp);
1171 #endif
1173 TAILQ_FOREACH(rap, ctx->ra_routers, next) {
1174 if (ifp == rap->iface &&
1175 IN6_ARE_ADDR_EQUAL(&rap->from, &from->sin6_addr))
1176 break;
1179 nd_ra = (struct nd_router_advert *)icp;
1181 /* We don't want to spam the log with the fact we got an RA every
1182 * 30 seconds or so, so only spam the log if it's different. */
1183 if (rap == NULL || (rap->data_len != len ||
1184 memcmp(rap->data, (unsigned char *)icp, rap->data_len) != 0))
1186 if (rap) {
1187 free(rap->data);
1188 rap->data_len = 0;
1190 new_data = true;
1191 } else
1192 new_data = false;
1193 if (rap == NULL) {
1194 rap = calloc(1, sizeof(*rap));
1195 if (rap == NULL) {
1196 logerr(__func__);
1197 return;
1199 rap->iface = ifp;
1200 rap->from = from->sin6_addr;
1201 strlcpy(rap->sfrom, sfrom, sizeof(rap->sfrom));
1202 TAILQ_INIT(&rap->addrs);
1203 new_rap = true;
1204 rap->isreachable = true;
1205 } else
1206 new_rap = false;
1207 if (rap->data_len == 0) {
1208 rap->data = malloc(len);
1209 if (rap->data == NULL) {
1210 logerr(__func__);
1211 if (new_rap)
1212 free(rap);
1213 return;
1215 memcpy(rap->data, icp, len);
1216 rap->data_len = len;
1219 /* We could change the debug level based on new_data, but some
1220 * routers like to decrease the advertised valid and preferred times
1221 * in accordance with the own prefix times which would result in too
1222 * much needless log spam. */
1223 if (rap->willexpire)
1224 new_data = true;
1225 loglevel = new_rap || rap->willexpire || !rap->isreachable ?
1226 LOG_INFO : LOG_DEBUG,
1227 logmessage(loglevel, "%s: Router Advertisement from %s",
1228 ifp->name, rap->sfrom);
1230 clock_gettime(CLOCK_MONOTONIC, &rap->acquired);
1231 rap->flags = nd_ra->nd_ra_flags_reserved;
1232 old_lifetime = rap->lifetime;
1233 rap->lifetime = ntohs(nd_ra->nd_ra_router_lifetime);
1234 if (!new_rap && rap->lifetime == 0 && old_lifetime != 0)
1235 logwarnx("%s: %s: no longer a default router",
1236 ifp->name, rap->sfrom);
1237 if (nd_ra->nd_ra_curhoplimit != 0)
1238 rap->hoplimit = nd_ra->nd_ra_curhoplimit;
1239 else
1240 rap->hoplimit = IPV6_DEFHLIM;
1241 if (nd_ra->nd_ra_reachable != 0) {
1242 rap->reachable = ntohl(nd_ra->nd_ra_reachable);
1243 if (rap->reachable > MAX_REACHABLE_TIME)
1244 rap->reachable = 0;
1245 } else
1246 rap->reachable = REACHABLE_TIME;
1247 if (nd_ra->nd_ra_retransmit != 0)
1248 rap->retrans = ntohl(nd_ra->nd_ra_retransmit);
1249 else
1250 rap->retrans = RETRANS_TIMER;
1251 rap->expired = rap->willexpire = rap->doexpire = false;
1252 rap->hasdns = false;
1253 rap->isreachable = true;
1254 has_address = false;
1255 rap->mtu = 0;
1257 #ifdef IPV6_AF_TEMPORARY
1258 ipv6_markaddrsstale(ifp, IPV6_AF_TEMPORARY);
1259 #endif
1260 TAILQ_FOREACH(ia, &rap->addrs, next) {
1261 ia->flags |= IPV6_AF_STALE;
1264 len -= sizeof(struct nd_router_advert);
1265 p = ((uint8_t *)icp) + sizeof(struct nd_router_advert);
1266 for (; len > 0; p += olen, len -= olen) {
1267 if (len < sizeof(ndo)) {
1268 logerrx("%s: short option", ifp->name);
1269 break;
1271 memcpy(&ndo, p, sizeof(ndo));
1272 olen = (size_t)ndo.nd_opt_len * 8;
1273 if (olen == 0) {
1274 logerrx("%s: zero length option", ifp->name);
1275 break;
1277 if (olen > len) {
1278 logerrx("%s: option length exceeds message",
1279 ifp->name);
1280 break;
1283 if (has_option_mask(ifp->options->rejectmasknd,
1284 ndo.nd_opt_type))
1286 for (i = 0, dho = ctx->nd_opts;
1287 i < ctx->nd_opts_len;
1288 i++, dho++)
1290 if (dho->option == ndo.nd_opt_type)
1291 break;
1293 if (dho != NULL)
1294 logwarnx("%s: reject RA (option %s) from %s",
1295 ifp->name, dho->var, rap->sfrom);
1296 else
1297 logwarnx("%s: reject RA (option %d) from %s",
1298 ifp->name, ndo.nd_opt_type, rap->sfrom);
1299 if (new_rap)
1300 ipv6nd_removefreedrop_ra(rap, 0, 0);
1301 else
1302 ipv6nd_free_ra(rap);
1303 return;
1306 if (has_option_mask(ifp->options->nomasknd, ndo.nd_opt_type))
1307 continue;
1309 switch (ndo.nd_opt_type) {
1310 case ND_OPT_PREFIX_INFORMATION:
1311 loglevel = new_data ? LOG_ERR : LOG_DEBUG;
1312 if (ndo.nd_opt_len != 4) {
1313 logmessage(loglevel,
1314 "%s: invalid option len for prefix",
1315 ifp->name);
1316 continue;
1318 memcpy(&pi, p, sizeof(pi));
1319 if (pi.nd_opt_pi_prefix_len > 128) {
1320 logmessage(loglevel, "%s: invalid prefix len",
1321 ifp->name);
1322 continue;
1324 /* nd_opt_pi_prefix is not aligned. */
1325 memcpy(&pi_prefix, &pi.nd_opt_pi_prefix,
1326 sizeof(pi_prefix));
1327 if (IN6_IS_ADDR_MULTICAST(&pi_prefix) ||
1328 IN6_IS_ADDR_LINKLOCAL(&pi_prefix))
1330 logmessage(loglevel, "%s: invalid prefix in RA",
1331 ifp->name);
1332 continue;
1334 if (ntohl(pi.nd_opt_pi_preferred_time) >
1335 ntohl(pi.nd_opt_pi_valid_time))
1337 logmessage(loglevel, "%s: pltime > vltime",
1338 ifp->name);
1339 continue;
1342 flags = IPV6_AF_RAPFX;
1343 /* If no flags are set, that means the prefix is
1344 * available via the router. */
1345 if (pi.nd_opt_pi_flags_reserved & ND_OPT_PI_FLAG_ONLINK)
1346 flags |= IPV6_AF_ONLINK;
1347 if (pi.nd_opt_pi_flags_reserved & ND_OPT_PI_FLAG_AUTO &&
1348 rap->iface->options->options &
1349 DHCPCD_IPV6RA_AUTOCONF)
1350 flags |= IPV6_AF_AUTOCONF;
1351 if (pi.nd_opt_pi_flags_reserved & ND_OPT_PI_FLAG_ROUTER)
1352 flags |= IPV6_AF_ROUTER;
1354 ia = ipv6nd_rapfindprefix(rap,
1355 &pi_prefix, pi.nd_opt_pi_prefix_len);
1356 if (ia == NULL) {
1357 ia = ipv6_newaddr(rap->iface,
1358 &pi_prefix, pi.nd_opt_pi_prefix_len, flags);
1359 if (ia == NULL)
1360 break;
1361 ia->prefix = pi_prefix;
1362 if (flags & IPV6_AF_AUTOCONF)
1363 ia->dadcallback = ipv6nd_dadcallback;
1364 ia->created = ia->acquired = rap->acquired;
1365 TAILQ_INSERT_TAIL(&rap->addrs, ia, next);
1367 #ifdef IPV6_MANAGETEMPADDR
1368 /* New address to dhcpcd RA handling.
1369 * If the address already exists and a valid
1370 * temporary address also exists then
1371 * extend the existing one rather than
1372 * create a new one */
1373 if (flags & IPV6_AF_AUTOCONF &&
1374 ipv6_iffindaddr(ifp, &ia->addr,
1375 IN6_IFF_NOTUSEABLE) &&
1376 ipv6_settemptime(ia, 0))
1377 new_ia = false;
1378 else
1379 new_ia = true;
1380 #endif
1381 } else {
1382 #ifdef IPV6_MANAGETEMPADDR
1383 new_ia = false;
1384 #endif
1385 ia->flags |= flags;
1386 ia->flags &= ~IPV6_AF_STALE;
1387 ia->acquired = rap->acquired;
1389 ia->prefix_vltime =
1390 ntohl(pi.nd_opt_pi_valid_time);
1391 ia->prefix_pltime =
1392 ntohl(pi.nd_opt_pi_preferred_time);
1393 if (ia->prefix_vltime != 0 &&
1394 ia->flags & IPV6_AF_AUTOCONF)
1395 has_address = true;
1397 #ifdef IPV6_MANAGETEMPADDR
1398 /* RFC4941 Section 3.3.3 */
1399 if (ia->flags & IPV6_AF_AUTOCONF &&
1400 ia->iface->options->options & DHCPCD_SLAACTEMP &&
1401 IA6_CANAUTOCONF(ia))
1403 if (!new_ia) {
1404 if (ipv6_settemptime(ia, 1) == NULL)
1405 new_ia = true;
1407 if (new_ia && ia->prefix_pltime) {
1408 if (ipv6_createtempaddr(ia,
1409 &ia->acquired) == NULL)
1410 logerr("ipv6_createtempaddr");
1413 #endif
1414 break;
1416 case ND_OPT_MTU:
1417 if (len < sizeof(mtu)) {
1418 logmessage(loglevel, "%s: short MTU option", ifp->name);
1419 break;
1421 memcpy(&mtu, p, sizeof(mtu));
1422 mtu.nd_opt_mtu_mtu = ntohl(mtu.nd_opt_mtu_mtu);
1423 if (mtu.nd_opt_mtu_mtu < IPV6_MMTU) {
1424 logmessage(loglevel, "%s: invalid MTU %d",
1425 ifp->name, mtu.nd_opt_mtu_mtu);
1426 break;
1428 ifmtu = if_getmtu(ifp);
1429 if (ifmtu == -1)
1430 logerr("if_getmtu");
1431 else if (mtu.nd_opt_mtu_mtu > (uint32_t)ifmtu) {
1432 logmessage(loglevel, "%s: advertised MTU %d"
1433 " is greater than link MTU %d",
1434 ifp->name, mtu.nd_opt_mtu_mtu, ifmtu);
1435 rap->mtu = (uint32_t)ifmtu;
1436 } else
1437 rap->mtu = mtu.nd_opt_mtu_mtu;
1438 break;
1439 case ND_OPT_RDNSS:
1440 if (len < sizeof(rdnss)) {
1441 logmessage(loglevel, "%s: short RDNSS option", ifp->name);
1442 break;
1444 memcpy(&rdnss, p, sizeof(rdnss));
1445 if (rdnss.nd_opt_rdnss_lifetime &&
1446 rdnss.nd_opt_rdnss_len > 1)
1447 rap->hasdns = 1;
1448 break;
1449 default:
1450 continue;
1454 for (i = 0, dho = ctx->nd_opts;
1455 i < ctx->nd_opts_len;
1456 i++, dho++)
1458 if (has_option_mask(ifp->options->requiremasknd,
1459 dho->option))
1461 logwarnx("%s: reject RA (no option %s) from %s",
1462 ifp->name, dho->var, rap->sfrom);
1463 if (new_rap)
1464 ipv6nd_removefreedrop_ra(rap, 0, 0);
1465 else
1466 ipv6nd_free_ra(rap);
1467 return;
1471 TAILQ_FOREACH(ia, &rap->addrs, next) {
1472 if (!(ia->flags & IPV6_AF_STALE) || ia->prefix_pltime == 0)
1473 continue;
1474 if (ipv6nd_findmarkstale(rap, ia, false) != NULL)
1475 continue;
1476 ipv6nd_findmarkstale(rap, ia, true);
1477 logdebugx("%s: %s: became stale", ifp->name, ia->saddr);
1478 /* Technically this violates RFC 4861 6.3.4,
1479 * but we need a mechanism to tell the kernel to
1480 * try and prefer other addresses. */
1481 ia->prefix_pltime = 0;
1484 if (new_data && !has_address && rap->lifetime && !ipv6_anyglobal(ifp))
1485 logwarnx("%s: no global addresses for default route",
1486 ifp->name);
1488 if (new_rap)
1489 TAILQ_INSERT_TAIL(ctx->ra_routers, rap, next);
1490 if (new_data)
1491 ipv6nd_sortrouters(ifp->ctx);
1493 if (ifp->ctx->options & DHCPCD_TEST) {
1494 script_runreason(ifp, "TEST");
1495 goto handle_flag;
1497 ipv6nd_applyra(ifp);
1498 ipv6_addaddrs(&rap->addrs);
1499 #ifdef IPV6_MANAGETEMPADDR
1500 ipv6_addtempaddrs(ifp, &rap->acquired);
1501 #endif
1503 rt_build(ifp->ctx, AF_INET6);
1504 ipv6nd_scriptrun(rap);
1506 eloop_timeout_delete(ifp->ctx->eloop, NULL, ifp);
1507 eloop_timeout_delete(ifp->ctx->eloop, NULL, rap); /* reachable timer */
1509 handle_flag:
1510 if (!(ifp->options->options & DHCPCD_DHCP6))
1511 goto nodhcp6;
1512 /* Only log a DHCPv6 start error if compiled in or debugging is enabled. */
1513 #ifdef DHCP6
1514 #define LOG_DHCP6 logerr
1515 #else
1516 #define LOG_DHCP6 logdebug
1517 #endif
1518 if (rap->flags & ND_RA_FLAG_MANAGED) {
1519 if (new_data && dhcp6_start(ifp, DH6S_REQUEST) == -1)
1520 LOG_DHCP6("dhcp6_start: %s", ifp->name);
1521 } else if (rap->flags & ND_RA_FLAG_OTHER) {
1522 if (new_data && dhcp6_start(ifp, DH6S_INFORM) == -1)
1523 LOG_DHCP6("dhcp6_start: %s", ifp->name);
1524 } else {
1525 #ifdef DHCP6
1526 if (new_data)
1527 logdebugx("%s: No DHCPv6 instruction in RA", ifp->name);
1528 #endif
1529 nodhcp6:
1530 if (ifp->ctx->options & DHCPCD_TEST) {
1531 eloop_exit(ifp->ctx->eloop, EXIT_SUCCESS);
1532 return;
1536 /* Expire should be called last as the rap object could be destroyed */
1537 ipv6nd_expirera(ifp);
1540 bool
1541 ipv6nd_hasralifetime(const struct interface *ifp, bool lifetime)
1543 const struct ra *rap;
1545 if (ifp->ctx->ra_routers) {
1546 TAILQ_FOREACH(rap, ifp->ctx->ra_routers, next)
1547 if (rap->iface == ifp &&
1548 !rap->expired &&
1549 (!lifetime ||rap->lifetime))
1550 return true;
1552 return false;
1555 bool
1556 ipv6nd_hasradhcp(const struct interface *ifp, bool managed)
1558 const struct ra *rap;
1560 if (ifp->ctx->ra_routers) {
1561 TAILQ_FOREACH(rap, ifp->ctx->ra_routers, next) {
1562 if (rap->iface == ifp &&
1563 !rap->expired && !rap->willexpire &&
1564 ((managed && rap->flags & ND_RA_FLAG_MANAGED) ||
1565 (!managed && rap->flags & ND_RA_FLAG_OTHER)))
1566 return true;
1569 return false;
1572 static const uint8_t *
1573 ipv6nd_getoption(struct dhcpcd_ctx *ctx,
1574 size_t *os, unsigned int *code, size_t *len,
1575 const uint8_t *od, size_t ol, struct dhcp_opt **oopt)
1577 struct nd_opt_hdr ndo;
1578 size_t i;
1579 struct dhcp_opt *opt;
1581 if (od) {
1582 *os = sizeof(ndo);
1583 if (ol < *os) {
1584 errno = EINVAL;
1585 return NULL;
1587 memcpy(&ndo, od, sizeof(ndo));
1588 i = (size_t)(ndo.nd_opt_len * 8);
1589 if (i > ol) {
1590 errno = EINVAL;
1591 return NULL;
1593 *len = i;
1594 *code = ndo.nd_opt_type;
1597 for (i = 0, opt = ctx->nd_opts;
1598 i < ctx->nd_opts_len; i++, opt++)
1600 if (opt->option == *code) {
1601 *oopt = opt;
1602 break;
1606 if (od)
1607 return od + sizeof(ndo);
1608 return NULL;
1611 ssize_t
1612 ipv6nd_env(FILE *fp, const struct interface *ifp)
1614 size_t i, j, n, len, olen;
1615 struct ra *rap;
1616 char ndprefix[32];
1617 struct dhcp_opt *opt;
1618 uint8_t *p;
1619 struct nd_opt_hdr ndo;
1620 struct ipv6_addr *ia;
1621 struct timespec now;
1622 int pref;
1624 clock_gettime(CLOCK_MONOTONIC, &now);
1625 i = n = 0;
1626 TAILQ_FOREACH(rap, ifp->ctx->ra_routers, next) {
1627 if (rap->iface != ifp || rap->expired)
1628 continue;
1629 i++;
1630 snprintf(ndprefix, sizeof(ndprefix), "nd%zu", i);
1631 if (efprintf(fp, "%s_from=%s", ndprefix, rap->sfrom) == -1)
1632 return -1;
1633 if (efprintf(fp, "%s_acquired=%lld", ndprefix,
1634 (long long)rap->acquired.tv_sec) == -1)
1635 return -1;
1636 if (efprintf(fp, "%s_now=%lld", ndprefix,
1637 (long long)now.tv_sec) == -1)
1638 return -1;
1639 if (efprintf(fp, "%s_hoplimit=%u", ndprefix, rap->hoplimit) == -1)
1640 return -1;
1641 pref = ipv6nd_rtpref(rap);
1642 if (efprintf(fp, "%s_flags=%s%s%s%s%s", ndprefix,
1643 rap->flags & ND_RA_FLAG_MANAGED ? "M" : "",
1644 rap->flags & ND_RA_FLAG_OTHER ? "O" : "",
1645 rap->flags & ND_RA_FLAG_HOME_AGENT ? "H" : "",
1646 pref == RTPREF_HIGH ? "h" : pref == RTPREF_LOW ? "l" : "",
1647 rap->flags & ND_RA_FLAG_PROXY ? "P" : "") == -1)
1648 return -1;
1649 if (efprintf(fp, "%s_lifetime=%u", ndprefix, rap->lifetime) == -1)
1650 return -1;
1652 /* Zero our indexes */
1653 for (j = 0, opt = rap->iface->ctx->nd_opts;
1654 j < rap->iface->ctx->nd_opts_len;
1655 j++, opt++)
1656 dhcp_zero_index(opt);
1657 for (j = 0, opt = rap->iface->options->nd_override;
1658 j < rap->iface->options->nd_override_len;
1659 j++, opt++)
1660 dhcp_zero_index(opt);
1662 /* Unlike DHCP, ND6 options *may* occur more than once.
1663 * There is also no provision for option concatenation
1664 * unlike DHCP. */
1665 len = rap->data_len - sizeof(struct nd_router_advert);
1666 for (p = rap->data + sizeof(struct nd_router_advert);
1667 len >= sizeof(ndo);
1668 p += olen, len -= olen)
1670 memcpy(&ndo, p, sizeof(ndo));
1671 olen = (size_t)(ndo.nd_opt_len * 8);
1672 if (olen > len) {
1673 errno = EINVAL;
1674 break;
1676 if (has_option_mask(rap->iface->options->nomasknd,
1677 ndo.nd_opt_type))
1678 continue;
1679 for (j = 0, opt = rap->iface->options->nd_override;
1680 j < rap->iface->options->nd_override_len;
1681 j++, opt++)
1682 if (opt->option == ndo.nd_opt_type)
1683 break;
1684 if (j == rap->iface->options->nd_override_len) {
1685 for (j = 0, opt = rap->iface->ctx->nd_opts;
1686 j < rap->iface->ctx->nd_opts_len;
1687 j++, opt++)
1688 if (opt->option == ndo.nd_opt_type)
1689 break;
1690 if (j == rap->iface->ctx->nd_opts_len)
1691 opt = NULL;
1693 if (opt == NULL)
1694 continue;
1695 dhcp_envoption(rap->iface->ctx, fp,
1696 ndprefix, rap->iface->name,
1697 opt, ipv6nd_getoption,
1698 p + sizeof(ndo), olen - sizeof(ndo));
1701 /* We need to output the addresses we actually made
1702 * from the prefix information options as well. */
1703 j = 0;
1704 TAILQ_FOREACH(ia, &rap->addrs, next) {
1705 if (!(ia->flags & IPV6_AF_AUTOCONF) ||
1706 #ifdef IPV6_AF_TEMPORARY
1707 ia->flags & IPV6_AF_TEMPORARY ||
1708 #endif
1709 !(ia->flags & IPV6_AF_ADDED) ||
1710 ia->prefix_vltime == 0)
1711 continue;
1712 if (efprintf(fp, "%s_addr%zu=%s",
1713 ndprefix, ++j, ia->saddr) == -1)
1714 return -1;
1717 return 1;
1720 void
1721 ipv6nd_handleifa(int cmd, struct ipv6_addr *addr, pid_t pid)
1723 struct ra *rap;
1725 /* IPv6 init may not have happened yet if we are learning
1726 * existing addresses when dhcpcd starts. */
1727 if (addr->iface->ctx->ra_routers == NULL)
1728 return;
1730 TAILQ_FOREACH(rap, addr->iface->ctx->ra_routers, next) {
1731 if (rap->iface != addr->iface)
1732 continue;
1733 ipv6_handleifa_addrs(cmd, &rap->addrs, addr, pid);
1737 void
1738 ipv6nd_expirera(void *arg)
1740 struct interface *ifp;
1741 struct ra *rap, *ran;
1742 struct timespec now;
1743 uint32_t elapsed;
1744 bool expired, valid;
1745 struct ipv6_addr *ia;
1746 size_t len, olen;
1747 uint8_t *p;
1748 struct nd_opt_hdr ndo;
1749 #if 0
1750 struct nd_opt_prefix_info pi;
1751 #endif
1752 struct nd_opt_dnssl dnssl;
1753 struct nd_opt_rdnss rdnss;
1754 unsigned int next = 0, ltime;
1755 size_t nexpired = 0;
1757 ifp = arg;
1758 clock_gettime(CLOCK_MONOTONIC, &now);
1759 expired = false;
1761 TAILQ_FOREACH_SAFE(rap, ifp->ctx->ra_routers, next, ran) {
1762 if (rap->iface != ifp || rap->expired)
1763 continue;
1764 valid = false;
1765 if (rap->lifetime) {
1766 elapsed = (uint32_t)eloop_timespec_diff(&now,
1767 &rap->acquired, NULL);
1768 if (elapsed >= rap->lifetime || rap->doexpire) {
1769 if (!rap->expired) {
1770 logwarnx("%s: %s: router expired",
1771 ifp->name, rap->sfrom);
1772 rap->lifetime = 0;
1773 expired = true;
1775 } else {
1776 valid = true;
1777 ltime = rap->lifetime - elapsed;
1778 if (next == 0 || ltime < next)
1779 next = ltime;
1783 /* Not every prefix is tied to an address which
1784 * the kernel can expire, so we need to handle it ourself.
1785 * Also, some OS don't support address lifetimes (Solaris). */
1786 TAILQ_FOREACH(ia, &rap->addrs, next) {
1787 if (ia->prefix_vltime == 0)
1788 continue;
1789 if (ia->prefix_vltime == ND6_INFINITE_LIFETIME &&
1790 !rap->doexpire)
1792 valid = true;
1793 continue;
1795 elapsed = (uint32_t)eloop_timespec_diff(&now,
1796 &ia->acquired, NULL);
1797 if (elapsed >= ia->prefix_vltime || rap->doexpire) {
1798 if (ia->flags & IPV6_AF_ADDED) {
1799 logwarnx("%s: expired %s %s",
1800 ia->iface->name,
1801 ia->flags & IPV6_AF_AUTOCONF ?
1802 "address" : "prefix",
1803 ia->saddr);
1804 if (if_address6(RTM_DELADDR, ia)== -1 &&
1805 errno != EADDRNOTAVAIL &&
1806 errno != ENXIO)
1807 logerr(__func__);
1809 ia->prefix_vltime = ia->prefix_pltime = 0;
1810 ia->flags &=
1811 ~(IPV6_AF_ADDED | IPV6_AF_DADCOMPLETED);
1812 expired = true;
1813 } else {
1814 valid = true;
1815 ltime = ia->prefix_vltime - elapsed;
1816 if (next == 0 || ltime < next)
1817 next = ltime;
1821 /* Work out expiry for ND options */
1822 elapsed = (uint32_t)eloop_timespec_diff(&now,
1823 &rap->acquired, NULL);
1824 len = rap->data_len - sizeof(struct nd_router_advert);
1825 for (p = rap->data + sizeof(struct nd_router_advert);
1826 len >= sizeof(ndo);
1827 p += olen, len -= olen)
1829 memcpy(&ndo, p, sizeof(ndo));
1830 olen = (size_t)(ndo.nd_opt_len * 8);
1831 if (olen > len) {
1832 errno = EINVAL;
1833 break;
1836 if (has_option_mask(rap->iface->options->nomasknd,
1837 ndo.nd_opt_type))
1838 continue;
1840 switch (ndo.nd_opt_type) {
1841 /* Prefix info is already checked in the above loop. */
1842 #if 0
1843 case ND_OPT_PREFIX_INFORMATION:
1844 if (len < sizeof(pi))
1845 break;
1846 memcpy(&pi, p, sizeof(pi));
1847 ltime = pi.nd_opt_pi_valid_time;
1848 break;
1849 #endif
1850 case ND_OPT_DNSSL:
1851 if (len < sizeof(dnssl))
1852 continue;
1853 memcpy(&dnssl, p, sizeof(dnssl));
1854 ltime = dnssl.nd_opt_dnssl_lifetime;
1855 break;
1856 case ND_OPT_RDNSS:
1857 if (len < sizeof(rdnss))
1858 continue;
1859 memcpy(&rdnss, p, sizeof(rdnss));
1860 ltime = rdnss.nd_opt_rdnss_lifetime;
1861 break;
1862 default:
1863 continue;
1866 if (ltime == 0)
1867 continue;
1868 if (rap->doexpire) {
1869 expired = true;
1870 continue;
1872 if (ltime == ND6_INFINITE_LIFETIME) {
1873 valid = true;
1874 continue;
1877 ltime = ntohl(ltime);
1878 if (elapsed >= ltime) {
1879 expired = true;
1880 continue;
1883 valid = true;
1884 ltime -= elapsed;
1885 if (next == 0 || ltime < next)
1886 next = ltime;
1889 if (valid)
1890 continue;
1892 /* Router has expired. Let's not keep a lot of them. */
1893 rap->expired = true;
1894 if (++nexpired > EXPIRED_MAX)
1895 ipv6nd_free_ra(rap);
1898 if (next != 0)
1899 eloop_timeout_add_sec(ifp->ctx->eloop,
1900 next, ipv6nd_expirera, ifp);
1901 if (expired) {
1902 logwarnx("%s: part of a Router Advertisement expired",
1903 ifp->name);
1904 ipv6nd_sortrouters(ifp->ctx);
1905 ipv6nd_applyra(ifp);
1906 rt_build(ifp->ctx, AF_INET6);
1907 script_runreason(ifp, "ROUTERADVERT");
1911 void
1912 ipv6nd_drop(struct interface *ifp)
1914 struct ra *rap, *ran;
1915 bool expired = false;
1917 if (ifp->ctx->ra_routers == NULL)
1918 return;
1920 eloop_timeout_delete(ifp->ctx->eloop, NULL, ifp);
1921 TAILQ_FOREACH_SAFE(rap, ifp->ctx->ra_routers, next, ran) {
1922 if (rap->iface == ifp) {
1923 rap->expired = expired = true;
1924 ipv6nd_drop_ra(rap);
1927 if (expired) {
1928 ipv6nd_applyra(ifp);
1929 rt_build(ifp->ctx, AF_INET6);
1930 if ((ifp->options->options & DHCPCD_NODROP) != DHCPCD_NODROP)
1931 script_runreason(ifp, "ROUTERADVERT");
1935 void
1936 ipv6nd_recvmsg(struct dhcpcd_ctx *ctx, struct msghdr *msg)
1938 struct sockaddr_in6 *from = (struct sockaddr_in6 *)msg->msg_name;
1939 char sfrom[INET6_ADDRSTRLEN];
1940 int hoplimit = 0;
1941 struct icmp6_hdr *icp;
1942 struct interface *ifp;
1943 size_t len = msg->msg_iov[0].iov_len;
1945 inet_ntop(AF_INET6, &from->sin6_addr, sfrom, sizeof(sfrom));
1946 if ((size_t)len < sizeof(struct icmp6_hdr)) {
1947 logerrx("IPv6 ICMP packet too short from %s", sfrom);
1948 return;
1951 ifp = if_findifpfromcmsg(ctx, msg, &hoplimit);
1952 if (ifp == NULL) {
1953 logerr(__func__);
1954 return;
1957 /* Don't do anything if the user hasn't configured it. */
1958 if (ifp->active != IF_ACTIVE_USER ||
1959 !(ifp->options->options & DHCPCD_IPV6))
1960 return;
1962 icp = (struct icmp6_hdr *)msg->msg_iov[0].iov_base;
1963 if (icp->icmp6_code == 0) {
1964 switch(icp->icmp6_type) {
1965 case ND_ROUTER_ADVERT:
1966 ipv6nd_handlera(ctx, from, sfrom,
1967 ifp, icp, (size_t)len, hoplimit);
1968 return;
1972 logerrx("invalid IPv6 type %d or code %d from %s",
1973 icp->icmp6_type, icp->icmp6_code, sfrom);
1976 static void
1977 ipv6nd_handledata(void *arg)
1979 struct dhcpcd_ctx *ctx;
1980 int fd;
1981 struct sockaddr_in6 from;
1982 union {
1983 struct icmp6_hdr hdr;
1984 uint8_t buf[64 * 1024]; /* Maximum ICMPv6 size */
1985 } iovbuf;
1986 struct iovec iov = {
1987 .iov_base = iovbuf.buf, .iov_len = sizeof(iovbuf.buf),
1989 union {
1990 struct cmsghdr hdr;
1991 uint8_t buf[CMSG_SPACE(sizeof(struct in6_pktinfo)) +
1992 CMSG_SPACE(sizeof(int))];
1993 } cmsgbuf = { .buf = { 0 } };
1994 struct msghdr msg = {
1995 .msg_name = &from, .msg_namelen = sizeof(from),
1996 .msg_iov = &iov, .msg_iovlen = 1,
1997 .msg_control = cmsgbuf.buf, .msg_controllen = sizeof(cmsgbuf.buf),
1999 ssize_t len;
2001 #ifdef __sun
2002 struct interface *ifp;
2003 struct rs_state *state;
2005 ifp = arg;
2006 state = RS_STATE(ifp);
2007 ctx = ifp->ctx;
2008 fd = state->nd_fd;
2009 #else
2010 ctx = arg;
2011 fd = ctx->nd_fd;
2012 #endif
2013 len = recvmsg(fd, &msg, 0);
2014 if (len == -1) {
2015 logerr(__func__);
2016 return;
2019 iov.iov_len = (size_t)len;
2020 ipv6nd_recvmsg(ctx, &msg);
2023 static void
2024 ipv6nd_startrs1(void *arg)
2026 struct interface *ifp = arg;
2027 struct rs_state *state;
2029 loginfox("%s: soliciting an IPv6 router", ifp->name);
2030 state = RS_STATE(ifp);
2031 if (state == NULL) {
2032 ifp->if_data[IF_DATA_IPV6ND] = calloc(1, sizeof(*state));
2033 state = RS_STATE(ifp);
2034 if (state == NULL) {
2035 logerr(__func__);
2036 return;
2038 #ifdef __sun
2039 state->nd_fd = -1;
2040 #endif
2043 /* Always make a new probe as the underlying hardware
2044 * address could have changed. */
2045 ipv6nd_makersprobe(ifp);
2046 if (state->rs == NULL) {
2047 logerr(__func__);
2048 return;
2051 state->retrans = RETRANS_TIMER;
2052 state->rsprobes = 0;
2053 ipv6nd_sendrsprobe(ifp);
2056 void
2057 ipv6nd_startrs(struct interface *ifp)
2059 unsigned int delay;
2061 eloop_timeout_delete(ifp->ctx->eloop, NULL, ifp);
2062 if (!(ifp->options->options & DHCPCD_INITIAL_DELAY)) {
2063 ipv6nd_startrs1(ifp);
2064 return;
2067 delay = arc4random_uniform(MAX_RTR_SOLICITATION_DELAY * MSEC_PER_SEC);
2068 logdebugx("%s: delaying IPv6 router solicitation for %0.1f seconds",
2069 ifp->name, (float)delay / MSEC_PER_SEC);
2070 eloop_timeout_add_msec(ifp->ctx->eloop, delay, ipv6nd_startrs1, ifp);
2071 return;