1 /* SPDX-License-Identifier: LGPL-2.1+ */
3 This file is part of systemd.
5 Copyright 2013 Tom Gundersen <teg@jklm.no>
11 #include "alloc-util.h"
12 #include "conf-files.h"
13 #include "conf-parser.h"
14 #include "dns-domain.h"
16 #include "hostname-util.h"
17 #include "in-addr-util.h"
18 #include "network-internal.h"
19 #include "networkd-manager.h"
20 #include "networkd-network.h"
21 #include "parse-util.h"
23 #include "stat-util.h"
24 #include "string-table.h"
25 #include "string-util.h"
29 static void network_config_hash_func(const void *p
, struct siphash
*state
) {
30 const NetworkConfigSection
*c
= p
;
32 siphash24_compress(c
->filename
, strlen(c
->filename
), state
);
33 siphash24_compress(&c
->line
, sizeof(c
->line
), state
);
36 static int network_config_compare_func(const void *a
, const void *b
) {
37 const NetworkConfigSection
*x
= a
, *y
= b
;
40 r
= strcmp(x
->filename
, y
->filename
);
44 return y
->line
- x
->line
;
47 const struct hash_ops network_config_hash_ops
= {
48 .hash
= network_config_hash_func
,
49 .compare
= network_config_compare_func
,
52 int network_config_section_new(const char *filename
, unsigned line
, NetworkConfigSection
**s
) {
53 NetworkConfigSection
*cs
;
55 cs
= malloc0(offsetof(NetworkConfigSection
, filename
) + strlen(filename
) + 1);
59 strcpy(cs
->filename
, filename
);
67 void network_config_section_free(NetworkConfigSection
*cs
) {
71 /* Set defaults following RFC7844 */
72 void network_apply_anonymize_if_set(Network
*network
) {
73 if (!network
->dhcp_anonymize
)
76 SHOULD NOT send the Host Name option */
77 network
->dhcp_send_hostname
= false;
78 /* RFC7844 section 3.:
79 MAY contain the Client Identifier option
81 clients MUST use client identifiers based solely
82 on the link-layer address */
83 /* NOTE: Using MAC, as it does not reveal extra information,
84 * and some servers might not answer if this option is not sent */
85 network
->dhcp_client_identifier
= DHCP_CLIENT_ID_MAC
;
87 SHOULD NOT use the Vendor Class Identifier option */
88 /* NOTE: it was not initiallized to any value in network_load_one. */
89 network
->dhcp_vendor_class_identifier
= false;
90 /* RFC7844 section 3.6.:
91 The client intending to protect its privacy SHOULD only request a
92 minimal number of options in the PRL and SHOULD also randomly shuffle
93 the ordering of option codes in the PRL. If this random ordering
94 cannot be implemented, the client MAY order the option codes in the
95 PRL by option code number (lowest to highest).
97 /* NOTE: dhcp_use_mtu is false by default,
98 * though it was not initiallized to any value in network_load_one.
99 * Maybe there should be another var called *send*?
100 * (to use the MTU sent by the server but to do not send
101 * the option in the PRL). */
102 network
->dhcp_use_mtu
= false;
103 /* NOTE: when Anonymize=yes, the PRL route options are sent by default,
104 * but this is needed to use them. */
105 network
->dhcp_use_routes
= true;
106 /* RFC7844 section 3.6.
107 * same comments as previous option */
108 network
->dhcp_use_timezone
= false;
111 static int network_load_one(Manager
*manager
, const char *filename
) {
112 _cleanup_network_free_ Network
*network
= NULL
;
113 _cleanup_fclose_
FILE *file
= NULL
;
115 const char *dropin_dirname
;
123 file
= fopen(filename
, "re");
131 if (null_or_empty_fd(fileno(file
))) {
132 log_debug("Skipping empty file: %s", filename
);
136 network
= new0(Network
, 1);
140 network
->manager
= manager
;
142 LIST_HEAD_INIT(network
->static_addresses
);
143 LIST_HEAD_INIT(network
->static_routes
);
144 LIST_HEAD_INIT(network
->static_fdb_entries
);
145 LIST_HEAD_INIT(network
->ipv6_proxy_ndp_addresses
);
146 LIST_HEAD_INIT(network
->address_labels
);
147 LIST_HEAD_INIT(network
->static_prefixes
);
148 LIST_HEAD_INIT(network
->rules
);
150 network
->stacked_netdevs
= hashmap_new(&string_hash_ops
);
151 if (!network
->stacked_netdevs
)
154 network
->addresses_by_section
= hashmap_new(&network_config_hash_ops
);
155 if (!network
->addresses_by_section
)
158 network
->routes_by_section
= hashmap_new(&network_config_hash_ops
);
159 if (!network
->routes_by_section
)
162 network
->fdb_entries_by_section
= hashmap_new(NULL
);
163 if (!network
->fdb_entries_by_section
)
166 network
->address_labels_by_section
= hashmap_new(&network_config_hash_ops
);
167 if (!network
->address_labels_by_section
)
170 network
->prefixes_by_section
= hashmap_new(&network_config_hash_ops
);
171 if (!network
->prefixes_by_section
)
174 network
->rules_by_section
= hashmap_new(&network_config_hash_ops
);
175 if (!network
->rules_by_section
)
178 network
->filename
= strdup(filename
);
179 if (!network
->filename
)
182 network
->name
= strdup(basename(filename
));
186 d
= strrchr(network
->name
, '.');
190 assert(streq(d
, ".network"));
194 network
->required_for_online
= true;
195 network
->dhcp
= ADDRESS_FAMILY_NO
;
196 network
->dhcp_use_ntp
= true;
197 network
->dhcp_use_dns
= true;
198 network
->dhcp_use_hostname
= true;
199 network
->dhcp_use_routes
= true;
200 /* NOTE: this var might be overwriten by network_apply_anonymize_if_set */
201 network
->dhcp_send_hostname
= true;
202 /* To enable/disable RFC7844 Anonymity Profiles */
203 network
->dhcp_anonymize
= false;
204 network
->dhcp_route_metric
= DHCP_ROUTE_METRIC
;
205 /* NOTE: this var might be overwrite by network_apply_anonymize_if_set */
206 network
->dhcp_client_identifier
= DHCP_CLIENT_ID_DUID
;
207 network
->dhcp_route_table
= RT_TABLE_MAIN
;
208 network
->dhcp_route_table_set
= false;
209 /* NOTE: the following vars were not set to any default,
210 * even if they are commented in the man?
211 * These vars might be overwriten by network_apply_anonymize_if_set */
212 network
->dhcp_vendor_class_identifier
= false;
213 /* NOTE: from man: UseMTU=... Defaults to false*/
214 network
->dhcp_use_mtu
= false;
215 /* NOTE: from man: UseTimezone=... Defaults to "no".*/
216 network
->dhcp_use_timezone
= false;
217 network
->rapid_commit
= true;
219 network
->dhcp_server_emit_dns
= true;
220 network
->dhcp_server_emit_ntp
= true;
221 network
->dhcp_server_emit_router
= true;
222 network
->dhcp_server_emit_timezone
= true;
224 network
->router_emit_dns
= true;
225 network
->router_emit_domains
= true;
227 network
->use_bpdu
= true;
228 network
->allow_port_to_be_root
= true;
229 network
->unicast_flood
= true;
230 network
->priority
= LINK_BRIDGE_PORT_PRIORITY_INVALID
;
232 network
->lldp_mode
= LLDP_MODE_ROUTERS_ONLY
;
234 network
->llmnr
= RESOLVE_SUPPORT_YES
;
235 network
->mdns
= RESOLVE_SUPPORT_NO
;
236 network
->dnssec_mode
= _DNSSEC_MODE_INVALID
;
238 network
->link_local
= ADDRESS_FAMILY_IPV6
;
240 network
->ipv6_privacy_extensions
= IPV6_PRIVACY_EXTENSIONS_NO
;
241 network
->ipv6_accept_ra
= -1;
242 network
->ipv6_dad_transmits
= -1;
243 network
->ipv6_hop_limit
= -1;
244 network
->ipv6_proxy_ndp
= -1;
245 network
->duid
.type
= _DUID_TYPE_INVALID
;
246 network
->proxy_arp
= -1;
248 network
->ipv6_accept_ra_use_dns
= true;
249 network
->ipv6_accept_ra_route_table
= RT_TABLE_MAIN
;
251 dropin_dirname
= strjoina(network
->name
, ".network.d");
253 r
= config_parse_many(filename
, network_dirs
, dropin_dirname
,
259 "RoutingPolicyRule\0"
262 "DHCPv4\0" /* compat */
265 "IPv6NDPProxyAddress\0"
269 "IPv6PrefixDelegation\0"
271 config_item_perf_lookup
, network_network_gperf_lookup
,
272 CONFIG_PARSE_WARN
, network
);
276 network_apply_anonymize_if_set(network
);
278 /* IPMasquerade=yes implies IPForward=yes */
279 if (network
->ip_masquerade
)
280 network
->ip_forward
|= ADDRESS_FAMILY_IPV4
;
282 LIST_PREPEND(networks
, manager
->networks
, network
);
284 r
= hashmap_ensure_allocated(&manager
->networks_by_name
, &string_hash_ops
);
288 r
= hashmap_put(manager
->networks_by_name
, network
->name
, network
);
292 LIST_FOREACH(routes
, route
, network
->static_routes
) {
293 if (!route
->family
) {
294 log_warning("Route section without Gateway field configured in %s. "
295 "Ignoring", filename
);
300 LIST_FOREACH(addresses
, address
, network
->static_addresses
) {
301 if (!address
->family
) {
302 log_warning("Address section without Address field configured in %s. "
303 "Ignoring", filename
);
313 int network_load(Manager
*manager
) {
315 _cleanup_strv_free_
char **files
= NULL
;
321 while ((network
= manager
->networks
))
322 network_free(network
);
324 r
= conf_files_list_strv(&files
, ".network", NULL
, 0, network_dirs
);
326 return log_error_errno(r
, "Failed to enumerate network files: %m");
328 STRV_FOREACH_BACKWARDS(f
, files
) {
329 r
= network_load_one(manager
, *f
);
337 void network_free(Network
*network
) {
338 IPv6ProxyNDPAddress
*ipv6_proxy_ndp_address
;
339 RoutingPolicyRule
*rule
;
351 free(network
->filename
);
353 free(network
->match_mac
);
354 strv_free(network
->match_path
);
355 strv_free(network
->match_driver
);
356 strv_free(network
->match_type
);
357 strv_free(network
->match_name
);
359 free(network
->description
);
360 free(network
->dhcp_vendor_class_identifier
);
361 free(network
->dhcp_hostname
);
365 strv_free(network
->ntp
);
367 strv_free(network
->search_domains
);
368 strv_free(network
->route_domains
);
369 strv_free(network
->bind_carrier
);
371 netdev_unref(network
->bridge
);
372 netdev_unref(network
->bond
);
373 netdev_unref(network
->vrf
);
375 HASHMAP_FOREACH(netdev
, network
->stacked_netdevs
, i
) {
376 hashmap_remove(network
->stacked_netdevs
, netdev
->ifname
);
377 netdev_unref(netdev
);
379 hashmap_free(network
->stacked_netdevs
);
381 while ((route
= network
->static_routes
))
384 while ((address
= network
->static_addresses
))
385 address_free(address
);
387 while ((fdb_entry
= network
->static_fdb_entries
))
388 fdb_entry_free(fdb_entry
);
390 while ((ipv6_proxy_ndp_address
= network
->ipv6_proxy_ndp_addresses
))
391 ipv6_proxy_ndp_address_free(ipv6_proxy_ndp_address
);
393 while ((label
= network
->address_labels
))
394 address_label_free(label
);
396 while ((prefix
= network
->static_prefixes
))
399 while ((rule
= network
->rules
))
400 routing_policy_rule_free(rule
);
402 hashmap_free(network
->addresses_by_section
);
403 hashmap_free(network
->routes_by_section
);
404 hashmap_free(network
->fdb_entries_by_section
);
405 hashmap_free(network
->address_labels_by_section
);
406 hashmap_free(network
->prefixes_by_section
);
407 hashmap_free(network
->rules_by_section
);
409 if (network
->manager
) {
410 if (network
->manager
->networks
)
411 LIST_REMOVE(networks
, network
->manager
->networks
, network
);
413 if (network
->manager
->networks_by_name
)
414 hashmap_remove(network
->manager
->networks_by_name
, network
->name
);
419 condition_free_list(network
->match_host
);
420 condition_free_list(network
->match_virt
);
421 condition_free_list(network
->match_kernel_cmdline
);
422 condition_free_list(network
->match_kernel_version
);
423 condition_free_list(network
->match_arch
);
425 free(network
->dhcp_server_timezone
);
426 free(network
->dhcp_server_dns
);
427 free(network
->dhcp_server_ntp
);
429 set_free_free(network
->dnssec_negative_trust_anchors
);
434 int network_get_by_name(Manager
*manager
, const char *name
, Network
**ret
) {
441 network
= hashmap_get(manager
->networks_by_name
, name
);
450 int network_get(Manager
*manager
, struct udev_device
*device
,
451 const char *ifname
, const struct ether_addr
*address
,
454 struct udev_device
*parent
;
455 const char *path
= NULL
, *parent_driver
= NULL
, *driver
= NULL
, *devtype
= NULL
;
461 path
= udev_device_get_property_value(device
, "ID_PATH");
463 parent
= udev_device_get_parent(device
);
465 parent_driver
= udev_device_get_driver(parent
);
467 driver
= udev_device_get_property_value(device
, "ID_NET_DRIVER");
469 devtype
= udev_device_get_devtype(device
);
472 LIST_FOREACH(networks
, network
, manager
->networks
) {
473 if (net_match_config(network
->match_mac
, network
->match_path
,
474 network
->match_driver
, network
->match_type
,
475 network
->match_name
, network
->match_host
,
476 network
->match_virt
, network
->match_kernel_cmdline
,
477 network
->match_kernel_version
, network
->match_arch
,
478 address
, path
, parent_driver
, driver
,
480 if (network
->match_name
&& device
) {
482 uint8_t name_assign_type
= NET_NAME_UNKNOWN
;
484 attr
= udev_device_get_sysattr_value(device
, "name_assign_type");
486 (void) safe_atou8(attr
, &name_assign_type
);
488 if (name_assign_type
== NET_NAME_ENUM
)
489 log_warning("%s: found matching network '%s', based on potentially unpredictable ifname",
490 ifname
, network
->filename
);
492 log_debug("%s: found matching network '%s'", ifname
, network
->filename
);
494 log_debug("%s: found matching network '%s'", ifname
, network
->filename
);
506 int network_apply(Network
*network
, Link
*link
) {
512 link
->network
= network
;
514 if (network
->ipv4ll_route
) {
517 r
= route_new_static(network
, NULL
, 0, &route
);
521 r
= inet_pton(AF_INET
, "169.254.0.0", &route
->dst
.in
);
527 route
->family
= AF_INET
;
528 route
->dst_prefixlen
= 16;
529 route
->scope
= RT_SCOPE_LINK
;
530 route
->priority
= IPV4LL_ROUTE_METRIC
;
531 route
->protocol
= RTPROT_STATIC
;
534 if (network
->n_dns
> 0 ||
535 !strv_isempty(network
->ntp
) ||
536 !strv_isempty(network
->search_domains
) ||
537 !strv_isempty(network
->route_domains
))
543 bool network_has_static_ipv6_addresses(Network
*network
) {
548 LIST_FOREACH(addresses
, address
, network
->static_addresses
) {
549 if (address
->family
== AF_INET6
)
556 int config_parse_netdev(const char *unit
,
557 const char *filename
,
560 unsigned section_line
,
566 Network
*network
= userdata
;
567 _cleanup_free_
char *kind_string
= NULL
;
578 kind_string
= strdup(lvalue
);
582 /* the keys are CamelCase versions of the kind */
583 for (p
= kind_string
; *p
; p
++)
586 kind
= netdev_kind_from_string(kind_string
);
587 if (kind
== _NETDEV_KIND_INVALID
) {
588 log_syntax(unit
, LOG_ERR
, filename
, line
, 0, "Invalid NetDev kind: %s", lvalue
);
592 r
= netdev_get(network
->manager
, rvalue
, &netdev
);
594 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "%s could not be found, ignoring assignment: %s", lvalue
, rvalue
);
598 if (netdev
->kind
!= kind
) {
599 log_syntax(unit
, LOG_ERR
, filename
, line
, 0, "NetDev is not a %s, ignoring assignment: %s", lvalue
, rvalue
);
604 case NETDEV_KIND_BRIDGE
:
605 network
->bridge
= netdev
;
608 case NETDEV_KIND_BOND
:
609 network
->bond
= netdev
;
612 case NETDEV_KIND_VRF
:
613 network
->vrf
= netdev
;
616 case NETDEV_KIND_VLAN
:
617 case NETDEV_KIND_MACVLAN
:
618 case NETDEV_KIND_MACVTAP
:
619 case NETDEV_KIND_IPVLAN
:
620 case NETDEV_KIND_VXLAN
:
621 case NETDEV_KIND_VCAN
:
622 r
= hashmap_put(network
->stacked_netdevs
, netdev
->ifname
, netdev
);
624 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Cannot add NetDev '%s' to network: %m", rvalue
);
630 assert_not_reached("Cannot parse NetDev");
638 int config_parse_domains(
640 const char *filename
,
643 unsigned section_line
,
658 if (isempty(rvalue
)) {
659 n
->search_domains
= strv_free(n
->search_domains
);
660 n
->route_domains
= strv_free(n
->route_domains
);
666 _cleanup_free_
char *w
= NULL
, *normalized
= NULL
;
670 r
= extract_first_word(&p
, &w
, NULL
, 0);
672 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Failed to extract search or route domain, ignoring: %s", rvalue
);
678 is_route
= w
[0] == '~';
679 domain
= is_route
? w
+ 1 : w
;
681 if (dns_name_is_root(domain
) || streq(domain
, "*")) {
682 /* If the root domain appears as is, or the special token "*" is found, we'll consider this as
683 * routing domain, unconditionally. */
685 domain
= "."; /* make sure we don't allow empty strings, thus write the root domain as "." */
688 r
= dns_name_normalize(domain
, &normalized
);
690 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "'%s' is not a valid domain name, ignoring.", domain
);
696 if (is_localhost(domain
)) {
697 log_syntax(unit
, LOG_ERR
, filename
, line
, 0, "'localhost' domain names may not be configure as search or route domains, ignoring assignment: %s", domain
);
703 r
= strv_extend(&n
->route_domains
, domain
);
708 r
= strv_extend(&n
->search_domains
, domain
);
714 strv_uniq(n
->route_domains
);
715 strv_uniq(n
->search_domains
);
720 int config_parse_tunnel(const char *unit
,
721 const char *filename
,
724 unsigned section_line
,
730 Network
*network
= userdata
;
739 r
= netdev_get(network
->manager
, rvalue
, &netdev
);
741 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Tunnel is invalid, ignoring assignment: %s", rvalue
);
745 if (!IN_SET(netdev
->kind
,
751 NETDEV_KIND_IP6GRETAP
,
754 NETDEV_KIND_IP6TNL
)) {
755 log_syntax(unit
, LOG_ERR
, filename
, line
, 0,
756 "NetDev is not a tunnel, ignoring assignment: %s", rvalue
);
760 r
= hashmap_put(network
->stacked_netdevs
, netdev
->ifname
, netdev
);
762 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Cannot add VLAN '%s' to network, ignoring: %m", rvalue
);
771 int config_parse_ipv4ll(
773 const char *filename
,
776 unsigned section_line
,
783 AddressFamilyBoolean
*link_local
= data
;
790 /* Note that this is mostly like
791 * config_parse_address_family_boolean(), except that it
792 * applies only to IPv4 */
794 SET_FLAG(*link_local
, ADDRESS_FAMILY_IPV4
, parse_boolean(rvalue
));
799 int config_parse_dhcp(
801 const char *filename
,
804 unsigned section_line
,
811 AddressFamilyBoolean
*dhcp
= data
, s
;
818 /* Note that this is mostly like
819 * config_parse_address_family_boolean(), except that it
820 * understands some old names for the enum values */
822 s
= address_family_boolean_from_string(rvalue
);
825 /* Previously, we had a slightly different enum here,
826 * support its values for compatbility. */
828 if (streq(rvalue
, "none"))
829 s
= ADDRESS_FAMILY_NO
;
830 else if (streq(rvalue
, "v4"))
831 s
= ADDRESS_FAMILY_IPV4
;
832 else if (streq(rvalue
, "v6"))
833 s
= ADDRESS_FAMILY_IPV6
;
834 else if (streq(rvalue
, "both"))
835 s
= ADDRESS_FAMILY_YES
;
837 log_syntax(unit
, LOG_ERR
, filename
, line
, 0, "Failed to parse DHCP option, ignoring: %s", rvalue
);
846 static const char* const dhcp_client_identifier_table
[_DHCP_CLIENT_ID_MAX
] = {
847 [DHCP_CLIENT_ID_MAC
] = "mac",
848 [DHCP_CLIENT_ID_DUID
] = "duid",
849 [DHCP_CLIENT_ID_DUID_ONLY
] = "duid-only",
852 DEFINE_PRIVATE_STRING_TABLE_LOOKUP_FROM_STRING(dhcp_client_identifier
, DHCPClientIdentifier
);
853 DEFINE_CONFIG_PARSE_ENUM(config_parse_dhcp_client_identifier
, dhcp_client_identifier
, DHCPClientIdentifier
, "Failed to parse client identifier type");
855 int config_parse_ipv6token(
857 const char *filename
,
860 unsigned section_line
,
867 union in_addr_union buffer
;
868 struct in6_addr
*token
= data
;
876 r
= in_addr_from_string(AF_INET6
, rvalue
, &buffer
);
878 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Failed to parse IPv6 token, ignoring: %s", rvalue
);
882 r
= in_addr_is_null(AF_INET6
, &buffer
);
884 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "IPv6 token cannot be the ANY address, ignoring: %s", rvalue
);
888 if ((buffer
.in6
.s6_addr32
[0] | buffer
.in6
.s6_addr32
[1]) != 0) {
889 log_syntax(unit
, LOG_ERR
, filename
, line
, 0, "IPv6 token cannot be longer than 64 bits, ignoring: %s", rvalue
);
898 static const char* const ipv6_privacy_extensions_table
[_IPV6_PRIVACY_EXTENSIONS_MAX
] = {
899 [IPV6_PRIVACY_EXTENSIONS_NO
] = "no",
900 [IPV6_PRIVACY_EXTENSIONS_PREFER_PUBLIC
] = "prefer-public",
901 [IPV6_PRIVACY_EXTENSIONS_YES
] = "yes",
904 DEFINE_STRING_TABLE_LOOKUP(ipv6_privacy_extensions
, IPv6PrivacyExtensions
);
906 int config_parse_ipv6_privacy_extensions(
908 const char *filename
,
911 unsigned section_line
,
918 IPv6PrivacyExtensions
*ipv6_privacy_extensions
= data
;
924 assert(ipv6_privacy_extensions
);
926 /* Our enum shall be a superset of booleans, hence first try
927 * to parse as boolean, and then as enum */
929 k
= parse_boolean(rvalue
);
931 *ipv6_privacy_extensions
= IPV6_PRIVACY_EXTENSIONS_YES
;
933 *ipv6_privacy_extensions
= IPV6_PRIVACY_EXTENSIONS_NO
;
935 IPv6PrivacyExtensions s
;
937 s
= ipv6_privacy_extensions_from_string(rvalue
);
940 if (streq(rvalue
, "kernel"))
941 s
= _IPV6_PRIVACY_EXTENSIONS_INVALID
;
943 log_syntax(unit
, LOG_ERR
, filename
, line
, 0, "Failed to parse IPv6 privacy extensions option, ignoring: %s", rvalue
);
948 *ipv6_privacy_extensions
= s
;
954 int config_parse_hostname(
956 const char *filename
,
959 unsigned section_line
,
966 char **hostname
= data
, *hn
= NULL
;
973 r
= config_parse_string(unit
, filename
, line
, section
, section_line
, lvalue
, ltype
, rvalue
, &hn
, userdata
);
977 if (!hostname_is_valid(hn
, false)) {
978 log_syntax(unit
, LOG_ERR
, filename
, line
, 0, "Hostname is not valid, ignoring assignment: %s", rvalue
);
984 *hostname
= hostname_cleanup(hn
);
988 int config_parse_timezone(
990 const char *filename
,
993 unsigned section_line
,
1000 char **datap
= data
, *tz
= NULL
;
1007 r
= config_parse_string(unit
, filename
, line
, section
, section_line
, lvalue
, ltype
, rvalue
, &tz
, userdata
);
1011 if (!timezone_is_valid(tz
)) {
1012 log_syntax(unit
, LOG_ERR
, filename
, line
, 0, "Timezone is not valid, ignoring assignment: %s", rvalue
);
1023 int config_parse_dhcp_server_dns(
1025 const char *filename
,
1027 const char *section
,
1028 unsigned section_line
,
1036 const char *p
= rvalue
;
1044 _cleanup_free_
char *w
= NULL
;
1045 struct in_addr a
, *m
;
1047 r
= extract_first_word(&p
, &w
, NULL
, 0);
1051 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Failed to extract word, ignoring: %s", rvalue
);
1057 if (inet_pton(AF_INET
, w
, &a
) <= 0) {
1058 log_syntax(unit
, LOG_ERR
, filename
, line
, 0, "Failed to parse DNS server address, ignoring: %s", w
);
1062 m
= reallocarray(n
->dhcp_server_dns
, n
->n_dhcp_server_dns
+ 1, sizeof(struct in_addr
));
1066 m
[n
->n_dhcp_server_dns
++] = a
;
1067 n
->dhcp_server_dns
= m
;
1073 int config_parse_radv_dns(
1075 const char *filename
,
1077 const char *section
,
1078 unsigned section_line
,
1086 const char *p
= rvalue
;
1094 _cleanup_free_
char *w
= NULL
;
1095 union in_addr_union a
;
1097 r
= extract_first_word(&p
, &w
, NULL
, 0);
1101 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Failed to extract word, ignoring: %s", rvalue
);
1107 if (in_addr_from_string(AF_INET6
, w
, &a
) >= 0) {
1110 m
= reallocarray(n
->router_dns
, n
->n_router_dns
+ 1, sizeof(struct in6_addr
));
1114 m
[n
->n_router_dns
++] = a
.in6
;
1118 log_syntax(unit
, LOG_ERR
, filename
, line
, 0, "Failed to parse DNS server address, ignoring: %s", w
);
1125 int config_parse_radv_search_domains(
1127 const char *filename
,
1129 const char *section
,
1130 unsigned section_line
,
1138 const char *p
= rvalue
;
1146 _cleanup_free_
char *w
= NULL
;
1147 _cleanup_free_
char *idna
= NULL
;
1149 r
= extract_first_word(&p
, &w
, NULL
, 0);
1153 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Failed to extract word, ignoring: %s", rvalue
);
1159 r
= dns_name_apply_idna(w
, &idna
);
1161 r
= strv_push(&n
->router_search_domains
, idna
);
1164 } else if (r
== 0) {
1165 r
= strv_push(&n
->router_search_domains
, w
);
1174 int config_parse_dhcp_server_ntp(
1176 const char *filename
,
1178 const char *section
,
1179 unsigned section_line
,
1187 const char *p
= rvalue
;
1195 _cleanup_free_
char *w
= NULL
;
1196 struct in_addr a
, *m
;
1198 r
= extract_first_word(&p
, &w
, NULL
, 0);
1202 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Failed to extract word, ignoring: %s", rvalue
);
1208 if (inet_pton(AF_INET
, w
, &a
) <= 0) {
1209 log_syntax(unit
, LOG_ERR
, filename
, line
, 0, "Failed to parse NTP server address, ignoring: %s", w
);
1213 m
= reallocarray(n
->dhcp_server_ntp
, n
->n_dhcp_server_ntp
+ 1, sizeof(struct in_addr
));
1217 m
[n
->n_dhcp_server_ntp
++] = a
;
1218 n
->dhcp_server_ntp
= m
;
1222 int config_parse_dns(
1224 const char *filename
,
1226 const char *section
,
1227 unsigned section_line
,
1234 Network
*n
= userdata
;
1242 _cleanup_free_
char *w
= NULL
;
1243 union in_addr_union a
;
1244 struct in_addr_data
*m
;
1247 r
= extract_first_word(&rvalue
, &w
, NULL
, 0);
1251 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Invalid syntax, ignoring: %s", rvalue
);
1257 r
= in_addr_from_string_auto(w
, &family
, &a
);
1259 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Failed to parse dns server address, ignoring: %s", w
);
1263 m
= reallocarray(n
->dns
, n
->n_dns
+ 1, sizeof(struct in_addr_data
));
1267 m
[n
->n_dns
++] = (struct in_addr_data
) {
1278 int config_parse_dnssec_negative_trust_anchors(
1280 const char *filename
,
1282 const char *section
,
1283 unsigned section_line
,
1290 const char *p
= rvalue
;
1298 if (isempty(rvalue
)) {
1299 n
->dnssec_negative_trust_anchors
= set_free_free(n
->dnssec_negative_trust_anchors
);
1304 _cleanup_free_
char *w
= NULL
;
1306 r
= extract_first_word(&p
, &w
, NULL
, 0);
1308 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Failed to extract negative trust anchor domain, ignoring: %s", rvalue
);
1314 r
= dns_name_is_valid(w
);
1316 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "%s is not a valid domain name, ignoring.", w
);
1320 r
= set_ensure_allocated(&n
->dnssec_negative_trust_anchors
, &dns_name_hash_ops
);
1324 r
= set_put(n
->dnssec_negative_trust_anchors
, w
);
1334 int config_parse_ntp(
1336 const char *filename
,
1338 const char *section
,
1339 unsigned section_line
,
1353 if (isempty(rvalue
)) {
1359 _cleanup_free_
char *w
= NULL
;
1361 r
= extract_first_word(&rvalue
, &w
, NULL
, 0);
1365 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Failed to extract NTP server name, ignoring: %s", rvalue
);
1371 r
= dns_name_is_valid_or_address(w
);
1373 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "%s is not a valid domain name or IP address, ignoring.", w
);
1377 r
= strv_push(l
, w
);
1387 int config_parse_dhcp_route_table(const char *unit
,
1388 const char *filename
,
1390 const char *section
,
1391 unsigned section_line
,
1397 Network
*network
= data
;
1406 r
= safe_atou32(rvalue
, &rt
);
1408 log_syntax(unit
, LOG_ERR
, filename
, line
, r
,
1409 "Unable to read RouteTable, ignoring assignment: %s", rvalue
);
1413 network
->dhcp_route_table
= rt
;
1414 network
->dhcp_route_table_set
= true;
1419 DEFINE_CONFIG_PARSE_ENUM(config_parse_dhcp_use_domains
, dhcp_use_domains
, DHCPUseDomains
, "Failed to parse DHCP use domains setting");
1421 static const char* const dhcp_use_domains_table
[_DHCP_USE_DOMAINS_MAX
] = {
1422 [DHCP_USE_DOMAINS_NO
] = "no",
1423 [DHCP_USE_DOMAINS_ROUTE
] = "route",
1424 [DHCP_USE_DOMAINS_YES
] = "yes",
1427 DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(dhcp_use_domains
, DHCPUseDomains
, DHCP_USE_DOMAINS_YES
);
1429 DEFINE_CONFIG_PARSE_ENUM(config_parse_lldp_mode
, lldp_mode
, LLDPMode
, "Failed to parse LLDP= setting.");
1431 static const char* const lldp_mode_table
[_LLDP_MODE_MAX
] = {
1432 [LLDP_MODE_NO
] = "no",
1433 [LLDP_MODE_YES
] = "yes",
1434 [LLDP_MODE_ROUTERS_ONLY
] = "routers-only",
1437 DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(lldp_mode
, LLDPMode
, LLDP_MODE_YES
);