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 r
= set_ensure_allocated(&link
->ndisc_rdnss
, &ndisc_rdnss_hash_ops
);
598 x
= new(NDiscRDNSS
, 1);
604 .valid_until
= time_now
+ lifetime
* USEC_PER_SEC
,
607 r
= set_put(link
->ndisc_rdnss
, x
);
620 static void ndisc_dnssl_hash_func(const NDiscDNSSL
*x
, struct siphash
*state
) {
621 siphash24_compress(NDISC_DNSSL_DOMAIN(x
), strlen(NDISC_DNSSL_DOMAIN(x
)), state
);
624 static int ndisc_dnssl_compare_func(const NDiscDNSSL
*a
, const NDiscDNSSL
*b
) {
625 return strcmp(NDISC_DNSSL_DOMAIN(a
), NDISC_DNSSL_DOMAIN(b
));
628 DEFINE_PRIVATE_HASH_OPS(ndisc_dnssl_hash_ops
, NDiscDNSSL
, ndisc_dnssl_hash_func
, ndisc_dnssl_compare_func
);
630 static void ndisc_router_process_dnssl(Link
*link
, sd_ndisc_router
*rt
) {
631 _cleanup_strv_free_
char **l
= NULL
;
640 r
= sd_ndisc_router_get_timestamp(rt
, clock_boottime_or_monotonic(), &time_now
);
642 log_link_warning_errno(link
, r
, "Failed to get RA timestamp: %m");
646 r
= sd_ndisc_router_dnssl_get_lifetime(rt
, &lifetime
);
648 log_link_warning_errno(link
, r
, "Failed to get RDNSS lifetime: %m");
652 r
= sd_ndisc_router_dnssl_get_domains(rt
, &l
);
654 log_link_warning_errno(link
, r
, "Failed to get RDNSS addresses: %m");
659 _cleanup_free_ NDiscDNSSL
*s
;
662 s
= malloc0(ALIGN(sizeof(NDiscDNSSL
)) + strlen(*i
) + 1);
668 strcpy(NDISC_DNSSL_DOMAIN(s
), *i
);
671 (void) set_remove(link
->ndisc_dnssl
, s
);
676 x
= set_get(link
->ndisc_dnssl
, s
);
678 x
->valid_until
= time_now
+ lifetime
* USEC_PER_SEC
;
684 if (set_size(link
->ndisc_dnssl
) >= NDISC_DNSSL_MAX
) {
685 log_link_warning(link
, "Too many DNSSL records per link, ignoring.");
689 r
= set_ensure_allocated(&link
->ndisc_dnssl
, &ndisc_dnssl_hash_ops
);
695 s
->valid_until
= time_now
+ lifetime
* USEC_PER_SEC
;
697 r
= set_put(link
->ndisc_dnssl
, s
);
709 static int ndisc_router_process_options(Link
*link
, sd_ndisc_router
*rt
) {
713 assert(link
->network
);
716 r
= sd_ndisc_router_option_rewind(rt
);
721 return log_link_warning_errno(link
, r
, "Failed to iterate through options: %m");
722 if (r
== 0) /* EOF */
725 r
= sd_ndisc_router_option_get_type(rt
, &type
);
727 return log_link_warning_errno(link
, r
, "Failed to get RA option type: %m");
731 case SD_NDISC_OPTION_PREFIX_INFORMATION
: {
732 union in_addr_union a
;
735 r
= sd_ndisc_router_prefix_get_address(rt
, &a
.in6
);
737 return log_link_error_errno(link
, r
, "Failed to get prefix address: %m");
739 if (set_contains(link
->network
->ndisc_black_listed_prefix
, &a
.in6
)) {
741 _cleanup_free_
char *b
= NULL
;
743 (void) in_addr_to_string(AF_INET6
, &a
, &b
);
744 log_link_debug(link
, "Prefix '%s' is black listed, ignoring", strna(b
));
750 r
= sd_ndisc_router_prefix_get_flags(rt
, &flags
);
752 return log_link_warning_errno(link
, r
, "Failed to get RA prefix flags: %m");
754 if (link
->network
->ipv6_accept_ra_use_onlink_prefix
&&
755 FLAGS_SET(flags
, ND_OPT_PI_FLAG_ONLINK
))
756 (void) ndisc_router_process_onlink_prefix(link
, rt
);
758 if (link
->network
->ipv6_accept_ra_use_autonomous_prefix
&&
759 FLAGS_SET(flags
, ND_OPT_PI_FLAG_AUTO
))
760 (void) ndisc_router_process_autonomous_prefix(link
, rt
);
765 case SD_NDISC_OPTION_ROUTE_INFORMATION
:
766 (void) ndisc_router_process_route(link
, rt
);
769 case SD_NDISC_OPTION_RDNSS
:
770 if (link
->network
->ipv6_accept_ra_use_dns
)
771 (void) ndisc_router_process_rdnss(link
, rt
);
774 case SD_NDISC_OPTION_DNSSL
:
775 if (link
->network
->ipv6_accept_ra_use_dns
)
776 (void) ndisc_router_process_dnssl(link
, rt
);
780 r
= sd_ndisc_router_option_next(rt
);
786 static int ndisc_router_handler(Link
*link
, sd_ndisc_router
*rt
) {
791 assert(link
->network
);
792 assert(link
->manager
);
795 r
= sd_ndisc_router_get_flags(rt
, &flags
);
797 return log_link_warning_errno(link
, r
, "Failed to get RA flags: %m");
799 if ((flags
& (ND_RA_FLAG_MANAGED
| ND_RA_FLAG_OTHER
) && link
->network
->ipv6_accept_ra_start_dhcp6_client
)) {
801 if (link
->network
->ipv6_accept_ra_start_dhcp6_client
== IPV6_ACCEPT_RA_START_DHCP6_CLIENT_ALWAYS
)
802 r
= dhcp6_request_address(link
, false);
804 /* (re)start DHCPv6 client in stateful or stateless mode according to RA flags */
805 r
= dhcp6_request_address(link
, !(flags
& ND_RA_FLAG_MANAGED
));
807 if (r
< 0 && r
!= -EBUSY
)
808 log_link_warning_errno(link
, r
, "Could not acquire DHCPv6 lease on NDisc request: %m");
810 log_link_debug(link
, "Acquiring DHCPv6 lease on NDisc request");
815 (void) ndisc_router_process_default(link
, rt
);
816 (void) ndisc_router_process_options(link
, rt
);
821 static void ndisc_handler(sd_ndisc
*nd
, sd_ndisc_event event
, sd_ndisc_router
*rt
, void *userdata
) {
822 Link
*link
= userdata
;
826 if (IN_SET(link
->state
, LINK_STATE_FAILED
, LINK_STATE_LINGER
))
831 case SD_NDISC_EVENT_ROUTER
:
832 (void) ndisc_router_handler(link
, rt
);
835 case SD_NDISC_EVENT_TIMEOUT
:
836 link
->ndisc_configured
= true;
837 link_check_ready(link
);
841 log_link_warning(link
, "IPv6 Neighbor Discovery unknown event: %d", event
);
845 int ndisc_configure(Link
*link
) {
850 r
= sd_ndisc_new(&link
->ndisc
);
854 r
= sd_ndisc_attach_event(link
->ndisc
, NULL
, 0);
858 r
= sd_ndisc_set_mac(link
->ndisc
, &link
->mac
);
862 r
= sd_ndisc_set_ifindex(link
->ndisc
, link
->ifindex
);
866 r
= sd_ndisc_set_callback(link
->ndisc
, ndisc_handler
, link
);
873 void ndisc_vacuum(Link
*link
) {
881 /* Removes all RDNSS and DNSSL entries whose validity time has passed */
883 time_now
= now(clock_boottime_or_monotonic());
885 SET_FOREACH(r
, link
->ndisc_rdnss
, i
)
886 if (r
->valid_until
< time_now
) {
887 free(set_remove(link
->ndisc_rdnss
, r
));
891 SET_FOREACH(d
, link
->ndisc_dnssl
, i
)
892 if (d
->valid_until
< time_now
) {
893 free(set_remove(link
->ndisc_dnssl
, d
));
898 void ndisc_flush(Link
*link
) {
901 /* Removes all RDNSS and DNSSL entries, without exception */
903 link
->ndisc_rdnss
= set_free_free(link
->ndisc_rdnss
);
904 link
->ndisc_dnssl
= set_free_free(link
->ndisc_dnssl
);
907 int ipv6token_new(IPv6Token
**ret
) {
910 p
= new(IPv6Token
, 1);
915 .address_generation_type
= IPV6_TOKEN_ADDRESS_GENERATION_NONE
,
923 DEFINE_HASH_OPS_WITH_VALUE_DESTRUCTOR(
927 trivial_compare_func
,
931 int config_parse_ndisc_black_listed_prefix(
933 const char *filename
,
936 unsigned section_line
,
943 Network
*network
= data
;
952 if (isempty(rvalue
)) {
953 network
->ndisc_black_listed_prefix
= set_free_free(network
->ndisc_black_listed_prefix
);
958 _cleanup_free_
char *n
= NULL
;
959 _cleanup_free_
struct in6_addr
*a
= NULL
;
960 union in_addr_union ip
;
962 r
= extract_first_word(&p
, &n
, NULL
, 0);
964 log_syntax(unit
, LOG_ERR
, filename
, line
, r
,
965 "Failed to parse NDISC black listed prefix, ignoring assignment: %s",
972 r
= in_addr_from_string(AF_INET6
, n
, &ip
);
974 log_syntax(unit
, LOG_ERR
, filename
, line
, r
,
975 "NDISC black listed prefix is invalid, ignoring assignment: %s", n
);
979 if (set_contains(network
->ndisc_black_listed_prefix
, &ip
.in6
))
982 r
= set_ensure_allocated(&network
->ndisc_black_listed_prefix
, &in6_addr_hash_ops
);
986 a
= newdup(struct in6_addr
, &ip
.in6
, 1);
990 r
= set_put(network
->ndisc_black_listed_prefix
, a
);
992 log_syntax(unit
, LOG_ERR
, filename
, line
, r
,
993 "Failed to store NDISC black listed prefix '%s', ignoring assignment: %m", n
);
1003 int config_parse_address_generation_type(
1005 const char *filename
,
1007 const char *section
,
1008 unsigned section_line
,
1015 _cleanup_free_ IPv6Token
*token
= NULL
;
1016 union in_addr_union buffer
;
1017 Network
*network
= data
;
1026 if (isempty(rvalue
)) {
1027 network
->ipv6_tokens
= ordered_hashmap_free(network
->ipv6_tokens
);
1031 r
= ipv6token_new(&token
);
1035 if ((p
= startswith(rvalue
, "static:")))
1036 token
->address_generation_type
= IPV6_TOKEN_ADDRESS_GENERATION_STATIC
;
1037 else if ((p
= startswith(rvalue
, "prefixstable:")))
1038 token
->address_generation_type
= IPV6_TOKEN_ADDRESS_GENERATION_PREFIXSTABLE
;
1040 token
->address_generation_type
= IPV6_TOKEN_ADDRESS_GENERATION_STATIC
;
1044 r
= in_addr_from_string(AF_INET6
, p
, &buffer
);
1046 log_syntax(unit
, LOG_ERR
, filename
, line
, r
,
1047 "Failed to parse IPv6 %s, ignoring: %s", lvalue
, rvalue
);
1051 if (in_addr_is_null(AF_INET6
, &buffer
)) {
1052 log_syntax(unit
, LOG_ERR
, filename
, line
, 0,
1053 "IPv6 %s cannot be the ANY address, ignoring: %s", lvalue
, rvalue
);
1057 token
->prefix
= buffer
.in6
;
1059 r
= ordered_hashmap_ensure_allocated(&network
->ipv6_tokens
, &ipv6_token_hash_ops
);
1063 r
= ordered_hashmap_put(network
->ipv6_tokens
, &token
->prefix
, token
);
1065 log_syntax(unit
, LOG_ERR
, filename
, line
, r
,
1066 "Failed to store IPv6 token '%s'", rvalue
);
1075 DEFINE_CONFIG_PARSE_ENUM(config_parse_ipv6_accept_ra_start_dhcp6_client
, ipv6_accept_ra_start_dhcp6_client
, IPv6AcceptRAStartDHCP6Client
,
1076 "Failed to parse DHCPv6Client= setting")
1077 static const char* const ipv6_accept_ra_start_dhcp6_client_table
[_IPV6_ACCEPT_RA_START_DHCP6_CLIENT_MAX
] = {
1078 [IPV6_ACCEPT_RA_START_DHCP6_CLIENT_NO
] = "no",
1079 [IPV6_ACCEPT_RA_START_DHCP6_CLIENT_ALWAYS
] = "always",
1080 [IPV6_ACCEPT_RA_START_DHCP6_CLIENT_YES
] = "yes",
1083 DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(ipv6_accept_ra_start_dhcp6_client
, IPv6AcceptRAStartDHCP6Client
, IPV6_ACCEPT_RA_START_DHCP6_CLIENT_YES
);