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 "networkd-queue.h"
19 #include "networkd-state-file.h"
20 #include "string-table.h"
21 #include "string-util.h"
24 #define NDISC_DNSSL_MAX 64U
25 #define NDISC_RDNSS_MAX 64U
27 #define DAD_CONFLICTS_IDGEN_RETRIES_RFC7217 3
29 /* https://tools.ietf.org/html/rfc5453 */
30 /* https://www.iana.org/assignments/ipv6-interface-ids/ipv6-interface-ids.xml */
32 #define SUBNET_ROUTER_ANYCAST_ADDRESS_RFC4291 ((struct in6_addr) { .s6_addr = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } })
33 #define SUBNET_ROUTER_ANYCAST_PREFIXLEN 8
34 #define RESERVED_IPV6_INTERFACE_IDENTIFIERS_ADDRESS_RFC4291 ((struct in6_addr) { .s6_addr = { 0x02, 0x00, 0x5E, 0xFF, 0xFE } })
35 #define RESERVED_IPV6_INTERFACE_IDENTIFIERS_PREFIXLEN 5
36 #define RESERVED_SUBNET_ANYCAST_ADDRESSES_RFC4291 ((struct in6_addr) { .s6_addr = { 0xFD, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF } })
37 #define RESERVED_SUBNET_ANYCAST_PREFIXLEN 7
39 #define NDISC_APP_ID SD_ID128_MAKE(13,ac,81,a7,d5,3f,49,78,92,79,5d,0c,29,3a,bc,7e)
41 bool link_ipv6_accept_ra_enabled(Link
*link
) {
44 if (!socket_ipv6_is_supported())
47 if (link
->flags
& IFF_LOOPBACK
)
53 if (!link_ipv6ll_enabled(link
))
56 assert(link
->network
->ipv6_accept_ra
>= 0);
57 return link
->network
->ipv6_accept_ra
;
60 void network_adjust_ipv6_accept_ra(Network
*network
) {
63 if (!FLAGS_SET(network
->link_local
, ADDRESS_FAMILY_IPV6
)) {
64 if (network
->ipv6_accept_ra
> 0)
65 log_warning("%s: IPv6AcceptRA= is enabled but IPv6 link local addressing is disabled or not supported. "
66 "Disabling IPv6AcceptRA=.", network
->filename
);
67 network
->ipv6_accept_ra
= false;
70 if (network
->ipv6_accept_ra
< 0)
71 /* default to accept RA if ip_forward is disabled and ignore RA if ip_forward is enabled */
72 network
->ipv6_accept_ra
= !FLAGS_SET(network
->ip_forward
, ADDRESS_FAMILY_IPV6
);
74 /* When RouterAllowList=, PrefixAllowList= or RouteAllowList= are specified, then
75 * RouterDenyList=, PrefixDenyList= or RouteDenyList= are ignored, respectively. */
76 if (!set_isempty(network
->ndisc_allow_listed_router
))
77 network
->ndisc_deny_listed_router
= set_free_free(network
->ndisc_deny_listed_router
);
78 if (!set_isempty(network
->ndisc_allow_listed_prefix
))
79 network
->ndisc_deny_listed_prefix
= set_free_free(network
->ndisc_deny_listed_prefix
);
80 if (!set_isempty(network
->ndisc_allow_listed_route_prefix
))
81 network
->ndisc_deny_listed_route_prefix
= set_free_free(network
->ndisc_deny_listed_route_prefix
);
84 static int ndisc_remove_old_one(Link
*link
, const struct in6_addr
*router
, bool force
);
86 static int ndisc_address_callback(Address
*address
) {
87 struct in6_addr router
= {};
91 assert(address
->link
);
92 assert(address
->family
== AF_INET6
);
94 SET_FOREACH(n
, address
->link
->ndisc_addresses
)
95 if (n
->address
== address
) {
100 if (in6_addr_is_null(&router
)) {
101 _cleanup_free_
char *buf
= NULL
;
103 (void) in6_addr_prefix_to_string(&address
->in_addr
.in6
, address
->prefixlen
, &buf
);
104 log_link_debug(address
->link
, "%s is called for %s, but it is already removed, ignoring.",
105 __func__
, strna(buf
));
109 /* Make this called only once */
110 SET_FOREACH(n
, address
->link
->ndisc_addresses
)
111 if (in6_addr_equal(&n
->router
, &router
))
112 n
->address
->callback
= NULL
;
114 return ndisc_remove_old_one(address
->link
, &router
, true);
117 static int ndisc_remove_old_one(Link
*link
, const struct in6_addr
*router
, bool force
) {
123 bool updated
= false;
129 bool set_callback
= false;
131 if (!link
->ndisc_addresses_configured
|| !link
->ndisc_routes_configured
)
134 SET_FOREACH(na
, link
->ndisc_addresses
)
135 if (!na
->marked
&& in6_addr_equal(&na
->router
, router
)) {
141 SET_FOREACH(na
, link
->ndisc_addresses
)
142 if (!na
->marked
&& address_is_ready(na
->address
)) {
143 set_callback
= false;
148 SET_FOREACH(na
, link
->ndisc_addresses
)
149 if (!na
->marked
&& in6_addr_equal(&na
->router
, router
))
150 na
->address
->callback
= ndisc_address_callback
;
153 _cleanup_free_
char *buf
= NULL
;
155 (void) in6_addr_to_string(router
, &buf
);
156 log_link_debug(link
, "No SLAAC address obtained from %s is ready. "
157 "The old NDisc information will be removed later.",
165 _cleanup_free_
char *buf
= NULL
;
167 (void) in6_addr_to_string(router
, &buf
);
168 log_link_debug(link
, "Removing old NDisc information obtained from %s.", strna(buf
));
171 SET_FOREACH(na
, link
->ndisc_addresses
)
172 if (na
->marked
&& in6_addr_equal(&na
->router
, router
)) {
173 k
= address_remove(na
->address
, link
);
178 SET_FOREACH(nr
, link
->ndisc_routes
)
179 if (nr
->marked
&& in6_addr_equal(&nr
->router
, router
)) {
180 k
= route_remove(nr
->route
, NULL
, link
);
185 SET_FOREACH(rdnss
, link
->ndisc_rdnss
)
186 if (rdnss
->marked
&& in6_addr_equal(&rdnss
->router
, router
)) {
187 free(set_remove(link
->ndisc_rdnss
, rdnss
));
191 SET_FOREACH(dnssl
, link
->ndisc_dnssl
)
192 if (dnssl
->marked
&& in6_addr_equal(&dnssl
->router
, router
)) {
193 free(set_remove(link
->ndisc_dnssl
, dnssl
));
203 static int ndisc_remove_old(Link
*link
) {
204 _cleanup_set_free_free_ Set
*routers
= NULL
;
205 _cleanup_free_
struct in6_addr
*router
= NULL
;
215 routers
= set_new(&in6_addr_hash_ops
);
219 SET_FOREACH(na
, link
->ndisc_addresses
)
220 if (!set_contains(routers
, &na
->router
)) {
221 router
= newdup(struct in6_addr
, &na
->router
, 1);
225 r
= set_put(routers
, router
);
233 SET_FOREACH(nr
, link
->ndisc_routes
)
234 if (!set_contains(routers
, &nr
->router
)) {
235 router
= newdup(struct in6_addr
, &nr
->router
, 1);
239 r
= set_put(routers
, router
);
247 SET_FOREACH(rdnss
, link
->ndisc_rdnss
)
248 if (!set_contains(routers
, &rdnss
->router
)) {
249 router
= newdup(struct in6_addr
, &rdnss
->router
, 1);
253 r
= set_put(routers
, router
);
261 SET_FOREACH(dnssl
, link
->ndisc_dnssl
)
262 if (!set_contains(routers
, &dnssl
->router
)) {
263 router
= newdup(struct in6_addr
, &dnssl
->router
, 1);
267 r
= set_put(routers
, router
);
276 SET_FOREACH(a
, routers
) {
277 k
= ndisc_remove_old_one(link
, a
, false);
285 static void ndisc_route_hash_func(const NDiscRoute
*x
, struct siphash
*state
) {
286 route_hash_func(x
->route
, state
);
289 static int ndisc_route_compare_func(const NDiscRoute
*a
, const NDiscRoute
*b
) {
290 return route_compare_func(a
->route
, b
->route
);
293 DEFINE_PRIVATE_HASH_OPS_WITH_KEY_DESTRUCTOR(
294 ndisc_route_hash_ops
,
296 ndisc_route_hash_func
,
297 ndisc_route_compare_func
,
300 static int ndisc_route_handler(sd_netlink
*rtnl
, sd_netlink_message
*m
, Link
*link
) {
304 assert(link
->ndisc_routes_messages
> 0);
306 link
->ndisc_routes_messages
--;
308 r
= route_configure_handler_internal(rtnl
, m
, link
, "Could not set NDisc route");
312 if (link
->ndisc_routes_messages
== 0) {
313 log_link_debug(link
, "NDisc routes set.");
314 link
->ndisc_routes_configured
= true;
316 r
= ndisc_remove_old(link
);
318 link_enter_failed(link
);
322 link_check_ready(link
);
328 static int ndisc_after_route_configure(Request
*req
, void *object
) {
329 _cleanup_free_ NDiscRoute
*nr
= NULL
;
330 NDiscRoute
*nr_exist
;
331 struct in6_addr router
;
332 Route
*route
= object
;
339 assert(req
->type
== REQUEST_TYPE_ROUTE
);
340 assert(req
->userdata
);
346 r
= sd_ndisc_router_get_address(rt
, &router
);
348 return log_link_error_errno(link
, r
, "Failed to get router address from RA: %m");
350 nr
= new(NDiscRoute
, 1);
359 nr_exist
= set_get(link
->ndisc_routes
, nr
);
361 nr_exist
->marked
= false;
362 nr_exist
->router
= router
;
366 r
= set_ensure_put(&link
->ndisc_routes
, &ndisc_route_hash_ops
, nr
);
368 return log_link_error_errno(link
, r
, "Failed to store NDisc SLAAC route: %m");
375 static void ndisc_request_on_free(Request
*req
) {
378 sd_ndisc_router_unref(req
->userdata
);
381 static int ndisc_request_route(Route
*in
, Link
*link
, sd_ndisc_router
*rt
) {
382 _cleanup_(route_freep
) Route
*route
= in
;
390 r
= link_has_route(link
, route
);
394 link
->ndisc_routes_configured
= false;
396 r
= link_request_route(link
, TAKE_PTR(route
), true, &link
->ndisc_routes_messages
,
397 ndisc_route_handler
, &req
);
401 req
->userdata
= sd_ndisc_router_ref(rt
);
402 req
->after_configure
= ndisc_after_route_configure
;
403 req
->on_free
= ndisc_request_on_free
;
408 static void ndisc_address_hash_func(const NDiscAddress
*x
, struct siphash
*state
) {
409 address_hash_func(x
->address
, state
);
412 static int ndisc_address_compare_func(const NDiscAddress
*a
, const NDiscAddress
*b
) {
413 return address_compare_func(a
->address
, b
->address
);
416 DEFINE_PRIVATE_HASH_OPS_WITH_KEY_DESTRUCTOR(
417 ndisc_address_hash_ops
,
419 ndisc_address_hash_func
,
420 ndisc_address_compare_func
,
423 static int ndisc_address_handler(sd_netlink
*rtnl
, sd_netlink_message
*m
, Link
*link
) {
427 assert(link
->ndisc_addresses_messages
> 0);
429 link
->ndisc_addresses_messages
--;
431 r
= address_configure_handler_internal(rtnl
, m
, link
, "Could not set NDisc address");
435 if (link
->ndisc_addresses_messages
== 0) {
436 log_link_debug(link
, "NDisc SLAAC addresses set.");
437 link
->ndisc_addresses_configured
= true;
439 r
= ndisc_remove_old(link
);
441 link_enter_failed(link
);
449 static int ndisc_after_address_configure(Request
*req
, void *object
) {
450 _cleanup_free_ NDiscAddress
*na
= NULL
;
451 NDiscAddress
*na_exist
;
452 struct in6_addr router
;
454 Address
*address
= object
;
460 assert(req
->type
== REQUEST_TYPE_ADDRESS
);
461 assert(req
->userdata
);
467 r
= sd_ndisc_router_get_address(rt
, &router
);
469 return log_link_error_errno(link
, r
, "Failed to get router address from RA: %m");
471 na
= new(NDiscAddress
, 1);
475 *na
= (NDiscAddress
) {
480 na_exist
= set_get(link
->ndisc_addresses
, na
);
482 na_exist
->marked
= false;
483 na_exist
->router
= router
;
487 r
= set_ensure_put(&link
->ndisc_addresses
, &ndisc_address_hash_ops
, na
);
489 return log_link_error_errno(link
, r
, "Failed to store NDisc SLAAC address: %m");
496 static int ndisc_request_address(Address
*in
, Link
*link
, sd_ndisc_router
*rt
) {
497 _cleanup_(address_freep
) Address
*address
= in
;
505 if (address_get(link
, address
, NULL
) < 0)
506 link
->ndisc_addresses_configured
= false;
508 r
= link_request_address(link
, TAKE_PTR(address
), true, &link
->ndisc_addresses_messages
,
509 ndisc_address_handler
, &req
);
513 req
->userdata
= sd_ndisc_router_ref(rt
);
514 req
->after_configure
= ndisc_after_address_configure
;
515 req
->on_free
= ndisc_request_on_free
;
520 static int ndisc_router_process_default(Link
*link
, sd_ndisc_router
*rt
) {
521 _cleanup_(route_freep
) Route
*route
= NULL
;
522 struct in6_addr gateway
;
532 r
= sd_ndisc_router_get_lifetime(rt
, &lifetime
);
534 return log_link_error_errno(link
, r
, "Failed to get gateway lifetime from RA: %m");
536 if (lifetime
== 0) /* not a default router */
539 r
= sd_ndisc_router_get_address(rt
, &gateway
);
541 return log_link_error_errno(link
, r
, "Failed to get gateway address from RA: %m");
543 if (link_get_ipv6_address(link
, &gateway
, NULL
) >= 0) {
545 _cleanup_free_
char *buffer
= NULL
;
547 (void) in6_addr_to_string(&gateway
, &buffer
);
548 log_link_debug(link
, "No NDisc route added, gateway %s matches local address",
554 r
= sd_ndisc_router_get_preference(rt
, &preference
);
556 return log_link_error_errno(link
, r
, "Failed to get default router preference from RA: %m");
558 r
= sd_ndisc_router_get_timestamp(rt
, clock_boottime_or_monotonic(), &time_now
);
560 return log_link_error_errno(link
, r
, "Failed to get RA timestamp: %m");
562 r
= sd_ndisc_router_get_mtu(rt
, &mtu
);
566 return log_link_error_errno(link
, r
, "Failed to get default router MTU from RA: %m");
568 table
= link_get_ipv6_accept_ra_route_table(link
);
570 r
= route_new(&route
);
574 route
->family
= AF_INET6
;
575 route
->table
= table
;
576 route
->priority
= link
->network
->ipv6_accept_ra_route_metric
;
577 route
->protocol
= RTPROT_RA
;
578 route
->pref
= preference
;
579 route
->gw_family
= AF_INET6
;
580 route
->gw
.in6
= gateway
;
581 route
->lifetime
= usec_add(time_now
, lifetime
* USEC_PER_SEC
);
584 r
= ndisc_request_route(TAKE_PTR(route
), link
, rt
);
586 return log_link_error_errno(link
, r
, "Could not request default route: %m");
589 HASHMAP_FOREACH(route_gw
, link
->network
->routes_by_section
) {
590 if (!route_gw
->gateway_from_dhcp_or_ra
)
593 if (route_gw
->gw_family
!= AF_INET6
)
596 r
= route_dup(route_gw
, &route
);
600 route
->gw
.in6
= gateway
;
601 if (!route
->table_set
)
602 route
->table
= table
;
603 if (!route
->priority_set
)
604 route
->priority
= link
->network
->ipv6_accept_ra_route_metric
;
605 if (!route
->protocol_set
)
606 route
->protocol
= RTPROT_RA
;
607 if (!route
->pref_set
)
608 route
->pref
= preference
;
609 route
->lifetime
= usec_add(time_now
, lifetime
* USEC_PER_SEC
);
613 r
= ndisc_request_route(TAKE_PTR(route
), link
, rt
);
615 return log_link_error_errno(link
, r
, "Could not request gateway: %m");
621 static bool stableprivate_address_is_valid(const struct in6_addr
*addr
) {
624 /* According to rfc4291, generated address should not be in the following ranges. */
626 if (memcmp(addr
, &SUBNET_ROUTER_ANYCAST_ADDRESS_RFC4291
, SUBNET_ROUTER_ANYCAST_PREFIXLEN
) == 0)
629 if (memcmp(addr
, &RESERVED_IPV6_INTERFACE_IDENTIFIERS_ADDRESS_RFC4291
, RESERVED_IPV6_INTERFACE_IDENTIFIERS_PREFIXLEN
) == 0)
632 if (memcmp(addr
, &RESERVED_SUBNET_ANYCAST_ADDRESSES_RFC4291
, RESERVED_SUBNET_ANYCAST_PREFIXLEN
) == 0)
638 static int make_stableprivate_address(Link
*link
, const struct in6_addr
*prefix
, uint8_t prefix_len
, uint8_t dad_counter
, struct in6_addr
**ret
) {
639 _cleanup_free_
struct in6_addr
*addr
= NULL
;
640 sd_id128_t secret_key
;
641 struct siphash state
;
646 /* According to rfc7217 section 5.1
647 * RID = F(Prefix, Net_Iface, Network_ID, DAD_Counter, secret_key) */
649 r
= sd_id128_get_machine_app_specific(NDISC_APP_ID
, &secret_key
);
651 return log_error_errno(r
, "Failed to generate key: %m");
653 siphash24_init(&state
, secret_key
.bytes
);
655 l
= MAX(DIV_ROUND_UP(prefix_len
, 8), 8);
656 siphash24_compress(prefix
, l
, &state
);
657 siphash24_compress_string(link
->ifname
, &state
);
658 /* Only last 8 bytes of IB MAC are stable */
659 if (link
->iftype
== ARPHRD_INFINIBAND
)
660 siphash24_compress(&link
->hw_addr
.infiniband
[12], 8, &state
);
662 siphash24_compress(link
->hw_addr
.bytes
, link
->hw_addr
.length
, &state
);
663 siphash24_compress(&dad_counter
, sizeof(uint8_t), &state
);
665 rid
= htole64(siphash24_finalize(&state
));
667 addr
= new(struct in6_addr
, 1);
671 memcpy(addr
->s6_addr
, prefix
->s6_addr
, l
);
672 memcpy(addr
->s6_addr
+ l
, &rid
, 16 - l
);
674 if (!stableprivate_address_is_valid(addr
)) {
679 *ret
= TAKE_PTR(addr
);
683 static int ndisc_router_generate_addresses(Link
*link
, struct in6_addr
*address
, uint8_t prefixlen
, Set
**ret
) {
684 _cleanup_set_free_free_ Set
*addresses
= NULL
;
692 addresses
= set_new(&in6_addr_hash_ops
);
696 ORDERED_SET_FOREACH(j
, link
->network
->ipv6_tokens
) {
697 _cleanup_free_
struct in6_addr
*new_address
= NULL
;
699 if (j
->address_generation_type
== IPV6_TOKEN_ADDRESS_GENERATION_PREFIXSTABLE
700 && (in6_addr_is_null(&j
->prefix
) || in6_addr_equal(&j
->prefix
, address
))) {
701 /* While this loop uses dad_counter and a retry limit as specified in RFC 7217, the loop
702 * does not actually attempt Duplicate Address Detection; the counter will be incremented
703 * only when the address generation algorithm produces an invalid address, and the loop
704 * may exit with an address which ends up being unusable due to duplication on the link. */
705 for (; j
->dad_counter
< DAD_CONFLICTS_IDGEN_RETRIES_RFC7217
; j
->dad_counter
++) {
706 r
= make_stableprivate_address(link
, address
, prefixlen
, j
->dad_counter
, &new_address
);
712 } else if (j
->address_generation_type
== IPV6_TOKEN_ADDRESS_GENERATION_STATIC
) {
713 new_address
= new(struct in6_addr
, 1);
717 memcpy(new_address
->s6_addr
, address
->s6_addr
, 8);
718 memcpy(new_address
->s6_addr
+ 8, j
->prefix
.s6_addr
+ 8, 8);
722 r
= set_put(addresses
, new_address
);
724 return log_link_error_errno(link
, r
, "Failed to store SLAAC address: %m");
726 log_link_debug_errno(link
, r
, "Generated SLAAC address is duplicated, ignoring.");
728 TAKE_PTR(new_address
);
732 /* fall back to EUI-64 if no tokens provided addresses */
733 if (set_isempty(addresses
)) {
734 _cleanup_free_
struct in6_addr
*new_address
= NULL
;
736 new_address
= newdup(struct in6_addr
, address
, 1);
740 r
= generate_ipv6_eui_64_address(link
, new_address
);
742 return log_link_error_errno(link
, r
, "Failed to generate EUI64 address: %m");
744 r
= set_put(addresses
, new_address
);
746 return log_link_error_errno(link
, r
, "Failed to store SLAAC address: %m");
748 TAKE_PTR(new_address
);
751 *ret
= TAKE_PTR(addresses
);
756 static int ndisc_router_process_autonomous_prefix(Link
*link
, sd_ndisc_router
*rt
) {
757 uint32_t lifetime_valid
, lifetime_preferred
;
758 _cleanup_set_free_free_ Set
*addresses
= NULL
;
759 struct in6_addr addr
, *a
;
767 r
= sd_ndisc_router_get_timestamp(rt
, clock_boottime_or_monotonic(), &time_now
);
769 return log_link_error_errno(link
, r
, "Failed to get RA timestamp: %m");
771 r
= sd_ndisc_router_prefix_get_prefixlen(rt
, &prefixlen
);
773 return log_link_error_errno(link
, r
, "Failed to get prefix length: %m");
775 r
= sd_ndisc_router_prefix_get_valid_lifetime(rt
, &lifetime_valid
);
777 return log_link_error_errno(link
, r
, "Failed to get prefix valid lifetime: %m");
779 if (lifetime_valid
== 0) {
780 log_link_debug(link
, "Ignoring prefix as its valid lifetime is zero.");
784 r
= sd_ndisc_router_prefix_get_preferred_lifetime(rt
, &lifetime_preferred
);
786 return log_link_error_errno(link
, r
, "Failed to get prefix preferred lifetime: %m");
788 /* The preferred lifetime is never greater than the valid lifetime */
789 if (lifetime_preferred
> lifetime_valid
)
792 r
= sd_ndisc_router_prefix_get_address(rt
, &addr
);
794 return log_link_error_errno(link
, r
, "Failed to get prefix address: %m");
796 r
= ndisc_router_generate_addresses(link
, &addr
, prefixlen
, &addresses
);
800 SET_FOREACH(a
, addresses
) {
801 _cleanup_(address_freep
) Address
*address
= NULL
;
804 r
= address_new(&address
);
808 address
->family
= AF_INET6
;
809 address
->in_addr
.in6
= *a
;
810 address
->prefixlen
= prefixlen
;
811 address
->flags
= IFA_F_NOPREFIXROUTE
|IFA_F_MANAGETEMPADDR
;
812 address
->cinfo
.ifa_valid
= lifetime_valid
;
813 address
->cinfo
.ifa_prefered
= lifetime_preferred
;
815 /* See RFC4862, section 5.5.3.e. But the following logic is deviated from RFC4862 by
816 * honoring all valid lifetimes to improve the reaction of SLAAC to renumbering events.
817 * See draft-ietf-6man-slaac-renum-02, section 4.2. */
818 r
= address_get(link
, address
, &e
);
820 /* If the address is already assigned, but not valid anymore, then refuse to
821 * update the address. */
822 if (e
->cinfo
.tstamp
/ 100 + e
->cinfo
.ifa_valid
< time_now
/ USEC_PER_SEC
)
826 r
= ndisc_request_address(TAKE_PTR(address
), link
, rt
);
828 return log_link_error_errno(link
, r
, "Could not request SLAAC address: %m");
834 static int ndisc_router_process_onlink_prefix(Link
*link
, sd_ndisc_router
*rt
) {
835 _cleanup_(route_freep
) Route
*route
= NULL
;
844 r
= sd_ndisc_router_get_timestamp(rt
, clock_boottime_or_monotonic(), &time_now
);
846 return log_link_error_errno(link
, r
, "Failed to get RA timestamp: %m");
848 r
= sd_ndisc_router_prefix_get_prefixlen(rt
, &prefixlen
);
850 return log_link_error_errno(link
, r
, "Failed to get prefix length: %m");
852 r
= sd_ndisc_router_prefix_get_valid_lifetime(rt
, &lifetime
);
854 return log_link_error_errno(link
, r
, "Failed to get prefix lifetime: %m");
856 r
= route_new(&route
);
860 route
->family
= AF_INET6
;
861 route
->table
= link_get_ipv6_accept_ra_route_table(link
);
862 route
->priority
= link
->network
->ipv6_accept_ra_route_metric
;
863 route
->protocol
= RTPROT_RA
;
864 route
->flags
= RTM_F_PREFIX
;
865 route
->dst_prefixlen
= prefixlen
;
866 route
->lifetime
= usec_add(time_now
, lifetime
* USEC_PER_SEC
);
868 r
= sd_ndisc_router_prefix_get_address(rt
, &route
->dst
.in6
);
870 return log_link_error_errno(link
, r
, "Failed to get prefix address: %m");
872 r
= ndisc_request_route(TAKE_PTR(route
), link
, rt
);
874 return log_link_error_errno(link
, r
, "Could not request prefix route: %m");;
879 static int ndisc_router_process_route(Link
*link
, sd_ndisc_router
*rt
) {
880 _cleanup_(route_freep
) Route
*route
= NULL
;
881 struct in6_addr gateway
, dst
;
883 unsigned preference
, prefixlen
;
889 r
= sd_ndisc_router_route_get_lifetime(rt
, &lifetime
);
891 return log_link_error_errno(link
, r
, "Failed to get route lifetime from RA: %m");
896 r
= sd_ndisc_router_route_get_address(rt
, &dst
);
898 return log_link_error_errno(link
, r
, "Failed to get route destination address: %m");
900 if ((!set_isempty(link
->network
->ndisc_allow_listed_route_prefix
) &&
901 !set_contains(link
->network
->ndisc_allow_listed_route_prefix
, &dst
)) ||
902 set_contains(link
->network
->ndisc_deny_listed_route_prefix
, &dst
)) {
904 _cleanup_free_
char *buf
= NULL
;
906 (void) in6_addr_to_string(&dst
, &buf
);
907 if (!set_isempty(link
->network
->ndisc_allow_listed_route_prefix
))
908 log_link_debug(link
, "Route prefix '%s' is not in allow list, ignoring", strna(buf
));
910 log_link_debug(link
, "Route prefix '%s' is in deny list, ignoring", strna(buf
));
915 r
= sd_ndisc_router_get_address(rt
, &gateway
);
917 return log_link_error_errno(link
, r
, "Failed to get gateway address from RA: %m");
919 if (link_get_ipv6_address(link
, &gateway
, NULL
) >= 0) {
921 _cleanup_free_
char *buf
= NULL
;
923 (void) in6_addr_to_string(&gateway
, &buf
);
924 log_link_debug(link
, "Advertised route gateway %s is local to the link, ignoring route", strna(buf
));
929 r
= sd_ndisc_router_route_get_prefixlen(rt
, &prefixlen
);
931 return log_link_error_errno(link
, r
, "Failed to get route prefix length: %m");
933 r
= sd_ndisc_router_route_get_preference(rt
, &preference
);
935 return log_link_error_errno(link
, r
, "Failed to get default router preference from RA: %m");
937 r
= sd_ndisc_router_get_timestamp(rt
, clock_boottime_or_monotonic(), &time_now
);
939 return log_link_error_errno(link
, r
, "Failed to get RA timestamp: %m");
941 r
= route_new(&route
);
945 route
->family
= AF_INET6
;
946 route
->table
= link_get_ipv6_accept_ra_route_table(link
);
947 route
->priority
= link
->network
->ipv6_accept_ra_route_metric
;
948 route
->protocol
= RTPROT_RA
;
949 route
->pref
= preference
;
950 route
->gw
.in6
= gateway
;
951 route
->gw_family
= AF_INET6
;
952 route
->dst
.in6
= dst
;
953 route
->dst_prefixlen
= prefixlen
;
954 route
->lifetime
= usec_add(time_now
, lifetime
* USEC_PER_SEC
);
956 r
= ndisc_request_route(TAKE_PTR(route
), link
, rt
);
958 return log_link_error_errno(link
, r
, "Could not request additional route: %m");
963 static void ndisc_rdnss_hash_func(const NDiscRDNSS
*x
, struct siphash
*state
) {
964 siphash24_compress(&x
->address
, sizeof(x
->address
), state
);
967 static int ndisc_rdnss_compare_func(const NDiscRDNSS
*a
, const NDiscRDNSS
*b
) {
968 return memcmp(&a
->address
, &b
->address
, sizeof(a
->address
));
971 DEFINE_PRIVATE_HASH_OPS_WITH_KEY_DESTRUCTOR(
972 ndisc_rdnss_hash_ops
,
974 ndisc_rdnss_hash_func
,
975 ndisc_rdnss_compare_func
,
978 static int ndisc_router_process_rdnss(Link
*link
, sd_ndisc_router
*rt
) {
980 const struct in6_addr
*a
;
981 struct in6_addr router
;
984 bool updated
= false;
990 r
= sd_ndisc_router_get_address(rt
, &router
);
992 return log_link_error_errno(link
, r
, "Failed to get router address from RA: %m");
994 r
= sd_ndisc_router_get_timestamp(rt
, clock_boottime_or_monotonic(), &time_now
);
996 return log_link_error_errno(link
, r
, "Failed to get RA timestamp: %m");
998 r
= sd_ndisc_router_rdnss_get_lifetime(rt
, &lifetime
);
1000 return log_link_error_errno(link
, r
, "Failed to get RDNSS lifetime: %m");
1002 n
= sd_ndisc_router_rdnss_get_addresses(rt
, &a
);
1004 return log_link_error_errno(link
, n
, "Failed to get RDNSS addresses: %m");
1006 SET_FOREACH(rdnss
, link
->ndisc_rdnss
)
1007 if (in6_addr_equal(&rdnss
->router
, &router
))
1008 rdnss
->marked
= true;
1013 if (n
>= (int) NDISC_RDNSS_MAX
) {
1014 log_link_warning(link
, "Too many RDNSS records per link. Only first %i records will be used.", NDISC_RDNSS_MAX
);
1015 n
= NDISC_RDNSS_MAX
;
1018 for (int j
= 0; j
< n
; j
++) {
1019 _cleanup_free_ NDiscRDNSS
*x
= NULL
;
1024 rdnss
= set_get(link
->ndisc_rdnss
, &d
);
1026 rdnss
->marked
= false;
1027 rdnss
->router
= router
;
1028 rdnss
->valid_until
= time_now
+ lifetime
* USEC_PER_SEC
;
1032 x
= new(NDiscRDNSS
, 1);
1039 .valid_until
= time_now
+ lifetime
* USEC_PER_SEC
,
1042 r
= set_ensure_consume(&link
->ndisc_rdnss
, &ndisc_rdnss_hash_ops
, TAKE_PTR(x
));
1056 static void ndisc_dnssl_hash_func(const NDiscDNSSL
*x
, struct siphash
*state
) {
1057 siphash24_compress_string(NDISC_DNSSL_DOMAIN(x
), state
);
1060 static int ndisc_dnssl_compare_func(const NDiscDNSSL
*a
, const NDiscDNSSL
*b
) {
1061 return strcmp(NDISC_DNSSL_DOMAIN(a
), NDISC_DNSSL_DOMAIN(b
));
1064 DEFINE_PRIVATE_HASH_OPS_WITH_KEY_DESTRUCTOR(
1065 ndisc_dnssl_hash_ops
,
1067 ndisc_dnssl_hash_func
,
1068 ndisc_dnssl_compare_func
,
1071 static int ndisc_router_process_dnssl(Link
*link
, sd_ndisc_router
*rt
) {
1072 _cleanup_strv_free_
char **l
= NULL
;
1073 struct in6_addr router
;
1077 bool updated
= false;
1084 r
= sd_ndisc_router_get_address(rt
, &router
);
1086 return log_link_error_errno(link
, r
, "Failed to get router address from RA: %m");
1088 r
= sd_ndisc_router_get_timestamp(rt
, clock_boottime_or_monotonic(), &time_now
);
1090 return log_link_error_errno(link
, r
, "Failed to get RA timestamp: %m");
1092 r
= sd_ndisc_router_dnssl_get_lifetime(rt
, &lifetime
);
1094 return log_link_error_errno(link
, r
, "Failed to get DNSSL lifetime: %m");
1096 r
= sd_ndisc_router_dnssl_get_domains(rt
, &l
);
1098 return log_link_error_errno(link
, r
, "Failed to get DNSSL addresses: %m");
1100 SET_FOREACH(dnssl
, link
->ndisc_dnssl
)
1101 if (in6_addr_equal(&dnssl
->router
, &router
))
1102 dnssl
->marked
= true;
1107 if (strv_length(l
) >= NDISC_DNSSL_MAX
) {
1108 log_link_warning(link
, "Too many DNSSL records per link. Only first %i records will be used.", NDISC_DNSSL_MAX
);
1109 STRV_FOREACH(j
, l
+ NDISC_DNSSL_MAX
)
1113 STRV_FOREACH(j
, l
) {
1114 _cleanup_free_ NDiscDNSSL
*s
= NULL
;
1116 s
= malloc0(ALIGN(sizeof(NDiscDNSSL
)) + strlen(*j
) + 1);
1120 strcpy(NDISC_DNSSL_DOMAIN(s
), *j
);
1122 dnssl
= set_get(link
->ndisc_dnssl
, s
);
1124 dnssl
->marked
= false;
1125 dnssl
->router
= router
;
1126 dnssl
->valid_until
= time_now
+ lifetime
* USEC_PER_SEC
;
1131 s
->valid_until
= time_now
+ lifetime
* USEC_PER_SEC
;
1133 r
= set_ensure_consume(&link
->ndisc_dnssl
, &ndisc_dnssl_hash_ops
, TAKE_PTR(s
));
1147 static int ndisc_router_process_options(Link
*link
, sd_ndisc_router
*rt
) {
1149 assert(link
->network
);
1152 for (int r
= sd_ndisc_router_option_rewind(rt
); ; r
= sd_ndisc_router_option_next(rt
)) {
1156 return log_link_error_errno(link
, r
, "Failed to iterate through options: %m");
1157 if (r
== 0) /* EOF */
1160 r
= sd_ndisc_router_option_get_type(rt
, &type
);
1162 return log_link_error_errno(link
, r
, "Failed to get RA option type: %m");
1166 case SD_NDISC_OPTION_PREFIX_INFORMATION
: {
1170 r
= sd_ndisc_router_prefix_get_address(rt
, &a
);
1172 return log_link_error_errno(link
, r
, "Failed to get prefix address: %m");
1174 if ((!set_isempty(link
->network
->ndisc_allow_listed_prefix
) &&
1175 !set_contains(link
->network
->ndisc_allow_listed_prefix
, &a
)) ||
1176 set_contains(link
->network
->ndisc_deny_listed_prefix
, &a
)) {
1177 if (DEBUG_LOGGING
) {
1178 _cleanup_free_
char *b
= NULL
;
1180 (void) in6_addr_to_string(&a
, &b
);
1181 if (!set_isempty(link
->network
->ndisc_allow_listed_prefix
))
1182 log_link_debug(link
, "Prefix '%s' is not in allow list, ignoring", strna(b
));
1184 log_link_debug(link
, "Prefix '%s' is in deny list, ignoring", strna(b
));
1189 r
= sd_ndisc_router_prefix_get_flags(rt
, &flags
);
1191 return log_link_error_errno(link
, r
, "Failed to get RA prefix flags: %m");
1193 if (link
->network
->ipv6_accept_ra_use_onlink_prefix
&&
1194 FLAGS_SET(flags
, ND_OPT_PI_FLAG_ONLINK
)) {
1195 r
= ndisc_router_process_onlink_prefix(link
, rt
);
1200 if (link
->network
->ipv6_accept_ra_use_autonomous_prefix
&&
1201 FLAGS_SET(flags
, ND_OPT_PI_FLAG_AUTO
)) {
1202 r
= ndisc_router_process_autonomous_prefix(link
, rt
);
1209 case SD_NDISC_OPTION_ROUTE_INFORMATION
:
1210 r
= ndisc_router_process_route(link
, rt
);
1215 case SD_NDISC_OPTION_RDNSS
:
1216 if (link
->network
->ipv6_accept_ra_use_dns
) {
1217 r
= ndisc_router_process_rdnss(link
, rt
);
1223 case SD_NDISC_OPTION_DNSSL
:
1224 if (link
->network
->ipv6_accept_ra_use_dns
) {
1225 r
= ndisc_router_process_dnssl(link
, rt
);
1234 static int ndisc_router_handler(Link
*link
, sd_ndisc_router
*rt
) {
1235 struct in6_addr router
;
1242 assert(link
->network
);
1243 assert(link
->manager
);
1246 r
= sd_ndisc_router_get_address(rt
, &router
);
1248 return log_link_error_errno(link
, r
, "Failed to get router address from RA: %m");
1250 if ((!set_isempty(link
->network
->ndisc_allow_listed_router
) &&
1251 !set_contains(link
->network
->ndisc_allow_listed_router
, &router
)) ||
1252 set_contains(link
->network
->ndisc_deny_listed_router
, &router
)) {
1253 if (DEBUG_LOGGING
) {
1254 _cleanup_free_
char *buf
= NULL
;
1256 (void) in6_addr_to_string(&router
, &buf
);
1257 if (!set_isempty(link
->network
->ndisc_allow_listed_router
))
1258 log_link_debug(link
, "Router '%s' is not in allow list, ignoring", strna(buf
));
1260 log_link_debug(link
, "Router '%s' is in deny list, ignoring", strna(buf
));
1265 SET_FOREACH(na
, link
->ndisc_addresses
)
1266 if (in6_addr_equal(&na
->router
, &router
))
1269 SET_FOREACH(nr
, link
->ndisc_routes
)
1270 if (in6_addr_equal(&nr
->router
, &router
))
1273 r
= sd_ndisc_router_get_flags(rt
, &flags
);
1275 return log_link_error_errno(link
, r
, "Failed to get RA flags: %m");
1277 if ((flags
& (ND_RA_FLAG_MANAGED
| ND_RA_FLAG_OTHER
) &&
1278 link
->network
->ipv6_accept_ra_start_dhcp6_client
!= IPV6_ACCEPT_RA_START_DHCP6_CLIENT_NO
) ||
1279 link
->network
->ipv6_accept_ra_start_dhcp6_client
== IPV6_ACCEPT_RA_START_DHCP6_CLIENT_ALWAYS
) {
1281 if (flags
& (ND_RA_FLAG_MANAGED
| ND_RA_FLAG_OTHER
))
1282 /* (re)start DHCPv6 client in stateful or stateless mode according to RA flags */
1283 r
= dhcp6_request_information(link
, !(flags
& ND_RA_FLAG_MANAGED
));
1285 /* When IPv6AcceptRA.DHCPv6Client=always, start dhcp6 client in managed mode
1286 * even if router does not have M or O flag. */
1287 r
= dhcp6_request_information(link
, false);
1288 if (r
< 0 && r
!= -EBUSY
)
1289 return log_link_error_errno(link
, r
, "Could not acquire DHCPv6 lease on NDisc request: %m");
1291 log_link_debug(link
, "Acquiring DHCPv6 lease on NDisc request");
1294 r
= ndisc_router_process_default(link
, rt
);
1297 r
= ndisc_router_process_options(link
, rt
);
1301 if (link
->ndisc_addresses_messages
== 0)
1302 link
->ndisc_addresses_configured
= true;
1304 log_link_debug(link
, "Setting SLAAC addresses.");
1306 if (link
->ndisc_routes_messages
== 0)
1307 link
->ndisc_routes_configured
= true;
1309 log_link_debug(link
, "Setting NDisc routes.");
1311 r
= ndisc_remove_old(link
);
1315 if (!link
->ndisc_addresses_configured
|| !link
->ndisc_routes_configured
)
1316 link_set_state(link
, LINK_STATE_CONFIGURING
);
1318 link_check_ready(link
);
1322 static void ndisc_handler(sd_ndisc
*nd
, sd_ndisc_event_t event
, sd_ndisc_router
*rt
, void *userdata
) {
1323 Link
*link
= userdata
;
1328 if (IN_SET(link
->state
, LINK_STATE_FAILED
, LINK_STATE_LINGER
))
1333 case SD_NDISC_EVENT_ROUTER
:
1334 r
= ndisc_router_handler(link
, rt
);
1336 link_enter_failed(link
);
1341 case SD_NDISC_EVENT_TIMEOUT
:
1342 log_link_debug(link
, "NDisc handler get timeout event");
1343 if (link
->ndisc_addresses_messages
== 0 && link
->ndisc_routes_messages
== 0) {
1344 link
->ndisc_addresses_configured
= true;
1345 link
->ndisc_routes_configured
= true;
1346 link_check_ready(link
);
1350 assert_not_reached("Unknown NDisc event");
1354 int ndisc_configure(Link
*link
) {
1359 if (!link_ipv6_accept_ra_enabled(link
))
1363 return -EBUSY
; /* Already configured. */
1365 r
= sd_ndisc_new(&link
->ndisc
);
1369 r
= sd_ndisc_attach_event(link
->ndisc
, link
->manager
->event
, 0);
1373 r
= sd_ndisc_set_mac(link
->ndisc
, &link
->hw_addr
.ether
);
1377 r
= sd_ndisc_set_ifindex(link
->ndisc
, link
->ifindex
);
1381 r
= sd_ndisc_set_callback(link
->ndisc
, ndisc_handler
, link
);
1388 int ndisc_start(Link
*link
) {
1391 if (!link
->ndisc
|| !link
->dhcp6_client
)
1394 log_link_debug(link
, "Discovering IPv6 routers");
1396 return sd_ndisc_start(link
->ndisc
);
1399 void ndisc_vacuum(Link
*link
) {
1406 /* Removes all RDNSS and DNSSL entries whose validity time has passed */
1408 time_now
= now(clock_boottime_or_monotonic());
1410 SET_FOREACH(r
, link
->ndisc_rdnss
)
1411 if (r
->valid_until
< time_now
)
1412 free(set_remove(link
->ndisc_rdnss
, r
));
1414 SET_FOREACH(d
, link
->ndisc_dnssl
)
1415 if (d
->valid_until
< time_now
)
1416 free(set_remove(link
->ndisc_dnssl
, d
));
1419 void ndisc_flush(Link
*link
) {
1422 /* Removes all RDNSS and DNSSL entries, without exception */
1424 link
->ndisc_rdnss
= set_free(link
->ndisc_rdnss
);
1425 link
->ndisc_dnssl
= set_free(link
->ndisc_dnssl
);
1428 int ipv6token_new(IPv6Token
**ret
) {
1431 p
= new(IPv6Token
, 1);
1436 .address_generation_type
= IPV6_TOKEN_ADDRESS_GENERATION_NONE
,
1444 static void ipv6_token_hash_func(const IPv6Token
*p
, struct siphash
*state
) {
1445 siphash24_compress(&p
->address_generation_type
, sizeof(p
->address_generation_type
), state
);
1446 siphash24_compress(&p
->prefix
, sizeof(p
->prefix
), state
);
1449 static int ipv6_token_compare_func(const IPv6Token
*a
, const IPv6Token
*b
) {
1452 r
= CMP(a
->address_generation_type
, b
->address_generation_type
);
1456 return memcmp(&a
->prefix
, &b
->prefix
, sizeof(struct in6_addr
));
1459 DEFINE_HASH_OPS_WITH_KEY_DESTRUCTOR(
1460 ipv6_token_hash_ops
,
1462 ipv6_token_hash_func
,
1463 ipv6_token_compare_func
,
1466 int config_parse_ndisc_address_filter(
1468 const char *filename
,
1470 const char *section
,
1471 unsigned section_line
,
1486 if (isempty(rvalue
)) {
1487 *list
= set_free_free(*list
);
1491 for (const char *p
= rvalue
;;) {
1492 _cleanup_free_
char *n
= NULL
;
1493 _cleanup_free_
struct in6_addr
*a
= NULL
;
1494 union in_addr_union ip
;
1496 r
= extract_first_word(&p
, &n
, NULL
, 0);
1500 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
1501 "Failed to parse NDisc %s=, ignoring assignment: %s",
1508 r
= in_addr_from_string(AF_INET6
, n
, &ip
);
1510 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
1511 "NDisc %s= entry is invalid, ignoring assignment: %s",
1516 a
= newdup(struct in6_addr
, &ip
.in6
, 1);
1520 r
= set_ensure_consume(list
, &in6_addr_hash_ops
, TAKE_PTR(a
));
1524 log_syntax(unit
, LOG_WARNING
, filename
, line
, 0,
1525 "NDisc %s= entry is duplicated, ignoring assignment: %s",
1530 int config_parse_address_generation_type(
1532 const char *filename
,
1534 const char *section
,
1535 unsigned section_line
,
1542 _cleanup_free_ IPv6Token
*token
= NULL
;
1543 union in_addr_union buffer
;
1544 Network
*network
= data
;
1553 if (isempty(rvalue
)) {
1554 network
->ipv6_tokens
= ordered_set_free(network
->ipv6_tokens
);
1558 r
= ipv6token_new(&token
);
1562 if ((p
= startswith(rvalue
, "prefixstable"))) {
1563 token
->address_generation_type
= IPV6_TOKEN_ADDRESS_GENERATION_PREFIXSTABLE
;
1566 else if (*p
== '\0')
1569 log_syntax(unit
, LOG_WARNING
, filename
, line
, 0,
1570 "Invalid IPv6 token mode in %s=, ignoring assignment: %s",
1575 token
->address_generation_type
= IPV6_TOKEN_ADDRESS_GENERATION_STATIC
;
1576 p
= startswith(rvalue
, "static:");
1582 r
= in_addr_from_string(AF_INET6
, p
, &buffer
);
1584 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
1585 "Failed to parse IP address in %s=, ignoring assignment: %s",
1589 if (token
->address_generation_type
== IPV6_TOKEN_ADDRESS_GENERATION_STATIC
&&
1590 in_addr_is_null(AF_INET6
, &buffer
)) {
1591 log_syntax(unit
, LOG_WARNING
, filename
, line
, 0,
1592 "IPv6 address in %s= cannot be the ANY address, ignoring assignment: %s",
1596 token
->prefix
= buffer
.in6
;
1599 r
= ordered_set_ensure_put(&network
->ipv6_tokens
, &ipv6_token_hash_ops
, token
);
1603 log_syntax(unit
, LOG_DEBUG
, filename
, line
, r
,
1604 "IPv6 token '%s' is duplicated, ignoring: %m", rvalue
);
1606 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
1607 "Failed to store IPv6 token '%s', ignoring: %m", rvalue
);
1614 DEFINE_CONFIG_PARSE_ENUM(config_parse_ipv6_accept_ra_use_domains
, dhcp_use_domains
, DHCPUseDomains
,
1615 "Failed to parse UseDomains= setting");
1616 DEFINE_CONFIG_PARSE_ENUM(config_parse_ipv6_accept_ra_start_dhcp6_client
, ipv6_accept_ra_start_dhcp6_client
, IPv6AcceptRAStartDHCP6Client
,
1617 "Failed to parse DHCPv6Client= setting");
1618 static const char* const ipv6_accept_ra_start_dhcp6_client_table
[_IPV6_ACCEPT_RA_START_DHCP6_CLIENT_MAX
] = {
1619 [IPV6_ACCEPT_RA_START_DHCP6_CLIENT_NO
] = "no",
1620 [IPV6_ACCEPT_RA_START_DHCP6_CLIENT_ALWAYS
] = "always",
1621 [IPV6_ACCEPT_RA_START_DHCP6_CLIENT_YES
] = "yes",
1624 DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(ipv6_accept_ra_start_dhcp6_client
, IPv6AcceptRAStartDHCP6Client
, IPV6_ACCEPT_RA_START_DHCP6_CLIENT_YES
);