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 int network_load_one(Manager
*manager
, const char *filename
) {
101 _cleanup_free_
char *fname
= NULL
, *name
= NULL
;
102 _cleanup_(network_freep
) Network
*network
= NULL
;
103 _cleanup_fclose_
FILE *file
= NULL
;
104 const char *dropin_dirname
;
113 file
= fopen(filename
, "re");
121 if (null_or_empty_fd(fileno(file
))) {
122 log_debug("Skipping empty file: %s", filename
);
126 fname
= strdup(filename
);
130 name
= strdup(basename(filename
));
134 d
= strrchr(name
, '.');
140 dropin_dirname
= strjoina(name
, ".network.d");
142 network
= new(Network
, 1);
146 *network
= (Network
) {
148 .filename
= TAKE_PTR(fname
),
149 .name
= TAKE_PTR(name
),
151 .required_for_online
= true,
152 .dhcp
= ADDRESS_FAMILY_NO
,
153 .dhcp_use_ntp
= true,
154 .dhcp_use_dns
= true,
155 .dhcp_use_hostname
= true,
156 .dhcp_use_routes
= true,
157 /* NOTE: this var might be overwriten by network_apply_anonymize_if_set */
158 .dhcp_send_hostname
= true,
159 /* To enable/disable RFC7844 Anonymity Profiles */
160 .dhcp_anonymize
= false,
161 .dhcp_route_metric
= DHCP_ROUTE_METRIC
,
162 /* NOTE: this var might be overwrite by network_apply_anonymize_if_set */
163 .dhcp_client_identifier
= DHCP_CLIENT_ID_DUID
,
164 .dhcp_route_table
= RT_TABLE_MAIN
,
165 .dhcp_route_table_set
= false,
166 /* NOTE: from man: UseMTU=... Defaults to false*/
167 .dhcp_use_mtu
= false,
168 /* NOTE: from man: UseTimezone=... Defaults to "no".*/
169 .dhcp_use_timezone
= false,
170 .rapid_commit
= true,
172 .dhcp_server_emit_dns
= true,
173 .dhcp_server_emit_ntp
= true,
174 .dhcp_server_emit_router
= true,
175 .dhcp_server_emit_timezone
= true,
177 .router_emit_dns
= true,
178 .router_emit_domains
= true,
183 .allow_port_to_be_root
= -1,
185 .multicast_to_unicast
= -1,
186 .priority
= LINK_BRIDGE_PORT_PRIORITY_INVALID
,
188 .lldp_mode
= LLDP_MODE_ROUTERS_ONLY
,
190 .dns_default_route
= -1,
191 .llmnr
= RESOLVE_SUPPORT_YES
,
192 .mdns
= RESOLVE_SUPPORT_NO
,
193 .dnssec_mode
= _DNSSEC_MODE_INVALID
,
194 .dns_over_tls_mode
= _DNS_OVER_TLS_MODE_INVALID
,
196 .link_local
= ADDRESS_FAMILY_IPV6
,
198 .ipv6_privacy_extensions
= IPV6_PRIVACY_EXTENSIONS_NO
,
199 .ipv6_accept_ra
= -1,
200 .ipv6_dad_transmits
= -1,
201 .ipv6_hop_limit
= -1,
202 .ipv6_proxy_ndp
= -1,
203 .duid
.type
= _DUID_TYPE_INVALID
,
208 .ipv6_accept_ra_use_dns
= true,
209 .ipv6_accept_ra_use_autonomous_prefix
= true,
210 .ipv6_accept_ra_use_onlink_prefix
= true,
211 .ipv6_accept_ra_route_table
= RT_TABLE_MAIN
,
212 .ipv6_accept_ra_route_table_set
= false,
215 r
= config_parse_many(filename
, network_dirs
, dropin_dirname
,
222 "RoutingPolicyRule\0"
225 "DHCPv4\0" /* compat */
228 "IPv6NDPProxyAddress\0"
232 "IPv6PrefixDelegation\0"
235 config_item_perf_lookup
, network_network_gperf_lookup
,
236 CONFIG_PARSE_WARN
, network
);
238 /* Unset manager here. Otherwise, LIST_REMOVE() in network_free() fails. */
239 network
->manager
= NULL
;
243 network_apply_anonymize_if_set(network
);
245 /* IPMasquerade=yes implies IPForward=yes */
246 if (network
->ip_masquerade
)
247 network
->ip_forward
|= ADDRESS_FAMILY_IPV4
;
249 if (network
->mtu
> 0 && network
->dhcp_use_mtu
) {
250 log_warning("MTUBytes= in [Link] section and UseMTU= in [DHCP] section are set in %s. "
251 "Disabling UseMTU=.", filename
);
252 network
->dhcp_use_mtu
= false;
255 LIST_PREPEND(networks
, manager
->networks
, network
);
257 r
= hashmap_ensure_allocated(&manager
->networks_by_name
, &string_hash_ops
);
261 r
= hashmap_put(manager
->networks_by_name
, network
->name
, network
);
265 LIST_FOREACH(routes
, route
, network
->static_routes
)
266 if (!route
->family
) {
267 log_warning("Route section without Gateway field configured in %s. "
268 "Ignoring", filename
);
272 LIST_FOREACH(addresses
, address
, network
->static_addresses
)
273 if (!address
->family
) {
274 log_warning("Address section without Address field configured in %s. "
275 "Ignoring", filename
);
284 int network_load(Manager
*manager
) {
286 _cleanup_strv_free_
char **files
= NULL
;
292 while ((network
= manager
->networks
))
293 network_free(network
);
295 r
= conf_files_list_strv(&files
, ".network", NULL
, 0, network_dirs
);
297 return log_error_errno(r
, "Failed to enumerate network files: %m");
299 STRV_FOREACH_BACKWARDS(f
, files
) {
300 r
= network_load_one(manager
, *f
);
308 void network_free(Network
*network
) {
309 IPv6ProxyNDPAddress
*ipv6_proxy_ndp_address
;
310 RoutingPolicyRule
*rule
;
321 free(network
->filename
);
323 set_free_free(network
->match_mac
);
324 strv_free(network
->match_path
);
325 strv_free(network
->match_driver
);
326 strv_free(network
->match_type
);
327 strv_free(network
->match_name
);
329 free(network
->description
);
330 free(network
->dhcp_vendor_class_identifier
);
331 strv_free(network
->dhcp_user_class
);
332 free(network
->dhcp_hostname
);
336 strv_free(network
->ntp
);
338 strv_free(network
->search_domains
);
339 strv_free(network
->route_domains
);
340 strv_free(network
->bind_carrier
);
342 strv_free(network
->router_search_domains
);
343 free(network
->router_dns
);
345 netdev_unref(network
->bridge
);
346 netdev_unref(network
->bond
);
347 netdev_unref(network
->vrf
);
349 hashmap_free_with_destructor(network
->stacked_netdevs
, netdev_unref
);
351 while ((route
= network
->static_routes
))
354 while ((address
= network
->static_addresses
))
355 address_free(address
);
357 while ((fdb_entry
= network
->static_fdb_entries
))
358 fdb_entry_free(fdb_entry
);
360 while ((ipv6_proxy_ndp_address
= network
->ipv6_proxy_ndp_addresses
))
361 ipv6_proxy_ndp_address_free(ipv6_proxy_ndp_address
);
363 while ((neighbor
= network
->neighbors
))
364 neighbor_free(neighbor
);
366 while ((label
= network
->address_labels
))
367 address_label_free(label
);
369 while ((prefix
= network
->static_prefixes
))
372 while ((rule
= network
->rules
))
373 routing_policy_rule_free(rule
);
375 hashmap_free(network
->addresses_by_section
);
376 hashmap_free(network
->routes_by_section
);
377 hashmap_free(network
->fdb_entries_by_section
);
378 hashmap_free(network
->neighbors_by_section
);
379 hashmap_free(network
->address_labels_by_section
);
380 hashmap_free(network
->prefixes_by_section
);
381 hashmap_free(network
->rules_by_section
);
383 if (network
->manager
) {
384 if (network
->manager
->networks
)
385 LIST_REMOVE(networks
, network
->manager
->networks
, network
);
387 if (network
->manager
->networks_by_name
&& network
->name
)
388 hashmap_remove(network
->manager
->networks_by_name
, network
->name
);
390 if (network
->manager
->duids_requesting_uuid
)
391 set_remove(network
->manager
->duids_requesting_uuid
, &network
->duid
);
396 condition_free_list(network
->match_host
);
397 condition_free_list(network
->match_virt
);
398 condition_free_list(network
->match_kernel_cmdline
);
399 condition_free_list(network
->match_kernel_version
);
400 condition_free_list(network
->match_arch
);
402 free(network
->dhcp_server_timezone
);
403 free(network
->dhcp_server_dns
);
404 free(network
->dhcp_server_ntp
);
406 set_free_free(network
->dnssec_negative_trust_anchors
);
411 int network_get_by_name(Manager
*manager
, const char *name
, Network
**ret
) {
418 network
= hashmap_get(manager
->networks_by_name
, name
);
427 int network_get(Manager
*manager
, sd_device
*device
,
428 const char *ifname
, const struct ether_addr
*address
,
430 const char *path
= NULL
, *parent_driver
= NULL
, *driver
= NULL
, *devtype
= NULL
;
438 (void) sd_device_get_property_value(device
, "ID_PATH", &path
);
440 if (sd_device_get_parent(device
, &parent
) >= 0)
441 (void) sd_device_get_driver(parent
, &parent_driver
);
443 (void) sd_device_get_property_value(device
, "ID_NET_DRIVER", &driver
);
445 (void) sd_device_get_devtype(device
, &devtype
);
448 LIST_FOREACH(networks
, network
, manager
->networks
) {
449 if (net_match_config(network
->match_mac
, network
->match_path
,
450 network
->match_driver
, network
->match_type
,
451 network
->match_name
, network
->match_host
,
452 network
->match_virt
, network
->match_kernel_cmdline
,
453 network
->match_kernel_version
, network
->match_arch
,
454 address
, path
, parent_driver
, driver
,
456 if (network
->match_name
&& device
) {
458 uint8_t name_assign_type
= NET_NAME_UNKNOWN
;
460 if (sd_device_get_sysattr_value(device
, "name_assign_type", &attr
) >= 0)
461 (void) safe_atou8(attr
, &name_assign_type
);
463 if (name_assign_type
== NET_NAME_ENUM
)
464 log_warning("%s: found matching network '%s', based on potentially unpredictable ifname",
465 ifname
, network
->filename
);
467 log_debug("%s: found matching network '%s'", ifname
, network
->filename
);
469 log_debug("%s: found matching network '%s'", ifname
, network
->filename
);
481 int network_apply(Network
*network
, Link
*link
) {
487 link
->network
= network
;
489 if (network
->ipv4ll_route
) {
492 r
= route_new_static(network
, NULL
, 0, &route
);
496 r
= inet_pton(AF_INET
, "169.254.0.0", &route
->dst
.in
);
502 route
->family
= AF_INET
;
503 route
->dst_prefixlen
= 16;
504 route
->scope
= RT_SCOPE_LINK
;
505 route
->priority
= IPV4LL_ROUTE_METRIC
;
506 route
->protocol
= RTPROT_STATIC
;
509 if (network
->n_dns
> 0 ||
510 !strv_isempty(network
->ntp
) ||
511 !strv_isempty(network
->search_domains
) ||
512 !strv_isempty(network
->route_domains
))
518 bool network_has_static_ipv6_addresses(Network
*network
) {
523 LIST_FOREACH(addresses
, address
, network
->static_addresses
) {
524 if (address
->family
== AF_INET6
)
531 int config_parse_netdev(const char *unit
,
532 const char *filename
,
535 unsigned section_line
,
541 Network
*network
= userdata
;
542 _cleanup_free_
char *kind_string
= NULL
;
553 kind_string
= strdup(lvalue
);
557 /* the keys are CamelCase versions of the kind */
558 for (p
= kind_string
; *p
; p
++)
561 kind
= netdev_kind_from_string(kind_string
);
562 if (kind
== _NETDEV_KIND_INVALID
) {
563 log_syntax(unit
, LOG_ERR
, filename
, line
, 0, "Invalid NetDev kind: %s", lvalue
);
567 r
= netdev_get(network
->manager
, rvalue
, &netdev
);
569 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "%s could not be found, ignoring assignment: %s", lvalue
, rvalue
);
573 if (netdev
->kind
!= kind
) {
574 log_syntax(unit
, LOG_ERR
, filename
, line
, 0, "NetDev is not a %s, ignoring assignment: %s", lvalue
, rvalue
);
579 case NETDEV_KIND_BRIDGE
:
580 network
->bridge
= netdev_unref(network
->bridge
);
581 network
->bridge
= netdev
;
584 case NETDEV_KIND_BOND
:
585 network
->bond
= netdev_unref(network
->bond
);
586 network
->bond
= netdev
;
589 case NETDEV_KIND_VRF
:
590 network
->vrf
= netdev_unref(network
->vrf
);
591 network
->vrf
= netdev
;
594 case NETDEV_KIND_VLAN
:
595 case NETDEV_KIND_MACVLAN
:
596 case NETDEV_KIND_MACVTAP
:
597 case NETDEV_KIND_IPVLAN
:
598 case NETDEV_KIND_VXLAN
:
599 case NETDEV_KIND_VCAN
:
600 r
= hashmap_ensure_allocated(&network
->stacked_netdevs
, &string_hash_ops
);
604 r
= hashmap_put(network
->stacked_netdevs
, netdev
->ifname
, netdev
);
606 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Cannot add NetDev '%s' to network: %m", rvalue
);
612 assert_not_reached("Cannot parse NetDev");
620 int config_parse_domains(
622 const char *filename
,
625 unsigned section_line
,
640 if (isempty(rvalue
)) {
641 n
->search_domains
= strv_free(n
->search_domains
);
642 n
->route_domains
= strv_free(n
->route_domains
);
648 _cleanup_free_
char *w
= NULL
, *normalized
= NULL
;
652 r
= extract_first_word(&p
, &w
, NULL
, 0);
654 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Failed to extract search or route domain, ignoring: %s", rvalue
);
660 is_route
= w
[0] == '~';
661 domain
= is_route
? w
+ 1 : w
;
663 if (dns_name_is_root(domain
) || streq(domain
, "*")) {
664 /* If the root domain appears as is, or the special token "*" is found, we'll consider this as
665 * routing domain, unconditionally. */
667 domain
= "."; /* make sure we don't allow empty strings, thus write the root domain as "." */
669 r
= dns_name_normalize(domain
, 0, &normalized
);
671 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "'%s' is not a valid domain name, ignoring.", domain
);
677 if (is_localhost(domain
)) {
678 log_syntax(unit
, LOG_ERR
, filename
, line
, 0, "'localhost' domain names may not be configure as search or route domains, ignoring assignment: %s", domain
);
684 r
= strv_extend(&n
->route_domains
, domain
);
686 r
= strv_extend(&n
->search_domains
, domain
);
691 strv_uniq(n
->route_domains
);
692 strv_uniq(n
->search_domains
);
697 int config_parse_tunnel(const char *unit
,
698 const char *filename
,
701 unsigned section_line
,
707 Network
*network
= userdata
;
716 r
= netdev_get(network
->manager
, rvalue
, &netdev
);
718 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Tunnel is invalid, ignoring assignment: %s", rvalue
);
722 if (!IN_SET(netdev
->kind
,
728 NETDEV_KIND_IP6GRETAP
,
731 NETDEV_KIND_IP6TNL
)) {
732 log_syntax(unit
, LOG_ERR
, filename
, line
, 0,
733 "NetDev is not a tunnel, ignoring assignment: %s", rvalue
);
737 r
= hashmap_ensure_allocated(&network
->stacked_netdevs
, &string_hash_ops
);
741 r
= hashmap_put(network
->stacked_netdevs
, netdev
->ifname
, netdev
);
743 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Cannot add VLAN '%s' to network, ignoring: %m", rvalue
);
752 int config_parse_ipv4ll(
754 const char *filename
,
757 unsigned section_line
,
764 AddressFamilyBoolean
*link_local
= data
;
771 /* Note that this is mostly like
772 * config_parse_address_family_boolean(), except that it
773 * applies only to IPv4 */
775 SET_FLAG(*link_local
, ADDRESS_FAMILY_IPV4
, parse_boolean(rvalue
));
780 int config_parse_dhcp(
782 const char *filename
,
785 unsigned section_line
,
792 AddressFamilyBoolean
*dhcp
= data
, s
;
799 /* Note that this is mostly like
800 * config_parse_address_family_boolean(), except that it
801 * understands some old names for the enum values */
803 s
= address_family_boolean_from_string(rvalue
);
806 /* Previously, we had a slightly different enum here,
807 * support its values for compatbility. */
809 if (streq(rvalue
, "none"))
810 s
= ADDRESS_FAMILY_NO
;
811 else if (streq(rvalue
, "v4"))
812 s
= ADDRESS_FAMILY_IPV4
;
813 else if (streq(rvalue
, "v6"))
814 s
= ADDRESS_FAMILY_IPV6
;
815 else if (streq(rvalue
, "both"))
816 s
= ADDRESS_FAMILY_YES
;
818 log_syntax(unit
, LOG_ERR
, filename
, line
, 0, "Failed to parse DHCP option, ignoring: %s", rvalue
);
827 static const char* const dhcp_client_identifier_table
[_DHCP_CLIENT_ID_MAX
] = {
828 [DHCP_CLIENT_ID_MAC
] = "mac",
829 [DHCP_CLIENT_ID_DUID
] = "duid",
830 [DHCP_CLIENT_ID_DUID_ONLY
] = "duid-only",
833 DEFINE_PRIVATE_STRING_TABLE_LOOKUP_FROM_STRING(dhcp_client_identifier
, DHCPClientIdentifier
);
834 DEFINE_CONFIG_PARSE_ENUM(config_parse_dhcp_client_identifier
, dhcp_client_identifier
, DHCPClientIdentifier
, "Failed to parse client identifier type");
836 int config_parse_ipv6token(
838 const char *filename
,
841 unsigned section_line
,
848 union in_addr_union buffer
;
849 struct in6_addr
*token
= data
;
857 r
= in_addr_from_string(AF_INET6
, rvalue
, &buffer
);
859 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Failed to parse IPv6 token, ignoring: %s", rvalue
);
863 if (in_addr_is_null(AF_INET6
, &buffer
)) {
864 log_syntax(unit
, LOG_ERR
, filename
, line
, 0, "IPv6 token cannot be the ANY address, ignoring: %s", rvalue
);
868 if ((buffer
.in6
.s6_addr32
[0] | buffer
.in6
.s6_addr32
[1]) != 0) {
869 log_syntax(unit
, LOG_ERR
, filename
, line
, 0, "IPv6 token cannot be longer than 64 bits, ignoring: %s", rvalue
);
878 static const char* const ipv6_privacy_extensions_table
[_IPV6_PRIVACY_EXTENSIONS_MAX
] = {
879 [IPV6_PRIVACY_EXTENSIONS_NO
] = "no",
880 [IPV6_PRIVACY_EXTENSIONS_PREFER_PUBLIC
] = "prefer-public",
881 [IPV6_PRIVACY_EXTENSIONS_YES
] = "yes",
884 DEFINE_STRING_TABLE_LOOKUP(ipv6_privacy_extensions
, IPv6PrivacyExtensions
);
886 int config_parse_ipv6_privacy_extensions(
888 const char *filename
,
891 unsigned section_line
,
898 IPv6PrivacyExtensions
*ipv6_privacy_extensions
= data
;
904 assert(ipv6_privacy_extensions
);
906 /* Our enum shall be a superset of booleans, hence first try
907 * to parse as boolean, and then as enum */
909 k
= parse_boolean(rvalue
);
911 *ipv6_privacy_extensions
= IPV6_PRIVACY_EXTENSIONS_YES
;
913 *ipv6_privacy_extensions
= IPV6_PRIVACY_EXTENSIONS_NO
;
915 IPv6PrivacyExtensions s
;
917 s
= ipv6_privacy_extensions_from_string(rvalue
);
920 if (streq(rvalue
, "kernel"))
921 s
= _IPV6_PRIVACY_EXTENSIONS_INVALID
;
923 log_syntax(unit
, LOG_ERR
, filename
, line
, 0, "Failed to parse IPv6 privacy extensions option, ignoring: %s", rvalue
);
928 *ipv6_privacy_extensions
= s
;
934 int config_parse_hostname(
936 const char *filename
,
939 unsigned section_line
,
946 _cleanup_free_
char *hn
= NULL
;
947 char **hostname
= data
;
954 r
= config_parse_string(unit
, filename
, line
, section
, section_line
, lvalue
, ltype
, rvalue
, &hn
, userdata
);
958 if (!hostname_is_valid(hn
, false)) {
959 log_syntax(unit
, LOG_ERR
, filename
, line
, 0, "Hostname is not valid, ignoring assignment: %s", rvalue
);
963 r
= dns_name_is_valid(hn
);
965 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Failed to check validity of hostname '%s', ignoring assignment: %m", rvalue
);
969 log_syntax(unit
, LOG_ERR
, filename
, line
, 0, "Hostname is not a valid DNS domain name, ignoring assignment: %s", rvalue
);
973 return free_and_replace(*hostname
, hn
);
976 int config_parse_timezone(
978 const char *filename
,
981 unsigned section_line
,
988 _cleanup_free_
char *tz
= NULL
;
996 r
= config_parse_string(unit
, filename
, line
, section
, section_line
, lvalue
, ltype
, rvalue
, &tz
, userdata
);
1000 if (!timezone_is_valid(tz
, LOG_ERR
)) {
1001 log_syntax(unit
, LOG_ERR
, filename
, line
, 0, "Timezone is not valid, ignoring assignment: %s", rvalue
);
1005 return free_and_replace(*datap
, tz
);
1008 int config_parse_dhcp_server_dns(
1010 const char *filename
,
1012 const char *section
,
1013 unsigned section_line
,
1021 const char *p
= rvalue
;
1029 _cleanup_free_
char *w
= NULL
;
1030 struct in_addr a
, *m
;
1032 r
= extract_first_word(&p
, &w
, NULL
, 0);
1036 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Failed to extract word, ignoring: %s", rvalue
);
1042 if (inet_pton(AF_INET
, w
, &a
) <= 0) {
1043 log_syntax(unit
, LOG_ERR
, filename
, line
, 0, "Failed to parse DNS server address, ignoring: %s", w
);
1047 m
= reallocarray(n
->dhcp_server_dns
, n
->n_dhcp_server_dns
+ 1, sizeof(struct in_addr
));
1051 m
[n
->n_dhcp_server_dns
++] = a
;
1052 n
->dhcp_server_dns
= m
;
1058 int config_parse_radv_dns(
1060 const char *filename
,
1062 const char *section
,
1063 unsigned section_line
,
1071 const char *p
= rvalue
;
1079 _cleanup_free_
char *w
= NULL
;
1080 union in_addr_union a
;
1082 r
= extract_first_word(&p
, &w
, NULL
, 0);
1086 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Failed to extract word, ignoring: %s", rvalue
);
1092 if (in_addr_from_string(AF_INET6
, w
, &a
) >= 0) {
1095 m
= reallocarray(n
->router_dns
, n
->n_router_dns
+ 1, sizeof(struct in6_addr
));
1099 m
[n
->n_router_dns
++] = a
.in6
;
1103 log_syntax(unit
, LOG_ERR
, filename
, line
, 0, "Failed to parse DNS server address, ignoring: %s", w
);
1110 int config_parse_radv_search_domains(
1112 const char *filename
,
1114 const char *section
,
1115 unsigned section_line
,
1123 const char *p
= rvalue
;
1131 _cleanup_free_
char *w
= NULL
, *idna
= NULL
;
1133 r
= extract_first_word(&p
, &w
, NULL
, 0);
1137 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Failed to extract word, ignoring: %s", rvalue
);
1143 r
= dns_name_apply_idna(w
, &idna
);
1145 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Failed to apply IDNA to domain name '%s', ignoring: %m", w
);
1149 r
= strv_push(&n
->router_search_domains
, idna
);
1153 r
= strv_push(&n
->router_search_domains
, w
);
1162 int config_parse_dhcp_server_ntp(
1164 const char *filename
,
1166 const char *section
,
1167 unsigned section_line
,
1175 const char *p
= rvalue
;
1183 _cleanup_free_
char *w
= NULL
;
1184 struct in_addr a
, *m
;
1186 r
= extract_first_word(&p
, &w
, NULL
, 0);
1190 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Failed to extract word, ignoring: %s", rvalue
);
1196 if (inet_pton(AF_INET
, w
, &a
) <= 0) {
1197 log_syntax(unit
, LOG_ERR
, filename
, line
, 0, "Failed to parse NTP server address, ignoring: %s", w
);
1201 m
= reallocarray(n
->dhcp_server_ntp
, n
->n_dhcp_server_ntp
+ 1, sizeof(struct in_addr
));
1205 m
[n
->n_dhcp_server_ntp
++] = a
;
1206 n
->dhcp_server_ntp
= m
;
1210 int config_parse_dns(
1212 const char *filename
,
1214 const char *section
,
1215 unsigned section_line
,
1222 Network
*n
= userdata
;
1230 _cleanup_free_
char *w
= NULL
;
1231 union in_addr_union a
;
1232 struct in_addr_data
*m
;
1235 r
= extract_first_word(&rvalue
, &w
, NULL
, 0);
1239 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Invalid syntax, ignoring: %s", rvalue
);
1245 r
= in_addr_from_string_auto(w
, &family
, &a
);
1247 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Failed to parse dns server address, ignoring: %s", w
);
1251 m
= reallocarray(n
->dns
, n
->n_dns
+ 1, sizeof(struct in_addr_data
));
1255 m
[n
->n_dns
++] = (struct in_addr_data
) {
1266 int config_parse_dnssec_negative_trust_anchors(
1268 const char *filename
,
1270 const char *section
,
1271 unsigned section_line
,
1278 const char *p
= rvalue
;
1286 if (isempty(rvalue
)) {
1287 n
->dnssec_negative_trust_anchors
= set_free_free(n
->dnssec_negative_trust_anchors
);
1292 _cleanup_free_
char *w
= NULL
;
1294 r
= extract_first_word(&p
, &w
, NULL
, 0);
1296 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Failed to extract negative trust anchor domain, ignoring: %s", rvalue
);
1302 r
= dns_name_is_valid(w
);
1304 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "%s is not a valid domain name, ignoring.", w
);
1308 r
= set_ensure_allocated(&n
->dnssec_negative_trust_anchors
, &dns_name_hash_ops
);
1312 r
= set_put(n
->dnssec_negative_trust_anchors
, w
);
1322 int config_parse_ntp(
1324 const char *filename
,
1326 const char *section
,
1327 unsigned section_line
,
1341 if (isempty(rvalue
)) {
1347 _cleanup_free_
char *w
= NULL
;
1349 r
= extract_first_word(&rvalue
, &w
, NULL
, 0);
1353 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Failed to extract NTP server name, ignoring: %s", rvalue
);
1359 r
= dns_name_is_valid_or_address(w
);
1361 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "%s is not a valid domain name or IP address, ignoring.", w
);
1365 r
= strv_push(l
, w
);
1375 int config_parse_dhcp_user_class(
1377 const char *filename
,
1379 const char *section
,
1380 unsigned section_line
,
1394 if (isempty(rvalue
)) {
1400 _cleanup_free_
char *w
= NULL
;
1402 r
= extract_first_word(&rvalue
, &w
, NULL
, 0);
1406 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Failed to split user classes option, ignoring: %s", rvalue
);
1412 if (strlen(w
) > 255) {
1413 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "%s length is not in the range 1-255, ignoring.", w
);
1417 r
= strv_push(l
, w
);
1427 int config_parse_section_route_table(
1429 const char *filename
,
1431 const char *section
,
1432 unsigned section_line
,
1439 Network
*network
= data
;
1448 r
= safe_atou32(rvalue
, &rt
);
1450 log_syntax(unit
, LOG_ERR
, filename
, line
, r
,
1451 "Failed to parse RouteTable=%s, ignoring assignment: %m", rvalue
);
1455 if (streq_ptr(section
, "DHCP")) {
1456 network
->dhcp_route_table
= rt
;
1457 network
->dhcp_route_table_set
= true;
1458 } else { /* section is IPv6AcceptRA */
1459 network
->ipv6_accept_ra_route_table
= rt
;
1460 network
->ipv6_accept_ra_route_table_set
= true;
1466 DEFINE_CONFIG_PARSE_ENUM(config_parse_dhcp_use_domains
, dhcp_use_domains
, DHCPUseDomains
, "Failed to parse DHCP use domains setting");
1468 static const char* const dhcp_use_domains_table
[_DHCP_USE_DOMAINS_MAX
] = {
1469 [DHCP_USE_DOMAINS_NO
] = "no",
1470 [DHCP_USE_DOMAINS_ROUTE
] = "route",
1471 [DHCP_USE_DOMAINS_YES
] = "yes",
1474 DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(dhcp_use_domains
, DHCPUseDomains
, DHCP_USE_DOMAINS_YES
);
1476 DEFINE_CONFIG_PARSE_ENUM(config_parse_lldp_mode
, lldp_mode
, LLDPMode
, "Failed to parse LLDP= setting.");
1478 static const char* const lldp_mode_table
[_LLDP_MODE_MAX
] = {
1479 [LLDP_MODE_NO
] = "no",
1480 [LLDP_MODE_YES
] = "yes",
1481 [LLDP_MODE_ROUTERS_ONLY
] = "routers-only",
1484 DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(lldp_mode
, LLDPMode
, LLDP_MODE_YES
);
1486 int config_parse_iaid(const char *unit
,
1487 const char *filename
,
1489 const char *section
,
1490 unsigned section_line
,
1496 Network
*network
= data
;
1505 r
= safe_atou32(rvalue
, &iaid
);
1507 log_syntax(unit
, LOG_ERR
, filename
, line
, r
,
1508 "Unable to read IAID, ignoring assignment: %s", rvalue
);
1512 network
->iaid
= iaid
;
1513 network
->iaid_set
= true;