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 "event-util.h"
14 #include "missing_network.h"
15 #include "networkd-address-generation.h"
16 #include "networkd-address.h"
17 #include "networkd-dhcp6.h"
18 #include "networkd-manager.h"
19 #include "networkd-ndisc.h"
20 #include "networkd-queue.h"
21 #include "networkd-route.h"
22 #include "networkd-state-file.h"
23 #include "string-table.h"
24 #include "string-util.h"
26 #include "sysctl-util.h"
28 #define NDISC_DNSSL_MAX 64U
29 #define NDISC_RDNSS_MAX 64U
30 /* Not defined RFC, but let's set an upper limit to make not consume much memory.
31 * This should be safe as typically there should be at most 1 portal per network. */
32 #define NDISC_CAPTIVE_PORTAL_MAX 64U
34 bool link_ipv6_accept_ra_enabled(Link
*link
) {
37 if (!socket_ipv6_is_supported())
40 if (link
->flags
& IFF_LOOPBACK
)
43 if (link
->iftype
== ARPHRD_CAN
)
49 if (!link_may_have_ipv6ll(link
, /* check_multicast = */ true))
52 assert(link
->network
->ipv6_accept_ra
>= 0);
53 return link
->network
->ipv6_accept_ra
;
56 void network_adjust_ipv6_accept_ra(Network
*network
) {
59 if (!FLAGS_SET(network
->link_local
, ADDRESS_FAMILY_IPV6
)) {
60 if (network
->ipv6_accept_ra
> 0)
61 log_warning("%s: IPv6AcceptRA= is enabled but IPv6 link-local addressing is disabled or not supported. "
62 "Disabling IPv6AcceptRA=.", network
->filename
);
63 network
->ipv6_accept_ra
= false;
66 if (network
->ipv6_accept_ra
< 0)
67 /* default to accept RA if ip_forward is disabled and ignore RA if ip_forward is enabled */
68 network
->ipv6_accept_ra
= !FLAGS_SET(network
->ip_forward
, ADDRESS_FAMILY_IPV6
);
70 /* When RouterAllowList=, PrefixAllowList= or RouteAllowList= are specified, then
71 * RouterDenyList=, PrefixDenyList= or RouteDenyList= are ignored, respectively. */
72 if (!set_isempty(network
->ndisc_allow_listed_router
))
73 network
->ndisc_deny_listed_router
= set_free_free(network
->ndisc_deny_listed_router
);
74 if (!set_isempty(network
->ndisc_allow_listed_prefix
))
75 network
->ndisc_deny_listed_prefix
= set_free_free(network
->ndisc_deny_listed_prefix
);
76 if (!set_isempty(network
->ndisc_allow_listed_route_prefix
))
77 network
->ndisc_deny_listed_route_prefix
= set_free_free(network
->ndisc_deny_listed_route_prefix
);
80 static int ndisc_check_ready(Link
*link
);
82 static int ndisc_address_ready_callback(Address
*address
) {
86 assert(address
->link
);
88 SET_FOREACH(a
, address
->link
->addresses
)
89 if (a
->source
== NETWORK_CONFIG_SOURCE_NDISC
)
92 return ndisc_check_ready(address
->link
);
95 static int ndisc_check_ready(Link
*link
) {
96 bool found
= false, ready
= false;
101 if (link
->ndisc_messages
> 0) {
102 log_link_debug(link
, "%s(): SLAAC addresses and routes are not set.", __func__
);
106 SET_FOREACH(address
, link
->addresses
) {
107 if (address
->source
!= NETWORK_CONFIG_SOURCE_NDISC
)
112 if (address_is_ready(address
)) {
118 if (found
&& !ready
) {
119 SET_FOREACH(address
, link
->addresses
)
120 if (address
->source
== NETWORK_CONFIG_SOURCE_NDISC
)
121 address
->callback
= ndisc_address_ready_callback
;
123 log_link_debug(link
, "%s(): no SLAAC address is ready.", __func__
);
127 link
->ndisc_configured
= true;
128 log_link_debug(link
, "SLAAC addresses and routes set.");
130 link_check_ready(link
);
134 static int ndisc_route_handler(sd_netlink
*rtnl
, sd_netlink_message
*m
, Request
*req
, Link
*link
, Route
*route
) {
139 r
= route_configure_handler_internal(rtnl
, m
, link
, "Could not set NDisc route");
143 r
= ndisc_check_ready(link
);
145 link_enter_failed(link
);
150 static void ndisc_set_route_priority(Link
*link
, Route
*route
) {
154 if (route
->priority_set
)
155 return; /* explicitly configured. */
157 switch (route
->pref
) {
158 case SD_NDISC_PREFERENCE_LOW
:
159 route
->priority
= link
->network
->ipv6_accept_ra_route_metric_low
;
161 case SD_NDISC_PREFERENCE_MEDIUM
:
162 route
->priority
= link
->network
->ipv6_accept_ra_route_metric_medium
;
164 case SD_NDISC_PREFERENCE_HIGH
:
165 route
->priority
= link
->network
->ipv6_accept_ra_route_metric_high
;
168 assert_not_reached();
172 static int ndisc_request_route(Route
*in
, Link
*link
, sd_ndisc_router
*rt
) {
173 _cleanup_(route_freep
) Route
*route
= in
;
174 struct in6_addr router
;
175 uint8_t hop_limit
= 0;
182 assert(link
->network
);
185 r
= sd_ndisc_router_get_address(rt
, &router
);
189 if (link
->network
->ipv6_accept_ra_use_mtu
) {
190 r
= sd_ndisc_router_get_mtu(rt
, &mtu
);
191 if (r
< 0 && r
!= -ENODATA
)
192 return log_link_warning_errno(link
, r
, "Failed to get default router MTU from RA: %m");
195 if (link
->network
->ipv6_accept_ra_use_hop_limit
) {
196 r
= sd_ndisc_router_get_hop_limit(rt
, &hop_limit
);
197 if (r
< 0 && r
!= -ENODATA
)
198 return log_link_warning_errno(link
, r
, "Failed to get default router hop limit from RA: %m");
201 route
->source
= NETWORK_CONFIG_SOURCE_NDISC
;
202 route
->provider
.in6
= router
;
203 if (!route
->table_set
)
204 route
->table
= link_get_ipv6_accept_ra_route_table(link
);
205 ndisc_set_route_priority(link
, route
);
206 if (!route
->protocol_set
)
207 route
->protocol
= RTPROT_RA
;
208 if (route
->quickack
< 0)
209 route
->quickack
= link
->network
->ipv6_accept_ra_quickack
;
213 if (route
->hop_limit
== 0)
214 route
->hop_limit
= hop_limit
;
216 is_new
= route_get(NULL
, link
, route
, NULL
) < 0;
218 r
= link_request_route(link
, TAKE_PTR(route
), true, &link
->ndisc_messages
,
219 ndisc_route_handler
, NULL
);
223 link
->ndisc_configured
= false;
228 static int ndisc_address_handler(sd_netlink
*rtnl
, sd_netlink_message
*m
, Request
*req
, Link
*link
, Address
*address
) {
233 r
= address_configure_handler_internal(rtnl
, m
, link
, "Could not set NDisc address");
237 r
= ndisc_check_ready(link
);
239 link_enter_failed(link
);
244 static int ndisc_request_address(Address
*in
, Link
*link
, sd_ndisc_router
*rt
) {
245 _cleanup_(address_freep
) Address
*address
= in
;
246 struct in6_addr router
;
254 r
= sd_ndisc_router_get_address(rt
, &router
);
258 address
->source
= NETWORK_CONFIG_SOURCE_NDISC
;
259 address
->provider
.in6
= router
;
261 r
= free_and_strdup_warn(&address
->netlabel
, link
->network
->ndisc_netlabel
);
265 is_new
= address_get(link
, address
, NULL
) < 0;
267 r
= link_request_address(link
, address
, &link
->ndisc_messages
,
268 ndisc_address_handler
, NULL
);
272 link
->ndisc_configured
= false;
277 static int ndisc_router_process_default(Link
*link
, sd_ndisc_router
*rt
) {
278 usec_t lifetime_usec
, timestamp_usec
;
279 uint32_t icmp6_ratelimit
= 0;
280 struct in6_addr gateway
;
281 uint16_t lifetime_sec
;
286 assert(link
->network
);
289 if (!link
->network
->ipv6_accept_ra_use_gateway
&&
290 hashmap_isempty(link
->network
->routes_by_section
))
293 r
= sd_ndisc_router_get_lifetime(rt
, &lifetime_sec
);
295 return log_link_warning_errno(link
, r
, "Failed to get gateway lifetime from RA: %m");
297 r
= sd_ndisc_router_get_timestamp(rt
, CLOCK_BOOTTIME
, ×tamp_usec
);
299 return log_link_warning_errno(link
, r
, "Failed to get RA timestamp: %m");
301 lifetime_usec
= sec16_to_usec(lifetime_sec
, timestamp_usec
);
303 r
= sd_ndisc_router_get_address(rt
, &gateway
);
305 return log_link_warning_errno(link
, r
, "Failed to get gateway address from RA: %m");
307 if (link_get_ipv6_address(link
, &gateway
, 0, NULL
) >= 0) {
309 log_link_debug(link
, "No NDisc route added, gateway %s matches local address",
310 IN6_ADDR_TO_STRING(&gateway
));
314 r
= sd_ndisc_router_get_preference(rt
, &preference
);
316 return log_link_warning_errno(link
, r
, "Failed to get default router preference from RA: %m");
318 if (link
->network
->ipv6_accept_ra_use_gateway
) {
319 _cleanup_(route_freep
) Route
*route
= NULL
;
321 r
= route_new(&route
);
325 route
->family
= AF_INET6
;
326 route
->pref
= preference
;
327 route
->gw_family
= AF_INET6
;
328 route
->gw
.in6
= gateway
;
329 route
->lifetime_usec
= lifetime_usec
;
331 r
= ndisc_request_route(TAKE_PTR(route
), link
, rt
);
333 return log_link_warning_errno(link
, r
, "Could not request default route: %m");
337 HASHMAP_FOREACH(route_gw
, link
->network
->routes_by_section
) {
338 _cleanup_(route_freep
) Route
*route
= NULL
;
340 if (!route_gw
->gateway_from_dhcp_or_ra
)
343 if (route_gw
->gw_family
!= AF_INET6
)
346 r
= route_dup(route_gw
, &route
);
350 route
->gw
.in6
= gateway
;
351 if (!route
->pref_set
)
352 route
->pref
= preference
;
353 route
->lifetime_usec
= lifetime_usec
;
355 r
= ndisc_request_route(TAKE_PTR(route
), link
, rt
);
357 return log_link_warning_errno(link
, r
, "Could not request gateway: %m");
360 r
= sd_ndisc_router_get_icmp6_ratelimit(rt
, &icmp6_ratelimit
);
362 log_link_debug(link
, "Failed to get default router preference from RA: %m");
364 if (icmp6_ratelimit
> 0 && link
->network
->ipv6_accept_ra_use_icmp6_ratelimit
) {
365 char buf
[DECIMAL_STR_MAX(unsigned)];
367 xsprintf(buf
, "%u", icmp6_ratelimit
);
369 r
= sysctl_write("net/ipv6/icmp/ratelimit", buf
);
371 log_link_warning_errno(link
, r
, "Could not configure icmp6 rate limit: %m");
377 static int ndisc_router_process_autonomous_prefix(Link
*link
, sd_ndisc_router
*rt
) {
378 uint32_t lifetime_valid_sec
, lifetime_preferred_sec
;
379 usec_t lifetime_valid_usec
, lifetime_preferred_usec
, timestamp_usec
;
380 _cleanup_set_free_ Set
*addresses
= NULL
;
381 struct in6_addr prefix
, *a
;
386 assert(link
->network
);
389 if (!link
->network
->ipv6_accept_ra_use_autonomous_prefix
)
392 r
= sd_ndisc_router_get_timestamp(rt
, CLOCK_BOOTTIME
, ×tamp_usec
);
394 return log_link_warning_errno(link
, r
, "Failed to get RA timestamp: %m");
396 r
= sd_ndisc_router_prefix_get_address(rt
, &prefix
);
398 return log_link_warning_errno(link
, r
, "Failed to get prefix address: %m");
400 r
= sd_ndisc_router_prefix_get_prefixlen(rt
, &prefixlen
);
402 return log_link_warning_errno(link
, r
, "Failed to get prefix length: %m");
404 /* ndisc_generate_addresses() below requires the prefix length <= 64. */
405 if (prefixlen
> 64) {
406 log_link_debug(link
, "Prefix is longer than 64, ignoring autonomous prefix %s.",
407 IN6_ADDR_PREFIX_TO_STRING(&prefix
, prefixlen
));
411 r
= sd_ndisc_router_prefix_get_valid_lifetime(rt
, &lifetime_valid_sec
);
413 return log_link_warning_errno(link
, r
, "Failed to get prefix valid lifetime: %m");
415 r
= sd_ndisc_router_prefix_get_preferred_lifetime(rt
, &lifetime_preferred_sec
);
417 return log_link_warning_errno(link
, r
, "Failed to get prefix preferred lifetime: %m");
419 /* The preferred lifetime is never greater than the valid lifetime */
420 if (lifetime_preferred_sec
> lifetime_valid_sec
)
423 lifetime_valid_usec
= sec_to_usec(lifetime_valid_sec
, timestamp_usec
);
424 lifetime_preferred_usec
= sec_to_usec(lifetime_preferred_sec
, timestamp_usec
);
426 r
= ndisc_generate_addresses(link
, &prefix
, prefixlen
, &addresses
);
428 return log_link_warning_errno(link
, r
, "Failed to generate SLAAC addresses: %m");
430 SET_FOREACH(a
, addresses
) {
431 _cleanup_(address_freep
) Address
*address
= NULL
;
433 r
= address_new(&address
);
437 address
->family
= AF_INET6
;
438 address
->in_addr
.in6
= *a
;
439 address
->prefixlen
= prefixlen
;
440 address
->flags
= IFA_F_NOPREFIXROUTE
|IFA_F_MANAGETEMPADDR
;
441 address
->lifetime_valid_usec
= lifetime_valid_usec
;
442 address
->lifetime_preferred_usec
= lifetime_preferred_usec
;
444 r
= ndisc_request_address(TAKE_PTR(address
), link
, rt
);
446 return log_link_warning_errno(link
, r
, "Could not request SLAAC address: %m");
452 static int ndisc_router_process_onlink_prefix(Link
*link
, sd_ndisc_router
*rt
) {
453 _cleanup_(route_freep
) Route
*route
= NULL
;
454 unsigned prefixlen
, preference
;
455 usec_t timestamp_usec
;
456 uint32_t lifetime_sec
;
457 struct in6_addr prefix
;
461 assert(link
->network
);
464 if (!link
->network
->ipv6_accept_ra_use_onlink_prefix
)
467 r
= sd_ndisc_router_prefix_get_valid_lifetime(rt
, &lifetime_sec
);
469 return log_link_warning_errno(link
, r
, "Failed to get prefix lifetime: %m");
471 r
= sd_ndisc_router_get_timestamp(rt
, CLOCK_BOOTTIME
, ×tamp_usec
);
473 return log_link_warning_errno(link
, r
, "Failed to get RA timestamp: %m");
475 r
= sd_ndisc_router_prefix_get_address(rt
, &prefix
);
477 return log_link_warning_errno(link
, r
, "Failed to get prefix address: %m");
479 r
= sd_ndisc_router_prefix_get_prefixlen(rt
, &prefixlen
);
481 return log_link_warning_errno(link
, r
, "Failed to get prefix length: %m");
483 /* Prefix Information option does not have preference, hence we use the 'main' preference here */
484 r
= sd_ndisc_router_get_preference(rt
, &preference
);
486 log_link_warning_errno(link
, r
, "Failed to get default router preference from RA: %m");
488 r
= route_new(&route
);
492 route
->family
= AF_INET6
;
493 route
->dst
.in6
= prefix
;
494 route
->dst_prefixlen
= prefixlen
;
495 route
->pref
= preference
;
496 route
->lifetime_usec
= sec_to_usec(lifetime_sec
, timestamp_usec
);
498 r
= ndisc_request_route(TAKE_PTR(route
), link
, rt
);
500 return log_link_warning_errno(link
, r
, "Could not request prefix route: %m");
505 static int ndisc_router_process_prefix(Link
*link
, sd_ndisc_router
*rt
) {
512 assert(link
->network
);
515 r
= sd_ndisc_router_prefix_get_address(rt
, &a
);
517 return log_link_warning_errno(link
, r
, "Failed to get prefix address: %m");
519 /* RFC 4861 Section 4.6.2:
520 * A router SHOULD NOT send a prefix option for the link-local prefix and a host SHOULD ignore such
521 * a prefix option. */
522 if (in6_addr_is_link_local(&a
)) {
523 log_link_debug(link
, "Received link-local prefix, ignoring autonomous prefix.");
527 r
= sd_ndisc_router_prefix_get_prefixlen(rt
, &prefixlen
);
529 return log_link_warning_errno(link
, r
, "Failed to get prefix length: %m");
531 if (in6_prefix_is_filtered(&a
, prefixlen
, link
->network
->ndisc_allow_listed_prefix
, link
->network
->ndisc_deny_listed_prefix
)) {
533 log_link_debug(link
, "Prefix '%s' is %s, ignoring",
534 !set_isempty(link
->network
->ndisc_allow_listed_prefix
) ? "not in allow list"
536 IN6_ADDR_PREFIX_TO_STRING(&a
, prefixlen
));
540 r
= sd_ndisc_router_prefix_get_flags(rt
, &flags
);
542 return log_link_warning_errno(link
, r
, "Failed to get RA prefix flags: %m");
544 if (FLAGS_SET(flags
, ND_OPT_PI_FLAG_ONLINK
)) {
545 r
= ndisc_router_process_onlink_prefix(link
, rt
);
550 if (FLAGS_SET(flags
, ND_OPT_PI_FLAG_AUTO
)) {
551 r
= ndisc_router_process_autonomous_prefix(link
, rt
);
559 static int ndisc_router_process_route(Link
*link
, sd_ndisc_router
*rt
) {
560 _cleanup_(route_freep
) Route
*route
= NULL
;
561 unsigned preference
, prefixlen
;
562 struct in6_addr gateway
, dst
;
563 uint32_t lifetime_sec
;
564 usec_t timestamp_usec
;
569 if (!link
->network
->ipv6_accept_ra_use_route_prefix
)
572 r
= sd_ndisc_router_route_get_lifetime(rt
, &lifetime_sec
);
574 return log_link_warning_errno(link
, r
, "Failed to get route lifetime from RA: %m");
576 r
= sd_ndisc_router_route_get_address(rt
, &dst
);
578 return log_link_warning_errno(link
, r
, "Failed to get route destination address: %m");
580 r
= sd_ndisc_router_route_get_prefixlen(rt
, &prefixlen
);
582 return log_link_warning_errno(link
, r
, "Failed to get route prefix length: %m");
584 if (in6_addr_is_null(&dst
) && prefixlen
== 0) {
585 log_link_debug(link
, "Route prefix is ::/0, ignoring");
589 if (in6_prefix_is_filtered(&dst
, prefixlen
,
590 link
->network
->ndisc_allow_listed_route_prefix
,
591 link
->network
->ndisc_deny_listed_route_prefix
)) {
594 log_link_debug(link
, "Route prefix %s is %s, ignoring",
595 !set_isempty(link
->network
->ndisc_allow_listed_route_prefix
) ? "not in allow list"
597 IN6_ADDR_PREFIX_TO_STRING(&dst
, prefixlen
));
601 r
= sd_ndisc_router_get_address(rt
, &gateway
);
603 return log_link_warning_errno(link
, r
, "Failed to get gateway address from RA: %m");
605 if (link_get_ipv6_address(link
, &gateway
, 0, NULL
) >= 0) {
607 log_link_debug(link
, "Advertised route gateway %s is local to the link, ignoring route",
608 IN6_ADDR_TO_STRING(&gateway
));
612 r
= sd_ndisc_router_route_get_preference(rt
, &preference
);
614 log_link_debug_errno(link
, r
, "Received route prefix with unsupported preference, ignoring: %m");
618 return log_link_warning_errno(link
, r
, "Failed to get default router preference from RA: %m");
620 r
= sd_ndisc_router_get_timestamp(rt
, CLOCK_BOOTTIME
, ×tamp_usec
);
622 return log_link_warning_errno(link
, r
, "Failed to get RA timestamp: %m");
624 r
= route_new(&route
);
628 route
->family
= AF_INET6
;
629 route
->pref
= preference
;
630 route
->gw
.in6
= gateway
;
631 route
->gw_family
= AF_INET6
;
632 route
->dst
.in6
= dst
;
633 route
->dst_prefixlen
= prefixlen
;
634 route
->lifetime_usec
= sec_to_usec(lifetime_sec
, timestamp_usec
);
636 r
= ndisc_request_route(TAKE_PTR(route
), link
, rt
);
638 return log_link_warning_errno(link
, r
, "Could not request additional route: %m");
643 static void ndisc_rdnss_hash_func(const NDiscRDNSS
*x
, struct siphash
*state
) {
644 siphash24_compress(&x
->address
, sizeof(x
->address
), state
);
647 static int ndisc_rdnss_compare_func(const NDiscRDNSS
*a
, const NDiscRDNSS
*b
) {
648 return memcmp(&a
->address
, &b
->address
, sizeof(a
->address
));
651 DEFINE_PRIVATE_HASH_OPS_WITH_KEY_DESTRUCTOR(
652 ndisc_rdnss_hash_ops
,
654 ndisc_rdnss_hash_func
,
655 ndisc_rdnss_compare_func
,
658 static int ndisc_router_process_rdnss(Link
*link
, sd_ndisc_router
*rt
) {
659 usec_t lifetime_usec
, timestamp_usec
;
660 uint32_t lifetime_sec
;
661 const struct in6_addr
*a
;
662 struct in6_addr router
;
663 bool updated
= false, logged_about_too_many
= false;
667 assert(link
->network
);
670 if (!link
->network
->ipv6_accept_ra_use_dns
)
673 r
= sd_ndisc_router_get_address(rt
, &router
);
675 return log_link_warning_errno(link
, r
, "Failed to get router address from RA: %m");
677 r
= sd_ndisc_router_get_timestamp(rt
, CLOCK_BOOTTIME
, ×tamp_usec
);
679 return log_link_warning_errno(link
, r
, "Failed to get RA timestamp: %m");
681 r
= sd_ndisc_router_rdnss_get_lifetime(rt
, &lifetime_sec
);
683 return log_link_warning_errno(link
, r
, "Failed to get RDNSS lifetime: %m");
685 lifetime_usec
= sec_to_usec(lifetime_sec
, timestamp_usec
);
687 n
= sd_ndisc_router_rdnss_get_addresses(rt
, &a
);
689 return log_link_warning_errno(link
, n
, "Failed to get RDNSS addresses: %m");
691 for (int j
= 0; j
< n
; j
++) {
692 _cleanup_free_ NDiscRDNSS
*x
= NULL
;
693 NDiscRDNSS
*rdnss
, d
= {
697 if (lifetime_usec
== 0) {
698 /* The entry is outdated. */
699 free(set_remove(link
->ndisc_rdnss
, &d
));
704 rdnss
= set_get(link
->ndisc_rdnss
, &d
);
706 rdnss
->router
= router
;
707 rdnss
->lifetime_usec
= lifetime_usec
;
711 if (set_size(link
->ndisc_rdnss
) >= NDISC_RDNSS_MAX
) {
712 if (!logged_about_too_many
)
713 log_link_warning(link
, "Too many RDNSS records per link. Only first %u records will be used.", NDISC_RDNSS_MAX
);
714 logged_about_too_many
= true;
718 x
= new(NDiscRDNSS
, 1);
725 .lifetime_usec
= lifetime_usec
,
728 r
= set_ensure_consume(&link
->ndisc_rdnss
, &ndisc_rdnss_hash_ops
, TAKE_PTR(x
));
742 static void ndisc_dnssl_hash_func(const NDiscDNSSL
*x
, struct siphash
*state
) {
743 siphash24_compress_string(NDISC_DNSSL_DOMAIN(x
), state
);
746 static int ndisc_dnssl_compare_func(const NDiscDNSSL
*a
, const NDiscDNSSL
*b
) {
747 return strcmp(NDISC_DNSSL_DOMAIN(a
), NDISC_DNSSL_DOMAIN(b
));
750 DEFINE_PRIVATE_HASH_OPS_WITH_KEY_DESTRUCTOR(
751 ndisc_dnssl_hash_ops
,
753 ndisc_dnssl_hash_func
,
754 ndisc_dnssl_compare_func
,
757 static int ndisc_router_process_dnssl(Link
*link
, sd_ndisc_router
*rt
) {
758 _cleanup_strv_free_
char **l
= NULL
;
759 usec_t lifetime_usec
, timestamp_usec
;
760 struct in6_addr router
;
761 uint32_t lifetime_sec
;
762 bool updated
= false, logged_about_too_many
= false;
766 assert(link
->network
);
769 if (link
->network
->ipv6_accept_ra_use_domains
== DHCP_USE_DOMAINS_NO
)
772 r
= sd_ndisc_router_get_address(rt
, &router
);
774 return log_link_warning_errno(link
, r
, "Failed to get router address from RA: %m");
776 r
= sd_ndisc_router_get_timestamp(rt
, CLOCK_BOOTTIME
, ×tamp_usec
);
778 return log_link_warning_errno(link
, r
, "Failed to get RA timestamp: %m");
780 r
= sd_ndisc_router_dnssl_get_lifetime(rt
, &lifetime_sec
);
782 return log_link_warning_errno(link
, r
, "Failed to get DNSSL lifetime: %m");
784 lifetime_usec
= sec_to_usec(lifetime_sec
, timestamp_usec
);
786 r
= sd_ndisc_router_dnssl_get_domains(rt
, &l
);
788 return log_link_warning_errno(link
, r
, "Failed to get DNSSL addresses: %m");
791 _cleanup_free_ NDiscDNSSL
*s
= NULL
;
794 s
= malloc0(ALIGN(sizeof(NDiscDNSSL
)) + strlen(*j
) + 1);
798 strcpy(NDISC_DNSSL_DOMAIN(s
), *j
);
800 if (lifetime_usec
== 0) {
801 /* The entry is outdated. */
802 free(set_remove(link
->ndisc_dnssl
, s
));
807 dnssl
= set_get(link
->ndisc_dnssl
, s
);
809 dnssl
->router
= router
;
810 dnssl
->lifetime_usec
= lifetime_usec
;
814 if (set_size(link
->ndisc_dnssl
) >= NDISC_DNSSL_MAX
) {
815 if (!logged_about_too_many
)
816 log_link_warning(link
, "Too many DNSSL records per link. Only first %u records will be used.", NDISC_DNSSL_MAX
);
817 logged_about_too_many
= true;
822 s
->lifetime_usec
= lifetime_usec
;
824 r
= set_ensure_consume(&link
->ndisc_dnssl
, &ndisc_dnssl_hash_ops
, TAKE_PTR(s
));
838 static NDiscCaptivePortal
* ndisc_captive_portal_free(NDiscCaptivePortal
*x
) {
842 free(x
->captive_portal
);
846 DEFINE_TRIVIAL_CLEANUP_FUNC(NDiscCaptivePortal
*, ndisc_captive_portal_free
);
848 static void ndisc_captive_portal_hash_func(const NDiscCaptivePortal
*x
, struct siphash
*state
) {
850 siphash24_compress_string(x
->captive_portal
, state
);
853 static int ndisc_captive_portal_compare_func(const NDiscCaptivePortal
*a
, const NDiscCaptivePortal
*b
) {
856 return strcmp_ptr(a
->captive_portal
, b
->captive_portal
);
859 DEFINE_PRIVATE_HASH_OPS_WITH_KEY_DESTRUCTOR(
860 ndisc_captive_portal_hash_ops
,
862 ndisc_captive_portal_hash_func
,
863 ndisc_captive_portal_compare_func
,
864 ndisc_captive_portal_free
);
866 static int ndisc_router_process_captive_portal(Link
*link
, sd_ndisc_router
*rt
) {
867 _cleanup_(ndisc_captive_portal_freep
) NDiscCaptivePortal
*new_entry
= NULL
;
868 _cleanup_free_
char *captive_portal
= NULL
;
869 usec_t lifetime_usec
, timestamp_usec
;
870 NDiscCaptivePortal
*exist
;
871 struct in6_addr router
;
872 uint16_t lifetime_sec
;
878 assert(link
->network
);
881 if (!link
->network
->ipv6_accept_ra_use_captive_portal
)
884 r
= sd_ndisc_router_get_address(rt
, &router
);
886 return log_link_warning_errno(link
, r
, "Failed to get router address from RA: %m");
888 /* RFC 4861 section 4.2. states that the lifetime in the message header should be used only for the
889 * default gateway, but the captive portal option does not have a lifetime field, hence, we use the
890 * main lifetime for the portal. */
891 r
= sd_ndisc_router_get_lifetime(rt
, &lifetime_sec
);
893 return log_link_warning_errno(link
, r
, "Failed to get lifetime of RA message: %m");
895 r
= sd_ndisc_router_get_timestamp(rt
, CLOCK_BOOTTIME
, ×tamp_usec
);
897 return log_link_warning_errno(link
, r
, "Failed to get RA timestamp: %m");
899 lifetime_usec
= sec16_to_usec(lifetime_sec
, timestamp_usec
);
901 r
= sd_ndisc_router_captive_portal_get_uri(rt
, &uri
, &len
);
903 return log_link_warning_errno(link
, r
, "Failed to get captive portal from RA: %m");
906 return log_link_warning_errno(link
, SYNTHETIC_ERRNO(EBADMSG
), "Received empty captive portal, ignoring.");
908 r
= make_cstring(uri
, len
, MAKE_CSTRING_REFUSE_TRAILING_NUL
, &captive_portal
);
910 return log_link_warning_errno(link
, r
, "Failed to convert captive portal URI: %m");
912 if (!in_charset(captive_portal
, URI_VALID
))
913 return log_link_warning_errno(link
, SYNTHETIC_ERRNO(EBADMSG
), "Received invalid captive portal, ignoring.");
915 if (lifetime_usec
== 0) {
916 /* Drop the portal with zero lifetime. */
917 ndisc_captive_portal_free(set_remove(link
->ndisc_captive_portals
,
918 &(NDiscCaptivePortal
) {
919 .captive_portal
= captive_portal
,
924 exist
= set_get(link
->ndisc_captive_portals
,
925 &(NDiscCaptivePortal
) {
926 .captive_portal
= captive_portal
,
929 /* update existing entry */
930 exist
->router
= router
;
931 exist
->lifetime_usec
= lifetime_usec
;
935 if (set_size(link
->ndisc_captive_portals
) >= NDISC_CAPTIVE_PORTAL_MAX
) {
936 NDiscCaptivePortal
*c
, *target
= NULL
;
938 /* Find the portal who has the minimal lifetime and drop it to store new one. */
939 SET_FOREACH(c
, link
->ndisc_captive_portals
)
940 if (!target
|| c
->lifetime_usec
< target
->lifetime_usec
)
944 assert(set_remove(link
->ndisc_captive_portals
, target
) == target
);
945 ndisc_captive_portal_free(target
);
948 new_entry
= new(NDiscCaptivePortal
, 1);
952 *new_entry
= (NDiscCaptivePortal
) {
954 .lifetime_usec
= lifetime_usec
,
955 .captive_portal
= TAKE_PTR(captive_portal
),
958 r
= set_ensure_put(&link
->ndisc_captive_portals
, &ndisc_captive_portal_hash_ops
, new_entry
);
968 static void ndisc_pref64_hash_func(const NDiscPREF64
*x
, struct siphash
*state
) {
971 siphash24_compress(&x
->prefix_len
, sizeof(x
->prefix_len
), state
);
972 siphash24_compress(&x
->prefix
, sizeof(x
->prefix
), state
);
975 static int ndisc_pref64_compare_func(const NDiscPREF64
*a
, const NDiscPREF64
*b
) {
981 r
= CMP(a
->prefix_len
, b
->prefix_len
);
985 return memcmp(&a
->prefix
, &b
->prefix
, sizeof(a
->prefix
));
988 DEFINE_PRIVATE_HASH_OPS_WITH_KEY_DESTRUCTOR(
989 ndisc_pref64_hash_ops
,
991 ndisc_pref64_hash_func
,
992 ndisc_pref64_compare_func
,
995 static int ndisc_router_process_pref64(Link
*link
, sd_ndisc_router
*rt
) {
996 _cleanup_free_ NDiscPREF64
*new_entry
= NULL
;
997 usec_t lifetime_usec
, timestamp_usec
;
998 struct in6_addr a
, router
;
999 uint16_t lifetime_sec
;
1000 unsigned prefix_len
;
1005 assert(link
->network
);
1008 if (!link
->network
->ipv6_accept_ra_use_pref64
)
1011 r
= sd_ndisc_router_get_address(rt
, &router
);
1013 return log_link_warning_errno(link
, r
, "Failed to get router address from RA: %m");
1015 r
= sd_ndisc_router_prefix64_get_prefix(rt
, &a
);
1017 return log_link_warning_errno(link
, r
, "Failed to get pref64 prefix: %m");
1019 r
= sd_ndisc_router_prefix64_get_prefixlen(rt
, &prefix_len
);
1021 return log_link_warning_errno(link
, r
, "Failed to get pref64 prefix length: %m");
1023 r
= sd_ndisc_router_prefix64_get_lifetime_sec(rt
, &lifetime_sec
);
1025 return log_link_warning_errno(link
, r
, "Failed to get pref64 prefix lifetime: %m");
1027 r
= sd_ndisc_router_get_timestamp(rt
, CLOCK_BOOTTIME
, ×tamp_usec
);
1029 return log_link_warning_errno(link
, r
, "Failed to get RA timestamp: %m");
1031 lifetime_usec
= sec16_to_usec(lifetime_sec
, timestamp_usec
);
1033 if (lifetime_usec
== 0) {
1034 free(set_remove(link
->ndisc_pref64
,
1037 .prefix_len
= prefix_len
1042 exist
= set_get(link
->ndisc_pref64
,
1045 .prefix_len
= prefix_len
1048 /* update existing entry */
1049 exist
->router
= router
;
1050 exist
->lifetime_usec
= lifetime_usec
;
1054 new_entry
= new(NDiscPREF64
, 1);
1058 *new_entry
= (NDiscPREF64
) {
1060 .lifetime_usec
= lifetime_usec
,
1062 .prefix_len
= prefix_len
,
1065 r
= set_ensure_put(&link
->ndisc_pref64
, &ndisc_pref64_hash_ops
, new_entry
);
1070 TAKE_PTR(new_entry
);
1075 static int ndisc_router_process_options(Link
*link
, sd_ndisc_router
*rt
) {
1076 size_t n_captive_portal
= 0;
1080 assert(link
->network
);
1083 for (r
= sd_ndisc_router_option_rewind(rt
); ; r
= sd_ndisc_router_option_next(rt
)) {
1087 return log_link_warning_errno(link
, r
, "Failed to iterate through options: %m");
1088 if (r
== 0) /* EOF */
1091 r
= sd_ndisc_router_option_get_type(rt
, &type
);
1093 return log_link_warning_errno(link
, r
, "Failed to get RA option type: %m");
1096 case SD_NDISC_OPTION_PREFIX_INFORMATION
:
1097 r
= ndisc_router_process_prefix(link
, rt
);
1100 case SD_NDISC_OPTION_ROUTE_INFORMATION
:
1101 r
= ndisc_router_process_route(link
, rt
);
1104 case SD_NDISC_OPTION_RDNSS
:
1105 r
= ndisc_router_process_rdnss(link
, rt
);
1108 case SD_NDISC_OPTION_DNSSL
:
1109 r
= ndisc_router_process_dnssl(link
, rt
);
1111 case SD_NDISC_OPTION_CAPTIVE_PORTAL
:
1112 if (n_captive_portal
> 0) {
1113 if (n_captive_portal
== 1)
1114 log_link_notice(link
, "Received RA with multiple captive portals, only using the first one.");
1119 r
= ndisc_router_process_captive_portal(link
, rt
);
1123 case SD_NDISC_OPTION_PREF64
:
1124 r
= ndisc_router_process_pref64(link
, rt
);
1127 if (r
< 0 && r
!= -EBADMSG
)
1132 static int ndisc_drop_outdated(Link
*link
, usec_t timestamp_usec
) {
1133 bool updated
= false;
1136 NDiscCaptivePortal
*cp
;
1143 /* If an address or friends is already assigned, but not valid anymore, then refuse to update it,
1144 * and let's immediately remove it.
1145 * See RFC4862, section 5.5.3.e. But the following logic is deviated from RFC4862 by honoring all
1146 * valid lifetimes to improve the reaction of SLAAC to renumbering events.
1147 * See draft-ietf-6man-slaac-renum-02, section 4.2. */
1149 SET_FOREACH(route
, link
->routes
) {
1150 if (route
->source
!= NETWORK_CONFIG_SOURCE_NDISC
)
1153 if (route
->lifetime_usec
>= timestamp_usec
)
1154 continue; /* the route is still valid */
1156 k
= route_remove_and_drop(route
);
1158 r
= log_link_warning_errno(link
, k
, "Failed to remove outdated SLAAC route, ignoring: %m");
1161 SET_FOREACH(address
, link
->addresses
) {
1162 if (address
->source
!= NETWORK_CONFIG_SOURCE_NDISC
)
1165 if (address
->lifetime_valid_usec
>= timestamp_usec
)
1166 continue; /* the address is still valid */
1168 k
= address_remove_and_drop(address
);
1170 r
= log_link_warning_errno(link
, k
, "Failed to remove outdated SLAAC address, ignoring: %m");
1173 SET_FOREACH(rdnss
, link
->ndisc_rdnss
) {
1174 if (rdnss
->lifetime_usec
>= timestamp_usec
)
1175 continue; /* the DNS server is still valid */
1177 free(set_remove(link
->ndisc_rdnss
, rdnss
));
1181 SET_FOREACH(dnssl
, link
->ndisc_dnssl
) {
1182 if (dnssl
->lifetime_usec
>= timestamp_usec
)
1183 continue; /* the DNS domain is still valid */
1185 free(set_remove(link
->ndisc_dnssl
, dnssl
));
1189 SET_FOREACH(cp
, link
->ndisc_captive_portals
) {
1190 if (cp
->lifetime_usec
>= timestamp_usec
)
1191 continue; /* the captive portal is still valid */
1193 ndisc_captive_portal_free(set_remove(link
->ndisc_captive_portals
, cp
));
1203 static int ndisc_setup_expire(Link
*link
);
1205 static int ndisc_expire_handler(sd_event_source
*s
, uint64_t usec
, void *userdata
) {
1206 Link
*link
= ASSERT_PTR(userdata
);
1209 assert(link
->manager
);
1211 assert_se(sd_event_now(link
->manager
->event
, CLOCK_BOOTTIME
, &now_usec
) >= 0);
1213 (void) ndisc_drop_outdated(link
, now_usec
);
1214 (void) ndisc_setup_expire(link
);
1218 static int ndisc_setup_expire(Link
*link
) {
1219 usec_t lifetime_usec
= USEC_INFINITY
;
1220 NDiscCaptivePortal
*cp
;
1228 assert(link
->manager
);
1230 SET_FOREACH(route
, link
->routes
) {
1231 if (route
->source
!= NETWORK_CONFIG_SOURCE_NDISC
)
1234 if (!route_exists(route
))
1237 lifetime_usec
= MIN(lifetime_usec
, route
->lifetime_usec
);
1240 SET_FOREACH(address
, link
->addresses
) {
1241 if (address
->source
!= NETWORK_CONFIG_SOURCE_NDISC
)
1244 if (!address_exists(address
))
1247 lifetime_usec
= MIN(lifetime_usec
, address
->lifetime_valid_usec
);
1250 SET_FOREACH(rdnss
, link
->ndisc_rdnss
)
1251 lifetime_usec
= MIN(lifetime_usec
, rdnss
->lifetime_usec
);
1253 SET_FOREACH(dnssl
, link
->ndisc_dnssl
)
1254 lifetime_usec
= MIN(lifetime_usec
, dnssl
->lifetime_usec
);
1256 SET_FOREACH(cp
, link
->ndisc_captive_portals
)
1257 lifetime_usec
= MIN(lifetime_usec
, cp
->lifetime_usec
);
1259 if (lifetime_usec
== USEC_INFINITY
)
1262 r
= event_reset_time(link
->manager
->event
, &link
->ndisc_expire
, CLOCK_BOOTTIME
,
1263 lifetime_usec
, 0, ndisc_expire_handler
, link
, 0, "ndisc-expiration", true);
1265 return log_link_warning_errno(link
, r
, "Failed to update expiration timer for ndisc: %m");
1270 static int ndisc_start_dhcp6_client(Link
*link
, sd_ndisc_router
*rt
) {
1274 assert(link
->network
);
1276 switch (link
->network
->ipv6_accept_ra_start_dhcp6_client
) {
1277 case IPV6_ACCEPT_RA_START_DHCP6_CLIENT_NO
:
1280 case IPV6_ACCEPT_RA_START_DHCP6_CLIENT_YES
: {
1283 r
= sd_ndisc_router_get_flags(rt
, &flags
);
1285 return log_link_warning_errno(link
, r
, "Failed to get RA flags: %m");
1287 if ((flags
& (ND_RA_FLAG_MANAGED
| ND_RA_FLAG_OTHER
)) == 0)
1290 /* (re)start DHCPv6 client in stateful or stateless mode according to RA flags.
1291 * Note, if both "managed" and "other configuration" bits are set, then ignore
1292 * "other configuration" bit. See RFC 4861. */
1293 r
= dhcp6_start_on_ra(link
, !(flags
& ND_RA_FLAG_MANAGED
));
1296 case IPV6_ACCEPT_RA_START_DHCP6_CLIENT_ALWAYS
:
1297 /* When IPv6AcceptRA.DHCPv6Client=always, start dhcp6 client in solicit mode
1298 * even if the router flags have neither M nor O flags. */
1299 r
= dhcp6_start_on_ra(link
, /* information_request = */ false);
1303 assert_not_reached();
1307 return log_link_warning_errno(link
, r
, "Could not acquire DHCPv6 lease on NDisc request: %m");
1309 log_link_debug(link
, "Acquiring DHCPv6 lease on NDisc request");
1313 static int ndisc_router_handler(Link
*link
, sd_ndisc_router
*rt
) {
1314 struct in6_addr router
;
1315 usec_t timestamp_usec
;
1319 assert(link
->network
);
1320 assert(link
->manager
);
1323 r
= sd_ndisc_router_get_address(rt
, &router
);
1324 if (r
== -ENODATA
) {
1325 log_link_debug(link
, "Received RA without router address, ignoring.");
1329 return log_link_warning_errno(link
, r
, "Failed to get router address from RA: %m");
1331 if (in6_prefix_is_filtered(&router
, 128, link
->network
->ndisc_allow_listed_router
, link
->network
->ndisc_deny_listed_router
)) {
1332 if (DEBUG_LOGGING
) {
1333 if (!set_isempty(link
->network
->ndisc_allow_listed_router
))
1334 log_link_debug(link
, "Router %s is not in allow list, ignoring.", IN6_ADDR_TO_STRING(&router
));
1336 log_link_debug(link
, "Router %s is in deny list, ignoring.", IN6_ADDR_TO_STRING(&router
));
1341 r
= sd_ndisc_router_get_timestamp(rt
, CLOCK_BOOTTIME
, ×tamp_usec
);
1342 if (r
== -ENODATA
) {
1343 log_link_debug(link
, "Received RA without timestamp, ignoring.");
1349 r
= ndisc_drop_outdated(link
, timestamp_usec
);
1353 r
= ndisc_start_dhcp6_client(link
, rt
);
1357 r
= ndisc_router_process_default(link
, rt
);
1361 r
= ndisc_router_process_options(link
, rt
);
1365 r
= ndisc_setup_expire(link
);
1369 if (link
->ndisc_messages
== 0)
1370 link
->ndisc_configured
= true;
1372 log_link_debug(link
, "Setting SLAAC addresses and router.");
1374 if (!link
->ndisc_configured
)
1375 link_set_state(link
, LINK_STATE_CONFIGURING
);
1377 link_check_ready(link
);
1381 static void ndisc_handler(sd_ndisc
*nd
, sd_ndisc_event_t event
, sd_ndisc_router
*rt
, void *userdata
) {
1382 Link
*link
= ASSERT_PTR(userdata
);
1385 if (IN_SET(link
->state
, LINK_STATE_FAILED
, LINK_STATE_LINGER
))
1390 case SD_NDISC_EVENT_ROUTER
:
1391 r
= ndisc_router_handler(link
, rt
);
1392 if (r
< 0 && r
!= -EBADMSG
) {
1393 link_enter_failed(link
);
1398 case SD_NDISC_EVENT_TIMEOUT
:
1399 log_link_debug(link
, "NDisc handler get timeout event");
1400 if (link
->ndisc_messages
== 0) {
1401 link
->ndisc_configured
= true;
1402 link_check_ready(link
);
1406 assert_not_reached();
1410 static int ndisc_configure(Link
*link
) {
1415 if (!link_ipv6_accept_ra_enabled(link
))
1419 return -EBUSY
; /* Already configured. */
1421 r
= sd_ndisc_new(&link
->ndisc
);
1425 r
= sd_ndisc_attach_event(link
->ndisc
, link
->manager
->event
, 0);
1429 if (link
->hw_addr
.length
== ETH_ALEN
) {
1430 r
= sd_ndisc_set_mac(link
->ndisc
, &link
->hw_addr
.ether
);
1435 r
= sd_ndisc_set_ifindex(link
->ndisc
, link
->ifindex
);
1439 r
= sd_ndisc_set_callback(link
->ndisc
, ndisc_handler
, link
);
1446 int ndisc_start(Link
*link
) {
1451 if (!link
->ndisc
|| !link
->dhcp6_client
)
1454 if (!link_has_carrier(link
))
1457 if (in6_addr_is_null(&link
->ipv6ll_address
))
1460 log_link_debug(link
, "Discovering IPv6 routers");
1462 r
= sd_ndisc_start(link
->ndisc
);
1469 static int ndisc_process_request(Request
*req
, Link
*link
, void *userdata
) {
1474 if (!link_is_ready_to_configure(link
, /* allow_unmanaged = */ false))
1477 r
= ndisc_configure(link
);
1479 return log_link_warning_errno(link
, r
, "Failed to configure IPv6 Router Discovery: %m");
1481 r
= ndisc_start(link
);
1483 return log_link_warning_errno(link
, r
, "Failed to start IPv6 Router Discovery: %m");
1485 log_link_debug(link
, "IPv6 Router Discovery is configured%s.",
1486 r
> 0 ? " and started" : "");
1490 int link_request_ndisc(Link
*link
) {
1495 if (!link_ipv6_accept_ra_enabled(link
))
1501 r
= link_queue_request(link
, REQUEST_TYPE_NDISC
, ndisc_process_request
, NULL
);
1503 return log_link_warning_errno(link
, r
, "Failed to request configuring of the IPv6 Router Discovery: %m");
1505 log_link_debug(link
, "Requested configuring of the IPv6 Router Discovery.");
1509 int ndisc_stop(Link
*link
) {
1512 link
->ndisc_expire
= sd_event_source_disable_unref(link
->ndisc_expire
);
1514 return sd_ndisc_stop(link
->ndisc
);
1518 void ndisc_flush(Link
*link
) {
1521 /* Remove all RDNSS, DNSSL, and Captive Portal entries, without exception. */
1523 link
->ndisc_rdnss
= set_free(link
->ndisc_rdnss
);
1524 link
->ndisc_dnssl
= set_free(link
->ndisc_dnssl
);
1525 link
->ndisc_captive_portals
= set_free(link
->ndisc_captive_portals
);
1526 link
->ndisc_pref64
= set_free(link
->ndisc_pref64
);
1529 static const char* const ipv6_accept_ra_start_dhcp6_client_table
[_IPV6_ACCEPT_RA_START_DHCP6_CLIENT_MAX
] = {
1530 [IPV6_ACCEPT_RA_START_DHCP6_CLIENT_NO
] = "no",
1531 [IPV6_ACCEPT_RA_START_DHCP6_CLIENT_ALWAYS
] = "always",
1532 [IPV6_ACCEPT_RA_START_DHCP6_CLIENT_YES
] = "yes",
1535 DEFINE_PRIVATE_STRING_TABLE_LOOKUP_FROM_STRING_WITH_BOOLEAN(ipv6_accept_ra_start_dhcp6_client
, IPv6AcceptRAStartDHCP6Client
, IPV6_ACCEPT_RA_START_DHCP6_CLIENT_YES
);
1537 DEFINE_CONFIG_PARSE_ENUM(config_parse_ipv6_accept_ra_use_domains
, dhcp_use_domains
, DHCPUseDomains
,
1538 "Failed to parse UseDomains= setting");
1539 DEFINE_CONFIG_PARSE_ENUM(config_parse_ipv6_accept_ra_start_dhcp6_client
, ipv6_accept_ra_start_dhcp6_client
, IPv6AcceptRAStartDHCP6Client
,
1540 "Failed to parse DHCPv6Client= setting");