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 "networkd-address-generation.h"
11 #include "networkd-address.h"
12 #include "networkd-dhcp-prefix-delegation.h"
13 #include "networkd-link.h"
14 #include "networkd-manager.h"
15 #include "networkd-network.h"
16 #include "networkd-queue.h"
17 #include "networkd-radv.h"
18 #include "networkd-route-util.h"
19 #include "parse-util.h"
20 #include "radv-internal.h"
21 #include "string-util.h"
22 #include "string-table.h"
25 void network_adjust_radv(Network
*network
) {
28 /* After this function is called, network->router_prefix_delegation can be treated as a boolean. */
30 if (network
->dhcp_pd
< 0)
31 /* For backward compatibility. */
32 network
->dhcp_pd
= FLAGS_SET(network
->router_prefix_delegation
, RADV_PREFIX_DELEGATION_DHCP6
);
34 if (!FLAGS_SET(network
->link_local
, ADDRESS_FAMILY_IPV6
)) {
35 if (network
->router_prefix_delegation
!= RADV_PREFIX_DELEGATION_NONE
)
36 log_warning("%s: IPv6PrefixDelegation= is enabled but IPv6 link-local addressing is disabled. "
37 "Disabling IPv6PrefixDelegation=.", network
->filename
);
39 network
->router_prefix_delegation
= RADV_PREFIX_DELEGATION_NONE
;
42 if (network
->router_prefix_delegation
== RADV_PREFIX_DELEGATION_NONE
) {
43 network
->n_router_dns
= 0;
44 network
->router_dns
= mfree(network
->router_dns
);
45 network
->router_search_domains
= ordered_set_free(network
->router_search_domains
);
48 if (!FLAGS_SET(network
->router_prefix_delegation
, RADV_PREFIX_DELEGATION_STATIC
)) {
49 network
->prefixes_by_section
= hashmap_free_with_destructor(network
->prefixes_by_section
, prefix_free
);
50 network
->route_prefixes_by_section
= hashmap_free_with_destructor(network
->route_prefixes_by_section
, route_prefix_free
);
51 network
->pref64_prefixes_by_section
= hashmap_free_with_destructor(network
->pref64_prefixes_by_section
, pref64_prefix_free
);
55 bool link_radv_enabled(Link
*link
) {
58 if (!link_may_have_ipv6ll(link
, /* check_multicast = */ true))
61 if (link
->hw_addr
.length
!= ETH_ALEN
)
64 return link
->network
->router_prefix_delegation
;
67 Prefix
*prefix_free(Prefix
*prefix
) {
71 if (prefix
->network
) {
72 assert(prefix
->section
);
73 hashmap_remove(prefix
->network
->prefixes_by_section
, prefix
->section
);
76 config_section_free(prefix
->section
);
77 set_free(prefix
->tokens
);
82 DEFINE_SECTION_CLEANUP_FUNCTIONS(Prefix
, prefix_free
);
84 static int prefix_new_static(Network
*network
, const char *filename
, unsigned section_line
, Prefix
**ret
) {
85 _cleanup_(config_section_freep
) ConfigSection
*n
= NULL
;
86 _cleanup_(prefix_freep
) Prefix
*prefix
= NULL
;
92 assert(section_line
> 0);
94 r
= config_section_new(filename
, section_line
, &n
);
98 prefix
= hashmap_get(network
->prefixes_by_section
, n
);
100 *ret
= TAKE_PTR(prefix
);
104 prefix
= new(Prefix
, 1);
110 .section
= TAKE_PTR(n
),
112 .preferred_lifetime
= RADV_DEFAULT_PREFERRED_LIFETIME_USEC
,
113 .valid_lifetime
= RADV_DEFAULT_VALID_LIFETIME_USEC
,
115 .address_auto_configuration
= true,
118 r
= hashmap_ensure_put(&network
->prefixes_by_section
, &config_section_hash_ops
, prefix
->section
, prefix
);
122 *ret
= TAKE_PTR(prefix
);
126 RoutePrefix
*route_prefix_free(RoutePrefix
*prefix
) {
130 if (prefix
->network
) {
131 assert(prefix
->section
);
132 hashmap_remove(prefix
->network
->route_prefixes_by_section
, prefix
->section
);
135 config_section_free(prefix
->section
);
137 return mfree(prefix
);
140 DEFINE_SECTION_CLEANUP_FUNCTIONS(RoutePrefix
, route_prefix_free
);
142 static int route_prefix_new_static(Network
*network
, const char *filename
, unsigned section_line
, RoutePrefix
**ret
) {
143 _cleanup_(config_section_freep
) ConfigSection
*n
= NULL
;
144 _cleanup_(route_prefix_freep
) RoutePrefix
*prefix
= NULL
;
150 assert(section_line
> 0);
152 r
= config_section_new(filename
, section_line
, &n
);
156 prefix
= hashmap_get(network
->route_prefixes_by_section
, n
);
158 *ret
= TAKE_PTR(prefix
);
162 prefix
= new(RoutePrefix
, 1);
166 *prefix
= (RoutePrefix
) {
168 .section
= TAKE_PTR(n
),
170 .lifetime
= RADV_DEFAULT_VALID_LIFETIME_USEC
,
173 r
= hashmap_ensure_put(&network
->route_prefixes_by_section
, &config_section_hash_ops
, prefix
->section
, prefix
);
177 *ret
= TAKE_PTR(prefix
);
181 pref64Prefix
*pref64_prefix_free(pref64Prefix
*prefix
) {
185 if (prefix
->network
) {
186 assert(prefix
->section
);
187 hashmap_remove(prefix
->network
->pref64_prefixes_by_section
, prefix
->section
);
190 config_section_free(prefix
->section
);
192 return mfree(prefix
);
195 DEFINE_SECTION_CLEANUP_FUNCTIONS(pref64Prefix
, pref64_prefix_free
);
197 static int pref64_prefix_new_static(Network
*network
, const char *filename
, unsigned section_line
, pref64Prefix
**ret
) {
198 _cleanup_(config_section_freep
) ConfigSection
*n
= NULL
;
199 _cleanup_(pref64_prefix_freep
) pref64Prefix
*prefix
= NULL
;
205 assert(section_line
> 0);
207 r
= config_section_new(filename
, section_line
, &n
);
211 prefix
= hashmap_get(network
->pref64_prefixes_by_section
, n
);
213 *ret
= TAKE_PTR(prefix
);
217 prefix
= new(pref64Prefix
, 1);
221 *prefix
= (pref64Prefix
) {
223 .section
= TAKE_PTR(n
),
225 .lifetime
= RADV_PREF64_DEFAULT_LIFETIME_USEC
,
228 r
= hashmap_ensure_put(&network
->pref64_prefixes_by_section
, &config_section_hash_ops
, prefix
->section
, prefix
);
232 *ret
= TAKE_PTR(prefix
);
236 int link_request_radv_addresses(Link
*link
) {
242 if (!link_radv_enabled(link
))
245 HASHMAP_FOREACH(p
, link
->network
->prefixes_by_section
) {
249 /* radv_generate_addresses() below requires the prefix length <= 64. */
250 if (p
->prefixlen
> 64)
253 _cleanup_hashmap_free_ Hashmap
*tokens_by_address
= NULL
;
254 r
= radv_generate_addresses(link
, p
->tokens
, &p
->prefix
, p
->prefixlen
, &tokens_by_address
);
260 HASHMAP_FOREACH_KEY(token
, a
, tokens_by_address
) {
261 _cleanup_(address_unrefp
) Address
*address
= NULL
;
263 r
= address_new(&address
);
267 address
->source
= NETWORK_CONFIG_SOURCE_STATIC
;
268 address
->family
= AF_INET6
;
269 address
->in_addr
.in6
= *a
;
270 address
->prefixlen
= p
->prefixlen
;
271 address
->route_metric
= p
->route_metric
;
272 address
->token
= ipv6_token_ref(token
);
274 r
= link_request_static_address(link
, address
);
283 int link_reconfigure_radv_address(Address
*address
, Link
*link
) {
287 assert(address
->source
== NETWORK_CONFIG_SOURCE_STATIC
);
290 r
= regenerate_address(address
, link
);
294 r
= link_request_static_address(link
, address
);
298 if (link
->static_address_messages
!= 0) {
299 link
->static_addresses_configured
= false;
300 link_set_state(link
, LINK_STATE_CONFIGURING
);
306 static int radv_set_prefix(Link
*link
, Prefix
*prefix
) {
307 _cleanup_(sd_radv_prefix_unrefp
) sd_radv_prefix
*p
= NULL
;
314 r
= sd_radv_prefix_new(&p
);
318 r
= sd_radv_prefix_set_prefix(p
, &prefix
->prefix
, prefix
->prefixlen
);
322 r
= sd_radv_prefix_set_preferred_lifetime(p
, prefix
->preferred_lifetime
, USEC_INFINITY
);
326 r
= sd_radv_prefix_set_valid_lifetime(p
, prefix
->valid_lifetime
, USEC_INFINITY
);
330 r
= sd_radv_prefix_set_onlink(p
, prefix
->onlink
);
334 r
= sd_radv_prefix_set_address_autoconfiguration(p
, prefix
->address_auto_configuration
);
338 return sd_radv_add_prefix(link
->radv
, p
);
341 static int radv_set_route_prefix(Link
*link
, RoutePrefix
*prefix
) {
342 _cleanup_(sd_radv_route_prefix_unrefp
) sd_radv_route_prefix
*p
= NULL
;
349 r
= sd_radv_route_prefix_new(&p
);
353 r
= sd_radv_route_prefix_set_prefix(p
, &prefix
->prefix
, prefix
->prefixlen
);
357 r
= sd_radv_route_prefix_set_lifetime(p
, prefix
->lifetime
, USEC_INFINITY
);
361 return sd_radv_add_route_prefix(link
->radv
, p
);
364 static int radv_set_pref64_prefix(Link
*link
, pref64Prefix
*prefix
) {
365 _cleanup_(sd_radv_pref64_prefix_unrefp
) sd_radv_pref64_prefix
*p
= NULL
;
372 r
= sd_radv_pref64_prefix_new(&p
);
376 r
= sd_radv_pref64_prefix_set_prefix(p
, &prefix
->prefix
, prefix
->prefixlen
, prefix
->lifetime
);
380 return sd_radv_add_pref64_prefix(link
->radv
, p
);
383 static int network_get_ipv6_dns(Network
*network
, struct in6_addr
**ret_addresses
, size_t *ret_size
) {
384 _cleanup_free_
struct in6_addr
*addresses
= NULL
;
385 size_t n_addresses
= 0;
388 assert(ret_addresses
);
391 for (size_t i
= 0; i
< network
->n_dns
; i
++) {
392 union in_addr_union
*addr
;
394 if (network
->dns
[i
]->family
!= AF_INET6
)
397 addr
= &network
->dns
[i
]->address
;
399 if (in_addr_is_null(AF_INET6
, addr
) ||
400 in_addr_is_link_local(AF_INET6
, addr
) ||
401 in_addr_is_localhost(AF_INET6
, addr
))
404 if (!GREEDY_REALLOC(addresses
, n_addresses
+ 1))
407 addresses
[n_addresses
++] = addr
->in6
;
410 *ret_addresses
= TAKE_PTR(addresses
);
411 *ret_size
= n_addresses
;
416 static int radv_set_dns(Link
*link
, Link
*uplink
) {
417 _cleanup_free_
struct in6_addr
*dns
= NULL
;
421 if (!link
->network
->router_emit_dns
)
424 if (link
->network
->router_dns
) {
427 dns
= new(struct in6_addr
, link
->network
->n_router_dns
);
432 for (size_t i
= 0; i
< link
->network
->n_router_dns
; i
++)
433 if (in6_addr_is_null(&link
->network
->router_dns
[i
])) {
434 if (in6_addr_is_set(&link
->ipv6ll_address
))
435 *(p
++) = link
->ipv6ll_address
;
437 *(p
++) = link
->network
->router_dns
[i
];
444 r
= network_get_ipv6_dns(link
->network
, &dns
, &n_dns
);
449 assert(uplink
->network
);
451 r
= network_get_ipv6_dns(uplink
->network
, &dns
, &n_dns
);
459 return sd_radv_set_rdnss(link
->radv
,
460 link
->network
->router_dns_lifetime_usec
,
464 static int radv_set_domains(Link
*link
, Link
*uplink
) {
465 _cleanup_free_
char **s
= NULL
; /* just free() because the strings are owned by the set */
466 OrderedSet
*search_domains
;
468 if (!link
->network
->router_emit_domains
)
471 search_domains
= link
->network
->router_search_domains
;
476 search_domains
= link
->network
->search_domains
;
481 assert(uplink
->network
);
483 search_domains
= uplink
->network
->search_domains
;
491 s
= ordered_set_get_strv(search_domains
);
495 return sd_radv_set_dnssl(link
->radv
,
496 link
->network
->router_dns_lifetime_usec
,
501 static int radv_find_uplink(Link
*link
, Link
**ret
) {
506 if (link
->network
->router_uplink_name
)
507 return link_get_by_name(link
->manager
, link
->network
->router_uplink_name
, ret
);
509 if (link
->network
->router_uplink_index
> 0)
510 return link_get_by_index(link
->manager
, link
->network
->router_uplink_index
, ret
);
512 if (link
->network
->router_uplink_index
== UPLINK_INDEX_AUTO
) {
513 if (link_dhcp_pd_is_enabled(link
))
514 r
= dhcp_pd_find_uplink(link
, ret
); /* When DHCP-PD is enabled, use its uplink. */
516 r
= manager_find_uplink(link
->manager
, AF_INET6
, link
, ret
);
518 /* It is not necessary to propagate error in automatic selection. */
527 static int radv_configure(Link
*link
) {
535 assert(link
->network
);
540 r
= sd_radv_new(&link
->radv
);
544 r
= sd_radv_attach_event(link
->radv
, link
->manager
->event
, 0);
548 if (link
->hw_addr
.length
== ETH_ALEN
) {
549 r
= sd_radv_set_mac(link
->radv
, &link
->hw_addr
.ether
);
554 r
= sd_radv_set_ifindex(link
->radv
, link
->ifindex
);
558 r
= sd_radv_set_managed_information(link
->radv
, link
->network
->router_managed
);
562 r
= sd_radv_set_other_information(link
->radv
, link
->network
->router_other_information
);
566 r
= sd_radv_set_router_lifetime(link
->radv
, link
->network
->router_lifetime_usec
);
570 r
= sd_radv_set_hop_limit(link
->radv
, link
->network
->router_hop_limit
);
574 if (link
->network
->router_lifetime_usec
> 0) {
575 r
= sd_radv_set_preference(link
->radv
, link
->network
->router_preference
);
580 if (link
->network
->router_retransmit_usec
> 0) {
581 r
= sd_radv_set_retransmit(link
->radv
, link
->network
->router_retransmit_usec
);
586 HASHMAP_FOREACH(p
, link
->network
->prefixes_by_section
) {
587 r
= radv_set_prefix(link
, p
);
588 if (r
< 0 && r
!= -EEXIST
)
592 HASHMAP_FOREACH(q
, link
->network
->route_prefixes_by_section
) {
593 r
= radv_set_route_prefix(link
, q
);
594 if (r
< 0 && r
!= -EEXIST
)
598 HASHMAP_FOREACH(n
, link
->network
->pref64_prefixes_by_section
) {
599 r
= radv_set_pref64_prefix(link
, n
);
600 if (r
< 0 && r
!= -EEXIST
)
604 (void) radv_find_uplink(link
, &uplink
);
606 r
= radv_set_dns(link
, uplink
);
608 return log_link_debug_errno(link
, r
, "Could not set RA DNS: %m");
610 r
= radv_set_domains(link
, uplink
);
612 return log_link_debug_errno(link
, r
, "Could not set RA Domains: %m");
614 r
= sd_radv_set_home_agent_information(link
->radv
, link
->network
->router_home_agent_information
);
618 r
= sd_radv_set_home_agent_preference(link
->radv
, link
->network
->router_home_agent_preference
);
622 r
= sd_radv_set_home_agent_lifetime(link
->radv
, link
->network
->home_agent_lifetime_usec
);
629 int radv_update_mac(Link
*link
) {
638 if (link
->hw_addr
.length
!= ETH_ALEN
)
641 restart
= sd_radv_is_running(link
->radv
);
643 r
= sd_radv_stop(link
->radv
);
647 r
= sd_radv_set_mac(link
->radv
, &link
->hw_addr
.ether
);
652 r
= sd_radv_start(link
->radv
);
660 static int radv_is_ready_to_configure(Link
*link
) {
661 bool needs_uplink
= false;
665 assert(link
->network
);
667 if (!link_is_ready_to_configure(link
, /* allow_unmanaged = */ false))
670 if (in6_addr_is_null(&link
->ipv6ll_address
))
673 if (link
->hw_addr
.length
!= ETH_ALEN
|| hw_addr_is_null(&link
->hw_addr
))
676 if (link
->network
->router_emit_dns
&& !link
->network
->router_dns
) {
677 _cleanup_free_
struct in6_addr
*dns
= NULL
;
680 r
= network_get_ipv6_dns(link
->network
, &dns
, &n_dns
);
684 needs_uplink
= r
== 0;
687 if (link
->network
->router_emit_domains
&&
688 !link
->network
->router_search_domains
&&
689 !link
->network
->search_domains
)
695 if (radv_find_uplink(link
, &uplink
) < 0)
698 if (uplink
&& !uplink
->network
)
705 static int radv_process_request(Request
*req
, Link
*link
, void *userdata
) {
710 r
= radv_is_ready_to_configure(link
);
714 r
= radv_configure(link
);
716 return log_link_warning_errno(link
, r
, "Failed to configure IPv6 Router Advertisement engine: %m");
718 if (link_has_carrier(link
)) {
719 r
= radv_start(link
);
721 return log_link_warning_errno(link
, r
, "Failed to start IPv6 Router Advertisement engine: %m");
724 log_link_debug(link
, "IPv6 Router Advertisement engine is configured%s.",
725 link_has_carrier(link
) ? " and started" : "");
729 int link_request_radv(Link
*link
) {
734 if (!link_radv_enabled(link
))
740 r
= link_queue_request(link
, REQUEST_TYPE_RADV
, radv_process_request
, NULL
);
742 return log_link_warning_errno(link
, r
, "Failed to request configuring of the IPv6 Router Advertisement engine: %m");
744 log_link_debug(link
, "Requested configuring of the IPv6 Router Advertisement engine.");
748 int radv_start(Link
*link
) {
752 assert(link
->network
);
757 if (!link_has_carrier(link
))
760 if (in6_addr_is_null(&link
->ipv6ll_address
))
763 if (sd_radv_is_running(link
->radv
))
766 if (link
->network
->dhcp_pd_announce
) {
767 r
= dhcp_request_prefix_delegation(link
);
769 return log_link_debug_errno(link
, r
, "Failed to request DHCP delegated subnet prefix: %m");
772 log_link_debug(link
, "Starting IPv6 Router Advertisements");
773 return sd_radv_start(link
->radv
);
778 const struct in6_addr
*prefix
,
780 usec_t lifetime_preferred_usec
,
781 usec_t lifetime_valid_usec
) {
783 _cleanup_(sd_radv_prefix_unrefp
) sd_radv_prefix
*p
= NULL
;
791 r
= sd_radv_prefix_new(&p
);
795 r
= sd_radv_prefix_set_prefix(p
, prefix
, prefix_len
);
799 r
= sd_radv_prefix_set_preferred_lifetime(p
, RADV_DEFAULT_PREFERRED_LIFETIME_USEC
, lifetime_preferred_usec
);
803 r
= sd_radv_prefix_set_valid_lifetime(p
, RADV_DEFAULT_VALID_LIFETIME_USEC
, lifetime_valid_usec
);
807 r
= sd_radv_add_prefix(link
->radv
, p
);
808 if (r
< 0 && r
!= -EEXIST
)
814 static int prefix_section_verify(Prefix
*p
) {
817 if (section_is_invalid(p
->section
))
820 if (in6_addr_is_null(&p
->prefix
))
821 return log_warning_errno(SYNTHETIC_ERRNO(EINVAL
),
822 "%s: [IPv6Prefix] section without Prefix= field configured, "
823 "or specified prefix is the null address. "
824 "Ignoring [IPv6Prefix] section from line %u.",
825 p
->section
->filename
, p
->section
->line
);
827 if (p
->prefixlen
< 3 || p
->prefixlen
> 128)
828 return log_warning_errno(SYNTHETIC_ERRNO(EINVAL
),
829 "%s: Invalid prefix length %u is specified in [IPv6Prefix] section. "
830 "Valid range is 3…128. Ignoring [IPv6Prefix] section from line %u.",
831 p
->section
->filename
, p
->prefixlen
, p
->section
->line
);
833 if (p
->prefixlen
> 64) {
834 log_info("%s:%u: Unusual prefix length %u (> 64) is specified in [IPv6Prefix] section from line %s%s.",
835 p
->section
->filename
, p
->section
->line
,
837 p
->assign
? ", refusing to assign an address in " : "",
838 p
->assign
? IN6_ADDR_PREFIX_TO_STRING(&p
->prefix
, p
->prefixlen
) : "");
843 if (p
->preferred_lifetime
> p
->valid_lifetime
)
844 return log_warning_errno(SYNTHETIC_ERRNO(EINVAL
),
845 "%s: The preferred lifetime %s is longer than the valid lifetime %s. "
846 "Ignoring [IPv6Prefix] section from line %u.",
847 p
->section
->filename
,
848 FORMAT_TIMESPAN(p
->preferred_lifetime
, USEC_PER_SEC
),
849 FORMAT_TIMESPAN(p
->valid_lifetime
, USEC_PER_SEC
),
855 void network_drop_invalid_prefixes(Network
*network
) {
860 HASHMAP_FOREACH(p
, network
->prefixes_by_section
)
861 if (prefix_section_verify(p
) < 0)
865 static int route_prefix_section_verify(RoutePrefix
*p
) {
866 if (section_is_invalid(p
->section
))
869 if (p
->prefixlen
> 128)
870 return log_warning_errno(SYNTHETIC_ERRNO(EINVAL
),
871 "%s: Invalid prefix length %u is specified in [IPv6RoutePrefix] section. "
872 "Valid range is 0…128. Ignoring [IPv6RoutePrefix] section from line %u.",
873 p
->section
->filename
, p
->prefixlen
, p
->section
->line
);
878 void network_drop_invalid_route_prefixes(Network
*network
) {
883 HASHMAP_FOREACH(p
, network
->route_prefixes_by_section
)
884 if (route_prefix_section_verify(p
) < 0)
885 route_prefix_free(p
);
888 void network_drop_invalid_pref64_prefixes(Network
*network
) {
893 HASHMAP_FOREACH(p
, network
->pref64_prefixes_by_section
)
894 if (section_is_invalid(p
->section
))
895 pref64_prefix_free(p
);
898 int config_parse_prefix(
900 const char *filename
,
903 unsigned section_line
,
910 _cleanup_(prefix_free_or_set_invalidp
) Prefix
*p
= NULL
;
911 Network
*network
= ASSERT_PTR(userdata
);
912 union in_addr_union a
;
920 r
= prefix_new_static(network
, filename
, section_line
, &p
);
924 r
= in_addr_prefix_from_string(rvalue
, AF_INET6
, &a
, &p
->prefixlen
);
926 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
927 "Prefix is invalid, ignoring assignment: %s", rvalue
);
931 (void) in6_addr_mask(&a
.in6
, p
->prefixlen
);
938 int config_parse_prefix_boolean(
940 const char *filename
,
943 unsigned section_line
,
950 _cleanup_(prefix_free_or_set_invalidp
) Prefix
*p
= NULL
;
951 Network
*network
= ASSERT_PTR(userdata
);
959 r
= prefix_new_static(network
, filename
, section_line
, &p
);
963 r
= parse_boolean(rvalue
);
965 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
966 "Failed to parse %s=, ignoring assignment: %s", lvalue
, rvalue
);
970 if (streq(lvalue
, "OnLink"))
972 else if (streq(lvalue
, "AddressAutoconfiguration"))
973 p
->address_auto_configuration
= r
;
974 else if (streq(lvalue
, "Assign"))
977 assert_not_reached();
983 int config_parse_prefix_lifetime(
985 const char *filename
,
988 unsigned section_line
,
995 _cleanup_(prefix_free_or_set_invalidp
) Prefix
*p
= NULL
;
996 Network
*network
= ASSERT_PTR(userdata
);
1005 r
= prefix_new_static(network
, filename
, section_line
, &p
);
1009 r
= parse_sec(rvalue
, &usec
);
1011 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
1012 "Lifetime is invalid, ignoring assignment: %s", rvalue
);
1016 if (usec
!= USEC_INFINITY
&& DIV_ROUND_UP(usec
, USEC_PER_SEC
) >= UINT32_MAX
) {
1017 log_syntax(unit
, LOG_WARNING
, filename
, line
, 0,
1018 "Lifetime is too long, ignoring assignment: %s", rvalue
);
1022 if (streq(lvalue
, "PreferredLifetimeSec"))
1023 p
->preferred_lifetime
= usec
;
1024 else if (streq(lvalue
, "ValidLifetimeSec"))
1025 p
->valid_lifetime
= usec
;
1027 assert_not_reached();
1033 int config_parse_prefix_metric(
1035 const char *filename
,
1037 const char *section
,
1038 unsigned section_line
,
1045 _cleanup_(prefix_free_or_set_invalidp
) Prefix
*p
= NULL
;
1046 Network
*network
= ASSERT_PTR(userdata
);
1054 r
= prefix_new_static(network
, filename
, section_line
, &p
);
1058 r
= safe_atou32(rvalue
, &p
->route_metric
);
1060 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
1061 "Failed to parse %s=, ignoring assignment: %s",
1070 int config_parse_prefix_token(
1072 const char *filename
,
1074 const char *section
,
1075 unsigned section_line
,
1082 _cleanup_(prefix_free_or_set_invalidp
) Prefix
*p
= NULL
;
1083 Network
*network
= ASSERT_PTR(userdata
);
1091 r
= prefix_new_static(network
, filename
, section_line
, &p
);
1095 r
= config_parse_address_generation_type(unit
, filename
, line
, section
, section_line
,
1096 lvalue
, ltype
, rvalue
, &p
->tokens
, userdata
);
1104 int config_parse_route_prefix(
1106 const char *filename
,
1108 const char *section
,
1109 unsigned section_line
,
1116 _cleanup_(route_prefix_free_or_set_invalidp
) RoutePrefix
*p
= NULL
;
1117 Network
*network
= ASSERT_PTR(userdata
);
1118 union in_addr_union a
;
1126 r
= route_prefix_new_static(network
, filename
, section_line
, &p
);
1130 r
= in_addr_prefix_from_string(rvalue
, AF_INET6
, &a
, &p
->prefixlen
);
1132 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
1133 "Route prefix is invalid, ignoring assignment: %s", rvalue
);
1137 (void) in6_addr_mask(&a
.in6
, p
->prefixlen
);
1144 int config_parse_route_prefix_lifetime(
1146 const char *filename
,
1148 const char *section
,
1149 unsigned section_line
,
1156 _cleanup_(route_prefix_free_or_set_invalidp
) RoutePrefix
*p
= NULL
;
1157 Network
*network
= ASSERT_PTR(userdata
);
1166 r
= route_prefix_new_static(network
, filename
, section_line
, &p
);
1170 r
= parse_sec(rvalue
, &usec
);
1172 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
1173 "Route lifetime is invalid, ignoring assignment: %s", rvalue
);
1177 if (usec
!= USEC_INFINITY
&& DIV_ROUND_UP(usec
, USEC_PER_SEC
) >= UINT32_MAX
) {
1178 log_syntax(unit
, LOG_WARNING
, filename
, line
, 0,
1179 "Lifetime is too long, ignoring assignment: %s", rvalue
);
1189 int config_parse_pref64_prefix(
1191 const char *filename
,
1193 const char *section
,
1194 unsigned section_line
,
1201 _cleanup_(pref64_prefix_free_or_set_invalidp
) pref64Prefix
*p
= NULL
;
1202 Network
*network
= ASSERT_PTR(userdata
);
1203 union in_addr_union a
;
1212 r
= pref64_prefix_new_static(network
, filename
, section_line
, &p
);
1216 r
= in_addr_prefix_from_string(rvalue
, AF_INET6
, &a
, &prefixlen
);
1218 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
1219 "PREF64 prefix is invalid, ignoring assignment: %s", rvalue
);
1223 if (!IN_SET(prefixlen
, 96, 64, 56, 48, 40, 32)) {
1224 log_syntax(unit
, LOG_WARNING
, filename
, line
, 0,
1225 "PREF64 prefixlen is invalid, ignoring assignment: %s", rvalue
);
1229 (void) in6_addr_mask(&a
.in6
, prefixlen
);
1231 p
->prefixlen
= prefixlen
;
1237 int config_parse_pref64_prefix_lifetime(
1239 const char *filename
,
1241 const char *section
,
1242 unsigned section_line
,
1249 _cleanup_(pref64_prefix_free_or_set_invalidp
) pref64Prefix
*p
= NULL
;
1250 Network
*network
= ASSERT_PTR(userdata
);
1259 r
= pref64_prefix_new_static(network
, filename
, section_line
, &p
);
1263 r
= parse_sec(rvalue
, &usec
);
1265 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
1266 "PREF64 lifetime is invalid, ignoring assignment: %s", rvalue
);
1270 if (usec
== USEC_INFINITY
|| DIV_ROUND_UP(usec
, 8 * USEC_PER_SEC
) >= UINT64_C(1) << 13) {
1271 log_syntax(unit
, LOG_WARNING
, filename
, line
, 0,
1272 "PREF64 lifetime is too long, ignoring assignment: %s", rvalue
);
1282 int config_parse_radv_dns(
1284 const char *filename
,
1286 const char *section
,
1287 unsigned section_line
,
1301 if (isempty(rvalue
)) {
1302 n
->n_router_dns
= 0;
1303 n
->router_dns
= mfree(n
->router_dns
);
1307 for (const char *p
= rvalue
;;) {
1308 _cleanup_free_
char *w
= NULL
;
1309 union in_addr_union a
;
1311 r
= extract_first_word(&p
, &w
, NULL
, 0);
1315 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
1316 "Failed to extract word, ignoring: %s", rvalue
);
1322 if (streq(w
, "_link_local"))
1325 r
= in_addr_from_string(AF_INET6
, w
, &a
);
1327 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
1328 "Failed to parse DNS server address, ignoring: %s", w
);
1332 if (in_addr_is_null(AF_INET6
, &a
)) {
1333 log_syntax(unit
, LOG_WARNING
, filename
, line
, 0,
1334 "DNS server address is null, ignoring: %s", w
);
1340 m
= reallocarray(n
->router_dns
, n
->n_router_dns
+ 1, sizeof(struct in6_addr
));
1344 m
[n
->n_router_dns
++] = a
.in6
;
1349 int config_parse_radv_search_domains(
1351 const char *filename
,
1353 const char *section
,
1354 unsigned section_line
,
1368 if (isempty(rvalue
)) {
1369 n
->router_search_domains
= ordered_set_free(n
->router_search_domains
);
1373 for (const char *p
= rvalue
;;) {
1374 _cleanup_free_
char *w
= NULL
, *idna
= NULL
;
1376 r
= extract_first_word(&p
, &w
, NULL
, 0);
1380 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
1381 "Failed to extract word, ignoring: %s", rvalue
);
1387 r
= dns_name_apply_idna(w
, &idna
);
1389 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
1390 "Failed to apply IDNA to domain name '%s', ignoring: %m", w
);
1393 /* transfer ownership to simplify subsequent operations */
1396 r
= ordered_set_ensure_allocated(&n
->router_search_domains
, &string_hash_ops_free
);
1400 r
= ordered_set_consume(n
->router_search_domains
, TAKE_PTR(idna
));
1406 static const char * const radv_prefix_delegation_table
[_RADV_PREFIX_DELEGATION_MAX
] = {
1407 [RADV_PREFIX_DELEGATION_NONE
] = "no",
1408 [RADV_PREFIX_DELEGATION_STATIC
] = "static",
1409 [RADV_PREFIX_DELEGATION_DHCP6
] = "dhcpv6",
1410 [RADV_PREFIX_DELEGATION_BOTH
] = "yes",
1413 DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(
1414 radv_prefix_delegation
,
1415 RADVPrefixDelegation
,
1416 RADV_PREFIX_DELEGATION_BOTH
);
1418 int config_parse_router_prefix_delegation(
1420 const char *filename
,
1422 const char *section
,
1423 unsigned section_line
,
1430 RADVPrefixDelegation val
, *ra
= ASSERT_PTR(data
);
1437 if (streq(lvalue
, "IPv6SendRA")) {
1438 r
= parse_boolean(rvalue
);
1440 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
1441 "Invalid %s= setting, ignoring assignment: %s", lvalue
, rvalue
);
1445 /* When IPv6SendRA= is enabled, only static prefixes are sent by default, and users
1446 * need to explicitly enable DHCPv6PrefixDelegation=. */
1447 *ra
= r
? RADV_PREFIX_DELEGATION_STATIC
: RADV_PREFIX_DELEGATION_NONE
;
1451 /* For backward compatibility */
1452 val
= radv_prefix_delegation_from_string(rvalue
);
1454 log_syntax(unit
, LOG_WARNING
, filename
, line
, val
,
1455 "Invalid %s= setting, ignoring assignment: %s", lvalue
, rvalue
);
1463 int config_parse_router_lifetime(
1465 const char *filename
,
1467 const char *section
,
1468 unsigned section_line
,
1475 usec_t usec
, *lifetime
= ASSERT_PTR(data
);
1483 if (isempty(rvalue
)) {
1484 *lifetime
= RADV_DEFAULT_ROUTER_LIFETIME_USEC
;
1488 r
= parse_sec(rvalue
, &usec
);
1490 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
1491 "Failed to parse router lifetime, ignoring assignment: %s", rvalue
);
1495 if (usec
< RADV_MIN_ROUTER_LIFETIME_USEC
) {
1496 log_syntax(unit
, LOG_WARNING
, filename
, line
, 0,
1497 "Router lifetime %s is too short, using %s.",
1498 FORMAT_TIMESPAN(usec
, USEC_PER_SEC
),
1499 FORMAT_TIMESPAN(RADV_MIN_ROUTER_LIFETIME_USEC
, USEC_PER_SEC
));
1500 usec
= RADV_MIN_ROUTER_LIFETIME_USEC
;
1501 } else if (usec
> RADV_MAX_ROUTER_LIFETIME_USEC
) {
1502 log_syntax(unit
, LOG_WARNING
, filename
, line
, 0,
1503 "Router lifetime %s is too large, using %s.",
1504 FORMAT_TIMESPAN(usec
, USEC_PER_SEC
),
1505 FORMAT_TIMESPAN(RADV_MAX_ROUTER_LIFETIME_USEC
, USEC_PER_SEC
));
1506 usec
= RADV_MAX_ROUTER_LIFETIME_USEC
;
1514 int config_parse_router_retransmit(
1516 const char *filename
,
1518 const char *section
,
1519 unsigned section_line
,
1526 usec_t usec
, *router_retransmit_usec
= ASSERT_PTR(data
);
1534 if (isempty(rvalue
)) {
1535 *router_retransmit_usec
= 0;
1539 r
= parse_sec(rvalue
, &usec
);
1541 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
1542 "Failed to parse %s=, ignoring assignment: %s", lvalue
, rvalue
);
1546 if (usec
!= USEC_INFINITY
&&
1547 usec
> RADV_MAX_RETRANSMIT_USEC
) {
1548 log_syntax(unit
, LOG_WARNING
, filename
, line
, 0,
1549 "Invalid [%s] %s=, ignoring assignment: %s", section
, lvalue
, rvalue
);
1553 *router_retransmit_usec
= usec
;
1557 int config_parse_router_preference(
1559 const char *filename
,
1561 const char *section
,
1562 unsigned section_line
,
1569 Network
*network
= userdata
;
1577 if (streq(rvalue
, "high"))
1578 network
->router_preference
= SD_NDISC_PREFERENCE_HIGH
;
1579 else if (STR_IN_SET(rvalue
, "medium", "normal", "default"))
1580 network
->router_preference
= SD_NDISC_PREFERENCE_MEDIUM
;
1581 else if (streq(rvalue
, "low"))
1582 network
->router_preference
= SD_NDISC_PREFERENCE_LOW
;
1584 log_syntax(unit
, LOG_WARNING
, filename
, line
, 0,
1585 "Invalid router preference, ignoring assignment: %s", rvalue
);
1590 int config_parse_router_home_agent_lifetime(
1592 const char *filename
,
1594 const char *section
,
1595 unsigned section_line
,
1602 usec_t usec
, *home_agent_lifetime_usec
= ASSERT_PTR(data
);
1610 if (isempty(rvalue
)) {
1611 *home_agent_lifetime_usec
= 0;
1615 r
= parse_sec(rvalue
, &usec
);
1617 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
1618 "Failed to parse %s=, ignoring assignment: %s", lvalue
, rvalue
);
1622 if (!timestamp_is_set(usec
) ||
1623 usec
> RADV_HOME_AGENT_MAX_LIFETIME_USEC
) {
1624 log_syntax(unit
, LOG_WARNING
, filename
, line
, 0,
1625 "Invalid [%s] %s=, ignoring assignment: %s", section
, lvalue
, rvalue
);
1629 *home_agent_lifetime_usec
= usec
;