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"
41 static void network_config_hash_func(const void *p
, struct siphash
*state
) {
42 const NetworkConfigSection
*c
= p
;
44 siphash24_compress(c
->filename
, strlen(c
->filename
), state
);
45 siphash24_compress(&c
->line
, sizeof(c
->line
), state
);
48 static int network_config_compare_func(const void *a
, const void *b
) {
49 const NetworkConfigSection
*x
= a
, *y
= b
;
52 r
= strcmp(x
->filename
, y
->filename
);
56 return y
->line
- x
->line
;
59 const struct hash_ops network_config_hash_ops
= {
60 .hash
= network_config_hash_func
,
61 .compare
= network_config_compare_func
,
64 int network_config_section_new(const char *filename
, unsigned line
, NetworkConfigSection
**s
) {
65 NetworkConfigSection
*cs
;
67 cs
= malloc0(offsetof(NetworkConfigSection
, filename
) + strlen(filename
) + 1);
71 strcpy(cs
->filename
, filename
);
80 void network_config_section_free(NetworkConfigSection
*cs
) {
84 /* Set defaults following RFC7844 */
85 void network_apply_anonymize_if_set(Network
*network
) {
86 if (!network
->dhcp_anonymize
)
89 SHOULD NOT send the Host Name option */
90 network
->dhcp_send_hostname
= false;
91 /* RFC7844 section 3.:
92 MAY contain the Client Identifier option
94 clients MUST use client identifiers based solely
95 on the link-layer address */
96 /* NOTE: Using MAC, as it does not reveal extra information,
97 * and some servers might not answer if this option is not sent */
98 network
->dhcp_client_identifier
= DHCP_CLIENT_ID_MAC
;
100 SHOULD NOT use the Vendor Class Identifier option */
101 /* NOTE: it was not initiallized to any value in network_load_one. */
102 network
->dhcp_vendor_class_identifier
= false;
103 /* RFC7844 section 3.6.:
104 The client intending to protect its privacy SHOULD only request a
105 minimal number of options in the PRL and SHOULD also randomly shuffle
106 the ordering of option codes in the PRL. If this random ordering
107 cannot be implemented, the client MAY order the option codes in the
108 PRL by option code number (lowest to highest).
110 /* NOTE: dhcp_use_mtu is false by default,
111 * though it was not initiallized to any value in network_load_one.
112 * Maybe there should be another var called *send*?
113 * (to use the MTU sent by the server but to do not send
114 * the option in the PRL). */
115 network
->dhcp_use_mtu
= false;
116 /* NOTE: when Anonymize=yes, the PRL route options are sent by default,
117 * but this is needed to use them. */
118 network
->dhcp_use_routes
= true;
119 /* RFC7844 section 3.6.
120 * same comments as previous option */
121 network
->dhcp_use_timezone
= false;
124 static int network_load_one(Manager
*manager
, const char *filename
) {
125 _cleanup_network_free_ Network
*network
= NULL
;
126 _cleanup_fclose_
FILE *file
= NULL
;
128 const char *dropin_dirname
;
136 file
= fopen(filename
, "re");
144 if (null_or_empty_fd(fileno(file
))) {
145 log_debug("Skipping empty file: %s", filename
);
149 network
= new0(Network
, 1);
153 network
->manager
= manager
;
155 LIST_HEAD_INIT(network
->static_addresses
);
156 LIST_HEAD_INIT(network
->static_routes
);
157 LIST_HEAD_INIT(network
->static_fdb_entries
);
158 LIST_HEAD_INIT(network
->ipv6_proxy_ndp_addresses
);
159 LIST_HEAD_INIT(network
->address_labels
);
160 LIST_HEAD_INIT(network
->static_prefixes
);
161 LIST_HEAD_INIT(network
->rules
);
163 network
->stacked_netdevs
= hashmap_new(&string_hash_ops
);
164 if (!network
->stacked_netdevs
)
167 network
->addresses_by_section
= hashmap_new(&network_config_hash_ops
);
168 if (!network
->addresses_by_section
)
171 network
->routes_by_section
= hashmap_new(&network_config_hash_ops
);
172 if (!network
->routes_by_section
)
175 network
->fdb_entries_by_section
= hashmap_new(NULL
);
176 if (!network
->fdb_entries_by_section
)
179 network
->address_labels_by_section
= hashmap_new(&network_config_hash_ops
);
180 if (!network
->address_labels_by_section
)
183 network
->prefixes_by_section
= hashmap_new(&network_config_hash_ops
);
184 if (!network
->prefixes_by_section
)
187 network
->rules_by_section
= hashmap_new(&network_config_hash_ops
);
188 if (!network
->rules_by_section
)
191 network
->filename
= strdup(filename
);
192 if (!network
->filename
)
195 network
->name
= strdup(basename(filename
));
199 d
= strrchr(network
->name
, '.');
203 assert(streq(d
, ".network"));
207 network
->dhcp
= ADDRESS_FAMILY_NO
;
208 network
->dhcp_use_ntp
= true;
209 network
->dhcp_use_dns
= true;
210 network
->dhcp_use_hostname
= true;
211 network
->dhcp_use_routes
= true;
212 /* NOTE: this var might be overwriten by network_apply_anonymize_if_set */
213 network
->dhcp_send_hostname
= true;
214 /* To enable/disable RFC7844 Anonymity Profiles */
215 network
->dhcp_anonymize
= false;
216 network
->dhcp_route_metric
= DHCP_ROUTE_METRIC
;
217 /* NOTE: this var might be overwrite by network_apply_anonymize_if_set */
218 network
->dhcp_client_identifier
= DHCP_CLIENT_ID_DUID
;
219 network
->dhcp_route_table
= RT_TABLE_MAIN
;
220 network
->dhcp_route_table_set
= false;
221 /* NOTE: the following vars were not set to any default,
222 * even if they are commented in the man?
223 * These vars might be overwriten by network_apply_anonymize_if_set */
224 network
->dhcp_vendor_class_identifier
= false;
225 /* NOTE: from man: UseMTU=... Defaults to false*/
226 network
->dhcp_use_mtu
= false;
227 /* NOTE: from man: UseTimezone=... Defaults to "no".*/
228 network
->dhcp_use_timezone
= false;
230 network
->dhcp_server_emit_dns
= true;
231 network
->dhcp_server_emit_ntp
= true;
232 network
->dhcp_server_emit_router
= true;
233 network
->dhcp_server_emit_timezone
= true;
235 network
->router_emit_dns
= true;
236 network
->router_emit_domains
= true;
238 network
->use_bpdu
= true;
239 network
->allow_port_to_be_root
= true;
240 network
->unicast_flood
= true;
241 network
->priority
= LINK_BRIDGE_PORT_PRIORITY_INVALID
;
243 network
->lldp_mode
= LLDP_MODE_ROUTERS_ONLY
;
245 network
->llmnr
= RESOLVE_SUPPORT_YES
;
246 network
->mdns
= RESOLVE_SUPPORT_NO
;
247 network
->dnssec_mode
= _DNSSEC_MODE_INVALID
;
249 network
->link_local
= ADDRESS_FAMILY_IPV6
;
251 network
->ipv6_privacy_extensions
= IPV6_PRIVACY_EXTENSIONS_NO
;
252 network
->ipv6_accept_ra
= -1;
253 network
->ipv6_dad_transmits
= -1;
254 network
->ipv6_hop_limit
= -1;
255 network
->ipv6_proxy_ndp
= -1;
256 network
->duid
.type
= _DUID_TYPE_INVALID
;
257 network
->proxy_arp
= -1;
259 network
->ipv6_accept_ra_use_dns
= true;
260 network
->ipv6_accept_ra_route_table
= RT_TABLE_MAIN
;
262 dropin_dirname
= strjoina(network
->name
, ".network.d");
264 r
= config_parse_many(filename
, network_dirs
, dropin_dirname
,
270 "RoutingPolicyRule\0"
273 "DHCPv4\0" /* compat */
276 "IPv6NDPProxyAddress\0"
280 "IPv6PrefixDelegation\0"
282 config_item_perf_lookup
, network_network_gperf_lookup
,
283 CONFIG_PARSE_WARN
, network
);
287 network_apply_anonymize_if_set(network
);
289 /* IPMasquerade=yes implies IPForward=yes */
290 if (network
->ip_masquerade
)
291 network
->ip_forward
|= ADDRESS_FAMILY_IPV4
;
293 LIST_PREPEND(networks
, manager
->networks
, network
);
295 r
= hashmap_ensure_allocated(&manager
->networks_by_name
, &string_hash_ops
);
299 r
= hashmap_put(manager
->networks_by_name
, network
->name
, network
);
303 LIST_FOREACH(routes
, route
, network
->static_routes
) {
304 if (!route
->family
) {
305 log_warning("Route section without Gateway field configured in %s. "
306 "Ignoring", filename
);
311 LIST_FOREACH(addresses
, address
, network
->static_addresses
) {
312 if (!address
->family
) {
313 log_warning("Address section without Address field configured in %s. "
314 "Ignoring", filename
);
324 int network_load(Manager
*manager
) {
326 _cleanup_strv_free_
char **files
= NULL
;
332 while ((network
= manager
->networks
))
333 network_free(network
);
335 r
= conf_files_list_strv(&files
, ".network", NULL
, 0, network_dirs
);
337 return log_error_errno(r
, "Failed to enumerate network files: %m");
339 STRV_FOREACH_BACKWARDS(f
, files
) {
340 r
= network_load_one(manager
, *f
);
348 void network_free(Network
*network
) {
349 IPv6ProxyNDPAddress
*ipv6_proxy_ndp_address
;
350 RoutingPolicyRule
*rule
;
362 free(network
->filename
);
364 free(network
->match_mac
);
365 strv_free(network
->match_path
);
366 strv_free(network
->match_driver
);
367 strv_free(network
->match_type
);
368 strv_free(network
->match_name
);
370 free(network
->description
);
371 free(network
->dhcp_vendor_class_identifier
);
372 free(network
->dhcp_hostname
);
376 strv_free(network
->ntp
);
378 strv_free(network
->search_domains
);
379 strv_free(network
->route_domains
);
380 strv_free(network
->bind_carrier
);
382 netdev_unref(network
->bridge
);
383 netdev_unref(network
->bond
);
384 netdev_unref(network
->vrf
);
386 HASHMAP_FOREACH(netdev
, network
->stacked_netdevs
, i
) {
387 hashmap_remove(network
->stacked_netdevs
, netdev
->ifname
);
388 netdev_unref(netdev
);
390 hashmap_free(network
->stacked_netdevs
);
392 while ((route
= network
->static_routes
))
395 while ((address
= network
->static_addresses
))
396 address_free(address
);
398 while ((fdb_entry
= network
->static_fdb_entries
))
399 fdb_entry_free(fdb_entry
);
401 while ((ipv6_proxy_ndp_address
= network
->ipv6_proxy_ndp_addresses
))
402 ipv6_proxy_ndp_address_free(ipv6_proxy_ndp_address
);
404 while ((label
= network
->address_labels
))
405 address_label_free(label
);
407 while ((prefix
= network
->static_prefixes
))
410 while ((rule
= network
->rules
))
411 routing_policy_rule_free(rule
);
413 hashmap_free(network
->addresses_by_section
);
414 hashmap_free(network
->routes_by_section
);
415 hashmap_free(network
->fdb_entries_by_section
);
416 hashmap_free(network
->address_labels_by_section
);
417 hashmap_free(network
->prefixes_by_section
);
418 hashmap_free(network
->rules_by_section
);
420 if (network
->manager
) {
421 if (network
->manager
->networks
)
422 LIST_REMOVE(networks
, network
->manager
->networks
, network
);
424 if (network
->manager
->networks_by_name
)
425 hashmap_remove(network
->manager
->networks_by_name
, network
->name
);
430 condition_free_list(network
->match_host
);
431 condition_free_list(network
->match_virt
);
432 condition_free_list(network
->match_kernel
);
433 condition_free_list(network
->match_arch
);
435 free(network
->dhcp_server_timezone
);
436 free(network
->dhcp_server_dns
);
437 free(network
->dhcp_server_ntp
);
439 set_free_free(network
->dnssec_negative_trust_anchors
);
444 int network_get_by_name(Manager
*manager
, const char *name
, Network
**ret
) {
451 network
= hashmap_get(manager
->networks_by_name
, name
);
460 int network_get(Manager
*manager
, struct udev_device
*device
,
461 const char *ifname
, const struct ether_addr
*address
,
464 struct udev_device
*parent
;
465 const char *path
= NULL
, *parent_driver
= NULL
, *driver
= NULL
, *devtype
= NULL
;
471 path
= udev_device_get_property_value(device
, "ID_PATH");
473 parent
= udev_device_get_parent(device
);
475 parent_driver
= udev_device_get_driver(parent
);
477 driver
= udev_device_get_property_value(device
, "ID_NET_DRIVER");
479 devtype
= udev_device_get_devtype(device
);
482 LIST_FOREACH(networks
, network
, manager
->networks
) {
483 if (net_match_config(network
->match_mac
, network
->match_path
,
484 network
->match_driver
, network
->match_type
,
485 network
->match_name
, network
->match_host
,
486 network
->match_virt
, network
->match_kernel
,
488 address
, path
, parent_driver
, driver
,
490 if (network
->match_name
&& device
) {
492 uint8_t name_assign_type
= NET_NAME_UNKNOWN
;
494 attr
= udev_device_get_sysattr_value(device
, "name_assign_type");
496 (void) safe_atou8(attr
, &name_assign_type
);
498 if (name_assign_type
== NET_NAME_ENUM
)
499 log_warning("%s: found matching network '%s', based on potentially unpredictable ifname",
500 ifname
, network
->filename
);
502 log_debug("%s: found matching network '%s'", ifname
, network
->filename
);
504 log_debug("%s: found matching network '%s'", ifname
, network
->filename
);
516 int network_apply(Network
*network
, Link
*link
) {
522 link
->network
= network
;
524 if (network
->ipv4ll_route
) {
527 r
= route_new_static(network
, NULL
, 0, &route
);
531 r
= inet_pton(AF_INET
, "169.254.0.0", &route
->dst
.in
);
537 route
->family
= AF_INET
;
538 route
->dst_prefixlen
= 16;
539 route
->scope
= RT_SCOPE_LINK
;
540 route
->priority
= IPV4LL_ROUTE_METRIC
;
541 route
->protocol
= RTPROT_STATIC
;
544 if (network
->n_dns
> 0 ||
545 !strv_isempty(network
->ntp
) ||
546 !strv_isempty(network
->search_domains
) ||
547 !strv_isempty(network
->route_domains
))
553 bool network_has_static_ipv6_addresses(Network
*network
) {
558 LIST_FOREACH(addresses
, address
, network
->static_addresses
) {
559 if (address
->family
== AF_INET6
)
566 int config_parse_netdev(const char *unit
,
567 const char *filename
,
570 unsigned section_line
,
576 Network
*network
= userdata
;
577 _cleanup_free_
char *kind_string
= NULL
;
588 kind_string
= strdup(lvalue
);
592 /* the keys are CamelCase versions of the kind */
593 for (p
= kind_string
; *p
; p
++)
596 kind
= netdev_kind_from_string(kind_string
);
597 if (kind
== _NETDEV_KIND_INVALID
) {
598 log_syntax(unit
, LOG_ERR
, filename
, line
, 0, "Invalid NetDev kind: %s", lvalue
);
602 r
= netdev_get(network
->manager
, rvalue
, &netdev
);
604 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "%s could not be found, ignoring assignment: %s", lvalue
, rvalue
);
608 if (netdev
->kind
!= kind
) {
609 log_syntax(unit
, LOG_ERR
, filename
, line
, 0, "NetDev is not a %s, ignoring assignment: %s", lvalue
, rvalue
);
614 case NETDEV_KIND_BRIDGE
:
615 network
->bridge
= netdev
;
618 case NETDEV_KIND_BOND
:
619 network
->bond
= netdev
;
622 case NETDEV_KIND_VRF
:
623 network
->vrf
= netdev
;
626 case NETDEV_KIND_VLAN
:
627 case NETDEV_KIND_MACVLAN
:
628 case NETDEV_KIND_MACVTAP
:
629 case NETDEV_KIND_IPVLAN
:
630 case NETDEV_KIND_VXLAN
:
631 case NETDEV_KIND_VCAN
:
632 r
= hashmap_put(network
->stacked_netdevs
, netdev
->ifname
, netdev
);
634 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Can not add NetDev '%s' to network: %m", rvalue
);
640 assert_not_reached("Can not parse NetDev");
648 int config_parse_domains(
650 const char *filename
,
653 unsigned section_line
,
668 if (isempty(rvalue
)) {
669 n
->search_domains
= strv_free(n
->search_domains
);
670 n
->route_domains
= strv_free(n
->route_domains
);
676 _cleanup_free_
char *w
= NULL
, *normalized
= NULL
;
680 r
= extract_first_word(&p
, &w
, NULL
, 0);
682 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Failed to extract search or route domain, ignoring: %s", rvalue
);
688 is_route
= w
[0] == '~';
689 domain
= is_route
? w
+ 1 : w
;
691 if (dns_name_is_root(domain
) || streq(domain
, "*")) {
692 /* If the root domain appears as is, or the special token "*" is found, we'll consider this as
693 * routing domain, unconditionally. */
695 domain
= "."; /* make sure we don't allow empty strings, thus write the root domain as "." */
698 r
= dns_name_normalize(domain
, &normalized
);
700 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "'%s' is not a valid domain name, ignoring.", domain
);
706 if (is_localhost(domain
)) {
707 log_syntax(unit
, LOG_ERR
, filename
, line
, 0, "'localhost' domain names may not be configure as search or route domains, ignoring assignment: %s", domain
);
713 r
= strv_extend(&n
->route_domains
, domain
);
718 r
= strv_extend(&n
->search_domains
, domain
);
724 strv_uniq(n
->route_domains
);
725 strv_uniq(n
->search_domains
);
730 int config_parse_tunnel(const char *unit
,
731 const char *filename
,
734 unsigned section_line
,
740 Network
*network
= userdata
;
749 r
= netdev_get(network
->manager
, rvalue
, &netdev
);
751 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Tunnel is invalid, ignoring assignment: %s", rvalue
);
755 if (!IN_SET(netdev
->kind
,
761 NETDEV_KIND_IP6GRETAP
,
764 NETDEV_KIND_IP6TNL
)) {
765 log_syntax(unit
, LOG_ERR
, filename
, line
, 0,
766 "NetDev is not a tunnel, ignoring assignment: %s", rvalue
);
770 r
= hashmap_put(network
->stacked_netdevs
, netdev
->ifname
, netdev
);
772 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Cannot add VLAN '%s' to network, ignoring: %m", rvalue
);
781 int config_parse_ipv4ll(
783 const char *filename
,
786 unsigned section_line
,
793 AddressFamilyBoolean
*link_local
= data
;
800 /* Note that this is mostly like
801 * config_parse_address_family_boolean(), except that it
802 * applies only to IPv4 */
804 SET_FLAG(*link_local
, ADDRESS_FAMILY_IPV4
, parse_boolean(rvalue
));
809 int config_parse_dhcp(
811 const char *filename
,
814 unsigned section_line
,
821 AddressFamilyBoolean
*dhcp
= data
, s
;
828 /* Note that this is mostly like
829 * config_parse_address_family_boolean(), except that it
830 * understands some old names for the enum values */
832 s
= address_family_boolean_from_string(rvalue
);
835 /* Previously, we had a slightly different enum here,
836 * support its values for compatbility. */
838 if (streq(rvalue
, "none"))
839 s
= ADDRESS_FAMILY_NO
;
840 else if (streq(rvalue
, "v4"))
841 s
= ADDRESS_FAMILY_IPV4
;
842 else if (streq(rvalue
, "v6"))
843 s
= ADDRESS_FAMILY_IPV6
;
844 else if (streq(rvalue
, "both"))
845 s
= ADDRESS_FAMILY_YES
;
847 log_syntax(unit
, LOG_ERR
, filename
, line
, 0, "Failed to parse DHCP option, ignoring: %s", rvalue
);
856 static const char* const dhcp_client_identifier_table
[_DHCP_CLIENT_ID_MAX
] = {
857 [DHCP_CLIENT_ID_MAC
] = "mac",
858 [DHCP_CLIENT_ID_DUID
] = "duid"
861 DEFINE_PRIVATE_STRING_TABLE_LOOKUP_FROM_STRING(dhcp_client_identifier
, DHCPClientIdentifier
);
862 DEFINE_CONFIG_PARSE_ENUM(config_parse_dhcp_client_identifier
, dhcp_client_identifier
, DHCPClientIdentifier
, "Failed to parse client identifier type");
864 int config_parse_ipv6token(
866 const char *filename
,
869 unsigned section_line
,
876 union in_addr_union buffer
;
877 struct in6_addr
*token
= data
;
885 r
= in_addr_from_string(AF_INET6
, rvalue
, &buffer
);
887 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Failed to parse IPv6 token, ignoring: %s", rvalue
);
891 r
= in_addr_is_null(AF_INET6
, &buffer
);
893 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "IPv6 token can not be the ANY address, ignoring: %s", rvalue
);
897 if ((buffer
.in6
.s6_addr32
[0] | buffer
.in6
.s6_addr32
[1]) != 0) {
898 log_syntax(unit
, LOG_ERR
, filename
, line
, 0, "IPv6 token can not be longer than 64 bits, ignoring: %s", rvalue
);
907 static const char* const ipv6_privacy_extensions_table
[_IPV6_PRIVACY_EXTENSIONS_MAX
] = {
908 [IPV6_PRIVACY_EXTENSIONS_NO
] = "no",
909 [IPV6_PRIVACY_EXTENSIONS_PREFER_PUBLIC
] = "prefer-public",
910 [IPV6_PRIVACY_EXTENSIONS_YES
] = "yes",
913 DEFINE_STRING_TABLE_LOOKUP(ipv6_privacy_extensions
, IPv6PrivacyExtensions
);
915 int config_parse_ipv6_privacy_extensions(
917 const char *filename
,
920 unsigned section_line
,
927 IPv6PrivacyExtensions
*ipv6_privacy_extensions
= data
;
933 assert(ipv6_privacy_extensions
);
935 /* Our enum shall be a superset of booleans, hence first try
936 * to parse as boolean, and then as enum */
938 k
= parse_boolean(rvalue
);
940 *ipv6_privacy_extensions
= IPV6_PRIVACY_EXTENSIONS_YES
;
942 *ipv6_privacy_extensions
= IPV6_PRIVACY_EXTENSIONS_NO
;
944 IPv6PrivacyExtensions s
;
946 s
= ipv6_privacy_extensions_from_string(rvalue
);
949 if (streq(rvalue
, "kernel"))
950 s
= _IPV6_PRIVACY_EXTENSIONS_INVALID
;
952 log_syntax(unit
, LOG_ERR
, filename
, line
, 0, "Failed to parse IPv6 privacy extensions option, ignoring: %s", rvalue
);
957 *ipv6_privacy_extensions
= s
;
963 int config_parse_hostname(
965 const char *filename
,
968 unsigned section_line
,
975 char **hostname
= data
, *hn
= NULL
;
982 r
= config_parse_string(unit
, filename
, line
, section
, section_line
, lvalue
, ltype
, rvalue
, &hn
, userdata
);
986 if (!hostname_is_valid(hn
, false)) {
987 log_syntax(unit
, LOG_ERR
, filename
, line
, 0, "Hostname is not valid, ignoring assignment: %s", rvalue
);
993 *hostname
= hostname_cleanup(hn
);
997 int config_parse_timezone(
999 const char *filename
,
1001 const char *section
,
1002 unsigned section_line
,
1009 char **datap
= data
, *tz
= NULL
;
1016 r
= config_parse_string(unit
, filename
, line
, section
, section_line
, lvalue
, ltype
, rvalue
, &tz
, userdata
);
1020 if (!timezone_is_valid(tz
)) {
1021 log_syntax(unit
, LOG_ERR
, filename
, line
, 0, "Timezone is not valid, ignoring assignment: %s", rvalue
);
1032 int config_parse_dhcp_server_dns(
1034 const char *filename
,
1036 const char *section
,
1037 unsigned section_line
,
1045 const char *p
= rvalue
;
1053 _cleanup_free_
char *w
= NULL
;
1054 struct in_addr a
, *m
;
1056 r
= extract_first_word(&p
, &w
, NULL
, 0);
1060 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Failed to extract word, ignoring: %s", rvalue
);
1066 if (inet_pton(AF_INET
, w
, &a
) <= 0) {
1067 log_syntax(unit
, LOG_ERR
, filename
, line
, 0, "Failed to parse DNS server address, ignoring: %s", w
);
1071 m
= realloc(n
->dhcp_server_dns
, (n
->n_dhcp_server_dns
+ 1) * sizeof(struct in_addr
));
1075 m
[n
->n_dhcp_server_dns
++] = a
;
1076 n
->dhcp_server_dns
= m
;
1082 int config_parse_radv_dns(
1084 const char *filename
,
1086 const char *section
,
1087 unsigned section_line
,
1095 const char *p
= rvalue
;
1103 _cleanup_free_
char *w
= NULL
;
1104 union in_addr_union a
;
1106 r
= extract_first_word(&p
, &w
, NULL
, 0);
1110 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Failed to extract word, ignoring: %s", rvalue
);
1116 if (in_addr_from_string(AF_INET6
, w
, &a
) >= 0) {
1119 m
= realloc(n
->router_dns
, (n
->n_router_dns
+ 1) * sizeof(struct in6_addr
));
1123 m
[n
->n_router_dns
++] = a
.in6
;
1127 log_syntax(unit
, LOG_ERR
, filename
, line
, 0, "Failed to parse DNS server address, ignoring: %s", w
);
1134 int config_parse_radv_search_domains(
1136 const char *filename
,
1138 const char *section
,
1139 unsigned section_line
,
1147 const char *p
= rvalue
;
1155 _cleanup_free_
char *w
= NULL
;
1156 _cleanup_free_
char *idna
= NULL
;
1158 r
= extract_first_word(&p
, &w
, NULL
, 0);
1162 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Failed to extract word, ignoring: %s", rvalue
);
1168 r
= dns_name_apply_idna(w
, &idna
);
1170 r
= strv_push(&n
->router_search_domains
, idna
);
1173 } else if (r
== 0) {
1174 r
= strv_push(&n
->router_search_domains
, w
);
1183 int config_parse_dhcp_server_ntp(
1185 const char *filename
,
1187 const char *section
,
1188 unsigned section_line
,
1196 const char *p
= rvalue
;
1204 _cleanup_free_
char *w
= NULL
;
1205 struct in_addr a
, *m
;
1207 r
= extract_first_word(&p
, &w
, NULL
, 0);
1211 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Failed to extract word, ignoring: %s", rvalue
);
1217 if (inet_pton(AF_INET
, w
, &a
) <= 0) {
1218 log_syntax(unit
, LOG_ERR
, filename
, line
, 0, "Failed to parse NTP server address, ignoring: %s", w
);
1222 m
= realloc(n
->dhcp_server_ntp
, (n
->n_dhcp_server_ntp
+ 1) * sizeof(struct in_addr
));
1226 m
[n
->n_dhcp_server_ntp
++] = a
;
1227 n
->dhcp_server_ntp
= m
;
1231 int config_parse_dns(
1233 const char *filename
,
1235 const char *section
,
1236 unsigned section_line
,
1243 Network
*n
= userdata
;
1251 _cleanup_free_
char *w
= NULL
;
1252 union in_addr_union a
;
1253 struct in_addr_data
*m
;
1256 r
= extract_first_word(&rvalue
, &w
, NULL
, 0);
1260 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Invalid syntax, ignoring: %s", rvalue
);
1266 r
= in_addr_from_string_auto(w
, &family
, &a
);
1268 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Failed to parse dns server address, ignoring: %s", w
);
1272 m
= realloc(n
->dns
, (n
->n_dns
+ 1) * sizeof(struct in_addr_data
));
1276 m
[n
->n_dns
++] = (struct in_addr_data
) {
1287 int config_parse_dnssec_negative_trust_anchors(
1289 const char *filename
,
1291 const char *section
,
1292 unsigned section_line
,
1299 const char *p
= rvalue
;
1307 if (isempty(rvalue
)) {
1308 n
->dnssec_negative_trust_anchors
= set_free_free(n
->dnssec_negative_trust_anchors
);
1313 _cleanup_free_
char *w
= NULL
;
1315 r
= extract_first_word(&p
, &w
, NULL
, 0);
1317 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Failed to extract negative trust anchor domain, ignoring: %s", rvalue
);
1323 r
= dns_name_is_valid(w
);
1325 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "%s is not a valid domain name, ignoring.", w
);
1329 r
= set_ensure_allocated(&n
->dnssec_negative_trust_anchors
, &dns_name_hash_ops
);
1333 r
= set_put(n
->dnssec_negative_trust_anchors
, w
);
1343 int config_parse_ntp(
1345 const char *filename
,
1347 const char *section
,
1348 unsigned section_line
,
1362 if (isempty(rvalue
)) {
1368 _cleanup_free_
char *w
= NULL
;
1370 r
= extract_first_word(&rvalue
, &w
, NULL
, 0);
1374 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Failed to extract NTP server name, ignoring: %s", rvalue
);
1380 r
= dns_name_is_valid_or_address(w
);
1382 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "%s is not a valid domain name or IP address, ignoring.", w
);
1386 r
= strv_push(l
, w
);
1396 int config_parse_dhcp_route_table(const char *unit
,
1397 const char *filename
,
1399 const char *section
,
1400 unsigned section_line
,
1406 Network
*network
= data
;
1415 r
= safe_atou32(rvalue
, &rt
);
1417 log_syntax(unit
, LOG_ERR
, filename
, line
, r
,
1418 "Unable to read RouteTable, ignoring assignment: %s", rvalue
);
1422 network
->dhcp_route_table
= rt
;
1423 network
->dhcp_route_table_set
= true;
1428 DEFINE_CONFIG_PARSE_ENUM(config_parse_dhcp_use_domains
, dhcp_use_domains
, DHCPUseDomains
, "Failed to parse DHCP use domains setting");
1430 static const char* const dhcp_use_domains_table
[_DHCP_USE_DOMAINS_MAX
] = {
1431 [DHCP_USE_DOMAINS_NO
] = "no",
1432 [DHCP_USE_DOMAINS_ROUTE
] = "route",
1433 [DHCP_USE_DOMAINS_YES
] = "yes",
1436 DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(dhcp_use_domains
, DHCPUseDomains
, DHCP_USE_DOMAINS_YES
);
1438 DEFINE_CONFIG_PARSE_ENUM(config_parse_lldp_mode
, lldp_mode
, LLDPMode
, "Failed to parse LLDP= setting.");
1440 static const char* const lldp_mode_table
[_LLDP_MODE_MAX
] = {
1441 [LLDP_MODE_NO
] = "no",
1442 [LLDP_MODE_YES
] = "yes",
1443 [LLDP_MODE_ROUTERS_ONLY
] = "routers-only",
1446 DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(lldp_mode
, LLDPMode
, LLDP_MODE_YES
);