1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
3 Copyright © 2017 Intel Corporation. All rights reserved.
6 #include <netinet/icmp6.h>
9 #include "dns-domain.h"
10 #include "ndisc-router-internal.h"
11 #include "networkd-address-generation.h"
12 #include "networkd-address.h"
13 #include "networkd-dhcp-prefix-delegation.h"
14 #include "networkd-link.h"
15 #include "networkd-manager.h"
16 #include "networkd-network.h"
17 #include "networkd-queue.h"
18 #include "networkd-radv.h"
19 #include "networkd-route-util.h"
20 #include "parse-util.h"
21 #include "radv-internal.h"
22 #include "string-util.h"
23 #include "string-table.h"
26 bool link_radv_enabled(Link
*link
) {
29 if (!link_may_have_ipv6ll(link
, /* check_multicast = */ true))
32 if (link
->hw_addr
.length
!= ETH_ALEN
)
35 return link
->network
->router_prefix_delegation
;
38 Prefix
* prefix_free(Prefix
*prefix
) {
42 if (prefix
->network
) {
43 assert(prefix
->section
);
44 hashmap_remove(prefix
->network
->prefixes_by_section
, prefix
->section
);
47 config_section_free(prefix
->section
);
48 set_free(prefix
->tokens
);
53 DEFINE_SECTION_CLEANUP_FUNCTIONS(Prefix
, prefix_free
);
55 static int prefix_new_static(Network
*network
, const char *filename
, unsigned section_line
, Prefix
**ret
) {
56 _cleanup_(config_section_freep
) ConfigSection
*n
= NULL
;
57 _cleanup_(prefix_freep
) Prefix
*prefix
= NULL
;
63 assert(section_line
> 0);
65 r
= config_section_new(filename
, section_line
, &n
);
69 prefix
= hashmap_get(network
->prefixes_by_section
, n
);
71 *ret
= TAKE_PTR(prefix
);
75 prefix
= new(Prefix
, 1);
81 .section
= TAKE_PTR(n
),
83 .prefix
.flags
= ND_OPT_PI_FLAG_ONLINK
| ND_OPT_PI_FLAG_AUTO
,
84 .prefix
.valid_lifetime
= RADV_DEFAULT_VALID_LIFETIME_USEC
,
85 .prefix
.preferred_lifetime
= RADV_DEFAULT_PREFERRED_LIFETIME_USEC
,
86 .prefix
.valid_until
= USEC_INFINITY
,
87 .prefix
.preferred_until
= USEC_INFINITY
,
90 r
= hashmap_ensure_put(&network
->prefixes_by_section
, &config_section_hash_ops
, prefix
->section
, prefix
);
94 *ret
= TAKE_PTR(prefix
);
98 RoutePrefix
* route_prefix_free(RoutePrefix
*prefix
) {
102 if (prefix
->network
) {
103 assert(prefix
->section
);
104 hashmap_remove(prefix
->network
->route_prefixes_by_section
, prefix
->section
);
107 config_section_free(prefix
->section
);
109 return mfree(prefix
);
112 DEFINE_SECTION_CLEANUP_FUNCTIONS(RoutePrefix
, route_prefix_free
);
114 static int route_prefix_new_static(Network
*network
, const char *filename
, unsigned section_line
, RoutePrefix
**ret
) {
115 _cleanup_(config_section_freep
) ConfigSection
*n
= NULL
;
116 _cleanup_(route_prefix_freep
) RoutePrefix
*prefix
= NULL
;
122 assert(section_line
> 0);
124 r
= config_section_new(filename
, section_line
, &n
);
128 prefix
= hashmap_get(network
->route_prefixes_by_section
, n
);
130 *ret
= TAKE_PTR(prefix
);
134 prefix
= new(RoutePrefix
, 1);
138 *prefix
= (RoutePrefix
) {
140 .section
= TAKE_PTR(n
),
142 .route
.lifetime
= RADV_DEFAULT_VALID_LIFETIME_USEC
,
143 .route
.valid_until
= USEC_INFINITY
,
146 r
= hashmap_ensure_put(&network
->route_prefixes_by_section
, &config_section_hash_ops
, prefix
->section
, prefix
);
150 *ret
= TAKE_PTR(prefix
);
154 Prefix64
* prefix64_free(Prefix64
*prefix
) {
158 if (prefix
->network
) {
159 assert(prefix
->section
);
160 hashmap_remove(prefix
->network
->pref64_prefixes_by_section
, prefix
->section
);
163 config_section_free(prefix
->section
);
165 return mfree(prefix
);
168 DEFINE_SECTION_CLEANUP_FUNCTIONS(Prefix64
, prefix64_free
);
170 static int prefix64_new_static(Network
*network
, const char *filename
, unsigned section_line
, Prefix64
**ret
) {
171 _cleanup_(config_section_freep
) ConfigSection
*n
= NULL
;
172 _cleanup_(prefix64_freep
) Prefix64
*prefix
= NULL
;
178 assert(section_line
> 0);
180 r
= config_section_new(filename
, section_line
, &n
);
184 prefix
= hashmap_get(network
->pref64_prefixes_by_section
, n
);
186 *ret
= TAKE_PTR(prefix
);
190 prefix
= new(Prefix64
, 1);
194 *prefix
= (Prefix64
) {
196 .section
= TAKE_PTR(n
),
198 .prefix64
.lifetime
= RADV_PREF64_DEFAULT_LIFETIME_USEC
,
199 .prefix64
.valid_until
= USEC_INFINITY
,
202 r
= hashmap_ensure_put(&network
->pref64_prefixes_by_section
, &config_section_hash_ops
, prefix
->section
, prefix
);
206 *ret
= TAKE_PTR(prefix
);
210 int link_request_radv_addresses(Link
*link
) {
216 if (!link_radv_enabled(link
))
219 HASHMAP_FOREACH(p
, link
->network
->prefixes_by_section
) {
223 /* radv_generate_addresses() below requires the prefix length <= 64. */
224 if (p
->prefix
.prefixlen
> 64)
227 _cleanup_hashmap_free_ Hashmap
*tokens_by_address
= NULL
;
228 r
= radv_generate_addresses(link
, p
->tokens
, &p
->prefix
.address
, p
->prefix
.prefixlen
, &tokens_by_address
);
234 HASHMAP_FOREACH_KEY(token
, a
, tokens_by_address
) {
235 _cleanup_(address_unrefp
) Address
*address
= NULL
;
237 r
= address_new(&address
);
241 address
->source
= NETWORK_CONFIG_SOURCE_STATIC
;
242 address
->family
= AF_INET6
;
243 address
->in_addr
.in6
= *a
;
244 address
->prefixlen
= p
->prefix
.prefixlen
;
245 address
->route_metric
= p
->route_metric
;
246 address
->token
= ipv6_token_ref(token
);
248 r
= link_request_static_address(link
, address
);
257 int link_reconfigure_radv_address(Address
*address
, Link
*link
) {
261 assert(address
->source
== NETWORK_CONFIG_SOURCE_STATIC
);
264 r
= regenerate_address(address
, link
);
268 r
= link_request_static_address(link
, address
);
272 if (link
->static_address_messages
!= 0) {
273 link
->static_addresses_configured
= false;
274 link_set_state(link
, LINK_STATE_CONFIGURING
);
280 static int radv_set_prefix(Link
*link
, Prefix
*prefix
) {
281 _cleanup_(sd_radv_prefix_unrefp
) sd_radv_prefix
*p
= NULL
;
288 r
= sd_radv_prefix_new(&p
);
292 r
= sd_radv_prefix_set_prefix(p
, &prefix
->prefix
.address
, prefix
->prefix
.prefixlen
);
296 r
= sd_radv_prefix_set_preferred_lifetime(p
, prefix
->prefix
.preferred_lifetime
, prefix
->prefix
.preferred_until
);
300 r
= sd_radv_prefix_set_valid_lifetime(p
, prefix
->prefix
.valid_lifetime
, prefix
->prefix
.valid_until
);
304 r
= sd_radv_prefix_set_onlink(p
, FLAGS_SET(prefix
->prefix
.flags
, ND_OPT_PI_FLAG_ONLINK
));
308 r
= sd_radv_prefix_set_address_autoconfiguration(p
, FLAGS_SET(prefix
->prefix
.flags
, ND_OPT_PI_FLAG_AUTO
));
312 return sd_radv_add_prefix(link
->radv
, p
);
315 static int radv_set_route_prefix(Link
*link
, RoutePrefix
*prefix
) {
316 _cleanup_(sd_radv_route_prefix_unrefp
) sd_radv_route_prefix
*p
= NULL
;
323 r
= sd_radv_route_prefix_new(&p
);
327 r
= sd_radv_route_prefix_set_prefix(p
, &prefix
->route
.address
, prefix
->route
.prefixlen
);
331 r
= sd_radv_route_prefix_set_lifetime(p
, prefix
->route
.lifetime
, prefix
->route
.valid_until
);
335 return sd_radv_add_route_prefix(link
->radv
, p
);
338 static int radv_set_pref64_prefix(Link
*link
, Prefix64
*prefix
) {
339 _cleanup_(sd_radv_pref64_prefix_unrefp
) sd_radv_pref64_prefix
*p
= NULL
;
346 r
= sd_radv_pref64_prefix_new(&p
);
350 r
= sd_radv_pref64_prefix_set_prefix(p
, &prefix
->prefix64
.prefix
, prefix
->prefix64
.prefixlen
, prefix
->prefix64
.lifetime
);
354 return sd_radv_add_pref64_prefix(link
->radv
, p
);
357 static int network_get_ipv6_dns(Network
*network
, struct in6_addr
**ret_addresses
, size_t *ret_size
) {
358 _cleanup_free_
struct in6_addr
*addresses
= NULL
;
359 size_t n_addresses
= 0;
362 assert(ret_addresses
);
365 for (size_t i
= 0; i
< network
->n_dns
; i
++) {
366 union in_addr_union
*addr
;
368 if (network
->dns
[i
]->family
!= AF_INET6
)
371 addr
= &network
->dns
[i
]->address
;
373 if (in_addr_is_null(AF_INET6
, addr
) ||
374 in_addr_is_link_local(AF_INET6
, addr
) ||
375 in_addr_is_localhost(AF_INET6
, addr
))
378 if (!GREEDY_REALLOC(addresses
, n_addresses
+ 1))
381 addresses
[n_addresses
++] = addr
->in6
;
384 *ret_addresses
= TAKE_PTR(addresses
);
385 *ret_size
= n_addresses
;
390 static int radv_set_dns(Link
*link
, Link
*uplink
) {
391 _cleanup_free_
struct in6_addr
*dns
= NULL
;
395 if (!link
->network
->router_emit_dns
)
398 if (link
->network
->router_dns
) {
401 dns
= new(struct in6_addr
, link
->network
->n_router_dns
);
406 for (size_t i
= 0; i
< link
->network
->n_router_dns
; i
++)
407 if (in6_addr_is_null(&link
->network
->router_dns
[i
])) {
408 if (in6_addr_is_set(&link
->ipv6ll_address
))
409 *(p
++) = link
->ipv6ll_address
;
411 *(p
++) = link
->network
->router_dns
[i
];
418 r
= network_get_ipv6_dns(link
->network
, &dns
, &n_dns
);
423 assert(uplink
->network
);
425 r
= network_get_ipv6_dns(uplink
->network
, &dns
, &n_dns
);
433 return sd_radv_set_rdnss(link
->radv
,
434 link
->network
->router_dns_lifetime_usec
,
438 static int radv_set_domains(Link
*link
, Link
*uplink
) {
439 _cleanup_free_
char **s
= NULL
; /* just free() because the strings are owned by the set */
440 OrderedSet
*search_domains
;
442 if (!link
->network
->router_emit_domains
)
445 search_domains
= link
->network
->router_search_domains
;
450 search_domains
= link
->network
->search_domains
;
455 assert(uplink
->network
);
457 search_domains
= uplink
->network
->search_domains
;
465 s
= ordered_set_get_strv(search_domains
);
469 return sd_radv_set_dnssl(link
->radv
,
470 link
->network
->router_dns_lifetime_usec
,
475 static int radv_find_uplink(Link
*link
, Link
**ret
) {
480 if (link
->network
->router_uplink_name
)
481 return link_get_by_name(link
->manager
, link
->network
->router_uplink_name
, ret
);
483 if (link
->network
->router_uplink_index
> 0)
484 return link_get_by_index(link
->manager
, link
->network
->router_uplink_index
, ret
);
486 if (link
->network
->router_uplink_index
== UPLINK_INDEX_AUTO
) {
487 if (link_dhcp_pd_is_enabled(link
))
488 r
= dhcp_pd_find_uplink(link
, ret
); /* When DHCP-PD is enabled, use its uplink. */
490 r
= manager_find_uplink(link
->manager
, AF_INET6
, link
, ret
);
492 /* It is not necessary to propagate error in automatic selection. */
501 static int radv_configure(Link
*link
) {
506 assert(link
->network
);
511 r
= sd_radv_new(&link
->radv
);
515 r
= sd_radv_attach_event(link
->radv
, link
->manager
->event
, 0);
519 if (link
->hw_addr
.length
== ETH_ALEN
) {
520 r
= sd_radv_set_mac(link
->radv
, &link
->hw_addr
.ether
);
525 r
= sd_radv_set_ifindex(link
->radv
, link
->ifindex
);
529 r
= sd_radv_set_managed_information(link
->radv
, link
->network
->router_managed
);
533 r
= sd_radv_set_other_information(link
->radv
, link
->network
->router_other_information
);
537 r
= sd_radv_set_router_lifetime(link
->radv
, link
->network
->router_lifetime_usec
);
541 r
= sd_radv_set_hop_limit(link
->radv
, link
->network
->router_hop_limit
);
545 r
= sd_radv_set_preference(link
->radv
, link
->network
->router_preference
);
549 r
= sd_radv_set_reachable_time(link
->radv
, link
->network
->router_reachable_usec
);
553 r
= sd_radv_set_retransmit(link
->radv
, link
->network
->router_retransmit_usec
);
558 HASHMAP_FOREACH(p
, link
->network
->prefixes_by_section
) {
559 r
= radv_set_prefix(link
, p
);
560 if (r
< 0 && r
!= -EEXIST
)
565 HASHMAP_FOREACH(q
, link
->network
->route_prefixes_by_section
) {
566 r
= radv_set_route_prefix(link
, q
);
567 if (r
< 0 && r
!= -EEXIST
)
572 HASHMAP_FOREACH(n
, link
->network
->pref64_prefixes_by_section
) {
573 r
= radv_set_pref64_prefix(link
, n
);
574 if (r
< 0 && r
!= -EEXIST
)
578 (void) radv_find_uplink(link
, &uplink
);
580 r
= radv_set_dns(link
, uplink
);
582 return log_link_debug_errno(link
, r
, "Could not set RA DNS: %m");
584 r
= radv_set_domains(link
, uplink
);
586 return log_link_debug_errno(link
, r
, "Could not set RA Domains: %m");
588 r
= sd_radv_set_home_agent_information(link
->radv
, link
->network
->router_home_agent_information
);
592 r
= sd_radv_set_home_agent_preference(link
->radv
, link
->network
->router_home_agent_preference
);
596 r
= sd_radv_set_home_agent_lifetime(link
->radv
, link
->network
->home_agent_lifetime_usec
);
603 int radv_update_mac(Link
*link
) {
609 if (link
->hw_addr
.length
!= ETH_ALEN
)
612 return sd_radv_set_mac(link
->radv
, &link
->hw_addr
.ether
);
615 static int radv_is_ready_to_configure(Link
*link
) {
616 bool needs_uplink
= false;
620 assert(link
->network
);
622 if (!link_is_ready_to_configure(link
, /* allow_unmanaged = */ false))
625 if (in6_addr_is_null(&link
->ipv6ll_address
))
628 if (link
->hw_addr
.length
!= ETH_ALEN
|| hw_addr_is_null(&link
->hw_addr
))
631 if (link
->network
->router_emit_dns
&& !link
->network
->router_dns
) {
632 _cleanup_free_
struct in6_addr
*dns
= NULL
;
635 r
= network_get_ipv6_dns(link
->network
, &dns
, &n_dns
);
639 needs_uplink
= r
== 0;
642 if (link
->network
->router_emit_domains
&&
643 !link
->network
->router_search_domains
&&
644 !link
->network
->search_domains
)
650 if (radv_find_uplink(link
, &uplink
) < 0)
653 if (uplink
&& !uplink
->network
)
660 static int radv_process_request(Request
*req
, Link
*link
, void *userdata
) {
665 r
= radv_is_ready_to_configure(link
);
669 r
= radv_configure(link
);
671 return log_link_warning_errno(link
, r
, "Failed to configure IPv6 Router Advertisement engine: %m");
673 if (link_has_carrier(link
)) {
674 r
= radv_start(link
);
676 return log_link_warning_errno(link
, r
, "Failed to start IPv6 Router Advertisement engine: %m");
679 log_link_debug(link
, "IPv6 Router Advertisement engine is configured%s.",
680 link_has_carrier(link
) ? " and started" : "");
684 int link_request_radv(Link
*link
) {
689 if (!link_radv_enabled(link
))
695 r
= link_queue_request(link
, REQUEST_TYPE_RADV
, radv_process_request
, NULL
);
697 return log_link_warning_errno(link
, r
, "Failed to request configuring of the IPv6 Router Advertisement engine: %m");
699 log_link_debug(link
, "Requested configuring of the IPv6 Router Advertisement engine.");
703 int radv_start(Link
*link
) {
707 assert(link
->network
);
712 if (!link_has_carrier(link
))
715 if (in6_addr_is_null(&link
->ipv6ll_address
))
718 if (sd_radv_is_running(link
->radv
))
721 if (link
->network
->dhcp_pd_announce
) {
722 r
= dhcp_request_prefix_delegation(link
);
724 return log_link_debug_errno(link
, r
, "Failed to request DHCP delegated subnet prefix: %m");
727 r
= sd_radv_set_link_local_address(link
->radv
, &link
->ipv6ll_address
);
731 log_link_debug(link
, "Starting IPv6 Router Advertisements");
732 return sd_radv_start(link
->radv
);
737 const struct in6_addr
*prefix
,
739 usec_t lifetime_preferred_usec
,
740 usec_t lifetime_valid_usec
) {
742 _cleanup_(sd_radv_prefix_unrefp
) sd_radv_prefix
*p
= NULL
;
750 r
= sd_radv_prefix_new(&p
);
754 r
= sd_radv_prefix_set_prefix(p
, prefix
, prefix_len
);
758 r
= sd_radv_prefix_set_preferred_lifetime(p
, RADV_DEFAULT_PREFERRED_LIFETIME_USEC
, lifetime_preferred_usec
);
762 r
= sd_radv_prefix_set_valid_lifetime(p
, RADV_DEFAULT_VALID_LIFETIME_USEC
, lifetime_valid_usec
);
766 r
= sd_radv_add_prefix(link
->radv
, p
);
772 if (sd_radv_is_running(link
->radv
)) {
773 /* Announce updated prefixe now. */
774 r
= sd_radv_send(link
->radv
);
782 static int prefix_section_verify(Prefix
*p
) {
785 if (section_is_invalid(p
->section
))
788 if (in6_addr_is_null(&p
->prefix
.address
))
789 return log_warning_errno(SYNTHETIC_ERRNO(EINVAL
),
790 "%s: [IPv6Prefix] section without Prefix= field configured, "
791 "or specified prefix is the null address. "
792 "Ignoring [IPv6Prefix] section from line %u.",
793 p
->section
->filename
, p
->section
->line
);
795 if (p
->prefix
.prefixlen
< 3 || p
->prefix
.prefixlen
> 128)
796 return log_warning_errno(SYNTHETIC_ERRNO(EINVAL
),
797 "%s: Invalid prefix length %u is specified in [IPv6Prefix] section. "
798 "Valid range is 3…128. Ignoring [IPv6Prefix] section from line %u.",
799 p
->section
->filename
, p
->prefix
.prefixlen
, p
->section
->line
);
801 if (p
->prefix
.prefixlen
> 64) {
802 log_info("%s:%u: Unusual prefix length %u (> 64) is specified in [IPv6Prefix] section from line %s%s.",
803 p
->section
->filename
, p
->section
->line
,
805 p
->assign
? ", refusing to assign an address in " : "",
806 p
->assign
? IN6_ADDR_PREFIX_TO_STRING(&p
->prefix
.address
, p
->prefix
.prefixlen
) : "");
811 if (p
->prefix
.preferred_lifetime
> p
->prefix
.valid_lifetime
)
812 return log_warning_errno(SYNTHETIC_ERRNO(EINVAL
),
813 "%s: The preferred lifetime %s is longer than the valid lifetime %s. "
814 "Ignoring [IPv6Prefix] section from line %u.",
815 p
->section
->filename
,
816 FORMAT_TIMESPAN(p
->prefix
.preferred_lifetime
, USEC_PER_SEC
),
817 FORMAT_TIMESPAN(p
->prefix
.valid_lifetime
, USEC_PER_SEC
),
823 static int route_prefix_section_verify(RoutePrefix
*p
) {
824 if (section_is_invalid(p
->section
))
827 if (p
->route
.prefixlen
> 128)
828 return log_warning_errno(SYNTHETIC_ERRNO(EINVAL
),
829 "%s: Invalid prefix length %u is specified in [IPv6RoutePrefix] section. "
830 "Valid range is 0…128. Ignoring [IPv6RoutePrefix] section from line %u.",
831 p
->section
->filename
, p
->route
.prefixlen
, p
->section
->line
);
836 void network_adjust_radv(Network
*network
) {
839 /* After this function is called, network->router_prefix_delegation can be treated as a boolean. */
841 if (network
->dhcp_pd
< 0)
842 /* For backward compatibility. */
843 network
->dhcp_pd
= FLAGS_SET(network
->router_prefix_delegation
, RADV_PREFIX_DELEGATION_DHCP6
);
845 if (!FLAGS_SET(network
->link_local
, ADDRESS_FAMILY_IPV6
)) {
846 if (network
->router_prefix_delegation
!= RADV_PREFIX_DELEGATION_NONE
)
847 log_warning("%s: IPv6PrefixDelegation= is enabled but IPv6 link-local addressing is disabled. "
848 "Disabling IPv6PrefixDelegation=.", network
->filename
);
850 network
->router_prefix_delegation
= RADV_PREFIX_DELEGATION_NONE
;
853 if (network
->router_prefix_delegation
== RADV_PREFIX_DELEGATION_NONE
) {
854 network
->n_router_dns
= 0;
855 network
->router_dns
= mfree(network
->router_dns
);
856 network
->router_search_domains
= ordered_set_free(network
->router_search_domains
);
859 if (!FLAGS_SET(network
->router_prefix_delegation
, RADV_PREFIX_DELEGATION_STATIC
)) {
860 network
->prefixes_by_section
= hashmap_free_with_destructor(network
->prefixes_by_section
, prefix_free
);
861 network
->route_prefixes_by_section
= hashmap_free_with_destructor(network
->route_prefixes_by_section
, route_prefix_free
);
862 network
->pref64_prefixes_by_section
= hashmap_free_with_destructor(network
->pref64_prefixes_by_section
, prefix64_free
);
865 if (!network
->router_prefix_delegation
)
868 /* Below, let's verify router settings, if enabled. */
870 if (network
->router_lifetime_usec
== 0 && network
->router_preference
!= SD_NDISC_PREFERENCE_MEDIUM
)
871 /* RFC 4191, Section 2.2,
872 * If the Router Lifetime is zero, the preference value MUST be set to (00) by the sender.
874 * Note, radv_send_router() gracefully handle that. So, it is not necessary to refuse, but
875 * let's warn about that. */
876 log_notice("%s: RouterPreference=%s specified with RouterLifetimeSec=0, ignoring RouterPreference= setting.",
877 network
->filename
, ndisc_router_preference_to_string(network
->router_preference
));
880 HASHMAP_FOREACH(prefix
, network
->prefixes_by_section
)
881 if (prefix_section_verify(prefix
) < 0)
886 HASHMAP_FOREACH(route
, network
->route_prefixes_by_section
)
887 if (route_prefix_section_verify(route
) < 0)
888 route_prefix_free(route
);
891 HASHMAP_FOREACH(pref64
, network
->pref64_prefixes_by_section
)
892 if (section_is_invalid(pref64
->section
))
893 prefix64_free(pref64
);
896 int config_parse_prefix(
898 const char *filename
,
901 unsigned section_line
,
908 _cleanup_(prefix_free_or_set_invalidp
) Prefix
*p
= NULL
;
909 Network
*network
= ASSERT_PTR(userdata
);
910 union in_addr_union a
;
918 r
= prefix_new_static(network
, filename
, section_line
, &p
);
922 r
= in_addr_prefix_from_string(rvalue
, AF_INET6
, &a
, &p
->prefix
.prefixlen
);
924 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
925 "Prefix is invalid, ignoring assignment: %s", rvalue
);
929 (void) in6_addr_mask(&a
.in6
, p
->prefix
.prefixlen
);
930 p
->prefix
.address
= a
.in6
;
936 int config_parse_prefix_boolean(
938 const char *filename
,
941 unsigned section_line
,
948 _cleanup_(prefix_free_or_set_invalidp
) Prefix
*p
= NULL
;
949 Network
*network
= ASSERT_PTR(userdata
);
957 r
= prefix_new_static(network
, filename
, section_line
, &p
);
961 r
= parse_boolean(rvalue
);
963 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
964 "Failed to parse %s=, ignoring assignment: %s", lvalue
, rvalue
);
969 SET_FLAG(p
->prefix
.flags
, ltype
, r
);
971 assert(streq(lvalue
, "Assign"));
979 int config_parse_prefix_lifetime(
981 const char *filename
,
984 unsigned section_line
,
991 _cleanup_(prefix_free_or_set_invalidp
) Prefix
*p
= NULL
;
992 Network
*network
= ASSERT_PTR(userdata
);
1001 r
= prefix_new_static(network
, filename
, section_line
, &p
);
1005 r
= parse_sec(rvalue
, &usec
);
1007 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
1008 "Lifetime is invalid, ignoring assignment: %s", rvalue
);
1012 if (usec
!= USEC_INFINITY
&& DIV_ROUND_UP(usec
, USEC_PER_SEC
) >= UINT32_MAX
) {
1013 log_syntax(unit
, LOG_WARNING
, filename
, line
, 0,
1014 "Lifetime is too long, ignoring assignment: %s", rvalue
);
1018 if (streq(lvalue
, "PreferredLifetimeSec"))
1019 p
->prefix
.preferred_lifetime
= usec
;
1020 else if (streq(lvalue
, "ValidLifetimeSec"))
1021 p
->prefix
.valid_lifetime
= usec
;
1023 assert_not_reached();
1029 int config_parse_prefix_metric(
1031 const char *filename
,
1033 const char *section
,
1034 unsigned section_line
,
1041 _cleanup_(prefix_free_or_set_invalidp
) Prefix
*p
= NULL
;
1042 Network
*network
= ASSERT_PTR(userdata
);
1050 r
= prefix_new_static(network
, filename
, section_line
, &p
);
1054 r
= safe_atou32(rvalue
, &p
->route_metric
);
1056 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
1057 "Failed to parse %s=, ignoring assignment: %s",
1066 int config_parse_prefix_token(
1068 const char *filename
,
1070 const char *section
,
1071 unsigned section_line
,
1078 _cleanup_(prefix_free_or_set_invalidp
) Prefix
*p
= NULL
;
1079 Network
*network
= ASSERT_PTR(userdata
);
1087 r
= prefix_new_static(network
, filename
, section_line
, &p
);
1091 r
= config_parse_address_generation_type(unit
, filename
, line
, section
, section_line
,
1092 lvalue
, ltype
, rvalue
, &p
->tokens
, userdata
);
1100 int config_parse_route_prefix(
1102 const char *filename
,
1104 const char *section
,
1105 unsigned section_line
,
1112 _cleanup_(route_prefix_free_or_set_invalidp
) RoutePrefix
*p
= NULL
;
1113 Network
*network
= ASSERT_PTR(userdata
);
1114 union in_addr_union a
;
1122 r
= route_prefix_new_static(network
, filename
, section_line
, &p
);
1126 r
= in_addr_prefix_from_string(rvalue
, AF_INET6
, &a
, &p
->route
.prefixlen
);
1128 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
1129 "Route prefix is invalid, ignoring assignment: %s", rvalue
);
1133 (void) in6_addr_mask(&a
.in6
, p
->route
.prefixlen
);
1134 p
->route
.address
= a
.in6
;
1140 int config_parse_route_prefix_lifetime(
1142 const char *filename
,
1144 const char *section
,
1145 unsigned section_line
,
1152 _cleanup_(route_prefix_free_or_set_invalidp
) RoutePrefix
*p
= NULL
;
1153 Network
*network
= ASSERT_PTR(userdata
);
1162 r
= route_prefix_new_static(network
, filename
, section_line
, &p
);
1166 r
= parse_sec(rvalue
, &usec
);
1168 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
1169 "Route lifetime is invalid, ignoring assignment: %s", rvalue
);
1173 if (usec
!= USEC_INFINITY
&& DIV_ROUND_UP(usec
, USEC_PER_SEC
) >= UINT32_MAX
) {
1174 log_syntax(unit
, LOG_WARNING
, filename
, line
, 0,
1175 "Lifetime is too long, ignoring assignment: %s", rvalue
);
1179 p
->route
.lifetime
= usec
;
1185 int config_parse_pref64_prefix(
1187 const char *filename
,
1189 const char *section
,
1190 unsigned section_line
,
1197 _cleanup_(prefix64_free_or_set_invalidp
) Prefix64
*p
= NULL
;
1198 Network
*network
= ASSERT_PTR(userdata
);
1199 union in_addr_union a
;
1208 r
= prefix64_new_static(network
, filename
, section_line
, &p
);
1212 r
= in_addr_prefix_from_string(rvalue
, AF_INET6
, &a
, &prefixlen
);
1214 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
1215 "PREF64 prefix is invalid, ignoring assignment: %s", rvalue
);
1219 if (!IN_SET(prefixlen
, 96, 64, 56, 48, 40, 32)) {
1220 log_syntax(unit
, LOG_WARNING
, filename
, line
, 0,
1221 "PREF64 prefixlen is invalid, ignoring assignment: %s", rvalue
);
1225 (void) in6_addr_mask(&a
.in6
, prefixlen
);
1226 p
->prefix64
.prefix
= a
.in6
;
1227 p
->prefix64
.prefixlen
= prefixlen
;
1233 int config_parse_pref64_prefix_lifetime(
1235 const char *filename
,
1237 const char *section
,
1238 unsigned section_line
,
1245 _cleanup_(prefix64_free_or_set_invalidp
) Prefix64
*p
= NULL
;
1246 Network
*network
= ASSERT_PTR(userdata
);
1255 r
= prefix64_new_static(network
, filename
, section_line
, &p
);
1259 r
= parse_sec(rvalue
, &usec
);
1261 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
1262 "PREF64 lifetime is invalid, ignoring assignment: %s", rvalue
);
1266 if (usec
== USEC_INFINITY
|| DIV_ROUND_UP(usec
, 8 * USEC_PER_SEC
) >= UINT64_C(1) << 13) {
1267 log_syntax(unit
, LOG_WARNING
, filename
, line
, 0,
1268 "PREF64 lifetime is too long, ignoring assignment: %s", rvalue
);
1272 p
->prefix64
.lifetime
= usec
;
1278 int config_parse_radv_dns(
1280 const char *filename
,
1282 const char *section
,
1283 unsigned section_line
,
1297 if (isempty(rvalue
)) {
1298 n
->n_router_dns
= 0;
1299 n
->router_dns
= mfree(n
->router_dns
);
1303 for (const char *p
= rvalue
;;) {
1304 _cleanup_free_
char *w
= NULL
;
1305 union in_addr_union a
;
1307 r
= extract_first_word(&p
, &w
, NULL
, 0);
1311 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
1312 "Failed to extract word, ignoring: %s", rvalue
);
1318 if (streq(w
, "_link_local"))
1321 r
= in_addr_from_string(AF_INET6
, w
, &a
);
1323 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
1324 "Failed to parse DNS server address, ignoring: %s", w
);
1328 if (in_addr_is_null(AF_INET6
, &a
)) {
1329 log_syntax(unit
, LOG_WARNING
, filename
, line
, 0,
1330 "DNS server address is null, ignoring: %s", w
);
1336 m
= reallocarray(n
->router_dns
, n
->n_router_dns
+ 1, sizeof(struct in6_addr
));
1340 m
[n
->n_router_dns
++] = a
.in6
;
1345 int config_parse_radv_search_domains(
1347 const char *filename
,
1349 const char *section
,
1350 unsigned section_line
,
1364 if (isempty(rvalue
)) {
1365 n
->router_search_domains
= ordered_set_free(n
->router_search_domains
);
1369 for (const char *p
= rvalue
;;) {
1370 _cleanup_free_
char *w
= NULL
, *idna
= NULL
;
1372 r
= extract_first_word(&p
, &w
, NULL
, 0);
1376 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
1377 "Failed to extract word, ignoring: %s", rvalue
);
1383 r
= dns_name_apply_idna(w
, &idna
);
1385 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
1386 "Failed to apply IDNA to domain name '%s', ignoring: %m", w
);
1389 /* transfer ownership to simplify subsequent operations */
1392 r
= ordered_set_ensure_allocated(&n
->router_search_domains
, &string_hash_ops_free
);
1396 r
= ordered_set_consume(n
->router_search_domains
, TAKE_PTR(idna
));
1402 static const char * const radv_prefix_delegation_table
[_RADV_PREFIX_DELEGATION_MAX
] = {
1403 [RADV_PREFIX_DELEGATION_NONE
] = "no",
1404 [RADV_PREFIX_DELEGATION_STATIC
] = "static",
1405 [RADV_PREFIX_DELEGATION_DHCP6
] = "dhcpv6",
1406 [RADV_PREFIX_DELEGATION_BOTH
] = "yes",
1409 DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(
1410 radv_prefix_delegation
,
1411 RADVPrefixDelegation
,
1412 RADV_PREFIX_DELEGATION_BOTH
);
1414 int config_parse_router_prefix_delegation(
1416 const char *filename
,
1418 const char *section
,
1419 unsigned section_line
,
1426 RADVPrefixDelegation val
, *ra
= ASSERT_PTR(data
);
1433 if (streq(lvalue
, "IPv6SendRA")) {
1434 r
= parse_boolean(rvalue
);
1436 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
1437 "Invalid %s= setting, ignoring assignment: %s", lvalue
, rvalue
);
1441 /* When IPv6SendRA= is enabled, only static prefixes are sent by default, and users
1442 * need to explicitly enable DHCPv6PrefixDelegation=. */
1443 *ra
= r
? RADV_PREFIX_DELEGATION_STATIC
: RADV_PREFIX_DELEGATION_NONE
;
1447 /* For backward compatibility */
1448 val
= radv_prefix_delegation_from_string(rvalue
);
1450 log_syntax(unit
, LOG_WARNING
, filename
, line
, val
,
1451 "Invalid %s= setting, ignoring assignment: %s", lvalue
, rvalue
);
1459 int config_parse_router_lifetime(
1461 const char *filename
,
1463 const char *section
,
1464 unsigned section_line
,
1471 usec_t usec
, *lifetime
= ASSERT_PTR(data
);
1479 if (isempty(rvalue
)) {
1480 *lifetime
= RADV_DEFAULT_ROUTER_LIFETIME_USEC
;
1484 r
= parse_sec(rvalue
, &usec
);
1486 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
1487 "Failed to parse router lifetime, ignoring assignment: %s", rvalue
);
1491 if (usec
< RADV_MIN_ROUTER_LIFETIME_USEC
) {
1492 log_syntax(unit
, LOG_WARNING
, filename
, line
, 0,
1493 "Router lifetime %s is too short, using %s.",
1494 FORMAT_TIMESPAN(usec
, USEC_PER_SEC
),
1495 FORMAT_TIMESPAN(RADV_MIN_ROUTER_LIFETIME_USEC
, USEC_PER_SEC
));
1496 usec
= RADV_MIN_ROUTER_LIFETIME_USEC
;
1497 } else if (usec
> RADV_MAX_ROUTER_LIFETIME_USEC
) {
1498 log_syntax(unit
, LOG_WARNING
, filename
, line
, 0,
1499 "Router lifetime %s is too large, using %s.",
1500 FORMAT_TIMESPAN(usec
, USEC_PER_SEC
),
1501 FORMAT_TIMESPAN(RADV_MAX_ROUTER_LIFETIME_USEC
, USEC_PER_SEC
));
1502 usec
= RADV_MAX_ROUTER_LIFETIME_USEC
;
1510 int config_parse_router_uint32_msec_usec(
1512 const char *filename
,
1514 const char *section
,
1515 unsigned section_line
,
1522 usec_t usec
, *router_usec
= ASSERT_PTR(data
);
1530 if (isempty(rvalue
)) {
1535 r
= parse_sec(rvalue
, &usec
);
1537 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
1538 "Failed to parse %s=, ignoring assignment: %s", lvalue
, rvalue
);
1542 if (usec
!= USEC_INFINITY
&&
1543 usec
> RADV_MAX_UINT32_MSEC_USEC
) {
1544 log_syntax(unit
, LOG_WARNING
, filename
, line
, 0,
1545 "Invalid [%s] %s=, ignoring assignment: %s", section
, lvalue
, rvalue
);
1549 *router_usec
= usec
;
1553 int config_parse_router_preference(
1555 const char *filename
,
1557 const char *section
,
1558 unsigned section_line
,
1565 Network
*network
= userdata
;
1573 if (streq(rvalue
, "high"))
1574 network
->router_preference
= SD_NDISC_PREFERENCE_HIGH
;
1575 else if (STR_IN_SET(rvalue
, "medium", "normal", "default"))
1576 network
->router_preference
= SD_NDISC_PREFERENCE_MEDIUM
;
1577 else if (streq(rvalue
, "low"))
1578 network
->router_preference
= SD_NDISC_PREFERENCE_LOW
;
1580 log_syntax(unit
, LOG_WARNING
, filename
, line
, 0,
1581 "Invalid router preference, ignoring assignment: %s", rvalue
);
1586 int config_parse_router_home_agent_lifetime(
1588 const char *filename
,
1590 const char *section
,
1591 unsigned section_line
,
1598 usec_t usec
, *home_agent_lifetime_usec
= ASSERT_PTR(data
);
1606 if (isempty(rvalue
)) {
1607 *home_agent_lifetime_usec
= 0;
1611 r
= parse_sec(rvalue
, &usec
);
1613 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
1614 "Failed to parse %s=, ignoring assignment: %s", lvalue
, rvalue
);
1618 if (!timestamp_is_set(usec
) ||
1619 usec
> RADV_HOME_AGENT_MAX_LIFETIME_USEC
) {
1620 log_syntax(unit
, LOG_WARNING
, filename
, line
, 0,
1621 "Invalid [%s] %s=, ignoring assignment: %s", section
, lvalue
, rvalue
);
1625 *home_agent_lifetime_usec
= usec
;