1 /* SPDX-License-Identifier: LGPL-2.1+ */
3 #include <linux/netdevice.h>
5 #include "alloc-util.h"
6 #include "conf-files.h"
7 #include "conf-parser.h"
8 #include "dns-domain.h"
10 #include "hostname-util.h"
11 #include "in-addr-util.h"
12 #include "network-internal.h"
13 #include "networkd-manager.h"
14 #include "networkd-network.h"
15 #include "parse-util.h"
17 #include "socket-util.h"
18 #include "stat-util.h"
19 #include "string-table.h"
20 #include "string-util.h"
24 /* Let's assume that anything above this number is a user misconfiguration. */
25 #define MAX_NTP_SERVERS 128
27 /* Set defaults following RFC7844 */
28 void network_apply_anonymize_if_set(Network
*network
) {
29 if (!network
->dhcp_anonymize
)
32 SHOULD NOT send the Host Name option */
33 network
->dhcp_send_hostname
= false;
34 /* RFC7844 section 3.:
35 MAY contain the Client Identifier option
37 clients MUST use client identifiers based solely
38 on the link-layer address */
39 /* NOTE: Using MAC, as it does not reveal extra information,
40 * and some servers might not answer if this option is not sent */
41 network
->dhcp_client_identifier
= DHCP_CLIENT_ID_MAC
;
43 SHOULD NOT use the Vendor Class Identifier option */
44 network
->dhcp_vendor_class_identifier
= mfree(network
->dhcp_vendor_class_identifier
);
45 /* RFC7844 section 3.6.:
46 The client intending to protect its privacy SHOULD only request a
47 minimal number of options in the PRL and SHOULD also randomly shuffle
48 the ordering of option codes in the PRL. If this random ordering
49 cannot be implemented, the client MAY order the option codes in the
50 PRL by option code number (lowest to highest).
52 /* NOTE: dhcp_use_mtu is false by default,
53 * though it was not initiallized to any value in network_load_one.
54 * Maybe there should be another var called *send*?
55 * (to use the MTU sent by the server but to do not send
56 * the option in the PRL). */
57 network
->dhcp_use_mtu
= false;
58 /* NOTE: when Anonymize=yes, the PRL route options are sent by default,
59 * but this is needed to use them. */
60 network
->dhcp_use_routes
= true;
61 /* RFC7844 section 3.6.
62 * same comments as previous option */
63 network
->dhcp_use_timezone
= false;
66 static int network_resolve_netdev_one(Network
*network
, const char *name
, NetDevKind kind
, NetDev
**ret_netdev
) {
67 const char *kind_string
;
71 /* For test-networkd-conf, the check must be earlier than the assertions. */
76 assert(network
->manager
);
77 assert(network
->filename
);
80 if (kind
== _NETDEV_KIND_TUNNEL
)
81 kind_string
= "tunnel";
83 kind_string
= netdev_kind_to_string(kind
);
85 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
),
86 "%s: Invalid NetDev kind of %s, ignoring assignment.",
87 network
->filename
, name
);
90 r
= netdev_get(network
->manager
, name
, &netdev
);
92 return log_error_errno(r
, "%s: %s NetDev could not be found, ignoring assignment.",
93 network
->filename
, name
);
95 if (netdev
->kind
!= kind
&& !(kind
== _NETDEV_KIND_TUNNEL
&&
102 NETDEV_KIND_IP6GRETAP
,
106 NETDEV_KIND_ERSPAN
)))
107 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
),
108 "%s: NetDev %s is not a %s, ignoring assignment",
109 network
->filename
, name
, kind_string
);
111 *ret_netdev
= netdev_ref(netdev
);
115 static int network_resolve_stacked_netdevs(Network
*network
) {
122 HASHMAP_FOREACH_KEY(kind
, name
, network
->stacked_netdev_names
, i
) {
123 _cleanup_(netdev_unrefp
) NetDev
*netdev
= NULL
;
125 r
= network_resolve_netdev_one(network
, name
, PTR_TO_INT(kind
), &netdev
);
129 r
= hashmap_ensure_allocated(&network
->stacked_netdevs
, &string_hash_ops
);
133 r
= hashmap_put(network
->stacked_netdevs
, netdev
->ifname
, netdev
);
135 return log_error_errno(r
, "%s: Failed to add NetDev '%s' to network: %m",
136 network
->filename
, (const char *) name
);
144 static uint32_t network_get_stacked_netdevs_mtu(Network
*network
) {
149 HASHMAP_FOREACH(dev
, network
->stacked_netdevs
, i
)
150 if (dev
->kind
== NETDEV_KIND_VLAN
&& dev
->mtu
> 0)
151 /* See vlan_dev_change_mtu() in kernel.
152 * Note that the additional 4bytes may not be necessary for all devices. */
153 mtu
= MAX(mtu
, dev
->mtu
+ 4);
155 else if (dev
->kind
== NETDEV_KIND_MACVLAN
&& dev
->mtu
> mtu
)
156 /* See macvlan_change_mtu() in kernel. */
162 int network_verify(Network
*network
) {
163 Address
*address
, *address_next
;
164 Route
*route
, *route_next
;
165 FdbEntry
*fdb
, *fdb_next
;
166 Neighbor
*neighbor
, *neighbor_next
;
167 AddressLabel
*label
, *label_next
;
168 Prefix
*prefix
, *prefix_next
;
169 RoutingPolicyRule
*rule
, *rule_next
;
173 assert(network
->filename
);
175 if (set_isempty(network
->match_mac
) && strv_isempty(network
->match_path
) &&
176 strv_isempty(network
->match_driver
) && strv_isempty(network
->match_type
) &&
177 strv_isempty(network
->match_name
) && !network
->conditions
)
178 log_warning("%s: No valid settings found in the [Match] section. "
179 "The file will match all interfaces. "
180 "If that is intended, please add Name=* in the [Match] section.",
183 /* skip out early if configuration does not match the environment */
184 if (!condition_test_list(network
->conditions
, NULL
, NULL
, NULL
))
185 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL
),
186 "%s: Conditions in the file do not match the system environment, skipping.",
189 (void) network_resolve_netdev_one(network
, network
->bond_name
, NETDEV_KIND_BOND
, &network
->bond
);
190 (void) network_resolve_netdev_one(network
, network
->bridge_name
, NETDEV_KIND_BRIDGE
, &network
->bridge
);
191 (void) network_resolve_netdev_one(network
, network
->vrf_name
, NETDEV_KIND_VRF
, &network
->vrf
);
192 (void) network_resolve_stacked_netdevs(network
);
194 /* Free unnecessary entries. */
195 network
->bond_name
= mfree(network
->bond_name
);
196 network
->bridge_name
= mfree(network
->bridge_name
);
197 network
->vrf_name
= mfree(network
->vrf_name
);
198 network
->stacked_netdev_names
= hashmap_free_free_key(network
->stacked_netdev_names
);
201 /* Bonding slave does not support addressing. */
202 if (network
->ipv6_accept_ra
> 0) {
203 log_warning("%s: Cannot enable IPv6AcceptRA= when Bond= is specified, disabling IPv6AcceptRA=.",
205 network
->ipv6_accept_ra
= 0;
207 if (network
->link_local
>= 0 && network
->link_local
!= ADDRESS_FAMILY_NO
) {
208 log_warning("%s: Cannot enable LinkLocalAddressing= when Bond= is specified, disabling LinkLocalAddressing=.",
210 network
->link_local
= ADDRESS_FAMILY_NO
;
212 if (network
->dhcp
!= ADDRESS_FAMILY_NO
) {
213 log_warning("%s: Cannot enable DHCP= when Bond= is specified, disabling DHCP=.",
215 network
->dhcp
= ADDRESS_FAMILY_NO
;
217 if (network
->dhcp_server
) {
218 log_warning("%s: Cannot enable DHCPServer= when Bond= is specified, disabling DHCPServer=.",
220 network
->dhcp_server
= false;
222 if (network
->n_static_addresses
> 0) {
223 log_warning("%s: Cannot set addresses when Bond= is specified, ignoring addresses.",
225 while ((address
= network
->static_addresses
))
226 address_free(address
);
228 if (network
->n_static_routes
> 0) {
229 log_warning("%s: Cannot set routes when Bond= is specified, ignoring routes.",
231 while ((route
= network
->static_routes
))
236 if (network
->link_local
< 0)
237 network
->link_local
= network
->bridge
? ADDRESS_FAMILY_NO
: ADDRESS_FAMILY_IPV6
;
239 if (network
->ipv6_accept_ra
< 0 && network
->bridge
)
240 network
->ipv6_accept_ra
= false;
242 /* IPMasquerade=yes implies IPForward=yes */
243 if (network
->ip_masquerade
)
244 network
->ip_forward
|= ADDRESS_FAMILY_IPV4
;
246 network
->mtu_is_set
= network
->mtu
> 0;
247 mtu
= network_get_stacked_netdevs_mtu(network
);
248 if (network
->mtu
< mtu
) {
249 if (network
->mtu_is_set
)
250 log_notice("%s: Bumping MTUBytes= from %"PRIu32
" to %"PRIu32
" because of stacked device",
251 network
->filename
, network
->mtu
, mtu
);
255 if (network
->mtu_is_set
&& network
->dhcp_use_mtu
) {
256 log_warning("%s: MTUBytes= in [Link] section and UseMTU= in [DHCP] section are set. "
257 "Disabling UseMTU=.", network
->filename
);
258 network
->dhcp_use_mtu
= false;
261 LIST_FOREACH_SAFE(addresses
, address
, address_next
, network
->static_addresses
)
262 if (address_section_verify(address
) < 0)
263 address_free(address
);
265 LIST_FOREACH_SAFE(routes
, route
, route_next
, network
->static_routes
)
266 if (route_section_verify(route
, network
) < 0)
269 LIST_FOREACH_SAFE(static_fdb_entries
, fdb
, fdb_next
, network
->static_fdb_entries
)
270 if (section_is_invalid(fdb
->section
))
273 LIST_FOREACH_SAFE(neighbors
, neighbor
, neighbor_next
, network
->neighbors
)
274 if (section_is_invalid(neighbor
->section
))
275 neighbor_free(neighbor
);
277 LIST_FOREACH_SAFE(labels
, label
, label_next
, network
->address_labels
)
278 if (section_is_invalid(label
->section
))
279 address_label_free(label
);
281 LIST_FOREACH_SAFE(prefixes
, prefix
, prefix_next
, network
->static_prefixes
)
282 if (section_is_invalid(prefix
->section
))
285 LIST_FOREACH_SAFE(rules
, rule
, rule_next
, network
->rules
)
286 if (section_is_invalid(rule
->section
))
287 routing_policy_rule_free(rule
);
292 int network_load_one(Manager
*manager
, const char *filename
) {
293 _cleanup_free_
char *fname
= NULL
, *name
= NULL
;
294 _cleanup_(network_freep
) Network
*network
= NULL
;
295 _cleanup_fclose_
FILE *file
= NULL
;
296 const char *dropin_dirname
;
303 file
= fopen(filename
, "re");
311 if (null_or_empty_fd(fileno(file
))) {
312 log_debug("Skipping empty file: %s", filename
);
316 fname
= strdup(filename
);
320 name
= strdup(basename(filename
));
324 d
= strrchr(name
, '.');
330 dropin_dirname
= strjoina(name
, ".network.d");
332 network
= new(Network
, 1);
336 *network
= (Network
) {
337 .filename
= TAKE_PTR(fname
),
338 .name
= TAKE_PTR(name
),
340 .required_for_online
= true,
341 .required_operstate_for_online
= LINK_OPERSTATE_DEGRADED
,
342 .dhcp
= ADDRESS_FAMILY_NO
,
343 .dhcp_use_ntp
= true,
344 .dhcp_use_dns
= true,
345 .dhcp_use_hostname
= true,
346 .dhcp_use_routes
= true,
347 /* NOTE: this var might be overwriten by network_apply_anonymize_if_set */
348 .dhcp_send_hostname
= true,
349 /* To enable/disable RFC7844 Anonymity Profiles */
350 .dhcp_anonymize
= false,
351 .dhcp_route_metric
= DHCP_ROUTE_METRIC
,
352 /* NOTE: this var might be overwrite by network_apply_anonymize_if_set */
353 .dhcp_client_identifier
= DHCP_CLIENT_ID_DUID
,
354 .dhcp_route_table
= RT_TABLE_MAIN
,
355 .dhcp_route_table_set
= false,
356 /* NOTE: from man: UseMTU=... Defaults to false*/
357 .dhcp_use_mtu
= false,
358 /* NOTE: from man: UseTimezone=... Defaults to "no".*/
359 .dhcp_use_timezone
= false,
360 .rapid_commit
= true,
362 .dhcp_server_emit_dns
= true,
363 .dhcp_server_emit_ntp
= true,
364 .dhcp_server_emit_router
= true,
365 .dhcp_server_emit_timezone
= true,
367 .router_emit_dns
= true,
368 .router_emit_domains
= true,
373 .allow_port_to_be_root
= -1,
375 .multicast_flood
= -1,
376 .multicast_to_unicast
= -1,
377 .neighbor_suppression
= -1,
379 .priority
= LINK_BRIDGE_PORT_PRIORITY_INVALID
,
381 .lldp_mode
= LLDP_MODE_ROUTERS_ONLY
,
383 .dns_default_route
= -1,
384 .llmnr
= RESOLVE_SUPPORT_YES
,
385 .mdns
= RESOLVE_SUPPORT_NO
,
386 .dnssec_mode
= _DNSSEC_MODE_INVALID
,
387 .dns_over_tls_mode
= _DNS_OVER_TLS_MODE_INVALID
,
389 /* If LinkLocalAddressing= is not set, then set to ADDRESS_FAMILY_IPV6 later. */
390 .link_local
= _ADDRESS_FAMILY_BOOLEAN_INVALID
,
392 .ipv6_privacy_extensions
= IPV6_PRIVACY_EXTENSIONS_NO
,
393 .ipv6_accept_ra
= -1,
394 .ipv6_dad_transmits
= -1,
395 .ipv6_hop_limit
= -1,
396 .ipv6_proxy_ndp
= -1,
397 .duid
.type
= _DUID_TYPE_INVALID
,
402 .ipv6_accept_ra_use_dns
= true,
403 .ipv6_accept_ra_use_autonomous_prefix
= true,
404 .ipv6_accept_ra_use_onlink_prefix
= true,
405 .ipv6_accept_ra_route_table
= RT_TABLE_MAIN
,
406 .ipv6_accept_ra_route_table_set
= false,
408 .can_triple_sampling
= -1,
411 r
= config_parse_many(filename
, NETWORK_DIRS
, dropin_dirname
,
418 "RoutingPolicyRule\0"
421 "DHCPv4\0" /* compat */
424 "IPv6NDPProxyAddress\0"
428 "IPv6PrefixDelegation\0"
431 config_item_perf_lookup
, network_network_gperf_lookup
,
432 CONFIG_PARSE_WARN
, network
);
436 network_apply_anonymize_if_set(network
);
438 r
= network_add_ipv4ll_route(network
);
440 log_warning_errno(r
, "%s: Failed to add IPv4LL route, ignoring: %m", network
->filename
);
442 LIST_PREPEND(networks
, manager
->networks
, network
);
443 network
->manager
= manager
;
445 r
= hashmap_ensure_allocated(&manager
->networks_by_name
, &string_hash_ops
);
449 r
= hashmap_put(manager
->networks_by_name
, network
->name
, network
);
453 if (network_verify(network
) < 0)
460 int network_load(Manager
*manager
) {
462 _cleanup_strv_free_
char **files
= NULL
;
468 while ((network
= manager
->networks
))
469 network_free(network
);
471 r
= conf_files_list_strv(&files
, ".network", NULL
, 0, NETWORK_DIRS
);
473 return log_error_errno(r
, "Failed to enumerate network files: %m");
475 STRV_FOREACH_BACKWARDS(f
, files
) {
476 r
= network_load_one(manager
, *f
);
484 void network_free(Network
*network
) {
485 IPv6ProxyNDPAddress
*ipv6_proxy_ndp_address
;
486 RoutingPolicyRule
*rule
;
497 free(network
->filename
);
499 set_free_free(network
->match_mac
);
500 strv_free(network
->match_path
);
501 strv_free(network
->match_driver
);
502 strv_free(network
->match_type
);
503 strv_free(network
->match_name
);
504 condition_free_list(network
->conditions
);
506 free(network
->description
);
507 free(network
->dhcp_vendor_class_identifier
);
508 strv_free(network
->dhcp_user_class
);
509 free(network
->dhcp_hostname
);
513 strv_free(network
->ntp
);
515 ordered_set_free_free(network
->search_domains
);
516 ordered_set_free_free(network
->route_domains
);
517 strv_free(network
->bind_carrier
);
519 ordered_set_free_free(network
->router_search_domains
);
520 free(network
->router_dns
);
522 free(network
->bridge_name
);
523 free(network
->bond_name
);
524 free(network
->vrf_name
);
525 hashmap_free_free_key(network
->stacked_netdev_names
);
526 netdev_unref(network
->bridge
);
527 netdev_unref(network
->bond
);
528 netdev_unref(network
->vrf
);
529 hashmap_free_with_destructor(network
->stacked_netdevs
, netdev_unref
);
531 while ((route
= network
->static_routes
))
534 while ((address
= network
->static_addresses
))
535 address_free(address
);
537 while ((fdb_entry
= network
->static_fdb_entries
))
538 fdb_entry_free(fdb_entry
);
540 while ((ipv6_proxy_ndp_address
= network
->ipv6_proxy_ndp_addresses
))
541 ipv6_proxy_ndp_address_free(ipv6_proxy_ndp_address
);
543 while ((neighbor
= network
->neighbors
))
544 neighbor_free(neighbor
);
546 while ((label
= network
->address_labels
))
547 address_label_free(label
);
549 while ((prefix
= network
->static_prefixes
))
552 while ((rule
= network
->rules
))
553 routing_policy_rule_free(rule
);
555 hashmap_free(network
->addresses_by_section
);
556 hashmap_free(network
->routes_by_section
);
557 hashmap_free(network
->fdb_entries_by_section
);
558 hashmap_free(network
->neighbors_by_section
);
559 hashmap_free(network
->address_labels_by_section
);
560 hashmap_free(network
->prefixes_by_section
);
561 hashmap_free(network
->rules_by_section
);
563 if (network
->manager
) {
564 if (network
->manager
->networks
)
565 LIST_REMOVE(networks
, network
->manager
->networks
, network
);
567 if (network
->manager
->networks_by_name
&& network
->name
)
568 hashmap_remove(network
->manager
->networks_by_name
, network
->name
);
570 if (network
->manager
->duids_requesting_uuid
)
571 set_remove(network
->manager
->duids_requesting_uuid
, &network
->duid
);
576 free(network
->dhcp_server_timezone
);
577 free(network
->dhcp_server_dns
);
578 free(network
->dhcp_server_ntp
);
580 set_free_free(network
->dnssec_negative_trust_anchors
);
585 int network_get_by_name(Manager
*manager
, const char *name
, Network
**ret
) {
592 network
= hashmap_get(manager
->networks_by_name
, name
);
601 int network_get(Manager
*manager
, sd_device
*device
,
602 const char *ifname
, const struct ether_addr
*address
,
604 const char *path
= NULL
, *driver
= NULL
, *devtype
= NULL
;
611 (void) sd_device_get_property_value(device
, "ID_PATH", &path
);
613 (void) sd_device_get_property_value(device
, "ID_NET_DRIVER", &driver
);
615 (void) sd_device_get_devtype(device
, &devtype
);
618 LIST_FOREACH(networks
, network
, manager
->networks
) {
619 if (net_match_config(network
->match_mac
, network
->match_path
,
620 network
->match_driver
, network
->match_type
,
622 address
, path
, driver
, devtype
, ifname
)) {
623 if (network
->match_name
&& device
) {
625 uint8_t name_assign_type
= NET_NAME_UNKNOWN
;
627 if (sd_device_get_sysattr_value(device
, "name_assign_type", &attr
) >= 0)
628 (void) safe_atou8(attr
, &name_assign_type
);
630 if (name_assign_type
== NET_NAME_ENUM
)
631 log_warning("%s: found matching network '%s', based on potentially unpredictable ifname",
632 ifname
, network
->filename
);
634 log_debug("%s: found matching network '%s'", ifname
, network
->filename
);
636 log_debug("%s: found matching network '%s'", ifname
, network
->filename
);
648 int network_apply(Network
*network
, Link
*link
) {
652 link
->network
= network
;
654 if (network
->n_dns
> 0 ||
655 !strv_isempty(network
->ntp
) ||
656 !ordered_set_isempty(network
->search_domains
) ||
657 !ordered_set_isempty(network
->route_domains
))
663 bool network_has_static_ipv6_addresses(Network
*network
) {
668 LIST_FOREACH(addresses
, address
, network
->static_addresses
) {
669 if (address
->family
== AF_INET6
)
676 int config_parse_stacked_netdev(const char *unit
,
677 const char *filename
,
680 unsigned section_line
,
686 _cleanup_free_
char *name
= NULL
;
687 NetDevKind kind
= ltype
;
696 NETDEV_KIND_VLAN
, NETDEV_KIND_MACVLAN
, NETDEV_KIND_MACVTAP
,
697 NETDEV_KIND_IPVLAN
, NETDEV_KIND_VXLAN
, NETDEV_KIND_L2TP
,
698 NETDEV_KIND_MACSEC
, _NETDEV_KIND_TUNNEL
));
700 if (!ifname_valid(rvalue
)) {
701 log_syntax(unit
, LOG_ERR
, filename
, line
, 0,
702 "Invalid netdev name in %s=, ignoring assignment: %s", lvalue
, rvalue
);
706 name
= strdup(rvalue
);
710 r
= hashmap_ensure_allocated(h
, &string_hash_ops
);
714 r
= hashmap_put(*h
, name
, INT_TO_PTR(kind
));
716 log_syntax(unit
, LOG_ERR
, filename
, line
, r
,
717 "Cannot add NetDev '%s' to network, ignoring assignment: %m", name
);
719 log_syntax(unit
, LOG_DEBUG
, filename
, line
, r
,
720 "NetDev '%s' specified twice, ignoring.", name
);
727 int config_parse_domains(
729 const char *filename
,
732 unsigned section_line
,
747 if (isempty(rvalue
)) {
748 n
->search_domains
= ordered_set_free_free(n
->search_domains
);
749 n
->route_domains
= ordered_set_free_free(n
->route_domains
);
755 _cleanup_free_
char *w
= NULL
, *normalized
= NULL
;
759 r
= extract_first_word(&p
, &w
, NULL
, 0);
761 log_syntax(unit
, LOG_ERR
, filename
, line
, r
,
762 "Failed to extract search or route domain, ignoring: %s", rvalue
);
768 is_route
= w
[0] == '~';
769 domain
= is_route
? w
+ 1 : w
;
771 if (dns_name_is_root(domain
) || streq(domain
, "*")) {
772 /* If the root domain appears as is, or the special token "*" is found, we'll
773 * consider this as routing domain, unconditionally. */
775 domain
= "."; /* make sure we don't allow empty strings, thus write the root
778 r
= dns_name_normalize(domain
, 0, &normalized
);
780 log_syntax(unit
, LOG_ERR
, filename
, line
, r
,
781 "'%s' is not a valid domain name, ignoring.", domain
);
787 if (is_localhost(domain
)) {
788 log_syntax(unit
, LOG_ERR
, filename
, line
, 0,
789 "'localhost' domain may not be configured as search or route domain, ignoring assignment: %s",
795 OrderedSet
**set
= is_route
? &n
->route_domains
: &n
->search_domains
;
796 r
= ordered_set_ensure_allocated(set
, &string_hash_ops
);
800 r
= ordered_set_put_strdup(*set
, domain
);
808 int config_parse_ipv4ll(
810 const char *filename
,
813 unsigned section_line
,
820 AddressFamilyBoolean
*link_local
= data
;
827 /* Note that this is mostly like
828 * config_parse_address_family_boolean(), except that it
829 * applies only to IPv4 */
831 SET_FLAG(*link_local
, ADDRESS_FAMILY_IPV4
, parse_boolean(rvalue
));
836 int config_parse_dhcp(
838 const char *filename
,
841 unsigned section_line
,
848 AddressFamilyBoolean
*dhcp
= data
, s
;
855 /* Note that this is mostly like
856 * config_parse_address_family_boolean(), except that it
857 * understands some old names for the enum values */
859 s
= address_family_boolean_from_string(rvalue
);
862 /* Previously, we had a slightly different enum here,
863 * support its values for compatbility. */
865 if (streq(rvalue
, "none"))
866 s
= ADDRESS_FAMILY_NO
;
867 else if (streq(rvalue
, "v4"))
868 s
= ADDRESS_FAMILY_IPV4
;
869 else if (streq(rvalue
, "v6"))
870 s
= ADDRESS_FAMILY_IPV6
;
871 else if (streq(rvalue
, "both"))
872 s
= ADDRESS_FAMILY_YES
;
874 log_syntax(unit
, LOG_ERR
, filename
, line
, 0,
875 "Failed to parse DHCP option, ignoring: %s", rvalue
);
879 log_syntax(unit
, LOG_WARNING
, filename
, line
, 0,
880 "DHCP=%s is deprecated, please use DHCP=%s instead.",
881 rvalue
, address_family_boolean_to_string(s
));
888 static const char* const dhcp_client_identifier_table
[_DHCP_CLIENT_ID_MAX
] = {
889 [DHCP_CLIENT_ID_MAC
] = "mac",
890 [DHCP_CLIENT_ID_DUID
] = "duid",
891 [DHCP_CLIENT_ID_DUID_ONLY
] = "duid-only",
894 DEFINE_PRIVATE_STRING_TABLE_LOOKUP_FROM_STRING(dhcp_client_identifier
, DHCPClientIdentifier
);
895 DEFINE_CONFIG_PARSE_ENUM(config_parse_dhcp_client_identifier
, dhcp_client_identifier
, DHCPClientIdentifier
,
896 "Failed to parse client identifier type");
898 int config_parse_ipv6token(
900 const char *filename
,
903 unsigned section_line
,
910 union in_addr_union buffer
;
911 struct in6_addr
*token
= data
;
919 r
= in_addr_from_string(AF_INET6
, rvalue
, &buffer
);
921 log_syntax(unit
, LOG_ERR
, filename
, line
, r
,
922 "Failed to parse IPv6 token, ignoring: %s", rvalue
);
926 if (in_addr_is_null(AF_INET6
, &buffer
)) {
927 log_syntax(unit
, LOG_ERR
, filename
, line
, 0,
928 "IPv6 token cannot be the ANY address, ignoring: %s", rvalue
);
932 if ((buffer
.in6
.s6_addr32
[0] | buffer
.in6
.s6_addr32
[1]) != 0) {
933 log_syntax(unit
, LOG_ERR
, filename
, line
, 0,
934 "IPv6 token cannot be longer than 64 bits, ignoring: %s", rvalue
);
943 static const char* const ipv6_privacy_extensions_table
[_IPV6_PRIVACY_EXTENSIONS_MAX
] = {
944 [IPV6_PRIVACY_EXTENSIONS_NO
] = "no",
945 [IPV6_PRIVACY_EXTENSIONS_PREFER_PUBLIC
] = "prefer-public",
946 [IPV6_PRIVACY_EXTENSIONS_YES
] = "yes",
949 DEFINE_STRING_TABLE_LOOKUP(ipv6_privacy_extensions
, IPv6PrivacyExtensions
);
951 int config_parse_ipv6_privacy_extensions(
953 const char *filename
,
956 unsigned section_line
,
963 IPv6PrivacyExtensions
*ipv6_privacy_extensions
= data
;
969 assert(ipv6_privacy_extensions
);
971 /* Our enum shall be a superset of booleans, hence first try
972 * to parse as boolean, and then as enum */
974 k
= parse_boolean(rvalue
);
976 *ipv6_privacy_extensions
= IPV6_PRIVACY_EXTENSIONS_YES
;
978 *ipv6_privacy_extensions
= IPV6_PRIVACY_EXTENSIONS_NO
;
980 IPv6PrivacyExtensions s
;
982 s
= ipv6_privacy_extensions_from_string(rvalue
);
985 if (streq(rvalue
, "kernel"))
986 s
= _IPV6_PRIVACY_EXTENSIONS_INVALID
;
988 log_syntax(unit
, LOG_ERR
, filename
, line
, 0,
989 "Failed to parse IPv6 privacy extensions option, ignoring: %s", rvalue
);
994 *ipv6_privacy_extensions
= s
;
1000 int config_parse_hostname(
1002 const char *filename
,
1004 const char *section
,
1005 unsigned section_line
,
1012 _cleanup_free_
char *hn
= NULL
;
1013 char **hostname
= data
;
1020 r
= config_parse_string(unit
, filename
, line
, section
, section_line
, lvalue
, ltype
, rvalue
, &hn
, userdata
);
1024 if (!hostname_is_valid(hn
, false)) {
1025 log_syntax(unit
, LOG_ERR
, filename
, line
, 0,
1026 "Hostname is not valid, ignoring assignment: %s", rvalue
);
1030 r
= dns_name_is_valid(hn
);
1032 log_syntax(unit
, LOG_ERR
, filename
, line
, r
,
1033 "Failed to check validity of hostname '%s', ignoring assignment: %m", rvalue
);
1037 log_syntax(unit
, LOG_ERR
, filename
, line
, 0,
1038 "Hostname is not a valid DNS domain name, ignoring assignment: %s", rvalue
);
1042 return free_and_replace(*hostname
, hn
);
1045 int config_parse_timezone(
1047 const char *filename
,
1049 const char *section
,
1050 unsigned section_line
,
1057 _cleanup_free_
char *tz
= NULL
;
1058 char **datap
= data
;
1065 r
= config_parse_string(unit
, filename
, line
, section
, section_line
, lvalue
, ltype
, rvalue
, &tz
, userdata
);
1069 if (!timezone_is_valid(tz
, LOG_ERR
)) {
1070 log_syntax(unit
, LOG_ERR
, filename
, line
, 0,
1071 "Timezone is not valid, ignoring assignment: %s", rvalue
);
1075 return free_and_replace(*datap
, tz
);
1078 int config_parse_dhcp_server_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 struct in_addr a
, *m
;
1102 r
= extract_first_word(&p
, &w
, NULL
, 0);
1106 log_syntax(unit
, LOG_ERR
, filename
, line
, r
,
1107 "Failed to extract word, ignoring: %s", rvalue
);
1113 if (inet_pton(AF_INET
, w
, &a
) <= 0) {
1114 log_syntax(unit
, LOG_ERR
, filename
, line
, 0,
1115 "Failed to parse DNS server address, ignoring: %s", w
);
1119 m
= reallocarray(n
->dhcp_server_dns
, n
->n_dhcp_server_dns
+ 1, sizeof(struct in_addr
));
1123 m
[n
->n_dhcp_server_dns
++] = a
;
1124 n
->dhcp_server_dns
= m
;
1130 int config_parse_radv_dns(
1132 const char *filename
,
1134 const char *section
,
1135 unsigned section_line
,
1143 const char *p
= rvalue
;
1151 _cleanup_free_
char *w
= NULL
;
1152 union in_addr_union a
;
1154 r
= extract_first_word(&p
, &w
, NULL
, 0);
1158 log_syntax(unit
, LOG_ERR
, filename
, line
, r
,
1159 "Failed to extract word, ignoring: %s", rvalue
);
1165 if (in_addr_from_string(AF_INET6
, w
, &a
) >= 0) {
1168 m
= reallocarray(n
->router_dns
, n
->n_router_dns
+ 1, sizeof(struct in6_addr
));
1172 m
[n
->n_router_dns
++] = a
.in6
;
1176 log_syntax(unit
, LOG_ERR
, filename
, line
, 0,
1177 "Failed to parse DNS server address, ignoring: %s", w
);
1183 int config_parse_radv_search_domains(
1185 const char *filename
,
1187 const char *section
,
1188 unsigned section_line
,
1196 const char *p
= rvalue
;
1204 _cleanup_free_
char *w
= NULL
, *idna
= NULL
;
1206 r
= extract_first_word(&p
, &w
, NULL
, 0);
1210 log_syntax(unit
, LOG_ERR
, filename
, line
, r
,
1211 "Failed to extract word, ignoring: %s", rvalue
);
1217 r
= dns_name_apply_idna(w
, &idna
);
1219 log_syntax(unit
, LOG_ERR
, filename
, line
, r
,
1220 "Failed to apply IDNA to domain name '%s', ignoring: %m", w
);
1223 /* transfer ownership to simplify subsequent operations */
1226 r
= ordered_set_ensure_allocated(&n
->router_search_domains
, &string_hash_ops
);
1230 r
= ordered_set_consume(n
->router_search_domains
, TAKE_PTR(idna
));
1238 int config_parse_dhcp_server_ntp(
1240 const char *filename
,
1242 const char *section
,
1243 unsigned section_line
,
1251 const char *p
= rvalue
;
1259 _cleanup_free_
char *w
= NULL
;
1260 struct in_addr a
, *m
;
1262 r
= extract_first_word(&p
, &w
, NULL
, 0);
1266 log_syntax(unit
, LOG_ERR
, filename
, line
, r
,
1267 "Failed to extract word, ignoring: %s", rvalue
);
1273 if (inet_pton(AF_INET
, w
, &a
) <= 0) {
1274 log_syntax(unit
, LOG_ERR
, filename
, line
, 0,
1275 "Failed to parse NTP server address, ignoring: %s", w
);
1279 m
= reallocarray(n
->dhcp_server_ntp
, n
->n_dhcp_server_ntp
+ 1, sizeof(struct in_addr
));
1283 m
[n
->n_dhcp_server_ntp
++] = a
;
1284 n
->dhcp_server_ntp
= m
;
1288 int config_parse_dns(
1290 const char *filename
,
1292 const char *section
,
1293 unsigned section_line
,
1300 Network
*n
= userdata
;
1308 _cleanup_free_
char *w
= NULL
;
1309 union in_addr_union a
;
1310 struct in_addr_data
*m
;
1313 r
= extract_first_word(&rvalue
, &w
, NULL
, 0);
1317 log_syntax(unit
, LOG_ERR
, filename
, line
, r
,
1318 "Invalid syntax, ignoring: %s", rvalue
);
1324 r
= in_addr_from_string_auto(w
, &family
, &a
);
1326 log_syntax(unit
, LOG_ERR
, filename
, line
, r
,
1327 "Failed to parse dns server address, ignoring: %s", w
);
1331 m
= reallocarray(n
->dns
, n
->n_dns
+ 1, sizeof(struct in_addr_data
));
1335 m
[n
->n_dns
++] = (struct in_addr_data
) {
1346 int config_parse_dnssec_negative_trust_anchors(
1348 const char *filename
,
1350 const char *section
,
1351 unsigned section_line
,
1358 const char *p
= rvalue
;
1366 if (isempty(rvalue
)) {
1367 n
->dnssec_negative_trust_anchors
= set_free_free(n
->dnssec_negative_trust_anchors
);
1372 _cleanup_free_
char *w
= NULL
;
1374 r
= extract_first_word(&p
, &w
, NULL
, 0);
1376 log_syntax(unit
, LOG_ERR
, filename
, line
, r
,
1377 "Failed to extract negative trust anchor domain, ignoring: %s", rvalue
);
1383 r
= dns_name_is_valid(w
);
1385 log_syntax(unit
, LOG_ERR
, filename
, line
, r
,
1386 "%s is not a valid domain name, ignoring.", w
);
1390 r
= set_ensure_allocated(&n
->dnssec_negative_trust_anchors
, &dns_name_hash_ops
);
1394 r
= set_put(n
->dnssec_negative_trust_anchors
, w
);
1404 int config_parse_ntp(
1406 const char *filename
,
1408 const char *section
,
1409 unsigned section_line
,
1423 if (isempty(rvalue
)) {
1429 _cleanup_free_
char *w
= NULL
;
1431 r
= extract_first_word(&rvalue
, &w
, NULL
, 0);
1435 log_syntax(unit
, LOG_ERR
, filename
, line
, r
,
1436 "Failed to extract NTP server name, ignoring: %s", rvalue
);
1442 r
= dns_name_is_valid_or_address(w
);
1444 log_syntax(unit
, LOG_ERR
, filename
, line
, r
,
1445 "%s is not a valid domain name or IP address, ignoring.", w
);
1449 if (strv_length(*l
) > MAX_NTP_SERVERS
) {
1450 log_syntax(unit
, LOG_WARNING
, filename
, line
, 0,
1451 "More than %u NTP servers specified, ignoring \"%s\" and any subsequent entries.",
1452 MAX_NTP_SERVERS
, w
);
1456 r
= strv_consume(l
, TAKE_PTR(w
));
1464 int config_parse_dhcp_user_class(
1466 const char *filename
,
1468 const char *section
,
1469 unsigned section_line
,
1483 if (isempty(rvalue
)) {
1489 _cleanup_free_
char *w
= NULL
;
1491 r
= extract_first_word(&rvalue
, &w
, NULL
, 0);
1495 log_syntax(unit
, LOG_ERR
, filename
, line
, r
,
1496 "Failed to split user classes option, ignoring: %s", rvalue
);
1502 if (strlen(w
) > 255) {
1503 log_syntax(unit
, LOG_ERR
, filename
, line
, 0,
1504 "%s length is not in the range 1-255, ignoring.", w
);
1508 r
= strv_push(l
, w
);
1518 int config_parse_section_route_table(
1520 const char *filename
,
1522 const char *section
,
1523 unsigned section_line
,
1530 Network
*network
= data
;
1539 r
= safe_atou32(rvalue
, &rt
);
1541 log_syntax(unit
, LOG_ERR
, filename
, line
, r
,
1542 "Failed to parse RouteTable=%s, ignoring assignment: %m", rvalue
);
1546 if (streq_ptr(section
, "DHCP")) {
1547 network
->dhcp_route_table
= rt
;
1548 network
->dhcp_route_table_set
= true;
1549 } else { /* section is IPv6AcceptRA */
1550 network
->ipv6_accept_ra_route_table
= rt
;
1551 network
->ipv6_accept_ra_route_table_set
= true;
1557 DEFINE_CONFIG_PARSE_ENUM(config_parse_dhcp_use_domains
, dhcp_use_domains
, DHCPUseDomains
,
1558 "Failed to parse DHCP use domains setting");
1560 static const char* const dhcp_use_domains_table
[_DHCP_USE_DOMAINS_MAX
] = {
1561 [DHCP_USE_DOMAINS_NO
] = "no",
1562 [DHCP_USE_DOMAINS_ROUTE
] = "route",
1563 [DHCP_USE_DOMAINS_YES
] = "yes",
1566 DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(dhcp_use_domains
, DHCPUseDomains
, DHCP_USE_DOMAINS_YES
);
1568 DEFINE_CONFIG_PARSE_ENUM(config_parse_lldp_mode
, lldp_mode
, LLDPMode
, "Failed to parse LLDP= setting.");
1570 static const char* const lldp_mode_table
[_LLDP_MODE_MAX
] = {
1571 [LLDP_MODE_NO
] = "no",
1572 [LLDP_MODE_YES
] = "yes",
1573 [LLDP_MODE_ROUTERS_ONLY
] = "routers-only",
1576 DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(lldp_mode
, LLDPMode
, LLDP_MODE_YES
);
1578 int config_parse_iaid(const char *unit
,
1579 const char *filename
,
1581 const char *section
,
1582 unsigned section_line
,
1588 Network
*network
= data
;
1597 r
= safe_atou32(rvalue
, &iaid
);
1599 log_syntax(unit
, LOG_ERR
, filename
, line
, r
,
1600 "Unable to read IAID, ignoring assignment: %s", rvalue
);
1604 network
->iaid
= iaid
;
1605 network
->iaid_set
= true;
1610 int config_parse_required_for_online(
1612 const char *filename
,
1614 const char *section
,
1615 unsigned section_line
,
1622 Network
*network
= data
;
1623 LinkOperationalState s
;
1624 bool required
= true;
1627 if (isempty(rvalue
)) {
1628 network
->required_for_online
= true;
1629 network
->required_operstate_for_online
= LINK_OPERSTATE_DEGRADED
;
1633 s
= link_operstate_from_string(rvalue
);
1635 r
= parse_boolean(rvalue
);
1637 log_syntax(unit
, LOG_ERR
, filename
, line
, r
,
1638 "Failed to parse %s= setting, ignoring assignment: %s",
1644 s
= LINK_OPERSTATE_DEGRADED
;
1647 network
->required_for_online
= required
;
1648 network
->required_operstate_for_online
= s
;