1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
4 #include <netinet/in.h>
5 #include <linux/netdevice.h>
8 #include "alloc-util.h"
9 #include "conf-files.h"
10 #include "conf-parser.h"
11 #include "dns-domain.h"
13 #include "hostname-util.h"
14 #include "in-addr-util.h"
15 #include "net-condition.h"
16 #include "netdev/macvlan.h"
17 #include "networkd-address-label.h"
18 #include "networkd-address.h"
19 #include "networkd-bridge-fdb.h"
20 #include "networkd-bridge-mdb.h"
21 #include "networkd-dhcp-common.h"
22 #include "networkd-dhcp-server-static-lease.h"
23 #include "networkd-ipv6-proxy-ndp.h"
24 #include "networkd-manager.h"
25 #include "networkd-ndisc.h"
26 #include "networkd-neighbor.h"
27 #include "networkd-network.h"
28 #include "networkd-nexthop.h"
29 #include "networkd-radv.h"
30 #include "networkd-route.h"
31 #include "networkd-routing-policy-rule.h"
32 #include "networkd-sriov.h"
33 #include "parse-util.h"
34 #include "path-lookup.h"
36 #include "radv-internal.h"
38 #include "socket-util.h"
39 #include "stat-util.h"
40 #include "string-table.h"
41 #include "string-util.h"
45 /* Let's assume that anything above this number is a user misconfiguration. */
46 #define MAX_NTP_SERVERS 128U
48 static int network_resolve_netdev_one(Network
*network
, const char *name
, NetDevKind kind
, NetDev
**ret
) {
49 const char *kind_string
;
53 /* For test-networkd-conf, the check must be earlier than the assertions. */
58 assert(network
->manager
);
59 assert(network
->filename
);
62 if (kind
== _NETDEV_KIND_TUNNEL
)
63 kind_string
= "tunnel";
65 kind_string
= netdev_kind_to_string(kind
);
67 return log_warning_errno(SYNTHETIC_ERRNO(EINVAL
),
68 "%s: Invalid NetDev kind of %s, ignoring assignment.",
69 network
->filename
, name
);
72 r
= netdev_get(network
->manager
, name
, &netdev
);
74 return log_warning_errno(r
, "%s: %s NetDev could not be found, ignoring assignment.",
75 network
->filename
, name
);
77 if (netdev
->kind
!= kind
&& !(kind
== _NETDEV_KIND_TUNNEL
&&
83 NETDEV_KIND_IP6GRETAP
,
89 return log_warning_errno(SYNTHETIC_ERRNO(EINVAL
),
90 "%s: NetDev %s is not a %s, ignoring assignment",
91 network
->filename
, name
, kind_string
);
93 *ret
= netdev_ref(netdev
);
97 static int network_resolve_stacked_netdevs(Network
*network
) {
103 HASHMAP_FOREACH_KEY(kind
, name
, network
->stacked_netdev_names
) {
104 _cleanup_(netdev_unrefp
) NetDev
*netdev
= NULL
;
106 if (network_resolve_netdev_one(network
, name
, PTR_TO_INT(kind
), &netdev
) <= 0)
109 r
= hashmap_ensure_put(&network
->stacked_netdevs
, &string_hash_ops
, netdev
->ifname
, netdev
);
113 log_warning_errno(r
, "%s: Failed to add NetDev '%s' to network, ignoring: %m",
114 network
->filename
, (const char *) name
);
122 int network_verify(Network
*network
) {
126 assert(network
->manager
);
127 assert(network
->filename
);
129 if (net_match_is_empty(&network
->match
) && !network
->conditions
)
130 return log_warning_errno(SYNTHETIC_ERRNO(EINVAL
),
131 "%s: No valid settings found in the [Match] section, ignoring file. "
132 "To match all interfaces, add Name=* in the [Match] section.",
135 /* skip out early if configuration does not match the environment */
136 if (!condition_test_list(network
->conditions
, environ
, NULL
, NULL
, NULL
))
137 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL
),
138 "%s: Conditions in the file do not match the system environment, skipping.",
141 if (network
->keep_master
) {
142 if (network
->batadv_name
)
143 log_warning("%s: BatmanAdvanced= set with KeepMaster= enabled, ignoring BatmanAdvanced=.",
145 if (network
->bond_name
)
146 log_warning("%s: Bond= set with KeepMaster= enabled, ignoring Bond=.",
148 if (network
->bridge_name
)
149 log_warning("%s: Bridge= set with KeepMaster= enabled, ignoring Bridge=.",
151 if (network
->vrf_name
)
152 log_warning("%s: VRF= set with KeepMaster= enabled, ignoring VRF=.",
155 network
->batadv_name
= mfree(network
->batadv_name
);
156 network
->bond_name
= mfree(network
->bond_name
);
157 network
->bridge_name
= mfree(network
->bridge_name
);
158 network
->vrf_name
= mfree(network
->vrf_name
);
161 (void) network_resolve_netdev_one(network
, network
->batadv_name
, NETDEV_KIND_BATADV
, &network
->batadv
);
162 (void) network_resolve_netdev_one(network
, network
->bond_name
, NETDEV_KIND_BOND
, &network
->bond
);
163 (void) network_resolve_netdev_one(network
, network
->bridge_name
, NETDEV_KIND_BRIDGE
, &network
->bridge
);
164 (void) network_resolve_netdev_one(network
, network
->vrf_name
, NETDEV_KIND_VRF
, &network
->vrf
);
165 r
= network_resolve_stacked_netdevs(network
);
169 /* Free unnecessary entries. */
170 network
->batadv_name
= mfree(network
->batadv_name
);
171 network
->bond_name
= mfree(network
->bond_name
);
172 network
->bridge_name
= mfree(network
->bridge_name
);
173 network
->vrf_name
= mfree(network
->vrf_name
);
174 network
->stacked_netdev_names
= hashmap_free_free_key(network
->stacked_netdev_names
);
177 /* Bonding slave does not support addressing. */
178 if (network
->link_local
>= 0 && network
->link_local
!= ADDRESS_FAMILY_NO
) {
179 log_warning("%s: Cannot enable LinkLocalAddressing= when Bond= is specified, disabling LinkLocalAddressing=.",
181 network
->link_local
= ADDRESS_FAMILY_NO
;
183 if (!ordered_hashmap_isempty(network
->addresses_by_section
))
184 log_warning("%s: Cannot set addresses when Bond= is specified, ignoring addresses.",
186 if (!hashmap_isempty(network
->routes_by_section
))
187 log_warning("%s: Cannot set routes when Bond= is specified, ignoring routes.",
190 network
->addresses_by_section
= ordered_hashmap_free_with_destructor(network
->addresses_by_section
, address_free
);
191 network
->routes_by_section
= hashmap_free_with_destructor(network
->routes_by_section
, route_free
);
194 if (network
->link_local
< 0) {
195 network
->link_local
= ADDRESS_FAMILY_IPV6
;
197 if (network
->keep_master
|| network
->bridge
)
198 network
->link_local
= ADDRESS_FAMILY_NO
;
202 HASHMAP_FOREACH(netdev
, network
->stacked_netdevs
) {
205 if (netdev
->kind
== NETDEV_KIND_MACVLAN
)
207 else if (netdev
->kind
== NETDEV_KIND_MACVTAP
)
212 if (m
->mode
== NETDEV_MACVLAN_MODE_PASSTHRU
)
213 network
->link_local
= ADDRESS_FAMILY_NO
;
215 /* There won't be a passthru MACVLAN/MACVTAP if there's already one in another mode */
221 if (network
->ipv6ll_address_gen_mode
== IPV6_LINK_LOCAL_ADDRESSS_GEN_MODE_NONE
)
222 SET_FLAG(network
->link_local
, ADDRESS_FAMILY_IPV6
, false);
224 if (in6_addr_is_set(&network
->ipv6ll_stable_secret
) &&
225 network
->ipv6ll_address_gen_mode
< 0)
226 network
->ipv6ll_address_gen_mode
= IPV6_LINK_LOCAL_ADDRESSS_GEN_MODE_STABLE_PRIVACY
;
228 /* IPMasquerade implies IPForward */
229 network
->ip_forward
|= network
->ip_masquerade
;
231 network_adjust_ipv6_proxy_ndp(network
);
232 network_adjust_ipv6_accept_ra(network
);
233 network_adjust_dhcp(network
);
234 network_adjust_radv(network
);
235 network_adjust_bridge_vlan(network
);
237 if (network
->mtu
> 0 && network
->dhcp_use_mtu
) {
238 log_warning("%s: MTUBytes= in [Link] section and UseMTU= in [DHCP] section are set. "
239 "Disabling UseMTU=.", network
->filename
);
240 network
->dhcp_use_mtu
= false;
243 if (network
->dhcp_critical
>= 0) {
244 if (network
->keep_configuration
>= 0) {
245 if (network
->manager
->keep_configuration
< 0)
246 log_warning("%s: Both KeepConfiguration= and deprecated CriticalConnection= are set. "
247 "Ignoring CriticalConnection=.", network
->filename
);
248 } else if (network
->dhcp_critical
)
249 /* CriticalConnection=yes also preserve foreign static configurations. */
250 network
->keep_configuration
= KEEP_CONFIGURATION_YES
;
252 network
->keep_configuration
= KEEP_CONFIGURATION_NO
;
255 if (!strv_isempty(network
->bind_carrier
)) {
256 if (!IN_SET(network
->activation_policy
, _ACTIVATION_POLICY_INVALID
, ACTIVATION_POLICY_BOUND
))
257 log_warning("%s: ActivationPolicy=bound is required with BindCarrier=. "
258 "Setting ActivationPolicy=bound.", network
->filename
);
259 network
->activation_policy
= ACTIVATION_POLICY_BOUND
;
260 } else if (network
->activation_policy
== ACTIVATION_POLICY_BOUND
) {
261 log_warning("%s: ActivationPolicy=bound requires BindCarrier=. "
262 "Ignoring ActivationPolicy=bound.", network
->filename
);
263 network
->activation_policy
= ACTIVATION_POLICY_UP
;
266 if (network
->activation_policy
== _ACTIVATION_POLICY_INVALID
)
267 network
->activation_policy
= ACTIVATION_POLICY_UP
;
269 if (network
->activation_policy
== ACTIVATION_POLICY_ALWAYS_UP
) {
270 if (network
->ignore_carrier_loss_set
&& network
->ignore_carrier_loss_usec
< USEC_INFINITY
)
271 log_warning("%s: IgnoreCarrierLoss=no or finite timespan conflicts with ActivationPolicy=always-up. "
272 "Setting IgnoreCarrierLoss=yes.", network
->filename
);
273 network
->ignore_carrier_loss_set
= true;
274 network
->ignore_carrier_loss_usec
= USEC_INFINITY
;
277 if (!network
->ignore_carrier_loss_set
) {
278 network
->ignore_carrier_loss_set
= true;
279 network
->ignore_carrier_loss_usec
= network
->configure_without_carrier
? USEC_INFINITY
: 0;
282 if (IN_SET(network
->activation_policy
, ACTIVATION_POLICY_DOWN
, ACTIVATION_POLICY_ALWAYS_DOWN
, ACTIVATION_POLICY_MANUAL
)) {
283 if (network
->required_for_online
< 0 ||
284 (network
->required_for_online
== true && network
->activation_policy
== ACTIVATION_POLICY_ALWAYS_DOWN
)) {
285 log_debug("%s: Setting RequiredForOnline=no because ActivationPolicy=%s.", network
->filename
,
286 activation_policy_to_string(network
->activation_policy
));
287 network
->required_for_online
= false;
288 } else if (network
->required_for_online
== true)
289 log_warning("%s: RequiredForOnline=yes and ActivationPolicy=%s, "
290 "this may cause a delay at boot.", network
->filename
,
291 activation_policy_to_string(network
->activation_policy
));
294 if (network
->required_for_online
< 0)
295 network
->required_for_online
= true;
297 if (network
->keep_configuration
< 0)
298 network
->keep_configuration
= KEEP_CONFIGURATION_NO
;
300 if (network
->ipv6_proxy_ndp
== 0 && !set_isempty(network
->ipv6_proxy_ndp_addresses
)) {
301 log_warning("%s: IPv6ProxyNDP= is disabled. Ignoring IPv6ProxyNDPAddress=.", network
->filename
);
302 network
->ipv6_proxy_ndp_addresses
= set_free_free(network
->ipv6_proxy_ndp_addresses
);
305 r
= network_drop_invalid_addresses(network
);
307 return r
; /* network_drop_invalid_addresses() logs internally. */
308 network_drop_invalid_routes(network
);
309 network_drop_invalid_nexthops(network
);
310 network_drop_invalid_bridge_fdb_entries(network
);
311 network_drop_invalid_bridge_mdb_entries(network
);
312 r
= network_drop_invalid_neighbors(network
);
315 network_drop_invalid_address_labels(network
);
316 network_drop_invalid_prefixes(network
);
317 network_drop_invalid_route_prefixes(network
);
318 network_drop_invalid_routing_policy_rules(network
);
319 network_drop_invalid_qdisc(network
);
320 network_drop_invalid_tclass(network
);
321 r
= sr_iov_drop_invalid_sections(UINT32_MAX
, network
->sr_iov_by_section
);
323 return r
; /* sr_iov_drop_invalid_sections() logs internally. */
324 network_drop_invalid_static_leases(network
);
329 int network_load_one(Manager
*manager
, OrderedHashmap
**networks
, const char *filename
) {
330 _cleanup_free_
char *fname
= NULL
, *name
= NULL
;
331 _cleanup_(network_unrefp
) Network
*network
= NULL
;
332 const char *dropin_dirname
;
339 r
= null_or_empty_path(filename
);
341 return log_warning_errno(r
, "Failed to check if \"%s\" is empty: %m", filename
);
343 log_debug("Skipping empty file: %s", filename
);
347 fname
= strdup(filename
);
351 name
= strdup(basename(filename
));
355 d
= strrchr(name
, '.');
357 return log_warning_errno(SYNTHETIC_ERRNO(EINVAL
), "Invalid file name: %s", filename
);
361 dropin_dirname
= strjoina(name
, ".network.d");
363 network
= new(Network
, 1);
367 *network
= (Network
) {
368 .filename
= TAKE_PTR(fname
),
369 .name
= TAKE_PTR(name
),
374 .required_for_online
= -1,
375 .required_operstate_for_online
= LINK_OPERSTATE_RANGE_DEFAULT
,
376 .activation_policy
= _ACTIVATION_POLICY_INVALID
,
383 .keep_configuration
= manager
->keep_configuration
,
385 .dhcp_duid
.type
= _DUID_TYPE_INVALID
,
387 .dhcp_use_ntp
= true,
388 .dhcp_routes_to_ntp
= true,
389 .dhcp_use_sip
= true,
390 .dhcp_use_captive_portal
= true,
391 .dhcp_use_dns
= true,
392 .dhcp_routes_to_dns
= true,
393 .dhcp_use_hostname
= true,
394 .dhcp_use_routes
= true,
395 .dhcp_use_gateway
= -1,
396 .dhcp_send_hostname
= true,
397 .dhcp_send_release
= true,
398 .dhcp_route_metric
= DHCP_ROUTE_METRIC
,
399 .dhcp_use_rapid_commit
= -1,
400 .dhcp_client_identifier
= _DHCP_CLIENT_ID_INVALID
,
401 .dhcp_route_table
= RT_TABLE_MAIN
,
402 .dhcp_ip_service_type
= -1,
403 .dhcp_broadcast
= -1,
404 .dhcp_ipv6_only_mode
= -1,
406 .dhcp6_use_address
= true,
407 .dhcp6_use_pd_prefix
= true,
408 .dhcp6_use_dns
= true,
409 .dhcp6_use_hostname
= true,
410 .dhcp6_use_ntp
= true,
411 .dhcp6_use_captive_portal
= true,
412 .dhcp6_use_rapid_commit
= true,
413 .dhcp6_send_hostname
= true,
414 .dhcp6_duid
.type
= _DUID_TYPE_INVALID
,
415 .dhcp6_client_start_mode
= _DHCP6_CLIENT_START_MODE_INVALID
,
416 .dhcp6_send_release
= true,
419 .dhcp_pd_announce
= true,
420 .dhcp_pd_assign
= true,
421 .dhcp_pd_manage_temporary_address
= true,
422 .dhcp_pd_subnet_id
= -1,
423 .dhcp_pd_route_metric
= DHCP6PD_ROUTE_METRIC
,
425 .dhcp_server_bind_to_interface
= true,
426 .dhcp_server_emit
[SD_DHCP_LEASE_DNS
].emit
= true,
427 .dhcp_server_emit
[SD_DHCP_LEASE_NTP
].emit
= true,
428 .dhcp_server_emit
[SD_DHCP_LEASE_SIP
].emit
= true,
429 .dhcp_server_emit_router
= true,
430 .dhcp_server_emit_timezone
= true,
431 .dhcp_server_rapid_commit
= true,
433 .router_lifetime_usec
= RADV_DEFAULT_ROUTER_LIFETIME_USEC
,
434 .router_dns_lifetime_usec
= RADV_DEFAULT_VALID_LIFETIME_USEC
,
435 .router_emit_dns
= true,
436 .router_emit_domains
= true,
442 .allow_port_to_be_root
= -1,
444 .multicast_flood
= -1,
445 .multicast_to_unicast
= -1,
446 .neighbor_suppression
= -1,
448 .bridge_proxy_arp
= -1,
449 .bridge_proxy_arp_wifi
= -1,
450 .priority
= LINK_BRIDGE_PORT_PRIORITY_INVALID
,
451 .multicast_router
= _MULTICAST_ROUTER_INVALID
,
453 .bridge_vlan_pvid
= BRIDGE_VLAN_KEEP_PVID
,
455 .lldp_mode
= LLDP_MODE_ROUTERS_ONLY
,
456 .lldp_multicast_mode
= _SD_LLDP_MULTICAST_MODE_INVALID
,
458 .dns_default_route
= -1,
459 .llmnr
= RESOLVE_SUPPORT_YES
,
460 .mdns
= RESOLVE_SUPPORT_NO
,
461 .dnssec_mode
= _DNSSEC_MODE_INVALID
,
462 .dns_over_tls_mode
= _DNS_OVER_TLS_MODE_INVALID
,
464 /* If LinkLocalAddressing= is not set, then set to ADDRESS_FAMILY_IPV6 later. */
465 .link_local
= _ADDRESS_FAMILY_INVALID
,
466 .ipv6ll_address_gen_mode
= _IPV6_LINK_LOCAL_ADDRESS_GEN_MODE_INVALID
,
468 .ipv4_accept_local
= -1,
469 .ipv4_route_localnet
= -1,
470 .ipv6_privacy_extensions
= _IPV6_PRIVACY_EXTENSIONS_INVALID
,
471 .ipv6_dad_transmits
= -1,
472 .ipv6_proxy_ndp
= -1,
474 .ipv4_rp_filter
= _IP_REVERSE_PATH_FILTER_INVALID
,
476 .ipv6_accept_ra
= -1,
477 .ipv6_accept_ra_use_dns
= true,
478 .ipv6_accept_ra_use_gateway
= true,
479 .ipv6_accept_ra_use_captive_portal
= true,
480 .ipv6_accept_ra_use_route_prefix
= true,
481 .ipv6_accept_ra_use_autonomous_prefix
= true,
482 .ipv6_accept_ra_use_onlink_prefix
= true,
483 .ipv6_accept_ra_use_mtu
= true,
484 .ipv6_accept_ra_use_hop_limit
= true,
485 .ipv6_accept_ra_use_icmp6_ratelimit
= true,
486 .ipv6_accept_ra_route_table
= RT_TABLE_MAIN
,
487 .ipv6_accept_ra_route_metric_high
= IPV6RA_ROUTE_METRIC_HIGH
,
488 .ipv6_accept_ra_route_metric_medium
= IPV6RA_ROUTE_METRIC_MEDIUM
,
489 .ipv6_accept_ra_route_metric_low
= IPV6RA_ROUTE_METRIC_LOW
,
490 .ipv6_accept_ra_start_dhcp6_client
= IPV6_ACCEPT_RA_START_DHCP6_CLIENT_YES
,
492 .can_termination
= -1,
494 .ipoib_mode
= _IP_OVER_INFINIBAND_MODE_INVALID
,
498 r
= config_parse_many(
499 STRV_MAKE_CONST(filename
), NETWORK_DIRS
, dropin_dirname
, /* root = */ NULL
,
507 "RoutingPolicyRule\0"
510 "DHCP\0" /* compat */
513 "DHCPv6PrefixDelegation\0" /* compat */
514 "DHCPPrefixDelegation\0"
516 "DHCPServerStaticLease\0"
518 "IPv6NDPProxyAddress\0"
524 "IPv6PrefixDelegation\0"
529 "TrafficControlQueueingDiscipline\0"
535 "DeficitRoundRobinScheduler\0"
536 "DeficitRoundRobinSchedulerClass\0"
537 "EnhancedTransmissionSelection\0"
539 "FairQueueingControlledDelay\0"
541 "GenericRandomEarlyDetection\0"
542 "HeavyHitterFilter\0"
543 "HierarchyTokenBucket\0"
544 "HierarchyTokenBucketClass\0"
550 "QuickFairQueueing\0"
551 "QuickFairQueueingClass\0"
552 "StochasticFairBlue\0"
553 "StochasticFairnessQueueing\0"
554 "TokenBucketFilter\0"
555 "TrivialLinkEqualizer\0",
556 config_item_perf_lookup
, network_network_gperf_lookup
,
559 &network
->stats_by_path
,
562 return r
; /* config_parse_many() logs internally. */
564 r
= network_add_ipv4ll_route(network
);
566 return log_warning_errno(r
, "%s: Failed to add IPv4LL route: %m", network
->filename
);
568 r
= network_add_default_route_on_device(network
);
570 return log_warning_errno(r
, "%s: Failed to add default route on device: %m",
573 r
= network_verify(network
);
575 return r
; /* network_verify() logs internally. */
577 r
= ordered_hashmap_ensure_put(networks
, &string_hash_ops
, network
->name
, network
);
579 return log_warning_errno(r
, "%s: Failed to store configuration into hashmap: %m", filename
);
585 int network_load(Manager
*manager
, OrderedHashmap
**networks
) {
586 _cleanup_strv_free_
char **files
= NULL
;
591 ordered_hashmap_clear_with_destructor(*networks
, network_unref
);
593 r
= conf_files_list_strv(&files
, ".network", NULL
, 0, NETWORK_DIRS
);
595 return log_error_errno(r
, "Failed to enumerate network files: %m");
597 STRV_FOREACH(f
, files
)
598 (void) network_load_one(manager
, networks
, *f
);
603 int network_reload(Manager
*manager
) {
604 OrderedHashmap
*new_networks
= NULL
;
610 r
= network_load(manager
, &new_networks
);
614 ORDERED_HASHMAP_FOREACH(n
, new_networks
) {
615 r
= network_get_by_name(manager
, n
->name
, &old
);
617 log_debug("Found new .network file: %s", n
->filename
);
621 if (!stats_by_path_equal(n
->stats_by_path
, old
->stats_by_path
)) {
622 log_debug("Found updated .network file: %s", n
->filename
);
626 r
= ordered_hashmap_replace(new_networks
, old
->name
, old
);
634 ordered_hashmap_free_with_destructor(manager
->networks
, network_unref
);
635 manager
->networks
= new_networks
;
637 return manager_build_dhcp_pd_subnet_ids(manager
);
640 ordered_hashmap_free_with_destructor(new_networks
, network_unref
);
645 int manager_build_dhcp_pd_subnet_ids(Manager
*manager
) {
651 set_clear(manager
->dhcp_pd_subnet_ids
);
653 ORDERED_HASHMAP_FOREACH(n
, manager
->networks
) {
660 if (n
->dhcp_pd_subnet_id
< 0)
663 r
= set_ensure_put(&manager
->dhcp_pd_subnet_ids
, &uint64_hash_ops
, &n
->dhcp_pd_subnet_id
);
671 static Network
*network_free(Network
*network
) {
676 free(network
->filename
);
677 free(network
->description
);
678 strv_free(network
->dropins
);
679 hashmap_free(network
->stats_by_path
);
682 net_match_clear(&network
->match
);
683 condition_free_list(network
->conditions
);
686 strv_free(network
->bind_carrier
);
689 strv_free(network
->ntp
);
692 for (unsigned i
= 0; i
< network
->n_dns
; i
++)
693 in_addr_full_free(network
->dns
[i
]);
695 ordered_set_free(network
->search_domains
);
696 ordered_set_free(network
->route_domains
);
697 set_free_free(network
->dnssec_negative_trust_anchors
);
700 free(network
->dhcp_server_relay_agent_circuit_id
);
701 free(network
->dhcp_server_relay_agent_remote_id
);
702 free(network
->dhcp_server_boot_server_name
);
703 free(network
->dhcp_server_boot_filename
);
704 free(network
->dhcp_server_timezone
);
705 free(network
->dhcp_server_uplink_name
);
706 for (sd_dhcp_lease_server_type_t t
= 0; t
< _SD_DHCP_LEASE_SERVER_TYPE_MAX
; t
++)
707 free(network
->dhcp_server_emit
[t
].addresses
);
708 ordered_hashmap_free(network
->dhcp_server_send_options
);
709 ordered_hashmap_free(network
->dhcp_server_send_vendor_options
);
712 free(network
->dhcp_vendor_class_identifier
);
713 free(network
->dhcp_mudurl
);
714 free(network
->dhcp_hostname
);
715 free(network
->dhcp_label
);
716 set_free(network
->dhcp_deny_listed_ip
);
717 set_free(network
->dhcp_allow_listed_ip
);
718 strv_free(network
->dhcp_user_class
);
719 set_free(network
->dhcp_request_options
);
720 ordered_hashmap_free(network
->dhcp_client_send_options
);
721 ordered_hashmap_free(network
->dhcp_client_send_vendor_options
);
722 free(network
->dhcp_netlabel
);
723 nft_set_context_clear(&network
->dhcp_nft_set_context
);
726 free(network
->dhcp6_mudurl
);
727 free(network
->dhcp6_hostname
);
728 strv_free(network
->dhcp6_user_class
);
729 strv_free(network
->dhcp6_vendor_class
);
730 set_free(network
->dhcp6_request_options
);
731 ordered_hashmap_free(network
->dhcp6_client_send_options
);
732 ordered_hashmap_free(network
->dhcp6_client_send_vendor_options
);
733 free(network
->dhcp6_netlabel
);
734 nft_set_context_clear(&network
->dhcp6_nft_set_context
);
737 free(network
->dhcp_pd_uplink_name
);
738 set_free(network
->dhcp_pd_tokens
);
739 free(network
->dhcp_pd_netlabel
);
740 nft_set_context_clear(&network
->dhcp_pd_nft_set_context
);
742 /* Router advertisement */
743 ordered_set_free(network
->router_search_domains
);
744 free(network
->router_dns
);
745 free(network
->router_uplink_name
);
748 set_free(network
->ndisc_deny_listed_router
);
749 set_free(network
->ndisc_allow_listed_router
);
750 set_free(network
->ndisc_deny_listed_prefix
);
751 set_free(network
->ndisc_allow_listed_prefix
);
752 set_free(network
->ndisc_deny_listed_route_prefix
);
753 set_free(network
->ndisc_allow_listed_route_prefix
);
754 set_free(network
->ndisc_tokens
);
755 free(network
->ndisc_netlabel
);
756 nft_set_context_clear(&network
->ndisc_nft_set_context
);
759 free(network
->lldp_mudurl
);
762 free(network
->batadv_name
);
763 free(network
->bridge_name
);
764 free(network
->bond_name
);
765 free(network
->vrf_name
);
766 hashmap_free_free_key(network
->stacked_netdev_names
);
767 netdev_unref(network
->bridge
);
768 netdev_unref(network
->bond
);
769 netdev_unref(network
->vrf
);
770 hashmap_free_with_destructor(network
->stacked_netdevs
, netdev_unref
);
773 set_free_free(network
->ipv6_proxy_ndp_addresses
);
774 ordered_hashmap_free_with_destructor(network
->addresses_by_section
, address_free
);
775 hashmap_free_with_destructor(network
->routes_by_section
, route_free
);
776 hashmap_free_with_destructor(network
->nexthops_by_section
, nexthop_free
);
777 hashmap_free_with_destructor(network
->bridge_fdb_entries_by_section
, bridge_fdb_free
);
778 hashmap_free_with_destructor(network
->bridge_mdb_entries_by_section
, bridge_mdb_free
);
779 ordered_hashmap_free_with_destructor(network
->neighbors_by_section
, neighbor_free
);
780 hashmap_free_with_destructor(network
->address_labels_by_section
, address_label_free
);
781 hashmap_free_with_destructor(network
->prefixes_by_section
, prefix_free
);
782 hashmap_free_with_destructor(network
->route_prefixes_by_section
, route_prefix_free
);
783 hashmap_free_with_destructor(network
->pref64_prefixes_by_section
, pref64_prefix_free
);
784 hashmap_free_with_destructor(network
->rules_by_section
, routing_policy_rule_free
);
785 hashmap_free_with_destructor(network
->dhcp_static_leases_by_section
, dhcp_static_lease_free
);
786 ordered_hashmap_free_with_destructor(network
->sr_iov_by_section
, sr_iov_free
);
787 hashmap_free_with_destructor(network
->qdiscs_by_section
, qdisc_free
);
788 hashmap_free_with_destructor(network
->tclasses_by_section
, tclass_free
);
790 return mfree(network
);
793 DEFINE_TRIVIAL_REF_UNREF_FUNC(Network
, network
, network_free
);
795 int network_get_by_name(Manager
*manager
, const char *name
, Network
**ret
) {
802 network
= ordered_hashmap_get(manager
->networks
, name
);
811 bool network_has_static_ipv6_configurations(Network
*network
) {
820 ORDERED_HASHMAP_FOREACH(address
, network
->addresses_by_section
)
821 if (address
->family
== AF_INET6
)
824 HASHMAP_FOREACH(route
, network
->routes_by_section
)
825 if (route
->family
== AF_INET6
)
828 HASHMAP_FOREACH(fdb
, network
->bridge_fdb_entries_by_section
)
829 if (fdb
->family
== AF_INET6
)
832 HASHMAP_FOREACH(mdb
, network
->bridge_mdb_entries_by_section
)
833 if (mdb
->family
== AF_INET6
)
836 ORDERED_HASHMAP_FOREACH(neighbor
, network
->neighbors_by_section
)
837 if (neighbor
->family
== AF_INET6
)
840 if (!hashmap_isempty(network
->address_labels_by_section
))
843 if (!hashmap_isempty(network
->prefixes_by_section
))
846 if (!hashmap_isempty(network
->route_prefixes_by_section
))
849 if (!hashmap_isempty(network
->pref64_prefixes_by_section
))
855 int config_parse_stacked_netdev(
857 const char *filename
,
860 unsigned section_line
,
867 _cleanup_free_
char *name
= NULL
;
868 NetDevKind kind
= ltype
;
869 Hashmap
**h
= ASSERT_PTR(data
);
885 _NETDEV_KIND_TUNNEL
));
887 if (!ifname_valid(rvalue
)) {
888 log_syntax(unit
, LOG_WARNING
, filename
, line
, 0,
889 "Invalid netdev name in %s=, ignoring assignment: %s", lvalue
, rvalue
);
893 name
= strdup(rvalue
);
897 r
= hashmap_ensure_put(h
, &string_hash_ops
, name
, INT_TO_PTR(kind
));
901 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
902 "Cannot add NetDev '%s' to network, ignoring assignment: %m", name
);
904 log_syntax(unit
, LOG_DEBUG
, filename
, line
, r
,
905 "NetDev '%s' specified twice, ignoring.", name
);
912 int config_parse_domains(
914 const char *filename
,
917 unsigned section_line
,
924 Network
*n
= ASSERT_PTR(userdata
);
931 if (isempty(rvalue
)) {
932 n
->search_domains
= ordered_set_free(n
->search_domains
);
933 n
->route_domains
= ordered_set_free(n
->route_domains
);
937 for (const char *p
= rvalue
;;) {
938 _cleanup_free_
char *w
= NULL
, *normalized
= NULL
;
942 r
= extract_first_word(&p
, &w
, NULL
, 0);
946 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
947 "Failed to extract search or route domain, ignoring: %s", rvalue
);
953 is_route
= w
[0] == '~';
954 domain
= is_route
? w
+ 1 : w
;
956 if (dns_name_is_root(domain
) || streq(domain
, "*")) {
957 /* If the root domain appears as is, or the special token "*" is found, we'll
958 * consider this as routing domain, unconditionally. */
960 domain
= "."; /* make sure we don't allow empty strings, thus write the root
963 r
= dns_name_normalize(domain
, 0, &normalized
);
965 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
966 "'%s' is not a valid domain name, ignoring.", domain
);
972 if (is_localhost(domain
)) {
973 log_syntax(unit
, LOG_WARNING
, filename
, line
, 0,
974 "'localhost' domain may not be configured as search or route domain, ignoring assignment: %s",
980 OrderedSet
**set
= is_route
? &n
->route_domains
: &n
->search_domains
;
981 r
= ordered_set_put_strdup(set
, domain
);
989 int config_parse_timezone(
991 const char *filename
,
994 unsigned section_line
,
1001 char **tz
= ASSERT_PTR(data
);
1008 if (isempty(rvalue
)) {
1013 r
= verify_timezone(rvalue
, LOG_WARNING
);
1015 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
1016 "Timezone is not valid, ignoring assignment: %s", rvalue
);
1020 return free_and_strdup_warn(tz
, rvalue
);
1023 int config_parse_dns(
1025 const char *filename
,
1027 const char *section
,
1028 unsigned section_line
,
1035 Network
*n
= ASSERT_PTR(userdata
);
1042 if (isempty(rvalue
)) {
1043 for (unsigned i
= 0; i
< n
->n_dns
; i
++)
1044 in_addr_full_free(n
->dns
[i
]);
1045 n
->dns
= mfree(n
->dns
);
1050 for (const char *p
= rvalue
;;) {
1051 _cleanup_(in_addr_full_freep
) struct in_addr_full
*dns
= NULL
;
1052 _cleanup_free_
char *w
= NULL
;
1053 struct in_addr_full
**m
;
1055 r
= extract_first_word(&p
, &w
, NULL
, 0);
1059 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
1060 "Invalid syntax, ignoring: %s", rvalue
);
1066 r
= in_addr_full_new_from_string(w
, &dns
);
1068 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
1069 "Failed to parse dns server address, ignoring: %s", w
);
1073 if (IN_SET(dns
->port
, 53, 853))
1076 m
= reallocarray(n
->dns
, n
->n_dns
+ 1, sizeof(struct in_addr_full
*));
1080 m
[n
->n_dns
++] = TAKE_PTR(dns
);
1085 int config_parse_dnssec_negative_trust_anchors(
1087 const char *filename
,
1089 const char *section
,
1090 unsigned section_line
,
1097 Set
**nta
= ASSERT_PTR(data
);
1104 if (isempty(rvalue
)) {
1105 *nta
= set_free_free(*nta
);
1109 for (const char *p
= rvalue
;;) {
1110 _cleanup_free_
char *w
= NULL
;
1112 r
= extract_first_word(&p
, &w
, NULL
, 0);
1116 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
1117 "Failed to extract negative trust anchor domain, ignoring: %s", rvalue
);
1123 r
= dns_name_is_valid(w
);
1125 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
1126 "%s is not a valid domain name, ignoring.", w
);
1130 r
= set_ensure_consume(nta
, &dns_name_hash_ops
, TAKE_PTR(w
));
1136 int config_parse_ntp(
1138 const char *filename
,
1140 const char *section
,
1141 unsigned section_line
,
1148 char ***l
= ASSERT_PTR(data
);
1155 if (isempty(rvalue
)) {
1160 for (const char *p
= rvalue
;;) {
1161 _cleanup_free_
char *w
= NULL
;
1163 r
= extract_first_word(&p
, &w
, NULL
, 0);
1167 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
1168 "Failed to extract NTP server name, ignoring: %s", rvalue
);
1174 r
= dns_name_is_valid_or_address(w
);
1176 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
1177 "%s is not a valid domain name or IP address, ignoring.", w
);
1181 if (strv_length(*l
) > MAX_NTP_SERVERS
) {
1182 log_syntax(unit
, LOG_WARNING
, filename
, line
, 0,
1183 "More than %u NTP servers specified, ignoring \"%s\" and any subsequent entries.",
1184 MAX_NTP_SERVERS
, w
);
1188 r
= strv_consume(l
, TAKE_PTR(w
));
1194 int config_parse_required_for_online(
1196 const char *filename
,
1198 const char *section
,
1199 unsigned section_line
,
1206 Network
*network
= ASSERT_PTR(userdata
);
1207 LinkOperationalStateRange range
;
1208 bool required
= true;
1215 if (isempty(rvalue
)) {
1216 network
->required_for_online
= -1;
1217 network
->required_operstate_for_online
= LINK_OPERSTATE_RANGE_DEFAULT
;
1221 r
= parse_operational_state_range(rvalue
, &range
);
1223 r
= parse_boolean(rvalue
);
1225 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
1226 "Failed to parse %s= setting, ignoring assignment: %s",
1232 range
= LINK_OPERSTATE_RANGE_DEFAULT
;
1235 network
->required_for_online
= required
;
1236 network
->required_operstate_for_online
= range
;
1241 int config_parse_link_group(
1243 const char *filename
,
1245 const char *section
,
1246 unsigned section_line
,
1253 Network
*network
= ASSERT_PTR(userdata
);
1261 if (isempty(rvalue
)) {
1262 network
->group
= -1;
1266 r
= safe_atoi32(rvalue
, &group
);
1268 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
1269 "Failed to parse Group=, ignoring assignment: %s", rvalue
);
1274 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
1275 "Value of Group= must be in the range 0…2147483647, ignoring assignment: %s", rvalue
);
1279 network
->group
= group
;
1283 int config_parse_ignore_carrier_loss(
1285 const char *filename
,
1287 const char *section
,
1288 unsigned section_line
,
1295 Network
*network
= ASSERT_PTR(userdata
);
1303 if (isempty(rvalue
)) {
1304 network
->ignore_carrier_loss_set
= false;
1308 r
= parse_boolean(rvalue
);
1310 network
->ignore_carrier_loss_set
= true;
1311 network
->ignore_carrier_loss_usec
= r
> 0 ? USEC_INFINITY
: 0;
1315 r
= parse_sec(rvalue
, &usec
);
1317 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
1318 "Failed to parse %s=, ignoring assignment: %s", lvalue
, rvalue
);
1322 network
->ignore_carrier_loss_set
= true;
1323 network
->ignore_carrier_loss_usec
= usec
;
1327 DEFINE_CONFIG_PARSE_ENUM(config_parse_required_family_for_online
, link_required_address_family
, AddressFamily
,
1328 "Failed to parse RequiredFamilyForOnline= setting");
1330 DEFINE_CONFIG_PARSE_ENUM(config_parse_keep_configuration
, keep_configuration
, KeepConfiguration
,
1331 "Failed to parse KeepConfiguration= setting");
1333 static const char* const keep_configuration_table
[_KEEP_CONFIGURATION_MAX
] = {
1334 [KEEP_CONFIGURATION_NO
] = "no",
1335 [KEEP_CONFIGURATION_DHCP_ON_STOP
] = "dhcp-on-stop",
1336 [KEEP_CONFIGURATION_DHCP
] = "dhcp",
1337 [KEEP_CONFIGURATION_STATIC
] = "static",
1338 [KEEP_CONFIGURATION_YES
] = "yes",
1341 DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(keep_configuration
, KeepConfiguration
, KEEP_CONFIGURATION_YES
);
1343 static const char* const activation_policy_table
[_ACTIVATION_POLICY_MAX
] = {
1344 [ACTIVATION_POLICY_UP
] = "up",
1345 [ACTIVATION_POLICY_ALWAYS_UP
] = "always-up",
1346 [ACTIVATION_POLICY_MANUAL
] = "manual",
1347 [ACTIVATION_POLICY_ALWAYS_DOWN
] = "always-down",
1348 [ACTIVATION_POLICY_DOWN
] = "down",
1349 [ACTIVATION_POLICY_BOUND
] = "bound",
1352 DEFINE_STRING_TABLE_LOOKUP(activation_policy
, ActivationPolicy
);
1353 DEFINE_CONFIG_PARSE_ENUM(config_parse_activation_policy
, activation_policy
, ActivationPolicy
, "Failed to parse activation policy");