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