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_route_handler(sd_netlink
*rtnl
, sd_netlink_message
*m
, Link
*link
) {
42 assert(link
->ndisc_routes_messages
> 0);
44 link
->ndisc_routes_messages
--;
46 if (IN_SET(link
->state
, LINK_STATE_FAILED
, LINK_STATE_LINGER
))
49 r
= sd_netlink_message_get_errno(m
);
50 if (r
< 0 && r
!= -EEXIST
) {
51 log_link_message_error_errno(link
, m
, r
, "Could not set NDisc route");
52 link_enter_failed(link
);
56 if (link
->ndisc_routes_messages
== 0) {
57 log_link_debug(link
, "NDisc routes set.");
58 link
->ndisc_routes_configured
= true;
59 link_check_ready(link
);
65 static int ndisc_address_handler(sd_netlink
*rtnl
, sd_netlink_message
*m
, Link
*link
) {
69 assert(link
->ndisc_addresses_messages
> 0);
71 link
->ndisc_addresses_messages
--;
73 if (IN_SET(link
->state
, LINK_STATE_FAILED
, LINK_STATE_LINGER
))
76 r
= sd_netlink_message_get_errno(m
);
77 if (r
< 0 && r
!= -EEXIST
) {
78 log_link_message_error_errno(link
, m
, r
, "Could not set NDisc address");
79 link_enter_failed(link
);
82 (void) manager_rtnl_process_address(rtnl
, m
, link
->manager
);
84 if (link
->ndisc_addresses_messages
== 0) {
85 log_link_debug(link
, "NDisc SLAAC addresses set.");
86 link
->ndisc_addresses_configured
= true;
87 r
= link_request_set_routes(link
);
89 link_enter_failed(link
);
97 static int ndisc_router_process_default(Link
*link
, sd_ndisc_router
*rt
) {
98 _cleanup_(route_freep
) Route
*route
= NULL
;
99 union in_addr_union gateway
;
109 r
= sd_ndisc_router_get_lifetime(rt
, &lifetime
);
111 return log_link_error_errno(link
, r
, "Failed to get gateway lifetime from RA: %m");
113 if (lifetime
== 0) /* not a default router */
116 r
= sd_ndisc_router_get_address(rt
, &gateway
.in6
);
118 return log_link_error_errno(link
, r
, "Failed to get gateway address from RA: %m");
120 if (address_exists(link
, AF_INET6
, &gateway
)) {
122 _cleanup_free_
char *buffer
= NULL
;
124 (void) in_addr_to_string(AF_INET6
, &gateway
, &buffer
);
125 log_link_debug(link
, "No NDisc route added, gateway %s matches local address",
131 r
= sd_ndisc_router_get_preference(rt
, &preference
);
133 return log_link_error_errno(link
, r
, "Failed to get default router preference from RA: %m");
135 r
= sd_ndisc_router_get_timestamp(rt
, clock_boottime_or_monotonic(), &time_now
);
137 return log_link_error_errno(link
, r
, "Failed to get RA timestamp: %m");
139 r
= sd_ndisc_router_get_mtu(rt
, &mtu
);
143 return log_link_error_errno(link
, r
, "Failed to get default router MTU from RA: %m");
145 r
= route_new(&route
);
149 route
->family
= AF_INET6
;
150 route
->table
= link_get_ipv6_accept_ra_route_table(link
);
151 route
->priority
= link
->network
->dhcp6_route_metric
;
152 route
->protocol
= RTPROT_RA
;
153 route
->pref
= preference
;
155 route
->lifetime
= time_now
+ lifetime
* USEC_PER_SEC
;
158 r
= route_configure(route
, link
, ndisc_route_handler
, NULL
);
160 return log_link_error_errno(link
, r
, "Could not set default route: %m");
162 link
->ndisc_routes_messages
++;
165 LIST_FOREACH(routes
, route_gw
, link
->network
->static_routes
) {
166 if (!route_gw
->gateway_from_dhcp
)
169 if (route_gw
->family
!= AF_INET6
)
172 route_gw
->gw
= gateway
;
174 r
= route_configure(route_gw
, link
, ndisc_route_handler
, NULL
);
176 return log_link_error_errno(link
, r
, "Could not set gateway: %m");
178 link
->ndisc_routes_messages
++;
184 static bool stableprivate_address_is_valid(const struct in6_addr
*addr
) {
187 /* According to rfc4291, generated address should not be in the following ranges. */
189 if (memcmp(addr
, &SUBNET_ROUTER_ANYCAST_ADDRESS_RFC4291
, SUBNET_ROUTER_ANYCAST_PREFIXLEN
) == 0)
192 if (memcmp(addr
, &RESERVED_IPV6_INTERFACE_IDENTIFIERS_ADDRESS_RFC4291
, RESERVED_IPV6_INTERFACE_IDENTIFIERS_PREFIXLEN
) == 0)
195 if (memcmp(addr
, &RESERVED_SUBNET_ANYCAST_ADDRESSES_RFC4291
, RESERVED_SUBNET_ANYCAST_PREFIXLEN
) == 0)
201 static int make_stableprivate_address(Link
*link
, const struct in6_addr
*prefix
, uint8_t prefix_len
, uint8_t dad_counter
, struct in6_addr
**ret
) {
202 _cleanup_free_
struct in6_addr
*addr
= NULL
;
203 sd_id128_t secret_key
;
204 struct siphash state
;
209 /* According to rfc7217 section 5.1
210 * RID = F(Prefix, Net_Iface, Network_ID, DAD_Counter, secret_key) */
212 r
= sd_id128_get_machine_app_specific(NDISC_APP_ID
, &secret_key
);
214 return log_error_errno(r
, "Failed to generate key: %m");
216 siphash24_init(&state
, secret_key
.bytes
);
218 l
= MAX(DIV_ROUND_UP(prefix_len
, 8), 8);
219 siphash24_compress(prefix
, l
, &state
);
220 siphash24_compress_string(link
->ifname
, &state
);
221 siphash24_compress(&link
->mac
, sizeof(struct ether_addr
), &state
);
222 siphash24_compress(&dad_counter
, sizeof(uint8_t), &state
);
224 rid
= htole64(siphash24_finalize(&state
));
226 addr
= new(struct in6_addr
, 1);
230 memcpy(addr
->s6_addr
, prefix
->s6_addr
, l
);
231 memcpy(addr
->s6_addr
+ l
, &rid
, 16 - l
);
233 if (!stableprivate_address_is_valid(addr
)) {
238 *ret
= TAKE_PTR(addr
);
242 static int ndisc_router_generate_addresses(Link
*link
, struct in6_addr
*address
, uint8_t prefixlen
, Set
**ret
) {
243 _cleanup_set_free_free_ Set
*addresses
= NULL
;
252 addresses
= set_new(&in6_addr_hash_ops
);
256 ORDERED_SET_FOREACH(j
, link
->network
->ipv6_tokens
, i
) {
257 _cleanup_free_
struct in6_addr
*new_address
= NULL
;
259 if (j
->address_generation_type
== IPV6_TOKEN_ADDRESS_GENERATION_PREFIXSTABLE
260 && IN6_ARE_ADDR_EQUAL(&j
->prefix
, address
)) {
261 /* While this loop uses dad_counter and a retry limit as specified in RFC 7217, the loop
262 does not actually attempt Duplicate Address Detection; the counter will be incremented
263 only when the address generation algorithm produces an invalid address, and the loop
264 may exit with an address which ends up being unusable due to duplication on the link.
266 for (; j
->dad_counter
< DAD_CONFLICTS_IDGEN_RETRIES_RFC7217
; j
->dad_counter
++) {
267 r
= make_stableprivate_address(link
, &j
->prefix
, prefixlen
, j
->dad_counter
, &new_address
);
273 } else if (j
->address_generation_type
== IPV6_TOKEN_ADDRESS_GENERATION_STATIC
) {
274 new_address
= new(struct in6_addr
, 1);
278 memcpy(new_address
->s6_addr
, address
->s6_addr
, 8);
279 memcpy(new_address
->s6_addr
+ 8, j
->prefix
.s6_addr
+ 8, 8);
283 r
= set_put(addresses
, new_address
);
285 return log_link_error_errno(link
, r
, "Failed to store SLAAC address: %m");
287 log_link_debug_errno(link
, r
, "Generated SLAAC address is duplicated, ignoring.");
289 TAKE_PTR(new_address
);
293 /* fall back to EUI-64 if no tokens provided addresses */
294 if (set_isempty(addresses
)) {
295 _cleanup_free_
struct in6_addr
*new_address
= NULL
;
297 new_address
= newdup(struct in6_addr
, address
, 1);
301 r
= generate_ipv6_eui_64_address(link
, new_address
);
303 return log_link_error_errno(link
, r
, "Failed to generate EUI64 address: %m");
305 r
= set_put(addresses
, new_address
);
307 return log_link_error_errno(link
, r
, "Failed to store SLAAC address: %m");
309 TAKE_PTR(new_address
);
312 *ret
= TAKE_PTR(addresses
);
317 static int ndisc_router_process_autonomous_prefix(Link
*link
, sd_ndisc_router
*rt
) {
318 uint32_t lifetime_valid
, lifetime_preferred
, lifetime_remaining
;
319 _cleanup_set_free_free_ Set
*addresses
= NULL
;
320 _cleanup_(address_freep
) Address
*address
= NULL
;
321 struct in6_addr addr
, *a
;
330 r
= sd_ndisc_router_get_timestamp(rt
, clock_boottime_or_monotonic(), &time_now
);
332 return log_link_error_errno(link
, r
, "Failed to get RA timestamp: %m");
334 r
= sd_ndisc_router_prefix_get_prefixlen(rt
, &prefixlen
);
336 return log_link_error_errno(link
, r
, "Failed to get prefix length: %m");
338 r
= sd_ndisc_router_prefix_get_valid_lifetime(rt
, &lifetime_valid
);
340 return log_link_error_errno(link
, r
, "Failed to get prefix valid lifetime: %m");
342 r
= sd_ndisc_router_prefix_get_preferred_lifetime(rt
, &lifetime_preferred
);
344 return log_link_error_errno(link
, r
, "Failed to get prefix preferred lifetime: %m");
346 /* The preferred lifetime is never greater than the valid lifetime */
347 if (lifetime_preferred
> lifetime_valid
)
350 r
= sd_ndisc_router_prefix_get_address(rt
, &addr
);
352 return log_link_error_errno(link
, r
, "Failed to get prefix address: %m");
354 r
= ndisc_router_generate_addresses(link
, &addr
, prefixlen
, &addresses
);
358 r
= address_new(&address
);
362 address
->family
= AF_INET6
;
363 address
->prefixlen
= prefixlen
;
364 address
->flags
= IFA_F_NOPREFIXROUTE
|IFA_F_MANAGETEMPADDR
;
365 address
->cinfo
.ifa_prefered
= lifetime_preferred
;
367 SET_FOREACH(a
, addresses
, i
) {
368 Address
*existing_address
;
370 /* see RFC4862 section 5.5.3.e */
371 r
= address_get(link
, AF_INET6
, (union in_addr_union
*) a
, prefixlen
, &existing_address
);
373 lifetime_remaining
= existing_address
->cinfo
.tstamp
/ 100 + existing_address
->cinfo
.ifa_valid
- time_now
/ USEC_PER_SEC
;
374 if (lifetime_valid
> NDISC_PREFIX_LFT_MIN
|| lifetime_valid
> lifetime_remaining
)
375 address
->cinfo
.ifa_valid
= lifetime_valid
;
376 else if (lifetime_remaining
<= NDISC_PREFIX_LFT_MIN
)
377 address
->cinfo
.ifa_valid
= lifetime_remaining
;
379 address
->cinfo
.ifa_valid
= NDISC_PREFIX_LFT_MIN
;
380 } else if (lifetime_valid
> 0)
381 address
->cinfo
.ifa_valid
= lifetime_valid
;
383 continue; /* see RFC4862 section 5.5.3.d */
385 if (address
->cinfo
.ifa_valid
== 0)
388 address
->in_addr
.in6
= *a
;
390 r
= address_configure(address
, link
, ndisc_address_handler
, true, NULL
);
392 return log_link_error_errno(link
, r
, "Could not set SLAAC address: %m");
394 link
->ndisc_addresses_messages
++;
400 static int ndisc_router_process_onlink_prefix(Link
*link
, sd_ndisc_router
*rt
) {
401 _cleanup_(route_freep
) Route
*route
= NULL
;
410 r
= sd_ndisc_router_get_timestamp(rt
, clock_boottime_or_monotonic(), &time_now
);
412 return log_link_error_errno(link
, r
, "Failed to get RA timestamp: %m");
414 r
= sd_ndisc_router_prefix_get_prefixlen(rt
, &prefixlen
);
416 return log_link_error_errno(link
, r
, "Failed to get prefix length: %m");
418 r
= sd_ndisc_router_prefix_get_valid_lifetime(rt
, &lifetime
);
420 return log_link_error_errno(link
, r
, "Failed to get prefix lifetime: %m");
422 r
= route_new(&route
);
426 route
->family
= AF_INET6
;
427 route
->table
= link_get_ipv6_accept_ra_route_table(link
);
428 route
->priority
= link
->network
->dhcp6_route_metric
;
429 route
->protocol
= RTPROT_RA
;
430 route
->flags
= RTM_F_PREFIX
;
431 route
->dst_prefixlen
= prefixlen
;
432 route
->lifetime
= time_now
+ lifetime
* USEC_PER_SEC
;
434 r
= sd_ndisc_router_prefix_get_address(rt
, &route
->dst
.in6
);
436 return log_link_error_errno(link
, r
, "Failed to get prefix address: %m");
438 r
= route_configure(route
, link
, ndisc_route_handler
, NULL
);
440 return log_link_error_errno(link
, r
, "Could not set prefix route: %m");;
442 link
->ndisc_routes_messages
++;
447 static int ndisc_router_process_route(Link
*link
, sd_ndisc_router
*rt
) {
448 _cleanup_(route_freep
) Route
*route
= NULL
;
449 struct in6_addr gateway
;
451 unsigned preference
, prefixlen
;
457 r
= sd_ndisc_router_route_get_lifetime(rt
, &lifetime
);
459 return log_link_error_errno(link
, r
, "Failed to get gateway lifetime from RA: %m");
464 r
= sd_ndisc_router_get_address(rt
, &gateway
);
466 return log_link_error_errno(link
, r
, "Failed to get gateway address from RA: %m");
468 r
= sd_ndisc_router_route_get_prefixlen(rt
, &prefixlen
);
470 return log_link_error_errno(link
, r
, "Failed to get route prefix length: %m");
472 r
= sd_ndisc_router_route_get_preference(rt
, &preference
);
474 return log_link_error_errno(link
, r
, "Failed to get default router preference from RA: %m");
476 r
= sd_ndisc_router_get_timestamp(rt
, clock_boottime_or_monotonic(), &time_now
);
478 return log_link_error_errno(link
, r
, "Failed to get RA timestamp: %m");
480 r
= route_new(&route
);
484 route
->family
= AF_INET6
;
485 route
->table
= link_get_ipv6_accept_ra_route_table(link
);
486 route
->priority
= link
->network
->dhcp6_route_metric
;
487 route
->protocol
= RTPROT_RA
;
488 route
->pref
= preference
;
489 route
->gw
.in6
= gateway
;
490 route
->dst_prefixlen
= prefixlen
;
491 route
->lifetime
= time_now
+ lifetime
* USEC_PER_SEC
;
493 r
= sd_ndisc_router_route_get_address(rt
, &route
->dst
.in6
);
495 return log_link_error_errno(link
, r
, "Failed to get route address: %m");
497 r
= route_configure(route
, link
, ndisc_route_handler
, NULL
);
499 return log_link_error_errno(link
, r
, "Could not set additional route: %m");
501 link
->ndisc_routes_messages
++;
506 static void ndisc_rdnss_hash_func(const NDiscRDNSS
*x
, struct siphash
*state
) {
507 siphash24_compress(&x
->address
, sizeof(x
->address
), state
);
510 static int ndisc_rdnss_compare_func(const NDiscRDNSS
*a
, const NDiscRDNSS
*b
) {
511 return memcmp(&a
->address
, &b
->address
, sizeof(a
->address
));
514 DEFINE_PRIVATE_HASH_OPS(ndisc_rdnss_hash_ops
, NDiscRDNSS
, ndisc_rdnss_hash_func
, ndisc_rdnss_compare_func
);
516 static int ndisc_router_process_rdnss(Link
*link
, sd_ndisc_router
*rt
) {
518 const struct in6_addr
*a
;
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_rdnss_get_lifetime(rt
, &lifetime
);
531 return log_link_error_errno(link
, r
, "Failed to get RDNSS lifetime: %m");
533 n
= sd_ndisc_router_rdnss_get_addresses(rt
, &a
);
535 return log_link_error_errno(link
, n
, "Failed to get RDNSS addresses: %m");
537 for (int i
= 0; i
< n
; i
++) {
538 _cleanup_free_ NDiscRDNSS
*x
= NULL
;
544 (void) set_remove(link
->ndisc_rdnss
, &d
);
549 y
= set_get(link
->ndisc_rdnss
, &d
);
551 y
->valid_until
= time_now
+ lifetime
* USEC_PER_SEC
;
557 if (set_size(link
->ndisc_rdnss
) >= NDISC_RDNSS_MAX
) {
558 log_link_warning(link
, "Too many RDNSS records per link, ignoring.");
562 x
= new(NDiscRDNSS
, 1);
568 .valid_until
= time_now
+ lifetime
* USEC_PER_SEC
,
571 r
= set_ensure_consume(&link
->ndisc_rdnss
, &ndisc_rdnss_hash_ops
, TAKE_PTR(x
));
582 static void ndisc_dnssl_hash_func(const NDiscDNSSL
*x
, struct siphash
*state
) {
583 siphash24_compress_string(NDISC_DNSSL_DOMAIN(x
), state
);
586 static int ndisc_dnssl_compare_func(const NDiscDNSSL
*a
, const NDiscDNSSL
*b
) {
587 return strcmp(NDISC_DNSSL_DOMAIN(a
), NDISC_DNSSL_DOMAIN(b
));
590 DEFINE_PRIVATE_HASH_OPS(ndisc_dnssl_hash_ops
, NDiscDNSSL
, ndisc_dnssl_hash_func
, ndisc_dnssl_compare_func
);
592 static int ndisc_router_process_dnssl(Link
*link
, sd_ndisc_router
*rt
) {
593 _cleanup_strv_free_
char **l
= NULL
;
602 r
= sd_ndisc_router_get_timestamp(rt
, clock_boottime_or_monotonic(), &time_now
);
604 return log_link_error_errno(link
, r
, "Failed to get RA timestamp: %m");
606 r
= sd_ndisc_router_dnssl_get_lifetime(rt
, &lifetime
);
608 return log_link_error_errno(link
, r
, "Failed to get DNSSL lifetime: %m");
610 r
= sd_ndisc_router_dnssl_get_domains(rt
, &l
);
612 return log_link_error_errno(link
, r
, "Failed to get DNSSL addresses: %m");
615 _cleanup_free_ NDiscDNSSL
*s
= NULL
;
618 s
= malloc0(ALIGN(sizeof(NDiscDNSSL
)) + strlen(*i
) + 1);
622 strcpy(NDISC_DNSSL_DOMAIN(s
), *i
);
625 (void) set_remove(link
->ndisc_dnssl
, s
);
630 x
= set_get(link
->ndisc_dnssl
, s
);
632 x
->valid_until
= time_now
+ lifetime
* USEC_PER_SEC
;
638 if (set_size(link
->ndisc_dnssl
) >= NDISC_DNSSL_MAX
) {
639 log_link_warning(link
, "Too many DNSSL records per link, ignoring.");
643 s
->valid_until
= time_now
+ lifetime
* USEC_PER_SEC
;
645 r
= set_ensure_consume(&link
->ndisc_dnssl
, &ndisc_dnssl_hash_ops
, TAKE_PTR(s
));
656 static int ndisc_router_process_options(Link
*link
, sd_ndisc_router
*rt
) {
658 assert(link
->network
);
661 for (int r
= sd_ndisc_router_option_rewind(rt
); ; r
= sd_ndisc_router_option_next(rt
)) {
665 return log_link_error_errno(link
, r
, "Failed to iterate through options: %m");
666 if (r
== 0) /* EOF */
669 r
= sd_ndisc_router_option_get_type(rt
, &type
);
671 return log_link_error_errno(link
, r
, "Failed to get RA option type: %m");
675 case SD_NDISC_OPTION_PREFIX_INFORMATION
: {
676 union in_addr_union a
;
679 r
= sd_ndisc_router_prefix_get_address(rt
, &a
.in6
);
681 return log_link_error_errno(link
, r
, "Failed to get prefix address: %m");
683 if (set_contains(link
->network
->ndisc_deny_listed_prefix
, &a
.in6
)) {
685 _cleanup_free_
char *b
= NULL
;
687 (void) in_addr_to_string(AF_INET6
, &a
, &b
);
688 log_link_debug(link
, "Prefix '%s' is deny-listed, ignoring", strna(b
));
693 r
= sd_ndisc_router_prefix_get_flags(rt
, &flags
);
695 return log_link_error_errno(link
, r
, "Failed to get RA prefix flags: %m");
697 if (link
->network
->ipv6_accept_ra_use_onlink_prefix
&&
698 FLAGS_SET(flags
, ND_OPT_PI_FLAG_ONLINK
)) {
699 r
= ndisc_router_process_onlink_prefix(link
, rt
);
704 if (link
->network
->ipv6_accept_ra_use_autonomous_prefix
&&
705 FLAGS_SET(flags
, ND_OPT_PI_FLAG_AUTO
)) {
706 r
= ndisc_router_process_autonomous_prefix(link
, rt
);
713 case SD_NDISC_OPTION_ROUTE_INFORMATION
:
714 r
= ndisc_router_process_route(link
, rt
);
719 case SD_NDISC_OPTION_RDNSS
:
720 if (link
->network
->ipv6_accept_ra_use_dns
) {
721 r
= ndisc_router_process_rdnss(link
, rt
);
727 case SD_NDISC_OPTION_DNSSL
:
728 if (link
->network
->ipv6_accept_ra_use_dns
) {
729 r
= ndisc_router_process_dnssl(link
, rt
);
738 static int ndisc_router_handler(Link
*link
, sd_ndisc_router
*rt
) {
743 assert(link
->network
);
744 assert(link
->manager
);
747 r
= sd_ndisc_router_get_flags(rt
, &flags
);
749 return log_link_error_errno(link
, r
, "Failed to get RA flags: %m");
751 if ((flags
& (ND_RA_FLAG_MANAGED
| ND_RA_FLAG_OTHER
) && link
->network
->ipv6_accept_ra_start_dhcp6_client
)) {
753 if (link
->network
->ipv6_accept_ra_start_dhcp6_client
== IPV6_ACCEPT_RA_START_DHCP6_CLIENT_ALWAYS
)
754 r
= dhcp6_request_address(link
, false);
756 /* (re)start DHCPv6 client in stateful or stateless mode according to RA flags */
757 r
= dhcp6_request_address(link
, !(flags
& ND_RA_FLAG_MANAGED
));
758 if (r
< 0 && r
!= -EBUSY
)
759 return log_link_error_errno(link
, r
, "Could not acquire DHCPv6 lease on NDisc request: %m");
761 log_link_debug(link
, "Acquiring DHCPv6 lease on NDisc request");
766 r
= ndisc_router_process_default(link
, rt
);
769 r
= ndisc_router_process_options(link
, rt
);
776 static void ndisc_handler(sd_ndisc
*nd
, sd_ndisc_event event
, sd_ndisc_router
*rt
, void *userdata
) {
777 Link
*link
= userdata
;
782 if (IN_SET(link
->state
, LINK_STATE_FAILED
, LINK_STATE_LINGER
))
787 case SD_NDISC_EVENT_ROUTER
:
788 link
->ndisc_addresses_configured
= false;
789 link
->ndisc_routes_configured
= false;
791 r
= ndisc_router_handler(link
, rt
);
793 link_enter_failed(link
);
797 if (link
->ndisc_addresses_messages
== 0)
798 link
->ndisc_addresses_configured
= true;
800 log_link_debug(link
, "Setting SLAAC addresses.");
802 /* address_handler calls link_request_set_routes() and link_request_set_nexthop().
803 * Before they are called, the related flags must be cleared. Otherwise, the link
804 * becomes configured state before routes are configured. */
805 link
->static_routes_configured
= false;
806 link
->static_nexthops_configured
= false;
809 if (link
->ndisc_routes_messages
== 0)
810 link
->ndisc_routes_configured
= true;
812 log_link_debug(link
, "Setting NDisc routes.");
814 if (link
->ndisc_addresses_configured
&& link
->ndisc_routes_configured
)
815 link_check_ready(link
);
817 link_set_state(link
, LINK_STATE_CONFIGURING
);
820 case SD_NDISC_EVENT_TIMEOUT
:
821 log_link_debug(link
, "NDisc handler get timeout event");
822 if (link
->ndisc_addresses_messages
== 0 && link
->ndisc_routes_messages
== 0) {
823 link
->ndisc_addresses_configured
= true;
824 link
->ndisc_routes_configured
= true;
825 link_check_ready(link
);
829 assert_not_reached("Unknown NDisc event");
833 int ndisc_configure(Link
*link
) {
838 r
= sd_ndisc_new(&link
->ndisc
);
842 r
= sd_ndisc_attach_event(link
->ndisc
, NULL
, 0);
846 r
= sd_ndisc_set_mac(link
->ndisc
, &link
->mac
);
850 r
= sd_ndisc_set_ifindex(link
->ndisc
, link
->ifindex
);
854 r
= sd_ndisc_set_callback(link
->ndisc
, ndisc_handler
, link
);
861 void ndisc_vacuum(Link
*link
) {
869 /* Removes all RDNSS and DNSSL entries whose validity time has passed */
871 time_now
= now(clock_boottime_or_monotonic());
873 SET_FOREACH(r
, link
->ndisc_rdnss
, i
)
874 if (r
->valid_until
< time_now
) {
875 free(set_remove(link
->ndisc_rdnss
, r
));
879 SET_FOREACH(d
, link
->ndisc_dnssl
, i
)
880 if (d
->valid_until
< time_now
) {
881 free(set_remove(link
->ndisc_dnssl
, d
));
886 void ndisc_flush(Link
*link
) {
889 /* Removes all RDNSS and DNSSL entries, without exception */
891 link
->ndisc_rdnss
= set_free_free(link
->ndisc_rdnss
);
892 link
->ndisc_dnssl
= set_free_free(link
->ndisc_dnssl
);
895 int ipv6token_new(IPv6Token
**ret
) {
898 p
= new(IPv6Token
, 1);
903 .address_generation_type
= IPV6_TOKEN_ADDRESS_GENERATION_NONE
,
911 static void ipv6_token_hash_func(const IPv6Token
*p
, struct siphash
*state
) {
912 siphash24_compress(&p
->address_generation_type
, sizeof(p
->address_generation_type
), state
);
913 siphash24_compress(&p
->prefix
, sizeof(p
->prefix
), state
);
916 static int ipv6_token_compare_func(const IPv6Token
*a
, const IPv6Token
*b
) {
919 r
= CMP(a
->address_generation_type
, b
->address_generation_type
);
923 return memcmp(&a
->prefix
, &b
->prefix
, sizeof(struct in6_addr
));
926 DEFINE_HASH_OPS_WITH_KEY_DESTRUCTOR(
929 ipv6_token_hash_func
,
930 ipv6_token_compare_func
,
933 int config_parse_ndisc_deny_listed_prefix(
935 const char *filename
,
938 unsigned section_line
,
945 Network
*network
= data
;
954 if (isempty(rvalue
)) {
955 network
->ndisc_deny_listed_prefix
= set_free_free(network
->ndisc_deny_listed_prefix
);
960 _cleanup_free_
char *n
= NULL
;
961 _cleanup_free_
struct in6_addr
*a
= NULL
;
962 union in_addr_union ip
;
964 r
= extract_first_word(&p
, &n
, NULL
, 0);
968 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
969 "Failed to parse NDisc deny-listed prefix, ignoring assignment: %s",
976 r
= in_addr_from_string(AF_INET6
, n
, &ip
);
978 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
979 "NDisc deny-listed prefix is invalid, ignoring assignment: %s", n
);
983 if (set_contains(network
->ndisc_deny_listed_prefix
, &ip
.in6
))
986 a
= newdup(struct in6_addr
, &ip
.in6
, 1);
990 r
= set_ensure_consume(&network
->ndisc_deny_listed_prefix
, &in6_addr_hash_ops
, TAKE_PTR(a
));
996 int config_parse_address_generation_type(
998 const char *filename
,
1000 const char *section
,
1001 unsigned section_line
,
1008 _cleanup_free_ IPv6Token
*token
= NULL
;
1009 union in_addr_union buffer
;
1010 Network
*network
= data
;
1019 if (isempty(rvalue
)) {
1020 network
->ipv6_tokens
= ordered_set_free(network
->ipv6_tokens
);
1024 r
= ipv6token_new(&token
);
1028 if ((p
= startswith(rvalue
, "static:")))
1029 token
->address_generation_type
= IPV6_TOKEN_ADDRESS_GENERATION_STATIC
;
1030 else if ((p
= startswith(rvalue
, "prefixstable:")))
1031 token
->address_generation_type
= IPV6_TOKEN_ADDRESS_GENERATION_PREFIXSTABLE
;
1033 token
->address_generation_type
= IPV6_TOKEN_ADDRESS_GENERATION_STATIC
;
1037 r
= in_addr_from_string(AF_INET6
, p
, &buffer
);
1039 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
1040 "Failed to parse IPv6 %s, ignoring: %s", lvalue
, rvalue
);
1044 if (in_addr_is_null(AF_INET6
, &buffer
)) {
1045 log_syntax(unit
, LOG_WARNING
, filename
, line
, 0,
1046 "IPv6 %s cannot be the ANY address, ignoring: %s", lvalue
, rvalue
);
1050 token
->prefix
= buffer
.in6
;
1052 r
= ordered_set_ensure_allocated(&network
->ipv6_tokens
, &ipv6_token_hash_ops
);
1056 r
= ordered_set_put(network
->ipv6_tokens
, token
);
1058 log_syntax(unit
, LOG_DEBUG
, filename
, line
, r
,
1059 "IPv6 token '%s' is duplicated, ignoring: %m", rvalue
);
1061 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
1062 "Failed to store IPv6 token '%s', ignoring: %m", rvalue
);
1069 DEFINE_CONFIG_PARSE_ENUM(config_parse_ipv6_accept_ra_start_dhcp6_client
, ipv6_accept_ra_start_dhcp6_client
, IPv6AcceptRAStartDHCP6Client
,
1070 "Failed to parse DHCPv6Client= setting")
1071 static const char* const ipv6_accept_ra_start_dhcp6_client_table
[_IPV6_ACCEPT_RA_START_DHCP6_CLIENT_MAX
] = {
1072 [IPV6_ACCEPT_RA_START_DHCP6_CLIENT_NO
] = "no",
1073 [IPV6_ACCEPT_RA_START_DHCP6_CLIENT_ALWAYS
] = "always",
1074 [IPV6_ACCEPT_RA_START_DHCP6_CLIENT_YES
] = "yes",
1077 DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(ipv6_accept_ra_start_dhcp6_client
, IPv6AcceptRAStartDHCP6Client
, IPV6_ACCEPT_RA_START_DHCP6_CLIENT_YES
);