1 /* SPDX-License-Identifier: LGPL-2.1+ */
3 Copyright © 2014 Intel Corporation. All rights reserved.
6 #include <netinet/icmp6.h>
11 #include "missing_network.h"
12 #include "networkd-dhcp6.h"
13 #include "networkd-manager.h"
14 #include "networkd-ndisc.h"
15 #include "networkd-route.h"
16 #include "string-table.h"
17 #include "string-util.h"
20 #define NDISC_DNSSL_MAX 64U
21 #define NDISC_RDNSS_MAX 64U
22 #define NDISC_PREFIX_LFT_MIN 7200U
24 #define DAD_CONFLICTS_IDGEN_RETRIES_RFC7217 3
26 /* https://tools.ietf.org/html/rfc5453 */
27 /* https://www.iana.org/assignments/ipv6-interface-ids/ipv6-interface-ids.xml */
29 #define SUBNET_ROUTER_ANYCAST_ADDRESS_RFC4291 ((struct in6_addr) { .s6_addr = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } })
30 #define SUBNET_ROUTER_ANYCAST_PREFIXLEN 8
31 #define RESERVED_IPV6_INTERFACE_IDENTIFIERS_ADDRESS_RFC4291 ((struct in6_addr) { .s6_addr = { 0x02, 0x00, 0x5E, 0xFF, 0xFE } })
32 #define RESERVED_IPV6_INTERFACE_IDENTIFIERS_PREFIXLEN 5
33 #define RESERVED_SUBNET_ANYCAST_ADDRESSES_RFC4291 ((struct in6_addr) { .s6_addr = { 0xFD, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF } })
34 #define RESERVED_SUBNET_ANYCAST_PREFIXLEN 7
36 #define NDISC_APP_ID SD_ID128_MAKE(13,ac,81,a7,d5,3f,49,78,92,79,5d,0c,29,3a,bc,7e)
38 static int ndisc_remove_old(Link
*link
, bool force
);
40 static int ndisc_address_callback(Address
*address
) {
45 assert(address
->link
);
47 /* Make this called only once */
48 SET_FOREACH(a
, address
->link
->ndisc_addresses
, i
)
51 return ndisc_remove_old(address
->link
, true);
54 static int ndisc_remove_old(Link
*link
, bool force
) {
63 bool set_callback
= !set_isempty(link
->ndisc_addresses
);
65 if (!link
->ndisc_addresses_configured
|| !link
->ndisc_routes_configured
)
68 SET_FOREACH(address
, link
->ndisc_addresses
, i
)
69 if (address_is_ready(address
)) {
75 SET_FOREACH(address
, link
->ndisc_addresses
, i
)
76 address
->callback
= ndisc_address_callback
;
81 if (!set_isempty(link
->ndisc_addresses_old
) || !set_isempty(link
->ndisc_routes_old
))
82 log_link_debug(link
, "Removing old NDisc addresses and routes.");
86 SET_FOREACH(address
, link
->ndisc_addresses_old
, i
) {
87 k
= address_remove(address
, link
, NULL
);
92 SET_FOREACH(route
, link
->ndisc_routes_old
, i
) {
93 k
= route_remove(route
, link
, NULL
);
101 static int ndisc_route_handler(sd_netlink
*rtnl
, sd_netlink_message
*m
, Link
*link
) {
105 assert(link
->ndisc_routes_messages
> 0);
107 link
->ndisc_routes_messages
--;
109 if (IN_SET(link
->state
, LINK_STATE_FAILED
, LINK_STATE_LINGER
))
112 r
= sd_netlink_message_get_errno(m
);
113 if (r
< 0 && r
!= -EEXIST
) {
114 log_link_message_error_errno(link
, m
, r
, "Could not set NDisc route");
115 link_enter_failed(link
);
119 if (link
->ndisc_routes_messages
== 0) {
120 log_link_debug(link
, "NDisc routes set.");
121 link
->ndisc_routes_configured
= true;
123 r
= ndisc_remove_old(link
, false);
125 link_enter_failed(link
);
129 link_check_ready(link
);
135 static int ndisc_address_handler(sd_netlink
*rtnl
, sd_netlink_message
*m
, Link
*link
) {
139 assert(link
->ndisc_addresses_messages
> 0);
141 link
->ndisc_addresses_messages
--;
143 if (IN_SET(link
->state
, LINK_STATE_FAILED
, LINK_STATE_LINGER
))
146 r
= sd_netlink_message_get_errno(m
);
147 if (r
< 0 && r
!= -EEXIST
) {
148 log_link_message_error_errno(link
, m
, r
, "Could not set NDisc address");
149 link_enter_failed(link
);
152 (void) manager_rtnl_process_address(rtnl
, m
, link
->manager
);
154 if (link
->ndisc_addresses_messages
== 0) {
155 log_link_debug(link
, "NDisc SLAAC addresses set.");
156 link
->ndisc_addresses_configured
= true;
158 r
= ndisc_remove_old(link
, false);
160 link_enter_failed(link
);
164 r
= link_request_set_routes(link
);
166 link_enter_failed(link
);
174 static int ndisc_route_configure(Route
*route
, Link
*link
) {
181 r
= route_configure(route
, link
, ndisc_route_handler
, &ret
);
183 return log_link_error_errno(link
, r
, "Failed to set NDisc route: %m");
185 link
->ndisc_routes_messages
++;
187 r
= set_ensure_put(&link
->ndisc_routes
, &route_hash_ops
, ret
);
189 return log_link_error_errno(link
, r
, "Failed to store NDisc route: %m");
191 (void) set_remove(link
->ndisc_routes_old
, ret
);
196 static int ndisc_address_configure(Address
*address
, Link
*link
) {
203 r
= address_configure(address
, link
, ndisc_address_handler
, true, &ret
);
205 return log_link_error_errno(link
, r
, "Failed to set NDisc SLAAC address: %m");
207 link
->ndisc_addresses_messages
++;
209 r
= set_ensure_put(&link
->ndisc_addresses
, &address_hash_ops
, ret
);
211 return log_link_error_errno(link
, r
, "Failed to store NDisc SLAAC address: %m");
213 (void) set_remove(link
->ndisc_addresses_old
, ret
);
218 static int ndisc_router_process_default(Link
*link
, sd_ndisc_router
*rt
) {
219 _cleanup_(route_freep
) Route
*route
= NULL
;
220 union in_addr_union gateway
;
230 r
= sd_ndisc_router_get_lifetime(rt
, &lifetime
);
232 return log_link_error_errno(link
, r
, "Failed to get gateway lifetime from RA: %m");
234 if (lifetime
== 0) /* not a default router */
237 r
= sd_ndisc_router_get_address(rt
, &gateway
.in6
);
239 return log_link_error_errno(link
, r
, "Failed to get gateway address from RA: %m");
241 if (address_exists(link
, AF_INET6
, &gateway
)) {
243 _cleanup_free_
char *buffer
= NULL
;
245 (void) in_addr_to_string(AF_INET6
, &gateway
, &buffer
);
246 log_link_debug(link
, "No NDisc route added, gateway %s matches local address",
252 r
= sd_ndisc_router_get_preference(rt
, &preference
);
254 return log_link_error_errno(link
, r
, "Failed to get default router preference from RA: %m");
256 r
= sd_ndisc_router_get_timestamp(rt
, clock_boottime_or_monotonic(), &time_now
);
258 return log_link_error_errno(link
, r
, "Failed to get RA timestamp: %m");
260 r
= sd_ndisc_router_get_mtu(rt
, &mtu
);
264 return log_link_error_errno(link
, r
, "Failed to get default router MTU from RA: %m");
266 r
= route_new(&route
);
270 route
->family
= AF_INET6
;
271 route
->table
= link_get_ipv6_accept_ra_route_table(link
);
272 route
->priority
= link
->network
->dhcp6_route_metric
;
273 route
->protocol
= RTPROT_RA
;
274 route
->pref
= preference
;
276 route
->lifetime
= time_now
+ lifetime
* USEC_PER_SEC
;
279 r
= ndisc_route_configure(route
, link
);
281 return log_link_error_errno(link
, r
, "Could not set default route: %m");
284 LIST_FOREACH(routes
, route_gw
, link
->network
->static_routes
) {
285 if (!route_gw
->gateway_from_dhcp
)
288 if (route_gw
->family
!= AF_INET6
)
291 route_gw
->gw
= gateway
;
293 r
= ndisc_route_configure(route_gw
, link
);
295 return log_link_error_errno(link
, r
, "Could not set gateway: %m");
301 static bool stableprivate_address_is_valid(const struct in6_addr
*addr
) {
304 /* According to rfc4291, generated address should not be in the following ranges. */
306 if (memcmp(addr
, &SUBNET_ROUTER_ANYCAST_ADDRESS_RFC4291
, SUBNET_ROUTER_ANYCAST_PREFIXLEN
) == 0)
309 if (memcmp(addr
, &RESERVED_IPV6_INTERFACE_IDENTIFIERS_ADDRESS_RFC4291
, RESERVED_IPV6_INTERFACE_IDENTIFIERS_PREFIXLEN
) == 0)
312 if (memcmp(addr
, &RESERVED_SUBNET_ANYCAST_ADDRESSES_RFC4291
, RESERVED_SUBNET_ANYCAST_PREFIXLEN
) == 0)
318 static int make_stableprivate_address(Link
*link
, const struct in6_addr
*prefix
, uint8_t prefix_len
, uint8_t dad_counter
, struct in6_addr
**ret
) {
319 _cleanup_free_
struct in6_addr
*addr
= NULL
;
320 sd_id128_t secret_key
;
321 struct siphash state
;
326 /* According to rfc7217 section 5.1
327 * RID = F(Prefix, Net_Iface, Network_ID, DAD_Counter, secret_key) */
329 r
= sd_id128_get_machine_app_specific(NDISC_APP_ID
, &secret_key
);
331 return log_error_errno(r
, "Failed to generate key: %m");
333 siphash24_init(&state
, secret_key
.bytes
);
335 l
= MAX(DIV_ROUND_UP(prefix_len
, 8), 8);
336 siphash24_compress(prefix
, l
, &state
);
337 siphash24_compress_string(link
->ifname
, &state
);
338 siphash24_compress(&link
->mac
, sizeof(struct ether_addr
), &state
);
339 siphash24_compress(&dad_counter
, sizeof(uint8_t), &state
);
341 rid
= htole64(siphash24_finalize(&state
));
343 addr
= new(struct in6_addr
, 1);
347 memcpy(addr
->s6_addr
, prefix
->s6_addr
, l
);
348 memcpy(addr
->s6_addr
+ l
, &rid
, 16 - l
);
350 if (!stableprivate_address_is_valid(addr
)) {
355 *ret
= TAKE_PTR(addr
);
359 static int ndisc_router_generate_addresses(Link
*link
, struct in6_addr
*address
, uint8_t prefixlen
, Set
**ret
) {
360 _cleanup_set_free_free_ Set
*addresses
= NULL
;
369 addresses
= set_new(&in6_addr_hash_ops
);
373 ORDERED_SET_FOREACH(j
, link
->network
->ipv6_tokens
, i
) {
374 _cleanup_free_
struct in6_addr
*new_address
= NULL
;
376 if (j
->address_generation_type
== IPV6_TOKEN_ADDRESS_GENERATION_PREFIXSTABLE
377 && IN6_ARE_ADDR_EQUAL(&j
->prefix
, address
)) {
378 /* While this loop uses dad_counter and a retry limit as specified in RFC 7217, the loop
379 does not actually attempt Duplicate Address Detection; the counter will be incremented
380 only when the address generation algorithm produces an invalid address, and the loop
381 may exit with an address which ends up being unusable due to duplication on the link.
383 for (; j
->dad_counter
< DAD_CONFLICTS_IDGEN_RETRIES_RFC7217
; j
->dad_counter
++) {
384 r
= make_stableprivate_address(link
, &j
->prefix
, prefixlen
, j
->dad_counter
, &new_address
);
390 } else if (j
->address_generation_type
== IPV6_TOKEN_ADDRESS_GENERATION_STATIC
) {
391 new_address
= new(struct in6_addr
, 1);
395 memcpy(new_address
->s6_addr
, address
->s6_addr
, 8);
396 memcpy(new_address
->s6_addr
+ 8, j
->prefix
.s6_addr
+ 8, 8);
400 r
= set_put(addresses
, new_address
);
402 return log_link_error_errno(link
, r
, "Failed to store SLAAC address: %m");
404 log_link_debug_errno(link
, r
, "Generated SLAAC address is duplicated, ignoring.");
406 TAKE_PTR(new_address
);
410 /* fall back to EUI-64 if no tokens provided addresses */
411 if (set_isempty(addresses
)) {
412 _cleanup_free_
struct in6_addr
*new_address
= NULL
;
414 new_address
= newdup(struct in6_addr
, address
, 1);
418 r
= generate_ipv6_eui_64_address(link
, new_address
);
420 return log_link_error_errno(link
, r
, "Failed to generate EUI64 address: %m");
422 r
= set_put(addresses
, new_address
);
424 return log_link_error_errno(link
, r
, "Failed to store SLAAC address: %m");
426 TAKE_PTR(new_address
);
429 *ret
= TAKE_PTR(addresses
);
434 static int ndisc_router_process_autonomous_prefix(Link
*link
, sd_ndisc_router
*rt
) {
435 uint32_t lifetime_valid
, lifetime_preferred
, lifetime_remaining
;
436 _cleanup_set_free_free_ Set
*addresses
= NULL
;
437 _cleanup_(address_freep
) Address
*address
= NULL
;
438 struct in6_addr addr
, *a
;
447 r
= sd_ndisc_router_get_timestamp(rt
, clock_boottime_or_monotonic(), &time_now
);
449 return log_link_error_errno(link
, r
, "Failed to get RA timestamp: %m");
451 r
= sd_ndisc_router_prefix_get_prefixlen(rt
, &prefixlen
);
453 return log_link_error_errno(link
, r
, "Failed to get prefix length: %m");
455 r
= sd_ndisc_router_prefix_get_valid_lifetime(rt
, &lifetime_valid
);
457 return log_link_error_errno(link
, r
, "Failed to get prefix valid lifetime: %m");
459 r
= sd_ndisc_router_prefix_get_preferred_lifetime(rt
, &lifetime_preferred
);
461 return log_link_error_errno(link
, r
, "Failed to get prefix preferred lifetime: %m");
463 /* The preferred lifetime is never greater than the valid lifetime */
464 if (lifetime_preferred
> lifetime_valid
)
467 r
= sd_ndisc_router_prefix_get_address(rt
, &addr
);
469 return log_link_error_errno(link
, r
, "Failed to get prefix address: %m");
471 r
= ndisc_router_generate_addresses(link
, &addr
, prefixlen
, &addresses
);
475 r
= address_new(&address
);
479 address
->family
= AF_INET6
;
480 address
->prefixlen
= prefixlen
;
481 address
->flags
= IFA_F_NOPREFIXROUTE
|IFA_F_MANAGETEMPADDR
;
482 address
->cinfo
.ifa_prefered
= lifetime_preferred
;
484 SET_FOREACH(a
, addresses
, i
) {
485 Address
*existing_address
;
487 /* see RFC4862 section 5.5.3.e */
488 r
= address_get(link
, AF_INET6
, (union in_addr_union
*) a
, prefixlen
, &existing_address
);
490 lifetime_remaining
= existing_address
->cinfo
.tstamp
/ 100 + existing_address
->cinfo
.ifa_valid
- time_now
/ USEC_PER_SEC
;
491 if (lifetime_valid
> NDISC_PREFIX_LFT_MIN
|| lifetime_valid
> lifetime_remaining
)
492 address
->cinfo
.ifa_valid
= lifetime_valid
;
493 else if (lifetime_remaining
<= NDISC_PREFIX_LFT_MIN
)
494 address
->cinfo
.ifa_valid
= lifetime_remaining
;
496 address
->cinfo
.ifa_valid
= NDISC_PREFIX_LFT_MIN
;
497 } else if (lifetime_valid
> 0)
498 address
->cinfo
.ifa_valid
= lifetime_valid
;
500 continue; /* see RFC4862 section 5.5.3.d */
502 if (address
->cinfo
.ifa_valid
== 0)
505 address
->in_addr
.in6
= *a
;
507 r
= ndisc_address_configure(address
, link
);
509 return log_link_error_errno(link
, r
, "Could not set SLAAC address: %m");
515 static int ndisc_router_process_onlink_prefix(Link
*link
, sd_ndisc_router
*rt
) {
516 _cleanup_(route_freep
) Route
*route
= NULL
;
525 r
= sd_ndisc_router_get_timestamp(rt
, clock_boottime_or_monotonic(), &time_now
);
527 return log_link_error_errno(link
, r
, "Failed to get RA timestamp: %m");
529 r
= sd_ndisc_router_prefix_get_prefixlen(rt
, &prefixlen
);
531 return log_link_error_errno(link
, r
, "Failed to get prefix length: %m");
533 r
= sd_ndisc_router_prefix_get_valid_lifetime(rt
, &lifetime
);
535 return log_link_error_errno(link
, r
, "Failed to get prefix lifetime: %m");
537 r
= route_new(&route
);
541 route
->family
= AF_INET6
;
542 route
->table
= link_get_ipv6_accept_ra_route_table(link
);
543 route
->priority
= link
->network
->dhcp6_route_metric
;
544 route
->protocol
= RTPROT_RA
;
545 route
->flags
= RTM_F_PREFIX
;
546 route
->dst_prefixlen
= prefixlen
;
547 route
->lifetime
= time_now
+ lifetime
* USEC_PER_SEC
;
549 r
= sd_ndisc_router_prefix_get_address(rt
, &route
->dst
.in6
);
551 return log_link_error_errno(link
, r
, "Failed to get prefix address: %m");
553 r
= ndisc_route_configure(route
, link
);
555 return log_link_error_errno(link
, r
, "Could not set prefix route: %m");;
560 static int ndisc_router_process_route(Link
*link
, sd_ndisc_router
*rt
) {
561 _cleanup_(route_freep
) Route
*route
= NULL
;
562 struct in6_addr gateway
;
564 unsigned preference
, prefixlen
;
570 r
= sd_ndisc_router_route_get_lifetime(rt
, &lifetime
);
572 return log_link_error_errno(link
, r
, "Failed to get gateway lifetime from RA: %m");
577 r
= sd_ndisc_router_get_address(rt
, &gateway
);
579 return log_link_error_errno(link
, r
, "Failed to get gateway address from RA: %m");
581 r
= sd_ndisc_router_route_get_prefixlen(rt
, &prefixlen
);
583 return log_link_error_errno(link
, r
, "Failed to get route prefix length: %m");
585 r
= sd_ndisc_router_route_get_preference(rt
, &preference
);
587 return log_link_error_errno(link
, r
, "Failed to get default router preference from RA: %m");
589 r
= sd_ndisc_router_get_timestamp(rt
, clock_boottime_or_monotonic(), &time_now
);
591 return log_link_error_errno(link
, r
, "Failed to get RA timestamp: %m");
593 r
= route_new(&route
);
597 route
->family
= AF_INET6
;
598 route
->table
= link_get_ipv6_accept_ra_route_table(link
);
599 route
->priority
= link
->network
->dhcp6_route_metric
;
600 route
->protocol
= RTPROT_RA
;
601 route
->pref
= preference
;
602 route
->gw
.in6
= gateway
;
603 route
->dst_prefixlen
= prefixlen
;
604 route
->lifetime
= time_now
+ lifetime
* USEC_PER_SEC
;
606 r
= sd_ndisc_router_route_get_address(rt
, &route
->dst
.in6
);
608 return log_link_error_errno(link
, r
, "Failed to get route address: %m");
610 r
= ndisc_route_configure(route
, link
);
612 return log_link_error_errno(link
, r
, "Could not set additional route: %m");
617 static void ndisc_rdnss_hash_func(const NDiscRDNSS
*x
, struct siphash
*state
) {
618 siphash24_compress(&x
->address
, sizeof(x
->address
), state
);
621 static int ndisc_rdnss_compare_func(const NDiscRDNSS
*a
, const NDiscRDNSS
*b
) {
622 return memcmp(&a
->address
, &b
->address
, sizeof(a
->address
));
625 DEFINE_PRIVATE_HASH_OPS(ndisc_rdnss_hash_ops
, NDiscRDNSS
, ndisc_rdnss_hash_func
, ndisc_rdnss_compare_func
);
627 static int ndisc_router_process_rdnss(Link
*link
, sd_ndisc_router
*rt
) {
629 const struct in6_addr
*a
;
636 r
= sd_ndisc_router_get_timestamp(rt
, clock_boottime_or_monotonic(), &time_now
);
638 return log_link_error_errno(link
, r
, "Failed to get RA timestamp: %m");
640 r
= sd_ndisc_router_rdnss_get_lifetime(rt
, &lifetime
);
642 return log_link_error_errno(link
, r
, "Failed to get RDNSS lifetime: %m");
644 n
= sd_ndisc_router_rdnss_get_addresses(rt
, &a
);
646 return log_link_error_errno(link
, n
, "Failed to get RDNSS addresses: %m");
648 for (int i
= 0; i
< n
; i
++) {
649 _cleanup_free_ NDiscRDNSS
*x
= NULL
;
655 (void) set_remove(link
->ndisc_rdnss
, &d
);
660 y
= set_get(link
->ndisc_rdnss
, &d
);
662 y
->valid_until
= time_now
+ lifetime
* USEC_PER_SEC
;
668 if (set_size(link
->ndisc_rdnss
) >= NDISC_RDNSS_MAX
) {
669 log_link_warning(link
, "Too many RDNSS records per link, ignoring.");
673 x
= new(NDiscRDNSS
, 1);
679 .valid_until
= time_now
+ lifetime
* USEC_PER_SEC
,
682 r
= set_ensure_consume(&link
->ndisc_rdnss
, &ndisc_rdnss_hash_ops
, TAKE_PTR(x
));
693 static void ndisc_dnssl_hash_func(const NDiscDNSSL
*x
, struct siphash
*state
) {
694 siphash24_compress_string(NDISC_DNSSL_DOMAIN(x
), state
);
697 static int ndisc_dnssl_compare_func(const NDiscDNSSL
*a
, const NDiscDNSSL
*b
) {
698 return strcmp(NDISC_DNSSL_DOMAIN(a
), NDISC_DNSSL_DOMAIN(b
));
701 DEFINE_PRIVATE_HASH_OPS(ndisc_dnssl_hash_ops
, NDiscDNSSL
, ndisc_dnssl_hash_func
, ndisc_dnssl_compare_func
);
703 static int ndisc_router_process_dnssl(Link
*link
, sd_ndisc_router
*rt
) {
704 _cleanup_strv_free_
char **l
= NULL
;
713 r
= sd_ndisc_router_get_timestamp(rt
, clock_boottime_or_monotonic(), &time_now
);
715 return log_link_error_errno(link
, r
, "Failed to get RA timestamp: %m");
717 r
= sd_ndisc_router_dnssl_get_lifetime(rt
, &lifetime
);
719 return log_link_error_errno(link
, r
, "Failed to get DNSSL lifetime: %m");
721 r
= sd_ndisc_router_dnssl_get_domains(rt
, &l
);
723 return log_link_error_errno(link
, r
, "Failed to get DNSSL addresses: %m");
726 _cleanup_free_ NDiscDNSSL
*s
= NULL
;
729 s
= malloc0(ALIGN(sizeof(NDiscDNSSL
)) + strlen(*i
) + 1);
733 strcpy(NDISC_DNSSL_DOMAIN(s
), *i
);
736 (void) set_remove(link
->ndisc_dnssl
, s
);
741 x
= set_get(link
->ndisc_dnssl
, s
);
743 x
->valid_until
= time_now
+ lifetime
* USEC_PER_SEC
;
749 if (set_size(link
->ndisc_dnssl
) >= NDISC_DNSSL_MAX
) {
750 log_link_warning(link
, "Too many DNSSL records per link, ignoring.");
754 s
->valid_until
= time_now
+ lifetime
* USEC_PER_SEC
;
756 r
= set_ensure_consume(&link
->ndisc_dnssl
, &ndisc_dnssl_hash_ops
, TAKE_PTR(s
));
767 static int ndisc_router_process_options(Link
*link
, sd_ndisc_router
*rt
) {
769 assert(link
->network
);
772 for (int r
= sd_ndisc_router_option_rewind(rt
); ; r
= sd_ndisc_router_option_next(rt
)) {
776 return log_link_error_errno(link
, r
, "Failed to iterate through options: %m");
777 if (r
== 0) /* EOF */
780 r
= sd_ndisc_router_option_get_type(rt
, &type
);
782 return log_link_error_errno(link
, r
, "Failed to get RA option type: %m");
786 case SD_NDISC_OPTION_PREFIX_INFORMATION
: {
787 union in_addr_union a
;
790 r
= sd_ndisc_router_prefix_get_address(rt
, &a
.in6
);
792 return log_link_error_errno(link
, r
, "Failed to get prefix address: %m");
794 if (set_contains(link
->network
->ndisc_deny_listed_prefix
, &a
.in6
)) {
796 _cleanup_free_
char *b
= NULL
;
798 (void) in_addr_to_string(AF_INET6
, &a
, &b
);
799 log_link_debug(link
, "Prefix '%s' is deny-listed, ignoring", strna(b
));
804 r
= sd_ndisc_router_prefix_get_flags(rt
, &flags
);
806 return log_link_error_errno(link
, r
, "Failed to get RA prefix flags: %m");
808 if (link
->network
->ipv6_accept_ra_use_onlink_prefix
&&
809 FLAGS_SET(flags
, ND_OPT_PI_FLAG_ONLINK
)) {
810 r
= ndisc_router_process_onlink_prefix(link
, rt
);
815 if (link
->network
->ipv6_accept_ra_use_autonomous_prefix
&&
816 FLAGS_SET(flags
, ND_OPT_PI_FLAG_AUTO
)) {
817 r
= ndisc_router_process_autonomous_prefix(link
, rt
);
824 case SD_NDISC_OPTION_ROUTE_INFORMATION
:
825 r
= ndisc_router_process_route(link
, rt
);
830 case SD_NDISC_OPTION_RDNSS
:
831 if (link
->network
->ipv6_accept_ra_use_dns
) {
832 r
= ndisc_router_process_rdnss(link
, rt
);
838 case SD_NDISC_OPTION_DNSSL
:
839 if (link
->network
->ipv6_accept_ra_use_dns
) {
840 r
= ndisc_router_process_dnssl(link
, rt
);
849 static int ndisc_router_handler(Link
*link
, sd_ndisc_router
*rt
) {
856 assert(link
->network
);
857 assert(link
->manager
);
860 link
->ndisc_addresses_configured
= false;
861 link
->ndisc_routes_configured
= false;
865 while ((address
= set_steal_first(link
->ndisc_addresses
))) {
866 r
= set_ensure_put(&link
->ndisc_addresses_old
, &address_hash_ops
, address
);
868 return log_link_error_errno(link
, r
, "Failed to store old NDisc SLAAC address: %m");
871 while ((route
= set_steal_first(link
->ndisc_routes
))) {
872 r
= set_ensure_put(&link
->ndisc_routes_old
, &route_hash_ops
, route
);
874 return log_link_error_errno(link
, r
, "Failed to store old NDisc route: %m");
877 r
= sd_ndisc_router_get_flags(rt
, &flags
);
879 return log_link_error_errno(link
, r
, "Failed to get RA flags: %m");
881 if ((flags
& (ND_RA_FLAG_MANAGED
| ND_RA_FLAG_OTHER
) && link
->network
->ipv6_accept_ra_start_dhcp6_client
)) {
883 if (link
->network
->ipv6_accept_ra_start_dhcp6_client
== IPV6_ACCEPT_RA_START_DHCP6_CLIENT_ALWAYS
)
884 r
= dhcp6_request_address(link
, false);
886 /* (re)start DHCPv6 client in stateful or stateless mode according to RA flags */
887 r
= dhcp6_request_address(link
, !(flags
& ND_RA_FLAG_MANAGED
));
888 if (r
< 0 && r
!= -EBUSY
)
889 return log_link_error_errno(link
, r
, "Could not acquire DHCPv6 lease on NDisc request: %m");
891 log_link_debug(link
, "Acquiring DHCPv6 lease on NDisc request");
894 r
= ndisc_router_process_default(link
, rt
);
897 r
= ndisc_router_process_options(link
, rt
);
901 if (link
->ndisc_addresses_messages
== 0)
902 link
->ndisc_addresses_configured
= true;
904 log_link_debug(link
, "Setting SLAAC addresses.");
906 /* address_handler calls link_request_set_routes() and link_request_set_nexthop().
907 * Before they are called, the related flags must be cleared. Otherwise, the link
908 * becomes configured state before routes are configured. */
909 link
->static_routes_configured
= false;
910 link
->static_nexthops_configured
= false;
913 if (link
->ndisc_routes_messages
== 0)
914 link
->ndisc_routes_configured
= true;
916 log_link_debug(link
, "Setting NDisc routes.");
918 r
= ndisc_remove_old(link
, false);
922 if (link
->ndisc_addresses_configured
&& link
->ndisc_routes_configured
)
923 link_check_ready(link
);
925 link_set_state(link
, LINK_STATE_CONFIGURING
);
930 static void ndisc_handler(sd_ndisc
*nd
, sd_ndisc_event event
, sd_ndisc_router
*rt
, void *userdata
) {
931 Link
*link
= userdata
;
936 if (IN_SET(link
->state
, LINK_STATE_FAILED
, LINK_STATE_LINGER
))
941 case SD_NDISC_EVENT_ROUTER
:
942 r
= ndisc_router_handler(link
, rt
);
944 link_enter_failed(link
);
949 case SD_NDISC_EVENT_TIMEOUT
:
950 log_link_debug(link
, "NDisc handler get timeout event");
951 if (link
->ndisc_addresses_messages
== 0 && link
->ndisc_routes_messages
== 0) {
952 link
->ndisc_addresses_configured
= true;
953 link
->ndisc_routes_configured
= true;
954 link_check_ready(link
);
958 assert_not_reached("Unknown NDisc event");
962 int ndisc_configure(Link
*link
) {
967 r
= sd_ndisc_new(&link
->ndisc
);
971 r
= sd_ndisc_attach_event(link
->ndisc
, NULL
, 0);
975 r
= sd_ndisc_set_mac(link
->ndisc
, &link
->mac
);
979 r
= sd_ndisc_set_ifindex(link
->ndisc
, link
->ifindex
);
983 r
= sd_ndisc_set_callback(link
->ndisc
, ndisc_handler
, link
);
990 void ndisc_vacuum(Link
*link
) {
998 /* Removes all RDNSS and DNSSL entries whose validity time has passed */
1000 time_now
= now(clock_boottime_or_monotonic());
1002 SET_FOREACH(r
, link
->ndisc_rdnss
, i
)
1003 if (r
->valid_until
< time_now
) {
1004 free(set_remove(link
->ndisc_rdnss
, r
));
1008 SET_FOREACH(d
, link
->ndisc_dnssl
, i
)
1009 if (d
->valid_until
< time_now
) {
1010 free(set_remove(link
->ndisc_dnssl
, d
));
1015 void ndisc_flush(Link
*link
) {
1018 /* Removes all RDNSS and DNSSL entries, without exception */
1020 link
->ndisc_rdnss
= set_free_free(link
->ndisc_rdnss
);
1021 link
->ndisc_dnssl
= set_free_free(link
->ndisc_dnssl
);
1024 int ipv6token_new(IPv6Token
**ret
) {
1027 p
= new(IPv6Token
, 1);
1032 .address_generation_type
= IPV6_TOKEN_ADDRESS_GENERATION_NONE
,
1040 static void ipv6_token_hash_func(const IPv6Token
*p
, struct siphash
*state
) {
1041 siphash24_compress(&p
->address_generation_type
, sizeof(p
->address_generation_type
), state
);
1042 siphash24_compress(&p
->prefix
, sizeof(p
->prefix
), state
);
1045 static int ipv6_token_compare_func(const IPv6Token
*a
, const IPv6Token
*b
) {
1048 r
= CMP(a
->address_generation_type
, b
->address_generation_type
);
1052 return memcmp(&a
->prefix
, &b
->prefix
, sizeof(struct in6_addr
));
1055 DEFINE_HASH_OPS_WITH_KEY_DESTRUCTOR(
1056 ipv6_token_hash_ops
,
1058 ipv6_token_hash_func
,
1059 ipv6_token_compare_func
,
1062 int config_parse_ndisc_deny_listed_prefix(
1064 const char *filename
,
1066 const char *section
,
1067 unsigned section_line
,
1074 Network
*network
= data
;
1083 if (isempty(rvalue
)) {
1084 network
->ndisc_deny_listed_prefix
= set_free_free(network
->ndisc_deny_listed_prefix
);
1088 for (p
= rvalue
;;) {
1089 _cleanup_free_
char *n
= NULL
;
1090 _cleanup_free_
struct in6_addr
*a
= NULL
;
1091 union in_addr_union ip
;
1093 r
= extract_first_word(&p
, &n
, NULL
, 0);
1097 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
1098 "Failed to parse NDisc deny-listed prefix, ignoring assignment: %s",
1105 r
= in_addr_from_string(AF_INET6
, n
, &ip
);
1107 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
1108 "NDisc deny-listed prefix is invalid, ignoring assignment: %s", n
);
1112 if (set_contains(network
->ndisc_deny_listed_prefix
, &ip
.in6
))
1115 a
= newdup(struct in6_addr
, &ip
.in6
, 1);
1119 r
= set_ensure_consume(&network
->ndisc_deny_listed_prefix
, &in6_addr_hash_ops
, TAKE_PTR(a
));
1125 int config_parse_address_generation_type(
1127 const char *filename
,
1129 const char *section
,
1130 unsigned section_line
,
1137 _cleanup_free_ IPv6Token
*token
= NULL
;
1138 union in_addr_union buffer
;
1139 Network
*network
= data
;
1148 if (isempty(rvalue
)) {
1149 network
->ipv6_tokens
= ordered_set_free(network
->ipv6_tokens
);
1153 r
= ipv6token_new(&token
);
1157 if ((p
= startswith(rvalue
, "static:")))
1158 token
->address_generation_type
= IPV6_TOKEN_ADDRESS_GENERATION_STATIC
;
1159 else if ((p
= startswith(rvalue
, "prefixstable:")))
1160 token
->address_generation_type
= IPV6_TOKEN_ADDRESS_GENERATION_PREFIXSTABLE
;
1162 token
->address_generation_type
= IPV6_TOKEN_ADDRESS_GENERATION_STATIC
;
1166 r
= in_addr_from_string(AF_INET6
, p
, &buffer
);
1168 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
1169 "Failed to parse IPv6 %s, ignoring: %s", lvalue
, rvalue
);
1173 if (in_addr_is_null(AF_INET6
, &buffer
)) {
1174 log_syntax(unit
, LOG_WARNING
, filename
, line
, 0,
1175 "IPv6 %s cannot be the ANY address, ignoring: %s", lvalue
, rvalue
);
1179 token
->prefix
= buffer
.in6
;
1181 r
= ordered_set_ensure_allocated(&network
->ipv6_tokens
, &ipv6_token_hash_ops
);
1185 r
= ordered_set_put(network
->ipv6_tokens
, token
);
1187 log_syntax(unit
, LOG_DEBUG
, filename
, line
, r
,
1188 "IPv6 token '%s' is duplicated, ignoring: %m", rvalue
);
1190 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
1191 "Failed to store IPv6 token '%s', ignoring: %m", rvalue
);
1198 DEFINE_CONFIG_PARSE_ENUM(config_parse_ipv6_accept_ra_start_dhcp6_client
, ipv6_accept_ra_start_dhcp6_client
, IPv6AcceptRAStartDHCP6Client
,
1199 "Failed to parse DHCPv6Client= setting")
1200 static const char* const ipv6_accept_ra_start_dhcp6_client_table
[_IPV6_ACCEPT_RA_START_DHCP6_CLIENT_MAX
] = {
1201 [IPV6_ACCEPT_RA_START_DHCP6_CLIENT_NO
] = "no",
1202 [IPV6_ACCEPT_RA_START_DHCP6_CLIENT_ALWAYS
] = "always",
1203 [IPV6_ACCEPT_RA_START_DHCP6_CLIENT_YES
] = "yes",
1206 DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(ipv6_accept_ra_start_dhcp6_client
, IPv6AcceptRAStartDHCP6Client
, IPV6_ACCEPT_RA_START_DHCP6_CLIENT_YES
);