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_put(&link
->ndisc_rdnss
, &ndisc_rdnss_hash_ops
, x
);
615 static void ndisc_dnssl_hash_func(const NDiscDNSSL
*x
, struct siphash
*state
) {
616 siphash24_compress(NDISC_DNSSL_DOMAIN(x
), strlen(NDISC_DNSSL_DOMAIN(x
)), state
);
619 static int ndisc_dnssl_compare_func(const NDiscDNSSL
*a
, const NDiscDNSSL
*b
) {
620 return strcmp(NDISC_DNSSL_DOMAIN(a
), NDISC_DNSSL_DOMAIN(b
));
623 DEFINE_PRIVATE_HASH_OPS(ndisc_dnssl_hash_ops
, NDiscDNSSL
, ndisc_dnssl_hash_func
, ndisc_dnssl_compare_func
);
625 static void ndisc_router_process_dnssl(Link
*link
, sd_ndisc_router
*rt
) {
626 _cleanup_strv_free_
char **l
= NULL
;
635 r
= sd_ndisc_router_get_timestamp(rt
, clock_boottime_or_monotonic(), &time_now
);
637 log_link_warning_errno(link
, r
, "Failed to get RA timestamp: %m");
641 r
= sd_ndisc_router_dnssl_get_lifetime(rt
, &lifetime
);
643 log_link_warning_errno(link
, r
, "Failed to get RDNSS lifetime: %m");
647 r
= sd_ndisc_router_dnssl_get_domains(rt
, &l
);
649 log_link_warning_errno(link
, r
, "Failed to get RDNSS addresses: %m");
654 _cleanup_free_ NDiscDNSSL
*s
;
657 s
= malloc0(ALIGN(sizeof(NDiscDNSSL
)) + strlen(*i
) + 1);
663 strcpy(NDISC_DNSSL_DOMAIN(s
), *i
);
666 (void) set_remove(link
->ndisc_dnssl
, s
);
671 x
= set_get(link
->ndisc_dnssl
, s
);
673 x
->valid_until
= time_now
+ lifetime
* USEC_PER_SEC
;
679 if (set_size(link
->ndisc_dnssl
) >= NDISC_DNSSL_MAX
) {
680 log_link_warning(link
, "Too many DNSSL records per link, ignoring.");
684 s
->valid_until
= time_now
+ lifetime
* USEC_PER_SEC
;
686 r
= set_ensure_put(&link
->ndisc_dnssl
, &ndisc_dnssl_hash_ops
, s
);
698 static int ndisc_router_process_options(Link
*link
, sd_ndisc_router
*rt
) {
702 assert(link
->network
);
705 r
= sd_ndisc_router_option_rewind(rt
);
710 return log_link_warning_errno(link
, r
, "Failed to iterate through options: %m");
711 if (r
== 0) /* EOF */
714 r
= sd_ndisc_router_option_get_type(rt
, &type
);
716 return log_link_warning_errno(link
, r
, "Failed to get RA option type: %m");
720 case SD_NDISC_OPTION_PREFIX_INFORMATION
: {
721 union in_addr_union a
;
724 r
= sd_ndisc_router_prefix_get_address(rt
, &a
.in6
);
726 return log_link_error_errno(link
, r
, "Failed to get prefix address: %m");
728 if (set_contains(link
->network
->ndisc_black_listed_prefix
, &a
.in6
)) {
730 _cleanup_free_
char *b
= NULL
;
732 (void) in_addr_to_string(AF_INET6
, &a
, &b
);
733 log_link_debug(link
, "Prefix '%s' is black listed, ignoring", strna(b
));
739 r
= sd_ndisc_router_prefix_get_flags(rt
, &flags
);
741 return log_link_warning_errno(link
, r
, "Failed to get RA prefix flags: %m");
743 if (link
->network
->ipv6_accept_ra_use_onlink_prefix
&&
744 FLAGS_SET(flags
, ND_OPT_PI_FLAG_ONLINK
))
745 (void) ndisc_router_process_onlink_prefix(link
, rt
);
747 if (link
->network
->ipv6_accept_ra_use_autonomous_prefix
&&
748 FLAGS_SET(flags
, ND_OPT_PI_FLAG_AUTO
))
749 (void) ndisc_router_process_autonomous_prefix(link
, rt
);
754 case SD_NDISC_OPTION_ROUTE_INFORMATION
:
755 (void) ndisc_router_process_route(link
, rt
);
758 case SD_NDISC_OPTION_RDNSS
:
759 if (link
->network
->ipv6_accept_ra_use_dns
)
760 (void) ndisc_router_process_rdnss(link
, rt
);
763 case SD_NDISC_OPTION_DNSSL
:
764 if (link
->network
->ipv6_accept_ra_use_dns
)
765 (void) ndisc_router_process_dnssl(link
, rt
);
769 r
= sd_ndisc_router_option_next(rt
);
775 static int ndisc_router_handler(Link
*link
, sd_ndisc_router
*rt
) {
780 assert(link
->network
);
781 assert(link
->manager
);
784 r
= sd_ndisc_router_get_flags(rt
, &flags
);
786 return log_link_warning_errno(link
, r
, "Failed to get RA flags: %m");
788 if ((flags
& (ND_RA_FLAG_MANAGED
| ND_RA_FLAG_OTHER
) && link
->network
->ipv6_accept_ra_start_dhcp6_client
)) {
790 if (link
->network
->ipv6_accept_ra_start_dhcp6_client
== IPV6_ACCEPT_RA_START_DHCP6_CLIENT_ALWAYS
)
791 r
= dhcp6_request_address(link
, false);
793 /* (re)start DHCPv6 client in stateful or stateless mode according to RA flags */
794 r
= dhcp6_request_address(link
, !(flags
& ND_RA_FLAG_MANAGED
));
796 if (r
< 0 && r
!= -EBUSY
)
797 log_link_warning_errno(link
, r
, "Could not acquire DHCPv6 lease on NDisc request: %m");
799 log_link_debug(link
, "Acquiring DHCPv6 lease on NDisc request");
804 (void) ndisc_router_process_default(link
, rt
);
805 (void) ndisc_router_process_options(link
, rt
);
810 static void ndisc_handler(sd_ndisc
*nd
, sd_ndisc_event event
, sd_ndisc_router
*rt
, void *userdata
) {
811 Link
*link
= userdata
;
815 if (IN_SET(link
->state
, LINK_STATE_FAILED
, LINK_STATE_LINGER
))
820 case SD_NDISC_EVENT_ROUTER
:
821 (void) ndisc_router_handler(link
, rt
);
824 case SD_NDISC_EVENT_TIMEOUT
:
825 link
->ndisc_configured
= true;
826 link_check_ready(link
);
830 log_link_warning(link
, "IPv6 Neighbor Discovery unknown event: %d", event
);
834 int ndisc_configure(Link
*link
) {
839 r
= sd_ndisc_new(&link
->ndisc
);
843 r
= sd_ndisc_attach_event(link
->ndisc
, NULL
, 0);
847 r
= sd_ndisc_set_mac(link
->ndisc
, &link
->mac
);
851 r
= sd_ndisc_set_ifindex(link
->ndisc
, link
->ifindex
);
855 r
= sd_ndisc_set_callback(link
->ndisc
, ndisc_handler
, link
);
862 void ndisc_vacuum(Link
*link
) {
870 /* Removes all RDNSS and DNSSL entries whose validity time has passed */
872 time_now
= now(clock_boottime_or_monotonic());
874 SET_FOREACH(r
, link
->ndisc_rdnss
, i
)
875 if (r
->valid_until
< time_now
) {
876 free(set_remove(link
->ndisc_rdnss
, r
));
880 SET_FOREACH(d
, link
->ndisc_dnssl
, i
)
881 if (d
->valid_until
< time_now
) {
882 free(set_remove(link
->ndisc_dnssl
, d
));
887 void ndisc_flush(Link
*link
) {
890 /* Removes all RDNSS and DNSSL entries, without exception */
892 link
->ndisc_rdnss
= set_free_free(link
->ndisc_rdnss
);
893 link
->ndisc_dnssl
= set_free_free(link
->ndisc_dnssl
);
896 int ipv6token_new(IPv6Token
**ret
) {
899 p
= new(IPv6Token
, 1);
904 .address_generation_type
= IPV6_TOKEN_ADDRESS_GENERATION_NONE
,
912 DEFINE_HASH_OPS_WITH_VALUE_DESTRUCTOR(
916 trivial_compare_func
,
920 int config_parse_ndisc_black_listed_prefix(
922 const char *filename
,
925 unsigned section_line
,
932 Network
*network
= data
;
941 if (isempty(rvalue
)) {
942 network
->ndisc_black_listed_prefix
= set_free_free(network
->ndisc_black_listed_prefix
);
947 _cleanup_free_
char *n
= NULL
;
948 _cleanup_free_
struct in6_addr
*a
= NULL
;
949 union in_addr_union ip
;
951 r
= extract_first_word(&p
, &n
, NULL
, 0);
953 log_syntax(unit
, LOG_ERR
, filename
, line
, r
,
954 "Failed to parse NDISC black listed prefix, ignoring assignment: %s",
961 r
= in_addr_from_string(AF_INET6
, n
, &ip
);
963 log_syntax(unit
, LOG_ERR
, filename
, line
, r
,
964 "NDISC black listed prefix is invalid, ignoring assignment: %s", n
);
968 if (set_contains(network
->ndisc_black_listed_prefix
, &ip
.in6
))
971 a
= newdup(struct in6_addr
, &ip
.in6
, 1);
975 r
= set_ensure_put(&network
->ndisc_black_listed_prefix
, &in6_addr_hash_ops
, a
);
977 log_syntax(unit
, LOG_ERR
, filename
, line
, r
,
978 "Failed to store NDISC black listed prefix '%s', ignoring assignment: %m", n
);
987 int config_parse_address_generation_type(
989 const char *filename
,
992 unsigned section_line
,
999 _cleanup_free_ IPv6Token
*token
= NULL
;
1000 union in_addr_union buffer
;
1001 Network
*network
= data
;
1010 if (isempty(rvalue
)) {
1011 network
->ipv6_tokens
= ordered_hashmap_free(network
->ipv6_tokens
);
1015 r
= ipv6token_new(&token
);
1019 if ((p
= startswith(rvalue
, "static:")))
1020 token
->address_generation_type
= IPV6_TOKEN_ADDRESS_GENERATION_STATIC
;
1021 else if ((p
= startswith(rvalue
, "prefixstable:")))
1022 token
->address_generation_type
= IPV6_TOKEN_ADDRESS_GENERATION_PREFIXSTABLE
;
1024 token
->address_generation_type
= IPV6_TOKEN_ADDRESS_GENERATION_STATIC
;
1028 r
= in_addr_from_string(AF_INET6
, p
, &buffer
);
1030 log_syntax(unit
, LOG_ERR
, filename
, line
, r
,
1031 "Failed to parse IPv6 %s, ignoring: %s", lvalue
, rvalue
);
1035 if (in_addr_is_null(AF_INET6
, &buffer
)) {
1036 log_syntax(unit
, LOG_ERR
, filename
, line
, 0,
1037 "IPv6 %s cannot be the ANY address, ignoring: %s", lvalue
, rvalue
);
1041 token
->prefix
= buffer
.in6
;
1043 r
= ordered_hashmap_ensure_allocated(&network
->ipv6_tokens
, &ipv6_token_hash_ops
);
1047 r
= ordered_hashmap_put(network
->ipv6_tokens
, &token
->prefix
, token
);
1049 log_syntax(unit
, LOG_ERR
, filename
, line
, r
,
1050 "Failed to store IPv6 token '%s'", rvalue
);
1059 DEFINE_CONFIG_PARSE_ENUM(config_parse_ipv6_accept_ra_start_dhcp6_client
, ipv6_accept_ra_start_dhcp6_client
, IPv6AcceptRAStartDHCP6Client
,
1060 "Failed to parse DHCPv6Client= setting")
1061 static const char* const ipv6_accept_ra_start_dhcp6_client_table
[_IPV6_ACCEPT_RA_START_DHCP6_CLIENT_MAX
] = {
1062 [IPV6_ACCEPT_RA_START_DHCP6_CLIENT_NO
] = "no",
1063 [IPV6_ACCEPT_RA_START_DHCP6_CLIENT_ALWAYS
] = "always",
1064 [IPV6_ACCEPT_RA_START_DHCP6_CLIENT_YES
] = "yes",
1067 DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(ipv6_accept_ra_start_dhcp6_client
, IPv6AcceptRAStartDHCP6Client
, IPV6_ACCEPT_RA_START_DHCP6_CLIENT_YES
);