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
);
160 LIST_HEAD_INIT(network
->rules
);
162 network
->stacked_netdevs
= hashmap_new(&string_hash_ops
);
163 if (!network
->stacked_netdevs
)
166 network
->addresses_by_section
= hashmap_new(&network_config_hash_ops
);
167 if (!network
->addresses_by_section
)
170 network
->routes_by_section
= hashmap_new(&network_config_hash_ops
);
171 if (!network
->routes_by_section
)
174 network
->fdb_entries_by_section
= hashmap_new(NULL
);
175 if (!network
->fdb_entries_by_section
)
178 network
->address_labels_by_section
= hashmap_new(&network_config_hash_ops
);
179 if (!network
->address_labels_by_section
)
182 network
->prefixes_by_section
= hashmap_new(&network_config_hash_ops
);
183 if (!network
->prefixes_by_section
)
186 network
->rules_by_section
= hashmap_new(&network_config_hash_ops
);
187 if (!network
->rules_by_section
)
190 network
->filename
= strdup(filename
);
191 if (!network
->filename
)
194 network
->name
= strdup(basename(filename
));
198 d
= strrchr(network
->name
, '.');
202 assert(streq(d
, ".network"));
206 network
->dhcp
= ADDRESS_FAMILY_NO
;
207 network
->dhcp_use_ntp
= true;
208 network
->dhcp_use_dns
= true;
209 network
->dhcp_use_hostname
= true;
210 /* NOTE: this var might be overwriten by network_apply_anonymize_if_set */
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 /* NOTE: the following vars were not set to any default,
221 * even if they are commented in the man?
222 * These vars might be overwriten by network_apply_anonymize_if_set */
223 network
->dhcp_vendor_class_identifier
= false;
224 /* NOTE: from man: UseMTU=... Defaults to false*/
225 network
->dhcp_use_mtu
= false;
226 /* NOTE: from man: UseTimezone=... Defaults to "no".*/
227 network
->dhcp_use_timezone
= false;
229 network
->dhcp_server_emit_dns
= true;
230 network
->dhcp_server_emit_ntp
= true;
231 network
->dhcp_server_emit_router
= true;
232 network
->dhcp_server_emit_timezone
= true;
234 network
->use_bpdu
= true;
235 network
->allow_port_to_be_root
= true;
236 network
->unicast_flood
= true;
237 network
->priority
= LINK_BRIDGE_PORT_PRIORITY_INVALID
;
239 network
->lldp_mode
= LLDP_MODE_ROUTERS_ONLY
;
241 network
->llmnr
= RESOLVE_SUPPORT_YES
;
242 network
->mdns
= RESOLVE_SUPPORT_NO
;
243 network
->dnssec_mode
= _DNSSEC_MODE_INVALID
;
245 network
->link_local
= ADDRESS_FAMILY_IPV6
;
247 network
->ipv6_privacy_extensions
= IPV6_PRIVACY_EXTENSIONS_NO
;
248 network
->ipv6_accept_ra
= -1;
249 network
->ipv6_dad_transmits
= -1;
250 network
->ipv6_hop_limit
= -1;
251 network
->ipv6_proxy_ndp
= -1;
252 network
->duid
.type
= _DUID_TYPE_INVALID
;
253 network
->proxy_arp
= -1;
255 network
->ipv6_accept_ra_use_dns
= true;
256 network
->ipv6_accept_ra_route_table
= RT_TABLE_MAIN
;
258 dropin_dirname
= strjoina(network
->name
, ".network.d");
260 r
= config_parse_many(filename
, network_dirs
, dropin_dirname
,
266 "RoutingPolicyRule\0"
269 "DHCPv4\0" /* compat */
272 "IPv6NDPProxyAddress\0"
276 "IPv6PrefixDelegation\0"
278 config_item_perf_lookup
, network_network_gperf_lookup
,
283 network_apply_anonymize_if_set(network
);
285 /* IPMasquerade=yes implies IPForward=yes */
286 if (network
->ip_masquerade
)
287 network
->ip_forward
|= ADDRESS_FAMILY_IPV4
;
289 LIST_PREPEND(networks
, manager
->networks
, network
);
291 r
= hashmap_ensure_allocated(&manager
->networks_by_name
, &string_hash_ops
);
295 r
= hashmap_put(manager
->networks_by_name
, network
->name
, network
);
299 LIST_FOREACH(routes
, route
, network
->static_routes
) {
300 if (!route
->family
) {
301 log_warning("Route section without Gateway field configured in %s. "
302 "Ignoring", filename
);
307 LIST_FOREACH(addresses
, address
, network
->static_addresses
) {
308 if (!address
->family
) {
309 log_warning("Address section without Address field configured in %s. "
310 "Ignoring", filename
);
320 int network_load(Manager
*manager
) {
322 _cleanup_strv_free_
char **files
= NULL
;
328 while ((network
= manager
->networks
))
329 network_free(network
);
331 r
= conf_files_list_strv(&files
, ".network", NULL
, 0, network_dirs
);
333 return log_error_errno(r
, "Failed to enumerate network files: %m");
335 STRV_FOREACH_BACKWARDS(f
, files
) {
336 r
= network_load_one(manager
, *f
);
344 void network_free(Network
*network
) {
345 IPv6ProxyNDPAddress
*ipv6_proxy_ndp_address
;
346 RoutingPolicyRule
*rule
;
358 free(network
->filename
);
360 free(network
->match_mac
);
361 strv_free(network
->match_path
);
362 strv_free(network
->match_driver
);
363 strv_free(network
->match_type
);
364 strv_free(network
->match_name
);
366 free(network
->description
);
367 free(network
->dhcp_vendor_class_identifier
);
368 free(network
->dhcp_hostname
);
372 strv_free(network
->ntp
);
374 strv_free(network
->search_domains
);
375 strv_free(network
->route_domains
);
376 strv_free(network
->bind_carrier
);
378 netdev_unref(network
->bridge
);
379 netdev_unref(network
->bond
);
380 netdev_unref(network
->vrf
);
382 HASHMAP_FOREACH(netdev
, network
->stacked_netdevs
, i
) {
383 hashmap_remove(network
->stacked_netdevs
, netdev
->ifname
);
384 netdev_unref(netdev
);
386 hashmap_free(network
->stacked_netdevs
);
388 while ((route
= network
->static_routes
))
391 while ((address
= network
->static_addresses
))
392 address_free(address
);
394 while ((fdb_entry
= network
->static_fdb_entries
))
395 fdb_entry_free(fdb_entry
);
397 while ((ipv6_proxy_ndp_address
= network
->ipv6_proxy_ndp_addresses
))
398 ipv6_proxy_ndp_address_free(ipv6_proxy_ndp_address
);
400 while ((label
= network
->address_labels
))
401 address_label_free(label
);
403 while ((prefix
= network
->static_prefixes
))
406 while ((rule
= network
->rules
))
407 routing_policy_rule_free(rule
);
409 hashmap_free(network
->addresses_by_section
);
410 hashmap_free(network
->routes_by_section
);
411 hashmap_free(network
->fdb_entries_by_section
);
412 hashmap_free(network
->address_labels_by_section
);
413 hashmap_free(network
->prefixes_by_section
);
414 hashmap_free(network
->rules_by_section
);
416 if (network
->manager
) {
417 if (network
->manager
->networks
)
418 LIST_REMOVE(networks
, network
->manager
->networks
, network
);
420 if (network
->manager
->networks_by_name
)
421 hashmap_remove(network
->manager
->networks_by_name
, network
->name
);
426 condition_free_list(network
->match_host
);
427 condition_free_list(network
->match_virt
);
428 condition_free_list(network
->match_kernel
);
429 condition_free_list(network
->match_arch
);
431 free(network
->dhcp_server_timezone
);
432 free(network
->dhcp_server_dns
);
433 free(network
->dhcp_server_ntp
);
435 set_free_free(network
->dnssec_negative_trust_anchors
);
440 int network_get_by_name(Manager
*manager
, const char *name
, Network
**ret
) {
447 network
= hashmap_get(manager
->networks_by_name
, name
);
456 int network_get(Manager
*manager
, struct udev_device
*device
,
457 const char *ifname
, const struct ether_addr
*address
,
460 struct udev_device
*parent
;
461 const char *path
= NULL
, *parent_driver
= NULL
, *driver
= NULL
, *devtype
= NULL
;
467 path
= udev_device_get_property_value(device
, "ID_PATH");
469 parent
= udev_device_get_parent(device
);
471 parent_driver
= udev_device_get_driver(parent
);
473 driver
= udev_device_get_property_value(device
, "ID_NET_DRIVER");
475 devtype
= udev_device_get_devtype(device
);
478 LIST_FOREACH(networks
, network
, manager
->networks
) {
479 if (net_match_config(network
->match_mac
, network
->match_path
,
480 network
->match_driver
, network
->match_type
,
481 network
->match_name
, network
->match_host
,
482 network
->match_virt
, network
->match_kernel
,
484 address
, path
, parent_driver
, driver
,
486 if (network
->match_name
&& device
) {
488 uint8_t name_assign_type
= NET_NAME_UNKNOWN
;
490 attr
= udev_device_get_sysattr_value(device
, "name_assign_type");
492 (void) safe_atou8(attr
, &name_assign_type
);
494 if (name_assign_type
== NET_NAME_ENUM
)
495 log_warning("%s: found matching network '%s', based on potentially unpredictable ifname",
496 ifname
, network
->filename
);
498 log_debug("%s: found matching network '%s'", ifname
, network
->filename
);
500 log_debug("%s: found matching network '%s'", ifname
, network
->filename
);
512 int network_apply(Network
*network
, Link
*link
) {
518 link
->network
= network
;
520 if (network
->ipv4ll_route
) {
523 r
= route_new_static(network
, NULL
, 0, &route
);
527 r
= inet_pton(AF_INET
, "169.254.0.0", &route
->dst
.in
);
533 route
->family
= AF_INET
;
534 route
->dst_prefixlen
= 16;
535 route
->scope
= RT_SCOPE_LINK
;
536 route
->priority
= IPV4LL_ROUTE_METRIC
;
537 route
->protocol
= RTPROT_STATIC
;
540 if (network
->n_dns
> 0 ||
541 !strv_isempty(network
->ntp
) ||
542 !strv_isempty(network
->search_domains
) ||
543 !strv_isempty(network
->route_domains
))
549 bool network_has_static_ipv6_addresses(Network
*network
) {
554 LIST_FOREACH(addresses
, address
, network
->static_addresses
) {
555 if (address
->family
== AF_INET6
)
562 int config_parse_netdev(const char *unit
,
563 const char *filename
,
566 unsigned section_line
,
572 Network
*network
= userdata
;
573 _cleanup_free_
char *kind_string
= NULL
;
584 kind_string
= strdup(lvalue
);
588 /* the keys are CamelCase versions of the kind */
589 for (p
= kind_string
; *p
; p
++)
592 kind
= netdev_kind_from_string(kind_string
);
593 if (kind
== _NETDEV_KIND_INVALID
) {
594 log_syntax(unit
, LOG_ERR
, filename
, line
, 0, "Invalid NetDev kind: %s", lvalue
);
598 r
= netdev_get(network
->manager
, rvalue
, &netdev
);
600 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "%s could not be found, ignoring assignment: %s", lvalue
, rvalue
);
604 if (netdev
->kind
!= kind
) {
605 log_syntax(unit
, LOG_ERR
, filename
, line
, 0, "NetDev is not a %s, ignoring assignment: %s", lvalue
, rvalue
);
610 case NETDEV_KIND_BRIDGE
:
611 network
->bridge
= netdev
;
614 case NETDEV_KIND_BOND
:
615 network
->bond
= netdev
;
618 case NETDEV_KIND_VRF
:
619 network
->vrf
= netdev
;
622 case NETDEV_KIND_VLAN
:
623 case NETDEV_KIND_MACVLAN
:
624 case NETDEV_KIND_MACVTAP
:
625 case NETDEV_KIND_IPVLAN
:
626 case NETDEV_KIND_VXLAN
:
627 case NETDEV_KIND_VCAN
:
628 r
= hashmap_put(network
->stacked_netdevs
, netdev
->ifname
, netdev
);
630 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Can not add NetDev '%s' to network: %m", rvalue
);
636 assert_not_reached("Can not parse NetDev");
644 int config_parse_domains(
646 const char *filename
,
649 unsigned section_line
,
664 if (isempty(rvalue
)) {
665 n
->search_domains
= strv_free(n
->search_domains
);
666 n
->route_domains
= strv_free(n
->route_domains
);
672 _cleanup_free_
char *w
= NULL
, *normalized
= NULL
;
676 r
= extract_first_word(&p
, &w
, NULL
, 0);
678 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Failed to extract search or route domain, ignoring: %s", rvalue
);
684 is_route
= w
[0] == '~';
685 domain
= is_route
? w
+ 1 : w
;
687 if (dns_name_is_root(domain
) || streq(domain
, "*")) {
688 /* If the root domain appears as is, or the special token "*" is found, we'll consider this as
689 * routing domain, unconditionally. */
691 domain
= "."; /* make sure we don't allow empty strings, thus write the root domain as "." */
694 r
= dns_name_normalize(domain
, &normalized
);
696 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "'%s' is not a valid domain name, ignoring.", domain
);
702 if (is_localhost(domain
)) {
703 log_syntax(unit
, LOG_ERR
, filename
, line
, 0, "'localhost' domain names may not be configure as search or route domains, ignoring assignment: %s", domain
);
709 r
= strv_extend(&n
->route_domains
, domain
);
714 r
= strv_extend(&n
->search_domains
, domain
);
720 strv_uniq(n
->route_domains
);
721 strv_uniq(n
->search_domains
);
726 int config_parse_tunnel(const char *unit
,
727 const char *filename
,
730 unsigned section_line
,
736 Network
*network
= userdata
;
745 r
= netdev_get(network
->manager
, rvalue
, &netdev
);
747 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Tunnel is invalid, ignoring assignment: %s", rvalue
);
751 if (netdev
->kind
!= NETDEV_KIND_IPIP
&&
752 netdev
->kind
!= NETDEV_KIND_SIT
&&
753 netdev
->kind
!= NETDEV_KIND_GRE
&&
754 netdev
->kind
!= NETDEV_KIND_GRETAP
&&
755 netdev
->kind
!= NETDEV_KIND_IP6GRE
&&
756 netdev
->kind
!= NETDEV_KIND_IP6GRETAP
&&
757 netdev
->kind
!= NETDEV_KIND_VTI
&&
758 netdev
->kind
!= NETDEV_KIND_VTI6
&&
759 netdev
->kind
!= NETDEV_KIND_IP6TNL
761 log_syntax(unit
, LOG_ERR
, filename
, line
, 0,
762 "NetDev is not a tunnel, ignoring assignment: %s", rvalue
);
766 r
= hashmap_put(network
->stacked_netdevs
, netdev
->ifname
, netdev
);
768 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Cannot add VLAN '%s' to network, ignoring: %m", rvalue
);
777 int config_parse_ipv4ll(
779 const char *filename
,
782 unsigned section_line
,
789 AddressFamilyBoolean
*link_local
= data
;
796 /* Note that this is mostly like
797 * config_parse_address_family_boolean(), except that it
798 * applies only to IPv4 */
800 SET_FLAG(*link_local
, ADDRESS_FAMILY_IPV4
, parse_boolean(rvalue
));
805 int config_parse_dhcp(
807 const char *filename
,
810 unsigned section_line
,
817 AddressFamilyBoolean
*dhcp
= data
, s
;
824 /* Note that this is mostly like
825 * config_parse_address_family_boolean(), except that it
826 * understands some old names for the enum values */
828 s
= address_family_boolean_from_string(rvalue
);
831 /* Previously, we had a slightly different enum here,
832 * support its values for compatbility. */
834 if (streq(rvalue
, "none"))
835 s
= ADDRESS_FAMILY_NO
;
836 else if (streq(rvalue
, "v4"))
837 s
= ADDRESS_FAMILY_IPV4
;
838 else if (streq(rvalue
, "v6"))
839 s
= ADDRESS_FAMILY_IPV6
;
840 else if (streq(rvalue
, "both"))
841 s
= ADDRESS_FAMILY_YES
;
843 log_syntax(unit
, LOG_ERR
, filename
, line
, 0, "Failed to parse DHCP option, ignoring: %s", rvalue
);
852 static const char* const dhcp_client_identifier_table
[_DHCP_CLIENT_ID_MAX
] = {
853 [DHCP_CLIENT_ID_MAC
] = "mac",
854 [DHCP_CLIENT_ID_DUID
] = "duid"
857 DEFINE_PRIVATE_STRING_TABLE_LOOKUP_FROM_STRING(dhcp_client_identifier
, DHCPClientIdentifier
);
858 DEFINE_CONFIG_PARSE_ENUM(config_parse_dhcp_client_identifier
, dhcp_client_identifier
, DHCPClientIdentifier
, "Failed to parse client identifier type");
860 int config_parse_ipv6token(
862 const char *filename
,
865 unsigned section_line
,
872 union in_addr_union buffer
;
873 struct in6_addr
*token
= data
;
881 r
= in_addr_from_string(AF_INET6
, rvalue
, &buffer
);
883 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Failed to parse IPv6 token, ignoring: %s", rvalue
);
887 r
= in_addr_is_null(AF_INET6
, &buffer
);
889 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "IPv6 token can not be the ANY address, ignoring: %s", rvalue
);
893 if ((buffer
.in6
.s6_addr32
[0] | buffer
.in6
.s6_addr32
[1]) != 0) {
894 log_syntax(unit
, LOG_ERR
, filename
, line
, 0, "IPv6 token can not be longer than 64 bits, ignoring: %s", rvalue
);
903 static const char* const ipv6_privacy_extensions_table
[_IPV6_PRIVACY_EXTENSIONS_MAX
] = {
904 [IPV6_PRIVACY_EXTENSIONS_NO
] = "no",
905 [IPV6_PRIVACY_EXTENSIONS_PREFER_PUBLIC
] = "prefer-public",
906 [IPV6_PRIVACY_EXTENSIONS_YES
] = "yes",
909 DEFINE_STRING_TABLE_LOOKUP(ipv6_privacy_extensions
, IPv6PrivacyExtensions
);
911 int config_parse_ipv6_privacy_extensions(
913 const char *filename
,
916 unsigned section_line
,
923 IPv6PrivacyExtensions
*ipv6_privacy_extensions
= data
;
929 assert(ipv6_privacy_extensions
);
931 /* Our enum shall be a superset of booleans, hence first try
932 * to parse as boolean, and then as enum */
934 k
= parse_boolean(rvalue
);
936 *ipv6_privacy_extensions
= IPV6_PRIVACY_EXTENSIONS_YES
;
938 *ipv6_privacy_extensions
= IPV6_PRIVACY_EXTENSIONS_NO
;
940 IPv6PrivacyExtensions s
;
942 s
= ipv6_privacy_extensions_from_string(rvalue
);
945 if (streq(rvalue
, "kernel"))
946 s
= _IPV6_PRIVACY_EXTENSIONS_INVALID
;
948 log_syntax(unit
, LOG_ERR
, filename
, line
, 0, "Failed to parse IPv6 privacy extensions option, ignoring: %s", rvalue
);
953 *ipv6_privacy_extensions
= s
;
959 int config_parse_hostname(
961 const char *filename
,
964 unsigned section_line
,
971 char **hostname
= data
, *hn
= NULL
;
978 r
= config_parse_string(unit
, filename
, line
, section
, section_line
, lvalue
, ltype
, rvalue
, &hn
, userdata
);
982 if (!hostname_is_valid(hn
, false)) {
983 log_syntax(unit
, LOG_ERR
, filename
, line
, 0, "Hostname is not valid, ignoring assignment: %s", rvalue
);
989 *hostname
= hostname_cleanup(hn
);
993 int config_parse_timezone(
995 const char *filename
,
998 unsigned section_line
,
1005 char **datap
= data
, *tz
= NULL
;
1012 r
= config_parse_string(unit
, filename
, line
, section
, section_line
, lvalue
, ltype
, rvalue
, &tz
, userdata
);
1016 if (!timezone_is_valid(tz
)) {
1017 log_syntax(unit
, LOG_ERR
, filename
, line
, 0, "Timezone is not valid, ignoring assignment: %s", rvalue
);
1028 int config_parse_dhcp_server_dns(
1030 const char *filename
,
1032 const char *section
,
1033 unsigned section_line
,
1041 const char *p
= rvalue
;
1049 _cleanup_free_
char *w
= NULL
;
1050 struct in_addr a
, *m
;
1052 r
= extract_first_word(&p
, &w
, NULL
, 0);
1056 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Failed to extract word, ignoring: %s", rvalue
);
1062 if (inet_pton(AF_INET
, w
, &a
) <= 0) {
1063 log_syntax(unit
, LOG_ERR
, filename
, line
, 0, "Failed to parse DNS server address, ignoring: %s", w
);
1067 m
= realloc(n
->dhcp_server_dns
, (n
->n_dhcp_server_dns
+ 1) * sizeof(struct in_addr
));
1071 m
[n
->n_dhcp_server_dns
++] = a
;
1072 n
->dhcp_server_dns
= m
;
1078 int config_parse_radv_dns(
1080 const char *filename
,
1082 const char *section
,
1083 unsigned section_line
,
1091 const char *p
= rvalue
;
1099 _cleanup_free_
char *w
= NULL
;
1100 union in_addr_union a
;
1102 r
= extract_first_word(&p
, &w
, NULL
, 0);
1106 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Failed to extract word, ignoring: %s", rvalue
);
1112 if (in_addr_from_string(AF_INET6
, w
, &a
) >= 0) {
1115 m
= realloc(n
->router_dns
, (n
->n_router_dns
+ 1) * sizeof(struct in6_addr
));
1119 m
[n
->n_router_dns
++] = a
.in6
;
1123 log_syntax(unit
, LOG_ERR
, filename
, line
, 0, "Failed to parse DNS server address, ignoring: %s", w
);
1130 int config_parse_dhcp_server_ntp(
1132 const char *filename
,
1134 const char *section
,
1135 unsigned section_line
,
1143 const char *p
= rvalue
;
1151 _cleanup_free_
char *w
= NULL
;
1152 struct in_addr a
, *m
;
1154 r
= extract_first_word(&p
, &w
, NULL
, 0);
1158 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Failed to extract word, ignoring: %s", rvalue
);
1164 if (inet_pton(AF_INET
, w
, &a
) <= 0) {
1165 log_syntax(unit
, LOG_ERR
, filename
, line
, 0, "Failed to parse NTP server address, ignoring: %s", w
);
1169 m
= realloc(n
->dhcp_server_ntp
, (n
->n_dhcp_server_ntp
+ 1) * sizeof(struct in_addr
));
1173 m
[n
->n_dhcp_server_ntp
++] = a
;
1174 n
->dhcp_server_ntp
= m
;
1178 int config_parse_dns(
1180 const char *filename
,
1182 const char *section
,
1183 unsigned section_line
,
1190 Network
*n
= userdata
;
1198 _cleanup_free_
char *w
= NULL
;
1199 union in_addr_union a
;
1200 struct in_addr_data
*m
;
1203 r
= extract_first_word(&rvalue
, &w
, NULL
, 0);
1207 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Invalid syntax, ignoring: %s", rvalue
);
1213 r
= in_addr_from_string_auto(w
, &family
, &a
);
1215 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Failed to parse dns server address, ignoring: %s", w
);
1219 m
= realloc(n
->dns
, (n
->n_dns
+ 1) * sizeof(struct in_addr_data
));
1223 m
[n
->n_dns
++] = (struct in_addr_data
) {
1234 int config_parse_dnssec_negative_trust_anchors(
1236 const char *filename
,
1238 const char *section
,
1239 unsigned section_line
,
1246 const char *p
= rvalue
;
1254 if (isempty(rvalue
)) {
1255 n
->dnssec_negative_trust_anchors
= set_free_free(n
->dnssec_negative_trust_anchors
);
1260 _cleanup_free_
char *w
= NULL
;
1262 r
= extract_first_word(&p
, &w
, NULL
, 0);
1264 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Failed to extract negative trust anchor domain, ignoring: %s", rvalue
);
1270 r
= dns_name_is_valid(w
);
1272 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "%s is not a valid domain name, ignoring.", w
);
1276 r
= set_ensure_allocated(&n
->dnssec_negative_trust_anchors
, &dns_name_hash_ops
);
1280 r
= set_put(n
->dnssec_negative_trust_anchors
, w
);
1290 int config_parse_ntp(
1292 const char *filename
,
1294 const char *section
,
1295 unsigned section_line
,
1309 if (isempty(rvalue
)) {
1315 _cleanup_free_
char *w
= NULL
;
1317 r
= extract_first_word(&rvalue
, &w
, NULL
, 0);
1321 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Failed to extract NTP server name, ignoring: %s", rvalue
);
1327 r
= dns_name_is_valid_or_address(w
);
1329 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "%s is not a valid domain name or IP address, ignoring.", w
);
1333 r
= strv_push(l
, w
);
1343 int config_parse_dhcp_route_table(const char *unit
,
1344 const char *filename
,
1346 const char *section
,
1347 unsigned section_line
,
1361 r
= safe_atou32(rvalue
, &rt
);
1363 log_syntax(unit
, LOG_ERR
, filename
, line
, r
,
1364 "Unable to read RouteTable, ignoring assignment: %s", rvalue
);
1368 *((uint32_t *)data
) = rt
;
1373 DEFINE_CONFIG_PARSE_ENUM(config_parse_dhcp_use_domains
, dhcp_use_domains
, DHCPUseDomains
, "Failed to parse DHCP use domains setting");
1375 static const char* const dhcp_use_domains_table
[_DHCP_USE_DOMAINS_MAX
] = {
1376 [DHCP_USE_DOMAINS_NO
] = "no",
1377 [DHCP_USE_DOMAINS_ROUTE
] = "route",
1378 [DHCP_USE_DOMAINS_YES
] = "yes",
1381 DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(dhcp_use_domains
, DHCPUseDomains
, DHCP_USE_DOMAINS_YES
);
1383 DEFINE_CONFIG_PARSE_ENUM(config_parse_lldp_mode
, lldp_mode
, LLDPMode
, "Failed to parse LLDP= setting.");
1385 static const char* const lldp_mode_table
[_LLDP_MODE_MAX
] = {
1386 [LLDP_MODE_NO
] = "no",
1387 [LLDP_MODE_YES
] = "yes",
1388 [LLDP_MODE_ROUTERS_ONLY
] = "routers-only",
1391 DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(lldp_mode
, LLDPMode
, LLDP_MODE_YES
);