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(network
->addresses_by_section
);
191 network
->routes_by_section
= hashmap_free(network
->routes_by_section
);
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 network_adjust_ipv6_proxy_ndp(network
);
229 network_adjust_ipv6_accept_ra(network
);
230 network_adjust_dhcp(network
);
231 network_adjust_radv(network
);
232 network_adjust_bridge_vlan(network
);
234 if (network
->mtu
> 0 && network
->dhcp_use_mtu
) {
235 log_warning("%s: MTUBytes= in [Link] section and UseMTU= in [DHCP] section are set. "
236 "Disabling UseMTU=.", network
->filename
);
237 network
->dhcp_use_mtu
= false;
240 if (network
->dhcp_critical
>= 0) {
241 if (network
->keep_configuration
>= 0) {
242 if (network
->manager
->keep_configuration
< 0)
243 log_warning("%s: Both KeepConfiguration= and deprecated CriticalConnection= are set. "
244 "Ignoring CriticalConnection=.", network
->filename
);
245 } else if (network
->dhcp_critical
)
246 /* CriticalConnection=yes also preserve foreign static configurations. */
247 network
->keep_configuration
= KEEP_CONFIGURATION_YES
;
249 network
->keep_configuration
= KEEP_CONFIGURATION_NO
;
252 if (!strv_isempty(network
->bind_carrier
)) {
253 if (!IN_SET(network
->activation_policy
, _ACTIVATION_POLICY_INVALID
, ACTIVATION_POLICY_BOUND
))
254 log_warning("%s: ActivationPolicy=bound is required with BindCarrier=. "
255 "Setting ActivationPolicy=bound.", network
->filename
);
256 network
->activation_policy
= ACTIVATION_POLICY_BOUND
;
257 } else if (network
->activation_policy
== ACTIVATION_POLICY_BOUND
) {
258 log_warning("%s: ActivationPolicy=bound requires BindCarrier=. "
259 "Ignoring ActivationPolicy=bound.", network
->filename
);
260 network
->activation_policy
= ACTIVATION_POLICY_UP
;
263 if (network
->activation_policy
== _ACTIVATION_POLICY_INVALID
)
264 network
->activation_policy
= ACTIVATION_POLICY_UP
;
266 if (network
->activation_policy
== ACTIVATION_POLICY_ALWAYS_UP
) {
267 if (network
->ignore_carrier_loss_set
&& network
->ignore_carrier_loss_usec
< USEC_INFINITY
)
268 log_warning("%s: IgnoreCarrierLoss=no or finite timespan conflicts with ActivationPolicy=always-up. "
269 "Setting IgnoreCarrierLoss=yes.", network
->filename
);
270 network
->ignore_carrier_loss_set
= true;
271 network
->ignore_carrier_loss_usec
= USEC_INFINITY
;
274 if (!network
->ignore_carrier_loss_set
) /* Set implied default. */
275 network
->ignore_carrier_loss_usec
= network
->configure_without_carrier
? USEC_INFINITY
: 0;
277 if (IN_SET(network
->activation_policy
, ACTIVATION_POLICY_DOWN
, ACTIVATION_POLICY_ALWAYS_DOWN
, ACTIVATION_POLICY_MANUAL
)) {
278 if (network
->required_for_online
< 0 ||
279 (network
->required_for_online
== true && network
->activation_policy
== ACTIVATION_POLICY_ALWAYS_DOWN
)) {
280 log_debug("%s: Setting RequiredForOnline=no because ActivationPolicy=%s.", network
->filename
,
281 activation_policy_to_string(network
->activation_policy
));
282 network
->required_for_online
= false;
283 } else if (network
->required_for_online
== true)
284 log_warning("%s: RequiredForOnline=yes and ActivationPolicy=%s, "
285 "this may cause a delay at boot.", network
->filename
,
286 activation_policy_to_string(network
->activation_policy
));
289 if (network
->required_for_online
< 0)
290 network
->required_for_online
= true;
292 if (network
->keep_configuration
< 0)
293 network
->keep_configuration
= KEEP_CONFIGURATION_NO
;
295 if (network
->ipv6_proxy_ndp
== 0 && !set_isempty(network
->ipv6_proxy_ndp_addresses
)) {
296 log_warning("%s: IPv6ProxyNDP= is disabled. Ignoring IPv6ProxyNDPAddress=.", network
->filename
);
297 network
->ipv6_proxy_ndp_addresses
= set_free_free(network
->ipv6_proxy_ndp_addresses
);
300 r
= network_drop_invalid_addresses(network
);
302 return r
; /* network_drop_invalid_addresses() logs internally. */
303 network_drop_invalid_routes(network
);
304 r
= network_drop_invalid_nexthops(network
);
307 network_drop_invalid_bridge_fdb_entries(network
);
308 network_drop_invalid_bridge_mdb_entries(network
);
309 r
= network_drop_invalid_neighbors(network
);
312 network_drop_invalid_address_labels(network
);
313 network_drop_invalid_prefixes(network
);
314 network_drop_invalid_route_prefixes(network
);
315 network_drop_invalid_routing_policy_rules(network
);
316 network_drop_invalid_qdisc(network
);
317 network_drop_invalid_tclass(network
);
318 r
= sr_iov_drop_invalid_sections(UINT32_MAX
, network
->sr_iov_by_section
);
320 return r
; /* sr_iov_drop_invalid_sections() logs internally. */
321 network_drop_invalid_static_leases(network
);
326 int network_load_one(Manager
*manager
, OrderedHashmap
**networks
, const char *filename
) {
327 _cleanup_free_
char *fname
= NULL
, *name
= NULL
;
328 _cleanup_(network_unrefp
) Network
*network
= NULL
;
329 const char *dropin_dirname
;
336 r
= null_or_empty_path(filename
);
338 return log_warning_errno(r
, "Failed to check if \"%s\" is empty: %m", filename
);
340 log_debug("Skipping empty file: %s", filename
);
344 fname
= strdup(filename
);
348 name
= strdup(basename(filename
));
352 d
= strrchr(name
, '.');
354 return log_warning_errno(SYNTHETIC_ERRNO(EINVAL
), "Invalid file name: %s", filename
);
358 dropin_dirname
= strjoina(name
, ".network.d");
360 network
= new(Network
, 1);
364 *network
= (Network
) {
365 .filename
= TAKE_PTR(fname
),
366 .name
= TAKE_PTR(name
),
371 .required_for_online
= -1,
372 .required_operstate_for_online
= LINK_OPERSTATE_RANGE_INVALID
,
373 .activation_policy
= _ACTIVATION_POLICY_INVALID
,
380 .keep_configuration
= manager
->keep_configuration
,
382 .dhcp_duid
.type
= _DUID_TYPE_INVALID
,
384 .dhcp_use_ntp
= true,
385 .dhcp_routes_to_ntp
= true,
386 .dhcp_use_sip
= true,
387 .dhcp_use_captive_portal
= true,
388 .dhcp_use_dns
= true,
389 .dhcp_routes_to_dns
= true,
390 .dhcp_use_hostname
= true,
391 .dhcp_use_routes
= true,
392 .dhcp_use_gateway
= -1,
393 .dhcp_send_hostname
= true,
394 .dhcp_send_release
= true,
395 .dhcp_route_metric
= DHCP_ROUTE_METRIC
,
396 .dhcp_use_rapid_commit
= -1,
397 .dhcp_client_identifier
= _DHCP_CLIENT_ID_INVALID
,
398 .dhcp_route_table
= RT_TABLE_MAIN
,
399 .dhcp_ip_service_type
= -1,
400 .dhcp_broadcast
= -1,
401 .dhcp_ipv6_only_mode
= -1,
403 .dhcp6_use_address
= true,
404 .dhcp6_use_pd_prefix
= true,
405 .dhcp6_use_dns
= true,
406 .dhcp6_use_hostname
= true,
407 .dhcp6_use_ntp
= true,
408 .dhcp6_use_captive_portal
= true,
409 .dhcp6_use_rapid_commit
= true,
410 .dhcp6_send_hostname
= true,
411 .dhcp6_duid
.type
= _DUID_TYPE_INVALID
,
412 .dhcp6_client_start_mode
= _DHCP6_CLIENT_START_MODE_INVALID
,
413 .dhcp6_send_release
= true,
416 .dhcp_pd_announce
= true,
417 .dhcp_pd_assign
= true,
418 .dhcp_pd_manage_temporary_address
= true,
419 .dhcp_pd_subnet_id
= -1,
420 .dhcp_pd_route_metric
= DHCP6PD_ROUTE_METRIC
,
422 .dhcp_server_bind_to_interface
= true,
423 .dhcp_server_emit
[SD_DHCP_LEASE_DNS
].emit
= true,
424 .dhcp_server_emit
[SD_DHCP_LEASE_NTP
].emit
= true,
425 .dhcp_server_emit
[SD_DHCP_LEASE_SIP
].emit
= true,
426 .dhcp_server_emit_router
= true,
427 .dhcp_server_emit_timezone
= true,
428 .dhcp_server_rapid_commit
= true,
430 .router_lifetime_usec
= RADV_DEFAULT_ROUTER_LIFETIME_USEC
,
431 .router_dns_lifetime_usec
= RADV_DEFAULT_VALID_LIFETIME_USEC
,
432 .router_emit_dns
= true,
433 .router_emit_domains
= true,
439 .allow_port_to_be_root
= -1,
441 .multicast_flood
= -1,
442 .multicast_to_unicast
= -1,
443 .neighbor_suppression
= -1,
445 .bridge_proxy_arp
= -1,
446 .bridge_proxy_arp_wifi
= -1,
447 .priority
= LINK_BRIDGE_PORT_PRIORITY_INVALID
,
448 .multicast_router
= _MULTICAST_ROUTER_INVALID
,
450 .bridge_vlan_pvid
= BRIDGE_VLAN_KEEP_PVID
,
452 .lldp_mode
= LLDP_MODE_ROUTERS_ONLY
,
453 .lldp_multicast_mode
= _SD_LLDP_MULTICAST_MODE_INVALID
,
455 .dns_default_route
= -1,
456 .llmnr
= RESOLVE_SUPPORT_YES
,
457 .mdns
= RESOLVE_SUPPORT_NO
,
458 .dnssec_mode
= _DNSSEC_MODE_INVALID
,
459 .dns_over_tls_mode
= _DNS_OVER_TLS_MODE_INVALID
,
461 /* If LinkLocalAddressing= is not set, then set to ADDRESS_FAMILY_IPV6 later. */
462 .link_local
= _ADDRESS_FAMILY_INVALID
,
463 .ipv6ll_address_gen_mode
= _IPV6_LINK_LOCAL_ADDRESS_GEN_MODE_INVALID
,
465 .ip_forwarding
= { -1, -1, },
466 .ipv4_accept_local
= -1,
467 .ipv4_route_localnet
= -1,
468 .ipv6_privacy_extensions
= _IPV6_PRIVACY_EXTENSIONS_INVALID
,
469 .ipv6_dad_transmits
= -1,
470 .ipv6_proxy_ndp
= -1,
472 .proxy_arp_pvlan
= -1,
473 .ipv4_rp_filter
= _IP_REVERSE_PATH_FILTER_INVALID
,
475 .ipv6_accept_ra
= -1,
476 .ipv6_accept_ra_use_dns
= true,
477 .ipv6_accept_ra_use_gateway
= true,
478 .ipv6_accept_ra_use_captive_portal
= true,
479 .ipv6_accept_ra_use_route_prefix
= true,
480 .ipv6_accept_ra_use_autonomous_prefix
= true,
481 .ipv6_accept_ra_use_onlink_prefix
= true,
482 .ipv6_accept_ra_use_mtu
= true,
483 .ipv6_accept_ra_use_hop_limit
= true,
484 .ipv6_accept_ra_use_reachable_time
= true,
485 .ipv6_accept_ra_use_retransmission_time
= true,
486 .ipv6_accept_ra_use_icmp6_ratelimit
= true,
487 .ipv6_accept_ra_route_table
= RT_TABLE_MAIN
,
488 .ipv6_accept_ra_route_metric_high
= IPV6RA_ROUTE_METRIC_HIGH
,
489 .ipv6_accept_ra_route_metric_medium
= IPV6RA_ROUTE_METRIC_MEDIUM
,
490 .ipv6_accept_ra_route_metric_low
= IPV6RA_ROUTE_METRIC_LOW
,
491 .ipv6_accept_ra_start_dhcp6_client
= IPV6_ACCEPT_RA_START_DHCP6_CLIENT_YES
,
493 .can_termination
= -1,
495 .ipoib_mode
= _IP_OVER_INFINIBAND_MODE_INVALID
,
499 r
= config_parse_many(
500 STRV_MAKE_CONST(filename
), NETWORK_DIRS
, dropin_dirname
, /* root = */ NULL
,
508 "RoutingPolicyRule\0"
511 "DHCP\0" /* compat */
514 "DHCPv6PrefixDelegation\0" /* compat */
515 "DHCPPrefixDelegation\0"
517 "DHCPServerStaticLease\0"
519 "IPv6NDPProxyAddress\0"
525 "IPv6PrefixDelegation\0"
530 "TrafficControlQueueingDiscipline\0"
536 "DeficitRoundRobinScheduler\0"
537 "DeficitRoundRobinSchedulerClass\0"
538 "EnhancedTransmissionSelection\0"
540 "FairQueueingControlledDelay\0"
542 "GenericRandomEarlyDetection\0"
543 "HeavyHitterFilter\0"
544 "HierarchyTokenBucket\0"
545 "HierarchyTokenBucketClass\0"
551 "QuickFairQueueing\0"
552 "QuickFairQueueingClass\0"
553 "StochasticFairBlue\0"
554 "StochasticFairnessQueueing\0"
555 "TokenBucketFilter\0"
556 "TrivialLinkEqualizer\0",
557 config_item_perf_lookup
, network_network_gperf_lookup
,
560 &network
->stats_by_path
,
563 return r
; /* config_parse_many() logs internally. */
565 r
= network_add_ipv4ll_route(network
);
567 return log_warning_errno(r
, "%s: Failed to add IPv4LL route: %m", network
->filename
);
569 r
= network_add_default_route_on_device(network
);
571 return log_warning_errno(r
, "%s: Failed to add default route on device: %m",
574 r
= network_verify(network
);
576 return r
; /* network_verify() logs internally. */
578 r
= ordered_hashmap_ensure_put(networks
, &string_hash_ops
, network
->name
, network
);
580 return log_warning_errno(r
, "%s: Failed to store configuration into hashmap: %m", filename
);
586 int network_load(Manager
*manager
, OrderedHashmap
**networks
) {
587 _cleanup_strv_free_
char **files
= NULL
;
592 ordered_hashmap_clear_with_destructor(*networks
, network_unref
);
594 r
= conf_files_list_strv(&files
, ".network", NULL
, 0, NETWORK_DIRS
);
596 return log_error_errno(r
, "Failed to enumerate network files: %m");
598 STRV_FOREACH(f
, files
)
599 (void) network_load_one(manager
, networks
, *f
);
604 int network_reload(Manager
*manager
) {
605 OrderedHashmap
*new_networks
= NULL
;
611 r
= network_load(manager
, &new_networks
);
615 ORDERED_HASHMAP_FOREACH(n
, new_networks
) {
616 r
= network_get_by_name(manager
, n
->name
, &old
);
618 log_debug("Found new .network file: %s", n
->filename
);
622 if (!stats_by_path_equal(n
->stats_by_path
, old
->stats_by_path
)) {
623 log_debug("Found updated .network file: %s", n
->filename
);
627 r
= ordered_hashmap_replace(new_networks
, old
->name
, old
);
635 ordered_hashmap_free_with_destructor(manager
->networks
, network_unref
);
636 manager
->networks
= new_networks
;
638 r
= manager_build_dhcp_pd_subnet_ids(manager
);
642 r
= manager_build_nexthop_ids(manager
);
649 ordered_hashmap_free_with_destructor(new_networks
, network_unref
);
654 int manager_build_dhcp_pd_subnet_ids(Manager
*manager
) {
660 set_clear(manager
->dhcp_pd_subnet_ids
);
662 ORDERED_HASHMAP_FOREACH(n
, manager
->networks
) {
669 if (n
->dhcp_pd_subnet_id
< 0)
672 r
= set_ensure_put(&manager
->dhcp_pd_subnet_ids
, &uint64_hash_ops
, &n
->dhcp_pd_subnet_id
);
680 static Network
*network_free(Network
*network
) {
685 free(network
->filename
);
686 free(network
->description
);
687 strv_free(network
->dropins
);
688 hashmap_free(network
->stats_by_path
);
691 net_match_clear(&network
->match
);
692 condition_free_list(network
->conditions
);
695 strv_free(network
->bind_carrier
);
698 strv_free(network
->ntp
);
701 for (unsigned i
= 0; i
< network
->n_dns
; i
++)
702 in_addr_full_free(network
->dns
[i
]);
704 ordered_set_free(network
->search_domains
);
705 ordered_set_free(network
->route_domains
);
706 set_free_free(network
->dnssec_negative_trust_anchors
);
709 free(network
->dhcp_server_relay_agent_circuit_id
);
710 free(network
->dhcp_server_relay_agent_remote_id
);
711 free(network
->dhcp_server_boot_server_name
);
712 free(network
->dhcp_server_boot_filename
);
713 free(network
->dhcp_server_timezone
);
714 free(network
->dhcp_server_uplink_name
);
715 for (sd_dhcp_lease_server_type_t t
= 0; t
< _SD_DHCP_LEASE_SERVER_TYPE_MAX
; t
++)
716 free(network
->dhcp_server_emit
[t
].addresses
);
717 ordered_hashmap_free(network
->dhcp_server_send_options
);
718 ordered_hashmap_free(network
->dhcp_server_send_vendor_options
);
721 free(network
->dhcp_vendor_class_identifier
);
722 free(network
->dhcp_mudurl
);
723 free(network
->dhcp_hostname
);
724 free(network
->dhcp_label
);
725 set_free(network
->dhcp_deny_listed_ip
);
726 set_free(network
->dhcp_allow_listed_ip
);
727 strv_free(network
->dhcp_user_class
);
728 set_free(network
->dhcp_request_options
);
729 ordered_hashmap_free(network
->dhcp_client_send_options
);
730 ordered_hashmap_free(network
->dhcp_client_send_vendor_options
);
731 free(network
->dhcp_netlabel
);
732 nft_set_context_clear(&network
->dhcp_nft_set_context
);
735 free(network
->dhcp6_mudurl
);
736 free(network
->dhcp6_hostname
);
737 strv_free(network
->dhcp6_user_class
);
738 strv_free(network
->dhcp6_vendor_class
);
739 set_free(network
->dhcp6_request_options
);
740 ordered_hashmap_free(network
->dhcp6_client_send_options
);
741 ordered_hashmap_free(network
->dhcp6_client_send_vendor_options
);
742 free(network
->dhcp6_netlabel
);
743 nft_set_context_clear(&network
->dhcp6_nft_set_context
);
746 free(network
->dhcp_pd_uplink_name
);
747 set_free(network
->dhcp_pd_tokens
);
748 free(network
->dhcp_pd_netlabel
);
749 nft_set_context_clear(&network
->dhcp_pd_nft_set_context
);
751 /* Router advertisement */
752 ordered_set_free(network
->router_search_domains
);
753 free(network
->router_dns
);
754 free(network
->router_uplink_name
);
757 set_free(network
->ndisc_deny_listed_router
);
758 set_free(network
->ndisc_allow_listed_router
);
759 set_free(network
->ndisc_deny_listed_prefix
);
760 set_free(network
->ndisc_allow_listed_prefix
);
761 set_free(network
->ndisc_deny_listed_route_prefix
);
762 set_free(network
->ndisc_allow_listed_route_prefix
);
763 set_free(network
->ndisc_tokens
);
764 free(network
->ndisc_netlabel
);
765 nft_set_context_clear(&network
->ndisc_nft_set_context
);
768 free(network
->lldp_mudurl
);
771 free(network
->batadv_name
);
772 free(network
->bridge_name
);
773 free(network
->bond_name
);
774 free(network
->vrf_name
);
775 hashmap_free_free_key(network
->stacked_netdev_names
);
776 netdev_unref(network
->bridge
);
777 netdev_unref(network
->bond
);
778 netdev_unref(network
->vrf
);
779 hashmap_free_with_destructor(network
->stacked_netdevs
, netdev_unref
);
782 set_free_free(network
->ipv6_proxy_ndp_addresses
);
783 ordered_hashmap_free(network
->addresses_by_section
);
784 hashmap_free(network
->routes_by_section
);
785 ordered_hashmap_free(network
->nexthops_by_section
);
786 hashmap_free_with_destructor(network
->bridge_fdb_entries_by_section
, bridge_fdb_free
);
787 hashmap_free_with_destructor(network
->bridge_mdb_entries_by_section
, bridge_mdb_free
);
788 ordered_hashmap_free(network
->neighbors_by_section
);
789 hashmap_free_with_destructor(network
->address_labels_by_section
, address_label_free
);
790 hashmap_free_with_destructor(network
->prefixes_by_section
, prefix_free
);
791 hashmap_free_with_destructor(network
->route_prefixes_by_section
, route_prefix_free
);
792 hashmap_free_with_destructor(network
->pref64_prefixes_by_section
, pref64_prefix_free
);
793 hashmap_free_with_destructor(network
->rules_by_section
, routing_policy_rule_free
);
794 hashmap_free_with_destructor(network
->dhcp_static_leases_by_section
, dhcp_static_lease_free
);
795 ordered_hashmap_free_with_destructor(network
->sr_iov_by_section
, sr_iov_free
);
796 hashmap_free_with_destructor(network
->qdiscs_by_section
, qdisc_free
);
797 hashmap_free_with_destructor(network
->tclasses_by_section
, tclass_free
);
799 return mfree(network
);
802 DEFINE_TRIVIAL_REF_UNREF_FUNC(Network
, network
, network_free
);
804 int network_get_by_name(Manager
*manager
, const char *name
, Network
**ret
) {
811 network
= ordered_hashmap_get(manager
->networks
, name
);
820 bool network_has_static_ipv6_configurations(Network
*network
) {
829 ORDERED_HASHMAP_FOREACH(address
, network
->addresses_by_section
)
830 if (address
->family
== AF_INET6
)
833 HASHMAP_FOREACH(route
, network
->routes_by_section
)
834 if (route
->family
== AF_INET6
)
837 HASHMAP_FOREACH(fdb
, network
->bridge_fdb_entries_by_section
)
838 if (fdb
->family
== AF_INET6
)
841 HASHMAP_FOREACH(mdb
, network
->bridge_mdb_entries_by_section
)
842 if (mdb
->family
== AF_INET6
)
845 ORDERED_HASHMAP_FOREACH(neighbor
, network
->neighbors_by_section
)
846 if (neighbor
->family
== AF_INET6
)
849 if (!hashmap_isempty(network
->address_labels_by_section
))
852 if (!hashmap_isempty(network
->prefixes_by_section
))
855 if (!hashmap_isempty(network
->route_prefixes_by_section
))
858 if (!hashmap_isempty(network
->pref64_prefixes_by_section
))
864 int config_parse_stacked_netdev(
866 const char *filename
,
869 unsigned section_line
,
876 _cleanup_free_
char *name
= NULL
;
877 NetDevKind kind
= ltype
;
878 Hashmap
**h
= ASSERT_PTR(data
);
894 _NETDEV_KIND_TUNNEL
));
896 if (!ifname_valid(rvalue
)) {
897 log_syntax(unit
, LOG_WARNING
, filename
, line
, 0,
898 "Invalid netdev name in %s=, ignoring assignment: %s", lvalue
, rvalue
);
902 name
= strdup(rvalue
);
906 r
= hashmap_ensure_put(h
, &string_hash_ops
, name
, INT_TO_PTR(kind
));
910 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
911 "Cannot add NetDev '%s' to network, ignoring assignment: %m", name
);
913 log_syntax(unit
, LOG_DEBUG
, filename
, line
, r
,
914 "NetDev '%s' specified twice, ignoring.", name
);
921 int config_parse_domains(
923 const char *filename
,
926 unsigned section_line
,
933 Network
*n
= ASSERT_PTR(userdata
);
940 if (isempty(rvalue
)) {
941 n
->search_domains
= ordered_set_free(n
->search_domains
);
942 n
->route_domains
= ordered_set_free(n
->route_domains
);
946 for (const char *p
= rvalue
;;) {
947 _cleanup_free_
char *w
= NULL
, *normalized
= NULL
;
951 r
= extract_first_word(&p
, &w
, NULL
, 0);
955 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
956 "Failed to extract search or route domain, ignoring: %s", rvalue
);
962 is_route
= w
[0] == '~';
963 domain
= is_route
? w
+ 1 : w
;
965 if (dns_name_is_root(domain
) || streq(domain
, "*")) {
966 /* If the root domain appears as is, or the special token "*" is found, we'll
967 * consider this as routing domain, unconditionally. */
969 domain
= "."; /* make sure we don't allow empty strings, thus write the root
972 r
= dns_name_normalize(domain
, 0, &normalized
);
974 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
975 "'%s' is not a valid domain name, ignoring.", domain
);
981 if (is_localhost(domain
)) {
982 log_syntax(unit
, LOG_WARNING
, filename
, line
, 0,
983 "'localhost' domain may not be configured as search or route domain, ignoring assignment: %s",
989 OrderedSet
**set
= is_route
? &n
->route_domains
: &n
->search_domains
;
990 r
= ordered_set_put_strdup(set
, domain
);
998 int config_parse_timezone(
1000 const char *filename
,
1002 const char *section
,
1003 unsigned section_line
,
1010 char **tz
= ASSERT_PTR(data
);
1017 if (isempty(rvalue
)) {
1022 r
= verify_timezone(rvalue
, LOG_WARNING
);
1024 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
1025 "Timezone is not valid, ignoring assignment: %s", rvalue
);
1029 return free_and_strdup_warn(tz
, rvalue
);
1032 int config_parse_dns(
1034 const char *filename
,
1036 const char *section
,
1037 unsigned section_line
,
1044 Network
*n
= ASSERT_PTR(userdata
);
1051 if (isempty(rvalue
)) {
1052 for (unsigned i
= 0; i
< n
->n_dns
; i
++)
1053 in_addr_full_free(n
->dns
[i
]);
1054 n
->dns
= mfree(n
->dns
);
1059 for (const char *p
= rvalue
;;) {
1060 _cleanup_(in_addr_full_freep
) struct in_addr_full
*dns
= NULL
;
1061 _cleanup_free_
char *w
= NULL
;
1062 struct in_addr_full
**m
;
1064 r
= extract_first_word(&p
, &w
, NULL
, 0);
1068 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
1069 "Invalid syntax, ignoring: %s", rvalue
);
1075 r
= in_addr_full_new_from_string(w
, &dns
);
1077 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
1078 "Failed to parse dns server address, ignoring: %s", w
);
1082 if (IN_SET(dns
->port
, 53, 853))
1085 m
= reallocarray(n
->dns
, n
->n_dns
+ 1, sizeof(struct in_addr_full
*));
1089 m
[n
->n_dns
++] = TAKE_PTR(dns
);
1094 int config_parse_dnssec_negative_trust_anchors(
1096 const char *filename
,
1098 const char *section
,
1099 unsigned section_line
,
1106 Set
**nta
= ASSERT_PTR(data
);
1113 if (isempty(rvalue
)) {
1114 *nta
= set_free_free(*nta
);
1118 for (const char *p
= rvalue
;;) {
1119 _cleanup_free_
char *w
= NULL
;
1121 r
= extract_first_word(&p
, &w
, NULL
, 0);
1125 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
1126 "Failed to extract negative trust anchor domain, ignoring: %s", rvalue
);
1132 r
= dns_name_is_valid(w
);
1134 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
1135 "%s is not a valid domain name, ignoring.", w
);
1139 r
= set_ensure_consume(nta
, &dns_name_hash_ops
, TAKE_PTR(w
));
1145 int config_parse_ntp(
1147 const char *filename
,
1149 const char *section
,
1150 unsigned section_line
,
1157 char ***l
= ASSERT_PTR(data
);
1164 if (isempty(rvalue
)) {
1169 for (const char *p
= rvalue
;;) {
1170 _cleanup_free_
char *w
= NULL
;
1172 r
= extract_first_word(&p
, &w
, NULL
, 0);
1176 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
1177 "Failed to extract NTP server name, ignoring: %s", rvalue
);
1183 r
= dns_name_is_valid_or_address(w
);
1185 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
1186 "%s is not a valid domain name or IP address, ignoring.", w
);
1190 if (strv_length(*l
) > MAX_NTP_SERVERS
) {
1191 log_syntax(unit
, LOG_WARNING
, filename
, line
, 0,
1192 "More than %u NTP servers specified, ignoring \"%s\" and any subsequent entries.",
1193 MAX_NTP_SERVERS
, w
);
1197 r
= strv_consume(l
, TAKE_PTR(w
));
1203 int config_parse_required_for_online(
1205 const char *filename
,
1207 const char *section
,
1208 unsigned section_line
,
1215 Network
*network
= ASSERT_PTR(userdata
);
1222 if (isempty(rvalue
)) {
1223 network
->required_for_online
= -1;
1224 network
->required_operstate_for_online
= LINK_OPERSTATE_RANGE_INVALID
;
1228 r
= parse_operational_state_range(rvalue
, &network
->required_operstate_for_online
);
1230 r
= parse_boolean(rvalue
);
1232 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
1233 "Failed to parse %s= setting, ignoring assignment: %s",
1238 network
->required_for_online
= r
;
1239 network
->required_operstate_for_online
= LINK_OPERSTATE_RANGE_DEFAULT
;
1243 network
->required_for_online
= true;
1247 int config_parse_link_group(
1249 const char *filename
,
1251 const char *section
,
1252 unsigned section_line
,
1259 Network
*network
= ASSERT_PTR(userdata
);
1267 if (isempty(rvalue
)) {
1268 network
->group
= -1;
1272 r
= safe_atoi32(rvalue
, &group
);
1274 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
1275 "Failed to parse Group=, ignoring assignment: %s", rvalue
);
1280 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
1281 "Value of Group= must be in the range 0…2147483647, ignoring assignment: %s", rvalue
);
1285 network
->group
= group
;
1289 int config_parse_ignore_carrier_loss(
1291 const char *filename
,
1293 const char *section
,
1294 unsigned section_line
,
1301 Network
*network
= ASSERT_PTR(userdata
);
1309 if (isempty(rvalue
)) {
1310 network
->ignore_carrier_loss_set
= false;
1314 r
= parse_boolean(rvalue
);
1316 network
->ignore_carrier_loss_set
= true;
1317 network
->ignore_carrier_loss_usec
= r
> 0 ? USEC_INFINITY
: 0;
1321 r
= parse_sec(rvalue
, &usec
);
1323 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
1324 "Failed to parse %s=, ignoring assignment: %s", lvalue
, rvalue
);
1328 network
->ignore_carrier_loss_set
= true;
1329 network
->ignore_carrier_loss_usec
= usec
;
1333 DEFINE_CONFIG_PARSE_ENUM(config_parse_required_family_for_online
, link_required_address_family
, AddressFamily
,
1334 "Failed to parse RequiredFamilyForOnline= setting");
1336 DEFINE_CONFIG_PARSE_ENUM(config_parse_keep_configuration
, keep_configuration
, KeepConfiguration
,
1337 "Failed to parse KeepConfiguration= setting");
1339 static const char* const keep_configuration_table
[_KEEP_CONFIGURATION_MAX
] = {
1340 [KEEP_CONFIGURATION_NO
] = "no",
1341 [KEEP_CONFIGURATION_DHCP_ON_STOP
] = "dhcp-on-stop",
1342 [KEEP_CONFIGURATION_DHCP
] = "dhcp",
1343 [KEEP_CONFIGURATION_STATIC
] = "static",
1344 [KEEP_CONFIGURATION_YES
] = "yes",
1347 DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(keep_configuration
, KeepConfiguration
, KEEP_CONFIGURATION_YES
);
1349 static const char* const activation_policy_table
[_ACTIVATION_POLICY_MAX
] = {
1350 [ACTIVATION_POLICY_UP
] = "up",
1351 [ACTIVATION_POLICY_ALWAYS_UP
] = "always-up",
1352 [ACTIVATION_POLICY_MANUAL
] = "manual",
1353 [ACTIVATION_POLICY_ALWAYS_DOWN
] = "always-down",
1354 [ACTIVATION_POLICY_DOWN
] = "down",
1355 [ACTIVATION_POLICY_BOUND
] = "bound",
1358 DEFINE_STRING_TABLE_LOOKUP(activation_policy
, ActivationPolicy
);
1359 DEFINE_CONFIG_PARSE_ENUM(config_parse_activation_policy
, activation_policy
, ActivationPolicy
, "Failed to parse activation policy");