1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
3 Copyright © 2014 Intel Corporation. All rights reserved.
7 #include <netinet/icmp6.h>
9 #include <linux/if_arp.h>
13 #include "missing_network.h"
14 #include "networkd-address-generation.h"
15 #include "networkd-address.h"
16 #include "networkd-dhcp6.h"
17 #include "networkd-manager.h"
18 #include "networkd-ndisc.h"
19 #include "networkd-queue.h"
20 #include "networkd-route.h"
21 #include "networkd-state-file.h"
22 #include "string-table.h"
23 #include "string-util.h"
26 #define NDISC_DNSSL_MAX 64U
27 #define NDISC_RDNSS_MAX 64U
29 bool link_ipv6_accept_ra_enabled(Link
*link
) {
32 if (!socket_ipv6_is_supported())
35 if (link
->flags
& IFF_LOOPBACK
)
38 if (link
->iftype
== ARPHRD_CAN
)
44 if (!link_may_have_ipv6ll(link
, /* check_multicast = */ true))
47 assert(link
->network
->ipv6_accept_ra
>= 0);
48 return link
->network
->ipv6_accept_ra
;
51 void network_adjust_ipv6_accept_ra(Network
*network
) {
54 if (!FLAGS_SET(network
->link_local
, ADDRESS_FAMILY_IPV6
)) {
55 if (network
->ipv6_accept_ra
> 0)
56 log_warning("%s: IPv6AcceptRA= is enabled but IPv6 link-local addressing is disabled or not supported. "
57 "Disabling IPv6AcceptRA=.", network
->filename
);
58 network
->ipv6_accept_ra
= false;
61 if (network
->ipv6_accept_ra
< 0)
62 /* default to accept RA if ip_forward is disabled and ignore RA if ip_forward is enabled */
63 network
->ipv6_accept_ra
= !FLAGS_SET(network
->ip_forward
, ADDRESS_FAMILY_IPV6
);
65 /* When RouterAllowList=, PrefixAllowList= or RouteAllowList= are specified, then
66 * RouterDenyList=, PrefixDenyList= or RouteDenyList= are ignored, respectively. */
67 if (!set_isempty(network
->ndisc_allow_listed_router
))
68 network
->ndisc_deny_listed_router
= set_free_free(network
->ndisc_deny_listed_router
);
69 if (!set_isempty(network
->ndisc_allow_listed_prefix
))
70 network
->ndisc_deny_listed_prefix
= set_free_free(network
->ndisc_deny_listed_prefix
);
71 if (!set_isempty(network
->ndisc_allow_listed_route_prefix
))
72 network
->ndisc_deny_listed_route_prefix
= set_free_free(network
->ndisc_deny_listed_route_prefix
);
75 static int ndisc_remove(Link
*link
, struct in6_addr
*router
) {
85 SET_FOREACH(route
, link
->routes
) {
86 if (route
->source
!= NETWORK_CONFIG_SOURCE_NDISC
)
88 if (!route_is_marked(route
))
90 if (router
&& !in6_addr_equal(router
, &route
->provider
.in6
))
93 k
= route_remove(route
);
97 route_cancel_request(route
, link
);
100 SET_FOREACH(address
, link
->addresses
) {
101 if (address
->source
!= NETWORK_CONFIG_SOURCE_NDISC
)
103 if (!address_is_marked(address
))
105 if (router
&& !in6_addr_equal(router
, &address
->provider
.in6
))
108 k
= address_remove(address
);
112 address_cancel_request(address
);
115 SET_FOREACH(rdnss
, link
->ndisc_rdnss
) {
118 if (router
&& !in6_addr_equal(router
, &rdnss
->router
))
121 free(set_remove(link
->ndisc_rdnss
, rdnss
));
125 SET_FOREACH(dnssl
, link
->ndisc_dnssl
) {
128 if (router
&& !in6_addr_equal(router
, &dnssl
->router
))
131 free(set_remove(link
->ndisc_dnssl
, dnssl
));
141 static int ndisc_check_ready(Link
*link
);
143 static int ndisc_address_ready_callback(Address
*address
) {
147 assert(address
->link
);
149 SET_FOREACH(a
, address
->link
->addresses
)
150 if (a
->source
== NETWORK_CONFIG_SOURCE_NDISC
)
153 return ndisc_check_ready(address
->link
);
156 static int ndisc_check_ready(Link
*link
) {
157 bool found
= false, ready
= false;
163 if (link
->ndisc_messages
> 0) {
164 log_link_debug(link
, "%s(): SLAAC addresses and routes are not set.", __func__
);
168 SET_FOREACH(address
, link
->addresses
) {
169 if (address
->source
!= NETWORK_CONFIG_SOURCE_NDISC
)
174 if (address_is_ready(address
)) {
180 if (found
&& !ready
) {
181 SET_FOREACH(address
, link
->addresses
)
182 if (address
->source
== NETWORK_CONFIG_SOURCE_NDISC
)
183 address
->callback
= ndisc_address_ready_callback
;
185 log_link_debug(link
, "%s(): no SLAAC address is ready.", __func__
);
189 link
->ndisc_configured
= true;
190 log_link_debug(link
, "SLAAC addresses and routes set.");
192 r
= ndisc_remove(link
, NULL
);
196 link_check_ready(link
);
200 static int ndisc_route_handler(sd_netlink
*rtnl
, sd_netlink_message
*m
, Request
*req
, Link
*link
, Route
*route
) {
205 r
= route_configure_handler_internal(rtnl
, m
, link
, "Could not set NDisc route");
209 r
= ndisc_check_ready(link
);
211 link_enter_failed(link
);
216 static int ndisc_request_route(Route
*in
, Link
*link
, sd_ndisc_router
*rt
) {
217 _cleanup_(route_freep
) Route
*route
= in
;
218 struct in6_addr router
;
226 r
= sd_ndisc_router_get_address(rt
, &router
);
230 route
->source
= NETWORK_CONFIG_SOURCE_NDISC
;
231 route
->provider
.in6
= router
;
232 if (!route
->table_set
)
233 route
->table
= link_get_ipv6_accept_ra_route_table(link
);
234 if (!route
->priority_set
)
235 route
->priority
= link
->network
->ipv6_accept_ra_route_metric
;
236 if (!route
->protocol_set
)
237 route
->protocol
= RTPROT_RA
;
239 if (route_get(NULL
, link
, route
, &existing
) < 0)
240 link
->ndisc_configured
= false;
242 route_unmark(existing
);
244 return link_request_route(link
, TAKE_PTR(route
), true, &link
->ndisc_messages
,
245 ndisc_route_handler
, NULL
);
248 static int ndisc_address_handler(sd_netlink
*rtnl
, sd_netlink_message
*m
, Request
*req
, Link
*link
, Address
*address
) {
253 r
= address_configure_handler_internal(rtnl
, m
, link
, "Could not set NDisc address");
257 r
= ndisc_check_ready(link
);
259 link_enter_failed(link
);
264 static int ndisc_request_address(Address
*in
, Link
*link
, sd_ndisc_router
*rt
) {
265 _cleanup_(address_freep
) Address
*address
= in
;
266 struct in6_addr router
;
274 r
= sd_ndisc_router_get_address(rt
, &router
);
278 address
->source
= NETWORK_CONFIG_SOURCE_NDISC
;
279 address
->provider
.in6
= router
;
281 r
= free_and_strdup_warn(&address
->netlabel
, link
->network
->ndisc_netlabel
);
285 if (address_get(link
, address
, &existing
) < 0)
286 link
->ndisc_configured
= false;
288 address_unmark(existing
);
290 return link_request_address(link
, TAKE_PTR(address
), true, &link
->ndisc_messages
,
291 ndisc_address_handler
, NULL
);
294 static int ndisc_router_process_default(Link
*link
, sd_ndisc_router
*rt
) {
295 usec_t lifetime_usec
, timestamp_usec
;
296 struct in6_addr gateway
;
297 uint16_t lifetime_sec
;
303 assert(link
->network
);
306 if (!link
->network
->ipv6_accept_ra_use_gateway
&&
307 hashmap_isempty(link
->network
->routes_by_section
))
310 r
= sd_ndisc_router_get_lifetime(rt
, &lifetime_sec
);
312 return log_link_error_errno(link
, r
, "Failed to get gateway lifetime from RA: %m");
314 if (lifetime_sec
== 0) /* not a default router */
317 r
= sd_ndisc_router_get_timestamp(rt
, CLOCK_BOOTTIME
, ×tamp_usec
);
319 return log_link_error_errno(link
, r
, "Failed to get RA timestamp: %m");
321 lifetime_usec
= sec16_to_usec(lifetime_sec
, timestamp_usec
);
323 r
= sd_ndisc_router_get_address(rt
, &gateway
);
325 return log_link_error_errno(link
, r
, "Failed to get gateway address from RA: %m");
327 if (link_get_ipv6_address(link
, &gateway
, 0, NULL
) >= 0) {
329 log_link_debug(link
, "No NDisc route added, gateway %s matches local address",
330 IN6_ADDR_TO_STRING(&gateway
));
334 r
= sd_ndisc_router_get_preference(rt
, &preference
);
336 return log_link_error_errno(link
, r
, "Failed to get default router preference from RA: %m");
338 if (link
->network
->ipv6_accept_ra_use_mtu
) {
339 r
= sd_ndisc_router_get_mtu(rt
, &mtu
);
340 if (r
< 0 && r
!= -ENODATA
)
341 return log_link_error_errno(link
, r
, "Failed to get default router MTU from RA: %m");
344 if (link
->network
->ipv6_accept_ra_use_gateway
) {
345 _cleanup_(route_freep
) Route
*route
= NULL
;
347 r
= route_new(&route
);
351 route
->family
= AF_INET6
;
352 route
->pref
= preference
;
353 route
->gw_family
= AF_INET6
;
354 route
->gw
.in6
= gateway
;
355 route
->lifetime_usec
= lifetime_usec
;
358 r
= ndisc_request_route(TAKE_PTR(route
), link
, rt
);
360 return log_link_error_errno(link
, r
, "Could not request default route: %m");
364 HASHMAP_FOREACH(route_gw
, link
->network
->routes_by_section
) {
365 _cleanup_(route_freep
) Route
*route
= NULL
;
367 if (!route_gw
->gateway_from_dhcp_or_ra
)
370 if (route_gw
->gw_family
!= AF_INET6
)
373 r
= route_dup(route_gw
, &route
);
377 route
->gw
.in6
= gateway
;
378 if (!route
->pref_set
)
379 route
->pref
= preference
;
380 route
->lifetime_usec
= lifetime_usec
;
384 r
= ndisc_request_route(TAKE_PTR(route
), link
, rt
);
386 return log_link_error_errno(link
, r
, "Could not request gateway: %m");
392 static int ndisc_router_process_autonomous_prefix(Link
*link
, sd_ndisc_router
*rt
) {
393 uint32_t lifetime_valid_sec
, lifetime_preferred_sec
;
394 usec_t lifetime_valid_usec
, lifetime_preferred_usec
, timestamp_usec
;
395 _cleanup_set_free_ Set
*addresses
= NULL
;
396 struct in6_addr prefix
, *a
;
401 assert(link
->network
);
404 if (!link
->network
->ipv6_accept_ra_use_autonomous_prefix
)
407 r
= sd_ndisc_router_get_timestamp(rt
, CLOCK_BOOTTIME
, ×tamp_usec
);
409 return log_link_error_errno(link
, r
, "Failed to get RA timestamp: %m");
411 r
= sd_ndisc_router_prefix_get_address(rt
, &prefix
);
413 return log_link_error_errno(link
, r
, "Failed to get prefix address: %m");
415 r
= sd_ndisc_router_prefix_get_prefixlen(rt
, &prefixlen
);
417 return log_link_error_errno(link
, r
, "Failed to get prefix length: %m");
419 /* ndisc_generate_addresses() below requires the prefix length <= 64. */
420 if (prefixlen
> 64) {
421 log_link_debug(link
, "Prefix is longer than 64, ignoring autonomous prefix %s.",
422 IN6_ADDR_PREFIX_TO_STRING(&prefix
, prefixlen
));
426 r
= sd_ndisc_router_prefix_get_valid_lifetime(rt
, &lifetime_valid_sec
);
428 return log_link_error_errno(link
, r
, "Failed to get prefix valid lifetime: %m");
430 if (lifetime_valid_sec
== 0) {
431 log_link_debug(link
, "Ignoring prefix as its valid lifetime is zero.");
435 r
= sd_ndisc_router_prefix_get_preferred_lifetime(rt
, &lifetime_preferred_sec
);
437 return log_link_error_errno(link
, r
, "Failed to get prefix preferred lifetime: %m");
439 /* The preferred lifetime is never greater than the valid lifetime */
440 if (lifetime_preferred_sec
> lifetime_valid_sec
)
443 lifetime_valid_usec
= sec_to_usec(lifetime_valid_sec
, timestamp_usec
);
444 lifetime_preferred_usec
= sec_to_usec(lifetime_preferred_sec
, timestamp_usec
);
446 r
= ndisc_generate_addresses(link
, &prefix
, prefixlen
, &addresses
);
448 return log_link_error_errno(link
, r
, "Failed to generate SLAAC addresses: %m");
450 SET_FOREACH(a
, addresses
) {
451 _cleanup_(address_freep
) Address
*address
= NULL
;
454 r
= address_new(&address
);
458 address
->family
= AF_INET6
;
459 address
->in_addr
.in6
= *a
;
460 address
->prefixlen
= prefixlen
;
461 address
->flags
= IFA_F_NOPREFIXROUTE
|IFA_F_MANAGETEMPADDR
;
462 address
->lifetime_valid_usec
= lifetime_valid_usec
;
463 address
->lifetime_preferred_usec
= lifetime_preferred_usec
;
465 /* See RFC4862, section 5.5.3.e. But the following logic is deviated from RFC4862 by
466 * honoring all valid lifetimes to improve the reaction of SLAAC to renumbering events.
467 * See draft-ietf-6man-slaac-renum-02, section 4.2. */
468 r
= address_get(link
, address
, &e
);
470 /* If the address is already assigned, but not valid anymore, then refuse to
471 * update the address, and it will be removed. */
472 if (e
->lifetime_valid_usec
< timestamp_usec
)
476 r
= ndisc_request_address(TAKE_PTR(address
), link
, rt
);
478 return log_link_error_errno(link
, r
, "Could not request SLAAC address: %m");
484 static int ndisc_router_process_onlink_prefix(Link
*link
, sd_ndisc_router
*rt
) {
485 _cleanup_(route_freep
) Route
*route
= NULL
;
486 usec_t timestamp_usec
;
487 uint32_t lifetime_sec
;
492 assert(link
->network
);
495 if (!link
->network
->ipv6_accept_ra_use_onlink_prefix
)
498 r
= sd_ndisc_router_prefix_get_valid_lifetime(rt
, &lifetime_sec
);
500 return log_link_error_errno(link
, r
, "Failed to get prefix lifetime: %m");
502 if (lifetime_sec
== 0)
505 r
= sd_ndisc_router_get_timestamp(rt
, CLOCK_BOOTTIME
, ×tamp_usec
);
507 return log_link_error_errno(link
, r
, "Failed to get RA timestamp: %m");
509 r
= sd_ndisc_router_prefix_get_prefixlen(rt
, &prefixlen
);
511 return log_link_error_errno(link
, r
, "Failed to get prefix length: %m");
513 r
= route_new(&route
);
517 route
->family
= AF_INET6
;
518 route
->flags
= RTM_F_PREFIX
;
519 route
->dst_prefixlen
= prefixlen
;
520 route
->lifetime_usec
= sec_to_usec(lifetime_sec
, timestamp_usec
);
522 r
= sd_ndisc_router_prefix_get_address(rt
, &route
->dst
.in6
);
524 return log_link_error_errno(link
, r
, "Failed to get prefix address: %m");
526 r
= ndisc_request_route(TAKE_PTR(route
), link
, rt
);
528 return log_link_error_errno(link
, r
, "Could not request prefix route: %m");
533 static int ndisc_router_process_prefix(Link
*link
, sd_ndisc_router
*rt
) {
540 assert(link
->network
);
543 r
= sd_ndisc_router_prefix_get_address(rt
, &a
);
545 return log_link_error_errno(link
, r
, "Failed to get prefix address: %m");
547 r
= sd_ndisc_router_prefix_get_prefixlen(rt
, &prefixlen
);
549 return log_link_error_errno(link
, r
, "Failed to get prefix length: %m");
551 if (in6_prefix_is_filtered(&a
, prefixlen
, link
->network
->ndisc_allow_listed_prefix
, link
->network
->ndisc_deny_listed_prefix
)) {
553 log_link_debug(link
, "Prefix '%s' is %s, ignoring",
554 !set_isempty(link
->network
->ndisc_allow_listed_prefix
) ? "not in allow list"
556 IN6_ADDR_PREFIX_TO_STRING(&a
, prefixlen
));
560 r
= sd_ndisc_router_prefix_get_flags(rt
, &flags
);
562 return log_link_error_errno(link
, r
, "Failed to get RA prefix flags: %m");
564 if (FLAGS_SET(flags
, ND_OPT_PI_FLAG_ONLINK
)) {
565 r
= ndisc_router_process_onlink_prefix(link
, rt
);
570 if (FLAGS_SET(flags
, ND_OPT_PI_FLAG_AUTO
)) {
571 r
= ndisc_router_process_autonomous_prefix(link
, rt
);
579 static int ndisc_router_process_route(Link
*link
, sd_ndisc_router
*rt
) {
580 _cleanup_(route_freep
) Route
*route
= NULL
;
581 unsigned preference
, prefixlen
;
582 struct in6_addr gateway
, dst
;
583 uint32_t lifetime_sec
;
584 usec_t timestamp_usec
;
589 if (!link
->network
->ipv6_accept_ra_use_route_prefix
)
592 r
= sd_ndisc_router_route_get_lifetime(rt
, &lifetime_sec
);
594 return log_link_error_errno(link
, r
, "Failed to get route lifetime from RA: %m");
596 if (lifetime_sec
== 0)
599 r
= sd_ndisc_router_route_get_address(rt
, &dst
);
601 return log_link_error_errno(link
, r
, "Failed to get route destination address: %m");
603 r
= sd_ndisc_router_route_get_prefixlen(rt
, &prefixlen
);
605 return log_link_error_errno(link
, r
, "Failed to get route prefix length: %m");
607 if (in6_addr_is_null(&dst
) && prefixlen
== 0) {
608 log_link_debug(link
, "Route prefix is ::/0, ignoring");
612 if (in6_prefix_is_filtered(&dst
, prefixlen
,
613 link
->network
->ndisc_allow_listed_route_prefix
,
614 link
->network
->ndisc_deny_listed_route_prefix
)) {
617 log_link_debug(link
, "Route prefix %s is %s, ignoring",
618 !set_isempty(link
->network
->ndisc_allow_listed_route_prefix
) ? "not in allow list"
620 IN6_ADDR_PREFIX_TO_STRING(&dst
, prefixlen
));
624 r
= sd_ndisc_router_get_address(rt
, &gateway
);
626 return log_link_error_errno(link
, r
, "Failed to get gateway address from RA: %m");
628 if (link_get_ipv6_address(link
, &gateway
, 0, NULL
) >= 0) {
630 log_link_debug(link
, "Advertised route gateway %s is local to the link, ignoring route",
631 IN6_ADDR_TO_STRING(&gateway
));
635 r
= sd_ndisc_router_route_get_preference(rt
, &preference
);
637 return log_link_error_errno(link
, r
, "Failed to get default router preference from RA: %m");
639 r
= sd_ndisc_router_get_timestamp(rt
, CLOCK_BOOTTIME
, ×tamp_usec
);
641 return log_link_error_errno(link
, r
, "Failed to get RA timestamp: %m");
643 r
= route_new(&route
);
647 route
->family
= AF_INET6
;
648 route
->pref
= preference
;
649 route
->gw
.in6
= gateway
;
650 route
->gw_family
= AF_INET6
;
651 route
->dst
.in6
= dst
;
652 route
->dst_prefixlen
= prefixlen
;
653 route
->lifetime_usec
= sec_to_usec(lifetime_sec
, timestamp_usec
);
655 r
= ndisc_request_route(TAKE_PTR(route
), link
, rt
);
657 return log_link_error_errno(link
, r
, "Could not request additional route: %m");
662 static void ndisc_rdnss_hash_func(const NDiscRDNSS
*x
, struct siphash
*state
) {
663 siphash24_compress(&x
->address
, sizeof(x
->address
), state
);
666 static int ndisc_rdnss_compare_func(const NDiscRDNSS
*a
, const NDiscRDNSS
*b
) {
667 return memcmp(&a
->address
, &b
->address
, sizeof(a
->address
));
670 DEFINE_PRIVATE_HASH_OPS_WITH_KEY_DESTRUCTOR(
671 ndisc_rdnss_hash_ops
,
673 ndisc_rdnss_hash_func
,
674 ndisc_rdnss_compare_func
,
677 static int ndisc_router_process_rdnss(Link
*link
, sd_ndisc_router
*rt
) {
678 usec_t lifetime_usec
, timestamp_usec
;
679 uint32_t lifetime_sec
;
680 const struct in6_addr
*a
;
681 struct in6_addr router
;
682 bool updated
= false;
686 assert(link
->network
);
689 if (!link
->network
->ipv6_accept_ra_use_dns
)
692 r
= sd_ndisc_router_get_address(rt
, &router
);
694 return log_link_error_errno(link
, r
, "Failed to get router address from RA: %m");
696 r
= sd_ndisc_router_get_timestamp(rt
, CLOCK_BOOTTIME
, ×tamp_usec
);
698 return log_link_error_errno(link
, r
, "Failed to get RA timestamp: %m");
700 r
= sd_ndisc_router_rdnss_get_lifetime(rt
, &lifetime_sec
);
702 return log_link_error_errno(link
, r
, "Failed to get RDNSS lifetime: %m");
704 if (lifetime_sec
== 0)
707 lifetime_usec
= sec_to_usec(lifetime_sec
, timestamp_usec
);
709 n
= sd_ndisc_router_rdnss_get_addresses(rt
, &a
);
711 return log_link_error_errno(link
, n
, "Failed to get RDNSS addresses: %m");
713 if (n
>= (int) NDISC_RDNSS_MAX
) {
714 log_link_warning(link
, "Too many RDNSS records per link. Only first %u records will be used.", NDISC_RDNSS_MAX
);
718 for (int j
= 0; j
< n
; j
++) {
719 _cleanup_free_ NDiscRDNSS
*x
= NULL
;
720 NDiscRDNSS
*rdnss
, d
= {
724 rdnss
= set_get(link
->ndisc_rdnss
, &d
);
726 rdnss
->marked
= false;
727 rdnss
->router
= router
;
728 rdnss
->lifetime_usec
= lifetime_usec
;
732 x
= new(NDiscRDNSS
, 1);
739 .lifetime_usec
= lifetime_usec
,
742 r
= set_ensure_consume(&link
->ndisc_rdnss
, &ndisc_rdnss_hash_ops
, TAKE_PTR(x
));
756 static void ndisc_dnssl_hash_func(const NDiscDNSSL
*x
, struct siphash
*state
) {
757 siphash24_compress_string(NDISC_DNSSL_DOMAIN(x
), state
);
760 static int ndisc_dnssl_compare_func(const NDiscDNSSL
*a
, const NDiscDNSSL
*b
) {
761 return strcmp(NDISC_DNSSL_DOMAIN(a
), NDISC_DNSSL_DOMAIN(b
));
764 DEFINE_PRIVATE_HASH_OPS_WITH_KEY_DESTRUCTOR(
765 ndisc_dnssl_hash_ops
,
767 ndisc_dnssl_hash_func
,
768 ndisc_dnssl_compare_func
,
771 static int ndisc_router_process_dnssl(Link
*link
, sd_ndisc_router
*rt
) {
772 _cleanup_strv_free_
char **l
= NULL
;
773 usec_t lifetime_usec
, timestamp_usec
;
774 struct in6_addr router
;
775 uint32_t lifetime_sec
;
776 bool updated
= false;
780 assert(link
->network
);
783 if (link
->network
->ipv6_accept_ra_use_domains
== DHCP_USE_DOMAINS_NO
)
786 r
= sd_ndisc_router_get_address(rt
, &router
);
788 return log_link_error_errno(link
, r
, "Failed to get router address from RA: %m");
790 r
= sd_ndisc_router_get_timestamp(rt
, CLOCK_BOOTTIME
, ×tamp_usec
);
792 return log_link_error_errno(link
, r
, "Failed to get RA timestamp: %m");
794 r
= sd_ndisc_router_dnssl_get_lifetime(rt
, &lifetime_sec
);
796 return log_link_error_errno(link
, r
, "Failed to get DNSSL lifetime: %m");
798 if (lifetime_sec
== 0)
801 lifetime_usec
= sec_to_usec(lifetime_sec
, timestamp_usec
);
803 r
= sd_ndisc_router_dnssl_get_domains(rt
, &l
);
805 return log_link_error_errno(link
, r
, "Failed to get DNSSL addresses: %m");
807 if (strv_length(l
) >= NDISC_DNSSL_MAX
) {
808 log_link_warning(link
, "Too many DNSSL records per link. Only first %u records will be used.", NDISC_DNSSL_MAX
);
809 STRV_FOREACH(j
, l
+ NDISC_DNSSL_MAX
)
814 _cleanup_free_ NDiscDNSSL
*s
= NULL
;
817 s
= malloc0(ALIGN(sizeof(NDiscDNSSL
)) + strlen(*j
) + 1);
821 strcpy(NDISC_DNSSL_DOMAIN(s
), *j
);
823 dnssl
= set_get(link
->ndisc_dnssl
, s
);
825 dnssl
->marked
= false;
826 dnssl
->router
= router
;
827 dnssl
->lifetime_usec
= lifetime_usec
;
832 s
->lifetime_usec
= lifetime_usec
;
834 r
= set_ensure_consume(&link
->ndisc_dnssl
, &ndisc_dnssl_hash_ops
, TAKE_PTR(s
));
848 static int ndisc_router_process_options(Link
*link
, sd_ndisc_router
*rt
) {
852 assert(link
->network
);
855 for (r
= sd_ndisc_router_option_rewind(rt
); ; r
= sd_ndisc_router_option_next(rt
)) {
859 return log_link_error_errno(link
, r
, "Failed to iterate through options: %m");
860 if (r
== 0) /* EOF */
863 r
= sd_ndisc_router_option_get_type(rt
, &type
);
865 return log_link_error_errno(link
, r
, "Failed to get RA option type: %m");
869 case SD_NDISC_OPTION_PREFIX_INFORMATION
:
870 r
= ndisc_router_process_prefix(link
, rt
);
875 case SD_NDISC_OPTION_ROUTE_INFORMATION
:
876 r
= ndisc_router_process_route(link
, rt
);
881 case SD_NDISC_OPTION_RDNSS
:
882 r
= ndisc_router_process_rdnss(link
, rt
);
887 case SD_NDISC_OPTION_DNSSL
:
888 r
= ndisc_router_process_dnssl(link
, rt
);
896 static void ndisc_mark(Link
*link
, const struct in6_addr
*router
) {
903 link_mark_addresses(link
, NETWORK_CONFIG_SOURCE_NDISC
, router
);
904 link_mark_routes(link
, NETWORK_CONFIG_SOURCE_NDISC
, router
);
906 SET_FOREACH(rdnss
, link
->ndisc_rdnss
)
907 if (in6_addr_equal(&rdnss
->router
, router
))
908 rdnss
->marked
= true;
910 SET_FOREACH(dnssl
, link
->ndisc_dnssl
)
911 if (in6_addr_equal(&dnssl
->router
, router
))
912 dnssl
->marked
= true;
915 static int ndisc_start_dhcp6_client(Link
*link
, sd_ndisc_router
*rt
) {
919 assert(link
->network
);
921 switch (link
->network
->ipv6_accept_ra_start_dhcp6_client
) {
922 case IPV6_ACCEPT_RA_START_DHCP6_CLIENT_NO
:
925 case IPV6_ACCEPT_RA_START_DHCP6_CLIENT_YES
: {
928 r
= sd_ndisc_router_get_flags(rt
, &flags
);
930 return log_link_warning_errno(link
, r
, "Failed to get RA flags: %m");
932 if ((flags
& (ND_RA_FLAG_MANAGED
| ND_RA_FLAG_OTHER
)) == 0)
935 /* (re)start DHCPv6 client in stateful or stateless mode according to RA flags.
936 * Note, if both "managed" and "other configuration" bits are set, then ignore
937 * "other configuration" bit. See RFC 4861. */
938 r
= dhcp6_start_on_ra(link
, !(flags
& ND_RA_FLAG_MANAGED
));
941 case IPV6_ACCEPT_RA_START_DHCP6_CLIENT_ALWAYS
:
942 /* When IPv6AcceptRA.DHCPv6Client=always, start dhcp6 client in solicit mode
943 * even if the router flags have neither M nor O flags. */
944 r
= dhcp6_start_on_ra(link
, /* information_request = */ false);
948 assert_not_reached();
952 return log_link_error_errno(link
, r
, "Could not acquire DHCPv6 lease on NDisc request: %m");
954 log_link_debug(link
, "Acquiring DHCPv6 lease on NDisc request");
958 static int ndisc_router_handler(Link
*link
, sd_ndisc_router
*rt
) {
959 struct in6_addr router
;
963 assert(link
->network
);
964 assert(link
->manager
);
967 r
= sd_ndisc_router_get_address(rt
, &router
);
969 return log_link_error_errno(link
, r
, "Failed to get router address from RA: %m");
971 if (in6_prefix_is_filtered(&router
, 128, link
->network
->ndisc_allow_listed_router
, link
->network
->ndisc_deny_listed_router
)) {
973 if (!set_isempty(link
->network
->ndisc_allow_listed_router
))
974 log_link_debug(link
, "Router %s is not in allow list, ignoring.", IN6_ADDR_TO_STRING(&router
));
976 log_link_debug(link
, "Router %s is in deny list, ignoring.", IN6_ADDR_TO_STRING(&router
));
981 ndisc_mark(link
, &router
);
983 r
= ndisc_start_dhcp6_client(link
, rt
);
987 r
= ndisc_router_process_default(link
, rt
);
991 r
= ndisc_router_process_options(link
, rt
);
995 if (link
->ndisc_messages
== 0) {
996 link
->ndisc_configured
= true;
998 r
= ndisc_remove(link
, &router
);
1002 log_link_debug(link
, "Setting SLAAC addresses and router.");
1004 if (!link
->ndisc_configured
)
1005 link_set_state(link
, LINK_STATE_CONFIGURING
);
1007 link_check_ready(link
);
1011 static void ndisc_handler(sd_ndisc
*nd
, sd_ndisc_event_t event
, sd_ndisc_router
*rt
, void *userdata
) {
1012 Link
*link
= ASSERT_PTR(userdata
);
1015 if (IN_SET(link
->state
, LINK_STATE_FAILED
, LINK_STATE_LINGER
))
1020 case SD_NDISC_EVENT_ROUTER
:
1021 r
= ndisc_router_handler(link
, rt
);
1023 link_enter_failed(link
);
1028 case SD_NDISC_EVENT_TIMEOUT
:
1029 log_link_debug(link
, "NDisc handler get timeout event");
1030 if (link
->ndisc_messages
== 0) {
1031 link
->ndisc_configured
= true;
1032 link_check_ready(link
);
1036 assert_not_reached();
1040 static int ndisc_configure(Link
*link
) {
1045 if (!link_ipv6_accept_ra_enabled(link
))
1049 return -EBUSY
; /* Already configured. */
1051 r
= sd_ndisc_new(&link
->ndisc
);
1055 r
= sd_ndisc_attach_event(link
->ndisc
, link
->manager
->event
, 0);
1059 if (link
->hw_addr
.length
== ETH_ALEN
) {
1060 r
= sd_ndisc_set_mac(link
->ndisc
, &link
->hw_addr
.ether
);
1065 r
= sd_ndisc_set_ifindex(link
->ndisc
, link
->ifindex
);
1069 r
= sd_ndisc_set_callback(link
->ndisc
, ndisc_handler
, link
);
1076 int ndisc_start(Link
*link
) {
1081 if (!link
->ndisc
|| !link
->dhcp6_client
)
1084 if (!link_has_carrier(link
))
1087 if (in6_addr_is_null(&link
->ipv6ll_address
))
1090 log_link_debug(link
, "Discovering IPv6 routers");
1092 r
= sd_ndisc_start(link
->ndisc
);
1099 static int ndisc_process_request(Request
*req
, Link
*link
, void *userdata
) {
1104 if (!link_is_ready_to_configure(link
, /* allow_unmanaged = */ false))
1107 r
= ndisc_configure(link
);
1109 return log_link_warning_errno(link
, r
, "Failed to configure IPv6 Router Discovery: %m");
1111 r
= ndisc_start(link
);
1113 return log_link_warning_errno(link
, r
, "Failed to start IPv6 Router Discovery: %m");
1115 log_link_debug(link
, "IPv6 Router Discovery is configured%s.",
1116 r
> 0 ? " and started" : "");
1120 int link_request_ndisc(Link
*link
) {
1125 if (!link_ipv6_accept_ra_enabled(link
))
1131 r
= link_queue_request(link
, REQUEST_TYPE_NDISC
, ndisc_process_request
, NULL
);
1133 return log_link_warning_errno(link
, r
, "Failed to request configuring of the IPv6 Router Discovery: %m");
1135 log_link_debug(link
, "Requested configuring of the IPv6 Router Discovery.");
1139 void ndisc_vacuum(Link
*link
) {
1145 assert(link
->manager
);
1147 /* Removes all RDNSS and DNSSL entries whose validity time has passed */
1149 assert_se(sd_event_now(link
->manager
->event
, CLOCK_BOOTTIME
, &now_usec
) >= 0);
1151 SET_FOREACH(r
, link
->ndisc_rdnss
)
1152 if (r
->lifetime_usec
< now_usec
)
1153 free(set_remove(link
->ndisc_rdnss
, r
));
1155 SET_FOREACH(d
, link
->ndisc_dnssl
)
1156 if (d
->lifetime_usec
< now_usec
)
1157 free(set_remove(link
->ndisc_dnssl
, d
));
1160 void ndisc_flush(Link
*link
) {
1163 /* Removes all RDNSS and DNSSL entries, without exception */
1165 link
->ndisc_rdnss
= set_free(link
->ndisc_rdnss
);
1166 link
->ndisc_dnssl
= set_free(link
->ndisc_dnssl
);
1169 static const char* const ipv6_accept_ra_start_dhcp6_client_table
[_IPV6_ACCEPT_RA_START_DHCP6_CLIENT_MAX
] = {
1170 [IPV6_ACCEPT_RA_START_DHCP6_CLIENT_NO
] = "no",
1171 [IPV6_ACCEPT_RA_START_DHCP6_CLIENT_ALWAYS
] = "always",
1172 [IPV6_ACCEPT_RA_START_DHCP6_CLIENT_YES
] = "yes",
1175 DEFINE_PRIVATE_STRING_TABLE_LOOKUP_FROM_STRING_WITH_BOOLEAN(ipv6_accept_ra_start_dhcp6_client
, IPv6AcceptRAStartDHCP6Client
, IPV6_ACCEPT_RA_START_DHCP6_CLIENT_YES
);
1177 DEFINE_CONFIG_PARSE_ENUM(config_parse_ipv6_accept_ra_use_domains
, dhcp_use_domains
, DHCPUseDomains
,
1178 "Failed to parse UseDomains= setting");
1179 DEFINE_CONFIG_PARSE_ENUM(config_parse_ipv6_accept_ra_start_dhcp6_client
, ipv6_accept_ra_start_dhcp6_client
, IPv6AcceptRAStartDHCP6Client
,
1180 "Failed to parse DHCPv6Client= setting");