1 /* SPDX-License-Identifier: LGPL-2.1+ */
6 #include "alloc-util.h"
7 #include "conf-files.h"
8 #include "conf-parser.h"
9 #include "dns-domain.h"
11 #include "hostname-util.h"
12 #include "in-addr-util.h"
13 #include "missing_network.h"
14 #include "network-internal.h"
15 #include "networkd-manager.h"
16 #include "networkd-network.h"
17 #include "parse-util.h"
19 #include "socket-util.h"
20 #include "stat-util.h"
21 #include "string-table.h"
22 #include "string-util.h"
26 /* Let's assume that anything above this number is a user misconfiguration. */
27 #define MAX_NTP_SERVERS 128
29 static void network_config_hash_func(const NetworkConfigSection
*c
, struct siphash
*state
) {
30 siphash24_compress(c
->filename
, strlen(c
->filename
), state
);
31 siphash24_compress(&c
->line
, sizeof(c
->line
), state
);
34 static int network_config_compare_func(const NetworkConfigSection
*x
, const NetworkConfigSection
*y
) {
37 r
= strcmp(x
->filename
, y
->filename
);
41 return CMP(x
->line
, y
->line
);
44 DEFINE_HASH_OPS(network_config_hash_ops
, NetworkConfigSection
, network_config_hash_func
, network_config_compare_func
);
46 int network_config_section_new(const char *filename
, unsigned line
, NetworkConfigSection
**s
) {
47 NetworkConfigSection
*cs
;
49 cs
= malloc0(offsetof(NetworkConfigSection
, filename
) + strlen(filename
) + 1);
53 strcpy(cs
->filename
, filename
);
61 void network_config_section_free(NetworkConfigSection
*cs
) {
65 /* Set defaults following RFC7844 */
66 void network_apply_anonymize_if_set(Network
*network
) {
67 if (!network
->dhcp_anonymize
)
70 SHOULD NOT send the Host Name option */
71 network
->dhcp_send_hostname
= false;
72 /* RFC7844 section 3.:
73 MAY contain the Client Identifier option
75 clients MUST use client identifiers based solely
76 on the link-layer address */
77 /* NOTE: Using MAC, as it does not reveal extra information,
78 * and some servers might not answer if this option is not sent */
79 network
->dhcp_client_identifier
= DHCP_CLIENT_ID_MAC
;
81 SHOULD NOT use the Vendor Class Identifier option */
82 network
->dhcp_vendor_class_identifier
= mfree(network
->dhcp_vendor_class_identifier
);
83 /* RFC7844 section 3.6.:
84 The client intending to protect its privacy SHOULD only request a
85 minimal number of options in the PRL and SHOULD also randomly shuffle
86 the ordering of option codes in the PRL. If this random ordering
87 cannot be implemented, the client MAY order the option codes in the
88 PRL by option code number (lowest to highest).
90 /* NOTE: dhcp_use_mtu is false by default,
91 * though it was not initiallized to any value in network_load_one.
92 * Maybe there should be another var called *send*?
93 * (to use the MTU sent by the server but to do not send
94 * the option in the PRL). */
95 network
->dhcp_use_mtu
= false;
96 /* NOTE: when Anonymize=yes, the PRL route options are sent by default,
97 * but this is needed to use them. */
98 network
->dhcp_use_routes
= true;
99 /* RFC7844 section 3.6.
100 * same comments as previous option */
101 network
->dhcp_use_timezone
= false;
104 static int network_resolve_netdev_one(Network
*network
, const char *name
, NetDevKind kind
, NetDev
**ret_netdev
) {
105 const char *kind_string
;
110 assert(network
->manager
);
111 assert(network
->filename
);
117 if (kind
== _NETDEV_KIND_TUNNEL
)
118 kind_string
= "tunnel";
120 kind_string
= netdev_kind_to_string(kind
);
122 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
),
123 "%s: Invalid NetDev kind of %s, ignoring assignment.",
124 network
->filename
, name
);
127 r
= netdev_get(network
->manager
, name
, &netdev
);
129 return log_error_errno(r
, "%s: %s NetDev could not be found, ignoring assignment.",
130 network
->filename
, name
);
132 if (netdev
->kind
!= kind
&& !(kind
== _NETDEV_KIND_TUNNEL
&&
139 NETDEV_KIND_IP6GRETAP
,
142 NETDEV_KIND_IP6TNL
)))
143 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
),
144 "%s: NetDev %s is not a %s, ignoring assignment",
145 network
->filename
, name
, kind_string
);
147 *ret_netdev
= netdev_ref(netdev
);
151 static int network_resolve_stacked_netdevs(Network
*network
) {
158 HASHMAP_FOREACH_KEY(kind
, name
, network
->stacked_netdev_names
, i
) {
159 _cleanup_(netdev_unrefp
) NetDev
*netdev
= NULL
;
161 r
= network_resolve_netdev_one(network
, name
, PTR_TO_INT(kind
), &netdev
);
165 r
= hashmap_ensure_allocated(&network
->stacked_netdevs
, &string_hash_ops
);
169 r
= hashmap_put(network
->stacked_netdevs
, netdev
->ifname
, netdev
);
171 return log_error_errno(r
, "%s: Failed to add NetDev '%s' to network: %m",
172 network
->filename
, (const char *) name
);
180 static uint32_t network_get_stacked_netdevs_mtu(Network
*network
) {
185 HASHMAP_FOREACH(dev
, network
->stacked_netdevs
, i
)
186 if (dev
->kind
== NETDEV_KIND_VLAN
&& dev
->mtu
> 0)
187 /* See vlan_dev_change_mtu() in kernel.
188 * Note that the additional 4bytes may not be necessary for all devices. */
189 mtu
= MAX(mtu
, dev
->mtu
+ 4);
191 else if (dev
->kind
== NETDEV_KIND_MACVLAN
&& dev
->mtu
> mtu
)
192 /* See macvlan_change_mtu() in kernel. */
198 static int network_verify(Network
*network
) {
204 assert(network
->filename
);
206 /* skip out early if configuration does not match the environment */
207 if (!net_match_config(NULL
, NULL
, NULL
, NULL
, NULL
,
208 network
->match_host
, network
->match_virt
, network
->match_kernel_cmdline
,
209 network
->match_kernel_version
, network
->match_arch
,
210 NULL
, NULL
, NULL
, NULL
, NULL
))
211 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL
),
212 "%s: Conditions in the file do not match the system environment, skipping.",
215 (void) network_resolve_netdev_one(network
, network
->bond_name
, NETDEV_KIND_BOND
, &network
->bond
);
216 (void) network_resolve_netdev_one(network
, network
->bridge_name
, NETDEV_KIND_BRIDGE
, &network
->bridge
);
217 (void) network_resolve_netdev_one(network
, network
->vrf_name
, NETDEV_KIND_VRF
, &network
->vrf
);
218 (void) network_resolve_stacked_netdevs(network
);
220 /* Free unnecessary entries. */
221 network
->bond_name
= mfree(network
->bond_name
);
222 network
->bridge_name
= mfree(network
->bridge_name
);
223 network
->vrf_name
= mfree(network
->vrf_name
);
224 network
->stacked_netdev_names
= hashmap_free_free_key(network
->stacked_netdev_names
);
227 /* Bonding slave does not support addressing. */
228 if (network
->ipv6_accept_ra
> 0) {
229 log_warning("%s: Cannot enable IPv6AcceptRA= when Bond= is specified, disabling IPv6AcceptRA=.",
231 network
->ipv6_accept_ra
= 0;
233 if (network
->link_local
>= 0 && network
->link_local
!= ADDRESS_FAMILY_NO
) {
234 log_warning("%s: Cannot enable LinkLocalAddressing= when Bond= is specified, disabling LinkLocalAddressing=.",
236 network
->link_local
= ADDRESS_FAMILY_NO
;
238 if (network
->dhcp
!= ADDRESS_FAMILY_NO
) {
239 log_warning("%s: Cannot enable DHCP= when Bond= is specified, disabling DHCP=.",
241 network
->dhcp
= ADDRESS_FAMILY_NO
;
243 if (network
->dhcp_server
) {
244 log_warning("%s: Cannot enable DHCPServer= when Bond= is specified, disabling DHCPServer=.",
246 network
->dhcp_server
= false;
248 if (network
->n_static_addresses
> 0) {
249 log_warning("%s: Cannot set addresses when Bond= is specified, ignoring addresses.",
251 while ((address
= network
->static_addresses
))
252 address_free(address
);
254 if (network
->n_static_routes
> 0) {
255 log_warning("%s: Cannot set routes when Bond= is specified, ignoring routes.",
257 while ((route
= network
->static_routes
))
262 if (network
->link_local
< 0)
263 network
->link_local
= network
->bridge
? ADDRESS_FAMILY_NO
: ADDRESS_FAMILY_IPV6
;
265 if (network
->ipv6_accept_ra
< 0 && network
->bridge
)
266 network
->ipv6_accept_ra
= false;
268 /* IPMasquerade=yes implies IPForward=yes */
269 if (network
->ip_masquerade
)
270 network
->ip_forward
|= ADDRESS_FAMILY_IPV4
;
272 network
->mtu_is_set
= network
->mtu
> 0;
273 mtu
= network_get_stacked_netdevs_mtu(network
);
274 if (network
->mtu
< mtu
) {
275 if (network
->mtu_is_set
)
276 log_notice("%s: Bumping MTUBytes= from %"PRIu32
" to %"PRIu32
" because of stacked device",
277 network
->filename
, network
->mtu
, mtu
);
281 if (network
->mtu_is_set
&& network
->dhcp_use_mtu
) {
282 log_warning("%s: MTUBytes= in [Link] section and UseMTU= in [DHCP] section are set. "
283 "Disabling UseMTU=.", network
->filename
);
284 network
->dhcp_use_mtu
= false;
287 LIST_FOREACH(routes
, route
, network
->static_routes
)
289 return log_warning_errno(SYNTHETIC_ERRNO(EINVAL
),
290 "%s: Route section without Gateway field configured. "
292 network
->filename
, network
->filename
);
294 LIST_FOREACH(addresses
, address
, network
->static_addresses
)
295 if (!address
->family
)
296 return log_warning_errno(SYNTHETIC_ERRNO(EINVAL
),
297 "%s: Address section without Address field configured. "
299 network
->filename
, network
->filename
);
304 int network_load_one(Manager
*manager
, const char *filename
) {
305 _cleanup_free_
char *fname
= NULL
, *name
= NULL
;
306 _cleanup_(network_freep
) Network
*network
= NULL
;
307 _cleanup_fclose_
FILE *file
= NULL
;
308 const char *dropin_dirname
;
315 file
= fopen(filename
, "re");
323 if (null_or_empty_fd(fileno(file
))) {
324 log_debug("Skipping empty file: %s", filename
);
328 fname
= strdup(filename
);
332 name
= strdup(basename(filename
));
336 d
= strrchr(name
, '.');
342 dropin_dirname
= strjoina(name
, ".network.d");
344 network
= new(Network
, 1);
348 *network
= (Network
) {
349 .filename
= TAKE_PTR(fname
),
350 .name
= TAKE_PTR(name
),
352 .required_for_online
= true,
353 .dhcp
= ADDRESS_FAMILY_NO
,
354 .dhcp_use_ntp
= true,
355 .dhcp_use_dns
= true,
356 .dhcp_use_hostname
= true,
357 .dhcp_use_routes
= true,
358 /* NOTE: this var might be overwriten by network_apply_anonymize_if_set */
359 .dhcp_send_hostname
= true,
360 /* To enable/disable RFC7844 Anonymity Profiles */
361 .dhcp_anonymize
= false,
362 .dhcp_route_metric
= DHCP_ROUTE_METRIC
,
363 /* NOTE: this var might be overwrite by network_apply_anonymize_if_set */
364 .dhcp_client_identifier
= DHCP_CLIENT_ID_DUID
,
365 .dhcp_route_table
= RT_TABLE_MAIN
,
366 .dhcp_route_table_set
= false,
367 /* NOTE: from man: UseMTU=... Defaults to false*/
368 .dhcp_use_mtu
= false,
369 /* NOTE: from man: UseTimezone=... Defaults to "no".*/
370 .dhcp_use_timezone
= false,
371 .rapid_commit
= true,
373 .dhcp_server_emit_dns
= true,
374 .dhcp_server_emit_ntp
= true,
375 .dhcp_server_emit_router
= true,
376 .dhcp_server_emit_timezone
= true,
378 .router_emit_dns
= true,
379 .router_emit_domains
= true,
384 .allow_port_to_be_root
= -1,
386 .multicast_to_unicast
= -1,
387 .priority
= LINK_BRIDGE_PORT_PRIORITY_INVALID
,
389 .lldp_mode
= LLDP_MODE_ROUTERS_ONLY
,
391 .dns_default_route
= -1,
392 .llmnr
= RESOLVE_SUPPORT_YES
,
393 .mdns
= RESOLVE_SUPPORT_NO
,
394 .dnssec_mode
= _DNSSEC_MODE_INVALID
,
395 .dns_over_tls_mode
= _DNS_OVER_TLS_MODE_INVALID
,
397 /* If LinkLocalAddressing= is not set, then set to ADDRESS_FAMILY_IPV6 later. */
398 .link_local
= _ADDRESS_FAMILY_BOOLEAN_INVALID
,
400 .ipv6_privacy_extensions
= IPV6_PRIVACY_EXTENSIONS_NO
,
401 .ipv6_accept_ra
= -1,
402 .ipv6_dad_transmits
= -1,
403 .ipv6_hop_limit
= -1,
404 .ipv6_proxy_ndp
= -1,
405 .duid
.type
= _DUID_TYPE_INVALID
,
410 .ipv6_accept_ra_use_dns
= true,
411 .ipv6_accept_ra_use_autonomous_prefix
= true,
412 .ipv6_accept_ra_use_onlink_prefix
= true,
413 .ipv6_accept_ra_route_table
= RT_TABLE_MAIN
,
414 .ipv6_accept_ra_route_table_set
= false,
417 r
= config_parse_many(filename
, NETWORK_DIRS
, dropin_dirname
,
424 "RoutingPolicyRule\0"
427 "DHCPv4\0" /* compat */
430 "IPv6NDPProxyAddress\0"
434 "IPv6PrefixDelegation\0"
437 config_item_perf_lookup
, network_network_gperf_lookup
,
438 CONFIG_PARSE_WARN
, network
);
442 network_apply_anonymize_if_set(network
);
444 LIST_PREPEND(networks
, manager
->networks
, network
);
445 network
->manager
= manager
;
447 r
= hashmap_ensure_allocated(&manager
->networks_by_name
, &string_hash_ops
);
451 r
= hashmap_put(manager
->networks_by_name
, network
->name
, network
);
455 if (network_verify(network
) < 0)
462 int network_load(Manager
*manager
) {
464 _cleanup_strv_free_
char **files
= NULL
;
470 while ((network
= manager
->networks
))
471 network_free(network
);
473 r
= conf_files_list_strv(&files
, ".network", NULL
, 0, NETWORK_DIRS
);
475 return log_error_errno(r
, "Failed to enumerate network files: %m");
477 STRV_FOREACH_BACKWARDS(f
, files
) {
478 r
= network_load_one(manager
, *f
);
486 void network_free(Network
*network
) {
487 IPv6ProxyNDPAddress
*ipv6_proxy_ndp_address
;
488 RoutingPolicyRule
*rule
;
499 free(network
->filename
);
501 set_free_free(network
->match_mac
);
502 strv_free(network
->match_path
);
503 strv_free(network
->match_driver
);
504 strv_free(network
->match_type
);
505 strv_free(network
->match_name
);
507 free(network
->description
);
508 free(network
->dhcp_vendor_class_identifier
);
509 strv_free(network
->dhcp_user_class
);
510 free(network
->dhcp_hostname
);
514 strv_free(network
->ntp
);
516 ordered_set_free_free(network
->search_domains
);
517 ordered_set_free_free(network
->route_domains
);
518 strv_free(network
->bind_carrier
);
520 ordered_set_free_free(network
->router_search_domains
);
521 free(network
->router_dns
);
523 free(network
->bridge_name
);
524 free(network
->bond_name
);
525 free(network
->vrf_name
);
526 hashmap_free_free_key(network
->stacked_netdev_names
);
527 netdev_unref(network
->bridge
);
528 netdev_unref(network
->bond
);
529 netdev_unref(network
->vrf
);
530 hashmap_free_with_destructor(network
->stacked_netdevs
, netdev_unref
);
532 while ((route
= network
->static_routes
))
535 while ((address
= network
->static_addresses
))
536 address_free(address
);
538 while ((fdb_entry
= network
->static_fdb_entries
))
539 fdb_entry_free(fdb_entry
);
541 while ((ipv6_proxy_ndp_address
= network
->ipv6_proxy_ndp_addresses
))
542 ipv6_proxy_ndp_address_free(ipv6_proxy_ndp_address
);
544 while ((neighbor
= network
->neighbors
))
545 neighbor_free(neighbor
);
547 while ((label
= network
->address_labels
))
548 address_label_free(label
);
550 while ((prefix
= network
->static_prefixes
))
553 while ((rule
= network
->rules
))
554 routing_policy_rule_free(rule
);
556 hashmap_free(network
->addresses_by_section
);
557 hashmap_free(network
->routes_by_section
);
558 hashmap_free(network
->fdb_entries_by_section
);
559 hashmap_free(network
->neighbors_by_section
);
560 hashmap_free(network
->address_labels_by_section
);
561 hashmap_free(network
->prefixes_by_section
);
562 hashmap_free(network
->rules_by_section
);
564 if (network
->manager
) {
565 if (network
->manager
->networks
)
566 LIST_REMOVE(networks
, network
->manager
->networks
, network
);
568 if (network
->manager
->networks_by_name
&& network
->name
)
569 hashmap_remove(network
->manager
->networks_by_name
, network
->name
);
571 if (network
->manager
->duids_requesting_uuid
)
572 set_remove(network
->manager
->duids_requesting_uuid
, &network
->duid
);
577 condition_free_list(network
->match_host
);
578 condition_free_list(network
->match_virt
);
579 condition_free_list(network
->match_kernel_cmdline
);
580 condition_free_list(network
->match_kernel_version
);
581 condition_free_list(network
->match_arch
);
583 free(network
->dhcp_server_timezone
);
584 free(network
->dhcp_server_dns
);
585 free(network
->dhcp_server_ntp
);
587 set_free_free(network
->dnssec_negative_trust_anchors
);
592 int network_get_by_name(Manager
*manager
, const char *name
, Network
**ret
) {
599 network
= hashmap_get(manager
->networks_by_name
, name
);
608 int network_get(Manager
*manager
, sd_device
*device
,
609 const char *ifname
, const struct ether_addr
*address
,
611 const char *path
= NULL
, *driver
= NULL
, *devtype
= NULL
;
618 (void) sd_device_get_property_value(device
, "ID_PATH", &path
);
620 (void) sd_device_get_property_value(device
, "ID_NET_DRIVER", &driver
);
622 (void) sd_device_get_devtype(device
, &devtype
);
625 LIST_FOREACH(networks
, network
, manager
->networks
) {
626 if (net_match_config(network
->match_mac
, network
->match_path
,
627 network
->match_driver
, network
->match_type
,
628 network
->match_name
, network
->match_host
,
629 network
->match_virt
, network
->match_kernel_cmdline
,
630 network
->match_kernel_version
, network
->match_arch
,
631 address
, path
, driver
, devtype
, ifname
)) {
632 if (network
->match_name
&& device
) {
634 uint8_t name_assign_type
= NET_NAME_UNKNOWN
;
636 if (sd_device_get_sysattr_value(device
, "name_assign_type", &attr
) >= 0)
637 (void) safe_atou8(attr
, &name_assign_type
);
639 if (name_assign_type
== NET_NAME_ENUM
)
640 log_warning("%s: found matching network '%s', based on potentially unpredictable ifname",
641 ifname
, network
->filename
);
643 log_debug("%s: found matching network '%s'", ifname
, network
->filename
);
645 log_debug("%s: found matching network '%s'", ifname
, network
->filename
);
657 int network_apply(Network
*network
, Link
*link
) {
663 link
->network
= network
;
665 if (network
->ipv4ll_route
) {
668 r
= route_new_static(network
, NULL
, 0, &route
);
672 r
= inet_pton(AF_INET
, "169.254.0.0", &route
->dst
.in
);
678 route
->family
= AF_INET
;
679 route
->dst_prefixlen
= 16;
680 route
->scope
= RT_SCOPE_LINK
;
681 route
->priority
= IPV4LL_ROUTE_METRIC
;
682 route
->protocol
= RTPROT_STATIC
;
685 if (network
->n_dns
> 0 ||
686 !strv_isempty(network
->ntp
) ||
687 !ordered_set_isempty(network
->search_domains
) ||
688 !ordered_set_isempty(network
->route_domains
))
694 bool network_has_static_ipv6_addresses(Network
*network
) {
699 LIST_FOREACH(addresses
, address
, network
->static_addresses
) {
700 if (address
->family
== AF_INET6
)
707 int config_parse_stacked_netdev(const char *unit
,
708 const char *filename
,
711 unsigned section_line
,
717 _cleanup_free_
char *kind_string
= NULL
, *name
= NULL
;
728 if (ltype
== _NETDEV_KIND_TUNNEL
)
729 kind
= _NETDEV_KIND_TUNNEL
;
731 kind_string
= strdup(lvalue
);
735 /* the keys are CamelCase versions of the kind */
736 for (p
= kind_string
; *p
; p
++)
739 kind
= netdev_kind_from_string(kind_string
);
740 if (kind
< 0 || IN_SET(kind
, NETDEV_KIND_BRIDGE
, NETDEV_KIND_BOND
, NETDEV_KIND_VRF
)) {
741 log_syntax(unit
, LOG_ERR
, filename
, line
, 0,
742 "Invalid NetDev kind: %s", lvalue
);
747 if (!ifname_valid(rvalue
)) {
748 log_syntax(unit
, LOG_ERR
, filename
, line
, 0,
749 "Invalid netdev name in %s=, ignoring assignment: %s", lvalue
, rvalue
);
753 name
= strdup(rvalue
);
757 r
= hashmap_ensure_allocated(h
, &string_hash_ops
);
761 r
= hashmap_put(*h
, name
, INT_TO_PTR(kind
));
763 log_syntax(unit
, LOG_ERR
, filename
, line
, r
,
764 "Cannot add NetDev '%s' to network, ignoring assignment: %m", name
);
766 log_syntax(unit
, LOG_DEBUG
, filename
, line
, r
,
767 "NetDev '%s' specified twice, ignoring.", name
);
774 int config_parse_domains(
776 const char *filename
,
779 unsigned section_line
,
794 if (isempty(rvalue
)) {
795 n
->search_domains
= ordered_set_free_free(n
->search_domains
);
796 n
->route_domains
= ordered_set_free_free(n
->route_domains
);
802 _cleanup_free_
char *w
= NULL
, *normalized
= NULL
;
806 r
= extract_first_word(&p
, &w
, NULL
, 0);
808 log_syntax(unit
, LOG_ERR
, filename
, line
, r
,
809 "Failed to extract search or route domain, ignoring: %s", rvalue
);
815 is_route
= w
[0] == '~';
816 domain
= is_route
? w
+ 1 : w
;
818 if (dns_name_is_root(domain
) || streq(domain
, "*")) {
819 /* If the root domain appears as is, or the special token "*" is found, we'll
820 * consider this as routing domain, unconditionally. */
822 domain
= "."; /* make sure we don't allow empty strings, thus write the root
825 r
= dns_name_normalize(domain
, 0, &normalized
);
827 log_syntax(unit
, LOG_ERR
, filename
, line
, r
,
828 "'%s' is not a valid domain name, ignoring.", domain
);
834 if (is_localhost(domain
)) {
835 log_syntax(unit
, LOG_ERR
, filename
, line
, 0,
836 "'localhost' domain may not be configured as search or route domain, ignoring assignment: %s",
842 OrderedSet
**set
= is_route
? &n
->route_domains
: &n
->search_domains
;
843 r
= ordered_set_ensure_allocated(set
, &string_hash_ops
);
847 r
= ordered_set_put_strdup(*set
, domain
);
855 int config_parse_ipv4ll(
857 const char *filename
,
860 unsigned section_line
,
867 AddressFamilyBoolean
*link_local
= data
;
874 /* Note that this is mostly like
875 * config_parse_address_family_boolean(), except that it
876 * applies only to IPv4 */
878 SET_FLAG(*link_local
, ADDRESS_FAMILY_IPV4
, parse_boolean(rvalue
));
883 int config_parse_dhcp(
885 const char *filename
,
888 unsigned section_line
,
895 AddressFamilyBoolean
*dhcp
= data
, s
;
902 /* Note that this is mostly like
903 * config_parse_address_family_boolean(), except that it
904 * understands some old names for the enum values */
906 s
= address_family_boolean_from_string(rvalue
);
909 /* Previously, we had a slightly different enum here,
910 * support its values for compatbility. */
912 if (streq(rvalue
, "none"))
913 s
= ADDRESS_FAMILY_NO
;
914 else if (streq(rvalue
, "v4"))
915 s
= ADDRESS_FAMILY_IPV4
;
916 else if (streq(rvalue
, "v6"))
917 s
= ADDRESS_FAMILY_IPV6
;
918 else if (streq(rvalue
, "both"))
919 s
= ADDRESS_FAMILY_YES
;
921 log_syntax(unit
, LOG_ERR
, filename
, line
, 0,
922 "Failed to parse DHCP option, ignoring: %s", rvalue
);
926 log_syntax(unit
, LOG_WARNING
, filename
, line
, 0,
927 "DHCP=%s is deprecated, please use DHCP=%s instead.",
928 rvalue
, address_family_boolean_to_string(s
));
935 static const char* const dhcp_client_identifier_table
[_DHCP_CLIENT_ID_MAX
] = {
936 [DHCP_CLIENT_ID_MAC
] = "mac",
937 [DHCP_CLIENT_ID_DUID
] = "duid",
938 [DHCP_CLIENT_ID_DUID_ONLY
] = "duid-only",
941 DEFINE_PRIVATE_STRING_TABLE_LOOKUP_FROM_STRING(dhcp_client_identifier
, DHCPClientIdentifier
);
942 DEFINE_CONFIG_PARSE_ENUM(config_parse_dhcp_client_identifier
, dhcp_client_identifier
, DHCPClientIdentifier
,
943 "Failed to parse client identifier type");
945 int config_parse_ipv6token(
947 const char *filename
,
950 unsigned section_line
,
957 union in_addr_union buffer
;
958 struct in6_addr
*token
= data
;
966 r
= in_addr_from_string(AF_INET6
, rvalue
, &buffer
);
968 log_syntax(unit
, LOG_ERR
, filename
, line
, r
,
969 "Failed to parse IPv6 token, ignoring: %s", rvalue
);
973 if (in_addr_is_null(AF_INET6
, &buffer
)) {
974 log_syntax(unit
, LOG_ERR
, filename
, line
, 0,
975 "IPv6 token cannot be the ANY address, ignoring: %s", rvalue
);
979 if ((buffer
.in6
.s6_addr32
[0] | buffer
.in6
.s6_addr32
[1]) != 0) {
980 log_syntax(unit
, LOG_ERR
, filename
, line
, 0,
981 "IPv6 token cannot be longer than 64 bits, ignoring: %s", rvalue
);
990 static const char* const ipv6_privacy_extensions_table
[_IPV6_PRIVACY_EXTENSIONS_MAX
] = {
991 [IPV6_PRIVACY_EXTENSIONS_NO
] = "no",
992 [IPV6_PRIVACY_EXTENSIONS_PREFER_PUBLIC
] = "prefer-public",
993 [IPV6_PRIVACY_EXTENSIONS_YES
] = "yes",
996 DEFINE_STRING_TABLE_LOOKUP(ipv6_privacy_extensions
, IPv6PrivacyExtensions
);
998 int config_parse_ipv6_privacy_extensions(
1000 const char *filename
,
1002 const char *section
,
1003 unsigned section_line
,
1010 IPv6PrivacyExtensions
*ipv6_privacy_extensions
= data
;
1016 assert(ipv6_privacy_extensions
);
1018 /* Our enum shall be a superset of booleans, hence first try
1019 * to parse as boolean, and then as enum */
1021 k
= parse_boolean(rvalue
);
1023 *ipv6_privacy_extensions
= IPV6_PRIVACY_EXTENSIONS_YES
;
1025 *ipv6_privacy_extensions
= IPV6_PRIVACY_EXTENSIONS_NO
;
1027 IPv6PrivacyExtensions s
;
1029 s
= ipv6_privacy_extensions_from_string(rvalue
);
1032 if (streq(rvalue
, "kernel"))
1033 s
= _IPV6_PRIVACY_EXTENSIONS_INVALID
;
1035 log_syntax(unit
, LOG_ERR
, filename
, line
, 0,
1036 "Failed to parse IPv6 privacy extensions option, ignoring: %s", rvalue
);
1041 *ipv6_privacy_extensions
= s
;
1047 int config_parse_hostname(
1049 const char *filename
,
1051 const char *section
,
1052 unsigned section_line
,
1059 _cleanup_free_
char *hn
= NULL
;
1060 char **hostname
= data
;
1067 r
= config_parse_string(unit
, filename
, line
, section
, section_line
, lvalue
, ltype
, rvalue
, &hn
, userdata
);
1071 if (!hostname_is_valid(hn
, false)) {
1072 log_syntax(unit
, LOG_ERR
, filename
, line
, 0,
1073 "Hostname is not valid, ignoring assignment: %s", rvalue
);
1077 r
= dns_name_is_valid(hn
);
1079 log_syntax(unit
, LOG_ERR
, filename
, line
, r
,
1080 "Failed to check validity of hostname '%s', ignoring assignment: %m", rvalue
);
1084 log_syntax(unit
, LOG_ERR
, filename
, line
, 0,
1085 "Hostname is not a valid DNS domain name, ignoring assignment: %s", rvalue
);
1089 return free_and_replace(*hostname
, hn
);
1092 int config_parse_timezone(
1094 const char *filename
,
1096 const char *section
,
1097 unsigned section_line
,
1104 _cleanup_free_
char *tz
= NULL
;
1105 char **datap
= data
;
1112 r
= config_parse_string(unit
, filename
, line
, section
, section_line
, lvalue
, ltype
, rvalue
, &tz
, userdata
);
1116 if (!timezone_is_valid(tz
, LOG_ERR
)) {
1117 log_syntax(unit
, LOG_ERR
, filename
, line
, 0,
1118 "Timezone is not valid, ignoring assignment: %s", rvalue
);
1122 return free_and_replace(*datap
, tz
);
1125 int config_parse_dhcp_server_dns(
1127 const char *filename
,
1129 const char *section
,
1130 unsigned section_line
,
1138 const char *p
= rvalue
;
1146 _cleanup_free_
char *w
= NULL
;
1147 struct in_addr a
, *m
;
1149 r
= extract_first_word(&p
, &w
, NULL
, 0);
1153 log_syntax(unit
, LOG_ERR
, filename
, line
, r
,
1154 "Failed to extract word, ignoring: %s", rvalue
);
1160 if (inet_pton(AF_INET
, w
, &a
) <= 0) {
1161 log_syntax(unit
, LOG_ERR
, filename
, line
, 0,
1162 "Failed to parse DNS server address, ignoring: %s", w
);
1166 m
= reallocarray(n
->dhcp_server_dns
, n
->n_dhcp_server_dns
+ 1, sizeof(struct in_addr
));
1170 m
[n
->n_dhcp_server_dns
++] = a
;
1171 n
->dhcp_server_dns
= m
;
1177 int config_parse_radv_dns(
1179 const char *filename
,
1181 const char *section
,
1182 unsigned section_line
,
1190 const char *p
= rvalue
;
1198 _cleanup_free_
char *w
= NULL
;
1199 union in_addr_union a
;
1201 r
= extract_first_word(&p
, &w
, NULL
, 0);
1205 log_syntax(unit
, LOG_ERR
, filename
, line
, r
,
1206 "Failed to extract word, ignoring: %s", rvalue
);
1212 if (in_addr_from_string(AF_INET6
, w
, &a
) >= 0) {
1215 m
= reallocarray(n
->router_dns
, n
->n_router_dns
+ 1, sizeof(struct in6_addr
));
1219 m
[n
->n_router_dns
++] = a
.in6
;
1223 log_syntax(unit
, LOG_ERR
, filename
, line
, 0,
1224 "Failed to parse DNS server address, ignoring: %s", w
);
1230 int config_parse_radv_search_domains(
1232 const char *filename
,
1234 const char *section
,
1235 unsigned section_line
,
1243 const char *p
= rvalue
;
1251 _cleanup_free_
char *w
= NULL
, *idna
= NULL
;
1253 r
= extract_first_word(&p
, &w
, NULL
, 0);
1257 log_syntax(unit
, LOG_ERR
, filename
, line
, r
,
1258 "Failed to extract word, ignoring: %s", rvalue
);
1264 r
= dns_name_apply_idna(w
, &idna
);
1266 log_syntax(unit
, LOG_ERR
, filename
, line
, r
,
1267 "Failed to apply IDNA to domain name '%s', ignoring: %m", w
);
1270 /* transfer ownership to simplify subsequent operations */
1273 r
= ordered_set_ensure_allocated(&n
->router_search_domains
, &string_hash_ops
);
1277 r
= ordered_set_consume(n
->router_search_domains
, TAKE_PTR(idna
));
1285 int config_parse_dhcp_server_ntp(
1287 const char *filename
,
1289 const char *section
,
1290 unsigned section_line
,
1298 const char *p
= rvalue
;
1306 _cleanup_free_
char *w
= NULL
;
1307 struct in_addr a
, *m
;
1309 r
= extract_first_word(&p
, &w
, NULL
, 0);
1313 log_syntax(unit
, LOG_ERR
, filename
, line
, r
,
1314 "Failed to extract word, ignoring: %s", rvalue
);
1320 if (inet_pton(AF_INET
, w
, &a
) <= 0) {
1321 log_syntax(unit
, LOG_ERR
, filename
, line
, 0,
1322 "Failed to parse NTP server address, ignoring: %s", w
);
1326 m
= reallocarray(n
->dhcp_server_ntp
, n
->n_dhcp_server_ntp
+ 1, sizeof(struct in_addr
));
1330 m
[n
->n_dhcp_server_ntp
++] = a
;
1331 n
->dhcp_server_ntp
= m
;
1335 int config_parse_dns(
1337 const char *filename
,
1339 const char *section
,
1340 unsigned section_line
,
1347 Network
*n
= userdata
;
1355 _cleanup_free_
char *w
= NULL
;
1356 union in_addr_union a
;
1357 struct in_addr_data
*m
;
1360 r
= extract_first_word(&rvalue
, &w
, NULL
, 0);
1364 log_syntax(unit
, LOG_ERR
, filename
, line
, r
,
1365 "Invalid syntax, ignoring: %s", rvalue
);
1371 r
= in_addr_from_string_auto(w
, &family
, &a
);
1373 log_syntax(unit
, LOG_ERR
, filename
, line
, r
,
1374 "Failed to parse dns server address, ignoring: %s", w
);
1378 m
= reallocarray(n
->dns
, n
->n_dns
+ 1, sizeof(struct in_addr_data
));
1382 m
[n
->n_dns
++] = (struct in_addr_data
) {
1393 int config_parse_dnssec_negative_trust_anchors(
1395 const char *filename
,
1397 const char *section
,
1398 unsigned section_line
,
1405 const char *p
= rvalue
;
1413 if (isempty(rvalue
)) {
1414 n
->dnssec_negative_trust_anchors
= set_free_free(n
->dnssec_negative_trust_anchors
);
1419 _cleanup_free_
char *w
= NULL
;
1421 r
= extract_first_word(&p
, &w
, NULL
, 0);
1423 log_syntax(unit
, LOG_ERR
, filename
, line
, r
,
1424 "Failed to extract negative trust anchor domain, ignoring: %s", rvalue
);
1430 r
= dns_name_is_valid(w
);
1432 log_syntax(unit
, LOG_ERR
, filename
, line
, r
,
1433 "%s is not a valid domain name, ignoring.", w
);
1437 r
= set_ensure_allocated(&n
->dnssec_negative_trust_anchors
, &dns_name_hash_ops
);
1441 r
= set_put(n
->dnssec_negative_trust_anchors
, w
);
1451 int config_parse_ntp(
1453 const char *filename
,
1455 const char *section
,
1456 unsigned section_line
,
1470 if (isempty(rvalue
)) {
1476 _cleanup_free_
char *w
= NULL
;
1478 r
= extract_first_word(&rvalue
, &w
, NULL
, 0);
1482 log_syntax(unit
, LOG_ERR
, filename
, line
, r
,
1483 "Failed to extract NTP server name, ignoring: %s", rvalue
);
1489 r
= dns_name_is_valid_or_address(w
);
1491 log_syntax(unit
, LOG_ERR
, filename
, line
, r
,
1492 "%s is not a valid domain name or IP address, ignoring.", w
);
1496 if (strv_length(*l
) > MAX_NTP_SERVERS
) {
1497 log_syntax(unit
, LOG_WARNING
, filename
, line
, 0,
1498 "More than %u NTP servers specified, ignoring \"%s\" and any subsequent entries.",
1499 MAX_NTP_SERVERS
, w
);
1503 r
= strv_consume(l
, TAKE_PTR(w
));
1511 int config_parse_dhcp_user_class(
1513 const char *filename
,
1515 const char *section
,
1516 unsigned section_line
,
1530 if (isempty(rvalue
)) {
1536 _cleanup_free_
char *w
= NULL
;
1538 r
= extract_first_word(&rvalue
, &w
, NULL
, 0);
1542 log_syntax(unit
, LOG_ERR
, filename
, line
, r
,
1543 "Failed to split user classes option, ignoring: %s", rvalue
);
1549 if (strlen(w
) > 255) {
1550 log_syntax(unit
, LOG_ERR
, filename
, line
, 0,
1551 "%s length is not in the range 1-255, ignoring.", w
);
1555 r
= strv_push(l
, w
);
1565 int config_parse_section_route_table(
1567 const char *filename
,
1569 const char *section
,
1570 unsigned section_line
,
1577 Network
*network
= data
;
1586 r
= safe_atou32(rvalue
, &rt
);
1588 log_syntax(unit
, LOG_ERR
, filename
, line
, r
,
1589 "Failed to parse RouteTable=%s, ignoring assignment: %m", rvalue
);
1593 if (streq_ptr(section
, "DHCP")) {
1594 network
->dhcp_route_table
= rt
;
1595 network
->dhcp_route_table_set
= true;
1596 } else { /* section is IPv6AcceptRA */
1597 network
->ipv6_accept_ra_route_table
= rt
;
1598 network
->ipv6_accept_ra_route_table_set
= true;
1604 DEFINE_CONFIG_PARSE_ENUM(config_parse_dhcp_use_domains
, dhcp_use_domains
, DHCPUseDomains
,
1605 "Failed to parse DHCP use domains setting");
1607 static const char* const dhcp_use_domains_table
[_DHCP_USE_DOMAINS_MAX
] = {
1608 [DHCP_USE_DOMAINS_NO
] = "no",
1609 [DHCP_USE_DOMAINS_ROUTE
] = "route",
1610 [DHCP_USE_DOMAINS_YES
] = "yes",
1613 DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(dhcp_use_domains
, DHCPUseDomains
, DHCP_USE_DOMAINS_YES
);
1615 DEFINE_CONFIG_PARSE_ENUM(config_parse_lldp_mode
, lldp_mode
, LLDPMode
, "Failed to parse LLDP= setting.");
1617 static const char* const lldp_mode_table
[_LLDP_MODE_MAX
] = {
1618 [LLDP_MODE_NO
] = "no",
1619 [LLDP_MODE_YES
] = "yes",
1620 [LLDP_MODE_ROUTERS_ONLY
] = "routers-only",
1623 DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(lldp_mode
, LLDPMode
, LLDP_MODE_YES
);
1625 int config_parse_iaid(const char *unit
,
1626 const char *filename
,
1628 const char *section
,
1629 unsigned section_line
,
1635 Network
*network
= data
;
1644 r
= safe_atou32(rvalue
, &iaid
);
1646 log_syntax(unit
, LOG_ERR
, filename
, line
, r
,
1647 "Unable to read IAID, ignoring assignment: %s", rvalue
);
1651 network
->iaid
= iaid
;
1652 network
->iaid_set
= true;