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 y
->line
- x
->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 /* NOTE: it was not initiallized to any value in network_load_one. */
84 network
->dhcp_vendor_class_identifier
= false;
85 /* RFC7844 section 3.6.:
86 The client intending to protect its privacy SHOULD only request a
87 minimal number of options in the PRL and SHOULD also randomly shuffle
88 the ordering of option codes in the PRL. If this random ordering
89 cannot be implemented, the client MAY order the option codes in the
90 PRL by option code number (lowest to highest).
92 /* NOTE: dhcp_use_mtu is false by default,
93 * though it was not initiallized to any value in network_load_one.
94 * Maybe there should be another var called *send*?
95 * (to use the MTU sent by the server but to do not send
96 * the option in the PRL). */
97 network
->dhcp_use_mtu
= false;
98 /* NOTE: when Anonymize=yes, the PRL route options are sent by default,
99 * but this is needed to use them. */
100 network
->dhcp_use_routes
= true;
101 /* RFC7844 section 3.6.
102 * same comments as previous option */
103 network
->dhcp_use_timezone
= false;
106 static int network_load_one(Manager
*manager
, const char *filename
) {
107 _cleanup_(network_freep
) Network
*network
= NULL
;
108 _cleanup_fclose_
FILE *file
= NULL
;
110 const char *dropin_dirname
;
118 file
= fopen(filename
, "re");
126 if (null_or_empty_fd(fileno(file
))) {
127 log_debug("Skipping empty file: %s", filename
);
131 network
= new0(Network
, 1);
135 network
->manager
= manager
;
137 LIST_HEAD_INIT(network
->static_addresses
);
138 LIST_HEAD_INIT(network
->static_routes
);
139 LIST_HEAD_INIT(network
->static_fdb_entries
);
140 LIST_HEAD_INIT(network
->ipv6_proxy_ndp_addresses
);
141 LIST_HEAD_INIT(network
->address_labels
);
142 LIST_HEAD_INIT(network
->static_prefixes
);
143 LIST_HEAD_INIT(network
->rules
);
145 network
->stacked_netdevs
= hashmap_new(&string_hash_ops
);
146 if (!network
->stacked_netdevs
)
149 network
->addresses_by_section
= hashmap_new(&network_config_hash_ops
);
150 if (!network
->addresses_by_section
)
153 network
->routes_by_section
= hashmap_new(&network_config_hash_ops
);
154 if (!network
->routes_by_section
)
157 network
->fdb_entries_by_section
= hashmap_new(NULL
);
158 if (!network
->fdb_entries_by_section
)
161 network
->address_labels_by_section
= hashmap_new(&network_config_hash_ops
);
162 if (!network
->address_labels_by_section
)
165 network
->prefixes_by_section
= hashmap_new(&network_config_hash_ops
);
166 if (!network
->prefixes_by_section
)
169 network
->rules_by_section
= hashmap_new(&network_config_hash_ops
);
170 if (!network
->rules_by_section
)
173 network
->filename
= strdup(filename
);
174 if (!network
->filename
)
177 network
->name
= strdup(basename(filename
));
181 d
= strrchr(network
->name
, '.');
185 assert(streq(d
, ".network"));
189 network
->required_for_online
= true;
190 network
->dhcp
= ADDRESS_FAMILY_NO
;
191 network
->dhcp_use_ntp
= true;
192 network
->dhcp_use_dns
= true;
193 network
->dhcp_use_hostname
= true;
194 network
->dhcp_use_routes
= true;
195 /* NOTE: this var might be overwriten by network_apply_anonymize_if_set */
196 network
->dhcp_send_hostname
= true;
197 /* To enable/disable RFC7844 Anonymity Profiles */
198 network
->dhcp_anonymize
= false;
199 network
->dhcp_route_metric
= DHCP_ROUTE_METRIC
;
200 /* NOTE: this var might be overwrite by network_apply_anonymize_if_set */
201 network
->dhcp_client_identifier
= DHCP_CLIENT_ID_DUID
;
202 network
->dhcp_route_table
= RT_TABLE_MAIN
;
203 network
->dhcp_route_table_set
= false;
204 /* NOTE: the following vars were not set to any default,
205 * even if they are commented in the man?
206 * These vars might be overwriten by network_apply_anonymize_if_set */
207 network
->dhcp_vendor_class_identifier
= false;
208 /* NOTE: from man: UseMTU=... Defaults to false*/
209 network
->dhcp_use_mtu
= false;
210 /* NOTE: from man: UseTimezone=... Defaults to "no".*/
211 network
->dhcp_use_timezone
= false;
212 network
->rapid_commit
= true;
214 network
->dhcp_server_emit_dns
= true;
215 network
->dhcp_server_emit_ntp
= true;
216 network
->dhcp_server_emit_router
= true;
217 network
->dhcp_server_emit_timezone
= true;
219 network
->router_emit_dns
= true;
220 network
->router_emit_domains
= true;
222 network
->use_bpdu
= -1;
223 network
->hairpin
= -1;
224 network
->fast_leave
= -1;
225 network
->allow_port_to_be_root
= -1;
226 network
->unicast_flood
= -1;
227 network
->priority
= LINK_BRIDGE_PORT_PRIORITY_INVALID
;
229 network
->lldp_mode
= LLDP_MODE_ROUTERS_ONLY
;
231 network
->llmnr
= RESOLVE_SUPPORT_YES
;
232 network
->mdns
= RESOLVE_SUPPORT_NO
;
233 network
->dnssec_mode
= _DNSSEC_MODE_INVALID
;
234 network
->dns_over_tls_mode
= _DNS_OVER_TLS_MODE_INVALID
;
236 network
->link_local
= ADDRESS_FAMILY_IPV6
;
238 network
->ipv6_privacy_extensions
= IPV6_PRIVACY_EXTENSIONS_NO
;
239 network
->ipv6_accept_ra
= -1;
240 network
->ipv6_dad_transmits
= -1;
241 network
->ipv6_hop_limit
= -1;
242 network
->ipv6_proxy_ndp
= -1;
243 network
->duid
.type
= _DUID_TYPE_INVALID
;
244 network
->proxy_arp
= -1;
246 network
->multicast
= -1;
247 network
->allmulticast
= -1;
248 network
->ipv6_accept_ra_use_dns
= true;
249 network
->ipv6_accept_ra_route_table
= RT_TABLE_MAIN
;
250 network
->ipv6_mtu
= 0;
252 dropin_dirname
= strjoina(network
->name
, ".network.d");
254 r
= config_parse_many(filename
, network_dirs
, dropin_dirname
,
260 "RoutingPolicyRule\0"
263 "DHCPv4\0" /* compat */
266 "IPv6NDPProxyAddress\0"
270 "IPv6PrefixDelegation\0"
273 config_item_perf_lookup
, network_network_gperf_lookup
,
274 CONFIG_PARSE_WARN
, network
);
278 network_apply_anonymize_if_set(network
);
280 /* IPMasquerade=yes implies IPForward=yes */
281 if (network
->ip_masquerade
)
282 network
->ip_forward
|= ADDRESS_FAMILY_IPV4
;
284 LIST_PREPEND(networks
, manager
->networks
, network
);
286 r
= hashmap_ensure_allocated(&manager
->networks_by_name
, &string_hash_ops
);
290 r
= hashmap_put(manager
->networks_by_name
, network
->name
, network
);
294 LIST_FOREACH(routes
, route
, network
->static_routes
) {
295 if (!route
->family
) {
296 log_warning("Route section without Gateway field configured in %s. "
297 "Ignoring", filename
);
302 LIST_FOREACH(addresses
, address
, network
->static_addresses
) {
303 if (!address
->family
) {
304 log_warning("Address section without Address field configured in %s. "
305 "Ignoring", filename
);
315 int network_load(Manager
*manager
) {
317 _cleanup_strv_free_
char **files
= NULL
;
323 while ((network
= manager
->networks
))
324 network_free(network
);
326 r
= conf_files_list_strv(&files
, ".network", NULL
, 0, network_dirs
);
328 return log_error_errno(r
, "Failed to enumerate network files: %m");
330 STRV_FOREACH_BACKWARDS(f
, files
) {
331 r
= network_load_one(manager
, *f
);
339 void network_free(Network
*network
) {
340 IPv6ProxyNDPAddress
*ipv6_proxy_ndp_address
;
341 RoutingPolicyRule
*rule
;
353 free(network
->filename
);
355 set_free_free(network
->match_mac
);
356 strv_free(network
->match_path
);
357 strv_free(network
->match_driver
);
358 strv_free(network
->match_type
);
359 strv_free(network
->match_name
);
361 free(network
->description
);
362 free(network
->dhcp_vendor_class_identifier
);
363 strv_free(network
->dhcp_user_class
);
364 free(network
->dhcp_hostname
);
368 strv_free(network
->ntp
);
370 strv_free(network
->search_domains
);
371 strv_free(network
->route_domains
);
372 strv_free(network
->bind_carrier
);
374 netdev_unref(network
->bridge
);
375 netdev_unref(network
->bond
);
376 netdev_unref(network
->vrf
);
378 HASHMAP_FOREACH(netdev
, network
->stacked_netdevs
, i
) {
379 hashmap_remove(network
->stacked_netdevs
, netdev
->ifname
);
380 netdev_unref(netdev
);
382 hashmap_free(network
->stacked_netdevs
);
384 while ((route
= network
->static_routes
))
387 while ((address
= network
->static_addresses
))
388 address_free(address
);
390 while ((fdb_entry
= network
->static_fdb_entries
))
391 fdb_entry_free(fdb_entry
);
393 while ((ipv6_proxy_ndp_address
= network
->ipv6_proxy_ndp_addresses
))
394 ipv6_proxy_ndp_address_free(ipv6_proxy_ndp_address
);
396 while ((label
= network
->address_labels
))
397 address_label_free(label
);
399 while ((prefix
= network
->static_prefixes
))
402 while ((rule
= network
->rules
))
403 routing_policy_rule_free(rule
);
405 hashmap_free(network
->addresses_by_section
);
406 hashmap_free(network
->routes_by_section
);
407 hashmap_free(network
->fdb_entries_by_section
);
408 hashmap_free(network
->address_labels_by_section
);
409 hashmap_free(network
->prefixes_by_section
);
410 hashmap_free(network
->rules_by_section
);
412 if (network
->manager
) {
413 if (network
->manager
->networks
)
414 LIST_REMOVE(networks
, network
->manager
->networks
, network
);
416 if (network
->manager
->networks_by_name
)
417 hashmap_remove(network
->manager
->networks_by_name
, network
->name
);
422 condition_free_list(network
->match_host
);
423 condition_free_list(network
->match_virt
);
424 condition_free_list(network
->match_kernel_cmdline
);
425 condition_free_list(network
->match_kernel_version
);
426 condition_free_list(network
->match_arch
);
428 free(network
->dhcp_server_timezone
);
429 free(network
->dhcp_server_dns
);
430 free(network
->dhcp_server_ntp
);
432 set_free_free(network
->dnssec_negative_trust_anchors
);
437 int network_get_by_name(Manager
*manager
, const char *name
, Network
**ret
) {
444 network
= hashmap_get(manager
->networks_by_name
, name
);
453 int network_get(Manager
*manager
, struct udev_device
*device
,
454 const char *ifname
, const struct ether_addr
*address
,
457 struct udev_device
*parent
;
458 const char *path
= NULL
, *parent_driver
= NULL
, *driver
= NULL
, *devtype
= NULL
;
464 path
= udev_device_get_property_value(device
, "ID_PATH");
466 parent
= udev_device_get_parent(device
);
468 parent_driver
= udev_device_get_driver(parent
);
470 driver
= udev_device_get_property_value(device
, "ID_NET_DRIVER");
472 devtype
= udev_device_get_devtype(device
);
475 LIST_FOREACH(networks
, network
, manager
->networks
) {
476 if (net_match_config(network
->match_mac
, network
->match_path
,
477 network
->match_driver
, network
->match_type
,
478 network
->match_name
, network
->match_host
,
479 network
->match_virt
, network
->match_kernel_cmdline
,
480 network
->match_kernel_version
, network
->match_arch
,
481 address
, path
, parent_driver
, driver
,
483 if (network
->match_name
&& device
) {
485 uint8_t name_assign_type
= NET_NAME_UNKNOWN
;
487 attr
= udev_device_get_sysattr_value(device
, "name_assign_type");
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
;
611 case NETDEV_KIND_BOND
:
612 network
->bond
= netdev
;
615 case NETDEV_KIND_VRF
:
616 network
->vrf
= netdev
;
619 case NETDEV_KIND_VLAN
:
620 case NETDEV_KIND_MACVLAN
:
621 case NETDEV_KIND_MACVTAP
:
622 case NETDEV_KIND_IPVLAN
:
623 case NETDEV_KIND_VXLAN
:
624 case NETDEV_KIND_VCAN
:
625 r
= hashmap_put(network
->stacked_netdevs
, netdev
->ifname
, netdev
);
627 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Cannot add NetDev '%s' to network: %m", rvalue
);
633 assert_not_reached("Cannot parse NetDev");
641 int config_parse_domains(
643 const char *filename
,
646 unsigned section_line
,
661 if (isempty(rvalue
)) {
662 n
->search_domains
= strv_free(n
->search_domains
);
663 n
->route_domains
= strv_free(n
->route_domains
);
669 _cleanup_free_
char *w
= NULL
, *normalized
= NULL
;
673 r
= extract_first_word(&p
, &w
, NULL
, 0);
675 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Failed to extract search or route domain, ignoring: %s", rvalue
);
681 is_route
= w
[0] == '~';
682 domain
= is_route
? w
+ 1 : w
;
684 if (dns_name_is_root(domain
) || streq(domain
, "*")) {
685 /* If the root domain appears as is, or the special token "*" is found, we'll consider this as
686 * routing domain, unconditionally. */
688 domain
= "."; /* make sure we don't allow empty strings, thus write the root domain as "." */
691 r
= dns_name_normalize(domain
, &normalized
);
693 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "'%s' is not a valid domain name, ignoring.", domain
);
699 if (is_localhost(domain
)) {
700 log_syntax(unit
, LOG_ERR
, filename
, line
, 0, "'localhost' domain names may not be configure as search or route domains, ignoring assignment: %s", domain
);
706 r
= strv_extend(&n
->route_domains
, domain
);
711 r
= strv_extend(&n
->search_domains
, domain
);
717 strv_uniq(n
->route_domains
);
718 strv_uniq(n
->search_domains
);
723 int config_parse_tunnel(const char *unit
,
724 const char *filename
,
727 unsigned section_line
,
733 Network
*network
= userdata
;
742 r
= netdev_get(network
->manager
, rvalue
, &netdev
);
744 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Tunnel is invalid, ignoring assignment: %s", rvalue
);
748 if (!IN_SET(netdev
->kind
,
754 NETDEV_KIND_IP6GRETAP
,
757 NETDEV_KIND_IP6TNL
)) {
758 log_syntax(unit
, LOG_ERR
, filename
, line
, 0,
759 "NetDev is not a tunnel, ignoring assignment: %s", rvalue
);
763 r
= hashmap_put(network
->stacked_netdevs
, netdev
->ifname
, netdev
);
765 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Cannot add VLAN '%s' to network, ignoring: %m", rvalue
);
774 int config_parse_ipv4ll(
776 const char *filename
,
779 unsigned section_line
,
786 AddressFamilyBoolean
*link_local
= data
;
793 /* Note that this is mostly like
794 * config_parse_address_family_boolean(), except that it
795 * applies only to IPv4 */
797 SET_FLAG(*link_local
, ADDRESS_FAMILY_IPV4
, parse_boolean(rvalue
));
802 int config_parse_dhcp(
804 const char *filename
,
807 unsigned section_line
,
814 AddressFamilyBoolean
*dhcp
= data
, s
;
821 /* Note that this is mostly like
822 * config_parse_address_family_boolean(), except that it
823 * understands some old names for the enum values */
825 s
= address_family_boolean_from_string(rvalue
);
828 /* Previously, we had a slightly different enum here,
829 * support its values for compatbility. */
831 if (streq(rvalue
, "none"))
832 s
= ADDRESS_FAMILY_NO
;
833 else if (streq(rvalue
, "v4"))
834 s
= ADDRESS_FAMILY_IPV4
;
835 else if (streq(rvalue
, "v6"))
836 s
= ADDRESS_FAMILY_IPV6
;
837 else if (streq(rvalue
, "both"))
838 s
= ADDRESS_FAMILY_YES
;
840 log_syntax(unit
, LOG_ERR
, filename
, line
, 0, "Failed to parse DHCP option, ignoring: %s", rvalue
);
849 static const char* const dhcp_client_identifier_table
[_DHCP_CLIENT_ID_MAX
] = {
850 [DHCP_CLIENT_ID_MAC
] = "mac",
851 [DHCP_CLIENT_ID_DUID
] = "duid",
852 [DHCP_CLIENT_ID_DUID_ONLY
] = "duid-only",
855 DEFINE_PRIVATE_STRING_TABLE_LOOKUP_FROM_STRING(dhcp_client_identifier
, DHCPClientIdentifier
);
856 DEFINE_CONFIG_PARSE_ENUM(config_parse_dhcp_client_identifier
, dhcp_client_identifier
, DHCPClientIdentifier
, "Failed to parse client identifier type");
858 int config_parse_ipv6token(
860 const char *filename
,
863 unsigned section_line
,
870 union in_addr_union buffer
;
871 struct in6_addr
*token
= data
;
879 r
= in_addr_from_string(AF_INET6
, rvalue
, &buffer
);
881 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Failed to parse IPv6 token, ignoring: %s", rvalue
);
885 r
= in_addr_is_null(AF_INET6
, &buffer
);
887 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "IPv6 token cannot be the ANY address, ignoring: %s", rvalue
);
891 if ((buffer
.in6
.s6_addr32
[0] | buffer
.in6
.s6_addr32
[1]) != 0) {
892 log_syntax(unit
, LOG_ERR
, filename
, line
, 0, "IPv6 token cannot be longer than 64 bits, ignoring: %s", rvalue
);
901 static const char* const ipv6_privacy_extensions_table
[_IPV6_PRIVACY_EXTENSIONS_MAX
] = {
902 [IPV6_PRIVACY_EXTENSIONS_NO
] = "no",
903 [IPV6_PRIVACY_EXTENSIONS_PREFER_PUBLIC
] = "prefer-public",
904 [IPV6_PRIVACY_EXTENSIONS_YES
] = "yes",
907 DEFINE_STRING_TABLE_LOOKUP(ipv6_privacy_extensions
, IPv6PrivacyExtensions
);
909 int config_parse_ipv6_privacy_extensions(
911 const char *filename
,
914 unsigned section_line
,
921 IPv6PrivacyExtensions
*ipv6_privacy_extensions
= data
;
927 assert(ipv6_privacy_extensions
);
929 /* Our enum shall be a superset of booleans, hence first try
930 * to parse as boolean, and then as enum */
932 k
= parse_boolean(rvalue
);
934 *ipv6_privacy_extensions
= IPV6_PRIVACY_EXTENSIONS_YES
;
936 *ipv6_privacy_extensions
= IPV6_PRIVACY_EXTENSIONS_NO
;
938 IPv6PrivacyExtensions s
;
940 s
= ipv6_privacy_extensions_from_string(rvalue
);
943 if (streq(rvalue
, "kernel"))
944 s
= _IPV6_PRIVACY_EXTENSIONS_INVALID
;
946 log_syntax(unit
, LOG_ERR
, filename
, line
, 0, "Failed to parse IPv6 privacy extensions option, ignoring: %s", rvalue
);
951 *ipv6_privacy_extensions
= s
;
957 int config_parse_hostname(
959 const char *filename
,
962 unsigned section_line
,
969 char **hostname
= data
, *hn
= NULL
;
976 r
= config_parse_string(unit
, filename
, line
, section
, section_line
, lvalue
, ltype
, rvalue
, &hn
, userdata
);
980 if (!hostname_is_valid(hn
, false)) {
981 log_syntax(unit
, LOG_ERR
, filename
, line
, 0, "Hostname is not valid, ignoring assignment: %s", rvalue
);
987 *hostname
= hostname_cleanup(hn
);
991 int config_parse_timezone(
993 const char *filename
,
996 unsigned section_line
,
1003 char **datap
= data
, *tz
= NULL
;
1010 r
= config_parse_string(unit
, filename
, line
, section
, section_line
, lvalue
, ltype
, rvalue
, &tz
, userdata
);
1014 if (!timezone_is_valid(tz
, LOG_ERR
)) {
1015 log_syntax(unit
, LOG_ERR
, filename
, line
, 0, "Timezone is not valid, ignoring assignment: %s", rvalue
);
1026 int config_parse_dhcp_server_dns(
1028 const char *filename
,
1030 const char *section
,
1031 unsigned section_line
,
1039 const char *p
= rvalue
;
1047 _cleanup_free_
char *w
= NULL
;
1048 struct in_addr a
, *m
;
1050 r
= extract_first_word(&p
, &w
, NULL
, 0);
1054 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Failed to extract word, ignoring: %s", rvalue
);
1060 if (inet_pton(AF_INET
, w
, &a
) <= 0) {
1061 log_syntax(unit
, LOG_ERR
, filename
, line
, 0, "Failed to parse DNS server address, ignoring: %s", w
);
1065 m
= reallocarray(n
->dhcp_server_dns
, n
->n_dhcp_server_dns
+ 1, sizeof(struct in_addr
));
1069 m
[n
->n_dhcp_server_dns
++] = a
;
1070 n
->dhcp_server_dns
= m
;
1076 int config_parse_radv_dns(
1078 const char *filename
,
1080 const char *section
,
1081 unsigned section_line
,
1089 const char *p
= rvalue
;
1097 _cleanup_free_
char *w
= NULL
;
1098 union in_addr_union a
;
1100 r
= extract_first_word(&p
, &w
, NULL
, 0);
1104 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Failed to extract word, ignoring: %s", rvalue
);
1110 if (in_addr_from_string(AF_INET6
, w
, &a
) >= 0) {
1113 m
= reallocarray(n
->router_dns
, n
->n_router_dns
+ 1, sizeof(struct in6_addr
));
1117 m
[n
->n_router_dns
++] = a
.in6
;
1121 log_syntax(unit
, LOG_ERR
, filename
, line
, 0, "Failed to parse DNS server address, ignoring: %s", w
);
1128 int config_parse_radv_search_domains(
1130 const char *filename
,
1132 const char *section
,
1133 unsigned section_line
,
1141 const char *p
= rvalue
;
1149 _cleanup_free_
char *w
= NULL
;
1150 _cleanup_free_
char *idna
= NULL
;
1152 r
= extract_first_word(&p
, &w
, NULL
, 0);
1156 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Failed to extract word, ignoring: %s", rvalue
);
1162 r
= dns_name_apply_idna(w
, &idna
);
1164 r
= strv_push(&n
->router_search_domains
, idna
);
1167 } else if (r
== 0) {
1168 r
= strv_push(&n
->router_search_domains
, w
);
1177 int config_parse_dhcp_server_ntp(
1179 const char *filename
,
1181 const char *section
,
1182 unsigned section_line
,
1190 const char *p
= rvalue
;
1198 _cleanup_free_
char *w
= NULL
;
1199 struct in_addr a
, *m
;
1201 r
= extract_first_word(&p
, &w
, NULL
, 0);
1205 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Failed to extract word, ignoring: %s", rvalue
);
1211 if (inet_pton(AF_INET
, w
, &a
) <= 0) {
1212 log_syntax(unit
, LOG_ERR
, filename
, line
, 0, "Failed to parse NTP server address, ignoring: %s", w
);
1216 m
= reallocarray(n
->dhcp_server_ntp
, n
->n_dhcp_server_ntp
+ 1, sizeof(struct in_addr
));
1220 m
[n
->n_dhcp_server_ntp
++] = a
;
1221 n
->dhcp_server_ntp
= m
;
1225 int config_parse_dns(
1227 const char *filename
,
1229 const char *section
,
1230 unsigned section_line
,
1237 Network
*n
= userdata
;
1245 _cleanup_free_
char *w
= NULL
;
1246 union in_addr_union a
;
1247 struct in_addr_data
*m
;
1250 r
= extract_first_word(&rvalue
, &w
, NULL
, 0);
1254 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Invalid syntax, ignoring: %s", rvalue
);
1260 r
= in_addr_from_string_auto(w
, &family
, &a
);
1262 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Failed to parse dns server address, ignoring: %s", w
);
1266 m
= reallocarray(n
->dns
, n
->n_dns
+ 1, sizeof(struct in_addr_data
));
1270 m
[n
->n_dns
++] = (struct in_addr_data
) {
1281 int config_parse_dnssec_negative_trust_anchors(
1283 const char *filename
,
1285 const char *section
,
1286 unsigned section_line
,
1293 const char *p
= rvalue
;
1301 if (isempty(rvalue
)) {
1302 n
->dnssec_negative_trust_anchors
= set_free_free(n
->dnssec_negative_trust_anchors
);
1307 _cleanup_free_
char *w
= NULL
;
1309 r
= extract_first_word(&p
, &w
, NULL
, 0);
1311 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Failed to extract negative trust anchor domain, ignoring: %s", rvalue
);
1317 r
= dns_name_is_valid(w
);
1319 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "%s is not a valid domain name, ignoring.", w
);
1323 r
= set_ensure_allocated(&n
->dnssec_negative_trust_anchors
, &dns_name_hash_ops
);
1327 r
= set_put(n
->dnssec_negative_trust_anchors
, w
);
1337 int config_parse_ntp(
1339 const char *filename
,
1341 const char *section
,
1342 unsigned section_line
,
1356 if (isempty(rvalue
)) {
1362 _cleanup_free_
char *w
= NULL
;
1364 r
= extract_first_word(&rvalue
, &w
, NULL
, 0);
1368 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Failed to extract NTP server name, ignoring: %s", rvalue
);
1374 r
= dns_name_is_valid_or_address(w
);
1376 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "%s is not a valid domain name or IP address, ignoring.", w
);
1380 r
= strv_push(l
, w
);
1390 int config_parse_dhcp_user_class(
1392 const char *filename
,
1394 const char *section
,
1395 unsigned section_line
,
1409 if (isempty(rvalue
)) {
1415 _cleanup_free_
char *w
= NULL
;
1417 r
= extract_first_word(&rvalue
, &w
, NULL
, 0);
1421 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Failed to split user classes option, ignoring: %s", rvalue
);
1427 if (strlen(w
) > 255) {
1428 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "%s length is not in the range 1-255, ignoring.", w
);
1432 r
= strv_push(l
, w
);
1442 int config_parse_dhcp_route_table(const char *unit
,
1443 const char *filename
,
1445 const char *section
,
1446 unsigned section_line
,
1452 Network
*network
= data
;
1461 r
= safe_atou32(rvalue
, &rt
);
1463 log_syntax(unit
, LOG_ERR
, filename
, line
, r
,
1464 "Unable to read RouteTable, ignoring assignment: %s", rvalue
);
1468 network
->dhcp_route_table
= rt
;
1469 network
->dhcp_route_table_set
= true;
1474 DEFINE_CONFIG_PARSE_ENUM(config_parse_dhcp_use_domains
, dhcp_use_domains
, DHCPUseDomains
, "Failed to parse DHCP use domains setting");
1476 static const char* const dhcp_use_domains_table
[_DHCP_USE_DOMAINS_MAX
] = {
1477 [DHCP_USE_DOMAINS_NO
] = "no",
1478 [DHCP_USE_DOMAINS_ROUTE
] = "route",
1479 [DHCP_USE_DOMAINS_YES
] = "yes",
1482 DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(dhcp_use_domains
, DHCPUseDomains
, DHCP_USE_DOMAINS_YES
);
1484 DEFINE_CONFIG_PARSE_ENUM(config_parse_lldp_mode
, lldp_mode
, LLDPMode
, "Failed to parse LLDP= setting.");
1486 static const char* const lldp_mode_table
[_LLDP_MODE_MAX
] = {
1487 [LLDP_MODE_NO
] = "no",
1488 [LLDP_MODE_YES
] = "yes",
1489 [LLDP_MODE_ROUTERS_ONLY
] = "routers-only",
1492 DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(lldp_mode
, LLDPMode
, LLDP_MODE_YES
);