xref: /dragonfly/contrib/dhcpcd/src/ipv6nd.c (revision 207ba670)
1 /* SPDX-License-Identifier: BSD-2-Clause */
2 /*
3  * dhcpcd - IPv6 ND handling
4  * Copyright (c) 2006-2019 Roy Marples <roy@marples.name>
5  * All rights reserved
6 
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.
15  *
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.
27  */
28 
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>
37 
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 <unistd.h>
45 
46 #define ELOOP_QUEUE 3
47 #include "common.h"
48 #include "dhcpcd.h"
49 #include "dhcp-common.h"
50 #include "dhcp6.h"
51 #include "eloop.h"
52 #include "if.h"
53 #include "ipv6.h"
54 #include "ipv6nd.h"
55 #include "logerr.h"
56 #include "route.h"
57 #include "script.h"
58 
59 /* Debugging Router Solicitations is a lot of spam, so disable it */
60 //#define DEBUG_RS
61 
62 #ifndef ND_OPT_RDNSS
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 */
70 };
71 __CTASSERT(sizeof(struct nd_opt_rdnss) == 8);
72 #endif
73 
74 #ifndef ND_OPT_DNSSL
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 */
82 };
83 __CTASSERT(sizeof(struct nd_opt_rdnss) == 8);
84 #endif
85 
86 /* Impossible options, so we can easily add extras */
87 #define _ND_OPT_PREFIX_ADDR	255 + 1
88 
89 /* Minimal IPv6 MTU */
90 #ifndef IPV6_MMTU
91 #define IPV6_MMTU 1280
92 #endif
93 
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
100 #endif
101 
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 */
108 
109 #define	EXPIRED_MAX	5	/* Remember 5 expired routers to avoid
110 				   logspam. */
111 
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 */
116 
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
123 #endif
124 
125 /* Debugging Neighbor Solicitations is a lot of spam, so disable it */
126 //#define DEBUG_NS
127 //
128 
129 static void ipv6nd_handledata(void *);
130 
131 /*
132  * Android ships buggy ICMP6 filter headers.
133  * Supply our own until they fix their shit.
134  * References:
135  *     https://android-review.googlesource.com/#/c/58438/
136  *     http://code.google.com/p/android/issues/original?id=32621&seq=24
137  */
138 #ifdef __ANDROID__
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));
157 #endif
158 
159 /* Support older systems with different defines */
160 #if !defined(IPV6_RECVHOPLIMIT) && defined(IPV6_HOPLIMIT)
161 #define IPV6_RECVHOPLIMIT IPV6_HOPLIMIT
162 #endif
163 #if !defined(IPV6_RECVPKTINFO) && defined(IPV6_PKTINFO)
164 #define IPV6_RECVPKTINFO IPV6_PKTINFO
165 #endif
166 
167 /* Handy defines */
168 #define ipv6nd_free_ra(ra) ipv6nd_freedrop_ra((ra),  0)
169 #define ipv6nd_drop_ra(ra) ipv6nd_freedrop_ra((ra),  1)
170 
171 void
172 ipv6nd_printoptions(const struct dhcpcd_ctx *ctx,
173     const struct dhcp_opt *opts, size_t opts_len)
174 {
175 	size_t i, j;
176 	const struct dhcp_opt *opt, *opt2;
177 	int cols;
178 
179 	for (i = 0, opt = ctx->nd_opts;
180 	    i < ctx->nd_opts_len; i++, opt++)
181 	{
182 		for (j = 0, opt2 = opts; j < opts_len; j++, opt2++)
183 			if (opt2->option == opt->option)
184 				break;
185 		if (j == opts_len) {
186 			cols = printf("%03d %s", opt->option, opt->var);
187 			dhcp_print_option_encoding(opt, cols);
188 		}
189 	}
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);
193 	}
194 }
195 
196 static int
197 ipv6nd_open0(void)
198 {
199 	int fd, on;
200 	struct icmp6_filter filt;
201 
202 #define SOCK_FLAGS	SOCK_CLOEXEC | SOCK_NONBLOCK
203 	fd = xsocket(PF_INET6, SOCK_RAW | SOCK_FLAGS, IPPROTO_ICMPV6);
204 #undef SOCK_FLAGS
205 	if (fd == -1)
206 		return -1;
207 
208 	/* RFC4861 4.1 */
209 	on = 255;
210 	if (setsockopt(fd, IPPROTO_IPV6, IPV6_MULTICAST_HOPS,
211 	    &on, sizeof(on)) == -1)
212 		goto eexit;
213 
214 	on = 1;
215 	if (setsockopt(fd, IPPROTO_IPV6, IPV6_RECVPKTINFO,
216 	    &on, sizeof(on)) == -1)
217 		goto eexit;
218 
219 	on = 1;
220 	if (setsockopt(fd, IPPROTO_IPV6, IPV6_RECVHOPLIMIT,
221 	    &on, sizeof(on)) == -1)
222 		goto eexit;
223 
224 	ICMP6_FILTER_SETBLOCKALL(&filt);
225 	ICMP6_FILTER_SETPASS(ND_ROUTER_ADVERT, &filt);
226 	if (setsockopt(fd, IPPROTO_ICMPV6, ICMP6_FILTER,
227 	    &filt, sizeof(filt)) == -1)
228 		goto eexit;
229 
230 	return fd;
231 
232 eexit:
233 	close(fd);
234 	return -1;
235 }
236 
237 #ifdef __sun
238 static int
239 ipv6nd_open(struct interface *ifp)
240 {
241 	int fd;
242 	struct ipv6_mreq mreq = {
243 	    .ipv6mr_multiaddr = IN6ADDR_LINKLOCAL_ALLNODES_INIT,
244 	    .ipv6mr_interface = ifp->index
245 	};
246 	struct rs_state *state = RS_STATE(ifp);
247 	uint_t ifindex = ifp->index;
248 
249 	if (state->nd_fd != -1)
250 		return state->nd_fd;
251 
252 	fd = ipv6nd_open0();
253 	if (fd == -1)
254 		return -1;
255 
256 	if (setsockopt(fd, IPPROTO_IPV6, IPV6_BOUND_IF,
257 	    &ifindex, sizeof(ifindex)) == -1)
258 	{
259 		close(fd);
260 		return -1;
261 	}
262 
263 	if (setsockopt(fd, IPPROTO_IPV6, IPV6_JOIN_GROUP,
264 	    &mreq, sizeof(mreq)) == -1)
265 	{
266 		close(fd);
267 		return -1;
268 	}
269 
270 	state->nd_fd = fd;
271 	eloop_event_add(ifp->ctx->eloop, fd, ipv6nd_handledata, ifp);
272 	return fd;
273 }
274 #else
275 static int
276 ipv6nd_open(struct dhcpcd_ctx *ctx)
277 {
278 	int fd;
279 
280 	if (ctx->nd_fd != -1)
281 		return ctx->nd_fd;
282 
283 	fd = ipv6nd_open0();
284 	if (fd == -1)
285 		return -1;
286 
287 	ctx->nd_fd = fd;
288 	eloop_event_add(ctx->eloop, fd, ipv6nd_handledata, ctx);
289 	return fd;
290 }
291 #endif
292 
293 static int
294 ipv6nd_makersprobe(struct interface *ifp)
295 {
296 	struct rs_state *state;
297 	struct nd_router_solicit *rs;
298 
299 	state = RS_STATE(ifp);
300 	free(state->rs);
301 	state->rslen = sizeof(*rs);
302 	if (ifp->hwlen != 0)
303 		state->rslen += (size_t)ROUNDUP8(ifp->hwlen + 2);
304 	state->rs = calloc(1, state->rslen);
305 	if (state->rs == NULL)
306 		return -1;
307 	rs = state->rs;
308 	rs->nd_rs_type = ND_ROUTER_SOLICIT;
309 	//rs->nd_rs_code = 0;
310 	//rs->nd_rs_cksum = 0;
311 	//rs->nd_rs_reserved = 0;
312 
313 	if (ifp->hwlen != 0) {
314 		struct nd_opt_hdr *nd;
315 
316 		nd = (struct nd_opt_hdr *)(state->rs + 1);
317 		nd->nd_opt_type = ND_OPT_SOURCE_LINKADDR;
318 		nd->nd_opt_len = (uint8_t)((ROUNDUP8(ifp->hwlen + 2)) >> 3);
319 		memcpy(nd + 1, ifp->hwaddr, ifp->hwlen);
320 	}
321 	return 0;
322 }
323 
324 static void
325 ipv6nd_sendrsprobe(void *arg)
326 {
327 	struct interface *ifp = arg;
328 	struct rs_state *state = RS_STATE(ifp);
329 	struct sockaddr_in6 dst = {
330 		.sin6_family = AF_INET6,
331 		.sin6_addr = IN6ADDR_LINKLOCAL_ALLROUTERS_INIT,
332 		.sin6_scope_id = ifp->index,
333 	};
334 	struct iovec iov = { .iov_base = state->rs, .iov_len = state->rslen };
335 	unsigned char ctl[CMSG_SPACE(sizeof(struct in6_pktinfo))] = { 0 };
336 	struct msghdr msg = {
337 	    .msg_name = &dst, .msg_namelen = sizeof(dst),
338 	    .msg_iov = &iov, .msg_iovlen = 1,
339 	    .msg_control = ctl, .msg_controllen = sizeof(ctl),
340 	};
341 	struct cmsghdr *cm;
342 	struct in6_pktinfo pi = { .ipi6_ifindex = ifp->index };
343 	int s;
344 
345 	if (ipv6_linklocal(ifp) == NULL) {
346 		logdebugx("%s: delaying Router Solicitation for LL address",
347 		    ifp->name);
348 		ipv6_addlinklocalcallback(ifp, ipv6nd_sendrsprobe, ifp);
349 		return;
350 	}
351 
352 #ifdef HAVE_SA_LEN
353 	dst.sin6_len = sizeof(dst);
354 #endif
355 
356 	/* Set the outbound interface */
357 	cm = CMSG_FIRSTHDR(&msg);
358 	if (cm == NULL) /* unlikely */
359 		return;
360 	cm->cmsg_level = IPPROTO_IPV6;
361 	cm->cmsg_type = IPV6_PKTINFO;
362 	cm->cmsg_len = CMSG_LEN(sizeof(pi));
363 	memcpy(CMSG_DATA(cm), &pi, sizeof(pi));
364 
365 	logdebugx("%s: sending Router Solicitation", ifp->name);
366 #ifdef __sun
367 	s = state->nd_fd;
368 #else
369 	s = ifp->ctx->nd_fd;
370 #endif
371 	if (sendmsg(s, &msg, 0) == -1) {
372 		logerr(__func__);
373 		/* Allow IPv6ND to continue .... at most a few errors
374 		 * would be logged.
375 		 * Generally the error is ENOBUFS when struggling to
376 		 * associate with an access point. */
377 	}
378 
379 	if (state->rsprobes++ < MAX_RTR_SOLICITATIONS)
380 		eloop_timeout_add_sec(ifp->ctx->eloop,
381 		    RTR_SOLICITATION_INTERVAL, ipv6nd_sendrsprobe, ifp);
382 	else {
383 		logwarnx("%s: no IPv6 Routers available", ifp->name);
384 		ipv6nd_drop(ifp);
385 	}
386 }
387 
388 #ifdef ND6_ADVERTISE
389 static void
390 ipv6nd_sendadvertisement(void *arg)
391 {
392 	struct ipv6_addr *ia = arg;
393 	struct interface *ifp = ia->iface;
394 	struct dhcpcd_ctx *ctx = ifp->ctx;
395 	struct sockaddr_in6 dst = {
396 	    .sin6_family = AF_INET6,
397 	    .sin6_addr = IN6ADDR_LINKLOCAL_ALLNODES_INIT,
398 	    .sin6_scope_id = ifp->index,
399 	};
400 	struct iovec iov = { .iov_base = ia->na, .iov_len = ia->na_len };
401 	unsigned char ctl[CMSG_SPACE(sizeof(struct in6_pktinfo))] = { 0 };
402 	struct msghdr msg = {
403 	    .msg_name = &dst, .msg_namelen = sizeof(dst),
404 	    .msg_iov = &iov, .msg_iovlen = 1,
405 	    .msg_control = ctl, .msg_controllen = sizeof(ctl),
406 	};
407 	struct cmsghdr *cm;
408 	struct in6_pktinfo pi = { .ipi6_ifindex = ifp->index };
409 	const struct rs_state *state = RS_CSTATE(ifp);
410 	int s;
411 
412 	if (state == NULL || ifp->carrier <= LINK_DOWN)
413 		goto freeit;
414 
415 #ifdef SIN6_LEN
416 	dst.sin6_len = sizeof(dst);
417 #endif
418 
419 	/* Set the outbound interface. */
420 	cm = CMSG_FIRSTHDR(&msg);
421 	assert(cm != NULL);
422 	cm->cmsg_level = IPPROTO_IPV6;
423 	cm->cmsg_type = IPV6_PKTINFO;
424 	cm->cmsg_len = CMSG_LEN(sizeof(pi));
425 	memcpy(CMSG_DATA(cm), &pi, sizeof(pi));
426 	logdebugx("%s: sending NA for %s", ifp->name, ia->saddr);
427 #ifdef __sun
428 	s = state->nd_fd;
429 #else
430 	s = ctx->nd_fd;
431 #endif
432 	if (sendmsg(s, &msg, 0) == -1)
433 		logerr(__func__);
434 
435 	if (++ia->na_count < MAX_NEIGHBOR_ADVERTISEMENT) {
436 		eloop_timeout_add_sec(ctx->eloop,
437 		    state->retrans / 1000, ipv6nd_sendadvertisement, ia);
438 		return;
439 	}
440 
441 freeit:
442 	free(ia->na);
443 	ia->na = NULL;
444 	ia->na_count = 0;
445 }
446 
447 void
448 ipv6nd_advertise(struct ipv6_addr *ia)
449 {
450 	struct dhcpcd_ctx *ctx;
451 	struct interface *ifp;
452 	struct ipv6_state *state;
453 	struct ipv6_addr *iap, *iaf;
454 	struct nd_neighbor_advert *na;
455 
456 	if (IN6_IS_ADDR_MULTICAST(&ia->addr))
457 		return;
458 
459 #ifdef __sun
460 	if (!(ia->flags & IPV6_AF_AUTOCONF) && ia->flags & IPV6_AF_RAPFX)
461 		return;
462 #endif
463 
464 	ctx = ia->iface->ctx;
465 	/* Find the most preferred address to advertise. */
466 	iaf = NULL;
467 	TAILQ_FOREACH(ifp, ctx->ifaces, next) {
468 		state = IPV6_STATE(ifp);
469 		if (state == NULL || ifp->carrier <= LINK_DOWN)
470 			continue;
471 
472 		TAILQ_FOREACH(iap, &state->addrs, next) {
473 			if (!IN6_ARE_ADDR_EQUAL(&iap->addr, &ia->addr))
474 				continue;
475 
476 			/* Cancel any current advertisement. */
477 			eloop_timeout_delete(ctx->eloop,
478 			    ipv6nd_sendadvertisement, iap);
479 
480 			/* Don't advertise what we can't use. */
481 			if (iap->prefix_vltime == 0 ||
482 			    iap->addr_flags & IN6_IFF_NOTUSEABLE)
483 				continue;
484 
485 			if (iaf == NULL ||
486 			    iaf->iface->metric > iap->iface->metric)
487 				iaf = iap;
488 		}
489 	}
490 	if (iaf == NULL)
491 		return;
492 
493 	/* Make the packet. */
494 	ifp = iaf->iface;
495 	iaf->na_len = sizeof(*na);
496 	if (ifp->hwlen != 0)
497 		iaf->na_len += (size_t)ROUNDUP8(ifp->hwlen + 2);
498 	na = calloc(1, iaf->na_len);
499 	if (na == NULL) {
500 		logerr(__func__);
501 		return;
502 	}
503 
504 	na->nd_na_type = ND_NEIGHBOR_ADVERT;
505 	na->nd_na_flags_reserved = ND_NA_FLAG_OVERRIDE;
506 	if (ip6_forwarding(ifp->name) == 1)
507 		na->nd_na_flags_reserved |= ND_NA_FLAG_ROUTER;
508 	na->nd_na_target = ia->addr;
509 
510 	if (ifp->hwlen != 0) {
511 		struct nd_opt_hdr *opt;
512 
513 		opt = (struct nd_opt_hdr *)(na + 1);
514 		opt->nd_opt_type = ND_OPT_TARGET_LINKADDR;
515 		opt->nd_opt_len = (uint8_t)((ROUNDUP8(ifp->hwlen + 2)) >> 3);
516 		memcpy(opt + 1, ifp->hwaddr, ifp->hwlen);
517 	}
518 
519 	iaf->na_count = 0;
520 	free(iaf->na);
521 	iaf->na = na;
522 	eloop_timeout_delete(ctx->eloop, ipv6nd_sendadvertisement, iaf);
523 	ipv6nd_sendadvertisement(iaf);
524 }
525 #elif !defined(SMALL)
526 #warning kernel does not support userland sending ND6 advertisements
527 #endif /* ND6_ADVERTISE */
528 
529 static void
530 ipv6nd_expire(void *arg)
531 {
532 	struct interface *ifp = arg;
533 	struct ra *rap;
534 	struct ipv6_addr *ia;
535 	struct timespec now = { .tv_sec = 1 };
536 
537 	if (ifp->ctx->ra_routers == NULL)
538 		return;
539 
540 	TAILQ_FOREACH(rap, ifp->ctx->ra_routers, next) {
541 		if (rap->iface == ifp)
542 			continue;
543 		rap->acquired = now;
544 		TAILQ_FOREACH(ia, &rap->addrs, next) {
545 			ia->acquired = now;
546 		}
547 	}
548 	ipv6nd_expirera(ifp);
549 }
550 
551 void
552 ipv6nd_startexpire(struct interface *ifp)
553 {
554 
555 	eloop_timeout_add_sec(ifp->ctx->eloop, RTR_CARRIER_EXPIRE,
556 	    ipv6nd_expire, ifp);
557 }
558 
559 static int
560 ipv6nd_rtpref(struct ra *rap)
561 {
562 
563 	switch (rap->flags & ND_RA_FLAG_RTPREF_MASK) {
564 	case ND_RA_FLAG_RTPREF_HIGH:
565 		return RTPREF_HIGH;
566 	case ND_RA_FLAG_RTPREF_MEDIUM:
567 	case ND_RA_FLAG_RTPREF_RSV:
568 		return RTPREF_MEDIUM;
569 	case ND_RA_FLAG_RTPREF_LOW:
570 		return RTPREF_LOW;
571 	default:
572 		logerrx("%s: impossible RA flag %x", __func__, rap->flags);
573 		return RTPREF_INVALID;
574 	}
575 	/* NOTREACHED */
576 }
577 
578 static void
579 ipv6nd_sortrouters(struct dhcpcd_ctx *ctx)
580 {
581 	struct ra_head sorted_routers = TAILQ_HEAD_INITIALIZER(sorted_routers);
582 	struct ra *ra1, *ra2;
583 
584 	while ((ra1 = TAILQ_FIRST(ctx->ra_routers)) != NULL) {
585 		TAILQ_REMOVE(ctx->ra_routers, ra1, next);
586 		TAILQ_FOREACH(ra2, &sorted_routers, next) {
587 			if (ra1->iface->metric < ra2->iface->metric)
588 				continue;
589 			if (ra1->expired && !ra2->expired)
590 				continue;
591 			if (ra1->lifetime == 0 && ra2->lifetime != 0)
592 				continue;
593 			if (!ra1->isreachable && ra2->reachable)
594 				continue;
595 			if (ipv6nd_rtpref(ra1) < ipv6nd_rtpref(ra2))
596 				continue;
597 			/* All things being equal, prefer older routers. */
598 			if (timespeccmp(&ra1->acquired, &ra2->acquired, >=))
599 				continue;
600 			TAILQ_INSERT_BEFORE(ra2, ra1, next);
601 			break;
602 		}
603 		if (ra2 == NULL)
604 			TAILQ_INSERT_TAIL(&sorted_routers, ra1, next);
605 	}
606 
607 	TAILQ_CONCAT(ctx->ra_routers, &sorted_routers, next);
608 }
609 
610 static void
611 ipv6nd_applyra(struct dhcpcd_ctx *ctx, struct interface *ifp)
612 {
613 	struct ra *rap;
614 	struct rs_state *state = RS_STATE(ifp);
615 
616 	TAILQ_FOREACH(rap, ctx->ra_routers, next) {
617 		if (rap->iface == ifp)
618 			break;
619 	}
620 
621 	if (rap == NULL)
622 		return;
623 
624 	state->retrans = rap->retrans;
625 	if (if_applyra(rap) == -1)
626 		logerr(__func__);
627 }
628 
629 /*
630  * Neighbour reachability.
631  *
632  * RFC 4681 6.2.5 says when a node is no longer a router it MUST
633  * send a RA with a zero lifetime.
634  * All OS's I know of set the NA router flag if they are a router
635  * or not and disregard that they are actively advertising or
636  * shutting down. If the interface is disabled, it cant't send a NA at all.
637  *
638  * As such we CANNOT rely on the NA Router flag and MUST use
639  * unreachability or receive a RA with a lifetime of zero to remove
640  * the node as a default router.
641  */
642 void
643 ipv6nd_neighbour(struct dhcpcd_ctx *ctx, struct in6_addr *addr, bool reachable)
644 {
645 	struct ra *rap, *rapr;
646 
647 	if (ctx->ra_routers == NULL)
648 		return;
649 
650 	TAILQ_FOREACH(rap, ctx->ra_routers, next) {
651 		if (IN6_ARE_ADDR_EQUAL(&rap->from, addr))
652 			break;
653 	}
654 
655 	if (rap == NULL || rap->expired || rap->isreachable == reachable)
656 		return;
657 
658 	rap->isreachable = reachable;
659 	loginfox("%s: %s is %s", rap->iface->name, rap->sfrom,
660 	    reachable ? "reachable again" : "unreachable");
661 
662 	/* See if we can install a reachable default router. */
663 	ipv6nd_sortrouters(ctx);
664 	ipv6nd_applyra(ctx, rap->iface);
665 	rt_build(ctx, AF_INET6);
666 
667 	if (reachable)
668 		return;
669 
670 	/* If we have no reachable default routers, try and solicit one. */
671 	TAILQ_FOREACH(rapr, ctx->ra_routers, next) {
672 		if (rap == rapr || rap->iface != rapr->iface)
673 			continue;
674 		if (rapr->isreachable && !rapr->expired && rapr->lifetime)
675 			break;
676 	}
677 
678 	if (rapr == NULL)
679 		ipv6nd_startrs(rap->iface);
680 }
681 
682 const struct ipv6_addr *
683 ipv6nd_iffindaddr(const struct interface *ifp, const struct in6_addr *addr,
684     unsigned int flags)
685 {
686 	struct ra *rap;
687 	struct ipv6_addr *ap;
688 
689 	if (ifp->ctx->ra_routers == NULL)
690 		return NULL;
691 
692 	TAILQ_FOREACH(rap, ifp->ctx->ra_routers, next) {
693 		if (rap->iface != ifp)
694 			continue;
695 		TAILQ_FOREACH(ap, &rap->addrs, next) {
696 			if (ipv6_findaddrmatch(ap, addr, flags))
697 				return ap;
698 		}
699 	}
700 	return NULL;
701 }
702 
703 struct ipv6_addr *
704 ipv6nd_findaddr(struct dhcpcd_ctx *ctx, const struct in6_addr *addr,
705     unsigned int flags)
706 {
707 	struct ra *rap;
708 	struct ipv6_addr *ap;
709 
710 	if (ctx->ra_routers == NULL)
711 		return NULL;
712 
713 	TAILQ_FOREACH(rap, ctx->ra_routers, next) {
714 		TAILQ_FOREACH(ap, &rap->addrs, next) {
715 			if (ipv6_findaddrmatch(ap, addr, flags))
716 				return ap;
717 		}
718 	}
719 	return NULL;
720 }
721 
722 static void
723 ipv6nd_removefreedrop_ra(struct ra *rap, int remove_ra, int drop_ra)
724 {
725 
726 	eloop_timeout_delete(rap->iface->ctx->eloop, NULL, rap->iface);
727 	eloop_timeout_delete(rap->iface->ctx->eloop, NULL, rap);
728 	if (remove_ra)
729 		TAILQ_REMOVE(rap->iface->ctx->ra_routers, rap, next);
730 	ipv6_freedrop_addrs(&rap->addrs, drop_ra, NULL);
731 	free(rap->data);
732 	free(rap);
733 }
734 
735 static void
736 ipv6nd_freedrop_ra(struct ra *rap, int drop)
737 {
738 
739 	ipv6nd_removefreedrop_ra(rap, 1, drop);
740 }
741 
742 ssize_t
743 ipv6nd_free(struct interface *ifp)
744 {
745 	struct rs_state *state;
746 	struct ra *rap, *ran;
747 	struct dhcpcd_ctx *ctx;
748 	ssize_t n;
749 
750 	state = RS_STATE(ifp);
751 	if (state == NULL)
752 		return 0;
753 
754 	ctx = ifp->ctx;
755 #ifdef __sun
756 	eloop_event_delete(ctx->eloop, state->nd_fd);
757 	close(state->nd_fd);
758 #endif
759 	free(state->rs);
760 	free(state);
761 	ifp->if_data[IF_DATA_IPV6ND] = NULL;
762 	n = 0;
763 	TAILQ_FOREACH_SAFE(rap, ifp->ctx->ra_routers, next, ran) {
764 		if (rap->iface == ifp) {
765 			ipv6nd_free_ra(rap);
766 			n++;
767 		}
768 	}
769 
770 #ifndef __sun
771 	/* If we don't have any more IPv6 enabled interfaces,
772 	 * close the global socket and release resources */
773 	TAILQ_FOREACH(ifp, ctx->ifaces, next) {
774 		if (RS_STATE(ifp))
775 			break;
776 	}
777 	if (ifp == NULL) {
778 		if (ctx->nd_fd != -1) {
779 			eloop_event_delete(ctx->eloop, ctx->nd_fd);
780 			close(ctx->nd_fd);
781 			ctx->nd_fd = -1;
782 		}
783 	}
784 #endif
785 
786 	return n;
787 }
788 
789 static int
790 ipv6nd_scriptrun(struct ra *rap)
791 {
792 	int hasdns, hasaddress, pid;
793 	struct ipv6_addr *ap;
794 
795 	hasaddress = 0;
796 	/* If all addresses have completed DAD run the script */
797 	TAILQ_FOREACH(ap, &rap->addrs, next) {
798 		if ((ap->flags & (IPV6_AF_AUTOCONF | IPV6_AF_ADDED)) ==
799 		    (IPV6_AF_AUTOCONF | IPV6_AF_ADDED))
800 		{
801 			hasaddress = 1;
802 			if (!(ap->flags & IPV6_AF_DADCOMPLETED) &&
803 			    ipv6_iffindaddr(ap->iface, &ap->addr,
804 			    IN6_IFF_TENTATIVE))
805 				ap->flags |= IPV6_AF_DADCOMPLETED;
806 			if ((ap->flags & IPV6_AF_DADCOMPLETED) == 0) {
807 				logdebugx("%s: waiting for Router Advertisement"
808 				    " DAD to complete",
809 				    rap->iface->name);
810 				return 0;
811 			}
812 		}
813 	}
814 
815 	/* If we don't require RDNSS then set hasdns = 1 so we fork */
816 	if (!(rap->iface->options->options & DHCPCD_IPV6RA_REQRDNSS))
817 		hasdns = 1;
818 	else {
819 		hasdns = rap->hasdns;
820 	}
821 
822 	script_runreason(rap->iface, "ROUTERADVERT");
823 	pid = 0;
824 	if (hasdns && (hasaddress ||
825 	    !(rap->flags & (ND_RA_FLAG_MANAGED | ND_RA_FLAG_OTHER))))
826 		pid = dhcpcd_daemonise(rap->iface->ctx);
827 #if 0
828 	else if (options & DHCPCD_DAEMONISE &&
829 	    !(options & DHCPCD_DAEMONISED) && new_data)
830 		logwarnx("%s: did not fork due to an absent"
831 		    " RDNSS option in the RA",
832 		    ifp->name);
833 }
834 #endif
835 	return pid;
836 }
837 
838 static void
839 ipv6nd_addaddr(void *arg)
840 {
841 	struct ipv6_addr *ap = arg;
842 
843 	ipv6_addaddr(ap, NULL);
844 }
845 
846 int
847 ipv6nd_dadcompleted(const struct interface *ifp)
848 {
849 	const struct ra *rap;
850 	const struct ipv6_addr *ap;
851 
852 	TAILQ_FOREACH(rap, ifp->ctx->ra_routers, next) {
853 		if (rap->iface != ifp)
854 			continue;
855 		TAILQ_FOREACH(ap, &rap->addrs, next) {
856 			if (ap->flags & IPV6_AF_AUTOCONF &&
857 			    ap->flags & IPV6_AF_ADDED &&
858 			    !(ap->flags & IPV6_AF_DADCOMPLETED))
859 				return 0;
860 		}
861 	}
862 	return 1;
863 }
864 
865 static void
866 ipv6nd_dadcallback(void *arg)
867 {
868 	struct ipv6_addr *ia = arg, *rapap;
869 	struct interface *ifp;
870 	struct ra *rap;
871 	int wascompleted, found;
872 	struct timespec tv;
873 	char buf[INET6_ADDRSTRLEN];
874 	const char *p;
875 	int dadcounter;
876 
877 	ifp = ia->iface;
878 	wascompleted = (ia->flags & IPV6_AF_DADCOMPLETED);
879 	ia->flags |= IPV6_AF_DADCOMPLETED;
880 	if (ia->flags & IPV6_AF_DUPLICATED) {
881 		ia->dadcounter++;
882 		logwarnx("%s: DAD detected %s", ifp->name, ia->saddr);
883 
884 		/* Try and make another stable private address.
885 		 * Because ap->dadcounter is always increamented,
886 		 * a different address is generated. */
887 		/* XXX Cache DAD counter per prefix/id/ssid? */
888 		if (ifp->options->options & DHCPCD_SLAACPRIVATE) {
889 			if (ia->dadcounter >= IDGEN_RETRIES) {
890 				logerrx("%s: unable to obtain a"
891 				    " stable private address",
892 				    ifp->name);
893 				goto try_script;
894 			}
895 			loginfox("%s: deleting address %s",
896 			    ifp->name, ia->saddr);
897 			if (if_address6(RTM_DELADDR, ia) == -1 &&
898 			    errno != EADDRNOTAVAIL && errno != ENXIO)
899 				logerr(__func__);
900 			dadcounter = ia->dadcounter;
901 			if (ipv6_makestableprivate(&ia->addr,
902 			    &ia->prefix, ia->prefix_len,
903 			    ifp, &dadcounter) == -1)
904 			{
905 				logerr("ipv6_makestableprivate");
906 				return;
907 			}
908 			ia->dadcounter = dadcounter;
909 			ia->flags &= ~(IPV6_AF_ADDED | IPV6_AF_DADCOMPLETED);
910 			ia->flags |= IPV6_AF_NEW;
911 			p = inet_ntop(AF_INET6, &ia->addr, buf, sizeof(buf));
912 			if (p)
913 				snprintf(ia->saddr,
914 				    sizeof(ia->saddr),
915 				    "%s/%d",
916 				    p, ia->prefix_len);
917 			else
918 				ia->saddr[0] = '\0';
919 			tv.tv_sec = 0;
920 			tv.tv_nsec = (suseconds_t)
921 			    arc4random_uniform(IDGEN_DELAY * NSEC_PER_SEC);
922 			timespecnorm(&tv);
923 			eloop_timeout_add_tv(ifp->ctx->eloop, &tv,
924 			    ipv6nd_addaddr, ia);
925 			return;
926 		}
927 	}
928 
929 try_script:
930 	if (!wascompleted) {
931 		TAILQ_FOREACH(rap, ifp->ctx->ra_routers, next) {
932 			if (rap->iface != ifp)
933 				continue;
934 			wascompleted = 1;
935 			found = 0;
936 			TAILQ_FOREACH(rapap, &rap->addrs, next) {
937 				if (rapap->flags & IPV6_AF_AUTOCONF &&
938 				    rapap->flags & IPV6_AF_ADDED &&
939 				    (rapap->flags & IPV6_AF_DADCOMPLETED) == 0)
940 				{
941 					wascompleted = 0;
942 					break;
943 				}
944 				if (rapap == ia)
945 					found = 1;
946 			}
947 
948 			if (wascompleted && found) {
949 				logdebugx("%s: Router Advertisement DAD "
950 				    "completed",
951 				    rap->iface->name);
952 				if (ipv6nd_scriptrun(rap))
953 					return;
954 			}
955 		}
956 #ifdef ND6_ADVERTISE
957 		ipv6nd_advertise(ia);
958 #endif
959 	}
960 }
961 
962 #ifndef DHCP6
963 /* If DHCPv6 is compiled out, supply a shim to provide an error message
964  * if IPv6RA requests DHCPv6. */
965 enum DH6S {
966 	DH6S_REQUEST,
967 	DH6S_INFORM,
968 };
969 static int
970 dhcp6_start(__unused struct interface *ifp, __unused enum DH6S init_state)
971 {
972 
973 	errno = ENOTSUP;
974 	return -1;
975 }
976 #endif
977 
978 static void
979 ipv6nd_handlera(struct dhcpcd_ctx *ctx,
980     const struct sockaddr_in6 *from, const char *sfrom,
981     struct interface *ifp, struct icmp6_hdr *icp, size_t len, int hoplimit)
982 {
983 	size_t i, olen;
984 	struct nd_router_advert *nd_ra;
985 	struct nd_opt_hdr ndo;
986 	struct nd_opt_prefix_info pi;
987 	struct nd_opt_mtu mtu;
988 	struct nd_opt_rdnss rdnss;
989 	uint8_t *p;
990 	struct ra *rap;
991 	struct in6_addr pi_prefix;
992 	struct ipv6_addr *ap;
993 	struct dhcp_opt *dho;
994 	bool new_rap, new_data, has_address;
995 	uint32_t old_lifetime;
996 	int ifmtu;
997 	__printflike(1, 2) void (*logfunc)(const char *, ...);
998 #ifdef IPV6_MANAGETEMPADDR
999 	uint8_t new_ap;
1000 #endif
1001 
1002 	if (ifp == NULL) {
1003 #ifdef DEBUG_RS
1004 		logdebugx("RA for unexpected interface from %s", sfrom);
1005 #endif
1006 		return;
1007 	}
1008 
1009 	if (len < sizeof(struct nd_router_advert)) {
1010 		logerrx("IPv6 RA packet too short from %s", sfrom);
1011 		return;
1012 	}
1013 
1014 	/* RFC 4861 7.1.2 */
1015 	if (hoplimit != 255) {
1016 		logerrx("invalid hoplimit(%d) in RA from %s", hoplimit, sfrom);
1017 		return;
1018 	}
1019 	if (!IN6_IS_ADDR_LINKLOCAL(&from->sin6_addr)) {
1020 		logerrx("RA from non local address %s", sfrom);
1021 		return;
1022 	}
1023 
1024 	if (!(ifp->options->options & DHCPCD_IPV6RS)) {
1025 #ifdef DEBUG_RS
1026 		logerrx("%s: unexpected RA from %s", ifp->name, sfrom);
1027 #endif
1028 		return;
1029 	}
1030 
1031 	/* We could receive a RA before we sent a RS*/
1032 	if (ipv6_linklocal(ifp) == NULL) {
1033 #ifdef DEBUG_RS
1034 		logdebugx("%s: received RA from %s (no link-local)",
1035 		    ifp->name, sfrom);
1036 #endif
1037 		return;
1038 	}
1039 
1040 	if (ipv6_iffindaddr(ifp, &from->sin6_addr, IN6_IFF_TENTATIVE)) {
1041 		logdebugx("%s: ignoring RA from ourself %s",
1042 		    ifp->name, sfrom);
1043 		return;
1044 	}
1045 
1046 	TAILQ_FOREACH(rap, ctx->ra_routers, next) {
1047 		if (ifp == rap->iface &&
1048 		    IN6_ARE_ADDR_EQUAL(&rap->from, &from->sin6_addr))
1049 			break;
1050 	}
1051 
1052 	nd_ra = (struct nd_router_advert *)icp;
1053 
1054 	/* We don't want to spam the log with the fact we got an RA every
1055 	 * 30 seconds or so, so only spam the log if it's different. */
1056 	if (rap == NULL || (rap->data_len != len ||
1057 	     memcmp(rap->data, (unsigned char *)icp, rap->data_len) != 0))
1058 	{
1059 		if (rap) {
1060 			free(rap->data);
1061 			rap->data_len = 0;
1062 		}
1063 		new_data = true;
1064 	} else
1065 		new_data = false;
1066 	if (rap == NULL) {
1067 		rap = calloc(1, sizeof(*rap));
1068 		if (rap == NULL) {
1069 			logerr(__func__);
1070 			return;
1071 		}
1072 		rap->iface = ifp;
1073 		rap->from = from->sin6_addr;
1074 		strlcpy(rap->sfrom, sfrom, sizeof(rap->sfrom));
1075 		TAILQ_INIT(&rap->addrs);
1076 		new_rap = true;
1077 		rap->isreachable = true;
1078 	} else
1079 		new_rap = false;
1080 	if (rap->data_len == 0) {
1081 		rap->data = malloc(len);
1082 		if (rap->data == NULL) {
1083 			logerr(__func__);
1084 			if (new_rap)
1085 				free(rap);
1086 			return;
1087 		}
1088 		memcpy(rap->data, icp, len);
1089 		rap->data_len = len;
1090 	}
1091 
1092 	/* We could change the debug level based on new_data, but some
1093 	 * routers like to decrease the advertised valid and preferred times
1094 	 * in accordance with the own prefix times which would result in too
1095 	 * much needless log spam. */
1096 	logfunc = new_data || !rap->isreachable ? loginfox : logdebugx,
1097 	logfunc("%s: Router Advertisement from %s", ifp->name, rap->sfrom);
1098 
1099 	clock_gettime(CLOCK_MONOTONIC, &rap->acquired);
1100 	rap->flags = nd_ra->nd_ra_flags_reserved;
1101 	old_lifetime = rap->lifetime;
1102 	rap->lifetime = ntohs(nd_ra->nd_ra_router_lifetime);
1103 	if (!new_rap && rap->lifetime == 0 && old_lifetime != 0)
1104 		logwarnx("%s: %s: no longer a default router",
1105 		    ifp->name, rap->sfrom);
1106 	if (nd_ra->nd_ra_curhoplimit != 0)
1107 		rap->hoplimit = nd_ra->nd_ra_curhoplimit;
1108 	else
1109 		rap->hoplimit = IPV6_DEFHLIM;
1110 	if (nd_ra->nd_ra_reachable != 0) {
1111 		rap->reachable = ntohl(nd_ra->nd_ra_reachable);
1112 		if (rap->reachable > MAX_REACHABLE_TIME)
1113 			rap->reachable = 0;
1114 	} else
1115 		rap->reachable = REACHABLE_TIME;
1116 	if (nd_ra->nd_ra_retransmit != 0)
1117 		rap->retrans = ntohl(nd_ra->nd_ra_retransmit);
1118 	else
1119 		rap->retrans = RETRANS_TIMER;
1120 	rap->expired = false;
1121 	rap->hasdns = false;
1122 	rap->isreachable = true;
1123 	has_address = false;
1124 	rap->mtu = 0;
1125 
1126 #ifdef IPV6_AF_TEMPORARY
1127 	ipv6_markaddrsstale(ifp, IPV6_AF_TEMPORARY);
1128 #endif
1129 	TAILQ_FOREACH(ap, &rap->addrs, next) {
1130 		ap->flags |= IPV6_AF_STALE;
1131 	}
1132 
1133 	len -= sizeof(struct nd_router_advert);
1134 	p = ((uint8_t *)icp) + sizeof(struct nd_router_advert);
1135 	for (; len > 0; p += olen, len -= olen) {
1136 		if (len < sizeof(ndo)) {
1137 			logerrx("%s: short option", ifp->name);
1138 			break;
1139 		}
1140 		memcpy(&ndo, p, sizeof(ndo));
1141 		olen = (size_t)ndo.nd_opt_len * 8;
1142 		if (olen == 0) {
1143 			logerrx("%s: zero length option", ifp->name);
1144 			break;
1145 		}
1146 		if (olen > len) {
1147 			logerrx("%s: option length exceeds message",
1148 			    ifp->name);
1149 			break;
1150 		}
1151 
1152 		if (has_option_mask(ifp->options->rejectmasknd,
1153 		    ndo.nd_opt_type))
1154 		{
1155 			for (i = 0, dho = ctx->nd_opts;
1156 			    i < ctx->nd_opts_len;
1157 			    i++, dho++)
1158 			{
1159 				if (dho->option == ndo.nd_opt_type)
1160 					break;
1161 			}
1162 			if (dho != NULL)
1163 				logwarnx("%s: reject RA (option %s) from %s",
1164 				    ifp->name, dho->var, rap->sfrom);
1165 			else
1166 				logwarnx("%s: reject RA (option %d) from %s",
1167 				    ifp->name, ndo.nd_opt_type, rap->sfrom);
1168 			if (new_rap)
1169 				ipv6nd_removefreedrop_ra(rap, 0, 0);
1170 			else
1171 				ipv6nd_free_ra(rap);
1172 			return;
1173 		}
1174 
1175 		if (has_option_mask(ifp->options->nomasknd, ndo.nd_opt_type))
1176 			continue;
1177 
1178 		switch (ndo.nd_opt_type) {
1179 		case ND_OPT_PREFIX_INFORMATION:
1180 			logfunc = new_data ? logerrx : logdebugx;
1181 			if (ndo.nd_opt_len != 4) {
1182 				logfunc("%s: invalid option len for prefix",
1183 				    ifp->name);
1184 				continue;
1185 			}
1186 			memcpy(&pi, p, sizeof(pi));
1187 			if (pi.nd_opt_pi_prefix_len > 128) {
1188 				logfunc("%s: invalid prefix len", ifp->name);
1189 				continue;
1190 			}
1191 			/* nd_opt_pi_prefix is not aligned. */
1192 			memcpy(&pi_prefix, &pi.nd_opt_pi_prefix,
1193 			    sizeof(pi_prefix));
1194 			if (IN6_IS_ADDR_MULTICAST(&pi_prefix) ||
1195 			    IN6_IS_ADDR_LINKLOCAL(&pi_prefix))
1196 			{
1197 				logfunc("%s: invalid prefix in RA", ifp->name);
1198 				continue;
1199 			}
1200 			if (ntohl(pi.nd_opt_pi_preferred_time) >
1201 			    ntohl(pi.nd_opt_pi_valid_time))
1202 			{
1203 				logfunc("%s: pltime > vltime", ifp->name);
1204 				continue;
1205 			}
1206 			TAILQ_FOREACH(ap, &rap->addrs, next)
1207 				if (ap->prefix_len ==pi.nd_opt_pi_prefix_len &&
1208 				    IN6_ARE_ADDR_EQUAL(&ap->prefix, &pi_prefix))
1209 					break;
1210 			if (ap == NULL) {
1211 				unsigned int flags;
1212 
1213 				flags = IPV6_AF_RAPFX;
1214 				if (pi.nd_opt_pi_flags_reserved &
1215 				    ND_OPT_PI_FLAG_AUTO &&
1216 				    rap->iface->options->options &
1217 				    DHCPCD_IPV6RA_AUTOCONF)
1218 					flags |= IPV6_AF_AUTOCONF;
1219 
1220 				ap = ipv6_newaddr(rap->iface,
1221 				    &pi_prefix, pi.nd_opt_pi_prefix_len, flags);
1222 				if (ap == NULL)
1223 					break;
1224 				ap->prefix = pi_prefix;
1225 				if (flags & IPV6_AF_AUTOCONF)
1226 					ap->dadcallback = ipv6nd_dadcallback;
1227 				ap->created = ap->acquired = rap->acquired;
1228 				TAILQ_INSERT_TAIL(&rap->addrs, ap, next);
1229 
1230 #ifdef IPV6_MANAGETEMPADDR
1231 				/* New address to dhcpcd RA handling.
1232 				 * If the address already exists and a valid
1233 				 * temporary address also exists then
1234 				 * extend the existing one rather than
1235 				 * create a new one */
1236 				if (flags & IPV6_AF_AUTOCONF &&
1237 				    ipv6_iffindaddr(ifp, &ap->addr,
1238 				    IN6_IFF_NOTUSEABLE) &&
1239 				    ipv6_settemptime(ap, 0))
1240 					new_ap = 0;
1241 				else
1242 					new_ap = 1;
1243 #endif
1244 			} else {
1245 #ifdef IPV6_MANAGETEMPADDR
1246 				new_ap = 0;
1247 #endif
1248 				ap->flags &= ~IPV6_AF_STALE;
1249 				ap->acquired = rap->acquired;
1250 			}
1251 			if (pi.nd_opt_pi_flags_reserved &
1252 			    ND_OPT_PI_FLAG_ONLINK)
1253 				ap->flags |= IPV6_AF_ONLINK;
1254 			ap->prefix_vltime =
1255 			    ntohl(pi.nd_opt_pi_valid_time);
1256 			ap->prefix_pltime =
1257 			    ntohl(pi.nd_opt_pi_preferred_time);
1258 			if (ap->prefix_vltime != 0 &&
1259 			    ap->flags & IPV6_AF_AUTOCONF)
1260 				has_address = true;
1261 
1262 #ifdef IPV6_MANAGETEMPADDR
1263 			/* RFC4941 Section 3.3.3 */
1264 			if (ap->flags & IPV6_AF_AUTOCONF &&
1265 			    ip6_use_tempaddr(ap->iface->name))
1266 			{
1267 				if (!new_ap) {
1268 					if (ipv6_settemptime(ap, 1) == NULL)
1269 						new_ap = 1;
1270 				}
1271 				if (new_ap && ap->prefix_pltime) {
1272 					if (ipv6_createtempaddr(ap,
1273 					    &ap->acquired) == NULL)
1274 						logerr("ipv6_createtempaddr");
1275 				}
1276 			}
1277 #endif
1278 			break;
1279 
1280 		case ND_OPT_MTU:
1281 			if (len < sizeof(mtu)) {
1282 				logfunc("%s: short MTU option", ifp->name);
1283 				break;
1284 			}
1285 			memcpy(&mtu, p, sizeof(mtu));
1286 			mtu.nd_opt_mtu_mtu = ntohl(mtu.nd_opt_mtu_mtu);
1287 			if (mtu.nd_opt_mtu_mtu < IPV6_MMTU) {
1288 				logfunc("%s: invalid MTU %d",
1289 				    ifp->name, mtu.nd_opt_mtu_mtu);
1290 				break;
1291 			}
1292 			ifmtu = if_getmtu(ifp);
1293 			if (ifmtu == -1)
1294 				logerr("if_getmtu");
1295 			else if (mtu.nd_opt_mtu_mtu > (uint32_t)ifmtu) {
1296 				logfunc("%s: advertised MTU %d"
1297 				    " is greater than link MTU %d",
1298 				    ifp->name, mtu.nd_opt_mtu_mtu, ifmtu);
1299 				rap->mtu = (uint32_t)ifmtu;
1300 			} else
1301 				rap->mtu = mtu.nd_opt_mtu_mtu;
1302 			break;
1303 		case ND_OPT_RDNSS:
1304 			if (len < sizeof(rdnss)) {
1305 				logfunc("%s: short RDNSS option", ifp->name);
1306 				break;
1307 			}
1308 			memcpy(&rdnss, p, sizeof(rdnss));
1309 			if (rdnss.nd_opt_rdnss_lifetime &&
1310 			    rdnss.nd_opt_rdnss_len > 1)
1311 				rap->hasdns = 1;
1312 			break;
1313 		default:
1314 			continue;
1315 		}
1316 	}
1317 
1318 	for (i = 0, dho = ctx->nd_opts;
1319 	    i < ctx->nd_opts_len;
1320 	    i++, dho++)
1321 	{
1322 		if (has_option_mask(ifp->options->requiremasknd,
1323 		    dho->option))
1324 		{
1325 			logwarnx("%s: reject RA (no option %s) from %s",
1326 			    ifp->name, dho->var, rap->sfrom);
1327 			if (new_rap)
1328 				ipv6nd_removefreedrop_ra(rap, 0, 0);
1329 			else
1330 				ipv6nd_free_ra(rap);
1331 			return;
1332 		}
1333 	}
1334 
1335 	if (new_data && !has_address && rap->lifetime && !ipv6_anyglobal(ifp))
1336 		logwarnx("%s: no global addresses for default route",
1337 		    ifp->name);
1338 
1339 	if (new_rap)
1340 		TAILQ_INSERT_TAIL(ctx->ra_routers, rap, next);
1341 	if (new_data)
1342 		ipv6nd_sortrouters(ifp->ctx);
1343 
1344 	if (ifp->ctx->options & DHCPCD_TEST) {
1345 		script_runreason(ifp, "TEST");
1346 		goto handle_flag;
1347 	}
1348 	ipv6nd_applyra(ifp->ctx, ifp);
1349 	ipv6_addaddrs(&rap->addrs);
1350 #ifdef IPV6_MANAGETEMPADDR
1351 	ipv6_addtempaddrs(ifp, &rap->acquired);
1352 #endif
1353 
1354 	rt_build(ifp->ctx, AF_INET6);
1355 	if (ipv6nd_scriptrun(rap))
1356 		return;
1357 
1358 	eloop_timeout_delete(ifp->ctx->eloop, NULL, ifp);
1359 	eloop_timeout_delete(ifp->ctx->eloop, NULL, rap); /* reachable timer */
1360 
1361 handle_flag:
1362 	if (!(ifp->options->options & DHCPCD_DHCP6))
1363 		goto nodhcp6;
1364 /* Only log a DHCPv6 start error if compiled in or debugging is enabled. */
1365 #ifdef DHCP6
1366 #define LOG_DHCP6	logerr
1367 #else
1368 #define LOG_DHCP6	logdebug
1369 #endif
1370 	if (rap->flags & ND_RA_FLAG_MANAGED) {
1371 		if (new_data && dhcp6_start(ifp, DH6S_REQUEST) == -1)
1372 			LOG_DHCP6("dhcp6_start: %s", ifp->name);
1373 	} else if (rap->flags & ND_RA_FLAG_OTHER) {
1374 		if (new_data && dhcp6_start(ifp, DH6S_INFORM) == -1)
1375 			LOG_DHCP6("dhcp6_start: %s", ifp->name);
1376 	} else {
1377 #ifdef DHCP6
1378 		if (new_data)
1379 			logdebugx("%s: No DHCPv6 instruction in RA", ifp->name);
1380 #endif
1381 nodhcp6:
1382 		if (ifp->ctx->options & DHCPCD_TEST) {
1383 			eloop_exit(ifp->ctx->eloop, EXIT_SUCCESS);
1384 			return;
1385 		}
1386 	}
1387 
1388 	/* Expire should be called last as the rap object could be destroyed */
1389 	ipv6nd_expirera(ifp);
1390 }
1391 
1392 bool
1393 ipv6nd_hasralifetime(const struct interface *ifp, bool lifetime)
1394 {
1395 	const struct ra *rap;
1396 
1397 	if (ifp->ctx->ra_routers) {
1398 		TAILQ_FOREACH(rap, ifp->ctx->ra_routers, next)
1399 			if (rap->iface == ifp && !rap->expired &&
1400 			    (!lifetime ||rap->lifetime))
1401 				return true;
1402 	}
1403 	return false;
1404 }
1405 
1406 bool
1407 ipv6nd_hasradhcp(const struct interface *ifp)
1408 {
1409 	const struct ra *rap;
1410 
1411 	if (ifp->ctx->ra_routers) {
1412 		TAILQ_FOREACH(rap, ifp->ctx->ra_routers, next) {
1413 			if (rap->iface == ifp &&
1414 			    !rap->expired &&
1415 			    (rap->flags &(ND_RA_FLAG_MANAGED|ND_RA_FLAG_OTHER)))
1416 				return true;
1417 		}
1418 	}
1419 	return false;
1420 }
1421 
1422 static const uint8_t *
1423 ipv6nd_getoption(struct dhcpcd_ctx *ctx,
1424     size_t *os, unsigned int *code, size_t *len,
1425     const uint8_t *od, size_t ol, struct dhcp_opt **oopt)
1426 {
1427 	struct nd_opt_hdr ndo;
1428 	size_t i;
1429 	struct dhcp_opt *opt;
1430 
1431 	if (od) {
1432 		*os = sizeof(ndo);
1433 		if (ol < *os) {
1434 			errno = EINVAL;
1435 			return NULL;
1436 		}
1437 		memcpy(&ndo, od, sizeof(ndo));
1438 		i = (size_t)(ndo.nd_opt_len * 8);
1439 		if (i > ol) {
1440 			errno = EINVAL;
1441 			return NULL;
1442 		}
1443 		*len = i;
1444 		*code = ndo.nd_opt_type;
1445 	}
1446 
1447 	for (i = 0, opt = ctx->nd_opts;
1448 	    i < ctx->nd_opts_len; i++, opt++)
1449 	{
1450 		if (opt->option == *code) {
1451 			*oopt = opt;
1452 			break;
1453 		}
1454 	}
1455 
1456 	if (od)
1457 		return od + sizeof(ndo);
1458 	return NULL;
1459 }
1460 
1461 ssize_t
1462 ipv6nd_env(FILE *fp, const struct interface *ifp)
1463 {
1464 	size_t i, j, n, len, olen;
1465 	struct ra *rap;
1466 	char ndprefix[32];
1467 	struct dhcp_opt *opt;
1468 	uint8_t *p;
1469 	struct nd_opt_hdr ndo;
1470 	struct ipv6_addr *ia;
1471 	struct timespec now;
1472 
1473 	clock_gettime(CLOCK_MONOTONIC, &now);
1474 	i = n = 0;
1475 	TAILQ_FOREACH(rap, ifp->ctx->ra_routers, next) {
1476 		if (rap->iface != ifp || rap->expired)
1477 			continue;
1478 		i++;
1479 		snprintf(ndprefix, sizeof(ndprefix), "nd%zu", i);
1480 		if (efprintf(fp, "%s_from=%s", ndprefix, rap->sfrom) == -1)
1481 			return -1;
1482 		if (efprintf(fp, "%s_acquired=%lld", ndprefix,
1483 		    (long long)rap->acquired.tv_sec) == -1)
1484 			return -1;
1485 		if (efprintf(fp, "%s_now=%lld", ndprefix,
1486 		    (long long)now.tv_sec) == -1)
1487 			return -1;
1488 
1489 		/* Zero our indexes */
1490 		for (j = 0, opt = rap->iface->ctx->nd_opts;
1491 		    j < rap->iface->ctx->nd_opts_len;
1492 		    j++, opt++)
1493 			dhcp_zero_index(opt);
1494 		for (j = 0, opt = rap->iface->options->nd_override;
1495 		    j < rap->iface->options->nd_override_len;
1496 		    j++, opt++)
1497 			dhcp_zero_index(opt);
1498 
1499 		/* Unlike DHCP, ND6 options *may* occur more than once.
1500 		 * There is also no provision for option concatenation
1501 		 * unlike DHCP. */
1502 		len = rap->data_len - sizeof(struct nd_router_advert);
1503 		for (p = rap->data + sizeof(struct nd_router_advert);
1504 		    len >= sizeof(ndo);
1505 		    p += olen, len -= olen)
1506 		{
1507 			memcpy(&ndo, p, sizeof(ndo));
1508 			olen = (size_t)(ndo.nd_opt_len * 8);
1509 			if (olen > len) {
1510 				errno =	EINVAL;
1511 				break;
1512 			}
1513 			if (has_option_mask(rap->iface->options->nomasknd,
1514 			    ndo.nd_opt_type))
1515 				continue;
1516 			for (j = 0, opt = rap->iface->options->nd_override;
1517 			    j < rap->iface->options->nd_override_len;
1518 			    j++, opt++)
1519 				if (opt->option == ndo.nd_opt_type)
1520 					break;
1521 			if (j == rap->iface->options->nd_override_len) {
1522 				for (j = 0, opt = rap->iface->ctx->nd_opts;
1523 				    j < rap->iface->ctx->nd_opts_len;
1524 				    j++, opt++)
1525 					if (opt->option == ndo.nd_opt_type)
1526 						break;
1527 				if (j == rap->iface->ctx->nd_opts_len)
1528 					opt = NULL;
1529 			}
1530 			if (opt == NULL)
1531 				continue;
1532 			dhcp_envoption(rap->iface->ctx, fp,
1533 			    ndprefix, rap->iface->name,
1534 			    opt, ipv6nd_getoption,
1535 			    p + sizeof(ndo), olen - sizeof(ndo));
1536 		}
1537 
1538 		/* We need to output the addresses we actually made
1539 		 * from the prefix information options as well. */
1540 		j = 0;
1541 		TAILQ_FOREACH(ia, &rap->addrs, next) {
1542 			if (!(ia->flags & IPV6_AF_AUTOCONF) ||
1543 #ifdef IPV6_AF_TEMPORARY
1544 			    ia->flags & IPV6_AF_TEMPORARY ||
1545 #endif
1546 			    !(ia->flags & IPV6_AF_ADDED) ||
1547 			    ia->prefix_vltime == 0)
1548 				continue;
1549 			if (efprintf(fp, "%s_addr%zu=%s",
1550 			    ndprefix, j++, ia->saddr) == -1)
1551 				return -1;
1552 		}
1553 	}
1554 	return 1;
1555 }
1556 
1557 void
1558 ipv6nd_handleifa(int cmd, struct ipv6_addr *addr, pid_t pid)
1559 {
1560 	struct ra *rap;
1561 
1562 	/* IPv6 init may not have happened yet if we are learning
1563 	 * existing addresses when dhcpcd starts. */
1564 	if (addr->iface->ctx->ra_routers == NULL)
1565 		return;
1566 
1567 	TAILQ_FOREACH(rap, addr->iface->ctx->ra_routers, next) {
1568 		if (rap->iface != addr->iface)
1569 			continue;
1570 		ipv6_handleifa_addrs(cmd, &rap->addrs, addr, pid);
1571 	}
1572 }
1573 
1574 void
1575 ipv6nd_expirera(void *arg)
1576 {
1577 	struct interface *ifp;
1578 	struct ra *rap, *ran;
1579 	struct timespec now, lt, expire, next;
1580 	bool expired, valid;
1581 	struct ipv6_addr *ia;
1582 	size_t len, olen;
1583 	uint8_t *p;
1584 	struct nd_opt_hdr ndo;
1585 #if 0
1586 	struct nd_opt_prefix_info pi;
1587 #endif
1588 	struct nd_opt_dnssl dnssl;
1589 	struct nd_opt_rdnss rdnss;
1590 	uint32_t ltime;
1591 	size_t nexpired = 0;
1592 
1593 	ifp = arg;
1594 	clock_gettime(CLOCK_MONOTONIC, &now);
1595 	expired = false;
1596 	timespecclear(&next);
1597 
1598 	TAILQ_FOREACH_SAFE(rap, ifp->ctx->ra_routers, next, ran) {
1599 		if (rap->iface != ifp || rap->expired)
1600 			continue;
1601 		valid = false;
1602 		if (rap->lifetime) {
1603 			lt.tv_sec = (time_t)rap->lifetime;
1604 			lt.tv_nsec = 0;
1605 			timespecadd(&rap->acquired, &lt, &expire);
1606 			if (timespeccmp(&now, &expire, >)) {
1607 				if (!rap->expired) {
1608 					logwarnx("%s: %s: router expired",
1609 					    ifp->name, rap->sfrom);
1610 					rap->lifetime = 0;
1611 					expired = true;
1612 				}
1613 			} else {
1614 				valid = true;
1615 				timespecsub(&expire, &now, &lt);
1616 				if (!timespecisset(&next) ||
1617 				    timespeccmp(&next, &lt, >))
1618 					next = lt;
1619 			}
1620 		}
1621 
1622 		/* Not every prefix is tied to an address which
1623 		 * the kernel can expire, so we need to handle it ourself.
1624 		 * Also, some OS don't support address lifetimes (Solaris). */
1625 		TAILQ_FOREACH(ia, &rap->addrs, next) {
1626 			if (ia->prefix_vltime == 0)
1627 				continue;
1628 			if (ia->prefix_vltime == ND6_INFINITE_LIFETIME) {
1629 				valid = true;
1630 				continue;
1631 			}
1632 			lt.tv_sec = (time_t)ia->prefix_vltime;
1633 			lt.tv_nsec = 0;
1634 			timespecadd(&ia->acquired, &lt, &expire);
1635 			if (timespeccmp(&now, &expire, >)) {
1636 				if (ia->flags & IPV6_AF_ADDED) {
1637 					logwarnx("%s: expired address %s",
1638 					    ia->iface->name, ia->saddr);
1639 					if (if_address6(RTM_DELADDR, ia)== -1 &&
1640 					    errno != EADDRNOTAVAIL &&
1641 					    errno != ENXIO)
1642 						logerr(__func__);
1643 				}
1644 				ia->prefix_vltime = ia->prefix_pltime = 0;
1645 				ia->flags &=
1646 				    ~(IPV6_AF_ADDED | IPV6_AF_DADCOMPLETED);
1647 				expired = true;
1648 			} else {
1649 				timespecsub(&expire, &now, &lt);
1650 				if (!timespecisset(&next) ||
1651 				    timespeccmp(&next, &lt, >))
1652 					next = lt;
1653 				valid = true;
1654 			}
1655 		}
1656 
1657 		/* Work out expiry for ND options */
1658 		len = rap->data_len - sizeof(struct nd_router_advert);
1659 		for (p = rap->data + sizeof(struct nd_router_advert);
1660 		    len >= sizeof(ndo);
1661 		    p += olen, len -= olen)
1662 		{
1663 			memcpy(&ndo, p, sizeof(ndo));
1664 			olen = (size_t)(ndo.nd_opt_len * 8);
1665 			if (olen > len) {
1666 				errno =	EINVAL;
1667 				break;
1668 			}
1669 
1670 			if (has_option_mask(rap->iface->options->nomasknd,
1671 			    ndo.nd_opt_type))
1672 				continue;
1673 
1674 			switch (ndo.nd_opt_type) {
1675 			/* Prefix info is already checked in the above loop. */
1676 #if 0
1677 			case ND_OPT_PREFIX_INFORMATION:
1678 				if (len < sizeof(pi))
1679 					break;
1680 				memcpy(&pi, p, sizeof(pi));
1681 				ltime = pi.nd_opt_pi_valid_time;
1682 				break;
1683 #endif
1684 			case ND_OPT_DNSSL:
1685 				if (len < sizeof(dnssl))
1686 					continue;
1687 				memcpy(&dnssl, p, sizeof(dnssl));
1688 				ltime = dnssl.nd_opt_dnssl_lifetime;
1689 				break;
1690 			case ND_OPT_RDNSS:
1691 				if (len < sizeof(rdnss))
1692 					continue;
1693 				memcpy(&rdnss, p, sizeof(rdnss));
1694 				ltime = rdnss.nd_opt_rdnss_lifetime;
1695 				break;
1696 			default:
1697 				continue;
1698 			}
1699 
1700 			if (ltime == 0)
1701 				continue;
1702 			if (ltime == ND6_INFINITE_LIFETIME) {
1703 				valid = true;
1704 				continue;
1705 			}
1706 
1707 			lt.tv_sec = (time_t)ntohl(ltime);
1708 			lt.tv_nsec = 0;
1709 			timespecadd(&rap->acquired, &lt, &expire);
1710 			if (timespeccmp(&now, &expire, >)) {
1711 				expired = true;
1712 				continue;
1713 			}
1714 
1715 			timespecsub(&expire, &now, &lt);
1716 			if (!timespecisset(&next) ||
1717 			    timespeccmp(&next, &lt, >))
1718 			{
1719 				next = lt;
1720 				valid = true;
1721 			}
1722 		}
1723 
1724 		if (valid)
1725 			continue;
1726 
1727 		/* Router has expired. Let's not keep a lot of them. */
1728 		rap->expired = true;
1729 		if (++nexpired > EXPIRED_MAX)
1730 			ipv6nd_free_ra(rap);
1731 	}
1732 
1733 	if (timespecisset(&next))
1734 		eloop_timeout_add_tv(ifp->ctx->eloop,
1735 		    &next, ipv6nd_expirera, ifp);
1736 	if (expired) {
1737 		logwarnx("%s: part of Router Advertisement expired", ifp->name);
1738 		rt_build(ifp->ctx, AF_INET6);
1739 		script_runreason(ifp, "ROUTERADVERT");
1740 	}
1741 }
1742 
1743 void
1744 ipv6nd_drop(struct interface *ifp)
1745 {
1746 	struct ra *rap, *ran;
1747 	bool expired = false;
1748 
1749 	if (ifp->ctx->ra_routers == NULL)
1750 		return;
1751 
1752 	eloop_timeout_delete(ifp->ctx->eloop, NULL, ifp);
1753 	TAILQ_FOREACH_SAFE(rap, ifp->ctx->ra_routers, next, ran) {
1754 		if (rap->iface == ifp) {
1755 			rap->expired = expired = true;
1756 			ipv6nd_drop_ra(rap);
1757 		}
1758 	}
1759 	if (expired) {
1760 		rt_build(ifp->ctx, AF_INET6);
1761 		if ((ifp->options->options & DHCPCD_NODROP) != DHCPCD_NODROP)
1762 			script_runreason(ifp, "ROUTERADVERT");
1763 	}
1764 }
1765 
1766 static void
1767 ipv6nd_recvmsg(struct dhcpcd_ctx *ctx, struct msghdr *msg)
1768 {
1769 	struct sockaddr_in6 *from = (struct sockaddr_in6 *)msg->msg_name;
1770 	char sfrom[INET6_ADDRSTRLEN];
1771 	int hoplimit = 0;
1772 	struct icmp6_hdr *icp;
1773 	struct interface *ifp;
1774 	size_t len = msg->msg_iov[0].iov_len;
1775 
1776 	inet_ntop(AF_INET6, &from->sin6_addr, sfrom, sizeof(sfrom));
1777 	if ((size_t)len < sizeof(struct icmp6_hdr)) {
1778 		logerrx("IPv6 ICMP packet too short from %s", sfrom);
1779 		return;
1780 	}
1781 
1782 	ifp = if_findifpfromcmsg(ctx, msg, &hoplimit);
1783 	if (ifp == NULL) {
1784 		logerr(__func__);
1785 		return;
1786 	}
1787 
1788 	/* Don't do anything if the user hasn't configured it. */
1789 	if (ifp->active != IF_ACTIVE_USER ||
1790 	    !(ifp->options->options & DHCPCD_IPV6))
1791 		return;
1792 
1793 	icp = (struct icmp6_hdr *)msg->msg_iov[0].iov_base;
1794 	if (icp->icmp6_code == 0) {
1795 		switch(icp->icmp6_type) {
1796 			case ND_ROUTER_ADVERT:
1797 				ipv6nd_handlera(ctx, from, sfrom,
1798 				    ifp, icp, (size_t)len, hoplimit);
1799 				return;
1800 		}
1801 	}
1802 
1803 	logerrx("invalid IPv6 type %d or code %d from %s",
1804 	    icp->icmp6_type, icp->icmp6_code, sfrom);
1805 }
1806 
1807 static void
1808 ipv6nd_handledata(void *arg)
1809 {
1810 	struct dhcpcd_ctx *ctx;
1811 	int fd;
1812 	struct sockaddr_in6 from;
1813 	unsigned char buf[64 * 1024]; /* Maximum ICMPv6 size */
1814 	struct iovec iov = {
1815 		.iov_base = buf,
1816 		.iov_len = sizeof(buf),
1817 	};
1818 	unsigned char ctl[CMSG_SPACE(sizeof(struct in6_pktinfo)) + CMSG_SPACE(sizeof(int))] = { 0 };
1819 	struct msghdr msg = {
1820 	    .msg_name = &from, .msg_namelen = sizeof(from),
1821 	    .msg_iov = &iov, .msg_iovlen = 1,
1822 	    .msg_control = ctl, .msg_controllen = sizeof(ctl),
1823 	};
1824 	ssize_t len;
1825 
1826 #ifdef __sun
1827 	struct interface *ifp;
1828 	struct rs_state *state;
1829 
1830 	ifp = arg;
1831 	state = RS_STATE(ifp);
1832 	ctx = ifp->ctx;
1833 	fd = state->nd_fd;
1834 #else
1835 	ctx = arg;
1836 	fd = ctx->nd_fd;
1837 #endif
1838 	len = recvmsg(fd, &msg, 0);
1839 	if (len == -1) {
1840 		logerr(__func__);
1841 		return;
1842 	}
1843 
1844 	iov.iov_len = (size_t)len;
1845 	ipv6nd_recvmsg(ctx, &msg);
1846 }
1847 
1848 static void
1849 ipv6nd_startrs1(void *arg)
1850 {
1851 	struct interface *ifp = arg;
1852 	struct rs_state *state;
1853 
1854 	loginfox("%s: soliciting an IPv6 router", ifp->name);
1855 	state = RS_STATE(ifp);
1856 	if (state == NULL) {
1857 		ifp->if_data[IF_DATA_IPV6ND] = calloc(1, sizeof(*state));
1858 		state = RS_STATE(ifp);
1859 		if (state == NULL) {
1860 			logerr(__func__);
1861 			return;
1862 		}
1863 #ifdef __sun
1864 		state->nd_fd = -1;
1865 #endif
1866 	}
1867 
1868 #ifdef __sun
1869 	if (ipv6nd_open(ifp) == -1) {
1870 		logerr(__func__);
1871 		return;
1872 	}
1873 #else
1874 	if (ipv6nd_open(ifp->ctx) == -1) {
1875 		logerr(__func__);
1876 		return;
1877 	}
1878 #endif
1879 
1880 	/* Always make a new probe as the underlying hardware
1881 	 * address could have changed. */
1882 	ipv6nd_makersprobe(ifp);
1883 	if (state->rs == NULL) {
1884 		logerr(__func__);
1885 		return;
1886 	}
1887 
1888 	state->retrans = RETRANS_TIMER;
1889 	state->rsprobes = 0;
1890 	ipv6nd_sendrsprobe(ifp);
1891 }
1892 
1893 void
1894 ipv6nd_startrs(struct interface *ifp)
1895 {
1896 	struct timespec tv;
1897 
1898 	eloop_timeout_delete(ifp->ctx->eloop, NULL, ifp);
1899 	if (!(ifp->options->options & DHCPCD_INITIAL_DELAY)) {
1900 		ipv6nd_startrs1(ifp);
1901 		return;
1902 	}
1903 
1904 	tv.tv_sec = 0;
1905 	tv.tv_nsec = (suseconds_t)arc4random_uniform(
1906 	    MAX_RTR_SOLICITATION_DELAY * NSEC_PER_SEC);
1907 	timespecnorm(&tv);
1908 	logdebugx("%s: delaying IPv6 router solicitation for %0.1f seconds",
1909 	    ifp->name, timespec_to_double(&tv));
1910 	eloop_timeout_add_tv(ifp->ctx->eloop, &tv, ipv6nd_startrs1, ifp);
1911 	return;
1912 }
1913