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 bool stableprivate_address_is_valid(const struct in6_addr
*addr
) {
41 /* According to rfc4291, generated address should not be in the following ranges. */
43 if (memcmp(addr
, &SUBNET_ROUTER_ANYCAST_ADDRESS_RFC4291
, SUBNET_ROUTER_ANYCAST_PREFIXLEN
) == 0)
46 if (memcmp(addr
, &RESERVED_IPV6_INTERFACE_IDENTIFIERS_ADDRESS_RFC4291
, RESERVED_IPV6_INTERFACE_IDENTIFIERS_PREFIXLEN
) == 0)
49 if (memcmp(addr
, &RESERVED_SUBNET_ANYCAST_ADDRESSES_RFC4291
, RESERVED_SUBNET_ANYCAST_PREFIXLEN
) == 0)
55 static int make_stableprivate_address(Link
*link
, const struct in6_addr
*prefix
, uint8_t prefix_len
, uint8_t dad_counter
, struct in6_addr
*addr
) {
56 sd_id128_t secret_key
;
62 /* According to rfc7217 section 5.1
63 * RID = F(Prefix, Net_Iface, Network_ID, DAD_Counter, secret_key) */
65 r
= sd_id128_get_machine_app_specific(NDISC_APP_ID
, &secret_key
);
67 return log_error_errno(r
, "Failed to generate key: %m");
69 siphash24_init(&state
, secret_key
.bytes
);
71 l
= MAX(DIV_ROUND_UP(prefix_len
, 8), 8);
72 siphash24_compress(prefix
, l
, &state
);
73 siphash24_compress(link
->ifname
, strlen(link
->ifname
), &state
);
74 siphash24_compress(&link
->mac
, sizeof(struct ether_addr
), &state
);
75 siphash24_compress(&dad_counter
, sizeof(uint8_t), &state
);
77 rid
= htole64(siphash24_finalize(&state
));
79 memcpy(addr
->s6_addr
, prefix
->s6_addr
, l
);
80 memcpy(addr
->s6_addr
+ l
, &rid
, 16 - l
);
85 static int ndisc_netlink_route_message_handler(sd_netlink
*rtnl
, sd_netlink_message
*m
, Link
*link
) {
89 assert(link
->ndisc_messages
> 0);
91 link
->ndisc_messages
--;
93 if (IN_SET(link
->state
, LINK_STATE_FAILED
, LINK_STATE_LINGER
))
96 r
= sd_netlink_message_get_errno(m
);
97 if (r
< 0 && r
!= -EEXIST
) {
98 log_link_message_error_errno(link
, m
, r
, "Could not set NDisc route or address");
99 link_enter_failed(link
);
103 if (link
->ndisc_messages
== 0) {
104 link
->ndisc_configured
= true;
105 r
= link_request_set_routes(link
);
107 link_enter_failed(link
);
110 link_check_ready(link
);
116 static int ndisc_netlink_address_message_handler(sd_netlink
*rtnl
, sd_netlink_message
*m
, Link
*link
) {
120 assert(link
->ndisc_messages
> 0);
122 link
->ndisc_messages
--;
124 if (IN_SET(link
->state
, LINK_STATE_FAILED
, LINK_STATE_LINGER
))
127 r
= sd_netlink_message_get_errno(m
);
128 if (r
< 0 && r
!= -EEXIST
) {
129 log_link_message_error_errno(link
, m
, r
, "Could not set NDisc route or address");
130 link_enter_failed(link
);
133 (void) manager_rtnl_process_address(rtnl
, m
, link
->manager
);
135 if (link
->ndisc_messages
== 0) {
136 link
->ndisc_configured
= true;
137 r
= link_request_set_routes(link
);
139 link_enter_failed(link
);
142 link_check_ready(link
);
148 static int ndisc_router_process_default(Link
*link
, sd_ndisc_router
*rt
) {
149 _cleanup_(route_freep
) Route
*route
= NULL
;
150 union in_addr_union gateway
;
162 r
= sd_ndisc_router_get_lifetime(rt
, &lifetime
);
164 return log_link_warning_errno(link
, r
, "Failed to get gateway address from RA: %m");
166 if (lifetime
== 0) /* not a default router */
169 r
= sd_ndisc_router_get_address(rt
, &gateway
.in6
);
171 return log_link_warning_errno(link
, r
, "Failed to get gateway address from RA: %m");
173 SET_FOREACH(address
, link
->addresses
, i
) {
174 if (address
->family
!= AF_INET6
)
176 if (in_addr_equal(AF_INET6
, &gateway
, &address
->in_addr
)) {
177 _cleanup_free_
char *buffer
= NULL
;
179 (void) in_addr_to_string(AF_INET6
, &address
->in_addr
, &buffer
);
180 log_link_debug(link
, "No NDisc route added, gateway %s matches local address",
186 SET_FOREACH(address
, link
->addresses_foreign
, i
) {
187 if (address
->family
!= AF_INET6
)
189 if (in_addr_equal(AF_INET6
, &gateway
, &address
->in_addr
)) {
190 _cleanup_free_
char *buffer
= NULL
;
192 (void) in_addr_to_string(AF_INET6
, &address
->in_addr
, &buffer
);
193 log_link_debug(link
, "No NDisc route added, gateway %s matches local address",
199 r
= sd_ndisc_router_get_preference(rt
, &preference
);
201 return log_link_warning_errno(link
, r
, "Failed to get default router preference from RA: %m");
203 r
= sd_ndisc_router_get_timestamp(rt
, clock_boottime_or_monotonic(), &time_now
);
205 return log_link_warning_errno(link
, r
, "Failed to get RA timestamp: %m");
207 r
= sd_ndisc_router_get_mtu(rt
, &mtu
);
211 return log_link_warning_errno(link
, r
, "Failed to get default router MTU from RA: %m");
213 r
= route_new(&route
);
215 return log_link_error_errno(link
, r
, "Could not allocate route: %m");
217 route
->family
= AF_INET6
;
218 route
->table
= link_get_ipv6_accept_ra_route_table(link
);
219 route
->priority
= link
->network
->dhcp6_route_metric
;
220 route
->protocol
= RTPROT_RA
;
221 route
->pref
= preference
;
223 route
->lifetime
= time_now
+ lifetime
* USEC_PER_SEC
;
226 r
= route_configure(route
, link
, ndisc_netlink_route_message_handler
);
228 log_link_warning_errno(link
, r
, "Could not set default route: %m");
229 link_enter_failed(link
);
233 link
->ndisc_messages
++;
236 LIST_FOREACH(routes
, route_gw
, link
->network
->static_routes
) {
237 if (!route_gw
->gateway_from_dhcp
)
240 if (route_gw
->family
!= AF_INET6
)
243 route_gw
->gw
= gateway
;
245 r
= route_configure(route_gw
, link
, ndisc_netlink_route_message_handler
);
247 log_link_error_errno(link
, r
, "Could not set gateway: %m");
248 link_enter_failed(link
);
252 link
->ndisc_messages
++;
258 static int ndisc_router_generate_addresses(Link
*link
, unsigned prefixlen
, uint32_t lifetime_preferred
, Address
*address
, Set
**ret
) {
259 _cleanup_set_free_free_ Set
*addresses
= NULL
;
260 struct in6_addr addr
;
269 addresses
= set_new(&address_hash_ops
);
273 addr
= address
->in_addr
.in6
;
274 ORDERED_HASHMAP_FOREACH(j
, link
->network
->ipv6_tokens
, i
) {
275 bool have_address
= false;
276 _cleanup_(address_freep
) Address
*new_address
= NULL
;
278 r
= address_new(&new_address
);
282 *new_address
= *address
;
284 if (j
->address_generation_type
== IPV6_TOKEN_ADDRESS_GENERATION_PREFIXSTABLE
285 && memcmp(&j
->prefix
, &addr
, FAMILY_ADDRESS_SIZE(address
->family
)) == 0) {
286 /* While this loop uses dad_counter and a retry limit as specified in RFC 7217, the loop
287 does not actually attempt Duplicate Address Detection; the counter will be incremented
288 only when the address generation algorithm produces an invalid address, and the loop
289 may exit with an address which ends up being unusable due to duplication on the link.
291 for (; j
->dad_counter
< DAD_CONFLICTS_IDGEN_RETRIES_RFC7217
; j
->dad_counter
++) {
292 r
= make_stableprivate_address(link
, &j
->prefix
, prefixlen
, j
->dad_counter
, &new_address
->in_addr
.in6
);
296 if (stableprivate_address_is_valid(&new_address
->in_addr
.in6
)) {
301 } else if (j
->address_generation_type
== IPV6_TOKEN_ADDRESS_GENERATION_STATIC
) {
302 memcpy(new_address
->in_addr
.in6
.s6_addr
+ 8, j
->prefix
.s6_addr
+ 8, 8);
307 new_address
->prefixlen
= prefixlen
;
308 new_address
->flags
= IFA_F_NOPREFIXROUTE
|IFA_F_MANAGETEMPADDR
;
309 new_address
->cinfo
.ifa_prefered
= lifetime_preferred
;
311 r
= set_put(addresses
, new_address
);
313 return log_link_warning_errno(link
, r
, "Failed to store address: %m");
314 TAKE_PTR(new_address
);
318 /* fall back to EUI-64 if no tokens provided addresses */
319 if (set_isempty(addresses
)) {
320 _cleanup_(address_freep
) Address
*new_address
= NULL
;
322 r
= address_new(&new_address
);
326 *new_address
= *address
;
328 r
= generate_ipv6_eui_64_address(link
, &new_address
->in_addr
.in6
);
330 return log_link_error_errno(link
, r
, "Failed to generate EUI64 address: %m");
332 new_address
->prefixlen
= prefixlen
;
333 new_address
->flags
= IFA_F_NOPREFIXROUTE
|IFA_F_MANAGETEMPADDR
;
334 new_address
->cinfo
.ifa_prefered
= lifetime_preferred
;
336 r
= set_put(addresses
, new_address
);
338 return log_link_warning_errno(link
, r
, "Failed to store address: %m");
339 TAKE_PTR(new_address
);
342 *ret
= TAKE_PTR(addresses
);
347 static int ndisc_router_process_autonomous_prefix(Link
*link
, sd_ndisc_router
*rt
) {
348 uint32_t lifetime_valid
, lifetime_preferred
, lifetime_remaining
;
349 _cleanup_set_free_free_ Set
*addresses
= NULL
;
350 _cleanup_(address_freep
) Address
*address
= NULL
;
353 Address
*existing_address
, *a
;
360 r
= sd_ndisc_router_get_timestamp(rt
, clock_boottime_or_monotonic(), &time_now
);
362 return log_link_warning_errno(link
, r
, "Failed to get RA timestamp: %m");
364 r
= sd_ndisc_router_prefix_get_prefixlen(rt
, &prefixlen
);
366 return log_link_error_errno(link
, r
, "Failed to get prefix length: %m");
368 r
= sd_ndisc_router_prefix_get_valid_lifetime(rt
, &lifetime_valid
);
370 return log_link_error_errno(link
, r
, "Failed to get prefix valid lifetime: %m");
372 r
= sd_ndisc_router_prefix_get_preferred_lifetime(rt
, &lifetime_preferred
);
374 return log_link_error_errno(link
, r
, "Failed to get prefix preferred lifetime: %m");
376 /* The preferred lifetime is never greater than the valid lifetime */
377 if (lifetime_preferred
> lifetime_valid
)
380 r
= address_new(&address
);
382 return log_link_error_errno(link
, r
, "Could not allocate address: %m");
384 address
->family
= AF_INET6
;
385 r
= sd_ndisc_router_prefix_get_address(rt
, &address
->in_addr
.in6
);
387 return log_link_error_errno(link
, r
, "Failed to get prefix address: %m");
389 r
= ndisc_router_generate_addresses(link
, prefixlen
, lifetime_preferred
, address
, &addresses
);
391 return log_link_error_errno(link
, r
, "Failed to generate SLAAC addresses: %m");
393 SET_FOREACH(a
, addresses
, i
) {
394 /* see RFC4862 section 5.5.3.e */
395 r
= address_get(link
, a
->family
, &a
->in_addr
, a
->prefixlen
, &existing_address
);
397 lifetime_remaining
= existing_address
->cinfo
.tstamp
/ 100 + existing_address
->cinfo
.ifa_valid
- time_now
/ USEC_PER_SEC
;
398 if (lifetime_valid
> NDISC_PREFIX_LFT_MIN
|| lifetime_valid
> lifetime_remaining
)
399 a
->cinfo
.ifa_valid
= lifetime_valid
;
400 else if (lifetime_remaining
<= NDISC_PREFIX_LFT_MIN
)
401 a
->cinfo
.ifa_valid
= lifetime_remaining
;
403 a
->cinfo
.ifa_valid
= NDISC_PREFIX_LFT_MIN
;
404 } else if (lifetime_valid
> 0)
405 a
->cinfo
.ifa_valid
= lifetime_valid
;
407 return 0; /* see RFC4862 section 5.5.3.d */
409 if (a
->cinfo
.ifa_valid
== 0)
412 r
= address_configure(a
, link
, ndisc_netlink_address_message_handler
, true);
414 log_link_warning_errno(link
, r
, "Could not set SLAAC address: %m");
415 link_enter_failed(link
);
420 link
->ndisc_messages
++;
426 static int ndisc_router_process_onlink_prefix(Link
*link
, sd_ndisc_router
*rt
) {
427 _cleanup_(route_freep
) Route
*route
= NULL
;
436 r
= sd_ndisc_router_get_timestamp(rt
, clock_boottime_or_monotonic(), &time_now
);
438 return log_link_warning_errno(link
, r
, "Failed to get RA timestamp: %m");
440 r
= sd_ndisc_router_prefix_get_prefixlen(rt
, &prefixlen
);
442 return log_link_error_errno(link
, r
, "Failed to get prefix length: %m");
444 r
= sd_ndisc_router_prefix_get_valid_lifetime(rt
, &lifetime
);
446 return log_link_error_errno(link
, r
, "Failed to get prefix lifetime: %m");
448 r
= route_new(&route
);
450 return log_link_error_errno(link
, r
, "Could not allocate route: %m");
452 route
->family
= AF_INET6
;
453 route
->table
= link_get_ipv6_accept_ra_route_table(link
);
454 route
->priority
= link
->network
->dhcp6_route_metric
;
455 route
->protocol
= RTPROT_RA
;
456 route
->flags
= RTM_F_PREFIX
;
457 route
->dst_prefixlen
= prefixlen
;
458 route
->lifetime
= time_now
+ lifetime
* USEC_PER_SEC
;
460 r
= sd_ndisc_router_prefix_get_address(rt
, &route
->dst
.in6
);
462 return log_link_error_errno(link
, r
, "Failed to get prefix address: %m");
464 r
= route_configure(route
, link
, ndisc_netlink_route_message_handler
);
466 log_link_warning_errno(link
, r
, "Could not set prefix route: %m");
467 link_enter_failed(link
);
471 link
->ndisc_messages
++;
476 static int ndisc_router_process_route(Link
*link
, sd_ndisc_router
*rt
) {
477 _cleanup_(route_freep
) Route
*route
= NULL
;
478 struct in6_addr gateway
;
480 unsigned preference
, prefixlen
;
486 r
= sd_ndisc_router_route_get_lifetime(rt
, &lifetime
);
488 return log_link_warning_errno(link
, r
, "Failed to get gateway address from RA: %m");
493 r
= sd_ndisc_router_get_address(rt
, &gateway
);
495 return log_link_warning_errno(link
, r
, "Failed to get gateway address from RA: %m");
497 r
= sd_ndisc_router_route_get_prefixlen(rt
, &prefixlen
);
499 return log_link_warning_errno(link
, r
, "Failed to get route prefix length: %m");
501 r
= sd_ndisc_router_route_get_preference(rt
, &preference
);
503 return log_link_warning_errno(link
, r
, "Failed to get default router preference from RA: %m");
505 r
= sd_ndisc_router_get_timestamp(rt
, clock_boottime_or_monotonic(), &time_now
);
507 return log_link_warning_errno(link
, r
, "Failed to get RA timestamp: %m");
509 r
= route_new(&route
);
511 return log_link_error_errno(link
, r
, "Could not allocate route: %m");
513 route
->family
= AF_INET6
;
514 route
->table
= link_get_ipv6_accept_ra_route_table(link
);
515 route
->priority
= link
->network
->dhcp6_route_metric
;
516 route
->protocol
= RTPROT_RA
;
517 route
->pref
= preference
;
518 route
->gw
.in6
= gateway
;
519 route
->dst_prefixlen
= prefixlen
;
520 route
->lifetime
= time_now
+ lifetime
* USEC_PER_SEC
;
522 r
= sd_ndisc_router_route_get_address(rt
, &route
->dst
.in6
);
524 return log_link_error_errno(link
, r
, "Failed to get route address: %m");
526 r
= route_configure(route
, link
, ndisc_netlink_route_message_handler
);
528 log_link_warning_errno(link
, r
, "Could not set additional route: %m");
529 link_enter_failed(link
);
533 link
->ndisc_messages
++;
538 static void ndisc_rdnss_hash_func(const NDiscRDNSS
*x
, struct siphash
*state
) {
539 siphash24_compress(&x
->address
, sizeof(x
->address
), state
);
542 static int ndisc_rdnss_compare_func(const NDiscRDNSS
*a
, const NDiscRDNSS
*b
) {
543 return memcmp(&a
->address
, &b
->address
, sizeof(a
->address
));
546 DEFINE_PRIVATE_HASH_OPS(ndisc_rdnss_hash_ops
, NDiscRDNSS
, ndisc_rdnss_hash_func
, ndisc_rdnss_compare_func
);
548 static int ndisc_router_process_rdnss(Link
*link
, sd_ndisc_router
*rt
) {
550 const struct in6_addr
*a
;
557 r
= sd_ndisc_router_get_timestamp(rt
, clock_boottime_or_monotonic(), &time_now
);
559 return log_link_warning_errno(link
, r
, "Failed to get RA timestamp: %m");
561 r
= sd_ndisc_router_rdnss_get_lifetime(rt
, &lifetime
);
563 return log_link_warning_errno(link
, r
, "Failed to get RDNSS lifetime: %m");
565 n
= sd_ndisc_router_rdnss_get_addresses(rt
, &a
);
567 return log_link_warning_errno(link
, n
, "Failed to get RDNSS addresses: %m");
569 for (i
= 0; i
< n
; i
++) {
570 _cleanup_free_ NDiscRDNSS
*x
= NULL
;
576 (void) set_remove(link
->ndisc_rdnss
, &d
);
581 y
= set_get(link
->ndisc_rdnss
, &d
);
583 y
->valid_until
= time_now
+ lifetime
* USEC_PER_SEC
;
589 if (set_size(link
->ndisc_rdnss
) >= NDISC_RDNSS_MAX
) {
590 log_link_warning(link
, "Too many RDNSS records per link, ignoring.");
594 x
= new(NDiscRDNSS
, 1);
600 .valid_until
= time_now
+ lifetime
* USEC_PER_SEC
,
603 r
= set_ensure_consume(&link
->ndisc_rdnss
, &ndisc_rdnss_hash_ops
, TAKE_PTR(x
));
614 static void ndisc_dnssl_hash_func(const NDiscDNSSL
*x
, struct siphash
*state
) {
615 siphash24_compress(NDISC_DNSSL_DOMAIN(x
), strlen(NDISC_DNSSL_DOMAIN(x
)), state
);
618 static int ndisc_dnssl_compare_func(const NDiscDNSSL
*a
, const NDiscDNSSL
*b
) {
619 return strcmp(NDISC_DNSSL_DOMAIN(a
), NDISC_DNSSL_DOMAIN(b
));
622 DEFINE_PRIVATE_HASH_OPS(ndisc_dnssl_hash_ops
, NDiscDNSSL
, ndisc_dnssl_hash_func
, ndisc_dnssl_compare_func
);
624 static void ndisc_router_process_dnssl(Link
*link
, sd_ndisc_router
*rt
) {
625 _cleanup_strv_free_
char **l
= NULL
;
634 r
= sd_ndisc_router_get_timestamp(rt
, clock_boottime_or_monotonic(), &time_now
);
636 log_link_warning_errno(link
, r
, "Failed to get RA timestamp: %m");
640 r
= sd_ndisc_router_dnssl_get_lifetime(rt
, &lifetime
);
642 log_link_warning_errno(link
, r
, "Failed to get RDNSS lifetime: %m");
646 r
= sd_ndisc_router_dnssl_get_domains(rt
, &l
);
648 log_link_warning_errno(link
, r
, "Failed to get RDNSS addresses: %m");
653 _cleanup_free_ NDiscDNSSL
*s
;
656 s
= malloc0(ALIGN(sizeof(NDiscDNSSL
)) + strlen(*i
) + 1);
662 strcpy(NDISC_DNSSL_DOMAIN(s
), *i
);
665 (void) set_remove(link
->ndisc_dnssl
, s
);
670 x
= set_get(link
->ndisc_dnssl
, s
);
672 x
->valid_until
= time_now
+ lifetime
* USEC_PER_SEC
;
678 if (set_size(link
->ndisc_dnssl
) >= NDISC_DNSSL_MAX
) {
679 log_link_warning(link
, "Too many DNSSL records per link, ignoring.");
683 s
->valid_until
= time_now
+ lifetime
* USEC_PER_SEC
;
685 r
= set_ensure_consume(&link
->ndisc_dnssl
, &ndisc_dnssl_hash_ops
, TAKE_PTR(s
));
696 static int ndisc_router_process_options(Link
*link
, sd_ndisc_router
*rt
) {
700 assert(link
->network
);
703 r
= sd_ndisc_router_option_rewind(rt
);
708 return log_link_warning_errno(link
, r
, "Failed to iterate through options: %m");
709 if (r
== 0) /* EOF */
712 r
= sd_ndisc_router_option_get_type(rt
, &type
);
714 return log_link_warning_errno(link
, r
, "Failed to get RA option type: %m");
718 case SD_NDISC_OPTION_PREFIX_INFORMATION
: {
719 union in_addr_union a
;
722 r
= sd_ndisc_router_prefix_get_address(rt
, &a
.in6
);
724 return log_link_error_errno(link
, r
, "Failed to get prefix address: %m");
726 if (set_contains(link
->network
->ndisc_black_listed_prefix
, &a
.in6
)) {
728 _cleanup_free_
char *b
= NULL
;
730 (void) in_addr_to_string(AF_INET6
, &a
, &b
);
731 log_link_debug(link
, "Prefix '%s' is black listed, ignoring", strna(b
));
737 r
= sd_ndisc_router_prefix_get_flags(rt
, &flags
);
739 return log_link_warning_errno(link
, r
, "Failed to get RA prefix flags: %m");
741 if (link
->network
->ipv6_accept_ra_use_onlink_prefix
&&
742 FLAGS_SET(flags
, ND_OPT_PI_FLAG_ONLINK
))
743 (void) ndisc_router_process_onlink_prefix(link
, rt
);
745 if (link
->network
->ipv6_accept_ra_use_autonomous_prefix
&&
746 FLAGS_SET(flags
, ND_OPT_PI_FLAG_AUTO
))
747 (void) ndisc_router_process_autonomous_prefix(link
, rt
);
752 case SD_NDISC_OPTION_ROUTE_INFORMATION
:
753 (void) ndisc_router_process_route(link
, rt
);
756 case SD_NDISC_OPTION_RDNSS
:
757 if (link
->network
->ipv6_accept_ra_use_dns
)
758 (void) ndisc_router_process_rdnss(link
, rt
);
761 case SD_NDISC_OPTION_DNSSL
:
762 if (link
->network
->ipv6_accept_ra_use_dns
)
763 (void) ndisc_router_process_dnssl(link
, rt
);
767 r
= sd_ndisc_router_option_next(rt
);
773 static int ndisc_router_handler(Link
*link
, sd_ndisc_router
*rt
) {
778 assert(link
->network
);
779 assert(link
->manager
);
782 r
= sd_ndisc_router_get_flags(rt
, &flags
);
784 return log_link_warning_errno(link
, r
, "Failed to get RA flags: %m");
786 if ((flags
& (ND_RA_FLAG_MANAGED
| ND_RA_FLAG_OTHER
) && link
->network
->ipv6_accept_ra_start_dhcp6_client
)) {
788 if (link
->network
->ipv6_accept_ra_start_dhcp6_client
== IPV6_ACCEPT_RA_START_DHCP6_CLIENT_ALWAYS
)
789 r
= dhcp6_request_address(link
, false);
791 /* (re)start DHCPv6 client in stateful or stateless mode according to RA flags */
792 r
= dhcp6_request_address(link
, !(flags
& ND_RA_FLAG_MANAGED
));
794 if (r
< 0 && r
!= -EBUSY
)
795 log_link_warning_errno(link
, r
, "Could not acquire DHCPv6 lease on NDisc request: %m");
797 log_link_debug(link
, "Acquiring DHCPv6 lease on NDisc request");
802 (void) ndisc_router_process_default(link
, rt
);
803 (void) ndisc_router_process_options(link
, rt
);
808 static void ndisc_handler(sd_ndisc
*nd
, sd_ndisc_event event
, sd_ndisc_router
*rt
, void *userdata
) {
809 Link
*link
= userdata
;
813 if (IN_SET(link
->state
, LINK_STATE_FAILED
, LINK_STATE_LINGER
))
818 case SD_NDISC_EVENT_ROUTER
:
819 (void) ndisc_router_handler(link
, rt
);
822 case SD_NDISC_EVENT_TIMEOUT
:
823 link
->ndisc_configured
= true;
824 link_check_ready(link
);
828 log_link_warning(link
, "IPv6 Neighbor Discovery unknown event: %d", event
);
832 int ndisc_configure(Link
*link
) {
837 r
= sd_ndisc_new(&link
->ndisc
);
841 r
= sd_ndisc_attach_event(link
->ndisc
, NULL
, 0);
845 r
= sd_ndisc_set_mac(link
->ndisc
, &link
->mac
);
849 r
= sd_ndisc_set_ifindex(link
->ndisc
, link
->ifindex
);
853 r
= sd_ndisc_set_callback(link
->ndisc
, ndisc_handler
, link
);
860 void ndisc_vacuum(Link
*link
) {
868 /* Removes all RDNSS and DNSSL entries whose validity time has passed */
870 time_now
= now(clock_boottime_or_monotonic());
872 SET_FOREACH(r
, link
->ndisc_rdnss
, i
)
873 if (r
->valid_until
< time_now
) {
874 free(set_remove(link
->ndisc_rdnss
, r
));
878 SET_FOREACH(d
, link
->ndisc_dnssl
, i
)
879 if (d
->valid_until
< time_now
) {
880 free(set_remove(link
->ndisc_dnssl
, d
));
885 void ndisc_flush(Link
*link
) {
888 /* Removes all RDNSS and DNSSL entries, without exception */
890 link
->ndisc_rdnss
= set_free_free(link
->ndisc_rdnss
);
891 link
->ndisc_dnssl
= set_free_free(link
->ndisc_dnssl
);
894 int ipv6token_new(IPv6Token
**ret
) {
897 p
= new(IPv6Token
, 1);
902 .address_generation_type
= IPV6_TOKEN_ADDRESS_GENERATION_NONE
,
910 DEFINE_HASH_OPS_WITH_VALUE_DESTRUCTOR(
914 trivial_compare_func
,
918 int config_parse_ndisc_black_listed_prefix(
920 const char *filename
,
923 unsigned section_line
,
930 Network
*network
= data
;
939 if (isempty(rvalue
)) {
940 network
->ndisc_black_listed_prefix
= set_free_free(network
->ndisc_black_listed_prefix
);
945 _cleanup_free_
char *n
= NULL
;
946 _cleanup_free_
struct in6_addr
*a
= NULL
;
947 union in_addr_union ip
;
949 r
= extract_first_word(&p
, &n
, NULL
, 0);
951 log_syntax(unit
, LOG_ERR
, filename
, line
, r
,
952 "Failed to parse NDISC black listed prefix, ignoring assignment: %s",
959 r
= in_addr_from_string(AF_INET6
, n
, &ip
);
961 log_syntax(unit
, LOG_ERR
, filename
, line
, r
,
962 "NDISC black listed prefix is invalid, ignoring assignment: %s", n
);
966 if (set_contains(network
->ndisc_black_listed_prefix
, &ip
.in6
))
969 a
= newdup(struct in6_addr
, &ip
.in6
, 1);
973 r
= set_ensure_consume(&network
->ndisc_black_listed_prefix
, &in6_addr_hash_ops
, TAKE_PTR(a
));
981 int config_parse_address_generation_type(
983 const char *filename
,
986 unsigned section_line
,
993 _cleanup_free_ IPv6Token
*token
= NULL
;
994 union in_addr_union buffer
;
995 Network
*network
= data
;
1004 if (isempty(rvalue
)) {
1005 network
->ipv6_tokens
= ordered_hashmap_free(network
->ipv6_tokens
);
1009 r
= ipv6token_new(&token
);
1013 if ((p
= startswith(rvalue
, "static:")))
1014 token
->address_generation_type
= IPV6_TOKEN_ADDRESS_GENERATION_STATIC
;
1015 else if ((p
= startswith(rvalue
, "prefixstable:")))
1016 token
->address_generation_type
= IPV6_TOKEN_ADDRESS_GENERATION_PREFIXSTABLE
;
1018 token
->address_generation_type
= IPV6_TOKEN_ADDRESS_GENERATION_STATIC
;
1022 r
= in_addr_from_string(AF_INET6
, p
, &buffer
);
1024 log_syntax(unit
, LOG_ERR
, filename
, line
, r
,
1025 "Failed to parse IPv6 %s, ignoring: %s", lvalue
, rvalue
);
1029 if (in_addr_is_null(AF_INET6
, &buffer
)) {
1030 log_syntax(unit
, LOG_ERR
, filename
, line
, 0,
1031 "IPv6 %s cannot be the ANY address, ignoring: %s", lvalue
, rvalue
);
1035 token
->prefix
= buffer
.in6
;
1037 r
= ordered_hashmap_ensure_allocated(&network
->ipv6_tokens
, &ipv6_token_hash_ops
);
1041 r
= ordered_hashmap_put(network
->ipv6_tokens
, &token
->prefix
, token
);
1043 log_syntax(unit
, LOG_ERR
, filename
, line
, r
,
1044 "Failed to store IPv6 token '%s'", rvalue
);
1053 DEFINE_CONFIG_PARSE_ENUM(config_parse_ipv6_accept_ra_start_dhcp6_client
, ipv6_accept_ra_start_dhcp6_client
, IPv6AcceptRAStartDHCP6Client
,
1054 "Failed to parse DHCPv6Client= setting")
1055 static const char* const ipv6_accept_ra_start_dhcp6_client_table
[_IPV6_ACCEPT_RA_START_DHCP6_CLIENT_MAX
] = {
1056 [IPV6_ACCEPT_RA_START_DHCP6_CLIENT_NO
] = "no",
1057 [IPV6_ACCEPT_RA_START_DHCP6_CLIENT_ALWAYS
] = "always",
1058 [IPV6_ACCEPT_RA_START_DHCP6_CLIENT_YES
] = "yes",
1061 DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(ipv6_accept_ra_start_dhcp6_client
, IPv6AcceptRAStartDHCP6Client
, IPV6_ACCEPT_RA_START_DHCP6_CLIENT_YES
);