1/*
2 * dhcpcd - IPv6 ND handling
3 * Copyright (c) 2006-2019 Roy Marples <roy@marples.name>
4 * All rights reserved
5
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 * SUCH DAMAGE.
26 */
27
28#include <sys/ioctl.h>
29#include <sys/param.h>
30#include <sys/socket.h>
31#include <net/if.h>
32#include <net/route.h>
33#include <netinet/in.h>
34#include <netinet/ip6.h>
35#include <netinet/icmp6.h>
36
37#include <assert.h>
38#include <errno.h>
39#include <fcntl.h>
40#include <stddef.h>
41#include <stdlib.h>
42#include <string.h>
43#include <unistd.h>
44
45#define ELOOP_QUEUE 3
46#include "common.h"
47#include "dhcpcd.h"
48#include "dhcp-common.h"
49#include "dhcp6.h"
50#include "eloop.h"
51#include "if.h"
52#include "ipv6.h"
53#include "ipv6nd.h"
54#include "logerr.h"
55#include "route.h"
56#include "script.h"
57
58/* Debugging Router Solicitations is a lot of spam, so disable it */
59//#define DEBUG_RS
60
61#ifndef ND_OPT_RDNSS
62#define ND_OPT_RDNSS 25
63struct nd_opt_rdnss { /* RDNSS option RFC 6106 */
64 uint8_t nd_opt_rdnss_type;
65 uint8_t nd_opt_rdnss_len;
66 uint16_t nd_opt_rdnss_reserved;
67 uint32_t nd_opt_rdnss_lifetime;
68 /* followed by list of IP prefixes */
69};
70__CTASSERT(sizeof(struct nd_opt_rdnss) == 8);
71#endif
72
73#ifndef ND_OPT_DNSSL
74#define ND_OPT_DNSSL 31
75struct nd_opt_dnssl { /* DNSSL option RFC 6106 */
76 uint8_t nd_opt_dnssl_type;
77 uint8_t nd_opt_dnssl_len;
78 uint16_t nd_opt_dnssl_reserved;
79 uint32_t nd_opt_dnssl_lifetime;
80 /* followed by list of DNS servers */
81};
82__CTASSERT(sizeof(struct nd_opt_rdnss) == 8);
83#endif
84
85/* Impossible options, so we can easily add extras */
86#define _ND_OPT_PREFIX_ADDR 255 + 1
87
88/* Minimal IPv6 MTU */
89#ifndef IPV6_MMTU
90#define IPV6_MMTU 1280
91#endif
92
93#ifndef ND_RA_FLAG_RTPREF_HIGH
94#define ND_RA_FLAG_RTPREF_MASK 0x18
95#define ND_RA_FLAG_RTPREF_HIGH 0x08
96#define ND_RA_FLAG_RTPREF_MEDIUM 0x00
97#define ND_RA_FLAG_RTPREF_LOW 0x18
98#define ND_RA_FLAG_RTPREF_RSV 0x10
99#endif
100
101/* RTPREF_MEDIUM has to be 0! */
102#define RTPREF_HIGH 1
103#define RTPREF_MEDIUM 0
104#define RTPREF_LOW (-1)
105#define RTPREF_RESERVED (-2)
106#define RTPREF_INVALID (-3) /* internal */
107
108#define MIN_RANDOM_FACTOR 500 /* millisecs */
109#define MAX_RANDOM_FACTOR 1500 /* millisecs */
110#define MIN_RANDOM_FACTOR_U MIN_RANDOM_FACTOR * 1000 /* usecs */
111#define MAX_RANDOM_FACTOR_U MAX_RANDOM_FACTOR * 1000 /* usecs */
112
113#if BYTE_ORDER == BIG_ENDIAN
114#define IPV6_ADDR_INT32_ONE 1
115#define IPV6_ADDR_INT16_MLL 0xff02
116#elif BYTE_ORDER == LITTLE_ENDIAN
117#define IPV6_ADDR_INT32_ONE 0x01000000
118#define IPV6_ADDR_INT16_MLL 0x02ff
119#endif
120
121/* Debugging Neighbor Solicitations is a lot of spam, so disable it */
122//#define DEBUG_NS
123//
124
125static void ipv6nd_handledata(void *);
126
127/*
128 * Android ships buggy ICMP6 filter headers.
129 * Supply our own until they fix their shit.
130 * References:
131 * https://android-review.googlesource.com/#/c/58438/
132 * http://code.google.com/p/android/issues/original?id=32621&seq=24
133 */
134#ifdef __ANDROID__
135#undef ICMP6_FILTER_WILLPASS
136#undef ICMP6_FILTER_WILLBLOCK
137#undef ICMP6_FILTER_SETPASS
138#undef ICMP6_FILTER_SETBLOCK
139#undef ICMP6_FILTER_SETPASSALL
140#undef ICMP6_FILTER_SETBLOCKALL
141#define ICMP6_FILTER_WILLPASS(type, filterp) \
142 ((((filterp)->icmp6_filt[(type) >> 5]) & (1 << ((type) & 31))) == 0)
143#define ICMP6_FILTER_WILLBLOCK(type, filterp) \
144 ((((filterp)->icmp6_filt[(type) >> 5]) & (1 << ((type) & 31))) != 0)
145#define ICMP6_FILTER_SETPASS(type, filterp) \
146 ((((filterp)->icmp6_filt[(type) >> 5]) &= ~(1 << ((type) & 31))))
147#define ICMP6_FILTER_SETBLOCK(type, filterp) \
148 ((((filterp)->icmp6_filt[(type) >> 5]) |= (1 << ((type) & 31))))
149#define ICMP6_FILTER_SETPASSALL(filterp) \
150 memset(filterp, 0, sizeof(struct icmp6_filter));
151#define ICMP6_FILTER_SETBLOCKALL(filterp) \
152 memset(filterp, 0xff, sizeof(struct icmp6_filter));
153#endif
154
155/* Support older systems with different defines */
156#if !defined(IPV6_RECVHOPLIMIT) && defined(IPV6_HOPLIMIT)
157#define IPV6_RECVHOPLIMIT IPV6_HOPLIMIT
158#endif
159#if !defined(IPV6_RECVPKTINFO) && defined(IPV6_PKTINFO)
160#define IPV6_RECVPKTINFO IPV6_PKTINFO
161#endif
162
163/* Handy defines */
164#define ipv6nd_free_ra(ra) ipv6nd_freedrop_ra((ra), 0)
165#define ipv6nd_drop_ra(ra) ipv6nd_freedrop_ra((ra), 1)
166
167void
168ipv6nd_printoptions(const struct dhcpcd_ctx *ctx,
169 const struct dhcp_opt *opts, size_t opts_len)
170{
171 size_t i, j;
172 const struct dhcp_opt *opt, *opt2;
173 int cols;
174
175 for (i = 0, opt = ctx->nd_opts;
176 i < ctx->nd_opts_len; i++, opt++)
177 {
178 for (j = 0, opt2 = opts; j < opts_len; j++, opt2++)
179 if (opt2->option == opt->option)
180 break;
181 if (j == opts_len) {
182 cols = printf("%03d %s", opt->option, opt->var);
183 dhcp_print_option_encoding(opt, cols);
184 }
185 }
186 for (i = 0, opt = opts; i < opts_len; i++, opt++) {
187 cols = printf("%03d %s", opt->option, opt->var);
188 dhcp_print_option_encoding(opt, cols);
189 }
190}
191
192static int
193ipv6nd_open0(void)
194{
195 int s, on;
196 struct icmp6_filter filt;
197
198#define SOCK_FLAGS SOCK_CLOEXEC | SOCK_NONBLOCK
199 s = xsocket(PF_INET6, SOCK_RAW | SOCK_FLAGS, IPPROTO_ICMPV6);
200#undef SOCK_FLAGS
201 if (s == -1)
202 return -1;
203
204 /* RFC4861 4.1 */
205 on = 255;
206 if (setsockopt(s, IPPROTO_IPV6, IPV6_MULTICAST_HOPS,
207 &on, sizeof(on)) == -1)
208 goto eexit;
209
210 on = 1;
211 if (setsockopt(s, IPPROTO_IPV6, IPV6_RECVHOPLIMIT,
212 &on, sizeof(on)) == -1)
213 goto eexit;
214
215 ICMP6_FILTER_SETBLOCKALL(&filt);
216 ICMP6_FILTER_SETPASS(ND_NEIGHBOR_ADVERT, &filt);
217 ICMP6_FILTER_SETPASS(ND_ROUTER_ADVERT, &filt);
218 if (setsockopt(s, IPPROTO_ICMPV6, ICMP6_FILTER,
219 &filt, sizeof(filt)) == -1)
220 goto eexit;
221
222 return s;
223
224eexit:
225 close(s);
226 return -1;
227}
228
229#ifdef __sun
230static int
231ipv6nd_open(struct interface *ifp)
232{
233 int s;
234 struct ipv6_mreq mreq = {
235 .ipv6mr_multiaddr = IN6ADDR_LINKLOCAL_ALLNODES_INIT,
236 .ipv6mr_interface = ifp->index
237 };
238 struct rs_state *state = RS_STATE(ifp);
239 uint_t ifindex = ifp->index;
240
241 if (state->nd_fd != -1)
242 return state->nd_fd;
243
244 s = ipv6nd_open0();
245 if (s == -1)
246 return -1;
247
248 if (setsockopt(s, IPPROTO_IPV6, IPV6_BOUND_IF,
249 &ifindex, sizeof(ifindex)) == -1)
250 {
251 close(s);
252 return -1;
253 }
254
255 if (setsockopt(s, IPPROTO_IPV6, IPV6_JOIN_GROUP,
256 &mreq, sizeof(mreq)) == -1)
257 {
258 close(s);
259 return -1;
260 }
261
262 state->nd_fd = s;
263 eloop_event_add(ifp->ctx->eloop, s, ipv6nd_handledata, ifp);
264 return s;
265}
266#else
267static int
268ipv6nd_open(struct dhcpcd_ctx *ctx)
269{
270 int s, on;
271
272 if (ctx->nd_fd != -1)
273 return ctx->nd_fd;
274
275 s = ipv6nd_open0();
276 if (s == -1)
277 return -1;
278
279 on = 1;
280 if (setsockopt(s, IPPROTO_IPV6, IPV6_RECVPKTINFO,
281 &on, sizeof(on)) == -1)
282 {
283 close(s);
284 return -1;
285 }
286
287 ctx->nd_fd = s;
288 eloop_event_add(ctx->eloop, s, ipv6nd_handledata, ctx);
289 return s;
290}
291#endif
292
293static int
294ipv6nd_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
324static void
325ipv6nd_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
388static void
389ipv6nd_sendadvertisement(void *arg)
390{
391 struct ipv6_addr *ia = arg;
392 struct interface *ifp = ia->iface;
393 struct dhcpcd_ctx *ctx = ifp->ctx;
394 struct sockaddr_in6 dst = {
395 .sin6_family = AF_INET6,
396 .sin6_addr = IN6ADDR_LINKLOCAL_ALLNODES_INIT,
397 .sin6_scope_id = ifp->index,
398 };
399 struct iovec iov = { .iov_base = ia->na, .iov_len = ia->na_len };
400 unsigned char ctl[CMSG_SPACE(sizeof(struct in6_pktinfo))] = { 0 };
401 struct msghdr msg = {
402 .msg_name = &dst, .msg_namelen = sizeof(dst),
403 .msg_iov = &iov, .msg_iovlen = 1,
404 .msg_control = ctl, .msg_controllen = sizeof(ctl),
405 };
406 struct cmsghdr *cm;
407 struct in6_pktinfo pi = { .ipi6_ifindex = ifp->index };
408 const struct rs_state *state = RS_CSTATE(ifp);
409 int s;
410
411 if (state == NULL || ifp->carrier <= LINK_DOWN)
412 goto freeit;
413
414#ifdef SIN6_LEN
415 dst.sin6_len = sizeof(dst);
416#endif
417
418 /* Set the outbound interface. */
419 cm = CMSG_FIRSTHDR(&msg);
420 assert(cm != NULL);
421 cm->cmsg_level = IPPROTO_IPV6;
422 cm->cmsg_type = IPV6_PKTINFO;
423 cm->cmsg_len = CMSG_LEN(sizeof(pi));
424 memcpy(CMSG_DATA(cm), &pi, sizeof(pi));
425 logdebugx("%s: sending NA for %s", ifp->name, ia->saddr);
426#ifdef __sun
427 s = state->nd_fd;
428#else
429 s = ctx->nd_fd;
430#endif
431 if (sendmsg(s, &msg, 0) == -1)
432#ifdef __OpenBSD__
433/* This isn't too critical as they don't support IPv6 address sharing */
434#warning Cannot send NA messages on OpenBSD
435 logdebug(__func__);
436#else
437 logerr(__func__);
438#endif
439
440 if (++ia->na_count < MAX_NEIGHBOR_ADVERTISEMENT) {
441 eloop_timeout_add_sec(ctx->eloop,
442 state->retrans / 1000, ipv6nd_sendadvertisement, ia);
443 return;
444 }
445
446freeit:
447 free(ia->na);
448 ia->na = NULL;
449 ia->na_count = 0;
450}
451
452void
453ipv6nd_advertise(struct ipv6_addr *ia)
454{
455 struct dhcpcd_ctx *ctx;
456 struct interface *ifp;
457 struct ipv6_state *state;
458 struct ipv6_addr *iap, *iaf;
459 struct nd_neighbor_advert *na;
460
461 if (IN6_IS_ADDR_MULTICAST(&ia->addr))
462 return;
463
464 ctx = ia->iface->ctx;
465 if_sortinterfaces(ctx);
466 /* Find the most preferred address to advertise. */
467 iaf = NULL;
468 TAILQ_FOREACH(ifp, ctx->ifaces, next) {
469 state = IPV6_STATE(ifp);
470 if (state == NULL || ifp->carrier <= LINK_DOWN)
471 continue;
472
473 TAILQ_FOREACH(iap, &state->addrs, next) {
474 if (!IN6_ARE_ADDR_EQUAL(&iap->addr, &ia->addr))
475 continue;
476
477 /* Cancel any current advertisement. */
478 eloop_timeout_delete(ctx->eloop,
479 ipv6nd_sendadvertisement, iap);
480
481 /* Don't advertise what we can't use. */
482 if (iap->prefix_vltime == 0 ||
483 iap->addr_flags & IN6_IFF_NOTUSEABLE)
484 continue;
485
486 if (iaf == NULL)
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
526void
527ipv6nd_expire(struct interface *ifp, uint32_t seconds)
528{
529 struct ra *rap;
530 struct timespec now;
531 uint32_t vltime = seconds;
532 uint32_t pltime = seconds / 2;
533
534 if (ifp->ctx->ra_routers == NULL)
535 return;
536
537 clock_gettime(CLOCK_MONOTONIC, &now);
538
539 TAILQ_FOREACH(rap, ifp->ctx->ra_routers, next) {
540 if (rap->iface == ifp) {
541 rap->acquired = now;
542 rap->expired = seconds ? 0 : 1;
543 if (seconds) {
544 struct ipv6_addr *ia;
545
546 rap->lifetime = seconds;
547 TAILQ_FOREACH(ia, &rap->addrs, next) {
548 if (ia->prefix_pltime > pltime ||
549 ia->prefix_vltime > vltime)
550 {
551 ia->acquired = now;
552 if (ia->prefix_pltime != 0)
553 ia->prefix_pltime =
554 pltime;
555 ia->prefix_vltime = vltime;
556 }
557 }
558 ipv6_addaddrs(&rap->addrs);
559 }
560 }
561 }
562 if (seconds)
563 ipv6nd_expirera(ifp);
564 else
565 rt_build(ifp->ctx, AF_INET6);
566}
567
568static void
569ipv6nd_reachable(struct ra *rap, int flags)
570{
571
572 if (rap->lifetime == 0)
573 return;
574
575 if (flags & IPV6ND_REACHABLE) {
576 if (rap->expired == 0)
577 return;
578 loginfox("%s: %s is reachable again",
579 rap->iface->name, rap->sfrom);
580 rap->expired = 0;
581 } else {
582 if (rap->expired != 0)
583 return;
584 logwarnx("%s: %s is unreachable, expiring it",
585 rap->iface->name, rap->sfrom);
586 rap->expired = 1;
587 }
588
589 rt_build(rap->iface->ctx, AF_INET6);
590 /* XXX Not really an RA */
591 script_runreason(rap->iface, "ROUTERADVERT");
592}
593
594void
595ipv6nd_neighbour(struct dhcpcd_ctx *ctx, struct in6_addr *addr, int flags)
596{
597 struct ra *rap;
598
599 if (ctx->ra_routers) {
600 TAILQ_FOREACH(rap, ctx->ra_routers, next) {
601 if (IN6_ARE_ADDR_EQUAL(&rap->from, addr)) {
602 ipv6nd_reachable(rap, flags);
603 break;
604 }
605 }
606 }
607}
608
609const struct ipv6_addr *
610ipv6nd_iffindaddr(const struct interface *ifp, const struct in6_addr *addr,
611 unsigned int flags)
612{
613 struct ra *rap;
614 struct ipv6_addr *ap;
615
616 if (ifp->ctx->ra_routers == NULL)
617 return NULL;
618
619 TAILQ_FOREACH(rap, ifp->ctx->ra_routers, next) {
620 if (rap->iface != ifp)
621 continue;
622 TAILQ_FOREACH(ap, &rap->addrs, next) {
623 if (ipv6_findaddrmatch(ap, addr, flags))
624 return ap;
625 }
626 }
627 return NULL;
628}
629
630struct ipv6_addr *
631ipv6nd_findaddr(struct dhcpcd_ctx *ctx, const struct in6_addr *addr,
632 unsigned int flags)
633{
634 struct ra *rap;
635 struct ipv6_addr *ap;
636
637 if (ctx->ra_routers == NULL)
638 return NULL;
639
640 TAILQ_FOREACH(rap, ctx->ra_routers, next) {
641 TAILQ_FOREACH(ap, &rap->addrs, next) {
642 if (ipv6_findaddrmatch(ap, addr, flags))
643 return ap;
644 }
645 }
646 return NULL;
647}
648
649static void
650ipv6nd_removefreedrop_ra(struct ra *rap, int remove_ra, int drop_ra)
651{
652
653 eloop_timeout_delete(rap->iface->ctx->eloop, NULL, rap->iface);
654 eloop_timeout_delete(rap->iface->ctx->eloop, NULL, rap);
655 if (remove_ra)
656 TAILQ_REMOVE(rap->iface->ctx->ra_routers, rap, next);
657 ipv6_freedrop_addrs(&rap->addrs, drop_ra, NULL);
658 free(rap->data);
659 free(rap);
660}
661
662static void
663ipv6nd_freedrop_ra(struct ra *rap, int drop)
664{
665
666 ipv6nd_removefreedrop_ra(rap, 1, drop);
667}
668
669ssize_t
670ipv6nd_free(struct interface *ifp)
671{
672 struct rs_state *state;
673 struct ra *rap, *ran;
674 struct dhcpcd_ctx *ctx;
675 ssize_t n;
676
677 state = RS_STATE(ifp);
678 if (state == NULL)
679 return 0;
680
681 ctx = ifp->ctx;
682#ifdef __sun
683 eloop_event_delete(ctx->eloop, state->nd_fd);
684 close(state->nd_fd);
685#endif
686 free(state->rs);
687 free(state);
688 ifp->if_data[IF_DATA_IPV6ND] = NULL;
689 n = 0;
690 TAILQ_FOREACH_SAFE(rap, ifp->ctx->ra_routers, next, ran) {
691 if (rap->iface == ifp) {
692 ipv6nd_free_ra(rap);
693 n++;
694 }
695 }
696
697#ifndef __sun
698 /* If we don't have any more IPv6 enabled interfaces,
699 * close the global socket and release resources */
700 TAILQ_FOREACH(ifp, ctx->ifaces, next) {
701 if (RS_STATE(ifp))
702 break;
703 }
704 if (ifp == NULL) {
705 if (ctx->nd_fd != -1) {
706 eloop_event_delete(ctx->eloop, ctx->nd_fd);
707 close(ctx->nd_fd);
708 ctx->nd_fd = -1;
709 }
710 }
711#endif
712
713 return n;
714}
715
716static int
717rtpref(struct ra *rap)
718{
719
720 switch (rap->flags & ND_RA_FLAG_RTPREF_MASK) {
721 case ND_RA_FLAG_RTPREF_HIGH:
722 return (RTPREF_HIGH);
723 case ND_RA_FLAG_RTPREF_MEDIUM:
724 case ND_RA_FLAG_RTPREF_RSV:
725 return (RTPREF_MEDIUM);
726 case ND_RA_FLAG_RTPREF_LOW:
727 return (RTPREF_LOW);
728 default:
729 logerrx("rtpref: impossible RA flag %x", rap->flags);
730 return (RTPREF_INVALID);
731 }
732 /* NOTREACHED */
733}
734
735static void
736add_router(struct dhcpcd_ctx *ctx, struct ra *router)
737{
738 struct ra *rap;
739
740 TAILQ_FOREACH(rap, ctx->ra_routers, next) {
741 if (router->iface->metric < rap->iface->metric ||
742 (router->iface->metric == rap->iface->metric &&
743 rtpref(router) > rtpref(rap)))
744 {
745 TAILQ_INSERT_BEFORE(rap, router, next);
746 return;
747 }
748 }
749 TAILQ_INSERT_TAIL(ctx->ra_routers, router, next);
750}
751
752static int
753ipv6nd_scriptrun(struct ra *rap)
754{
755 int hasdns, hasaddress, pid;
756 struct ipv6_addr *ap;
757
758 hasaddress = 0;
759 /* If all addresses have completed DAD run the script */
760 TAILQ_FOREACH(ap, &rap->addrs, next) {
761 if ((ap->flags & (IPV6_AF_AUTOCONF | IPV6_AF_ADDED)) ==
762 (IPV6_AF_AUTOCONF | IPV6_AF_ADDED))
763 {
764 hasaddress = 1;
765 if (!(ap->flags & IPV6_AF_DADCOMPLETED) &&
766 ipv6_iffindaddr(ap->iface, &ap->addr,
767 IN6_IFF_TENTATIVE))
768 ap->flags |= IPV6_AF_DADCOMPLETED;
769 if ((ap->flags & IPV6_AF_DADCOMPLETED) == 0) {
770 logdebugx("%s: waiting for Router Advertisement"
771 " DAD to complete",
772 rap->iface->name);
773 return 0;
774 }
775 }
776 }
777
778 /* If we don't require RDNSS then set hasdns = 1 so we fork */
779 if (!(rap->iface->options->options & DHCPCD_IPV6RA_REQRDNSS))
780 hasdns = 1;
781 else {
782 hasdns = rap->hasdns;
783 }
784
785 script_runreason(rap->iface, "ROUTERADVERT");
786 pid = 0;
787 if (hasdns && (hasaddress ||
788 !(rap->flags & (ND_RA_FLAG_MANAGED | ND_RA_FLAG_OTHER))))
789 pid = dhcpcd_daemonise(rap->iface->ctx);
790#if 0
791 else if (options & DHCPCD_DAEMONISE &&
792 !(options & DHCPCD_DAEMONISED) && new_data)
793 logwarnx("%s: did not fork due to an absent"
794 " RDNSS option in the RA",
795 ifp->name);
796}
797#endif
798 return pid;
799}
800
801static void
802ipv6nd_addaddr(void *arg)
803{
804 struct ipv6_addr *ap = arg;
805
806 ipv6_addaddr(ap, NULL);
807}
808
809int
810ipv6nd_dadcompleted(const struct interface *ifp)
811{
812 const struct ra *rap;
813 const struct ipv6_addr *ap;
814
815 TAILQ_FOREACH(rap, ifp->ctx->ra_routers, next) {
816 if (rap->iface != ifp)
817 continue;
818 TAILQ_FOREACH(ap, &rap->addrs, next) {
819 if (ap->flags & IPV6_AF_AUTOCONF &&
820 ap->flags & IPV6_AF_ADDED &&
821 !(ap->flags & IPV6_AF_DADCOMPLETED))
822 return 0;
823 }
824 }
825 return 1;
826}
827
828static void
829ipv6nd_dadcallback(void *arg)
830{
831 struct ipv6_addr *ia = arg, *rapap;
832 struct interface *ifp;
833 struct ra *rap;
834 int wascompleted, found;
835 struct timespec tv;
836 char buf[INET6_ADDRSTRLEN];
837 const char *p;
838 int dadcounter;
839
840 ifp = ia->iface;
841 wascompleted = (ia->flags & IPV6_AF_DADCOMPLETED);
842 ia->flags |= IPV6_AF_DADCOMPLETED;
843 if (ia->flags & IPV6_AF_DUPLICATED) {
844 ia->dadcounter++;
845 logwarnx("%s: DAD detected %s", ifp->name, ia->saddr);
846
847 /* Try and make another stable private address.
848 * Because ap->dadcounter is always increamented,
849 * a different address is generated. */
850 /* XXX Cache DAD counter per prefix/id/ssid? */
851 if (ifp->options->options & DHCPCD_SLAACPRIVATE) {
852 if (ia->dadcounter >= IDGEN_RETRIES) {
853 logerrx("%s: unable to obtain a"
854 " stable private address",
855 ifp->name);
856 goto try_script;
857 }
858 loginfox("%s: deleting address %s",
859 ifp->name, ia->saddr);
860 if (if_address6(RTM_DELADDR, ia) == -1 &&
861 errno != EADDRNOTAVAIL && errno != ENXIO)
862 logerr(__func__);
863 dadcounter = ia->dadcounter;
864 if (ipv6_makestableprivate(&ia->addr,
865 &ia->prefix, ia->prefix_len,
866 ifp, &dadcounter) == -1)
867 {
868 logerr("ipv6_makestableprivate");
869 return;
870 }
871 ia->dadcounter = dadcounter;
872 ia->flags &= ~(IPV6_AF_ADDED | IPV6_AF_DADCOMPLETED);
873 ia->flags |= IPV6_AF_NEW;
874 p = inet_ntop(AF_INET6, &ia->addr, buf, sizeof(buf));
875 if (p)
876 snprintf(ia->saddr,
877 sizeof(ia->saddr),
878 "%s/%d",
879 p, ia->prefix_len);
880 else
881 ia->saddr[0] = '\0';
882 tv.tv_sec = 0;
883 tv.tv_nsec = (suseconds_t)
884 arc4random_uniform(IDGEN_DELAY * NSEC_PER_SEC);
885 timespecnorm(&tv);
886 eloop_timeout_add_tv(ifp->ctx->eloop, &tv,
887 ipv6nd_addaddr, ia);
888 return;
889 }
890 }
891
892try_script:
893 if (!wascompleted) {
894 TAILQ_FOREACH(rap, ifp->ctx->ra_routers, next) {
895 if (rap->iface != ifp)
896 continue;
897 wascompleted = 1;
898 found = 0;
899 TAILQ_FOREACH(rapap, &rap->addrs, next) {
900 if (rapap->flags & IPV6_AF_AUTOCONF &&
901 rapap->flags & IPV6_AF_ADDED &&
902 (rapap->flags & IPV6_AF_DADCOMPLETED) == 0)
903 {
904 wascompleted = 0;
905 break;
906 }
907 if (rapap == ia)
908 found = 1;
909 }
910
911 if (wascompleted && found) {
912 logdebugx("%s: Router Advertisement DAD "
913 "completed",
914 rap->iface->name);
915 if (ipv6nd_scriptrun(rap))
916 return;
917 }
918 }
919 ipv6nd_advertise(ia);
920 }
921}
922
923#ifndef DHCP6
924/* If DHCPv6 is compiled out, supply a shim to provide an error message
925 * if IPv6RA requests DHCPv6. */
926enum DH6S {
927 DH6S_REQUEST,
928 DH6S_INFORM,
929};
930static int
931dhcp6_start(__unused struct interface *ifp, __unused enum DH6S init_state)
932{
933
934 errno = ENOTSUP;
935 return -1;
936}
937#endif
938
939static void
940ipv6nd_handlera(struct dhcpcd_ctx *ctx,
941 const struct sockaddr_in6 *from, const char *sfrom,
942 struct interface *ifp, struct icmp6_hdr *icp, size_t len, int hoplimit)
943{
944 size_t i, olen;
945 struct nd_router_advert *nd_ra;
946 struct nd_opt_hdr ndo;
947 struct nd_opt_prefix_info pi;
948 struct nd_opt_mtu mtu;
949 struct nd_opt_rdnss rdnss;
950 uint8_t *p;
951 struct ra *rap;
952 struct in6_addr pi_prefix;
953 struct ipv6_addr *ap;
954 struct dhcp_opt *dho;
955 bool new_rap, new_data;
956 uint32_t old_lifetime;
957 __printflike(1, 2) void (*logfunc)(const char *, ...);
958#ifdef IPV6_MANAGETEMPADDR
959 uint8_t new_ap;
960#endif
961
962 if (ifp == NULL) {
963#ifdef DEBUG_RS
964 logdebugx("RA for unexpected interface from %s", sfrom);
965#endif
966 return;
967 }
968
969 if (len < sizeof(struct nd_router_advert)) {
970 logerrx("IPv6 RA packet too short from %s", sfrom);
971 return;
972 }
973
974 /* RFC 4861 7.1.2 */
975 if (hoplimit != 255) {
976 logerrx("invalid hoplimit(%d) in RA from %s", hoplimit, sfrom);
977 return;
978 }
979 if (!IN6_IS_ADDR_LINKLOCAL(&from->sin6_addr)) {
980 logerrx("RA from non local address %s", sfrom);
981 return;
982 }
983
984 if (!(ifp->options->options & DHCPCD_IPV6RS)) {
985#ifdef DEBUG_RS
986 logerrx("%s: unexpected RA from %s", ifp->name, sfrom);
987#endif
988 return;
989 }
990
991 /* We could receive a RA before we sent a RS*/
992 if (ipv6_linklocal(ifp) == NULL) {
993#ifdef DEBUG_RS
994 logdebugx("%s: received RA from %s (no link-local)",
995 ifp->name, sfrom);
996#endif
997 return;
998 }
999
1000 if (ipv6_iffindaddr(ifp, &from->sin6_addr, IN6_IFF_TENTATIVE)) {
1001 logdebugx("%s: ignoring RA from ourself %s",
1002 ifp->name, sfrom);
1003 return;
1004 }
1005
1006 TAILQ_FOREACH(rap, ctx->ra_routers, next) {
1007 if (ifp == rap->iface &&
1008 IN6_ARE_ADDR_EQUAL(&rap->from, &from->sin6_addr))
1009 break;
1010 }
1011
1012 nd_ra = (struct nd_router_advert *)icp;
1013
1014 /* We don't want to spam the log with the fact we got an RA every
1015 * 30 seconds or so, so only spam the log if it's different. */
1016 if (rap == NULL || (rap->data_len != len ||
1017 memcmp(rap->data, (unsigned char *)icp, rap->data_len) != 0))
1018 {
1019 if (rap) {
1020 free(rap->data);
1021 rap->data_len = 0;
1022 }
1023 new_data = true;
1024 } else
1025 new_data = false;
1026 if (rap == NULL) {
1027 rap = calloc(1, sizeof(*rap));
1028 if (rap == NULL) {
1029 logerr(__func__);
1030 return;
1031 }
1032 rap->iface = ifp;
1033 rap->from = from->sin6_addr;
1034 strlcpy(rap->sfrom, sfrom, sizeof(rap->sfrom));
1035 TAILQ_INIT(&rap->addrs);
1036 new_rap = true;
1037 } else
1038 new_rap = false;
1039 if (rap->data_len == 0) {
1040 rap->data = malloc(len);
1041 if (rap->data == NULL) {
1042 logerr(__func__);
1043 if (new_rap)
1044 free(rap);
1045 return;
1046 }
1047 memcpy(rap->data, icp, len);
1048 rap->data_len = len;
1049 }
1050
1051 /* We could change the debug level based on new_data, but some
1052 * routers like to decrease the advertised valid and preferred times
1053 * in accordance with the own prefix times which would result in too
1054 * much needless log spam. */
1055 logfunc = new_rap ? loginfox : logdebugx,
1056 logfunc("%s: Router Advertisement from %s", ifp->name, rap->sfrom);
1057
1058 clock_gettime(CLOCK_MONOTONIC, &rap->acquired);
1059 rap->flags = nd_ra->nd_ra_flags_reserved;
1060 old_lifetime = rap->lifetime;
1061 rap->lifetime = ntohs(nd_ra->nd_ra_router_lifetime);
1062 if (!new_rap && rap->lifetime == 0 && old_lifetime != 0)
1063 logwarnx("%s: %s: no longer a default router",
1064 ifp->name, rap->sfrom);
1065 if (nd_ra->nd_ra_reachable) {
1066 rap->reachable = ntohl(nd_ra->nd_ra_reachable);
1067 if (rap->reachable > MAX_REACHABLE_TIME)
1068 rap->reachable = 0;
1069 }
1070 if (nd_ra->nd_ra_retransmit) {
1071 struct rs_state *state = RS_STATE(ifp);
1072
1073 state->retrans = rap->retrans = ntohl(nd_ra->nd_ra_retransmit);
1074 }
1075 if (rap->lifetime)
1076 rap->expired = 0;
1077 rap->hasdns = 0;
1078
1079#ifdef IPV6_AF_TEMPORARY
1080 ipv6_markaddrsstale(ifp, IPV6_AF_TEMPORARY);
1081#endif
1082 TAILQ_FOREACH(ap, &rap->addrs, next) {
1083 ap->flags |= IPV6_AF_STALE;
1084 }
1085
1086 len -= sizeof(struct nd_router_advert);
1087 p = ((uint8_t *)icp) + sizeof(struct nd_router_advert);
1088 for (; len > 0; p += olen, len -= olen) {
1089 if (len < sizeof(ndo)) {
1090 logerrx("%s: short option", ifp->name);
1091 break;
1092 }
1093 memcpy(&ndo, p, sizeof(ndo));
1094 olen = (size_t)ndo.nd_opt_len * 8;
1095 if (olen == 0) {
1096 logerrx("%s: zero length option", ifp->name);
1097 break;
1098 }
1099 if (olen > len) {
1100 logerrx("%s: option length exceeds message",
1101 ifp->name);
1102 break;
1103 }
1104
1105 if (has_option_mask(ifp->options->rejectmasknd,
1106 ndo.nd_opt_type))
1107 {
1108 for (i = 0, dho = ctx->nd_opts;
1109 i < ctx->nd_opts_len;
1110 i++, dho++)
1111 {
1112 if (dho->option == ndo.nd_opt_type)
1113 break;
1114 }
1115 if (dho != NULL)
1116 logwarnx("%s: reject RA (option %s) from %s",
1117 ifp->name, dho->var, rap->sfrom);
1118 else
1119 logwarnx("%s: reject RA (option %d) from %s",
1120 ifp->name, ndo.nd_opt_type, rap->sfrom);
1121 if (new_rap)
1122 ipv6nd_removefreedrop_ra(rap, 0, 0);
1123 else
1124 ipv6nd_free_ra(rap);
1125 return;
1126 }
1127
1128 if (has_option_mask(ifp->options->nomasknd, ndo.nd_opt_type))
1129 continue;
1130
1131 switch (ndo.nd_opt_type) {
1132 case ND_OPT_PREFIX_INFORMATION:
1133 logfunc = new_data ? logerrx : logdebugx;
1134 if (ndo.nd_opt_len != 4) {
1135 logfunc("%s: invalid option len for prefix",
1136 ifp->name);
1137 continue;
1138 }
1139 memcpy(&pi, p, sizeof(pi));
1140 if (pi.nd_opt_pi_prefix_len > 128) {
1141 logfunc("%s: invalid prefix len", ifp->name);
1142 continue;
1143 }
1144 /* nd_opt_pi_prefix is not aligned. */
1145 memcpy(&pi_prefix, &pi.nd_opt_pi_prefix,
1146 sizeof(pi_prefix));
1147 if (IN6_IS_ADDR_MULTICAST(&pi_prefix) ||
1148 IN6_IS_ADDR_LINKLOCAL(&pi_prefix))
1149 {
1150 logfunc("%s: invalid prefix in RA", ifp->name);
1151 continue;
1152 }
1153 if (ntohl(pi.nd_opt_pi_preferred_time) >
1154 ntohl(pi.nd_opt_pi_valid_time))
1155 {
1156 logfunc("%s: pltime > vltime", ifp->name);
1157 continue;
1158 }
1159 TAILQ_FOREACH(ap, &rap->addrs, next)
1160 if (ap->prefix_len ==pi.nd_opt_pi_prefix_len &&
1161 IN6_ARE_ADDR_EQUAL(&ap->prefix, &pi_prefix))
1162 break;
1163 if (ap == NULL) {
1164 unsigned int flags;
1165
1166 flags = IPV6_AF_RAPFX;
1167 if (pi.nd_opt_pi_flags_reserved &
1168 ND_OPT_PI_FLAG_AUTO &&
1169 rap->iface->options->options &
1170 DHCPCD_IPV6RA_AUTOCONF)
1171 flags |= IPV6_AF_AUTOCONF;
1172
1173 ap = ipv6_newaddr(rap->iface,
1174 &pi_prefix, pi.nd_opt_pi_prefix_len, flags);
1175 if (ap == NULL)
1176 break;
1177 ap->prefix = pi_prefix;
1178 if (flags & IPV6_AF_AUTOCONF)
1179 ap->dadcallback = ipv6nd_dadcallback;
1180 ap->created = ap->acquired = rap->acquired;
1181 TAILQ_INSERT_TAIL(&rap->addrs, ap, next);
1182
1183#ifdef IPV6_MANAGETEMPADDR
1184 /* New address to dhcpcd RA handling.
1185 * If the address already exists and a valid
1186 * temporary address also exists then
1187 * extend the existing one rather than
1188 * create a new one */
1189 if (flags & IPV6_AF_AUTOCONF &&
1190 ipv6_iffindaddr(ifp, &ap->addr,
1191 IN6_IFF_NOTUSEABLE) &&
1192 ipv6_settemptime(ap, 0))
1193 new_ap = 0;
1194 else
1195 new_ap = 1;
1196#endif
1197 } else {
1198#ifdef IPV6_MANAGETEMPADDR
1199 new_ap = 0;
1200#endif
1201 ap->flags &= ~IPV6_AF_STALE;
1202 ap->acquired = rap->acquired;
1203 }
1204 if (pi.nd_opt_pi_flags_reserved &
1205 ND_OPT_PI_FLAG_ONLINK)
1206 ap->flags |= IPV6_AF_ONLINK;
1207 ap->prefix_vltime =
1208 ntohl(pi.nd_opt_pi_valid_time);
1209 ap->prefix_pltime =
1210 ntohl(pi.nd_opt_pi_preferred_time);
1211
1212#ifdef IPV6_MANAGETEMPADDR
1213 /* RFC4941 Section 3.3.3 */
1214 if (ap->flags & IPV6_AF_AUTOCONF &&
1215 ip6_use_tempaddr(ap->iface->name))
1216 {
1217 if (!new_ap) {
1218 if (ipv6_settemptime(ap, 1) == NULL)
1219 new_ap = 1;
1220 }
1221 if (new_ap && ap->prefix_pltime) {
1222 if (ipv6_createtempaddr(ap,
1223 &ap->acquired) == NULL)
1224 logerr("ipv6_createtempaddr");
1225 }
1226 }
1227#endif
1228 break;
1229
1230 case ND_OPT_MTU:
1231 memcpy(&mtu, p, sizeof(mtu));
1232 mtu.nd_opt_mtu_mtu = ntohl(mtu.nd_opt_mtu_mtu);
1233 if (mtu.nd_opt_mtu_mtu < IPV6_MMTU) {
1234 logerrx("%s: invalid MTU %d",
1235 ifp->name, mtu.nd_opt_mtu_mtu);
1236 break;
1237 }
1238 rap->mtu = mtu.nd_opt_mtu_mtu;
1239 break;
1240
1241 case ND_OPT_RDNSS:
1242 memcpy(&rdnss, p, sizeof(rdnss));
1243 if (rdnss.nd_opt_rdnss_lifetime &&
1244 rdnss.nd_opt_rdnss_len > 1)
1245 rap->hasdns = 1;
1246 break;
1247 default:
1248 continue;
1249 }
1250 }
1251
1252 for (i = 0, dho = ctx->nd_opts;
1253 i < ctx->nd_opts_len;
1254 i++, dho++)
1255 {
1256 if (has_option_mask(ifp->options->requiremasknd,
1257 dho->option))
1258 {
1259 logwarnx("%s: reject RA (no option %s) from %s",
1260 ifp->name, dho->var, rap->sfrom);
1261 if (new_rap)
1262 ipv6nd_removefreedrop_ra(rap, 0, 0);
1263 else
1264 ipv6nd_free_ra(rap);
1265 return;
1266 }
1267 }
1268
1269 if (new_rap)
1270 add_router(ifp->ctx, rap);
1271
1272 if (ifp->ctx->options & DHCPCD_TEST) {
1273 script_runreason(ifp, "TEST");
1274 goto handle_flag;
1275 }
1276 ipv6_addaddrs(&rap->addrs);
1277#ifdef IPV6_MANAGETEMPADDR
1278 ipv6_addtempaddrs(ifp, &rap->acquired);
1279#endif
1280
1281 /* Find any freshly added routes, such as the subnet route.
1282 * We do this because we cannot rely on recieving the kernel
1283 * notification right now via our link socket. */
1284 if_initrt(ifp->ctx, AF_INET6);
1285
1286 rt_build(ifp->ctx, AF_INET6);
1287 if (ipv6nd_scriptrun(rap))
1288 return;
1289
1290 eloop_timeout_delete(ifp->ctx->eloop, NULL, ifp);
1291 eloop_timeout_delete(ifp->ctx->eloop, NULL, rap); /* reachable timer */
1292
1293handle_flag:
1294 if (!(ifp->options->options & DHCPCD_DHCP6))
1295 goto nodhcp6;
1296/* Only log a DHCPv6 start error if compiled in or debugging is enabled. */
1297#ifdef DHCP6
1298#define LOG_DHCP6 logerr
1299#else
1300#define LOG_DHCP6 logdebug
1301#endif
1302 if (rap->flags & ND_RA_FLAG_MANAGED) {
1303 if (new_data && dhcp6_start(ifp, DH6S_REQUEST) == -1)
1304 LOG_DHCP6("dhcp6_start: %s", ifp->name);
1305 } else if (rap->flags & ND_RA_FLAG_OTHER) {
1306 if (new_data && dhcp6_start(ifp, DH6S_INFORM) == -1)
1307 LOG_DHCP6("dhcp6_start: %s", ifp->name);
1308 } else {
1309#ifdef DHCP6
1310 if (new_data)
1311 logdebugx("%s: No DHCPv6 instruction in RA", ifp->name);
1312#endif
1313nodhcp6:
1314 if (ifp->ctx->options & DHCPCD_TEST) {
1315 eloop_exit(ifp->ctx->eloop, EXIT_SUCCESS);
1316 return;
1317 }
1318 }
1319
1320 /* Expire should be called last as the rap object could be destroyed */
1321 ipv6nd_expirera(ifp);
1322}
1323
1324int
1325ipv6nd_hasra(const struct interface *ifp)
1326{
1327 const struct ra *rap;
1328
1329 if (ifp->ctx->ra_routers) {
1330 TAILQ_FOREACH(rap, ifp->ctx->ra_routers, next)
1331 if (rap->iface == ifp && !rap->expired)
1332 return 1;
1333 }
1334 return 0;
1335}
1336
1337int
1338ipv6nd_hasradhcp(const struct interface *ifp)
1339{
1340 const struct ra *rap;
1341
1342 if (ifp->ctx->ra_routers) {
1343 TAILQ_FOREACH(rap, ifp->ctx->ra_routers, next) {
1344 if (rap->iface == ifp &&
1345 !rap->expired &&
1346 (rap->flags & (ND_RA_FLAG_MANAGED | ND_RA_FLAG_OTHER)))
1347 return 1;
1348 }
1349 }
1350 return 0;
1351}
1352
1353static const uint8_t *
1354ipv6nd_getoption(struct dhcpcd_ctx *ctx,
1355 size_t *os, unsigned int *code, size_t *len,
1356 const uint8_t *od, size_t ol, struct dhcp_opt **oopt)
1357{
1358 struct nd_opt_hdr ndo;
1359 size_t i;
1360 struct dhcp_opt *opt;
1361
1362 if (od) {
1363 *os = sizeof(ndo);
1364 if (ol < *os) {
1365 errno = EINVAL;
1366 return NULL;
1367 }
1368 memcpy(&ndo, od, sizeof(ndo));
1369 i = (size_t)(ndo.nd_opt_len * 8);
1370 if (i > ol) {
1371 errno = EINVAL;
1372 return NULL;
1373 }
1374 *len = i;
1375 *code = ndo.nd_opt_type;
1376 }
1377
1378 for (i = 0, opt = ctx->nd_opts;
1379 i < ctx->nd_opts_len; i++, opt++)
1380 {
1381 if (opt->option == *code) {
1382 *oopt = opt;
1383 break;
1384 }
1385 }
1386
1387 if (od)
1388 return od + sizeof(ndo);
1389 return NULL;
1390}
1391
1392ssize_t
1393ipv6nd_env(char **env, const char *prefix, const struct interface *ifp)
1394{
1395 size_t i, j, n, len, olen;
1396 struct ra *rap;
1397 char ndprefix[32], abuf[24];
1398 struct dhcp_opt *opt;
1399 uint8_t *p;
1400 struct nd_opt_hdr ndo;
1401 struct ipv6_addr *ia;
1402 struct timespec now;
1403
1404 clock_gettime(CLOCK_MONOTONIC, &now);
1405 i = n = 0;
1406 TAILQ_FOREACH(rap, ifp->ctx->ra_routers, next) {
1407 if (rap->iface != ifp)
1408 continue;
1409 i++;
1410 if (prefix != NULL)
1411 snprintf(ndprefix, sizeof(ndprefix),
1412 "%s_nd%zu", prefix, i);
1413 else
1414 snprintf(ndprefix, sizeof(ndprefix),
1415 "nd%zu", i);
1416 if (env)
1417 setvar(&env[n], ndprefix, "from", rap->sfrom);
1418 n++;
1419 if (env)
1420 setvard(&env[n], ndprefix, "acquired",
1421 (size_t)rap->acquired.tv_sec);
1422 n++;
1423 if (env)
1424 setvard(&env[n], ndprefix, "now", (size_t)now.tv_sec);
1425 n++;
1426
1427 /* Zero our indexes */
1428 if (env) {
1429 for (j = 0, opt = rap->iface->ctx->nd_opts;
1430 j < rap->iface->ctx->nd_opts_len;
1431 j++, opt++)
1432 dhcp_zero_index(opt);
1433 for (j = 0, opt = rap->iface->options->nd_override;
1434 j < rap->iface->options->nd_override_len;
1435 j++, opt++)
1436 dhcp_zero_index(opt);
1437 }
1438
1439 /* Unlike DHCP, ND6 options *may* occur more than once.
1440 * There is also no provision for option concatenation
1441 * unlike DHCP. */
1442 len = rap->data_len - sizeof(struct nd_router_advert);
1443 for (p = rap->data + sizeof(struct nd_router_advert);
1444 len >= sizeof(ndo);
1445 p += olen, len -= olen)
1446 {
1447 memcpy(&ndo, p, sizeof(ndo));
1448 olen = (size_t)(ndo.nd_opt_len * 8);
1449 if (olen > len) {
1450 errno = EINVAL;
1451 break;
1452 }
1453 if (has_option_mask(rap->iface->options->nomasknd,
1454 ndo.nd_opt_type))
1455 continue;
1456 for (j = 0, opt = rap->iface->options->nd_override;
1457 j < rap->iface->options->nd_override_len;
1458 j++, opt++)
1459 if (opt->option == ndo.nd_opt_type)
1460 break;
1461 if (j == rap->iface->options->nd_override_len) {
1462 for (j = 0, opt = rap->iface->ctx->nd_opts;
1463 j < rap->iface->ctx->nd_opts_len;
1464 j++, opt++)
1465 if (opt->option == ndo.nd_opt_type)
1466 break;
1467 if (j == rap->iface->ctx->nd_opts_len)
1468 opt = NULL;
1469 }
1470 if (opt) {
1471 n += dhcp_envoption(rap->iface->ctx,
1472 env == NULL ? NULL : &env[n],
1473 ndprefix, rap->iface->name,
1474 opt, ipv6nd_getoption,
1475 p + sizeof(ndo), olen - sizeof(ndo));
1476 }
1477 }
1478
1479 /* We need to output the addresses we actually made
1480 * from the prefix information options as well. */
1481 j = 0;
1482 TAILQ_FOREACH(ia, &rap->addrs, next) {
1483 if (!(ia->flags & IPV6_AF_AUTOCONF)
1484#ifdef IPV6_AF_TEMPORARY
1485 || ia->flags & IPV6_AF_TEMPORARY
1486#endif
1487 )
1488 continue;
1489 j++;
1490 if (env) {
1491 snprintf(abuf, sizeof(abuf), "addr%zu", j);
1492 setvar(&env[n], ndprefix, abuf, ia->saddr);
1493 }
1494 n++;
1495 }
1496 }
1497 return (ssize_t)n;
1498}
1499
1500void
1501ipv6nd_handleifa(int cmd, struct ipv6_addr *addr, pid_t pid)
1502{
1503 struct ra *rap;
1504
1505 /* IPv6 init may not have happened yet if we are learning
1506 * existing addresses when dhcpcd starts. */
1507 if (addr->iface->ctx->ra_routers == NULL)
1508 return;
1509
1510 TAILQ_FOREACH(rap, addr->iface->ctx->ra_routers, next) {
1511 if (rap->iface != addr->iface)
1512 continue;
1513 ipv6_handleifa_addrs(cmd, &rap->addrs, addr, pid);
1514 }
1515}
1516
1517void
1518ipv6nd_expirera(void *arg)
1519{
1520 struct interface *ifp;
1521 struct ra *rap, *ran;
1522 struct timespec now, lt, expire, next;
1523 bool expired, valid, validone;
1524 struct ipv6_addr *ia;
1525
1526 ifp = arg;
1527 clock_gettime(CLOCK_MONOTONIC, &now);
1528 expired = false;
1529 timespecclear(&next);
1530
1531 TAILQ_FOREACH_SAFE(rap, ifp->ctx->ra_routers, next, ran) {
1532 if (rap->iface != ifp)
1533 continue;
1534 valid = validone = false;
1535 if (rap->lifetime) {
1536 lt.tv_sec = (time_t)rap->lifetime;
1537 lt.tv_nsec = 0;
1538 timespecadd(&rap->acquired, &lt, &expire);
1539 if (rap->lifetime == 0 || timespeccmp(&now, &expire, >))
1540 {
1541 if (!rap->expired) {
1542 logwarnx("%s: %s: router expired",
1543 ifp->name, rap->sfrom);
1544 rap->expired = expired = 1;
1545 rap->lifetime = 0;
1546 }
1547 } else {
1548 valid = true;
1549 timespecsub(&expire, &now, &lt);
1550 if (!timespecisset(&next) ||
1551 timespeccmp(&next, &lt, >))
1552 next = lt;
1553 }
1554 }
1555
1556 /* Not every prefix is tied to an address which
1557 * the kernel can expire, so we need to handle it ourself.
1558 * Also, some OS don't support address lifetimes (Solaris). */
1559 TAILQ_FOREACH(ia, &rap->addrs, next) {
1560 if (ia->prefix_vltime == 0)
1561 continue;
1562 if (ia->prefix_vltime == ND6_INFINITE_LIFETIME) {
1563 validone = true;
1564 continue;
1565 }
1566 lt.tv_sec = (time_t)ia->prefix_vltime;
1567 lt.tv_nsec = 0;
1568 timespecadd(&ia->acquired, &lt, &expire);
1569 if (timespeccmp(&now, &expire, >)) {
1570 if (ia->flags & IPV6_AF_ADDED) {
1571 logwarnx("%s: expired address %s",
1572 ia->iface->name, ia->saddr);
1573 if (if_address6(RTM_DELADDR, ia)== -1 &&
1574 errno != EADDRNOTAVAIL &&
1575 errno != ENXIO)
1576 logerr(__func__);
1577 }
1578 ia->prefix_vltime = ia->prefix_pltime = 0;
1579 ia->flags &=
1580 ~(IPV6_AF_ADDED | IPV6_AF_DADCOMPLETED);
1581 expired = true;
1582 } else {
1583 timespecsub(&expire, &now, &lt);
1584 if (!timespecisset(&next) ||
1585 timespeccmp(&next, &lt, >))
1586 next = lt;
1587 validone = true;
1588 }
1589 }
1590
1591 /* XXX FixMe!
1592 * We need to extract the lifetime from each option and check
1593 * if that has expired or not.
1594 * If it has, zero the option out in the returned data. */
1595
1596 /* No valid lifetimes are left on the RA, so we might
1597 * as well punt it. */
1598 if (!valid && !validone)
1599 ipv6nd_free_ra(rap);
1600 }
1601
1602 if (timespecisset(&next))
1603 eloop_timeout_add_tv(ifp->ctx->eloop,
1604 &next, ipv6nd_expirera, ifp);
1605 if (expired) {
1606 rt_build(ifp->ctx, AF_INET6);
1607 script_runreason(ifp, "ROUTERADVERT");
1608 }
1609}
1610
1611void
1612ipv6nd_drop(struct interface *ifp)
1613{
1614 struct ra *rap, *ran;
1615 uint8_t expired = 0;
1616
1617 if (ifp->ctx->ra_routers == NULL)
1618 return;
1619
1620 eloop_timeout_delete(ifp->ctx->eloop, NULL, ifp);
1621 TAILQ_FOREACH_SAFE(rap, ifp->ctx->ra_routers, next, ran) {
1622 if (rap->iface == ifp) {
1623 rap->expired = expired = 1;
1624 ipv6nd_drop_ra(rap);
1625 }
1626 }
1627 if (expired) {
1628 rt_build(ifp->ctx, AF_INET6);
1629 if ((ifp->options->options & DHCPCD_NODROP) != DHCPCD_NODROP)
1630 script_runreason(ifp, "ROUTERADVERT");
1631 }
1632}
1633
1634static void
1635ipv6nd_handlena(struct dhcpcd_ctx *ctx, const char *sfrom,
1636 struct interface *ifp, struct icmp6_hdr *icp, size_t len, int hoplimit)
1637{
1638 struct nd_neighbor_advert *nd_na;
1639 struct in6_addr nd_na_target;
1640 struct ra *rap;
1641 uint32_t is_router, is_solicited;
1642 char buf[INET6_ADDRSTRLEN];
1643 const char *taddr;
1644
1645 if (ifp == NULL) {
1646#ifdef DEBUG_NS
1647 logdebugx("NA for unexpected interface from %s", sfrom);
1648#endif
1649 return;
1650 }
1651
1652 if ((size_t)len < sizeof(struct nd_neighbor_advert)) {
1653 logerrx("%s: IPv6 NA too short from %s", ifp->name, sfrom);
1654 return;
1655 }
1656
1657 /* RFC 4861 7.1.2 */
1658 if (hoplimit != 255) {
1659 logerrx("invalid hoplimit(%d) in NA from %s",
1660 hoplimit, sfrom);
1661 return;
1662 }
1663
1664 nd_na = (struct nd_neighbor_advert *)icp;
1665 is_router = nd_na->nd_na_flags_reserved & ND_NA_FLAG_ROUTER;
1666 is_solicited = nd_na->nd_na_flags_reserved & ND_NA_FLAG_SOLICITED;
1667 taddr = inet_ntop(AF_INET6, &nd_na->nd_na_target,
1668 buf, INET6_ADDRSTRLEN);
1669
1670 /* nd_na->nd_na_target is not aligned. */
1671 memcpy(&nd_na_target, &nd_na->nd_na_target, sizeof(nd_na_target));
1672 if (IN6_IS_ADDR_MULTICAST(&nd_na_target)) {
1673 logerrx("%s: NA multicast address %s (%s)",
1674 ifp->name, taddr, sfrom);
1675 return;
1676 }
1677
1678 TAILQ_FOREACH(rap, ctx->ra_routers, next) {
1679 if (rap->iface == ifp &&
1680 IN6_ARE_ADDR_EQUAL(&rap->from, &nd_na_target))
1681 break;
1682 }
1683 if (rap == NULL) {
1684#ifdef DEBUG_NS
1685 logdebugx("%s: unexpected NA from %s for %s",
1686 ifp->name, sfrom, taddr);
1687#endif
1688 return;
1689 }
1690
1691#ifdef DEBUG_NS
1692 logdebugx("%s: %sNA for %s from %s",
1693 ifp->name, is_solicited ? "solicited " : "", taddr, sfrom);
1694#endif
1695
1696 /* Node is no longer a router, so remove it from consideration */
1697 if (!is_router && !rap->expired) {
1698 loginfox("%s: %s not a router (%s)",
1699 ifp->name, taddr, sfrom);
1700 rap->expired = 1;
1701 rt_build(ifp->ctx, AF_INET6);
1702 script_runreason(ifp, "ROUTERADVERT");
1703 return;
1704 }
1705
1706 if (is_solicited && is_router && rap->lifetime)
1707 ipv6nd_reachable(rap, IPV6ND_REACHABLE);
1708}
1709
1710static void
1711ipv6nd_handledata(void *arg)
1712{
1713 struct dhcpcd_ctx *ctx;
1714 int s;
1715 struct sockaddr_in6 from;
1716 unsigned char buf[64 * 1024]; /* Maximum ICMPv6 size */
1717 struct iovec iov = {
1718 .iov_base = buf,
1719 .iov_len = sizeof(buf),
1720 };
1721 unsigned char ctl[CMSG_SPACE(sizeof(struct in6_pktinfo)) + CMSG_SPACE(sizeof(int))] = { 0 };
1722 struct msghdr msg = {
1723 .msg_name = &from, .msg_namelen = sizeof(from),
1724 .msg_iov = &iov, .msg_iovlen = 1,
1725 .msg_control = ctl, .msg_controllen = sizeof(ctl),
1726 };
1727 ssize_t len;
1728 char sfrom[INET6_ADDRSTRLEN];
1729 int hoplimit = 0;
1730 struct icmp6_hdr *icp;
1731 struct interface *ifp;
1732
1733#ifdef __sun
1734 struct rs_state *state;
1735
1736 ifp = arg;
1737 state = RS_STATE(ifp);
1738 ctx = ifp->ctx;
1739 s = state->nd_fd;
1740#else
1741 ctx = arg;
1742 s = ctx->nd_fd;
1743#endif
1744 len = recvmsg(s, &msg, 0);
1745 if (len == -1) {
1746 logerr(__func__);
1747 return;
1748 }
1749 inet_ntop(AF_INET6, &from.sin6_addr, sfrom, sizeof(sfrom));
1750 if ((size_t)len < sizeof(struct icmp6_hdr)) {
1751 logerrx("IPv6 ICMP packet too short from %s", sfrom);
1752 return;
1753 }
1754
1755#ifdef __sun
1756 if_findifpfromcmsg(ctx, &msg, &hoplimit);
1757#else
1758 ifp = if_findifpfromcmsg(ctx, &msg, &hoplimit);
1759 if (ifp == NULL) {
1760 logerr(__func__);
1761 return;
1762 }
1763#endif
1764
1765 /* Don't do anything if the user hasn't configured it. */
1766 if (ifp->active != IF_ACTIVE_USER ||
1767 !(ifp->options->options & DHCPCD_IPV6))
1768 return;
1769
1770 icp = (struct icmp6_hdr *)buf;
1771 if (icp->icmp6_code == 0) {
1772 switch(icp->icmp6_type) {
1773 case ND_NEIGHBOR_ADVERT:
1774 ipv6nd_handlena(ctx, sfrom,
1775 ifp, icp, (size_t)len, hoplimit);
1776 return;
1777 case ND_ROUTER_ADVERT:
1778 ipv6nd_handlera(ctx, &from, sfrom,
1779 ifp, icp, (size_t)len, hoplimit);
1780 return;
1781 }
1782 }
1783
1784 logerrx("invalid IPv6 type %d or code %d from %s",
1785 icp->icmp6_type, icp->icmp6_code, sfrom);
1786}
1787
1788static void
1789ipv6nd_startrs1(void *arg)
1790{
1791 struct interface *ifp = arg;
1792 struct rs_state *state;
1793
1794 loginfox("%s: soliciting an IPv6 router", ifp->name);
1795 state = RS_STATE(ifp);
1796 if (state == NULL) {
1797 ifp->if_data[IF_DATA_IPV6ND] = calloc(1, sizeof(*state));
1798 state = RS_STATE(ifp);
1799 if (state == NULL) {
1800 logerr(__func__);
1801 return;
1802 }
1803#ifdef __sun
1804 state->nd_fd = -1;
1805#endif
1806 }
1807
1808#ifdef __sun
1809 if (ipv6nd_open(ifp) == -1) {
1810 logerr(__func__);
1811 return;
1812 }
1813#else
1814 if (ipv6nd_open(ifp->ctx) == -1) {
1815 logerr(__func__);
1816 return;
1817 }
1818#endif
1819
1820 /* Always make a new probe as the underlying hardware
1821 * address could have changed. */
1822 ipv6nd_makersprobe(ifp);
1823 if (state->rs == NULL) {
1824 logerr(__func__);
1825 return;
1826 }
1827
1828 state->retrans = RETRANS_TIMER;
1829 state->rsprobes = 0;
1830 ipv6nd_sendrsprobe(ifp);
1831}
1832
1833void
1834ipv6nd_startrs(struct interface *ifp)
1835{
1836 struct timespec tv;
1837
1838 eloop_timeout_delete(ifp->ctx->eloop, NULL, ifp);
1839 if (!(ifp->options->options & DHCPCD_INITIAL_DELAY)) {
1840 ipv6nd_startrs1(ifp);
1841 return;
1842 }
1843
1844 tv.tv_sec = 0;
1845 tv.tv_nsec = (suseconds_t)arc4random_uniform(
1846 MAX_RTR_SOLICITATION_DELAY * NSEC_PER_SEC);
1847 timespecnorm(&tv);
1848 logdebugx("%s: delaying IPv6 router solicitation for %0.1f seconds",
1849 ifp->name, timespec_to_double(&tv));
1850 eloop_timeout_add_tv(ifp->ctx->eloop, &tv, ipv6nd_startrs1, ifp);
1851 return;
1852}
1853