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 "stat-util.h"
20 #include "string-table.h"
21 #include "string-util.h"
25 static void network_config_hash_func(const NetworkConfigSection
*c
, struct siphash
*state
) {
26 siphash24_compress(c
->filename
, strlen(c
->filename
), state
);
27 siphash24_compress(&c
->line
, sizeof(c
->line
), state
);
30 static int network_config_compare_func(const NetworkConfigSection
*x
, const NetworkConfigSection
*y
) {
33 r
= strcmp(x
->filename
, y
->filename
);
37 return CMP(x
->line
, y
->line
);
40 DEFINE_HASH_OPS(network_config_hash_ops
, NetworkConfigSection
, network_config_hash_func
, network_config_compare_func
);
42 int network_config_section_new(const char *filename
, unsigned line
, NetworkConfigSection
**s
) {
43 NetworkConfigSection
*cs
;
45 cs
= malloc0(offsetof(NetworkConfigSection
, filename
) + strlen(filename
) + 1);
49 strcpy(cs
->filename
, filename
);
57 void network_config_section_free(NetworkConfigSection
*cs
) {
61 /* Set defaults following RFC7844 */
62 void network_apply_anonymize_if_set(Network
*network
) {
63 if (!network
->dhcp_anonymize
)
66 SHOULD NOT send the Host Name option */
67 network
->dhcp_send_hostname
= false;
68 /* RFC7844 section 3.:
69 MAY contain the Client Identifier option
71 clients MUST use client identifiers based solely
72 on the link-layer address */
73 /* NOTE: Using MAC, as it does not reveal extra information,
74 * and some servers might not answer if this option is not sent */
75 network
->dhcp_client_identifier
= DHCP_CLIENT_ID_MAC
;
77 SHOULD NOT use the Vendor Class Identifier option */
78 network
->dhcp_vendor_class_identifier
= mfree(network
->dhcp_vendor_class_identifier
);
79 /* RFC7844 section 3.6.:
80 The client intending to protect its privacy SHOULD only request a
81 minimal number of options in the PRL and SHOULD also randomly shuffle
82 the ordering of option codes in the PRL. If this random ordering
83 cannot be implemented, the client MAY order the option codes in the
84 PRL by option code number (lowest to highest).
86 /* NOTE: dhcp_use_mtu is false by default,
87 * though it was not initiallized to any value in network_load_one.
88 * Maybe there should be another var called *send*?
89 * (to use the MTU sent by the server but to do not send
90 * the option in the PRL). */
91 network
->dhcp_use_mtu
= false;
92 /* NOTE: when Anonymize=yes, the PRL route options are sent by default,
93 * but this is needed to use them. */
94 network
->dhcp_use_routes
= true;
95 /* RFC7844 section 3.6.
96 * same comments as previous option */
97 network
->dhcp_use_timezone
= false;
100 static int network_verify(Network
*network
) {
105 assert(network
->filename
);
108 /* Bonding slave does not support addressing. */
109 if (network
->ipv6_accept_ra
> 0) {
110 log_warning("%s: Cannot enable IPv6AcceptRA= when Bond= is specified, disabling IPv6AcceptRA=.",
112 network
->ipv6_accept_ra
= 0;
114 if (network
->link_local
>= 0 && network
->link_local
!= ADDRESS_FAMILY_NO
) {
115 log_warning("%s: Cannot enable LinkLocalAddressing= when Bond= is specified, disabling LinkLocalAddressing=.",
117 network
->link_local
= ADDRESS_FAMILY_NO
;
119 if (network
->dhcp
!= ADDRESS_FAMILY_NO
) {
120 log_warning("%s: Cannot enable DHCP= when Bond= is specified, disabling DHCP=.",
122 network
->dhcp
= ADDRESS_FAMILY_NO
;
124 if (network
->dhcp_server
) {
125 log_warning("%s: Cannot enable DHCPServer= when Bond= is specified, disabling DHCPServer=.",
127 network
->dhcp_server
= false;
129 if (network
->n_static_addresses
> 0) {
130 log_warning("%s: Cannot set addresses when Bond= is specified, ignoring addresses.",
132 while ((address
= network
->static_addresses
))
133 address_free(address
);
135 if (network
->n_static_routes
> 0) {
136 log_warning("%s: Cannot set routes when Bond= is specified, ignoring routes.",
138 while ((route
= network
->static_routes
))
143 if (network
->link_local
< 0)
144 network
->link_local
= ADDRESS_FAMILY_IPV6
;
146 /* IPMasquerade=yes implies IPForward=yes */
147 if (network
->ip_masquerade
)
148 network
->ip_forward
|= ADDRESS_FAMILY_IPV4
;
150 if (network
->mtu
> 0 && network
->dhcp_use_mtu
) {
151 log_warning("%s: MTUBytes= in [Link] section and UseMTU= in [DHCP] section are set. "
152 "Disabling UseMTU=.", network
->filename
);
153 network
->dhcp_use_mtu
= false;
156 LIST_FOREACH(routes
, route
, network
->static_routes
)
158 return log_warning_errno(SYNTHETIC_ERRNO(EINVAL
),
159 "%s: Route section without Gateway field configured. "
161 network
->filename
, network
->filename
);
163 LIST_FOREACH(addresses
, address
, network
->static_addresses
)
164 if (!address
->family
)
165 return log_warning_errno(SYNTHETIC_ERRNO(EINVAL
),
166 "%s: Address section without Address field configured. "
168 network
->filename
, network
->filename
);
173 int network_load_one(Manager
*manager
, const char *filename
) {
174 _cleanup_free_
char *fname
= NULL
, *name
= NULL
;
175 _cleanup_(network_freep
) Network
*network
= NULL
;
176 _cleanup_fclose_
FILE *file
= NULL
;
177 const char *dropin_dirname
;
184 file
= fopen(filename
, "re");
192 if (null_or_empty_fd(fileno(file
))) {
193 log_debug("Skipping empty file: %s", filename
);
197 fname
= strdup(filename
);
201 name
= strdup(basename(filename
));
205 d
= strrchr(name
, '.');
211 dropin_dirname
= strjoina(name
, ".network.d");
213 network
= new(Network
, 1);
217 *network
= (Network
) {
219 .filename
= TAKE_PTR(fname
),
220 .name
= TAKE_PTR(name
),
222 .required_for_online
= true,
223 .dhcp
= ADDRESS_FAMILY_NO
,
224 .dhcp_use_ntp
= true,
225 .dhcp_use_dns
= true,
226 .dhcp_use_hostname
= true,
227 .dhcp_use_routes
= true,
228 /* NOTE: this var might be overwriten by network_apply_anonymize_if_set */
229 .dhcp_send_hostname
= true,
230 /* To enable/disable RFC7844 Anonymity Profiles */
231 .dhcp_anonymize
= false,
232 .dhcp_route_metric
= DHCP_ROUTE_METRIC
,
233 /* NOTE: this var might be overwrite by network_apply_anonymize_if_set */
234 .dhcp_client_identifier
= DHCP_CLIENT_ID_DUID
,
235 .dhcp_route_table
= RT_TABLE_MAIN
,
236 .dhcp_route_table_set
= false,
237 /* NOTE: from man: UseMTU=... Defaults to false*/
238 .dhcp_use_mtu
= false,
239 /* NOTE: from man: UseTimezone=... Defaults to "no".*/
240 .dhcp_use_timezone
= false,
241 .rapid_commit
= true,
243 .dhcp_server_emit_dns
= true,
244 .dhcp_server_emit_ntp
= true,
245 .dhcp_server_emit_router
= true,
246 .dhcp_server_emit_timezone
= true,
248 .router_emit_dns
= true,
249 .router_emit_domains
= true,
254 .allow_port_to_be_root
= -1,
256 .multicast_to_unicast
= -1,
257 .priority
= LINK_BRIDGE_PORT_PRIORITY_INVALID
,
259 .lldp_mode
= LLDP_MODE_ROUTERS_ONLY
,
261 .dns_default_route
= -1,
262 .llmnr
= RESOLVE_SUPPORT_YES
,
263 .mdns
= RESOLVE_SUPPORT_NO
,
264 .dnssec_mode
= _DNSSEC_MODE_INVALID
,
265 .dns_over_tls_mode
= _DNS_OVER_TLS_MODE_INVALID
,
267 /* If LinkLocalAddressing= is not set, then set to ADDRESS_FAMILY_IPV6 later. */
268 .link_local
= _ADDRESS_FAMILY_BOOLEAN_INVALID
,
270 .ipv6_privacy_extensions
= IPV6_PRIVACY_EXTENSIONS_NO
,
271 .ipv6_accept_ra
= -1,
272 .ipv6_dad_transmits
= -1,
273 .ipv6_hop_limit
= -1,
274 .ipv6_proxy_ndp
= -1,
275 .duid
.type
= _DUID_TYPE_INVALID
,
280 .ipv6_accept_ra_use_dns
= true,
281 .ipv6_accept_ra_use_autonomous_prefix
= true,
282 .ipv6_accept_ra_use_onlink_prefix
= true,
283 .ipv6_accept_ra_route_table
= RT_TABLE_MAIN
,
284 .ipv6_accept_ra_route_table_set
= false,
287 r
= config_parse_many(filename
, NETWORK_DIRS
, dropin_dirname
,
294 "RoutingPolicyRule\0"
297 "DHCPv4\0" /* compat */
300 "IPv6NDPProxyAddress\0"
304 "IPv6PrefixDelegation\0"
307 config_item_perf_lookup
, network_network_gperf_lookup
,
308 CONFIG_PARSE_WARN
, network
);
310 /* Unset manager here. Otherwise, LIST_REMOVE() in network_free() fails. */
311 network
->manager
= NULL
;
315 network_apply_anonymize_if_set(network
);
317 LIST_PREPEND(networks
, manager
->networks
, network
);
319 r
= hashmap_ensure_allocated(&manager
->networks_by_name
, &string_hash_ops
);
323 r
= hashmap_put(manager
->networks_by_name
, network
->name
, network
);
327 if (network_verify(network
) < 0)
334 int network_load(Manager
*manager
) {
336 _cleanup_strv_free_
char **files
= NULL
;
342 while ((network
= manager
->networks
))
343 network_free(network
);
345 r
= conf_files_list_strv(&files
, ".network", NULL
, 0, NETWORK_DIRS
);
347 return log_error_errno(r
, "Failed to enumerate network files: %m");
349 STRV_FOREACH_BACKWARDS(f
, files
) {
350 r
= network_load_one(manager
, *f
);
358 void network_free(Network
*network
) {
359 IPv6ProxyNDPAddress
*ipv6_proxy_ndp_address
;
360 RoutingPolicyRule
*rule
;
371 free(network
->filename
);
373 set_free_free(network
->match_mac
);
374 strv_free(network
->match_path
);
375 strv_free(network
->match_driver
);
376 strv_free(network
->match_type
);
377 strv_free(network
->match_name
);
379 free(network
->description
);
380 free(network
->dhcp_vendor_class_identifier
);
381 strv_free(network
->dhcp_user_class
);
382 free(network
->dhcp_hostname
);
386 strv_free(network
->ntp
);
388 ordered_set_free_free(network
->search_domains
);
389 ordered_set_free_free(network
->route_domains
);
390 strv_free(network
->bind_carrier
);
392 ordered_set_free_free(network
->router_search_domains
);
393 free(network
->router_dns
);
395 netdev_unref(network
->bridge
);
396 netdev_unref(network
->bond
);
397 netdev_unref(network
->vrf
);
399 hashmap_free_with_destructor(network
->stacked_netdevs
, netdev_unref
);
401 while ((route
= network
->static_routes
))
404 while ((address
= network
->static_addresses
))
405 address_free(address
);
407 while ((fdb_entry
= network
->static_fdb_entries
))
408 fdb_entry_free(fdb_entry
);
410 while ((ipv6_proxy_ndp_address
= network
->ipv6_proxy_ndp_addresses
))
411 ipv6_proxy_ndp_address_free(ipv6_proxy_ndp_address
);
413 while ((neighbor
= network
->neighbors
))
414 neighbor_free(neighbor
);
416 while ((label
= network
->address_labels
))
417 address_label_free(label
);
419 while ((prefix
= network
->static_prefixes
))
422 while ((rule
= network
->rules
))
423 routing_policy_rule_free(rule
);
425 hashmap_free(network
->addresses_by_section
);
426 hashmap_free(network
->routes_by_section
);
427 hashmap_free(network
->fdb_entries_by_section
);
428 hashmap_free(network
->neighbors_by_section
);
429 hashmap_free(network
->address_labels_by_section
);
430 hashmap_free(network
->prefixes_by_section
);
431 hashmap_free(network
->rules_by_section
);
433 if (network
->manager
) {
434 if (network
->manager
->networks
)
435 LIST_REMOVE(networks
, network
->manager
->networks
, network
);
437 if (network
->manager
->networks_by_name
&& network
->name
)
438 hashmap_remove(network
->manager
->networks_by_name
, network
->name
);
440 if (network
->manager
->duids_requesting_uuid
)
441 set_remove(network
->manager
->duids_requesting_uuid
, &network
->duid
);
446 condition_free_list(network
->match_host
);
447 condition_free_list(network
->match_virt
);
448 condition_free_list(network
->match_kernel_cmdline
);
449 condition_free_list(network
->match_kernel_version
);
450 condition_free_list(network
->match_arch
);
452 free(network
->dhcp_server_timezone
);
453 free(network
->dhcp_server_dns
);
454 free(network
->dhcp_server_ntp
);
456 set_free_free(network
->dnssec_negative_trust_anchors
);
461 int network_get_by_name(Manager
*manager
, const char *name
, Network
**ret
) {
468 network
= hashmap_get(manager
->networks_by_name
, name
);
477 int network_get(Manager
*manager
, sd_device
*device
,
478 const char *ifname
, const struct ether_addr
*address
,
480 const char *path
= NULL
, *driver
= NULL
, *devtype
= NULL
;
487 (void) sd_device_get_property_value(device
, "ID_PATH", &path
);
489 (void) sd_device_get_property_value(device
, "ID_NET_DRIVER", &driver
);
491 (void) sd_device_get_devtype(device
, &devtype
);
494 LIST_FOREACH(networks
, network
, manager
->networks
) {
495 if (net_match_config(network
->match_mac
, network
->match_path
,
496 network
->match_driver
, network
->match_type
,
497 network
->match_name
, network
->match_host
,
498 network
->match_virt
, network
->match_kernel_cmdline
,
499 network
->match_kernel_version
, network
->match_arch
,
500 address
, path
, driver
, devtype
, ifname
)) {
501 if (network
->match_name
&& device
) {
503 uint8_t name_assign_type
= NET_NAME_UNKNOWN
;
505 if (sd_device_get_sysattr_value(device
, "name_assign_type", &attr
) >= 0)
506 (void) safe_atou8(attr
, &name_assign_type
);
508 if (name_assign_type
== NET_NAME_ENUM
)
509 log_warning("%s: found matching network '%s', based on potentially unpredictable ifname",
510 ifname
, network
->filename
);
512 log_debug("%s: found matching network '%s'", ifname
, network
->filename
);
514 log_debug("%s: found matching network '%s'", ifname
, network
->filename
);
526 int network_apply(Network
*network
, Link
*link
) {
532 link
->network
= network
;
534 if (network
->ipv4ll_route
) {
537 r
= route_new_static(network
, NULL
, 0, &route
);
541 r
= inet_pton(AF_INET
, "169.254.0.0", &route
->dst
.in
);
547 route
->family
= AF_INET
;
548 route
->dst_prefixlen
= 16;
549 route
->scope
= RT_SCOPE_LINK
;
550 route
->priority
= IPV4LL_ROUTE_METRIC
;
551 route
->protocol
= RTPROT_STATIC
;
554 if (network
->n_dns
> 0 ||
555 !strv_isempty(network
->ntp
) ||
556 !ordered_set_isempty(network
->search_domains
) ||
557 !ordered_set_isempty(network
->route_domains
))
563 bool network_has_static_ipv6_addresses(Network
*network
) {
568 LIST_FOREACH(addresses
, address
, network
->static_addresses
) {
569 if (address
->family
== AF_INET6
)
576 int config_parse_netdev(const char *unit
,
577 const char *filename
,
580 unsigned section_line
,
586 Network
*network
= userdata
;
587 _cleanup_free_
char *kind_string
= NULL
;
598 kind_string
= strdup(lvalue
);
602 /* the keys are CamelCase versions of the kind */
603 for (p
= kind_string
; *p
; p
++)
606 kind
= netdev_kind_from_string(kind_string
);
607 if (kind
== _NETDEV_KIND_INVALID
) {
608 log_syntax(unit
, LOG_ERR
, filename
, line
, 0,
609 "Invalid NetDev kind: %s", lvalue
);
613 r
= netdev_get(network
->manager
, rvalue
, &netdev
);
615 log_syntax(unit
, LOG_ERR
, filename
, line
, r
,
616 "%s could not be found, ignoring assignment: %s", lvalue
, rvalue
);
620 if (netdev
->kind
!= kind
) {
621 log_syntax(unit
, LOG_ERR
, filename
, line
, 0,
622 "NetDev is not a %s, ignoring assignment: %s", lvalue
, rvalue
);
627 case NETDEV_KIND_BRIDGE
:
628 network
->bridge
= netdev_unref(network
->bridge
);
629 network
->bridge
= netdev
;
632 case NETDEV_KIND_BOND
:
633 network
->bond
= netdev_unref(network
->bond
);
634 network
->bond
= netdev
;
637 case NETDEV_KIND_VRF
:
638 network
->vrf
= netdev_unref(network
->vrf
);
639 network
->vrf
= netdev
;
642 case NETDEV_KIND_VLAN
:
643 case NETDEV_KIND_MACVLAN
:
644 case NETDEV_KIND_MACVTAP
:
645 case NETDEV_KIND_IPVLAN
:
646 case NETDEV_KIND_VXLAN
:
647 case NETDEV_KIND_VCAN
:
648 r
= hashmap_ensure_allocated(&network
->stacked_netdevs
, &string_hash_ops
);
652 r
= hashmap_put(network
->stacked_netdevs
, netdev
->ifname
, netdev
);
654 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Cannot add NetDev '%s' to network: %m", rvalue
);
660 assert_not_reached("Cannot parse NetDev");
668 int config_parse_domains(
670 const char *filename
,
673 unsigned section_line
,
688 if (isempty(rvalue
)) {
689 n
->search_domains
= ordered_set_free_free(n
->search_domains
);
690 n
->route_domains
= ordered_set_free_free(n
->route_domains
);
696 _cleanup_free_
char *w
= NULL
, *normalized
= NULL
;
700 r
= extract_first_word(&p
, &w
, NULL
, 0);
702 log_syntax(unit
, LOG_ERR
, filename
, line
, r
,
703 "Failed to extract search or route domain, ignoring: %s", rvalue
);
709 is_route
= w
[0] == '~';
710 domain
= is_route
? w
+ 1 : w
;
712 if (dns_name_is_root(domain
) || streq(domain
, "*")) {
713 /* If the root domain appears as is, or the special token "*" is found, we'll
714 * consider this as routing domain, unconditionally. */
716 domain
= "."; /* make sure we don't allow empty strings, thus write the root
719 r
= dns_name_normalize(domain
, 0, &normalized
);
721 log_syntax(unit
, LOG_ERR
, filename
, line
, r
,
722 "'%s' is not a valid domain name, ignoring.", domain
);
728 if (is_localhost(domain
)) {
729 log_syntax(unit
, LOG_ERR
, filename
, line
, 0,
730 "'localhost' domain may not be configured as search or route domain, ignoring assignment: %s",
736 OrderedSet
**set
= is_route
? &n
->route_domains
: &n
->search_domains
;
737 r
= ordered_set_ensure_allocated(set
, &string_hash_ops
);
741 r
= ordered_set_put_strdup(*set
, domain
);
749 int config_parse_tunnel(const char *unit
,
750 const char *filename
,
753 unsigned section_line
,
759 Network
*network
= userdata
;
768 r
= netdev_get(network
->manager
, rvalue
, &netdev
);
770 log_syntax(unit
, LOG_ERR
, filename
, line
, r
,
771 "Tunnel is invalid, ignoring assignment: %s", rvalue
);
775 if (!IN_SET(netdev
->kind
,
781 NETDEV_KIND_IP6GRETAP
,
784 NETDEV_KIND_IP6TNL
)) {
785 log_syntax(unit
, LOG_ERR
, filename
, line
, 0,
786 "NetDev is not a tunnel, ignoring assignment: %s", rvalue
);
790 r
= hashmap_ensure_allocated(&network
->stacked_netdevs
, &string_hash_ops
);
794 r
= hashmap_put(network
->stacked_netdevs
, netdev
->ifname
, netdev
);
796 log_syntax(unit
, LOG_ERR
, filename
, line
, r
,
797 "Cannot add VLAN '%s' to network, ignoring: %m", rvalue
);
806 int config_parse_ipv4ll(
808 const char *filename
,
811 unsigned section_line
,
818 AddressFamilyBoolean
*link_local
= data
;
825 /* Note that this is mostly like
826 * config_parse_address_family_boolean(), except that it
827 * applies only to IPv4 */
829 SET_FLAG(*link_local
, ADDRESS_FAMILY_IPV4
, parse_boolean(rvalue
));
834 int config_parse_dhcp(
836 const char *filename
,
839 unsigned section_line
,
846 AddressFamilyBoolean
*dhcp
= data
, s
;
853 /* Note that this is mostly like
854 * config_parse_address_family_boolean(), except that it
855 * understands some old names for the enum values */
857 s
= address_family_boolean_from_string(rvalue
);
860 /* Previously, we had a slightly different enum here,
861 * support its values for compatbility. */
863 if (streq(rvalue
, "none"))
864 s
= ADDRESS_FAMILY_NO
;
865 else if (streq(rvalue
, "v4"))
866 s
= ADDRESS_FAMILY_IPV4
;
867 else if (streq(rvalue
, "v6"))
868 s
= ADDRESS_FAMILY_IPV6
;
869 else if (streq(rvalue
, "both"))
870 s
= ADDRESS_FAMILY_YES
;
872 log_syntax(unit
, LOG_ERR
, filename
, line
, 0,
873 "Failed to parse DHCP option, ignoring: %s", rvalue
);
877 log_syntax(unit
, LOG_WARNING
, filename
, line
, 0,
878 "DHCP=%s is deprecated, please use DHCP=%s instead.",
879 rvalue
, address_family_boolean_to_string(s
));
886 static const char* const dhcp_client_identifier_table
[_DHCP_CLIENT_ID_MAX
] = {
887 [DHCP_CLIENT_ID_MAC
] = "mac",
888 [DHCP_CLIENT_ID_DUID
] = "duid",
889 [DHCP_CLIENT_ID_DUID_ONLY
] = "duid-only",
892 DEFINE_PRIVATE_STRING_TABLE_LOOKUP_FROM_STRING(dhcp_client_identifier
, DHCPClientIdentifier
);
893 DEFINE_CONFIG_PARSE_ENUM(config_parse_dhcp_client_identifier
, dhcp_client_identifier
, DHCPClientIdentifier
,
894 "Failed to parse client identifier type");
896 int config_parse_ipv6token(
898 const char *filename
,
901 unsigned section_line
,
908 union in_addr_union buffer
;
909 struct in6_addr
*token
= data
;
917 r
= in_addr_from_string(AF_INET6
, rvalue
, &buffer
);
919 log_syntax(unit
, LOG_ERR
, filename
, line
, r
,
920 "Failed to parse IPv6 token, ignoring: %s", rvalue
);
924 if (in_addr_is_null(AF_INET6
, &buffer
)) {
925 log_syntax(unit
, LOG_ERR
, filename
, line
, 0,
926 "IPv6 token cannot be the ANY address, ignoring: %s", rvalue
);
930 if ((buffer
.in6
.s6_addr32
[0] | buffer
.in6
.s6_addr32
[1]) != 0) {
931 log_syntax(unit
, LOG_ERR
, filename
, line
, 0,
932 "IPv6 token cannot be longer than 64 bits, ignoring: %s", rvalue
);
941 static const char* const ipv6_privacy_extensions_table
[_IPV6_PRIVACY_EXTENSIONS_MAX
] = {
942 [IPV6_PRIVACY_EXTENSIONS_NO
] = "no",
943 [IPV6_PRIVACY_EXTENSIONS_PREFER_PUBLIC
] = "prefer-public",
944 [IPV6_PRIVACY_EXTENSIONS_YES
] = "yes",
947 DEFINE_STRING_TABLE_LOOKUP(ipv6_privacy_extensions
, IPv6PrivacyExtensions
);
949 int config_parse_ipv6_privacy_extensions(
951 const char *filename
,
954 unsigned section_line
,
961 IPv6PrivacyExtensions
*ipv6_privacy_extensions
= data
;
967 assert(ipv6_privacy_extensions
);
969 /* Our enum shall be a superset of booleans, hence first try
970 * to parse as boolean, and then as enum */
972 k
= parse_boolean(rvalue
);
974 *ipv6_privacy_extensions
= IPV6_PRIVACY_EXTENSIONS_YES
;
976 *ipv6_privacy_extensions
= IPV6_PRIVACY_EXTENSIONS_NO
;
978 IPv6PrivacyExtensions s
;
980 s
= ipv6_privacy_extensions_from_string(rvalue
);
983 if (streq(rvalue
, "kernel"))
984 s
= _IPV6_PRIVACY_EXTENSIONS_INVALID
;
986 log_syntax(unit
, LOG_ERR
, filename
, line
, 0,
987 "Failed to parse IPv6 privacy extensions option, ignoring: %s", rvalue
);
992 *ipv6_privacy_extensions
= s
;
998 int config_parse_hostname(
1000 const char *filename
,
1002 const char *section
,
1003 unsigned section_line
,
1010 _cleanup_free_
char *hn
= NULL
;
1011 char **hostname
= data
;
1018 r
= config_parse_string(unit
, filename
, line
, section
, section_line
, lvalue
, ltype
, rvalue
, &hn
, userdata
);
1022 if (!hostname_is_valid(hn
, false)) {
1023 log_syntax(unit
, LOG_ERR
, filename
, line
, 0,
1024 "Hostname is not valid, ignoring assignment: %s", rvalue
);
1028 r
= dns_name_is_valid(hn
);
1030 log_syntax(unit
, LOG_ERR
, filename
, line
, r
,
1031 "Failed to check validity of hostname '%s', ignoring assignment: %m", rvalue
);
1035 log_syntax(unit
, LOG_ERR
, filename
, line
, 0,
1036 "Hostname is not a valid DNS domain name, ignoring assignment: %s", rvalue
);
1040 return free_and_replace(*hostname
, hn
);
1043 int config_parse_timezone(
1045 const char *filename
,
1047 const char *section
,
1048 unsigned section_line
,
1055 _cleanup_free_
char *tz
= NULL
;
1056 char **datap
= data
;
1063 r
= config_parse_string(unit
, filename
, line
, section
, section_line
, lvalue
, ltype
, rvalue
, &tz
, userdata
);
1067 if (!timezone_is_valid(tz
, LOG_ERR
)) {
1068 log_syntax(unit
, LOG_ERR
, filename
, line
, 0,
1069 "Timezone is not valid, ignoring assignment: %s", rvalue
);
1073 return free_and_replace(*datap
, tz
);
1076 int config_parse_dhcp_server_dns(
1078 const char *filename
,
1080 const char *section
,
1081 unsigned section_line
,
1089 const char *p
= rvalue
;
1097 _cleanup_free_
char *w
= NULL
;
1098 struct in_addr a
, *m
;
1100 r
= extract_first_word(&p
, &w
, NULL
, 0);
1104 log_syntax(unit
, LOG_ERR
, filename
, line
, r
,
1105 "Failed to extract word, ignoring: %s", rvalue
);
1111 if (inet_pton(AF_INET
, w
, &a
) <= 0) {
1112 log_syntax(unit
, LOG_ERR
, filename
, line
, 0,
1113 "Failed to parse DNS server address, ignoring: %s", w
);
1117 m
= reallocarray(n
->dhcp_server_dns
, n
->n_dhcp_server_dns
+ 1, sizeof(struct in_addr
));
1121 m
[n
->n_dhcp_server_dns
++] = a
;
1122 n
->dhcp_server_dns
= m
;
1128 int config_parse_radv_dns(
1130 const char *filename
,
1132 const char *section
,
1133 unsigned section_line
,
1141 const char *p
= rvalue
;
1149 _cleanup_free_
char *w
= NULL
;
1150 union in_addr_union a
;
1152 r
= extract_first_word(&p
, &w
, NULL
, 0);
1156 log_syntax(unit
, LOG_ERR
, filename
, line
, r
,
1157 "Failed to extract word, ignoring: %s", rvalue
);
1163 if (in_addr_from_string(AF_INET6
, w
, &a
) >= 0) {
1166 m
= reallocarray(n
->router_dns
, n
->n_router_dns
+ 1, sizeof(struct in6_addr
));
1170 m
[n
->n_router_dns
++] = a
.in6
;
1174 log_syntax(unit
, LOG_ERR
, filename
, line
, 0,
1175 "Failed to parse DNS server address, ignoring: %s", w
);
1181 int config_parse_radv_search_domains(
1183 const char *filename
,
1185 const char *section
,
1186 unsigned section_line
,
1194 const char *p
= rvalue
;
1202 _cleanup_free_
char *w
= NULL
, *idna
= NULL
;
1204 r
= extract_first_word(&p
, &w
, NULL
, 0);
1208 log_syntax(unit
, LOG_ERR
, filename
, line
, r
,
1209 "Failed to extract word, ignoring: %s", rvalue
);
1215 r
= dns_name_apply_idna(w
, &idna
);
1217 log_syntax(unit
, LOG_ERR
, filename
, line
, r
,
1218 "Failed to apply IDNA to domain name '%s', ignoring: %m", w
);
1221 /* transfer ownership to simplify subsequent operations */
1224 r
= ordered_set_ensure_allocated(&n
->router_search_domains
, &string_hash_ops
);
1228 r
= ordered_set_consume(n
->router_search_domains
, TAKE_PTR(idna
));
1236 int config_parse_dhcp_server_ntp(
1238 const char *filename
,
1240 const char *section
,
1241 unsigned section_line
,
1249 const char *p
= rvalue
;
1257 _cleanup_free_
char *w
= NULL
;
1258 struct in_addr a
, *m
;
1260 r
= extract_first_word(&p
, &w
, NULL
, 0);
1264 log_syntax(unit
, LOG_ERR
, filename
, line
, r
,
1265 "Failed to extract word, ignoring: %s", rvalue
);
1271 if (inet_pton(AF_INET
, w
, &a
) <= 0) {
1272 log_syntax(unit
, LOG_ERR
, filename
, line
, 0,
1273 "Failed to parse NTP server address, ignoring: %s", w
);
1277 m
= reallocarray(n
->dhcp_server_ntp
, n
->n_dhcp_server_ntp
+ 1, sizeof(struct in_addr
));
1281 m
[n
->n_dhcp_server_ntp
++] = a
;
1282 n
->dhcp_server_ntp
= m
;
1286 int config_parse_dns(
1288 const char *filename
,
1290 const char *section
,
1291 unsigned section_line
,
1298 Network
*n
= userdata
;
1306 _cleanup_free_
char *w
= NULL
;
1307 union in_addr_union a
;
1308 struct in_addr_data
*m
;
1311 r
= extract_first_word(&rvalue
, &w
, NULL
, 0);
1315 log_syntax(unit
, LOG_ERR
, filename
, line
, r
,
1316 "Invalid syntax, ignoring: %s", rvalue
);
1322 r
= in_addr_from_string_auto(w
, &family
, &a
);
1324 log_syntax(unit
, LOG_ERR
, filename
, line
, r
,
1325 "Failed to parse dns server address, ignoring: %s", w
);
1329 m
= reallocarray(n
->dns
, n
->n_dns
+ 1, sizeof(struct in_addr_data
));
1333 m
[n
->n_dns
++] = (struct in_addr_data
) {
1344 int config_parse_dnssec_negative_trust_anchors(
1346 const char *filename
,
1348 const char *section
,
1349 unsigned section_line
,
1356 const char *p
= rvalue
;
1364 if (isempty(rvalue
)) {
1365 n
->dnssec_negative_trust_anchors
= set_free_free(n
->dnssec_negative_trust_anchors
);
1370 _cleanup_free_
char *w
= NULL
;
1372 r
= extract_first_word(&p
, &w
, NULL
, 0);
1374 log_syntax(unit
, LOG_ERR
, filename
, line
, r
,
1375 "Failed to extract negative trust anchor domain, ignoring: %s", rvalue
);
1381 r
= dns_name_is_valid(w
);
1383 log_syntax(unit
, LOG_ERR
, filename
, line
, r
,
1384 "%s is not a valid domain name, ignoring.", w
);
1388 r
= set_ensure_allocated(&n
->dnssec_negative_trust_anchors
, &dns_name_hash_ops
);
1392 r
= set_put(n
->dnssec_negative_trust_anchors
, w
);
1402 int config_parse_ntp(
1404 const char *filename
,
1406 const char *section
,
1407 unsigned section_line
,
1421 if (isempty(rvalue
)) {
1427 _cleanup_free_
char *w
= NULL
;
1429 r
= extract_first_word(&rvalue
, &w
, NULL
, 0);
1433 log_syntax(unit
, LOG_ERR
, filename
, line
, r
,
1434 "Failed to extract NTP server name, ignoring: %s", rvalue
);
1440 r
= dns_name_is_valid_or_address(w
);
1442 log_syntax(unit
, LOG_ERR
, filename
, line
, r
,
1443 "%s is not a valid domain name or IP address, ignoring.", w
);
1447 r
= strv_push(l
, w
);
1457 int config_parse_dhcp_user_class(
1459 const char *filename
,
1461 const char *section
,
1462 unsigned section_line
,
1476 if (isempty(rvalue
)) {
1482 _cleanup_free_
char *w
= NULL
;
1484 r
= extract_first_word(&rvalue
, &w
, NULL
, 0);
1488 log_syntax(unit
, LOG_ERR
, filename
, line
, r
,
1489 "Failed to split user classes option, ignoring: %s", rvalue
);
1495 if (strlen(w
) > 255) {
1496 log_syntax(unit
, LOG_ERR
, filename
, line
, r
,
1497 "%s length is not in the range 1-255, ignoring.", w
);
1501 r
= strv_push(l
, w
);
1511 int config_parse_section_route_table(
1513 const char *filename
,
1515 const char *section
,
1516 unsigned section_line
,
1523 Network
*network
= data
;
1532 r
= safe_atou32(rvalue
, &rt
);
1534 log_syntax(unit
, LOG_ERR
, filename
, line
, r
,
1535 "Failed to parse RouteTable=%s, ignoring assignment: %m", rvalue
);
1539 if (streq_ptr(section
, "DHCP")) {
1540 network
->dhcp_route_table
= rt
;
1541 network
->dhcp_route_table_set
= true;
1542 } else { /* section is IPv6AcceptRA */
1543 network
->ipv6_accept_ra_route_table
= rt
;
1544 network
->ipv6_accept_ra_route_table_set
= true;
1550 DEFINE_CONFIG_PARSE_ENUM(config_parse_dhcp_use_domains
, dhcp_use_domains
, DHCPUseDomains
,
1551 "Failed to parse DHCP use domains setting");
1553 static const char* const dhcp_use_domains_table
[_DHCP_USE_DOMAINS_MAX
] = {
1554 [DHCP_USE_DOMAINS_NO
] = "no",
1555 [DHCP_USE_DOMAINS_ROUTE
] = "route",
1556 [DHCP_USE_DOMAINS_YES
] = "yes",
1559 DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(dhcp_use_domains
, DHCPUseDomains
, DHCP_USE_DOMAINS_YES
);
1561 DEFINE_CONFIG_PARSE_ENUM(config_parse_lldp_mode
, lldp_mode
, LLDPMode
, "Failed to parse LLDP= setting.");
1563 static const char* const lldp_mode_table
[_LLDP_MODE_MAX
] = {
1564 [LLDP_MODE_NO
] = "no",
1565 [LLDP_MODE_YES
] = "yes",
1566 [LLDP_MODE_ROUTERS_ONLY
] = "routers-only",
1569 DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(lldp_mode
, LLDPMode
, LLDP_MODE_YES
);
1571 int config_parse_iaid(const char *unit
,
1572 const char *filename
,
1574 const char *section
,
1575 unsigned section_line
,
1581 Network
*network
= data
;
1590 r
= safe_atou32(rvalue
, &iaid
);
1592 log_syntax(unit
, LOG_ERR
, filename
, line
, r
,
1593 "Unable to read IAID, ignoring assignment: %s", rvalue
);
1597 network
->iaid
= iaid
;
1598 network
->iaid_set
= true;