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
;
158 r
= sd_ndisc_router_get_lifetime(rt
, &lifetime
);
160 return log_link_warning_errno(link
, r
, "Failed to get gateway address from RA: %m");
162 if (lifetime
== 0) /* not a default router */
165 r
= sd_ndisc_router_get_address(rt
, &gateway
.in6
);
167 return log_link_warning_errno(link
, r
, "Failed to get gateway address from RA: %m");
169 SET_FOREACH(address
, link
->addresses
, i
) {
170 if (address
->family
!= AF_INET6
)
172 if (in_addr_equal(AF_INET6
, &gateway
, &address
->in_addr
)) {
173 _cleanup_free_
char *buffer
= NULL
;
175 (void) in_addr_to_string(AF_INET6
, &address
->in_addr
, &buffer
);
176 log_link_debug(link
, "No NDisc route added, gateway %s matches local address",
182 SET_FOREACH(address
, link
->addresses_foreign
, i
) {
183 if (address
->family
!= AF_INET6
)
185 if (in_addr_equal(AF_INET6
, &gateway
, &address
->in_addr
)) {
186 _cleanup_free_
char *buffer
= NULL
;
188 (void) in_addr_to_string(AF_INET6
, &address
->in_addr
, &buffer
);
189 log_link_debug(link
, "No NDisc route added, gateway %s matches local address",
195 r
= sd_ndisc_router_get_preference(rt
, &preference
);
197 return log_link_warning_errno(link
, r
, "Failed to get default router preference from RA: %m");
199 r
= sd_ndisc_router_get_timestamp(rt
, clock_boottime_or_monotonic(), &time_now
);
201 return log_link_warning_errno(link
, r
, "Failed to get RA timestamp: %m");
203 r
= sd_ndisc_router_get_mtu(rt
, &mtu
);
207 return log_link_warning_errno(link
, r
, "Failed to get default router MTU from RA: %m");
209 r
= route_new(&route
);
211 return log_link_error_errno(link
, r
, "Could not allocate route: %m");
213 route
->family
= AF_INET6
;
214 route
->table
= link_get_ipv6_accept_ra_route_table(link
);
215 route
->priority
= link
->network
->dhcp6_route_metric
;
216 route
->protocol
= RTPROT_RA
;
217 route
->pref
= preference
;
219 route
->lifetime
= time_now
+ lifetime
* USEC_PER_SEC
;
222 r
= route_configure(route
, link
, ndisc_route_handler
);
224 log_link_warning_errno(link
, r
, "Could not set default route: %m");
225 link_enter_failed(link
);
229 link
->ndisc_routes_messages
++;
232 LIST_FOREACH(routes
, route_gw
, link
->network
->static_routes
) {
233 if (!route_gw
->gateway_from_dhcp
)
236 if (route_gw
->family
!= AF_INET6
)
239 route_gw
->gw
= gateway
;
241 r
= route_configure(route_gw
, link
, ndisc_route_handler
);
243 log_link_error_errno(link
, r
, "Could not set gateway: %m");
244 link_enter_failed(link
);
248 link
->ndisc_routes_messages
++;
254 static int ndisc_router_generate_addresses(Link
*link
, unsigned prefixlen
, uint32_t lifetime_preferred
, Address
*address
, Set
**ret
) {
255 _cleanup_set_free_free_ Set
*addresses
= NULL
;
256 struct in6_addr addr
;
265 addresses
= set_new(&address_hash_ops
);
269 addr
= address
->in_addr
.in6
;
270 ORDERED_HASHMAP_FOREACH(j
, link
->network
->ipv6_tokens
, i
) {
271 bool have_address
= false;
272 _cleanup_(address_freep
) Address
*new_address
= NULL
;
274 r
= address_new(&new_address
);
278 *new_address
= *address
;
280 if (j
->address_generation_type
== IPV6_TOKEN_ADDRESS_GENERATION_PREFIXSTABLE
281 && memcmp(&j
->prefix
, &addr
, FAMILY_ADDRESS_SIZE(address
->family
)) == 0) {
282 /* While this loop uses dad_counter and a retry limit as specified in RFC 7217, the loop
283 does not actually attempt Duplicate Address Detection; the counter will be incremented
284 only when the address generation algorithm produces an invalid address, and the loop
285 may exit with an address which ends up being unusable due to duplication on the link.
287 for (; j
->dad_counter
< DAD_CONFLICTS_IDGEN_RETRIES_RFC7217
; j
->dad_counter
++) {
288 r
= make_stableprivate_address(link
, &j
->prefix
, prefixlen
, j
->dad_counter
, &new_address
->in_addr
.in6
);
292 if (stableprivate_address_is_valid(&new_address
->in_addr
.in6
)) {
297 } else if (j
->address_generation_type
== IPV6_TOKEN_ADDRESS_GENERATION_STATIC
) {
298 memcpy(new_address
->in_addr
.in6
.s6_addr
+ 8, j
->prefix
.s6_addr
+ 8, 8);
303 new_address
->prefixlen
= prefixlen
;
304 new_address
->flags
= IFA_F_NOPREFIXROUTE
|IFA_F_MANAGETEMPADDR
;
305 new_address
->cinfo
.ifa_prefered
= lifetime_preferred
;
307 r
= set_put(addresses
, new_address
);
309 return log_link_warning_errno(link
, r
, "Failed to store address: %m");
310 TAKE_PTR(new_address
);
314 /* fall back to EUI-64 if no tokens provided addresses */
315 if (set_isempty(addresses
)) {
316 _cleanup_(address_freep
) Address
*new_address
= NULL
;
318 r
= address_new(&new_address
);
322 *new_address
= *address
;
324 r
= generate_ipv6_eui_64_address(link
, &new_address
->in_addr
.in6
);
326 return log_link_error_errno(link
, r
, "Failed to generate EUI64 address: %m");
328 new_address
->prefixlen
= prefixlen
;
329 new_address
->flags
= IFA_F_NOPREFIXROUTE
|IFA_F_MANAGETEMPADDR
;
330 new_address
->cinfo
.ifa_prefered
= lifetime_preferred
;
332 r
= set_put(addresses
, new_address
);
334 return log_link_warning_errno(link
, r
, "Failed to store address: %m");
335 TAKE_PTR(new_address
);
338 *ret
= TAKE_PTR(addresses
);
343 static int ndisc_router_process_autonomous_prefix(Link
*link
, sd_ndisc_router
*rt
) {
344 uint32_t lifetime_valid
, lifetime_preferred
, lifetime_remaining
;
345 _cleanup_set_free_free_ Set
*addresses
= NULL
;
346 _cleanup_(address_freep
) Address
*address
= NULL
;
349 Address
*existing_address
, *a
;
356 r
= sd_ndisc_router_get_timestamp(rt
, clock_boottime_or_monotonic(), &time_now
);
358 return log_link_warning_errno(link
, r
, "Failed to get RA timestamp: %m");
360 r
= sd_ndisc_router_prefix_get_prefixlen(rt
, &prefixlen
);
362 return log_link_error_errno(link
, r
, "Failed to get prefix length: %m");
364 r
= sd_ndisc_router_prefix_get_valid_lifetime(rt
, &lifetime_valid
);
366 return log_link_error_errno(link
, r
, "Failed to get prefix valid lifetime: %m");
368 r
= sd_ndisc_router_prefix_get_preferred_lifetime(rt
, &lifetime_preferred
);
370 return log_link_error_errno(link
, r
, "Failed to get prefix preferred lifetime: %m");
372 /* The preferred lifetime is never greater than the valid lifetime */
373 if (lifetime_preferred
> lifetime_valid
)
376 r
= address_new(&address
);
378 return log_link_error_errno(link
, r
, "Could not allocate address: %m");
380 address
->family
= AF_INET6
;
381 r
= sd_ndisc_router_prefix_get_address(rt
, &address
->in_addr
.in6
);
383 return log_link_error_errno(link
, r
, "Failed to get prefix address: %m");
385 r
= ndisc_router_generate_addresses(link
, prefixlen
, lifetime_preferred
, address
, &addresses
);
387 return log_link_error_errno(link
, r
, "Failed to generate SLAAC addresses: %m");
389 SET_FOREACH(a
, addresses
, i
) {
390 /* see RFC4862 section 5.5.3.e */
391 r
= address_get(link
, a
->family
, &a
->in_addr
, a
->prefixlen
, &existing_address
);
393 lifetime_remaining
= existing_address
->cinfo
.tstamp
/ 100 + existing_address
->cinfo
.ifa_valid
- time_now
/ USEC_PER_SEC
;
394 if (lifetime_valid
> NDISC_PREFIX_LFT_MIN
|| lifetime_valid
> lifetime_remaining
)
395 a
->cinfo
.ifa_valid
= lifetime_valid
;
396 else if (lifetime_remaining
<= NDISC_PREFIX_LFT_MIN
)
397 a
->cinfo
.ifa_valid
= lifetime_remaining
;
399 a
->cinfo
.ifa_valid
= NDISC_PREFIX_LFT_MIN
;
400 } else if (lifetime_valid
> 0)
401 a
->cinfo
.ifa_valid
= lifetime_valid
;
403 continue; /* see RFC4862 section 5.5.3.d */
405 if (a
->cinfo
.ifa_valid
== 0)
408 r
= address_configure(a
, link
, ndisc_address_handler
, true);
410 log_link_warning_errno(link
, r
, "Could not set SLAAC address: %m");
411 link_enter_failed(link
);
415 link
->ndisc_addresses_messages
++;
421 static int ndisc_router_process_onlink_prefix(Link
*link
, sd_ndisc_router
*rt
) {
422 _cleanup_(route_freep
) Route
*route
= NULL
;
431 r
= sd_ndisc_router_get_timestamp(rt
, clock_boottime_or_monotonic(), &time_now
);
433 return log_link_warning_errno(link
, r
, "Failed to get RA timestamp: %m");
435 r
= sd_ndisc_router_prefix_get_prefixlen(rt
, &prefixlen
);
437 return log_link_error_errno(link
, r
, "Failed to get prefix length: %m");
439 r
= sd_ndisc_router_prefix_get_valid_lifetime(rt
, &lifetime
);
441 return log_link_error_errno(link
, r
, "Failed to get prefix lifetime: %m");
443 r
= route_new(&route
);
445 return log_link_error_errno(link
, r
, "Could not allocate route: %m");
447 route
->family
= AF_INET6
;
448 route
->table
= link_get_ipv6_accept_ra_route_table(link
);
449 route
->priority
= link
->network
->dhcp6_route_metric
;
450 route
->protocol
= RTPROT_RA
;
451 route
->flags
= RTM_F_PREFIX
;
452 route
->dst_prefixlen
= prefixlen
;
453 route
->lifetime
= time_now
+ lifetime
* USEC_PER_SEC
;
455 r
= sd_ndisc_router_prefix_get_address(rt
, &route
->dst
.in6
);
457 return log_link_error_errno(link
, r
, "Failed to get prefix address: %m");
459 r
= route_configure(route
, link
, ndisc_route_handler
);
461 log_link_warning_errno(link
, r
, "Could not set prefix route: %m");
462 link_enter_failed(link
);
466 link
->ndisc_routes_messages
++;
471 static int ndisc_router_process_route(Link
*link
, sd_ndisc_router
*rt
) {
472 _cleanup_(route_freep
) Route
*route
= NULL
;
473 struct in6_addr gateway
;
475 unsigned preference
, prefixlen
;
481 r
= sd_ndisc_router_route_get_lifetime(rt
, &lifetime
);
483 return log_link_warning_errno(link
, r
, "Failed to get gateway address from RA: %m");
488 r
= sd_ndisc_router_get_address(rt
, &gateway
);
490 return log_link_warning_errno(link
, r
, "Failed to get gateway address from RA: %m");
492 r
= sd_ndisc_router_route_get_prefixlen(rt
, &prefixlen
);
494 return log_link_warning_errno(link
, r
, "Failed to get route prefix length: %m");
496 r
= sd_ndisc_router_route_get_preference(rt
, &preference
);
498 return log_link_warning_errno(link
, r
, "Failed to get default router preference from RA: %m");
500 r
= sd_ndisc_router_get_timestamp(rt
, clock_boottime_or_monotonic(), &time_now
);
502 return log_link_warning_errno(link
, r
, "Failed to get RA timestamp: %m");
504 r
= route_new(&route
);
506 return log_link_error_errno(link
, r
, "Could not allocate route: %m");
508 route
->family
= AF_INET6
;
509 route
->table
= link_get_ipv6_accept_ra_route_table(link
);
510 route
->priority
= link
->network
->dhcp6_route_metric
;
511 route
->protocol
= RTPROT_RA
;
512 route
->pref
= preference
;
513 route
->gw
.in6
= gateway
;
514 route
->dst_prefixlen
= prefixlen
;
515 route
->lifetime
= time_now
+ lifetime
* USEC_PER_SEC
;
517 r
= sd_ndisc_router_route_get_address(rt
, &route
->dst
.in6
);
519 return log_link_error_errno(link
, r
, "Failed to get route address: %m");
521 r
= route_configure(route
, link
, ndisc_route_handler
);
523 log_link_warning_errno(link
, r
, "Could not set additional route: %m");
524 link_enter_failed(link
);
528 link
->ndisc_routes_messages
++;
533 static void ndisc_rdnss_hash_func(const NDiscRDNSS
*x
, struct siphash
*state
) {
534 siphash24_compress(&x
->address
, sizeof(x
->address
), state
);
537 static int ndisc_rdnss_compare_func(const NDiscRDNSS
*a
, const NDiscRDNSS
*b
) {
538 return memcmp(&a
->address
, &b
->address
, sizeof(a
->address
));
541 DEFINE_PRIVATE_HASH_OPS(ndisc_rdnss_hash_ops
, NDiscRDNSS
, ndisc_rdnss_hash_func
, ndisc_rdnss_compare_func
);
543 static int ndisc_router_process_rdnss(Link
*link
, sd_ndisc_router
*rt
) {
545 const struct in6_addr
*a
;
552 r
= sd_ndisc_router_get_timestamp(rt
, clock_boottime_or_monotonic(), &time_now
);
554 return log_link_warning_errno(link
, r
, "Failed to get RA timestamp: %m");
556 r
= sd_ndisc_router_rdnss_get_lifetime(rt
, &lifetime
);
558 return log_link_warning_errno(link
, r
, "Failed to get RDNSS lifetime: %m");
560 n
= sd_ndisc_router_rdnss_get_addresses(rt
, &a
);
562 return log_link_warning_errno(link
, n
, "Failed to get RDNSS addresses: %m");
564 for (i
= 0; i
< n
; i
++) {
565 _cleanup_free_ NDiscRDNSS
*x
= NULL
;
571 (void) set_remove(link
->ndisc_rdnss
, &d
);
576 y
= set_get(link
->ndisc_rdnss
, &d
);
578 y
->valid_until
= time_now
+ lifetime
* USEC_PER_SEC
;
584 if (set_size(link
->ndisc_rdnss
) >= NDISC_RDNSS_MAX
) {
585 log_link_warning(link
, "Too many RDNSS records per link, ignoring.");
589 x
= new(NDiscRDNSS
, 1);
595 .valid_until
= time_now
+ lifetime
* USEC_PER_SEC
,
598 r
= set_ensure_consume(&link
->ndisc_rdnss
, &ndisc_rdnss_hash_ops
, TAKE_PTR(x
));
609 static void ndisc_dnssl_hash_func(const NDiscDNSSL
*x
, struct siphash
*state
) {
610 siphash24_compress(NDISC_DNSSL_DOMAIN(x
), strlen(NDISC_DNSSL_DOMAIN(x
)), state
);
613 static int ndisc_dnssl_compare_func(const NDiscDNSSL
*a
, const NDiscDNSSL
*b
) {
614 return strcmp(NDISC_DNSSL_DOMAIN(a
), NDISC_DNSSL_DOMAIN(b
));
617 DEFINE_PRIVATE_HASH_OPS(ndisc_dnssl_hash_ops
, NDiscDNSSL
, ndisc_dnssl_hash_func
, ndisc_dnssl_compare_func
);
619 static void ndisc_router_process_dnssl(Link
*link
, sd_ndisc_router
*rt
) {
620 _cleanup_strv_free_
char **l
= NULL
;
629 r
= sd_ndisc_router_get_timestamp(rt
, clock_boottime_or_monotonic(), &time_now
);
631 log_link_warning_errno(link
, r
, "Failed to get RA timestamp: %m");
635 r
= sd_ndisc_router_dnssl_get_lifetime(rt
, &lifetime
);
637 log_link_warning_errno(link
, r
, "Failed to get RDNSS lifetime: %m");
641 r
= sd_ndisc_router_dnssl_get_domains(rt
, &l
);
643 log_link_warning_errno(link
, r
, "Failed to get RDNSS addresses: %m");
648 _cleanup_free_ NDiscDNSSL
*s
;
651 s
= malloc0(ALIGN(sizeof(NDiscDNSSL
)) + strlen(*i
) + 1);
657 strcpy(NDISC_DNSSL_DOMAIN(s
), *i
);
660 (void) set_remove(link
->ndisc_dnssl
, s
);
665 x
= set_get(link
->ndisc_dnssl
, s
);
667 x
->valid_until
= time_now
+ lifetime
* USEC_PER_SEC
;
673 if (set_size(link
->ndisc_dnssl
) >= NDISC_DNSSL_MAX
) {
674 log_link_warning(link
, "Too many DNSSL records per link, ignoring.");
678 s
->valid_until
= time_now
+ lifetime
* USEC_PER_SEC
;
680 r
= set_ensure_consume(&link
->ndisc_dnssl
, &ndisc_dnssl_hash_ops
, TAKE_PTR(s
));
691 static int ndisc_router_process_options(Link
*link
, sd_ndisc_router
*rt
) {
695 assert(link
->network
);
698 r
= sd_ndisc_router_option_rewind(rt
);
703 return log_link_warning_errno(link
, r
, "Failed to iterate through options: %m");
704 if (r
== 0) /* EOF */
707 r
= sd_ndisc_router_option_get_type(rt
, &type
);
709 return log_link_warning_errno(link
, r
, "Failed to get RA option type: %m");
713 case SD_NDISC_OPTION_PREFIX_INFORMATION
: {
714 union in_addr_union a
;
717 r
= sd_ndisc_router_prefix_get_address(rt
, &a
.in6
);
719 return log_link_error_errno(link
, r
, "Failed to get prefix address: %m");
721 if (set_contains(link
->network
->ndisc_deny_listed_prefix
, &a
.in6
)) {
723 _cleanup_free_
char *b
= NULL
;
725 (void) in_addr_to_string(AF_INET6
, &a
, &b
);
726 log_link_debug(link
, "Prefix '%s' is deny-listed, ignoring", strna(b
));
732 r
= sd_ndisc_router_prefix_get_flags(rt
, &flags
);
734 return log_link_warning_errno(link
, r
, "Failed to get RA prefix flags: %m");
736 if (link
->network
->ipv6_accept_ra_use_onlink_prefix
&&
737 FLAGS_SET(flags
, ND_OPT_PI_FLAG_ONLINK
))
738 (void) ndisc_router_process_onlink_prefix(link
, rt
);
740 if (link
->network
->ipv6_accept_ra_use_autonomous_prefix
&&
741 FLAGS_SET(flags
, ND_OPT_PI_FLAG_AUTO
))
742 (void) ndisc_router_process_autonomous_prefix(link
, rt
);
747 case SD_NDISC_OPTION_ROUTE_INFORMATION
:
748 (void) ndisc_router_process_route(link
, rt
);
751 case SD_NDISC_OPTION_RDNSS
:
752 if (link
->network
->ipv6_accept_ra_use_dns
)
753 (void) ndisc_router_process_rdnss(link
, rt
);
756 case SD_NDISC_OPTION_DNSSL
:
757 if (link
->network
->ipv6_accept_ra_use_dns
)
758 (void) ndisc_router_process_dnssl(link
, rt
);
762 r
= sd_ndisc_router_option_next(rt
);
768 static int ndisc_router_handler(Link
*link
, sd_ndisc_router
*rt
) {
773 assert(link
->network
);
774 assert(link
->manager
);
777 r
= sd_ndisc_router_get_flags(rt
, &flags
);
779 return log_link_warning_errno(link
, r
, "Failed to get RA flags: %m");
781 if ((flags
& (ND_RA_FLAG_MANAGED
| ND_RA_FLAG_OTHER
) && link
->network
->ipv6_accept_ra_start_dhcp6_client
)) {
783 if (link
->network
->ipv6_accept_ra_start_dhcp6_client
== IPV6_ACCEPT_RA_START_DHCP6_CLIENT_ALWAYS
)
784 r
= dhcp6_request_address(link
, false);
786 /* (re)start DHCPv6 client in stateful or stateless mode according to RA flags */
787 r
= dhcp6_request_address(link
, !(flags
& ND_RA_FLAG_MANAGED
));
789 if (r
< 0 && r
!= -EBUSY
)
790 log_link_warning_errno(link
, r
, "Could not acquire DHCPv6 lease on NDisc request: %m");
792 log_link_debug(link
, "Acquiring DHCPv6 lease on NDisc request");
797 (void) ndisc_router_process_default(link
, rt
);
798 (void) ndisc_router_process_options(link
, rt
);
803 static void ndisc_handler(sd_ndisc
*nd
, sd_ndisc_event event
, sd_ndisc_router
*rt
, void *userdata
) {
804 Link
*link
= userdata
;
808 if (IN_SET(link
->state
, LINK_STATE_FAILED
, LINK_STATE_LINGER
))
813 case SD_NDISC_EVENT_ROUTER
:
814 link
->ndisc_addresses_configured
= false;
815 link
->ndisc_routes_configured
= false;
817 (void) ndisc_router_handler(link
, rt
);
819 if (link
->ndisc_addresses_messages
== 0)
820 link
->ndisc_addresses_configured
= true;
822 log_link_debug(link
, "Setting SLAAC addresses.");
824 if (link
->ndisc_routes_messages
== 0)
825 link
->ndisc_routes_configured
= true;
827 log_link_debug(link
, "Setting NDisc routes.");
829 if (link
->ndisc_addresses_configured
&& link
->ndisc_routes_configured
)
830 link_check_ready(link
);
832 link_set_state(link
, LINK_STATE_CONFIGURING
);
835 case SD_NDISC_EVENT_TIMEOUT
:
836 log_link_debug(link
, "NDISC handler get timeout event");
837 link
->ndisc_addresses_configured
= true;
838 link
->ndisc_routes_configured
= true;
839 link_check_ready(link
);
843 log_link_warning(link
, "IPv6 Neighbor Discovery unknown event: %d", event
);
847 int ndisc_configure(Link
*link
) {
852 r
= sd_ndisc_new(&link
->ndisc
);
856 r
= sd_ndisc_attach_event(link
->ndisc
, NULL
, 0);
860 r
= sd_ndisc_set_mac(link
->ndisc
, &link
->mac
);
864 r
= sd_ndisc_set_ifindex(link
->ndisc
, link
->ifindex
);
868 r
= sd_ndisc_set_callback(link
->ndisc
, ndisc_handler
, link
);
875 void ndisc_vacuum(Link
*link
) {
883 /* Removes all RDNSS and DNSSL entries whose validity time has passed */
885 time_now
= now(clock_boottime_or_monotonic());
887 SET_FOREACH(r
, link
->ndisc_rdnss
, i
)
888 if (r
->valid_until
< time_now
) {
889 free(set_remove(link
->ndisc_rdnss
, r
));
893 SET_FOREACH(d
, link
->ndisc_dnssl
, i
)
894 if (d
->valid_until
< time_now
) {
895 free(set_remove(link
->ndisc_dnssl
, d
));
900 void ndisc_flush(Link
*link
) {
903 /* Removes all RDNSS and DNSSL entries, without exception */
905 link
->ndisc_rdnss
= set_free_free(link
->ndisc_rdnss
);
906 link
->ndisc_dnssl
= set_free_free(link
->ndisc_dnssl
);
909 int ipv6token_new(IPv6Token
**ret
) {
912 p
= new(IPv6Token
, 1);
917 .address_generation_type
= IPV6_TOKEN_ADDRESS_GENERATION_NONE
,
925 DEFINE_HASH_OPS_WITH_VALUE_DESTRUCTOR(
929 trivial_compare_func
,
933 int config_parse_ndisc_deny_listed_prefix(
935 const char *filename
,
938 unsigned section_line
,
945 Network
*network
= data
;
954 if (isempty(rvalue
)) {
955 network
->ndisc_deny_listed_prefix
= set_free_free(network
->ndisc_deny_listed_prefix
);
960 _cleanup_free_
char *n
= NULL
;
961 _cleanup_free_
struct in6_addr
*a
= NULL
;
962 union in_addr_union ip
;
964 r
= extract_first_word(&p
, &n
, NULL
, 0);
966 log_syntax(unit
, LOG_ERR
, filename
, line
, r
,
967 "Failed to parse NDISC deny-listed prefix, ignoring assignment: %s",
974 r
= in_addr_from_string(AF_INET6
, n
, &ip
);
976 log_syntax(unit
, LOG_ERR
, filename
, line
, r
,
977 "NDISC deny-listed prefix is invalid, ignoring assignment: %s", n
);
981 if (set_contains(network
->ndisc_deny_listed_prefix
, &ip
.in6
))
984 a
= newdup(struct in6_addr
, &ip
.in6
, 1);
988 r
= set_ensure_consume(&network
->ndisc_deny_listed_prefix
, &in6_addr_hash_ops
, TAKE_PTR(a
));
996 int config_parse_address_generation_type(
998 const char *filename
,
1000 const char *section
,
1001 unsigned section_line
,
1008 _cleanup_free_ IPv6Token
*token
= NULL
;
1009 union in_addr_union buffer
;
1010 Network
*network
= data
;
1019 if (isempty(rvalue
)) {
1020 network
->ipv6_tokens
= ordered_hashmap_free(network
->ipv6_tokens
);
1024 r
= ipv6token_new(&token
);
1028 if ((p
= startswith(rvalue
, "static:")))
1029 token
->address_generation_type
= IPV6_TOKEN_ADDRESS_GENERATION_STATIC
;
1030 else if ((p
= startswith(rvalue
, "prefixstable:")))
1031 token
->address_generation_type
= IPV6_TOKEN_ADDRESS_GENERATION_PREFIXSTABLE
;
1033 token
->address_generation_type
= IPV6_TOKEN_ADDRESS_GENERATION_STATIC
;
1037 r
= in_addr_from_string(AF_INET6
, p
, &buffer
);
1039 log_syntax(unit
, LOG_ERR
, filename
, line
, r
,
1040 "Failed to parse IPv6 %s, ignoring: %s", lvalue
, rvalue
);
1044 if (in_addr_is_null(AF_INET6
, &buffer
)) {
1045 log_syntax(unit
, LOG_ERR
, filename
, line
, 0,
1046 "IPv6 %s cannot be the ANY address, ignoring: %s", lvalue
, rvalue
);
1050 token
->prefix
= buffer
.in6
;
1052 r
= ordered_hashmap_ensure_allocated(&network
->ipv6_tokens
, &ipv6_token_hash_ops
);
1056 r
= ordered_hashmap_put(network
->ipv6_tokens
, &token
->prefix
, token
);
1058 log_syntax(unit
, LOG_ERR
, filename
, line
, r
,
1059 "Failed to store IPv6 token '%s'", rvalue
);
1068 DEFINE_CONFIG_PARSE_ENUM(config_parse_ipv6_accept_ra_start_dhcp6_client
, ipv6_accept_ra_start_dhcp6_client
, IPv6AcceptRAStartDHCP6Client
,
1069 "Failed to parse DHCPv6Client= setting")
1070 static const char* const ipv6_accept_ra_start_dhcp6_client_table
[_IPV6_ACCEPT_RA_START_DHCP6_CLIENT_MAX
] = {
1071 [IPV6_ACCEPT_RA_START_DHCP6_CLIENT_NO
] = "no",
1072 [IPV6_ACCEPT_RA_START_DHCP6_CLIENT_ALWAYS
] = "always",
1073 [IPV6_ACCEPT_RA_START_DHCP6_CLIENT_YES
] = "yes",
1076 DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(ipv6_accept_ra_start_dhcp6_client
, IPv6AcceptRAStartDHCP6Client
, IPV6_ACCEPT_RA_START_DHCP6_CLIENT_YES
);