2 This file is part of systemd.
4 Copyright 2013 Tom Gundersen <teg@jklm.no>
6 systemd is free software; you can redistribute it and/or modify it
7 under the terms of the GNU Lesser General Public License as published by
8 the Free Software Foundation; either version 2.1 of the License, or
9 (at your option) any later version.
11 systemd is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Lesser General Public License for more details.
16 You should have received a copy of the GNU Lesser General Public License
17 along with systemd; If not, see <http://www.gnu.org/licenses/>.
23 #include "alloc-util.h"
24 #include "conf-files.h"
25 #include "conf-parser.h"
26 #include "dns-domain.h"
28 #include "hostname-util.h"
29 #include "in-addr-util.h"
30 #include "network-internal.h"
31 #include "networkd-manager.h"
32 #include "networkd-network.h"
33 #include "parse-util.h"
35 #include "stat-util.h"
36 #include "string-table.h"
37 #include "string-util.h"
40 static void network_config_hash_func(const void *p
, struct siphash
*state
) {
41 const NetworkConfigSection
*c
= p
;
43 siphash24_compress(c
->filename
, strlen(c
->filename
), state
);
44 siphash24_compress(&c
->line
, sizeof(c
->line
), state
);
47 static int network_config_compare_func(const void *a
, const void *b
) {
48 const NetworkConfigSection
*x
= a
, *y
= b
;
51 r
= strcmp(x
->filename
, y
->filename
);
55 return y
->line
- x
->line
;
58 const struct hash_ops network_config_hash_ops
= {
59 .hash
= network_config_hash_func
,
60 .compare
= network_config_compare_func
,
63 int network_config_section_new(const char *filename
, unsigned line
, NetworkConfigSection
**s
) {
64 NetworkConfigSection
*cs
;
66 cs
= malloc0(offsetof(NetworkConfigSection
, filename
) + strlen(filename
) + 1);
70 strcpy(cs
->filename
, filename
);
79 void network_config_section_free(NetworkConfigSection
*cs
) {
83 /* Set defaults following RFC7844 */
84 void network_apply_anonymize_if_set(Network
*network
) {
85 if (!network
->dhcp_anonymize
)
88 SHOULD NOT send the Host Name option */
89 network
->dhcp_send_hostname
= false;
90 /* RFC7844 section 3.:
91 MAY contain the Client Identifier option
93 clients MUST use client identifiers based solely
94 on the link-layer address */
95 /* NOTE: Using MAC, as it does not reveal extra information,
96 * and some servers might not answer if this option is not sent */
97 network
->dhcp_client_identifier
= DHCP_CLIENT_ID_MAC
;
99 SHOULD NOT use the Vendor Class Identifier option */
100 /* NOTE: it was not initiallized to any value in network_load_one. */
101 network
->dhcp_vendor_class_identifier
= false;
102 /* RFC7844 section 3.6.:
103 The client intending to protect its privacy SHOULD only request a
104 minimal number of options in the PRL and SHOULD also randomly shuffle
105 the ordering of option codes in the PRL. If this random ordering
106 cannot be implemented, the client MAY order the option codes in the
107 PRL by option code number (lowest to highest).
109 /* NOTE: dhcp_use_mtu is false by default,
110 * though it was not initiallized to any value in network_load_one.
111 * Maybe there should be another var called *send*?
112 * (to use the MTU sent by the server but to do not send
113 * the option in the PRL). */
114 network
->dhcp_use_mtu
= false;
115 /* RFC7844 section 3.6.
116 * same comments as previous option */
117 network
->dhcp_use_routes
= false;
118 /* RFC7844 section 3.6.
119 * same comments as previous option */
120 network
->dhcp_use_timezone
= false;
123 static int network_load_one(Manager
*manager
, const char *filename
) {
124 _cleanup_network_free_ Network
*network
= NULL
;
125 _cleanup_fclose_
FILE *file
= NULL
;
127 const char *dropin_dirname
;
135 file
= fopen(filename
, "re");
143 if (null_or_empty_fd(fileno(file
))) {
144 log_debug("Skipping empty file: %s", filename
);
148 network
= new0(Network
, 1);
152 network
->manager
= manager
;
154 LIST_HEAD_INIT(network
->static_addresses
);
155 LIST_HEAD_INIT(network
->static_routes
);
156 LIST_HEAD_INIT(network
->static_fdb_entries
);
157 LIST_HEAD_INIT(network
->ipv6_proxy_ndp_addresses
);
158 LIST_HEAD_INIT(network
->address_labels
);
159 LIST_HEAD_INIT(network
->static_prefixes
);
161 network
->stacked_netdevs
= hashmap_new(&string_hash_ops
);
162 if (!network
->stacked_netdevs
)
165 network
->addresses_by_section
= hashmap_new(&network_config_hash_ops
);
166 if (!network
->addresses_by_section
)
169 network
->routes_by_section
= hashmap_new(&network_config_hash_ops
);
170 if (!network
->routes_by_section
)
173 network
->fdb_entries_by_section
= hashmap_new(NULL
);
174 if (!network
->fdb_entries_by_section
)
177 network
->address_labels_by_section
= hashmap_new(&network_config_hash_ops
);
178 if (!network
->address_labels_by_section
)
181 network
->prefixes_by_section
= hashmap_new(&network_config_hash_ops
);
182 if (!network
->prefixes_by_section
)
185 network
->filename
= strdup(filename
);
186 if (!network
->filename
)
189 network
->name
= strdup(basename(filename
));
193 d
= strrchr(network
->name
, '.');
197 assert(streq(d
, ".network"));
201 network
->dhcp
= ADDRESS_FAMILY_NO
;
202 network
->dhcp_use_ntp
= true;
203 network
->dhcp_use_dns
= true;
204 network
->dhcp_use_hostname
= true;
205 /* NOTE: this var might be overwriten by network_apply_anonymize_if_set */
206 network
->dhcp_use_routes
= true;
207 /* NOTE: this var might be overwriten by network_apply_anonymize_if_set */
208 network
->dhcp_send_hostname
= true;
209 /* To enable/disable RFC7844 Anonymity Profiles */
210 network
->dhcp_anonymize
= false;
211 network
->dhcp_route_metric
= DHCP_ROUTE_METRIC
;
212 /* NOTE: this var might be overwrite by network_apply_anonymize_if_set */
213 network
->dhcp_client_identifier
= DHCP_CLIENT_ID_DUID
;
214 network
->dhcp_route_table
= RT_TABLE_MAIN
;
215 /* NOTE: the following vars were not set to any default,
216 * even if they are commented in the man?
217 * These vars might be overwriten by network_apply_anonymize_if_set */
218 network
->dhcp_vendor_class_identifier
= false;
219 /* NOTE: from man: UseMTU=... Defaults to false*/
220 network
->dhcp_use_mtu
= false;
221 /* NOTE: from man: UseTimezone=... Defaults to "no".*/
222 network
->dhcp_use_timezone
= false;
224 network
->dhcp_server_emit_dns
= true;
225 network
->dhcp_server_emit_ntp
= true;
226 network
->dhcp_server_emit_router
= true;
227 network
->dhcp_server_emit_timezone
= true;
229 network
->use_bpdu
= true;
230 network
->allow_port_to_be_root
= true;
231 network
->unicast_flood
= true;
232 network
->priority
= LINK_BRIDGE_PORT_PRIORITY_INVALID
;
234 network
->lldp_mode
= LLDP_MODE_ROUTERS_ONLY
;
236 network
->llmnr
= RESOLVE_SUPPORT_YES
;
237 network
->mdns
= RESOLVE_SUPPORT_NO
;
238 network
->dnssec_mode
= _DNSSEC_MODE_INVALID
;
240 network
->link_local
= ADDRESS_FAMILY_IPV6
;
242 network
->ipv6_privacy_extensions
= IPV6_PRIVACY_EXTENSIONS_NO
;
243 network
->ipv6_accept_ra
= -1;
244 network
->ipv6_dad_transmits
= -1;
245 network
->ipv6_hop_limit
= -1;
246 network
->ipv6_proxy_ndp
= -1;
247 network
->duid
.type
= _DUID_TYPE_INVALID
;
248 network
->proxy_arp
= -1;
250 network
->ipv6_accept_ra_use_dns
= true;
251 network
->ipv6_accept_ra_route_table
= RT_TABLE_MAIN
;
253 dropin_dirname
= strjoina(network
->name
, ".network.d");
255 r
= config_parse_many(filename
, network_dirs
, dropin_dirname
,
263 "DHCPv4\0" /* compat */
266 "IPv6NDPProxyAddress\0"
270 "IPv6PrefixDelegation\0"
272 config_item_perf_lookup
, network_network_gperf_lookup
,
277 network_apply_anonymize_if_set(network
);
279 /* IPMasquerade=yes implies IPForward=yes */
280 if (network
->ip_masquerade
)
281 network
->ip_forward
|= ADDRESS_FAMILY_IPV4
;
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
) {
343 IPv6ProxyNDPAddress
*ipv6_proxy_ndp_address
;
351 free(network
->filename
);
353 free(network
->match_mac
);
354 strv_free(network
->match_path
);
355 strv_free(network
->match_driver
);
356 strv_free(network
->match_type
);
357 strv_free(network
->match_name
);
359 free(network
->description
);
360 free(network
->dhcp_vendor_class_identifier
);
361 free(network
->dhcp_hostname
);
365 strv_free(network
->ntp
);
367 strv_free(network
->search_domains
);
368 strv_free(network
->route_domains
);
369 strv_free(network
->bind_carrier
);
371 netdev_unref(network
->bridge
);
372 netdev_unref(network
->bond
);
373 netdev_unref(network
->vrf
);
375 HASHMAP_FOREACH(netdev
, network
->stacked_netdevs
, i
) {
376 hashmap_remove(network
->stacked_netdevs
, netdev
->ifname
);
377 netdev_unref(netdev
);
379 hashmap_free(network
->stacked_netdevs
);
381 while ((route
= network
->static_routes
))
384 while ((address
= network
->static_addresses
))
385 address_free(address
);
387 while ((fdb_entry
= network
->static_fdb_entries
))
388 fdb_entry_free(fdb_entry
);
390 while ((ipv6_proxy_ndp_address
= network
->ipv6_proxy_ndp_addresses
))
391 ipv6_proxy_ndp_address_free(ipv6_proxy_ndp_address
);
393 while ((label
= network
->address_labels
))
394 address_label_free(label
);
396 while ((prefix
= network
->static_prefixes
))
399 hashmap_free(network
->addresses_by_section
);
400 hashmap_free(network
->routes_by_section
);
401 hashmap_free(network
->fdb_entries_by_section
);
402 hashmap_free(network
->address_labels_by_section
);
403 hashmap_free(network
->prefixes_by_section
);
405 if (network
->manager
) {
406 if (network
->manager
->networks
)
407 LIST_REMOVE(networks
, network
->manager
->networks
, network
);
409 if (network
->manager
->networks_by_name
)
410 hashmap_remove(network
->manager
->networks_by_name
, network
->name
);
415 condition_free_list(network
->match_host
);
416 condition_free_list(network
->match_virt
);
417 condition_free_list(network
->match_kernel
);
418 condition_free_list(network
->match_arch
);
420 free(network
->dhcp_server_timezone
);
421 free(network
->dhcp_server_dns
);
422 free(network
->dhcp_server_ntp
);
424 set_free_free(network
->dnssec_negative_trust_anchors
);
429 int network_get_by_name(Manager
*manager
, const char *name
, Network
**ret
) {
436 network
= hashmap_get(manager
->networks_by_name
, name
);
445 int network_get(Manager
*manager
, struct udev_device
*device
,
446 const char *ifname
, const struct ether_addr
*address
,
449 struct udev_device
*parent
;
450 const char *path
= NULL
, *parent_driver
= NULL
, *driver
= NULL
, *devtype
= NULL
;
456 path
= udev_device_get_property_value(device
, "ID_PATH");
458 parent
= udev_device_get_parent(device
);
460 parent_driver
= udev_device_get_driver(parent
);
462 driver
= udev_device_get_property_value(device
, "ID_NET_DRIVER");
464 devtype
= udev_device_get_devtype(device
);
467 LIST_FOREACH(networks
, network
, manager
->networks
) {
468 if (net_match_config(network
->match_mac
, network
->match_path
,
469 network
->match_driver
, network
->match_type
,
470 network
->match_name
, network
->match_host
,
471 network
->match_virt
, network
->match_kernel
,
473 address
, path
, parent_driver
, driver
,
475 if (network
->match_name
&& device
) {
477 uint8_t name_assign_type
= NET_NAME_UNKNOWN
;
479 attr
= udev_device_get_sysattr_value(device
, "name_assign_type");
481 (void) safe_atou8(attr
, &name_assign_type
);
483 if (name_assign_type
== NET_NAME_ENUM
)
484 log_warning("%s: found matching network '%s', based on potentially unpredictable ifname",
485 ifname
, network
->filename
);
487 log_debug("%s: found matching network '%s'", ifname
, network
->filename
);
489 log_debug("%s: found matching network '%s'", ifname
, network
->filename
);
501 int network_apply(Network
*network
, Link
*link
) {
507 link
->network
= network
;
509 if (network
->ipv4ll_route
) {
512 r
= route_new_static(network
, NULL
, 0, &route
);
516 r
= inet_pton(AF_INET
, "169.254.0.0", &route
->dst
.in
);
522 route
->family
= AF_INET
;
523 route
->dst_prefixlen
= 16;
524 route
->scope
= RT_SCOPE_LINK
;
525 route
->priority
= IPV4LL_ROUTE_METRIC
;
526 route
->protocol
= RTPROT_STATIC
;
529 if (network
->n_dns
> 0 ||
530 !strv_isempty(network
->ntp
) ||
531 !strv_isempty(network
->search_domains
) ||
532 !strv_isempty(network
->route_domains
))
538 bool network_has_static_ipv6_addresses(Network
*network
) {
543 LIST_FOREACH(addresses
, address
, network
->static_addresses
) {
544 if (address
->family
== AF_INET6
)
551 int config_parse_netdev(const char *unit
,
552 const char *filename
,
555 unsigned section_line
,
561 Network
*network
= userdata
;
562 _cleanup_free_
char *kind_string
= NULL
;
573 kind_string
= strdup(lvalue
);
577 /* the keys are CamelCase versions of the kind */
578 for (p
= kind_string
; *p
; p
++)
581 kind
= netdev_kind_from_string(kind_string
);
582 if (kind
== _NETDEV_KIND_INVALID
) {
583 log_syntax(unit
, LOG_ERR
, filename
, line
, 0, "Invalid NetDev kind: %s", lvalue
);
587 r
= netdev_get(network
->manager
, rvalue
, &netdev
);
589 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "%s could not be found, ignoring assignment: %s", lvalue
, rvalue
);
593 if (netdev
->kind
!= kind
) {
594 log_syntax(unit
, LOG_ERR
, filename
, line
, 0, "NetDev is not a %s, ignoring assignment: %s", lvalue
, rvalue
);
599 case NETDEV_KIND_BRIDGE
:
600 network
->bridge
= netdev
;
603 case NETDEV_KIND_BOND
:
604 network
->bond
= netdev
;
607 case NETDEV_KIND_VRF
:
608 network
->vrf
= netdev
;
611 case NETDEV_KIND_VLAN
:
612 case NETDEV_KIND_MACVLAN
:
613 case NETDEV_KIND_MACVTAP
:
614 case NETDEV_KIND_IPVLAN
:
615 case NETDEV_KIND_VXLAN
:
616 case NETDEV_KIND_VCAN
:
617 r
= hashmap_put(network
->stacked_netdevs
, netdev
->ifname
, netdev
);
619 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Can not add NetDev '%s' to network: %m", rvalue
);
625 assert_not_reached("Can not parse NetDev");
633 int config_parse_domains(
635 const char *filename
,
638 unsigned section_line
,
653 if (isempty(rvalue
)) {
654 n
->search_domains
= strv_free(n
->search_domains
);
655 n
->route_domains
= strv_free(n
->route_domains
);
661 _cleanup_free_
char *w
= NULL
, *normalized
= NULL
;
665 r
= extract_first_word(&p
, &w
, NULL
, 0);
667 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Failed to extract search or route domain, ignoring: %s", rvalue
);
673 is_route
= w
[0] == '~';
674 domain
= is_route
? w
+ 1 : w
;
676 if (dns_name_is_root(domain
) || streq(domain
, "*")) {
677 /* If the root domain appears as is, or the special token "*" is found, we'll consider this as
678 * routing domain, unconditionally. */
680 domain
= "."; /* make sure we don't allow empty strings, thus write the root domain as "." */
683 r
= dns_name_normalize(domain
, &normalized
);
685 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "'%s' is not a valid domain name, ignoring.", domain
);
691 if (is_localhost(domain
)) {
692 log_syntax(unit
, LOG_ERR
, filename
, line
, 0, "'localhost' domain names may not be configure as search or route domains, ignoring assignment: %s", domain
);
698 r
= strv_extend(&n
->route_domains
, domain
);
703 r
= strv_extend(&n
->search_domains
, domain
);
709 strv_uniq(n
->route_domains
);
710 strv_uniq(n
->search_domains
);
715 int config_parse_tunnel(const char *unit
,
716 const char *filename
,
719 unsigned section_line
,
725 Network
*network
= userdata
;
734 r
= netdev_get(network
->manager
, rvalue
, &netdev
);
736 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Tunnel is invalid, ignoring assignment: %s", rvalue
);
740 if (netdev
->kind
!= NETDEV_KIND_IPIP
&&
741 netdev
->kind
!= NETDEV_KIND_SIT
&&
742 netdev
->kind
!= NETDEV_KIND_GRE
&&
743 netdev
->kind
!= NETDEV_KIND_GRETAP
&&
744 netdev
->kind
!= NETDEV_KIND_IP6GRE
&&
745 netdev
->kind
!= NETDEV_KIND_IP6GRETAP
&&
746 netdev
->kind
!= NETDEV_KIND_VTI
&&
747 netdev
->kind
!= NETDEV_KIND_VTI6
&&
748 netdev
->kind
!= NETDEV_KIND_IP6TNL
750 log_syntax(unit
, LOG_ERR
, filename
, line
, 0,
751 "NetDev is not a tunnel, ignoring assignment: %s", rvalue
);
755 r
= hashmap_put(network
->stacked_netdevs
, netdev
->ifname
, netdev
);
757 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Cannot add VLAN '%s' to network, ignoring: %m", rvalue
);
766 int config_parse_ipv4ll(
768 const char *filename
,
771 unsigned section_line
,
778 AddressFamilyBoolean
*link_local
= data
;
785 /* Note that this is mostly like
786 * config_parse_address_family_boolean(), except that it
787 * applies only to IPv4 */
789 SET_FLAG(*link_local
, ADDRESS_FAMILY_IPV4
, parse_boolean(rvalue
));
794 int config_parse_dhcp(
796 const char *filename
,
799 unsigned section_line
,
806 AddressFamilyBoolean
*dhcp
= data
, s
;
813 /* Note that this is mostly like
814 * config_parse_address_family_boolean(), except that it
815 * understands some old names for the enum values */
817 s
= address_family_boolean_from_string(rvalue
);
820 /* Previously, we had a slightly different enum here,
821 * support its values for compatbility. */
823 if (streq(rvalue
, "none"))
824 s
= ADDRESS_FAMILY_NO
;
825 else if (streq(rvalue
, "v4"))
826 s
= ADDRESS_FAMILY_IPV4
;
827 else if (streq(rvalue
, "v6"))
828 s
= ADDRESS_FAMILY_IPV6
;
829 else if (streq(rvalue
, "both"))
830 s
= ADDRESS_FAMILY_YES
;
832 log_syntax(unit
, LOG_ERR
, filename
, line
, 0, "Failed to parse DHCP option, ignoring: %s", rvalue
);
841 static const char* const dhcp_client_identifier_table
[_DHCP_CLIENT_ID_MAX
] = {
842 [DHCP_CLIENT_ID_MAC
] = "mac",
843 [DHCP_CLIENT_ID_DUID
] = "duid"
846 DEFINE_PRIVATE_STRING_TABLE_LOOKUP_FROM_STRING(dhcp_client_identifier
, DHCPClientIdentifier
);
847 DEFINE_CONFIG_PARSE_ENUM(config_parse_dhcp_client_identifier
, dhcp_client_identifier
, DHCPClientIdentifier
, "Failed to parse client identifier type");
849 int config_parse_ipv6token(
851 const char *filename
,
854 unsigned section_line
,
861 union in_addr_union buffer
;
862 struct in6_addr
*token
= data
;
870 r
= in_addr_from_string(AF_INET6
, rvalue
, &buffer
);
872 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Failed to parse IPv6 token, ignoring: %s", rvalue
);
876 r
= in_addr_is_null(AF_INET6
, &buffer
);
878 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "IPv6 token can not be the ANY address, ignoring: %s", rvalue
);
882 if ((buffer
.in6
.s6_addr32
[0] | buffer
.in6
.s6_addr32
[1]) != 0) {
883 log_syntax(unit
, LOG_ERR
, filename
, line
, 0, "IPv6 token can not be longer than 64 bits, ignoring: %s", rvalue
);
892 static const char* const ipv6_privacy_extensions_table
[_IPV6_PRIVACY_EXTENSIONS_MAX
] = {
893 [IPV6_PRIVACY_EXTENSIONS_NO
] = "no",
894 [IPV6_PRIVACY_EXTENSIONS_PREFER_PUBLIC
] = "prefer-public",
895 [IPV6_PRIVACY_EXTENSIONS_YES
] = "yes",
898 DEFINE_STRING_TABLE_LOOKUP(ipv6_privacy_extensions
, IPv6PrivacyExtensions
);
900 int config_parse_ipv6_privacy_extensions(
902 const char *filename
,
905 unsigned section_line
,
912 IPv6PrivacyExtensions
*ipv6_privacy_extensions
= data
;
918 assert(ipv6_privacy_extensions
);
920 /* Our enum shall be a superset of booleans, hence first try
921 * to parse as boolean, and then as enum */
923 k
= parse_boolean(rvalue
);
925 *ipv6_privacy_extensions
= IPV6_PRIVACY_EXTENSIONS_YES
;
927 *ipv6_privacy_extensions
= IPV6_PRIVACY_EXTENSIONS_NO
;
929 IPv6PrivacyExtensions s
;
931 s
= ipv6_privacy_extensions_from_string(rvalue
);
934 if (streq(rvalue
, "kernel"))
935 s
= _IPV6_PRIVACY_EXTENSIONS_INVALID
;
937 log_syntax(unit
, LOG_ERR
, filename
, line
, 0, "Failed to parse IPv6 privacy extensions option, ignoring: %s", rvalue
);
942 *ipv6_privacy_extensions
= s
;
948 int config_parse_hostname(
950 const char *filename
,
953 unsigned section_line
,
960 char **hostname
= data
, *hn
= NULL
;
967 r
= config_parse_string(unit
, filename
, line
, section
, section_line
, lvalue
, ltype
, rvalue
, &hn
, userdata
);
971 if (!hostname_is_valid(hn
, false)) {
972 log_syntax(unit
, LOG_ERR
, filename
, line
, 0, "Hostname is not valid, ignoring assignment: %s", rvalue
);
978 *hostname
= hostname_cleanup(hn
);
982 int config_parse_timezone(
984 const char *filename
,
987 unsigned section_line
,
994 char **datap
= data
, *tz
= NULL
;
1001 r
= config_parse_string(unit
, filename
, line
, section
, section_line
, lvalue
, ltype
, rvalue
, &tz
, userdata
);
1005 if (!timezone_is_valid(tz
)) {
1006 log_syntax(unit
, LOG_ERR
, filename
, line
, 0, "Timezone is not valid, ignoring assignment: %s", rvalue
);
1017 int config_parse_dhcp_server_dns(
1019 const char *filename
,
1021 const char *section
,
1022 unsigned section_line
,
1030 const char *p
= rvalue
;
1038 _cleanup_free_
char *w
= NULL
;
1039 struct in_addr a
, *m
;
1041 r
= extract_first_word(&p
, &w
, NULL
, 0);
1045 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Failed to extract word, ignoring: %s", rvalue
);
1051 if (inet_pton(AF_INET
, w
, &a
) <= 0) {
1052 log_syntax(unit
, LOG_ERR
, filename
, line
, 0, "Failed to parse DNS server address, ignoring: %s", w
);
1056 m
= realloc(n
->dhcp_server_dns
, (n
->n_dhcp_server_dns
+ 1) * sizeof(struct in_addr
));
1060 m
[n
->n_dhcp_server_dns
++] = a
;
1061 n
->dhcp_server_dns
= m
;
1067 int config_parse_radv_dns(
1069 const char *filename
,
1071 const char *section
,
1072 unsigned section_line
,
1080 const char *p
= rvalue
;
1088 _cleanup_free_
char *w
= NULL
;
1089 union in_addr_union a
;
1091 r
= extract_first_word(&p
, &w
, NULL
, 0);
1095 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Failed to extract word, ignoring: %s", rvalue
);
1101 if (in_addr_from_string(AF_INET6
, w
, &a
) >= 0) {
1104 m
= realloc(n
->router_dns
, (n
->n_router_dns
+ 1) * sizeof(struct in6_addr
));
1108 m
[n
->n_router_dns
++] = a
.in6
;
1112 log_syntax(unit
, LOG_ERR
, filename
, line
, 0, "Failed to parse DNS server address, ignoring: %s", w
);
1119 int config_parse_dhcp_server_ntp(
1121 const char *filename
,
1123 const char *section
,
1124 unsigned section_line
,
1132 const char *p
= rvalue
;
1140 _cleanup_free_
char *w
= NULL
;
1141 struct in_addr a
, *m
;
1143 r
= extract_first_word(&p
, &w
, NULL
, 0);
1147 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Failed to extract word, ignoring: %s", rvalue
);
1153 if (inet_pton(AF_INET
, w
, &a
) <= 0) {
1154 log_syntax(unit
, LOG_ERR
, filename
, line
, 0, "Failed to parse NTP server address, ignoring: %s", w
);
1158 m
= realloc(n
->dhcp_server_ntp
, (n
->n_dhcp_server_ntp
+ 1) * sizeof(struct in_addr
));
1162 m
[n
->n_dhcp_server_ntp
++] = a
;
1163 n
->dhcp_server_ntp
= m
;
1167 int config_parse_dns(
1169 const char *filename
,
1171 const char *section
,
1172 unsigned section_line
,
1179 Network
*n
= userdata
;
1187 _cleanup_free_
char *w
= NULL
;
1188 union in_addr_union a
;
1189 struct in_addr_data
*m
;
1192 r
= extract_first_word(&rvalue
, &w
, NULL
, 0);
1196 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Invalid syntax, ignoring: %s", rvalue
);
1202 r
= in_addr_from_string_auto(w
, &family
, &a
);
1204 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Failed to parse dns server address, ignoring: %s", w
);
1208 m
= realloc(n
->dns
, (n
->n_dns
+ 1) * sizeof(struct in_addr_data
));
1212 m
[n
->n_dns
++] = (struct in_addr_data
) {
1223 int config_parse_dnssec_negative_trust_anchors(
1225 const char *filename
,
1227 const char *section
,
1228 unsigned section_line
,
1235 const char *p
= rvalue
;
1243 if (isempty(rvalue
)) {
1244 n
->dnssec_negative_trust_anchors
= set_free_free(n
->dnssec_negative_trust_anchors
);
1249 _cleanup_free_
char *w
= NULL
;
1251 r
= extract_first_word(&p
, &w
, NULL
, 0);
1253 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Failed to extract negative trust anchor domain, ignoring: %s", rvalue
);
1259 r
= dns_name_is_valid(w
);
1261 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "%s is not a valid domain name, ignoring.", w
);
1265 r
= set_ensure_allocated(&n
->dnssec_negative_trust_anchors
, &dns_name_hash_ops
);
1269 r
= set_put(n
->dnssec_negative_trust_anchors
, w
);
1279 int config_parse_ntp(
1281 const char *filename
,
1283 const char *section
,
1284 unsigned section_line
,
1298 if (isempty(rvalue
)) {
1304 _cleanup_free_
char *w
= NULL
;
1306 r
= extract_first_word(&rvalue
, &w
, NULL
, 0);
1310 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Failed to extract NTP server name, ignoring: %s", rvalue
);
1316 r
= dns_name_is_valid_or_address(w
);
1318 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "%s is not a valid domain name or IP address, ignoring.", w
);
1322 r
= strv_push(l
, w
);
1332 int config_parse_dhcp_route_table(const char *unit
,
1333 const char *filename
,
1335 const char *section
,
1336 unsigned section_line
,
1350 r
= safe_atou32(rvalue
, &rt
);
1352 log_syntax(unit
, LOG_ERR
, filename
, line
, r
,
1353 "Unable to read RouteTable, ignoring assignment: %s", rvalue
);
1357 *((uint32_t *)data
) = rt
;
1362 DEFINE_CONFIG_PARSE_ENUM(config_parse_dhcp_use_domains
, dhcp_use_domains
, DHCPUseDomains
, "Failed to parse DHCP use domains setting");
1364 static const char* const dhcp_use_domains_table
[_DHCP_USE_DOMAINS_MAX
] = {
1365 [DHCP_USE_DOMAINS_NO
] = "no",
1366 [DHCP_USE_DOMAINS_ROUTE
] = "route",
1367 [DHCP_USE_DOMAINS_YES
] = "yes",
1370 DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(dhcp_use_domains
, DHCPUseDomains
, DHCP_USE_DOMAINS_YES
);
1372 DEFINE_CONFIG_PARSE_ENUM(config_parse_lldp_mode
, lldp_mode
, LLDPMode
, "Failed to parse LLDP= setting.");
1374 static const char* const lldp_mode_table
[_LLDP_MODE_MAX
] = {
1375 [LLDP_MODE_NO
] = "no",
1376 [LLDP_MODE_YES
] = "yes",
1377 [LLDP_MODE_ROUTERS_ONLY
] = "routers-only",
1380 DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(lldp_mode
, LLDPMode
, LLDP_MODE_YES
);