1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
3 Copyright © 2014 Intel Corporation. All rights reserved.
7 #include <netinet/icmp6.h>
8 #include <net/if_arp.h>
13 #include "missing_network.h"
14 #include "networkd-address.h"
15 #include "networkd-dhcp6.h"
16 #include "networkd-manager.h"
17 #include "networkd-ndisc.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 assert(link
->network
->ipv6_accept_ra
>= 0);
56 return link
->network
->ipv6_accept_ra
;
59 void network_adjust_ipv6_accept_ra(Network
*network
) {
62 if (!FLAGS_SET(network
->link_local
, ADDRESS_FAMILY_IPV6
)) {
63 if (network
->ipv6_accept_ra
> 0)
64 log_warning("%s: IPv6AcceptRA= is enabled but IPv6 link local addressing is disabled or not supported. "
65 "Disabling IPv6AcceptRA=.", network
->filename
);
66 network
->ipv6_accept_ra
= false;
69 if (network
->ipv6_accept_ra
< 0)
70 /* default to accept RA if ip_forward is disabled and ignore RA if ip_forward is enabled */
71 network
->ipv6_accept_ra
= !FLAGS_SET(network
->ip_forward
, ADDRESS_FAMILY_IPV6
);
74 static int ndisc_remove_old_one(Link
*link
, const struct in6_addr
*router
, bool force
);
76 static int ndisc_address_callback(Address
*address
) {
77 struct in6_addr router
= {};
81 assert(address
->link
);
83 SET_FOREACH(n
, address
->link
->ndisc_addresses
)
84 if (n
->address
== address
) {
89 if (IN6_IS_ADDR_UNSPECIFIED(&router
)) {
90 _cleanup_free_
char *buf
= NULL
;
92 (void) in_addr_to_string(address
->family
, &address
->in_addr
, &buf
);
93 log_link_debug(address
->link
, "%s is called for %s/%u, but it is already removed, ignoring.",
94 __func__
, strna(buf
), address
->prefixlen
);
98 /* Make this called only once */
99 SET_FOREACH(n
, address
->link
->ndisc_addresses
)
100 if (IN6_ARE_ADDR_EQUAL(&n
->router
, &router
))
101 n
->address
->callback
= NULL
;
103 return ndisc_remove_old_one(address
->link
, &router
, true);
106 static int ndisc_remove_old_one(Link
*link
, const struct in6_addr
*router
, bool force
) {
117 bool set_callback
= false;
119 if (!link
->ndisc_addresses_configured
|| !link
->ndisc_routes_configured
)
122 SET_FOREACH(na
, link
->ndisc_addresses
)
123 if (!na
->marked
&& IN6_ARE_ADDR_EQUAL(&na
->router
, router
)) {
129 SET_FOREACH(na
, link
->ndisc_addresses
)
130 if (!na
->marked
&& address_is_ready(na
->address
)) {
131 set_callback
= false;
136 SET_FOREACH(na
, link
->ndisc_addresses
)
137 if (!na
->marked
&& IN6_ARE_ADDR_EQUAL(&na
->router
, router
))
138 na
->address
->callback
= ndisc_address_callback
;
141 _cleanup_free_
char *buf
= NULL
;
143 (void) in_addr_to_string(AF_INET6
, (union in_addr_union
*) router
, &buf
);
144 log_link_debug(link
, "No SLAAC address obtained from %s is ready. "
145 "The old NDisc information will be removed later.",
153 _cleanup_free_
char *buf
= NULL
;
155 (void) in_addr_to_string(AF_INET6
, (union in_addr_union
*) router
, &buf
);
156 log_link_debug(link
, "Removing old NDisc information obtained from %s.", strna(buf
));
161 SET_FOREACH(na
, link
->ndisc_addresses
)
162 if (na
->marked
&& IN6_ARE_ADDR_EQUAL(&na
->router
, router
)) {
163 k
= address_remove(na
->address
, link
, NULL
);
168 SET_FOREACH(nr
, link
->ndisc_routes
)
169 if (nr
->marked
&& IN6_ARE_ADDR_EQUAL(&nr
->router
, router
)) {
170 k
= route_remove(nr
->route
, NULL
, link
, NULL
);
175 SET_FOREACH(rdnss
, link
->ndisc_rdnss
)
176 if (rdnss
->marked
&& IN6_ARE_ADDR_EQUAL(&rdnss
->router
, router
))
177 free(set_remove(link
->ndisc_rdnss
, rdnss
));
179 SET_FOREACH(dnssl
, link
->ndisc_dnssl
)
180 if (dnssl
->marked
&& IN6_ARE_ADDR_EQUAL(&dnssl
->router
, router
))
181 free(set_remove(link
->ndisc_dnssl
, dnssl
));
186 static int ndisc_remove_old(Link
*link
) {
187 _cleanup_set_free_free_ Set
*routers
= NULL
;
188 _cleanup_free_
struct in6_addr
*router
= NULL
;
198 routers
= set_new(&in6_addr_hash_ops
);
202 SET_FOREACH(na
, link
->ndisc_addresses
)
203 if (!set_contains(routers
, &na
->router
)) {
204 router
= newdup(struct in6_addr
, &na
->router
, 1);
208 r
= set_put(routers
, router
);
216 SET_FOREACH(nr
, link
->ndisc_routes
)
217 if (!set_contains(routers
, &nr
->router
)) {
218 router
= newdup(struct in6_addr
, &nr
->router
, 1);
222 r
= set_put(routers
, router
);
230 SET_FOREACH(rdnss
, link
->ndisc_rdnss
)
231 if (!set_contains(routers
, &rdnss
->router
)) {
232 router
= newdup(struct in6_addr
, &rdnss
->router
, 1);
236 r
= set_put(routers
, router
);
244 SET_FOREACH(dnssl
, link
->ndisc_dnssl
)
245 if (!set_contains(routers
, &dnssl
->router
)) {
246 router
= newdup(struct in6_addr
, &dnssl
->router
, 1);
250 r
= set_put(routers
, router
);
259 SET_FOREACH(a
, routers
) {
260 k
= ndisc_remove_old_one(link
, a
, false);
268 static void ndisc_route_hash_func(const NDiscRoute
*x
, struct siphash
*state
) {
269 route_hash_func(x
->route
, state
);
272 static int ndisc_route_compare_func(const NDiscRoute
*a
, const NDiscRoute
*b
) {
273 return route_compare_func(a
->route
, b
->route
);
276 DEFINE_PRIVATE_HASH_OPS_WITH_KEY_DESTRUCTOR(
277 ndisc_route_hash_ops
,
279 ndisc_route_hash_func
,
280 ndisc_route_compare_func
,
283 static int ndisc_route_handler(sd_netlink
*rtnl
, sd_netlink_message
*m
, Link
*link
) {
287 assert(link
->ndisc_routes_messages
> 0);
289 link
->ndisc_routes_messages
--;
291 if (IN_SET(link
->state
, LINK_STATE_FAILED
, LINK_STATE_LINGER
))
294 r
= sd_netlink_message_get_errno(m
);
295 if (r
< 0 && r
!= -EEXIST
) {
296 log_link_message_error_errno(link
, m
, r
, "Could not set NDisc route");
297 link_enter_failed(link
);
301 if (link
->ndisc_routes_messages
== 0) {
302 log_link_debug(link
, "NDisc routes set.");
303 link
->ndisc_routes_configured
= true;
305 r
= ndisc_remove_old(link
);
307 link_enter_failed(link
);
311 link_check_ready(link
);
317 static int ndisc_route_configure(Route
*route
, Link
*link
, sd_ndisc_router
*rt
) {
318 _cleanup_free_ NDiscRoute
*nr
= NULL
;
319 NDiscRoute
*nr_exist
;
320 struct in6_addr router
;
328 r
= route_configure(route
, link
, ndisc_route_handler
, &ret
);
330 return log_link_error_errno(link
, r
, "Failed to set NDisc route: %m");
332 link
->ndisc_routes_messages
++;
334 r
= sd_ndisc_router_get_address(rt
, &router
);
336 return log_link_error_errno(link
, r
, "Failed to get router address from RA: %m");
338 nr
= new(NDiscRoute
, 1);
347 nr_exist
= set_get(link
->ndisc_routes
, nr
);
349 nr_exist
->marked
= false;
350 nr_exist
->router
= router
;
354 r
= set_ensure_put(&link
->ndisc_routes
, &ndisc_route_hash_ops
, nr
);
356 return log_link_error_errno(link
, r
, "Failed to store NDisc SLAAC route: %m");
363 static void ndisc_address_hash_func(const NDiscAddress
*x
, struct siphash
*state
) {
364 address_hash_func(x
->address
, state
);
367 static int ndisc_address_compare_func(const NDiscAddress
*a
, const NDiscAddress
*b
) {
368 return address_compare_func(a
->address
, b
->address
);
371 DEFINE_PRIVATE_HASH_OPS_WITH_KEY_DESTRUCTOR(
372 ndisc_address_hash_ops
,
374 ndisc_address_hash_func
,
375 ndisc_address_compare_func
,
378 static int ndisc_address_handler(sd_netlink
*rtnl
, sd_netlink_message
*m
, Link
*link
) {
382 assert(link
->ndisc_addresses_messages
> 0);
384 link
->ndisc_addresses_messages
--;
386 if (IN_SET(link
->state
, LINK_STATE_FAILED
, LINK_STATE_LINGER
))
389 r
= sd_netlink_message_get_errno(m
);
390 if (r
< 0 && r
!= -EEXIST
) {
391 log_link_message_error_errno(link
, m
, r
, "Could not set NDisc address");
392 link_enter_failed(link
);
395 (void) manager_rtnl_process_address(rtnl
, m
, link
->manager
);
397 if (link
->ndisc_addresses_messages
== 0) {
398 log_link_debug(link
, "NDisc SLAAC addresses set.");
399 link
->ndisc_addresses_configured
= true;
401 r
= ndisc_remove_old(link
);
403 link_enter_failed(link
);
407 r
= link_set_routes(link
);
409 link_enter_failed(link
);
417 static int ndisc_address_configure(Address
*address
, Link
*link
, sd_ndisc_router
*rt
) {
418 _cleanup_free_ NDiscAddress
*na
= NULL
;
419 NDiscAddress
*na_exist
;
420 struct in6_addr router
;
428 r
= address_configure(address
, link
, ndisc_address_handler
, true, &ret
);
430 return log_link_error_errno(link
, r
, "Failed to set NDisc SLAAC address: %m");
432 link
->ndisc_addresses_messages
++;
434 r
= sd_ndisc_router_get_address(rt
, &router
);
436 return log_link_error_errno(link
, r
, "Failed to get router address from RA: %m");
438 na
= new(NDiscAddress
, 1);
442 *na
= (NDiscAddress
) {
447 na_exist
= set_get(link
->ndisc_addresses
, na
);
449 na_exist
->marked
= false;
450 na_exist
->router
= router
;
454 r
= set_ensure_put(&link
->ndisc_addresses
, &ndisc_address_hash_ops
, na
);
456 return log_link_error_errno(link
, r
, "Failed to store NDisc SLAAC address: %m");
463 static int ndisc_router_process_default(Link
*link
, sd_ndisc_router
*rt
) {
464 _cleanup_(route_freep
) Route
*route
= NULL
;
465 union in_addr_union gateway
;
475 r
= sd_ndisc_router_get_lifetime(rt
, &lifetime
);
477 return log_link_error_errno(link
, r
, "Failed to get gateway lifetime from RA: %m");
479 if (lifetime
== 0) /* not a default router */
482 r
= sd_ndisc_router_get_address(rt
, &gateway
.in6
);
484 return log_link_error_errno(link
, r
, "Failed to get gateway address from RA: %m");
486 if (address_exists(link
, AF_INET6
, &gateway
)) {
488 _cleanup_free_
char *buffer
= NULL
;
490 (void) in_addr_to_string(AF_INET6
, &gateway
, &buffer
);
491 log_link_debug(link
, "No NDisc route added, gateway %s matches local address",
497 r
= sd_ndisc_router_get_preference(rt
, &preference
);
499 return log_link_error_errno(link
, r
, "Failed to get default router preference from RA: %m");
501 r
= sd_ndisc_router_get_timestamp(rt
, clock_boottime_or_monotonic(), &time_now
);
503 return log_link_error_errno(link
, r
, "Failed to get RA timestamp: %m");
505 r
= sd_ndisc_router_get_mtu(rt
, &mtu
);
509 return log_link_error_errno(link
, r
, "Failed to get default router MTU from RA: %m");
511 table
= link_get_ipv6_accept_ra_route_table(link
);
513 r
= route_new(&route
);
517 route
->family
= AF_INET6
;
518 route
->table
= table
;
519 route
->priority
= link
->network
->dhcp6_route_metric
;
520 route
->protocol
= RTPROT_RA
;
521 route
->pref
= preference
;
522 route
->gw_family
= AF_INET6
;
524 route
->lifetime
= time_now
+ lifetime
* USEC_PER_SEC
;
527 r
= ndisc_route_configure(route
, link
, rt
);
529 return log_link_error_errno(link
, r
, "Could not set default route: %m");
532 HASHMAP_FOREACH(route_gw
, link
->network
->routes_by_section
) {
533 if (!route_gw
->gateway_from_dhcp_or_ra
)
536 if (route_gw
->gw_family
!= AF_INET6
)
539 route_gw
->gw
= gateway
;
540 if (!route_gw
->table_set
)
541 route_gw
->table
= table
;
542 if (!route_gw
->priority_set
)
543 route_gw
->priority
= link
->network
->dhcp6_route_metric
;
544 if (!route_gw
->protocol_set
)
545 route_gw
->protocol
= RTPROT_RA
;
546 if (!route_gw
->pref_set
)
547 route
->pref
= preference
;
548 route_gw
->lifetime
= time_now
+ lifetime
* USEC_PER_SEC
;
549 if (route_gw
->mtu
== 0)
552 r
= ndisc_route_configure(route_gw
, link
, rt
);
554 return log_link_error_errno(link
, r
, "Could not set gateway: %m");
560 static bool stableprivate_address_is_valid(const struct in6_addr
*addr
) {
563 /* According to rfc4291, generated address should not be in the following ranges. */
565 if (memcmp(addr
, &SUBNET_ROUTER_ANYCAST_ADDRESS_RFC4291
, SUBNET_ROUTER_ANYCAST_PREFIXLEN
) == 0)
568 if (memcmp(addr
, &RESERVED_IPV6_INTERFACE_IDENTIFIERS_ADDRESS_RFC4291
, RESERVED_IPV6_INTERFACE_IDENTIFIERS_PREFIXLEN
) == 0)
571 if (memcmp(addr
, &RESERVED_SUBNET_ANYCAST_ADDRESSES_RFC4291
, RESERVED_SUBNET_ANYCAST_PREFIXLEN
) == 0)
577 static int make_stableprivate_address(Link
*link
, const struct in6_addr
*prefix
, uint8_t prefix_len
, uint8_t dad_counter
, struct in6_addr
**ret
) {
578 _cleanup_free_
struct in6_addr
*addr
= NULL
;
579 sd_id128_t secret_key
;
580 struct siphash state
;
585 /* According to rfc7217 section 5.1
586 * RID = F(Prefix, Net_Iface, Network_ID, DAD_Counter, secret_key) */
588 r
= sd_id128_get_machine_app_specific(NDISC_APP_ID
, &secret_key
);
590 return log_error_errno(r
, "Failed to generate key: %m");
592 siphash24_init(&state
, secret_key
.bytes
);
594 l
= MAX(DIV_ROUND_UP(prefix_len
, 8), 8);
595 siphash24_compress(prefix
, l
, &state
);
596 siphash24_compress_string(link
->ifname
, &state
);
597 /* Only last 8 bytes of IB MAC are stable */
598 if (link
->iftype
== ARPHRD_INFINIBAND
)
599 siphash24_compress(&link
->hw_addr
.addr
.infiniband
[12], 8, &state
);
601 siphash24_compress(link
->hw_addr
.addr
.bytes
, link
->hw_addr
.length
, &state
);
602 siphash24_compress(&dad_counter
, sizeof(uint8_t), &state
);
604 rid
= htole64(siphash24_finalize(&state
));
606 addr
= new(struct in6_addr
, 1);
610 memcpy(addr
->s6_addr
, prefix
->s6_addr
, l
);
611 memcpy(addr
->s6_addr
+ l
, &rid
, 16 - l
);
613 if (!stableprivate_address_is_valid(addr
)) {
618 *ret
= TAKE_PTR(addr
);
622 static int ndisc_router_generate_addresses(Link
*link
, struct in6_addr
*address
, uint8_t prefixlen
, Set
**ret
) {
623 _cleanup_set_free_free_ Set
*addresses
= NULL
;
631 addresses
= set_new(&in6_addr_hash_ops
);
635 ORDERED_SET_FOREACH(j
, link
->network
->ipv6_tokens
) {
636 _cleanup_free_
struct in6_addr
*new_address
= NULL
;
638 if (j
->address_generation_type
== IPV6_TOKEN_ADDRESS_GENERATION_PREFIXSTABLE
639 && (IN6_IS_ADDR_UNSPECIFIED(&j
->prefix
) || IN6_ARE_ADDR_EQUAL(&j
->prefix
, address
))) {
640 /* While this loop uses dad_counter and a retry limit as specified in RFC 7217, the loop
641 does not actually attempt Duplicate Address Detection; the counter will be incremented
642 only when the address generation algorithm produces an invalid address, and the loop
643 may exit with an address which ends up being unusable due to duplication on the link.
645 for (; j
->dad_counter
< DAD_CONFLICTS_IDGEN_RETRIES_RFC7217
; j
->dad_counter
++) {
646 r
= make_stableprivate_address(link
, address
, prefixlen
, j
->dad_counter
, &new_address
);
652 } else if (j
->address_generation_type
== IPV6_TOKEN_ADDRESS_GENERATION_STATIC
) {
653 new_address
= new(struct in6_addr
, 1);
657 memcpy(new_address
->s6_addr
, address
->s6_addr
, 8);
658 memcpy(new_address
->s6_addr
+ 8, j
->prefix
.s6_addr
+ 8, 8);
662 r
= set_put(addresses
, new_address
);
664 return log_link_error_errno(link
, r
, "Failed to store SLAAC address: %m");
666 log_link_debug_errno(link
, r
, "Generated SLAAC address is duplicated, ignoring.");
668 TAKE_PTR(new_address
);
672 /* fall back to EUI-64 if no tokens provided addresses */
673 if (set_isempty(addresses
)) {
674 _cleanup_free_
struct in6_addr
*new_address
= NULL
;
676 new_address
= newdup(struct in6_addr
, address
, 1);
680 r
= generate_ipv6_eui_64_address(link
, new_address
);
682 return log_link_error_errno(link
, r
, "Failed to generate EUI64 address: %m");
684 r
= set_put(addresses
, new_address
);
686 return log_link_error_errno(link
, r
, "Failed to store SLAAC address: %m");
688 TAKE_PTR(new_address
);
691 *ret
= TAKE_PTR(addresses
);
696 static int ndisc_router_process_autonomous_prefix(Link
*link
, sd_ndisc_router
*rt
) {
697 uint32_t lifetime_valid
, lifetime_preferred
, lifetime_remaining
;
698 _cleanup_set_free_free_ Set
*addresses
= NULL
;
699 _cleanup_(address_freep
) Address
*address
= NULL
;
700 struct in6_addr addr
, *a
;
708 r
= sd_ndisc_router_get_timestamp(rt
, clock_boottime_or_monotonic(), &time_now
);
710 return log_link_error_errno(link
, r
, "Failed to get RA timestamp: %m");
712 r
= sd_ndisc_router_prefix_get_prefixlen(rt
, &prefixlen
);
714 return log_link_error_errno(link
, r
, "Failed to get prefix length: %m");
716 r
= sd_ndisc_router_prefix_get_valid_lifetime(rt
, &lifetime_valid
);
718 return log_link_error_errno(link
, r
, "Failed to get prefix valid lifetime: %m");
720 r
= sd_ndisc_router_prefix_get_preferred_lifetime(rt
, &lifetime_preferred
);
722 return log_link_error_errno(link
, r
, "Failed to get prefix preferred lifetime: %m");
724 /* The preferred lifetime is never greater than the valid lifetime */
725 if (lifetime_preferred
> lifetime_valid
)
728 r
= sd_ndisc_router_prefix_get_address(rt
, &addr
);
730 return log_link_error_errno(link
, r
, "Failed to get prefix address: %m");
732 r
= ndisc_router_generate_addresses(link
, &addr
, prefixlen
, &addresses
);
736 r
= address_new(&address
);
740 address
->family
= AF_INET6
;
741 address
->prefixlen
= prefixlen
;
742 address
->flags
= IFA_F_NOPREFIXROUTE
|IFA_F_MANAGETEMPADDR
;
743 address
->cinfo
.ifa_prefered
= lifetime_preferred
;
745 SET_FOREACH(a
, addresses
) {
746 Address
*existing_address
;
748 address
->in_addr
.in6
= *a
;
750 /* see RFC4862 section 5.5.3.e */
751 r
= address_get(link
, address
, &existing_address
);
753 lifetime_remaining
= existing_address
->cinfo
.tstamp
/ 100 + existing_address
->cinfo
.ifa_valid
- time_now
/ USEC_PER_SEC
;
754 if (lifetime_valid
> NDISC_PREFIX_LFT_MIN
|| lifetime_valid
> lifetime_remaining
)
755 address
->cinfo
.ifa_valid
= lifetime_valid
;
756 else if (lifetime_remaining
<= NDISC_PREFIX_LFT_MIN
)
757 address
->cinfo
.ifa_valid
= lifetime_remaining
;
759 address
->cinfo
.ifa_valid
= NDISC_PREFIX_LFT_MIN
;
760 } else if (lifetime_valid
> 0)
761 address
->cinfo
.ifa_valid
= lifetime_valid
;
763 continue; /* see RFC4862 section 5.5.3.d */
765 if (address
->cinfo
.ifa_valid
== 0)
768 r
= ndisc_address_configure(address
, link
, rt
);
770 return log_link_error_errno(link
, r
, "Could not set SLAAC address: %m");
776 static int ndisc_router_process_onlink_prefix(Link
*link
, sd_ndisc_router
*rt
) {
777 _cleanup_(route_freep
) Route
*route
= NULL
;
786 r
= sd_ndisc_router_get_timestamp(rt
, clock_boottime_or_monotonic(), &time_now
);
788 return log_link_error_errno(link
, r
, "Failed to get RA timestamp: %m");
790 r
= sd_ndisc_router_prefix_get_prefixlen(rt
, &prefixlen
);
792 return log_link_error_errno(link
, r
, "Failed to get prefix length: %m");
794 r
= sd_ndisc_router_prefix_get_valid_lifetime(rt
, &lifetime
);
796 return log_link_error_errno(link
, r
, "Failed to get prefix lifetime: %m");
798 r
= route_new(&route
);
802 route
->family
= AF_INET6
;
803 route
->table
= link_get_ipv6_accept_ra_route_table(link
);
804 route
->priority
= link
->network
->dhcp6_route_metric
;
805 route
->protocol
= RTPROT_RA
;
806 route
->flags
= RTM_F_PREFIX
;
807 route
->dst_prefixlen
= prefixlen
;
808 route
->lifetime
= time_now
+ lifetime
* USEC_PER_SEC
;
810 r
= sd_ndisc_router_prefix_get_address(rt
, &route
->dst
.in6
);
812 return log_link_error_errno(link
, r
, "Failed to get prefix address: %m");
814 r
= ndisc_route_configure(route
, link
, rt
);
816 return log_link_error_errno(link
, r
, "Could not set prefix route: %m");;
821 static int ndisc_router_process_route(Link
*link
, sd_ndisc_router
*rt
) {
822 _cleanup_(route_freep
) Route
*route
= NULL
;
823 struct in6_addr gateway
;
825 unsigned preference
, prefixlen
;
831 r
= sd_ndisc_router_route_get_lifetime(rt
, &lifetime
);
833 return log_link_error_errno(link
, r
, "Failed to get gateway lifetime from RA: %m");
838 r
= sd_ndisc_router_get_address(rt
, &gateway
);
840 return log_link_error_errno(link
, r
, "Failed to get gateway address from RA: %m");
842 r
= sd_ndisc_router_route_get_prefixlen(rt
, &prefixlen
);
844 return log_link_error_errno(link
, r
, "Failed to get route prefix length: %m");
846 r
= sd_ndisc_router_route_get_preference(rt
, &preference
);
848 return log_link_error_errno(link
, r
, "Failed to get default router preference from RA: %m");
850 r
= sd_ndisc_router_get_timestamp(rt
, clock_boottime_or_monotonic(), &time_now
);
852 return log_link_error_errno(link
, r
, "Failed to get RA timestamp: %m");
854 r
= route_new(&route
);
858 route
->family
= AF_INET6
;
859 route
->table
= link_get_ipv6_accept_ra_route_table(link
);
860 route
->priority
= link
->network
->dhcp6_route_metric
;
861 route
->protocol
= RTPROT_RA
;
862 route
->pref
= preference
;
863 route
->gw
.in6
= gateway
;
864 route
->gw_family
= AF_INET6
;
865 route
->dst_prefixlen
= prefixlen
;
866 route
->lifetime
= time_now
+ lifetime
* USEC_PER_SEC
;
868 r
= sd_ndisc_router_route_get_address(rt
, &route
->dst
.in6
);
870 return log_link_error_errno(link
, r
, "Failed to get route address: %m");
872 r
= ndisc_route_configure(route
, link
, rt
);
874 return log_link_error_errno(link
, r
, "Could not set additional route: %m");
879 static void ndisc_rdnss_hash_func(const NDiscRDNSS
*x
, struct siphash
*state
) {
880 siphash24_compress(&x
->address
, sizeof(x
->address
), state
);
883 static int ndisc_rdnss_compare_func(const NDiscRDNSS
*a
, const NDiscRDNSS
*b
) {
884 return memcmp(&a
->address
, &b
->address
, sizeof(a
->address
));
887 DEFINE_PRIVATE_HASH_OPS_WITH_KEY_DESTRUCTOR(
888 ndisc_rdnss_hash_ops
,
890 ndisc_rdnss_hash_func
,
891 ndisc_rdnss_compare_func
,
894 static int ndisc_router_process_rdnss(Link
*link
, sd_ndisc_router
*rt
) {
896 const struct in6_addr
*a
;
897 struct in6_addr router
;
905 r
= sd_ndisc_router_get_address(rt
, &router
);
907 return log_link_error_errno(link
, r
, "Failed to get router address from RA: %m");
909 r
= sd_ndisc_router_get_timestamp(rt
, clock_boottime_or_monotonic(), &time_now
);
911 return log_link_error_errno(link
, r
, "Failed to get RA timestamp: %m");
913 r
= sd_ndisc_router_rdnss_get_lifetime(rt
, &lifetime
);
915 return log_link_error_errno(link
, r
, "Failed to get RDNSS lifetime: %m");
917 n
= sd_ndisc_router_rdnss_get_addresses(rt
, &a
);
919 return log_link_error_errno(link
, n
, "Failed to get RDNSS addresses: %m");
921 SET_FOREACH(rdnss
, link
->ndisc_rdnss
)
922 if (IN6_ARE_ADDR_EQUAL(&rdnss
->router
, &router
))
923 rdnss
->marked
= true;
928 if (n
>= (int) NDISC_RDNSS_MAX
) {
929 log_link_warning(link
, "Too many RDNSS records per link. Only first %i records will be used.", NDISC_RDNSS_MAX
);
933 for (int j
= 0; j
< n
; j
++) {
934 _cleanup_free_ NDiscRDNSS
*x
= NULL
;
939 rdnss
= set_get(link
->ndisc_rdnss
, &d
);
941 rdnss
->marked
= false;
942 rdnss
->router
= router
;
943 rdnss
->valid_until
= time_now
+ lifetime
* USEC_PER_SEC
;
947 x
= new(NDiscRDNSS
, 1);
954 .valid_until
= time_now
+ lifetime
* USEC_PER_SEC
,
957 r
= set_ensure_consume(&link
->ndisc_rdnss
, &ndisc_rdnss_hash_ops
, TAKE_PTR(x
));
966 static void ndisc_dnssl_hash_func(const NDiscDNSSL
*x
, struct siphash
*state
) {
967 siphash24_compress_string(NDISC_DNSSL_DOMAIN(x
), state
);
970 static int ndisc_dnssl_compare_func(const NDiscDNSSL
*a
, const NDiscDNSSL
*b
) {
971 return strcmp(NDISC_DNSSL_DOMAIN(a
), NDISC_DNSSL_DOMAIN(b
));
974 DEFINE_PRIVATE_HASH_OPS_WITH_KEY_DESTRUCTOR(
975 ndisc_dnssl_hash_ops
,
977 ndisc_dnssl_hash_func
,
978 ndisc_dnssl_compare_func
,
981 static int ndisc_router_process_dnssl(Link
*link
, sd_ndisc_router
*rt
) {
982 _cleanup_strv_free_
char **l
= NULL
;
983 struct in6_addr router
;
993 r
= sd_ndisc_router_get_address(rt
, &router
);
995 return log_link_error_errno(link
, r
, "Failed to get router address from RA: %m");
997 r
= sd_ndisc_router_get_timestamp(rt
, clock_boottime_or_monotonic(), &time_now
);
999 return log_link_error_errno(link
, r
, "Failed to get RA timestamp: %m");
1001 r
= sd_ndisc_router_dnssl_get_lifetime(rt
, &lifetime
);
1003 return log_link_error_errno(link
, r
, "Failed to get DNSSL lifetime: %m");
1005 r
= sd_ndisc_router_dnssl_get_domains(rt
, &l
);
1007 return log_link_error_errno(link
, r
, "Failed to get DNSSL addresses: %m");
1009 SET_FOREACH(dnssl
, link
->ndisc_dnssl
)
1010 if (IN6_ARE_ADDR_EQUAL(&dnssl
->router
, &router
))
1011 dnssl
->marked
= true;
1016 if (strv_length(l
) >= NDISC_DNSSL_MAX
) {
1017 log_link_warning(link
, "Too many DNSSL records per link. Only first %i records will be used.", NDISC_DNSSL_MAX
);
1018 STRV_FOREACH(j
, l
+ NDISC_DNSSL_MAX
)
1022 STRV_FOREACH(j
, l
) {
1023 _cleanup_free_ NDiscDNSSL
*s
= NULL
;
1025 s
= malloc0(ALIGN(sizeof(NDiscDNSSL
)) + strlen(*j
) + 1);
1029 strcpy(NDISC_DNSSL_DOMAIN(s
), *j
);
1031 dnssl
= set_get(link
->ndisc_dnssl
, s
);
1033 dnssl
->marked
= false;
1034 dnssl
->router
= router
;
1035 dnssl
->valid_until
= time_now
+ lifetime
* USEC_PER_SEC
;
1040 s
->valid_until
= time_now
+ lifetime
* USEC_PER_SEC
;
1042 r
= set_ensure_consume(&link
->ndisc_dnssl
, &ndisc_dnssl_hash_ops
, TAKE_PTR(s
));
1051 static int ndisc_router_process_options(Link
*link
, sd_ndisc_router
*rt
) {
1053 assert(link
->network
);
1056 for (int r
= sd_ndisc_router_option_rewind(rt
); ; r
= sd_ndisc_router_option_next(rt
)) {
1060 return log_link_error_errno(link
, r
, "Failed to iterate through options: %m");
1061 if (r
== 0) /* EOF */
1064 r
= sd_ndisc_router_option_get_type(rt
, &type
);
1066 return log_link_error_errno(link
, r
, "Failed to get RA option type: %m");
1070 case SD_NDISC_OPTION_PREFIX_INFORMATION
: {
1071 union in_addr_union a
;
1074 r
= sd_ndisc_router_prefix_get_address(rt
, &a
.in6
);
1076 return log_link_error_errno(link
, r
, "Failed to get prefix address: %m");
1078 if (set_contains(link
->network
->ndisc_deny_listed_prefix
, &a
.in6
)) {
1079 if (DEBUG_LOGGING
) {
1080 _cleanup_free_
char *b
= NULL
;
1082 (void) in_addr_to_string(AF_INET6
, &a
, &b
);
1083 log_link_debug(link
, "Prefix '%s' is deny-listed, ignoring", strna(b
));
1088 r
= sd_ndisc_router_prefix_get_flags(rt
, &flags
);
1090 return log_link_error_errno(link
, r
, "Failed to get RA prefix flags: %m");
1092 if (link
->network
->ipv6_accept_ra_use_onlink_prefix
&&
1093 FLAGS_SET(flags
, ND_OPT_PI_FLAG_ONLINK
)) {
1094 r
= ndisc_router_process_onlink_prefix(link
, rt
);
1099 if (link
->network
->ipv6_accept_ra_use_autonomous_prefix
&&
1100 FLAGS_SET(flags
, ND_OPT_PI_FLAG_AUTO
)) {
1101 r
= ndisc_router_process_autonomous_prefix(link
, rt
);
1108 case SD_NDISC_OPTION_ROUTE_INFORMATION
:
1109 r
= ndisc_router_process_route(link
, rt
);
1114 case SD_NDISC_OPTION_RDNSS
:
1115 if (link
->network
->ipv6_accept_ra_use_dns
) {
1116 r
= ndisc_router_process_rdnss(link
, rt
);
1122 case SD_NDISC_OPTION_DNSSL
:
1123 if (link
->network
->ipv6_accept_ra_use_dns
) {
1124 r
= ndisc_router_process_dnssl(link
, rt
);
1133 static int ndisc_router_handler(Link
*link
, sd_ndisc_router
*rt
) {
1134 struct in6_addr router
;
1141 assert(link
->network
);
1142 assert(link
->manager
);
1145 link
->ndisc_addresses_configured
= false;
1146 link
->ndisc_routes_configured
= false;
1150 r
= sd_ndisc_router_get_address(rt
, &router
);
1152 return log_link_error_errno(link
, r
, "Failed to get router address from RA: %m");
1154 SET_FOREACH(na
, link
->ndisc_addresses
)
1155 if (IN6_ARE_ADDR_EQUAL(&na
->router
, &router
))
1158 SET_FOREACH(nr
, link
->ndisc_routes
)
1159 if (IN6_ARE_ADDR_EQUAL(&nr
->router
, &router
))
1162 r
= sd_ndisc_router_get_flags(rt
, &flags
);
1164 return log_link_error_errno(link
, r
, "Failed to get RA flags: %m");
1166 if ((flags
& (ND_RA_FLAG_MANAGED
| ND_RA_FLAG_OTHER
) && link
->network
->ipv6_accept_ra_start_dhcp6_client
)) {
1168 if (link
->network
->ipv6_accept_ra_start_dhcp6_client
== IPV6_ACCEPT_RA_START_DHCP6_CLIENT_ALWAYS
)
1169 r
= dhcp6_request_address(link
, false);
1171 /* (re)start DHCPv6 client in stateful or stateless mode according to RA flags */
1172 r
= dhcp6_request_address(link
, !(flags
& ND_RA_FLAG_MANAGED
));
1173 if (r
< 0 && r
!= -EBUSY
)
1174 return log_link_error_errno(link
, r
, "Could not acquire DHCPv6 lease on NDisc request: %m");
1176 log_link_debug(link
, "Acquiring DHCPv6 lease on NDisc request");
1179 r
= ndisc_router_process_default(link
, rt
);
1182 r
= ndisc_router_process_options(link
, rt
);
1186 if (link
->ndisc_addresses_messages
== 0)
1187 link
->ndisc_addresses_configured
= true;
1189 log_link_debug(link
, "Setting SLAAC addresses.");
1191 /* address_handler calls link_set_routes() and link_set_nexthop(). Before they are
1192 * called, the related flags must be cleared. Otherwise, the link becomes configured
1193 * state before routes are configured. */
1194 link
->static_routes_configured
= false;
1195 link
->static_nexthops_configured
= false;
1198 if (link
->ndisc_routes_messages
== 0)
1199 link
->ndisc_routes_configured
= true;
1201 log_link_debug(link
, "Setting NDisc routes.");
1203 r
= ndisc_remove_old(link
);
1207 if (link
->ndisc_addresses_configured
&& link
->ndisc_routes_configured
)
1208 link_check_ready(link
);
1210 link_set_state(link
, LINK_STATE_CONFIGURING
);
1215 static void ndisc_handler(sd_ndisc
*nd
, sd_ndisc_event event
, sd_ndisc_router
*rt
, void *userdata
) {
1216 Link
*link
= userdata
;
1221 if (IN_SET(link
->state
, LINK_STATE_FAILED
, LINK_STATE_LINGER
))
1226 case SD_NDISC_EVENT_ROUTER
:
1227 r
= ndisc_router_handler(link
, rt
);
1229 link_enter_failed(link
);
1234 case SD_NDISC_EVENT_TIMEOUT
:
1235 log_link_debug(link
, "NDisc handler get timeout event");
1236 if (link
->ndisc_addresses_messages
== 0 && link
->ndisc_routes_messages
== 0) {
1237 link
->ndisc_addresses_configured
= true;
1238 link
->ndisc_routes_configured
= true;
1239 link_check_ready(link
);
1243 assert_not_reached("Unknown NDisc event");
1247 int ndisc_configure(Link
*link
) {
1252 if (!link_ipv6_accept_ra_enabled(link
))
1256 r
= sd_ndisc_new(&link
->ndisc
);
1260 r
= sd_ndisc_attach_event(link
->ndisc
, link
->manager
->event
, 0);
1265 r
= sd_ndisc_set_mac(link
->ndisc
, &link
->hw_addr
.addr
.ether
);
1269 r
= sd_ndisc_set_ifindex(link
->ndisc
, link
->ifindex
);
1273 r
= sd_ndisc_set_callback(link
->ndisc
, ndisc_handler
, link
);
1280 void ndisc_vacuum(Link
*link
) {
1284 bool updated
= false;
1288 /* Removes all RDNSS and DNSSL entries whose validity time has passed */
1290 time_now
= now(clock_boottime_or_monotonic());
1292 SET_FOREACH(r
, link
->ndisc_rdnss
)
1293 if (r
->valid_until
< time_now
) {
1294 free(set_remove(link
->ndisc_rdnss
, r
));
1298 SET_FOREACH(d
, link
->ndisc_dnssl
)
1299 if (d
->valid_until
< time_now
) {
1300 free(set_remove(link
->ndisc_dnssl
, d
));
1308 void ndisc_flush(Link
*link
) {
1311 /* Removes all RDNSS and DNSSL entries, without exception */
1313 link
->ndisc_rdnss
= set_free(link
->ndisc_rdnss
);
1314 link
->ndisc_dnssl
= set_free(link
->ndisc_dnssl
);
1317 int ipv6token_new(IPv6Token
**ret
) {
1320 p
= new(IPv6Token
, 1);
1325 .address_generation_type
= IPV6_TOKEN_ADDRESS_GENERATION_NONE
,
1333 static void ipv6_token_hash_func(const IPv6Token
*p
, struct siphash
*state
) {
1334 siphash24_compress(&p
->address_generation_type
, sizeof(p
->address_generation_type
), state
);
1335 siphash24_compress(&p
->prefix
, sizeof(p
->prefix
), state
);
1338 static int ipv6_token_compare_func(const IPv6Token
*a
, const IPv6Token
*b
) {
1341 r
= CMP(a
->address_generation_type
, b
->address_generation_type
);
1345 return memcmp(&a
->prefix
, &b
->prefix
, sizeof(struct in6_addr
));
1348 DEFINE_HASH_OPS_WITH_KEY_DESTRUCTOR(
1349 ipv6_token_hash_ops
,
1351 ipv6_token_hash_func
,
1352 ipv6_token_compare_func
,
1355 int config_parse_ndisc_deny_listed_prefix(
1357 const char *filename
,
1359 const char *section
,
1360 unsigned section_line
,
1367 Network
*network
= data
;
1376 if (isempty(rvalue
)) {
1377 network
->ndisc_deny_listed_prefix
= set_free_free(network
->ndisc_deny_listed_prefix
);
1381 for (p
= rvalue
;;) {
1382 _cleanup_free_
char *n
= NULL
;
1383 _cleanup_free_
struct in6_addr
*a
= NULL
;
1384 union in_addr_union ip
;
1386 r
= extract_first_word(&p
, &n
, NULL
, 0);
1390 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
1391 "Failed to parse NDisc deny-listed prefix, ignoring assignment: %s",
1398 r
= in_addr_from_string(AF_INET6
, n
, &ip
);
1400 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
1401 "NDisc deny-listed prefix is invalid, ignoring assignment: %s", n
);
1405 if (set_contains(network
->ndisc_deny_listed_prefix
, &ip
.in6
))
1408 a
= newdup(struct in6_addr
, &ip
.in6
, 1);
1412 r
= set_ensure_consume(&network
->ndisc_deny_listed_prefix
, &in6_addr_hash_ops
, TAKE_PTR(a
));
1418 int config_parse_address_generation_type(
1420 const char *filename
,
1422 const char *section
,
1423 unsigned section_line
,
1430 _cleanup_free_ IPv6Token
*token
= NULL
;
1431 union in_addr_union buffer
;
1432 Network
*network
= data
;
1441 if (isempty(rvalue
)) {
1442 network
->ipv6_tokens
= ordered_set_free(network
->ipv6_tokens
);
1446 r
= ipv6token_new(&token
);
1450 if ((p
= startswith(rvalue
, "prefixstable"))) {
1451 token
->address_generation_type
= IPV6_TOKEN_ADDRESS_GENERATION_PREFIXSTABLE
;
1454 else if (*p
== '\0')
1457 log_syntax(unit
, LOG_WARNING
, filename
, line
, 0,
1458 "Invalid IPv6 token mode in %s=, ignoring assignment: %s",
1463 token
->address_generation_type
= IPV6_TOKEN_ADDRESS_GENERATION_STATIC
;
1464 p
= startswith(rvalue
, "static:");
1470 r
= in_addr_from_string(AF_INET6
, p
, &buffer
);
1472 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
1473 "Failed to parse IP address in %s=, ignoring assignment: %s",
1477 if (token
->address_generation_type
== IPV6_TOKEN_ADDRESS_GENERATION_STATIC
&&
1478 in_addr_is_null(AF_INET6
, &buffer
)) {
1479 log_syntax(unit
, LOG_WARNING
, filename
, line
, 0,
1480 "IPv6 address in %s= cannot be the ANY address, ignoring assignment: %s",
1484 token
->prefix
= buffer
.in6
;
1487 r
= ordered_set_ensure_allocated(&network
->ipv6_tokens
, &ipv6_token_hash_ops
);
1491 r
= ordered_set_put(network
->ipv6_tokens
, token
);
1493 log_syntax(unit
, LOG_DEBUG
, filename
, line
, r
,
1494 "IPv6 token '%s' is duplicated, ignoring: %m", rvalue
);
1496 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
1497 "Failed to store IPv6 token '%s', ignoring: %m", rvalue
);
1504 DEFINE_CONFIG_PARSE_ENUM(config_parse_ipv6_accept_ra_start_dhcp6_client
, ipv6_accept_ra_start_dhcp6_client
, IPv6AcceptRAStartDHCP6Client
,
1505 "Failed to parse DHCPv6Client= setting")
1506 static const char* const ipv6_accept_ra_start_dhcp6_client_table
[_IPV6_ACCEPT_RA_START_DHCP6_CLIENT_MAX
] = {
1507 [IPV6_ACCEPT_RA_START_DHCP6_CLIENT_NO
] = "no",
1508 [IPV6_ACCEPT_RA_START_DHCP6_CLIENT_ALWAYS
] = "always",
1509 [IPV6_ACCEPT_RA_START_DHCP6_CLIENT_YES
] = "yes",
1512 DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(ipv6_accept_ra_start_dhcp6_client
, IPv6AcceptRAStartDHCP6Client
, IPV6_ACCEPT_RA_START_DHCP6_CLIENT_YES
);