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 int ndisc_remove_old(Link
*link
, bool force
);
40 static int ndisc_address_callback(Address
*address
) {
45 assert(address
->link
);
47 /* Make this called only once */
48 SET_FOREACH(a
, address
->link
->ndisc_addresses
, i
)
51 return ndisc_remove_old(address
->link
, true);
54 static int ndisc_remove_old(Link
*link
, bool force
) {
65 bool set_callback
= !set_isempty(link
->ndisc_addresses
);
67 if (!link
->ndisc_addresses_configured
|| !link
->ndisc_routes_configured
)
70 SET_FOREACH(address
, link
->ndisc_addresses
, i
)
71 if (address_is_ready(address
)) {
77 SET_FOREACH(address
, link
->ndisc_addresses
, i
)
78 address
->callback
= ndisc_address_callback
;
83 if (!set_isempty(link
->ndisc_addresses_old
) || !set_isempty(link
->ndisc_routes_old
))
84 log_link_debug(link
, "Removing old NDisc addresses and routes.");
88 SET_FOREACH(address
, link
->ndisc_addresses_old
, i
) {
89 k
= address_remove(address
, link
, NULL
);
94 SET_FOREACH(route
, link
->ndisc_routes_old
, i
) {
95 k
= route_remove(route
, link
, NULL
);
100 SET_FOREACH(rdnss
, link
->ndisc_rdnss
, i
)
102 free(set_remove(link
->ndisc_rdnss
, rdnss
));
104 SET_FOREACH(dnssl
, link
->ndisc_dnssl
, i
)
106 free(set_remove(link
->ndisc_dnssl
, dnssl
));
111 static int ndisc_route_handler(sd_netlink
*rtnl
, sd_netlink_message
*m
, Link
*link
) {
115 assert(link
->ndisc_routes_messages
> 0);
117 link
->ndisc_routes_messages
--;
119 if (IN_SET(link
->state
, LINK_STATE_FAILED
, LINK_STATE_LINGER
))
122 r
= sd_netlink_message_get_errno(m
);
123 if (r
< 0 && r
!= -EEXIST
) {
124 log_link_message_error_errno(link
, m
, r
, "Could not set NDisc route");
125 link_enter_failed(link
);
129 if (link
->ndisc_routes_messages
== 0) {
130 log_link_debug(link
, "NDisc routes set.");
131 link
->ndisc_routes_configured
= true;
133 r
= ndisc_remove_old(link
, false);
135 link_enter_failed(link
);
139 link_check_ready(link
);
145 static int ndisc_address_handler(sd_netlink
*rtnl
, sd_netlink_message
*m
, Link
*link
) {
149 assert(link
->ndisc_addresses_messages
> 0);
151 link
->ndisc_addresses_messages
--;
153 if (IN_SET(link
->state
, LINK_STATE_FAILED
, LINK_STATE_LINGER
))
156 r
= sd_netlink_message_get_errno(m
);
157 if (r
< 0 && r
!= -EEXIST
) {
158 log_link_message_error_errno(link
, m
, r
, "Could not set NDisc address");
159 link_enter_failed(link
);
162 (void) manager_rtnl_process_address(rtnl
, m
, link
->manager
);
164 if (link
->ndisc_addresses_messages
== 0) {
165 log_link_debug(link
, "NDisc SLAAC addresses set.");
166 link
->ndisc_addresses_configured
= true;
168 r
= ndisc_remove_old(link
, false);
170 link_enter_failed(link
);
174 r
= link_request_set_routes(link
);
176 link_enter_failed(link
);
184 static int ndisc_route_configure(Route
*route
, Link
*link
) {
191 r
= route_configure(route
, link
, ndisc_route_handler
, &ret
);
193 return log_link_error_errno(link
, r
, "Failed to set NDisc route: %m");
195 link
->ndisc_routes_messages
++;
197 r
= set_ensure_put(&link
->ndisc_routes
, &route_hash_ops
, ret
);
199 return log_link_error_errno(link
, r
, "Failed to store NDisc route: %m");
201 (void) set_remove(link
->ndisc_routes_old
, ret
);
206 static int ndisc_address_configure(Address
*address
, Link
*link
) {
213 r
= address_configure(address
, link
, ndisc_address_handler
, true, &ret
);
215 return log_link_error_errno(link
, r
, "Failed to set NDisc SLAAC address: %m");
217 link
->ndisc_addresses_messages
++;
219 r
= set_ensure_put(&link
->ndisc_addresses
, &address_hash_ops
, ret
);
221 return log_link_error_errno(link
, r
, "Failed to store NDisc SLAAC address: %m");
223 (void) set_remove(link
->ndisc_addresses_old
, ret
);
228 static int ndisc_router_process_default(Link
*link
, sd_ndisc_router
*rt
) {
229 _cleanup_(route_freep
) Route
*route
= NULL
;
230 union in_addr_union gateway
;
240 r
= sd_ndisc_router_get_lifetime(rt
, &lifetime
);
242 return log_link_error_errno(link
, r
, "Failed to get gateway lifetime from RA: %m");
244 if (lifetime
== 0) /* not a default router */
247 r
= sd_ndisc_router_get_address(rt
, &gateway
.in6
);
249 return log_link_error_errno(link
, r
, "Failed to get gateway address from RA: %m");
251 if (address_exists(link
, AF_INET6
, &gateway
)) {
253 _cleanup_free_
char *buffer
= NULL
;
255 (void) in_addr_to_string(AF_INET6
, &gateway
, &buffer
);
256 log_link_debug(link
, "No NDisc route added, gateway %s matches local address",
262 r
= sd_ndisc_router_get_preference(rt
, &preference
);
264 return log_link_error_errno(link
, r
, "Failed to get default router preference from RA: %m");
266 r
= sd_ndisc_router_get_timestamp(rt
, clock_boottime_or_monotonic(), &time_now
);
268 return log_link_error_errno(link
, r
, "Failed to get RA timestamp: %m");
270 r
= sd_ndisc_router_get_mtu(rt
, &mtu
);
274 return log_link_error_errno(link
, r
, "Failed to get default router MTU from RA: %m");
276 r
= route_new(&route
);
280 route
->family
= AF_INET6
;
281 route
->table
= link_get_ipv6_accept_ra_route_table(link
);
282 route
->priority
= link
->network
->dhcp6_route_metric
;
283 route
->protocol
= RTPROT_RA
;
284 route
->pref
= preference
;
286 route
->lifetime
= time_now
+ lifetime
* USEC_PER_SEC
;
289 r
= ndisc_route_configure(route
, link
);
291 return log_link_error_errno(link
, r
, "Could not set default route: %m");
294 LIST_FOREACH(routes
, route_gw
, link
->network
->static_routes
) {
295 if (!route_gw
->gateway_from_dhcp
)
298 if (route_gw
->family
!= AF_INET6
)
301 route_gw
->gw
= gateway
;
303 r
= ndisc_route_configure(route_gw
, link
);
305 return log_link_error_errno(link
, r
, "Could not set gateway: %m");
311 static bool stableprivate_address_is_valid(const struct in6_addr
*addr
) {
314 /* According to rfc4291, generated address should not be in the following ranges. */
316 if (memcmp(addr
, &SUBNET_ROUTER_ANYCAST_ADDRESS_RFC4291
, SUBNET_ROUTER_ANYCAST_PREFIXLEN
) == 0)
319 if (memcmp(addr
, &RESERVED_IPV6_INTERFACE_IDENTIFIERS_ADDRESS_RFC4291
, RESERVED_IPV6_INTERFACE_IDENTIFIERS_PREFIXLEN
) == 0)
322 if (memcmp(addr
, &RESERVED_SUBNET_ANYCAST_ADDRESSES_RFC4291
, RESERVED_SUBNET_ANYCAST_PREFIXLEN
) == 0)
328 static int make_stableprivate_address(Link
*link
, const struct in6_addr
*prefix
, uint8_t prefix_len
, uint8_t dad_counter
, struct in6_addr
**ret
) {
329 _cleanup_free_
struct in6_addr
*addr
= NULL
;
330 sd_id128_t secret_key
;
331 struct siphash state
;
336 /* According to rfc7217 section 5.1
337 * RID = F(Prefix, Net_Iface, Network_ID, DAD_Counter, secret_key) */
339 r
= sd_id128_get_machine_app_specific(NDISC_APP_ID
, &secret_key
);
341 return log_error_errno(r
, "Failed to generate key: %m");
343 siphash24_init(&state
, secret_key
.bytes
);
345 l
= MAX(DIV_ROUND_UP(prefix_len
, 8), 8);
346 siphash24_compress(prefix
, l
, &state
);
347 siphash24_compress_string(link
->ifname
, &state
);
348 siphash24_compress(&link
->mac
, sizeof(struct ether_addr
), &state
);
349 siphash24_compress(&dad_counter
, sizeof(uint8_t), &state
);
351 rid
= htole64(siphash24_finalize(&state
));
353 addr
= new(struct in6_addr
, 1);
357 memcpy(addr
->s6_addr
, prefix
->s6_addr
, l
);
358 memcpy(addr
->s6_addr
+ l
, &rid
, 16 - l
);
360 if (!stableprivate_address_is_valid(addr
)) {
365 *ret
= TAKE_PTR(addr
);
369 static int ndisc_router_generate_addresses(Link
*link
, struct in6_addr
*address
, uint8_t prefixlen
, Set
**ret
) {
370 _cleanup_set_free_free_ Set
*addresses
= NULL
;
379 addresses
= set_new(&in6_addr_hash_ops
);
383 ORDERED_SET_FOREACH(j
, link
->network
->ipv6_tokens
, i
) {
384 _cleanup_free_
struct in6_addr
*new_address
= NULL
;
386 if (j
->address_generation_type
== IPV6_TOKEN_ADDRESS_GENERATION_PREFIXSTABLE
387 && IN6_ARE_ADDR_EQUAL(&j
->prefix
, address
)) {
388 /* While this loop uses dad_counter and a retry limit as specified in RFC 7217, the loop
389 does not actually attempt Duplicate Address Detection; the counter will be incremented
390 only when the address generation algorithm produces an invalid address, and the loop
391 may exit with an address which ends up being unusable due to duplication on the link.
393 for (; j
->dad_counter
< DAD_CONFLICTS_IDGEN_RETRIES_RFC7217
; j
->dad_counter
++) {
394 r
= make_stableprivate_address(link
, &j
->prefix
, prefixlen
, j
->dad_counter
, &new_address
);
400 } else if (j
->address_generation_type
== IPV6_TOKEN_ADDRESS_GENERATION_STATIC
) {
401 new_address
= new(struct in6_addr
, 1);
405 memcpy(new_address
->s6_addr
, address
->s6_addr
, 8);
406 memcpy(new_address
->s6_addr
+ 8, j
->prefix
.s6_addr
+ 8, 8);
410 r
= set_put(addresses
, new_address
);
412 return log_link_error_errno(link
, r
, "Failed to store SLAAC address: %m");
414 log_link_debug_errno(link
, r
, "Generated SLAAC address is duplicated, ignoring.");
416 TAKE_PTR(new_address
);
420 /* fall back to EUI-64 if no tokens provided addresses */
421 if (set_isempty(addresses
)) {
422 _cleanup_free_
struct in6_addr
*new_address
= NULL
;
424 new_address
= newdup(struct in6_addr
, address
, 1);
428 r
= generate_ipv6_eui_64_address(link
, new_address
);
430 return log_link_error_errno(link
, r
, "Failed to generate EUI64 address: %m");
432 r
= set_put(addresses
, new_address
);
434 return log_link_error_errno(link
, r
, "Failed to store SLAAC address: %m");
436 TAKE_PTR(new_address
);
439 *ret
= TAKE_PTR(addresses
);
444 static int ndisc_router_process_autonomous_prefix(Link
*link
, sd_ndisc_router
*rt
) {
445 uint32_t lifetime_valid
, lifetime_preferred
, lifetime_remaining
;
446 _cleanup_set_free_free_ Set
*addresses
= NULL
;
447 _cleanup_(address_freep
) Address
*address
= NULL
;
448 struct in6_addr addr
, *a
;
457 r
= sd_ndisc_router_get_timestamp(rt
, clock_boottime_or_monotonic(), &time_now
);
459 return log_link_error_errno(link
, r
, "Failed to get RA timestamp: %m");
461 r
= sd_ndisc_router_prefix_get_prefixlen(rt
, &prefixlen
);
463 return log_link_error_errno(link
, r
, "Failed to get prefix length: %m");
465 r
= sd_ndisc_router_prefix_get_valid_lifetime(rt
, &lifetime_valid
);
467 return log_link_error_errno(link
, r
, "Failed to get prefix valid lifetime: %m");
469 r
= sd_ndisc_router_prefix_get_preferred_lifetime(rt
, &lifetime_preferred
);
471 return log_link_error_errno(link
, r
, "Failed to get prefix preferred lifetime: %m");
473 /* The preferred lifetime is never greater than the valid lifetime */
474 if (lifetime_preferred
> lifetime_valid
)
477 r
= sd_ndisc_router_prefix_get_address(rt
, &addr
);
479 return log_link_error_errno(link
, r
, "Failed to get prefix address: %m");
481 r
= ndisc_router_generate_addresses(link
, &addr
, prefixlen
, &addresses
);
485 r
= address_new(&address
);
489 address
->family
= AF_INET6
;
490 address
->prefixlen
= prefixlen
;
491 address
->flags
= IFA_F_NOPREFIXROUTE
|IFA_F_MANAGETEMPADDR
;
492 address
->cinfo
.ifa_prefered
= lifetime_preferred
;
494 SET_FOREACH(a
, addresses
, i
) {
495 Address
*existing_address
;
497 /* see RFC4862 section 5.5.3.e */
498 r
= address_get(link
, AF_INET6
, (union in_addr_union
*) a
, prefixlen
, &existing_address
);
500 lifetime_remaining
= existing_address
->cinfo
.tstamp
/ 100 + existing_address
->cinfo
.ifa_valid
- time_now
/ USEC_PER_SEC
;
501 if (lifetime_valid
> NDISC_PREFIX_LFT_MIN
|| lifetime_valid
> lifetime_remaining
)
502 address
->cinfo
.ifa_valid
= lifetime_valid
;
503 else if (lifetime_remaining
<= NDISC_PREFIX_LFT_MIN
)
504 address
->cinfo
.ifa_valid
= lifetime_remaining
;
506 address
->cinfo
.ifa_valid
= NDISC_PREFIX_LFT_MIN
;
507 } else if (lifetime_valid
> 0)
508 address
->cinfo
.ifa_valid
= lifetime_valid
;
510 continue; /* see RFC4862 section 5.5.3.d */
512 if (address
->cinfo
.ifa_valid
== 0)
515 address
->in_addr
.in6
= *a
;
517 r
= ndisc_address_configure(address
, link
);
519 return log_link_error_errno(link
, r
, "Could not set SLAAC address: %m");
525 static int ndisc_router_process_onlink_prefix(Link
*link
, sd_ndisc_router
*rt
) {
526 _cleanup_(route_freep
) Route
*route
= NULL
;
535 r
= sd_ndisc_router_get_timestamp(rt
, clock_boottime_or_monotonic(), &time_now
);
537 return log_link_error_errno(link
, r
, "Failed to get RA timestamp: %m");
539 r
= sd_ndisc_router_prefix_get_prefixlen(rt
, &prefixlen
);
541 return log_link_error_errno(link
, r
, "Failed to get prefix length: %m");
543 r
= sd_ndisc_router_prefix_get_valid_lifetime(rt
, &lifetime
);
545 return log_link_error_errno(link
, r
, "Failed to get prefix lifetime: %m");
547 r
= route_new(&route
);
551 route
->family
= AF_INET6
;
552 route
->table
= link_get_ipv6_accept_ra_route_table(link
);
553 route
->priority
= link
->network
->dhcp6_route_metric
;
554 route
->protocol
= RTPROT_RA
;
555 route
->flags
= RTM_F_PREFIX
;
556 route
->dst_prefixlen
= prefixlen
;
557 route
->lifetime
= time_now
+ lifetime
* USEC_PER_SEC
;
559 r
= sd_ndisc_router_prefix_get_address(rt
, &route
->dst
.in6
);
561 return log_link_error_errno(link
, r
, "Failed to get prefix address: %m");
563 r
= ndisc_route_configure(route
, link
);
565 return log_link_error_errno(link
, r
, "Could not set prefix route: %m");;
570 static int ndisc_router_process_route(Link
*link
, sd_ndisc_router
*rt
) {
571 _cleanup_(route_freep
) Route
*route
= NULL
;
572 struct in6_addr gateway
;
574 unsigned preference
, prefixlen
;
580 r
= sd_ndisc_router_route_get_lifetime(rt
, &lifetime
);
582 return log_link_error_errno(link
, r
, "Failed to get gateway lifetime from RA: %m");
587 r
= sd_ndisc_router_get_address(rt
, &gateway
);
589 return log_link_error_errno(link
, r
, "Failed to get gateway address from RA: %m");
591 r
= sd_ndisc_router_route_get_prefixlen(rt
, &prefixlen
);
593 return log_link_error_errno(link
, r
, "Failed to get route prefix length: %m");
595 r
= sd_ndisc_router_route_get_preference(rt
, &preference
);
597 return log_link_error_errno(link
, r
, "Failed to get default router preference from RA: %m");
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
= route_new(&route
);
607 route
->family
= AF_INET6
;
608 route
->table
= link_get_ipv6_accept_ra_route_table(link
);
609 route
->priority
= link
->network
->dhcp6_route_metric
;
610 route
->protocol
= RTPROT_RA
;
611 route
->pref
= preference
;
612 route
->gw
.in6
= gateway
;
613 route
->dst_prefixlen
= prefixlen
;
614 route
->lifetime
= time_now
+ lifetime
* USEC_PER_SEC
;
616 r
= sd_ndisc_router_route_get_address(rt
, &route
->dst
.in6
);
618 return log_link_error_errno(link
, r
, "Failed to get route address: %m");
620 r
= ndisc_route_configure(route
, link
);
622 return log_link_error_errno(link
, r
, "Could not set additional route: %m");
627 static void ndisc_rdnss_hash_func(const NDiscRDNSS
*x
, struct siphash
*state
) {
628 siphash24_compress(&x
->address
, sizeof(x
->address
), state
);
631 static int ndisc_rdnss_compare_func(const NDiscRDNSS
*a
, const NDiscRDNSS
*b
) {
632 return memcmp(&a
->address
, &b
->address
, sizeof(a
->address
));
635 DEFINE_PRIVATE_HASH_OPS_WITH_KEY_DESTRUCTOR(
636 ndisc_rdnss_hash_ops
,
638 ndisc_rdnss_hash_func
,
639 ndisc_rdnss_compare_func
,
642 static int ndisc_router_process_rdnss(Link
*link
, sd_ndisc_router
*rt
) {
644 const struct in6_addr
*a
;
653 r
= sd_ndisc_router_get_timestamp(rt
, clock_boottime_or_monotonic(), &time_now
);
655 return log_link_error_errno(link
, r
, "Failed to get RA timestamp: %m");
657 r
= sd_ndisc_router_rdnss_get_lifetime(rt
, &lifetime
);
659 return log_link_error_errno(link
, r
, "Failed to get RDNSS lifetime: %m");
661 n
= sd_ndisc_router_rdnss_get_addresses(rt
, &a
);
663 return log_link_error_errno(link
, n
, "Failed to get RDNSS addresses: %m");
665 SET_FOREACH(rdnss
, link
->ndisc_rdnss
, i
)
666 rdnss
->marked
= true;
671 if (n
>= (int) NDISC_RDNSS_MAX
) {
672 log_link_warning(link
, "Too many RDNSS records per link. Only first %i records will be used.", NDISC_RDNSS_MAX
);
676 for (int j
= 0; j
< n
; j
++) {
677 _cleanup_free_ NDiscRDNSS
*x
= NULL
;
682 rdnss
= set_get(link
->ndisc_rdnss
, &d
);
684 rdnss
->marked
= false;
685 rdnss
->valid_until
= time_now
+ lifetime
* USEC_PER_SEC
;
689 x
= new(NDiscRDNSS
, 1);
695 .valid_until
= time_now
+ lifetime
* USEC_PER_SEC
,
698 r
= set_ensure_consume(&link
->ndisc_rdnss
, &ndisc_rdnss_hash_ops
, TAKE_PTR(x
));
707 static void ndisc_dnssl_hash_func(const NDiscDNSSL
*x
, struct siphash
*state
) {
708 siphash24_compress_string(NDISC_DNSSL_DOMAIN(x
), state
);
711 static int ndisc_dnssl_compare_func(const NDiscDNSSL
*a
, const NDiscDNSSL
*b
) {
712 return strcmp(NDISC_DNSSL_DOMAIN(a
), NDISC_DNSSL_DOMAIN(b
));
715 DEFINE_PRIVATE_HASH_OPS_WITH_KEY_DESTRUCTOR(
716 ndisc_dnssl_hash_ops
,
718 ndisc_dnssl_hash_func
,
719 ndisc_dnssl_compare_func
,
722 static int ndisc_router_process_dnssl(Link
*link
, sd_ndisc_router
*rt
) {
723 _cleanup_strv_free_
char **l
= NULL
;
734 r
= sd_ndisc_router_get_timestamp(rt
, clock_boottime_or_monotonic(), &time_now
);
736 return log_link_error_errno(link
, r
, "Failed to get RA timestamp: %m");
738 r
= sd_ndisc_router_dnssl_get_lifetime(rt
, &lifetime
);
740 return log_link_error_errno(link
, r
, "Failed to get DNSSL lifetime: %m");
742 r
= sd_ndisc_router_dnssl_get_domains(rt
, &l
);
744 return log_link_error_errno(link
, r
, "Failed to get DNSSL addresses: %m");
746 SET_FOREACH(dnssl
, link
->ndisc_dnssl
, i
)
747 dnssl
->marked
= true;
752 if (strv_length(l
) >= NDISC_DNSSL_MAX
) {
753 log_link_warning(link
, "Too many DNSSL records per link. Only first %i records will be used.", NDISC_DNSSL_MAX
);
754 STRV_FOREACH(j
, l
+ NDISC_DNSSL_MAX
)
759 _cleanup_free_ NDiscDNSSL
*s
= NULL
;
761 s
= malloc0(ALIGN(sizeof(NDiscDNSSL
)) + strlen(*j
) + 1);
765 strcpy(NDISC_DNSSL_DOMAIN(s
), *j
);
767 dnssl
= set_get(link
->ndisc_dnssl
, s
);
769 dnssl
->marked
= false;
770 dnssl
->valid_until
= time_now
+ lifetime
* USEC_PER_SEC
;
774 s
->valid_until
= time_now
+ lifetime
* USEC_PER_SEC
;
776 r
= set_ensure_consume(&link
->ndisc_dnssl
, &ndisc_dnssl_hash_ops
, TAKE_PTR(s
));
785 static int ndisc_router_process_options(Link
*link
, sd_ndisc_router
*rt
) {
787 assert(link
->network
);
790 for (int r
= sd_ndisc_router_option_rewind(rt
); ; r
= sd_ndisc_router_option_next(rt
)) {
794 return log_link_error_errno(link
, r
, "Failed to iterate through options: %m");
795 if (r
== 0) /* EOF */
798 r
= sd_ndisc_router_option_get_type(rt
, &type
);
800 return log_link_error_errno(link
, r
, "Failed to get RA option type: %m");
804 case SD_NDISC_OPTION_PREFIX_INFORMATION
: {
805 union in_addr_union a
;
808 r
= sd_ndisc_router_prefix_get_address(rt
, &a
.in6
);
810 return log_link_error_errno(link
, r
, "Failed to get prefix address: %m");
812 if (set_contains(link
->network
->ndisc_deny_listed_prefix
, &a
.in6
)) {
814 _cleanup_free_
char *b
= NULL
;
816 (void) in_addr_to_string(AF_INET6
, &a
, &b
);
817 log_link_debug(link
, "Prefix '%s' is deny-listed, ignoring", strna(b
));
822 r
= sd_ndisc_router_prefix_get_flags(rt
, &flags
);
824 return log_link_error_errno(link
, r
, "Failed to get RA prefix flags: %m");
826 if (link
->network
->ipv6_accept_ra_use_onlink_prefix
&&
827 FLAGS_SET(flags
, ND_OPT_PI_FLAG_ONLINK
)) {
828 r
= ndisc_router_process_onlink_prefix(link
, rt
);
833 if (link
->network
->ipv6_accept_ra_use_autonomous_prefix
&&
834 FLAGS_SET(flags
, ND_OPT_PI_FLAG_AUTO
)) {
835 r
= ndisc_router_process_autonomous_prefix(link
, rt
);
842 case SD_NDISC_OPTION_ROUTE_INFORMATION
:
843 r
= ndisc_router_process_route(link
, rt
);
848 case SD_NDISC_OPTION_RDNSS
:
849 if (link
->network
->ipv6_accept_ra_use_dns
) {
850 r
= ndisc_router_process_rdnss(link
, rt
);
856 case SD_NDISC_OPTION_DNSSL
:
857 if (link
->network
->ipv6_accept_ra_use_dns
) {
858 r
= ndisc_router_process_dnssl(link
, rt
);
867 static int ndisc_router_handler(Link
*link
, sd_ndisc_router
*rt
) {
874 assert(link
->network
);
875 assert(link
->manager
);
878 link
->ndisc_addresses_configured
= false;
879 link
->ndisc_routes_configured
= false;
883 while ((address
= set_steal_first(link
->ndisc_addresses
))) {
884 r
= set_ensure_put(&link
->ndisc_addresses_old
, &address_hash_ops
, address
);
886 return log_link_error_errno(link
, r
, "Failed to store old NDisc SLAAC address: %m");
889 while ((route
= set_steal_first(link
->ndisc_routes
))) {
890 r
= set_ensure_put(&link
->ndisc_routes_old
, &route_hash_ops
, route
);
892 return log_link_error_errno(link
, r
, "Failed to store old NDisc route: %m");
895 r
= sd_ndisc_router_get_flags(rt
, &flags
);
897 return log_link_error_errno(link
, r
, "Failed to get RA flags: %m");
899 if ((flags
& (ND_RA_FLAG_MANAGED
| ND_RA_FLAG_OTHER
) && link
->network
->ipv6_accept_ra_start_dhcp6_client
)) {
901 if (link
->network
->ipv6_accept_ra_start_dhcp6_client
== IPV6_ACCEPT_RA_START_DHCP6_CLIENT_ALWAYS
)
902 r
= dhcp6_request_address(link
, false);
904 /* (re)start DHCPv6 client in stateful or stateless mode according to RA flags */
905 r
= dhcp6_request_address(link
, !(flags
& ND_RA_FLAG_MANAGED
));
906 if (r
< 0 && r
!= -EBUSY
)
907 return log_link_error_errno(link
, r
, "Could not acquire DHCPv6 lease on NDisc request: %m");
909 log_link_debug(link
, "Acquiring DHCPv6 lease on NDisc request");
912 r
= ndisc_router_process_default(link
, rt
);
915 r
= ndisc_router_process_options(link
, rt
);
919 if (link
->ndisc_addresses_messages
== 0)
920 link
->ndisc_addresses_configured
= true;
922 log_link_debug(link
, "Setting SLAAC addresses.");
924 /* address_handler calls link_request_set_routes() and link_request_set_nexthop().
925 * Before they are called, the related flags must be cleared. Otherwise, the link
926 * becomes configured state before routes are configured. */
927 link
->static_routes_configured
= false;
928 link
->static_nexthops_configured
= false;
931 if (link
->ndisc_routes_messages
== 0)
932 link
->ndisc_routes_configured
= true;
934 log_link_debug(link
, "Setting NDisc routes.");
936 r
= ndisc_remove_old(link
, false);
940 if (link
->ndisc_addresses_configured
&& link
->ndisc_routes_configured
)
941 link_check_ready(link
);
943 link_set_state(link
, LINK_STATE_CONFIGURING
);
948 static void ndisc_handler(sd_ndisc
*nd
, sd_ndisc_event event
, sd_ndisc_router
*rt
, void *userdata
) {
949 Link
*link
= userdata
;
954 if (IN_SET(link
->state
, LINK_STATE_FAILED
, LINK_STATE_LINGER
))
959 case SD_NDISC_EVENT_ROUTER
:
960 r
= ndisc_router_handler(link
, rt
);
962 link_enter_failed(link
);
967 case SD_NDISC_EVENT_TIMEOUT
:
968 log_link_debug(link
, "NDisc handler get timeout event");
969 if (link
->ndisc_addresses_messages
== 0 && link
->ndisc_routes_messages
== 0) {
970 link
->ndisc_addresses_configured
= true;
971 link
->ndisc_routes_configured
= true;
972 link_check_ready(link
);
976 assert_not_reached("Unknown NDisc event");
980 int ndisc_configure(Link
*link
) {
985 r
= sd_ndisc_new(&link
->ndisc
);
989 r
= sd_ndisc_attach_event(link
->ndisc
, NULL
, 0);
993 r
= sd_ndisc_set_mac(link
->ndisc
, &link
->mac
);
997 r
= sd_ndisc_set_ifindex(link
->ndisc
, link
->ifindex
);
1001 r
= sd_ndisc_set_callback(link
->ndisc
, ndisc_handler
, link
);
1008 void ndisc_vacuum(Link
*link
) {
1013 bool updated
= false;
1017 /* Removes all RDNSS and DNSSL entries whose validity time has passed */
1019 time_now
= now(clock_boottime_or_monotonic());
1021 SET_FOREACH(r
, link
->ndisc_rdnss
, i
)
1022 if (r
->valid_until
< time_now
) {
1023 free(set_remove(link
->ndisc_rdnss
, r
));
1027 SET_FOREACH(d
, link
->ndisc_dnssl
, i
)
1028 if (d
->valid_until
< time_now
) {
1029 free(set_remove(link
->ndisc_dnssl
, d
));
1037 void ndisc_flush(Link
*link
) {
1040 /* Removes all RDNSS and DNSSL entries, without exception */
1042 link
->ndisc_rdnss
= set_free(link
->ndisc_rdnss
);
1043 link
->ndisc_dnssl
= set_free(link
->ndisc_dnssl
);
1046 int ipv6token_new(IPv6Token
**ret
) {
1049 p
= new(IPv6Token
, 1);
1054 .address_generation_type
= IPV6_TOKEN_ADDRESS_GENERATION_NONE
,
1062 static void ipv6_token_hash_func(const IPv6Token
*p
, struct siphash
*state
) {
1063 siphash24_compress(&p
->address_generation_type
, sizeof(p
->address_generation_type
), state
);
1064 siphash24_compress(&p
->prefix
, sizeof(p
->prefix
), state
);
1067 static int ipv6_token_compare_func(const IPv6Token
*a
, const IPv6Token
*b
) {
1070 r
= CMP(a
->address_generation_type
, b
->address_generation_type
);
1074 return memcmp(&a
->prefix
, &b
->prefix
, sizeof(struct in6_addr
));
1077 DEFINE_HASH_OPS_WITH_KEY_DESTRUCTOR(
1078 ipv6_token_hash_ops
,
1080 ipv6_token_hash_func
,
1081 ipv6_token_compare_func
,
1084 int config_parse_ndisc_deny_listed_prefix(
1086 const char *filename
,
1088 const char *section
,
1089 unsigned section_line
,
1096 Network
*network
= data
;
1105 if (isempty(rvalue
)) {
1106 network
->ndisc_deny_listed_prefix
= set_free_free(network
->ndisc_deny_listed_prefix
);
1110 for (p
= rvalue
;;) {
1111 _cleanup_free_
char *n
= NULL
;
1112 _cleanup_free_
struct in6_addr
*a
= NULL
;
1113 union in_addr_union ip
;
1115 r
= extract_first_word(&p
, &n
, NULL
, 0);
1119 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
1120 "Failed to parse NDisc deny-listed prefix, ignoring assignment: %s",
1127 r
= in_addr_from_string(AF_INET6
, n
, &ip
);
1129 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
1130 "NDisc deny-listed prefix is invalid, ignoring assignment: %s", n
);
1134 if (set_contains(network
->ndisc_deny_listed_prefix
, &ip
.in6
))
1137 a
= newdup(struct in6_addr
, &ip
.in6
, 1);
1141 r
= set_ensure_consume(&network
->ndisc_deny_listed_prefix
, &in6_addr_hash_ops
, TAKE_PTR(a
));
1147 int config_parse_address_generation_type(
1149 const char *filename
,
1151 const char *section
,
1152 unsigned section_line
,
1159 _cleanup_free_ IPv6Token
*token
= NULL
;
1160 union in_addr_union buffer
;
1161 Network
*network
= data
;
1170 if (isempty(rvalue
)) {
1171 network
->ipv6_tokens
= ordered_set_free(network
->ipv6_tokens
);
1175 r
= ipv6token_new(&token
);
1179 if ((p
= startswith(rvalue
, "static:")))
1180 token
->address_generation_type
= IPV6_TOKEN_ADDRESS_GENERATION_STATIC
;
1181 else if ((p
= startswith(rvalue
, "prefixstable:")))
1182 token
->address_generation_type
= IPV6_TOKEN_ADDRESS_GENERATION_PREFIXSTABLE
;
1184 token
->address_generation_type
= IPV6_TOKEN_ADDRESS_GENERATION_STATIC
;
1188 r
= in_addr_from_string(AF_INET6
, p
, &buffer
);
1190 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
1191 "Failed to parse IPv6 %s, ignoring: %s", lvalue
, rvalue
);
1195 if (in_addr_is_null(AF_INET6
, &buffer
)) {
1196 log_syntax(unit
, LOG_WARNING
, filename
, line
, 0,
1197 "IPv6 %s cannot be the ANY address, ignoring: %s", lvalue
, rvalue
);
1201 token
->prefix
= buffer
.in6
;
1203 r
= ordered_set_ensure_allocated(&network
->ipv6_tokens
, &ipv6_token_hash_ops
);
1207 r
= ordered_set_put(network
->ipv6_tokens
, token
);
1209 log_syntax(unit
, LOG_DEBUG
, filename
, line
, r
,
1210 "IPv6 token '%s' is duplicated, ignoring: %m", rvalue
);
1212 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
1213 "Failed to store IPv6 token '%s', ignoring: %m", rvalue
);
1220 DEFINE_CONFIG_PARSE_ENUM(config_parse_ipv6_accept_ra_start_dhcp6_client
, ipv6_accept_ra_start_dhcp6_client
, IPv6AcceptRAStartDHCP6Client
,
1221 "Failed to parse DHCPv6Client= setting")
1222 static const char* const ipv6_accept_ra_start_dhcp6_client_table
[_IPV6_ACCEPT_RA_START_DHCP6_CLIENT_MAX
] = {
1223 [IPV6_ACCEPT_RA_START_DHCP6_CLIENT_NO
] = "no",
1224 [IPV6_ACCEPT_RA_START_DHCP6_CLIENT_ALWAYS
] = "always",
1225 [IPV6_ACCEPT_RA_START_DHCP6_CLIENT_YES
] = "yes",
1228 DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(ipv6_accept_ra_start_dhcp6_client
, IPv6AcceptRAStartDHCP6Client
, IPV6_ACCEPT_RA_START_DHCP6_CLIENT_YES
);