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 /* RFC7844 section 3.6.
117 * same comments as previous option */
118 network
->dhcp_use_routes
= false;
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 /* NOTE: this var might be overwriten by network_apply_anonymize_if_set */
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 network
->dhcp_use_mtu
= true;
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
->use_bpdu
= true;
236 network
->allow_port_to_be_root
= true;
237 network
->unicast_flood
= true;
238 network
->priority
= LINK_BRIDGE_PORT_PRIORITY_INVALID
;
240 network
->lldp_mode
= LLDP_MODE_ROUTERS_ONLY
;
242 network
->llmnr
= RESOLVE_SUPPORT_YES
;
243 network
->mdns
= RESOLVE_SUPPORT_NO
;
244 network
->dnssec_mode
= _DNSSEC_MODE_INVALID
;
246 network
->link_local
= ADDRESS_FAMILY_IPV6
;
248 network
->ipv6_privacy_extensions
= IPV6_PRIVACY_EXTENSIONS_NO
;
249 network
->ipv6_accept_ra
= -1;
250 network
->ipv6_dad_transmits
= -1;
251 network
->ipv6_hop_limit
= -1;
252 network
->ipv6_proxy_ndp
= -1;
253 network
->duid
.type
= _DUID_TYPE_INVALID
;
254 network
->proxy_arp
= -1;
256 network
->ipv6_accept_ra_use_dns
= true;
257 network
->ipv6_accept_ra_route_table
= RT_TABLE_MAIN
;
259 dropin_dirname
= strjoina(network
->name
, ".network.d");
261 r
= config_parse_many(filename
, network_dirs
, dropin_dirname
,
267 "RoutingPolicyRule\0"
270 "DHCPv4\0" /* compat */
273 "IPv6NDPProxyAddress\0"
277 "IPv6PrefixDelegation\0"
279 config_item_perf_lookup
, network_network_gperf_lookup
,
284 network_apply_anonymize_if_set(network
);
286 /* IPMasquerade=yes implies IPForward=yes */
287 if (network
->ip_masquerade
)
288 network
->ip_forward
|= ADDRESS_FAMILY_IPV4
;
290 LIST_PREPEND(networks
, manager
->networks
, network
);
292 r
= hashmap_ensure_allocated(&manager
->networks_by_name
, &string_hash_ops
);
296 r
= hashmap_put(manager
->networks_by_name
, network
->name
, network
);
300 LIST_FOREACH(routes
, route
, network
->static_routes
) {
301 if (!route
->family
) {
302 log_warning("Route section without Gateway field configured in %s. "
303 "Ignoring", filename
);
308 LIST_FOREACH(addresses
, address
, network
->static_addresses
) {
309 if (!address
->family
) {
310 log_warning("Address section without Address field configured in %s. "
311 "Ignoring", filename
);
321 int network_load(Manager
*manager
) {
323 _cleanup_strv_free_
char **files
= NULL
;
329 while ((network
= manager
->networks
))
330 network_free(network
);
332 r
= conf_files_list_strv(&files
, ".network", NULL
, 0, network_dirs
);
334 return log_error_errno(r
, "Failed to enumerate network files: %m");
336 STRV_FOREACH_BACKWARDS(f
, files
) {
337 r
= network_load_one(manager
, *f
);
345 void network_free(Network
*network
) {
346 IPv6ProxyNDPAddress
*ipv6_proxy_ndp_address
;
347 RoutingPolicyRule
*rule
;
359 free(network
->filename
);
361 free(network
->match_mac
);
362 strv_free(network
->match_path
);
363 strv_free(network
->match_driver
);
364 strv_free(network
->match_type
);
365 strv_free(network
->match_name
);
367 free(network
->description
);
368 free(network
->dhcp_vendor_class_identifier
);
369 free(network
->dhcp_hostname
);
373 strv_free(network
->ntp
);
375 strv_free(network
->search_domains
);
376 strv_free(network
->route_domains
);
377 strv_free(network
->bind_carrier
);
379 netdev_unref(network
->bridge
);
380 netdev_unref(network
->bond
);
381 netdev_unref(network
->vrf
);
383 HASHMAP_FOREACH(netdev
, network
->stacked_netdevs
, i
) {
384 hashmap_remove(network
->stacked_netdevs
, netdev
->ifname
);
385 netdev_unref(netdev
);
387 hashmap_free(network
->stacked_netdevs
);
389 while ((route
= network
->static_routes
))
392 while ((address
= network
->static_addresses
))
393 address_free(address
);
395 while ((fdb_entry
= network
->static_fdb_entries
))
396 fdb_entry_free(fdb_entry
);
398 while ((ipv6_proxy_ndp_address
= network
->ipv6_proxy_ndp_addresses
))
399 ipv6_proxy_ndp_address_free(ipv6_proxy_ndp_address
);
401 while ((label
= network
->address_labels
))
402 address_label_free(label
);
404 while ((prefix
= network
->static_prefixes
))
407 while ((rule
= network
->rules
))
408 routing_policy_rule_free(rule
);
410 hashmap_free(network
->addresses_by_section
);
411 hashmap_free(network
->routes_by_section
);
412 hashmap_free(network
->fdb_entries_by_section
);
413 hashmap_free(network
->address_labels_by_section
);
414 hashmap_free(network
->prefixes_by_section
);
415 hashmap_free(network
->rules_by_section
);
417 if (network
->manager
) {
418 if (network
->manager
->networks
)
419 LIST_REMOVE(networks
, network
->manager
->networks
, network
);
421 if (network
->manager
->networks_by_name
)
422 hashmap_remove(network
->manager
->networks_by_name
, network
->name
);
427 condition_free_list(network
->match_host
);
428 condition_free_list(network
->match_virt
);
429 condition_free_list(network
->match_kernel
);
430 condition_free_list(network
->match_arch
);
432 free(network
->dhcp_server_timezone
);
433 free(network
->dhcp_server_dns
);
434 free(network
->dhcp_server_ntp
);
436 set_free_free(network
->dnssec_negative_trust_anchors
);
441 int network_get_by_name(Manager
*manager
, const char *name
, Network
**ret
) {
448 network
= hashmap_get(manager
->networks_by_name
, name
);
457 int network_get(Manager
*manager
, struct udev_device
*device
,
458 const char *ifname
, const struct ether_addr
*address
,
461 struct udev_device
*parent
;
462 const char *path
= NULL
, *parent_driver
= NULL
, *driver
= NULL
, *devtype
= NULL
;
468 path
= udev_device_get_property_value(device
, "ID_PATH");
470 parent
= udev_device_get_parent(device
);
472 parent_driver
= udev_device_get_driver(parent
);
474 driver
= udev_device_get_property_value(device
, "ID_NET_DRIVER");
476 devtype
= udev_device_get_devtype(device
);
479 LIST_FOREACH(networks
, network
, manager
->networks
) {
480 if (net_match_config(network
->match_mac
, network
->match_path
,
481 network
->match_driver
, network
->match_type
,
482 network
->match_name
, network
->match_host
,
483 network
->match_virt
, network
->match_kernel
,
485 address
, path
, parent_driver
, driver
,
487 if (network
->match_name
&& device
) {
489 uint8_t name_assign_type
= NET_NAME_UNKNOWN
;
491 attr
= udev_device_get_sysattr_value(device
, "name_assign_type");
493 (void) safe_atou8(attr
, &name_assign_type
);
495 if (name_assign_type
== NET_NAME_ENUM
)
496 log_warning("%s: found matching network '%s', based on potentially unpredictable ifname",
497 ifname
, network
->filename
);
499 log_debug("%s: found matching network '%s'", ifname
, network
->filename
);
501 log_debug("%s: found matching network '%s'", ifname
, network
->filename
);
513 int network_apply(Network
*network
, Link
*link
) {
519 link
->network
= network
;
521 if (network
->ipv4ll_route
) {
524 r
= route_new_static(network
, NULL
, 0, &route
);
528 r
= inet_pton(AF_INET
, "169.254.0.0", &route
->dst
.in
);
534 route
->family
= AF_INET
;
535 route
->dst_prefixlen
= 16;
536 route
->scope
= RT_SCOPE_LINK
;
537 route
->priority
= IPV4LL_ROUTE_METRIC
;
538 route
->protocol
= RTPROT_STATIC
;
541 if (network
->n_dns
> 0 ||
542 !strv_isempty(network
->ntp
) ||
543 !strv_isempty(network
->search_domains
) ||
544 !strv_isempty(network
->route_domains
))
550 bool network_has_static_ipv6_addresses(Network
*network
) {
555 LIST_FOREACH(addresses
, address
, network
->static_addresses
) {
556 if (address
->family
== AF_INET6
)
563 int config_parse_netdev(const char *unit
,
564 const char *filename
,
567 unsigned section_line
,
573 Network
*network
= userdata
;
574 _cleanup_free_
char *kind_string
= NULL
;
585 kind_string
= strdup(lvalue
);
589 /* the keys are CamelCase versions of the kind */
590 for (p
= kind_string
; *p
; p
++)
593 kind
= netdev_kind_from_string(kind_string
);
594 if (kind
== _NETDEV_KIND_INVALID
) {
595 log_syntax(unit
, LOG_ERR
, filename
, line
, 0, "Invalid NetDev kind: %s", lvalue
);
599 r
= netdev_get(network
->manager
, rvalue
, &netdev
);
601 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "%s could not be found, ignoring assignment: %s", lvalue
, rvalue
);
605 if (netdev
->kind
!= kind
) {
606 log_syntax(unit
, LOG_ERR
, filename
, line
, 0, "NetDev is not a %s, ignoring assignment: %s", lvalue
, rvalue
);
611 case NETDEV_KIND_BRIDGE
:
612 network
->bridge
= netdev
;
615 case NETDEV_KIND_BOND
:
616 network
->bond
= netdev
;
619 case NETDEV_KIND_VRF
:
620 network
->vrf
= netdev
;
623 case NETDEV_KIND_VLAN
:
624 case NETDEV_KIND_MACVLAN
:
625 case NETDEV_KIND_MACVTAP
:
626 case NETDEV_KIND_IPVLAN
:
627 case NETDEV_KIND_VXLAN
:
628 case NETDEV_KIND_VCAN
:
629 r
= hashmap_put(network
->stacked_netdevs
, netdev
->ifname
, netdev
);
631 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Can not add NetDev '%s' to network: %m", rvalue
);
637 assert_not_reached("Can not parse NetDev");
645 int config_parse_domains(
647 const char *filename
,
650 unsigned section_line
,
665 if (isempty(rvalue
)) {
666 n
->search_domains
= strv_free(n
->search_domains
);
667 n
->route_domains
= strv_free(n
->route_domains
);
673 _cleanup_free_
char *w
= NULL
, *normalized
= NULL
;
677 r
= extract_first_word(&p
, &w
, NULL
, 0);
679 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Failed to extract search or route domain, ignoring: %s", rvalue
);
685 is_route
= w
[0] == '~';
686 domain
= is_route
? w
+ 1 : w
;
688 if (dns_name_is_root(domain
) || streq(domain
, "*")) {
689 /* If the root domain appears as is, or the special token "*" is found, we'll consider this as
690 * routing domain, unconditionally. */
692 domain
= "."; /* make sure we don't allow empty strings, thus write the root domain as "." */
695 r
= dns_name_normalize(domain
, &normalized
);
697 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "'%s' is not a valid domain name, ignoring.", domain
);
703 if (is_localhost(domain
)) {
704 log_syntax(unit
, LOG_ERR
, filename
, line
, 0, "'localhost' domain names may not be configure as search or route domains, ignoring assignment: %s", domain
);
710 r
= strv_extend(&n
->route_domains
, domain
);
715 r
= strv_extend(&n
->search_domains
, domain
);
721 strv_uniq(n
->route_domains
);
722 strv_uniq(n
->search_domains
);
727 int config_parse_tunnel(const char *unit
,
728 const char *filename
,
731 unsigned section_line
,
737 Network
*network
= userdata
;
746 r
= netdev_get(network
->manager
, rvalue
, &netdev
);
748 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Tunnel is invalid, ignoring assignment: %s", rvalue
);
752 if (!IN_SET(netdev
->kind
, NETDEV_KIND_IPIP
, NETDEV_KIND_SIT
, NETDEV_KIND_GRE
, NETDEV_KIND_GRETAP
, NETDEV_KIND_IP6GRE
, NETDEV_KIND_IP6GRETAP
, NETDEV_KIND_VTI
, NETDEV_KIND_VTI6
, NETDEV_KIND_IP6TNL
)) {
753 log_syntax(unit
, LOG_ERR
, filename
, line
, 0,
754 "NetDev is not a tunnel, ignoring assignment: %s", rvalue
);
758 r
= hashmap_put(network
->stacked_netdevs
, netdev
->ifname
, netdev
);
760 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Cannot add VLAN '%s' to network, ignoring: %m", rvalue
);
769 int config_parse_ipv4ll(
771 const char *filename
,
774 unsigned section_line
,
781 AddressFamilyBoolean
*link_local
= data
;
788 /* Note that this is mostly like
789 * config_parse_address_family_boolean(), except that it
790 * applies only to IPv4 */
792 SET_FLAG(*link_local
, ADDRESS_FAMILY_IPV4
, parse_boolean(rvalue
));
797 int config_parse_dhcp(
799 const char *filename
,
802 unsigned section_line
,
809 AddressFamilyBoolean
*dhcp
= data
, s
;
816 /* Note that this is mostly like
817 * config_parse_address_family_boolean(), except that it
818 * understands some old names for the enum values */
820 s
= address_family_boolean_from_string(rvalue
);
823 /* Previously, we had a slightly different enum here,
824 * support its values for compatbility. */
826 if (streq(rvalue
, "none"))
827 s
= ADDRESS_FAMILY_NO
;
828 else if (streq(rvalue
, "v4"))
829 s
= ADDRESS_FAMILY_IPV4
;
830 else if (streq(rvalue
, "v6"))
831 s
= ADDRESS_FAMILY_IPV6
;
832 else if (streq(rvalue
, "both"))
833 s
= ADDRESS_FAMILY_YES
;
835 log_syntax(unit
, LOG_ERR
, filename
, line
, 0, "Failed to parse DHCP option, ignoring: %s", rvalue
);
844 static const char* const dhcp_client_identifier_table
[_DHCP_CLIENT_ID_MAX
] = {
845 [DHCP_CLIENT_ID_MAC
] = "mac",
846 [DHCP_CLIENT_ID_DUID
] = "duid"
849 DEFINE_PRIVATE_STRING_TABLE_LOOKUP_FROM_STRING(dhcp_client_identifier
, DHCPClientIdentifier
);
850 DEFINE_CONFIG_PARSE_ENUM(config_parse_dhcp_client_identifier
, dhcp_client_identifier
, DHCPClientIdentifier
, "Failed to parse client identifier type");
852 int config_parse_ipv6token(
854 const char *filename
,
857 unsigned section_line
,
864 union in_addr_union buffer
;
865 struct in6_addr
*token
= data
;
873 r
= in_addr_from_string(AF_INET6
, rvalue
, &buffer
);
875 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Failed to parse IPv6 token, ignoring: %s", rvalue
);
879 r
= in_addr_is_null(AF_INET6
, &buffer
);
881 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "IPv6 token can not be the ANY address, ignoring: %s", rvalue
);
885 if ((buffer
.in6
.s6_addr32
[0] | buffer
.in6
.s6_addr32
[1]) != 0) {
886 log_syntax(unit
, LOG_ERR
, filename
, line
, 0, "IPv6 token can not be longer than 64 bits, ignoring: %s", rvalue
);
895 static const char* const ipv6_privacy_extensions_table
[_IPV6_PRIVACY_EXTENSIONS_MAX
] = {
896 [IPV6_PRIVACY_EXTENSIONS_NO
] = "no",
897 [IPV6_PRIVACY_EXTENSIONS_PREFER_PUBLIC
] = "prefer-public",
898 [IPV6_PRIVACY_EXTENSIONS_YES
] = "yes",
901 DEFINE_STRING_TABLE_LOOKUP(ipv6_privacy_extensions
, IPv6PrivacyExtensions
);
903 int config_parse_ipv6_privacy_extensions(
905 const char *filename
,
908 unsigned section_line
,
915 IPv6PrivacyExtensions
*ipv6_privacy_extensions
= data
;
921 assert(ipv6_privacy_extensions
);
923 /* Our enum shall be a superset of booleans, hence first try
924 * to parse as boolean, and then as enum */
926 k
= parse_boolean(rvalue
);
928 *ipv6_privacy_extensions
= IPV6_PRIVACY_EXTENSIONS_YES
;
930 *ipv6_privacy_extensions
= IPV6_PRIVACY_EXTENSIONS_NO
;
932 IPv6PrivacyExtensions s
;
934 s
= ipv6_privacy_extensions_from_string(rvalue
);
937 if (streq(rvalue
, "kernel"))
938 s
= _IPV6_PRIVACY_EXTENSIONS_INVALID
;
940 log_syntax(unit
, LOG_ERR
, filename
, line
, 0, "Failed to parse IPv6 privacy extensions option, ignoring: %s", rvalue
);
945 *ipv6_privacy_extensions
= s
;
951 int config_parse_hostname(
953 const char *filename
,
956 unsigned section_line
,
963 char **hostname
= data
, *hn
= NULL
;
970 r
= config_parse_string(unit
, filename
, line
, section
, section_line
, lvalue
, ltype
, rvalue
, &hn
, userdata
);
974 if (!hostname_is_valid(hn
, false)) {
975 log_syntax(unit
, LOG_ERR
, filename
, line
, 0, "Hostname is not valid, ignoring assignment: %s", rvalue
);
981 *hostname
= hostname_cleanup(hn
);
985 int config_parse_timezone(
987 const char *filename
,
990 unsigned section_line
,
997 char **datap
= data
, *tz
= NULL
;
1004 r
= config_parse_string(unit
, filename
, line
, section
, section_line
, lvalue
, ltype
, rvalue
, &tz
, userdata
);
1008 if (!timezone_is_valid(tz
)) {
1009 log_syntax(unit
, LOG_ERR
, filename
, line
, 0, "Timezone is not valid, ignoring assignment: %s", rvalue
);
1020 int config_parse_dhcp_server_dns(
1022 const char *filename
,
1024 const char *section
,
1025 unsigned section_line
,
1033 const char *p
= rvalue
;
1041 _cleanup_free_
char *w
= NULL
;
1042 struct in_addr a
, *m
;
1044 r
= extract_first_word(&p
, &w
, NULL
, 0);
1048 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Failed to extract word, ignoring: %s", rvalue
);
1054 if (inet_pton(AF_INET
, w
, &a
) <= 0) {
1055 log_syntax(unit
, LOG_ERR
, filename
, line
, 0, "Failed to parse DNS server address, ignoring: %s", w
);
1059 m
= realloc(n
->dhcp_server_dns
, (n
->n_dhcp_server_dns
+ 1) * sizeof(struct in_addr
));
1063 m
[n
->n_dhcp_server_dns
++] = a
;
1064 n
->dhcp_server_dns
= m
;
1070 int config_parse_radv_dns(
1072 const char *filename
,
1074 const char *section
,
1075 unsigned section_line
,
1083 const char *p
= rvalue
;
1091 _cleanup_free_
char *w
= NULL
;
1092 union in_addr_union a
;
1094 r
= extract_first_word(&p
, &w
, NULL
, 0);
1098 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Failed to extract word, ignoring: %s", rvalue
);
1104 if (in_addr_from_string(AF_INET6
, w
, &a
) >= 0) {
1107 m
= realloc(n
->router_dns
, (n
->n_router_dns
+ 1) * sizeof(struct in6_addr
));
1111 m
[n
->n_router_dns
++] = a
.in6
;
1115 log_syntax(unit
, LOG_ERR
, filename
, line
, 0, "Failed to parse DNS server address, ignoring: %s", w
);
1122 int config_parse_radv_search_domains(
1124 const char *filename
,
1126 const char *section
,
1127 unsigned section_line
,
1135 const char *p
= rvalue
;
1143 _cleanup_free_
char *w
= NULL
;
1144 _cleanup_free_
char *idna
= NULL
;
1146 r
= extract_first_word(&p
, &w
, NULL
, 0);
1150 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Failed to extract word, ignoring: %s", rvalue
);
1156 r
= dns_name_apply_idna(w
, &idna
);
1158 r
= strv_push(&n
->router_search_domains
, idna
);
1161 } else if (r
== 0) {
1162 r
= strv_push(&n
->router_search_domains
, w
);
1171 int config_parse_dhcp_server_ntp(
1173 const char *filename
,
1175 const char *section
,
1176 unsigned section_line
,
1184 const char *p
= rvalue
;
1192 _cleanup_free_
char *w
= NULL
;
1193 struct in_addr a
, *m
;
1195 r
= extract_first_word(&p
, &w
, NULL
, 0);
1199 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Failed to extract word, ignoring: %s", rvalue
);
1205 if (inet_pton(AF_INET
, w
, &a
) <= 0) {
1206 log_syntax(unit
, LOG_ERR
, filename
, line
, 0, "Failed to parse NTP server address, ignoring: %s", w
);
1210 m
= realloc(n
->dhcp_server_ntp
, (n
->n_dhcp_server_ntp
+ 1) * sizeof(struct in_addr
));
1214 m
[n
->n_dhcp_server_ntp
++] = a
;
1215 n
->dhcp_server_ntp
= m
;
1219 int config_parse_dns(
1221 const char *filename
,
1223 const char *section
,
1224 unsigned section_line
,
1231 Network
*n
= userdata
;
1239 _cleanup_free_
char *w
= NULL
;
1240 union in_addr_union a
;
1241 struct in_addr_data
*m
;
1244 r
= extract_first_word(&rvalue
, &w
, NULL
, 0);
1248 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Invalid syntax, ignoring: %s", rvalue
);
1254 r
= in_addr_from_string_auto(w
, &family
, &a
);
1256 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Failed to parse dns server address, ignoring: %s", w
);
1260 m
= realloc(n
->dns
, (n
->n_dns
+ 1) * sizeof(struct in_addr_data
));
1264 m
[n
->n_dns
++] = (struct in_addr_data
) {
1275 int config_parse_dnssec_negative_trust_anchors(
1277 const char *filename
,
1279 const char *section
,
1280 unsigned section_line
,
1287 const char *p
= rvalue
;
1295 if (isempty(rvalue
)) {
1296 n
->dnssec_negative_trust_anchors
= set_free_free(n
->dnssec_negative_trust_anchors
);
1301 _cleanup_free_
char *w
= NULL
;
1303 r
= extract_first_word(&p
, &w
, NULL
, 0);
1305 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Failed to extract negative trust anchor domain, ignoring: %s", rvalue
);
1311 r
= dns_name_is_valid(w
);
1313 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "%s is not a valid domain name, ignoring.", w
);
1317 r
= set_ensure_allocated(&n
->dnssec_negative_trust_anchors
, &dns_name_hash_ops
);
1321 r
= set_put(n
->dnssec_negative_trust_anchors
, w
);
1331 int config_parse_ntp(
1333 const char *filename
,
1335 const char *section
,
1336 unsigned section_line
,
1350 if (isempty(rvalue
)) {
1356 _cleanup_free_
char *w
= NULL
;
1358 r
= extract_first_word(&rvalue
, &w
, NULL
, 0);
1362 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Failed to extract NTP server name, ignoring: %s", rvalue
);
1368 r
= dns_name_is_valid_or_address(w
);
1370 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "%s is not a valid domain name or IP address, ignoring.", w
);
1374 r
= strv_push(l
, w
);
1384 int config_parse_dhcp_route_table(const char *unit
,
1385 const char *filename
,
1387 const char *section
,
1388 unsigned section_line
,
1394 Network
*network
= data
;
1403 r
= safe_atou32(rvalue
, &rt
);
1405 log_syntax(unit
, LOG_ERR
, filename
, line
, r
,
1406 "Unable to read RouteTable, ignoring assignment: %s", rvalue
);
1410 network
->dhcp_route_table
= rt
;
1411 network
->dhcp_route_table_set
= true;
1416 DEFINE_CONFIG_PARSE_ENUM(config_parse_dhcp_use_domains
, dhcp_use_domains
, DHCPUseDomains
, "Failed to parse DHCP use domains setting");
1418 static const char* const dhcp_use_domains_table
[_DHCP_USE_DOMAINS_MAX
] = {
1419 [DHCP_USE_DOMAINS_NO
] = "no",
1420 [DHCP_USE_DOMAINS_ROUTE
] = "route",
1421 [DHCP_USE_DOMAINS_YES
] = "yes",
1424 DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(dhcp_use_domains
, DHCPUseDomains
, DHCP_USE_DOMAINS_YES
);
1426 DEFINE_CONFIG_PARSE_ENUM(config_parse_lldp_mode
, lldp_mode
, LLDPMode
, "Failed to parse LLDP= setting.");
1428 static const char* const lldp_mode_table
[_LLDP_MODE_MAX
] = {
1429 [LLDP_MODE_NO
] = "no",
1430 [LLDP_MODE_YES
] = "yes",
1431 [LLDP_MODE_ROUTERS_ONLY
] = "routers-only",
1434 DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(lldp_mode
, LLDPMode
, LLDP_MODE_YES
);