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
, '.');
186 network
->required_for_online
= true;
187 network
->dhcp
= ADDRESS_FAMILY_NO
;
188 network
->dhcp_use_ntp
= true;
189 network
->dhcp_use_dns
= true;
190 network
->dhcp_use_hostname
= true;
191 network
->dhcp_use_routes
= true;
192 /* NOTE: this var might be overwriten by network_apply_anonymize_if_set */
193 network
->dhcp_send_hostname
= true;
194 /* To enable/disable RFC7844 Anonymity Profiles */
195 network
->dhcp_anonymize
= false;
196 network
->dhcp_route_metric
= DHCP_ROUTE_METRIC
;
197 /* NOTE: this var might be overwrite by network_apply_anonymize_if_set */
198 network
->dhcp_client_identifier
= DHCP_CLIENT_ID_DUID
;
199 network
->dhcp_route_table
= RT_TABLE_MAIN
;
200 network
->dhcp_route_table_set
= false;
201 /* NOTE: from man: UseMTU=... Defaults to false*/
202 network
->dhcp_use_mtu
= false;
203 /* NOTE: from man: UseTimezone=... Defaults to "no".*/
204 network
->dhcp_use_timezone
= false;
205 network
->rapid_commit
= true;
207 network
->dhcp_server_emit_dns
= true;
208 network
->dhcp_server_emit_ntp
= true;
209 network
->dhcp_server_emit_router
= true;
210 network
->dhcp_server_emit_timezone
= true;
212 network
->router_emit_dns
= true;
213 network
->router_emit_domains
= true;
215 network
->use_bpdu
= -1;
216 network
->hairpin
= -1;
217 network
->fast_leave
= -1;
218 network
->allow_port_to_be_root
= -1;
219 network
->unicast_flood
= -1;
220 network
->priority
= LINK_BRIDGE_PORT_PRIORITY_INVALID
;
222 network
->lldp_mode
= LLDP_MODE_ROUTERS_ONLY
;
224 network
->llmnr
= RESOLVE_SUPPORT_YES
;
225 network
->mdns
= RESOLVE_SUPPORT_NO
;
226 network
->dnssec_mode
= _DNSSEC_MODE_INVALID
;
227 network
->dns_over_tls_mode
= _DNS_OVER_TLS_MODE_INVALID
;
229 network
->link_local
= ADDRESS_FAMILY_IPV6
;
231 network
->ipv6_privacy_extensions
= IPV6_PRIVACY_EXTENSIONS_NO
;
232 network
->ipv6_accept_ra
= -1;
233 network
->ipv6_dad_transmits
= -1;
234 network
->ipv6_hop_limit
= -1;
235 network
->ipv6_proxy_ndp
= -1;
236 network
->duid
.type
= _DUID_TYPE_INVALID
;
237 network
->proxy_arp
= -1;
239 network
->multicast
= -1;
240 network
->allmulticast
= -1;
241 network
->ipv6_accept_ra_use_dns
= true;
242 network
->ipv6_accept_ra_route_table
= RT_TABLE_MAIN
;
243 network
->ipv6_mtu
= 0;
245 dropin_dirname
= strjoina(network
->name
, ".network.d");
247 r
= config_parse_many(filename
, network_dirs
, dropin_dirname
,
253 "RoutingPolicyRule\0"
256 "DHCPv4\0" /* compat */
259 "IPv6NDPProxyAddress\0"
263 "IPv6PrefixDelegation\0"
266 config_item_perf_lookup
, network_network_gperf_lookup
,
267 CONFIG_PARSE_WARN
, network
);
271 network_apply_anonymize_if_set(network
);
273 /* IPMasquerade=yes implies IPForward=yes */
274 if (network
->ip_masquerade
)
275 network
->ip_forward
|= ADDRESS_FAMILY_IPV4
;
277 if (network
->mtu
> 0 && network
->dhcp_use_mtu
) {
278 log_warning("MTUBytes= in [Link] section and UseMTU= in [DHCP] section are set in %s. "
279 "Disabling UseMTU=.", filename
);
280 network
->dhcp_use_mtu
= false;
283 LIST_PREPEND(networks
, manager
->networks
, network
);
285 r
= hashmap_ensure_allocated(&manager
->networks_by_name
, &string_hash_ops
);
289 r
= hashmap_put(manager
->networks_by_name
, network
->name
, network
);
293 LIST_FOREACH(routes
, route
, network
->static_routes
) {
294 if (!route
->family
) {
295 log_warning("Route section without Gateway field configured in %s. "
296 "Ignoring", filename
);
301 LIST_FOREACH(addresses
, address
, network
->static_addresses
) {
302 if (!address
->family
) {
303 log_warning("Address section without Address field configured in %s. "
304 "Ignoring", filename
);
314 int network_load(Manager
*manager
) {
316 _cleanup_strv_free_
char **files
= NULL
;
322 while ((network
= manager
->networks
))
323 network_free(network
);
325 r
= conf_files_list_strv(&files
, ".network", NULL
, 0, network_dirs
);
327 return log_error_errno(r
, "Failed to enumerate network files: %m");
329 STRV_FOREACH_BACKWARDS(f
, files
) {
330 r
= network_load_one(manager
, *f
);
338 void network_free(Network
*network
) {
339 IPv6ProxyNDPAddress
*ipv6_proxy_ndp_address
;
340 RoutingPolicyRule
*rule
;
352 free(network
->filename
);
354 set_free_free(network
->match_mac
);
355 strv_free(network
->match_path
);
356 strv_free(network
->match_driver
);
357 strv_free(network
->match_type
);
358 strv_free(network
->match_name
);
360 free(network
->description
);
361 free(network
->dhcp_vendor_class_identifier
);
362 strv_free(network
->dhcp_user_class
);
363 free(network
->dhcp_hostname
);
367 strv_free(network
->ntp
);
369 strv_free(network
->search_domains
);
370 strv_free(network
->route_domains
);
371 strv_free(network
->bind_carrier
);
373 netdev_unref(network
->bridge
);
374 netdev_unref(network
->bond
);
375 netdev_unref(network
->vrf
);
377 HASHMAP_FOREACH(netdev
, network
->stacked_netdevs
, i
) {
378 hashmap_remove(network
->stacked_netdevs
, netdev
->ifname
);
379 netdev_unref(netdev
);
381 hashmap_free(network
->stacked_netdevs
);
383 while ((route
= network
->static_routes
))
386 while ((address
= network
->static_addresses
))
387 address_free(address
);
389 while ((fdb_entry
= network
->static_fdb_entries
))
390 fdb_entry_free(fdb_entry
);
392 while ((ipv6_proxy_ndp_address
= network
->ipv6_proxy_ndp_addresses
))
393 ipv6_proxy_ndp_address_free(ipv6_proxy_ndp_address
);
395 while ((label
= network
->address_labels
))
396 address_label_free(label
);
398 while ((prefix
= network
->static_prefixes
))
401 while ((rule
= network
->rules
))
402 routing_policy_rule_free(rule
);
404 hashmap_free(network
->addresses_by_section
);
405 hashmap_free(network
->routes_by_section
);
406 hashmap_free(network
->fdb_entries_by_section
);
407 hashmap_free(network
->address_labels_by_section
);
408 hashmap_free(network
->prefixes_by_section
);
409 hashmap_free(network
->rules_by_section
);
411 if (network
->manager
) {
412 if (network
->manager
->networks
)
413 LIST_REMOVE(networks
, network
->manager
->networks
, network
);
415 if (network
->manager
->networks_by_name
)
416 hashmap_remove(network
->manager
->networks_by_name
, network
->name
);
418 if (network
->manager
->duids_requesting_uuid
)
419 set_remove(network
->manager
->duids_requesting_uuid
, &network
->duid
);
424 condition_free_list(network
->match_host
);
425 condition_free_list(network
->match_virt
);
426 condition_free_list(network
->match_kernel_cmdline
);
427 condition_free_list(network
->match_kernel_version
);
428 condition_free_list(network
->match_arch
);
430 free(network
->dhcp_server_timezone
);
431 free(network
->dhcp_server_dns
);
432 free(network
->dhcp_server_ntp
);
434 set_free_free(network
->dnssec_negative_trust_anchors
);
439 int network_get_by_name(Manager
*manager
, const char *name
, Network
**ret
) {
446 network
= hashmap_get(manager
->networks_by_name
, name
);
455 int network_get(Manager
*manager
, sd_device
*device
,
456 const char *ifname
, const struct ether_addr
*address
,
458 const char *path
= NULL
, *parent_driver
= NULL
, *driver
= NULL
, *devtype
= NULL
;
466 (void) sd_device_get_property_value(device
, "ID_PATH", &path
);
468 if (sd_device_get_parent(device
, &parent
) >= 0)
469 (void) sd_device_get_driver(parent
, &parent_driver
);
471 (void) sd_device_get_property_value(device
, "ID_NET_DRIVER", &driver
);
473 (void) sd_device_get_devtype(device
, &devtype
);
476 LIST_FOREACH(networks
, network
, manager
->networks
) {
477 if (net_match_config(network
->match_mac
, network
->match_path
,
478 network
->match_driver
, network
->match_type
,
479 network
->match_name
, network
->match_host
,
480 network
->match_virt
, network
->match_kernel_cmdline
,
481 network
->match_kernel_version
, network
->match_arch
,
482 address
, path
, parent_driver
, driver
,
484 if (network
->match_name
&& device
) {
486 uint8_t name_assign_type
= NET_NAME_UNKNOWN
;
488 if (sd_device_get_sysattr_value(device
, "name_assign_type", &attr
) >= 0)
489 (void) safe_atou8(attr
, &name_assign_type
);
491 if (name_assign_type
== NET_NAME_ENUM
)
492 log_warning("%s: found matching network '%s', based on potentially unpredictable ifname",
493 ifname
, network
->filename
);
495 log_debug("%s: found matching network '%s'", ifname
, network
->filename
);
497 log_debug("%s: found matching network '%s'", ifname
, network
->filename
);
509 int network_apply(Network
*network
, Link
*link
) {
515 link
->network
= network
;
517 if (network
->ipv4ll_route
) {
520 r
= route_new_static(network
, NULL
, 0, &route
);
524 r
= inet_pton(AF_INET
, "169.254.0.0", &route
->dst
.in
);
530 route
->family
= AF_INET
;
531 route
->dst_prefixlen
= 16;
532 route
->scope
= RT_SCOPE_LINK
;
533 route
->priority
= IPV4LL_ROUTE_METRIC
;
534 route
->protocol
= RTPROT_STATIC
;
537 if (network
->n_dns
> 0 ||
538 !strv_isempty(network
->ntp
) ||
539 !strv_isempty(network
->search_domains
) ||
540 !strv_isempty(network
->route_domains
))
546 bool network_has_static_ipv6_addresses(Network
*network
) {
551 LIST_FOREACH(addresses
, address
, network
->static_addresses
) {
552 if (address
->family
== AF_INET6
)
559 int config_parse_netdev(const char *unit
,
560 const char *filename
,
563 unsigned section_line
,
569 Network
*network
= userdata
;
570 _cleanup_free_
char *kind_string
= NULL
;
581 kind_string
= strdup(lvalue
);
585 /* the keys are CamelCase versions of the kind */
586 for (p
= kind_string
; *p
; p
++)
589 kind
= netdev_kind_from_string(kind_string
);
590 if (kind
== _NETDEV_KIND_INVALID
) {
591 log_syntax(unit
, LOG_ERR
, filename
, line
, 0, "Invalid NetDev kind: %s", lvalue
);
595 r
= netdev_get(network
->manager
, rvalue
, &netdev
);
597 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "%s could not be found, ignoring assignment: %s", lvalue
, rvalue
);
601 if (netdev
->kind
!= kind
) {
602 log_syntax(unit
, LOG_ERR
, filename
, line
, 0, "NetDev is not a %s, ignoring assignment: %s", lvalue
, rvalue
);
607 case NETDEV_KIND_BRIDGE
:
608 network
->bridge
= netdev_unref(network
->bridge
);
609 network
->bridge
= netdev
;
612 case NETDEV_KIND_BOND
:
613 network
->bond
= netdev_unref(network
->bond
);
614 network
->bond
= netdev
;
617 case NETDEV_KIND_VRF
:
618 network
->vrf
= netdev_unref(network
->vrf
);
619 network
->vrf
= netdev
;
622 case NETDEV_KIND_VLAN
:
623 case NETDEV_KIND_MACVLAN
:
624 case NETDEV_KIND_MACVTAP
:
625 case NETDEV_KIND_IPVLAN
:
626 case NETDEV_KIND_VXLAN
:
627 case NETDEV_KIND_VCAN
:
628 r
= hashmap_put(network
->stacked_netdevs
, netdev
->ifname
, netdev
);
630 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Cannot add NetDev '%s' to network: %m", rvalue
);
636 assert_not_reached("Cannot parse NetDev");
644 int config_parse_domains(
646 const char *filename
,
649 unsigned section_line
,
664 if (isempty(rvalue
)) {
665 n
->search_domains
= strv_free(n
->search_domains
);
666 n
->route_domains
= strv_free(n
->route_domains
);
672 _cleanup_free_
char *w
= NULL
, *normalized
= NULL
;
676 r
= extract_first_word(&p
, &w
, NULL
, 0);
678 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Failed to extract search or route domain, ignoring: %s", rvalue
);
684 is_route
= w
[0] == '~';
685 domain
= is_route
? w
+ 1 : w
;
687 if (dns_name_is_root(domain
) || streq(domain
, "*")) {
688 /* If the root domain appears as is, or the special token "*" is found, we'll consider this as
689 * routing domain, unconditionally. */
691 domain
= "."; /* make sure we don't allow empty strings, thus write the root domain as "." */
694 r
= dns_name_normalize(domain
, &normalized
);
696 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "'%s' is not a valid domain name, ignoring.", domain
);
702 if (is_localhost(domain
)) {
703 log_syntax(unit
, LOG_ERR
, filename
, line
, 0, "'localhost' domain names may not be configure as search or route domains, ignoring assignment: %s", domain
);
709 r
= strv_extend(&n
->route_domains
, domain
);
714 r
= strv_extend(&n
->search_domains
, domain
);
720 strv_uniq(n
->route_domains
);
721 strv_uniq(n
->search_domains
);
726 int config_parse_tunnel(const char *unit
,
727 const char *filename
,
730 unsigned section_line
,
736 Network
*network
= userdata
;
745 r
= netdev_get(network
->manager
, rvalue
, &netdev
);
747 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Tunnel is invalid, ignoring assignment: %s", rvalue
);
751 if (!IN_SET(netdev
->kind
,
757 NETDEV_KIND_IP6GRETAP
,
760 NETDEV_KIND_IP6TNL
)) {
761 log_syntax(unit
, LOG_ERR
, filename
, line
, 0,
762 "NetDev is not a tunnel, ignoring assignment: %s", rvalue
);
766 r
= hashmap_put(network
->stacked_netdevs
, netdev
->ifname
, netdev
);
768 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Cannot add VLAN '%s' to network, ignoring: %m", rvalue
);
777 int config_parse_ipv4ll(
779 const char *filename
,
782 unsigned section_line
,
789 AddressFamilyBoolean
*link_local
= data
;
796 /* Note that this is mostly like
797 * config_parse_address_family_boolean(), except that it
798 * applies only to IPv4 */
800 SET_FLAG(*link_local
, ADDRESS_FAMILY_IPV4
, parse_boolean(rvalue
));
805 int config_parse_dhcp(
807 const char *filename
,
810 unsigned section_line
,
817 AddressFamilyBoolean
*dhcp
= data
, s
;
824 /* Note that this is mostly like
825 * config_parse_address_family_boolean(), except that it
826 * understands some old names for the enum values */
828 s
= address_family_boolean_from_string(rvalue
);
831 /* Previously, we had a slightly different enum here,
832 * support its values for compatbility. */
834 if (streq(rvalue
, "none"))
835 s
= ADDRESS_FAMILY_NO
;
836 else if (streq(rvalue
, "v4"))
837 s
= ADDRESS_FAMILY_IPV4
;
838 else if (streq(rvalue
, "v6"))
839 s
= ADDRESS_FAMILY_IPV6
;
840 else if (streq(rvalue
, "both"))
841 s
= ADDRESS_FAMILY_YES
;
843 log_syntax(unit
, LOG_ERR
, filename
, line
, 0, "Failed to parse DHCP option, ignoring: %s", rvalue
);
852 static const char* const dhcp_client_identifier_table
[_DHCP_CLIENT_ID_MAX
] = {
853 [DHCP_CLIENT_ID_MAC
] = "mac",
854 [DHCP_CLIENT_ID_DUID
] = "duid",
855 [DHCP_CLIENT_ID_DUID_ONLY
] = "duid-only",
858 DEFINE_PRIVATE_STRING_TABLE_LOOKUP_FROM_STRING(dhcp_client_identifier
, DHCPClientIdentifier
);
859 DEFINE_CONFIG_PARSE_ENUM(config_parse_dhcp_client_identifier
, dhcp_client_identifier
, DHCPClientIdentifier
, "Failed to parse client identifier type");
861 int config_parse_ipv6token(
863 const char *filename
,
866 unsigned section_line
,
873 union in_addr_union buffer
;
874 struct in6_addr
*token
= data
;
882 r
= in_addr_from_string(AF_INET6
, rvalue
, &buffer
);
884 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Failed to parse IPv6 token, ignoring: %s", rvalue
);
888 r
= in_addr_is_null(AF_INET6
, &buffer
);
890 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "IPv6 token cannot be the ANY address, ignoring: %s", rvalue
);
894 if ((buffer
.in6
.s6_addr32
[0] | buffer
.in6
.s6_addr32
[1]) != 0) {
895 log_syntax(unit
, LOG_ERR
, filename
, line
, 0, "IPv6 token cannot be longer than 64 bits, ignoring: %s", rvalue
);
904 static const char* const ipv6_privacy_extensions_table
[_IPV6_PRIVACY_EXTENSIONS_MAX
] = {
905 [IPV6_PRIVACY_EXTENSIONS_NO
] = "no",
906 [IPV6_PRIVACY_EXTENSIONS_PREFER_PUBLIC
] = "prefer-public",
907 [IPV6_PRIVACY_EXTENSIONS_YES
] = "yes",
910 DEFINE_STRING_TABLE_LOOKUP(ipv6_privacy_extensions
, IPv6PrivacyExtensions
);
912 int config_parse_ipv6_privacy_extensions(
914 const char *filename
,
917 unsigned section_line
,
924 IPv6PrivacyExtensions
*ipv6_privacy_extensions
= data
;
930 assert(ipv6_privacy_extensions
);
932 /* Our enum shall be a superset of booleans, hence first try
933 * to parse as boolean, and then as enum */
935 k
= parse_boolean(rvalue
);
937 *ipv6_privacy_extensions
= IPV6_PRIVACY_EXTENSIONS_YES
;
939 *ipv6_privacy_extensions
= IPV6_PRIVACY_EXTENSIONS_NO
;
941 IPv6PrivacyExtensions s
;
943 s
= ipv6_privacy_extensions_from_string(rvalue
);
946 if (streq(rvalue
, "kernel"))
947 s
= _IPV6_PRIVACY_EXTENSIONS_INVALID
;
949 log_syntax(unit
, LOG_ERR
, filename
, line
, 0, "Failed to parse IPv6 privacy extensions option, ignoring: %s", rvalue
);
954 *ipv6_privacy_extensions
= s
;
960 int config_parse_hostname(
962 const char *filename
,
965 unsigned section_line
,
972 _cleanup_free_
char *hn
= NULL
;
973 char **hostname
= data
;
980 r
= config_parse_string(unit
, filename
, line
, section
, section_line
, lvalue
, ltype
, rvalue
, &hn
, userdata
);
984 if (!hostname_is_valid(hn
, false)) {
985 log_syntax(unit
, LOG_ERR
, filename
, line
, 0, "Hostname is not valid, ignoring assignment: %s", rvalue
);
989 r
= dns_name_is_valid(hn
);
991 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Failed to check validity of hostname '%s', ignoring assignment: %m", rvalue
);
995 log_syntax(unit
, LOG_ERR
, filename
, line
, 0, "Hostname is not a valid DNS domain name, ignoring assignment: %s", rvalue
);
999 return free_and_replace(*hostname
, hn
);
1002 int config_parse_timezone(
1004 const char *filename
,
1006 const char *section
,
1007 unsigned section_line
,
1014 _cleanup_free_
char *tz
= NULL
;
1015 char **datap
= data
;
1022 r
= config_parse_string(unit
, filename
, line
, section
, section_line
, lvalue
, ltype
, rvalue
, &tz
, userdata
);
1026 if (!timezone_is_valid(tz
, LOG_ERR
)) {
1027 log_syntax(unit
, LOG_ERR
, filename
, line
, 0, "Timezone is not valid, ignoring assignment: %s", rvalue
);
1031 return free_and_replace(*datap
, tz
);
1034 int config_parse_dhcp_server_dns(
1036 const char *filename
,
1038 const char *section
,
1039 unsigned section_line
,
1047 const char *p
= rvalue
;
1055 _cleanup_free_
char *w
= NULL
;
1056 struct in_addr a
, *m
;
1058 r
= extract_first_word(&p
, &w
, NULL
, 0);
1062 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Failed to extract word, ignoring: %s", rvalue
);
1068 if (inet_pton(AF_INET
, w
, &a
) <= 0) {
1069 log_syntax(unit
, LOG_ERR
, filename
, line
, 0, "Failed to parse DNS server address, ignoring: %s", w
);
1073 m
= reallocarray(n
->dhcp_server_dns
, n
->n_dhcp_server_dns
+ 1, sizeof(struct in_addr
));
1077 m
[n
->n_dhcp_server_dns
++] = a
;
1078 n
->dhcp_server_dns
= m
;
1084 int config_parse_radv_dns(
1086 const char *filename
,
1088 const char *section
,
1089 unsigned section_line
,
1097 const char *p
= rvalue
;
1105 _cleanup_free_
char *w
= NULL
;
1106 union in_addr_union a
;
1108 r
= extract_first_word(&p
, &w
, NULL
, 0);
1112 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Failed to extract word, ignoring: %s", rvalue
);
1118 if (in_addr_from_string(AF_INET6
, w
, &a
) >= 0) {
1121 m
= reallocarray(n
->router_dns
, n
->n_router_dns
+ 1, sizeof(struct in6_addr
));
1125 m
[n
->n_router_dns
++] = a
.in6
;
1129 log_syntax(unit
, LOG_ERR
, filename
, line
, 0, "Failed to parse DNS server address, ignoring: %s", w
);
1136 int config_parse_radv_search_domains(
1138 const char *filename
,
1140 const char *section
,
1141 unsigned section_line
,
1149 const char *p
= rvalue
;
1157 _cleanup_free_
char *w
= NULL
;
1158 _cleanup_free_
char *idna
= NULL
;
1160 r
= extract_first_word(&p
, &w
, NULL
, 0);
1164 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Failed to extract word, ignoring: %s", rvalue
);
1170 r
= dns_name_apply_idna(w
, &idna
);
1172 r
= strv_push(&n
->router_search_domains
, idna
);
1175 } else if (r
== 0) {
1176 r
= strv_push(&n
->router_search_domains
, w
);
1185 int config_parse_dhcp_server_ntp(
1187 const char *filename
,
1189 const char *section
,
1190 unsigned section_line
,
1198 const char *p
= rvalue
;
1206 _cleanup_free_
char *w
= NULL
;
1207 struct in_addr a
, *m
;
1209 r
= extract_first_word(&p
, &w
, NULL
, 0);
1213 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Failed to extract word, ignoring: %s", rvalue
);
1219 if (inet_pton(AF_INET
, w
, &a
) <= 0) {
1220 log_syntax(unit
, LOG_ERR
, filename
, line
, 0, "Failed to parse NTP server address, ignoring: %s", w
);
1224 m
= reallocarray(n
->dhcp_server_ntp
, n
->n_dhcp_server_ntp
+ 1, sizeof(struct in_addr
));
1228 m
[n
->n_dhcp_server_ntp
++] = a
;
1229 n
->dhcp_server_ntp
= m
;
1233 int config_parse_dns(
1235 const char *filename
,
1237 const char *section
,
1238 unsigned section_line
,
1245 Network
*n
= userdata
;
1253 _cleanup_free_
char *w
= NULL
;
1254 union in_addr_union a
;
1255 struct in_addr_data
*m
;
1258 r
= extract_first_word(&rvalue
, &w
, NULL
, 0);
1262 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Invalid syntax, ignoring: %s", rvalue
);
1268 r
= in_addr_from_string_auto(w
, &family
, &a
);
1270 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Failed to parse dns server address, ignoring: %s", w
);
1274 m
= reallocarray(n
->dns
, n
->n_dns
+ 1, sizeof(struct in_addr_data
));
1278 m
[n
->n_dns
++] = (struct in_addr_data
) {
1289 int config_parse_dnssec_negative_trust_anchors(
1291 const char *filename
,
1293 const char *section
,
1294 unsigned section_line
,
1301 const char *p
= rvalue
;
1309 if (isempty(rvalue
)) {
1310 n
->dnssec_negative_trust_anchors
= set_free_free(n
->dnssec_negative_trust_anchors
);
1315 _cleanup_free_
char *w
= NULL
;
1317 r
= extract_first_word(&p
, &w
, NULL
, 0);
1319 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Failed to extract negative trust anchor domain, ignoring: %s", rvalue
);
1325 r
= dns_name_is_valid(w
);
1327 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "%s is not a valid domain name, ignoring.", w
);
1331 r
= set_ensure_allocated(&n
->dnssec_negative_trust_anchors
, &dns_name_hash_ops
);
1335 r
= set_put(n
->dnssec_negative_trust_anchors
, w
);
1345 int config_parse_ntp(
1347 const char *filename
,
1349 const char *section
,
1350 unsigned section_line
,
1364 if (isempty(rvalue
)) {
1370 _cleanup_free_
char *w
= NULL
;
1372 r
= extract_first_word(&rvalue
, &w
, NULL
, 0);
1376 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Failed to extract NTP server name, ignoring: %s", rvalue
);
1382 r
= dns_name_is_valid_or_address(w
);
1384 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "%s is not a valid domain name or IP address, ignoring.", w
);
1388 r
= strv_push(l
, w
);
1398 int config_parse_dhcp_user_class(
1400 const char *filename
,
1402 const char *section
,
1403 unsigned section_line
,
1417 if (isempty(rvalue
)) {
1423 _cleanup_free_
char *w
= NULL
;
1425 r
= extract_first_word(&rvalue
, &w
, NULL
, 0);
1429 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Failed to split user classes option, ignoring: %s", rvalue
);
1435 if (strlen(w
) > 255) {
1436 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "%s length is not in the range 1-255, ignoring.", w
);
1440 r
= strv_push(l
, w
);
1450 int config_parse_dhcp_route_table(const char *unit
,
1451 const char *filename
,
1453 const char *section
,
1454 unsigned section_line
,
1460 Network
*network
= data
;
1469 r
= safe_atou32(rvalue
, &rt
);
1471 log_syntax(unit
, LOG_ERR
, filename
, line
, r
,
1472 "Unable to read RouteTable, ignoring assignment: %s", rvalue
);
1476 network
->dhcp_route_table
= rt
;
1477 network
->dhcp_route_table_set
= true;
1482 DEFINE_CONFIG_PARSE_ENUM(config_parse_dhcp_use_domains
, dhcp_use_domains
, DHCPUseDomains
, "Failed to parse DHCP use domains setting");
1484 static const char* const dhcp_use_domains_table
[_DHCP_USE_DOMAINS_MAX
] = {
1485 [DHCP_USE_DOMAINS_NO
] = "no",
1486 [DHCP_USE_DOMAINS_ROUTE
] = "route",
1487 [DHCP_USE_DOMAINS_YES
] = "yes",
1490 DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(dhcp_use_domains
, DHCPUseDomains
, DHCP_USE_DOMAINS_YES
);
1492 DEFINE_CONFIG_PARSE_ENUM(config_parse_lldp_mode
, lldp_mode
, LLDPMode
, "Failed to parse LLDP= setting.");
1494 static const char* const lldp_mode_table
[_LLDP_MODE_MAX
] = {
1495 [LLDP_MODE_NO
] = "no",
1496 [LLDP_MODE_YES
] = "yes",
1497 [LLDP_MODE_ROUTERS_ONLY
] = "routers-only",
1500 DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(lldp_mode
, LLDPMode
, LLDP_MODE_YES
);