1 /* SPDX-License-Identifier: LGPL-2.1+ */
6 #include "alloc-util.h"
7 #include "conf-files.h"
8 #include "conf-parser.h"
9 #include "dns-domain.h"
11 #include "hostname-util.h"
12 #include "in-addr-util.h"
13 #include "missing_network.h"
14 #include "network-internal.h"
15 #include "networkd-manager.h"
16 #include "networkd-network.h"
17 #include "parse-util.h"
19 #include "socket-util.h"
20 #include "stat-util.h"
21 #include "string-table.h"
22 #include "string-util.h"
26 /* Let's assume that anything above this number is a user misconfiguration. */
27 #define MAX_NTP_SERVERS 128
29 /* Set defaults following RFC7844 */
30 void network_apply_anonymize_if_set(Network
*network
) {
31 if (!network
->dhcp_anonymize
)
34 SHOULD NOT send the Host Name option */
35 network
->dhcp_send_hostname
= false;
36 /* RFC7844 section 3.:
37 MAY contain the Client Identifier option
39 clients MUST use client identifiers based solely
40 on the link-layer address */
41 /* NOTE: Using MAC, as it does not reveal extra information,
42 * and some servers might not answer if this option is not sent */
43 network
->dhcp_client_identifier
= DHCP_CLIENT_ID_MAC
;
45 SHOULD NOT use the Vendor Class Identifier option */
46 network
->dhcp_vendor_class_identifier
= mfree(network
->dhcp_vendor_class_identifier
);
47 /* RFC7844 section 3.6.:
48 The client intending to protect its privacy SHOULD only request a
49 minimal number of options in the PRL and SHOULD also randomly shuffle
50 the ordering of option codes in the PRL. If this random ordering
51 cannot be implemented, the client MAY order the option codes in the
52 PRL by option code number (lowest to highest).
54 /* NOTE: dhcp_use_mtu is false by default,
55 * though it was not initiallized to any value in network_load_one.
56 * Maybe there should be another var called *send*?
57 * (to use the MTU sent by the server but to do not send
58 * the option in the PRL). */
59 network
->dhcp_use_mtu
= false;
60 /* NOTE: when Anonymize=yes, the PRL route options are sent by default,
61 * but this is needed to use them. */
62 network
->dhcp_use_routes
= true;
63 /* RFC7844 section 3.6.
64 * same comments as previous option */
65 network
->dhcp_use_timezone
= false;
68 static int network_resolve_netdev_one(Network
*network
, const char *name
, NetDevKind kind
, NetDev
**ret_netdev
) {
69 const char *kind_string
;
73 /* For test-networkd-conf, the check must be earlier than the assertions. */
78 assert(network
->manager
);
79 assert(network
->filename
);
82 if (kind
== _NETDEV_KIND_TUNNEL
)
83 kind_string
= "tunnel";
85 kind_string
= netdev_kind_to_string(kind
);
87 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
),
88 "%s: Invalid NetDev kind of %s, ignoring assignment.",
89 network
->filename
, name
);
92 r
= netdev_get(network
->manager
, name
, &netdev
);
94 return log_error_errno(r
, "%s: %s NetDev could not be found, ignoring assignment.",
95 network
->filename
, name
);
97 if (netdev
->kind
!= kind
&& !(kind
== _NETDEV_KIND_TUNNEL
&&
104 NETDEV_KIND_IP6GRETAP
,
107 NETDEV_KIND_IP6TNL
)))
108 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
),
109 "%s: NetDev %s is not a %s, ignoring assignment",
110 network
->filename
, name
, kind_string
);
112 *ret_netdev
= netdev_ref(netdev
);
116 static int network_resolve_stacked_netdevs(Network
*network
) {
123 HASHMAP_FOREACH_KEY(kind
, name
, network
->stacked_netdev_names
, i
) {
124 _cleanup_(netdev_unrefp
) NetDev
*netdev
= NULL
;
126 r
= network_resolve_netdev_one(network
, name
, PTR_TO_INT(kind
), &netdev
);
130 r
= hashmap_ensure_allocated(&network
->stacked_netdevs
, &string_hash_ops
);
134 r
= hashmap_put(network
->stacked_netdevs
, netdev
->ifname
, netdev
);
136 return log_error_errno(r
, "%s: Failed to add NetDev '%s' to network: %m",
137 network
->filename
, (const char *) name
);
145 static uint32_t network_get_stacked_netdevs_mtu(Network
*network
) {
150 HASHMAP_FOREACH(dev
, network
->stacked_netdevs
, i
)
151 if (dev
->kind
== NETDEV_KIND_VLAN
&& dev
->mtu
> 0)
152 /* See vlan_dev_change_mtu() in kernel.
153 * Note that the additional 4bytes may not be necessary for all devices. */
154 mtu
= MAX(mtu
, dev
->mtu
+ 4);
156 else if (dev
->kind
== NETDEV_KIND_MACVLAN
&& dev
->mtu
> mtu
)
157 /* See macvlan_change_mtu() in kernel. */
163 int network_verify(Network
*network
) {
164 Address
*address
, *address_next
;
165 Route
*route
, *route_next
;
166 FdbEntry
*fdb
, *fdb_next
;
167 Neighbor
*neighbor
, *neighbor_next
;
168 AddressLabel
*label
, *label_next
;
169 Prefix
*prefix
, *prefix_next
;
170 RoutingPolicyRule
*rule
, *rule_next
;
174 assert(network
->filename
);
176 /* skip out early if configuration does not match the environment */
177 if (!net_match_config(NULL
, NULL
, NULL
, NULL
, NULL
,
178 network
->match_host
, network
->match_virt
, network
->match_kernel_cmdline
,
179 network
->match_kernel_version
, network
->match_arch
,
180 NULL
, NULL
, NULL
, NULL
, NULL
))
181 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL
),
182 "%s: Conditions in the file do not match the system environment, skipping.",
185 (void) network_resolve_netdev_one(network
, network
->bond_name
, NETDEV_KIND_BOND
, &network
->bond
);
186 (void) network_resolve_netdev_one(network
, network
->bridge_name
, NETDEV_KIND_BRIDGE
, &network
->bridge
);
187 (void) network_resolve_netdev_one(network
, network
->vrf_name
, NETDEV_KIND_VRF
, &network
->vrf
);
188 (void) network_resolve_stacked_netdevs(network
);
190 /* Free unnecessary entries. */
191 network
->bond_name
= mfree(network
->bond_name
);
192 network
->bridge_name
= mfree(network
->bridge_name
);
193 network
->vrf_name
= mfree(network
->vrf_name
);
194 network
->stacked_netdev_names
= hashmap_free_free_key(network
->stacked_netdev_names
);
197 /* Bonding slave does not support addressing. */
198 if (network
->ipv6_accept_ra
> 0) {
199 log_warning("%s: Cannot enable IPv6AcceptRA= when Bond= is specified, disabling IPv6AcceptRA=.",
201 network
->ipv6_accept_ra
= 0;
203 if (network
->link_local
>= 0 && network
->link_local
!= ADDRESS_FAMILY_NO
) {
204 log_warning("%s: Cannot enable LinkLocalAddressing= when Bond= is specified, disabling LinkLocalAddressing=.",
206 network
->link_local
= ADDRESS_FAMILY_NO
;
208 if (network
->dhcp
!= ADDRESS_FAMILY_NO
) {
209 log_warning("%s: Cannot enable DHCP= when Bond= is specified, disabling DHCP=.",
211 network
->dhcp
= ADDRESS_FAMILY_NO
;
213 if (network
->dhcp_server
) {
214 log_warning("%s: Cannot enable DHCPServer= when Bond= is specified, disabling DHCPServer=.",
216 network
->dhcp_server
= false;
218 if (network
->n_static_addresses
> 0) {
219 log_warning("%s: Cannot set addresses when Bond= is specified, ignoring addresses.",
221 while ((address
= network
->static_addresses
))
222 address_free(address
);
224 if (network
->n_static_routes
> 0) {
225 log_warning("%s: Cannot set routes when Bond= is specified, ignoring routes.",
227 while ((route
= network
->static_routes
))
232 if (network
->link_local
< 0)
233 network
->link_local
= network
->bridge
? ADDRESS_FAMILY_NO
: ADDRESS_FAMILY_IPV6
;
235 if (network
->ipv6_accept_ra
< 0 && network
->bridge
)
236 network
->ipv6_accept_ra
= false;
238 /* IPMasquerade=yes implies IPForward=yes */
239 if (network
->ip_masquerade
)
240 network
->ip_forward
|= ADDRESS_FAMILY_IPV4
;
242 network
->mtu_is_set
= network
->mtu
> 0;
243 mtu
= network_get_stacked_netdevs_mtu(network
);
244 if (network
->mtu
< mtu
) {
245 if (network
->mtu_is_set
)
246 log_notice("%s: Bumping MTUBytes= from %"PRIu32
" to %"PRIu32
" because of stacked device",
247 network
->filename
, network
->mtu
, mtu
);
251 if (network
->mtu_is_set
&& network
->dhcp_use_mtu
) {
252 log_warning("%s: MTUBytes= in [Link] section and UseMTU= in [DHCP] section are set. "
253 "Disabling UseMTU=.", network
->filename
);
254 network
->dhcp_use_mtu
= false;
257 LIST_FOREACH_SAFE(addresses
, address
, address_next
, network
->static_addresses
)
258 if (address_section_verify(address
) < 0)
259 address_free(address
);
261 LIST_FOREACH_SAFE(routes
, route
, route_next
, network
->static_routes
)
262 if (route_section_verify(route
, network
) < 0)
265 LIST_FOREACH_SAFE(static_fdb_entries
, fdb
, fdb_next
, network
->static_fdb_entries
)
266 if (section_is_invalid(fdb
->section
))
269 LIST_FOREACH_SAFE(neighbors
, neighbor
, neighbor_next
, network
->neighbors
)
270 if (section_is_invalid(neighbor
->section
))
271 neighbor_free(neighbor
);
273 LIST_FOREACH_SAFE(labels
, label
, label_next
, network
->address_labels
)
274 if (section_is_invalid(label
->section
))
275 address_label_free(label
);
277 LIST_FOREACH_SAFE(prefixes
, prefix
, prefix_next
, network
->static_prefixes
)
278 if (section_is_invalid(prefix
->section
))
281 LIST_FOREACH_SAFE(rules
, rule
, rule_next
, network
->rules
)
282 if (section_is_invalid(rule
->section
))
283 routing_policy_rule_free(rule
);
288 int network_load_one(Manager
*manager
, const char *filename
) {
289 _cleanup_free_
char *fname
= NULL
, *name
= NULL
;
290 _cleanup_(network_freep
) Network
*network
= NULL
;
291 _cleanup_fclose_
FILE *file
= NULL
;
292 const char *dropin_dirname
;
299 file
= fopen(filename
, "re");
307 if (null_or_empty_fd(fileno(file
))) {
308 log_debug("Skipping empty file: %s", filename
);
312 fname
= strdup(filename
);
316 name
= strdup(basename(filename
));
320 d
= strrchr(name
, '.');
326 dropin_dirname
= strjoina(name
, ".network.d");
328 network
= new(Network
, 1);
332 *network
= (Network
) {
333 .filename
= TAKE_PTR(fname
),
334 .name
= TAKE_PTR(name
),
336 .required_for_online
= true,
337 .required_operstate_for_online
= LINK_OPERSTATE_DEGRADED
,
338 .dhcp
= ADDRESS_FAMILY_NO
,
339 .dhcp_use_ntp
= true,
340 .dhcp_use_dns
= true,
341 .dhcp_use_hostname
= true,
342 .dhcp_use_routes
= true,
343 /* NOTE: this var might be overwriten by network_apply_anonymize_if_set */
344 .dhcp_send_hostname
= true,
345 /* To enable/disable RFC7844 Anonymity Profiles */
346 .dhcp_anonymize
= false,
347 .dhcp_route_metric
= DHCP_ROUTE_METRIC
,
348 /* NOTE: this var might be overwrite by network_apply_anonymize_if_set */
349 .dhcp_client_identifier
= DHCP_CLIENT_ID_DUID
,
350 .dhcp_route_table
= RT_TABLE_MAIN
,
351 .dhcp_route_table_set
= false,
352 /* NOTE: from man: UseMTU=... Defaults to false*/
353 .dhcp_use_mtu
= false,
354 /* NOTE: from man: UseTimezone=... Defaults to "no".*/
355 .dhcp_use_timezone
= false,
356 .rapid_commit
= true,
358 .dhcp_server_emit_dns
= true,
359 .dhcp_server_emit_ntp
= true,
360 .dhcp_server_emit_router
= true,
361 .dhcp_server_emit_timezone
= true,
363 .router_emit_dns
= true,
364 .router_emit_domains
= true,
369 .allow_port_to_be_root
= -1,
371 .multicast_flood
= -1,
372 .multicast_to_unicast
= -1,
373 .neighbor_suppression
= -1,
375 .priority
= LINK_BRIDGE_PORT_PRIORITY_INVALID
,
377 .lldp_mode
= LLDP_MODE_ROUTERS_ONLY
,
379 .dns_default_route
= -1,
380 .llmnr
= RESOLVE_SUPPORT_YES
,
381 .mdns
= RESOLVE_SUPPORT_NO
,
382 .dnssec_mode
= _DNSSEC_MODE_INVALID
,
383 .dns_over_tls_mode
= _DNS_OVER_TLS_MODE_INVALID
,
385 /* If LinkLocalAddressing= is not set, then set to ADDRESS_FAMILY_IPV6 later. */
386 .link_local
= _ADDRESS_FAMILY_BOOLEAN_INVALID
,
388 .ipv6_privacy_extensions
= IPV6_PRIVACY_EXTENSIONS_NO
,
389 .ipv6_accept_ra
= -1,
390 .ipv6_dad_transmits
= -1,
391 .ipv6_hop_limit
= -1,
392 .ipv6_proxy_ndp
= -1,
393 .duid
.type
= _DUID_TYPE_INVALID
,
398 .ipv6_accept_ra_use_dns
= true,
399 .ipv6_accept_ra_use_autonomous_prefix
= true,
400 .ipv6_accept_ra_use_onlink_prefix
= true,
401 .ipv6_accept_ra_route_table
= RT_TABLE_MAIN
,
402 .ipv6_accept_ra_route_table_set
= false,
404 .can_triple_sampling
= -1,
407 r
= config_parse_many(filename
, NETWORK_DIRS
, dropin_dirname
,
414 "RoutingPolicyRule\0"
417 "DHCPv4\0" /* compat */
420 "IPv6NDPProxyAddress\0"
424 "IPv6PrefixDelegation\0"
427 config_item_perf_lookup
, network_network_gperf_lookup
,
428 CONFIG_PARSE_WARN
, network
);
432 network_apply_anonymize_if_set(network
);
434 r
= network_add_ipv4ll_route(network
);
436 log_warning_errno(r
, "%s: Failed to add IPv4LL route, ignoring: %m", network
->filename
);
438 LIST_PREPEND(networks
, manager
->networks
, network
);
439 network
->manager
= manager
;
441 r
= hashmap_ensure_allocated(&manager
->networks_by_name
, &string_hash_ops
);
445 r
= hashmap_put(manager
->networks_by_name
, network
->name
, network
);
449 if (network_verify(network
) < 0)
456 int network_load(Manager
*manager
) {
458 _cleanup_strv_free_
char **files
= NULL
;
464 while ((network
= manager
->networks
))
465 network_free(network
);
467 r
= conf_files_list_strv(&files
, ".network", NULL
, 0, NETWORK_DIRS
);
469 return log_error_errno(r
, "Failed to enumerate network files: %m");
471 STRV_FOREACH_BACKWARDS(f
, files
) {
472 r
= network_load_one(manager
, *f
);
480 void network_free(Network
*network
) {
481 IPv6ProxyNDPAddress
*ipv6_proxy_ndp_address
;
482 RoutingPolicyRule
*rule
;
493 free(network
->filename
);
495 set_free_free(network
->match_mac
);
496 strv_free(network
->match_path
);
497 strv_free(network
->match_driver
);
498 strv_free(network
->match_type
);
499 strv_free(network
->match_name
);
501 free(network
->description
);
502 free(network
->dhcp_vendor_class_identifier
);
503 strv_free(network
->dhcp_user_class
);
504 free(network
->dhcp_hostname
);
508 strv_free(network
->ntp
);
510 ordered_set_free_free(network
->search_domains
);
511 ordered_set_free_free(network
->route_domains
);
512 strv_free(network
->bind_carrier
);
514 ordered_set_free_free(network
->router_search_domains
);
515 free(network
->router_dns
);
517 free(network
->bridge_name
);
518 free(network
->bond_name
);
519 free(network
->vrf_name
);
520 hashmap_free_free_key(network
->stacked_netdev_names
);
521 netdev_unref(network
->bridge
);
522 netdev_unref(network
->bond
);
523 netdev_unref(network
->vrf
);
524 hashmap_free_with_destructor(network
->stacked_netdevs
, netdev_unref
);
526 while ((route
= network
->static_routes
))
529 while ((address
= network
->static_addresses
))
530 address_free(address
);
532 while ((fdb_entry
= network
->static_fdb_entries
))
533 fdb_entry_free(fdb_entry
);
535 while ((ipv6_proxy_ndp_address
= network
->ipv6_proxy_ndp_addresses
))
536 ipv6_proxy_ndp_address_free(ipv6_proxy_ndp_address
);
538 while ((neighbor
= network
->neighbors
))
539 neighbor_free(neighbor
);
541 while ((label
= network
->address_labels
))
542 address_label_free(label
);
544 while ((prefix
= network
->static_prefixes
))
547 while ((rule
= network
->rules
))
548 routing_policy_rule_free(rule
);
550 hashmap_free(network
->addresses_by_section
);
551 hashmap_free(network
->routes_by_section
);
552 hashmap_free(network
->fdb_entries_by_section
);
553 hashmap_free(network
->neighbors_by_section
);
554 hashmap_free(network
->address_labels_by_section
);
555 hashmap_free(network
->prefixes_by_section
);
556 hashmap_free(network
->rules_by_section
);
558 if (network
->manager
) {
559 if (network
->manager
->networks
)
560 LIST_REMOVE(networks
, network
->manager
->networks
, network
);
562 if (network
->manager
->networks_by_name
&& network
->name
)
563 hashmap_remove(network
->manager
->networks_by_name
, network
->name
);
565 if (network
->manager
->duids_requesting_uuid
)
566 set_remove(network
->manager
->duids_requesting_uuid
, &network
->duid
);
571 condition_free_list(network
->match_host
);
572 condition_free_list(network
->match_virt
);
573 condition_free_list(network
->match_kernel_cmdline
);
574 condition_free_list(network
->match_kernel_version
);
575 condition_free_list(network
->match_arch
);
577 free(network
->dhcp_server_timezone
);
578 free(network
->dhcp_server_dns
);
579 free(network
->dhcp_server_ntp
);
581 set_free_free(network
->dnssec_negative_trust_anchors
);
586 int network_get_by_name(Manager
*manager
, const char *name
, Network
**ret
) {
593 network
= hashmap_get(manager
->networks_by_name
, name
);
602 int network_get(Manager
*manager
, sd_device
*device
,
603 const char *ifname
, const struct ether_addr
*address
,
605 const char *path
= NULL
, *driver
= NULL
, *devtype
= NULL
;
612 (void) sd_device_get_property_value(device
, "ID_PATH", &path
);
614 (void) sd_device_get_property_value(device
, "ID_NET_DRIVER", &driver
);
616 (void) sd_device_get_devtype(device
, &devtype
);
619 LIST_FOREACH(networks
, network
, manager
->networks
) {
620 if (net_match_config(network
->match_mac
, network
->match_path
,
621 network
->match_driver
, network
->match_type
,
622 network
->match_name
, network
->match_host
,
623 network
->match_virt
, network
->match_kernel_cmdline
,
624 network
->match_kernel_version
, network
->match_arch
,
625 address
, path
, driver
, devtype
, ifname
)) {
626 if (network
->match_name
&& device
) {
628 uint8_t name_assign_type
= NET_NAME_UNKNOWN
;
630 if (sd_device_get_sysattr_value(device
, "name_assign_type", &attr
) >= 0)
631 (void) safe_atou8(attr
, &name_assign_type
);
633 if (name_assign_type
== NET_NAME_ENUM
)
634 log_warning("%s: found matching network '%s', based on potentially unpredictable ifname",
635 ifname
, network
->filename
);
637 log_debug("%s: found matching network '%s'", ifname
, network
->filename
);
639 log_debug("%s: found matching network '%s'", ifname
, network
->filename
);
651 int network_apply(Network
*network
, Link
*link
) {
655 link
->network
= network
;
657 if (network
->n_dns
> 0 ||
658 !strv_isempty(network
->ntp
) ||
659 !ordered_set_isempty(network
->search_domains
) ||
660 !ordered_set_isempty(network
->route_domains
))
666 bool network_has_static_ipv6_addresses(Network
*network
) {
671 LIST_FOREACH(addresses
, address
, network
->static_addresses
) {
672 if (address
->family
== AF_INET6
)
679 int config_parse_stacked_netdev(const char *unit
,
680 const char *filename
,
683 unsigned section_line
,
689 _cleanup_free_
char *name
= NULL
;
690 NetDevKind kind
= ltype
;
699 NETDEV_KIND_VLAN
, NETDEV_KIND_MACVLAN
, NETDEV_KIND_MACVTAP
,
700 NETDEV_KIND_IPVLAN
, NETDEV_KIND_VXLAN
, NETDEV_KIND_L2TP
,
701 _NETDEV_KIND_TUNNEL
));
703 if (!ifname_valid(rvalue
)) {
704 log_syntax(unit
, LOG_ERR
, filename
, line
, 0,
705 "Invalid netdev name in %s=, ignoring assignment: %s", lvalue
, rvalue
);
709 name
= strdup(rvalue
);
713 r
= hashmap_ensure_allocated(h
, &string_hash_ops
);
717 r
= hashmap_put(*h
, name
, INT_TO_PTR(kind
));
719 log_syntax(unit
, LOG_ERR
, filename
, line
, r
,
720 "Cannot add NetDev '%s' to network, ignoring assignment: %m", name
);
722 log_syntax(unit
, LOG_DEBUG
, filename
, line
, r
,
723 "NetDev '%s' specified twice, ignoring.", name
);
730 int config_parse_domains(
732 const char *filename
,
735 unsigned section_line
,
750 if (isempty(rvalue
)) {
751 n
->search_domains
= ordered_set_free_free(n
->search_domains
);
752 n
->route_domains
= ordered_set_free_free(n
->route_domains
);
758 _cleanup_free_
char *w
= NULL
, *normalized
= NULL
;
762 r
= extract_first_word(&p
, &w
, NULL
, 0);
764 log_syntax(unit
, LOG_ERR
, filename
, line
, r
,
765 "Failed to extract search or route domain, ignoring: %s", rvalue
);
771 is_route
= w
[0] == '~';
772 domain
= is_route
? w
+ 1 : w
;
774 if (dns_name_is_root(domain
) || streq(domain
, "*")) {
775 /* If the root domain appears as is, or the special token "*" is found, we'll
776 * consider this as routing domain, unconditionally. */
778 domain
= "."; /* make sure we don't allow empty strings, thus write the root
781 r
= dns_name_normalize(domain
, 0, &normalized
);
783 log_syntax(unit
, LOG_ERR
, filename
, line
, r
,
784 "'%s' is not a valid domain name, ignoring.", domain
);
790 if (is_localhost(domain
)) {
791 log_syntax(unit
, LOG_ERR
, filename
, line
, 0,
792 "'localhost' domain may not be configured as search or route domain, ignoring assignment: %s",
798 OrderedSet
**set
= is_route
? &n
->route_domains
: &n
->search_domains
;
799 r
= ordered_set_ensure_allocated(set
, &string_hash_ops
);
803 r
= ordered_set_put_strdup(*set
, domain
);
811 int config_parse_ipv4ll(
813 const char *filename
,
816 unsigned section_line
,
823 AddressFamilyBoolean
*link_local
= data
;
830 /* Note that this is mostly like
831 * config_parse_address_family_boolean(), except that it
832 * applies only to IPv4 */
834 SET_FLAG(*link_local
, ADDRESS_FAMILY_IPV4
, parse_boolean(rvalue
));
839 int config_parse_dhcp(
841 const char *filename
,
844 unsigned section_line
,
851 AddressFamilyBoolean
*dhcp
= data
, s
;
858 /* Note that this is mostly like
859 * config_parse_address_family_boolean(), except that it
860 * understands some old names for the enum values */
862 s
= address_family_boolean_from_string(rvalue
);
865 /* Previously, we had a slightly different enum here,
866 * support its values for compatbility. */
868 if (streq(rvalue
, "none"))
869 s
= ADDRESS_FAMILY_NO
;
870 else if (streq(rvalue
, "v4"))
871 s
= ADDRESS_FAMILY_IPV4
;
872 else if (streq(rvalue
, "v6"))
873 s
= ADDRESS_FAMILY_IPV6
;
874 else if (streq(rvalue
, "both"))
875 s
= ADDRESS_FAMILY_YES
;
877 log_syntax(unit
, LOG_ERR
, filename
, line
, 0,
878 "Failed to parse DHCP option, ignoring: %s", rvalue
);
882 log_syntax(unit
, LOG_WARNING
, filename
, line
, 0,
883 "DHCP=%s is deprecated, please use DHCP=%s instead.",
884 rvalue
, address_family_boolean_to_string(s
));
891 static const char* const dhcp_client_identifier_table
[_DHCP_CLIENT_ID_MAX
] = {
892 [DHCP_CLIENT_ID_MAC
] = "mac",
893 [DHCP_CLIENT_ID_DUID
] = "duid",
894 [DHCP_CLIENT_ID_DUID_ONLY
] = "duid-only",
897 DEFINE_PRIVATE_STRING_TABLE_LOOKUP_FROM_STRING(dhcp_client_identifier
, DHCPClientIdentifier
);
898 DEFINE_CONFIG_PARSE_ENUM(config_parse_dhcp_client_identifier
, dhcp_client_identifier
, DHCPClientIdentifier
,
899 "Failed to parse client identifier type");
901 int config_parse_ipv6token(
903 const char *filename
,
906 unsigned section_line
,
913 union in_addr_union buffer
;
914 struct in6_addr
*token
= data
;
922 r
= in_addr_from_string(AF_INET6
, rvalue
, &buffer
);
924 log_syntax(unit
, LOG_ERR
, filename
, line
, r
,
925 "Failed to parse IPv6 token, ignoring: %s", rvalue
);
929 if (in_addr_is_null(AF_INET6
, &buffer
)) {
930 log_syntax(unit
, LOG_ERR
, filename
, line
, 0,
931 "IPv6 token cannot be the ANY address, ignoring: %s", rvalue
);
935 if ((buffer
.in6
.s6_addr32
[0] | buffer
.in6
.s6_addr32
[1]) != 0) {
936 log_syntax(unit
, LOG_ERR
, filename
, line
, 0,
937 "IPv6 token cannot be longer than 64 bits, ignoring: %s", rvalue
);
946 static const char* const ipv6_privacy_extensions_table
[_IPV6_PRIVACY_EXTENSIONS_MAX
] = {
947 [IPV6_PRIVACY_EXTENSIONS_NO
] = "no",
948 [IPV6_PRIVACY_EXTENSIONS_PREFER_PUBLIC
] = "prefer-public",
949 [IPV6_PRIVACY_EXTENSIONS_YES
] = "yes",
952 DEFINE_STRING_TABLE_LOOKUP(ipv6_privacy_extensions
, IPv6PrivacyExtensions
);
954 int config_parse_ipv6_privacy_extensions(
956 const char *filename
,
959 unsigned section_line
,
966 IPv6PrivacyExtensions
*ipv6_privacy_extensions
= data
;
972 assert(ipv6_privacy_extensions
);
974 /* Our enum shall be a superset of booleans, hence first try
975 * to parse as boolean, and then as enum */
977 k
= parse_boolean(rvalue
);
979 *ipv6_privacy_extensions
= IPV6_PRIVACY_EXTENSIONS_YES
;
981 *ipv6_privacy_extensions
= IPV6_PRIVACY_EXTENSIONS_NO
;
983 IPv6PrivacyExtensions s
;
985 s
= ipv6_privacy_extensions_from_string(rvalue
);
988 if (streq(rvalue
, "kernel"))
989 s
= _IPV6_PRIVACY_EXTENSIONS_INVALID
;
991 log_syntax(unit
, LOG_ERR
, filename
, line
, 0,
992 "Failed to parse IPv6 privacy extensions option, ignoring: %s", rvalue
);
997 *ipv6_privacy_extensions
= s
;
1003 int config_parse_hostname(
1005 const char *filename
,
1007 const char *section
,
1008 unsigned section_line
,
1015 _cleanup_free_
char *hn
= NULL
;
1016 char **hostname
= data
;
1023 r
= config_parse_string(unit
, filename
, line
, section
, section_line
, lvalue
, ltype
, rvalue
, &hn
, userdata
);
1027 if (!hostname_is_valid(hn
, false)) {
1028 log_syntax(unit
, LOG_ERR
, filename
, line
, 0,
1029 "Hostname is not valid, ignoring assignment: %s", rvalue
);
1033 r
= dns_name_is_valid(hn
);
1035 log_syntax(unit
, LOG_ERR
, filename
, line
, r
,
1036 "Failed to check validity of hostname '%s', ignoring assignment: %m", rvalue
);
1040 log_syntax(unit
, LOG_ERR
, filename
, line
, 0,
1041 "Hostname is not a valid DNS domain name, ignoring assignment: %s", rvalue
);
1045 return free_and_replace(*hostname
, hn
);
1048 int config_parse_timezone(
1050 const char *filename
,
1052 const char *section
,
1053 unsigned section_line
,
1060 _cleanup_free_
char *tz
= NULL
;
1061 char **datap
= data
;
1068 r
= config_parse_string(unit
, filename
, line
, section
, section_line
, lvalue
, ltype
, rvalue
, &tz
, userdata
);
1072 if (!timezone_is_valid(tz
, LOG_ERR
)) {
1073 log_syntax(unit
, LOG_ERR
, filename
, line
, 0,
1074 "Timezone is not valid, ignoring assignment: %s", rvalue
);
1078 return free_and_replace(*datap
, tz
);
1081 int config_parse_dhcp_server_dns(
1083 const char *filename
,
1085 const char *section
,
1086 unsigned section_line
,
1094 const char *p
= rvalue
;
1102 _cleanup_free_
char *w
= NULL
;
1103 struct in_addr a
, *m
;
1105 r
= extract_first_word(&p
, &w
, NULL
, 0);
1109 log_syntax(unit
, LOG_ERR
, filename
, line
, r
,
1110 "Failed to extract word, ignoring: %s", rvalue
);
1116 if (inet_pton(AF_INET
, w
, &a
) <= 0) {
1117 log_syntax(unit
, LOG_ERR
, filename
, line
, 0,
1118 "Failed to parse DNS server address, ignoring: %s", w
);
1122 m
= reallocarray(n
->dhcp_server_dns
, n
->n_dhcp_server_dns
+ 1, sizeof(struct in_addr
));
1126 m
[n
->n_dhcp_server_dns
++] = a
;
1127 n
->dhcp_server_dns
= m
;
1133 int config_parse_radv_dns(
1135 const char *filename
,
1137 const char *section
,
1138 unsigned section_line
,
1146 const char *p
= rvalue
;
1154 _cleanup_free_
char *w
= NULL
;
1155 union in_addr_union a
;
1157 r
= extract_first_word(&p
, &w
, NULL
, 0);
1161 log_syntax(unit
, LOG_ERR
, filename
, line
, r
,
1162 "Failed to extract word, ignoring: %s", rvalue
);
1168 if (in_addr_from_string(AF_INET6
, w
, &a
) >= 0) {
1171 m
= reallocarray(n
->router_dns
, n
->n_router_dns
+ 1, sizeof(struct in6_addr
));
1175 m
[n
->n_router_dns
++] = a
.in6
;
1179 log_syntax(unit
, LOG_ERR
, filename
, line
, 0,
1180 "Failed to parse DNS server address, ignoring: %s", w
);
1186 int config_parse_radv_search_domains(
1188 const char *filename
,
1190 const char *section
,
1191 unsigned section_line
,
1199 const char *p
= rvalue
;
1207 _cleanup_free_
char *w
= NULL
, *idna
= NULL
;
1209 r
= extract_first_word(&p
, &w
, NULL
, 0);
1213 log_syntax(unit
, LOG_ERR
, filename
, line
, r
,
1214 "Failed to extract word, ignoring: %s", rvalue
);
1220 r
= dns_name_apply_idna(w
, &idna
);
1222 log_syntax(unit
, LOG_ERR
, filename
, line
, r
,
1223 "Failed to apply IDNA to domain name '%s', ignoring: %m", w
);
1226 /* transfer ownership to simplify subsequent operations */
1229 r
= ordered_set_ensure_allocated(&n
->router_search_domains
, &string_hash_ops
);
1233 r
= ordered_set_consume(n
->router_search_domains
, TAKE_PTR(idna
));
1241 int config_parse_dhcp_server_ntp(
1243 const char *filename
,
1245 const char *section
,
1246 unsigned section_line
,
1254 const char *p
= rvalue
;
1262 _cleanup_free_
char *w
= NULL
;
1263 struct in_addr a
, *m
;
1265 r
= extract_first_word(&p
, &w
, NULL
, 0);
1269 log_syntax(unit
, LOG_ERR
, filename
, line
, r
,
1270 "Failed to extract word, ignoring: %s", rvalue
);
1276 if (inet_pton(AF_INET
, w
, &a
) <= 0) {
1277 log_syntax(unit
, LOG_ERR
, filename
, line
, 0,
1278 "Failed to parse NTP server address, ignoring: %s", w
);
1282 m
= reallocarray(n
->dhcp_server_ntp
, n
->n_dhcp_server_ntp
+ 1, sizeof(struct in_addr
));
1286 m
[n
->n_dhcp_server_ntp
++] = a
;
1287 n
->dhcp_server_ntp
= m
;
1291 int config_parse_dns(
1293 const char *filename
,
1295 const char *section
,
1296 unsigned section_line
,
1303 Network
*n
= userdata
;
1311 _cleanup_free_
char *w
= NULL
;
1312 union in_addr_union a
;
1313 struct in_addr_data
*m
;
1316 r
= extract_first_word(&rvalue
, &w
, NULL
, 0);
1320 log_syntax(unit
, LOG_ERR
, filename
, line
, r
,
1321 "Invalid syntax, ignoring: %s", rvalue
);
1327 r
= in_addr_from_string_auto(w
, &family
, &a
);
1329 log_syntax(unit
, LOG_ERR
, filename
, line
, r
,
1330 "Failed to parse dns server address, ignoring: %s", w
);
1334 m
= reallocarray(n
->dns
, n
->n_dns
+ 1, sizeof(struct in_addr_data
));
1338 m
[n
->n_dns
++] = (struct in_addr_data
) {
1349 int config_parse_dnssec_negative_trust_anchors(
1351 const char *filename
,
1353 const char *section
,
1354 unsigned section_line
,
1361 const char *p
= rvalue
;
1369 if (isempty(rvalue
)) {
1370 n
->dnssec_negative_trust_anchors
= set_free_free(n
->dnssec_negative_trust_anchors
);
1375 _cleanup_free_
char *w
= NULL
;
1377 r
= extract_first_word(&p
, &w
, NULL
, 0);
1379 log_syntax(unit
, LOG_ERR
, filename
, line
, r
,
1380 "Failed to extract negative trust anchor domain, ignoring: %s", rvalue
);
1386 r
= dns_name_is_valid(w
);
1388 log_syntax(unit
, LOG_ERR
, filename
, line
, r
,
1389 "%s is not a valid domain name, ignoring.", w
);
1393 r
= set_ensure_allocated(&n
->dnssec_negative_trust_anchors
, &dns_name_hash_ops
);
1397 r
= set_put(n
->dnssec_negative_trust_anchors
, w
);
1407 int config_parse_ntp(
1409 const char *filename
,
1411 const char *section
,
1412 unsigned section_line
,
1426 if (isempty(rvalue
)) {
1432 _cleanup_free_
char *w
= NULL
;
1434 r
= extract_first_word(&rvalue
, &w
, NULL
, 0);
1438 log_syntax(unit
, LOG_ERR
, filename
, line
, r
,
1439 "Failed to extract NTP server name, ignoring: %s", rvalue
);
1445 r
= dns_name_is_valid_or_address(w
);
1447 log_syntax(unit
, LOG_ERR
, filename
, line
, r
,
1448 "%s is not a valid domain name or IP address, ignoring.", w
);
1452 if (strv_length(*l
) > MAX_NTP_SERVERS
) {
1453 log_syntax(unit
, LOG_WARNING
, filename
, line
, 0,
1454 "More than %u NTP servers specified, ignoring \"%s\" and any subsequent entries.",
1455 MAX_NTP_SERVERS
, w
);
1459 r
= strv_consume(l
, TAKE_PTR(w
));
1467 int config_parse_dhcp_user_class(
1469 const char *filename
,
1471 const char *section
,
1472 unsigned section_line
,
1486 if (isempty(rvalue
)) {
1492 _cleanup_free_
char *w
= NULL
;
1494 r
= extract_first_word(&rvalue
, &w
, NULL
, 0);
1498 log_syntax(unit
, LOG_ERR
, filename
, line
, r
,
1499 "Failed to split user classes option, ignoring: %s", rvalue
);
1505 if (strlen(w
) > 255) {
1506 log_syntax(unit
, LOG_ERR
, filename
, line
, 0,
1507 "%s length is not in the range 1-255, ignoring.", w
);
1511 r
= strv_push(l
, w
);
1521 int config_parse_section_route_table(
1523 const char *filename
,
1525 const char *section
,
1526 unsigned section_line
,
1533 Network
*network
= data
;
1542 r
= safe_atou32(rvalue
, &rt
);
1544 log_syntax(unit
, LOG_ERR
, filename
, line
, r
,
1545 "Failed to parse RouteTable=%s, ignoring assignment: %m", rvalue
);
1549 if (streq_ptr(section
, "DHCP")) {
1550 network
->dhcp_route_table
= rt
;
1551 network
->dhcp_route_table_set
= true;
1552 } else { /* section is IPv6AcceptRA */
1553 network
->ipv6_accept_ra_route_table
= rt
;
1554 network
->ipv6_accept_ra_route_table_set
= true;
1560 DEFINE_CONFIG_PARSE_ENUM(config_parse_dhcp_use_domains
, dhcp_use_domains
, DHCPUseDomains
,
1561 "Failed to parse DHCP use domains setting");
1563 static const char* const dhcp_use_domains_table
[_DHCP_USE_DOMAINS_MAX
] = {
1564 [DHCP_USE_DOMAINS_NO
] = "no",
1565 [DHCP_USE_DOMAINS_ROUTE
] = "route",
1566 [DHCP_USE_DOMAINS_YES
] = "yes",
1569 DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(dhcp_use_domains
, DHCPUseDomains
, DHCP_USE_DOMAINS_YES
);
1571 DEFINE_CONFIG_PARSE_ENUM(config_parse_lldp_mode
, lldp_mode
, LLDPMode
, "Failed to parse LLDP= setting.");
1573 static const char* const lldp_mode_table
[_LLDP_MODE_MAX
] = {
1574 [LLDP_MODE_NO
] = "no",
1575 [LLDP_MODE_YES
] = "yes",
1576 [LLDP_MODE_ROUTERS_ONLY
] = "routers-only",
1579 DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(lldp_mode
, LLDPMode
, LLDP_MODE_YES
);
1581 int config_parse_iaid(const char *unit
,
1582 const char *filename
,
1584 const char *section
,
1585 unsigned section_line
,
1591 Network
*network
= data
;
1600 r
= safe_atou32(rvalue
, &iaid
);
1602 log_syntax(unit
, LOG_ERR
, filename
, line
, r
,
1603 "Unable to read IAID, ignoring assignment: %s", rvalue
);
1607 network
->iaid
= iaid
;
1608 network
->iaid_set
= true;
1613 int config_parse_required_for_online(
1615 const char *filename
,
1617 const char *section
,
1618 unsigned section_line
,
1625 Network
*network
= data
;
1626 LinkOperationalState s
;
1627 bool required
= true;
1630 if (isempty(rvalue
)) {
1631 network
->required_for_online
= true;
1632 network
->required_operstate_for_online
= LINK_OPERSTATE_DEGRADED
;
1636 s
= link_operstate_from_string(rvalue
);
1638 r
= parse_boolean(rvalue
);
1640 log_syntax(unit
, LOG_ERR
, filename
, line
, r
,
1641 "Failed to parse %s= setting, ignoring assignment: %s",
1647 s
= LINK_OPERSTATE_DEGRADED
;
1650 network
->required_for_online
= required
;
1651 network
->required_operstate_for_online
= s
;