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 static void network_config_hash_func(const NetworkConfigSection
*c
, struct siphash
*state
) {
27 siphash24_compress(c
->filename
, strlen(c
->filename
), state
);
28 siphash24_compress(&c
->line
, sizeof(c
->line
), state
);
31 static int network_config_compare_func(const NetworkConfigSection
*x
, const NetworkConfigSection
*y
) {
34 r
= strcmp(x
->filename
, y
->filename
);
38 return CMP(x
->line
, y
->line
);
41 DEFINE_HASH_OPS(network_config_hash_ops
, NetworkConfigSection
, network_config_hash_func
, network_config_compare_func
);
43 int network_config_section_new(const char *filename
, unsigned line
, NetworkConfigSection
**s
) {
44 NetworkConfigSection
*cs
;
46 cs
= malloc0(offsetof(NetworkConfigSection
, filename
) + strlen(filename
) + 1);
50 strcpy(cs
->filename
, filename
);
58 void network_config_section_free(NetworkConfigSection
*cs
) {
62 /* Set defaults following RFC7844 */
63 void network_apply_anonymize_if_set(Network
*network
) {
64 if (!network
->dhcp_anonymize
)
67 SHOULD NOT send the Host Name option */
68 network
->dhcp_send_hostname
= false;
69 /* RFC7844 section 3.:
70 MAY contain the Client Identifier option
72 clients MUST use client identifiers based solely
73 on the link-layer address */
74 /* NOTE: Using MAC, as it does not reveal extra information,
75 * and some servers might not answer if this option is not sent */
76 network
->dhcp_client_identifier
= DHCP_CLIENT_ID_MAC
;
78 SHOULD NOT use the Vendor Class Identifier option */
79 network
->dhcp_vendor_class_identifier
= mfree(network
->dhcp_vendor_class_identifier
);
80 /* RFC7844 section 3.6.:
81 The client intending to protect its privacy SHOULD only request a
82 minimal number of options in the PRL and SHOULD also randomly shuffle
83 the ordering of option codes in the PRL. If this random ordering
84 cannot be implemented, the client MAY order the option codes in the
85 PRL by option code number (lowest to highest).
87 /* NOTE: dhcp_use_mtu is false by default,
88 * though it was not initiallized to any value in network_load_one.
89 * Maybe there should be another var called *send*?
90 * (to use the MTU sent by the server but to do not send
91 * the option in the PRL). */
92 network
->dhcp_use_mtu
= false;
93 /* NOTE: when Anonymize=yes, the PRL route options are sent by default,
94 * but this is needed to use them. */
95 network
->dhcp_use_routes
= true;
96 /* RFC7844 section 3.6.
97 * same comments as previous option */
98 network
->dhcp_use_timezone
= false;
101 static int network_resolve_netdev_one(Network
*network
, const char *name
, NetDevKind kind
, NetDev
**ret_netdev
) {
102 const char *kind_string
;
107 assert(network
->manager
);
108 assert(network
->filename
);
114 if (kind
== _NETDEV_KIND_TUNNEL
)
115 kind_string
= "tunnel";
117 kind_string
= netdev_kind_to_string(kind
);
119 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
),
120 "%s: Invalid NetDev kind of %s, ignoring assignment.",
121 network
->filename
, name
);
124 r
= netdev_get(network
->manager
, name
, &netdev
);
126 return log_error_errno(r
, "%s: %s NetDev could not be found, ignoring assignment.",
127 network
->filename
, name
);
129 if (netdev
->kind
!= kind
&& !(kind
== _NETDEV_KIND_TUNNEL
&&
136 NETDEV_KIND_IP6GRETAP
,
139 NETDEV_KIND_IP6TNL
)))
140 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
),
141 "%s: NetDev %s is not a %s, ignoring assignment",
142 network
->filename
, name
, kind_string
);
144 *ret_netdev
= netdev_ref(netdev
);
148 static int network_resolve_stacked_netdevs(Network
*network
) {
155 HASHMAP_FOREACH_KEY(kind
, name
, network
->stacked_netdev_names
, i
) {
156 _cleanup_(netdev_unrefp
) NetDev
*netdev
= NULL
;
158 r
= network_resolve_netdev_one(network
, name
, PTR_TO_INT(kind
), &netdev
);
162 r
= hashmap_ensure_allocated(&network
->stacked_netdevs
, &string_hash_ops
);
166 r
= hashmap_put(network
->stacked_netdevs
, netdev
->ifname
, netdev
);
168 return log_error_errno(r
, "%s: Failed to add NetDev '%s' to network: %m",
169 network
->filename
, (const char *) name
);
177 static int network_verify(Network
*network
) {
182 assert(network
->filename
);
184 /* skip out early if configuration does not match the environment */
185 if (!net_match_config(NULL
, NULL
, NULL
, NULL
, NULL
,
186 network
->match_host
, network
->match_virt
, network
->match_kernel_cmdline
,
187 network
->match_kernel_version
, network
->match_arch
,
188 NULL
, NULL
, NULL
, NULL
, NULL
))
189 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL
),
190 "%s: Conditions in the file do not match the system environment, skipping.", network
->filename
);
192 (void) network_resolve_netdev_one(network
, network
->bond_name
, NETDEV_KIND_BOND
, &network
->bond
);
193 (void) network_resolve_netdev_one(network
, network
->bridge_name
, NETDEV_KIND_BRIDGE
, &network
->bridge
);
194 (void) network_resolve_netdev_one(network
, network
->vrf_name
, NETDEV_KIND_VRF
, &network
->vrf
);
195 (void) network_resolve_stacked_netdevs(network
);
197 /* Free unnecessary entries. */
198 network
->bond_name
= mfree(network
->bond_name
);
199 network
->bridge_name
= mfree(network
->bridge_name
);
200 network
->vrf_name
= mfree(network
->vrf_name
);
201 network
->stacked_netdev_names
= hashmap_free_free_key(network
->stacked_netdev_names
);
204 /* Bonding slave does not support addressing. */
205 if (network
->ipv6_accept_ra
> 0) {
206 log_warning("%s: Cannot enable IPv6AcceptRA= when Bond= is specified, disabling IPv6AcceptRA=.",
208 network
->ipv6_accept_ra
= 0;
210 if (network
->link_local
>= 0 && network
->link_local
!= ADDRESS_FAMILY_NO
) {
211 log_warning("%s: Cannot enable LinkLocalAddressing= when Bond= is specified, disabling LinkLocalAddressing=.",
213 network
->link_local
= ADDRESS_FAMILY_NO
;
215 if (network
->dhcp
!= ADDRESS_FAMILY_NO
) {
216 log_warning("%s: Cannot enable DHCP= when Bond= is specified, disabling DHCP=.",
218 network
->dhcp
= ADDRESS_FAMILY_NO
;
220 if (network
->dhcp_server
) {
221 log_warning("%s: Cannot enable DHCPServer= when Bond= is specified, disabling DHCPServer=.",
223 network
->dhcp_server
= false;
225 if (network
->n_static_addresses
> 0) {
226 log_warning("%s: Cannot set addresses when Bond= is specified, ignoring addresses.",
228 while ((address
= network
->static_addresses
))
229 address_free(address
);
231 if (network
->n_static_routes
> 0) {
232 log_warning("%s: Cannot set routes when Bond= is specified, ignoring routes.",
234 while ((route
= network
->static_routes
))
239 if (network
->link_local
< 0)
240 network
->link_local
= network
->bridge
? ADDRESS_FAMILY_NO
: ADDRESS_FAMILY_IPV6
;
242 if (network
->ipv6_accept_ra
< 0 && network
->bridge
)
243 network
->ipv6_accept_ra
= false;
245 /* IPMasquerade=yes implies IPForward=yes */
246 if (network
->ip_masquerade
)
247 network
->ip_forward
|= ADDRESS_FAMILY_IPV4
;
249 if (network
->mtu
> 0 && network
->dhcp_use_mtu
) {
250 log_warning("%s: MTUBytes= in [Link] section and UseMTU= in [DHCP] section are set. "
251 "Disabling UseMTU=.", network
->filename
);
252 network
->dhcp_use_mtu
= false;
255 LIST_FOREACH(routes
, route
, network
->static_routes
)
257 return log_warning_errno(SYNTHETIC_ERRNO(EINVAL
),
258 "%s: Route section without Gateway field configured. "
260 network
->filename
, network
->filename
);
262 LIST_FOREACH(addresses
, address
, network
->static_addresses
)
263 if (!address
->family
)
264 return log_warning_errno(SYNTHETIC_ERRNO(EINVAL
),
265 "%s: Address section without Address field configured. "
267 network
->filename
, network
->filename
);
272 int network_load_one(Manager
*manager
, const char *filename
) {
273 _cleanup_free_
char *fname
= NULL
, *name
= NULL
;
274 _cleanup_(network_freep
) Network
*network
= NULL
;
275 _cleanup_fclose_
FILE *file
= NULL
;
276 const char *dropin_dirname
;
283 file
= fopen(filename
, "re");
291 if (null_or_empty_fd(fileno(file
))) {
292 log_debug("Skipping empty file: %s", filename
);
296 fname
= strdup(filename
);
300 name
= strdup(basename(filename
));
304 d
= strrchr(name
, '.');
310 dropin_dirname
= strjoina(name
, ".network.d");
312 network
= new(Network
, 1);
316 *network
= (Network
) {
317 .filename
= TAKE_PTR(fname
),
318 .name
= TAKE_PTR(name
),
320 .required_for_online
= true,
321 .dhcp
= ADDRESS_FAMILY_NO
,
322 .dhcp_use_ntp
= true,
323 .dhcp_use_dns
= true,
324 .dhcp_use_hostname
= true,
325 .dhcp_use_routes
= true,
326 /* NOTE: this var might be overwriten by network_apply_anonymize_if_set */
327 .dhcp_send_hostname
= true,
328 /* To enable/disable RFC7844 Anonymity Profiles */
329 .dhcp_anonymize
= false,
330 .dhcp_route_metric
= DHCP_ROUTE_METRIC
,
331 /* NOTE: this var might be overwrite by network_apply_anonymize_if_set */
332 .dhcp_client_identifier
= DHCP_CLIENT_ID_DUID
,
333 .dhcp_route_table
= RT_TABLE_MAIN
,
334 .dhcp_route_table_set
= false,
335 /* NOTE: from man: UseMTU=... Defaults to false*/
336 .dhcp_use_mtu
= false,
337 /* NOTE: from man: UseTimezone=... Defaults to "no".*/
338 .dhcp_use_timezone
= false,
339 .rapid_commit
= true,
341 .dhcp_server_emit_dns
= true,
342 .dhcp_server_emit_ntp
= true,
343 .dhcp_server_emit_router
= true,
344 .dhcp_server_emit_timezone
= true,
346 .router_emit_dns
= true,
347 .router_emit_domains
= true,
352 .allow_port_to_be_root
= -1,
354 .multicast_to_unicast
= -1,
355 .priority
= LINK_BRIDGE_PORT_PRIORITY_INVALID
,
357 .lldp_mode
= LLDP_MODE_ROUTERS_ONLY
,
359 .dns_default_route
= -1,
360 .llmnr
= RESOLVE_SUPPORT_YES
,
361 .mdns
= RESOLVE_SUPPORT_NO
,
362 .dnssec_mode
= _DNSSEC_MODE_INVALID
,
363 .dns_over_tls_mode
= _DNS_OVER_TLS_MODE_INVALID
,
365 /* If LinkLocalAddressing= is not set, then set to ADDRESS_FAMILY_IPV6 later. */
366 .link_local
= _ADDRESS_FAMILY_BOOLEAN_INVALID
,
368 .ipv6_privacy_extensions
= IPV6_PRIVACY_EXTENSIONS_NO
,
369 .ipv6_accept_ra
= -1,
370 .ipv6_dad_transmits
= -1,
371 .ipv6_hop_limit
= -1,
372 .ipv6_proxy_ndp
= -1,
373 .duid
.type
= _DUID_TYPE_INVALID
,
378 .ipv6_accept_ra_use_dns
= true,
379 .ipv6_accept_ra_use_autonomous_prefix
= true,
380 .ipv6_accept_ra_use_onlink_prefix
= true,
381 .ipv6_accept_ra_route_table
= RT_TABLE_MAIN
,
382 .ipv6_accept_ra_route_table_set
= false,
385 r
= config_parse_many(filename
, NETWORK_DIRS
, dropin_dirname
,
392 "RoutingPolicyRule\0"
395 "DHCPv4\0" /* compat */
398 "IPv6NDPProxyAddress\0"
402 "IPv6PrefixDelegation\0"
405 config_item_perf_lookup
, network_network_gperf_lookup
,
406 CONFIG_PARSE_WARN
, network
);
410 network_apply_anonymize_if_set(network
);
412 LIST_PREPEND(networks
, manager
->networks
, network
);
413 network
->manager
= manager
;
415 r
= hashmap_ensure_allocated(&manager
->networks_by_name
, &string_hash_ops
);
419 r
= hashmap_put(manager
->networks_by_name
, network
->name
, network
);
423 if (network_verify(network
) < 0)
430 int network_load(Manager
*manager
) {
432 _cleanup_strv_free_
char **files
= NULL
;
438 while ((network
= manager
->networks
))
439 network_free(network
);
441 r
= conf_files_list_strv(&files
, ".network", NULL
, 0, NETWORK_DIRS
);
443 return log_error_errno(r
, "Failed to enumerate network files: %m");
445 STRV_FOREACH_BACKWARDS(f
, files
) {
446 r
= network_load_one(manager
, *f
);
454 void network_free(Network
*network
) {
455 IPv6ProxyNDPAddress
*ipv6_proxy_ndp_address
;
456 RoutingPolicyRule
*rule
;
467 free(network
->filename
);
469 set_free_free(network
->match_mac
);
470 strv_free(network
->match_path
);
471 strv_free(network
->match_driver
);
472 strv_free(network
->match_type
);
473 strv_free(network
->match_name
);
475 free(network
->description
);
476 free(network
->dhcp_vendor_class_identifier
);
477 strv_free(network
->dhcp_user_class
);
478 free(network
->dhcp_hostname
);
482 strv_free(network
->ntp
);
484 ordered_set_free_free(network
->search_domains
);
485 ordered_set_free_free(network
->route_domains
);
486 strv_free(network
->bind_carrier
);
488 ordered_set_free_free(network
->router_search_domains
);
489 free(network
->router_dns
);
491 free(network
->bridge_name
);
492 free(network
->bond_name
);
493 free(network
->vrf_name
);
494 hashmap_free_free_key(network
->stacked_netdev_names
);
495 netdev_unref(network
->bridge
);
496 netdev_unref(network
->bond
);
497 netdev_unref(network
->vrf
);
498 hashmap_free_with_destructor(network
->stacked_netdevs
, netdev_unref
);
500 while ((route
= network
->static_routes
))
503 while ((address
= network
->static_addresses
))
504 address_free(address
);
506 while ((fdb_entry
= network
->static_fdb_entries
))
507 fdb_entry_free(fdb_entry
);
509 while ((ipv6_proxy_ndp_address
= network
->ipv6_proxy_ndp_addresses
))
510 ipv6_proxy_ndp_address_free(ipv6_proxy_ndp_address
);
512 while ((neighbor
= network
->neighbors
))
513 neighbor_free(neighbor
);
515 while ((label
= network
->address_labels
))
516 address_label_free(label
);
518 while ((prefix
= network
->static_prefixes
))
521 while ((rule
= network
->rules
))
522 routing_policy_rule_free(rule
);
524 hashmap_free(network
->addresses_by_section
);
525 hashmap_free(network
->routes_by_section
);
526 hashmap_free(network
->fdb_entries_by_section
);
527 hashmap_free(network
->neighbors_by_section
);
528 hashmap_free(network
->address_labels_by_section
);
529 hashmap_free(network
->prefixes_by_section
);
530 hashmap_free(network
->rules_by_section
);
532 if (network
->manager
) {
533 if (network
->manager
->networks
)
534 LIST_REMOVE(networks
, network
->manager
->networks
, network
);
536 if (network
->manager
->networks_by_name
&& network
->name
)
537 hashmap_remove(network
->manager
->networks_by_name
, network
->name
);
539 if (network
->manager
->duids_requesting_uuid
)
540 set_remove(network
->manager
->duids_requesting_uuid
, &network
->duid
);
545 condition_free_list(network
->match_host
);
546 condition_free_list(network
->match_virt
);
547 condition_free_list(network
->match_kernel_cmdline
);
548 condition_free_list(network
->match_kernel_version
);
549 condition_free_list(network
->match_arch
);
551 free(network
->dhcp_server_timezone
);
552 free(network
->dhcp_server_dns
);
553 free(network
->dhcp_server_ntp
);
555 set_free_free(network
->dnssec_negative_trust_anchors
);
560 int network_get_by_name(Manager
*manager
, const char *name
, Network
**ret
) {
567 network
= hashmap_get(manager
->networks_by_name
, name
);
576 int network_get(Manager
*manager
, sd_device
*device
,
577 const char *ifname
, const struct ether_addr
*address
,
579 const char *path
= NULL
, *driver
= NULL
, *devtype
= NULL
;
586 (void) sd_device_get_property_value(device
, "ID_PATH", &path
);
588 (void) sd_device_get_property_value(device
, "ID_NET_DRIVER", &driver
);
590 (void) sd_device_get_devtype(device
, &devtype
);
593 LIST_FOREACH(networks
, network
, manager
->networks
) {
594 if (net_match_config(network
->match_mac
, network
->match_path
,
595 network
->match_driver
, network
->match_type
,
596 network
->match_name
, network
->match_host
,
597 network
->match_virt
, network
->match_kernel_cmdline
,
598 network
->match_kernel_version
, network
->match_arch
,
599 address
, path
, driver
, devtype
, ifname
)) {
600 if (network
->match_name
&& device
) {
602 uint8_t name_assign_type
= NET_NAME_UNKNOWN
;
604 if (sd_device_get_sysattr_value(device
, "name_assign_type", &attr
) >= 0)
605 (void) safe_atou8(attr
, &name_assign_type
);
607 if (name_assign_type
== NET_NAME_ENUM
)
608 log_warning("%s: found matching network '%s', based on potentially unpredictable ifname",
609 ifname
, network
->filename
);
611 log_debug("%s: found matching network '%s'", ifname
, network
->filename
);
613 log_debug("%s: found matching network '%s'", ifname
, network
->filename
);
625 int network_apply(Network
*network
, Link
*link
) {
631 link
->network
= network
;
633 if (network
->ipv4ll_route
) {
636 r
= route_new_static(network
, NULL
, 0, &route
);
640 r
= inet_pton(AF_INET
, "169.254.0.0", &route
->dst
.in
);
646 route
->family
= AF_INET
;
647 route
->dst_prefixlen
= 16;
648 route
->scope
= RT_SCOPE_LINK
;
649 route
->priority
= IPV4LL_ROUTE_METRIC
;
650 route
->protocol
= RTPROT_STATIC
;
653 if (network
->n_dns
> 0 ||
654 !strv_isempty(network
->ntp
) ||
655 !ordered_set_isempty(network
->search_domains
) ||
656 !ordered_set_isempty(network
->route_domains
))
662 bool network_has_static_ipv6_addresses(Network
*network
) {
667 LIST_FOREACH(addresses
, address
, network
->static_addresses
) {
668 if (address
->family
== AF_INET6
)
675 int config_parse_stacked_netdev(const char *unit
,
676 const char *filename
,
679 unsigned section_line
,
685 _cleanup_free_
char *kind_string
= NULL
, *name
= NULL
;
696 if (ltype
== _NETDEV_KIND_TUNNEL
)
697 kind
= _NETDEV_KIND_TUNNEL
;
699 kind_string
= strdup(lvalue
);
703 /* the keys are CamelCase versions of the kind */
704 for (p
= kind_string
; *p
; p
++)
707 kind
= netdev_kind_from_string(kind_string
);
708 if (kind
< 0 || IN_SET(kind
, NETDEV_KIND_BRIDGE
, NETDEV_KIND_BOND
, NETDEV_KIND_VRF
)) {
709 log_syntax(unit
, LOG_ERR
, filename
, line
, 0,
710 "Invalid NetDev kind: %s", lvalue
);
715 if (!ifname_valid(rvalue
)) {
716 log_syntax(unit
, LOG_ERR
, filename
, line
, 0, "Invalid netdev name in %s=, ignoring assignment: %s", lvalue
, rvalue
);
720 name
= strdup(rvalue
);
724 r
= hashmap_ensure_allocated(h
, &string_hash_ops
);
728 r
= hashmap_put(*h
, name
, INT_TO_PTR(kind
));
730 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Cannot add NetDev '%s' to network, ignoring assignment: %m", rvalue
);
739 int config_parse_domains(
741 const char *filename
,
744 unsigned section_line
,
759 if (isempty(rvalue
)) {
760 n
->search_domains
= ordered_set_free_free(n
->search_domains
);
761 n
->route_domains
= ordered_set_free_free(n
->route_domains
);
767 _cleanup_free_
char *w
= NULL
, *normalized
= NULL
;
771 r
= extract_first_word(&p
, &w
, NULL
, 0);
773 log_syntax(unit
, LOG_ERR
, filename
, line
, r
,
774 "Failed to extract search or route domain, ignoring: %s", rvalue
);
780 is_route
= w
[0] == '~';
781 domain
= is_route
? w
+ 1 : w
;
783 if (dns_name_is_root(domain
) || streq(domain
, "*")) {
784 /* If the root domain appears as is, or the special token "*" is found, we'll
785 * consider this as routing domain, unconditionally. */
787 domain
= "."; /* make sure we don't allow empty strings, thus write the root
790 r
= dns_name_normalize(domain
, 0, &normalized
);
792 log_syntax(unit
, LOG_ERR
, filename
, line
, r
,
793 "'%s' is not a valid domain name, ignoring.", domain
);
799 if (is_localhost(domain
)) {
800 log_syntax(unit
, LOG_ERR
, filename
, line
, 0,
801 "'localhost' domain may not be configured as search or route domain, ignoring assignment: %s",
807 OrderedSet
**set
= is_route
? &n
->route_domains
: &n
->search_domains
;
808 r
= ordered_set_ensure_allocated(set
, &string_hash_ops
);
812 r
= ordered_set_put_strdup(*set
, domain
);
820 int config_parse_ipv4ll(
822 const char *filename
,
825 unsigned section_line
,
832 AddressFamilyBoolean
*link_local
= data
;
839 /* Note that this is mostly like
840 * config_parse_address_family_boolean(), except that it
841 * applies only to IPv4 */
843 SET_FLAG(*link_local
, ADDRESS_FAMILY_IPV4
, parse_boolean(rvalue
));
848 int config_parse_dhcp(
850 const char *filename
,
853 unsigned section_line
,
860 AddressFamilyBoolean
*dhcp
= data
, s
;
867 /* Note that this is mostly like
868 * config_parse_address_family_boolean(), except that it
869 * understands some old names for the enum values */
871 s
= address_family_boolean_from_string(rvalue
);
874 /* Previously, we had a slightly different enum here,
875 * support its values for compatbility. */
877 if (streq(rvalue
, "none"))
878 s
= ADDRESS_FAMILY_NO
;
879 else if (streq(rvalue
, "v4"))
880 s
= ADDRESS_FAMILY_IPV4
;
881 else if (streq(rvalue
, "v6"))
882 s
= ADDRESS_FAMILY_IPV6
;
883 else if (streq(rvalue
, "both"))
884 s
= ADDRESS_FAMILY_YES
;
886 log_syntax(unit
, LOG_ERR
, filename
, line
, 0,
887 "Failed to parse DHCP option, ignoring: %s", rvalue
);
891 log_syntax(unit
, LOG_WARNING
, filename
, line
, 0,
892 "DHCP=%s is deprecated, please use DHCP=%s instead.",
893 rvalue
, address_family_boolean_to_string(s
));
900 static const char* const dhcp_client_identifier_table
[_DHCP_CLIENT_ID_MAX
] = {
901 [DHCP_CLIENT_ID_MAC
] = "mac",
902 [DHCP_CLIENT_ID_DUID
] = "duid",
903 [DHCP_CLIENT_ID_DUID_ONLY
] = "duid-only",
906 DEFINE_PRIVATE_STRING_TABLE_LOOKUP_FROM_STRING(dhcp_client_identifier
, DHCPClientIdentifier
);
907 DEFINE_CONFIG_PARSE_ENUM(config_parse_dhcp_client_identifier
, dhcp_client_identifier
, DHCPClientIdentifier
,
908 "Failed to parse client identifier type");
910 int config_parse_ipv6token(
912 const char *filename
,
915 unsigned section_line
,
922 union in_addr_union buffer
;
923 struct in6_addr
*token
= data
;
931 r
= in_addr_from_string(AF_INET6
, rvalue
, &buffer
);
933 log_syntax(unit
, LOG_ERR
, filename
, line
, r
,
934 "Failed to parse IPv6 token, ignoring: %s", rvalue
);
938 if (in_addr_is_null(AF_INET6
, &buffer
)) {
939 log_syntax(unit
, LOG_ERR
, filename
, line
, 0,
940 "IPv6 token cannot be the ANY address, ignoring: %s", rvalue
);
944 if ((buffer
.in6
.s6_addr32
[0] | buffer
.in6
.s6_addr32
[1]) != 0) {
945 log_syntax(unit
, LOG_ERR
, filename
, line
, 0,
946 "IPv6 token cannot be longer than 64 bits, ignoring: %s", rvalue
);
955 static const char* const ipv6_privacy_extensions_table
[_IPV6_PRIVACY_EXTENSIONS_MAX
] = {
956 [IPV6_PRIVACY_EXTENSIONS_NO
] = "no",
957 [IPV6_PRIVACY_EXTENSIONS_PREFER_PUBLIC
] = "prefer-public",
958 [IPV6_PRIVACY_EXTENSIONS_YES
] = "yes",
961 DEFINE_STRING_TABLE_LOOKUP(ipv6_privacy_extensions
, IPv6PrivacyExtensions
);
963 int config_parse_ipv6_privacy_extensions(
965 const char *filename
,
968 unsigned section_line
,
975 IPv6PrivacyExtensions
*ipv6_privacy_extensions
= data
;
981 assert(ipv6_privacy_extensions
);
983 /* Our enum shall be a superset of booleans, hence first try
984 * to parse as boolean, and then as enum */
986 k
= parse_boolean(rvalue
);
988 *ipv6_privacy_extensions
= IPV6_PRIVACY_EXTENSIONS_YES
;
990 *ipv6_privacy_extensions
= IPV6_PRIVACY_EXTENSIONS_NO
;
992 IPv6PrivacyExtensions s
;
994 s
= ipv6_privacy_extensions_from_string(rvalue
);
997 if (streq(rvalue
, "kernel"))
998 s
= _IPV6_PRIVACY_EXTENSIONS_INVALID
;
1000 log_syntax(unit
, LOG_ERR
, filename
, line
, 0,
1001 "Failed to parse IPv6 privacy extensions option, ignoring: %s", rvalue
);
1006 *ipv6_privacy_extensions
= s
;
1012 int config_parse_hostname(
1014 const char *filename
,
1016 const char *section
,
1017 unsigned section_line
,
1024 _cleanup_free_
char *hn
= NULL
;
1025 char **hostname
= data
;
1032 r
= config_parse_string(unit
, filename
, line
, section
, section_line
, lvalue
, ltype
, rvalue
, &hn
, userdata
);
1036 if (!hostname_is_valid(hn
, false)) {
1037 log_syntax(unit
, LOG_ERR
, filename
, line
, 0,
1038 "Hostname is not valid, ignoring assignment: %s", rvalue
);
1042 r
= dns_name_is_valid(hn
);
1044 log_syntax(unit
, LOG_ERR
, filename
, line
, r
,
1045 "Failed to check validity of hostname '%s', ignoring assignment: %m", rvalue
);
1049 log_syntax(unit
, LOG_ERR
, filename
, line
, 0,
1050 "Hostname is not a valid DNS domain name, ignoring assignment: %s", rvalue
);
1054 return free_and_replace(*hostname
, hn
);
1057 int config_parse_timezone(
1059 const char *filename
,
1061 const char *section
,
1062 unsigned section_line
,
1069 _cleanup_free_
char *tz
= NULL
;
1070 char **datap
= data
;
1077 r
= config_parse_string(unit
, filename
, line
, section
, section_line
, lvalue
, ltype
, rvalue
, &tz
, userdata
);
1081 if (!timezone_is_valid(tz
, LOG_ERR
)) {
1082 log_syntax(unit
, LOG_ERR
, filename
, line
, 0,
1083 "Timezone is not valid, ignoring assignment: %s", rvalue
);
1087 return free_and_replace(*datap
, tz
);
1090 int config_parse_dhcp_server_dns(
1092 const char *filename
,
1094 const char *section
,
1095 unsigned section_line
,
1103 const char *p
= rvalue
;
1111 _cleanup_free_
char *w
= NULL
;
1112 struct in_addr a
, *m
;
1114 r
= extract_first_word(&p
, &w
, NULL
, 0);
1118 log_syntax(unit
, LOG_ERR
, filename
, line
, r
,
1119 "Failed to extract word, ignoring: %s", rvalue
);
1125 if (inet_pton(AF_INET
, w
, &a
) <= 0) {
1126 log_syntax(unit
, LOG_ERR
, filename
, line
, 0,
1127 "Failed to parse DNS server address, ignoring: %s", w
);
1131 m
= reallocarray(n
->dhcp_server_dns
, n
->n_dhcp_server_dns
+ 1, sizeof(struct in_addr
));
1135 m
[n
->n_dhcp_server_dns
++] = a
;
1136 n
->dhcp_server_dns
= m
;
1142 int config_parse_radv_dns(
1144 const char *filename
,
1146 const char *section
,
1147 unsigned section_line
,
1155 const char *p
= rvalue
;
1163 _cleanup_free_
char *w
= NULL
;
1164 union in_addr_union a
;
1166 r
= extract_first_word(&p
, &w
, NULL
, 0);
1170 log_syntax(unit
, LOG_ERR
, filename
, line
, r
,
1171 "Failed to extract word, ignoring: %s", rvalue
);
1177 if (in_addr_from_string(AF_INET6
, w
, &a
) >= 0) {
1180 m
= reallocarray(n
->router_dns
, n
->n_router_dns
+ 1, sizeof(struct in6_addr
));
1184 m
[n
->n_router_dns
++] = a
.in6
;
1188 log_syntax(unit
, LOG_ERR
, filename
, line
, 0,
1189 "Failed to parse DNS server address, ignoring: %s", w
);
1195 int config_parse_radv_search_domains(
1197 const char *filename
,
1199 const char *section
,
1200 unsigned section_line
,
1208 const char *p
= rvalue
;
1216 _cleanup_free_
char *w
= NULL
, *idna
= NULL
;
1218 r
= extract_first_word(&p
, &w
, NULL
, 0);
1222 log_syntax(unit
, LOG_ERR
, filename
, line
, r
,
1223 "Failed to extract word, ignoring: %s", rvalue
);
1229 r
= dns_name_apply_idna(w
, &idna
);
1231 log_syntax(unit
, LOG_ERR
, filename
, line
, r
,
1232 "Failed to apply IDNA to domain name '%s', ignoring: %m", w
);
1235 /* transfer ownership to simplify subsequent operations */
1238 r
= ordered_set_ensure_allocated(&n
->router_search_domains
, &string_hash_ops
);
1242 r
= ordered_set_consume(n
->router_search_domains
, TAKE_PTR(idna
));
1250 int config_parse_dhcp_server_ntp(
1252 const char *filename
,
1254 const char *section
,
1255 unsigned section_line
,
1263 const char *p
= rvalue
;
1271 _cleanup_free_
char *w
= NULL
;
1272 struct in_addr a
, *m
;
1274 r
= extract_first_word(&p
, &w
, NULL
, 0);
1278 log_syntax(unit
, LOG_ERR
, filename
, line
, r
,
1279 "Failed to extract word, ignoring: %s", rvalue
);
1285 if (inet_pton(AF_INET
, w
, &a
) <= 0) {
1286 log_syntax(unit
, LOG_ERR
, filename
, line
, 0,
1287 "Failed to parse NTP server address, ignoring: %s", w
);
1291 m
= reallocarray(n
->dhcp_server_ntp
, n
->n_dhcp_server_ntp
+ 1, sizeof(struct in_addr
));
1295 m
[n
->n_dhcp_server_ntp
++] = a
;
1296 n
->dhcp_server_ntp
= m
;
1300 int config_parse_dns(
1302 const char *filename
,
1304 const char *section
,
1305 unsigned section_line
,
1312 Network
*n
= userdata
;
1320 _cleanup_free_
char *w
= NULL
;
1321 union in_addr_union a
;
1322 struct in_addr_data
*m
;
1325 r
= extract_first_word(&rvalue
, &w
, NULL
, 0);
1329 log_syntax(unit
, LOG_ERR
, filename
, line
, r
,
1330 "Invalid syntax, ignoring: %s", rvalue
);
1336 r
= in_addr_from_string_auto(w
, &family
, &a
);
1338 log_syntax(unit
, LOG_ERR
, filename
, line
, r
,
1339 "Failed to parse dns server address, ignoring: %s", w
);
1343 m
= reallocarray(n
->dns
, n
->n_dns
+ 1, sizeof(struct in_addr_data
));
1347 m
[n
->n_dns
++] = (struct in_addr_data
) {
1358 int config_parse_dnssec_negative_trust_anchors(
1360 const char *filename
,
1362 const char *section
,
1363 unsigned section_line
,
1370 const char *p
= rvalue
;
1378 if (isempty(rvalue
)) {
1379 n
->dnssec_negative_trust_anchors
= set_free_free(n
->dnssec_negative_trust_anchors
);
1384 _cleanup_free_
char *w
= NULL
;
1386 r
= extract_first_word(&p
, &w
, NULL
, 0);
1388 log_syntax(unit
, LOG_ERR
, filename
, line
, r
,
1389 "Failed to extract negative trust anchor domain, ignoring: %s", rvalue
);
1395 r
= dns_name_is_valid(w
);
1397 log_syntax(unit
, LOG_ERR
, filename
, line
, r
,
1398 "%s is not a valid domain name, ignoring.", w
);
1402 r
= set_ensure_allocated(&n
->dnssec_negative_trust_anchors
, &dns_name_hash_ops
);
1406 r
= set_put(n
->dnssec_negative_trust_anchors
, w
);
1416 int config_parse_ntp(
1418 const char *filename
,
1420 const char *section
,
1421 unsigned section_line
,
1435 if (isempty(rvalue
)) {
1441 _cleanup_free_
char *w
= NULL
;
1443 r
= extract_first_word(&rvalue
, &w
, NULL
, 0);
1447 log_syntax(unit
, LOG_ERR
, filename
, line
, r
,
1448 "Failed to extract NTP server name, ignoring: %s", rvalue
);
1454 r
= dns_name_is_valid_or_address(w
);
1456 log_syntax(unit
, LOG_ERR
, filename
, line
, r
,
1457 "%s is not a valid domain name or IP address, ignoring.", w
);
1461 r
= strv_push(l
, w
);
1471 int config_parse_dhcp_user_class(
1473 const char *filename
,
1475 const char *section
,
1476 unsigned section_line
,
1490 if (isempty(rvalue
)) {
1496 _cleanup_free_
char *w
= NULL
;
1498 r
= extract_first_word(&rvalue
, &w
, NULL
, 0);
1502 log_syntax(unit
, LOG_ERR
, filename
, line
, r
,
1503 "Failed to split user classes option, ignoring: %s", rvalue
);
1509 if (strlen(w
) > 255) {
1510 log_syntax(unit
, LOG_ERR
, filename
, line
, r
,
1511 "%s length is not in the range 1-255, ignoring.", w
);
1515 r
= strv_push(l
, w
);
1525 int config_parse_section_route_table(
1527 const char *filename
,
1529 const char *section
,
1530 unsigned section_line
,
1537 Network
*network
= data
;
1546 r
= safe_atou32(rvalue
, &rt
);
1548 log_syntax(unit
, LOG_ERR
, filename
, line
, r
,
1549 "Failed to parse RouteTable=%s, ignoring assignment: %m", rvalue
);
1553 if (streq_ptr(section
, "DHCP")) {
1554 network
->dhcp_route_table
= rt
;
1555 network
->dhcp_route_table_set
= true;
1556 } else { /* section is IPv6AcceptRA */
1557 network
->ipv6_accept_ra_route_table
= rt
;
1558 network
->ipv6_accept_ra_route_table_set
= true;
1564 DEFINE_CONFIG_PARSE_ENUM(config_parse_dhcp_use_domains
, dhcp_use_domains
, DHCPUseDomains
,
1565 "Failed to parse DHCP use domains setting");
1567 static const char* const dhcp_use_domains_table
[_DHCP_USE_DOMAINS_MAX
] = {
1568 [DHCP_USE_DOMAINS_NO
] = "no",
1569 [DHCP_USE_DOMAINS_ROUTE
] = "route",
1570 [DHCP_USE_DOMAINS_YES
] = "yes",
1573 DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(dhcp_use_domains
, DHCPUseDomains
, DHCP_USE_DOMAINS_YES
);
1575 DEFINE_CONFIG_PARSE_ENUM(config_parse_lldp_mode
, lldp_mode
, LLDPMode
, "Failed to parse LLDP= setting.");
1577 static const char* const lldp_mode_table
[_LLDP_MODE_MAX
] = {
1578 [LLDP_MODE_NO
] = "no",
1579 [LLDP_MODE_YES
] = "yes",
1580 [LLDP_MODE_ROUTERS_ONLY
] = "routers-only",
1583 DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(lldp_mode
, LLDPMode
, LLDP_MODE_YES
);
1585 int config_parse_iaid(const char *unit
,
1586 const char *filename
,
1588 const char *section
,
1589 unsigned section_line
,
1595 Network
*network
= data
;
1604 r
= safe_atou32(rvalue
, &iaid
);
1606 log_syntax(unit
, LOG_ERR
, filename
, line
, r
,
1607 "Unable to read IAID, ignoring assignment: %s", rvalue
);
1611 network
->iaid
= iaid
;
1612 network
->iaid_set
= true;