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 /* address_handler calls link_request_set_routes() and link_request_set_nexthop().
825 * Before they are called, the related flags must be cleared. Otherwise, the link
826 * becomes configured state before routes are configured. */
827 link
->static_routes_configured
= false;
828 link
->static_nexthops_configured
= false;
831 if (link
->ndisc_routes_messages
== 0)
832 link
->ndisc_routes_configured
= true;
834 log_link_debug(link
, "Setting NDisc routes.");
836 if (link
->ndisc_addresses_configured
&& link
->ndisc_routes_configured
)
837 link_check_ready(link
);
839 link_set_state(link
, LINK_STATE_CONFIGURING
);
842 case SD_NDISC_EVENT_TIMEOUT
:
843 log_link_debug(link
, "NDISC handler get timeout event");
844 link
->ndisc_addresses_configured
= true;
845 link
->ndisc_routes_configured
= true;
846 link_check_ready(link
);
850 log_link_warning(link
, "IPv6 Neighbor Discovery unknown event: %d", event
);
854 int ndisc_configure(Link
*link
) {
859 r
= sd_ndisc_new(&link
->ndisc
);
863 r
= sd_ndisc_attach_event(link
->ndisc
, NULL
, 0);
867 r
= sd_ndisc_set_mac(link
->ndisc
, &link
->mac
);
871 r
= sd_ndisc_set_ifindex(link
->ndisc
, link
->ifindex
);
875 r
= sd_ndisc_set_callback(link
->ndisc
, ndisc_handler
, link
);
882 void ndisc_vacuum(Link
*link
) {
890 /* Removes all RDNSS and DNSSL entries whose validity time has passed */
892 time_now
= now(clock_boottime_or_monotonic());
894 SET_FOREACH(r
, link
->ndisc_rdnss
, i
)
895 if (r
->valid_until
< time_now
) {
896 free(set_remove(link
->ndisc_rdnss
, r
));
900 SET_FOREACH(d
, link
->ndisc_dnssl
, i
)
901 if (d
->valid_until
< time_now
) {
902 free(set_remove(link
->ndisc_dnssl
, d
));
907 void ndisc_flush(Link
*link
) {
910 /* Removes all RDNSS and DNSSL entries, without exception */
912 link
->ndisc_rdnss
= set_free_free(link
->ndisc_rdnss
);
913 link
->ndisc_dnssl
= set_free_free(link
->ndisc_dnssl
);
916 int ipv6token_new(IPv6Token
**ret
) {
919 p
= new(IPv6Token
, 1);
924 .address_generation_type
= IPV6_TOKEN_ADDRESS_GENERATION_NONE
,
932 DEFINE_HASH_OPS_WITH_VALUE_DESTRUCTOR(
936 trivial_compare_func
,
940 int config_parse_ndisc_deny_listed_prefix(
942 const char *filename
,
945 unsigned section_line
,
952 Network
*network
= data
;
961 if (isempty(rvalue
)) {
962 network
->ndisc_deny_listed_prefix
= set_free_free(network
->ndisc_deny_listed_prefix
);
967 _cleanup_free_
char *n
= NULL
;
968 _cleanup_free_
struct in6_addr
*a
= NULL
;
969 union in_addr_union ip
;
971 r
= extract_first_word(&p
, &n
, NULL
, 0);
973 log_syntax(unit
, LOG_ERR
, filename
, line
, r
,
974 "Failed to parse NDISC deny-listed prefix, ignoring assignment: %s",
981 r
= in_addr_from_string(AF_INET6
, n
, &ip
);
983 log_syntax(unit
, LOG_ERR
, filename
, line
, r
,
984 "NDISC deny-listed prefix is invalid, ignoring assignment: %s", n
);
988 if (set_contains(network
->ndisc_deny_listed_prefix
, &ip
.in6
))
991 a
= newdup(struct in6_addr
, &ip
.in6
, 1);
995 r
= set_ensure_consume(&network
->ndisc_deny_listed_prefix
, &in6_addr_hash_ops
, TAKE_PTR(a
));
1003 int config_parse_address_generation_type(
1005 const char *filename
,
1007 const char *section
,
1008 unsigned section_line
,
1015 _cleanup_free_ IPv6Token
*token
= NULL
;
1016 union in_addr_union buffer
;
1017 Network
*network
= data
;
1026 if (isempty(rvalue
)) {
1027 network
->ipv6_tokens
= ordered_hashmap_free(network
->ipv6_tokens
);
1031 r
= ipv6token_new(&token
);
1035 if ((p
= startswith(rvalue
, "static:")))
1036 token
->address_generation_type
= IPV6_TOKEN_ADDRESS_GENERATION_STATIC
;
1037 else if ((p
= startswith(rvalue
, "prefixstable:")))
1038 token
->address_generation_type
= IPV6_TOKEN_ADDRESS_GENERATION_PREFIXSTABLE
;
1040 token
->address_generation_type
= IPV6_TOKEN_ADDRESS_GENERATION_STATIC
;
1044 r
= in_addr_from_string(AF_INET6
, p
, &buffer
);
1046 log_syntax(unit
, LOG_ERR
, filename
, line
, r
,
1047 "Failed to parse IPv6 %s, ignoring: %s", lvalue
, rvalue
);
1051 if (in_addr_is_null(AF_INET6
, &buffer
)) {
1052 log_syntax(unit
, LOG_ERR
, filename
, line
, 0,
1053 "IPv6 %s cannot be the ANY address, ignoring: %s", lvalue
, rvalue
);
1057 token
->prefix
= buffer
.in6
;
1059 r
= ordered_hashmap_ensure_allocated(&network
->ipv6_tokens
, &ipv6_token_hash_ops
);
1063 r
= ordered_hashmap_put(network
->ipv6_tokens
, &token
->prefix
, token
);
1065 log_syntax(unit
, LOG_ERR
, filename
, line
, r
,
1066 "Failed to store IPv6 token '%s'", rvalue
);
1075 DEFINE_CONFIG_PARSE_ENUM(config_parse_ipv6_accept_ra_start_dhcp6_client
, ipv6_accept_ra_start_dhcp6_client
, IPv6AcceptRAStartDHCP6Client
,
1076 "Failed to parse DHCPv6Client= setting")
1077 static const char* const ipv6_accept_ra_start_dhcp6_client_table
[_IPV6_ACCEPT_RA_START_DHCP6_CLIENT_MAX
] = {
1078 [IPV6_ACCEPT_RA_START_DHCP6_CLIENT_NO
] = "no",
1079 [IPV6_ACCEPT_RA_START_DHCP6_CLIENT_ALWAYS
] = "always",
1080 [IPV6_ACCEPT_RA_START_DHCP6_CLIENT_YES
] = "yes",
1083 DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(ipv6_accept_ra_start_dhcp6_client
, IPv6AcceptRAStartDHCP6Client
, IPV6_ACCEPT_RA_START_DHCP6_CLIENT_YES
);