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 typedef enum IPv6TokenAddressGeneration
{
42 IPV6_TOKEN_ADDRESS_GENERATION_NONE
,
43 IPV6_TOKEN_ADDRESS_GENERATION_STATIC
,
44 IPV6_TOKEN_ADDRESS_GENERATION_PREFIXSTABLE
,
45 _IPV6_TOKEN_ADDRESS_GENERATION_MAX
,
46 _IPV6_TOKEN_ADDRESS_GENERATION_INVALID
= -EINVAL
,
47 } IPv6TokenAddressGeneration
;
49 typedef struct IPv6Token
{
50 IPv6TokenAddressGeneration address_generation_type
;
53 struct in6_addr prefix
;
56 bool link_ipv6_accept_ra_enabled(Link
*link
) {
59 if (!socket_ipv6_is_supported())
62 if (link
->flags
& IFF_LOOPBACK
)
68 if (!link_ipv6ll_enabled(link
))
71 assert(link
->network
->ipv6_accept_ra
>= 0);
72 return link
->network
->ipv6_accept_ra
;
75 void network_adjust_ipv6_accept_ra(Network
*network
) {
78 if (!FLAGS_SET(network
->link_local
, ADDRESS_FAMILY_IPV6
)) {
79 if (network
->ipv6_accept_ra
> 0)
80 log_warning("%s: IPv6AcceptRA= is enabled but IPv6 link local addressing is disabled or not supported. "
81 "Disabling IPv6AcceptRA=.", network
->filename
);
82 network
->ipv6_accept_ra
= false;
85 if (network
->ipv6_accept_ra
< 0)
86 /* default to accept RA if ip_forward is disabled and ignore RA if ip_forward is enabled */
87 network
->ipv6_accept_ra
= !FLAGS_SET(network
->ip_forward
, ADDRESS_FAMILY_IPV6
);
89 /* When RouterAllowList=, PrefixAllowList= or RouteAllowList= are specified, then
90 * RouterDenyList=, PrefixDenyList= or RouteDenyList= are ignored, respectively. */
91 if (!set_isempty(network
->ndisc_allow_listed_router
))
92 network
->ndisc_deny_listed_router
= set_free_free(network
->ndisc_deny_listed_router
);
93 if (!set_isempty(network
->ndisc_allow_listed_prefix
))
94 network
->ndisc_deny_listed_prefix
= set_free_free(network
->ndisc_deny_listed_prefix
);
95 if (!set_isempty(network
->ndisc_allow_listed_route_prefix
))
96 network
->ndisc_deny_listed_route_prefix
= set_free_free(network
->ndisc_deny_listed_route_prefix
);
99 static int ndisc_remove_old_one(Link
*link
, const struct in6_addr
*router
, bool force
);
101 static int ndisc_address_callback(Address
*address
) {
102 struct in6_addr router
= {};
106 assert(address
->link
);
107 assert(address
->family
== AF_INET6
);
109 SET_FOREACH(n
, address
->link
->ndisc_addresses
)
110 if (n
->address
== address
) {
115 if (in6_addr_is_null(&router
)) {
116 _cleanup_free_
char *buf
= NULL
;
118 (void) in6_addr_prefix_to_string(&address
->in_addr
.in6
, address
->prefixlen
, &buf
);
119 log_link_debug(address
->link
, "%s is called for %s, but it is already removed, ignoring.",
120 __func__
, strna(buf
));
124 /* Make this called only once */
125 SET_FOREACH(n
, address
->link
->ndisc_addresses
)
126 if (in6_addr_equal(&n
->router
, &router
))
127 n
->address
->callback
= NULL
;
129 return ndisc_remove_old_one(address
->link
, &router
, true);
132 static int ndisc_remove_old_one(Link
*link
, const struct in6_addr
*router
, bool force
) {
138 bool updated
= false;
144 bool set_callback
= false;
146 SET_FOREACH(na
, link
->ndisc_addresses
)
147 if (!na
->marked
&& in6_addr_equal(&na
->router
, router
)) {
153 SET_FOREACH(na
, link
->ndisc_addresses
)
154 if (!na
->marked
&& address_is_ready(na
->address
)) {
155 set_callback
= false;
160 SET_FOREACH(na
, link
->ndisc_addresses
)
161 if (!na
->marked
&& in6_addr_equal(&na
->router
, router
))
162 na
->address
->callback
= ndisc_address_callback
;
165 _cleanup_free_
char *buf
= NULL
;
167 (void) in6_addr_to_string(router
, &buf
);
168 log_link_debug(link
, "No SLAAC address obtained from %s is ready. "
169 "The old NDisc information will be removed later.",
177 _cleanup_free_
char *buf
= NULL
;
179 (void) in6_addr_to_string(router
, &buf
);
180 log_link_debug(link
, "Removing old NDisc information obtained from %s.", strna(buf
));
183 SET_FOREACH(na
, link
->ndisc_addresses
)
184 if (na
->marked
&& in6_addr_equal(&na
->router
, router
)) {
185 k
= address_remove(na
->address
, link
);
190 SET_FOREACH(nr
, link
->ndisc_routes
)
191 if (nr
->marked
&& in6_addr_equal(&nr
->router
, router
)) {
192 k
= route_remove(nr
->route
, NULL
, link
);
197 SET_FOREACH(rdnss
, link
->ndisc_rdnss
)
198 if (rdnss
->marked
&& in6_addr_equal(&rdnss
->router
, router
)) {
199 free(set_remove(link
->ndisc_rdnss
, rdnss
));
203 SET_FOREACH(dnssl
, link
->ndisc_dnssl
)
204 if (dnssl
->marked
&& in6_addr_equal(&dnssl
->router
, router
)) {
205 free(set_remove(link
->ndisc_dnssl
, dnssl
));
215 static int ndisc_remove_old(Link
*link
) {
216 _cleanup_set_free_free_ Set
*routers
= NULL
;
217 _cleanup_free_
struct in6_addr
*router
= NULL
;
227 if (link
->ndisc_addresses_messages
> 0 ||
228 link
->ndisc_routes_messages
> 0)
231 routers
= set_new(&in6_addr_hash_ops
);
235 SET_FOREACH(na
, link
->ndisc_addresses
)
236 if (!set_contains(routers
, &na
->router
)) {
237 router
= newdup(struct in6_addr
, &na
->router
, 1);
241 r
= set_put(routers
, router
);
249 SET_FOREACH(nr
, link
->ndisc_routes
)
250 if (!set_contains(routers
, &nr
->router
)) {
251 router
= newdup(struct in6_addr
, &nr
->router
, 1);
255 r
= set_put(routers
, router
);
263 SET_FOREACH(rdnss
, link
->ndisc_rdnss
)
264 if (!set_contains(routers
, &rdnss
->router
)) {
265 router
= newdup(struct in6_addr
, &rdnss
->router
, 1);
269 r
= set_put(routers
, router
);
277 SET_FOREACH(dnssl
, link
->ndisc_dnssl
)
278 if (!set_contains(routers
, &dnssl
->router
)) {
279 router
= newdup(struct in6_addr
, &dnssl
->router
, 1);
283 r
= set_put(routers
, router
);
292 SET_FOREACH(a
, routers
) {
293 k
= ndisc_remove_old_one(link
, a
, false);
301 static void ndisc_route_hash_func(const NDiscRoute
*x
, struct siphash
*state
) {
302 route_hash_func(x
->route
, state
);
305 static int ndisc_route_compare_func(const NDiscRoute
*a
, const NDiscRoute
*b
) {
306 return route_compare_func(a
->route
, b
->route
);
309 DEFINE_PRIVATE_HASH_OPS_WITH_KEY_DESTRUCTOR(
310 ndisc_route_hash_ops
,
312 ndisc_route_hash_func
,
313 ndisc_route_compare_func
,
316 static int ndisc_route_handler(sd_netlink
*rtnl
, sd_netlink_message
*m
, Link
*link
) {
320 assert(link
->ndisc_routes_messages
> 0);
322 link
->ndisc_routes_messages
--;
324 r
= route_configure_handler_internal(rtnl
, m
, link
, "Could not set NDisc route");
328 if (link
->ndisc_routes_messages
== 0) {
329 log_link_debug(link
, "NDisc routes set.");
330 link
->ndisc_routes_configured
= true;
332 r
= ndisc_remove_old(link
);
334 link_enter_failed(link
);
338 link_check_ready(link
);
344 static int ndisc_after_route_configure(Request
*req
, void *object
) {
345 _cleanup_free_ NDiscRoute
*nr
= NULL
;
346 NDiscRoute
*nr_exist
;
347 struct in6_addr router
;
348 Route
*route
= object
;
355 assert(req
->type
== REQUEST_TYPE_ROUTE
);
356 assert(req
->userdata
);
362 r
= sd_ndisc_router_get_address(rt
, &router
);
364 return log_link_error_errno(link
, r
, "Failed to get router address from RA: %m");
366 nr
= new(NDiscRoute
, 1);
375 nr_exist
= set_get(link
->ndisc_routes
, nr
);
377 nr_exist
->marked
= false;
378 nr_exist
->router
= router
;
382 r
= set_ensure_put(&link
->ndisc_routes
, &ndisc_route_hash_ops
, nr
);
384 return log_link_error_errno(link
, r
, "Failed to store NDisc SLAAC route: %m");
391 static void ndisc_request_on_free(Request
*req
) {
394 sd_ndisc_router_unref(req
->userdata
);
397 static int ndisc_request_route(Route
*in
, Link
*link
, sd_ndisc_router
*rt
) {
398 _cleanup_(route_freep
) Route
*route
= in
;
406 if (!route
->table_set
)
407 route
->table
= link_get_ipv6_accept_ra_route_table(link
);
408 if (!route
->priority_set
)
409 route
->priority
= link
->network
->ipv6_accept_ra_route_metric
;
410 if (!route
->protocol_set
)
411 route
->protocol
= RTPROT_RA
;
413 r
= link_has_route(link
, route
);
417 link
->ndisc_routes_configured
= false;
419 r
= link_request_route(link
, TAKE_PTR(route
), true, &link
->ndisc_routes_messages
,
420 ndisc_route_handler
, &req
);
424 req
->userdata
= sd_ndisc_router_ref(rt
);
425 req
->after_configure
= ndisc_after_route_configure
;
426 req
->on_free
= ndisc_request_on_free
;
431 static void ndisc_address_hash_func(const NDiscAddress
*x
, struct siphash
*state
) {
432 address_hash_func(x
->address
, state
);
435 static int ndisc_address_compare_func(const NDiscAddress
*a
, const NDiscAddress
*b
) {
436 return address_compare_func(a
->address
, b
->address
);
439 DEFINE_PRIVATE_HASH_OPS_WITH_KEY_DESTRUCTOR(
440 ndisc_address_hash_ops
,
442 ndisc_address_hash_func
,
443 ndisc_address_compare_func
,
446 static int ndisc_address_handler(sd_netlink
*rtnl
, sd_netlink_message
*m
, Link
*link
) {
450 assert(link
->ndisc_addresses_messages
> 0);
452 link
->ndisc_addresses_messages
--;
454 r
= address_configure_handler_internal(rtnl
, m
, link
, "Could not set NDisc address");
458 if (link
->ndisc_addresses_messages
== 0) {
459 log_link_debug(link
, "NDisc SLAAC addresses set.");
460 link
->ndisc_addresses_configured
= true;
462 r
= ndisc_remove_old(link
);
464 link_enter_failed(link
);
472 static int ndisc_after_address_configure(Request
*req
, void *object
) {
473 _cleanup_free_ NDiscAddress
*na
= NULL
;
474 NDiscAddress
*na_exist
;
475 struct in6_addr router
;
477 Address
*address
= object
;
483 assert(req
->type
== REQUEST_TYPE_ADDRESS
);
484 assert(req
->userdata
);
490 r
= sd_ndisc_router_get_address(rt
, &router
);
492 return log_link_error_errno(link
, r
, "Failed to get router address from RA: %m");
494 na
= new(NDiscAddress
, 1);
498 *na
= (NDiscAddress
) {
503 na_exist
= set_get(link
->ndisc_addresses
, na
);
505 na_exist
->marked
= false;
506 na_exist
->router
= router
;
510 r
= set_ensure_put(&link
->ndisc_addresses
, &ndisc_address_hash_ops
, na
);
512 return log_link_error_errno(link
, r
, "Failed to store NDisc SLAAC address: %m");
519 static int ndisc_request_address(Address
*in
, Link
*link
, sd_ndisc_router
*rt
) {
520 _cleanup_(address_freep
) Address
*address
= in
;
528 if (address_get(link
, address
, NULL
) < 0)
529 link
->ndisc_addresses_configured
= false;
531 r
= link_request_address(link
, TAKE_PTR(address
), true, &link
->ndisc_addresses_messages
,
532 ndisc_address_handler
, &req
);
536 req
->userdata
= sd_ndisc_router_ref(rt
);
537 req
->after_configure
= ndisc_after_address_configure
;
538 req
->on_free
= ndisc_request_on_free
;
543 static int ndisc_router_process_default(Link
*link
, sd_ndisc_router
*rt
) {
544 _cleanup_(route_freep
) Route
*route
= NULL
;
545 struct in6_addr gateway
;
555 r
= sd_ndisc_router_get_lifetime(rt
, &lifetime
);
557 return log_link_error_errno(link
, r
, "Failed to get gateway lifetime from RA: %m");
559 if (lifetime
== 0) /* not a default router */
562 r
= sd_ndisc_router_get_address(rt
, &gateway
);
564 return log_link_error_errno(link
, r
, "Failed to get gateway address from RA: %m");
566 if (link_get_ipv6_address(link
, &gateway
, NULL
) >= 0) {
568 _cleanup_free_
char *buffer
= NULL
;
570 (void) in6_addr_to_string(&gateway
, &buffer
);
571 log_link_debug(link
, "No NDisc route added, gateway %s matches local address",
577 r
= sd_ndisc_router_get_preference(rt
, &preference
);
579 return log_link_error_errno(link
, r
, "Failed to get default router preference from RA: %m");
581 r
= sd_ndisc_router_get_timestamp(rt
, clock_boottime_or_monotonic(), &time_now
);
583 return log_link_error_errno(link
, r
, "Failed to get RA timestamp: %m");
585 if (link
->network
->ipv6_accept_ra_use_mtu
) {
586 r
= sd_ndisc_router_get_mtu(rt
, &mtu
);
587 if (r
< 0 && r
!= -ENODATA
)
588 return log_link_error_errno(link
, r
, "Failed to get default router MTU from RA: %m");
591 r
= route_new(&route
);
595 route
->family
= AF_INET6
;
596 route
->pref
= preference
;
597 route
->gw_family
= AF_INET6
;
598 route
->gw
.in6
= gateway
;
599 route
->lifetime
= usec_add(time_now
, lifetime
* USEC_PER_SEC
);
602 r
= ndisc_request_route(TAKE_PTR(route
), link
, rt
);
604 return log_link_error_errno(link
, r
, "Could not request default route: %m");
607 HASHMAP_FOREACH(route_gw
, link
->network
->routes_by_section
) {
608 if (!route_gw
->gateway_from_dhcp_or_ra
)
611 if (route_gw
->gw_family
!= AF_INET6
)
614 r
= route_dup(route_gw
, &route
);
618 route
->gw
.in6
= gateway
;
619 if (!route
->pref_set
)
620 route
->pref
= preference
;
621 route
->lifetime
= usec_add(time_now
, lifetime
* USEC_PER_SEC
);
625 r
= ndisc_request_route(TAKE_PTR(route
), link
, rt
);
627 return log_link_error_errno(link
, r
, "Could not request gateway: %m");
633 static bool stable_private_address_is_valid(const struct in6_addr
*addr
) {
636 /* According to rfc4291, generated address should not be in the following ranges. */
638 if (memcmp(addr
, &SUBNET_ROUTER_ANYCAST_ADDRESS_RFC4291
, SUBNET_ROUTER_ANYCAST_PREFIXLEN
) == 0)
641 if (memcmp(addr
, &RESERVED_IPV6_INTERFACE_IDENTIFIERS_ADDRESS_RFC4291
, RESERVED_IPV6_INTERFACE_IDENTIFIERS_PREFIXLEN
) == 0)
644 if (memcmp(addr
, &RESERVED_SUBNET_ANYCAST_ADDRESSES_RFC4291
, RESERVED_SUBNET_ANYCAST_PREFIXLEN
) == 0)
650 static int make_stable_private_address(Link
*link
, const struct in6_addr
*prefix
, uint8_t prefix_len
, uint8_t dad_counter
, struct in6_addr
**ret
) {
651 _cleanup_free_
struct in6_addr
*addr
= NULL
;
652 sd_id128_t secret_key
;
653 struct siphash state
;
658 /* According to rfc7217 section 5.1
659 * RID = F(Prefix, Net_Iface, Network_ID, DAD_Counter, secret_key) */
661 r
= sd_id128_get_machine_app_specific(NDISC_APP_ID
, &secret_key
);
663 return log_link_warning_errno(link
, r
, "Failed to generate key for IPv6 stable private address: %m");
665 siphash24_init(&state
, secret_key
.bytes
);
667 l
= MAX(DIV_ROUND_UP(prefix_len
, 8), 8);
668 siphash24_compress(prefix
, l
, &state
);
669 siphash24_compress_string(link
->ifname
, &state
);
670 /* Only last 8 bytes of IB MAC are stable */
671 if (link
->iftype
== ARPHRD_INFINIBAND
)
672 siphash24_compress(&link
->hw_addr
.infiniband
[12], 8, &state
);
674 siphash24_compress(link
->hw_addr
.bytes
, link
->hw_addr
.length
, &state
);
675 siphash24_compress(&dad_counter
, sizeof(uint8_t), &state
);
677 rid
= htole64(siphash24_finalize(&state
));
679 addr
= new(struct in6_addr
, 1);
683 memcpy(addr
->s6_addr
, prefix
->s6_addr
, l
);
684 memcpy(addr
->s6_addr
+ l
, &rid
, 16 - l
);
686 if (!stable_private_address_is_valid(addr
)) {
691 *ret
= TAKE_PTR(addr
);
695 static int ndisc_router_generate_addresses(Link
*link
, struct in6_addr
*address
, uint8_t prefixlen
, Set
**ret
) {
696 _cleanup_set_free_free_ Set
*addresses
= NULL
;
704 addresses
= set_new(&in6_addr_hash_ops
);
708 ORDERED_SET_FOREACH(j
, link
->network
->ipv6_tokens
) {
709 _cleanup_free_
struct in6_addr
*new_address
= NULL
;
711 if (j
->address_generation_type
== IPV6_TOKEN_ADDRESS_GENERATION_PREFIXSTABLE
712 && (in6_addr_is_null(&j
->prefix
) || in6_addr_equal(&j
->prefix
, address
))) {
713 /* While this loop uses dad_counter and a retry limit as specified in RFC 7217, the loop
714 * does not actually attempt Duplicate Address Detection; the counter will be incremented
715 * only when the address generation algorithm produces an invalid address, and the loop
716 * may exit with an address which ends up being unusable due to duplication on the link. */
717 for (; j
->dad_counter
< DAD_CONFLICTS_IDGEN_RETRIES_RFC7217
; j
->dad_counter
++) {
718 r
= make_stable_private_address(link
, address
, prefixlen
, j
->dad_counter
, &new_address
);
724 } else if (j
->address_generation_type
== IPV6_TOKEN_ADDRESS_GENERATION_STATIC
) {
725 new_address
= new(struct in6_addr
, 1);
729 memcpy(new_address
->s6_addr
, address
->s6_addr
, 8);
730 memcpy(new_address
->s6_addr
+ 8, j
->prefix
.s6_addr
+ 8, 8);
734 r
= set_put(addresses
, new_address
);
736 return log_link_error_errno(link
, r
, "Failed to store SLAAC address: %m");
738 log_link_debug_errno(link
, r
, "Generated SLAAC address is duplicated, ignoring.");
740 TAKE_PTR(new_address
);
744 /* fall back to EUI-64 if no tokens provided addresses */
745 if (set_isempty(addresses
)) {
746 _cleanup_free_
struct in6_addr
*new_address
= NULL
;
748 new_address
= newdup(struct in6_addr
, address
, 1);
752 r
= generate_ipv6_eui_64_address(link
, new_address
);
754 return log_link_error_errno(link
, r
, "Failed to generate EUI64 address: %m");
756 r
= set_put(addresses
, new_address
);
758 return log_link_error_errno(link
, r
, "Failed to store SLAAC address: %m");
760 TAKE_PTR(new_address
);
763 *ret
= TAKE_PTR(addresses
);
768 static int ndisc_router_process_autonomous_prefix(Link
*link
, sd_ndisc_router
*rt
) {
769 uint32_t lifetime_valid
, lifetime_preferred
;
770 _cleanup_set_free_free_ Set
*addresses
= NULL
;
771 struct in6_addr addr
, *a
;
779 /* Do not use clock_boottime_or_monotonic() here, as the kernel internally manages cstamp and
780 * tstamp with jiffies, and it is not increased while the system is suspended. */
781 r
= sd_ndisc_router_get_timestamp(rt
, CLOCK_MONOTONIC
, &time_now
);
783 return log_link_error_errno(link
, r
, "Failed to get RA timestamp: %m");
785 r
= sd_ndisc_router_prefix_get_prefixlen(rt
, &prefixlen
);
787 return log_link_error_errno(link
, r
, "Failed to get prefix length: %m");
789 r
= sd_ndisc_router_prefix_get_valid_lifetime(rt
, &lifetime_valid
);
791 return log_link_error_errno(link
, r
, "Failed to get prefix valid lifetime: %m");
793 if (lifetime_valid
== 0) {
794 log_link_debug(link
, "Ignoring prefix as its valid lifetime is zero.");
798 r
= sd_ndisc_router_prefix_get_preferred_lifetime(rt
, &lifetime_preferred
);
800 return log_link_error_errno(link
, r
, "Failed to get prefix preferred lifetime: %m");
802 /* The preferred lifetime is never greater than the valid lifetime */
803 if (lifetime_preferred
> lifetime_valid
)
806 r
= sd_ndisc_router_prefix_get_address(rt
, &addr
);
808 return log_link_error_errno(link
, r
, "Failed to get prefix address: %m");
810 r
= ndisc_router_generate_addresses(link
, &addr
, prefixlen
, &addresses
);
814 SET_FOREACH(a
, addresses
) {
815 _cleanup_(address_freep
) Address
*address
= NULL
;
818 r
= address_new(&address
);
822 address
->family
= AF_INET6
;
823 address
->in_addr
.in6
= *a
;
824 address
->prefixlen
= prefixlen
;
825 address
->flags
= IFA_F_NOPREFIXROUTE
|IFA_F_MANAGETEMPADDR
;
826 address
->cinfo
.ifa_valid
= lifetime_valid
;
827 address
->cinfo
.ifa_prefered
= lifetime_preferred
;
829 /* See RFC4862, section 5.5.3.e. But the following logic is deviated from RFC4862 by
830 * honoring all valid lifetimes to improve the reaction of SLAAC to renumbering events.
831 * See draft-ietf-6man-slaac-renum-02, section 4.2. */
832 r
= address_get(link
, address
, &e
);
834 /* If the address is already assigned, but not valid anymore, then refuse to
835 * update the address, and it will be removed. */
836 if (e
->cinfo
.ifa_valid
!= CACHE_INFO_INFINITY_LIFE_TIME
&&
837 usec_add(e
->cinfo
.tstamp
/ 100 * USEC_PER_SEC
,
838 e
->cinfo
.ifa_valid
* USEC_PER_SEC
) < time_now
)
842 r
= ndisc_request_address(TAKE_PTR(address
), link
, rt
);
844 return log_link_error_errno(link
, r
, "Could not request SLAAC address: %m");
850 static int ndisc_router_process_onlink_prefix(Link
*link
, sd_ndisc_router
*rt
) {
851 _cleanup_(route_freep
) Route
*route
= NULL
;
860 r
= sd_ndisc_router_get_timestamp(rt
, clock_boottime_or_monotonic(), &time_now
);
862 return log_link_error_errno(link
, r
, "Failed to get RA timestamp: %m");
864 r
= sd_ndisc_router_prefix_get_prefixlen(rt
, &prefixlen
);
866 return log_link_error_errno(link
, r
, "Failed to get prefix length: %m");
868 r
= sd_ndisc_router_prefix_get_valid_lifetime(rt
, &lifetime
);
870 return log_link_error_errno(link
, r
, "Failed to get prefix lifetime: %m");
872 r
= route_new(&route
);
876 route
->family
= AF_INET6
;
877 route
->flags
= RTM_F_PREFIX
;
878 route
->dst_prefixlen
= prefixlen
;
879 route
->lifetime
= usec_add(time_now
, lifetime
* USEC_PER_SEC
);
881 r
= sd_ndisc_router_prefix_get_address(rt
, &route
->dst
.in6
);
883 return log_link_error_errno(link
, r
, "Failed to get prefix address: %m");
885 r
= ndisc_request_route(TAKE_PTR(route
), link
, rt
);
887 return log_link_error_errno(link
, r
, "Could not request prefix route: %m");;
892 static int ndisc_router_process_route(Link
*link
, sd_ndisc_router
*rt
) {
893 _cleanup_(route_freep
) Route
*route
= NULL
;
894 struct in6_addr gateway
, dst
;
896 unsigned preference
, prefixlen
;
902 r
= sd_ndisc_router_route_get_lifetime(rt
, &lifetime
);
904 return log_link_error_errno(link
, r
, "Failed to get route lifetime from RA: %m");
909 r
= sd_ndisc_router_route_get_address(rt
, &dst
);
911 return log_link_error_errno(link
, r
, "Failed to get route destination address: %m");
913 r
= sd_ndisc_router_route_get_prefixlen(rt
, &prefixlen
);
915 return log_link_error_errno(link
, r
, "Failed to get route prefix length: %m");
917 if (in6_prefix_is_filtered(&dst
, prefixlen
, link
->network
->ndisc_allow_listed_route_prefix
, link
->network
->ndisc_deny_listed_route_prefix
)) {
919 _cleanup_free_
char *buf
= NULL
;
921 (void) in6_addr_prefix_to_string(&dst
, prefixlen
, &buf
);
922 if (!set_isempty(link
->network
->ndisc_allow_listed_route_prefix
))
923 log_link_debug(link
, "Route prefix '%s' is not in allow list, ignoring", strna(buf
));
925 log_link_debug(link
, "Route prefix '%s' is in deny list, ignoring", strna(buf
));
930 r
= sd_ndisc_router_get_address(rt
, &gateway
);
932 return log_link_error_errno(link
, r
, "Failed to get gateway address from RA: %m");
934 if (link_get_ipv6_address(link
, &gateway
, NULL
) >= 0) {
936 _cleanup_free_
char *buf
= NULL
;
938 (void) in6_addr_to_string(&gateway
, &buf
);
939 log_link_debug(link
, "Advertised route gateway %s is local to the link, ignoring route", strna(buf
));
944 r
= sd_ndisc_router_route_get_preference(rt
, &preference
);
946 return log_link_error_errno(link
, r
, "Failed to get default router preference from RA: %m");
948 r
= sd_ndisc_router_get_timestamp(rt
, clock_boottime_or_monotonic(), &time_now
);
950 return log_link_error_errno(link
, r
, "Failed to get RA timestamp: %m");
952 r
= route_new(&route
);
956 route
->family
= AF_INET6
;
957 route
->pref
= preference
;
958 route
->gw
.in6
= gateway
;
959 route
->gw_family
= AF_INET6
;
960 route
->dst
.in6
= dst
;
961 route
->dst_prefixlen
= prefixlen
;
962 route
->lifetime
= usec_add(time_now
, lifetime
* USEC_PER_SEC
);
964 r
= ndisc_request_route(TAKE_PTR(route
), link
, rt
);
966 return log_link_error_errno(link
, r
, "Could not request additional route: %m");
971 static void ndisc_rdnss_hash_func(const NDiscRDNSS
*x
, struct siphash
*state
) {
972 siphash24_compress(&x
->address
, sizeof(x
->address
), state
);
975 static int ndisc_rdnss_compare_func(const NDiscRDNSS
*a
, const NDiscRDNSS
*b
) {
976 return memcmp(&a
->address
, &b
->address
, sizeof(a
->address
));
979 DEFINE_PRIVATE_HASH_OPS_WITH_KEY_DESTRUCTOR(
980 ndisc_rdnss_hash_ops
,
982 ndisc_rdnss_hash_func
,
983 ndisc_rdnss_compare_func
,
986 static int ndisc_router_process_rdnss(Link
*link
, sd_ndisc_router
*rt
) {
988 const struct in6_addr
*a
;
989 struct in6_addr router
;
992 bool updated
= false;
998 r
= sd_ndisc_router_get_address(rt
, &router
);
1000 return log_link_error_errno(link
, r
, "Failed to get router address from RA: %m");
1002 r
= sd_ndisc_router_get_timestamp(rt
, clock_boottime_or_monotonic(), &time_now
);
1004 return log_link_error_errno(link
, r
, "Failed to get RA timestamp: %m");
1006 r
= sd_ndisc_router_rdnss_get_lifetime(rt
, &lifetime
);
1008 return log_link_error_errno(link
, r
, "Failed to get RDNSS lifetime: %m");
1010 n
= sd_ndisc_router_rdnss_get_addresses(rt
, &a
);
1012 return log_link_error_errno(link
, n
, "Failed to get RDNSS addresses: %m");
1014 SET_FOREACH(rdnss
, link
->ndisc_rdnss
)
1015 if (in6_addr_equal(&rdnss
->router
, &router
))
1016 rdnss
->marked
= true;
1021 if (n
>= (int) NDISC_RDNSS_MAX
) {
1022 log_link_warning(link
, "Too many RDNSS records per link. Only first %i records will be used.", NDISC_RDNSS_MAX
);
1023 n
= NDISC_RDNSS_MAX
;
1026 for (int j
= 0; j
< n
; j
++) {
1027 _cleanup_free_ NDiscRDNSS
*x
= NULL
;
1032 rdnss
= set_get(link
->ndisc_rdnss
, &d
);
1034 rdnss
->marked
= false;
1035 rdnss
->router
= router
;
1036 rdnss
->valid_until
= usec_add(time_now
, lifetime
* USEC_PER_SEC
);
1040 x
= new(NDiscRDNSS
, 1);
1047 .valid_until
= usec_add(time_now
, lifetime
* USEC_PER_SEC
),
1050 r
= set_ensure_consume(&link
->ndisc_rdnss
, &ndisc_rdnss_hash_ops
, TAKE_PTR(x
));
1064 static void ndisc_dnssl_hash_func(const NDiscDNSSL
*x
, struct siphash
*state
) {
1065 siphash24_compress_string(NDISC_DNSSL_DOMAIN(x
), state
);
1068 static int ndisc_dnssl_compare_func(const NDiscDNSSL
*a
, const NDiscDNSSL
*b
) {
1069 return strcmp(NDISC_DNSSL_DOMAIN(a
), NDISC_DNSSL_DOMAIN(b
));
1072 DEFINE_PRIVATE_HASH_OPS_WITH_KEY_DESTRUCTOR(
1073 ndisc_dnssl_hash_ops
,
1075 ndisc_dnssl_hash_func
,
1076 ndisc_dnssl_compare_func
,
1079 static int ndisc_router_process_dnssl(Link
*link
, sd_ndisc_router
*rt
) {
1080 _cleanup_strv_free_
char **l
= NULL
;
1081 struct in6_addr router
;
1085 bool updated
= false;
1092 r
= sd_ndisc_router_get_address(rt
, &router
);
1094 return log_link_error_errno(link
, r
, "Failed to get router address from RA: %m");
1096 r
= sd_ndisc_router_get_timestamp(rt
, clock_boottime_or_monotonic(), &time_now
);
1098 return log_link_error_errno(link
, r
, "Failed to get RA timestamp: %m");
1100 r
= sd_ndisc_router_dnssl_get_lifetime(rt
, &lifetime
);
1102 return log_link_error_errno(link
, r
, "Failed to get DNSSL lifetime: %m");
1104 r
= sd_ndisc_router_dnssl_get_domains(rt
, &l
);
1106 return log_link_error_errno(link
, r
, "Failed to get DNSSL addresses: %m");
1108 SET_FOREACH(dnssl
, link
->ndisc_dnssl
)
1109 if (in6_addr_equal(&dnssl
->router
, &router
))
1110 dnssl
->marked
= true;
1115 if (strv_length(l
) >= NDISC_DNSSL_MAX
) {
1116 log_link_warning(link
, "Too many DNSSL records per link. Only first %i records will be used.", NDISC_DNSSL_MAX
);
1117 STRV_FOREACH(j
, l
+ NDISC_DNSSL_MAX
)
1121 STRV_FOREACH(j
, l
) {
1122 _cleanup_free_ NDiscDNSSL
*s
= NULL
;
1124 s
= malloc0(ALIGN(sizeof(NDiscDNSSL
)) + strlen(*j
) + 1);
1128 strcpy(NDISC_DNSSL_DOMAIN(s
), *j
);
1130 dnssl
= set_get(link
->ndisc_dnssl
, s
);
1132 dnssl
->marked
= false;
1133 dnssl
->router
= router
;
1134 dnssl
->valid_until
= usec_add(time_now
, lifetime
* USEC_PER_SEC
);
1139 s
->valid_until
= usec_add(time_now
, lifetime
* USEC_PER_SEC
);
1141 r
= set_ensure_consume(&link
->ndisc_dnssl
, &ndisc_dnssl_hash_ops
, TAKE_PTR(s
));
1155 static int ndisc_router_process_options(Link
*link
, sd_ndisc_router
*rt
) {
1157 assert(link
->network
);
1160 for (int r
= sd_ndisc_router_option_rewind(rt
); ; r
= sd_ndisc_router_option_next(rt
)) {
1164 return log_link_error_errno(link
, r
, "Failed to iterate through options: %m");
1165 if (r
== 0) /* EOF */
1168 r
= sd_ndisc_router_option_get_type(rt
, &type
);
1170 return log_link_error_errno(link
, r
, "Failed to get RA option type: %m");
1174 case SD_NDISC_OPTION_PREFIX_INFORMATION
: {
1179 r
= sd_ndisc_router_prefix_get_address(rt
, &a
);
1181 return log_link_error_errno(link
, r
, "Failed to get prefix address: %m");
1183 r
= sd_ndisc_router_prefix_get_prefixlen(rt
, &prefixlen
);
1185 return log_link_error_errno(link
, r
, "Failed to get prefix length: %m");
1187 if (in6_prefix_is_filtered(&a
, prefixlen
, link
->network
->ndisc_allow_listed_prefix
, link
->network
->ndisc_deny_listed_prefix
)) {
1188 if (DEBUG_LOGGING
) {
1189 _cleanup_free_
char *b
= NULL
;
1191 (void) in6_addr_prefix_to_string(&a
, prefixlen
, &b
);
1192 if (!set_isempty(link
->network
->ndisc_allow_listed_prefix
))
1193 log_link_debug(link
, "Prefix '%s' is not in allow list, ignoring", strna(b
));
1195 log_link_debug(link
, "Prefix '%s' is in deny list, ignoring", strna(b
));
1200 r
= sd_ndisc_router_prefix_get_flags(rt
, &flags
);
1202 return log_link_error_errno(link
, r
, "Failed to get RA prefix flags: %m");
1204 if (link
->network
->ipv6_accept_ra_use_onlink_prefix
&&
1205 FLAGS_SET(flags
, ND_OPT_PI_FLAG_ONLINK
)) {
1206 r
= ndisc_router_process_onlink_prefix(link
, rt
);
1211 if (link
->network
->ipv6_accept_ra_use_autonomous_prefix
&&
1212 FLAGS_SET(flags
, ND_OPT_PI_FLAG_AUTO
)) {
1213 r
= ndisc_router_process_autonomous_prefix(link
, rt
);
1220 case SD_NDISC_OPTION_ROUTE_INFORMATION
:
1221 r
= ndisc_router_process_route(link
, rt
);
1226 case SD_NDISC_OPTION_RDNSS
:
1227 if (link
->network
->ipv6_accept_ra_use_dns
) {
1228 r
= ndisc_router_process_rdnss(link
, rt
);
1234 case SD_NDISC_OPTION_DNSSL
:
1235 if (link
->network
->ipv6_accept_ra_use_dns
) {
1236 r
= ndisc_router_process_dnssl(link
, rt
);
1245 static int ndisc_router_handler(Link
*link
, sd_ndisc_router
*rt
) {
1246 struct in6_addr router
;
1253 assert(link
->network
);
1254 assert(link
->manager
);
1257 r
= sd_ndisc_router_get_address(rt
, &router
);
1259 return log_link_error_errno(link
, r
, "Failed to get router address from RA: %m");
1261 if (in6_prefix_is_filtered(&router
, 128, link
->network
->ndisc_allow_listed_router
, link
->network
->ndisc_deny_listed_router
)) {
1262 if (DEBUG_LOGGING
) {
1263 _cleanup_free_
char *buf
= NULL
;
1265 (void) in6_addr_to_string(&router
, &buf
);
1266 if (!set_isempty(link
->network
->ndisc_allow_listed_router
))
1267 log_link_debug(link
, "Router '%s' is not in allow list, ignoring", strna(buf
));
1269 log_link_debug(link
, "Router '%s' is in deny list, ignoring", strna(buf
));
1274 SET_FOREACH(na
, link
->ndisc_addresses
)
1275 if (in6_addr_equal(&na
->router
, &router
))
1278 SET_FOREACH(nr
, link
->ndisc_routes
)
1279 if (in6_addr_equal(&nr
->router
, &router
))
1282 r
= sd_ndisc_router_get_flags(rt
, &flags
);
1284 return log_link_error_errno(link
, r
, "Failed to get RA flags: %m");
1286 if ((flags
& (ND_RA_FLAG_MANAGED
| ND_RA_FLAG_OTHER
) &&
1287 link
->network
->ipv6_accept_ra_start_dhcp6_client
!= IPV6_ACCEPT_RA_START_DHCP6_CLIENT_NO
) ||
1288 link
->network
->ipv6_accept_ra_start_dhcp6_client
== IPV6_ACCEPT_RA_START_DHCP6_CLIENT_ALWAYS
) {
1290 if (flags
& (ND_RA_FLAG_MANAGED
| ND_RA_FLAG_OTHER
))
1291 /* (re)start DHCPv6 client in stateful or stateless mode according to RA flags */
1292 r
= dhcp6_request_information(link
, !(flags
& ND_RA_FLAG_MANAGED
));
1294 /* When IPv6AcceptRA.DHCPv6Client=always, start dhcp6 client in managed mode
1295 * even if router does not have M or O flag. */
1296 r
= dhcp6_request_information(link
, false);
1297 if (r
< 0 && r
!= -EBUSY
)
1298 return log_link_error_errno(link
, r
, "Could not acquire DHCPv6 lease on NDisc request: %m");
1300 log_link_debug(link
, "Acquiring DHCPv6 lease on NDisc request");
1303 r
= ndisc_router_process_default(link
, rt
);
1306 r
= ndisc_router_process_options(link
, rt
);
1310 if (link
->ndisc_addresses_messages
== 0)
1311 link
->ndisc_addresses_configured
= true;
1313 log_link_debug(link
, "Setting SLAAC addresses.");
1315 if (link
->ndisc_routes_messages
== 0)
1316 link
->ndisc_routes_configured
= true;
1318 log_link_debug(link
, "Setting NDisc routes.");
1320 r
= ndisc_remove_old(link
);
1324 if (!link
->ndisc_addresses_configured
|| !link
->ndisc_routes_configured
)
1325 link_set_state(link
, LINK_STATE_CONFIGURING
);
1327 link_check_ready(link
);
1331 static void ndisc_handler(sd_ndisc
*nd
, sd_ndisc_event_t event
, sd_ndisc_router
*rt
, void *userdata
) {
1332 Link
*link
= userdata
;
1337 if (IN_SET(link
->state
, LINK_STATE_FAILED
, LINK_STATE_LINGER
))
1342 case SD_NDISC_EVENT_ROUTER
:
1343 r
= ndisc_router_handler(link
, rt
);
1345 link_enter_failed(link
);
1350 case SD_NDISC_EVENT_TIMEOUT
:
1351 log_link_debug(link
, "NDisc handler get timeout event");
1352 if (link
->ndisc_addresses_messages
== 0 && link
->ndisc_routes_messages
== 0) {
1353 link
->ndisc_addresses_configured
= true;
1354 link
->ndisc_routes_configured
= true;
1355 link_check_ready(link
);
1359 assert_not_reached();
1363 int ndisc_configure(Link
*link
) {
1368 if (!link_ipv6_accept_ra_enabled(link
))
1372 return -EBUSY
; /* Already configured. */
1374 r
= sd_ndisc_new(&link
->ndisc
);
1378 r
= sd_ndisc_attach_event(link
->ndisc
, link
->manager
->event
, 0);
1382 r
= sd_ndisc_set_mac(link
->ndisc
, &link
->hw_addr
.ether
);
1386 r
= sd_ndisc_set_ifindex(link
->ndisc
, link
->ifindex
);
1390 r
= sd_ndisc_set_callback(link
->ndisc
, ndisc_handler
, link
);
1397 int ndisc_start(Link
*link
) {
1400 if (!link
->ndisc
|| !link
->dhcp6_client
)
1403 if (!link_has_carrier(link
))
1406 log_link_debug(link
, "Discovering IPv6 routers");
1408 return sd_ndisc_start(link
->ndisc
);
1411 void ndisc_vacuum(Link
*link
) {
1418 /* Removes all RDNSS and DNSSL entries whose validity time has passed */
1420 time_now
= now(clock_boottime_or_monotonic());
1422 SET_FOREACH(r
, link
->ndisc_rdnss
)
1423 if (r
->valid_until
< time_now
)
1424 free(set_remove(link
->ndisc_rdnss
, r
));
1426 SET_FOREACH(d
, link
->ndisc_dnssl
)
1427 if (d
->valid_until
< time_now
)
1428 free(set_remove(link
->ndisc_dnssl
, d
));
1431 void ndisc_flush(Link
*link
) {
1434 /* Removes all RDNSS and DNSSL entries, without exception */
1436 link
->ndisc_rdnss
= set_free(link
->ndisc_rdnss
);
1437 link
->ndisc_dnssl
= set_free(link
->ndisc_dnssl
);
1440 static int ipv6token_new(IPv6Token
**ret
) {
1443 p
= new(IPv6Token
, 1);
1448 .address_generation_type
= IPV6_TOKEN_ADDRESS_GENERATION_NONE
,
1456 static void ipv6_token_hash_func(const IPv6Token
*p
, struct siphash
*state
) {
1457 siphash24_compress(&p
->address_generation_type
, sizeof(p
->address_generation_type
), state
);
1458 siphash24_compress(&p
->prefix
, sizeof(p
->prefix
), state
);
1461 static int ipv6_token_compare_func(const IPv6Token
*a
, const IPv6Token
*b
) {
1464 r
= CMP(a
->address_generation_type
, b
->address_generation_type
);
1468 return memcmp(&a
->prefix
, &b
->prefix
, sizeof(struct in6_addr
));
1471 DEFINE_HASH_OPS_WITH_KEY_DESTRUCTOR(
1472 ipv6_token_hash_ops
,
1474 ipv6_token_hash_func
,
1475 ipv6_token_compare_func
,
1478 int config_parse_address_generation_type(
1480 const char *filename
,
1482 const char *section
,
1483 unsigned section_line
,
1490 _cleanup_free_ IPv6Token
*token
= NULL
;
1491 union in_addr_union buffer
;
1492 Network
*network
= data
;
1501 if (isempty(rvalue
)) {
1502 network
->ipv6_tokens
= ordered_set_free(network
->ipv6_tokens
);
1506 r
= ipv6token_new(&token
);
1510 if ((p
= startswith(rvalue
, "prefixstable"))) {
1511 token
->address_generation_type
= IPV6_TOKEN_ADDRESS_GENERATION_PREFIXSTABLE
;
1514 else if (*p
== '\0')
1517 log_syntax(unit
, LOG_WARNING
, filename
, line
, 0,
1518 "Invalid IPv6 token mode in %s=, ignoring assignment: %s",
1523 token
->address_generation_type
= IPV6_TOKEN_ADDRESS_GENERATION_STATIC
;
1524 p
= startswith(rvalue
, "static:");
1530 r
= in_addr_from_string(AF_INET6
, p
, &buffer
);
1532 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
1533 "Failed to parse IP address in %s=, ignoring assignment: %s",
1537 if (token
->address_generation_type
== IPV6_TOKEN_ADDRESS_GENERATION_STATIC
&&
1538 in_addr_is_null(AF_INET6
, &buffer
)) {
1539 log_syntax(unit
, LOG_WARNING
, filename
, line
, 0,
1540 "IPv6 address in %s= cannot be the ANY address, ignoring assignment: %s",
1544 token
->prefix
= buffer
.in6
;
1547 r
= ordered_set_ensure_put(&network
->ipv6_tokens
, &ipv6_token_hash_ops
, token
);
1551 log_syntax(unit
, LOG_DEBUG
, filename
, line
, r
,
1552 "IPv6 token '%s' is duplicated, ignoring: %m", rvalue
);
1554 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
1555 "Failed to store IPv6 token '%s', ignoring: %m", rvalue
);
1562 DEFINE_CONFIG_PARSE_ENUM(config_parse_ipv6_accept_ra_use_domains
, dhcp_use_domains
, DHCPUseDomains
,
1563 "Failed to parse UseDomains= setting");
1564 DEFINE_CONFIG_PARSE_ENUM(config_parse_ipv6_accept_ra_start_dhcp6_client
, ipv6_accept_ra_start_dhcp6_client
, IPv6AcceptRAStartDHCP6Client
,
1565 "Failed to parse DHCPv6Client= setting");
1566 static const char* const ipv6_accept_ra_start_dhcp6_client_table
[_IPV6_ACCEPT_RA_START_DHCP6_CLIENT_MAX
] = {
1567 [IPV6_ACCEPT_RA_START_DHCP6_CLIENT_NO
] = "no",
1568 [IPV6_ACCEPT_RA_START_DHCP6_CLIENT_ALWAYS
] = "always",
1569 [IPV6_ACCEPT_RA_START_DHCP6_CLIENT_YES
] = "yes",
1572 DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(ipv6_accept_ra_start_dhcp6_client
, IPv6AcceptRAStartDHCP6Client
, IPV6_ACCEPT_RA_START_DHCP6_CLIENT_YES
);