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
);
54 bool link_radv_enabled(Link
*link
) {
57 if (!link_may_have_ipv6ll(link
, /* check_multicast = */ true))
60 if (link
->hw_addr
.length
!= ETH_ALEN
)
63 return link
->network
->router_prefix_delegation
;
66 Prefix
*prefix_free(Prefix
*prefix
) {
70 if (prefix
->network
) {
71 assert(prefix
->section
);
72 hashmap_remove(prefix
->network
->prefixes_by_section
, prefix
->section
);
75 config_section_free(prefix
->section
);
76 set_free(prefix
->tokens
);
81 DEFINE_SECTION_CLEANUP_FUNCTIONS(Prefix
, prefix_free
);
83 static int prefix_new_static(Network
*network
, const char *filename
, unsigned section_line
, Prefix
**ret
) {
84 _cleanup_(config_section_freep
) ConfigSection
*n
= NULL
;
85 _cleanup_(prefix_freep
) Prefix
*prefix
= NULL
;
91 assert(section_line
> 0);
93 r
= config_section_new(filename
, section_line
, &n
);
97 prefix
= hashmap_get(network
->prefixes_by_section
, n
);
99 *ret
= TAKE_PTR(prefix
);
103 prefix
= new(Prefix
, 1);
109 .section
= TAKE_PTR(n
),
111 .preferred_lifetime
= RADV_DEFAULT_PREFERRED_LIFETIME_USEC
,
112 .valid_lifetime
= RADV_DEFAULT_VALID_LIFETIME_USEC
,
114 .address_auto_configuration
= true,
117 r
= hashmap_ensure_put(&network
->prefixes_by_section
, &config_section_hash_ops
, prefix
->section
, prefix
);
121 *ret
= TAKE_PTR(prefix
);
125 RoutePrefix
*route_prefix_free(RoutePrefix
*prefix
) {
129 if (prefix
->network
) {
130 assert(prefix
->section
);
131 hashmap_remove(prefix
->network
->route_prefixes_by_section
, prefix
->section
);
134 config_section_free(prefix
->section
);
136 return mfree(prefix
);
139 DEFINE_SECTION_CLEANUP_FUNCTIONS(RoutePrefix
, route_prefix_free
);
141 static int route_prefix_new_static(Network
*network
, const char *filename
, unsigned section_line
, RoutePrefix
**ret
) {
142 _cleanup_(config_section_freep
) ConfigSection
*n
= NULL
;
143 _cleanup_(route_prefix_freep
) RoutePrefix
*prefix
= NULL
;
149 assert(section_line
> 0);
151 r
= config_section_new(filename
, section_line
, &n
);
155 prefix
= hashmap_get(network
->route_prefixes_by_section
, n
);
157 *ret
= TAKE_PTR(prefix
);
161 prefix
= new(RoutePrefix
, 1);
165 *prefix
= (RoutePrefix
) {
167 .section
= TAKE_PTR(n
),
169 .lifetime
= RADV_DEFAULT_VALID_LIFETIME_USEC
,
172 r
= hashmap_ensure_put(&network
->route_prefixes_by_section
, &config_section_hash_ops
, prefix
->section
, prefix
);
176 *ret
= TAKE_PTR(prefix
);
180 int link_request_radv_addresses(Link
*link
) {
186 if (!link_radv_enabled(link
))
189 HASHMAP_FOREACH(p
, link
->network
->prefixes_by_section
) {
190 _cleanup_set_free_ Set
*addresses
= NULL
;
196 /* radv_generate_addresses() below requires the prefix length <= 64. */
197 if (p
->prefixlen
> 64)
200 r
= radv_generate_addresses(link
, p
->tokens
, &p
->prefix
, p
->prefixlen
, &addresses
);
204 SET_FOREACH(a
, addresses
) {
205 _cleanup_(address_freep
) Address
*address
= NULL
;
207 r
= address_new(&address
);
211 address
->source
= NETWORK_CONFIG_SOURCE_STATIC
;
212 address
->family
= AF_INET6
;
213 address
->in_addr
.in6
= *a
;
214 address
->prefixlen
= p
->prefixlen
;
215 address
->route_metric
= p
->route_metric
;
217 r
= link_request_static_address(link
, address
);
226 static uint32_t usec_to_lifetime(usec_t usec
) {
229 if (usec
== USEC_INFINITY
)
232 t
= DIV_ROUND_UP(usec
, USEC_PER_SEC
);
239 static int radv_set_prefix(Link
*link
, Prefix
*prefix
) {
240 _cleanup_(sd_radv_prefix_unrefp
) sd_radv_prefix
*p
= NULL
;
247 r
= sd_radv_prefix_new(&p
);
251 r
= sd_radv_prefix_set_prefix(p
, &prefix
->prefix
, prefix
->prefixlen
);
255 r
= sd_radv_prefix_set_preferred_lifetime(p
, prefix
->preferred_lifetime
, USEC_INFINITY
);
259 r
= sd_radv_prefix_set_valid_lifetime(p
, prefix
->valid_lifetime
, USEC_INFINITY
);
263 r
= sd_radv_prefix_set_onlink(p
, prefix
->onlink
);
267 r
= sd_radv_prefix_set_address_autoconfiguration(p
, prefix
->address_auto_configuration
);
271 return sd_radv_add_prefix(link
->radv
, p
);
274 static int radv_set_route_prefix(Link
*link
, RoutePrefix
*prefix
) {
275 _cleanup_(sd_radv_route_prefix_unrefp
) sd_radv_route_prefix
*p
= NULL
;
282 r
= sd_radv_route_prefix_new(&p
);
286 r
= sd_radv_route_prefix_set_prefix(p
, &prefix
->prefix
, prefix
->prefixlen
);
290 r
= sd_radv_route_prefix_set_lifetime(p
, prefix
->lifetime
, USEC_INFINITY
);
294 return sd_radv_add_route_prefix(link
->radv
, p
);
297 static int network_get_ipv6_dns(Network
*network
, struct in6_addr
**ret_addresses
, size_t *ret_size
) {
298 _cleanup_free_
struct in6_addr
*addresses
= NULL
;
299 size_t n_addresses
= 0;
302 assert(ret_addresses
);
305 for (size_t i
= 0; i
< network
->n_dns
; i
++) {
306 union in_addr_union
*addr
;
308 if (network
->dns
[i
]->family
!= AF_INET6
)
311 addr
= &network
->dns
[i
]->address
;
313 if (in_addr_is_null(AF_INET6
, addr
) ||
314 in_addr_is_link_local(AF_INET6
, addr
) ||
315 in_addr_is_localhost(AF_INET6
, addr
))
318 if (!GREEDY_REALLOC(addresses
, n_addresses
+ 1))
321 addresses
[n_addresses
++] = addr
->in6
;
324 *ret_addresses
= TAKE_PTR(addresses
);
325 *ret_size
= n_addresses
;
330 static int radv_set_dns(Link
*link
, Link
*uplink
) {
331 _cleanup_free_
struct in6_addr
*dns
= NULL
;
335 if (!link
->network
->router_emit_dns
)
338 if (link
->network
->router_dns
) {
341 dns
= new(struct in6_addr
, link
->network
->n_router_dns
);
346 for (size_t i
= 0; i
< link
->network
->n_router_dns
; i
++)
347 if (in6_addr_is_null(&link
->network
->router_dns
[i
])) {
348 if (in6_addr_is_set(&link
->ipv6ll_address
))
349 *(p
++) = link
->ipv6ll_address
;
351 *(p
++) = link
->network
->router_dns
[i
];
358 r
= network_get_ipv6_dns(link
->network
, &dns
, &n_dns
);
363 assert(uplink
->network
);
365 r
= network_get_ipv6_dns(uplink
->network
, &dns
, &n_dns
);
373 return sd_radv_set_rdnss(link
->radv
,
374 usec_to_lifetime(link
->network
->router_dns_lifetime_usec
),
378 static int radv_set_domains(Link
*link
, Link
*uplink
) {
379 _cleanup_free_
char **s
= NULL
; /* just free() because the strings are owned by the set */
380 OrderedSet
*search_domains
;
382 if (!link
->network
->router_emit_domains
)
385 search_domains
= link
->network
->router_search_domains
;
390 search_domains
= link
->network
->search_domains
;
395 assert(uplink
->network
);
397 search_domains
= uplink
->network
->search_domains
;
405 s
= ordered_set_get_strv(search_domains
);
409 return sd_radv_set_dnssl(link
->radv
,
410 usec_to_lifetime(link
->network
->router_dns_lifetime_usec
),
415 static int radv_find_uplink(Link
*link
, Link
**ret
) {
420 if (link
->network
->router_uplink_name
)
421 return link_get_by_name(link
->manager
, link
->network
->router_uplink_name
, ret
);
423 if (link
->network
->router_uplink_index
> 0)
424 return link_get_by_index(link
->manager
, link
->network
->router_uplink_index
, ret
);
426 if (link
->network
->router_uplink_index
== UPLINK_INDEX_AUTO
) {
427 if (link_dhcp_pd_is_enabled(link
))
428 r
= dhcp_pd_find_uplink(link
, ret
); /* When DHCP-PD is enabled, use its uplink. */
430 r
= manager_find_uplink(link
->manager
, AF_INET6
, link
, ret
);
432 /* It is not necessary to propagate error in automatic selection. */
441 static int radv_configure(Link
*link
) {
448 assert(link
->network
);
453 r
= sd_radv_new(&link
->radv
);
457 r
= sd_radv_attach_event(link
->radv
, link
->manager
->event
, 0);
461 if (link
->hw_addr
.length
== ETH_ALEN
) {
462 r
= sd_radv_set_mac(link
->radv
, &link
->hw_addr
.ether
);
467 r
= sd_radv_set_ifindex(link
->radv
, link
->ifindex
);
471 r
= sd_radv_set_managed_information(link
->radv
, link
->network
->router_managed
);
475 r
= sd_radv_set_other_information(link
->radv
, link
->network
->router_other_information
);
479 r
= sd_radv_set_router_lifetime(link
->radv
, link
->network
->router_lifetime_usec
);
483 if (link
->network
->router_lifetime_usec
> 0) {
484 r
= sd_radv_set_preference(link
->radv
, link
->network
->router_preference
);
489 HASHMAP_FOREACH(p
, link
->network
->prefixes_by_section
) {
490 r
= radv_set_prefix(link
, p
);
491 if (r
< 0 && r
!= -EEXIST
)
495 HASHMAP_FOREACH(q
, link
->network
->route_prefixes_by_section
) {
496 r
= radv_set_route_prefix(link
, q
);
497 if (r
< 0 && r
!= -EEXIST
)
501 (void) radv_find_uplink(link
, &uplink
);
503 r
= radv_set_dns(link
, uplink
);
505 return log_link_debug_errno(link
, r
, "Could not set RA DNS: %m");
507 r
= radv_set_domains(link
, uplink
);
509 return log_link_debug_errno(link
, r
, "Could not set RA Domains: %m");
514 int radv_update_mac(Link
*link
) {
523 if (link
->hw_addr
.length
!= ETH_ALEN
)
526 restart
= sd_radv_is_running(link
->radv
);
528 r
= sd_radv_stop(link
->radv
);
532 r
= sd_radv_set_mac(link
->radv
, &link
->hw_addr
.ether
);
537 r
= sd_radv_start(link
->radv
);
545 static int radv_is_ready_to_configure(Link
*link
) {
546 bool needs_uplink
= false;
550 assert(link
->network
);
552 if (!link_is_ready_to_configure(link
, /* allow_unmanaged = */ false))
555 if (in6_addr_is_null(&link
->ipv6ll_address
))
558 if (link
->hw_addr
.length
!= ETH_ALEN
|| hw_addr_is_null(&link
->hw_addr
))
561 if (link
->network
->router_emit_dns
&& !link
->network
->router_dns
) {
562 _cleanup_free_
struct in6_addr
*dns
= NULL
;
565 r
= network_get_ipv6_dns(link
->network
, &dns
, &n_dns
);
569 needs_uplink
= r
== 0;
572 if (link
->network
->router_emit_domains
&&
573 !link
->network
->router_search_domains
&&
574 !link
->network
->search_domains
)
580 if (radv_find_uplink(link
, &uplink
) < 0)
583 if (uplink
&& !uplink
->network
)
590 static int radv_process_request(Request
*req
, Link
*link
, void *userdata
) {
595 r
= radv_is_ready_to_configure(link
);
599 r
= radv_configure(link
);
601 return log_link_warning_errno(link
, r
, "Failed to configure IPv6 Router Advertisement engine: %m");
603 if (link_has_carrier(link
)) {
604 r
= radv_start(link
);
606 return log_link_warning_errno(link
, r
, "Failed to start IPv6 Router Advertisement engine: %m");
609 log_link_debug(link
, "IPv6 Router Advertisement engine is configured%s.",
610 link_has_carrier(link
) ? " and started" : "");
614 int link_request_radv(Link
*link
) {
619 if (!link_radv_enabled(link
))
625 r
= link_queue_request(link
, REQUEST_TYPE_RADV
, radv_process_request
, NULL
);
627 return log_link_warning_errno(link
, r
, "Failed to request configuring of the IPv6 Router Advertisement engine: %m");
629 log_link_debug(link
, "Requested configuring of the IPv6 Router Advertisement engine.");
633 int radv_start(Link
*link
) {
637 assert(link
->network
);
642 if (!link_has_carrier(link
))
645 if (in6_addr_is_null(&link
->ipv6ll_address
))
648 if (sd_radv_is_running(link
->radv
))
651 if (link
->network
->dhcp_pd_announce
) {
652 r
= dhcp_request_prefix_delegation(link
);
654 return log_link_debug_errno(link
, r
, "Failed to request DHCP delegated subnet prefix: %m");
657 log_link_debug(link
, "Starting IPv6 Router Advertisements");
658 return sd_radv_start(link
->radv
);
663 const struct in6_addr
*prefix
,
665 usec_t lifetime_preferred_usec
,
666 usec_t lifetime_valid_usec
) {
668 _cleanup_(sd_radv_prefix_unrefp
) sd_radv_prefix
*p
= NULL
;
676 r
= sd_radv_prefix_new(&p
);
680 r
= sd_radv_prefix_set_prefix(p
, prefix
, prefix_len
);
684 r
= sd_radv_prefix_set_preferred_lifetime(p
, RADV_DEFAULT_PREFERRED_LIFETIME_USEC
, lifetime_preferred_usec
);
688 r
= sd_radv_prefix_set_valid_lifetime(p
, RADV_DEFAULT_VALID_LIFETIME_USEC
, lifetime_valid_usec
);
692 r
= sd_radv_add_prefix(link
->radv
, p
);
693 if (r
< 0 && r
!= -EEXIST
)
699 static int prefix_section_verify(Prefix
*p
) {
702 if (section_is_invalid(p
->section
))
705 if (in6_addr_is_null(&p
->prefix
))
706 return log_warning_errno(SYNTHETIC_ERRNO(EINVAL
),
707 "%s: [IPv6Prefix] section without Prefix= field configured, "
708 "or specified prefix is the null address. "
709 "Ignoring [IPv6Prefix] section from line %u.",
710 p
->section
->filename
, p
->section
->line
);
712 if (p
->prefixlen
< 3 || p
->prefixlen
> 128)
713 return log_warning_errno(SYNTHETIC_ERRNO(EINVAL
),
714 "%s: Invalid prefix length %u is specified in [IPv6Prefix] section. "
715 "Valid range is 3…128. Ignoring [IPv6Prefix] section from line %u.",
716 p
->section
->filename
, p
->prefixlen
, p
->section
->line
);
718 if (p
->prefixlen
> 64) {
719 log_info("%s:%u: Unusual prefix length %u (> 64) is specified in [IPv6Prefix] section from line %s%s.",
720 p
->section
->filename
, p
->section
->line
,
722 p
->assign
? ", refusing to assign an address in " : "",
723 p
->assign
? IN6_ADDR_PREFIX_TO_STRING(&p
->prefix
, p
->prefixlen
) : "");
728 if (p
->valid_lifetime
== 0)
729 return log_warning_errno(SYNTHETIC_ERRNO(EINVAL
),
730 "%s: The valid lifetime of prefix cannot be zero. "
731 "Ignoring [IPv6Prefix] section from line %u.",
732 p
->section
->filename
, p
->section
->line
);
734 if (p
->preferred_lifetime
> p
->valid_lifetime
)
735 return log_warning_errno(SYNTHETIC_ERRNO(EINVAL
),
736 "%s: The preferred lifetime %s is longer than the valid lifetime %s. "
737 "Ignoring [IPv6Prefix] section from line %u.",
738 p
->section
->filename
,
739 FORMAT_TIMESPAN(p
->preferred_lifetime
, USEC_PER_SEC
),
740 FORMAT_TIMESPAN(p
->valid_lifetime
, USEC_PER_SEC
),
746 void network_drop_invalid_prefixes(Network
*network
) {
751 HASHMAP_FOREACH(p
, network
->prefixes_by_section
)
752 if (prefix_section_verify(p
) < 0)
756 static int route_prefix_section_verify(RoutePrefix
*p
) {
757 if (section_is_invalid(p
->section
))
760 if (p
->prefixlen
> 128)
761 return log_warning_errno(SYNTHETIC_ERRNO(EINVAL
),
762 "%s: Invalid prefix length %u is specified in [IPv6RoutePrefix] section. "
763 "Valid range is 0…128. Ignoring [IPv6RoutePrefix] section from line %u.",
764 p
->section
->filename
, p
->prefixlen
, p
->section
->line
);
766 if (p
->lifetime
== 0)
767 return log_warning_errno(SYNTHETIC_ERRNO(EINVAL
),
768 "%s: The lifetime of route cannot be zero. "
769 "Ignoring [IPv6RoutePrefix] section from line %u.",
770 p
->section
->filename
, p
->section
->line
);
775 void network_drop_invalid_route_prefixes(Network
*network
) {
780 HASHMAP_FOREACH(p
, network
->route_prefixes_by_section
)
781 if (route_prefix_section_verify(p
) < 0)
782 route_prefix_free(p
);
785 int config_parse_prefix(
787 const char *filename
,
790 unsigned section_line
,
797 _cleanup_(prefix_free_or_set_invalidp
) Prefix
*p
= NULL
;
798 Network
*network
= ASSERT_PTR(userdata
);
799 union in_addr_union a
;
807 r
= prefix_new_static(network
, filename
, section_line
, &p
);
811 r
= in_addr_prefix_from_string(rvalue
, AF_INET6
, &a
, &p
->prefixlen
);
813 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
814 "Prefix is invalid, ignoring assignment: %s", rvalue
);
818 (void) in6_addr_mask(&a
.in6
, p
->prefixlen
);
825 int config_parse_prefix_boolean(
827 const char *filename
,
830 unsigned section_line
,
837 _cleanup_(prefix_free_or_set_invalidp
) Prefix
*p
= NULL
;
838 Network
*network
= ASSERT_PTR(userdata
);
846 r
= prefix_new_static(network
, filename
, section_line
, &p
);
850 r
= parse_boolean(rvalue
);
852 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
853 "Failed to parse %s=, ignoring assignment: %s", lvalue
, rvalue
);
857 if (streq(lvalue
, "OnLink"))
859 else if (streq(lvalue
, "AddressAutoconfiguration"))
860 p
->address_auto_configuration
= r
;
861 else if (streq(lvalue
, "Assign"))
864 assert_not_reached();
870 int config_parse_prefix_lifetime(
872 const char *filename
,
875 unsigned section_line
,
882 _cleanup_(prefix_free_or_set_invalidp
) Prefix
*p
= NULL
;
883 Network
*network
= ASSERT_PTR(userdata
);
892 r
= prefix_new_static(network
, filename
, section_line
, &p
);
896 r
= parse_sec(rvalue
, &usec
);
898 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
899 "Lifetime is invalid, ignoring assignment: %s", rvalue
);
903 if (usec
!= USEC_INFINITY
&& DIV_ROUND_UP(usec
, USEC_PER_SEC
) >= UINT32_MAX
) {
904 log_syntax(unit
, LOG_WARNING
, filename
, line
, 0,
905 "Lifetime is too long, ignoring assignment: %s", rvalue
);
909 if (streq(lvalue
, "PreferredLifetimeSec"))
910 p
->preferred_lifetime
= usec
;
911 else if (streq(lvalue
, "ValidLifetimeSec"))
912 p
->valid_lifetime
= usec
;
914 assert_not_reached();
920 int config_parse_prefix_metric(
922 const char *filename
,
925 unsigned section_line
,
932 _cleanup_(prefix_free_or_set_invalidp
) Prefix
*p
= NULL
;
933 Network
*network
= ASSERT_PTR(userdata
);
941 r
= prefix_new_static(network
, filename
, section_line
, &p
);
945 r
= safe_atou32(rvalue
, &p
->route_metric
);
947 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
948 "Failed to parse %s=, ignoring assignment: %s",
957 int config_parse_prefix_token(
959 const char *filename
,
962 unsigned section_line
,
969 _cleanup_(prefix_free_or_set_invalidp
) Prefix
*p
= NULL
;
970 Network
*network
= ASSERT_PTR(userdata
);
978 r
= prefix_new_static(network
, filename
, section_line
, &p
);
982 r
= config_parse_address_generation_type(unit
, filename
, line
, section
, section_line
,
983 lvalue
, ltype
, rvalue
, &p
->tokens
, userdata
);
991 int config_parse_route_prefix(
993 const char *filename
,
996 unsigned section_line
,
1003 _cleanup_(route_prefix_free_or_set_invalidp
) RoutePrefix
*p
= NULL
;
1004 Network
*network
= ASSERT_PTR(userdata
);
1005 union in_addr_union a
;
1013 r
= route_prefix_new_static(network
, filename
, section_line
, &p
);
1017 r
= in_addr_prefix_from_string(rvalue
, AF_INET6
, &a
, &p
->prefixlen
);
1019 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
1020 "Route prefix is invalid, ignoring assignment: %s", rvalue
);
1024 (void) in6_addr_mask(&a
.in6
, p
->prefixlen
);
1031 int config_parse_route_prefix_lifetime(
1033 const char *filename
,
1035 const char *section
,
1036 unsigned section_line
,
1043 _cleanup_(route_prefix_free_or_set_invalidp
) RoutePrefix
*p
= NULL
;
1044 Network
*network
= ASSERT_PTR(userdata
);
1053 r
= route_prefix_new_static(network
, filename
, section_line
, &p
);
1057 r
= parse_sec(rvalue
, &usec
);
1059 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
1060 "Route lifetime is invalid, ignoring assignment: %s", rvalue
);
1064 if (usec
!= USEC_INFINITY
&& DIV_ROUND_UP(usec
, USEC_PER_SEC
) >= UINT32_MAX
) {
1065 log_syntax(unit
, LOG_WARNING
, filename
, line
, 0,
1066 "Lifetime is too long, ignoring assignment: %s", rvalue
);
1076 int config_parse_radv_dns(
1078 const char *filename
,
1080 const char *section
,
1081 unsigned section_line
,
1095 if (isempty(rvalue
)) {
1096 n
->n_router_dns
= 0;
1097 n
->router_dns
= mfree(n
->router_dns
);
1101 for (const char *p
= rvalue
;;) {
1102 _cleanup_free_
char *w
= NULL
;
1103 union in_addr_union a
;
1105 r
= extract_first_word(&p
, &w
, NULL
, 0);
1109 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
1110 "Failed to extract word, ignoring: %s", rvalue
);
1116 if (streq(w
, "_link_local"))
1119 r
= in_addr_from_string(AF_INET6
, w
, &a
);
1121 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
1122 "Failed to parse DNS server address, ignoring: %s", w
);
1126 if (in_addr_is_null(AF_INET6
, &a
)) {
1127 log_syntax(unit
, LOG_WARNING
, filename
, line
, 0,
1128 "DNS server address is null, ignoring: %s", w
);
1134 m
= reallocarray(n
->router_dns
, n
->n_router_dns
+ 1, sizeof(struct in6_addr
));
1138 m
[n
->n_router_dns
++] = a
.in6
;
1143 int config_parse_radv_search_domains(
1145 const char *filename
,
1147 const char *section
,
1148 unsigned section_line
,
1162 if (isempty(rvalue
)) {
1163 n
->router_search_domains
= ordered_set_free(n
->router_search_domains
);
1167 for (const char *p
= rvalue
;;) {
1168 _cleanup_free_
char *w
= NULL
, *idna
= NULL
;
1170 r
= extract_first_word(&p
, &w
, NULL
, 0);
1174 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
1175 "Failed to extract word, ignoring: %s", rvalue
);
1181 r
= dns_name_apply_idna(w
, &idna
);
1183 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
1184 "Failed to apply IDNA to domain name '%s', ignoring: %m", w
);
1187 /* transfer ownership to simplify subsequent operations */
1190 r
= ordered_set_ensure_allocated(&n
->router_search_domains
, &string_hash_ops_free
);
1194 r
= ordered_set_consume(n
->router_search_domains
, TAKE_PTR(idna
));
1200 static const char * const radv_prefix_delegation_table
[_RADV_PREFIX_DELEGATION_MAX
] = {
1201 [RADV_PREFIX_DELEGATION_NONE
] = "no",
1202 [RADV_PREFIX_DELEGATION_STATIC
] = "static",
1203 [RADV_PREFIX_DELEGATION_DHCP6
] = "dhcpv6",
1204 [RADV_PREFIX_DELEGATION_BOTH
] = "yes",
1207 DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(
1208 radv_prefix_delegation
,
1209 RADVPrefixDelegation
,
1210 RADV_PREFIX_DELEGATION_BOTH
);
1212 int config_parse_router_prefix_delegation(
1214 const char *filename
,
1216 const char *section
,
1217 unsigned section_line
,
1224 RADVPrefixDelegation val
, *ra
= ASSERT_PTR(data
);
1231 if (streq(lvalue
, "IPv6SendRA")) {
1232 r
= parse_boolean(rvalue
);
1234 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
1235 "Invalid %s= setting, ignoring assignment: %s", lvalue
, rvalue
);
1239 /* When IPv6SendRA= is enabled, only static prefixes are sent by default, and users
1240 * need to explicitly enable DHCPv6PrefixDelegation=. */
1241 *ra
= r
? RADV_PREFIX_DELEGATION_STATIC
: RADV_PREFIX_DELEGATION_NONE
;
1245 /* For backward compatibility */
1246 val
= radv_prefix_delegation_from_string(rvalue
);
1248 log_syntax(unit
, LOG_WARNING
, filename
, line
, val
,
1249 "Invalid %s= setting, ignoring assignment: %s", lvalue
, rvalue
);
1257 int config_parse_router_lifetime(
1259 const char *filename
,
1261 const char *section
,
1262 unsigned section_line
,
1269 usec_t usec
, *lifetime
= ASSERT_PTR(data
);
1277 if (isempty(rvalue
)) {
1278 *lifetime
= RADV_DEFAULT_ROUTER_LIFETIME_USEC
;
1282 r
= parse_sec(rvalue
, &usec
);
1284 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
1285 "Failed to parse router lifetime, ignoring assignment: %s", rvalue
);
1289 if (usec
< RADV_MIN_ROUTER_LIFETIME_USEC
) {
1290 log_syntax(unit
, LOG_WARNING
, filename
, line
, 0,
1291 "Router lifetime %s is too short, using %s.",
1292 FORMAT_TIMESPAN(usec
, USEC_PER_SEC
),
1293 FORMAT_TIMESPAN(RADV_MIN_ROUTER_LIFETIME_USEC
, USEC_PER_SEC
));
1294 usec
= RADV_MIN_ROUTER_LIFETIME_USEC
;
1295 } else if (usec
> RADV_MAX_ROUTER_LIFETIME_USEC
) {
1296 log_syntax(unit
, LOG_WARNING
, filename
, line
, 0,
1297 "Router lifetime %s is too large, using %s.",
1298 FORMAT_TIMESPAN(usec
, USEC_PER_SEC
),
1299 FORMAT_TIMESPAN(RADV_MAX_ROUTER_LIFETIME_USEC
, USEC_PER_SEC
));
1300 usec
= RADV_MAX_ROUTER_LIFETIME_USEC
;
1308 int config_parse_router_preference(
1310 const char *filename
,
1312 const char *section
,
1313 unsigned section_line
,
1320 Network
*network
= userdata
;
1328 if (streq(rvalue
, "high"))
1329 network
->router_preference
= SD_NDISC_PREFERENCE_HIGH
;
1330 else if (STR_IN_SET(rvalue
, "medium", "normal", "default"))
1331 network
->router_preference
= SD_NDISC_PREFERENCE_MEDIUM
;
1332 else if (streq(rvalue
, "low"))
1333 network
->router_preference
= SD_NDISC_PREFERENCE_LOW
;
1335 log_syntax(unit
, LOG_WARNING
, filename
, line
, 0,
1336 "Invalid router preference, ignoring assignment: %s", rvalue
);