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