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_route_table
= RT_TABLE_MAIN
,
212 r
= config_parse_many(filename
, network_dirs
, dropin_dirname
,
219 "RoutingPolicyRule\0"
222 "DHCPv4\0" /* compat */
225 "IPv6NDPProxyAddress\0"
229 "IPv6PrefixDelegation\0"
232 config_item_perf_lookup
, network_network_gperf_lookup
,
233 CONFIG_PARSE_WARN
, network
);
235 /* Unset manager here. Otherwise, LIST_REMOVE() in network_free() fails. */
236 network
->manager
= NULL
;
240 network_apply_anonymize_if_set(network
);
242 /* IPMasquerade=yes implies IPForward=yes */
243 if (network
->ip_masquerade
)
244 network
->ip_forward
|= ADDRESS_FAMILY_IPV4
;
246 if (network
->mtu
> 0 && network
->dhcp_use_mtu
) {
247 log_warning("MTUBytes= in [Link] section and UseMTU= in [DHCP] section are set in %s. "
248 "Disabling UseMTU=.", filename
);
249 network
->dhcp_use_mtu
= false;
252 LIST_PREPEND(networks
, manager
->networks
, network
);
254 r
= hashmap_ensure_allocated(&manager
->networks_by_name
, &string_hash_ops
);
258 r
= hashmap_put(manager
->networks_by_name
, network
->name
, network
);
262 LIST_FOREACH(routes
, route
, network
->static_routes
)
263 if (!route
->family
) {
264 log_warning("Route section without Gateway field configured in %s. "
265 "Ignoring", filename
);
269 LIST_FOREACH(addresses
, address
, network
->static_addresses
)
270 if (!address
->family
) {
271 log_warning("Address section without Address field configured in %s. "
272 "Ignoring", filename
);
281 int network_load(Manager
*manager
) {
283 _cleanup_strv_free_
char **files
= NULL
;
289 while ((network
= manager
->networks
))
290 network_free(network
);
292 r
= conf_files_list_strv(&files
, ".network", NULL
, 0, network_dirs
);
294 return log_error_errno(r
, "Failed to enumerate network files: %m");
296 STRV_FOREACH_BACKWARDS(f
, files
) {
297 r
= network_load_one(manager
, *f
);
305 void network_free(Network
*network
) {
306 IPv6ProxyNDPAddress
*ipv6_proxy_ndp_address
;
307 RoutingPolicyRule
*rule
;
318 free(network
->filename
);
320 set_free_free(network
->match_mac
);
321 strv_free(network
->match_path
);
322 strv_free(network
->match_driver
);
323 strv_free(network
->match_type
);
324 strv_free(network
->match_name
);
326 free(network
->description
);
327 free(network
->dhcp_vendor_class_identifier
);
328 strv_free(network
->dhcp_user_class
);
329 free(network
->dhcp_hostname
);
333 strv_free(network
->ntp
);
335 strv_free(network
->search_domains
);
336 strv_free(network
->route_domains
);
337 strv_free(network
->bind_carrier
);
339 strv_free(network
->router_search_domains
);
340 free(network
->router_dns
);
342 netdev_unref(network
->bridge
);
343 netdev_unref(network
->bond
);
344 netdev_unref(network
->vrf
);
346 hashmap_free_with_destructor(network
->stacked_netdevs
, netdev_unref
);
348 while ((route
= network
->static_routes
))
351 while ((address
= network
->static_addresses
))
352 address_free(address
);
354 while ((fdb_entry
= network
->static_fdb_entries
))
355 fdb_entry_free(fdb_entry
);
357 while ((ipv6_proxy_ndp_address
= network
->ipv6_proxy_ndp_addresses
))
358 ipv6_proxy_ndp_address_free(ipv6_proxy_ndp_address
);
360 while ((neighbor
= network
->neighbors
))
361 neighbor_free(neighbor
);
363 while ((label
= network
->address_labels
))
364 address_label_free(label
);
366 while ((prefix
= network
->static_prefixes
))
369 while ((rule
= network
->rules
))
370 routing_policy_rule_free(rule
);
372 hashmap_free(network
->addresses_by_section
);
373 hashmap_free(network
->routes_by_section
);
374 hashmap_free(network
->fdb_entries_by_section
);
375 hashmap_free(network
->neighbors_by_section
);
376 hashmap_free(network
->address_labels_by_section
);
377 hashmap_free(network
->prefixes_by_section
);
378 hashmap_free(network
->rules_by_section
);
380 if (network
->manager
) {
381 if (network
->manager
->networks
)
382 LIST_REMOVE(networks
, network
->manager
->networks
, network
);
384 if (network
->manager
->networks_by_name
&& network
->name
)
385 hashmap_remove(network
->manager
->networks_by_name
, network
->name
);
387 if (network
->manager
->duids_requesting_uuid
)
388 set_remove(network
->manager
->duids_requesting_uuid
, &network
->duid
);
393 condition_free_list(network
->match_host
);
394 condition_free_list(network
->match_virt
);
395 condition_free_list(network
->match_kernel_cmdline
);
396 condition_free_list(network
->match_kernel_version
);
397 condition_free_list(network
->match_arch
);
399 free(network
->dhcp_server_timezone
);
400 free(network
->dhcp_server_dns
);
401 free(network
->dhcp_server_ntp
);
403 set_free_free(network
->dnssec_negative_trust_anchors
);
408 int network_get_by_name(Manager
*manager
, const char *name
, Network
**ret
) {
415 network
= hashmap_get(manager
->networks_by_name
, name
);
424 int network_get(Manager
*manager
, sd_device
*device
,
425 const char *ifname
, const struct ether_addr
*address
,
427 const char *path
= NULL
, *parent_driver
= NULL
, *driver
= NULL
, *devtype
= NULL
;
435 (void) sd_device_get_property_value(device
, "ID_PATH", &path
);
437 if (sd_device_get_parent(device
, &parent
) >= 0)
438 (void) sd_device_get_driver(parent
, &parent_driver
);
440 (void) sd_device_get_property_value(device
, "ID_NET_DRIVER", &driver
);
442 (void) sd_device_get_devtype(device
, &devtype
);
445 LIST_FOREACH(networks
, network
, manager
->networks
) {
446 if (net_match_config(network
->match_mac
, network
->match_path
,
447 network
->match_driver
, network
->match_type
,
448 network
->match_name
, network
->match_host
,
449 network
->match_virt
, network
->match_kernel_cmdline
,
450 network
->match_kernel_version
, network
->match_arch
,
451 address
, path
, parent_driver
, driver
,
453 if (network
->match_name
&& device
) {
455 uint8_t name_assign_type
= NET_NAME_UNKNOWN
;
457 if (sd_device_get_sysattr_value(device
, "name_assign_type", &attr
) >= 0)
458 (void) safe_atou8(attr
, &name_assign_type
);
460 if (name_assign_type
== NET_NAME_ENUM
)
461 log_warning("%s: found matching network '%s', based on potentially unpredictable ifname",
462 ifname
, network
->filename
);
464 log_debug("%s: found matching network '%s'", ifname
, network
->filename
);
466 log_debug("%s: found matching network '%s'", ifname
, network
->filename
);
478 int network_apply(Network
*network
, Link
*link
) {
484 link
->network
= network
;
486 if (network
->ipv4ll_route
) {
489 r
= route_new_static(network
, NULL
, 0, &route
);
493 r
= inet_pton(AF_INET
, "169.254.0.0", &route
->dst
.in
);
499 route
->family
= AF_INET
;
500 route
->dst_prefixlen
= 16;
501 route
->scope
= RT_SCOPE_LINK
;
502 route
->priority
= IPV4LL_ROUTE_METRIC
;
503 route
->protocol
= RTPROT_STATIC
;
506 if (network
->n_dns
> 0 ||
507 !strv_isempty(network
->ntp
) ||
508 !strv_isempty(network
->search_domains
) ||
509 !strv_isempty(network
->route_domains
))
515 bool network_has_static_ipv6_addresses(Network
*network
) {
520 LIST_FOREACH(addresses
, address
, network
->static_addresses
) {
521 if (address
->family
== AF_INET6
)
528 int config_parse_netdev(const char *unit
,
529 const char *filename
,
532 unsigned section_line
,
538 Network
*network
= userdata
;
539 _cleanup_free_
char *kind_string
= NULL
;
550 kind_string
= strdup(lvalue
);
554 /* the keys are CamelCase versions of the kind */
555 for (p
= kind_string
; *p
; p
++)
558 kind
= netdev_kind_from_string(kind_string
);
559 if (kind
== _NETDEV_KIND_INVALID
) {
560 log_syntax(unit
, LOG_ERR
, filename
, line
, 0, "Invalid NetDev kind: %s", lvalue
);
564 r
= netdev_get(network
->manager
, rvalue
, &netdev
);
566 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "%s could not be found, ignoring assignment: %s", lvalue
, rvalue
);
570 if (netdev
->kind
!= kind
) {
571 log_syntax(unit
, LOG_ERR
, filename
, line
, 0, "NetDev is not a %s, ignoring assignment: %s", lvalue
, rvalue
);
576 case NETDEV_KIND_BRIDGE
:
577 network
->bridge
= netdev_unref(network
->bridge
);
578 network
->bridge
= netdev
;
581 case NETDEV_KIND_BOND
:
582 network
->bond
= netdev_unref(network
->bond
);
583 network
->bond
= netdev
;
586 case NETDEV_KIND_VRF
:
587 network
->vrf
= netdev_unref(network
->vrf
);
588 network
->vrf
= netdev
;
591 case NETDEV_KIND_VLAN
:
592 case NETDEV_KIND_MACVLAN
:
593 case NETDEV_KIND_MACVTAP
:
594 case NETDEV_KIND_IPVLAN
:
595 case NETDEV_KIND_VXLAN
:
596 case NETDEV_KIND_VCAN
:
597 r
= hashmap_ensure_allocated(&network
->stacked_netdevs
, &string_hash_ops
);
601 r
= hashmap_put(network
->stacked_netdevs
, netdev
->ifname
, netdev
);
603 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Cannot add NetDev '%s' to network: %m", rvalue
);
609 assert_not_reached("Cannot parse NetDev");
617 int config_parse_domains(
619 const char *filename
,
622 unsigned section_line
,
637 if (isempty(rvalue
)) {
638 n
->search_domains
= strv_free(n
->search_domains
);
639 n
->route_domains
= strv_free(n
->route_domains
);
645 _cleanup_free_
char *w
= NULL
, *normalized
= NULL
;
649 r
= extract_first_word(&p
, &w
, NULL
, 0);
651 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Failed to extract search or route domain, ignoring: %s", rvalue
);
657 is_route
= w
[0] == '~';
658 domain
= is_route
? w
+ 1 : w
;
660 if (dns_name_is_root(domain
) || streq(domain
, "*")) {
661 /* If the root domain appears as is, or the special token "*" is found, we'll consider this as
662 * routing domain, unconditionally. */
664 domain
= "."; /* make sure we don't allow empty strings, thus write the root domain as "." */
666 r
= dns_name_normalize(domain
, 0, &normalized
);
668 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "'%s' is not a valid domain name, ignoring.", domain
);
674 if (is_localhost(domain
)) {
675 log_syntax(unit
, LOG_ERR
, filename
, line
, 0, "'localhost' domain names may not be configure as search or route domains, ignoring assignment: %s", domain
);
681 r
= strv_extend(&n
->route_domains
, domain
);
683 r
= strv_extend(&n
->search_domains
, domain
);
688 strv_uniq(n
->route_domains
);
689 strv_uniq(n
->search_domains
);
694 int config_parse_tunnel(const char *unit
,
695 const char *filename
,
698 unsigned section_line
,
704 Network
*network
= userdata
;
713 r
= netdev_get(network
->manager
, rvalue
, &netdev
);
715 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Tunnel is invalid, ignoring assignment: %s", rvalue
);
719 if (!IN_SET(netdev
->kind
,
725 NETDEV_KIND_IP6GRETAP
,
728 NETDEV_KIND_IP6TNL
)) {
729 log_syntax(unit
, LOG_ERR
, filename
, line
, 0,
730 "NetDev is not a tunnel, ignoring assignment: %s", rvalue
);
734 r
= hashmap_ensure_allocated(&network
->stacked_netdevs
, &string_hash_ops
);
738 r
= hashmap_put(network
->stacked_netdevs
, netdev
->ifname
, netdev
);
740 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Cannot add VLAN '%s' to network, ignoring: %m", rvalue
);
749 int config_parse_ipv4ll(
751 const char *filename
,
754 unsigned section_line
,
761 AddressFamilyBoolean
*link_local
= data
;
768 /* Note that this is mostly like
769 * config_parse_address_family_boolean(), except that it
770 * applies only to IPv4 */
772 SET_FLAG(*link_local
, ADDRESS_FAMILY_IPV4
, parse_boolean(rvalue
));
777 int config_parse_dhcp(
779 const char *filename
,
782 unsigned section_line
,
789 AddressFamilyBoolean
*dhcp
= data
, s
;
796 /* Note that this is mostly like
797 * config_parse_address_family_boolean(), except that it
798 * understands some old names for the enum values */
800 s
= address_family_boolean_from_string(rvalue
);
803 /* Previously, we had a slightly different enum here,
804 * support its values for compatbility. */
806 if (streq(rvalue
, "none"))
807 s
= ADDRESS_FAMILY_NO
;
808 else if (streq(rvalue
, "v4"))
809 s
= ADDRESS_FAMILY_IPV4
;
810 else if (streq(rvalue
, "v6"))
811 s
= ADDRESS_FAMILY_IPV6
;
812 else if (streq(rvalue
, "both"))
813 s
= ADDRESS_FAMILY_YES
;
815 log_syntax(unit
, LOG_ERR
, filename
, line
, 0, "Failed to parse DHCP option, ignoring: %s", rvalue
);
824 static const char* const dhcp_client_identifier_table
[_DHCP_CLIENT_ID_MAX
] = {
825 [DHCP_CLIENT_ID_MAC
] = "mac",
826 [DHCP_CLIENT_ID_DUID
] = "duid",
827 [DHCP_CLIENT_ID_DUID_ONLY
] = "duid-only",
830 DEFINE_PRIVATE_STRING_TABLE_LOOKUP_FROM_STRING(dhcp_client_identifier
, DHCPClientIdentifier
);
831 DEFINE_CONFIG_PARSE_ENUM(config_parse_dhcp_client_identifier
, dhcp_client_identifier
, DHCPClientIdentifier
, "Failed to parse client identifier type");
833 int config_parse_ipv6token(
835 const char *filename
,
838 unsigned section_line
,
845 union in_addr_union buffer
;
846 struct in6_addr
*token
= data
;
854 r
= in_addr_from_string(AF_INET6
, rvalue
, &buffer
);
856 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Failed to parse IPv6 token, ignoring: %s", rvalue
);
860 r
= in_addr_is_null(AF_INET6
, &buffer
);
862 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "IPv6 token cannot be the ANY address, ignoring: %s", rvalue
);
866 if ((buffer
.in6
.s6_addr32
[0] | buffer
.in6
.s6_addr32
[1]) != 0) {
867 log_syntax(unit
, LOG_ERR
, filename
, line
, 0, "IPv6 token cannot be longer than 64 bits, ignoring: %s", rvalue
);
876 static const char* const ipv6_privacy_extensions_table
[_IPV6_PRIVACY_EXTENSIONS_MAX
] = {
877 [IPV6_PRIVACY_EXTENSIONS_NO
] = "no",
878 [IPV6_PRIVACY_EXTENSIONS_PREFER_PUBLIC
] = "prefer-public",
879 [IPV6_PRIVACY_EXTENSIONS_YES
] = "yes",
882 DEFINE_STRING_TABLE_LOOKUP(ipv6_privacy_extensions
, IPv6PrivacyExtensions
);
884 int config_parse_ipv6_privacy_extensions(
886 const char *filename
,
889 unsigned section_line
,
896 IPv6PrivacyExtensions
*ipv6_privacy_extensions
= data
;
902 assert(ipv6_privacy_extensions
);
904 /* Our enum shall be a superset of booleans, hence first try
905 * to parse as boolean, and then as enum */
907 k
= parse_boolean(rvalue
);
909 *ipv6_privacy_extensions
= IPV6_PRIVACY_EXTENSIONS_YES
;
911 *ipv6_privacy_extensions
= IPV6_PRIVACY_EXTENSIONS_NO
;
913 IPv6PrivacyExtensions s
;
915 s
= ipv6_privacy_extensions_from_string(rvalue
);
918 if (streq(rvalue
, "kernel"))
919 s
= _IPV6_PRIVACY_EXTENSIONS_INVALID
;
921 log_syntax(unit
, LOG_ERR
, filename
, line
, 0, "Failed to parse IPv6 privacy extensions option, ignoring: %s", rvalue
);
926 *ipv6_privacy_extensions
= s
;
932 int config_parse_hostname(
934 const char *filename
,
937 unsigned section_line
,
944 _cleanup_free_
char *hn
= NULL
;
945 char **hostname
= data
;
952 r
= config_parse_string(unit
, filename
, line
, section
, section_line
, lvalue
, ltype
, rvalue
, &hn
, userdata
);
956 if (!hostname_is_valid(hn
, false)) {
957 log_syntax(unit
, LOG_ERR
, filename
, line
, 0, "Hostname is not valid, ignoring assignment: %s", rvalue
);
961 r
= dns_name_is_valid(hn
);
963 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Failed to check validity of hostname '%s', ignoring assignment: %m", rvalue
);
967 log_syntax(unit
, LOG_ERR
, filename
, line
, 0, "Hostname is not a valid DNS domain name, ignoring assignment: %s", rvalue
);
971 return free_and_replace(*hostname
, hn
);
974 int config_parse_timezone(
976 const char *filename
,
979 unsigned section_line
,
986 _cleanup_free_
char *tz
= NULL
;
994 r
= config_parse_string(unit
, filename
, line
, section
, section_line
, lvalue
, ltype
, rvalue
, &tz
, userdata
);
998 if (!timezone_is_valid(tz
, LOG_ERR
)) {
999 log_syntax(unit
, LOG_ERR
, filename
, line
, 0, "Timezone is not valid, ignoring assignment: %s", rvalue
);
1003 return free_and_replace(*datap
, tz
);
1006 int config_parse_dhcp_server_dns(
1008 const char *filename
,
1010 const char *section
,
1011 unsigned section_line
,
1019 const char *p
= rvalue
;
1027 _cleanup_free_
char *w
= NULL
;
1028 struct in_addr a
, *m
;
1030 r
= extract_first_word(&p
, &w
, NULL
, 0);
1034 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Failed to extract word, ignoring: %s", rvalue
);
1040 if (inet_pton(AF_INET
, w
, &a
) <= 0) {
1041 log_syntax(unit
, LOG_ERR
, filename
, line
, 0, "Failed to parse DNS server address, ignoring: %s", w
);
1045 m
= reallocarray(n
->dhcp_server_dns
, n
->n_dhcp_server_dns
+ 1, sizeof(struct in_addr
));
1049 m
[n
->n_dhcp_server_dns
++] = a
;
1050 n
->dhcp_server_dns
= m
;
1056 int config_parse_radv_dns(
1058 const char *filename
,
1060 const char *section
,
1061 unsigned section_line
,
1069 const char *p
= rvalue
;
1077 _cleanup_free_
char *w
= NULL
;
1078 union in_addr_union a
;
1080 r
= extract_first_word(&p
, &w
, NULL
, 0);
1084 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Failed to extract word, ignoring: %s", rvalue
);
1090 if (in_addr_from_string(AF_INET6
, w
, &a
) >= 0) {
1093 m
= reallocarray(n
->router_dns
, n
->n_router_dns
+ 1, sizeof(struct in6_addr
));
1097 m
[n
->n_router_dns
++] = a
.in6
;
1101 log_syntax(unit
, LOG_ERR
, filename
, line
, 0, "Failed to parse DNS server address, ignoring: %s", w
);
1108 int config_parse_radv_search_domains(
1110 const char *filename
,
1112 const char *section
,
1113 unsigned section_line
,
1121 const char *p
= rvalue
;
1129 _cleanup_free_
char *w
= NULL
, *idna
= NULL
;
1131 r
= extract_first_word(&p
, &w
, NULL
, 0);
1135 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Failed to extract word, ignoring: %s", rvalue
);
1141 r
= dns_name_apply_idna(w
, &idna
);
1143 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Failed to apply IDNA to domain name '%s', ignoring: %m", w
);
1147 r
= strv_push(&n
->router_search_domains
, idna
);
1151 r
= strv_push(&n
->router_search_domains
, w
);
1160 int config_parse_dhcp_server_ntp(
1162 const char *filename
,
1164 const char *section
,
1165 unsigned section_line
,
1173 const char *p
= rvalue
;
1181 _cleanup_free_
char *w
= NULL
;
1182 struct in_addr a
, *m
;
1184 r
= extract_first_word(&p
, &w
, NULL
, 0);
1188 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Failed to extract word, ignoring: %s", rvalue
);
1194 if (inet_pton(AF_INET
, w
, &a
) <= 0) {
1195 log_syntax(unit
, LOG_ERR
, filename
, line
, 0, "Failed to parse NTP server address, ignoring: %s", w
);
1199 m
= reallocarray(n
->dhcp_server_ntp
, n
->n_dhcp_server_ntp
+ 1, sizeof(struct in_addr
));
1203 m
[n
->n_dhcp_server_ntp
++] = a
;
1204 n
->dhcp_server_ntp
= m
;
1208 int config_parse_dns(
1210 const char *filename
,
1212 const char *section
,
1213 unsigned section_line
,
1220 Network
*n
= userdata
;
1228 _cleanup_free_
char *w
= NULL
;
1229 union in_addr_union a
;
1230 struct in_addr_data
*m
;
1233 r
= extract_first_word(&rvalue
, &w
, NULL
, 0);
1237 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Invalid syntax, ignoring: %s", rvalue
);
1243 r
= in_addr_from_string_auto(w
, &family
, &a
);
1245 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Failed to parse dns server address, ignoring: %s", w
);
1249 m
= reallocarray(n
->dns
, n
->n_dns
+ 1, sizeof(struct in_addr_data
));
1253 m
[n
->n_dns
++] = (struct in_addr_data
) {
1264 int config_parse_dnssec_negative_trust_anchors(
1266 const char *filename
,
1268 const char *section
,
1269 unsigned section_line
,
1276 const char *p
= rvalue
;
1284 if (isempty(rvalue
)) {
1285 n
->dnssec_negative_trust_anchors
= set_free_free(n
->dnssec_negative_trust_anchors
);
1290 _cleanup_free_
char *w
= NULL
;
1292 r
= extract_first_word(&p
, &w
, NULL
, 0);
1294 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Failed to extract negative trust anchor domain, ignoring: %s", rvalue
);
1300 r
= dns_name_is_valid(w
);
1302 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "%s is not a valid domain name, ignoring.", w
);
1306 r
= set_ensure_allocated(&n
->dnssec_negative_trust_anchors
, &dns_name_hash_ops
);
1310 r
= set_put(n
->dnssec_negative_trust_anchors
, w
);
1320 int config_parse_ntp(
1322 const char *filename
,
1324 const char *section
,
1325 unsigned section_line
,
1339 if (isempty(rvalue
)) {
1345 _cleanup_free_
char *w
= NULL
;
1347 r
= extract_first_word(&rvalue
, &w
, NULL
, 0);
1351 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Failed to extract NTP server name, ignoring: %s", rvalue
);
1357 r
= dns_name_is_valid_or_address(w
);
1359 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "%s is not a valid domain name or IP address, ignoring.", w
);
1363 r
= strv_push(l
, w
);
1373 int config_parse_dhcp_user_class(
1375 const char *filename
,
1377 const char *section
,
1378 unsigned section_line
,
1392 if (isempty(rvalue
)) {
1398 _cleanup_free_
char *w
= NULL
;
1400 r
= extract_first_word(&rvalue
, &w
, NULL
, 0);
1404 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Failed to split user classes option, ignoring: %s", rvalue
);
1410 if (strlen(w
) > 255) {
1411 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "%s length is not in the range 1-255, ignoring.", w
);
1415 r
= strv_push(l
, w
);
1425 int config_parse_dhcp_route_table(const char *unit
,
1426 const char *filename
,
1428 const char *section
,
1429 unsigned section_line
,
1435 Network
*network
= data
;
1444 r
= safe_atou32(rvalue
, &rt
);
1446 log_syntax(unit
, LOG_ERR
, filename
, line
, r
,
1447 "Unable to read RouteTable, ignoring assignment: %s", rvalue
);
1451 network
->dhcp_route_table
= rt
;
1452 network
->dhcp_route_table_set
= true;
1457 DEFINE_CONFIG_PARSE_ENUM(config_parse_dhcp_use_domains
, dhcp_use_domains
, DHCPUseDomains
, "Failed to parse DHCP use domains setting");
1459 static const char* const dhcp_use_domains_table
[_DHCP_USE_DOMAINS_MAX
] = {
1460 [DHCP_USE_DOMAINS_NO
] = "no",
1461 [DHCP_USE_DOMAINS_ROUTE
] = "route",
1462 [DHCP_USE_DOMAINS_YES
] = "yes",
1465 DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(dhcp_use_domains
, DHCPUseDomains
, DHCP_USE_DOMAINS_YES
);
1467 DEFINE_CONFIG_PARSE_ENUM(config_parse_lldp_mode
, lldp_mode
, LLDPMode
, "Failed to parse LLDP= setting.");
1469 static const char* const lldp_mode_table
[_LLDP_MODE_MAX
] = {
1470 [LLDP_MODE_NO
] = "no",
1471 [LLDP_MODE_YES
] = "yes",
1472 [LLDP_MODE_ROUTERS_ONLY
] = "routers-only",
1475 DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(lldp_mode
, LLDPMode
, LLDP_MODE_YES
);
1477 int config_parse_iaid(const char *unit
,
1478 const char *filename
,
1480 const char *section
,
1481 unsigned section_line
,
1487 Network
*network
= data
;
1496 r
= safe_atou32(rvalue
, &iaid
);
1498 log_syntax(unit
, LOG_ERR
, filename
, line
, r
,
1499 "Unable to read IAID, ignoring assignment: %s", rvalue
);
1503 network
->iaid
= iaid
;
1504 network
->iaid_set
= true;