1 /* SPDX-License-Identifier: LGPL-2.1+ */
3 This file is part of systemd.
5 Copyright 2013 Tom Gundersen <teg@jklm.no>
7 systemd is free software; you can redistribute it and/or modify it
8 under the terms of the GNU Lesser General Public License as published by
9 the Free Software Foundation; either version 2.1 of the License, or
10 (at your option) any later version.
12 systemd is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Lesser General Public License for more details.
17 You should have received a copy of the GNU Lesser General Public License
18 along with systemd; If not, see <http://www.gnu.org/licenses/>.
24 #include "alloc-util.h"
25 #include "conf-files.h"
26 #include "conf-parser.h"
27 #include "dns-domain.h"
29 #include "hostname-util.h"
30 #include "in-addr-util.h"
31 #include "network-internal.h"
32 #include "networkd-manager.h"
33 #include "networkd-network.h"
34 #include "parse-util.h"
36 #include "stat-util.h"
37 #include "string-table.h"
38 #include "string-util.h"
42 static void network_config_hash_func(const void *p
, struct siphash
*state
) {
43 const NetworkConfigSection
*c
= p
;
45 siphash24_compress(c
->filename
, strlen(c
->filename
), state
);
46 siphash24_compress(&c
->line
, sizeof(c
->line
), state
);
49 static int network_config_compare_func(const void *a
, const void *b
) {
50 const NetworkConfigSection
*x
= a
, *y
= b
;
53 r
= strcmp(x
->filename
, y
->filename
);
57 return y
->line
- x
->line
;
60 const struct hash_ops network_config_hash_ops
= {
61 .hash
= network_config_hash_func
,
62 .compare
= network_config_compare_func
,
65 int network_config_section_new(const char *filename
, unsigned line
, NetworkConfigSection
**s
) {
66 NetworkConfigSection
*cs
;
68 cs
= malloc0(offsetof(NetworkConfigSection
, filename
) + strlen(filename
) + 1);
72 strcpy(cs
->filename
, filename
);
81 void network_config_section_free(NetworkConfigSection
*cs
) {
85 /* Set defaults following RFC7844 */
86 void network_apply_anonymize_if_set(Network
*network
) {
87 if (!network
->dhcp_anonymize
)
90 SHOULD NOT send the Host Name option */
91 network
->dhcp_send_hostname
= false;
92 /* RFC7844 section 3.:
93 MAY contain the Client Identifier option
95 clients MUST use client identifiers based solely
96 on the link-layer address */
97 /* NOTE: Using MAC, as it does not reveal extra information,
98 * and some servers might not answer if this option is not sent */
99 network
->dhcp_client_identifier
= DHCP_CLIENT_ID_MAC
;
101 SHOULD NOT use the Vendor Class Identifier option */
102 /* NOTE: it was not initiallized to any value in network_load_one. */
103 network
->dhcp_vendor_class_identifier
= false;
104 /* RFC7844 section 3.6.:
105 The client intending to protect its privacy SHOULD only request a
106 minimal number of options in the PRL and SHOULD also randomly shuffle
107 the ordering of option codes in the PRL. If this random ordering
108 cannot be implemented, the client MAY order the option codes in the
109 PRL by option code number (lowest to highest).
111 /* NOTE: dhcp_use_mtu is false by default,
112 * though it was not initiallized to any value in network_load_one.
113 * Maybe there should be another var called *send*?
114 * (to use the MTU sent by the server but to do not send
115 * the option in the PRL). */
116 network
->dhcp_use_mtu
= false;
117 /* NOTE: when Anonymize=yes, the PRL route options are sent by default,
118 * but this is needed to use them. */
119 network
->dhcp_use_routes
= true;
120 /* RFC7844 section 3.6.
121 * same comments as previous option */
122 network
->dhcp_use_timezone
= false;
125 static int network_load_one(Manager
*manager
, const char *filename
) {
126 _cleanup_network_free_ Network
*network
= NULL
;
127 _cleanup_fclose_
FILE *file
= NULL
;
129 const char *dropin_dirname
;
137 file
= fopen(filename
, "re");
145 if (null_or_empty_fd(fileno(file
))) {
146 log_debug("Skipping empty file: %s", filename
);
150 network
= new0(Network
, 1);
154 network
->manager
= manager
;
156 LIST_HEAD_INIT(network
->static_addresses
);
157 LIST_HEAD_INIT(network
->static_routes
);
158 LIST_HEAD_INIT(network
->static_fdb_entries
);
159 LIST_HEAD_INIT(network
->ipv6_proxy_ndp_addresses
);
160 LIST_HEAD_INIT(network
->address_labels
);
161 LIST_HEAD_INIT(network
->static_prefixes
);
162 LIST_HEAD_INIT(network
->rules
);
164 network
->stacked_netdevs
= hashmap_new(&string_hash_ops
);
165 if (!network
->stacked_netdevs
)
168 network
->addresses_by_section
= hashmap_new(&network_config_hash_ops
);
169 if (!network
->addresses_by_section
)
172 network
->routes_by_section
= hashmap_new(&network_config_hash_ops
);
173 if (!network
->routes_by_section
)
176 network
->fdb_entries_by_section
= hashmap_new(NULL
);
177 if (!network
->fdb_entries_by_section
)
180 network
->address_labels_by_section
= hashmap_new(&network_config_hash_ops
);
181 if (!network
->address_labels_by_section
)
184 network
->prefixes_by_section
= hashmap_new(&network_config_hash_ops
);
185 if (!network
->prefixes_by_section
)
188 network
->rules_by_section
= hashmap_new(&network_config_hash_ops
);
189 if (!network
->rules_by_section
)
192 network
->filename
= strdup(filename
);
193 if (!network
->filename
)
196 network
->name
= strdup(basename(filename
));
200 d
= strrchr(network
->name
, '.');
204 assert(streq(d
, ".network"));
208 network
->dhcp
= ADDRESS_FAMILY_NO
;
209 network
->dhcp_use_ntp
= true;
210 network
->dhcp_use_dns
= true;
211 network
->dhcp_use_hostname
= true;
212 network
->dhcp_use_routes
= true;
213 /* NOTE: this var might be overwriten by network_apply_anonymize_if_set */
214 network
->dhcp_send_hostname
= true;
215 /* To enable/disable RFC7844 Anonymity Profiles */
216 network
->dhcp_anonymize
= false;
217 network
->dhcp_route_metric
= DHCP_ROUTE_METRIC
;
218 /* NOTE: this var might be overwrite by network_apply_anonymize_if_set */
219 network
->dhcp_client_identifier
= DHCP_CLIENT_ID_DUID
;
220 network
->dhcp_route_table
= RT_TABLE_MAIN
;
221 network
->dhcp_route_table_set
= false;
222 /* NOTE: the following vars were not set to any default,
223 * even if they are commented in the man?
224 * These vars might be overwriten by network_apply_anonymize_if_set */
225 network
->dhcp_vendor_class_identifier
= false;
226 /* NOTE: from man: UseMTU=... Defaults to false*/
227 network
->dhcp_use_mtu
= false;
228 /* NOTE: from man: UseTimezone=... Defaults to "no".*/
229 network
->dhcp_use_timezone
= false;
231 network
->dhcp_server_emit_dns
= true;
232 network
->dhcp_server_emit_ntp
= true;
233 network
->dhcp_server_emit_router
= true;
234 network
->dhcp_server_emit_timezone
= true;
236 network
->router_emit_dns
= true;
237 network
->router_emit_domains
= true;
239 network
->use_bpdu
= true;
240 network
->allow_port_to_be_root
= true;
241 network
->unicast_flood
= true;
242 network
->priority
= LINK_BRIDGE_PORT_PRIORITY_INVALID
;
244 network
->lldp_mode
= LLDP_MODE_ROUTERS_ONLY
;
246 network
->llmnr
= RESOLVE_SUPPORT_YES
;
247 network
->mdns
= RESOLVE_SUPPORT_NO
;
248 network
->dnssec_mode
= _DNSSEC_MODE_INVALID
;
250 network
->link_local
= ADDRESS_FAMILY_IPV6
;
252 network
->ipv6_privacy_extensions
= IPV6_PRIVACY_EXTENSIONS_NO
;
253 network
->ipv6_accept_ra
= -1;
254 network
->ipv6_dad_transmits
= -1;
255 network
->ipv6_hop_limit
= -1;
256 network
->ipv6_proxy_ndp
= -1;
257 network
->duid
.type
= _DUID_TYPE_INVALID
;
258 network
->proxy_arp
= -1;
260 network
->ipv6_accept_ra_use_dns
= true;
261 network
->ipv6_accept_ra_route_table
= RT_TABLE_MAIN
;
263 dropin_dirname
= strjoina(network
->name
, ".network.d");
265 r
= config_parse_many(filename
, network_dirs
, dropin_dirname
,
271 "RoutingPolicyRule\0"
274 "DHCPv4\0" /* compat */
277 "IPv6NDPProxyAddress\0"
281 "IPv6PrefixDelegation\0"
283 config_item_perf_lookup
, network_network_gperf_lookup
,
284 CONFIG_PARSE_WARN
, network
);
288 network_apply_anonymize_if_set(network
);
290 /* IPMasquerade=yes implies IPForward=yes */
291 if (network
->ip_masquerade
)
292 network
->ip_forward
|= ADDRESS_FAMILY_IPV4
;
294 LIST_PREPEND(networks
, manager
->networks
, network
);
296 r
= hashmap_ensure_allocated(&manager
->networks_by_name
, &string_hash_ops
);
300 r
= hashmap_put(manager
->networks_by_name
, network
->name
, network
);
304 LIST_FOREACH(routes
, route
, network
->static_routes
) {
305 if (!route
->family
) {
306 log_warning("Route section without Gateway field configured in %s. "
307 "Ignoring", filename
);
312 LIST_FOREACH(addresses
, address
, network
->static_addresses
) {
313 if (!address
->family
) {
314 log_warning("Address section without Address field configured in %s. "
315 "Ignoring", filename
);
325 int network_load(Manager
*manager
) {
327 _cleanup_strv_free_
char **files
= NULL
;
333 while ((network
= manager
->networks
))
334 network_free(network
);
336 r
= conf_files_list_strv(&files
, ".network", NULL
, 0, network_dirs
);
338 return log_error_errno(r
, "Failed to enumerate network files: %m");
340 STRV_FOREACH_BACKWARDS(f
, files
) {
341 r
= network_load_one(manager
, *f
);
349 void network_free(Network
*network
) {
350 IPv6ProxyNDPAddress
*ipv6_proxy_ndp_address
;
351 RoutingPolicyRule
*rule
;
363 free(network
->filename
);
365 free(network
->match_mac
);
366 strv_free(network
->match_path
);
367 strv_free(network
->match_driver
);
368 strv_free(network
->match_type
);
369 strv_free(network
->match_name
);
371 free(network
->description
);
372 free(network
->dhcp_vendor_class_identifier
);
373 free(network
->dhcp_hostname
);
377 strv_free(network
->ntp
);
379 strv_free(network
->search_domains
);
380 strv_free(network
->route_domains
);
381 strv_free(network
->bind_carrier
);
383 netdev_unref(network
->bridge
);
384 netdev_unref(network
->bond
);
385 netdev_unref(network
->vrf
);
387 HASHMAP_FOREACH(netdev
, network
->stacked_netdevs
, i
) {
388 hashmap_remove(network
->stacked_netdevs
, netdev
->ifname
);
389 netdev_unref(netdev
);
391 hashmap_free(network
->stacked_netdevs
);
393 while ((route
= network
->static_routes
))
396 while ((address
= network
->static_addresses
))
397 address_free(address
);
399 while ((fdb_entry
= network
->static_fdb_entries
))
400 fdb_entry_free(fdb_entry
);
402 while ((ipv6_proxy_ndp_address
= network
->ipv6_proxy_ndp_addresses
))
403 ipv6_proxy_ndp_address_free(ipv6_proxy_ndp_address
);
405 while ((label
= network
->address_labels
))
406 address_label_free(label
);
408 while ((prefix
= network
->static_prefixes
))
411 while ((rule
= network
->rules
))
412 routing_policy_rule_free(rule
);
414 hashmap_free(network
->addresses_by_section
);
415 hashmap_free(network
->routes_by_section
);
416 hashmap_free(network
->fdb_entries_by_section
);
417 hashmap_free(network
->address_labels_by_section
);
418 hashmap_free(network
->prefixes_by_section
);
419 hashmap_free(network
->rules_by_section
);
421 if (network
->manager
) {
422 if (network
->manager
->networks
)
423 LIST_REMOVE(networks
, network
->manager
->networks
, network
);
425 if (network
->manager
->networks_by_name
)
426 hashmap_remove(network
->manager
->networks_by_name
, network
->name
);
431 condition_free_list(network
->match_host
);
432 condition_free_list(network
->match_virt
);
433 condition_free_list(network
->match_kernel
);
434 condition_free_list(network
->match_arch
);
436 free(network
->dhcp_server_timezone
);
437 free(network
->dhcp_server_dns
);
438 free(network
->dhcp_server_ntp
);
440 set_free_free(network
->dnssec_negative_trust_anchors
);
445 int network_get_by_name(Manager
*manager
, const char *name
, Network
**ret
) {
452 network
= hashmap_get(manager
->networks_by_name
, name
);
461 int network_get(Manager
*manager
, struct udev_device
*device
,
462 const char *ifname
, const struct ether_addr
*address
,
465 struct udev_device
*parent
;
466 const char *path
= NULL
, *parent_driver
= NULL
, *driver
= NULL
, *devtype
= NULL
;
472 path
= udev_device_get_property_value(device
, "ID_PATH");
474 parent
= udev_device_get_parent(device
);
476 parent_driver
= udev_device_get_driver(parent
);
478 driver
= udev_device_get_property_value(device
, "ID_NET_DRIVER");
480 devtype
= udev_device_get_devtype(device
);
483 LIST_FOREACH(networks
, network
, manager
->networks
) {
484 if (net_match_config(network
->match_mac
, network
->match_path
,
485 network
->match_driver
, network
->match_type
,
486 network
->match_name
, network
->match_host
,
487 network
->match_virt
, network
->match_kernel
,
489 address
, path
, parent_driver
, driver
,
491 if (network
->match_name
&& device
) {
493 uint8_t name_assign_type
= NET_NAME_UNKNOWN
;
495 attr
= udev_device_get_sysattr_value(device
, "name_assign_type");
497 (void) safe_atou8(attr
, &name_assign_type
);
499 if (name_assign_type
== NET_NAME_ENUM
)
500 log_warning("%s: found matching network '%s', based on potentially unpredictable ifname",
501 ifname
, network
->filename
);
503 log_debug("%s: found matching network '%s'", ifname
, network
->filename
);
505 log_debug("%s: found matching network '%s'", ifname
, network
->filename
);
517 int network_apply(Network
*network
, Link
*link
) {
523 link
->network
= network
;
525 if (network
->ipv4ll_route
) {
528 r
= route_new_static(network
, NULL
, 0, &route
);
532 r
= inet_pton(AF_INET
, "169.254.0.0", &route
->dst
.in
);
538 route
->family
= AF_INET
;
539 route
->dst_prefixlen
= 16;
540 route
->scope
= RT_SCOPE_LINK
;
541 route
->priority
= IPV4LL_ROUTE_METRIC
;
542 route
->protocol
= RTPROT_STATIC
;
545 if (network
->n_dns
> 0 ||
546 !strv_isempty(network
->ntp
) ||
547 !strv_isempty(network
->search_domains
) ||
548 !strv_isempty(network
->route_domains
))
554 bool network_has_static_ipv6_addresses(Network
*network
) {
559 LIST_FOREACH(addresses
, address
, network
->static_addresses
) {
560 if (address
->family
== AF_INET6
)
567 int config_parse_netdev(const char *unit
,
568 const char *filename
,
571 unsigned section_line
,
577 Network
*network
= userdata
;
578 _cleanup_free_
char *kind_string
= NULL
;
589 kind_string
= strdup(lvalue
);
593 /* the keys are CamelCase versions of the kind */
594 for (p
= kind_string
; *p
; p
++)
597 kind
= netdev_kind_from_string(kind_string
);
598 if (kind
== _NETDEV_KIND_INVALID
) {
599 log_syntax(unit
, LOG_ERR
, filename
, line
, 0, "Invalid NetDev kind: %s", lvalue
);
603 r
= netdev_get(network
->manager
, rvalue
, &netdev
);
605 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "%s could not be found, ignoring assignment: %s", lvalue
, rvalue
);
609 if (netdev
->kind
!= kind
) {
610 log_syntax(unit
, LOG_ERR
, filename
, line
, 0, "NetDev is not a %s, ignoring assignment: %s", lvalue
, rvalue
);
615 case NETDEV_KIND_BRIDGE
:
616 network
->bridge
= netdev
;
619 case NETDEV_KIND_BOND
:
620 network
->bond
= netdev
;
623 case NETDEV_KIND_VRF
:
624 network
->vrf
= netdev
;
627 case NETDEV_KIND_VLAN
:
628 case NETDEV_KIND_MACVLAN
:
629 case NETDEV_KIND_MACVTAP
:
630 case NETDEV_KIND_IPVLAN
:
631 case NETDEV_KIND_VXLAN
:
632 case NETDEV_KIND_VCAN
:
633 r
= hashmap_put(network
->stacked_netdevs
, netdev
->ifname
, netdev
);
635 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Can not add NetDev '%s' to network: %m", rvalue
);
641 assert_not_reached("Can not parse NetDev");
649 int config_parse_domains(
651 const char *filename
,
654 unsigned section_line
,
669 if (isempty(rvalue
)) {
670 n
->search_domains
= strv_free(n
->search_domains
);
671 n
->route_domains
= strv_free(n
->route_domains
);
677 _cleanup_free_
char *w
= NULL
, *normalized
= NULL
;
681 r
= extract_first_word(&p
, &w
, NULL
, 0);
683 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Failed to extract search or route domain, ignoring: %s", rvalue
);
689 is_route
= w
[0] == '~';
690 domain
= is_route
? w
+ 1 : w
;
692 if (dns_name_is_root(domain
) || streq(domain
, "*")) {
693 /* If the root domain appears as is, or the special token "*" is found, we'll consider this as
694 * routing domain, unconditionally. */
696 domain
= "."; /* make sure we don't allow empty strings, thus write the root domain as "." */
699 r
= dns_name_normalize(domain
, &normalized
);
701 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "'%s' is not a valid domain name, ignoring.", domain
);
707 if (is_localhost(domain
)) {
708 log_syntax(unit
, LOG_ERR
, filename
, line
, 0, "'localhost' domain names may not be configure as search or route domains, ignoring assignment: %s", domain
);
714 r
= strv_extend(&n
->route_domains
, domain
);
719 r
= strv_extend(&n
->search_domains
, domain
);
725 strv_uniq(n
->route_domains
);
726 strv_uniq(n
->search_domains
);
731 int config_parse_tunnel(const char *unit
,
732 const char *filename
,
735 unsigned section_line
,
741 Network
*network
= userdata
;
750 r
= netdev_get(network
->manager
, rvalue
, &netdev
);
752 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Tunnel is invalid, ignoring assignment: %s", rvalue
);
756 if (!IN_SET(netdev
->kind
,
762 NETDEV_KIND_IP6GRETAP
,
765 NETDEV_KIND_IP6TNL
)) {
766 log_syntax(unit
, LOG_ERR
, filename
, line
, 0,
767 "NetDev is not a tunnel, ignoring assignment: %s", rvalue
);
771 r
= hashmap_put(network
->stacked_netdevs
, netdev
->ifname
, netdev
);
773 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Cannot add VLAN '%s' to network, ignoring: %m", rvalue
);
782 int config_parse_ipv4ll(
784 const char *filename
,
787 unsigned section_line
,
794 AddressFamilyBoolean
*link_local
= data
;
801 /* Note that this is mostly like
802 * config_parse_address_family_boolean(), except that it
803 * applies only to IPv4 */
805 SET_FLAG(*link_local
, ADDRESS_FAMILY_IPV4
, parse_boolean(rvalue
));
810 int config_parse_dhcp(
812 const char *filename
,
815 unsigned section_line
,
822 AddressFamilyBoolean
*dhcp
= data
, s
;
829 /* Note that this is mostly like
830 * config_parse_address_family_boolean(), except that it
831 * understands some old names for the enum values */
833 s
= address_family_boolean_from_string(rvalue
);
836 /* Previously, we had a slightly different enum here,
837 * support its values for compatbility. */
839 if (streq(rvalue
, "none"))
840 s
= ADDRESS_FAMILY_NO
;
841 else if (streq(rvalue
, "v4"))
842 s
= ADDRESS_FAMILY_IPV4
;
843 else if (streq(rvalue
, "v6"))
844 s
= ADDRESS_FAMILY_IPV6
;
845 else if (streq(rvalue
, "both"))
846 s
= ADDRESS_FAMILY_YES
;
848 log_syntax(unit
, LOG_ERR
, filename
, line
, 0, "Failed to parse DHCP option, ignoring: %s", rvalue
);
857 static const char* const dhcp_client_identifier_table
[_DHCP_CLIENT_ID_MAX
] = {
858 [DHCP_CLIENT_ID_MAC
] = "mac",
859 [DHCP_CLIENT_ID_DUID
] = "duid"
862 DEFINE_PRIVATE_STRING_TABLE_LOOKUP_FROM_STRING(dhcp_client_identifier
, DHCPClientIdentifier
);
863 DEFINE_CONFIG_PARSE_ENUM(config_parse_dhcp_client_identifier
, dhcp_client_identifier
, DHCPClientIdentifier
, "Failed to parse client identifier type");
865 int config_parse_ipv6token(
867 const char *filename
,
870 unsigned section_line
,
877 union in_addr_union buffer
;
878 struct in6_addr
*token
= data
;
886 r
= in_addr_from_string(AF_INET6
, rvalue
, &buffer
);
888 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Failed to parse IPv6 token, ignoring: %s", rvalue
);
892 r
= in_addr_is_null(AF_INET6
, &buffer
);
894 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "IPv6 token can not be the ANY address, ignoring: %s", rvalue
);
898 if ((buffer
.in6
.s6_addr32
[0] | buffer
.in6
.s6_addr32
[1]) != 0) {
899 log_syntax(unit
, LOG_ERR
, filename
, line
, 0, "IPv6 token can not be longer than 64 bits, ignoring: %s", rvalue
);
908 static const char* const ipv6_privacy_extensions_table
[_IPV6_PRIVACY_EXTENSIONS_MAX
] = {
909 [IPV6_PRIVACY_EXTENSIONS_NO
] = "no",
910 [IPV6_PRIVACY_EXTENSIONS_PREFER_PUBLIC
] = "prefer-public",
911 [IPV6_PRIVACY_EXTENSIONS_YES
] = "yes",
914 DEFINE_STRING_TABLE_LOOKUP(ipv6_privacy_extensions
, IPv6PrivacyExtensions
);
916 int config_parse_ipv6_privacy_extensions(
918 const char *filename
,
921 unsigned section_line
,
928 IPv6PrivacyExtensions
*ipv6_privacy_extensions
= data
;
934 assert(ipv6_privacy_extensions
);
936 /* Our enum shall be a superset of booleans, hence first try
937 * to parse as boolean, and then as enum */
939 k
= parse_boolean(rvalue
);
941 *ipv6_privacy_extensions
= IPV6_PRIVACY_EXTENSIONS_YES
;
943 *ipv6_privacy_extensions
= IPV6_PRIVACY_EXTENSIONS_NO
;
945 IPv6PrivacyExtensions s
;
947 s
= ipv6_privacy_extensions_from_string(rvalue
);
950 if (streq(rvalue
, "kernel"))
951 s
= _IPV6_PRIVACY_EXTENSIONS_INVALID
;
953 log_syntax(unit
, LOG_ERR
, filename
, line
, 0, "Failed to parse IPv6 privacy extensions option, ignoring: %s", rvalue
);
958 *ipv6_privacy_extensions
= s
;
964 int config_parse_hostname(
966 const char *filename
,
969 unsigned section_line
,
976 char **hostname
= data
, *hn
= NULL
;
983 r
= config_parse_string(unit
, filename
, line
, section
, section_line
, lvalue
, ltype
, rvalue
, &hn
, userdata
);
987 if (!hostname_is_valid(hn
, false)) {
988 log_syntax(unit
, LOG_ERR
, filename
, line
, 0, "Hostname is not valid, ignoring assignment: %s", rvalue
);
994 *hostname
= hostname_cleanup(hn
);
998 int config_parse_timezone(
1000 const char *filename
,
1002 const char *section
,
1003 unsigned section_line
,
1010 char **datap
= data
, *tz
= NULL
;
1017 r
= config_parse_string(unit
, filename
, line
, section
, section_line
, lvalue
, ltype
, rvalue
, &tz
, userdata
);
1021 if (!timezone_is_valid(tz
)) {
1022 log_syntax(unit
, LOG_ERR
, filename
, line
, 0, "Timezone is not valid, ignoring assignment: %s", rvalue
);
1033 int config_parse_dhcp_server_dns(
1035 const char *filename
,
1037 const char *section
,
1038 unsigned section_line
,
1046 const char *p
= rvalue
;
1054 _cleanup_free_
char *w
= NULL
;
1055 struct in_addr a
, *m
;
1057 r
= extract_first_word(&p
, &w
, NULL
, 0);
1061 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Failed to extract word, ignoring: %s", rvalue
);
1067 if (inet_pton(AF_INET
, w
, &a
) <= 0) {
1068 log_syntax(unit
, LOG_ERR
, filename
, line
, 0, "Failed to parse DNS server address, ignoring: %s", w
);
1072 m
= realloc(n
->dhcp_server_dns
, (n
->n_dhcp_server_dns
+ 1) * sizeof(struct in_addr
));
1076 m
[n
->n_dhcp_server_dns
++] = a
;
1077 n
->dhcp_server_dns
= m
;
1083 int config_parse_radv_dns(
1085 const char *filename
,
1087 const char *section
,
1088 unsigned section_line
,
1096 const char *p
= rvalue
;
1104 _cleanup_free_
char *w
= NULL
;
1105 union in_addr_union a
;
1107 r
= extract_first_word(&p
, &w
, NULL
, 0);
1111 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Failed to extract word, ignoring: %s", rvalue
);
1117 if (in_addr_from_string(AF_INET6
, w
, &a
) >= 0) {
1120 m
= realloc(n
->router_dns
, (n
->n_router_dns
+ 1) * sizeof(struct in6_addr
));
1124 m
[n
->n_router_dns
++] = a
.in6
;
1128 log_syntax(unit
, LOG_ERR
, filename
, line
, 0, "Failed to parse DNS server address, ignoring: %s", w
);
1135 int config_parse_radv_search_domains(
1137 const char *filename
,
1139 const char *section
,
1140 unsigned section_line
,
1148 const char *p
= rvalue
;
1156 _cleanup_free_
char *w
= NULL
;
1157 _cleanup_free_
char *idna
= NULL
;
1159 r
= extract_first_word(&p
, &w
, NULL
, 0);
1163 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Failed to extract word, ignoring: %s", rvalue
);
1169 r
= dns_name_apply_idna(w
, &idna
);
1171 r
= strv_push(&n
->router_search_domains
, idna
);
1174 } else if (r
== 0) {
1175 r
= strv_push(&n
->router_search_domains
, w
);
1184 int config_parse_dhcp_server_ntp(
1186 const char *filename
,
1188 const char *section
,
1189 unsigned section_line
,
1197 const char *p
= rvalue
;
1205 _cleanup_free_
char *w
= NULL
;
1206 struct in_addr a
, *m
;
1208 r
= extract_first_word(&p
, &w
, NULL
, 0);
1212 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Failed to extract word, ignoring: %s", rvalue
);
1218 if (inet_pton(AF_INET
, w
, &a
) <= 0) {
1219 log_syntax(unit
, LOG_ERR
, filename
, line
, 0, "Failed to parse NTP server address, ignoring: %s", w
);
1223 m
= realloc(n
->dhcp_server_ntp
, (n
->n_dhcp_server_ntp
+ 1) * sizeof(struct in_addr
));
1227 m
[n
->n_dhcp_server_ntp
++] = a
;
1228 n
->dhcp_server_ntp
= m
;
1232 int config_parse_dns(
1234 const char *filename
,
1236 const char *section
,
1237 unsigned section_line
,
1244 Network
*n
= userdata
;
1252 _cleanup_free_
char *w
= NULL
;
1253 union in_addr_union a
;
1254 struct in_addr_data
*m
;
1257 r
= extract_first_word(&rvalue
, &w
, NULL
, 0);
1261 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Invalid syntax, ignoring: %s", rvalue
);
1267 r
= in_addr_from_string_auto(w
, &family
, &a
);
1269 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Failed to parse dns server address, ignoring: %s", w
);
1273 m
= realloc(n
->dns
, (n
->n_dns
+ 1) * sizeof(struct in_addr_data
));
1277 m
[n
->n_dns
++] = (struct in_addr_data
) {
1288 int config_parse_dnssec_negative_trust_anchors(
1290 const char *filename
,
1292 const char *section
,
1293 unsigned section_line
,
1300 const char *p
= rvalue
;
1308 if (isempty(rvalue
)) {
1309 n
->dnssec_negative_trust_anchors
= set_free_free(n
->dnssec_negative_trust_anchors
);
1314 _cleanup_free_
char *w
= NULL
;
1316 r
= extract_first_word(&p
, &w
, NULL
, 0);
1318 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Failed to extract negative trust anchor domain, ignoring: %s", rvalue
);
1324 r
= dns_name_is_valid(w
);
1326 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "%s is not a valid domain name, ignoring.", w
);
1330 r
= set_ensure_allocated(&n
->dnssec_negative_trust_anchors
, &dns_name_hash_ops
);
1334 r
= set_put(n
->dnssec_negative_trust_anchors
, w
);
1344 int config_parse_ntp(
1346 const char *filename
,
1348 const char *section
,
1349 unsigned section_line
,
1363 if (isempty(rvalue
)) {
1369 _cleanup_free_
char *w
= NULL
;
1371 r
= extract_first_word(&rvalue
, &w
, NULL
, 0);
1375 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Failed to extract NTP server name, ignoring: %s", rvalue
);
1381 r
= dns_name_is_valid_or_address(w
);
1383 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "%s is not a valid domain name or IP address, ignoring.", w
);
1387 r
= strv_push(l
, w
);
1397 int config_parse_dhcp_route_table(const char *unit
,
1398 const char *filename
,
1400 const char *section
,
1401 unsigned section_line
,
1407 Network
*network
= data
;
1416 r
= safe_atou32(rvalue
, &rt
);
1418 log_syntax(unit
, LOG_ERR
, filename
, line
, r
,
1419 "Unable to read RouteTable, ignoring assignment: %s", rvalue
);
1423 network
->dhcp_route_table
= rt
;
1424 network
->dhcp_route_table_set
= true;
1429 DEFINE_CONFIG_PARSE_ENUM(config_parse_dhcp_use_domains
, dhcp_use_domains
, DHCPUseDomains
, "Failed to parse DHCP use domains setting");
1431 static const char* const dhcp_use_domains_table
[_DHCP_USE_DOMAINS_MAX
] = {
1432 [DHCP_USE_DOMAINS_NO
] = "no",
1433 [DHCP_USE_DOMAINS_ROUTE
] = "route",
1434 [DHCP_USE_DOMAINS_YES
] = "yes",
1437 DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(dhcp_use_domains
, DHCPUseDomains
, DHCP_USE_DOMAINS_YES
);
1439 DEFINE_CONFIG_PARSE_ENUM(config_parse_lldp_mode
, lldp_mode
, LLDPMode
, "Failed to parse LLDP= setting.");
1441 static const char* const lldp_mode_table
[_LLDP_MODE_MAX
] = {
1442 [LLDP_MODE_NO
] = "no",
1443 [LLDP_MODE_YES
] = "yes",
1444 [LLDP_MODE_ROUTERS_ONLY
] = "routers-only",
1447 DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(lldp_mode
, LLDPMode
, LLDP_MODE_YES
);