blob: 89f6782f73a1570b248a7473945e6d97bf099f87 [file] [log] [blame]
Samuel Tand7ed8512015-08-13 16:11:35 -07001/*
2 * dhcpcd - DHCP client daemon
3 * Copyright (c) 2006-2015 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 <errno.h>
38#include <fcntl.h>
39#include <stddef.h>
40#include <stdlib.h>
41#include <string.h>
42#include <unistd.h>
43
44#define ELOOP_QUEUE 3
45#include "common.h"
46#include "dhcpcd.h"
47#include "dhcp6.h"
48#include "eloop.h"
49#include "if.h"
50#include "ipv6.h"
51#include "ipv6nd.h"
52#include "script.h"
53
54/* Debugging Router Solicitations is a lot of spam, so disable it */
55//#define DEBUG_RS
56
57#ifndef ND_OPT_RDNSS
58#define ND_OPT_RDNSS 25
59struct nd_opt_rdnss { /* RDNSS option RFC 6106 */
60 uint8_t nd_opt_rdnss_type;
61 uint8_t nd_opt_rdnss_len;
62 uint16_t nd_opt_rdnss_reserved;
63 uint32_t nd_opt_rdnss_lifetime;
64 /* followed by list of IP prefixes */
65} __packed;
66#endif
67
68#ifndef ND_OPT_DNSSL
69#define ND_OPT_DNSSL 31
70struct nd_opt_dnssl { /* DNSSL option RFC 6106 */
71 uint8_t nd_opt_dnssl_type;
72 uint8_t nd_opt_dnssl_len;
73 uint16_t nd_opt_dnssl_reserved;
74 uint32_t nd_opt_dnssl_lifetime;
75 /* followed by list of DNS servers */
76} __packed;
77#endif
78
79/* Impossible options, so we can easily add extras */
80#define _ND_OPT_PREFIX_ADDR 255 + 1
81
82/* Minimal IPv6 MTU */
83#ifndef IPV6_MMTU
84#define IPV6_MMTU 1280
85#endif
86
87#ifndef ND_RA_FLAG_RTPREF_HIGH
88#define ND_RA_FLAG_RTPREF_MASK 0x18
89#define ND_RA_FLAG_RTPREF_HIGH 0x08
90#define ND_RA_FLAG_RTPREF_MEDIUM 0x00
91#define ND_RA_FLAG_RTPREF_LOW 0x18
92#define ND_RA_FLAG_RTPREF_RSV 0x10
93#endif
94
95/* RTPREF_MEDIUM has to be 0! */
96#define RTPREF_HIGH 1
97#define RTPREF_MEDIUM 0
98#define RTPREF_LOW (-1)
99#define RTPREF_RESERVED (-2)
100#define RTPREF_INVALID (-3) /* internal */
101
102#define MIN_RANDOM_FACTOR 500 /* millisecs */
103#define MAX_RANDOM_FACTOR 1500 /* millisecs */
104#define MIN_RANDOM_FACTOR_U MIN_RANDOM_FACTOR * 1000 /* usecs */
105#define MAX_RANDOM_FACTOR_U MAX_RANDOM_FACTOR * 1000 /* usecs */
106
107#if BYTE_ORDER == BIG_ENDIAN
108#define IPV6_ADDR_INT32_ONE 1
109#define IPV6_ADDR_INT16_MLL 0xff02
110#elif BYTE_ORDER == LITTLE_ENDIAN
111#define IPV6_ADDR_INT32_ONE 0x01000000
112#define IPV6_ADDR_INT16_MLL 0x02ff
113#endif
114
115/* Debugging Neighbor Solicitations is a lot of spam, so disable it */
116//#define DEBUG_NS
117//
118
119static void ipv6nd_handledata(void *);
120
121/*
122 * Android ships buggy ICMP6 filter headers.
123 * Supply our own until they fix their shit.
124 * References:
125 * https://android-review.googlesource.com/#/c/58438/
126 * http://code.google.com/p/android/issues/original?id=32621&seq=24
127 */
128#ifdef __ANDROID__
129#undef ICMP6_FILTER_WILLPASS
130#undef ICMP6_FILTER_WILLBLOCK
131#undef ICMP6_FILTER_SETPASS
132#undef ICMP6_FILTER_SETBLOCK
133#undef ICMP6_FILTER_SETPASSALL
134#undef ICMP6_FILTER_SETBLOCKALL
135#define ICMP6_FILTER_WILLPASS(type, filterp) \
136 ((((filterp)->icmp6_filt[(type) >> 5]) & (1 << ((type) & 31))) == 0)
137#define ICMP6_FILTER_WILLBLOCK(type, filterp) \
138 ((((filterp)->icmp6_filt[(type) >> 5]) & (1 << ((type) & 31))) != 0)
139#define ICMP6_FILTER_SETPASS(type, filterp) \
140 ((((filterp)->icmp6_filt[(type) >> 5]) &= ~(1 << ((type) & 31))))
141#define ICMP6_FILTER_SETBLOCK(type, filterp) \
142 ((((filterp)->icmp6_filt[(type) >> 5]) |= (1 << ((type) & 31))))
143#define ICMP6_FILTER_SETPASSALL(filterp) \
144 memset(filterp, 0, sizeof(struct icmp6_filter));
145#define ICMP6_FILTER_SETBLOCKALL(filterp) \
146 memset(filterp, 0xff, sizeof(struct icmp6_filter));
147#endif
148
149/* Support older systems with different defines */
150#if !defined(IPV6_RECVHOPLIMIT) && defined(IPV6_HOPLIMIT)
151#define IPV6_RECVHOPLIMIT IPV6_HOPLIMIT
152#endif
153#if !defined(IPV6_RECVPKTINFO) && defined(IPV6_PKTINFO)
154#define IPV6_RECVPKTINFO IPV6_PKTINFO
155#endif
156
157static int
158ipv6nd_open(struct dhcpcd_ctx *dctx)
159{
160 struct ipv6_ctx *ctx;
161 int on;
162 struct icmp6_filter filt;
163
164 ctx = dctx->ipv6;
165 if (ctx->nd_fd != -1)
166 return ctx->nd_fd;
167#ifdef SOCK_CLOEXEC
168 ctx->nd_fd = socket(PF_INET6, SOCK_RAW | SOCK_CLOEXEC | SOCK_NONBLOCK,
169 IPPROTO_ICMPV6);
170 if (ctx->nd_fd == -1)
171 return -1;
172#else
173 if ((ctx->nd_fd = socket(PF_INET6, SOCK_RAW, IPPROTO_ICMPV6)) == -1)
174 return -1;
175 if ((on = fcntl(ctx->nd_fd, F_GETFD, 0)) == -1 ||
176 fcntl(ctx->nd_fd, F_SETFD, on | FD_CLOEXEC) == -1)
177 {
178 close(ctx->nd_fd);
179 ctx->nd_fd = -1;
180 return -1;
181 }
182 if ((on = fcntl(ctx->nd_fd, F_GETFL, 0)) == -1 ||
183 fcntl(ctx->nd_fd, F_SETFL, on | O_NONBLOCK) == -1)
184 {
185 close(ctx->nd_fd);
186 ctx->nd_fd = -1;
187 return -1;
188 }
189#endif
190
191 /* RFC4861 4.1 */
192 on = 255;
193 if (setsockopt(ctx->nd_fd, IPPROTO_IPV6, IPV6_MULTICAST_HOPS,
194 &on, sizeof(on)) == -1)
195 goto eexit;
196
197 on = 1;
198 if (setsockopt(ctx->nd_fd, IPPROTO_IPV6, IPV6_RECVPKTINFO,
199 &on, sizeof(on)) == -1)
200 goto eexit;
201
202 on = 1;
203 if (setsockopt(ctx->nd_fd, IPPROTO_IPV6, IPV6_RECVHOPLIMIT,
204 &on, sizeof(on)) == -1)
205 goto eexit;
206
207 ICMP6_FILTER_SETBLOCKALL(&filt);
208 ICMP6_FILTER_SETPASS(ND_NEIGHBOR_ADVERT, &filt);
209 ICMP6_FILTER_SETPASS(ND_ROUTER_ADVERT, &filt);
210 if (setsockopt(ctx->nd_fd, IPPROTO_ICMPV6, ICMP6_FILTER,
211 &filt, sizeof(filt)) == -1)
212 goto eexit;
213
214 eloop_event_add(dctx->eloop, ctx->nd_fd,
215 ipv6nd_handledata, dctx, NULL, NULL);
216 return ctx->nd_fd;
217
218eexit:
219 if (ctx->nd_fd != -1) {
220 eloop_event_delete(dctx->eloop, ctx->nd_fd, 0);
221 close(ctx->nd_fd);
222 ctx->nd_fd = -1;
223 }
224 return -1;
225}
226
227static int
228ipv6nd_makersprobe(struct interface *ifp)
229{
230 struct rs_state *state;
231 struct nd_router_solicit *rs;
232 struct nd_opt_hdr *nd;
233
234 state = RS_STATE(ifp);
235 free(state->rs);
236 state->rslen = sizeof(*rs) + (size_t)ROUNDUP8(ifp->hwlen + 2);
237 state->rs = calloc(1, state->rslen);
238 if (state->rs == NULL)
239 return -1;
240 rs = (struct nd_router_solicit *)(void *)state->rs;
241 rs->nd_rs_type = ND_ROUTER_SOLICIT;
242 rs->nd_rs_code = 0;
243 rs->nd_rs_cksum = 0;
244 rs->nd_rs_reserved = 0;
245 nd = (struct nd_opt_hdr *)(state->rs + sizeof(*rs));
246 nd->nd_opt_type = ND_OPT_SOURCE_LINKADDR;
247 nd->nd_opt_len = (uint8_t)((ROUNDUP8(ifp->hwlen + 2)) >> 3);
248 memcpy(nd + 1, ifp->hwaddr, ifp->hwlen);
249 return 0;
250}
251
252static void
253ipv6nd_sendrsprobe(void *arg)
254{
255 struct interface *ifp = arg;
256 struct ipv6_ctx *ctx;
257 struct rs_state *state;
258 struct sockaddr_in6 dst;
259 struct cmsghdr *cm;
260 struct in6_pktinfo pi;
261
262 if (ipv6_linklocal(ifp) == NULL) {
263 logger(ifp->ctx, LOG_DEBUG,
264 "%s: delaying Router Solicitation for LL address",
265 ifp->name);
266 ipv6_addlinklocalcallback(ifp, ipv6nd_sendrsprobe, ifp);
267 return;
268 }
269
270 memset(&dst, 0, sizeof(dst));
271 dst.sin6_family = AF_INET6;
272#ifdef SIN6_LEN
273 dst.sin6_len = sizeof(dst);
274#endif
275 dst.sin6_scope_id = ifp->index;
276 if (inet_pton(AF_INET6, ALLROUTERS, &dst.sin6_addr) != 1) {
277 logger(ifp->ctx, LOG_ERR, "%s: %m", __func__);
278 return;
279 }
280
281 state = RS_STATE(ifp);
282 ctx = ifp->ctx->ipv6;
283 ctx->sndhdr.msg_name = (void *)&dst;
284 ctx->sndhdr.msg_iov[0].iov_base = state->rs;
285 ctx->sndhdr.msg_iov[0].iov_len = state->rslen;
286
287 /* Set the outbound interface */
288 cm = CMSG_FIRSTHDR(&ctx->sndhdr);
289 if (cm == NULL) /* unlikely */
290 return;
291 cm->cmsg_level = IPPROTO_IPV6;
292 cm->cmsg_type = IPV6_PKTINFO;
293 cm->cmsg_len = CMSG_LEN(sizeof(pi));
294 memset(&pi, 0, sizeof(pi));
295 pi.ipi6_ifindex = ifp->index;
296 memcpy(CMSG_DATA(cm), &pi, sizeof(pi));
297
298 logger(ifp->ctx, LOG_DEBUG,
299 "%s: sending Router Solicitation", ifp->name);
300 if (sendmsg(ctx->nd_fd, &ctx->sndhdr, 0) == -1) {
301 logger(ifp->ctx, LOG_ERR,
302 "%s: %s: sendmsg: %m", ifp->name, __func__);
303 ipv6nd_drop(ifp);
304 ifp->options->options &= ~(DHCPCD_IPV6 | DHCPCD_IPV6RS);
305 return;
306 }
307
308 if (state->rsprobes++ < MAX_RTR_SOLICITATIONS)
309 eloop_timeout_add_sec(ifp->ctx->eloop,
310 RTR_SOLICITATION_INTERVAL, ipv6nd_sendrsprobe, ifp);
311 else {
312 logger(ifp->ctx, LOG_WARNING,
313 "%s: no IPv6 Routers available", ifp->name);
314 ipv6nd_drop(ifp);
315 dhcp6_drop(ifp, "EXPIRE6");
316 }
317}
318
319void
320ipv6nd_expire(struct interface *ifp, uint32_t seconds)
321{
322 struct ra *rap;
323 struct timespec now;
324
325 get_monotonic(&now);
326
327 TAILQ_FOREACH(rap, ifp->ctx->ipv6->ra_routers, next) {
328 if (rap->iface == ifp) {
329 rap->received = now;
330 rap->expired = seconds ? 0 : 1;
331 if (seconds) {
332 struct ra_opt *rao;
333 struct ipv6_addr *ap;
334
335 rap->lifetime = seconds;
336 TAILQ_FOREACH(ap, &rap->addrs, next) {
337 if (ap->prefix_vltime) {
338 ap->prefix_vltime = seconds;
339 ap->prefix_pltime = seconds / 2;
340 }
341 }
342 ipv6_addaddrs(&rap->addrs);
343 TAILQ_FOREACH(rao, &rap->options, next) {
344 timespecclear(&rao->expire);
345 }
346 }
347 }
348 }
349 if (seconds)
350 ipv6nd_expirera(ifp);
351 else
352 ipv6_buildroutes(ifp->ctx);
353}
354
355static void
356ipv6nd_reachable(struct ra *rap, int flags)
357{
358
359 if (flags & IPV6ND_REACHABLE) {
360 if (rap->lifetime && rap->expired) {
361 logger(rap->iface->ctx, LOG_INFO,
362 "%s: %s is reachable again",
363 rap->iface->name, rap->sfrom);
364 rap->expired = 0;
365 ipv6_buildroutes(rap->iface->ctx);
366 /* XXX Not really an RA */
367 script_runreason(rap->iface, "ROUTERADVERT");
368 }
369 } else {
370 if (rap->lifetime && !rap->expired) {
371 logger(rap->iface->ctx, LOG_WARNING,
372 "%s: %s is unreachable, expiring it",
373 rap->iface->name, rap->sfrom);
374 rap->expired = 1;
375 ipv6_buildroutes(rap->iface->ctx);
376 /* XXX Not really an RA */
377 script_runreason(rap->iface, "ROUTERADVERT");
378 }
379 }
380}
381
382void
383ipv6nd_neighbour(struct dhcpcd_ctx *ctx, struct in6_addr *addr, int flags)
384{
385 struct ra *rap;
386
387 if (ctx->ipv6) {
388 TAILQ_FOREACH(rap, ctx->ipv6->ra_routers, next) {
389 if (IN6_ARE_ADDR_EQUAL(&rap->from, addr)) {
390 ipv6nd_reachable(rap, flags);
391 break;
392 }
393 }
394 }
395}
396
397static void
398ipv6nd_free_opts(struct ra *rap)
399{
400 struct ra_opt *rao;
401
402 while ((rao = TAILQ_FIRST(&rap->options))) {
403 TAILQ_REMOVE(&rap->options, rao, next);
404 free(rao->option);
405 free(rao);
406 }
407}
408
409struct ipv6_addr *
410ipv6nd_findaddr(struct dhcpcd_ctx *ctx, const struct in6_addr *addr,
411 short flags)
412{
413 struct ra *rap;
414 struct ipv6_addr *ap;
415
416 if (ctx->ipv6 == NULL)
417 return NULL;
418
419 TAILQ_FOREACH(rap, ctx->ipv6->ra_routers, next) {
420 TAILQ_FOREACH(ap, &rap->addrs, next) {
421 if (addr == NULL) {
422 if ((ap->flags &
423 (IPV6_AF_ADDED | IPV6_AF_DADCOMPLETED)) ==
424 (IPV6_AF_ADDED | IPV6_AF_DADCOMPLETED))
425 return ap;
426 } else if (ap->prefix_vltime &&
427 IN6_ARE_ADDR_EQUAL(&ap->addr, addr) &&
428 (!flags || ap->flags & flags))
429 return ap;
430 }
431 }
432 return NULL;
433}
434
435void ipv6nd_freedrop_ra(struct ra *rap, int drop)
436{
437
438 eloop_timeout_delete(rap->iface->ctx->eloop, NULL, rap->iface);
439 eloop_timeout_delete(rap->iface->ctx->eloop, NULL, rap);
440 if (!drop)
441 TAILQ_REMOVE(rap->iface->ctx->ipv6->ra_routers, rap, next);
442 ipv6_freedrop_addrs(&rap->addrs, drop, NULL);
443 ipv6nd_free_opts(rap);
444 free(rap->data);
445 free(rap);
446}
447
448ssize_t
449ipv6nd_free(struct interface *ifp)
450{
451 struct rs_state *state;
452 struct ra *rap, *ran;
453 struct dhcpcd_ctx *ctx;
454 ssize_t n;
455
456 state = RS_STATE(ifp);
457 if (state == NULL)
458 return 0;
459
460 free(state->rs);
461 free(state);
462 ifp->if_data[IF_DATA_IPV6ND] = NULL;
463 n = 0;
464 TAILQ_FOREACH_SAFE(rap, ifp->ctx->ipv6->ra_routers, next, ran) {
465 if (rap->iface == ifp) {
466 ipv6nd_free_ra(rap);
467 n++;
468 }
469 }
470
471 /* If we don't have any more IPv6 enabled interfaces,
472 * close the global socket and release resources */
473 ctx = ifp->ctx;
474 TAILQ_FOREACH(ifp, ctx->ifaces, next) {
475 if (RS_STATE(ifp))
476 break;
477 }
478 if (ifp == NULL) {
479 if (ctx->ipv6->nd_fd != -1) {
480 eloop_event_delete(ctx->eloop, ctx->ipv6->nd_fd, 0);
481 close(ctx->ipv6->nd_fd);
482 ctx->ipv6->nd_fd = -1;
483 }
484 }
485
486 return n;
487}
488
489static int
490rtpref(struct ra *rap)
491{
492
493 switch (rap->flags & ND_RA_FLAG_RTPREF_MASK) {
494 case ND_RA_FLAG_RTPREF_HIGH:
495 return (RTPREF_HIGH);
496 case ND_RA_FLAG_RTPREF_MEDIUM:
497 case ND_RA_FLAG_RTPREF_RSV:
498 return (RTPREF_MEDIUM);
499 case ND_RA_FLAG_RTPREF_LOW:
500 return (RTPREF_LOW);
501 default:
502 logger(rap->iface->ctx, LOG_ERR,
503 "rtpref: impossible RA flag %x", rap->flags);
504 return (RTPREF_INVALID);
505 }
506 /* NOTREACHED */
507}
508
509static void
510add_router(struct ipv6_ctx *ctx, struct ra *router)
511{
512 struct ra *rap;
513
514 TAILQ_FOREACH(rap, ctx->ra_routers, next) {
515 if (router->iface->metric < rap->iface->metric ||
516 (router->iface->metric == rap->iface->metric &&
517 rtpref(router) > rtpref(rap)))
518 {
519 TAILQ_INSERT_BEFORE(rap, router, next);
520 return;
521 }
522 }
523 TAILQ_INSERT_TAIL(ctx->ra_routers, router, next);
524}
525
526static int
527ipv6nd_scriptrun(struct ra *rap)
528{
529 int hasdns, hasaddress, pid;
530 struct ipv6_addr *ap;
531 const struct ra_opt *rao;
532
533 hasaddress = 0;
534 /* If all addresses have completed DAD run the script */
535 TAILQ_FOREACH(ap, &rap->addrs, next) {
536 if ((ap->flags & (IPV6_AF_AUTOCONF | IPV6_AF_ADDED)) ==
537 (IPV6_AF_AUTOCONF | IPV6_AF_ADDED))
538 {
539 hasaddress = 1;
540 if (!(ap->flags & IPV6_AF_DADCOMPLETED) &&
541 ipv6_iffindaddr(ap->iface, &ap->addr))
542 ap->flags |= IPV6_AF_DADCOMPLETED;
543 if ((ap->flags & IPV6_AF_DADCOMPLETED) == 0) {
544 logger(ap->iface->ctx, LOG_DEBUG,
545 "%s: waiting for Router Advertisement"
546 " DAD to complete",
547 rap->iface->name);
548 return 0;
549 }
550 }
551 }
552
553 /* If we don't require RDNSS then set hasdns = 1 so we fork */
554 if (!(rap->iface->options->options & DHCPCD_IPV6RA_REQRDNSS))
555 hasdns = 1;
556 else {
557 hasdns = 0;
558 TAILQ_FOREACH(rao, &rap->options, next) {
559 if (rao->type == ND_OPT_RDNSS &&
560 rao->option &&
561 timespecisset(&rao->expire))
562 {
563 hasdns = 1;
564 break;
565 }
566 }
567 }
568
569 script_runreason(rap->iface, "ROUTERADVERT");
570 pid = 0;
571 if (hasdns && (hasaddress ||
572 !(rap->flags & (ND_RA_FLAG_MANAGED | ND_RA_FLAG_OTHER))))
573 pid = dhcpcd_daemonise(rap->iface->ctx);
574#if 0
575 else if (options & DHCPCD_DAEMONISE &&
576 !(options & DHCPCD_DAEMONISED) && new_data)
577 logger(rap->iface->ctx, LOG_WARNING,
578 "%s: did not fork due to an absent"
579 " RDNSS option in the RA",
580 ifp->name);
581}
582#endif
583 return pid;
584}
585
586static void
587ipv6nd_addaddr(void *arg)
588{
589 struct ipv6_addr *ap = arg;
590
591 ipv6_addaddr(ap, NULL);
592}
593
594int
595ipv6nd_dadcompleted(const struct interface *ifp)
596{
597 const struct ra *rap;
598 const struct ipv6_addr *ap;
599
600 TAILQ_FOREACH(rap, ifp->ctx->ipv6->ra_routers, next) {
601 if (rap->iface != ifp)
602 continue;
603 TAILQ_FOREACH(ap, &rap->addrs, next) {
604 if (ap->flags & IPV6_AF_AUTOCONF &&
605 ap->flags & IPV6_AF_ADDED &&
606 !(ap->flags & IPV6_AF_DADCOMPLETED))
607 return 0;
608 }
609 }
610 return 1;
611}
612
613static void
614ipv6nd_dadcallback(void *arg)
615{
616 struct ipv6_addr *ap = arg, *rapap;
617 struct interface *ifp;
618 struct ra *rap;
619 int wascompleted, found;
620 struct timespec tv;
621 char buf[INET6_ADDRSTRLEN];
622 const char *p;
623 int dadcounter;
624
625 ifp = ap->iface;
626 wascompleted = (ap->flags & IPV6_AF_DADCOMPLETED);
627 ap->flags |= IPV6_AF_DADCOMPLETED;
628 if (ap->flags & IPV6_AF_DUPLICATED) {
629 ap->dadcounter++;
630 logger(ifp->ctx, LOG_WARNING, "%s: DAD detected %s",
631 ifp->name, ap->saddr);
632
633 /* Try and make another stable private address.
634 * Because ap->dadcounter is always increamented,
635 * a different address is generated. */
636 /* XXX Cache DAD counter per prefix/id/ssid? */
637 if (ifp->options->options & DHCPCD_SLAACPRIVATE) {
638 if (ap->dadcounter >= IDGEN_RETRIES) {
639 logger(ifp->ctx, LOG_ERR,
640 "%s: unable to obtain a"
641 " stable private address",
642 ifp->name);
643 goto try_script;
644 }
645 logger(ifp->ctx, LOG_INFO, "%s: deleting address %s",
646 ifp->name, ap->saddr);
647 if (if_deladdress6(ap) == -1 &&
648 errno != EADDRNOTAVAIL && errno != ENXIO)
649 logger(ifp->ctx, LOG_ERR, "if_deladdress6: %m");
650 dadcounter = ap->dadcounter;
651 if (ipv6_makestableprivate(&ap->addr,
652 &ap->prefix, ap->prefix_len,
653 ifp, &dadcounter) == -1)
654 {
655 logger(ifp->ctx, LOG_ERR,
656 "%s: ipv6_makestableprivate: %m",
657 ifp->name);
658 return;
659 }
660 ap->dadcounter = dadcounter;
661 ap->flags &= ~(IPV6_AF_ADDED | IPV6_AF_DADCOMPLETED);
662 ap->flags |= IPV6_AF_NEW;
663 p = inet_ntop(AF_INET6, &ap->addr, buf, sizeof(buf));
664 if (p)
665 snprintf(ap->saddr,
666 sizeof(ap->saddr),
667 "%s/%d",
668 p, ap->prefix_len);
669 else
670 ap->saddr[0] = '\0';
671 tv.tv_sec = 0;
672 tv.tv_nsec = (suseconds_t)
673 arc4random_uniform(IDGEN_DELAY * NSEC_PER_SEC);
674 timespecnorm(&tv);
675 eloop_timeout_add_tv(ifp->ctx->eloop, &tv,
676 ipv6nd_addaddr, ap);
677 return;
678 }
679 }
680
681try_script:
682 if (!wascompleted) {
683 TAILQ_FOREACH(rap, ifp->ctx->ipv6->ra_routers, next) {
684 if (rap->iface != ifp)
685 continue;
686 wascompleted = 1;
687 found = 0;
688 TAILQ_FOREACH(rapap, &rap->addrs, next) {
689 if (rapap->flags & IPV6_AF_AUTOCONF &&
690 rapap->flags & IPV6_AF_ADDED &&
691 (rapap->flags & IPV6_AF_DADCOMPLETED) == 0)
692 {
693 wascompleted = 0;
694 break;
695 }
696 if (rapap == ap)
697 found = 1;
698 }
699
700 if (wascompleted && found) {
701 logger(rap->iface->ctx, LOG_DEBUG,
702 "%s: Router Advertisement DAD completed",
703 rap->iface->name);
704 if (ipv6nd_scriptrun(rap))
705 return;
706 }
707 }
708 }
709}
710
711static int
712ipv6nd_ra_has_public_addr(const struct ra *rap)
713{
714 const struct ipv6_addr *ia;
715
716 TAILQ_FOREACH(ia, &rap->addrs, next) {
717 if (ia->flags & IPV6_AF_AUTOCONF &&
718 ipv6_publicaddr(ia))
719 return 1;
720 }
721 return 0;
722}
723
724static void
725ipv6nd_handlera(struct dhcpcd_ctx *dctx, struct interface *ifp,
726 struct icmp6_hdr *icp, size_t len)
727{
728 struct ipv6_ctx *ctx = dctx->ipv6;
729 size_t olen, l, n;
730 ssize_t r;
731 struct nd_router_advert *nd_ra;
732 struct nd_opt_prefix_info *pi;
733 struct nd_opt_mtu *mtu;
734 struct nd_opt_rdnss *rdnss;
735 struct nd_opt_dnssl *dnssl;
736 uint32_t lifetime, mtuv;
737 uint8_t *p, *op;
738 struct in6_addr addr;
739 char buf[INET6_ADDRSTRLEN];
740 const char *cbp;
741 struct ra *rap;
742 struct nd_opt_hdr *ndo;
743 struct ra_opt *rao;
744 struct ipv6_addr *ap;
745 char *opt, *opt2, *tmp;
746 struct timespec expire;
747 uint8_t new_rap, new_data;
748#ifdef IPV6_MANAGETEMPADDR
749 uint8_t new_ap;
750#endif
751
752 if (len < sizeof(struct nd_router_advert)) {
753 logger(dctx, LOG_ERR,
754 "IPv6 RA packet too short from %s", ctx->sfrom);
755 return;
756 }
757
758 if (!IN6_IS_ADDR_LINKLOCAL(&ctx->from.sin6_addr)) {
759 logger(dctx, LOG_ERR,
760 "RA from non local address %s", ctx->sfrom);
761 return;
762 }
763
764 if (ifp == NULL) {
765#ifdef DEBUG_RS
766 logger(dctx, LOG_DEBUG,
767 "RA for unexpected interface from %s", ctx->sfrom);
768#endif
769 return;
770 }
771 if (!(ifp->options->options & DHCPCD_IPV6RS)) {
772#ifdef DEBUG_RS
773 logger(ifp->ctx, LOG_DEBUG, "%s: unexpected RA from %s",
774 ifp->name, ctx->sfrom);
775#endif
776 return;
777 }
778
779 /* We could receive a RA before we sent a RS*/
780 if (ipv6_linklocal(ifp) == NULL) {
781#ifdef DEBUG_RS
782 logger(ifp->ctx, LOG_DEBUG,
783 "%s: received RA from %s (no link-local)",
784 ifp->name, ctx->sfrom);
785#endif
786 return;
787 }
788
789 if (ipv6_iffindaddr(ifp, &ctx->from.sin6_addr)) {
790 logger(ifp->ctx, LOG_DEBUG,
791 "%s: ignoring RA from ourself %s", ifp->name, ctx->sfrom);
792 return;
793 }
794
795 TAILQ_FOREACH(rap, ctx->ra_routers, next) {
796 if (ifp == rap->iface &&
797 IN6_ARE_ADDR_EQUAL(&rap->from, &ctx->from.sin6_addr))
798 break;
799 }
800
801 nd_ra = (struct nd_router_advert *)icp;
802
803 /* We don't want to spam the log with the fact we got an RA every
804 * 30 seconds or so, so only spam the log if it's different. */
805 if (rap == NULL || (rap->data_len != len ||
806 memcmp(rap->data, (unsigned char *)icp, rap->data_len) != 0))
807 {
808 if (rap) {
809 free(rap->data);
810 rap->data_len = 0;
811 rap->no_public_warned = 0;
812 }
813 new_data = 1;
814 } else
815 new_data = 0;
816 if (new_data || ifp->options->options & DHCPCD_DEBUG)
817 logger(ifp->ctx, LOG_INFO, "%s: Router Advertisement from %s",
818 ifp->name, ctx->sfrom);
819
820 if (rap == NULL) {
821 rap = calloc(1, sizeof(*rap));
822 if (rap == NULL) {
823 logger(ifp->ctx, LOG_ERR, "%s: %m", __func__);
824 return;
825 }
826 rap->iface = ifp;
827 rap->from = ctx->from.sin6_addr;
828 strlcpy(rap->sfrom, ctx->sfrom, sizeof(rap->sfrom));
829 TAILQ_INIT(&rap->addrs);
830 TAILQ_INIT(&rap->options);
831 new_rap = 1;
832 } else
833 new_rap = 0;
834 if (rap->data_len == 0) {
835 rap->data = malloc(len);
836 if (rap->data == NULL) {
837 logger(ifp->ctx, LOG_ERR, "%s: %m", __func__);
838 if (new_rap)
839 free(rap);
840 return;
841 }
842 memcpy(rap->data, icp, len);
843 rap->data_len = len;
844 }
845
846 get_monotonic(&rap->received);
847 rap->flags = nd_ra->nd_ra_flags_reserved;
848 if (new_rap == 0 && rap->lifetime == 0)
849 logger(ifp->ctx, LOG_WARNING, "%s: %s router available",
850 ifp->name, rap->sfrom);
851 rap->lifetime = ntohs(nd_ra->nd_ra_router_lifetime);
852 if (nd_ra->nd_ra_reachable) {
853 rap->reachable = ntohl(nd_ra->nd_ra_reachable);
854 if (rap->reachable > MAX_REACHABLE_TIME)
855 rap->reachable = 0;
856 }
857 if (nd_ra->nd_ra_retransmit)
858 rap->retrans = ntohl(nd_ra->nd_ra_retransmit);
859 if (rap->lifetime)
860 rap->expired = 0;
861
862 ipv6_settempstale(ifp);
863 TAILQ_FOREACH(ap, &rap->addrs, next) {
864 ap->flags |= IPV6_AF_STALE;
865 }
866
867 len -= sizeof(struct nd_router_advert);
868 p = ((uint8_t *)icp) + sizeof(struct nd_router_advert);
869 lifetime = ~0U;
870 for (; len > 0; p += olen, len -= olen) {
871 if (len < sizeof(struct nd_opt_hdr)) {
872 logger(ifp->ctx, LOG_ERR,
873 "%s: short option", ifp->name);
874 break;
875 }
876 ndo = (struct nd_opt_hdr *)p;
877 olen = (size_t)ndo->nd_opt_len * 8;
878 if (olen == 0) {
879 logger(ifp->ctx, LOG_ERR,
880 "%s: zero length option", ifp->name);
881 break;
882 }
883 if (olen > len) {
884 logger(ifp->ctx, LOG_ERR,
885 "%s: option length exceeds message", ifp->name);
886 break;
887 }
888
889 opt = opt2 = NULL;
890 switch (ndo->nd_opt_type) {
891 case ND_OPT_PREFIX_INFORMATION:
892 pi = (struct nd_opt_prefix_info *)(void *)ndo;
893 if (pi->nd_opt_pi_len != 4) {
894 logger(ifp->ctx, new_data ? LOG_ERR : LOG_DEBUG,
895 "%s: invalid option len for prefix",
896 ifp->name);
897 continue;
898 }
899 if (pi->nd_opt_pi_prefix_len > 128) {
900 logger(ifp->ctx, new_data ? LOG_ERR : LOG_DEBUG,
901 "%s: invalid prefix len",
902 ifp->name);
903 continue;
904 }
905 if (IN6_IS_ADDR_MULTICAST(&pi->nd_opt_pi_prefix) ||
906 IN6_IS_ADDR_LINKLOCAL(&pi->nd_opt_pi_prefix))
907 {
908 logger(ifp->ctx, new_data ? LOG_ERR : LOG_DEBUG,
909 "%s: invalid prefix in RA", ifp->name);
910 continue;
911 }
912 if (ntohl(pi->nd_opt_pi_preferred_time) >
913 ntohl(pi->nd_opt_pi_valid_time))
914 {
915 logger(ifp->ctx, new_data ? LOG_ERR : LOG_DEBUG,
916 "%s: pltime > vltime", ifp->name);
917 continue;
918 }
919 TAILQ_FOREACH(ap, &rap->addrs, next)
920 if (ap->prefix_len ==pi->nd_opt_pi_prefix_len &&
921 IN6_ARE_ADDR_EQUAL(&ap->prefix,
922 &pi->nd_opt_pi_prefix))
923 break;
924 if (ap == NULL) {
925 if (!(pi->nd_opt_pi_flags_reserved &
926 ND_OPT_PI_FLAG_AUTO) &&
927 !(pi->nd_opt_pi_flags_reserved &
928 ND_OPT_PI_FLAG_ONLINK))
929 continue;
930 ap = calloc(1, sizeof(*ap));
931 if (ap == NULL)
932 break;
933 ap->iface = rap->iface;
934 ap->flags = IPV6_AF_NEW;
935 ap->prefix_len = pi->nd_opt_pi_prefix_len;
936 ap->prefix = pi->nd_opt_pi_prefix;
937 if (pi->nd_opt_pi_flags_reserved &
938 ND_OPT_PI_FLAG_AUTO &&
939 ap->iface->options->options &
940 DHCPCD_IPV6RA_AUTOCONF)
941 {
942 ap->flags |= IPV6_AF_AUTOCONF;
943 ap->dadcounter =
944 ipv6_makeaddr(&ap->addr, ifp,
945 &ap->prefix,
946 pi->nd_opt_pi_prefix_len);
947 if (ap->dadcounter == -1) {
948 free(ap);
949 break;
950 }
951 cbp = inet_ntop(AF_INET6,
952 &ap->addr,
953 buf, sizeof(buf));
954 if (cbp)
955 snprintf(ap->saddr,
956 sizeof(ap->saddr),
957 "%s/%d",
958 cbp, ap->prefix_len);
959 else
960 ap->saddr[0] = '\0';
961 } else {
962 memset(&ap->addr, 0, sizeof(ap->addr));
963 ap->saddr[0] = '\0';
964 }
965 ap->dadcallback = ipv6nd_dadcallback;
966 ap->created = ap->acquired = rap->received;
967 TAILQ_INSERT_TAIL(&rap->addrs, ap, next);
968
969#ifdef IPV6_MANAGETEMPADDR
970 /* New address to dhcpcd RA handling.
971 * If the address already exists and a valid
972 * temporary address also exists then
973 * extend the existing one rather than
974 * create a new one */
975 if (ipv6_iffindaddr(ifp, &ap->addr) &&
976 ipv6_settemptime(ap, 0))
977 new_ap = 0;
978 else
979 new_ap = 1;
980#endif
981 } else {
982#ifdef IPV6_MANAGETEMPADDR
983 new_ap = 0;
984#endif
985 ap->flags &= ~IPV6_AF_STALE;
986 ap->acquired = rap->received;
987 }
988 if (pi->nd_opt_pi_flags_reserved &
989 ND_OPT_PI_FLAG_ONLINK)
990 ap->flags |= IPV6_AF_ONLINK;
991 ap->prefix_vltime =
992 ntohl(pi->nd_opt_pi_valid_time);
993 ap->prefix_pltime =
994 ntohl(pi->nd_opt_pi_preferred_time);
995 ap->nsprobes = 0;
996 cbp = inet_ntop(AF_INET6, &ap->prefix, buf, sizeof(buf));
997 if (cbp) {
998 l = strlen(cbp);
999 opt = malloc(l + 5);
1000 if (opt) {
1001 snprintf(opt, l + 5, "%s/%d", cbp,
1002 ap->prefix_len);
1003 opt2 = strdup(ap->saddr);
1004 }
1005 }
1006
1007#ifdef IPV6_MANAGETEMPADDR
1008 /* RFC4941 Section 3.3.3 */
1009 if (ap->flags & IPV6_AF_AUTOCONF &&
1010 ap->iface->options->options & DHCPCD_IPV6RA_OWN &&
1011 ip6_use_tempaddr(ap->iface->name))
1012 {
1013 if (!new_ap) {
1014 if (ipv6_settemptime(ap, 1) == NULL)
1015 new_ap = 1;
1016 }
1017 if (new_ap && ap->prefix_pltime) {
1018 if (ipv6_createtempaddr(ap,
1019 &ap->acquired) == NULL)
1020 logger(ap->iface->ctx, LOG_ERR,
1021 "ipv6_createtempaddr: %m");
1022 }
1023 }
1024#endif
1025
1026 lifetime = ap->prefix_vltime;
1027 break;
1028
1029 case ND_OPT_MTU:
1030 mtu = (struct nd_opt_mtu *)(void *)p;
1031 mtuv = ntohl(mtu->nd_opt_mtu_mtu);
1032 if (mtuv < IPV6_MMTU) {
1033 logger(ifp->ctx, LOG_ERR, "%s: invalid MTU %d",
1034 ifp->name, mtuv);
1035 break;
1036 }
1037 rap->mtu = mtuv;
1038 snprintf(buf, sizeof(buf), "%d", mtuv);
1039 opt = strdup(buf);
1040 break;
1041
1042 case ND_OPT_RDNSS:
1043 rdnss = (struct nd_opt_rdnss *)p;
1044 lifetime = ntohl(rdnss->nd_opt_rdnss_lifetime);
1045 op = (uint8_t *)ndo;
1046 op += offsetof(struct nd_opt_rdnss,
1047 nd_opt_rdnss_lifetime);
1048 op += sizeof(rdnss->nd_opt_rdnss_lifetime);
1049 l = 0;
1050 for (n = (size_t)ndo->nd_opt_len - 1; n > 1; n -= 2,
1051 op += sizeof(addr))
1052 {
1053 r = ipv6_printaddr(NULL, 0, op, ifp->name);
1054 if (r != -1)
1055 l += (size_t)r + 1;
1056 }
1057 op = (uint8_t *)ndo;
1058 op += offsetof(struct nd_opt_rdnss,
1059 nd_opt_rdnss_lifetime);
1060 op += sizeof(rdnss->nd_opt_rdnss_lifetime);
1061 tmp = opt = malloc(l);
1062 if (opt == NULL)
1063 continue;
1064 for (n = (size_t)ndo->nd_opt_len - 1; n > 1; n -= 2,
1065 op += sizeof(addr))
1066 {
1067 r = ipv6_printaddr(tmp, l, op,
1068 ifp->name);
1069 if (r != -1) {
1070 l -= ((size_t)r + 1);
1071 tmp += (size_t)r;
1072 *tmp++ = ' ';
1073 }
1074 }
1075 if (tmp != opt)
1076 (*--tmp) = '\0';
1077 else
1078 *opt = '\0';
1079 break;
1080
1081 case ND_OPT_DNSSL:
1082 dnssl = (struct nd_opt_dnssl *)p;
1083 lifetime = ntohl(dnssl->nd_opt_dnssl_lifetime);
1084 op = p + offsetof(struct nd_opt_dnssl,
1085 nd_opt_dnssl_lifetime);
1086 op += sizeof(dnssl->nd_opt_dnssl_lifetime);
1087 n = (size_t)(dnssl->nd_opt_dnssl_len - 1) * 8;
1088 r = decode_rfc3397(NULL, 0, op, n);
1089 if (r < 1) {
1090 logger(ifp->ctx, new_data ? LOG_ERR : LOG_DEBUG,
1091 "%s: invalid DNSSL option",
1092 ifp->name);
1093 continue;
1094 } else {
1095 l = (size_t)r + 1;
1096 tmp = malloc(l);
1097 if (tmp) {
1098 decode_rfc3397(tmp, l, op, n);
1099 l -= 1;
1100 n = (size_t)print_string(NULL, 0,
1101 STRING | ARRAY | DOMAIN,
1102 (const uint8_t *)tmp, l);
1103 n++;
1104 opt = malloc(n);
1105 if (opt) {
1106 print_string(opt, n,
1107 STRING | ARRAY | DOMAIN,
1108 (const uint8_t *)tmp, l);
1109 } else
1110 logger(ifp->ctx, LOG_ERR,
1111 "%s: %m", __func__);
1112 free(tmp);
1113 }
1114 }
1115 break;
1116
1117 default:
1118 continue;
1119 }
1120
1121 if (opt == NULL) {
1122 logger(ifp->ctx, LOG_ERR, "%s: %m", __func__);
1123 continue;
1124 }
1125
1126 n = ndo->nd_opt_type;
1127extra_opt:
1128 TAILQ_FOREACH(rao, &rap->options, next) {
1129 if (rao->type == n &&
1130 strcmp(rao->option, opt) == 0)
1131 break;
1132 }
1133 if (lifetime == 0 || *opt == '\0') {
1134 if (rao) {
1135 TAILQ_REMOVE(&rap->options, rao, next);
1136 free(rao->option);
1137 free(rao);
1138 }
1139 free(opt);
1140 free(opt2);
1141 continue;
1142 }
1143
1144 if (rao == NULL) {
1145 rao = malloc(sizeof(*rao));
1146 if (rao == NULL) {
1147 logger(ifp->ctx, LOG_ERR, "%s: %m", __func__);
1148 continue;
1149 }
1150 rao->type = (uint16_t)n;
1151 rao->option = opt;
1152 TAILQ_INSERT_TAIL(&rap->options, rao, next);
1153 } else
1154 free(opt);
1155 if (lifetime == ~0U)
1156 timespecclear(&rao->expire);
1157 else {
1158 expire.tv_sec = (time_t)lifetime;
1159 expire.tv_nsec = 0;
1160 timespecadd(&rap->received, &expire, &rao->expire);
1161 }
1162 if (rao && rao->type == ND_OPT_PREFIX_INFORMATION && opt2) {
1163 n = _ND_OPT_PREFIX_ADDR;
1164 opt = opt2;
1165 opt2 = NULL;
1166 goto extra_opt;
1167 }
1168 }
1169
1170 if (new_rap)
1171 add_router(ifp->ctx->ipv6, rap);
1172 if (!ipv6nd_ra_has_public_addr(rap) &&
1173 !(rap->iface->options->options & DHCPCD_IPV6RA_ACCEPT_NOPUBLIC) &&
1174 (!(rap->flags & ND_RA_FLAG_MANAGED) ||
1175 !dhcp6_has_public_addr(rap->iface)))
1176 {
1177 logger(rap->iface->ctx,
1178 rap->no_public_warned ? LOG_DEBUG : LOG_WARNING,
1179 "%s: ignoring RA from %s"
1180 " (no public prefix, no managed address)",
1181 rap->iface->name, rap->sfrom);
1182 rap->no_public_warned = 1;
1183 return;
1184 }
1185 if (ifp->ctx->options & DHCPCD_TEST) {
1186 script_runreason(ifp, "TEST");
1187 goto handle_flag;
1188 }
1189 ipv6_addaddrs(&rap->addrs);
1190#ifdef IPV6_MANAGETEMPADDR
1191 ipv6_addtempaddrs(ifp, &rap->received);
1192#endif
1193
1194 /* Find any freshly added routes, such as the subnet route.
1195 * We do this because we cannot rely on recieving the kernel
1196 * notification right now via our link socket. */
1197 if_initrt6(ifp);
1198
1199 ipv6_buildroutes(ifp->ctx);
1200 if (ipv6nd_scriptrun(rap))
1201 return;
1202
1203 eloop_timeout_delete(ifp->ctx->eloop, NULL, ifp);
1204 eloop_timeout_delete(ifp->ctx->eloop, NULL, rap); /* reachable timer */
1205
1206handle_flag:
1207 if (!(ifp->options->options & DHCPCD_DHCP6))
1208 goto nodhcp6;
1209 if (rap->flags & ND_RA_FLAG_MANAGED) {
1210 if (new_data && dhcp6_start(ifp, DH6S_INIT) == -1)
1211 logger(ifp->ctx, LOG_ERR,
1212 "dhcp6_start: %s: %m", ifp->name);
1213 } else if (rap->flags & ND_RA_FLAG_OTHER) {
1214 if (new_data && dhcp6_start(ifp, DH6S_INFORM) == -1)
1215 logger(ifp->ctx, LOG_ERR,
1216 "dhcp6_start: %s: %m", ifp->name);
1217 } else {
1218 if (new_data)
1219 logger(ifp->ctx, LOG_DEBUG,
1220 "%s: No DHCPv6 instruction in RA", ifp->name);
1221nodhcp6:
1222 if (ifp->ctx->options & DHCPCD_TEST) {
1223 eloop_exit(ifp->ctx->eloop, EXIT_SUCCESS);
1224 return;
1225 }
1226 }
1227
1228 /* Expire should be called last as the rap object could be destroyed */
1229 ipv6nd_expirera(ifp);
1230}
1231
1232/* Run RA's we ignored becuase they had no public addresses
1233 * This should only be called when DHCPv6 applies a public address */
1234void
1235ipv6nd_runignoredra(struct interface *ifp)
1236{
1237 struct ra *rap;
1238
1239 TAILQ_FOREACH(rap, ifp->ctx->ipv6->ra_routers, next) {
1240 if (rap->iface == ifp &&
1241 !rap->expired &&
1242 rap->no_public_warned)
1243 {
1244 rap->no_public_warned = 0;
1245 logger(rap->iface->ctx, LOG_INFO,
1246 "%s: applying ignored RA from %s",
1247 rap->iface->name, rap->sfrom);
1248 if (ifp->ctx->options & DHCPCD_TEST) {
1249 script_runreason(ifp, "TEST");
1250 continue;
1251 }
1252 if (ipv6nd_scriptrun(rap))
1253 return;
1254 eloop_timeout_delete(ifp->ctx->eloop, NULL, ifp);
1255 eloop_timeout_delete(ifp->ctx->eloop, NULL, rap);
1256 }
1257 }
1258}
1259
1260int
1261ipv6nd_hasra(const struct interface *ifp)
1262{
1263 const struct ra *rap;
1264
1265 if (ifp->ctx->ipv6) {
1266 TAILQ_FOREACH(rap, ifp->ctx->ipv6->ra_routers, next)
1267 if (rap->iface == ifp && !rap->expired)
1268 return 1;
1269 }
1270 return 0;
1271}
1272
1273int
1274ipv6nd_hasradhcp(const struct interface *ifp)
1275{
1276 const struct ra *rap;
1277
1278 if (ifp->ctx->ipv6) {
1279 TAILQ_FOREACH(rap, ifp->ctx->ipv6->ra_routers, next) {
1280 if (rap->iface == ifp &&
1281 !rap->expired &&
1282 (rap->flags & (ND_RA_FLAG_MANAGED | ND_RA_FLAG_OTHER)))
1283 return 1;
1284 }
1285 }
1286 return 0;
1287}
1288
1289ssize_t
1290ipv6nd_env(char **env, const char *prefix, const struct interface *ifp)
1291{
1292 size_t i, l, len;
1293 const struct ra *rap;
1294 const struct ra_opt *rao;
1295 char buffer[32];
1296 const char *optn;
1297 char **pref, **addr, **mtu, **rdnss, **dnssl, ***var, *new;
1298
1299 i = l = 0;
1300 TAILQ_FOREACH(rap, ifp->ctx->ipv6->ra_routers, next) {
1301 if (rap->iface != ifp)
1302 continue;
1303 i++;
1304 if (env) {
1305 snprintf(buffer, sizeof(buffer),
1306 "ra%zu_from", i);
1307 setvar(ifp->ctx, &env, prefix, buffer, rap->sfrom);
1308 }
1309 l++;
1310
1311 pref = addr = mtu = rdnss = dnssl = NULL;
1312 TAILQ_FOREACH(rao, &rap->options, next) {
1313 if (rao->option == NULL)
1314 continue;
1315 var = NULL;
1316 switch(rao->type) {
1317 case ND_OPT_PREFIX_INFORMATION:
1318 optn = "prefix";
1319 var = &pref;
1320 break;
1321 case _ND_OPT_PREFIX_ADDR:
1322 optn = "addr";
1323 var = &addr;
1324 break;
1325 case ND_OPT_MTU:
1326 optn = "mtu";
1327 var = &mtu;
1328 break;
1329 case ND_OPT_RDNSS:
1330 optn = "rdnss";
1331 var = &rdnss;
1332 break;
1333 case ND_OPT_DNSSL:
1334 optn = "dnssl";
1335 var = &dnssl;
1336 break;
1337 default:
1338 continue;
1339 }
1340 if (*var == NULL) {
1341 *var = env ? env : &new;
1342 l++;
1343 } else if (env) {
1344 /* With single only options, last one takes
1345 * precedence */
1346 if (rao->type == ND_OPT_MTU) {
1347 new = strchr(**var, '=');
1348 if (new == NULL) {
1349 logger(ifp->ctx, LOG_ERR,
1350 "new is null");
1351 continue;
1352 } else
1353 new++;
1354 len = (size_t)(new - **var) +
1355 strlen(rao->option) + 1;
1356 if (len > strlen(**var))
1357 new = realloc(**var, len);
1358 else
1359 new = **var;
1360 if (new) {
1361 **var = new;
1362 new = strchr(**var, '=');
1363 if (new) {
1364 len -=
1365 (size_t)
1366 (new - **var);
1367 strlcpy(new + 1,
1368 rao->option,
1369 len - 1);
1370 } else
1371 logger(ifp->ctx,
1372 LOG_ERR,
1373 "new is null");
1374 }
1375 continue;
1376 }
1377 len = strlen(rao->option) + 1;
1378 new = realloc(**var, strlen(**var) + 1 + len);
1379 if (new) {
1380 **var = new;
1381 new += strlen(new);
1382 *new++ = ' ';
1383 strlcpy(new, rao->option, len);
1384 } else
1385 logger(ifp->ctx, LOG_ERR,
1386 "%s: %m", __func__);
1387 continue;
1388 }
1389 if (env) {
1390 snprintf(buffer, sizeof(buffer),
1391 "ra%zu_%s", i, optn);
1392 setvar(ifp->ctx, &env,
1393 prefix, buffer, rao->option);
1394 }
1395 }
1396 }
1397
1398 if (env)
1399 setvard(ifp->ctx, &env, prefix, "ra_count", i);
1400 l++;
1401 return (ssize_t)l;
1402}
1403
1404void
1405ipv6nd_handleifa(struct dhcpcd_ctx *ctx, int cmd, const char *ifname,
1406 const struct in6_addr *addr, int flags)
1407{
1408 struct ra *rap;
1409
1410 if (ctx->ipv6 == NULL)
1411 return;
1412 TAILQ_FOREACH(rap, ctx->ipv6->ra_routers, next) {
1413 if (strcmp(rap->iface->name, ifname))
1414 continue;
1415 ipv6_handleifa_addrs(cmd, &rap->addrs, addr, flags);
1416 }
1417}
1418
1419void
1420ipv6nd_expirera(void *arg)
1421{
1422 struct interface *ifp;
1423 struct ra *rap, *ran;
1424 struct ra_opt *rao, *raon;
1425 struct timespec now, lt, expire, next;
1426 uint8_t expired, valid, validone;
1427
1428 ifp = arg;
1429 get_monotonic(&now);
1430 expired = 0;
1431 timespecclear(&next);
1432
1433 validone = 0;
1434 TAILQ_FOREACH_SAFE(rap, ifp->ctx->ipv6->ra_routers, next, ran) {
1435 if (rap->iface != ifp)
1436 continue;
1437 valid = 0;
1438 if (rap->lifetime) {
1439 lt.tv_sec = (time_t)rap->lifetime;
1440 lt.tv_nsec = 0;
1441 timespecadd(&rap->received, &lt, &expire);
1442 if (rap->lifetime == 0 || timespeccmp(&now, &expire, >))
1443 {
1444 if (!rap->expired) {
1445 logger(ifp->ctx, LOG_WARNING,
1446 "%s: %s: router expired",
1447 ifp->name, rap->sfrom);
1448 rap->expired = expired = 1;
1449 rap->lifetime = 0;
1450 }
1451 } else {
1452 valid = 1;
1453 timespecsub(&expire, &now, &lt);
1454 if (!timespecisset(&next) ||
1455 timespeccmp(&next, &lt, >))
1456 next = lt;
1457 }
1458 }
1459
1460 /* Addresses are expired in ipv6_addaddrs
1461 * so that DHCPv6 addresses can be removed also. */
1462 TAILQ_FOREACH_SAFE(rao, &rap->options, next, raon) {
1463 if (rap->expired) {
1464 switch(rao->type) {
1465 case ND_OPT_RDNSS: /* FALLTHROUGH */
1466 case ND_OPT_DNSSL:
1467 /* RFC6018 end of section 5.2 states
1468 * that if tha RA has a lifetime of 0
1469 * then we should expire these
1470 * options */
1471 TAILQ_REMOVE(&rap->options, rao, next);
1472 expired = 1;
1473 free(rao->option);
1474 free(rao);
1475 continue;
1476 }
1477 }
1478 if (!timespecisset(&rao->expire))
1479 continue;
1480 if (timespeccmp(&now, &rao->expire, >)) {
1481 /* Expired prefixes are logged above */
1482 if (rao->type != ND_OPT_PREFIX_INFORMATION)
1483 logger(ifp->ctx, LOG_WARNING,
1484 "%s: %s: expired option %d",
1485 ifp->name, rap->sfrom, rao->type);
1486 TAILQ_REMOVE(&rap->options, rao, next);
1487 expired = 1;
1488 free(rao->option);
1489 free(rao);
1490 continue;
1491 }
1492 valid = 1;
1493 timespecsub(&rao->expire, &now, &lt);
1494 if (!timespecisset(&next) || timespeccmp(&next, &lt, >))
1495 next = lt;
1496 }
1497
1498 /* No valid lifetimes are left on the RA, so we might
1499 * as well punt it. */
1500 if (!valid && TAILQ_FIRST(&rap->addrs) == NULL)
1501 ipv6nd_free_ra(rap);
1502 else
1503 validone = 1;
1504 }
1505
1506 if (timespecisset(&next))
1507 eloop_timeout_add_tv(ifp->ctx->eloop,
1508 &next, ipv6nd_expirera, ifp);
1509 if (expired) {
1510 ipv6_buildroutes(ifp->ctx);
1511 script_runreason(ifp, "ROUTERADVERT");
1512 }
1513
1514 /* No valid routers? Kill any DHCPv6. */
1515 if (!validone)
1516 dhcp6_drop(ifp, "EXPIRE6");
1517}
1518
1519void
1520ipv6nd_drop(struct interface *ifp)
1521{
1522 struct ra *rap;
1523 uint8_t expired = 0;
1524 TAILQ_HEAD(rahead, ra) rtrs;
1525
1526 if (ifp->ctx->ipv6 == NULL)
1527 return;
1528
1529 eloop_timeout_delete(ifp->ctx->eloop, NULL, ifp);
1530 TAILQ_INIT(&rtrs);
1531 TAILQ_FOREACH(rap, ifp->ctx->ipv6->ra_routers, next) {
1532 if (rap->iface == ifp) {
1533 rap->expired = expired = 1;
1534 TAILQ_REMOVE(ifp->ctx->ipv6->ra_routers, rap, next);
1535 TAILQ_INSERT_TAIL(&rtrs, rap, next);
1536 }
1537 }
1538 if (expired) {
1539 while ((rap = TAILQ_FIRST(&rtrs))) {
1540 TAILQ_REMOVE(&rtrs, rap, next);
1541 ipv6nd_drop_ra(rap);
1542 }
1543 ipv6_buildroutes(ifp->ctx);
1544 if ((ifp->options->options &
1545 (DHCPCD_EXITING | DHCPCD_PERSISTENT)) !=
1546 (DHCPCD_EXITING | DHCPCD_PERSISTENT))
1547 script_runreason(ifp, "ROUTERADVERT");
1548 }
1549}
1550
1551static void
1552ipv6nd_handlena(struct dhcpcd_ctx *dctx, struct interface *ifp,
1553 struct icmp6_hdr *icp, size_t len)
1554{
1555 struct ipv6_ctx *ctx = dctx->ipv6;
1556 struct nd_neighbor_advert *nd_na;
1557 struct ra *rap;
1558 uint32_t is_router, is_solicited;
1559 char buf[INET6_ADDRSTRLEN];
1560 const char *taddr;
1561
1562 if (ifp == NULL) {
1563#ifdef DEBUG_NS
1564 logger(ctx, LOG_DEBUG, "NA for unexpected interface from %s",
1565 dctx->sfrom);
1566#endif
1567 return;
1568 }
1569
1570 if ((size_t)len < sizeof(struct nd_neighbor_advert)) {
1571 logger(ifp->ctx, LOG_ERR, "%s: IPv6 NA too short from %s",
1572 ifp->name, ctx->sfrom);
1573 return;
1574 }
1575
1576 nd_na = (struct nd_neighbor_advert *)icp;
1577 is_router = nd_na->nd_na_flags_reserved & ND_NA_FLAG_ROUTER;
1578 is_solicited = nd_na->nd_na_flags_reserved & ND_NA_FLAG_SOLICITED;
1579 taddr = inet_ntop(AF_INET6, &nd_na->nd_na_target,
1580 buf, INET6_ADDRSTRLEN);
1581
1582 if (IN6_IS_ADDR_MULTICAST(&nd_na->nd_na_target)) {
1583 logger(ifp->ctx, LOG_ERR, "%s: NA multicast address %s (%s)",
1584 ifp->name, taddr, ctx->sfrom);
1585 return;
1586 }
1587
1588 TAILQ_FOREACH(rap, ctx->ra_routers, next) {
1589 if (rap->iface == ifp &&
1590 IN6_ARE_ADDR_EQUAL(&rap->from, &nd_na->nd_na_target))
1591 break;
1592 }
1593 if (rap == NULL) {
1594#ifdef DEBUG_NS
1595 logger(ifp->ctx, LOG_DEBUG, "%s: unexpected NA from %s for %s",
1596 ifp->name, ctx->sfrom, taddr);
1597#endif
1598 return;
1599 }
1600
1601#ifdef DEBUG_NS
1602 logger(ifp->ctx, LOG_DEBUG, "%s: %sNA for %s from %s",
1603 ifp->name, is_solicited ? "solicited " : "", taddr, ctx->sfrom);
1604#endif
1605
1606 /* Node is no longer a router, so remove it from consideration */
1607 if (!is_router && !rap->expired) {
1608 logger(ifp->ctx, LOG_INFO, "%s: %s not a router (%s)",
1609 ifp->name, taddr, ctx->sfrom);
1610 rap->expired = 1;
1611 ipv6_buildroutes(ifp->ctx);
1612 script_runreason(ifp, "ROUTERADVERT");
1613 return;
1614 }
1615
1616 if (is_solicited && is_router && rap->lifetime) {
1617 if (rap->expired) {
1618 rap->expired = 0;
1619 logger(ifp->ctx, LOG_INFO, "%s: %s reachable (%s)",
1620 ifp->name, taddr, ctx->sfrom);
1621 ipv6_buildroutes(ifp->ctx);
1622 script_runreason(rap->iface, "ROUTERADVERT"); /* XXX */
1623 }
1624 }
1625}
1626
1627static void
1628ipv6nd_handledata(void *arg)
1629{
1630 struct dhcpcd_ctx *dctx;
1631 struct ipv6_ctx *ctx;
1632 ssize_t len;
1633 struct cmsghdr *cm;
1634 int hoplimit;
1635 struct in6_pktinfo pkt;
1636 struct icmp6_hdr *icp;
1637 struct interface *ifp;
1638
1639 dctx = arg;
1640 ctx = dctx->ipv6;
1641 ctx->rcvhdr.msg_controllen = CMSG_SPACE(sizeof(struct in6_pktinfo)) +
1642 CMSG_SPACE(sizeof(int));
1643 len = recvmsg(ctx->nd_fd, &ctx->rcvhdr, 0);
1644 if (len == -1) {
1645 logger(dctx, LOG_ERR, "recvmsg: %m");
1646 eloop_event_delete(dctx->eloop, ctx->nd_fd, 0);
1647 close(ctx->nd_fd);
1648 ctx->nd_fd = -1;
1649 return;
1650 }
1651 ctx->sfrom = inet_ntop(AF_INET6, &ctx->from.sin6_addr,
1652 ctx->ntopbuf, INET6_ADDRSTRLEN);
1653 if ((size_t)len < sizeof(struct icmp6_hdr)) {
1654 logger(dctx, LOG_ERR, "IPv6 ICMP packet too short from %s",
1655 ctx->sfrom);
1656 return;
1657 }
1658
1659 pkt.ipi6_ifindex = 0;
1660 hoplimit = 0;
1661 for (cm = (struct cmsghdr *)CMSG_FIRSTHDR(&ctx->rcvhdr);
1662 cm;
1663 cm = (struct cmsghdr *)CMSG_NXTHDR(&ctx->rcvhdr, cm))
1664 {
1665 if (cm->cmsg_level != IPPROTO_IPV6)
1666 continue;
1667 switch(cm->cmsg_type) {
1668 case IPV6_PKTINFO:
1669 if (cm->cmsg_len == CMSG_LEN(sizeof(pkt)))
1670 memcpy(&pkt, CMSG_DATA(cm), sizeof(pkt));
1671 break;
1672 case IPV6_HOPLIMIT:
1673 if (cm->cmsg_len == CMSG_LEN(sizeof(int)))
1674 memcpy(&hoplimit, CMSG_DATA(cm), sizeof(int));
1675 break;
1676 }
1677 }
1678
1679 if (pkt.ipi6_ifindex == 0 || hoplimit == 0) {
1680 logger(dctx, LOG_ERR,
1681 "IPv6 RA/NA did not contain index or hop limit from %s",
1682 ctx->sfrom);
1683 return;
1684 }
1685
1686 TAILQ_FOREACH(ifp, dctx->ifaces, next) {
1687 if (ifp->index == (unsigned int)pkt.ipi6_ifindex &&
1688 !(ifp->options->options & DHCPCD_PFXDLGONLY))
1689 {
1690 if (!(ifp->options->options & DHCPCD_IPV6))
1691 return;
1692 break;
1693 }
1694 }
1695
1696 icp = (struct icmp6_hdr *)ctx->rcvhdr.msg_iov[0].iov_base;
1697 if (icp->icmp6_code == 0) {
1698 switch(icp->icmp6_type) {
1699 case ND_NEIGHBOR_ADVERT:
1700 ipv6nd_handlena(dctx, ifp, icp, (size_t)len);
1701 return;
1702 case ND_ROUTER_ADVERT:
1703 ipv6nd_handlera(dctx, ifp, icp, (size_t)len);
1704 return;
1705 }
1706 }
1707
1708 logger(dctx, LOG_ERR, "invalid IPv6 type %d or code %d from %s",
1709 icp->icmp6_type, icp->icmp6_code, ctx->sfrom);
1710}
1711
1712static void
1713ipv6nd_startrs1(void *arg)
1714{
1715 struct interface *ifp = arg;
1716 struct rs_state *state;
1717
1718 logger(ifp->ctx, LOG_INFO, "%s: soliciting an IPv6 router", ifp->name);
1719 if (ipv6nd_open(ifp->ctx) == -1) {
1720 logger(ifp->ctx, LOG_ERR, "%s: ipv6nd_open: %m", __func__);
1721 return;
1722 }
1723
1724 state = RS_STATE(ifp);
1725 if (state == NULL) {
1726 ifp->if_data[IF_DATA_IPV6ND] = calloc(1, sizeof(*state));
1727 state = RS_STATE(ifp);
1728 if (state == NULL) {
1729 logger(ifp->ctx, LOG_ERR, "%s: %m", __func__);
1730 return;
1731 }
1732 }
1733
1734 /* Always make a new probe as the underlying hardware
1735 * address could have changed. */
1736 ipv6nd_makersprobe(ifp);
1737 if (state->rs == NULL) {
1738 logger(ifp->ctx, LOG_ERR,
1739 "%s: ipv6ns_makersprobe: %m", __func__);
1740 return;
1741 }
1742
1743 state->rsprobes = 0;
1744 ipv6nd_sendrsprobe(ifp);
1745}
1746
1747void
1748ipv6nd_startrs(struct interface *ifp)
1749{
1750 struct timespec tv;
1751
1752 eloop_timeout_delete(ifp->ctx->eloop, NULL, ifp);
1753 tv.tv_sec = 0;
1754 tv.tv_nsec = (suseconds_t)arc4random_uniform(
1755 MAX_RTR_SOLICITATION_DELAY * NSEC_PER_SEC);
1756 timespecnorm(&tv);
1757 logger(ifp->ctx, LOG_DEBUG,
1758 "%s: delaying IPv6 router solicitation for %0.1f seconds",
1759 ifp->name, timespec_to_double(&tv));
1760 eloop_timeout_add_tv(ifp->ctx->eloop, &tv, ipv6nd_startrs1, ifp);
1761 return;
1762}