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
);
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
->required_for_online
= true;
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;
230 network
->rapid_commit
= true;
232 network
->dhcp_server_emit_dns
= true;
233 network
->dhcp_server_emit_ntp
= true;
234 network
->dhcp_server_emit_router
= true;
235 network
->dhcp_server_emit_timezone
= true;
237 network
->router_emit_dns
= true;
238 network
->router_emit_domains
= true;
240 network
->use_bpdu
= true;
241 network
->allow_port_to_be_root
= true;
242 network
->unicast_flood
= true;
243 network
->priority
= LINK_BRIDGE_PORT_PRIORITY_INVALID
;
245 network
->lldp_mode
= LLDP_MODE_ROUTERS_ONLY
;
247 network
->llmnr
= RESOLVE_SUPPORT_YES
;
248 network
->mdns
= RESOLVE_SUPPORT_NO
;
249 network
->dnssec_mode
= _DNSSEC_MODE_INVALID
;
251 network
->link_local
= ADDRESS_FAMILY_IPV6
;
253 network
->ipv6_privacy_extensions
= IPV6_PRIVACY_EXTENSIONS_NO
;
254 network
->ipv6_accept_ra
= -1;
255 network
->ipv6_dad_transmits
= -1;
256 network
->ipv6_hop_limit
= -1;
257 network
->ipv6_proxy_ndp
= -1;
258 network
->duid
.type
= _DUID_TYPE_INVALID
;
259 network
->proxy_arp
= -1;
261 network
->ipv6_accept_ra_use_dns
= true;
262 network
->ipv6_accept_ra_route_table
= RT_TABLE_MAIN
;
264 dropin_dirname
= strjoina(network
->name
, ".network.d");
266 r
= config_parse_many(filename
, network_dirs
, dropin_dirname
,
272 "RoutingPolicyRule\0"
275 "DHCPv4\0" /* compat */
278 "IPv6NDPProxyAddress\0"
282 "IPv6PrefixDelegation\0"
284 config_item_perf_lookup
, network_network_gperf_lookup
,
285 CONFIG_PARSE_WARN
, network
);
289 network_apply_anonymize_if_set(network
);
291 /* IPMasquerade=yes implies IPForward=yes */
292 if (network
->ip_masquerade
)
293 network
->ip_forward
|= ADDRESS_FAMILY_IPV4
;
295 LIST_PREPEND(networks
, manager
->networks
, network
);
297 r
= hashmap_ensure_allocated(&manager
->networks_by_name
, &string_hash_ops
);
301 r
= hashmap_put(manager
->networks_by_name
, network
->name
, network
);
305 LIST_FOREACH(routes
, route
, network
->static_routes
) {
306 if (!route
->family
) {
307 log_warning("Route section without Gateway field configured in %s. "
308 "Ignoring", filename
);
313 LIST_FOREACH(addresses
, address
, network
->static_addresses
) {
314 if (!address
->family
) {
315 log_warning("Address section without Address field configured in %s. "
316 "Ignoring", filename
);
326 int network_load(Manager
*manager
) {
328 _cleanup_strv_free_
char **files
= NULL
;
334 while ((network
= manager
->networks
))
335 network_free(network
);
337 r
= conf_files_list_strv(&files
, ".network", NULL
, 0, network_dirs
);
339 return log_error_errno(r
, "Failed to enumerate network files: %m");
341 STRV_FOREACH_BACKWARDS(f
, files
) {
342 r
= network_load_one(manager
, *f
);
350 void network_free(Network
*network
) {
351 IPv6ProxyNDPAddress
*ipv6_proxy_ndp_address
;
352 RoutingPolicyRule
*rule
;
364 free(network
->filename
);
366 free(network
->match_mac
);
367 strv_free(network
->match_path
);
368 strv_free(network
->match_driver
);
369 strv_free(network
->match_type
);
370 strv_free(network
->match_name
);
372 free(network
->description
);
373 free(network
->dhcp_vendor_class_identifier
);
374 free(network
->dhcp_hostname
);
378 strv_free(network
->ntp
);
380 strv_free(network
->search_domains
);
381 strv_free(network
->route_domains
);
382 strv_free(network
->bind_carrier
);
384 netdev_unref(network
->bridge
);
385 netdev_unref(network
->bond
);
386 netdev_unref(network
->vrf
);
388 HASHMAP_FOREACH(netdev
, network
->stacked_netdevs
, i
) {
389 hashmap_remove(network
->stacked_netdevs
, netdev
->ifname
);
390 netdev_unref(netdev
);
392 hashmap_free(network
->stacked_netdevs
);
394 while ((route
= network
->static_routes
))
397 while ((address
= network
->static_addresses
))
398 address_free(address
);
400 while ((fdb_entry
= network
->static_fdb_entries
))
401 fdb_entry_free(fdb_entry
);
403 while ((ipv6_proxy_ndp_address
= network
->ipv6_proxy_ndp_addresses
))
404 ipv6_proxy_ndp_address_free(ipv6_proxy_ndp_address
);
406 while ((label
= network
->address_labels
))
407 address_label_free(label
);
409 while ((prefix
= network
->static_prefixes
))
412 while ((rule
= network
->rules
))
413 routing_policy_rule_free(rule
);
415 hashmap_free(network
->addresses_by_section
);
416 hashmap_free(network
->routes_by_section
);
417 hashmap_free(network
->fdb_entries_by_section
);
418 hashmap_free(network
->address_labels_by_section
);
419 hashmap_free(network
->prefixes_by_section
);
420 hashmap_free(network
->rules_by_section
);
422 if (network
->manager
) {
423 if (network
->manager
->networks
)
424 LIST_REMOVE(networks
, network
->manager
->networks
, network
);
426 if (network
->manager
->networks_by_name
)
427 hashmap_remove(network
->manager
->networks_by_name
, network
->name
);
432 condition_free_list(network
->match_host
);
433 condition_free_list(network
->match_virt
);
434 condition_free_list(network
->match_kernel_cmdline
);
435 condition_free_list(network
->match_kernel_version
);
436 condition_free_list(network
->match_arch
);
438 free(network
->dhcp_server_timezone
);
439 free(network
->dhcp_server_dns
);
440 free(network
->dhcp_server_ntp
);
442 set_free_free(network
->dnssec_negative_trust_anchors
);
447 int network_get_by_name(Manager
*manager
, const char *name
, Network
**ret
) {
454 network
= hashmap_get(manager
->networks_by_name
, name
);
463 int network_get(Manager
*manager
, struct udev_device
*device
,
464 const char *ifname
, const struct ether_addr
*address
,
467 struct udev_device
*parent
;
468 const char *path
= NULL
, *parent_driver
= NULL
, *driver
= NULL
, *devtype
= NULL
;
474 path
= udev_device_get_property_value(device
, "ID_PATH");
476 parent
= udev_device_get_parent(device
);
478 parent_driver
= udev_device_get_driver(parent
);
480 driver
= udev_device_get_property_value(device
, "ID_NET_DRIVER");
482 devtype
= udev_device_get_devtype(device
);
485 LIST_FOREACH(networks
, network
, manager
->networks
) {
486 if (net_match_config(network
->match_mac
, network
->match_path
,
487 network
->match_driver
, network
->match_type
,
488 network
->match_name
, network
->match_host
,
489 network
->match_virt
, network
->match_kernel_cmdline
,
490 network
->match_kernel_version
, network
->match_arch
,
491 address
, path
, parent_driver
, driver
,
493 if (network
->match_name
&& device
) {
495 uint8_t name_assign_type
= NET_NAME_UNKNOWN
;
497 attr
= udev_device_get_sysattr_value(device
, "name_assign_type");
499 (void) safe_atou8(attr
, &name_assign_type
);
501 if (name_assign_type
== NET_NAME_ENUM
)
502 log_warning("%s: found matching network '%s', based on potentially unpredictable ifname",
503 ifname
, network
->filename
);
505 log_debug("%s: found matching network '%s'", ifname
, network
->filename
);
507 log_debug("%s: found matching network '%s'", ifname
, network
->filename
);
519 int network_apply(Network
*network
, Link
*link
) {
525 link
->network
= network
;
527 if (network
->ipv4ll_route
) {
530 r
= route_new_static(network
, NULL
, 0, &route
);
534 r
= inet_pton(AF_INET
, "169.254.0.0", &route
->dst
.in
);
540 route
->family
= AF_INET
;
541 route
->dst_prefixlen
= 16;
542 route
->scope
= RT_SCOPE_LINK
;
543 route
->priority
= IPV4LL_ROUTE_METRIC
;
544 route
->protocol
= RTPROT_STATIC
;
547 if (network
->n_dns
> 0 ||
548 !strv_isempty(network
->ntp
) ||
549 !strv_isempty(network
->search_domains
) ||
550 !strv_isempty(network
->route_domains
))
556 bool network_has_static_ipv6_addresses(Network
*network
) {
561 LIST_FOREACH(addresses
, address
, network
->static_addresses
) {
562 if (address
->family
== AF_INET6
)
569 int config_parse_netdev(const char *unit
,
570 const char *filename
,
573 unsigned section_line
,
579 Network
*network
= userdata
;
580 _cleanup_free_
char *kind_string
= NULL
;
591 kind_string
= strdup(lvalue
);
595 /* the keys are CamelCase versions of the kind */
596 for (p
= kind_string
; *p
; p
++)
599 kind
= netdev_kind_from_string(kind_string
);
600 if (kind
== _NETDEV_KIND_INVALID
) {
601 log_syntax(unit
, LOG_ERR
, filename
, line
, 0, "Invalid NetDev kind: %s", lvalue
);
605 r
= netdev_get(network
->manager
, rvalue
, &netdev
);
607 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "%s could not be found, ignoring assignment: %s", lvalue
, rvalue
);
611 if (netdev
->kind
!= kind
) {
612 log_syntax(unit
, LOG_ERR
, filename
, line
, 0, "NetDev is not a %s, ignoring assignment: %s", lvalue
, rvalue
);
617 case NETDEV_KIND_BRIDGE
:
618 network
->bridge
= netdev
;
621 case NETDEV_KIND_BOND
:
622 network
->bond
= netdev
;
625 case NETDEV_KIND_VRF
:
626 network
->vrf
= netdev
;
629 case NETDEV_KIND_VLAN
:
630 case NETDEV_KIND_MACVLAN
:
631 case NETDEV_KIND_MACVTAP
:
632 case NETDEV_KIND_IPVLAN
:
633 case NETDEV_KIND_VXLAN
:
634 case NETDEV_KIND_VCAN
:
635 r
= hashmap_put(network
->stacked_netdevs
, netdev
->ifname
, netdev
);
637 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Cannot add NetDev '%s' to network: %m", rvalue
);
643 assert_not_reached("Cannot parse NetDev");
651 int config_parse_domains(
653 const char *filename
,
656 unsigned section_line
,
671 if (isempty(rvalue
)) {
672 n
->search_domains
= strv_free(n
->search_domains
);
673 n
->route_domains
= strv_free(n
->route_domains
);
679 _cleanup_free_
char *w
= NULL
, *normalized
= NULL
;
683 r
= extract_first_word(&p
, &w
, NULL
, 0);
685 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Failed to extract search or route domain, ignoring: %s", rvalue
);
691 is_route
= w
[0] == '~';
692 domain
= is_route
? w
+ 1 : w
;
694 if (dns_name_is_root(domain
) || streq(domain
, "*")) {
695 /* If the root domain appears as is, or the special token "*" is found, we'll consider this as
696 * routing domain, unconditionally. */
698 domain
= "."; /* make sure we don't allow empty strings, thus write the root domain as "." */
701 r
= dns_name_normalize(domain
, &normalized
);
703 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "'%s' is not a valid domain name, ignoring.", domain
);
709 if (is_localhost(domain
)) {
710 log_syntax(unit
, LOG_ERR
, filename
, line
, 0, "'localhost' domain names may not be configure as search or route domains, ignoring assignment: %s", domain
);
716 r
= strv_extend(&n
->route_domains
, domain
);
721 r
= strv_extend(&n
->search_domains
, domain
);
727 strv_uniq(n
->route_domains
);
728 strv_uniq(n
->search_domains
);
733 int config_parse_tunnel(const char *unit
,
734 const char *filename
,
737 unsigned section_line
,
743 Network
*network
= userdata
;
752 r
= netdev_get(network
->manager
, rvalue
, &netdev
);
754 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Tunnel is invalid, ignoring assignment: %s", rvalue
);
758 if (!IN_SET(netdev
->kind
,
764 NETDEV_KIND_IP6GRETAP
,
767 NETDEV_KIND_IP6TNL
)) {
768 log_syntax(unit
, LOG_ERR
, filename
, line
, 0,
769 "NetDev is not a tunnel, ignoring assignment: %s", rvalue
);
773 r
= hashmap_put(network
->stacked_netdevs
, netdev
->ifname
, netdev
);
775 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Cannot add VLAN '%s' to network, ignoring: %m", rvalue
);
784 int config_parse_ipv4ll(
786 const char *filename
,
789 unsigned section_line
,
796 AddressFamilyBoolean
*link_local
= data
;
803 /* Note that this is mostly like
804 * config_parse_address_family_boolean(), except that it
805 * applies only to IPv4 */
807 SET_FLAG(*link_local
, ADDRESS_FAMILY_IPV4
, parse_boolean(rvalue
));
812 int config_parse_dhcp(
814 const char *filename
,
817 unsigned section_line
,
824 AddressFamilyBoolean
*dhcp
= data
, s
;
831 /* Note that this is mostly like
832 * config_parse_address_family_boolean(), except that it
833 * understands some old names for the enum values */
835 s
= address_family_boolean_from_string(rvalue
);
838 /* Previously, we had a slightly different enum here,
839 * support its values for compatbility. */
841 if (streq(rvalue
, "none"))
842 s
= ADDRESS_FAMILY_NO
;
843 else if (streq(rvalue
, "v4"))
844 s
= ADDRESS_FAMILY_IPV4
;
845 else if (streq(rvalue
, "v6"))
846 s
= ADDRESS_FAMILY_IPV6
;
847 else if (streq(rvalue
, "both"))
848 s
= ADDRESS_FAMILY_YES
;
850 log_syntax(unit
, LOG_ERR
, filename
, line
, 0, "Failed to parse DHCP option, ignoring: %s", rvalue
);
859 static const char* const dhcp_client_identifier_table
[_DHCP_CLIENT_ID_MAX
] = {
860 [DHCP_CLIENT_ID_MAC
] = "mac",
861 [DHCP_CLIENT_ID_DUID
] = "duid",
862 [DHCP_CLIENT_ID_DUID_ONLY
] = "duid-only",
865 DEFINE_PRIVATE_STRING_TABLE_LOOKUP_FROM_STRING(dhcp_client_identifier
, DHCPClientIdentifier
);
866 DEFINE_CONFIG_PARSE_ENUM(config_parse_dhcp_client_identifier
, dhcp_client_identifier
, DHCPClientIdentifier
, "Failed to parse client identifier type");
868 int config_parse_ipv6token(
870 const char *filename
,
873 unsigned section_line
,
880 union in_addr_union buffer
;
881 struct in6_addr
*token
= data
;
889 r
= in_addr_from_string(AF_INET6
, rvalue
, &buffer
);
891 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Failed to parse IPv6 token, ignoring: %s", rvalue
);
895 r
= in_addr_is_null(AF_INET6
, &buffer
);
897 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "IPv6 token cannot be the ANY address, ignoring: %s", rvalue
);
901 if ((buffer
.in6
.s6_addr32
[0] | buffer
.in6
.s6_addr32
[1]) != 0) {
902 log_syntax(unit
, LOG_ERR
, filename
, line
, 0, "IPv6 token cannot be longer than 64 bits, ignoring: %s", rvalue
);
911 static const char* const ipv6_privacy_extensions_table
[_IPV6_PRIVACY_EXTENSIONS_MAX
] = {
912 [IPV6_PRIVACY_EXTENSIONS_NO
] = "no",
913 [IPV6_PRIVACY_EXTENSIONS_PREFER_PUBLIC
] = "prefer-public",
914 [IPV6_PRIVACY_EXTENSIONS_YES
] = "yes",
917 DEFINE_STRING_TABLE_LOOKUP(ipv6_privacy_extensions
, IPv6PrivacyExtensions
);
919 int config_parse_ipv6_privacy_extensions(
921 const char *filename
,
924 unsigned section_line
,
931 IPv6PrivacyExtensions
*ipv6_privacy_extensions
= data
;
937 assert(ipv6_privacy_extensions
);
939 /* Our enum shall be a superset of booleans, hence first try
940 * to parse as boolean, and then as enum */
942 k
= parse_boolean(rvalue
);
944 *ipv6_privacy_extensions
= IPV6_PRIVACY_EXTENSIONS_YES
;
946 *ipv6_privacy_extensions
= IPV6_PRIVACY_EXTENSIONS_NO
;
948 IPv6PrivacyExtensions s
;
950 s
= ipv6_privacy_extensions_from_string(rvalue
);
953 if (streq(rvalue
, "kernel"))
954 s
= _IPV6_PRIVACY_EXTENSIONS_INVALID
;
956 log_syntax(unit
, LOG_ERR
, filename
, line
, 0, "Failed to parse IPv6 privacy extensions option, ignoring: %s", rvalue
);
961 *ipv6_privacy_extensions
= s
;
967 int config_parse_hostname(
969 const char *filename
,
972 unsigned section_line
,
979 char **hostname
= data
, *hn
= NULL
;
986 r
= config_parse_string(unit
, filename
, line
, section
, section_line
, lvalue
, ltype
, rvalue
, &hn
, userdata
);
990 if (!hostname_is_valid(hn
, false)) {
991 log_syntax(unit
, LOG_ERR
, filename
, line
, 0, "Hostname is not valid, ignoring assignment: %s", rvalue
);
997 *hostname
= hostname_cleanup(hn
);
1001 int config_parse_timezone(
1003 const char *filename
,
1005 const char *section
,
1006 unsigned section_line
,
1013 char **datap
= data
, *tz
= NULL
;
1020 r
= config_parse_string(unit
, filename
, line
, section
, section_line
, lvalue
, ltype
, rvalue
, &tz
, userdata
);
1024 if (!timezone_is_valid(tz
)) {
1025 log_syntax(unit
, LOG_ERR
, filename
, line
, 0, "Timezone is not valid, ignoring assignment: %s", rvalue
);
1036 int config_parse_dhcp_server_dns(
1038 const char *filename
,
1040 const char *section
,
1041 unsigned section_line
,
1049 const char *p
= rvalue
;
1057 _cleanup_free_
char *w
= NULL
;
1058 struct in_addr a
, *m
;
1060 r
= extract_first_word(&p
, &w
, NULL
, 0);
1064 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Failed to extract word, ignoring: %s", rvalue
);
1070 if (inet_pton(AF_INET
, w
, &a
) <= 0) {
1071 log_syntax(unit
, LOG_ERR
, filename
, line
, 0, "Failed to parse DNS server address, ignoring: %s", w
);
1075 m
= reallocarray(n
->dhcp_server_dns
, n
->n_dhcp_server_dns
+ 1, sizeof(struct in_addr
));
1079 m
[n
->n_dhcp_server_dns
++] = a
;
1080 n
->dhcp_server_dns
= m
;
1086 int config_parse_radv_dns(
1088 const char *filename
,
1090 const char *section
,
1091 unsigned section_line
,
1099 const char *p
= rvalue
;
1107 _cleanup_free_
char *w
= NULL
;
1108 union in_addr_union a
;
1110 r
= extract_first_word(&p
, &w
, NULL
, 0);
1114 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Failed to extract word, ignoring: %s", rvalue
);
1120 if (in_addr_from_string(AF_INET6
, w
, &a
) >= 0) {
1123 m
= reallocarray(n
->router_dns
, n
->n_router_dns
+ 1, sizeof(struct in6_addr
));
1127 m
[n
->n_router_dns
++] = a
.in6
;
1131 log_syntax(unit
, LOG_ERR
, filename
, line
, 0, "Failed to parse DNS server address, ignoring: %s", w
);
1138 int config_parse_radv_search_domains(
1140 const char *filename
,
1142 const char *section
,
1143 unsigned section_line
,
1151 const char *p
= rvalue
;
1159 _cleanup_free_
char *w
= NULL
;
1160 _cleanup_free_
char *idna
= NULL
;
1162 r
= extract_first_word(&p
, &w
, NULL
, 0);
1166 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Failed to extract word, ignoring: %s", rvalue
);
1172 r
= dns_name_apply_idna(w
, &idna
);
1174 r
= strv_push(&n
->router_search_domains
, idna
);
1177 } else if (r
== 0) {
1178 r
= strv_push(&n
->router_search_domains
, w
);
1187 int config_parse_dhcp_server_ntp(
1189 const char *filename
,
1191 const char *section
,
1192 unsigned section_line
,
1200 const char *p
= rvalue
;
1208 _cleanup_free_
char *w
= NULL
;
1209 struct in_addr a
, *m
;
1211 r
= extract_first_word(&p
, &w
, NULL
, 0);
1215 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Failed to extract word, ignoring: %s", rvalue
);
1221 if (inet_pton(AF_INET
, w
, &a
) <= 0) {
1222 log_syntax(unit
, LOG_ERR
, filename
, line
, 0, "Failed to parse NTP server address, ignoring: %s", w
);
1226 m
= reallocarray(n
->dhcp_server_ntp
, n
->n_dhcp_server_ntp
+ 1, sizeof(struct in_addr
));
1230 m
[n
->n_dhcp_server_ntp
++] = a
;
1231 n
->dhcp_server_ntp
= m
;
1235 int config_parse_dns(
1237 const char *filename
,
1239 const char *section
,
1240 unsigned section_line
,
1247 Network
*n
= userdata
;
1255 _cleanup_free_
char *w
= NULL
;
1256 union in_addr_union a
;
1257 struct in_addr_data
*m
;
1260 r
= extract_first_word(&rvalue
, &w
, NULL
, 0);
1264 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Invalid syntax, ignoring: %s", rvalue
);
1270 r
= in_addr_from_string_auto(w
, &family
, &a
);
1272 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Failed to parse dns server address, ignoring: %s", w
);
1276 m
= reallocarray(n
->dns
, n
->n_dns
+ 1, sizeof(struct in_addr_data
));
1280 m
[n
->n_dns
++] = (struct in_addr_data
) {
1291 int config_parse_dnssec_negative_trust_anchors(
1293 const char *filename
,
1295 const char *section
,
1296 unsigned section_line
,
1303 const char *p
= rvalue
;
1311 if (isempty(rvalue
)) {
1312 n
->dnssec_negative_trust_anchors
= set_free_free(n
->dnssec_negative_trust_anchors
);
1317 _cleanup_free_
char *w
= NULL
;
1319 r
= extract_first_word(&p
, &w
, NULL
, 0);
1321 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Failed to extract negative trust anchor domain, ignoring: %s", rvalue
);
1327 r
= dns_name_is_valid(w
);
1329 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "%s is not a valid domain name, ignoring.", w
);
1333 r
= set_ensure_allocated(&n
->dnssec_negative_trust_anchors
, &dns_name_hash_ops
);
1337 r
= set_put(n
->dnssec_negative_trust_anchors
, w
);
1347 int config_parse_ntp(
1349 const char *filename
,
1351 const char *section
,
1352 unsigned section_line
,
1366 if (isempty(rvalue
)) {
1372 _cleanup_free_
char *w
= NULL
;
1374 r
= extract_first_word(&rvalue
, &w
, NULL
, 0);
1378 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Failed to extract NTP server name, ignoring: %s", rvalue
);
1384 r
= dns_name_is_valid_or_address(w
);
1386 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "%s is not a valid domain name or IP address, ignoring.", w
);
1390 r
= strv_push(l
, w
);
1400 int config_parse_dhcp_route_table(const char *unit
,
1401 const char *filename
,
1403 const char *section
,
1404 unsigned section_line
,
1410 Network
*network
= data
;
1419 r
= safe_atou32(rvalue
, &rt
);
1421 log_syntax(unit
, LOG_ERR
, filename
, line
, r
,
1422 "Unable to read RouteTable, ignoring assignment: %s", rvalue
);
1426 network
->dhcp_route_table
= rt
;
1427 network
->dhcp_route_table_set
= true;
1432 DEFINE_CONFIG_PARSE_ENUM(config_parse_dhcp_use_domains
, dhcp_use_domains
, DHCPUseDomains
, "Failed to parse DHCP use domains setting");
1434 static const char* const dhcp_use_domains_table
[_DHCP_USE_DOMAINS_MAX
] = {
1435 [DHCP_USE_DOMAINS_NO
] = "no",
1436 [DHCP_USE_DOMAINS_ROUTE
] = "route",
1437 [DHCP_USE_DOMAINS_YES
] = "yes",
1440 DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(dhcp_use_domains
, DHCPUseDomains
, DHCP_USE_DOMAINS_YES
);
1442 DEFINE_CONFIG_PARSE_ENUM(config_parse_lldp_mode
, lldp_mode
, LLDPMode
, "Failed to parse LLDP= setting.");
1444 static const char* const lldp_mode_table
[_LLDP_MODE_MAX
] = {
1445 [LLDP_MODE_NO
] = "no",
1446 [LLDP_MODE_YES
] = "yes",
1447 [LLDP_MODE_ROUTERS_ONLY
] = "routers-only",
1450 DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(lldp_mode
, LLDPMode
, LLDP_MODE_YES
);