1 /* SPDX-License-Identifier: LGPL-2.1+ */
4 #include <netinet/in.h>
5 #include <linux/netdevice.h>
7 #include "alloc-util.h"
8 #include "conf-files.h"
9 #include "conf-parser.h"
10 #include "dns-domain.h"
12 #include "hostname-util.h"
13 #include "in-addr-util.h"
14 #include "networkd-dhcp-server.h"
15 #include "network-internal.h"
16 #include "networkd-manager.h"
17 #include "networkd-network.h"
18 #include "parse-util.h"
20 #include "socket-util.h"
21 #include "stat-util.h"
22 #include "string-table.h"
23 #include "string-util.h"
27 /* Let's assume that anything above this number is a user misconfiguration. */
28 #define MAX_NTP_SERVERS 128
30 /* Set defaults following RFC7844 */
31 void network_apply_anonymize_if_set(Network
*network
) {
32 if (!network
->dhcp_anonymize
)
35 SHOULD NOT send the Host Name option */
36 network
->dhcp_send_hostname
= false;
37 /* RFC7844 section 3.:
38 MAY contain the Client Identifier option
40 clients MUST use client identifiers based solely
41 on the link-layer address */
42 /* NOTE: Using MAC, as it does not reveal extra information,
43 * and some servers might not answer if this option is not sent */
44 network
->dhcp_client_identifier
= DHCP_CLIENT_ID_MAC
;
46 SHOULD NOT use the Vendor Class Identifier option */
47 network
->dhcp_vendor_class_identifier
= mfree(network
->dhcp_vendor_class_identifier
);
48 /* RFC7844 section 3.6.:
49 The client intending to protect its privacy SHOULD only request a
50 minimal number of options in the PRL and SHOULD also randomly shuffle
51 the ordering of option codes in the PRL. If this random ordering
52 cannot be implemented, the client MAY order the option codes in the
53 PRL by option code number (lowest to highest).
55 /* NOTE: dhcp_use_mtu is false by default,
56 * though it was not initiallized to any value in network_load_one.
57 * Maybe there should be another var called *send*?
58 * (to use the MTU sent by the server but to do not send
59 * the option in the PRL). */
60 network
->dhcp_use_mtu
= false;
61 /* NOTE: when Anonymize=yes, the PRL route options are sent by default,
62 * but this is needed to use them. */
63 network
->dhcp_use_routes
= true;
64 /* RFC7844 section 3.6.
65 * same comments as previous option */
66 network
->dhcp_use_timezone
= false;
69 static int network_resolve_netdev_one(Network
*network
, const char *name
, NetDevKind kind
, NetDev
**ret_netdev
) {
70 const char *kind_string
;
74 /* For test-networkd-conf, the check must be earlier than the assertions. */
79 assert(network
->manager
);
80 assert(network
->filename
);
83 if (kind
== _NETDEV_KIND_TUNNEL
)
84 kind_string
= "tunnel";
86 kind_string
= netdev_kind_to_string(kind
);
88 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
),
89 "%s: Invalid NetDev kind of %s, ignoring assignment.",
90 network
->filename
, name
);
93 r
= netdev_get(network
->manager
, name
, &netdev
);
95 return log_error_errno(r
, "%s: %s NetDev could not be found, ignoring assignment.",
96 network
->filename
, name
);
98 if (netdev
->kind
!= kind
&& !(kind
== _NETDEV_KIND_TUNNEL
&&
105 NETDEV_KIND_IP6GRETAP
,
109 NETDEV_KIND_ERSPAN
)))
110 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
),
111 "%s: NetDev %s is not a %s, ignoring assignment",
112 network
->filename
, name
, kind_string
);
114 *ret_netdev
= netdev_ref(netdev
);
118 static int network_resolve_stacked_netdevs(Network
*network
) {
125 HASHMAP_FOREACH_KEY(kind
, name
, network
->stacked_netdev_names
, i
) {
126 _cleanup_(netdev_unrefp
) NetDev
*netdev
= NULL
;
128 r
= network_resolve_netdev_one(network
, name
, PTR_TO_INT(kind
), &netdev
);
132 r
= hashmap_ensure_allocated(&network
->stacked_netdevs
, &string_hash_ops
);
136 r
= hashmap_put(network
->stacked_netdevs
, netdev
->ifname
, netdev
);
138 return log_error_errno(r
, "%s: Failed to add NetDev '%s' to network: %m",
139 network
->filename
, (const char *) name
);
147 int network_verify(Network
*network
) {
148 RoutingPolicyRule
*rule
, *rule_next
;
149 Neighbor
*neighbor
, *neighbor_next
;
150 AddressLabel
*label
, *label_next
;
151 NextHop
*nexthop
, *nextnop_next
;
152 Address
*address
, *address_next
;
153 Prefix
*prefix
, *prefix_next
;
154 Route
*route
, *route_next
;
155 FdbEntry
*fdb
, *fdb_next
;
158 assert(network
->filename
);
160 if (set_isempty(network
->match_mac
) && strv_isempty(network
->match_path
) &&
161 strv_isempty(network
->match_driver
) && strv_isempty(network
->match_type
) &&
162 strv_isempty(network
->match_name
) && strv_isempty(network
->match_property
) &&
163 strv_isempty(network
->match_ssid
) && !network
->conditions
)
164 log_warning("%s: No valid settings found in the [Match] section. "
165 "The file will match all interfaces. "
166 "If that is intended, please add Name=* in the [Match] section.",
169 /* skip out early if configuration does not match the environment */
170 if (!condition_test_list(network
->conditions
, NULL
, NULL
, NULL
))
171 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL
),
172 "%s: Conditions in the file do not match the system environment, skipping.",
175 (void) network_resolve_netdev_one(network
, network
->bond_name
, NETDEV_KIND_BOND
, &network
->bond
);
176 (void) network_resolve_netdev_one(network
, network
->bridge_name
, NETDEV_KIND_BRIDGE
, &network
->bridge
);
177 (void) network_resolve_netdev_one(network
, network
->vrf_name
, NETDEV_KIND_VRF
, &network
->vrf
);
178 (void) network_resolve_stacked_netdevs(network
);
180 /* Free unnecessary entries. */
181 network
->bond_name
= mfree(network
->bond_name
);
182 network
->bridge_name
= mfree(network
->bridge_name
);
183 network
->vrf_name
= mfree(network
->vrf_name
);
184 network
->stacked_netdev_names
= hashmap_free_free_key(network
->stacked_netdev_names
);
187 /* Bonding slave does not support addressing. */
188 if (network
->ipv6_accept_ra
> 0) {
189 log_warning("%s: Cannot enable IPv6AcceptRA= when Bond= is specified, disabling IPv6AcceptRA=.",
191 network
->ipv6_accept_ra
= 0;
193 if (network
->link_local
>= 0 && network
->link_local
!= ADDRESS_FAMILY_NO
) {
194 log_warning("%s: Cannot enable LinkLocalAddressing= when Bond= is specified, disabling LinkLocalAddressing=.",
196 network
->link_local
= ADDRESS_FAMILY_NO
;
198 if (network
->dhcp
!= ADDRESS_FAMILY_NO
) {
199 log_warning("%s: Cannot enable DHCP= when Bond= is specified, disabling DHCP=.",
201 network
->dhcp
= ADDRESS_FAMILY_NO
;
203 if (network
->dhcp_server
) {
204 log_warning("%s: Cannot enable DHCPServer= when Bond= is specified, disabling DHCPServer=.",
206 network
->dhcp_server
= false;
208 if (network
->n_static_addresses
> 0) {
209 log_warning("%s: Cannot set addresses when Bond= is specified, ignoring addresses.",
211 while ((address
= network
->static_addresses
))
212 address_free(address
);
214 if (network
->n_static_routes
> 0) {
215 log_warning("%s: Cannot set routes when Bond= is specified, ignoring routes.",
217 while ((route
= network
->static_routes
))
222 if (network
->link_local
< 0)
223 network
->link_local
= network
->bridge
? ADDRESS_FAMILY_NO
: ADDRESS_FAMILY_IPV6
;
225 if (!FLAGS_SET(network
->link_local
, ADDRESS_FAMILY_IPV6
)) {
226 if (network
->ipv6_accept_ra
> 0) {
227 log_warning("%s: IPv6AcceptRA= is enabled by the .network file but IPv6 link local addressing is disabled. "
228 "Disabling IPv6AcceptRA=.", network
->filename
);
229 network
->ipv6_accept_ra
= false;
232 if (FLAGS_SET(network
->dhcp
, ADDRESS_FAMILY_IPV6
)) {
233 log_warning("%s: DHCPv6 client is enabled by the .network file but IPv6 link local addressing is disabled. "
234 "Disabling DHCPv6 client.", network
->filename
);
235 SET_FLAG(network
->dhcp
, ADDRESS_FAMILY_IPV6
, false);
238 if (network
->router_prefix_delegation
!= RADV_PREFIX_DELEGATION_NONE
) {
239 log_warning("%s: IPv6PrefixDelegation= is enabled but IPv6 link local addressing is disabled. "
240 "Disabling IPv6PrefixDelegation=.", network
->filename
);
241 network
->router_prefix_delegation
= RADV_PREFIX_DELEGATION_NONE
;
245 if (FLAGS_SET(network
->link_local
, ADDRESS_FAMILY_FALLBACK_IPV4
) &&
246 !FLAGS_SET(network
->dhcp
, ADDRESS_FAMILY_IPV4
)) {
247 log_warning("%s: fallback assignment of IPv4 link local address is enabled but DHCPv4 is disabled. "
248 "Disabling the fallback assignment.", network
->filename
);
249 SET_FLAG(network
->link_local
, ADDRESS_FAMILY_FALLBACK_IPV4
, false);
252 if (network
->ipv6_accept_ra
< 0 && network
->bridge
)
253 network
->ipv6_accept_ra
= false;
255 /* IPMasquerade=yes implies IPForward=yes */
256 if (network
->ip_masquerade
)
257 network
->ip_forward
|= ADDRESS_FAMILY_IPV4
;
259 if (network
->mtu
> 0 && network
->dhcp_use_mtu
) {
260 log_warning("%s: MTUBytes= in [Link] section and UseMTU= in [DHCP] section are set. "
261 "Disabling UseMTU=.", network
->filename
);
262 network
->dhcp_use_mtu
= false;
265 if (network
->dhcp_critical
>= 0) {
266 if (network
->keep_configuration
>= 0)
267 log_warning("%s: Both KeepConfiguration= and deprecated CriticalConnection= are set. "
268 "Ignoring CriticalConnection=.", network
->filename
);
269 else if (network
->dhcp_critical
)
270 /* CriticalConnection=yes also preserve foreign static configurations. */
271 network
->keep_configuration
= KEEP_CONFIGURATION_YES
;
273 network
->keep_configuration
= KEEP_CONFIGURATION_NO
;
276 if (network
->keep_configuration
< 0)
277 network
->keep_configuration
= KEEP_CONFIGURATION_NO
;
279 LIST_FOREACH_SAFE(addresses
, address
, address_next
, network
->static_addresses
)
280 if (address_section_verify(address
) < 0)
281 address_free(address
);
283 LIST_FOREACH_SAFE(routes
, route
, route_next
, network
->static_routes
)
284 if (route_section_verify(route
, network
) < 0)
287 LIST_FOREACH_SAFE(nexthops
, nexthop
, nextnop_next
, network
->static_nexthops
)
288 if (nexthop_section_verify(nexthop
) < 0)
289 nexthop_free(nexthop
);
291 LIST_FOREACH_SAFE(static_fdb_entries
, fdb
, fdb_next
, network
->static_fdb_entries
)
292 if (section_is_invalid(fdb
->section
))
295 LIST_FOREACH_SAFE(neighbors
, neighbor
, neighbor_next
, network
->neighbors
)
296 if (neighbor_section_verify(neighbor
) < 0)
297 neighbor_free(neighbor
);
299 LIST_FOREACH_SAFE(labels
, label
, label_next
, network
->address_labels
)
300 if (section_is_invalid(label
->section
))
301 address_label_free(label
);
303 LIST_FOREACH_SAFE(prefixes
, prefix
, prefix_next
, network
->static_prefixes
)
304 if (section_is_invalid(prefix
->section
))
307 LIST_FOREACH_SAFE(prefixes
, prefix
, prefix_next
, network
->static_route_prefixes
)
308 if (section_is_invalid(prefix
->section
))
309 route_prefix_free(prefix
);
311 LIST_FOREACH_SAFE(rules
, rule
, rule_next
, network
->rules
)
312 if (routing_policy_rule_section_verify(rule
) < 0)
313 routing_policy_rule_free(rule
);
318 int network_load_one(Manager
*manager
, OrderedHashmap
**networks
, const char *filename
) {
319 _cleanup_free_
char *fname
= NULL
, *name
= NULL
;
320 _cleanup_(network_unrefp
) Network
*network
= NULL
;
321 _cleanup_fclose_
FILE *file
= NULL
;
322 const char *dropin_dirname
;
329 file
= fopen(filename
, "re");
337 if (null_or_empty_fd(fileno(file
))) {
338 log_debug("Skipping empty file: %s", filename
);
342 fname
= strdup(filename
);
346 name
= strdup(basename(filename
));
350 d
= strrchr(name
, '.');
356 dropin_dirname
= strjoina(name
, ".network.d");
358 network
= new(Network
, 1);
362 *network
= (Network
) {
363 .filename
= TAKE_PTR(fname
),
364 .name
= TAKE_PTR(name
),
369 .required_for_online
= true,
370 .required_operstate_for_online
= LINK_OPERSTATE_DEGRADED
,
371 .dhcp
= ADDRESS_FAMILY_NO
,
373 .dhcp_use_ntp
= true,
374 .dhcp_use_sip
= true,
375 .dhcp_use_dns
= true,
376 .dhcp_use_hostname
= true,
377 .dhcp_use_routes
= true,
378 /* NOTE: this var might be overwritten by network_apply_anonymize_if_set */
379 .dhcp_send_hostname
= true,
380 .dhcp_send_release
= true,
381 /* To enable/disable RFC7844 Anonymity Profiles */
382 .dhcp_anonymize
= false,
383 .dhcp_route_metric
= DHCP_ROUTE_METRIC
,
384 /* NOTE: this var might be overwritten by network_apply_anonymize_if_set */
385 .dhcp_client_identifier
= DHCP_CLIENT_ID_DUID
,
386 .dhcp_route_table
= RT_TABLE_MAIN
,
387 .dhcp_route_table_set
= false,
388 /* NOTE: from man: UseMTU=... Defaults to false*/
389 .dhcp_use_mtu
= false,
390 /* NOTE: from man: UseTimezone=... Defaults to "no".*/
391 .dhcp_use_timezone
= false,
392 .rapid_commit
= true,
394 .dhcp6_use_ntp
= true,
395 .dhcp6_use_dns
= true,
397 .dhcp_server_emit_dns
= true,
398 .dhcp_server_emit_ntp
= true,
399 .dhcp_server_emit_sip
= true,
400 .dhcp_server_emit_router
= true,
401 .dhcp_server_emit_timezone
= true,
403 .router_emit_dns
= true,
404 .router_emit_domains
= true,
409 .allow_port_to_be_root
= -1,
411 .multicast_flood
= -1,
412 .multicast_to_unicast
= -1,
413 .neighbor_suppression
= -1,
415 .bridge_proxy_arp
= -1,
416 .bridge_proxy_arp_wifi
= -1,
417 .priority
= LINK_BRIDGE_PORT_PRIORITY_INVALID
,
418 .multicast_router
= _MULTICAST_ROUTER_INVALID
,
420 .lldp_mode
= LLDP_MODE_ROUTERS_ONLY
,
422 .dns_default_route
= -1,
423 .llmnr
= RESOLVE_SUPPORT_YES
,
424 .mdns
= RESOLVE_SUPPORT_NO
,
425 .dnssec_mode
= _DNSSEC_MODE_INVALID
,
426 .dns_over_tls_mode
= _DNS_OVER_TLS_MODE_INVALID
,
428 /* If LinkLocalAddressing= is not set, then set to ADDRESS_FAMILY_IPV6 later. */
429 .link_local
= _ADDRESS_FAMILY_INVALID
,
431 .ipv6_privacy_extensions
= IPV6_PRIVACY_EXTENSIONS_NO
,
432 .ipv6_accept_ra
= -1,
433 .ipv6_dad_transmits
= -1,
434 .ipv6_hop_limit
= -1,
435 .ipv6_proxy_ndp
= -1,
436 .duid
.type
= _DUID_TYPE_INVALID
,
441 .ipv6_accept_ra_use_dns
= true,
442 .ipv6_accept_ra_use_autonomous_prefix
= true,
443 .ipv6_accept_ra_use_onlink_prefix
= true,
444 .ipv6_accept_ra_route_table
= RT_TABLE_MAIN
,
445 .ipv6_accept_ra_route_table_set
= false,
447 .keep_configuration
= _KEEP_CONFIGURATION_INVALID
,
449 .can_triple_sampling
= -1,
450 .ip_service_type
= -1,
453 r
= config_parse_many(filename
, NETWORK_DIRS
, dropin_dirname
,
460 "RoutingPolicyRule\0"
463 "DHCP\0" /* compat */
468 "IPv6NDPProxyAddress\0"
472 "IPv6PrefixDelegation\0"
475 "TrafficControlQueueingDiscipline\0"
477 config_item_perf_lookup
, network_network_gperf_lookup
,
478 CONFIG_PARSE_WARN
, network
);
482 network_apply_anonymize_if_set(network
);
484 r
= network_add_ipv4ll_route(network
);
486 log_warning_errno(r
, "%s: Failed to add IPv4LL route, ignoring: %m", network
->filename
);
488 r
= network_add_default_route_on_device(network
);
490 log_warning_errno(r
, "%s: Failed to add default route on device, ignoring: %m",
494 if (stat(filename
, &stats
) < 0)
496 network
->timestamp
= timespec_load(&stats
.st_mtim
);
498 if (network_verify(network
) < 0)
499 /* Ignore .network files that do not match the conditions. */
502 r
= ordered_hashmap_ensure_allocated(networks
, &string_hash_ops
);
506 r
= ordered_hashmap_put(*networks
, network
->name
, network
);
514 int network_load(Manager
*manager
, OrderedHashmap
**networks
) {
515 _cleanup_strv_free_
char **files
= NULL
;
521 ordered_hashmap_clear_with_destructor(*networks
, network_unref
);
523 r
= conf_files_list_strv(&files
, ".network", NULL
, 0, NETWORK_DIRS
);
525 return log_error_errno(r
, "Failed to enumerate network files: %m");
527 STRV_FOREACH(f
, files
) {
528 r
= network_load_one(manager
, networks
, *f
);
530 log_error_errno(r
, "Failed to load %s, ignoring: %m", *f
);
536 int network_reload(Manager
*manager
) {
537 OrderedHashmap
*new_networks
= NULL
;
544 r
= network_load(manager
, &new_networks
);
548 ORDERED_HASHMAP_FOREACH(n
, new_networks
, i
) {
549 r
= network_get_by_name(manager
, n
->name
, &old
);
551 continue; /* The .network file is new. */
553 if (n
->timestamp
!= old
->timestamp
)
554 continue; /* The .network file is modified. */
556 if (!streq(n
->filename
, old
->filename
))
559 r
= ordered_hashmap_replace(new_networks
, old
->name
, old
);
567 ordered_hashmap_free_with_destructor(manager
->networks
, network_unref
);
568 manager
->networks
= new_networks
;
573 ordered_hashmap_free_with_destructor(new_networks
, network_unref
);
578 static Network
*network_free(Network
*network
) {
579 IPv6ProxyNDPAddress
*ipv6_proxy_ndp_address
;
580 RoutingPolicyRule
*rule
;
592 free(network
->filename
);
594 set_free_free(network
->match_mac
);
595 strv_free(network
->match_path
);
596 strv_free(network
->match_driver
);
597 strv_free(network
->match_type
);
598 strv_free(network
->match_name
);
599 strv_free(network
->match_property
);
600 strv_free(network
->match_wlan_iftype
);
601 strv_free(network
->match_ssid
);
602 set_free_free(network
->match_bssid
);
603 condition_free_list(network
->conditions
);
605 free(network
->description
);
606 free(network
->dhcp_vendor_class_identifier
);
607 strv_free(network
->dhcp_user_class
);
608 free(network
->dhcp_hostname
);
609 set_free(network
->dhcp_black_listed_ip
);
610 set_free(network
->dhcp_request_options
);
613 strv_free(network
->ntp
);
615 strv_free(network
->sip
);
616 ordered_set_free_free(network
->search_domains
);
617 ordered_set_free_free(network
->route_domains
);
618 strv_free(network
->bind_carrier
);
620 ordered_set_free_free(network
->router_search_domains
);
621 free(network
->router_dns
);
622 set_free_free(network
->ndisc_black_listed_prefix
);
624 free(network
->bridge_name
);
625 free(network
->bond_name
);
626 free(network
->vrf_name
);
627 hashmap_free_free_key(network
->stacked_netdev_names
);
628 netdev_unref(network
->bridge
);
629 netdev_unref(network
->bond
);
630 netdev_unref(network
->vrf
);
631 hashmap_free_with_destructor(network
->stacked_netdevs
, netdev_unref
);
633 while ((route
= network
->static_routes
))
636 while ((nexthop
= network
->static_nexthops
))
637 nexthop_free(nexthop
);
639 while ((address
= network
->static_addresses
))
640 address_free(address
);
642 while ((fdb_entry
= network
->static_fdb_entries
))
643 fdb_entry_free(fdb_entry
);
645 while ((ipv6_proxy_ndp_address
= network
->ipv6_proxy_ndp_addresses
))
646 ipv6_proxy_ndp_address_free(ipv6_proxy_ndp_address
);
648 while ((neighbor
= network
->neighbors
))
649 neighbor_free(neighbor
);
651 while ((label
= network
->address_labels
))
652 address_label_free(label
);
654 while ((prefix
= network
->static_prefixes
))
657 while ((rule
= network
->rules
))
658 routing_policy_rule_free(rule
);
660 hashmap_free(network
->addresses_by_section
);
661 hashmap_free(network
->routes_by_section
);
662 hashmap_free(network
->nexthops_by_section
);
663 hashmap_free(network
->fdb_entries_by_section
);
664 hashmap_free(network
->neighbors_by_section
);
665 hashmap_free(network
->address_labels_by_section
);
666 hashmap_free(network
->prefixes_by_section
);
667 hashmap_free(network
->rules_by_section
);
668 ordered_hashmap_free_with_destructor(network
->qdiscs_by_section
, qdisc_free
);
670 if (network
->manager
&&
671 network
->manager
->duids_requesting_uuid
)
672 set_remove(network
->manager
->duids_requesting_uuid
, &network
->duid
);
676 free(network
->dhcp_server_timezone
);
677 free(network
->dhcp_server_dns
);
678 free(network
->dhcp_server_ntp
);
679 free(network
->dhcp_server_sip
);
681 set_free_free(network
->dnssec_negative_trust_anchors
);
683 ordered_hashmap_free(network
->dhcp_send_options
);
684 ordered_hashmap_free(network
->dhcp_server_raw_options
);
686 return mfree(network
);
689 DEFINE_TRIVIAL_REF_UNREF_FUNC(Network
, network
, network_free
);
691 int network_get_by_name(Manager
*manager
, const char *name
, Network
**ret
) {
698 network
= ordered_hashmap_get(manager
->networks
, name
);
707 int network_get(Manager
*manager
, sd_device
*device
,
708 const char *ifname
, const struct ether_addr
*address
,
709 enum nl80211_iftype wlan_iftype
, const char *ssid
, const struct ether_addr
*bssid
,
717 ORDERED_HASHMAP_FOREACH(network
, manager
->networks
, i
)
718 if (net_match_config(network
->match_mac
, network
->match_path
, network
->match_driver
,
719 network
->match_type
, network
->match_name
, network
->match_property
,
720 network
->match_wlan_iftype
, network
->match_ssid
, network
->match_bssid
,
721 device
, address
, ifname
, wlan_iftype
, ssid
, bssid
)) {
722 if (network
->match_name
&& device
) {
724 uint8_t name_assign_type
= NET_NAME_UNKNOWN
;
726 if (sd_device_get_sysattr_value(device
, "name_assign_type", &attr
) >= 0)
727 (void) safe_atou8(attr
, &name_assign_type
);
729 if (name_assign_type
== NET_NAME_ENUM
)
730 log_warning("%s: found matching network '%s', based on potentially unpredictable ifname",
731 ifname
, network
->filename
);
733 log_debug("%s: found matching network '%s'", ifname
, network
->filename
);
735 log_debug("%s: found matching network '%s'", ifname
, network
->filename
);
746 int network_apply(Network
*network
, Link
*link
) {
750 link
->network
= network_ref(network
);
752 if (network
->n_dns
> 0 ||
753 !strv_isempty(network
->ntp
) ||
754 !ordered_set_isempty(network
->search_domains
) ||
755 !ordered_set_isempty(network
->route_domains
))
761 bool network_has_static_ipv6_configurations(Network
*network
) {
769 LIST_FOREACH(addresses
, address
, network
->static_addresses
)
770 if (address
->family
== AF_INET6
)
773 LIST_FOREACH(routes
, route
, network
->static_routes
)
774 if (route
->family
== AF_INET6
)
777 LIST_FOREACH(static_fdb_entries
, fdb
, network
->static_fdb_entries
)
778 if (fdb
->family
== AF_INET6
)
781 LIST_FOREACH(neighbors
, neighbor
, network
->neighbors
)
782 if (neighbor
->family
== AF_INET6
)
785 if (!LIST_IS_EMPTY(network
->address_labels
))
788 if (!LIST_IS_EMPTY(network
->static_prefixes
))
794 int config_parse_stacked_netdev(const char *unit
,
795 const char *filename
,
798 unsigned section_line
,
804 _cleanup_free_
char *name
= NULL
;
805 NetDevKind kind
= ltype
;
814 NETDEV_KIND_VLAN
, NETDEV_KIND_MACVLAN
, NETDEV_KIND_MACVTAP
,
815 NETDEV_KIND_IPVLAN
, NETDEV_KIND_IPVTAP
, NETDEV_KIND_VXLAN
,
816 NETDEV_KIND_L2TP
, NETDEV_KIND_MACSEC
, _NETDEV_KIND_TUNNEL
,
819 if (!ifname_valid(rvalue
)) {
820 log_syntax(unit
, LOG_ERR
, filename
, line
, 0,
821 "Invalid netdev name in %s=, ignoring assignment: %s", lvalue
, rvalue
);
825 name
= strdup(rvalue
);
829 r
= hashmap_ensure_allocated(h
, &string_hash_ops
);
833 r
= hashmap_put(*h
, name
, INT_TO_PTR(kind
));
835 log_syntax(unit
, LOG_ERR
, filename
, line
, r
,
836 "Cannot add NetDev '%s' to network, ignoring assignment: %m", name
);
838 log_syntax(unit
, LOG_DEBUG
, filename
, line
, r
,
839 "NetDev '%s' specified twice, ignoring.", name
);
846 int config_parse_domains(
848 const char *filename
,
851 unsigned section_line
,
866 if (isempty(rvalue
)) {
867 n
->search_domains
= ordered_set_free_free(n
->search_domains
);
868 n
->route_domains
= ordered_set_free_free(n
->route_domains
);
874 _cleanup_free_
char *w
= NULL
, *normalized
= NULL
;
878 r
= extract_first_word(&p
, &w
, NULL
, 0);
880 log_syntax(unit
, LOG_ERR
, filename
, line
, r
,
881 "Failed to extract search or route domain, ignoring: %s", rvalue
);
887 is_route
= w
[0] == '~';
888 domain
= is_route
? w
+ 1 : w
;
890 if (dns_name_is_root(domain
) || streq(domain
, "*")) {
891 /* If the root domain appears as is, or the special token "*" is found, we'll
892 * consider this as routing domain, unconditionally. */
894 domain
= "."; /* make sure we don't allow empty strings, thus write the root
897 r
= dns_name_normalize(domain
, 0, &normalized
);
899 log_syntax(unit
, LOG_ERR
, filename
, line
, r
,
900 "'%s' is not a valid domain name, ignoring.", domain
);
906 if (is_localhost(domain
)) {
907 log_syntax(unit
, LOG_ERR
, filename
, line
, 0,
908 "'localhost' domain may not be configured as search or route domain, ignoring assignment: %s",
914 OrderedSet
**set
= is_route
? &n
->route_domains
: &n
->search_domains
;
915 r
= ordered_set_ensure_allocated(set
, &string_hash_ops
);
919 r
= ordered_set_put_strdup(*set
, domain
);
927 int config_parse_ipv6token(
929 const char *filename
,
932 unsigned section_line
,
939 union in_addr_union buffer
;
940 struct in6_addr
*token
= data
;
948 r
= in_addr_from_string(AF_INET6
, rvalue
, &buffer
);
950 log_syntax(unit
, LOG_ERR
, filename
, line
, r
,
951 "Failed to parse IPv6 token, ignoring: %s", rvalue
);
955 if (in_addr_is_null(AF_INET6
, &buffer
)) {
956 log_syntax(unit
, LOG_ERR
, filename
, line
, 0,
957 "IPv6 token cannot be the ANY address, ignoring: %s", rvalue
);
961 if ((buffer
.in6
.s6_addr32
[0] | buffer
.in6
.s6_addr32
[1]) != 0) {
962 log_syntax(unit
, LOG_ERR
, filename
, line
, 0,
963 "IPv6 token cannot be longer than 64 bits, ignoring: %s", rvalue
);
972 static const char* const ipv6_privacy_extensions_table
[_IPV6_PRIVACY_EXTENSIONS_MAX
] = {
973 [IPV6_PRIVACY_EXTENSIONS_NO
] = "no",
974 [IPV6_PRIVACY_EXTENSIONS_PREFER_PUBLIC
] = "prefer-public",
975 [IPV6_PRIVACY_EXTENSIONS_YES
] = "yes",
978 DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(ipv6_privacy_extensions
, IPv6PrivacyExtensions
,
979 IPV6_PRIVACY_EXTENSIONS_YES
);
981 int config_parse_ipv6_privacy_extensions(
983 const char *filename
,
986 unsigned section_line
,
993 IPv6PrivacyExtensions s
, *ipv6_privacy_extensions
= data
;
998 assert(ipv6_privacy_extensions
);
1000 s
= ipv6_privacy_extensions_from_string(rvalue
);
1002 if (streq(rvalue
, "kernel"))
1003 s
= _IPV6_PRIVACY_EXTENSIONS_INVALID
;
1005 log_syntax(unit
, LOG_ERR
, filename
, line
, 0,
1006 "Failed to parse IPv6 privacy extensions option, ignoring: %s", rvalue
);
1011 *ipv6_privacy_extensions
= s
;
1016 int config_parse_hostname(
1018 const char *filename
,
1020 const char *section
,
1021 unsigned section_line
,
1028 _cleanup_free_
char *hn
= NULL
;
1029 char **hostname
= data
;
1036 r
= config_parse_string(unit
, filename
, line
, section
, section_line
, lvalue
, ltype
, rvalue
, &hn
, userdata
);
1040 if (!hostname_is_valid(hn
, false)) {
1041 log_syntax(unit
, LOG_ERR
, filename
, line
, 0,
1042 "Hostname is not valid, ignoring assignment: %s", rvalue
);
1046 r
= dns_name_is_valid(hn
);
1048 log_syntax(unit
, LOG_ERR
, filename
, line
, r
,
1049 "Failed to check validity of hostname '%s', ignoring assignment: %m", rvalue
);
1053 log_syntax(unit
, LOG_ERR
, filename
, line
, 0,
1054 "Hostname is not a valid DNS domain name, ignoring assignment: %s", rvalue
);
1058 return free_and_replace(*hostname
, hn
);
1061 int config_parse_timezone(
1063 const char *filename
,
1065 const char *section
,
1066 unsigned section_line
,
1073 _cleanup_free_
char *tz
= NULL
;
1074 char **datap
= data
;
1081 r
= config_parse_string(unit
, filename
, line
, section
, section_line
, lvalue
, ltype
, rvalue
, &tz
, userdata
);
1085 if (!timezone_is_valid(tz
, LOG_ERR
)) {
1086 log_syntax(unit
, LOG_ERR
, filename
, line
, 0,
1087 "Timezone is not valid, ignoring assignment: %s", rvalue
);
1091 return free_and_replace(*datap
, tz
);
1094 int config_parse_dns(
1096 const char *filename
,
1098 const char *section
,
1099 unsigned section_line
,
1106 Network
*n
= userdata
;
1114 _cleanup_free_
char *w
= NULL
;
1115 union in_addr_union a
;
1116 struct in_addr_data
*m
;
1119 r
= extract_first_word(&rvalue
, &w
, NULL
, 0);
1123 log_syntax(unit
, LOG_ERR
, filename
, line
, r
,
1124 "Invalid syntax, ignoring: %s", rvalue
);
1130 r
= in_addr_from_string_auto(w
, &family
, &a
);
1132 log_syntax(unit
, LOG_ERR
, filename
, line
, r
,
1133 "Failed to parse dns server address, ignoring: %s", w
);
1137 m
= reallocarray(n
->dns
, n
->n_dns
+ 1, sizeof(struct in_addr_data
));
1141 m
[n
->n_dns
++] = (struct in_addr_data
) {
1152 int config_parse_dnssec_negative_trust_anchors(
1154 const char *filename
,
1156 const char *section
,
1157 unsigned section_line
,
1164 const char *p
= rvalue
;
1172 if (isempty(rvalue
)) {
1173 n
->dnssec_negative_trust_anchors
= set_free_free(n
->dnssec_negative_trust_anchors
);
1178 _cleanup_free_
char *w
= NULL
;
1180 r
= extract_first_word(&p
, &w
, NULL
, 0);
1182 log_syntax(unit
, LOG_ERR
, filename
, line
, r
,
1183 "Failed to extract negative trust anchor domain, ignoring: %s", rvalue
);
1189 r
= dns_name_is_valid(w
);
1191 log_syntax(unit
, LOG_ERR
, filename
, line
, r
,
1192 "%s is not a valid domain name, ignoring.", w
);
1196 r
= set_ensure_allocated(&n
->dnssec_negative_trust_anchors
, &dns_name_hash_ops
);
1200 r
= set_put(n
->dnssec_negative_trust_anchors
, w
);
1210 int config_parse_ntp(
1212 const char *filename
,
1214 const char *section
,
1215 unsigned section_line
,
1229 if (isempty(rvalue
)) {
1235 _cleanup_free_
char *w
= NULL
;
1237 r
= extract_first_word(&rvalue
, &w
, NULL
, 0);
1241 log_syntax(unit
, LOG_ERR
, filename
, line
, r
,
1242 "Failed to extract NTP server name, ignoring: %s", rvalue
);
1248 r
= dns_name_is_valid_or_address(w
);
1250 log_syntax(unit
, LOG_ERR
, filename
, line
, r
,
1251 "%s is not a valid domain name or IP address, ignoring.", w
);
1255 if (strv_length(*l
) > MAX_NTP_SERVERS
) {
1256 log_syntax(unit
, LOG_WARNING
, filename
, line
, 0,
1257 "More than %u NTP servers specified, ignoring \"%s\" and any subsequent entries.",
1258 MAX_NTP_SERVERS
, w
);
1262 r
= strv_consume(l
, TAKE_PTR(w
));
1270 int config_parse_required_for_online(
1272 const char *filename
,
1274 const char *section
,
1275 unsigned section_line
,
1282 Network
*network
= data
;
1283 LinkOperationalState s
;
1284 bool required
= true;
1287 if (isempty(rvalue
)) {
1288 network
->required_for_online
= true;
1289 network
->required_operstate_for_online
= LINK_OPERSTATE_DEGRADED
;
1293 s
= link_operstate_from_string(rvalue
);
1295 r
= parse_boolean(rvalue
);
1297 log_syntax(unit
, LOG_ERR
, filename
, line
, r
,
1298 "Failed to parse %s= setting, ignoring assignment: %s",
1304 s
= LINK_OPERSTATE_DEGRADED
;
1307 network
->required_for_online
= required
;
1308 network
->required_operstate_for_online
= s
;
1313 DEFINE_CONFIG_PARSE_ENUM(config_parse_keep_configuration
, keep_configuration
, KeepConfiguration
,
1314 "Failed to parse KeepConfiguration= setting");
1316 static const char* const keep_configuration_table
[_KEEP_CONFIGURATION_MAX
] = {
1317 [KEEP_CONFIGURATION_NO
] = "no",
1318 [KEEP_CONFIGURATION_DHCP_ON_STOP
] = "dhcp-on-stop",
1319 [KEEP_CONFIGURATION_DHCP
] = "dhcp",
1320 [KEEP_CONFIGURATION_STATIC
] = "static",
1321 [KEEP_CONFIGURATION_YES
] = "yes",
1324 DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(keep_configuration
, KeepConfiguration
, KEEP_CONFIGURATION_YES
);