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_client_identifier
= _DHCP_CLIENT_ID_INVALID
,
400 .dhcp_route_table
= RT_TABLE_MAIN
,
401 .dhcp_ip_service_type
= -1,
402 .dhcp_broadcast
= -1,
403 .dhcp_ipv6_only_mode
= -1,
405 .dhcp6_use_address
= true,
406 .dhcp6_use_pd_prefix
= true,
407 .dhcp6_use_dns
= true,
408 .dhcp6_use_hostname
= true,
409 .dhcp6_use_ntp
= true,
410 .dhcp6_use_captive_portal
= true,
411 .dhcp6_use_rapid_commit
= true,
412 .dhcp6_duid
.type
= _DUID_TYPE_INVALID
,
413 .dhcp6_client_start_mode
= _DHCP6_CLIENT_START_MODE_INVALID
,
414 .dhcp6_send_release
= true,
417 .dhcp_pd_announce
= true,
418 .dhcp_pd_assign
= true,
419 .dhcp_pd_manage_temporary_address
= true,
420 .dhcp_pd_subnet_id
= -1,
421 .dhcp_pd_route_metric
= DHCP6PD_ROUTE_METRIC
,
423 .dhcp_server_bind_to_interface
= true,
424 .dhcp_server_emit
[SD_DHCP_LEASE_DNS
].emit
= true,
425 .dhcp_server_emit
[SD_DHCP_LEASE_NTP
].emit
= true,
426 .dhcp_server_emit
[SD_DHCP_LEASE_SIP
].emit
= true,
427 .dhcp_server_emit_router
= true,
428 .dhcp_server_emit_timezone
= 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 .lldp_mode
= LLDP_MODE_ROUTERS_ONLY
,
451 .lldp_multicast_mode
= _SD_LLDP_MULTICAST_MODE_INVALID
,
453 .dns_default_route
= -1,
454 .llmnr
= RESOLVE_SUPPORT_YES
,
455 .mdns
= RESOLVE_SUPPORT_NO
,
456 .dnssec_mode
= _DNSSEC_MODE_INVALID
,
457 .dns_over_tls_mode
= _DNS_OVER_TLS_MODE_INVALID
,
459 /* If LinkLocalAddressing= is not set, then set to ADDRESS_FAMILY_IPV6 later. */
460 .link_local
= _ADDRESS_FAMILY_INVALID
,
461 .ipv6ll_address_gen_mode
= _IPV6_LINK_LOCAL_ADDRESS_GEN_MODE_INVALID
,
463 .ipv4_accept_local
= -1,
464 .ipv4_route_localnet
= -1,
465 .ipv6_privacy_extensions
= _IPV6_PRIVACY_EXTENSIONS_INVALID
,
466 .ipv6_dad_transmits
= -1,
467 .ipv6_hop_limit
= -1,
468 .ipv6_proxy_ndp
= -1,
470 .ipv4_rp_filter
= _IP_REVERSE_PATH_FILTER_INVALID
,
472 .ipv6_accept_ra
= -1,
473 .ipv6_accept_ra_use_dns
= true,
474 .ipv6_accept_ra_use_gateway
= true,
475 .ipv6_accept_ra_use_captive_portal
= true,
476 .ipv6_accept_ra_use_route_prefix
= true,
477 .ipv6_accept_ra_use_autonomous_prefix
= true,
478 .ipv6_accept_ra_use_onlink_prefix
= true,
479 .ipv6_accept_ra_use_mtu
= true,
480 .ipv6_accept_ra_use_hop_limit
= true,
481 .ipv6_accept_ra_use_icmp6_ratelimit
= true,
482 .ipv6_accept_ra_route_table
= RT_TABLE_MAIN
,
483 .ipv6_accept_ra_route_metric_high
= IPV6RA_ROUTE_METRIC_HIGH
,
484 .ipv6_accept_ra_route_metric_medium
= IPV6RA_ROUTE_METRIC_MEDIUM
,
485 .ipv6_accept_ra_route_metric_low
= IPV6RA_ROUTE_METRIC_LOW
,
486 .ipv6_accept_ra_start_dhcp6_client
= IPV6_ACCEPT_RA_START_DHCP6_CLIENT_YES
,
488 .can_termination
= -1,
490 .ipoib_mode
= _IP_OVER_INFINIBAND_MODE_INVALID
,
494 r
= config_parse_many(
495 STRV_MAKE_CONST(filename
), NETWORK_DIRS
, dropin_dirname
, /* root = */ NULL
,
503 "RoutingPolicyRule\0"
506 "DHCP\0" /* compat */
509 "DHCPv6PrefixDelegation\0" /* compat */
510 "DHCPPrefixDelegation\0"
512 "DHCPServerStaticLease\0"
514 "IPv6NDPProxyAddress\0"
520 "IPv6PrefixDelegation\0"
525 "TrafficControlQueueingDiscipline\0"
531 "DeficitRoundRobinScheduler\0"
532 "DeficitRoundRobinSchedulerClass\0"
533 "EnhancedTransmissionSelection\0"
535 "FairQueueingControlledDelay\0"
537 "GenericRandomEarlyDetection\0"
538 "HeavyHitterFilter\0"
539 "HierarchyTokenBucket\0"
540 "HierarchyTokenBucketClass\0"
546 "QuickFairQueueing\0"
547 "QuickFairQueueingClass\0"
548 "StochasticFairBlue\0"
549 "StochasticFairnessQueueing\0"
550 "TokenBucketFilter\0"
551 "TrivialLinkEqualizer\0",
552 config_item_perf_lookup
, network_network_gperf_lookup
,
555 &network
->stats_by_path
,
558 return r
; /* config_parse_many() logs internally. */
560 r
= network_add_ipv4ll_route(network
);
562 return log_warning_errno(r
, "%s: Failed to add IPv4LL route: %m", network
->filename
);
564 r
= network_add_default_route_on_device(network
);
566 return log_warning_errno(r
, "%s: Failed to add default route on device: %m",
569 r
= network_verify(network
);
571 return r
; /* network_verify() logs internally. */
573 r
= ordered_hashmap_ensure_put(networks
, &string_hash_ops
, network
->name
, network
);
575 return log_warning_errno(r
, "%s: Failed to store configuration into hashmap: %m", filename
);
581 int network_load(Manager
*manager
, OrderedHashmap
**networks
) {
582 _cleanup_strv_free_
char **files
= NULL
;
587 ordered_hashmap_clear_with_destructor(*networks
, network_unref
);
589 r
= conf_files_list_strv(&files
, ".network", NULL
, 0, NETWORK_DIRS
);
591 return log_error_errno(r
, "Failed to enumerate network files: %m");
593 STRV_FOREACH(f
, files
)
594 (void) network_load_one(manager
, networks
, *f
);
599 int network_reload(Manager
*manager
) {
600 OrderedHashmap
*new_networks
= NULL
;
606 r
= network_load(manager
, &new_networks
);
610 ORDERED_HASHMAP_FOREACH(n
, new_networks
) {
611 r
= network_get_by_name(manager
, n
->name
, &old
);
613 log_debug("Found new .network file: %s", n
->filename
);
617 if (!stats_by_path_equal(n
->stats_by_path
, old
->stats_by_path
)) {
618 log_debug("Found updated .network file: %s", n
->filename
);
622 r
= ordered_hashmap_replace(new_networks
, old
->name
, old
);
630 ordered_hashmap_free_with_destructor(manager
->networks
, network_unref
);
631 manager
->networks
= new_networks
;
633 return manager_build_dhcp_pd_subnet_ids(manager
);
636 ordered_hashmap_free_with_destructor(new_networks
, network_unref
);
641 int manager_build_dhcp_pd_subnet_ids(Manager
*manager
) {
647 set_clear(manager
->dhcp_pd_subnet_ids
);
649 ORDERED_HASHMAP_FOREACH(n
, manager
->networks
) {
656 if (n
->dhcp_pd_subnet_id
< 0)
659 r
= set_ensure_put(&manager
->dhcp_pd_subnet_ids
, &uint64_hash_ops
, &n
->dhcp_pd_subnet_id
);
667 static Network
*network_free(Network
*network
) {
672 free(network
->filename
);
673 free(network
->description
);
674 strv_free(network
->dropins
);
675 hashmap_free(network
->stats_by_path
);
678 net_match_clear(&network
->match
);
679 condition_free_list(network
->conditions
);
682 strv_free(network
->bind_carrier
);
685 strv_free(network
->ntp
);
688 for (unsigned i
= 0; i
< network
->n_dns
; i
++)
689 in_addr_full_free(network
->dns
[i
]);
691 ordered_set_free(network
->search_domains
);
692 ordered_set_free(network
->route_domains
);
693 set_free_free(network
->dnssec_negative_trust_anchors
);
696 free(network
->dhcp_server_relay_agent_circuit_id
);
697 free(network
->dhcp_server_relay_agent_remote_id
);
698 free(network
->dhcp_server_boot_server_name
);
699 free(network
->dhcp_server_boot_filename
);
700 free(network
->dhcp_server_timezone
);
701 free(network
->dhcp_server_uplink_name
);
702 for (sd_dhcp_lease_server_type_t t
= 0; t
< _SD_DHCP_LEASE_SERVER_TYPE_MAX
; t
++)
703 free(network
->dhcp_server_emit
[t
].addresses
);
704 ordered_hashmap_free(network
->dhcp_server_send_options
);
705 ordered_hashmap_free(network
->dhcp_server_send_vendor_options
);
708 free(network
->dhcp_vendor_class_identifier
);
709 free(network
->dhcp_mudurl
);
710 free(network
->dhcp_hostname
);
711 free(network
->dhcp_label
);
712 set_free(network
->dhcp_deny_listed_ip
);
713 set_free(network
->dhcp_allow_listed_ip
);
714 strv_free(network
->dhcp_user_class
);
715 set_free(network
->dhcp_request_options
);
716 ordered_hashmap_free(network
->dhcp_client_send_options
);
717 ordered_hashmap_free(network
->dhcp_client_send_vendor_options
);
718 free(network
->dhcp_netlabel
);
719 nft_set_context_clear(&network
->dhcp_nft_set_context
);
722 free(network
->dhcp6_mudurl
);
723 strv_free(network
->dhcp6_user_class
);
724 strv_free(network
->dhcp6_vendor_class
);
725 set_free(network
->dhcp6_request_options
);
726 ordered_hashmap_free(network
->dhcp6_client_send_options
);
727 ordered_hashmap_free(network
->dhcp6_client_send_vendor_options
);
728 free(network
->dhcp6_netlabel
);
729 nft_set_context_clear(&network
->dhcp6_nft_set_context
);
732 free(network
->dhcp_pd_uplink_name
);
733 set_free(network
->dhcp_pd_tokens
);
734 free(network
->dhcp_pd_netlabel
);
735 nft_set_context_clear(&network
->dhcp_pd_nft_set_context
);
737 /* Router advertisement */
738 ordered_set_free(network
->router_search_domains
);
739 free(network
->router_dns
);
740 free(network
->router_uplink_name
);
743 set_free(network
->ndisc_deny_listed_router
);
744 set_free(network
->ndisc_allow_listed_router
);
745 set_free(network
->ndisc_deny_listed_prefix
);
746 set_free(network
->ndisc_allow_listed_prefix
);
747 set_free(network
->ndisc_deny_listed_route_prefix
);
748 set_free(network
->ndisc_allow_listed_route_prefix
);
749 set_free(network
->ndisc_tokens
);
750 free(network
->ndisc_netlabel
);
751 nft_set_context_clear(&network
->ndisc_nft_set_context
);
754 free(network
->lldp_mudurl
);
757 free(network
->batadv_name
);
758 free(network
->bridge_name
);
759 free(network
->bond_name
);
760 free(network
->vrf_name
);
761 hashmap_free_free_key(network
->stacked_netdev_names
);
762 netdev_unref(network
->bridge
);
763 netdev_unref(network
->bond
);
764 netdev_unref(network
->vrf
);
765 hashmap_free_with_destructor(network
->stacked_netdevs
, netdev_unref
);
768 set_free_free(network
->ipv6_proxy_ndp_addresses
);
769 ordered_hashmap_free_with_destructor(network
->addresses_by_section
, address_free
);
770 hashmap_free_with_destructor(network
->routes_by_section
, route_free
);
771 hashmap_free_with_destructor(network
->nexthops_by_section
, nexthop_free
);
772 hashmap_free_with_destructor(network
->bridge_fdb_entries_by_section
, bridge_fdb_free
);
773 hashmap_free_with_destructor(network
->bridge_mdb_entries_by_section
, bridge_mdb_free
);
774 ordered_hashmap_free_with_destructor(network
->neighbors_by_section
, neighbor_free
);
775 hashmap_free_with_destructor(network
->address_labels_by_section
, address_label_free
);
776 hashmap_free_with_destructor(network
->prefixes_by_section
, prefix_free
);
777 hashmap_free_with_destructor(network
->route_prefixes_by_section
, route_prefix_free
);
778 hashmap_free_with_destructor(network
->pref64_prefixes_by_section
, pref64_prefix_free
);
779 hashmap_free_with_destructor(network
->rules_by_section
, routing_policy_rule_free
);
780 hashmap_free_with_destructor(network
->dhcp_static_leases_by_section
, dhcp_static_lease_free
);
781 ordered_hashmap_free_with_destructor(network
->sr_iov_by_section
, sr_iov_free
);
782 hashmap_free_with_destructor(network
->qdiscs_by_section
, qdisc_free
);
783 hashmap_free_with_destructor(network
->tclasses_by_section
, tclass_free
);
785 return mfree(network
);
788 DEFINE_TRIVIAL_REF_UNREF_FUNC(Network
, network
, network_free
);
790 int network_get_by_name(Manager
*manager
, const char *name
, Network
**ret
) {
797 network
= ordered_hashmap_get(manager
->networks
, name
);
806 bool network_has_static_ipv6_configurations(Network
*network
) {
815 ORDERED_HASHMAP_FOREACH(address
, network
->addresses_by_section
)
816 if (address
->family
== AF_INET6
)
819 HASHMAP_FOREACH(route
, network
->routes_by_section
)
820 if (route
->family
== AF_INET6
)
823 HASHMAP_FOREACH(fdb
, network
->bridge_fdb_entries_by_section
)
824 if (fdb
->family
== AF_INET6
)
827 HASHMAP_FOREACH(mdb
, network
->bridge_mdb_entries_by_section
)
828 if (mdb
->family
== AF_INET6
)
831 ORDERED_HASHMAP_FOREACH(neighbor
, network
->neighbors_by_section
)
832 if (neighbor
->family
== AF_INET6
)
835 if (!hashmap_isempty(network
->address_labels_by_section
))
838 if (!hashmap_isempty(network
->prefixes_by_section
))
841 if (!hashmap_isempty(network
->route_prefixes_by_section
))
844 if (!hashmap_isempty(network
->pref64_prefixes_by_section
))
850 int config_parse_stacked_netdev(
852 const char *filename
,
855 unsigned section_line
,
862 _cleanup_free_
char *name
= NULL
;
863 NetDevKind kind
= ltype
;
864 Hashmap
**h
= ASSERT_PTR(data
);
880 _NETDEV_KIND_TUNNEL
));
882 if (!ifname_valid(rvalue
)) {
883 log_syntax(unit
, LOG_WARNING
, filename
, line
, 0,
884 "Invalid netdev name in %s=, ignoring assignment: %s", lvalue
, rvalue
);
888 name
= strdup(rvalue
);
892 r
= hashmap_ensure_put(h
, &string_hash_ops
, name
, INT_TO_PTR(kind
));
896 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
897 "Cannot add NetDev '%s' to network, ignoring assignment: %m", name
);
899 log_syntax(unit
, LOG_DEBUG
, filename
, line
, r
,
900 "NetDev '%s' specified twice, ignoring.", name
);
907 int config_parse_domains(
909 const char *filename
,
912 unsigned section_line
,
919 Network
*n
= ASSERT_PTR(userdata
);
926 if (isempty(rvalue
)) {
927 n
->search_domains
= ordered_set_free(n
->search_domains
);
928 n
->route_domains
= ordered_set_free(n
->route_domains
);
932 for (const char *p
= rvalue
;;) {
933 _cleanup_free_
char *w
= NULL
, *normalized
= NULL
;
937 r
= extract_first_word(&p
, &w
, NULL
, 0);
941 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
942 "Failed to extract search or route domain, ignoring: %s", rvalue
);
948 is_route
= w
[0] == '~';
949 domain
= is_route
? w
+ 1 : w
;
951 if (dns_name_is_root(domain
) || streq(domain
, "*")) {
952 /* If the root domain appears as is, or the special token "*" is found, we'll
953 * consider this as routing domain, unconditionally. */
955 domain
= "."; /* make sure we don't allow empty strings, thus write the root
958 r
= dns_name_normalize(domain
, 0, &normalized
);
960 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
961 "'%s' is not a valid domain name, ignoring.", domain
);
967 if (is_localhost(domain
)) {
968 log_syntax(unit
, LOG_WARNING
, filename
, line
, 0,
969 "'localhost' domain may not be configured as search or route domain, ignoring assignment: %s",
975 OrderedSet
**set
= is_route
? &n
->route_domains
: &n
->search_domains
;
976 r
= ordered_set_put_strdup(set
, domain
);
984 int config_parse_timezone(
986 const char *filename
,
989 unsigned section_line
,
996 char **tz
= ASSERT_PTR(data
);
1003 if (isempty(rvalue
)) {
1008 r
= verify_timezone(rvalue
, LOG_WARNING
);
1010 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
1011 "Timezone is not valid, ignoring assignment: %s", rvalue
);
1015 return free_and_strdup_warn(tz
, rvalue
);
1018 int config_parse_dns(
1020 const char *filename
,
1022 const char *section
,
1023 unsigned section_line
,
1030 Network
*n
= ASSERT_PTR(userdata
);
1037 if (isempty(rvalue
)) {
1038 for (unsigned i
= 0; i
< n
->n_dns
; i
++)
1039 in_addr_full_free(n
->dns
[i
]);
1040 n
->dns
= mfree(n
->dns
);
1045 for (const char *p
= rvalue
;;) {
1046 _cleanup_(in_addr_full_freep
) struct in_addr_full
*dns
= NULL
;
1047 _cleanup_free_
char *w
= NULL
;
1048 struct in_addr_full
**m
;
1050 r
= extract_first_word(&p
, &w
, NULL
, 0);
1054 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
1055 "Invalid syntax, ignoring: %s", rvalue
);
1061 r
= in_addr_full_new_from_string(w
, &dns
);
1063 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
1064 "Failed to parse dns server address, ignoring: %s", w
);
1068 if (IN_SET(dns
->port
, 53, 853))
1071 m
= reallocarray(n
->dns
, n
->n_dns
+ 1, sizeof(struct in_addr_full
*));
1075 m
[n
->n_dns
++] = TAKE_PTR(dns
);
1080 int config_parse_dnssec_negative_trust_anchors(
1082 const char *filename
,
1084 const char *section
,
1085 unsigned section_line
,
1092 Set
**nta
= ASSERT_PTR(data
);
1099 if (isempty(rvalue
)) {
1100 *nta
= set_free_free(*nta
);
1104 for (const char *p
= rvalue
;;) {
1105 _cleanup_free_
char *w
= NULL
;
1107 r
= extract_first_word(&p
, &w
, NULL
, 0);
1111 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
1112 "Failed to extract negative trust anchor domain, ignoring: %s", rvalue
);
1118 r
= dns_name_is_valid(w
);
1120 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
1121 "%s is not a valid domain name, ignoring.", w
);
1125 r
= set_ensure_consume(nta
, &dns_name_hash_ops
, TAKE_PTR(w
));
1131 int config_parse_ntp(
1133 const char *filename
,
1135 const char *section
,
1136 unsigned section_line
,
1143 char ***l
= ASSERT_PTR(data
);
1150 if (isempty(rvalue
)) {
1155 for (const char *p
= rvalue
;;) {
1156 _cleanup_free_
char *w
= NULL
;
1158 r
= extract_first_word(&p
, &w
, NULL
, 0);
1162 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
1163 "Failed to extract NTP server name, ignoring: %s", rvalue
);
1169 r
= dns_name_is_valid_or_address(w
);
1171 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
1172 "%s is not a valid domain name or IP address, ignoring.", w
);
1176 if (strv_length(*l
) > MAX_NTP_SERVERS
) {
1177 log_syntax(unit
, LOG_WARNING
, filename
, line
, 0,
1178 "More than %u NTP servers specified, ignoring \"%s\" and any subsequent entries.",
1179 MAX_NTP_SERVERS
, w
);
1183 r
= strv_consume(l
, TAKE_PTR(w
));
1189 int config_parse_required_for_online(
1191 const char *filename
,
1193 const char *section
,
1194 unsigned section_line
,
1201 Network
*network
= ASSERT_PTR(userdata
);
1202 LinkOperationalStateRange range
;
1203 bool required
= true;
1210 if (isempty(rvalue
)) {
1211 network
->required_for_online
= -1;
1212 network
->required_operstate_for_online
= LINK_OPERSTATE_RANGE_DEFAULT
;
1216 r
= parse_operational_state_range(rvalue
, &range
);
1218 r
= parse_boolean(rvalue
);
1220 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
1221 "Failed to parse %s= setting, ignoring assignment: %s",
1227 range
= LINK_OPERSTATE_RANGE_DEFAULT
;
1230 network
->required_for_online
= required
;
1231 network
->required_operstate_for_online
= range
;
1236 int config_parse_link_group(
1238 const char *filename
,
1240 const char *section
,
1241 unsigned section_line
,
1248 Network
*network
= ASSERT_PTR(userdata
);
1256 if (isempty(rvalue
)) {
1257 network
->group
= -1;
1261 r
= safe_atoi32(rvalue
, &group
);
1263 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
1264 "Failed to parse Group=, ignoring assignment: %s", rvalue
);
1269 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
1270 "Value of Group= must be in the range 0…2147483647, ignoring assignment: %s", rvalue
);
1274 network
->group
= group
;
1278 int config_parse_ignore_carrier_loss(
1280 const char *filename
,
1282 const char *section
,
1283 unsigned section_line
,
1290 Network
*network
= ASSERT_PTR(userdata
);
1298 if (isempty(rvalue
)) {
1299 network
->ignore_carrier_loss_set
= false;
1303 r
= parse_boolean(rvalue
);
1305 network
->ignore_carrier_loss_set
= true;
1306 network
->ignore_carrier_loss_usec
= r
> 0 ? USEC_INFINITY
: 0;
1310 r
= parse_sec(rvalue
, &usec
);
1312 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
1313 "Failed to parse %s=, ignoring assignment: %s", lvalue
, rvalue
);
1317 network
->ignore_carrier_loss_set
= true;
1318 network
->ignore_carrier_loss_usec
= usec
;
1322 DEFINE_CONFIG_PARSE_ENUM(config_parse_required_family_for_online
, link_required_address_family
, AddressFamily
,
1323 "Failed to parse RequiredFamilyForOnline= setting");
1325 DEFINE_CONFIG_PARSE_ENUM(config_parse_keep_configuration
, keep_configuration
, KeepConfiguration
,
1326 "Failed to parse KeepConfiguration= setting");
1328 static const char* const keep_configuration_table
[_KEEP_CONFIGURATION_MAX
] = {
1329 [KEEP_CONFIGURATION_NO
] = "no",
1330 [KEEP_CONFIGURATION_DHCP_ON_STOP
] = "dhcp-on-stop",
1331 [KEEP_CONFIGURATION_DHCP
] = "dhcp",
1332 [KEEP_CONFIGURATION_STATIC
] = "static",
1333 [KEEP_CONFIGURATION_YES
] = "yes",
1336 DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(keep_configuration
, KeepConfiguration
, KEEP_CONFIGURATION_YES
);
1338 static const char* const activation_policy_table
[_ACTIVATION_POLICY_MAX
] = {
1339 [ACTIVATION_POLICY_UP
] = "up",
1340 [ACTIVATION_POLICY_ALWAYS_UP
] = "always-up",
1341 [ACTIVATION_POLICY_MANUAL
] = "manual",
1342 [ACTIVATION_POLICY_ALWAYS_DOWN
] = "always-down",
1343 [ACTIVATION_POLICY_DOWN
] = "down",
1344 [ACTIVATION_POLICY_BOUND
] = "bound",
1347 DEFINE_STRING_TABLE_LOOKUP(activation_policy
, ActivationPolicy
);
1348 DEFINE_CONFIG_PARSE_ENUM(config_parse_activation_policy
, activation_policy
, ActivationPolicy
, "Failed to parse activation policy");