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 "network-internal.h"
14 #include "networkd-manager.h"
15 #include "networkd-network.h"
16 #include "parse-util.h"
18 #include "stat-util.h"
19 #include "string-table.h"
20 #include "string-util.h"
24 static void network_config_hash_func(const void *p
, struct siphash
*state
) {
25 const NetworkConfigSection
*c
= p
;
27 siphash24_compress(c
->filename
, strlen(c
->filename
), state
);
28 siphash24_compress(&c
->line
, sizeof(c
->line
), state
);
31 static int network_config_compare_func(const void *a
, const void *b
) {
32 const NetworkConfigSection
*x
= a
, *y
= b
;
35 r
= strcmp(x
->filename
, y
->filename
);
39 return CMP(x
->line
, y
->line
);
42 const struct hash_ops network_config_hash_ops
= {
43 .hash
= network_config_hash_func
,
44 .compare
= network_config_compare_func
,
47 int network_config_section_new(const char *filename
, unsigned line
, NetworkConfigSection
**s
) {
48 NetworkConfigSection
*cs
;
50 cs
= malloc0(offsetof(NetworkConfigSection
, filename
) + strlen(filename
) + 1);
54 strcpy(cs
->filename
, filename
);
62 void network_config_section_free(NetworkConfigSection
*cs
) {
66 /* Set defaults following RFC7844 */
67 void network_apply_anonymize_if_set(Network
*network
) {
68 if (!network
->dhcp_anonymize
)
71 SHOULD NOT send the Host Name option */
72 network
->dhcp_send_hostname
= false;
73 /* RFC7844 section 3.:
74 MAY contain the Client Identifier option
76 clients MUST use client identifiers based solely
77 on the link-layer address */
78 /* NOTE: Using MAC, as it does not reveal extra information,
79 * and some servers might not answer if this option is not sent */
80 network
->dhcp_client_identifier
= DHCP_CLIENT_ID_MAC
;
82 SHOULD NOT use the Vendor Class Identifier option */
83 network
->dhcp_vendor_class_identifier
= mfree(network
->dhcp_vendor_class_identifier
);
84 /* RFC7844 section 3.6.:
85 The client intending to protect its privacy SHOULD only request a
86 minimal number of options in the PRL and SHOULD also randomly shuffle
87 the ordering of option codes in the PRL. If this random ordering
88 cannot be implemented, the client MAY order the option codes in the
89 PRL by option code number (lowest to highest).
91 /* NOTE: dhcp_use_mtu is false by default,
92 * though it was not initiallized to any value in network_load_one.
93 * Maybe there should be another var called *send*?
94 * (to use the MTU sent by the server but to do not send
95 * the option in the PRL). */
96 network
->dhcp_use_mtu
= false;
97 /* NOTE: when Anonymize=yes, the PRL route options are sent by default,
98 * but this is needed to use them. */
99 network
->dhcp_use_routes
= true;
100 /* RFC7844 section 3.6.
101 * same comments as previous option */
102 network
->dhcp_use_timezone
= false;
105 static int network_load_one(Manager
*manager
, const char *filename
) {
106 _cleanup_(network_freep
) Network
*network
= NULL
;
107 _cleanup_fclose_
FILE *file
= NULL
;
109 const char *dropin_dirname
;
117 file
= fopen(filename
, "re");
125 if (null_or_empty_fd(fileno(file
))) {
126 log_debug("Skipping empty file: %s", filename
);
130 network
= new0(Network
, 1);
134 network
->manager
= manager
;
136 LIST_HEAD_INIT(network
->static_addresses
);
137 LIST_HEAD_INIT(network
->static_routes
);
138 LIST_HEAD_INIT(network
->static_fdb_entries
);
139 LIST_HEAD_INIT(network
->ipv6_proxy_ndp_addresses
);
140 LIST_HEAD_INIT(network
->address_labels
);
141 LIST_HEAD_INIT(network
->static_prefixes
);
142 LIST_HEAD_INIT(network
->rules
);
144 network
->stacked_netdevs
= hashmap_new(&string_hash_ops
);
145 if (!network
->stacked_netdevs
)
148 network
->addresses_by_section
= hashmap_new(&network_config_hash_ops
);
149 if (!network
->addresses_by_section
)
152 network
->routes_by_section
= hashmap_new(&network_config_hash_ops
);
153 if (!network
->routes_by_section
)
156 network
->fdb_entries_by_section
= hashmap_new(NULL
);
157 if (!network
->fdb_entries_by_section
)
160 network
->address_labels_by_section
= hashmap_new(&network_config_hash_ops
);
161 if (!network
->address_labels_by_section
)
164 network
->prefixes_by_section
= hashmap_new(&network_config_hash_ops
);
165 if (!network
->prefixes_by_section
)
168 network
->rules_by_section
= hashmap_new(&network_config_hash_ops
);
169 if (!network
->rules_by_section
)
172 network
->filename
= strdup(filename
);
173 if (!network
->filename
)
176 network
->name
= strdup(basename(filename
));
180 d
= strrchr(network
->name
, '.');
184 assert(streq(d
, ".network"));
188 network
->required_for_online
= true;
189 network
->dhcp
= ADDRESS_FAMILY_NO
;
190 network
->dhcp_use_ntp
= true;
191 network
->dhcp_use_dns
= true;
192 network
->dhcp_use_hostname
= true;
193 network
->dhcp_use_routes
= true;
194 /* NOTE: this var might be overwriten by network_apply_anonymize_if_set */
195 network
->dhcp_send_hostname
= true;
196 /* To enable/disable RFC7844 Anonymity Profiles */
197 network
->dhcp_anonymize
= false;
198 network
->dhcp_route_metric
= DHCP_ROUTE_METRIC
;
199 /* NOTE: this var might be overwrite by network_apply_anonymize_if_set */
200 network
->dhcp_client_identifier
= DHCP_CLIENT_ID_DUID
;
201 network
->dhcp_route_table
= RT_TABLE_MAIN
;
202 network
->dhcp_route_table_set
= false;
203 /* NOTE: from man: UseMTU=... Defaults to false*/
204 network
->dhcp_use_mtu
= false;
205 /* NOTE: from man: UseTimezone=... Defaults to "no".*/
206 network
->dhcp_use_timezone
= false;
207 network
->rapid_commit
= true;
209 network
->dhcp_server_emit_dns
= true;
210 network
->dhcp_server_emit_ntp
= true;
211 network
->dhcp_server_emit_router
= true;
212 network
->dhcp_server_emit_timezone
= true;
214 network
->router_emit_dns
= true;
215 network
->router_emit_domains
= true;
217 network
->use_bpdu
= -1;
218 network
->hairpin
= -1;
219 network
->fast_leave
= -1;
220 network
->allow_port_to_be_root
= -1;
221 network
->unicast_flood
= -1;
222 network
->priority
= LINK_BRIDGE_PORT_PRIORITY_INVALID
;
224 network
->lldp_mode
= LLDP_MODE_ROUTERS_ONLY
;
226 network
->llmnr
= RESOLVE_SUPPORT_YES
;
227 network
->mdns
= RESOLVE_SUPPORT_NO
;
228 network
->dnssec_mode
= _DNSSEC_MODE_INVALID
;
229 network
->dns_over_tls_mode
= _DNS_OVER_TLS_MODE_INVALID
;
231 network
->link_local
= ADDRESS_FAMILY_IPV6
;
233 network
->ipv6_privacy_extensions
= IPV6_PRIVACY_EXTENSIONS_NO
;
234 network
->ipv6_accept_ra
= -1;
235 network
->ipv6_dad_transmits
= -1;
236 network
->ipv6_hop_limit
= -1;
237 network
->ipv6_proxy_ndp
= -1;
238 network
->duid
.type
= _DUID_TYPE_INVALID
;
239 network
->proxy_arp
= -1;
241 network
->multicast
= -1;
242 network
->allmulticast
= -1;
243 network
->ipv6_accept_ra_use_dns
= true;
244 network
->ipv6_accept_ra_route_table
= RT_TABLE_MAIN
;
245 network
->ipv6_mtu
= 0;
247 dropin_dirname
= strjoina(network
->name
, ".network.d");
249 r
= config_parse_many(filename
, network_dirs
, dropin_dirname
,
255 "RoutingPolicyRule\0"
258 "DHCPv4\0" /* compat */
261 "IPv6NDPProxyAddress\0"
265 "IPv6PrefixDelegation\0"
268 config_item_perf_lookup
, network_network_gperf_lookup
,
269 CONFIG_PARSE_WARN
, network
);
273 network_apply_anonymize_if_set(network
);
275 /* IPMasquerade=yes implies IPForward=yes */
276 if (network
->ip_masquerade
)
277 network
->ip_forward
|= ADDRESS_FAMILY_IPV4
;
279 if (network
->mtu
> 0 && network
->dhcp_use_mtu
) {
280 log_warning("MTUBytes= in [Link] section and UseMTU= in [DHCP] section are set in %s. "
281 "Disabling UseMTU=.", filename
);
282 network
->dhcp_use_mtu
= false;
285 LIST_PREPEND(networks
, manager
->networks
, network
);
287 r
= hashmap_ensure_allocated(&manager
->networks_by_name
, &string_hash_ops
);
291 r
= hashmap_put(manager
->networks_by_name
, network
->name
, network
);
295 LIST_FOREACH(routes
, route
, network
->static_routes
) {
296 if (!route
->family
) {
297 log_warning("Route section without Gateway field configured in %s. "
298 "Ignoring", filename
);
303 LIST_FOREACH(addresses
, address
, network
->static_addresses
) {
304 if (!address
->family
) {
305 log_warning("Address section without Address field configured in %s. "
306 "Ignoring", filename
);
316 int network_load(Manager
*manager
) {
318 _cleanup_strv_free_
char **files
= NULL
;
324 while ((network
= manager
->networks
))
325 network_free(network
);
327 r
= conf_files_list_strv(&files
, ".network", NULL
, 0, network_dirs
);
329 return log_error_errno(r
, "Failed to enumerate network files: %m");
331 STRV_FOREACH_BACKWARDS(f
, files
) {
332 r
= network_load_one(manager
, *f
);
340 void network_free(Network
*network
) {
341 IPv6ProxyNDPAddress
*ipv6_proxy_ndp_address
;
342 RoutingPolicyRule
*rule
;
354 free(network
->filename
);
356 set_free_free(network
->match_mac
);
357 strv_free(network
->match_path
);
358 strv_free(network
->match_driver
);
359 strv_free(network
->match_type
);
360 strv_free(network
->match_name
);
362 free(network
->description
);
363 free(network
->dhcp_vendor_class_identifier
);
364 strv_free(network
->dhcp_user_class
);
365 free(network
->dhcp_hostname
);
369 strv_free(network
->ntp
);
371 strv_free(network
->search_domains
);
372 strv_free(network
->route_domains
);
373 strv_free(network
->bind_carrier
);
375 netdev_unref(network
->bridge
);
376 netdev_unref(network
->bond
);
377 netdev_unref(network
->vrf
);
379 HASHMAP_FOREACH(netdev
, network
->stacked_netdevs
, i
) {
380 hashmap_remove(network
->stacked_netdevs
, netdev
->ifname
);
381 netdev_unref(netdev
);
383 hashmap_free(network
->stacked_netdevs
);
385 while ((route
= network
->static_routes
))
388 while ((address
= network
->static_addresses
))
389 address_free(address
);
391 while ((fdb_entry
= network
->static_fdb_entries
))
392 fdb_entry_free(fdb_entry
);
394 while ((ipv6_proxy_ndp_address
= network
->ipv6_proxy_ndp_addresses
))
395 ipv6_proxy_ndp_address_free(ipv6_proxy_ndp_address
);
397 while ((label
= network
->address_labels
))
398 address_label_free(label
);
400 while ((prefix
= network
->static_prefixes
))
403 while ((rule
= network
->rules
))
404 routing_policy_rule_free(rule
);
406 hashmap_free(network
->addresses_by_section
);
407 hashmap_free(network
->routes_by_section
);
408 hashmap_free(network
->fdb_entries_by_section
);
409 hashmap_free(network
->address_labels_by_section
);
410 hashmap_free(network
->prefixes_by_section
);
411 hashmap_free(network
->rules_by_section
);
413 if (network
->manager
) {
414 if (network
->manager
->networks
)
415 LIST_REMOVE(networks
, network
->manager
->networks
, network
);
417 if (network
->manager
->networks_by_name
)
418 hashmap_remove(network
->manager
->networks_by_name
, network
->name
);
420 if (network
->manager
->duids_requesting_uuid
)
421 set_remove(network
->manager
->duids_requesting_uuid
, &network
->duid
);
426 condition_free_list(network
->match_host
);
427 condition_free_list(network
->match_virt
);
428 condition_free_list(network
->match_kernel_cmdline
);
429 condition_free_list(network
->match_kernel_version
);
430 condition_free_list(network
->match_arch
);
432 free(network
->dhcp_server_timezone
);
433 free(network
->dhcp_server_dns
);
434 free(network
->dhcp_server_ntp
);
436 set_free_free(network
->dnssec_negative_trust_anchors
);
441 int network_get_by_name(Manager
*manager
, const char *name
, Network
**ret
) {
448 network
= hashmap_get(manager
->networks_by_name
, name
);
457 int network_get(Manager
*manager
, sd_device
*device
,
458 const char *ifname
, const struct ether_addr
*address
,
460 const char *path
= NULL
, *parent_driver
= NULL
, *driver
= NULL
, *devtype
= NULL
;
468 (void) sd_device_get_property_value(device
, "ID_PATH", &path
);
470 if (sd_device_get_parent(device
, &parent
) >= 0)
471 (void) sd_device_get_driver(parent
, &parent_driver
);
473 (void) sd_device_get_property_value(device
, "ID_NET_DRIVER", &driver
);
475 (void) sd_device_get_devtype(device
, &devtype
);
478 LIST_FOREACH(networks
, network
, manager
->networks
) {
479 if (net_match_config(network
->match_mac
, network
->match_path
,
480 network
->match_driver
, network
->match_type
,
481 network
->match_name
, network
->match_host
,
482 network
->match_virt
, network
->match_kernel_cmdline
,
483 network
->match_kernel_version
, network
->match_arch
,
484 address
, path
, parent_driver
, driver
,
486 if (network
->match_name
&& device
) {
488 uint8_t name_assign_type
= NET_NAME_UNKNOWN
;
490 if (sd_device_get_sysattr_value(device
, "name_assign_type", &attr
) >= 0)
491 (void) safe_atou8(attr
, &name_assign_type
);
493 if (name_assign_type
== NET_NAME_ENUM
)
494 log_warning("%s: found matching network '%s', based on potentially unpredictable ifname",
495 ifname
, network
->filename
);
497 log_debug("%s: found matching network '%s'", ifname
, network
->filename
);
499 log_debug("%s: found matching network '%s'", ifname
, network
->filename
);
511 int network_apply(Network
*network
, Link
*link
) {
517 link
->network
= network
;
519 if (network
->ipv4ll_route
) {
522 r
= route_new_static(network
, NULL
, 0, &route
);
526 r
= inet_pton(AF_INET
, "169.254.0.0", &route
->dst
.in
);
532 route
->family
= AF_INET
;
533 route
->dst_prefixlen
= 16;
534 route
->scope
= RT_SCOPE_LINK
;
535 route
->priority
= IPV4LL_ROUTE_METRIC
;
536 route
->protocol
= RTPROT_STATIC
;
539 if (network
->n_dns
> 0 ||
540 !strv_isempty(network
->ntp
) ||
541 !strv_isempty(network
->search_domains
) ||
542 !strv_isempty(network
->route_domains
))
548 bool network_has_static_ipv6_addresses(Network
*network
) {
553 LIST_FOREACH(addresses
, address
, network
->static_addresses
) {
554 if (address
->family
== AF_INET6
)
561 int config_parse_netdev(const char *unit
,
562 const char *filename
,
565 unsigned section_line
,
571 Network
*network
= userdata
;
572 _cleanup_free_
char *kind_string
= NULL
;
583 kind_string
= strdup(lvalue
);
587 /* the keys are CamelCase versions of the kind */
588 for (p
= kind_string
; *p
; p
++)
591 kind
= netdev_kind_from_string(kind_string
);
592 if (kind
== _NETDEV_KIND_INVALID
) {
593 log_syntax(unit
, LOG_ERR
, filename
, line
, 0, "Invalid NetDev kind: %s", lvalue
);
597 r
= netdev_get(network
->manager
, rvalue
, &netdev
);
599 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "%s could not be found, ignoring assignment: %s", lvalue
, rvalue
);
603 if (netdev
->kind
!= kind
) {
604 log_syntax(unit
, LOG_ERR
, filename
, line
, 0, "NetDev is not a %s, ignoring assignment: %s", lvalue
, rvalue
);
609 case NETDEV_KIND_BRIDGE
:
610 network
->bridge
= netdev_unref(network
->bridge
);
611 network
->bridge
= netdev
;
614 case NETDEV_KIND_BOND
:
615 network
->bond
= netdev_unref(network
->bond
);
616 network
->bond
= netdev
;
619 case NETDEV_KIND_VRF
:
620 network
->vrf
= netdev_unref(network
->vrf
);
621 network
->vrf
= netdev
;
624 case NETDEV_KIND_VLAN
:
625 case NETDEV_KIND_MACVLAN
:
626 case NETDEV_KIND_MACVTAP
:
627 case NETDEV_KIND_IPVLAN
:
628 case NETDEV_KIND_VXLAN
:
629 case NETDEV_KIND_VCAN
:
630 r
= hashmap_put(network
->stacked_netdevs
, netdev
->ifname
, netdev
);
632 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Cannot add NetDev '%s' to network: %m", rvalue
);
638 assert_not_reached("Cannot parse NetDev");
646 int config_parse_domains(
648 const char *filename
,
651 unsigned section_line
,
666 if (isempty(rvalue
)) {
667 n
->search_domains
= strv_free(n
->search_domains
);
668 n
->route_domains
= strv_free(n
->route_domains
);
674 _cleanup_free_
char *w
= NULL
, *normalized
= NULL
;
678 r
= extract_first_word(&p
, &w
, NULL
, 0);
680 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Failed to extract search or route domain, ignoring: %s", rvalue
);
686 is_route
= w
[0] == '~';
687 domain
= is_route
? w
+ 1 : w
;
689 if (dns_name_is_root(domain
) || streq(domain
, "*")) {
690 /* If the root domain appears as is, or the special token "*" is found, we'll consider this as
691 * routing domain, unconditionally. */
693 domain
= "."; /* make sure we don't allow empty strings, thus write the root domain as "." */
696 r
= dns_name_normalize(domain
, &normalized
);
698 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "'%s' is not a valid domain name, ignoring.", domain
);
704 if (is_localhost(domain
)) {
705 log_syntax(unit
, LOG_ERR
, filename
, line
, 0, "'localhost' domain names may not be configure as search or route domains, ignoring assignment: %s", domain
);
711 r
= strv_extend(&n
->route_domains
, domain
);
716 r
= strv_extend(&n
->search_domains
, domain
);
722 strv_uniq(n
->route_domains
);
723 strv_uniq(n
->search_domains
);
728 int config_parse_tunnel(const char *unit
,
729 const char *filename
,
732 unsigned section_line
,
738 Network
*network
= userdata
;
747 r
= netdev_get(network
->manager
, rvalue
, &netdev
);
749 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Tunnel is invalid, ignoring assignment: %s", rvalue
);
753 if (!IN_SET(netdev
->kind
,
759 NETDEV_KIND_IP6GRETAP
,
762 NETDEV_KIND_IP6TNL
)) {
763 log_syntax(unit
, LOG_ERR
, filename
, line
, 0,
764 "NetDev is not a tunnel, ignoring assignment: %s", rvalue
);
768 r
= hashmap_put(network
->stacked_netdevs
, netdev
->ifname
, netdev
);
770 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Cannot add VLAN '%s' to network, ignoring: %m", rvalue
);
779 int config_parse_ipv4ll(
781 const char *filename
,
784 unsigned section_line
,
791 AddressFamilyBoolean
*link_local
= data
;
798 /* Note that this is mostly like
799 * config_parse_address_family_boolean(), except that it
800 * applies only to IPv4 */
802 SET_FLAG(*link_local
, ADDRESS_FAMILY_IPV4
, parse_boolean(rvalue
));
807 int config_parse_dhcp(
809 const char *filename
,
812 unsigned section_line
,
819 AddressFamilyBoolean
*dhcp
= data
, s
;
826 /* Note that this is mostly like
827 * config_parse_address_family_boolean(), except that it
828 * understands some old names for the enum values */
830 s
= address_family_boolean_from_string(rvalue
);
833 /* Previously, we had a slightly different enum here,
834 * support its values for compatbility. */
836 if (streq(rvalue
, "none"))
837 s
= ADDRESS_FAMILY_NO
;
838 else if (streq(rvalue
, "v4"))
839 s
= ADDRESS_FAMILY_IPV4
;
840 else if (streq(rvalue
, "v6"))
841 s
= ADDRESS_FAMILY_IPV6
;
842 else if (streq(rvalue
, "both"))
843 s
= ADDRESS_FAMILY_YES
;
845 log_syntax(unit
, LOG_ERR
, filename
, line
, 0, "Failed to parse DHCP option, ignoring: %s", rvalue
);
854 static const char* const dhcp_client_identifier_table
[_DHCP_CLIENT_ID_MAX
] = {
855 [DHCP_CLIENT_ID_MAC
] = "mac",
856 [DHCP_CLIENT_ID_DUID
] = "duid",
857 [DHCP_CLIENT_ID_DUID_ONLY
] = "duid-only",
860 DEFINE_PRIVATE_STRING_TABLE_LOOKUP_FROM_STRING(dhcp_client_identifier
, DHCPClientIdentifier
);
861 DEFINE_CONFIG_PARSE_ENUM(config_parse_dhcp_client_identifier
, dhcp_client_identifier
, DHCPClientIdentifier
, "Failed to parse client identifier type");
863 int config_parse_ipv6token(
865 const char *filename
,
868 unsigned section_line
,
875 union in_addr_union buffer
;
876 struct in6_addr
*token
= data
;
884 r
= in_addr_from_string(AF_INET6
, rvalue
, &buffer
);
886 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Failed to parse IPv6 token, ignoring: %s", rvalue
);
890 r
= in_addr_is_null(AF_INET6
, &buffer
);
892 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "IPv6 token cannot be the ANY address, ignoring: %s", rvalue
);
896 if ((buffer
.in6
.s6_addr32
[0] | buffer
.in6
.s6_addr32
[1]) != 0) {
897 log_syntax(unit
, LOG_ERR
, filename
, line
, 0, "IPv6 token cannot be longer than 64 bits, ignoring: %s", rvalue
);
906 static const char* const ipv6_privacy_extensions_table
[_IPV6_PRIVACY_EXTENSIONS_MAX
] = {
907 [IPV6_PRIVACY_EXTENSIONS_NO
] = "no",
908 [IPV6_PRIVACY_EXTENSIONS_PREFER_PUBLIC
] = "prefer-public",
909 [IPV6_PRIVACY_EXTENSIONS_YES
] = "yes",
912 DEFINE_STRING_TABLE_LOOKUP(ipv6_privacy_extensions
, IPv6PrivacyExtensions
);
914 int config_parse_ipv6_privacy_extensions(
916 const char *filename
,
919 unsigned section_line
,
926 IPv6PrivacyExtensions
*ipv6_privacy_extensions
= data
;
932 assert(ipv6_privacy_extensions
);
934 /* Our enum shall be a superset of booleans, hence first try
935 * to parse as boolean, and then as enum */
937 k
= parse_boolean(rvalue
);
939 *ipv6_privacy_extensions
= IPV6_PRIVACY_EXTENSIONS_YES
;
941 *ipv6_privacy_extensions
= IPV6_PRIVACY_EXTENSIONS_NO
;
943 IPv6PrivacyExtensions s
;
945 s
= ipv6_privacy_extensions_from_string(rvalue
);
948 if (streq(rvalue
, "kernel"))
949 s
= _IPV6_PRIVACY_EXTENSIONS_INVALID
;
951 log_syntax(unit
, LOG_ERR
, filename
, line
, 0, "Failed to parse IPv6 privacy extensions option, ignoring: %s", rvalue
);
956 *ipv6_privacy_extensions
= s
;
962 int config_parse_hostname(
964 const char *filename
,
967 unsigned section_line
,
974 _cleanup_free_
char *hn
= NULL
;
975 char **hostname
= data
;
982 r
= config_parse_string(unit
, filename
, line
, section
, section_line
, lvalue
, ltype
, rvalue
, &hn
, userdata
);
986 if (!hostname_is_valid(hn
, false)) {
987 log_syntax(unit
, LOG_ERR
, filename
, line
, 0, "Hostname is not valid, ignoring assignment: %s", rvalue
);
991 r
= dns_name_is_valid(hn
);
993 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Failed to check validity of hostname '%s', ignoring assignment: %m", rvalue
);
997 log_syntax(unit
, LOG_ERR
, filename
, line
, 0, "Hostname is not a valid DNS domain name, ignoring assignment: %s", rvalue
);
1001 return free_and_replace(*hostname
, hn
);
1004 int config_parse_timezone(
1006 const char *filename
,
1008 const char *section
,
1009 unsigned section_line
,
1016 _cleanup_free_
char *tz
= NULL
;
1017 char **datap
= data
;
1024 r
= config_parse_string(unit
, filename
, line
, section
, section_line
, lvalue
, ltype
, rvalue
, &tz
, userdata
);
1028 if (!timezone_is_valid(tz
, LOG_ERR
)) {
1029 log_syntax(unit
, LOG_ERR
, filename
, line
, 0, "Timezone is not valid, ignoring assignment: %s", rvalue
);
1033 return free_and_replace(*datap
, tz
);
1036 int config_parse_dhcp_server_dns(
1038 const char *filename
,
1040 const char *section
,
1041 unsigned section_line
,
1049 const char *p
= rvalue
;
1057 _cleanup_free_
char *w
= NULL
;
1058 struct in_addr a
, *m
;
1060 r
= extract_first_word(&p
, &w
, NULL
, 0);
1064 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Failed to extract word, ignoring: %s", rvalue
);
1070 if (inet_pton(AF_INET
, w
, &a
) <= 0) {
1071 log_syntax(unit
, LOG_ERR
, filename
, line
, 0, "Failed to parse DNS server address, ignoring: %s", w
);
1075 m
= reallocarray(n
->dhcp_server_dns
, n
->n_dhcp_server_dns
+ 1, sizeof(struct in_addr
));
1079 m
[n
->n_dhcp_server_dns
++] = a
;
1080 n
->dhcp_server_dns
= m
;
1086 int config_parse_radv_dns(
1088 const char *filename
,
1090 const char *section
,
1091 unsigned section_line
,
1099 const char *p
= rvalue
;
1107 _cleanup_free_
char *w
= NULL
;
1108 union in_addr_union a
;
1110 r
= extract_first_word(&p
, &w
, NULL
, 0);
1114 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Failed to extract word, ignoring: %s", rvalue
);
1120 if (in_addr_from_string(AF_INET6
, w
, &a
) >= 0) {
1123 m
= reallocarray(n
->router_dns
, n
->n_router_dns
+ 1, sizeof(struct in6_addr
));
1127 m
[n
->n_router_dns
++] = a
.in6
;
1131 log_syntax(unit
, LOG_ERR
, filename
, line
, 0, "Failed to parse DNS server address, ignoring: %s", w
);
1138 int config_parse_radv_search_domains(
1140 const char *filename
,
1142 const char *section
,
1143 unsigned section_line
,
1151 const char *p
= rvalue
;
1159 _cleanup_free_
char *w
= NULL
;
1160 _cleanup_free_
char *idna
= NULL
;
1162 r
= extract_first_word(&p
, &w
, NULL
, 0);
1166 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Failed to extract word, ignoring: %s", rvalue
);
1172 r
= dns_name_apply_idna(w
, &idna
);
1174 r
= strv_push(&n
->router_search_domains
, idna
);
1177 } else if (r
== 0) {
1178 r
= strv_push(&n
->router_search_domains
, w
);
1187 int config_parse_dhcp_server_ntp(
1189 const char *filename
,
1191 const char *section
,
1192 unsigned section_line
,
1200 const char *p
= rvalue
;
1208 _cleanup_free_
char *w
= NULL
;
1209 struct in_addr a
, *m
;
1211 r
= extract_first_word(&p
, &w
, NULL
, 0);
1215 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Failed to extract word, ignoring: %s", rvalue
);
1221 if (inet_pton(AF_INET
, w
, &a
) <= 0) {
1222 log_syntax(unit
, LOG_ERR
, filename
, line
, 0, "Failed to parse NTP server address, ignoring: %s", w
);
1226 m
= reallocarray(n
->dhcp_server_ntp
, n
->n_dhcp_server_ntp
+ 1, sizeof(struct in_addr
));
1230 m
[n
->n_dhcp_server_ntp
++] = a
;
1231 n
->dhcp_server_ntp
= m
;
1235 int config_parse_dns(
1237 const char *filename
,
1239 const char *section
,
1240 unsigned section_line
,
1247 Network
*n
= userdata
;
1255 _cleanup_free_
char *w
= NULL
;
1256 union in_addr_union a
;
1257 struct in_addr_data
*m
;
1260 r
= extract_first_word(&rvalue
, &w
, NULL
, 0);
1264 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Invalid syntax, ignoring: %s", rvalue
);
1270 r
= in_addr_from_string_auto(w
, &family
, &a
);
1272 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Failed to parse dns server address, ignoring: %s", w
);
1276 m
= reallocarray(n
->dns
, n
->n_dns
+ 1, sizeof(struct in_addr_data
));
1280 m
[n
->n_dns
++] = (struct in_addr_data
) {
1291 int config_parse_dnssec_negative_trust_anchors(
1293 const char *filename
,
1295 const char *section
,
1296 unsigned section_line
,
1303 const char *p
= rvalue
;
1311 if (isempty(rvalue
)) {
1312 n
->dnssec_negative_trust_anchors
= set_free_free(n
->dnssec_negative_trust_anchors
);
1317 _cleanup_free_
char *w
= NULL
;
1319 r
= extract_first_word(&p
, &w
, NULL
, 0);
1321 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Failed to extract negative trust anchor domain, ignoring: %s", rvalue
);
1327 r
= dns_name_is_valid(w
);
1329 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "%s is not a valid domain name, ignoring.", w
);
1333 r
= set_ensure_allocated(&n
->dnssec_negative_trust_anchors
, &dns_name_hash_ops
);
1337 r
= set_put(n
->dnssec_negative_trust_anchors
, w
);
1347 int config_parse_ntp(
1349 const char *filename
,
1351 const char *section
,
1352 unsigned section_line
,
1366 if (isempty(rvalue
)) {
1372 _cleanup_free_
char *w
= NULL
;
1374 r
= extract_first_word(&rvalue
, &w
, NULL
, 0);
1378 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Failed to extract NTP server name, ignoring: %s", rvalue
);
1384 r
= dns_name_is_valid_or_address(w
);
1386 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "%s is not a valid domain name or IP address, ignoring.", w
);
1390 r
= strv_push(l
, w
);
1400 int config_parse_dhcp_user_class(
1402 const char *filename
,
1404 const char *section
,
1405 unsigned section_line
,
1419 if (isempty(rvalue
)) {
1425 _cleanup_free_
char *w
= NULL
;
1427 r
= extract_first_word(&rvalue
, &w
, NULL
, 0);
1431 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Failed to split user classes option, ignoring: %s", rvalue
);
1437 if (strlen(w
) > 255) {
1438 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "%s length is not in the range 1-255, ignoring.", w
);
1442 r
= strv_push(l
, w
);
1452 int config_parse_dhcp_route_table(const char *unit
,
1453 const char *filename
,
1455 const char *section
,
1456 unsigned section_line
,
1462 Network
*network
= data
;
1471 r
= safe_atou32(rvalue
, &rt
);
1473 log_syntax(unit
, LOG_ERR
, filename
, line
, r
,
1474 "Unable to read RouteTable, ignoring assignment: %s", rvalue
);
1478 network
->dhcp_route_table
= rt
;
1479 network
->dhcp_route_table_set
= true;
1484 DEFINE_CONFIG_PARSE_ENUM(config_parse_dhcp_use_domains
, dhcp_use_domains
, DHCPUseDomains
, "Failed to parse DHCP use domains setting");
1486 static const char* const dhcp_use_domains_table
[_DHCP_USE_DOMAINS_MAX
] = {
1487 [DHCP_USE_DOMAINS_NO
] = "no",
1488 [DHCP_USE_DOMAINS_ROUTE
] = "route",
1489 [DHCP_USE_DOMAINS_YES
] = "yes",
1492 DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(dhcp_use_domains
, DHCPUseDomains
, DHCP_USE_DOMAINS_YES
);
1494 DEFINE_CONFIG_PARSE_ENUM(config_parse_lldp_mode
, lldp_mode
, LLDPMode
, "Failed to parse LLDP= setting.");
1496 static const char* const lldp_mode_table
[_LLDP_MODE_MAX
] = {
1497 [LLDP_MODE_NO
] = "no",
1498 [LLDP_MODE_YES
] = "yes",
1499 [LLDP_MODE_ROUTERS_ONLY
] = "routers-only",
1502 DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(lldp_mode
, LLDPMode
, LLDP_MODE_YES
);