2 __RCSID("$NetBSD: ipv6nd.c,v 1.26 2015/08/21 10:39:00 roy Exp $");
5 * dhcpcd - DHCP client daemon
6 * Copyright (c) 2006-2015 Roy Marples <roy@marples.name>
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 #include <sys/ioctl.h>
32 #include <sys/param.h>
33 #include <sys/socket.h>
35 #include <net/route.h>
36 #include <netinet/in.h>
37 #include <netinet/ip6.h>
38 #include <netinet/icmp6.h>
57 /* Debugging Router Solicitations is a lot of spam, so disable it */
61 #define ND_OPT_RDNSS 25
62 struct nd_opt_rdnss
{ /* RDNSS option RFC 6106 */
63 uint8_t nd_opt_rdnss_type
;
64 uint8_t nd_opt_rdnss_len
;
65 uint16_t nd_opt_rdnss_reserved
;
66 uint32_t nd_opt_rdnss_lifetime
;
67 /* followed by list of IP prefixes */
72 #define ND_OPT_DNSSL 31
73 struct nd_opt_dnssl
{ /* DNSSL option RFC 6106 */
74 uint8_t nd_opt_dnssl_type
;
75 uint8_t nd_opt_dnssl_len
;
76 uint16_t nd_opt_dnssl_reserved
;
77 uint32_t nd_opt_dnssl_lifetime
;
78 /* followed by list of DNS servers */
82 /* Impossible options, so we can easily add extras */
83 #define _ND_OPT_PREFIX_ADDR 255 + 1
85 /* Minimal IPv6 MTU */
87 #define IPV6_MMTU 1280
90 #ifndef ND_RA_FLAG_RTPREF_HIGH
91 #define ND_RA_FLAG_RTPREF_MASK 0x18
92 #define ND_RA_FLAG_RTPREF_HIGH 0x08
93 #define ND_RA_FLAG_RTPREF_MEDIUM 0x00
94 #define ND_RA_FLAG_RTPREF_LOW 0x18
95 #define ND_RA_FLAG_RTPREF_RSV 0x10
98 /* RTPREF_MEDIUM has to be 0! */
100 #define RTPREF_MEDIUM 0
101 #define RTPREF_LOW (-1)
102 #define RTPREF_RESERVED (-2)
103 #define RTPREF_INVALID (-3) /* internal */
105 #define MIN_RANDOM_FACTOR 500 /* millisecs */
106 #define MAX_RANDOM_FACTOR 1500 /* millisecs */
107 #define MIN_RANDOM_FACTOR_U MIN_RANDOM_FACTOR * 1000 /* usecs */
108 #define MAX_RANDOM_FACTOR_U MAX_RANDOM_FACTOR * 1000 /* usecs */
110 #if BYTE_ORDER == BIG_ENDIAN
111 #define IPV6_ADDR_INT32_ONE 1
112 #define IPV6_ADDR_INT16_MLL 0xff02
113 #elif BYTE_ORDER == LITTLE_ENDIAN
114 #define IPV6_ADDR_INT32_ONE 0x01000000
115 #define IPV6_ADDR_INT16_MLL 0x02ff
118 /* Debugging Neighbor Solicitations is a lot of spam, so disable it */
122 static void ipv6nd_handledata(void *);
125 * Android ships buggy ICMP6 filter headers.
126 * Supply our own until they fix their shit.
128 * https://android-review.googlesource.com/#/c/58438/
129 * http://code.google.com/p/android/issues/original?id=32621&seq=24
132 #undef ICMP6_FILTER_WILLPASS
133 #undef ICMP6_FILTER_WILLBLOCK
134 #undef ICMP6_FILTER_SETPASS
135 #undef ICMP6_FILTER_SETBLOCK
136 #undef ICMP6_FILTER_SETPASSALL
137 #undef ICMP6_FILTER_SETBLOCKALL
138 #define ICMP6_FILTER_WILLPASS(type, filterp) \
139 ((((filterp)->icmp6_filt[(type) >> 5]) & (1 << ((type) & 31))) == 0)
140 #define ICMP6_FILTER_WILLBLOCK(type, filterp) \
141 ((((filterp)->icmp6_filt[(type) >> 5]) & (1 << ((type) & 31))) != 0)
142 #define ICMP6_FILTER_SETPASS(type, filterp) \
143 ((((filterp)->icmp6_filt[(type) >> 5]) &= ~(1 << ((type) & 31))))
144 #define ICMP6_FILTER_SETBLOCK(type, filterp) \
145 ((((filterp)->icmp6_filt[(type) >> 5]) |= (1 << ((type) & 31))))
146 #define ICMP6_FILTER_SETPASSALL(filterp) \
147 memset(filterp, 0, sizeof(struct icmp6_filter));
148 #define ICMP6_FILTER_SETBLOCKALL(filterp) \
149 memset(filterp, 0xff, sizeof(struct icmp6_filter));
152 /* Support older systems with different defines */
153 #if !defined(IPV6_RECVHOPLIMIT) && defined(IPV6_HOPLIMIT)
154 #define IPV6_RECVHOPLIMIT IPV6_HOPLIMIT
156 #if !defined(IPV6_RECVPKTINFO) && defined(IPV6_PKTINFO)
157 #define IPV6_RECVPKTINFO IPV6_PKTINFO
161 ipv6nd_printoptions(const struct dhcpcd_ctx
*ctx
,
162 const struct dhcp_opt
*opts
, size_t opts_len
)
165 const struct dhcp_opt
*opt
, *opt2
;
168 for (i
= 0, opt
= ctx
->nd_opts
;
169 i
< ctx
->nd_opts_len
; i
++, opt
++)
171 for (j
= 0, opt2
= opts
; j
< opts_len
; j
++, opt2
++)
172 if (opt2
->option
== opt
->option
)
175 cols
= printf("%03d %s", opt
->option
, opt
->var
);
176 dhcp_print_option_encoding(opt
, cols
);
179 for (i
= 0, opt
= opts
; i
< opts_len
; i
++, opt
++) {
180 cols
= printf("%03d %s", opt
->option
, opt
->var
);
181 dhcp_print_option_encoding(opt
, cols
);
186 ipv6nd_open(struct dhcpcd_ctx
*dctx
)
188 struct ipv6_ctx
*ctx
;
190 struct icmp6_filter filt
;
193 if (ctx
->nd_fd
!= -1)
195 ctx
->nd_fd
= xsocket(PF_INET6
, SOCK_RAW
, IPPROTO_ICMPV6
,
196 O_NONBLOCK
|O_CLOEXEC
);
197 if (ctx
->nd_fd
== -1)
202 if (setsockopt(ctx
->nd_fd
, IPPROTO_IPV6
, IPV6_MULTICAST_HOPS
,
203 &on
, sizeof(on
)) == -1)
207 if (setsockopt(ctx
->nd_fd
, IPPROTO_IPV6
, IPV6_RECVPKTINFO
,
208 &on
, sizeof(on
)) == -1)
212 if (setsockopt(ctx
->nd_fd
, IPPROTO_IPV6
, IPV6_RECVHOPLIMIT
,
213 &on
, sizeof(on
)) == -1)
216 ICMP6_FILTER_SETBLOCKALL(&filt
);
217 ICMP6_FILTER_SETPASS(ND_NEIGHBOR_ADVERT
, &filt
);
218 ICMP6_FILTER_SETPASS(ND_ROUTER_ADVERT
, &filt
);
219 if (setsockopt(ctx
->nd_fd
, IPPROTO_ICMPV6
, ICMP6_FILTER
,
220 &filt
, sizeof(filt
)) == -1)
223 eloop_event_add(dctx
->eloop
, ctx
->nd_fd
,
224 ipv6nd_handledata
, dctx
, NULL
, NULL
);
228 if (ctx
->nd_fd
!= -1) {
229 eloop_event_delete(dctx
->eloop
, ctx
->nd_fd
);
237 ipv6nd_makersprobe(struct interface
*ifp
)
239 struct rs_state
*state
;
240 struct nd_router_solicit
*rs
;
241 struct nd_opt_hdr
*nd
;
243 state
= RS_STATE(ifp
);
245 state
->rslen
= sizeof(*rs
) + (size_t)ROUNDUP8(ifp
->hwlen
+ 2);
246 state
->rs
= calloc(1, state
->rslen
);
247 if (state
->rs
== NULL
)
249 rs
= (struct nd_router_solicit
*)(void *)state
->rs
;
250 rs
->nd_rs_type
= ND_ROUTER_SOLICIT
;
253 rs
->nd_rs_reserved
= 0;
254 nd
= (struct nd_opt_hdr
*)(state
->rs
+ sizeof(*rs
));
255 nd
->nd_opt_type
= ND_OPT_SOURCE_LINKADDR
;
256 nd
->nd_opt_len
= (uint8_t)((ROUNDUP8(ifp
->hwlen
+ 2)) >> 3);
257 memcpy(nd
+ 1, ifp
->hwaddr
, ifp
->hwlen
);
262 ipv6nd_sendrsprobe(void *arg
)
264 struct interface
*ifp
= arg
;
265 struct ipv6_ctx
*ctx
;
266 struct rs_state
*state
;
267 struct sockaddr_in6 dst
;
269 struct in6_pktinfo pi
;
271 if (ipv6_linklocal(ifp
) == NULL
) {
272 logger(ifp
->ctx
, LOG_DEBUG
,
273 "%s: delaying Router Solicitation for LL address",
275 ipv6_addlinklocalcallback(ifp
, ipv6nd_sendrsprobe
, ifp
);
279 memset(&dst
, 0, sizeof(dst
));
280 dst
.sin6_family
= AF_INET6
;
282 dst
.sin6_len
= sizeof(dst
);
284 dst
.sin6_scope_id
= ifp
->index
;
285 if (inet_pton(AF_INET6
, ALLROUTERS
, &dst
.sin6_addr
) != 1) {
286 logger(ifp
->ctx
, LOG_ERR
, "%s: %m", __func__
);
290 state
= RS_STATE(ifp
);
291 ctx
= ifp
->ctx
->ipv6
;
292 ctx
->sndhdr
.msg_name
= (void *)&dst
;
293 ctx
->sndhdr
.msg_iov
[0].iov_base
= state
->rs
;
294 ctx
->sndhdr
.msg_iov
[0].iov_len
= state
->rslen
;
296 /* Set the outbound interface */
297 cm
= CMSG_FIRSTHDR(&ctx
->sndhdr
);
298 if (cm
== NULL
) /* unlikely */
300 cm
->cmsg_level
= IPPROTO_IPV6
;
301 cm
->cmsg_type
= IPV6_PKTINFO
;
302 cm
->cmsg_len
= CMSG_LEN(sizeof(pi
));
303 memset(&pi
, 0, sizeof(pi
));
304 pi
.ipi6_ifindex
= ifp
->index
;
305 memcpy(CMSG_DATA(cm
), &pi
, sizeof(pi
));
307 logger(ifp
->ctx
, LOG_DEBUG
,
308 "%s: sending Router Solicitation", ifp
->name
);
309 if (sendmsg(ctx
->nd_fd
, &ctx
->sndhdr
, 0) == -1) {
310 logger(ifp
->ctx
, LOG_ERR
,
311 "%s: %s: sendmsg: %m", ifp
->name
, __func__
);
313 ifp
->options
->options
&= ~(DHCPCD_IPV6
| DHCPCD_IPV6RS
);
317 if (state
->rsprobes
++ < MAX_RTR_SOLICITATIONS
)
318 eloop_timeout_add_sec(ifp
->ctx
->eloop
,
319 RTR_SOLICITATION_INTERVAL
, ipv6nd_sendrsprobe
, ifp
);
321 logger(ifp
->ctx
, LOG_WARNING
,
322 "%s: no IPv6 Routers available", ifp
->name
);
324 dhcp6_drop(ifp
, "EXPIRE6");
329 ipv6nd_expire(struct interface
*ifp
, uint32_t seconds
)
334 if (ifp
->ctx
->ipv6
== NULL
)
337 clock_gettime(CLOCK_MONOTONIC
, &now
);
339 TAILQ_FOREACH(rap
, ifp
->ctx
->ipv6
->ra_routers
, next
) {
340 if (rap
->iface
== ifp
) {
342 rap
->expired
= seconds
? 0 : 1;
344 struct ipv6_addr
*ap
;
346 rap
->lifetime
= seconds
;
347 TAILQ_FOREACH(ap
, &rap
->addrs
, next
) {
348 if (ap
->prefix_vltime
) {
349 ap
->prefix_vltime
= seconds
;
350 ap
->prefix_pltime
= seconds
/ 2;
353 ipv6_addaddrs(&rap
->addrs
);
358 ipv6nd_expirera(ifp
);
360 ipv6_buildroutes(ifp
->ctx
);
364 ipv6nd_reachable(struct ra
*rap
, int flags
)
367 if (flags
& IPV6ND_REACHABLE
) {
368 if (rap
->lifetime
&& rap
->expired
) {
369 logger(rap
->iface
->ctx
, LOG_INFO
,
370 "%s: %s is reachable again",
371 rap
->iface
->name
, rap
->sfrom
);
373 ipv6_buildroutes(rap
->iface
->ctx
);
374 /* XXX Not really an RA */
375 script_runreason(rap
->iface
, "ROUTERADVERT");
378 if (rap
->lifetime
&& !rap
->expired
) {
379 logger(rap
->iface
->ctx
, LOG_WARNING
,
380 "%s: %s is unreachable, expiring it",
381 rap
->iface
->name
, rap
->sfrom
);
383 ipv6_buildroutes(rap
->iface
->ctx
);
384 /* XXX Not really an RA */
385 script_runreason(rap
->iface
, "ROUTERADVERT");
391 ipv6nd_neighbour(struct dhcpcd_ctx
*ctx
, struct in6_addr
*addr
, int flags
)
396 TAILQ_FOREACH(rap
, ctx
->ipv6
->ra_routers
, next
) {
397 if (IN6_ARE_ADDR_EQUAL(&rap
->from
, addr
)) {
398 ipv6nd_reachable(rap
, flags
);
405 const struct ipv6_addr
*
406 ipv6nd_iffindaddr(const struct interface
*ifp
, const struct in6_addr
*addr
,
410 struct ipv6_addr
*ap
;
412 if (ifp
->ctx
->ipv6
== NULL
)
415 TAILQ_FOREACH(rap
, ifp
->ctx
->ipv6
->ra_routers
, next
) {
416 if (rap
->iface
!= ifp
)
418 TAILQ_FOREACH(ap
, &rap
->addrs
, next
) {
419 if (ipv6_findaddrmatch(ap
, addr
, flags
))
427 ipv6nd_findaddr(struct dhcpcd_ctx
*ctx
, const struct in6_addr
*addr
,
431 struct ipv6_addr
*ap
;
433 if (ctx
->ipv6
== NULL
)
436 TAILQ_FOREACH(rap
, ctx
->ipv6
->ra_routers
, next
) {
437 TAILQ_FOREACH(ap
, &rap
->addrs
, next
) {
438 if (ipv6_findaddrmatch(ap
, addr
, flags
))
446 ipv6nd_removefreedrop_ra(struct ra
*rap
, int remove_ra
, int drop_ra
)
449 eloop_timeout_delete(rap
->iface
->ctx
->eloop
, NULL
, rap
->iface
);
450 eloop_timeout_delete(rap
->iface
->ctx
->eloop
, NULL
, rap
);
451 if (remove_ra
&& !drop_ra
)
452 TAILQ_REMOVE(rap
->iface
->ctx
->ipv6
->ra_routers
, rap
, next
);
453 ipv6_freedrop_addrs(&rap
->addrs
, drop_ra
, NULL
);
459 ipv6nd_freedrop_ra(struct ra
*rap
, int drop
)
462 ipv6nd_removefreedrop_ra(rap
, 1, drop
);
466 ipv6nd_free(struct interface
*ifp
)
468 struct rs_state
*state
;
469 struct ra
*rap
, *ran
;
470 struct dhcpcd_ctx
*ctx
;
473 state
= RS_STATE(ifp
);
479 ifp
->if_data
[IF_DATA_IPV6ND
] = NULL
;
481 TAILQ_FOREACH_SAFE(rap
, ifp
->ctx
->ipv6
->ra_routers
, next
, ran
) {
482 if (rap
->iface
== ifp
) {
488 /* If we don't have any more IPv6 enabled interfaces,
489 * close the global socket and release resources */
491 TAILQ_FOREACH(ifp
, ctx
->ifaces
, next
) {
496 if (ctx
->ipv6
->nd_fd
!= -1) {
497 eloop_event_delete(ctx
->eloop
, ctx
->ipv6
->nd_fd
);
498 close(ctx
->ipv6
->nd_fd
);
499 ctx
->ipv6
->nd_fd
= -1;
507 rtpref(struct ra
*rap
)
510 switch (rap
->flags
& ND_RA_FLAG_RTPREF_MASK
) {
511 case ND_RA_FLAG_RTPREF_HIGH
:
512 return (RTPREF_HIGH
);
513 case ND_RA_FLAG_RTPREF_MEDIUM
:
514 case ND_RA_FLAG_RTPREF_RSV
:
515 return (RTPREF_MEDIUM
);
516 case ND_RA_FLAG_RTPREF_LOW
:
519 logger(rap
->iface
->ctx
, LOG_ERR
,
520 "rtpref: impossible RA flag %x", rap
->flags
);
521 return (RTPREF_INVALID
);
527 add_router(struct ipv6_ctx
*ctx
, struct ra
*router
)
531 TAILQ_FOREACH(rap
, ctx
->ra_routers
, next
) {
532 if (router
->iface
->metric
< rap
->iface
->metric
||
533 (router
->iface
->metric
== rap
->iface
->metric
&&
534 rtpref(router
) > rtpref(rap
)))
536 TAILQ_INSERT_BEFORE(rap
, router
, next
);
540 TAILQ_INSERT_TAIL(ctx
->ra_routers
, router
, next
);
544 ipv6nd_scriptrun(struct ra
*rap
)
546 int hasdns
, hasaddress
, pid
;
547 struct ipv6_addr
*ap
;
550 /* If all addresses have completed DAD run the script */
551 TAILQ_FOREACH(ap
, &rap
->addrs
, next
) {
552 if ((ap
->flags
& (IPV6_AF_AUTOCONF
| IPV6_AF_ADDED
)) ==
553 (IPV6_AF_AUTOCONF
| IPV6_AF_ADDED
))
556 if (!(ap
->flags
& IPV6_AF_DADCOMPLETED
) &&
557 ipv6_iffindaddr(ap
->iface
, &ap
->addr
))
558 ap
->flags
|= IPV6_AF_DADCOMPLETED
;
559 if ((ap
->flags
& IPV6_AF_DADCOMPLETED
) == 0) {
560 logger(ap
->iface
->ctx
, LOG_DEBUG
,
561 "%s: waiting for Router Advertisement"
569 /* If we don't require RDNSS then set hasdns = 1 so we fork */
570 if (!(rap
->iface
->options
->options
& DHCPCD_IPV6RA_REQRDNSS
))
573 hasdns
= rap
->hasdns
;
576 script_runreason(rap
->iface
, "ROUTERADVERT");
578 if (hasdns
&& (hasaddress
||
579 !(rap
->flags
& (ND_RA_FLAG_MANAGED
| ND_RA_FLAG_OTHER
))))
580 pid
= dhcpcd_daemonise(rap
->iface
->ctx
);
582 else if (options
& DHCPCD_DAEMONISE
&&
583 !(options
& DHCPCD_DAEMONISED
) && new_data
)
584 logger(rap
->iface
->ctx
, LOG_WARNING
,
585 "%s: did not fork due to an absent"
586 " RDNSS option in the RA",
594 ipv6nd_addaddr(void *arg
)
596 struct ipv6_addr
*ap
= arg
;
598 ipv6_addaddr(ap
, NULL
);
602 ipv6nd_dadcompleted(const struct interface
*ifp
)
604 const struct ra
*rap
;
605 const struct ipv6_addr
*ap
;
607 TAILQ_FOREACH(rap
, ifp
->ctx
->ipv6
->ra_routers
, next
) {
608 if (rap
->iface
!= ifp
)
610 TAILQ_FOREACH(ap
, &rap
->addrs
, next
) {
611 if (ap
->flags
& IPV6_AF_AUTOCONF
&&
612 ap
->flags
& IPV6_AF_ADDED
&&
613 !(ap
->flags
& IPV6_AF_DADCOMPLETED
))
621 ipv6nd_dadcallback(void *arg
)
623 struct ipv6_addr
*ap
= arg
, *rapap
;
624 struct interface
*ifp
;
626 int wascompleted
, found
;
628 char buf
[INET6_ADDRSTRLEN
];
633 wascompleted
= (ap
->flags
& IPV6_AF_DADCOMPLETED
);
634 ap
->flags
|= IPV6_AF_DADCOMPLETED
;
635 if (ap
->flags
& IPV6_AF_DUPLICATED
) {
637 logger(ifp
->ctx
, LOG_WARNING
, "%s: DAD detected %s",
638 ifp
->name
, ap
->saddr
);
640 /* Try and make another stable private address.
641 * Because ap->dadcounter is always increamented,
642 * a different address is generated. */
643 /* XXX Cache DAD counter per prefix/id/ssid? */
644 if (ifp
->options
->options
& DHCPCD_SLAACPRIVATE
) {
645 if (ap
->dadcounter
>= IDGEN_RETRIES
) {
646 logger(ifp
->ctx
, LOG_ERR
,
647 "%s: unable to obtain a"
648 " stable private address",
652 logger(ifp
->ctx
, LOG_INFO
, "%s: deleting address %s",
653 ifp
->name
, ap
->saddr
);
654 if (if_deladdress6(ap
) == -1 &&
655 errno
!= EADDRNOTAVAIL
&& errno
!= ENXIO
)
656 logger(ifp
->ctx
, LOG_ERR
, "if_deladdress6: %m");
657 dadcounter
= ap
->dadcounter
;
658 if (ipv6_makestableprivate(&ap
->addr
,
659 &ap
->prefix
, ap
->prefix_len
,
660 ifp
, &dadcounter
) == -1)
662 logger(ifp
->ctx
, LOG_ERR
,
663 "%s: ipv6_makestableprivate: %m",
667 ap
->dadcounter
= dadcounter
;
668 ap
->flags
&= ~(IPV6_AF_ADDED
| IPV6_AF_DADCOMPLETED
);
669 ap
->flags
|= IPV6_AF_NEW
;
670 p
= inet_ntop(AF_INET6
, &ap
->addr
, buf
, sizeof(buf
));
679 tv
.tv_nsec
= (suseconds_t
)
680 arc4random_uniform(IDGEN_DELAY
* NSEC_PER_SEC
);
682 eloop_timeout_add_tv(ifp
->ctx
->eloop
, &tv
,
690 TAILQ_FOREACH(rap
, ifp
->ctx
->ipv6
->ra_routers
, next
) {
691 if (rap
->iface
!= ifp
)
695 TAILQ_FOREACH(rapap
, &rap
->addrs
, next
) {
696 if (rapap
->flags
& IPV6_AF_AUTOCONF
&&
697 rapap
->flags
& IPV6_AF_ADDED
&&
698 (rapap
->flags
& IPV6_AF_DADCOMPLETED
) == 0)
707 if (wascompleted
&& found
) {
708 logger(rap
->iface
->ctx
, LOG_DEBUG
,
709 "%s: Router Advertisement DAD completed",
711 if (ipv6nd_scriptrun(rap
))
719 ipv6nd_has_public_addr(const struct interface
*ifp
)
721 const struct ra
*rap
;
722 const struct ipv6_addr
*ia
;
724 TAILQ_FOREACH(rap
, ifp
->ctx
->ipv6
->ra_routers
, next
) {
725 if (rap
->iface
== ifp
) {
726 TAILQ_FOREACH(ia
, &rap
->addrs
, next
) {
727 if (ia
->flags
& IPV6_AF_AUTOCONF
&&
737 ipv6nd_handlera(struct dhcpcd_ctx
*dctx
, struct interface
*ifp
,
738 struct icmp6_hdr
*icp
, size_t len
, int hoplimit
)
740 struct ipv6_ctx
*ctx
= dctx
->ipv6
;
742 struct nd_router_advert
*nd_ra
;
743 struct nd_opt_prefix_info
*pi
;
744 struct nd_opt_mtu
*mtu
;
745 struct nd_opt_rdnss
*rdnss
;
748 char buf
[INET6_ADDRSTRLEN
];
751 struct nd_opt_hdr
*ndo
;
752 struct ipv6_addr
*ap
;
753 struct dhcp_opt
*dho
;
754 uint8_t new_rap
, new_data
;
755 #ifdef IPV6_MANAGETEMPADDR
761 logger(dctx
, LOG_DEBUG
,
762 "RA for unexpected interface from %s", ctx
->sfrom
);
767 if (len
< sizeof(struct nd_router_advert
)) {
768 logger(dctx
, LOG_ERR
,
769 "IPv6 RA packet too short from %s", ctx
->sfrom
);
774 if (hoplimit
!= 255) {
775 logger(dctx
, LOG_ERR
,
776 "invalid hoplimit(%d) in RA from %s", hoplimit
, ctx
->sfrom
);
780 if (!IN6_IS_ADDR_LINKLOCAL(&ctx
->from
.sin6_addr
)) {
781 logger(dctx
, LOG_ERR
,
782 "RA from non local address %s", ctx
->sfrom
);
786 if (!(ifp
->options
->options
& DHCPCD_IPV6RS
)) {
788 logger(ifp
->ctx
, LOG_DEBUG
, "%s: unexpected RA from %s",
789 ifp
->name
, ctx
->sfrom
);
794 /* We could receive a RA before we sent a RS*/
795 if (ipv6_linklocal(ifp
) == NULL
) {
797 logger(ifp
->ctx
, LOG_DEBUG
,
798 "%s: received RA from %s (no link-local)",
799 ifp
->name
, ctx
->sfrom
);
804 if (ipv6_iffindaddr(ifp
, &ctx
->from
.sin6_addr
)) {
805 logger(ifp
->ctx
, LOG_DEBUG
,
806 "%s: ignoring RA from ourself %s", ifp
->name
, ctx
->sfrom
);
810 TAILQ_FOREACH(rap
, ctx
->ra_routers
, next
) {
811 if (ifp
== rap
->iface
&&
812 IN6_ARE_ADDR_EQUAL(&rap
->from
, &ctx
->from
.sin6_addr
))
816 nd_ra
= (struct nd_router_advert
*)icp
;
818 /* We don't want to spam the log with the fact we got an RA every
819 * 30 seconds or so, so only spam the log if it's different. */
820 if (rap
== NULL
|| (rap
->data_len
!= len
||
821 memcmp(rap
->data
, (unsigned char *)icp
, rap
->data_len
) != 0))
826 rap
->no_public_warned
= 0;
831 if (new_data
|| ifp
->options
->options
& DHCPCD_DEBUG
)
832 logger(ifp
->ctx
, LOG_INFO
, "%s: Router Advertisement from %s",
833 ifp
->name
, ctx
->sfrom
);
836 rap
= calloc(1, sizeof(*rap
));
838 logger(ifp
->ctx
, LOG_ERR
, "%s: %m", __func__
);
842 rap
->from
= ctx
->from
.sin6_addr
;
843 strlcpy(rap
->sfrom
, ctx
->sfrom
, sizeof(rap
->sfrom
));
844 TAILQ_INIT(&rap
->addrs
);
848 if (rap
->data_len
== 0) {
849 rap
->data
= malloc(len
);
850 if (rap
->data
== NULL
) {
851 logger(ifp
->ctx
, LOG_ERR
, "%s: %m", __func__
);
856 memcpy(rap
->data
, icp
, len
);
860 clock_gettime(CLOCK_MONOTONIC
, &rap
->acquired
);
861 rap
->flags
= nd_ra
->nd_ra_flags_reserved
;
862 rap
->lifetime
= ntohs(nd_ra
->nd_ra_router_lifetime
);
863 if (nd_ra
->nd_ra_reachable
) {
864 rap
->reachable
= ntohl(nd_ra
->nd_ra_reachable
);
865 if (rap
->reachable
> MAX_REACHABLE_TIME
)
868 if (nd_ra
->nd_ra_retransmit
)
869 rap
->retrans
= ntohl(nd_ra
->nd_ra_retransmit
);
874 ipv6_settempstale(ifp
);
875 TAILQ_FOREACH(ap
, &rap
->addrs
, next
) {
876 ap
->flags
|= IPV6_AF_STALE
;
879 len
-= sizeof(struct nd_router_advert
);
880 p
= ((uint8_t *)icp
) + sizeof(struct nd_router_advert
);
881 for (; len
> 0; p
+= olen
, len
-= olen
) {
882 if (len
< sizeof(struct nd_opt_hdr
)) {
883 logger(ifp
->ctx
, LOG_ERR
,
884 "%s: short option", ifp
->name
);
887 ndo
= (struct nd_opt_hdr
*)p
;
888 olen
= (size_t)ndo
->nd_opt_len
* 8;
890 logger(ifp
->ctx
, LOG_ERR
,
891 "%s: zero length option", ifp
->name
);
895 logger(ifp
->ctx
, LOG_ERR
,
896 "%s: option length exceeds message", ifp
->name
);
900 if (has_option_mask(ifp
->options
->rejectmasknd
,
903 for (i
= 0, dho
= dctx
->nd_opts
;
904 i
< dctx
->nd_opts_len
;
907 if (dho
->option
== ndo
->nd_opt_type
)
911 logger(ifp
->ctx
, LOG_WARNING
,
912 "%s: reject RA (option %s) from %s",
913 ifp
->name
, dho
->var
, ctx
->sfrom
);
915 logger(ifp
->ctx
, LOG_WARNING
,
916 "%s: reject RA (option %d) from %s",
917 ifp
->name
, ndo
->nd_opt_type
, ctx
->sfrom
);
919 ipv6nd_removefreedrop_ra(rap
, 0, 0);
925 if (has_option_mask(ifp
->options
->nomasknd
, ndo
->nd_opt_type
))
928 switch (ndo
->nd_opt_type
) {
929 case ND_OPT_PREFIX_INFORMATION
:
930 pi
= (struct nd_opt_prefix_info
*)(void *)ndo
;
931 if (pi
->nd_opt_pi_len
!= 4) {
932 logger(ifp
->ctx
, new_data
? LOG_ERR
: LOG_DEBUG
,
933 "%s: invalid option len for prefix",
937 if (pi
->nd_opt_pi_prefix_len
> 128) {
938 logger(ifp
->ctx
, new_data
? LOG_ERR
: LOG_DEBUG
,
939 "%s: invalid prefix len",
943 if (IN6_IS_ADDR_MULTICAST(&pi
->nd_opt_pi_prefix
) ||
944 IN6_IS_ADDR_LINKLOCAL(&pi
->nd_opt_pi_prefix
))
946 logger(ifp
->ctx
, new_data
? LOG_ERR
: LOG_DEBUG
,
947 "%s: invalid prefix in RA", ifp
->name
);
950 if (ntohl(pi
->nd_opt_pi_preferred_time
) >
951 ntohl(pi
->nd_opt_pi_valid_time
))
953 logger(ifp
->ctx
, new_data
? LOG_ERR
: LOG_DEBUG
,
954 "%s: pltime > vltime", ifp
->name
);
957 TAILQ_FOREACH(ap
, &rap
->addrs
, next
)
958 if (ap
->prefix_len
==pi
->nd_opt_pi_prefix_len
&&
959 IN6_ARE_ADDR_EQUAL(&ap
->prefix
,
960 &pi
->nd_opt_pi_prefix
))
963 if (!(pi
->nd_opt_pi_flags_reserved
&
964 ND_OPT_PI_FLAG_AUTO
) &&
965 !(pi
->nd_opt_pi_flags_reserved
&
966 ND_OPT_PI_FLAG_ONLINK
))
968 ap
= calloc(1, sizeof(*ap
));
971 ap
->iface
= rap
->iface
;
972 ap
->flags
= IPV6_AF_NEW
;
973 ap
->prefix_len
= pi
->nd_opt_pi_prefix_len
;
974 ap
->prefix
= pi
->nd_opt_pi_prefix
;
975 if (pi
->nd_opt_pi_flags_reserved
&
976 ND_OPT_PI_FLAG_AUTO
&&
977 ap
->iface
->options
->options
&
978 DHCPCD_IPV6RA_AUTOCONF
)
980 ap
->flags
|= IPV6_AF_AUTOCONF
;
982 ipv6_makeaddr(&ap
->addr
, ifp
,
984 pi
->nd_opt_pi_prefix_len
);
985 if (ap
->dadcounter
== -1) {
989 cbp
= inet_ntop(AF_INET6
,
996 cbp
, ap
->prefix_len
);
1000 memset(&ap
->addr
, 0, sizeof(ap
->addr
));
1001 ap
->saddr
[0] = '\0';
1003 ap
->dadcallback
= ipv6nd_dadcallback
;
1004 ap
->created
= ap
->acquired
= rap
->acquired
;
1005 TAILQ_INSERT_TAIL(&rap
->addrs
, ap
, next
);
1007 #ifdef IPV6_MANAGETEMPADDR
1008 /* New address to dhcpcd RA handling.
1009 * If the address already exists and a valid
1010 * temporary address also exists then
1011 * extend the existing one rather than
1012 * create a new one */
1013 if (ipv6_iffindaddr(ifp
, &ap
->addr
) &&
1014 ipv6_settemptime(ap
, 0))
1020 #ifdef IPV6_MANAGETEMPADDR
1023 ap
->flags
&= ~IPV6_AF_STALE
;
1024 ap
->acquired
= rap
->acquired
;
1026 if (pi
->nd_opt_pi_flags_reserved
&
1027 ND_OPT_PI_FLAG_ONLINK
)
1028 ap
->flags
|= IPV6_AF_ONLINK
;
1030 ntohl(pi
->nd_opt_pi_valid_time
);
1032 ntohl(pi
->nd_opt_pi_preferred_time
);
1035 #ifdef IPV6_MANAGETEMPADDR
1036 /* RFC4941 Section 3.3.3 */
1037 if (ap
->flags
& IPV6_AF_AUTOCONF
&&
1038 ap
->iface
->options
->options
& DHCPCD_IPV6RA_OWN
&&
1039 ip6_use_tempaddr(ap
->iface
->name
))
1042 if (ipv6_settemptime(ap
, 1) == NULL
)
1045 if (new_ap
&& ap
->prefix_pltime
) {
1046 if (ipv6_createtempaddr(ap
,
1047 &ap
->acquired
) == NULL
)
1048 logger(ap
->iface
->ctx
, LOG_ERR
,
1049 "ipv6_createtempaddr: %m");
1056 mtu
= (struct nd_opt_mtu
*)(void *)p
;
1057 mtuv
= ntohl(mtu
->nd_opt_mtu_mtu
);
1058 if (mtuv
< IPV6_MMTU
) {
1059 logger(ifp
->ctx
, LOG_ERR
, "%s: invalid MTU %d",
1067 rdnss
= (struct nd_opt_rdnss
*)(void *)p
;
1068 if (rdnss
->nd_opt_rdnss_lifetime
&&
1069 rdnss
->nd_opt_rdnss_len
> 1)
1077 for (i
= 0, dho
= dctx
->nd_opts
;
1078 i
< dctx
->nd_opts_len
;
1081 if (has_option_mask(ifp
->options
->requiremasknd
,
1084 logger(ifp
->ctx
, LOG_WARNING
,
1085 "%s: reject RA (no option %s) from %s",
1086 ifp
->name
, dho
->var
, ctx
->sfrom
);
1088 ipv6nd_removefreedrop_ra(rap
, 0, 0);
1090 ipv6nd_free_ra(rap
);
1096 add_router(ifp
->ctx
->ipv6
, rap
);
1098 if (!ipv6nd_has_public_addr(rap
->iface
) &&
1099 !(rap
->iface
->options
->options
& DHCPCD_IPV6RA_ACCEPT_NOPUBLIC
) &&
1100 (!(rap
->flags
& ND_RA_FLAG_MANAGED
) ||
1101 !dhcp6_has_public_addr(rap
->iface
)))
1103 logger(rap
->iface
->ctx
,
1104 rap
->no_public_warned
? LOG_DEBUG
: LOG_WARNING
,
1105 "%s: ignoring RA from %s"
1106 " (no public prefix, no managed address)",
1107 rap
->iface
->name
, rap
->sfrom
);
1108 rap
->no_public_warned
= 1;
1111 if (ifp
->ctx
->options
& DHCPCD_TEST
) {
1112 script_runreason(ifp
, "TEST");
1115 ipv6_addaddrs(&rap
->addrs
);
1116 #ifdef IPV6_MANAGETEMPADDR
1117 ipv6_addtempaddrs(ifp
, &rap
->acquired
);
1120 /* Find any freshly added routes, such as the subnet route.
1121 * We do this because we cannot rely on recieving the kernel
1122 * notification right now via our link socket. */
1125 ipv6_buildroutes(ifp
->ctx
);
1126 if (ipv6nd_scriptrun(rap
))
1129 eloop_timeout_delete(ifp
->ctx
->eloop
, NULL
, ifp
);
1130 eloop_timeout_delete(ifp
->ctx
->eloop
, NULL
, rap
); /* reachable timer */
1133 if (!(ifp
->options
->options
& DHCPCD_DHCP6
))
1135 if (rap
->flags
& ND_RA_FLAG_MANAGED
) {
1136 if (new_data
&& dhcp6_start(ifp
, DH6S_INIT
) == -1)
1137 logger(ifp
->ctx
, LOG_ERR
,
1138 "dhcp6_start: %s: %m", ifp
->name
);
1139 } else if (rap
->flags
& ND_RA_FLAG_OTHER
) {
1140 if (new_data
&& dhcp6_start(ifp
, DH6S_INFORM
) == -1)
1141 logger(ifp
->ctx
, LOG_ERR
,
1142 "dhcp6_start: %s: %m", ifp
->name
);
1145 logger(ifp
->ctx
, LOG_DEBUG
,
1146 "%s: No DHCPv6 instruction in RA", ifp
->name
);
1148 if (ifp
->ctx
->options
& DHCPCD_TEST
) {
1149 eloop_exit(ifp
->ctx
->eloop
, EXIT_SUCCESS
);
1154 /* Expire should be called last as the rap object could be destroyed */
1155 ipv6nd_expirera(ifp
);
1158 /* Run RA's we ignored becuase they had no public addresses
1159 * This should only be called when DHCPv6 applies a public address */
1161 ipv6nd_runignoredra(struct interface
*ifp
)
1165 TAILQ_FOREACH(rap
, ifp
->ctx
->ipv6
->ra_routers
, next
) {
1166 if (rap
->iface
== ifp
&&
1168 rap
->no_public_warned
)
1170 rap
->no_public_warned
= 0;
1171 logger(rap
->iface
->ctx
, LOG_INFO
,
1172 "%s: applying ignored RA from %s",
1173 rap
->iface
->name
, rap
->sfrom
);
1174 if (ifp
->ctx
->options
& DHCPCD_TEST
) {
1175 script_runreason(ifp
, "TEST");
1178 if (ipv6nd_scriptrun(rap
))
1180 eloop_timeout_delete(ifp
->ctx
->eloop
, NULL
, ifp
);
1181 eloop_timeout_delete(ifp
->ctx
->eloop
, NULL
, rap
);
1187 ipv6nd_hasra(const struct interface
*ifp
)
1189 const struct ra
*rap
;
1191 if (ifp
->ctx
->ipv6
) {
1192 TAILQ_FOREACH(rap
, ifp
->ctx
->ipv6
->ra_routers
, next
)
1193 if (rap
->iface
== ifp
&& !rap
->expired
)
1200 ipv6nd_hasradhcp(const struct interface
*ifp
)
1202 const struct ra
*rap
;
1204 if (ifp
->ctx
->ipv6
) {
1205 TAILQ_FOREACH(rap
, ifp
->ctx
->ipv6
->ra_routers
, next
) {
1206 if (rap
->iface
== ifp
&&
1208 (rap
->flags
& (ND_RA_FLAG_MANAGED
| ND_RA_FLAG_OTHER
)))
1215 static const uint8_t *
1216 ipv6nd_getoption(struct dhcpcd_ctx
*ctx
,
1217 size_t *os
, unsigned int *code
, size_t *len
,
1218 const uint8_t *od
, size_t ol
, struct dhcp_opt
**oopt
)
1220 const struct nd_opt_hdr
*o
;
1222 struct dhcp_opt
*opt
;
1230 o
= (const struct nd_opt_hdr
*)od
;
1231 if (o
->nd_opt_len
> ol
) {
1235 *len
= ND_OPTION_LEN(o
);
1236 *code
= o
->nd_opt_type
;
1240 for (i
= 0, opt
= ctx
->nd_opts
;
1241 i
< ctx
->nd_opts_len
; i
++, opt
++)
1243 if (opt
->option
== *code
) {
1250 return ND_COPTION_DATA(o
);
1255 ipv6nd_env(char **env
, const char *prefix
, const struct interface
*ifp
)
1257 size_t i
, j
, n
, len
;
1259 char ndprefix
[32], abuf
[24];
1260 struct dhcp_opt
*opt
;
1261 const struct nd_opt_hdr
*o
;
1262 struct ipv6_addr
*ia
;
1263 struct timespec now
;
1265 clock_gettime(CLOCK_MONOTONIC
, &now
);
1267 TAILQ_FOREACH(rap
, ifp
->ctx
->ipv6
->ra_routers
, next
) {
1268 if (rap
->iface
!= ifp
)
1272 snprintf(ndprefix
, sizeof(ndprefix
),
1273 "%s_nd%zu", prefix
, i
);
1275 snprintf(ndprefix
, sizeof(ndprefix
),
1278 setvar(rap
->iface
->ctx
, &env
[n
], ndprefix
,
1279 "from", rap
->sfrom
);
1282 setvard(rap
->iface
->ctx
, &env
[n
], ndprefix
,
1283 "acquired", (size_t)rap
->acquired
.tv_sec
);
1286 setvard(rap
->iface
->ctx
, &env
[n
], ndprefix
,
1287 "now", (size_t)now
.tv_sec
);
1290 /* Zero our indexes */
1292 for (j
= 0, opt
= rap
->iface
->ctx
->nd_opts
;
1293 j
< rap
->iface
->ctx
->nd_opts_len
;
1295 dhcp_zero_index(opt
);
1296 for (j
= 0, opt
= rap
->iface
->options
->nd_override
;
1297 j
< rap
->iface
->options
->nd_override_len
;
1299 dhcp_zero_index(opt
);
1302 /* Unlike DHCP, ND6 options *may* occur more than once.
1303 * There is also no provision for option concatenation
1305 len
= rap
->data_len
-
1306 ((size_t)((const uint8_t *)ND_CFIRST_OPTION(rap
) -
1309 for (o
= ND_CFIRST_OPTION(rap
);
1310 len
>= (ssize_t
)sizeof(*o
);
1311 o
= ND_CNEXT_OPTION(o
))
1313 if ((size_t)o
->nd_opt_len
* 8 > len
) {
1317 len
-= (size_t)(o
->nd_opt_len
* 8);
1318 if (has_option_mask(rap
->iface
->options
->nomasknd
,
1321 for (j
= 0, opt
= rap
->iface
->options
->nd_override
;
1322 j
< rap
->iface
->options
->nd_override_len
;
1324 if (opt
->option
== o
->nd_opt_type
)
1326 if (j
== rap
->iface
->options
->nd_override_len
) {
1327 for (j
= 0, opt
= rap
->iface
->ctx
->nd_opts
;
1328 j
< rap
->iface
->ctx
->nd_opts_len
;
1330 if (opt
->option
== o
->nd_opt_type
)
1332 if (j
== rap
->iface
->ctx
->nd_opts_len
)
1336 n
+= dhcp_envoption(rap
->iface
->ctx
,
1337 env
== NULL
? NULL
: &env
[n
],
1338 ndprefix
, rap
->iface
->name
,
1339 opt
, ipv6nd_getoption
,
1340 ND_COPTION_DATA(o
), ND_OPTION_LEN(o
));
1344 /* We need to output the addresses we actually made
1345 * from the prefix information options as well. */
1347 TAILQ_FOREACH(ia
, &rap
->addrs
, next
) {
1348 if (!(ia
->flags
& IPV6_AF_AUTOCONF
)
1349 #ifdef IPV6_AF_TEMPORARY
1350 || ia
->flags
& IPV6_AF_TEMPORARY
1356 snprintf(abuf
, sizeof(abuf
), "addr%zu", j
);
1357 setvar(rap
->iface
->ctx
, &env
[n
], ndprefix
,
1367 ipv6nd_handleifa(struct dhcpcd_ctx
*ctx
, int cmd
, const char *ifname
,
1368 const struct in6_addr
*addr
, int flags
)
1372 if (ctx
->ipv6
== NULL
)
1374 TAILQ_FOREACH(rap
, ctx
->ipv6
->ra_routers
, next
) {
1375 if (strcmp(rap
->iface
->name
, ifname
))
1377 ipv6_handleifa_addrs(cmd
, &rap
->addrs
, addr
, flags
);
1382 ipv6nd_expirera(void *arg
)
1384 struct interface
*ifp
;
1385 struct ra
*rap
, *ran
;
1386 struct timespec now
, lt
, expire
, next
;
1387 uint8_t expired
, valid
, validone
;
1390 clock_gettime(CLOCK_MONOTONIC
, &now
);
1392 timespecclear(&next
);
1395 TAILQ_FOREACH_SAFE(rap
, ifp
->ctx
->ipv6
->ra_routers
, next
, ran
) {
1396 if (rap
->iface
!= ifp
)
1399 if (rap
->lifetime
) {
1400 lt
.tv_sec
= (time_t)rap
->lifetime
;
1402 timespecadd(&rap
->acquired
, <
, &expire
);
1403 if (rap
->lifetime
== 0 || timespeccmp(&now
, &expire
, >))
1405 if (!rap
->expired
) {
1406 logger(ifp
->ctx
, LOG_WARNING
,
1407 "%s: %s: router expired",
1408 ifp
->name
, rap
->sfrom
);
1409 rap
->expired
= expired
= 1;
1414 timespecsub(&expire
, &now
, <
);
1415 if (!timespecisset(&next
) ||
1416 timespeccmp(&next
, <
, >))
1422 * We need to extract the lifetime from each option and check
1423 * if that has expired or not.
1424 * If it has, zero the option out in the returned data. */
1426 /* No valid lifetimes are left on the RA, so we might
1427 * as well punt it. */
1428 if (!valid
&& TAILQ_FIRST(&rap
->addrs
) == NULL
)
1429 ipv6nd_free_ra(rap
);
1434 if (timespecisset(&next
))
1435 eloop_timeout_add_tv(ifp
->ctx
->eloop
,
1436 &next
, ipv6nd_expirera
, ifp
);
1438 ipv6_buildroutes(ifp
->ctx
);
1439 script_runreason(ifp
, "ROUTERADVERT");
1442 /* No valid routers? Kill any DHCPv6. */
1444 dhcp6_drop(ifp
, "EXPIRE6");
1448 ipv6nd_drop(struct interface
*ifp
)
1451 uint8_t expired
= 0;
1452 TAILQ_HEAD(rahead
, ra
) rtrs
;
1454 if (ifp
->ctx
->ipv6
== NULL
)
1457 eloop_timeout_delete(ifp
->ctx
->eloop
, NULL
, ifp
);
1459 TAILQ_FOREACH(rap
, ifp
->ctx
->ipv6
->ra_routers
, next
) {
1460 if (rap
->iface
== ifp
) {
1461 rap
->expired
= expired
= 1;
1462 TAILQ_REMOVE(ifp
->ctx
->ipv6
->ra_routers
, rap
, next
);
1463 TAILQ_INSERT_TAIL(&rtrs
, rap
, next
);
1467 while ((rap
= TAILQ_FIRST(&rtrs
))) {
1468 TAILQ_REMOVE(&rtrs
, rap
, next
);
1469 ipv6nd_drop_ra(rap
);
1471 ipv6_buildroutes(ifp
->ctx
);
1472 if ((ifp
->options
->options
& DHCPCD_NODROP
) != DHCPCD_NODROP
)
1473 script_runreason(ifp
, "ROUTERADVERT");
1478 ipv6nd_handlena(struct dhcpcd_ctx
*dctx
, struct interface
*ifp
,
1479 struct icmp6_hdr
*icp
, size_t len
, int hoplimit
)
1481 struct ipv6_ctx
*ctx
= dctx
->ipv6
;
1482 struct nd_neighbor_advert
*nd_na
;
1484 uint32_t is_router
, is_solicited
;
1485 char buf
[INET6_ADDRSTRLEN
];
1490 logger(ctx
, LOG_DEBUG
, "NA for unexpected interface from %s",
1496 if ((size_t)len
< sizeof(struct nd_neighbor_advert
)) {
1497 logger(ifp
->ctx
, LOG_ERR
, "%s: IPv6 NA too short from %s",
1498 ifp
->name
, ctx
->sfrom
);
1502 /* RFC 4861 7.1.2 */
1503 if (hoplimit
!= 255) {
1504 logger(dctx
, LOG_ERR
,
1505 "invalid hoplimit(%d) in NA from %s", hoplimit
, ctx
->sfrom
);
1509 nd_na
= (struct nd_neighbor_advert
*)icp
;
1510 is_router
= nd_na
->nd_na_flags_reserved
& ND_NA_FLAG_ROUTER
;
1511 is_solicited
= nd_na
->nd_na_flags_reserved
& ND_NA_FLAG_SOLICITED
;
1512 taddr
= inet_ntop(AF_INET6
, &nd_na
->nd_na_target
,
1513 buf
, INET6_ADDRSTRLEN
);
1515 if (IN6_IS_ADDR_MULTICAST(&nd_na
->nd_na_target
)) {
1516 logger(ifp
->ctx
, LOG_ERR
, "%s: NA multicast address %s (%s)",
1517 ifp
->name
, taddr
, ctx
->sfrom
);
1521 TAILQ_FOREACH(rap
, ctx
->ra_routers
, next
) {
1522 if (rap
->iface
== ifp
&&
1523 IN6_ARE_ADDR_EQUAL(&rap
->from
, &nd_na
->nd_na_target
))
1528 logger(ifp
->ctx
, LOG_DEBUG
, "%s: unexpected NA from %s for %s",
1529 ifp
->name
, ctx
->sfrom
, taddr
);
1535 logger(ifp
->ctx
, LOG_DEBUG
, "%s: %sNA for %s from %s",
1536 ifp
->name
, is_solicited
? "solicited " : "", taddr
, ctx
->sfrom
);
1539 /* Node is no longer a router, so remove it from consideration */
1540 if (!is_router
&& !rap
->expired
) {
1541 logger(ifp
->ctx
, LOG_INFO
, "%s: %s not a router (%s)",
1542 ifp
->name
, taddr
, ctx
->sfrom
);
1544 ipv6_buildroutes(ifp
->ctx
);
1545 script_runreason(ifp
, "ROUTERADVERT");
1549 if (is_solicited
&& is_router
&& rap
->lifetime
) {
1552 logger(ifp
->ctx
, LOG_INFO
, "%s: %s reachable (%s)",
1553 ifp
->name
, taddr
, ctx
->sfrom
);
1554 ipv6_buildroutes(ifp
->ctx
);
1555 script_runreason(rap
->iface
, "ROUTERADVERT"); /* XXX */
1561 ipv6nd_handledata(void *arg
)
1563 struct dhcpcd_ctx
*dctx
;
1564 struct ipv6_ctx
*ctx
;
1568 struct in6_pktinfo pkt
;
1569 struct icmp6_hdr
*icp
;
1570 struct interface
*ifp
;
1574 ctx
->rcvhdr
.msg_controllen
= CMSG_SPACE(sizeof(struct in6_pktinfo
)) +
1575 CMSG_SPACE(sizeof(int));
1576 len
= recvmsg(ctx
->nd_fd
, &ctx
->rcvhdr
, 0);
1578 logger(dctx
, LOG_ERR
, "recvmsg: %m");
1579 eloop_event_delete(dctx
->eloop
, ctx
->nd_fd
);
1584 ctx
->sfrom
= inet_ntop(AF_INET6
, &ctx
->from
.sin6_addr
,
1585 ctx
->ntopbuf
, INET6_ADDRSTRLEN
);
1586 if ((size_t)len
< sizeof(struct icmp6_hdr
)) {
1587 logger(dctx
, LOG_ERR
, "IPv6 ICMP packet too short from %s",
1592 pkt
.ipi6_ifindex
= 0;
1594 for (cm
= (struct cmsghdr
*)CMSG_FIRSTHDR(&ctx
->rcvhdr
);
1596 cm
= (struct cmsghdr
*)CMSG_NXTHDR(&ctx
->rcvhdr
, cm
))
1598 if (cm
->cmsg_level
!= IPPROTO_IPV6
)
1600 switch(cm
->cmsg_type
) {
1602 if (cm
->cmsg_len
== CMSG_LEN(sizeof(pkt
)))
1603 memcpy(&pkt
, CMSG_DATA(cm
), sizeof(pkt
));
1606 if (cm
->cmsg_len
== CMSG_LEN(sizeof(int)))
1607 memcpy(&hoplimit
, CMSG_DATA(cm
), sizeof(int));
1612 if (pkt
.ipi6_ifindex
== 0) {
1613 logger(dctx
, LOG_ERR
,
1614 "IPv6 RA/NA did not contain index from %s",
1619 TAILQ_FOREACH(ifp
, dctx
->ifaces
, next
) {
1620 if (ifp
->index
== (unsigned int)pkt
.ipi6_ifindex
) {
1621 if (!(ifp
->options
->options
& DHCPCD_IPV6
))
1627 icp
= (struct icmp6_hdr
*)ctx
->rcvhdr
.msg_iov
[0].iov_base
;
1628 if (icp
->icmp6_code
== 0) {
1629 switch(icp
->icmp6_type
) {
1630 case ND_NEIGHBOR_ADVERT
:
1631 ipv6nd_handlena(dctx
, ifp
, icp
, (size_t)len
,
1634 case ND_ROUTER_ADVERT
:
1635 ipv6nd_handlera(dctx
, ifp
, icp
, (size_t)len
,
1641 logger(dctx
, LOG_ERR
, "invalid IPv6 type %d or code %d from %s",
1642 icp
->icmp6_type
, icp
->icmp6_code
, ctx
->sfrom
);
1646 ipv6nd_startrs1(void *arg
)
1648 struct interface
*ifp
= arg
;
1649 struct rs_state
*state
;
1651 logger(ifp
->ctx
, LOG_INFO
, "%s: soliciting an IPv6 router", ifp
->name
);
1652 if (ipv6nd_open(ifp
->ctx
) == -1) {
1653 logger(ifp
->ctx
, LOG_ERR
, "%s: ipv6nd_open: %m", __func__
);
1657 state
= RS_STATE(ifp
);
1658 if (state
== NULL
) {
1659 ifp
->if_data
[IF_DATA_IPV6ND
] = calloc(1, sizeof(*state
));
1660 state
= RS_STATE(ifp
);
1661 if (state
== NULL
) {
1662 logger(ifp
->ctx
, LOG_ERR
, "%s: %m", __func__
);
1667 /* Always make a new probe as the underlying hardware
1668 * address could have changed. */
1669 ipv6nd_makersprobe(ifp
);
1670 if (state
->rs
== NULL
) {
1671 logger(ifp
->ctx
, LOG_ERR
,
1672 "%s: ipv6ns_makersprobe: %m", __func__
);
1676 state
->rsprobes
= 0;
1677 ipv6nd_sendrsprobe(ifp
);
1681 ipv6nd_startrs(struct interface
*ifp
)
1685 eloop_timeout_delete(ifp
->ctx
->eloop
, NULL
, ifp
);
1686 if (!(ifp
->options
->options
& DHCPCD_INITIAL_DELAY
)) {
1687 ipv6nd_startrs1(ifp
);
1692 tv
.tv_nsec
= (suseconds_t
)arc4random_uniform(
1693 MAX_RTR_SOLICITATION_DELAY
* NSEC_PER_SEC
);
1695 logger(ifp
->ctx
, LOG_DEBUG
,
1696 "%s: delaying IPv6 router solicitation for %0.1f seconds",
1697 ifp
->name
, timespec_to_double(&tv
));
1698 eloop_timeout_add_tv(ifp
->ctx
->eloop
, &tv
, ipv6nd_startrs1
, ifp
);