1 /* SPDX-License-Identifier: LGPL-2.1+ */
3 Copyright © 2014 Intel Corporation. All rights reserved.
6 #include <netinet/icmp6.h>
11 #include "missing_network.h"
12 #include "networkd-dhcp6.h"
13 #include "networkd-manager.h"
14 #include "networkd-ndisc.h"
15 #include "networkd-route.h"
16 #include "string-table.h"
17 #include "string-util.h"
20 #define NDISC_DNSSL_MAX 64U
21 #define NDISC_RDNSS_MAX 64U
22 #define NDISC_PREFIX_LFT_MIN 7200U
24 #define DAD_CONFLICTS_IDGEN_RETRIES_RFC7217 3
26 /* https://tools.ietf.org/html/rfc5453 */
27 /* https://www.iana.org/assignments/ipv6-interface-ids/ipv6-interface-ids.xml */
29 #define SUBNET_ROUTER_ANYCAST_ADDRESS_RFC4291 ((struct in6_addr) { .s6_addr = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } })
30 #define SUBNET_ROUTER_ANYCAST_PREFIXLEN 8
31 #define RESERVED_IPV6_INTERFACE_IDENTIFIERS_ADDRESS_RFC4291 ((struct in6_addr) { .s6_addr = { 0x02, 0x00, 0x5E, 0xFF, 0xFE } })
32 #define RESERVED_IPV6_INTERFACE_IDENTIFIERS_PREFIXLEN 5
33 #define RESERVED_SUBNET_ANYCAST_ADDRESSES_RFC4291 ((struct in6_addr) { .s6_addr = { 0xFD, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF } })
34 #define RESERVED_SUBNET_ANYCAST_PREFIXLEN 7
36 #define NDISC_APP_ID SD_ID128_MAKE(13,ac,81,a7,d5,3f,49,78,92,79,5d,0c,29,3a,bc,7e)
38 static bool stableprivate_address_is_valid(const struct in6_addr
*addr
) {
41 /* According to rfc4291, generated address should not be in the following ranges. */
43 if (memcmp(addr
, &SUBNET_ROUTER_ANYCAST_ADDRESS_RFC4291
, SUBNET_ROUTER_ANYCAST_PREFIXLEN
) == 0)
46 if (memcmp(addr
, &RESERVED_IPV6_INTERFACE_IDENTIFIERS_ADDRESS_RFC4291
, RESERVED_IPV6_INTERFACE_IDENTIFIERS_PREFIXLEN
) == 0)
49 if (memcmp(addr
, &RESERVED_SUBNET_ANYCAST_ADDRESSES_RFC4291
, RESERVED_SUBNET_ANYCAST_PREFIXLEN
) == 0)
55 static int make_stableprivate_address(Link
*link
, const struct in6_addr
*prefix
, uint8_t prefix_len
, uint8_t dad_counter
, struct in6_addr
*addr
) {
56 sd_id128_t secret_key
;
62 /* According to rfc7217 section 5.1
63 * RID = F(Prefix, Net_Iface, Network_ID, DAD_Counter, secret_key) */
65 r
= sd_id128_get_machine_app_specific(NDISC_APP_ID
, &secret_key
);
67 return log_error_errno(r
, "Failed to generate key: %m");
69 siphash24_init(&state
, secret_key
.bytes
);
71 l
= MAX(DIV_ROUND_UP(prefix_len
, 8), 8);
72 siphash24_compress(prefix
, l
, &state
);
73 siphash24_compress(link
->ifname
, strlen(link
->ifname
), &state
);
74 siphash24_compress(&link
->mac
, sizeof(struct ether_addr
), &state
);
75 siphash24_compress(&dad_counter
, sizeof(uint8_t), &state
);
77 rid
= htole64(siphash24_finalize(&state
));
79 memcpy(addr
->s6_addr
, prefix
->s6_addr
, l
);
80 memcpy(addr
->s6_addr
+ l
, &rid
, 16 - l
);
85 static int ndisc_route_handler(sd_netlink
*rtnl
, sd_netlink_message
*m
, Link
*link
) {
89 assert(link
->ndisc_routes_messages
> 0);
91 link
->ndisc_routes_messages
--;
93 if (IN_SET(link
->state
, LINK_STATE_FAILED
, LINK_STATE_LINGER
))
96 r
= sd_netlink_message_get_errno(m
);
97 if (r
< 0 && r
!= -EEXIST
) {
98 log_link_message_error_errno(link
, m
, r
, "Could not set NDisc route");
99 link_enter_failed(link
);
103 if (link
->ndisc_routes_messages
== 0) {
104 log_link_debug(link
, "NDisc routes set.");
105 link
->ndisc_routes_configured
= true;
106 link_check_ready(link
);
112 static int ndisc_address_handler(sd_netlink
*rtnl
, sd_netlink_message
*m
, Link
*link
) {
116 assert(link
->ndisc_addresses_messages
> 0);
118 link
->ndisc_addresses_messages
--;
120 if (IN_SET(link
->state
, LINK_STATE_FAILED
, LINK_STATE_LINGER
))
123 r
= sd_netlink_message_get_errno(m
);
124 if (r
< 0 && r
!= -EEXIST
) {
125 log_link_message_error_errno(link
, m
, r
, "Could not set NDisc address");
126 link_enter_failed(link
);
129 (void) manager_rtnl_process_address(rtnl
, m
, link
->manager
);
131 if (link
->ndisc_addresses_messages
== 0) {
132 log_link_debug(link
, "NDisc SLAAC addresses set.");
133 link
->ndisc_addresses_configured
= true;
134 r
= link_request_set_routes(link
);
136 link_enter_failed(link
);
144 static int ndisc_router_process_default(Link
*link
, sd_ndisc_router
*rt
) {
145 _cleanup_(route_freep
) Route
*route
= NULL
;
146 union in_addr_union gateway
;
156 r
= sd_ndisc_router_get_lifetime(rt
, &lifetime
);
158 return log_link_error_errno(link
, r
, "Failed to get gateway lifetime from RA: %m");
160 if (lifetime
== 0) /* not a default router */
163 r
= sd_ndisc_router_get_address(rt
, &gateway
.in6
);
165 return log_link_error_errno(link
, r
, "Failed to get gateway address from RA: %m");
167 if (address_exists(link
, AF_INET6
, &gateway
)) {
169 _cleanup_free_
char *buffer
= NULL
;
171 (void) in_addr_to_string(AF_INET6
, &gateway
, &buffer
);
172 log_link_debug(link
, "No NDisc route added, gateway %s matches local address",
178 r
= sd_ndisc_router_get_preference(rt
, &preference
);
180 return log_link_error_errno(link
, r
, "Failed to get default router preference from RA: %m");
182 r
= sd_ndisc_router_get_timestamp(rt
, clock_boottime_or_monotonic(), &time_now
);
184 return log_link_error_errno(link
, r
, "Failed to get RA timestamp: %m");
186 r
= sd_ndisc_router_get_mtu(rt
, &mtu
);
190 return log_link_error_errno(link
, r
, "Failed to get default router MTU from RA: %m");
192 r
= route_new(&route
);
196 route
->family
= AF_INET6
;
197 route
->table
= link_get_ipv6_accept_ra_route_table(link
);
198 route
->priority
= link
->network
->dhcp6_route_metric
;
199 route
->protocol
= RTPROT_RA
;
200 route
->pref
= preference
;
202 route
->lifetime
= time_now
+ lifetime
* USEC_PER_SEC
;
205 r
= route_configure(route
, link
, ndisc_route_handler
);
207 return log_link_error_errno(link
, r
, "Could not set default route: %m");
209 link
->ndisc_routes_messages
++;
212 LIST_FOREACH(routes
, route_gw
, link
->network
->static_routes
) {
213 if (!route_gw
->gateway_from_dhcp
)
216 if (route_gw
->family
!= AF_INET6
)
219 route_gw
->gw
= gateway
;
221 r
= route_configure(route_gw
, link
, ndisc_route_handler
);
223 return log_link_error_errno(link
, r
, "Could not set gateway: %m");
225 link
->ndisc_routes_messages
++;
231 static int ndisc_router_generate_addresses(Link
*link
, unsigned prefixlen
, uint32_t lifetime_preferred
, Address
*address
, Set
**ret
) {
232 _cleanup_set_free_free_ Set
*addresses
= NULL
;
233 struct in6_addr addr
;
242 addresses
= set_new(&address_hash_ops
);
246 addr
= address
->in_addr
.in6
;
247 ORDERED_HASHMAP_FOREACH(j
, link
->network
->ipv6_tokens
, i
) {
248 bool have_address
= false;
249 _cleanup_(address_freep
) Address
*new_address
= NULL
;
251 r
= address_new(&new_address
);
255 *new_address
= *address
;
257 if (j
->address_generation_type
== IPV6_TOKEN_ADDRESS_GENERATION_PREFIXSTABLE
258 && memcmp(&j
->prefix
, &addr
, FAMILY_ADDRESS_SIZE(address
->family
)) == 0) {
259 /* While this loop uses dad_counter and a retry limit as specified in RFC 7217, the loop
260 does not actually attempt Duplicate Address Detection; the counter will be incremented
261 only when the address generation algorithm produces an invalid address, and the loop
262 may exit with an address which ends up being unusable due to duplication on the link.
264 for (; j
->dad_counter
< DAD_CONFLICTS_IDGEN_RETRIES_RFC7217
; j
->dad_counter
++) {
265 r
= make_stableprivate_address(link
, &j
->prefix
, prefixlen
, j
->dad_counter
, &new_address
->in_addr
.in6
);
269 if (stableprivate_address_is_valid(&new_address
->in_addr
.in6
)) {
274 } else if (j
->address_generation_type
== IPV6_TOKEN_ADDRESS_GENERATION_STATIC
) {
275 memcpy(new_address
->in_addr
.in6
.s6_addr
+ 8, j
->prefix
.s6_addr
+ 8, 8);
280 new_address
->prefixlen
= prefixlen
;
281 new_address
->flags
= IFA_F_NOPREFIXROUTE
|IFA_F_MANAGETEMPADDR
;
282 new_address
->cinfo
.ifa_prefered
= lifetime_preferred
;
284 r
= set_put(addresses
, new_address
);
286 return log_link_error_errno(link
, r
, "Failed to store SLAAC address: %m");
287 TAKE_PTR(new_address
);
291 /* fall back to EUI-64 if no tokens provided addresses */
292 if (set_isempty(addresses
)) {
293 _cleanup_(address_freep
) Address
*new_address
= NULL
;
295 r
= address_new(&new_address
);
299 *new_address
= *address
;
301 r
= generate_ipv6_eui_64_address(link
, &new_address
->in_addr
.in6
);
303 return log_link_error_errno(link
, r
, "Failed to generate EUI64 address: %m");
305 new_address
->prefixlen
= prefixlen
;
306 new_address
->flags
= IFA_F_NOPREFIXROUTE
|IFA_F_MANAGETEMPADDR
;
307 new_address
->cinfo
.ifa_prefered
= lifetime_preferred
;
309 r
= set_put(addresses
, new_address
);
311 return log_link_error_errno(link
, r
, "Failed to store SLAAC address: %m");
312 TAKE_PTR(new_address
);
315 *ret
= TAKE_PTR(addresses
);
320 static int ndisc_router_process_autonomous_prefix(Link
*link
, sd_ndisc_router
*rt
) {
321 uint32_t lifetime_valid
, lifetime_preferred
, lifetime_remaining
;
322 _cleanup_set_free_free_ Set
*addresses
= NULL
;
323 _cleanup_(address_freep
) Address
*address
= NULL
;
333 r
= sd_ndisc_router_get_timestamp(rt
, clock_boottime_or_monotonic(), &time_now
);
335 return log_link_error_errno(link
, r
, "Failed to get RA timestamp: %m");
337 r
= sd_ndisc_router_prefix_get_prefixlen(rt
, &prefixlen
);
339 return log_link_error_errno(link
, r
, "Failed to get prefix length: %m");
341 r
= sd_ndisc_router_prefix_get_valid_lifetime(rt
, &lifetime_valid
);
343 return log_link_error_errno(link
, r
, "Failed to get prefix valid lifetime: %m");
345 r
= sd_ndisc_router_prefix_get_preferred_lifetime(rt
, &lifetime_preferred
);
347 return log_link_error_errno(link
, r
, "Failed to get prefix preferred lifetime: %m");
349 /* The preferred lifetime is never greater than the valid lifetime */
350 if (lifetime_preferred
> lifetime_valid
)
353 r
= address_new(&address
);
357 address
->family
= AF_INET6
;
358 r
= sd_ndisc_router_prefix_get_address(rt
, &address
->in_addr
.in6
);
360 return log_link_error_errno(link
, r
, "Failed to get prefix address: %m");
362 r
= ndisc_router_generate_addresses(link
, prefixlen
, lifetime_preferred
, address
, &addresses
);
366 SET_FOREACH(a
, addresses
, i
) {
367 Address
*existing_address
;
369 /* see RFC4862 section 5.5.3.e */
370 r
= address_get(link
, a
->family
, &a
->in_addr
, a
->prefixlen
, &existing_address
);
372 lifetime_remaining
= existing_address
->cinfo
.tstamp
/ 100 + existing_address
->cinfo
.ifa_valid
- time_now
/ USEC_PER_SEC
;
373 if (lifetime_valid
> NDISC_PREFIX_LFT_MIN
|| lifetime_valid
> lifetime_remaining
)
374 a
->cinfo
.ifa_valid
= lifetime_valid
;
375 else if (lifetime_remaining
<= NDISC_PREFIX_LFT_MIN
)
376 a
->cinfo
.ifa_valid
= lifetime_remaining
;
378 a
->cinfo
.ifa_valid
= NDISC_PREFIX_LFT_MIN
;
379 } else if (lifetime_valid
> 0)
380 a
->cinfo
.ifa_valid
= lifetime_valid
;
382 continue; /* see RFC4862 section 5.5.3.d */
384 if (a
->cinfo
.ifa_valid
== 0)
387 r
= address_configure(a
, link
, ndisc_address_handler
, true);
389 return log_link_error_errno(link
, r
, "Could not set SLAAC address: %m");
391 link
->ndisc_addresses_messages
++;
397 static int ndisc_router_process_onlink_prefix(Link
*link
, sd_ndisc_router
*rt
) {
398 _cleanup_(route_freep
) Route
*route
= NULL
;
407 r
= sd_ndisc_router_get_timestamp(rt
, clock_boottime_or_monotonic(), &time_now
);
409 return log_link_error_errno(link
, r
, "Failed to get RA timestamp: %m");
411 r
= sd_ndisc_router_prefix_get_prefixlen(rt
, &prefixlen
);
413 return log_link_error_errno(link
, r
, "Failed to get prefix length: %m");
415 r
= sd_ndisc_router_prefix_get_valid_lifetime(rt
, &lifetime
);
417 return log_link_error_errno(link
, r
, "Failed to get prefix lifetime: %m");
419 r
= route_new(&route
);
423 route
->family
= AF_INET6
;
424 route
->table
= link_get_ipv6_accept_ra_route_table(link
);
425 route
->priority
= link
->network
->dhcp6_route_metric
;
426 route
->protocol
= RTPROT_RA
;
427 route
->flags
= RTM_F_PREFIX
;
428 route
->dst_prefixlen
= prefixlen
;
429 route
->lifetime
= time_now
+ lifetime
* USEC_PER_SEC
;
431 r
= sd_ndisc_router_prefix_get_address(rt
, &route
->dst
.in6
);
433 return log_link_error_errno(link
, r
, "Failed to get prefix address: %m");
435 r
= route_configure(route
, link
, ndisc_route_handler
);
437 return log_link_error_errno(link
, r
, "Could not set prefix route: %m");;
439 link
->ndisc_routes_messages
++;
444 static int ndisc_router_process_route(Link
*link
, sd_ndisc_router
*rt
) {
445 _cleanup_(route_freep
) Route
*route
= NULL
;
446 struct in6_addr gateway
;
448 unsigned preference
, prefixlen
;
454 r
= sd_ndisc_router_route_get_lifetime(rt
, &lifetime
);
456 return log_link_error_errno(link
, r
, "Failed to get gateway lifetime from RA: %m");
461 r
= sd_ndisc_router_get_address(rt
, &gateway
);
463 return log_link_error_errno(link
, r
, "Failed to get gateway address from RA: %m");
465 r
= sd_ndisc_router_route_get_prefixlen(rt
, &prefixlen
);
467 return log_link_error_errno(link
, r
, "Failed to get route prefix length: %m");
469 r
= sd_ndisc_router_route_get_preference(rt
, &preference
);
471 return log_link_error_errno(link
, r
, "Failed to get default router preference from RA: %m");
473 r
= sd_ndisc_router_get_timestamp(rt
, clock_boottime_or_monotonic(), &time_now
);
475 return log_link_error_errno(link
, r
, "Failed to get RA timestamp: %m");
477 r
= route_new(&route
);
481 route
->family
= AF_INET6
;
482 route
->table
= link_get_ipv6_accept_ra_route_table(link
);
483 route
->priority
= link
->network
->dhcp6_route_metric
;
484 route
->protocol
= RTPROT_RA
;
485 route
->pref
= preference
;
486 route
->gw
.in6
= gateway
;
487 route
->dst_prefixlen
= prefixlen
;
488 route
->lifetime
= time_now
+ lifetime
* USEC_PER_SEC
;
490 r
= sd_ndisc_router_route_get_address(rt
, &route
->dst
.in6
);
492 return log_link_error_errno(link
, r
, "Failed to get route address: %m");
494 r
= route_configure(route
, link
, ndisc_route_handler
);
496 return log_link_error_errno(link
, r
, "Could not set additional route: %m");
498 link
->ndisc_routes_messages
++;
503 static void ndisc_rdnss_hash_func(const NDiscRDNSS
*x
, struct siphash
*state
) {
504 siphash24_compress(&x
->address
, sizeof(x
->address
), state
);
507 static int ndisc_rdnss_compare_func(const NDiscRDNSS
*a
, const NDiscRDNSS
*b
) {
508 return memcmp(&a
->address
, &b
->address
, sizeof(a
->address
));
511 DEFINE_PRIVATE_HASH_OPS(ndisc_rdnss_hash_ops
, NDiscRDNSS
, ndisc_rdnss_hash_func
, ndisc_rdnss_compare_func
);
513 static int ndisc_router_process_rdnss(Link
*link
, sd_ndisc_router
*rt
) {
515 const struct in6_addr
*a
;
522 r
= sd_ndisc_router_get_timestamp(rt
, clock_boottime_or_monotonic(), &time_now
);
524 return log_link_error_errno(link
, r
, "Failed to get RA timestamp: %m");
526 r
= sd_ndisc_router_rdnss_get_lifetime(rt
, &lifetime
);
528 return log_link_error_errno(link
, r
, "Failed to get RDNSS lifetime: %m");
530 n
= sd_ndisc_router_rdnss_get_addresses(rt
, &a
);
532 return log_link_error_errno(link
, n
, "Failed to get RDNSS addresses: %m");
534 for (int i
= 0; i
< n
; i
++) {
535 _cleanup_free_ NDiscRDNSS
*x
= NULL
;
541 (void) set_remove(link
->ndisc_rdnss
, &d
);
546 y
= set_get(link
->ndisc_rdnss
, &d
);
548 y
->valid_until
= time_now
+ lifetime
* USEC_PER_SEC
;
554 if (set_size(link
->ndisc_rdnss
) >= NDISC_RDNSS_MAX
) {
555 log_link_warning(link
, "Too many RDNSS records per link, ignoring.");
559 x
= new(NDiscRDNSS
, 1);
565 .valid_until
= time_now
+ lifetime
* USEC_PER_SEC
,
568 r
= set_ensure_consume(&link
->ndisc_rdnss
, &ndisc_rdnss_hash_ops
, TAKE_PTR(x
));
579 static void ndisc_dnssl_hash_func(const NDiscDNSSL
*x
, struct siphash
*state
) {
580 siphash24_compress(NDISC_DNSSL_DOMAIN(x
), strlen(NDISC_DNSSL_DOMAIN(x
)), state
);
583 static int ndisc_dnssl_compare_func(const NDiscDNSSL
*a
, const NDiscDNSSL
*b
) {
584 return strcmp(NDISC_DNSSL_DOMAIN(a
), NDISC_DNSSL_DOMAIN(b
));
587 DEFINE_PRIVATE_HASH_OPS(ndisc_dnssl_hash_ops
, NDiscDNSSL
, ndisc_dnssl_hash_func
, ndisc_dnssl_compare_func
);
589 static int ndisc_router_process_dnssl(Link
*link
, sd_ndisc_router
*rt
) {
590 _cleanup_strv_free_
char **l
= NULL
;
599 r
= sd_ndisc_router_get_timestamp(rt
, clock_boottime_or_monotonic(), &time_now
);
601 return log_link_error_errno(link
, r
, "Failed to get RA timestamp: %m");
603 r
= sd_ndisc_router_dnssl_get_lifetime(rt
, &lifetime
);
605 return log_link_error_errno(link
, r
, "Failed to get DNSSL lifetime: %m");
607 r
= sd_ndisc_router_dnssl_get_domains(rt
, &l
);
609 return log_link_error_errno(link
, r
, "Failed to get DNSSL addresses: %m");
612 _cleanup_free_ NDiscDNSSL
*s
= NULL
;
615 s
= malloc0(ALIGN(sizeof(NDiscDNSSL
)) + strlen(*i
) + 1);
619 strcpy(NDISC_DNSSL_DOMAIN(s
), *i
);
622 (void) set_remove(link
->ndisc_dnssl
, s
);
627 x
= set_get(link
->ndisc_dnssl
, s
);
629 x
->valid_until
= time_now
+ lifetime
* USEC_PER_SEC
;
635 if (set_size(link
->ndisc_dnssl
) >= NDISC_DNSSL_MAX
) {
636 log_link_warning(link
, "Too many DNSSL records per link, ignoring.");
640 s
->valid_until
= time_now
+ lifetime
* USEC_PER_SEC
;
642 r
= set_ensure_consume(&link
->ndisc_dnssl
, &ndisc_dnssl_hash_ops
, TAKE_PTR(s
));
653 static int ndisc_router_process_options(Link
*link
, sd_ndisc_router
*rt
) {
655 assert(link
->network
);
658 for (int r
= sd_ndisc_router_option_rewind(rt
); ; r
= sd_ndisc_router_option_next(rt
)) {
662 return log_link_error_errno(link
, r
, "Failed to iterate through options: %m");
663 if (r
== 0) /* EOF */
666 r
= sd_ndisc_router_option_get_type(rt
, &type
);
668 return log_link_error_errno(link
, r
, "Failed to get RA option type: %m");
672 case SD_NDISC_OPTION_PREFIX_INFORMATION
: {
673 union in_addr_union a
;
676 r
= sd_ndisc_router_prefix_get_address(rt
, &a
.in6
);
678 return log_link_error_errno(link
, r
, "Failed to get prefix address: %m");
680 if (set_contains(link
->network
->ndisc_deny_listed_prefix
, &a
.in6
)) {
682 _cleanup_free_
char *b
= NULL
;
684 (void) in_addr_to_string(AF_INET6
, &a
, &b
);
685 log_link_debug(link
, "Prefix '%s' is deny-listed, ignoring", strna(b
));
690 r
= sd_ndisc_router_prefix_get_flags(rt
, &flags
);
692 return log_link_error_errno(link
, r
, "Failed to get RA prefix flags: %m");
694 if (link
->network
->ipv6_accept_ra_use_onlink_prefix
&&
695 FLAGS_SET(flags
, ND_OPT_PI_FLAG_ONLINK
)) {
696 r
= ndisc_router_process_onlink_prefix(link
, rt
);
701 if (link
->network
->ipv6_accept_ra_use_autonomous_prefix
&&
702 FLAGS_SET(flags
, ND_OPT_PI_FLAG_AUTO
)) {
703 r
= ndisc_router_process_autonomous_prefix(link
, rt
);
710 case SD_NDISC_OPTION_ROUTE_INFORMATION
:
711 r
= ndisc_router_process_route(link
, rt
);
716 case SD_NDISC_OPTION_RDNSS
:
717 if (link
->network
->ipv6_accept_ra_use_dns
) {
718 r
= ndisc_router_process_rdnss(link
, rt
);
724 case SD_NDISC_OPTION_DNSSL
:
725 if (link
->network
->ipv6_accept_ra_use_dns
) {
726 r
= ndisc_router_process_dnssl(link
, rt
);
735 static int ndisc_router_handler(Link
*link
, sd_ndisc_router
*rt
) {
740 assert(link
->network
);
741 assert(link
->manager
);
744 r
= sd_ndisc_router_get_flags(rt
, &flags
);
746 return log_link_error_errno(link
, r
, "Failed to get RA flags: %m");
748 if ((flags
& (ND_RA_FLAG_MANAGED
| ND_RA_FLAG_OTHER
) && link
->network
->ipv6_accept_ra_start_dhcp6_client
)) {
750 if (link
->network
->ipv6_accept_ra_start_dhcp6_client
== IPV6_ACCEPT_RA_START_DHCP6_CLIENT_ALWAYS
)
751 r
= dhcp6_request_address(link
, false);
753 /* (re)start DHCPv6 client in stateful or stateless mode according to RA flags */
754 r
= dhcp6_request_address(link
, !(flags
& ND_RA_FLAG_MANAGED
));
755 if (r
< 0 && r
!= -EBUSY
)
756 return log_link_error_errno(link
, r
, "Could not acquire DHCPv6 lease on NDisc request: %m");
758 log_link_debug(link
, "Acquiring DHCPv6 lease on NDisc request");
763 r
= ndisc_router_process_default(link
, rt
);
766 r
= ndisc_router_process_options(link
, rt
);
773 static void ndisc_handler(sd_ndisc
*nd
, sd_ndisc_event event
, sd_ndisc_router
*rt
, void *userdata
) {
774 Link
*link
= userdata
;
779 if (IN_SET(link
->state
, LINK_STATE_FAILED
, LINK_STATE_LINGER
))
784 case SD_NDISC_EVENT_ROUTER
:
785 link
->ndisc_addresses_configured
= false;
786 link
->ndisc_routes_configured
= false;
788 r
= ndisc_router_handler(link
, rt
);
790 link_enter_failed(link
);
794 if (link
->ndisc_addresses_messages
== 0)
795 link
->ndisc_addresses_configured
= true;
797 log_link_debug(link
, "Setting SLAAC addresses.");
799 /* address_handler calls link_request_set_routes() and link_request_set_nexthop().
800 * Before they are called, the related flags must be cleared. Otherwise, the link
801 * becomes configured state before routes are configured. */
802 link
->static_routes_configured
= false;
803 link
->static_nexthops_configured
= false;
806 if (link
->ndisc_routes_messages
== 0)
807 link
->ndisc_routes_configured
= true;
809 log_link_debug(link
, "Setting NDisc routes.");
811 if (link
->ndisc_addresses_configured
&& link
->ndisc_routes_configured
)
812 link_check_ready(link
);
814 link_set_state(link
, LINK_STATE_CONFIGURING
);
817 case SD_NDISC_EVENT_TIMEOUT
:
818 log_link_debug(link
, "NDisc handler get timeout event");
819 link
->ndisc_addresses_configured
= true;
820 link
->ndisc_routes_configured
= true;
821 link_check_ready(link
);
825 assert_not_reached("Unknown NDisc event");
829 int ndisc_configure(Link
*link
) {
834 r
= sd_ndisc_new(&link
->ndisc
);
838 r
= sd_ndisc_attach_event(link
->ndisc
, NULL
, 0);
842 r
= sd_ndisc_set_mac(link
->ndisc
, &link
->mac
);
846 r
= sd_ndisc_set_ifindex(link
->ndisc
, link
->ifindex
);
850 r
= sd_ndisc_set_callback(link
->ndisc
, ndisc_handler
, link
);
857 void ndisc_vacuum(Link
*link
) {
865 /* Removes all RDNSS and DNSSL entries whose validity time has passed */
867 time_now
= now(clock_boottime_or_monotonic());
869 SET_FOREACH(r
, link
->ndisc_rdnss
, i
)
870 if (r
->valid_until
< time_now
) {
871 free(set_remove(link
->ndisc_rdnss
, r
));
875 SET_FOREACH(d
, link
->ndisc_dnssl
, i
)
876 if (d
->valid_until
< time_now
) {
877 free(set_remove(link
->ndisc_dnssl
, d
));
882 void ndisc_flush(Link
*link
) {
885 /* Removes all RDNSS and DNSSL entries, without exception */
887 link
->ndisc_rdnss
= set_free_free(link
->ndisc_rdnss
);
888 link
->ndisc_dnssl
= set_free_free(link
->ndisc_dnssl
);
891 int ipv6token_new(IPv6Token
**ret
) {
894 p
= new(IPv6Token
, 1);
899 .address_generation_type
= IPV6_TOKEN_ADDRESS_GENERATION_NONE
,
907 DEFINE_HASH_OPS_WITH_VALUE_DESTRUCTOR(
911 trivial_compare_func
,
915 int config_parse_ndisc_deny_listed_prefix(
917 const char *filename
,
920 unsigned section_line
,
927 Network
*network
= data
;
936 if (isempty(rvalue
)) {
937 network
->ndisc_deny_listed_prefix
= set_free_free(network
->ndisc_deny_listed_prefix
);
942 _cleanup_free_
char *n
= NULL
;
943 _cleanup_free_
struct in6_addr
*a
= NULL
;
944 union in_addr_union ip
;
946 r
= extract_first_word(&p
, &n
, NULL
, 0);
950 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
951 "Failed to parse NDisc deny-listed prefix, ignoring assignment: %s",
958 r
= in_addr_from_string(AF_INET6
, n
, &ip
);
960 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
961 "NDisc deny-listed prefix is invalid, ignoring assignment: %s", n
);
965 if (set_contains(network
->ndisc_deny_listed_prefix
, &ip
.in6
))
968 a
= newdup(struct in6_addr
, &ip
.in6
, 1);
972 r
= set_ensure_consume(&network
->ndisc_deny_listed_prefix
, &in6_addr_hash_ops
, TAKE_PTR(a
));
978 int config_parse_address_generation_type(
980 const char *filename
,
983 unsigned section_line
,
990 _cleanup_free_ IPv6Token
*token
= NULL
;
991 union in_addr_union buffer
;
992 Network
*network
= data
;
1001 if (isempty(rvalue
)) {
1002 network
->ipv6_tokens
= ordered_hashmap_free(network
->ipv6_tokens
);
1006 r
= ipv6token_new(&token
);
1010 if ((p
= startswith(rvalue
, "static:")))
1011 token
->address_generation_type
= IPV6_TOKEN_ADDRESS_GENERATION_STATIC
;
1012 else if ((p
= startswith(rvalue
, "prefixstable:")))
1013 token
->address_generation_type
= IPV6_TOKEN_ADDRESS_GENERATION_PREFIXSTABLE
;
1015 token
->address_generation_type
= IPV6_TOKEN_ADDRESS_GENERATION_STATIC
;
1019 r
= in_addr_from_string(AF_INET6
, p
, &buffer
);
1021 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
1022 "Failed to parse IPv6 %s, ignoring: %s", lvalue
, rvalue
);
1026 if (in_addr_is_null(AF_INET6
, &buffer
)) {
1027 log_syntax(unit
, LOG_WARNING
, filename
, line
, 0,
1028 "IPv6 %s cannot be the ANY address, ignoring: %s", lvalue
, rvalue
);
1032 token
->prefix
= buffer
.in6
;
1034 r
= ordered_hashmap_ensure_allocated(&network
->ipv6_tokens
, &ipv6_token_hash_ops
);
1038 r
= ordered_hashmap_put(network
->ipv6_tokens
, &token
->prefix
, token
);
1040 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
1041 "Failed to store IPv6 token '%s'", rvalue
);
1050 DEFINE_CONFIG_PARSE_ENUM(config_parse_ipv6_accept_ra_start_dhcp6_client
, ipv6_accept_ra_start_dhcp6_client
, IPv6AcceptRAStartDHCP6Client
,
1051 "Failed to parse DHCPv6Client= setting")
1052 static const char* const ipv6_accept_ra_start_dhcp6_client_table
[_IPV6_ACCEPT_RA_START_DHCP6_CLIENT_MAX
] = {
1053 [IPV6_ACCEPT_RA_START_DHCP6_CLIENT_NO
] = "no",
1054 [IPV6_ACCEPT_RA_START_DHCP6_CLIENT_ALWAYS
] = "always",
1055 [IPV6_ACCEPT_RA_START_DHCP6_CLIENT_YES
] = "yes",
1058 DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(ipv6_accept_ra_start_dhcp6_client
, IPv6AcceptRAStartDHCP6Client
, IPV6_ACCEPT_RA_START_DHCP6_CLIENT_YES
);