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