1 /* SPDX-License-Identifier: LGPL-2.1+ */
3 Copyright © 2014 Intel Corporation. All rights reserved.
7 #include <netinet/icmp6.h>
12 #include "missing_network.h"
13 #include "networkd-address.h"
14 #include "networkd-dhcp6.h"
15 #include "networkd-manager.h"
16 #include "networkd-ndisc.h"
17 #include "networkd-sysctl.h"
18 #include "string-table.h"
19 #include "string-util.h"
22 #define NDISC_DNSSL_MAX 64U
23 #define NDISC_RDNSS_MAX 64U
24 #define NDISC_PREFIX_LFT_MIN 7200U
26 #define DAD_CONFLICTS_IDGEN_RETRIES_RFC7217 3
28 /* https://tools.ietf.org/html/rfc5453 */
29 /* https://www.iana.org/assignments/ipv6-interface-ids/ipv6-interface-ids.xml */
31 #define SUBNET_ROUTER_ANYCAST_ADDRESS_RFC4291 ((struct in6_addr) { .s6_addr = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } })
32 #define SUBNET_ROUTER_ANYCAST_PREFIXLEN 8
33 #define RESERVED_IPV6_INTERFACE_IDENTIFIERS_ADDRESS_RFC4291 ((struct in6_addr) { .s6_addr = { 0x02, 0x00, 0x5E, 0xFF, 0xFE } })
34 #define RESERVED_IPV6_INTERFACE_IDENTIFIERS_PREFIXLEN 5
35 #define RESERVED_SUBNET_ANYCAST_ADDRESSES_RFC4291 ((struct in6_addr) { .s6_addr = { 0xFD, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF } })
36 #define RESERVED_SUBNET_ANYCAST_PREFIXLEN 7
38 #define NDISC_APP_ID SD_ID128_MAKE(13,ac,81,a7,d5,3f,49,78,92,79,5d,0c,29,3a,bc,7e)
40 bool link_ipv6_accept_ra_enabled(Link
*link
) {
43 if (!socket_ipv6_is_supported())
46 if (link
->flags
& IFF_LOOPBACK
)
52 if (!link_ipv6ll_enabled(link
))
55 /* If unset use system default (enabled if local forwarding is disabled.
56 * disabled if local forwarding is enabled).
57 * If set, ignore or enforce RA independent of local forwarding state.
59 if (link
->network
->ipv6_accept_ra
< 0)
60 /* default to accept RA if ip_forward is disabled and ignore RA if ip_forward is enabled */
61 return !link_ip_forward_enabled(link
, AF_INET6
);
62 else if (link
->network
->ipv6_accept_ra
> 0)
63 /* accept RA even if ip_forward is enabled */
70 static int ndisc_remove_old_one(Link
*link
, const struct in6_addr
*router
, bool force
);
72 static int ndisc_address_callback(Address
*address
) {
73 struct in6_addr router
= {};
77 assert(address
->link
);
79 SET_FOREACH(n
, address
->link
->ndisc_addresses
)
80 if (n
->address
== address
) {
85 if (IN6_IS_ADDR_UNSPECIFIED(&router
)) {
86 _cleanup_free_
char *buf
= NULL
;
88 (void) in_addr_to_string(address
->family
, &address
->in_addr
, &buf
);
89 log_link_debug(address
->link
, "%s is called for %s/%u, but it is already removed, ignoring.",
90 __func__
, strna(buf
), address
->prefixlen
);
94 /* Make this called only once */
95 SET_FOREACH(n
, address
->link
->ndisc_addresses
)
96 if (IN6_ARE_ADDR_EQUAL(&n
->router
, &router
))
97 n
->address
->callback
= NULL
;
99 return ndisc_remove_old_one(address
->link
, &router
, true);
102 static int ndisc_remove_old_one(Link
*link
, const struct in6_addr
*router
, bool force
) {
113 bool set_callback
= false;
115 if (!link
->ndisc_addresses_configured
|| !link
->ndisc_routes_configured
)
118 SET_FOREACH(na
, link
->ndisc_addresses
)
119 if (!na
->marked
&& IN6_ARE_ADDR_EQUAL(&na
->router
, router
)) {
125 SET_FOREACH(na
, link
->ndisc_addresses
)
126 if (!na
->marked
&& address_is_ready(na
->address
)) {
127 set_callback
= false;
132 SET_FOREACH(na
, link
->ndisc_addresses
)
133 if (!na
->marked
&& IN6_ARE_ADDR_EQUAL(&na
->router
, router
))
134 na
->address
->callback
= ndisc_address_callback
;
137 _cleanup_free_
char *buf
= NULL
;
139 (void) in_addr_to_string(AF_INET6
, (union in_addr_union
*) router
, &buf
);
140 log_link_debug(link
, "No SLAAC address obtained from %s is ready. "
141 "The old NDisc information will be removed later.",
149 _cleanup_free_
char *buf
= NULL
;
151 (void) in_addr_to_string(AF_INET6
, (union in_addr_union
*) router
, &buf
);
152 log_link_debug(link
, "Removing old NDisc information obtained from %s.", strna(buf
));
157 SET_FOREACH(na
, link
->ndisc_addresses
)
158 if (na
->marked
&& IN6_ARE_ADDR_EQUAL(&na
->router
, router
)) {
159 k
= address_remove(na
->address
, link
, NULL
);
164 SET_FOREACH(nr
, link
->ndisc_routes
)
165 if (nr
->marked
&& IN6_ARE_ADDR_EQUAL(&nr
->router
, router
)) {
166 k
= route_remove(nr
->route
, NULL
, link
, NULL
);
171 SET_FOREACH(rdnss
, link
->ndisc_rdnss
)
172 if (rdnss
->marked
&& IN6_ARE_ADDR_EQUAL(&rdnss
->router
, router
))
173 free(set_remove(link
->ndisc_rdnss
, rdnss
));
175 SET_FOREACH(dnssl
, link
->ndisc_dnssl
)
176 if (dnssl
->marked
&& IN6_ARE_ADDR_EQUAL(&dnssl
->router
, router
))
177 free(set_remove(link
->ndisc_dnssl
, dnssl
));
182 static int ndisc_remove_old(Link
*link
) {
183 _cleanup_set_free_free_ Set
*routers
= NULL
;
184 _cleanup_free_
struct in6_addr
*router
= NULL
;
194 routers
= set_new(&in6_addr_hash_ops
);
198 SET_FOREACH(na
, link
->ndisc_addresses
)
199 if (!set_contains(routers
, &na
->router
)) {
200 router
= newdup(struct in6_addr
, &na
->router
, 1);
204 r
= set_put(routers
, router
);
212 SET_FOREACH(nr
, link
->ndisc_routes
)
213 if (!set_contains(routers
, &nr
->router
)) {
214 router
= newdup(struct in6_addr
, &nr
->router
, 1);
218 r
= set_put(routers
, router
);
226 SET_FOREACH(rdnss
, link
->ndisc_rdnss
)
227 if (!set_contains(routers
, &rdnss
->router
)) {
228 router
= newdup(struct in6_addr
, &rdnss
->router
, 1);
232 r
= set_put(routers
, router
);
240 SET_FOREACH(dnssl
, link
->ndisc_dnssl
)
241 if (!set_contains(routers
, &dnssl
->router
)) {
242 router
= newdup(struct in6_addr
, &dnssl
->router
, 1);
246 r
= set_put(routers
, router
);
255 SET_FOREACH(a
, routers
) {
256 k
= ndisc_remove_old_one(link
, a
, false);
264 static void ndisc_route_hash_func(const NDiscRoute
*x
, struct siphash
*state
) {
265 route_hash_func(x
->route
, state
);
268 static int ndisc_route_compare_func(const NDiscRoute
*a
, const NDiscRoute
*b
) {
269 return route_compare_func(a
->route
, b
->route
);
272 DEFINE_PRIVATE_HASH_OPS_WITH_KEY_DESTRUCTOR(
273 ndisc_route_hash_ops
,
275 ndisc_route_hash_func
,
276 ndisc_route_compare_func
,
279 static int ndisc_route_handler(sd_netlink
*rtnl
, sd_netlink_message
*m
, Link
*link
) {
283 assert(link
->ndisc_routes_messages
> 0);
285 link
->ndisc_routes_messages
--;
287 if (IN_SET(link
->state
, LINK_STATE_FAILED
, LINK_STATE_LINGER
))
290 r
= sd_netlink_message_get_errno(m
);
291 if (r
< 0 && r
!= -EEXIST
) {
292 log_link_message_error_errno(link
, m
, r
, "Could not set NDisc route");
293 link_enter_failed(link
);
297 if (link
->ndisc_routes_messages
== 0) {
298 log_link_debug(link
, "NDisc routes set.");
299 link
->ndisc_routes_configured
= true;
301 r
= ndisc_remove_old(link
);
303 link_enter_failed(link
);
307 link_check_ready(link
);
313 static int ndisc_route_configure(Route
*route
, Link
*link
, sd_ndisc_router
*rt
) {
314 _cleanup_free_ NDiscRoute
*nr
= NULL
;
315 NDiscRoute
*nr_exist
;
316 struct in6_addr router
;
324 r
= route_configure(route
, link
, ndisc_route_handler
, &ret
);
326 return log_link_error_errno(link
, r
, "Failed to set NDisc route: %m");
328 link
->ndisc_routes_messages
++;
330 r
= sd_ndisc_router_get_address(rt
, &router
);
332 return log_link_error_errno(link
, r
, "Failed to get router address from RA: %m");
334 nr
= new(NDiscRoute
, 1);
343 nr_exist
= set_get(link
->ndisc_routes
, nr
);
345 nr_exist
->marked
= false;
346 nr_exist
->router
= router
;
350 r
= set_ensure_put(&link
->ndisc_routes
, &ndisc_route_hash_ops
, nr
);
352 return log_link_error_errno(link
, r
, "Failed to store NDisc SLAAC route: %m");
359 static void ndisc_address_hash_func(const NDiscAddress
*x
, struct siphash
*state
) {
360 address_hash_func(x
->address
, state
);
363 static int ndisc_address_compare_func(const NDiscAddress
*a
, const NDiscAddress
*b
) {
364 return address_compare_func(a
->address
, b
->address
);
367 DEFINE_PRIVATE_HASH_OPS_WITH_KEY_DESTRUCTOR(
368 ndisc_address_hash_ops
,
370 ndisc_address_hash_func
,
371 ndisc_address_compare_func
,
374 static int ndisc_address_handler(sd_netlink
*rtnl
, sd_netlink_message
*m
, Link
*link
) {
378 assert(link
->ndisc_addresses_messages
> 0);
380 link
->ndisc_addresses_messages
--;
382 if (IN_SET(link
->state
, LINK_STATE_FAILED
, LINK_STATE_LINGER
))
385 r
= sd_netlink_message_get_errno(m
);
386 if (r
< 0 && r
!= -EEXIST
) {
387 log_link_message_error_errno(link
, m
, r
, "Could not set NDisc address");
388 link_enter_failed(link
);
391 (void) manager_rtnl_process_address(rtnl
, m
, link
->manager
);
393 if (link
->ndisc_addresses_messages
== 0) {
394 log_link_debug(link
, "NDisc SLAAC addresses set.");
395 link
->ndisc_addresses_configured
= true;
397 r
= ndisc_remove_old(link
);
399 link_enter_failed(link
);
403 r
= link_set_routes(link
);
405 link_enter_failed(link
);
413 static int ndisc_address_configure(Address
*address
, Link
*link
, sd_ndisc_router
*rt
) {
414 _cleanup_free_ NDiscAddress
*na
= NULL
;
415 NDiscAddress
*na_exist
;
416 struct in6_addr router
;
424 r
= address_configure(address
, link
, ndisc_address_handler
, true, &ret
);
426 return log_link_error_errno(link
, r
, "Failed to set NDisc SLAAC address: %m");
428 link
->ndisc_addresses_messages
++;
430 r
= sd_ndisc_router_get_address(rt
, &router
);
432 return log_link_error_errno(link
, r
, "Failed to get router address from RA: %m");
434 na
= new(NDiscAddress
, 1);
438 *na
= (NDiscAddress
) {
443 na_exist
= set_get(link
->ndisc_addresses
, na
);
445 na_exist
->marked
= false;
446 na_exist
->router
= router
;
450 r
= set_ensure_put(&link
->ndisc_addresses
, &ndisc_address_hash_ops
, na
);
452 return log_link_error_errno(link
, r
, "Failed to store NDisc SLAAC address: %m");
459 static int ndisc_router_process_default(Link
*link
, sd_ndisc_router
*rt
) {
460 _cleanup_(route_freep
) Route
*route
= NULL
;
461 union in_addr_union gateway
;
471 r
= sd_ndisc_router_get_lifetime(rt
, &lifetime
);
473 return log_link_error_errno(link
, r
, "Failed to get gateway lifetime from RA: %m");
475 if (lifetime
== 0) /* not a default router */
478 r
= sd_ndisc_router_get_address(rt
, &gateway
.in6
);
480 return log_link_error_errno(link
, r
, "Failed to get gateway address from RA: %m");
482 if (address_exists(link
, AF_INET6
, &gateway
)) {
484 _cleanup_free_
char *buffer
= NULL
;
486 (void) in_addr_to_string(AF_INET6
, &gateway
, &buffer
);
487 log_link_debug(link
, "No NDisc route added, gateway %s matches local address",
493 r
= sd_ndisc_router_get_preference(rt
, &preference
);
495 return log_link_error_errno(link
, r
, "Failed to get default router preference from RA: %m");
497 r
= sd_ndisc_router_get_timestamp(rt
, clock_boottime_or_monotonic(), &time_now
);
499 return log_link_error_errno(link
, r
, "Failed to get RA timestamp: %m");
501 r
= sd_ndisc_router_get_mtu(rt
, &mtu
);
505 return log_link_error_errno(link
, r
, "Failed to get default router MTU from RA: %m");
507 r
= route_new(&route
);
511 route
->family
= AF_INET6
;
512 route
->table
= link_get_ipv6_accept_ra_route_table(link
);
513 route
->priority
= link
->network
->dhcp6_route_metric
;
514 route
->protocol
= RTPROT_RA
;
515 route
->pref
= preference
;
516 route
->gw_family
= AF_INET6
;
518 route
->lifetime
= time_now
+ lifetime
* USEC_PER_SEC
;
521 r
= ndisc_route_configure(route
, link
, rt
);
523 return log_link_error_errno(link
, r
, "Could not set default route: %m");
526 HASHMAP_FOREACH(route_gw
, link
->network
->routes_by_section
) {
527 if (!route_gw
->gateway_from_dhcp
)
530 if (route_gw
->family
!= AF_INET6
)
533 route_gw
->gw
= gateway
;
534 route_gw
->gw_family
= AF_INET6
;
536 r
= ndisc_route_configure(route_gw
, link
, rt
);
538 return log_link_error_errno(link
, r
, "Could not set gateway: %m");
544 static bool stableprivate_address_is_valid(const struct in6_addr
*addr
) {
547 /* According to rfc4291, generated address should not be in the following ranges. */
549 if (memcmp(addr
, &SUBNET_ROUTER_ANYCAST_ADDRESS_RFC4291
, SUBNET_ROUTER_ANYCAST_PREFIXLEN
) == 0)
552 if (memcmp(addr
, &RESERVED_IPV6_INTERFACE_IDENTIFIERS_ADDRESS_RFC4291
, RESERVED_IPV6_INTERFACE_IDENTIFIERS_PREFIXLEN
) == 0)
555 if (memcmp(addr
, &RESERVED_SUBNET_ANYCAST_ADDRESSES_RFC4291
, RESERVED_SUBNET_ANYCAST_PREFIXLEN
) == 0)
561 static int make_stableprivate_address(Link
*link
, const struct in6_addr
*prefix
, uint8_t prefix_len
, uint8_t dad_counter
, struct in6_addr
**ret
) {
562 _cleanup_free_
struct in6_addr
*addr
= NULL
;
563 sd_id128_t secret_key
;
564 struct siphash state
;
569 /* According to rfc7217 section 5.1
570 * RID = F(Prefix, Net_Iface, Network_ID, DAD_Counter, secret_key) */
572 r
= sd_id128_get_machine_app_specific(NDISC_APP_ID
, &secret_key
);
574 return log_error_errno(r
, "Failed to generate key: %m");
576 siphash24_init(&state
, secret_key
.bytes
);
578 l
= MAX(DIV_ROUND_UP(prefix_len
, 8), 8);
579 siphash24_compress(prefix
, l
, &state
);
580 siphash24_compress_string(link
->ifname
, &state
);
581 siphash24_compress(&link
->mac
, sizeof(struct ether_addr
), &state
);
582 siphash24_compress(&dad_counter
, sizeof(uint8_t), &state
);
584 rid
= htole64(siphash24_finalize(&state
));
586 addr
= new(struct in6_addr
, 1);
590 memcpy(addr
->s6_addr
, prefix
->s6_addr
, l
);
591 memcpy(addr
->s6_addr
+ l
, &rid
, 16 - l
);
593 if (!stableprivate_address_is_valid(addr
)) {
598 *ret
= TAKE_PTR(addr
);
602 static int ndisc_router_generate_addresses(Link
*link
, struct in6_addr
*address
, uint8_t prefixlen
, Set
**ret
) {
603 _cleanup_set_free_free_ Set
*addresses
= NULL
;
611 addresses
= set_new(&in6_addr_hash_ops
);
615 ORDERED_SET_FOREACH(j
, link
->network
->ipv6_tokens
) {
616 _cleanup_free_
struct in6_addr
*new_address
= NULL
;
618 if (j
->address_generation_type
== IPV6_TOKEN_ADDRESS_GENERATION_PREFIXSTABLE
619 && (IN6_IS_ADDR_UNSPECIFIED(&j
->prefix
) || IN6_ARE_ADDR_EQUAL(&j
->prefix
, address
))) {
620 /* While this loop uses dad_counter and a retry limit as specified in RFC 7217, the loop
621 does not actually attempt Duplicate Address Detection; the counter will be incremented
622 only when the address generation algorithm produces an invalid address, and the loop
623 may exit with an address which ends up being unusable due to duplication on the link.
625 for (; j
->dad_counter
< DAD_CONFLICTS_IDGEN_RETRIES_RFC7217
; j
->dad_counter
++) {
626 r
= make_stableprivate_address(link
, address
, prefixlen
, j
->dad_counter
, &new_address
);
632 } else if (j
->address_generation_type
== IPV6_TOKEN_ADDRESS_GENERATION_STATIC
) {
633 new_address
= new(struct in6_addr
, 1);
637 memcpy(new_address
->s6_addr
, address
->s6_addr
, 8);
638 memcpy(new_address
->s6_addr
+ 8, j
->prefix
.s6_addr
+ 8, 8);
642 r
= set_put(addresses
, new_address
);
644 return log_link_error_errno(link
, r
, "Failed to store SLAAC address: %m");
646 log_link_debug_errno(link
, r
, "Generated SLAAC address is duplicated, ignoring.");
648 TAKE_PTR(new_address
);
652 /* fall back to EUI-64 if no tokens provided addresses */
653 if (set_isempty(addresses
)) {
654 _cleanup_free_
struct in6_addr
*new_address
= NULL
;
656 new_address
= newdup(struct in6_addr
, address
, 1);
660 r
= generate_ipv6_eui_64_address(link
, new_address
);
662 return log_link_error_errno(link
, r
, "Failed to generate EUI64 address: %m");
664 r
= set_put(addresses
, new_address
);
666 return log_link_error_errno(link
, r
, "Failed to store SLAAC address: %m");
668 TAKE_PTR(new_address
);
671 *ret
= TAKE_PTR(addresses
);
676 static int ndisc_router_process_autonomous_prefix(Link
*link
, sd_ndisc_router
*rt
) {
677 uint32_t lifetime_valid
, lifetime_preferred
, lifetime_remaining
;
678 _cleanup_set_free_free_ Set
*addresses
= NULL
;
679 _cleanup_(address_freep
) Address
*address
= NULL
;
680 struct in6_addr addr
, *a
;
688 r
= sd_ndisc_router_get_timestamp(rt
, clock_boottime_or_monotonic(), &time_now
);
690 return log_link_error_errno(link
, r
, "Failed to get RA timestamp: %m");
692 r
= sd_ndisc_router_prefix_get_prefixlen(rt
, &prefixlen
);
694 return log_link_error_errno(link
, r
, "Failed to get prefix length: %m");
696 r
= sd_ndisc_router_prefix_get_valid_lifetime(rt
, &lifetime_valid
);
698 return log_link_error_errno(link
, r
, "Failed to get prefix valid lifetime: %m");
700 r
= sd_ndisc_router_prefix_get_preferred_lifetime(rt
, &lifetime_preferred
);
702 return log_link_error_errno(link
, r
, "Failed to get prefix preferred lifetime: %m");
704 /* The preferred lifetime is never greater than the valid lifetime */
705 if (lifetime_preferred
> lifetime_valid
)
708 r
= sd_ndisc_router_prefix_get_address(rt
, &addr
);
710 return log_link_error_errno(link
, r
, "Failed to get prefix address: %m");
712 r
= ndisc_router_generate_addresses(link
, &addr
, prefixlen
, &addresses
);
716 r
= address_new(&address
);
720 address
->family
= AF_INET6
;
721 address
->prefixlen
= prefixlen
;
722 address
->flags
= IFA_F_NOPREFIXROUTE
|IFA_F_MANAGETEMPADDR
;
723 address
->cinfo
.ifa_prefered
= lifetime_preferred
;
725 SET_FOREACH(a
, addresses
) {
726 Address
*existing_address
;
728 /* see RFC4862 section 5.5.3.e */
729 r
= address_get(link
, AF_INET6
, (union in_addr_union
*) a
, prefixlen
, &existing_address
);
731 lifetime_remaining
= existing_address
->cinfo
.tstamp
/ 100 + existing_address
->cinfo
.ifa_valid
- time_now
/ USEC_PER_SEC
;
732 if (lifetime_valid
> NDISC_PREFIX_LFT_MIN
|| lifetime_valid
> lifetime_remaining
)
733 address
->cinfo
.ifa_valid
= lifetime_valid
;
734 else if (lifetime_remaining
<= NDISC_PREFIX_LFT_MIN
)
735 address
->cinfo
.ifa_valid
= lifetime_remaining
;
737 address
->cinfo
.ifa_valid
= NDISC_PREFIX_LFT_MIN
;
738 } else if (lifetime_valid
> 0)
739 address
->cinfo
.ifa_valid
= lifetime_valid
;
741 continue; /* see RFC4862 section 5.5.3.d */
743 if (address
->cinfo
.ifa_valid
== 0)
746 address
->in_addr
.in6
= *a
;
748 r
= ndisc_address_configure(address
, link
, rt
);
750 return log_link_error_errno(link
, r
, "Could not set SLAAC address: %m");
756 static int ndisc_router_process_onlink_prefix(Link
*link
, sd_ndisc_router
*rt
) {
757 _cleanup_(route_freep
) Route
*route
= NULL
;
766 r
= sd_ndisc_router_get_timestamp(rt
, clock_boottime_or_monotonic(), &time_now
);
768 return log_link_error_errno(link
, r
, "Failed to get RA timestamp: %m");
770 r
= sd_ndisc_router_prefix_get_prefixlen(rt
, &prefixlen
);
772 return log_link_error_errno(link
, r
, "Failed to get prefix length: %m");
774 r
= sd_ndisc_router_prefix_get_valid_lifetime(rt
, &lifetime
);
776 return log_link_error_errno(link
, r
, "Failed to get prefix lifetime: %m");
778 r
= route_new(&route
);
782 route
->family
= AF_INET6
;
783 route
->table
= link_get_ipv6_accept_ra_route_table(link
);
784 route
->priority
= link
->network
->dhcp6_route_metric
;
785 route
->protocol
= RTPROT_RA
;
786 route
->flags
= RTM_F_PREFIX
;
787 route
->dst_prefixlen
= prefixlen
;
788 route
->lifetime
= time_now
+ lifetime
* USEC_PER_SEC
;
790 r
= sd_ndisc_router_prefix_get_address(rt
, &route
->dst
.in6
);
792 return log_link_error_errno(link
, r
, "Failed to get prefix address: %m");
794 r
= ndisc_route_configure(route
, link
, rt
);
796 return log_link_error_errno(link
, r
, "Could not set prefix route: %m");;
801 static int ndisc_router_process_route(Link
*link
, sd_ndisc_router
*rt
) {
802 _cleanup_(route_freep
) Route
*route
= NULL
;
803 struct in6_addr gateway
;
805 unsigned preference
, prefixlen
;
811 r
= sd_ndisc_router_route_get_lifetime(rt
, &lifetime
);
813 return log_link_error_errno(link
, r
, "Failed to get gateway lifetime from RA: %m");
818 r
= sd_ndisc_router_get_address(rt
, &gateway
);
820 return log_link_error_errno(link
, r
, "Failed to get gateway address from RA: %m");
822 r
= sd_ndisc_router_route_get_prefixlen(rt
, &prefixlen
);
824 return log_link_error_errno(link
, r
, "Failed to get route prefix length: %m");
826 r
= sd_ndisc_router_route_get_preference(rt
, &preference
);
828 return log_link_error_errno(link
, r
, "Failed to get default router preference from RA: %m");
830 r
= sd_ndisc_router_get_timestamp(rt
, clock_boottime_or_monotonic(), &time_now
);
832 return log_link_error_errno(link
, r
, "Failed to get RA timestamp: %m");
834 r
= route_new(&route
);
838 route
->family
= AF_INET6
;
839 route
->table
= link_get_ipv6_accept_ra_route_table(link
);
840 route
->priority
= link
->network
->dhcp6_route_metric
;
841 route
->protocol
= RTPROT_RA
;
842 route
->pref
= preference
;
843 route
->gw
.in6
= gateway
;
844 route
->gw_family
= AF_INET6
;
845 route
->dst_prefixlen
= prefixlen
;
846 route
->lifetime
= time_now
+ lifetime
* USEC_PER_SEC
;
848 r
= sd_ndisc_router_route_get_address(rt
, &route
->dst
.in6
);
850 return log_link_error_errno(link
, r
, "Failed to get route address: %m");
852 r
= ndisc_route_configure(route
, link
, rt
);
854 return log_link_error_errno(link
, r
, "Could not set additional route: %m");
859 static void ndisc_rdnss_hash_func(const NDiscRDNSS
*x
, struct siphash
*state
) {
860 siphash24_compress(&x
->address
, sizeof(x
->address
), state
);
863 static int ndisc_rdnss_compare_func(const NDiscRDNSS
*a
, const NDiscRDNSS
*b
) {
864 return memcmp(&a
->address
, &b
->address
, sizeof(a
->address
));
867 DEFINE_PRIVATE_HASH_OPS_WITH_KEY_DESTRUCTOR(
868 ndisc_rdnss_hash_ops
,
870 ndisc_rdnss_hash_func
,
871 ndisc_rdnss_compare_func
,
874 static int ndisc_router_process_rdnss(Link
*link
, sd_ndisc_router
*rt
) {
876 const struct in6_addr
*a
;
877 struct in6_addr router
;
885 r
= sd_ndisc_router_get_address(rt
, &router
);
887 return log_link_error_errno(link
, r
, "Failed to get router address from RA: %m");
889 r
= sd_ndisc_router_get_timestamp(rt
, clock_boottime_or_monotonic(), &time_now
);
891 return log_link_error_errno(link
, r
, "Failed to get RA timestamp: %m");
893 r
= sd_ndisc_router_rdnss_get_lifetime(rt
, &lifetime
);
895 return log_link_error_errno(link
, r
, "Failed to get RDNSS lifetime: %m");
897 n
= sd_ndisc_router_rdnss_get_addresses(rt
, &a
);
899 return log_link_error_errno(link
, n
, "Failed to get RDNSS addresses: %m");
901 SET_FOREACH(rdnss
, link
->ndisc_rdnss
)
902 if (IN6_ARE_ADDR_EQUAL(&rdnss
->router
, &router
))
903 rdnss
->marked
= true;
908 if (n
>= (int) NDISC_RDNSS_MAX
) {
909 log_link_warning(link
, "Too many RDNSS records per link. Only first %i records will be used.", NDISC_RDNSS_MAX
);
913 for (int j
= 0; j
< n
; j
++) {
914 _cleanup_free_ NDiscRDNSS
*x
= NULL
;
919 rdnss
= set_get(link
->ndisc_rdnss
, &d
);
921 rdnss
->marked
= false;
922 rdnss
->router
= router
;
923 rdnss
->valid_until
= time_now
+ lifetime
* USEC_PER_SEC
;
927 x
= new(NDiscRDNSS
, 1);
934 .valid_until
= time_now
+ lifetime
* USEC_PER_SEC
,
937 r
= set_ensure_consume(&link
->ndisc_rdnss
, &ndisc_rdnss_hash_ops
, TAKE_PTR(x
));
946 static void ndisc_dnssl_hash_func(const NDiscDNSSL
*x
, struct siphash
*state
) {
947 siphash24_compress_string(NDISC_DNSSL_DOMAIN(x
), state
);
950 static int ndisc_dnssl_compare_func(const NDiscDNSSL
*a
, const NDiscDNSSL
*b
) {
951 return strcmp(NDISC_DNSSL_DOMAIN(a
), NDISC_DNSSL_DOMAIN(b
));
954 DEFINE_PRIVATE_HASH_OPS_WITH_KEY_DESTRUCTOR(
955 ndisc_dnssl_hash_ops
,
957 ndisc_dnssl_hash_func
,
958 ndisc_dnssl_compare_func
,
961 static int ndisc_router_process_dnssl(Link
*link
, sd_ndisc_router
*rt
) {
962 _cleanup_strv_free_
char **l
= NULL
;
963 struct in6_addr router
;
973 r
= sd_ndisc_router_get_address(rt
, &router
);
975 return log_link_error_errno(link
, r
, "Failed to get router address from RA: %m");
977 r
= sd_ndisc_router_get_timestamp(rt
, clock_boottime_or_monotonic(), &time_now
);
979 return log_link_error_errno(link
, r
, "Failed to get RA timestamp: %m");
981 r
= sd_ndisc_router_dnssl_get_lifetime(rt
, &lifetime
);
983 return log_link_error_errno(link
, r
, "Failed to get DNSSL lifetime: %m");
985 r
= sd_ndisc_router_dnssl_get_domains(rt
, &l
);
987 return log_link_error_errno(link
, r
, "Failed to get DNSSL addresses: %m");
989 SET_FOREACH(dnssl
, link
->ndisc_dnssl
)
990 if (IN6_ARE_ADDR_EQUAL(&dnssl
->router
, &router
))
991 dnssl
->marked
= true;
996 if (strv_length(l
) >= NDISC_DNSSL_MAX
) {
997 log_link_warning(link
, "Too many DNSSL records per link. Only first %i records will be used.", NDISC_DNSSL_MAX
);
998 STRV_FOREACH(j
, l
+ NDISC_DNSSL_MAX
)
1002 STRV_FOREACH(j
, l
) {
1003 _cleanup_free_ NDiscDNSSL
*s
= NULL
;
1005 s
= malloc0(ALIGN(sizeof(NDiscDNSSL
)) + strlen(*j
) + 1);
1009 strcpy(NDISC_DNSSL_DOMAIN(s
), *j
);
1011 dnssl
= set_get(link
->ndisc_dnssl
, s
);
1013 dnssl
->marked
= false;
1014 dnssl
->router
= router
;
1015 dnssl
->valid_until
= time_now
+ lifetime
* USEC_PER_SEC
;
1020 s
->valid_until
= time_now
+ lifetime
* USEC_PER_SEC
;
1022 r
= set_ensure_consume(&link
->ndisc_dnssl
, &ndisc_dnssl_hash_ops
, TAKE_PTR(s
));
1031 static int ndisc_router_process_options(Link
*link
, sd_ndisc_router
*rt
) {
1033 assert(link
->network
);
1036 for (int r
= sd_ndisc_router_option_rewind(rt
); ; r
= sd_ndisc_router_option_next(rt
)) {
1040 return log_link_error_errno(link
, r
, "Failed to iterate through options: %m");
1041 if (r
== 0) /* EOF */
1044 r
= sd_ndisc_router_option_get_type(rt
, &type
);
1046 return log_link_error_errno(link
, r
, "Failed to get RA option type: %m");
1050 case SD_NDISC_OPTION_PREFIX_INFORMATION
: {
1051 union in_addr_union a
;
1054 r
= sd_ndisc_router_prefix_get_address(rt
, &a
.in6
);
1056 return log_link_error_errno(link
, r
, "Failed to get prefix address: %m");
1058 if (set_contains(link
->network
->ndisc_deny_listed_prefix
, &a
.in6
)) {
1059 if (DEBUG_LOGGING
) {
1060 _cleanup_free_
char *b
= NULL
;
1062 (void) in_addr_to_string(AF_INET6
, &a
, &b
);
1063 log_link_debug(link
, "Prefix '%s' is deny-listed, ignoring", strna(b
));
1068 r
= sd_ndisc_router_prefix_get_flags(rt
, &flags
);
1070 return log_link_error_errno(link
, r
, "Failed to get RA prefix flags: %m");
1072 if (link
->network
->ipv6_accept_ra_use_onlink_prefix
&&
1073 FLAGS_SET(flags
, ND_OPT_PI_FLAG_ONLINK
)) {
1074 r
= ndisc_router_process_onlink_prefix(link
, rt
);
1079 if (link
->network
->ipv6_accept_ra_use_autonomous_prefix
&&
1080 FLAGS_SET(flags
, ND_OPT_PI_FLAG_AUTO
)) {
1081 r
= ndisc_router_process_autonomous_prefix(link
, rt
);
1088 case SD_NDISC_OPTION_ROUTE_INFORMATION
:
1089 r
= ndisc_router_process_route(link
, rt
);
1094 case SD_NDISC_OPTION_RDNSS
:
1095 if (link
->network
->ipv6_accept_ra_use_dns
) {
1096 r
= ndisc_router_process_rdnss(link
, rt
);
1102 case SD_NDISC_OPTION_DNSSL
:
1103 if (link
->network
->ipv6_accept_ra_use_dns
) {
1104 r
= ndisc_router_process_dnssl(link
, rt
);
1113 static int ndisc_router_handler(Link
*link
, sd_ndisc_router
*rt
) {
1114 struct in6_addr router
;
1121 assert(link
->network
);
1122 assert(link
->manager
);
1125 link
->ndisc_addresses_configured
= false;
1126 link
->ndisc_routes_configured
= false;
1130 r
= sd_ndisc_router_get_address(rt
, &router
);
1132 return log_link_error_errno(link
, r
, "Failed to get router address from RA: %m");
1134 SET_FOREACH(na
, link
->ndisc_addresses
)
1135 if (IN6_ARE_ADDR_EQUAL(&na
->router
, &router
))
1138 SET_FOREACH(nr
, link
->ndisc_routes
)
1139 if (IN6_ARE_ADDR_EQUAL(&nr
->router
, &router
))
1142 r
= sd_ndisc_router_get_flags(rt
, &flags
);
1144 return log_link_error_errno(link
, r
, "Failed to get RA flags: %m");
1146 if ((flags
& (ND_RA_FLAG_MANAGED
| ND_RA_FLAG_OTHER
) && link
->network
->ipv6_accept_ra_start_dhcp6_client
)) {
1148 if (link
->network
->ipv6_accept_ra_start_dhcp6_client
== IPV6_ACCEPT_RA_START_DHCP6_CLIENT_ALWAYS
)
1149 r
= dhcp6_request_address(link
, false);
1151 /* (re)start DHCPv6 client in stateful or stateless mode according to RA flags */
1152 r
= dhcp6_request_address(link
, !(flags
& ND_RA_FLAG_MANAGED
));
1153 if (r
< 0 && r
!= -EBUSY
)
1154 return log_link_error_errno(link
, r
, "Could not acquire DHCPv6 lease on NDisc request: %m");
1156 log_link_debug(link
, "Acquiring DHCPv6 lease on NDisc request");
1159 r
= ndisc_router_process_default(link
, rt
);
1162 r
= ndisc_router_process_options(link
, rt
);
1166 if (link
->ndisc_addresses_messages
== 0)
1167 link
->ndisc_addresses_configured
= true;
1169 log_link_debug(link
, "Setting SLAAC addresses.");
1171 /* address_handler calls link_set_routes() and link_set_nexthop(). Before they are
1172 * called, the related flags must be cleared. Otherwise, the link becomes configured
1173 * state before routes are configured. */
1174 link
->static_routes_configured
= false;
1175 link
->static_nexthops_configured
= false;
1178 if (link
->ndisc_routes_messages
== 0)
1179 link
->ndisc_routes_configured
= true;
1181 log_link_debug(link
, "Setting NDisc routes.");
1183 r
= ndisc_remove_old(link
);
1187 if (link
->ndisc_addresses_configured
&& link
->ndisc_routes_configured
)
1188 link_check_ready(link
);
1190 link_set_state(link
, LINK_STATE_CONFIGURING
);
1195 static void ndisc_handler(sd_ndisc
*nd
, sd_ndisc_event event
, sd_ndisc_router
*rt
, void *userdata
) {
1196 Link
*link
= userdata
;
1201 if (IN_SET(link
->state
, LINK_STATE_FAILED
, LINK_STATE_LINGER
))
1206 case SD_NDISC_EVENT_ROUTER
:
1207 r
= ndisc_router_handler(link
, rt
);
1209 link_enter_failed(link
);
1214 case SD_NDISC_EVENT_TIMEOUT
:
1215 log_link_debug(link
, "NDisc handler get timeout event");
1216 if (link
->ndisc_addresses_messages
== 0 && link
->ndisc_routes_messages
== 0) {
1217 link
->ndisc_addresses_configured
= true;
1218 link
->ndisc_routes_configured
= true;
1219 link_check_ready(link
);
1223 assert_not_reached("Unknown NDisc event");
1227 int ndisc_configure(Link
*link
) {
1232 if (!link_ipv6_accept_ra_enabled(link
))
1236 r
= sd_ndisc_new(&link
->ndisc
);
1240 r
= sd_ndisc_attach_event(link
->ndisc
, link
->manager
->event
, 0);
1245 r
= sd_ndisc_set_mac(link
->ndisc
, &link
->mac
);
1249 r
= sd_ndisc_set_ifindex(link
->ndisc
, link
->ifindex
);
1253 r
= sd_ndisc_set_callback(link
->ndisc
, ndisc_handler
, link
);
1260 void ndisc_vacuum(Link
*link
) {
1264 bool updated
= false;
1268 /* Removes all RDNSS and DNSSL entries whose validity time has passed */
1270 time_now
= now(clock_boottime_or_monotonic());
1272 SET_FOREACH(r
, link
->ndisc_rdnss
)
1273 if (r
->valid_until
< time_now
) {
1274 free(set_remove(link
->ndisc_rdnss
, r
));
1278 SET_FOREACH(d
, link
->ndisc_dnssl
)
1279 if (d
->valid_until
< time_now
) {
1280 free(set_remove(link
->ndisc_dnssl
, d
));
1288 void ndisc_flush(Link
*link
) {
1291 /* Removes all RDNSS and DNSSL entries, without exception */
1293 link
->ndisc_rdnss
= set_free(link
->ndisc_rdnss
);
1294 link
->ndisc_dnssl
= set_free(link
->ndisc_dnssl
);
1297 int ipv6token_new(IPv6Token
**ret
) {
1300 p
= new(IPv6Token
, 1);
1305 .address_generation_type
= IPV6_TOKEN_ADDRESS_GENERATION_NONE
,
1313 static void ipv6_token_hash_func(const IPv6Token
*p
, struct siphash
*state
) {
1314 siphash24_compress(&p
->address_generation_type
, sizeof(p
->address_generation_type
), state
);
1315 siphash24_compress(&p
->prefix
, sizeof(p
->prefix
), state
);
1318 static int ipv6_token_compare_func(const IPv6Token
*a
, const IPv6Token
*b
) {
1321 r
= CMP(a
->address_generation_type
, b
->address_generation_type
);
1325 return memcmp(&a
->prefix
, &b
->prefix
, sizeof(struct in6_addr
));
1328 DEFINE_HASH_OPS_WITH_KEY_DESTRUCTOR(
1329 ipv6_token_hash_ops
,
1331 ipv6_token_hash_func
,
1332 ipv6_token_compare_func
,
1335 int config_parse_ndisc_deny_listed_prefix(
1337 const char *filename
,
1339 const char *section
,
1340 unsigned section_line
,
1347 Network
*network
= data
;
1356 if (isempty(rvalue
)) {
1357 network
->ndisc_deny_listed_prefix
= set_free_free(network
->ndisc_deny_listed_prefix
);
1361 for (p
= rvalue
;;) {
1362 _cleanup_free_
char *n
= NULL
;
1363 _cleanup_free_
struct in6_addr
*a
= NULL
;
1364 union in_addr_union ip
;
1366 r
= extract_first_word(&p
, &n
, NULL
, 0);
1370 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
1371 "Failed to parse NDisc deny-listed prefix, ignoring assignment: %s",
1378 r
= in_addr_from_string(AF_INET6
, n
, &ip
);
1380 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
1381 "NDisc deny-listed prefix is invalid, ignoring assignment: %s", n
);
1385 if (set_contains(network
->ndisc_deny_listed_prefix
, &ip
.in6
))
1388 a
= newdup(struct in6_addr
, &ip
.in6
, 1);
1392 r
= set_ensure_consume(&network
->ndisc_deny_listed_prefix
, &in6_addr_hash_ops
, TAKE_PTR(a
));
1398 int config_parse_address_generation_type(
1400 const char *filename
,
1402 const char *section
,
1403 unsigned section_line
,
1410 _cleanup_free_ IPv6Token
*token
= NULL
;
1411 union in_addr_union buffer
;
1412 Network
*network
= data
;
1421 if (isempty(rvalue
)) {
1422 network
->ipv6_tokens
= ordered_set_free(network
->ipv6_tokens
);
1426 r
= ipv6token_new(&token
);
1430 if ((p
= startswith(rvalue
, "prefixstable"))) {
1431 token
->address_generation_type
= IPV6_TOKEN_ADDRESS_GENERATION_PREFIXSTABLE
;
1434 else if (*p
== '\0')
1437 log_syntax(unit
, LOG_WARNING
, filename
, line
, 0,
1438 "Invalid IPv6 token mode in %s=, ignoring assignment: %s",
1443 token
->address_generation_type
= IPV6_TOKEN_ADDRESS_GENERATION_STATIC
;
1444 p
= startswith(rvalue
, "static:");
1450 r
= in_addr_from_string(AF_INET6
, p
, &buffer
);
1452 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
1453 "Failed to parse IP address in %s=, ignoring assignment: %s",
1457 if (token
->address_generation_type
== IPV6_TOKEN_ADDRESS_GENERATION_STATIC
&&
1458 in_addr_is_null(AF_INET6
, &buffer
)) {
1459 log_syntax(unit
, LOG_WARNING
, filename
, line
, 0,
1460 "IPv6 address in %s= cannot be the ANY address, ignoring assignment: %s",
1464 token
->prefix
= buffer
.in6
;
1467 r
= ordered_set_ensure_allocated(&network
->ipv6_tokens
, &ipv6_token_hash_ops
);
1471 r
= ordered_set_put(network
->ipv6_tokens
, token
);
1473 log_syntax(unit
, LOG_DEBUG
, filename
, line
, r
,
1474 "IPv6 token '%s' is duplicated, ignoring: %m", rvalue
);
1476 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
1477 "Failed to store IPv6 token '%s', ignoring: %m", rvalue
);
1484 DEFINE_CONFIG_PARSE_ENUM(config_parse_ipv6_accept_ra_start_dhcp6_client
, ipv6_accept_ra_start_dhcp6_client
, IPv6AcceptRAStartDHCP6Client
,
1485 "Failed to parse DHCPv6Client= setting")
1486 static const char* const ipv6_accept_ra_start_dhcp6_client_table
[_IPV6_ACCEPT_RA_START_DHCP6_CLIENT_MAX
] = {
1487 [IPV6_ACCEPT_RA_START_DHCP6_CLIENT_NO
] = "no",
1488 [IPV6_ACCEPT_RA_START_DHCP6_CLIENT_ALWAYS
] = "always",
1489 [IPV6_ACCEPT_RA_START_DHCP6_CLIENT_YES
] = "yes",
1492 DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(ipv6_accept_ra_start_dhcp6_client
, IPv6AcceptRAStartDHCP6Client
, IPV6_ACCEPT_RA_START_DHCP6_CLIENT_YES
);