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
,
214 r
= config_parse_many(filename
, network_dirs
, dropin_dirname
,
221 "RoutingPolicyRule\0"
224 "DHCPv4\0" /* compat */
227 "IPv6NDPProxyAddress\0"
231 "IPv6PrefixDelegation\0"
234 config_item_perf_lookup
, network_network_gperf_lookup
,
235 CONFIG_PARSE_WARN
, network
);
237 /* Unset manager here. Otherwise, LIST_REMOVE() in network_free() fails. */
238 network
->manager
= NULL
;
242 network_apply_anonymize_if_set(network
);
244 /* IPMasquerade=yes implies IPForward=yes */
245 if (network
->ip_masquerade
)
246 network
->ip_forward
|= ADDRESS_FAMILY_IPV4
;
248 if (network
->mtu
> 0 && network
->dhcp_use_mtu
) {
249 log_warning("MTUBytes= in [Link] section and UseMTU= in [DHCP] section are set in %s. "
250 "Disabling UseMTU=.", filename
);
251 network
->dhcp_use_mtu
= false;
254 LIST_PREPEND(networks
, manager
->networks
, network
);
256 r
= hashmap_ensure_allocated(&manager
->networks_by_name
, &string_hash_ops
);
260 r
= hashmap_put(manager
->networks_by_name
, network
->name
, network
);
264 LIST_FOREACH(routes
, route
, network
->static_routes
)
265 if (!route
->family
) {
266 log_warning("Route section without Gateway field configured in %s. "
267 "Ignoring", filename
);
271 LIST_FOREACH(addresses
, address
, network
->static_addresses
)
272 if (!address
->family
) {
273 log_warning("Address section without Address field configured in %s. "
274 "Ignoring", filename
);
283 int network_load(Manager
*manager
) {
285 _cleanup_strv_free_
char **files
= NULL
;
291 while ((network
= manager
->networks
))
292 network_free(network
);
294 r
= conf_files_list_strv(&files
, ".network", NULL
, 0, network_dirs
);
296 return log_error_errno(r
, "Failed to enumerate network files: %m");
298 STRV_FOREACH_BACKWARDS(f
, files
) {
299 r
= network_load_one(manager
, *f
);
307 void network_free(Network
*network
) {
308 IPv6ProxyNDPAddress
*ipv6_proxy_ndp_address
;
309 RoutingPolicyRule
*rule
;
320 free(network
->filename
);
322 set_free_free(network
->match_mac
);
323 strv_free(network
->match_path
);
324 strv_free(network
->match_driver
);
325 strv_free(network
->match_type
);
326 strv_free(network
->match_name
);
328 free(network
->description
);
329 free(network
->dhcp_vendor_class_identifier
);
330 strv_free(network
->dhcp_user_class
);
331 free(network
->dhcp_hostname
);
335 strv_free(network
->ntp
);
337 strv_free(network
->search_domains
);
338 strv_free(network
->route_domains
);
339 strv_free(network
->bind_carrier
);
341 strv_free(network
->router_search_domains
);
342 free(network
->router_dns
);
344 netdev_unref(network
->bridge
);
345 netdev_unref(network
->bond
);
346 netdev_unref(network
->vrf
);
348 hashmap_free_with_destructor(network
->stacked_netdevs
, netdev_unref
);
350 while ((route
= network
->static_routes
))
353 while ((address
= network
->static_addresses
))
354 address_free(address
);
356 while ((fdb_entry
= network
->static_fdb_entries
))
357 fdb_entry_free(fdb_entry
);
359 while ((ipv6_proxy_ndp_address
= network
->ipv6_proxy_ndp_addresses
))
360 ipv6_proxy_ndp_address_free(ipv6_proxy_ndp_address
);
362 while ((neighbor
= network
->neighbors
))
363 neighbor_free(neighbor
);
365 while ((label
= network
->address_labels
))
366 address_label_free(label
);
368 while ((prefix
= network
->static_prefixes
))
371 while ((rule
= network
->rules
))
372 routing_policy_rule_free(rule
);
374 hashmap_free(network
->addresses_by_section
);
375 hashmap_free(network
->routes_by_section
);
376 hashmap_free(network
->fdb_entries_by_section
);
377 hashmap_free(network
->neighbors_by_section
);
378 hashmap_free(network
->address_labels_by_section
);
379 hashmap_free(network
->prefixes_by_section
);
380 hashmap_free(network
->rules_by_section
);
382 if (network
->manager
) {
383 if (network
->manager
->networks
)
384 LIST_REMOVE(networks
, network
->manager
->networks
, network
);
386 if (network
->manager
->networks_by_name
&& network
->name
)
387 hashmap_remove(network
->manager
->networks_by_name
, network
->name
);
389 if (network
->manager
->duids_requesting_uuid
)
390 set_remove(network
->manager
->duids_requesting_uuid
, &network
->duid
);
395 condition_free_list(network
->match_host
);
396 condition_free_list(network
->match_virt
);
397 condition_free_list(network
->match_kernel_cmdline
);
398 condition_free_list(network
->match_kernel_version
);
399 condition_free_list(network
->match_arch
);
401 free(network
->dhcp_server_timezone
);
402 free(network
->dhcp_server_dns
);
403 free(network
->dhcp_server_ntp
);
405 set_free_free(network
->dnssec_negative_trust_anchors
);
410 int network_get_by_name(Manager
*manager
, const char *name
, Network
**ret
) {
417 network
= hashmap_get(manager
->networks_by_name
, name
);
426 int network_get(Manager
*manager
, sd_device
*device
,
427 const char *ifname
, const struct ether_addr
*address
,
429 const char *path
= NULL
, *parent_driver
= NULL
, *driver
= NULL
, *devtype
= NULL
;
437 (void) sd_device_get_property_value(device
, "ID_PATH", &path
);
439 if (sd_device_get_parent(device
, &parent
) >= 0)
440 (void) sd_device_get_driver(parent
, &parent_driver
);
442 (void) sd_device_get_property_value(device
, "ID_NET_DRIVER", &driver
);
444 (void) sd_device_get_devtype(device
, &devtype
);
447 LIST_FOREACH(networks
, network
, manager
->networks
) {
448 if (net_match_config(network
->match_mac
, network
->match_path
,
449 network
->match_driver
, network
->match_type
,
450 network
->match_name
, network
->match_host
,
451 network
->match_virt
, network
->match_kernel_cmdline
,
452 network
->match_kernel_version
, network
->match_arch
,
453 address
, path
, parent_driver
, driver
,
455 if (network
->match_name
&& device
) {
457 uint8_t name_assign_type
= NET_NAME_UNKNOWN
;
459 if (sd_device_get_sysattr_value(device
, "name_assign_type", &attr
) >= 0)
460 (void) safe_atou8(attr
, &name_assign_type
);
462 if (name_assign_type
== NET_NAME_ENUM
)
463 log_warning("%s: found matching network '%s', based on potentially unpredictable ifname",
464 ifname
, network
->filename
);
466 log_debug("%s: found matching network '%s'", ifname
, network
->filename
);
468 log_debug("%s: found matching network '%s'", ifname
, network
->filename
);
480 int network_apply(Network
*network
, Link
*link
) {
486 link
->network
= network
;
488 if (network
->ipv4ll_route
) {
491 r
= route_new_static(network
, NULL
, 0, &route
);
495 r
= inet_pton(AF_INET
, "169.254.0.0", &route
->dst
.in
);
501 route
->family
= AF_INET
;
502 route
->dst_prefixlen
= 16;
503 route
->scope
= RT_SCOPE_LINK
;
504 route
->priority
= IPV4LL_ROUTE_METRIC
;
505 route
->protocol
= RTPROT_STATIC
;
508 if (network
->n_dns
> 0 ||
509 !strv_isempty(network
->ntp
) ||
510 !strv_isempty(network
->search_domains
) ||
511 !strv_isempty(network
->route_domains
))
517 bool network_has_static_ipv6_addresses(Network
*network
) {
522 LIST_FOREACH(addresses
, address
, network
->static_addresses
) {
523 if (address
->family
== AF_INET6
)
530 int config_parse_netdev(const char *unit
,
531 const char *filename
,
534 unsigned section_line
,
540 Network
*network
= userdata
;
541 _cleanup_free_
char *kind_string
= NULL
;
552 kind_string
= strdup(lvalue
);
556 /* the keys are CamelCase versions of the kind */
557 for (p
= kind_string
; *p
; p
++)
560 kind
= netdev_kind_from_string(kind_string
);
561 if (kind
== _NETDEV_KIND_INVALID
) {
562 log_syntax(unit
, LOG_ERR
, filename
, line
, 0, "Invalid NetDev kind: %s", lvalue
);
566 r
= netdev_get(network
->manager
, rvalue
, &netdev
);
568 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "%s could not be found, ignoring assignment: %s", lvalue
, rvalue
);
572 if (netdev
->kind
!= kind
) {
573 log_syntax(unit
, LOG_ERR
, filename
, line
, 0, "NetDev is not a %s, ignoring assignment: %s", lvalue
, rvalue
);
578 case NETDEV_KIND_BRIDGE
:
579 network
->bridge
= netdev_unref(network
->bridge
);
580 network
->bridge
= netdev
;
583 case NETDEV_KIND_BOND
:
584 network
->bond
= netdev_unref(network
->bond
);
585 network
->bond
= netdev
;
588 case NETDEV_KIND_VRF
:
589 network
->vrf
= netdev_unref(network
->vrf
);
590 network
->vrf
= netdev
;
593 case NETDEV_KIND_VLAN
:
594 case NETDEV_KIND_MACVLAN
:
595 case NETDEV_KIND_MACVTAP
:
596 case NETDEV_KIND_IPVLAN
:
597 case NETDEV_KIND_VXLAN
:
598 case NETDEV_KIND_VCAN
:
599 r
= hashmap_ensure_allocated(&network
->stacked_netdevs
, &string_hash_ops
);
603 r
= hashmap_put(network
->stacked_netdevs
, netdev
->ifname
, netdev
);
605 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Cannot add NetDev '%s' to network: %m", rvalue
);
611 assert_not_reached("Cannot parse NetDev");
619 int config_parse_domains(
621 const char *filename
,
624 unsigned section_line
,
639 if (isempty(rvalue
)) {
640 n
->search_domains
= strv_free(n
->search_domains
);
641 n
->route_domains
= strv_free(n
->route_domains
);
647 _cleanup_free_
char *w
= NULL
, *normalized
= NULL
;
651 r
= extract_first_word(&p
, &w
, NULL
, 0);
653 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Failed to extract search or route domain, ignoring: %s", rvalue
);
659 is_route
= w
[0] == '~';
660 domain
= is_route
? w
+ 1 : w
;
662 if (dns_name_is_root(domain
) || streq(domain
, "*")) {
663 /* If the root domain appears as is, or the special token "*" is found, we'll consider this as
664 * routing domain, unconditionally. */
666 domain
= "."; /* make sure we don't allow empty strings, thus write the root domain as "." */
668 r
= dns_name_normalize(domain
, 0, &normalized
);
670 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "'%s' is not a valid domain name, ignoring.", domain
);
676 if (is_localhost(domain
)) {
677 log_syntax(unit
, LOG_ERR
, filename
, line
, 0, "'localhost' domain names may not be configure as search or route domains, ignoring assignment: %s", domain
);
683 r
= strv_extend(&n
->route_domains
, domain
);
685 r
= strv_extend(&n
->search_domains
, domain
);
690 strv_uniq(n
->route_domains
);
691 strv_uniq(n
->search_domains
);
696 int config_parse_tunnel(const char *unit
,
697 const char *filename
,
700 unsigned section_line
,
706 Network
*network
= userdata
;
715 r
= netdev_get(network
->manager
, rvalue
, &netdev
);
717 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Tunnel is invalid, ignoring assignment: %s", rvalue
);
721 if (!IN_SET(netdev
->kind
,
727 NETDEV_KIND_IP6GRETAP
,
730 NETDEV_KIND_IP6TNL
)) {
731 log_syntax(unit
, LOG_ERR
, filename
, line
, 0,
732 "NetDev is not a tunnel, ignoring assignment: %s", rvalue
);
736 r
= hashmap_ensure_allocated(&network
->stacked_netdevs
, &string_hash_ops
);
740 r
= hashmap_put(network
->stacked_netdevs
, netdev
->ifname
, netdev
);
742 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Cannot add VLAN '%s' to network, ignoring: %m", rvalue
);
751 int config_parse_ipv4ll(
753 const char *filename
,
756 unsigned section_line
,
763 AddressFamilyBoolean
*link_local
= data
;
770 /* Note that this is mostly like
771 * config_parse_address_family_boolean(), except that it
772 * applies only to IPv4 */
774 SET_FLAG(*link_local
, ADDRESS_FAMILY_IPV4
, parse_boolean(rvalue
));
779 int config_parse_dhcp(
781 const char *filename
,
784 unsigned section_line
,
791 AddressFamilyBoolean
*dhcp
= data
, s
;
798 /* Note that this is mostly like
799 * config_parse_address_family_boolean(), except that it
800 * understands some old names for the enum values */
802 s
= address_family_boolean_from_string(rvalue
);
805 /* Previously, we had a slightly different enum here,
806 * support its values for compatbility. */
808 if (streq(rvalue
, "none"))
809 s
= ADDRESS_FAMILY_NO
;
810 else if (streq(rvalue
, "v4"))
811 s
= ADDRESS_FAMILY_IPV4
;
812 else if (streq(rvalue
, "v6"))
813 s
= ADDRESS_FAMILY_IPV6
;
814 else if (streq(rvalue
, "both"))
815 s
= ADDRESS_FAMILY_YES
;
817 log_syntax(unit
, LOG_ERR
, filename
, line
, 0, "Failed to parse DHCP option, ignoring: %s", rvalue
);
826 static const char* const dhcp_client_identifier_table
[_DHCP_CLIENT_ID_MAX
] = {
827 [DHCP_CLIENT_ID_MAC
] = "mac",
828 [DHCP_CLIENT_ID_DUID
] = "duid",
829 [DHCP_CLIENT_ID_DUID_ONLY
] = "duid-only",
832 DEFINE_PRIVATE_STRING_TABLE_LOOKUP_FROM_STRING(dhcp_client_identifier
, DHCPClientIdentifier
);
833 DEFINE_CONFIG_PARSE_ENUM(config_parse_dhcp_client_identifier
, dhcp_client_identifier
, DHCPClientIdentifier
, "Failed to parse client identifier type");
835 int config_parse_ipv6token(
837 const char *filename
,
840 unsigned section_line
,
847 union in_addr_union buffer
;
848 struct in6_addr
*token
= data
;
856 r
= in_addr_from_string(AF_INET6
, rvalue
, &buffer
);
858 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Failed to parse IPv6 token, ignoring: %s", rvalue
);
862 r
= in_addr_is_null(AF_INET6
, &buffer
);
864 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "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_dhcp_route_table(const char *unit
,
1428 const char *filename
,
1430 const char *section
,
1431 unsigned section_line
,
1437 Network
*network
= data
;
1446 r
= safe_atou32(rvalue
, &rt
);
1448 log_syntax(unit
, LOG_ERR
, filename
, line
, r
,
1449 "Unable to read RouteTable, ignoring assignment: %s", rvalue
);
1453 network
->dhcp_route_table
= rt
;
1454 network
->dhcp_route_table_set
= true;
1459 DEFINE_CONFIG_PARSE_ENUM(config_parse_dhcp_use_domains
, dhcp_use_domains
, DHCPUseDomains
, "Failed to parse DHCP use domains setting");
1461 static const char* const dhcp_use_domains_table
[_DHCP_USE_DOMAINS_MAX
] = {
1462 [DHCP_USE_DOMAINS_NO
] = "no",
1463 [DHCP_USE_DOMAINS_ROUTE
] = "route",
1464 [DHCP_USE_DOMAINS_YES
] = "yes",
1467 DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(dhcp_use_domains
, DHCPUseDomains
, DHCP_USE_DOMAINS_YES
);
1469 DEFINE_CONFIG_PARSE_ENUM(config_parse_lldp_mode
, lldp_mode
, LLDPMode
, "Failed to parse LLDP= setting.");
1471 static const char* const lldp_mode_table
[_LLDP_MODE_MAX
] = {
1472 [LLDP_MODE_NO
] = "no",
1473 [LLDP_MODE_YES
] = "yes",
1474 [LLDP_MODE_ROUTERS_ONLY
] = "routers-only",
1477 DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(lldp_mode
, LLDPMode
, LLDP_MODE_YES
);
1479 int config_parse_iaid(const char *unit
,
1480 const char *filename
,
1482 const char *section
,
1483 unsigned section_line
,
1489 Network
*network
= data
;
1498 r
= safe_atou32(rvalue
, &iaid
);
1500 log_syntax(unit
, LOG_ERR
, filename
, line
, r
,
1501 "Unable to read IAID, ignoring assignment: %s", rvalue
);
1505 network
->iaid
= iaid
;
1506 network
->iaid_set
= true;