1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
5 #include "alloc-util.h"
7 #include "conf-files.h"
8 #include "conf-parser.h"
9 #include "in-addr-util.h"
10 #include "net-condition.h"
11 #include "netdev/macvlan.h"
12 #include "netif-sriov.h"
13 #include "network-util.h"
14 #include "networkd-address.h"
15 #include "networkd-address-label.h"
16 #include "networkd-bridge-fdb.h"
17 #include "networkd-bridge-mdb.h"
18 #include "networkd-dhcp-common.h"
19 #include "networkd-dhcp-server-static-lease.h"
20 #include "networkd-ipv6-proxy-ndp.h"
21 #include "networkd-manager.h"
22 #include "networkd-ndisc.h"
23 #include "networkd-neighbor.h"
24 #include "networkd-network.h"
25 #include "networkd-nexthop.h"
26 #include "networkd-radv.h"
27 #include "networkd-route.h"
28 #include "networkd-routing-policy-rule.h"
29 #include "ordered-set.h"
30 #include "parse-util.h"
31 #include "path-util.h"
33 #include "radv-internal.h"
35 #include "socket-util.h"
36 #include "stat-util.h"
37 #include "string-table.h"
38 #include "string-util.h"
42 DEFINE_PRIVATE_HASH_OPS_WITH_VALUE_DESTRUCTOR(
44 char, string_hash_func
, string_compare_func
,
45 Network
, network_unref
);
47 DEFINE_PRIVATE_HASH_OPS_WITH_VALUE_DESTRUCTOR(
48 stacked_netdevs_hash_ops
,
49 char, string_hash_func
, string_compare_func
,
50 NetDev
, netdev_unref
);
52 static int network_resolve_netdev_one(Network
*network
, const char *name
, NetDevKind kind
, NetDev
**ret
) {
53 const char *kind_string
;
57 /* For test-networkd-conf, the check must be earlier than the assertions. */
62 assert(network
->manager
);
63 assert(network
->filename
);
66 if (kind
== _NETDEV_KIND_TUNNEL
)
67 kind_string
= "tunnel";
69 kind_string
= netdev_kind_to_string(kind
);
71 return log_warning_errno(SYNTHETIC_ERRNO(EINVAL
),
72 "%s: Invalid NetDev kind of %s, ignoring assignment.",
73 network
->filename
, name
);
76 r
= netdev_get(network
->manager
, name
, &netdev
);
78 return log_warning_errno(r
, "%s: %s NetDev could not be found, ignoring assignment.",
79 network
->filename
, name
);
81 if (netdev
->kind
!= kind
&& !(kind
== _NETDEV_KIND_TUNNEL
&&
87 NETDEV_KIND_IP6GRETAP
,
93 return log_warning_errno(SYNTHETIC_ERRNO(EINVAL
),
94 "%s: NetDev %s is not a %s, ignoring assignment",
95 network
->filename
, name
, kind_string
);
97 *ret
= netdev_ref(netdev
);
101 static int network_resolve_stacked_netdevs(Network
*network
) {
107 HASHMAP_FOREACH_KEY(kind
, name
, network
->stacked_netdev_names
) {
108 _cleanup_(netdev_unrefp
) NetDev
*netdev
= NULL
;
110 if (network_resolve_netdev_one(network
, name
, PTR_TO_INT(kind
), &netdev
) <= 0)
113 r
= hashmap_ensure_put(&network
->stacked_netdevs
, &stacked_netdevs_hash_ops
, netdev
->ifname
, netdev
);
117 log_warning_errno(r
, "%s: Failed to add NetDev '%s' to network, ignoring: %m",
118 network
->filename
, (const char *) name
);
126 int network_verify(Network
*network
) {
130 assert(network
->manager
);
131 assert(network
->filename
);
133 if (net_match_is_empty(&network
->match
) && !network
->conditions
)
134 return log_warning_errno(SYNTHETIC_ERRNO(EINVAL
),
135 "%s: No valid settings found in the [Match] section, ignoring file. "
136 "To match all interfaces, add Name=* in the [Match] section.",
139 /* skip out early if configuration does not match the environment */
140 if (!condition_test_list(network
->conditions
, environ
, NULL
, NULL
, NULL
))
141 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL
),
142 "%s: Conditions in the file do not match the system environment, skipping.",
145 if (network
->keep_master
) {
146 if (network
->batadv_name
)
147 log_warning("%s: BatmanAdvanced= set with KeepMaster= enabled, ignoring BatmanAdvanced=.",
149 if (network
->bond_name
)
150 log_warning("%s: Bond= set with KeepMaster= enabled, ignoring Bond=.",
152 if (network
->bridge_name
)
153 log_warning("%s: Bridge= set with KeepMaster= enabled, ignoring Bridge=.",
155 if (network
->vrf_name
)
156 log_warning("%s: VRF= set with KeepMaster= enabled, ignoring VRF=.",
159 network
->batadv_name
= mfree(network
->batadv_name
);
160 network
->bond_name
= mfree(network
->bond_name
);
161 network
->bridge_name
= mfree(network
->bridge_name
);
162 network
->vrf_name
= mfree(network
->vrf_name
);
165 (void) network_resolve_netdev_one(network
, network
->batadv_name
, NETDEV_KIND_BATADV
, &network
->batadv
);
166 (void) network_resolve_netdev_one(network
, network
->bond_name
, NETDEV_KIND_BOND
, &network
->bond
);
167 (void) network_resolve_netdev_one(network
, network
->bridge_name
, NETDEV_KIND_BRIDGE
, &network
->bridge
);
168 (void) network_resolve_netdev_one(network
, network
->vrf_name
, NETDEV_KIND_VRF
, &network
->vrf
);
169 r
= network_resolve_stacked_netdevs(network
);
173 /* Free unnecessary entries. */
174 network
->batadv_name
= mfree(network
->batadv_name
);
175 network
->bond_name
= mfree(network
->bond_name
);
176 network
->bridge_name
= mfree(network
->bridge_name
);
177 network
->vrf_name
= mfree(network
->vrf_name
);
178 network
->stacked_netdev_names
= hashmap_free(network
->stacked_netdev_names
);
181 /* Bonding slave does not support addressing. */
182 if (network
->link_local
>= 0 && network
->link_local
!= ADDRESS_FAMILY_NO
) {
183 log_warning("%s: Cannot enable LinkLocalAddressing= when Bond= is specified, disabling LinkLocalAddressing=.",
185 network
->link_local
= ADDRESS_FAMILY_NO
;
187 if (!ordered_hashmap_isempty(network
->addresses_by_section
))
188 log_warning("%s: Cannot set addresses when Bond= is specified, ignoring addresses.",
190 if (!hashmap_isempty(network
->routes_by_section
))
191 log_warning("%s: Cannot set routes when Bond= is specified, ignoring routes.",
194 network
->addresses_by_section
= ordered_hashmap_free(network
->addresses_by_section
);
195 network
->routes_by_section
= hashmap_free(network
->routes_by_section
);
198 if (network
->link_local
< 0) {
199 network
->link_local
= ADDRESS_FAMILY_IPV6
;
201 if (network
->keep_master
|| network
->bridge
)
202 network
->link_local
= ADDRESS_FAMILY_NO
;
206 HASHMAP_FOREACH(netdev
, network
->stacked_netdevs
) {
209 if (netdev
->kind
== NETDEV_KIND_MACVLAN
)
211 else if (netdev
->kind
== NETDEV_KIND_MACVTAP
)
216 if (m
->mode
== NETDEV_MACVLAN_MODE_PASSTHRU
)
217 network
->link_local
= ADDRESS_FAMILY_NO
;
219 /* There won't be a passthru MACVLAN/MACVTAP if there's already one in another mode */
225 if (network
->ipv6ll_address_gen_mode
== IPV6_LINK_LOCAL_ADDRESSS_GEN_MODE_NONE
)
226 SET_FLAG(network
->link_local
, ADDRESS_FAMILY_IPV6
, false);
228 if (in6_addr_is_set(&network
->ipv6ll_stable_secret
) &&
229 network
->ipv6ll_address_gen_mode
< 0)
230 network
->ipv6ll_address_gen_mode
= IPV6_LINK_LOCAL_ADDRESSS_GEN_MODE_STABLE_PRIVACY
;
232 network_adjust_ipv6_proxy_ndp(network
);
233 network_adjust_ndisc(network
);
234 network_adjust_dhcp(network
);
235 network_adjust_radv(network
);
236 network_adjust_bridge_vlan(network
);
238 if (network
->mtu
> 0 && network
->dhcp_use_mtu
) {
239 log_warning("%s: MTUBytes= in [Link] section and UseMTU= in [DHCP] section are set. "
240 "Disabling UseMTU=.", network
->filename
);
241 network
->dhcp_use_mtu
= false;
244 if (network
->dhcp_critical
>= 0) {
245 if (network
->keep_configuration
>= 0) {
246 if (network
->manager
->keep_configuration
< 0)
247 log_warning("%s: Both KeepConfiguration= and deprecated CriticalConnection= are set. "
248 "Ignoring CriticalConnection=.", network
->filename
);
249 } else if (network
->dhcp_critical
)
250 /* CriticalConnection=yes also preserve foreign static configurations. */
251 network
->keep_configuration
= KEEP_CONFIGURATION_YES
;
253 network
->keep_configuration
= KEEP_CONFIGURATION_NO
;
256 if (!strv_isempty(network
->bind_carrier
)) {
257 if (!IN_SET(network
->activation_policy
, _ACTIVATION_POLICY_INVALID
, ACTIVATION_POLICY_BOUND
))
258 log_warning("%s: ActivationPolicy=bound is required with BindCarrier=. "
259 "Setting ActivationPolicy=bound.", network
->filename
);
260 network
->activation_policy
= ACTIVATION_POLICY_BOUND
;
261 } else if (network
->activation_policy
== ACTIVATION_POLICY_BOUND
) {
262 log_warning("%s: ActivationPolicy=bound requires BindCarrier=. "
263 "Ignoring ActivationPolicy=bound.", network
->filename
);
264 network
->activation_policy
= ACTIVATION_POLICY_UP
;
267 if (network
->activation_policy
== _ACTIVATION_POLICY_INVALID
)
268 network
->activation_policy
= ACTIVATION_POLICY_UP
;
270 if (network
->activation_policy
== ACTIVATION_POLICY_ALWAYS_UP
) {
271 if (network
->ignore_carrier_loss_set
&& network
->ignore_carrier_loss_usec
< USEC_INFINITY
)
272 log_warning("%s: IgnoreCarrierLoss=no or finite timespan conflicts with ActivationPolicy=always-up. "
273 "Setting IgnoreCarrierLoss=yes.", network
->filename
);
274 network
->ignore_carrier_loss_set
= true;
275 network
->ignore_carrier_loss_usec
= USEC_INFINITY
;
278 if (!network
->ignore_carrier_loss_set
) /* Set implied default. */
279 network
->ignore_carrier_loss_usec
= network
->configure_without_carrier
? USEC_INFINITY
: 0;
281 if (IN_SET(network
->activation_policy
, ACTIVATION_POLICY_DOWN
, ACTIVATION_POLICY_ALWAYS_DOWN
, ACTIVATION_POLICY_MANUAL
)) {
282 if (network
->required_for_online
< 0 ||
283 (network
->required_for_online
== true && network
->activation_policy
== ACTIVATION_POLICY_ALWAYS_DOWN
)) {
284 log_debug("%s: Setting RequiredForOnline=no because ActivationPolicy=%s.", network
->filename
,
285 activation_policy_to_string(network
->activation_policy
));
286 network
->required_for_online
= false;
287 } else if (network
->required_for_online
== true)
288 log_warning("%s: RequiredForOnline=yes and ActivationPolicy=%s, "
289 "this may cause a delay at boot.", network
->filename
,
290 activation_policy_to_string(network
->activation_policy
));
293 if (network
->required_for_online
< 0)
294 network
->required_for_online
= true;
296 if (network
->keep_configuration
< 0)
297 network
->keep_configuration
= KEEP_CONFIGURATION_NO
;
299 r
= network_drop_invalid_addresses(network
);
301 return r
; /* network_drop_invalid_addresses() logs internally. */
302 network_drop_invalid_routes(network
);
303 r
= network_drop_invalid_nexthops(network
);
306 network_drop_invalid_bridge_fdb_entries(network
);
307 network_drop_invalid_bridge_mdb_entries(network
);
308 r
= network_drop_invalid_neighbors(network
);
311 network_drop_invalid_address_labels(network
);
312 network_drop_invalid_routing_policy_rules(network
);
313 network_drop_invalid_qdisc(network
);
314 network_drop_invalid_tclass(network
);
315 r
= sr_iov_drop_invalid_sections(UINT32_MAX
, network
->sr_iov_by_section
);
317 return r
; /* sr_iov_drop_invalid_sections() logs internally. */
318 network_drop_invalid_static_leases(network
);
323 int network_load_one(Manager
*manager
, OrderedHashmap
**networks
, const char *filename
) {
324 _cleanup_free_
char *fname
= NULL
, *name
= NULL
;
325 _cleanup_(network_unrefp
) Network
*network
= NULL
;
326 const char *dropin_dirname
;
333 r
= null_or_empty_path(filename
);
335 return log_warning_errno(r
, "Failed to check if \"%s\" is empty: %m", filename
);
337 log_debug("Skipping empty file: %s", filename
);
341 fname
= strdup(filename
);
345 r
= path_extract_filename(filename
, &name
);
347 return log_warning_errno(r
, "Failed to extract file name of \"%s\": %m", filename
);
349 d
= strrchr(name
, '.');
351 return log_warning_errno(SYNTHETIC_ERRNO(EINVAL
), "Invalid file name: %s", filename
);
355 dropin_dirname
= strjoina(name
, ".network.d");
357 network
= new(Network
, 1);
361 *network
= (Network
) {
362 .filename
= TAKE_PTR(fname
),
363 .name
= TAKE_PTR(name
),
368 .required_for_online
= -1,
369 .required_operstate_for_online
= LINK_OPERSTATE_RANGE_INVALID
,
370 .activation_policy
= _ACTIVATION_POLICY_INVALID
,
377 .keep_configuration
= manager
->keep_configuration
,
379 .use_domains
= _USE_DOMAINS_INVALID
,
381 .compat_dhcp_use_domains
= _USE_DOMAINS_INVALID
,
382 .compat_dhcp_use_dns
= -1,
383 .compat_dhcp_use_ntp
= -1,
385 .dhcp_duid
.type
= _DUID_TYPE_INVALID
,
388 .dhcp_routes_to_ntp
= true,
389 .dhcp_use_sip
= true,
390 .dhcp_use_captive_portal
= true,
393 .dhcp_routes_to_dns
= true,
394 .dhcp_use_domains
= _USE_DOMAINS_INVALID
,
395 .dhcp_use_hostname
= true,
396 .dhcp_use_routes
= true,
397 .dhcp_use_gateway
= -1,
398 .dhcp_send_hostname
= true,
399 .dhcp_send_release
= true,
400 .dhcp_route_metric
= DHCP_ROUTE_METRIC
,
401 .dhcp_use_rapid_commit
= -1,
402 .dhcp_client_identifier
= _DHCP_CLIENT_ID_INVALID
,
403 .dhcp_route_table
= RT_TABLE_MAIN
,
404 .dhcp_ip_service_type
= -1,
405 .dhcp_broadcast
= -1,
406 .dhcp_ipv6_only_mode
= -1,
407 .dhcp_6rd_prefix_route_type
= RTN_UNREACHABLE
,
409 .dhcp6_use_address
= true,
410 .dhcp6_use_pd_prefix
= true,
413 .dhcp6_use_domains
= _USE_DOMAINS_INVALID
,
414 .dhcp6_use_hostname
= true,
416 .dhcp6_use_captive_portal
= true,
417 .dhcp6_use_rapid_commit
= true,
418 .dhcp6_send_hostname
= true,
419 .dhcp6_duid
.type
= _DUID_TYPE_INVALID
,
420 .dhcp6_client_start_mode
= _DHCP6_CLIENT_START_MODE_INVALID
,
421 .dhcp6_send_release
= true,
422 .dhcp6_pd_prefix_route_type
= RTN_UNREACHABLE
,
425 .dhcp_pd_announce
= true,
426 .dhcp_pd_assign
= true,
427 .dhcp_pd_manage_temporary_address
= true,
428 .dhcp_pd_subnet_id
= -1,
429 .dhcp_pd_route_metric
= DHCP6PD_ROUTE_METRIC
,
431 .dhcp_server_bind_to_interface
= true,
432 .dhcp_server_emit
[SD_DHCP_LEASE_DNS
].emit
= true,
433 .dhcp_server_emit
[SD_DHCP_LEASE_NTP
].emit
= true,
434 .dhcp_server_emit
[SD_DHCP_LEASE_SIP
].emit
= true,
435 .dhcp_server_emit_router
= true,
436 .dhcp_server_emit_timezone
= true,
437 .dhcp_server_rapid_commit
= true,
438 .dhcp_server_persist_leases
= _DHCP_SERVER_PERSIST_LEASES_INVALID
,
440 .router_lifetime_usec
= RADV_DEFAULT_ROUTER_LIFETIME_USEC
,
441 .router_dns_lifetime_usec
= RADV_DEFAULT_VALID_LIFETIME_USEC
,
442 .router_emit_dns
= true,
443 .router_emit_domains
= true,
449 .allow_port_to_be_root
= -1,
451 .multicast_flood
= -1,
452 .multicast_to_unicast
= -1,
453 .neighbor_suppression
= -1,
455 .bridge_proxy_arp
= -1,
456 .bridge_proxy_arp_wifi
= -1,
457 .priority
= LINK_BRIDGE_PORT_PRIORITY_INVALID
,
458 .multicast_router
= _MULTICAST_ROUTER_INVALID
,
460 .bridge_mac_authentication_bypass
= -1,
461 .bridge_vlan_tunnel
= -1,
463 .bridge_vlan_pvid
= BRIDGE_VLAN_KEEP_PVID
,
465 .lldp_mode
= LLDP_MODE_ROUTERS_ONLY
,
466 .lldp_multicast_mode
= _SD_LLDP_MULTICAST_MODE_INVALID
,
468 .dns_default_route
= -1,
469 .llmnr
= RESOLVE_SUPPORT_YES
,
470 .mdns
= RESOLVE_SUPPORT_NO
,
471 .dnssec_mode
= _DNSSEC_MODE_INVALID
,
472 .dns_over_tls_mode
= _DNS_OVER_TLS_MODE_INVALID
,
474 /* If LinkLocalAddressing= is not set, then set to ADDRESS_FAMILY_IPV6 later. */
475 .link_local
= _ADDRESS_FAMILY_INVALID
,
476 .ipv6ll_address_gen_mode
= _IPV6_LINK_LOCAL_ADDRESS_GEN_MODE_INVALID
,
478 .ip_forwarding
= { -1, -1, },
479 .ipv4_accept_local
= -1,
480 .ipv4_route_localnet
= -1,
481 .ipv6_privacy_extensions
= _IPV6_PRIVACY_EXTENSIONS_INVALID
,
482 .ipv6_dad_transmits
= -1,
483 .ipv6_proxy_ndp
= -1,
485 .proxy_arp_pvlan
= -1,
486 .ipv4_rp_filter
= _IP_REVERSE_PATH_FILTER_INVALID
,
487 .ipv4_force_igmp_version
= _IPV4_FORCE_IGMP_VERSION_INVALID
,
491 .ndisc_use_redirect
= true,
494 .ndisc_use_gateway
= true,
495 .ndisc_use_captive_portal
= true,
496 .ndisc_use_route_prefix
= true,
497 .ndisc_use_autonomous_prefix
= true,
498 .ndisc_use_onlink_prefix
= true,
499 .ndisc_use_mtu
= true,
500 .ndisc_use_hop_limit
= true,
501 .ndisc_use_reachable_time
= true,
502 .ndisc_use_retransmission_time
= true,
503 .ndisc_use_domains
= _USE_DOMAINS_INVALID
,
504 .ndisc_route_table
= RT_TABLE_MAIN
,
505 .ndisc_route_metric_high
= IPV6RA_ROUTE_METRIC_HIGH
,
506 .ndisc_route_metric_medium
= IPV6RA_ROUTE_METRIC_MEDIUM
,
507 .ndisc_route_metric_low
= IPV6RA_ROUTE_METRIC_LOW
,
508 .ndisc_start_dhcp6_client
= IPV6_ACCEPT_RA_START_DHCP6_CLIENT_YES
,
510 .can_termination
= -1,
512 .ipoib_mode
= _IP_OVER_INFINIBAND_MODE_INVALID
,
516 r
= config_parse_many(
517 STRV_MAKE_CONST(filename
), NETWORK_DIRS
, dropin_dirname
, /* root = */ NULL
,
525 "RoutingPolicyRule\0"
528 "DHCP\0" /* compat */
531 "DHCPv6PrefixDelegation\0" /* compat */
532 "DHCPPrefixDelegation\0"
534 "DHCPServerStaticLease\0"
536 "IPv6NDPProxyAddress\0"
542 "IPv6PrefixDelegation\0"
547 "TrafficControlQueueingDiscipline\0"
553 "DeficitRoundRobinScheduler\0"
554 "DeficitRoundRobinSchedulerClass\0"
555 "EnhancedTransmissionSelection\0"
557 "FairQueueingControlledDelay\0"
559 "GenericRandomEarlyDetection\0"
560 "HeavyHitterFilter\0"
561 "HierarchyTokenBucket\0"
562 "HierarchyTokenBucketClass\0"
563 "ClassfulMultiQueueing\0"
564 "BandMultiQueueing\0"
570 "QuickFairQueueing\0"
571 "QuickFairQueueingClass\0"
572 "StochasticFairBlue\0"
573 "StochasticFairnessQueueing\0"
574 "TokenBucketFilter\0"
575 "TrivialLinkEqualizer\0",
576 config_item_perf_lookup
, network_network_gperf_lookup
,
579 &network
->stats_by_path
,
582 return r
; /* config_parse_many() logs internally. */
584 r
= network_add_ipv4ll_route(network
);
586 return log_warning_errno(r
, "%s: Failed to add IPv4LL route: %m", network
->filename
);
588 r
= network_add_default_route_on_device(network
);
590 return log_warning_errno(r
, "%s: Failed to add default route on device: %m",
593 r
= network_verify(network
);
595 return r
; /* network_verify() logs internally. */
597 r
= ordered_hashmap_ensure_put(networks
, &network_hash_ops
, network
->name
, network
);
599 return log_warning_errno(r
, "%s: Failed to store configuration into hashmap: %m", filename
);
602 log_syntax(/* unit = */ NULL
, LOG_DEBUG
, filename
, /* config_line = */ 0, /* error = */ 0, "Successfully loaded.");
606 int network_load(Manager
*manager
, OrderedHashmap
**ret
) {
607 _cleanup_strv_free_
char **files
= NULL
;
608 OrderedHashmap
*networks
= NULL
;
614 r
= conf_files_list_strv(&files
, ".network", NULL
, 0, NETWORK_DIRS
);
616 return log_error_errno(r
, "Failed to enumerate network files: %m");
618 STRV_FOREACH(f
, files
)
619 (void) network_load_one(manager
, &networks
, *f
);
621 *ret
= TAKE_PTR(networks
);
625 static bool network_netdev_equal(Network
*a
, Network
*b
) {
629 if (a
->batadv
!= b
->batadv
||
630 a
->bridge
!= b
->bridge
||
631 a
->bond
!= b
->bond
||
636 if (hashmap_size(a
->stacked_netdevs
) != hashmap_size(b
->stacked_netdevs
))
640 HASHMAP_FOREACH(n
, a
->stacked_netdevs
)
641 if (hashmap_get(b
->stacked_netdevs
, n
->ifname
) != n
)
647 int network_reload(Manager
*manager
) {
648 _cleanup_ordered_hashmap_free_ OrderedHashmap
*new_networks
= NULL
;
654 r
= network_load(manager
, &new_networks
);
658 ORDERED_HASHMAP_FOREACH(n
, new_networks
) {
659 r
= network_get_by_name(manager
, n
->name
, &old
);
661 log_debug("%s: Found new .network file.", n
->filename
);
665 if (!stats_by_path_equal(n
->stats_by_path
, old
->stats_by_path
)) {
666 log_debug("%s: Found updated .network file.", n
->filename
);
670 if (!network_netdev_equal(n
, old
)) {
671 log_debug("%s: Detected update of referenced .netdev file(s).", n
->filename
);
675 /* Nothing updated, use the existing Network object, and drop the new one. */
676 r
= ordered_hashmap_replace(new_networks
, old
->name
, old
);
684 ordered_hashmap_free_and_replace(manager
->networks
, new_networks
);
686 r
= manager_build_dhcp_pd_subnet_ids(manager
);
690 r
= manager_build_nexthop_ids(manager
);
697 int manager_build_dhcp_pd_subnet_ids(Manager
*manager
) {
703 set_clear(manager
->dhcp_pd_subnet_ids
);
705 ORDERED_HASHMAP_FOREACH(n
, manager
->networks
) {
712 if (n
->dhcp_pd_subnet_id
< 0)
715 r
= set_ensure_put(&manager
->dhcp_pd_subnet_ids
, &uint64_hash_ops
, &n
->dhcp_pd_subnet_id
);
723 static Network
*network_free(Network
*network
) {
728 free(network
->filename
);
729 free(network
->description
);
730 strv_free(network
->dropins
);
731 hashmap_free(network
->stats_by_path
);
734 net_match_clear(&network
->match
);
735 condition_free_list(network
->conditions
);
738 strv_free(network
->bind_carrier
);
741 strv_free(network
->ntp
);
744 for (unsigned i
= 0; i
< network
->n_dns
; i
++)
745 in_addr_full_free(network
->dns
[i
]);
747 ordered_set_free(network
->search_domains
);
748 ordered_set_free(network
->route_domains
);
749 set_free(network
->dnssec_negative_trust_anchors
);
752 free(network
->dhcp_server_relay_agent_circuit_id
);
753 free(network
->dhcp_server_relay_agent_remote_id
);
754 free(network
->dhcp_server_boot_server_name
);
755 free(network
->dhcp_server_boot_filename
);
756 free(network
->dhcp_server_timezone
);
757 free(network
->dhcp_server_uplink_name
);
758 for (sd_dhcp_lease_server_type_t t
= 0; t
< _SD_DHCP_LEASE_SERVER_TYPE_MAX
; t
++)
759 free(network
->dhcp_server_emit
[t
].addresses
);
760 ordered_hashmap_free(network
->dhcp_server_send_options
);
761 ordered_hashmap_free(network
->dhcp_server_send_vendor_options
);
764 free(network
->dhcp_vendor_class_identifier
);
765 free(network
->dhcp_mudurl
);
766 free(network
->dhcp_hostname
);
767 free(network
->dhcp_label
);
768 set_free(network
->dhcp_deny_listed_ip
);
769 set_free(network
->dhcp_allow_listed_ip
);
770 strv_free(network
->dhcp_user_class
);
771 set_free(network
->dhcp_request_options
);
772 ordered_hashmap_free(network
->dhcp_client_send_options
);
773 ordered_hashmap_free(network
->dhcp_client_send_vendor_options
);
774 free(network
->dhcp_netlabel
);
775 nft_set_context_clear(&network
->dhcp_nft_set_context
);
778 free(network
->dhcp6_mudurl
);
779 free(network
->dhcp6_hostname
);
780 strv_free(network
->dhcp6_user_class
);
781 strv_free(network
->dhcp6_vendor_class
);
782 set_free(network
->dhcp6_request_options
);
783 ordered_hashmap_free(network
->dhcp6_client_send_options
);
784 ordered_hashmap_free(network
->dhcp6_client_send_vendor_options
);
785 free(network
->dhcp6_netlabel
);
786 nft_set_context_clear(&network
->dhcp6_nft_set_context
);
789 free(network
->dhcp_pd_uplink_name
);
790 set_free(network
->dhcp_pd_tokens
);
791 free(network
->dhcp_pd_netlabel
);
792 nft_set_context_clear(&network
->dhcp_pd_nft_set_context
);
794 /* Router advertisement */
795 ordered_set_free(network
->router_search_domains
);
796 free(network
->router_dns
);
797 free(network
->router_uplink_name
);
800 set_free(network
->ndisc_deny_listed_router
);
801 set_free(network
->ndisc_allow_listed_router
);
802 set_free(network
->ndisc_deny_listed_prefix
);
803 set_free(network
->ndisc_allow_listed_prefix
);
804 set_free(network
->ndisc_deny_listed_route_prefix
);
805 set_free(network
->ndisc_allow_listed_route_prefix
);
806 set_free(network
->ndisc_tokens
);
807 free(network
->ndisc_netlabel
);
808 nft_set_context_clear(&network
->ndisc_nft_set_context
);
811 free(network
->lldp_mudurl
);
814 free(network
->batadv_name
);
815 free(network
->bridge_name
);
816 free(network
->bond_name
);
817 free(network
->vrf_name
);
818 hashmap_free(network
->stacked_netdev_names
);
819 netdev_unref(network
->bridge
);
820 netdev_unref(network
->bond
);
821 netdev_unref(network
->vrf
);
822 hashmap_free(network
->stacked_netdevs
);
825 set_free(network
->ipv6_proxy_ndp_addresses
);
826 ordered_hashmap_free(network
->addresses_by_section
);
827 hashmap_free(network
->routes_by_section
);
828 ordered_hashmap_free(network
->nexthops_by_section
);
829 hashmap_free(network
->bridge_fdb_entries_by_section
);
830 hashmap_free(network
->bridge_mdb_entries_by_section
);
831 ordered_hashmap_free(network
->neighbors_by_section
);
832 hashmap_free(network
->address_labels_by_section
);
833 hashmap_free(network
->prefixes_by_section
);
834 hashmap_free(network
->route_prefixes_by_section
);
835 hashmap_free(network
->pref64_prefixes_by_section
);
836 hashmap_free(network
->rules_by_section
);
837 hashmap_free(network
->dhcp_static_leases_by_section
);
838 ordered_hashmap_free(network
->sr_iov_by_section
);
839 hashmap_free(network
->qdiscs_by_section
);
840 hashmap_free(network
->tclasses_by_section
);
842 return mfree(network
);
845 DEFINE_TRIVIAL_REF_UNREF_FUNC(Network
, network
, network_free
);
847 int network_get_by_name(Manager
*manager
, const char *name
, Network
**ret
) {
854 network
= ordered_hashmap_get(manager
->networks
, name
);
863 bool network_has_static_ipv6_configurations(Network
*network
) {
872 ORDERED_HASHMAP_FOREACH(address
, network
->addresses_by_section
)
873 if (address
->family
== AF_INET6
)
876 HASHMAP_FOREACH(route
, network
->routes_by_section
)
877 if (route
->family
== AF_INET6
)
880 HASHMAP_FOREACH(fdb
, network
->bridge_fdb_entries_by_section
)
881 if (fdb
->family
== AF_INET6
)
884 HASHMAP_FOREACH(mdb
, network
->bridge_mdb_entries_by_section
)
885 if (mdb
->family
== AF_INET6
)
888 ORDERED_HASHMAP_FOREACH(neighbor
, network
->neighbors_by_section
)
889 if (neighbor
->dst_addr
.family
== AF_INET6
)
892 if (!hashmap_isempty(network
->address_labels_by_section
))
895 if (!hashmap_isempty(network
->prefixes_by_section
))
898 if (!hashmap_isempty(network
->route_prefixes_by_section
))
901 if (!hashmap_isempty(network
->pref64_prefixes_by_section
))
907 int config_parse_stacked_netdev(
909 const char *filename
,
912 unsigned section_line
,
919 _cleanup_free_
char *name
= NULL
;
920 NetDevKind kind
= ltype
;
921 Hashmap
**h
= ASSERT_PTR(data
);
937 _NETDEV_KIND_TUNNEL
));
939 if (!ifname_valid(rvalue
)) {
940 log_syntax(unit
, LOG_WARNING
, filename
, line
, 0,
941 "Invalid netdev name in %s=, ignoring assignment: %s", lvalue
, rvalue
);
945 name
= strdup(rvalue
);
949 r
= hashmap_ensure_put(h
, &string_hash_ops_free
, name
, INT_TO_PTR(kind
));
953 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
954 "Cannot add NetDev '%s' to network, ignoring assignment: %m", name
);
956 log_syntax(unit
, LOG_DEBUG
, filename
, line
, r
,
957 "NetDev '%s' specified twice, ignoring.", name
);
964 int config_parse_required_for_online(
966 const char *filename
,
969 unsigned section_line
,
976 Network
*network
= ASSERT_PTR(userdata
);
983 if (isempty(rvalue
)) {
984 network
->required_for_online
= -1;
985 network
->required_operstate_for_online
= LINK_OPERSTATE_RANGE_INVALID
;
989 r
= parse_operational_state_range(rvalue
, &network
->required_operstate_for_online
);
991 r
= parse_boolean(rvalue
);
993 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
994 "Failed to parse %s= setting, ignoring assignment: %s",
999 network
->required_for_online
= r
;
1000 network
->required_operstate_for_online
= LINK_OPERSTATE_RANGE_DEFAULT
;
1004 network
->required_for_online
= true;
1008 int config_parse_link_group(
1010 const char *filename
,
1012 const char *section
,
1013 unsigned section_line
,
1020 Network
*network
= ASSERT_PTR(userdata
);
1028 if (isempty(rvalue
)) {
1029 network
->group
= -1;
1033 r
= safe_atoi32(rvalue
, &group
);
1035 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
1036 "Failed to parse Group=, ignoring assignment: %s", rvalue
);
1041 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
1042 "Value of Group= must be in the range 0…2147483647, ignoring assignment: %s", rvalue
);
1046 network
->group
= group
;
1050 int config_parse_ignore_carrier_loss(
1052 const char *filename
,
1054 const char *section
,
1055 unsigned section_line
,
1062 Network
*network
= ASSERT_PTR(userdata
);
1070 if (isempty(rvalue
)) {
1071 network
->ignore_carrier_loss_set
= false;
1075 r
= parse_boolean(rvalue
);
1077 network
->ignore_carrier_loss_set
= true;
1078 network
->ignore_carrier_loss_usec
= r
> 0 ? USEC_INFINITY
: 0;
1082 r
= parse_sec(rvalue
, &usec
);
1084 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
1085 "Failed to parse %s=, ignoring assignment: %s", lvalue
, rvalue
);
1089 network
->ignore_carrier_loss_set
= true;
1090 network
->ignore_carrier_loss_usec
= usec
;
1094 int config_parse_keep_configuration(
1096 const char *filename
,
1098 const char *section
,
1099 unsigned section_line
,
1106 KeepConfiguration t
, *k
= ASSERT_PTR(data
);
1107 Network
*network
= ASSERT_PTR(userdata
);
1109 if (isempty(rvalue
)) {
1110 *k
= ASSERT_PTR(network
->manager
)->keep_configuration
;
1114 /* backward compatibility */
1115 if (streq(rvalue
, "dhcp")) {
1116 *k
= KEEP_CONFIGURATION_DYNAMIC
;
1120 if (streq(rvalue
, "dhcp-on-stop")) {
1121 *k
= KEEP_CONFIGURATION_DYNAMIC_ON_STOP
;
1125 t
= keep_configuration_from_string(rvalue
);
1127 return log_syntax_parse_error(unit
, filename
, line
, t
, lvalue
, rvalue
);
1133 DEFINE_CONFIG_PARSE_ENUM(config_parse_required_family_for_online
, link_required_address_family
, AddressFamily
);
1135 static const char* const keep_configuration_table
[_KEEP_CONFIGURATION_MAX
] = {
1136 [KEEP_CONFIGURATION_NO
] = "no",
1137 [KEEP_CONFIGURATION_DYNAMIC_ON_STOP
] = "dynamic-on-stop",
1138 [KEEP_CONFIGURATION_DYNAMIC
] = "dynamic",
1139 [KEEP_CONFIGURATION_STATIC
] = "static",
1140 [KEEP_CONFIGURATION_YES
] = "yes",
1143 DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(keep_configuration
, KeepConfiguration
, KEEP_CONFIGURATION_YES
);
1145 static const char* const activation_policy_table
[_ACTIVATION_POLICY_MAX
] = {
1146 [ACTIVATION_POLICY_UP
] = "up",
1147 [ACTIVATION_POLICY_ALWAYS_UP
] = "always-up",
1148 [ACTIVATION_POLICY_MANUAL
] = "manual",
1149 [ACTIVATION_POLICY_ALWAYS_DOWN
] = "always-down",
1150 [ACTIVATION_POLICY_DOWN
] = "down",
1151 [ACTIVATION_POLICY_BOUND
] = "bound",
1154 DEFINE_STRING_TABLE_LOOKUP(activation_policy
, ActivationPolicy
);
1155 DEFINE_CONFIG_PARSE_ENUM(config_parse_activation_policy
, activation_policy
, ActivationPolicy
);