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-dhcp-server.h"
24 #include "networkd-ipv6-proxy-ndp.h"
25 #include "networkd-manager.h"
26 #include "networkd-ndisc.h"
27 #include "networkd-neighbor.h"
28 #include "networkd-network.h"
29 #include "networkd-nexthop.h"
30 #include "networkd-radv.h"
31 #include "networkd-route.h"
32 #include "networkd-routing-policy-rule.h"
33 #include "networkd-sriov.h"
34 #include "parse-util.h"
35 #include "path-lookup.h"
37 #include "radv-internal.h"
39 #include "socket-util.h"
40 #include "stat-util.h"
41 #include "string-table.h"
42 #include "string-util.h"
46 /* Let's assume that anything above this number is a user misconfiguration. */
47 #define MAX_NTP_SERVERS 128U
49 static int network_resolve_netdev_one(Network
*network
, const char *name
, NetDevKind kind
, NetDev
**ret
) {
50 const char *kind_string
;
54 /* For test-networkd-conf, the check must be earlier than the assertions. */
59 assert(network
->manager
);
60 assert(network
->filename
);
63 if (kind
== _NETDEV_KIND_TUNNEL
)
64 kind_string
= "tunnel";
66 kind_string
= netdev_kind_to_string(kind
);
68 return log_warning_errno(SYNTHETIC_ERRNO(EINVAL
),
69 "%s: Invalid NetDev kind of %s, ignoring assignment.",
70 network
->filename
, name
);
73 r
= netdev_get(network
->manager
, name
, &netdev
);
75 return log_warning_errno(r
, "%s: %s NetDev could not be found, ignoring assignment.",
76 network
->filename
, name
);
78 if (netdev
->kind
!= kind
&& !(kind
== _NETDEV_KIND_TUNNEL
&&
84 NETDEV_KIND_IP6GRETAP
,
90 return log_warning_errno(SYNTHETIC_ERRNO(EINVAL
),
91 "%s: NetDev %s is not a %s, ignoring assignment",
92 network
->filename
, name
, kind_string
);
94 *ret
= netdev_ref(netdev
);
98 static int network_resolve_stacked_netdevs(Network
*network
) {
104 HASHMAP_FOREACH_KEY(kind
, name
, network
->stacked_netdev_names
) {
105 _cleanup_(netdev_unrefp
) NetDev
*netdev
= NULL
;
107 if (network_resolve_netdev_one(network
, name
, PTR_TO_INT(kind
), &netdev
) <= 0)
110 r
= hashmap_ensure_put(&network
->stacked_netdevs
, &string_hash_ops
, netdev
->ifname
, netdev
);
114 log_warning_errno(r
, "%s: Failed to add NetDev '%s' to network, ignoring: %m",
115 network
->filename
, (const char *) name
);
123 int network_verify(Network
*network
) {
127 assert(network
->manager
);
128 assert(network
->filename
);
130 if (net_match_is_empty(&network
->match
) && !network
->conditions
)
131 return log_warning_errno(SYNTHETIC_ERRNO(EINVAL
),
132 "%s: No valid settings found in the [Match] section, ignoring file. "
133 "To match all interfaces, add Name=* in the [Match] section.",
136 /* skip out early if configuration does not match the environment */
137 if (!condition_test_list(network
->conditions
, environ
, NULL
, NULL
, NULL
))
138 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL
),
139 "%s: Conditions in the file do not match the system environment, skipping.",
142 if (network
->keep_master
) {
143 if (network
->batadv_name
)
144 log_warning("%s: BatmanAdvanced= set with KeepMaster= enabled, ignoring BatmanAdvanced=.",
146 if (network
->bond_name
)
147 log_warning("%s: Bond= set with KeepMaster= enabled, ignoring Bond=.",
149 if (network
->bridge_name
)
150 log_warning("%s: Bridge= set with KeepMaster= enabled, ignoring Bridge=.",
152 if (network
->vrf_name
)
153 log_warning("%s: VRF= set with KeepMaster= enabled, ignoring VRF=.",
156 network
->batadv_name
= mfree(network
->batadv_name
);
157 network
->bond_name
= mfree(network
->bond_name
);
158 network
->bridge_name
= mfree(network
->bridge_name
);
159 network
->vrf_name
= mfree(network
->vrf_name
);
162 (void) network_resolve_netdev_one(network
, network
->batadv_name
, NETDEV_KIND_BATADV
, &network
->batadv
);
163 (void) network_resolve_netdev_one(network
, network
->bond_name
, NETDEV_KIND_BOND
, &network
->bond
);
164 (void) network_resolve_netdev_one(network
, network
->bridge_name
, NETDEV_KIND_BRIDGE
, &network
->bridge
);
165 (void) network_resolve_netdev_one(network
, network
->vrf_name
, NETDEV_KIND_VRF
, &network
->vrf
);
166 r
= network_resolve_stacked_netdevs(network
);
170 /* Free unnecessary entries. */
171 network
->batadv_name
= mfree(network
->batadv_name
);
172 network
->bond_name
= mfree(network
->bond_name
);
173 network
->bridge_name
= mfree(network
->bridge_name
);
174 network
->vrf_name
= mfree(network
->vrf_name
);
175 network
->stacked_netdev_names
= hashmap_free_free_key(network
->stacked_netdev_names
);
178 /* Bonding slave does not support addressing. */
179 if (network
->link_local
>= 0 && network
->link_local
!= ADDRESS_FAMILY_NO
) {
180 log_warning("%s: Cannot enable LinkLocalAddressing= when Bond= is specified, disabling LinkLocalAddressing=.",
182 network
->link_local
= ADDRESS_FAMILY_NO
;
184 if (network
->dhcp_server
) {
185 log_warning("%s: Cannot enable DHCPServer= when Bond= is specified, disabling DHCPServer=.",
187 network
->dhcp_server
= false;
189 if (!ordered_hashmap_isempty(network
->addresses_by_section
))
190 log_warning("%s: Cannot set addresses when Bond= is specified, ignoring addresses.",
192 if (!hashmap_isempty(network
->routes_by_section
))
193 log_warning("%s: Cannot set routes when Bond= is specified, ignoring routes.",
196 network
->addresses_by_section
= ordered_hashmap_free_with_destructor(network
->addresses_by_section
, address_free
);
197 network
->routes_by_section
= hashmap_free_with_destructor(network
->routes_by_section
, route_free
);
200 if (network
->link_local
< 0) {
201 network
->link_local
= ADDRESS_FAMILY_IPV6
;
203 if (network
->keep_master
|| network
->bridge
)
204 network
->link_local
= ADDRESS_FAMILY_NO
;
208 HASHMAP_FOREACH(netdev
, network
->stacked_netdevs
) {
211 if (netdev
->kind
== NETDEV_KIND_MACVLAN
)
213 else if (netdev
->kind
== NETDEV_KIND_MACVTAP
)
220 if (m
->mode
== NETDEV_MACVLAN_MODE_PASSTHRU
)
221 network
->link_local
= ADDRESS_FAMILY_NO
;
223 /* There won't be a passthru MACVLAN/MACVTAP if there's already one in another mode */
229 if (network
->ipv6ll_address_gen_mode
== IPV6_LINK_LOCAL_ADDRESSS_GEN_MODE_NONE
)
230 SET_FLAG(network
->link_local
, ADDRESS_FAMILY_IPV6
, false);
232 if (in6_addr_is_set(&network
->ipv6ll_stable_secret
) &&
233 network
->ipv6ll_address_gen_mode
< 0)
234 network
->ipv6ll_address_gen_mode
= IPV6_LINK_LOCAL_ADDRESSS_GEN_MODE_STABLE_PRIVACY
;
236 /* IPMasquerade implies IPForward */
237 network
->ip_forward
|= network
->ip_masquerade
;
239 network_adjust_ipv6_proxy_ndp(network
);
240 network_adjust_ipv6_accept_ra(network
);
241 network_adjust_dhcp(network
);
242 network_adjust_radv(network
);
243 network_adjust_bridge_vlan(network
);
245 if (network
->mtu
> 0 && network
->dhcp_use_mtu
) {
246 log_warning("%s: MTUBytes= in [Link] section and UseMTU= in [DHCP] section are set. "
247 "Disabling UseMTU=.", network
->filename
);
248 network
->dhcp_use_mtu
= false;
251 if (network
->dhcp_critical
>= 0) {
252 if (network
->keep_configuration
>= 0) {
253 if (network
->manager
->keep_configuration
< 0)
254 log_warning("%s: Both KeepConfiguration= and deprecated CriticalConnection= are set. "
255 "Ignoring CriticalConnection=.", network
->filename
);
256 } else if (network
->dhcp_critical
)
257 /* CriticalConnection=yes also preserve foreign static configurations. */
258 network
->keep_configuration
= KEEP_CONFIGURATION_YES
;
260 network
->keep_configuration
= KEEP_CONFIGURATION_NO
;
263 if (!strv_isempty(network
->bind_carrier
)) {
264 if (!IN_SET(network
->activation_policy
, _ACTIVATION_POLICY_INVALID
, ACTIVATION_POLICY_BOUND
))
265 log_warning("%s: ActivationPolicy=bound is required with BindCarrier=. "
266 "Setting ActivationPolicy=bound.", network
->filename
);
267 network
->activation_policy
= ACTIVATION_POLICY_BOUND
;
268 } else if (network
->activation_policy
== ACTIVATION_POLICY_BOUND
) {
269 log_warning("%s: ActivationPolicy=bound requires BindCarrier=. "
270 "Ignoring ActivationPolicy=bound.", network
->filename
);
271 network
->activation_policy
= ACTIVATION_POLICY_UP
;
274 if (network
->activation_policy
== _ACTIVATION_POLICY_INVALID
)
275 network
->activation_policy
= ACTIVATION_POLICY_UP
;
277 if (network
->activation_policy
== ACTIVATION_POLICY_ALWAYS_UP
) {
278 if (network
->ignore_carrier_loss_set
&& network
->ignore_carrier_loss_usec
< USEC_INFINITY
)
279 log_warning("%s: IgnoreCarrierLoss=no or finite timespan conflicts with ActivationPolicy=always-up. "
280 "Setting IgnoreCarrierLoss=yes.", network
->filename
);
281 network
->ignore_carrier_loss_set
= true;
282 network
->ignore_carrier_loss_usec
= USEC_INFINITY
;
285 if (!network
->ignore_carrier_loss_set
) {
286 network
->ignore_carrier_loss_set
= true;
287 network
->ignore_carrier_loss_usec
= network
->configure_without_carrier
? USEC_INFINITY
: 0;
290 if (IN_SET(network
->activation_policy
, ACTIVATION_POLICY_DOWN
, ACTIVATION_POLICY_ALWAYS_DOWN
, ACTIVATION_POLICY_MANUAL
)) {
291 if (network
->required_for_online
< 0 ||
292 (network
->required_for_online
== true && network
->activation_policy
== ACTIVATION_POLICY_ALWAYS_DOWN
)) {
293 log_debug("%s: Setting RequiredForOnline=no because ActivationPolicy=%s.", network
->filename
,
294 activation_policy_to_string(network
->activation_policy
));
295 network
->required_for_online
= false;
296 } else if (network
->required_for_online
== true)
297 log_warning("%s: RequiredForOnline=yes and ActivationPolicy=%s, "
298 "this may cause a delay at boot.", network
->filename
,
299 activation_policy_to_string(network
->activation_policy
));
302 if (network
->required_for_online
< 0)
303 network
->required_for_online
= true;
305 if (network
->keep_configuration
< 0)
306 network
->keep_configuration
= KEEP_CONFIGURATION_NO
;
308 if (network
->ipv6_proxy_ndp
== 0 && !set_isempty(network
->ipv6_proxy_ndp_addresses
)) {
309 log_warning("%s: IPv6ProxyNDP= is disabled. Ignoring IPv6ProxyNDPAddress=.", network
->filename
);
310 network
->ipv6_proxy_ndp_addresses
= set_free_free(network
->ipv6_proxy_ndp_addresses
);
313 r
= network_drop_invalid_addresses(network
);
315 return r
; /* network_drop_invalid_addresses() logs internally. */
316 network_drop_invalid_routes(network
);
317 network_drop_invalid_nexthops(network
);
318 network_drop_invalid_bridge_fdb_entries(network
);
319 network_drop_invalid_bridge_mdb_entries(network
);
320 r
= network_drop_invalid_neighbors(network
);
323 network_drop_invalid_address_labels(network
);
324 network_drop_invalid_prefixes(network
);
325 network_drop_invalid_route_prefixes(network
);
326 network_drop_invalid_routing_policy_rules(network
);
327 network_drop_invalid_qdisc(network
);
328 network_drop_invalid_tclass(network
);
329 r
= sr_iov_drop_invalid_sections(UINT32_MAX
, network
->sr_iov_by_section
);
331 return r
; /* sr_iov_drop_invalid_sections() logs internally. */
332 network_drop_invalid_static_leases(network
);
334 network_adjust_dhcp_server(network
);
339 int network_load_one(Manager
*manager
, OrderedHashmap
**networks
, const char *filename
) {
340 _cleanup_free_
char *fname
= NULL
, *name
= NULL
;
341 _cleanup_(network_unrefp
) Network
*network
= NULL
;
342 const char *dropin_dirname
;
349 r
= null_or_empty_path(filename
);
351 return log_warning_errno(r
, "Failed to check if \"%s\" is empty: %m", filename
);
353 log_debug("Skipping empty file: %s", filename
);
357 fname
= strdup(filename
);
361 name
= strdup(basename(filename
));
365 d
= strrchr(name
, '.');
367 return log_warning_errno(SYNTHETIC_ERRNO(EINVAL
), "Invalid file name: %s", filename
);
371 dropin_dirname
= strjoina(name
, ".network.d");
373 network
= new(Network
, 1);
377 *network
= (Network
) {
378 .filename
= TAKE_PTR(fname
),
379 .name
= TAKE_PTR(name
),
384 .required_for_online
= -1,
385 .required_operstate_for_online
= LINK_OPERSTATE_RANGE_DEFAULT
,
386 .activation_policy
= _ACTIVATION_POLICY_INVALID
,
393 .keep_configuration
= manager
->keep_configuration
,
395 .dhcp_duid
.type
= _DUID_TYPE_INVALID
,
397 .dhcp_use_ntp
= true,
398 .dhcp_routes_to_ntp
= true,
399 .dhcp_use_sip
= true,
400 .dhcp_use_captive_portal
= true,
401 .dhcp_use_dns
= true,
402 .dhcp_routes_to_dns
= true,
403 .dhcp_use_hostname
= true,
404 .dhcp_use_routes
= true,
405 .dhcp_use_gateway
= -1,
406 .dhcp_send_hostname
= true,
407 .dhcp_send_release
= true,
408 .dhcp_route_metric
= DHCP_ROUTE_METRIC
,
409 .dhcp_client_identifier
= _DHCP_CLIENT_ID_INVALID
,
410 .dhcp_route_table
= RT_TABLE_MAIN
,
411 .dhcp_ip_service_type
= -1,
412 .dhcp_broadcast
= -1,
414 .dhcp6_use_address
= true,
415 .dhcp6_use_pd_prefix
= true,
416 .dhcp6_use_dns
= true,
417 .dhcp6_use_hostname
= true,
418 .dhcp6_use_ntp
= true,
419 .dhcp6_use_captive_portal
= true,
420 .dhcp6_use_rapid_commit
= true,
421 .dhcp6_duid
.type
= _DUID_TYPE_INVALID
,
422 .dhcp6_client_start_mode
= _DHCP6_CLIENT_START_MODE_INVALID
,
423 .dhcp6_send_release
= true,
426 .dhcp_pd_announce
= true,
427 .dhcp_pd_assign
= true,
428 .dhcp_pd_manage_temporary_address
= true,
429 .dhcp_pd_subnet_id
= -1,
430 .dhcp_pd_route_metric
= DHCP6PD_ROUTE_METRIC
,
432 .dhcp_server_bind_to_interface
= true,
433 .dhcp_server_emit
[SD_DHCP_LEASE_DNS
].emit
= true,
434 .dhcp_server_emit
[SD_DHCP_LEASE_NTP
].emit
= true,
435 .dhcp_server_emit
[SD_DHCP_LEASE_SIP
].emit
= true,
436 .dhcp_server_emit_router
= true,
437 .dhcp_server_emit_timezone
= true,
439 .router_lifetime_usec
= RADV_DEFAULT_ROUTER_LIFETIME_USEC
,
440 .router_dns_lifetime_usec
= RADV_DEFAULT_VALID_LIFETIME_USEC
,
441 .router_emit_dns
= true,
442 .router_emit_domains
= true,
448 .allow_port_to_be_root
= -1,
450 .multicast_flood
= -1,
451 .multicast_to_unicast
= -1,
452 .neighbor_suppression
= -1,
454 .bridge_proxy_arp
= -1,
455 .bridge_proxy_arp_wifi
= -1,
456 .priority
= LINK_BRIDGE_PORT_PRIORITY_INVALID
,
457 .multicast_router
= _MULTICAST_ROUTER_INVALID
,
459 .lldp_mode
= LLDP_MODE_ROUTERS_ONLY
,
460 .lldp_multicast_mode
= _SD_LLDP_MULTICAST_MODE_INVALID
,
462 .dns_default_route
= -1,
463 .llmnr
= RESOLVE_SUPPORT_YES
,
464 .mdns
= RESOLVE_SUPPORT_NO
,
465 .dnssec_mode
= _DNSSEC_MODE_INVALID
,
466 .dns_over_tls_mode
= _DNS_OVER_TLS_MODE_INVALID
,
468 /* If LinkLocalAddressing= is not set, then set to ADDRESS_FAMILY_IPV6 later. */
469 .link_local
= _ADDRESS_FAMILY_INVALID
,
470 .ipv6ll_address_gen_mode
= _IPV6_LINK_LOCAL_ADDRESS_GEN_MODE_INVALID
,
472 .ipv4_accept_local
= -1,
473 .ipv4_route_localnet
= -1,
474 .ipv6_privacy_extensions
= _IPV6_PRIVACY_EXTENSIONS_INVALID
,
475 .ipv6_dad_transmits
= -1,
476 .ipv6_hop_limit
= -1,
477 .ipv6_proxy_ndp
= -1,
479 .ipv4_rp_filter
= _IP_REVERSE_PATH_FILTER_INVALID
,
481 .ipv6_accept_ra
= -1,
482 .ipv6_accept_ra_use_dns
= true,
483 .ipv6_accept_ra_use_gateway
= true,
484 .ipv6_accept_ra_use_captive_portal
= true,
485 .ipv6_accept_ra_use_route_prefix
= true,
486 .ipv6_accept_ra_use_autonomous_prefix
= true,
487 .ipv6_accept_ra_use_onlink_prefix
= true,
488 .ipv6_accept_ra_use_mtu
= true,
489 .ipv6_accept_ra_use_hop_limit
= true,
490 .ipv6_accept_ra_use_icmp6_ratelimit
= true,
491 .ipv6_accept_ra_route_table
= RT_TABLE_MAIN
,
492 .ipv6_accept_ra_route_metric_high
= IPV6RA_ROUTE_METRIC_HIGH
,
493 .ipv6_accept_ra_route_metric_medium
= IPV6RA_ROUTE_METRIC_MEDIUM
,
494 .ipv6_accept_ra_route_metric_low
= IPV6RA_ROUTE_METRIC_LOW
,
495 .ipv6_accept_ra_start_dhcp6_client
= IPV6_ACCEPT_RA_START_DHCP6_CLIENT_YES
,
497 .can_termination
= -1,
499 .ipoib_mode
= _IP_OVER_INFINIBAND_MODE_INVALID
,
503 r
= config_parse_many(
504 STRV_MAKE_CONST(filename
), NETWORK_DIRS
, dropin_dirname
, /* root = */ NULL
,
512 "RoutingPolicyRule\0"
515 "DHCP\0" /* compat */
518 "DHCPv6PrefixDelegation\0" /* compat */
519 "DHCPPrefixDelegation\0"
521 "DHCPServerStaticLease\0"
523 "IPv6NDPProxyAddress\0"
529 "IPv6PrefixDelegation\0"
534 "TrafficControlQueueingDiscipline\0"
540 "DeficitRoundRobinScheduler\0"
541 "DeficitRoundRobinSchedulerClass\0"
542 "EnhancedTransmissionSelection\0"
544 "FairQueueingControlledDelay\0"
546 "GenericRandomEarlyDetection\0"
547 "HeavyHitterFilter\0"
548 "HierarchyTokenBucket\0"
549 "HierarchyTokenBucketClass\0"
555 "QuickFairQueueing\0"
556 "QuickFairQueueingClass\0"
557 "StochasticFairBlue\0"
558 "StochasticFairnessQueueing\0"
559 "TokenBucketFilter\0"
560 "TrivialLinkEqualizer\0",
561 config_item_perf_lookup
, network_network_gperf_lookup
,
564 &network
->stats_by_path
,
567 return r
; /* config_parse_many() logs internally. */
569 r
= network_add_ipv4ll_route(network
);
571 return log_warning_errno(r
, "%s: Failed to add IPv4LL route: %m", network
->filename
);
573 r
= network_add_default_route_on_device(network
);
575 return log_warning_errno(r
, "%s: Failed to add default route on device: %m",
578 r
= network_verify(network
);
580 return r
; /* network_verify() logs internally. */
582 r
= ordered_hashmap_ensure_put(networks
, &string_hash_ops
, network
->name
, network
);
584 return log_warning_errno(r
, "%s: Failed to store configuration into hashmap: %m", filename
);
590 int network_load(Manager
*manager
, OrderedHashmap
**networks
) {
591 _cleanup_strv_free_
char **files
= NULL
;
596 ordered_hashmap_clear_with_destructor(*networks
, network_unref
);
598 r
= conf_files_list_strv(&files
, ".network", NULL
, 0, NETWORK_DIRS
);
600 return log_error_errno(r
, "Failed to enumerate network files: %m");
602 STRV_FOREACH(f
, files
)
603 (void) network_load_one(manager
, networks
, *f
);
608 int network_reload(Manager
*manager
) {
609 OrderedHashmap
*new_networks
= NULL
;
615 r
= network_load(manager
, &new_networks
);
619 ORDERED_HASHMAP_FOREACH(n
, new_networks
) {
620 r
= network_get_by_name(manager
, n
->name
, &old
);
622 log_debug("Found new .network file: %s", n
->filename
);
626 if (!stats_by_path_equal(n
->stats_by_path
, old
->stats_by_path
)) {
627 log_debug("Found updated .network file: %s", n
->filename
);
631 r
= ordered_hashmap_replace(new_networks
, old
->name
, old
);
639 ordered_hashmap_free_with_destructor(manager
->networks
, network_unref
);
640 manager
->networks
= new_networks
;
642 return manager_build_dhcp_pd_subnet_ids(manager
);
645 ordered_hashmap_free_with_destructor(new_networks
, network_unref
);
650 int manager_build_dhcp_pd_subnet_ids(Manager
*manager
) {
656 set_clear(manager
->dhcp_pd_subnet_ids
);
658 ORDERED_HASHMAP_FOREACH(n
, manager
->networks
) {
665 if (n
->dhcp_pd_subnet_id
< 0)
668 r
= set_ensure_put(&manager
->dhcp_pd_subnet_ids
, &uint64_hash_ops
, &n
->dhcp_pd_subnet_id
);
676 static Network
*network_free(Network
*network
) {
681 free(network
->filename
);
682 free(network
->description
);
683 strv_free(network
->dropins
);
684 hashmap_free(network
->stats_by_path
);
687 net_match_clear(&network
->match
);
688 condition_free_list(network
->conditions
);
691 strv_free(network
->bind_carrier
);
694 strv_free(network
->ntp
);
697 for (unsigned i
= 0; i
< network
->n_dns
; i
++)
698 in_addr_full_free(network
->dns
[i
]);
700 ordered_set_free(network
->search_domains
);
701 ordered_set_free(network
->route_domains
);
702 set_free_free(network
->dnssec_negative_trust_anchors
);
705 free(network
->dhcp_server_relay_agent_circuit_id
);
706 free(network
->dhcp_server_relay_agent_remote_id
);
707 free(network
->dhcp_server_boot_server_name
);
708 free(network
->dhcp_server_boot_filename
);
709 free(network
->dhcp_server_timezone
);
710 free(network
->dhcp_server_uplink_name
);
711 for (sd_dhcp_lease_server_type_t t
= 0; t
< _SD_DHCP_LEASE_SERVER_TYPE_MAX
; t
++)
712 free(network
->dhcp_server_emit
[t
].addresses
);
713 ordered_hashmap_free(network
->dhcp_server_send_options
);
714 ordered_hashmap_free(network
->dhcp_server_send_vendor_options
);
717 free(network
->dhcp_vendor_class_identifier
);
718 free(network
->dhcp_mudurl
);
719 free(network
->dhcp_hostname
);
720 free(network
->dhcp_label
);
721 set_free(network
->dhcp_deny_listed_ip
);
722 set_free(network
->dhcp_allow_listed_ip
);
723 strv_free(network
->dhcp_user_class
);
724 set_free(network
->dhcp_request_options
);
725 ordered_hashmap_free(network
->dhcp_client_send_options
);
726 ordered_hashmap_free(network
->dhcp_client_send_vendor_options
);
727 free(network
->dhcp_netlabel
);
728 nft_set_context_clear(&network
->dhcp_nft_set_context
);
731 free(network
->dhcp6_mudurl
);
732 strv_free(network
->dhcp6_user_class
);
733 strv_free(network
->dhcp6_vendor_class
);
734 set_free(network
->dhcp6_request_options
);
735 ordered_hashmap_free(network
->dhcp6_client_send_options
);
736 ordered_hashmap_free(network
->dhcp6_client_send_vendor_options
);
737 free(network
->dhcp6_netlabel
);
738 nft_set_context_clear(&network
->dhcp6_nft_set_context
);
741 free(network
->dhcp_pd_uplink_name
);
742 set_free(network
->dhcp_pd_tokens
);
743 free(network
->dhcp_pd_netlabel
);
744 nft_set_context_clear(&network
->dhcp_pd_nft_set_context
);
746 /* Router advertisement */
747 ordered_set_free(network
->router_search_domains
);
748 free(network
->router_dns
);
749 free(network
->router_uplink_name
);
752 set_free(network
->ndisc_deny_listed_router
);
753 set_free(network
->ndisc_allow_listed_router
);
754 set_free(network
->ndisc_deny_listed_prefix
);
755 set_free(network
->ndisc_allow_listed_prefix
);
756 set_free(network
->ndisc_deny_listed_route_prefix
);
757 set_free(network
->ndisc_allow_listed_route_prefix
);
758 set_free(network
->ndisc_tokens
);
759 free(network
->ndisc_netlabel
);
760 nft_set_context_clear(&network
->ndisc_nft_set_context
);
763 free(network
->lldp_mudurl
);
766 free(network
->batadv_name
);
767 free(network
->bridge_name
);
768 free(network
->bond_name
);
769 free(network
->vrf_name
);
770 hashmap_free_free_key(network
->stacked_netdev_names
);
771 netdev_unref(network
->bridge
);
772 netdev_unref(network
->bond
);
773 netdev_unref(network
->vrf
);
774 hashmap_free_with_destructor(network
->stacked_netdevs
, netdev_unref
);
777 set_free_free(network
->ipv6_proxy_ndp_addresses
);
778 ordered_hashmap_free_with_destructor(network
->addresses_by_section
, address_free
);
779 hashmap_free_with_destructor(network
->routes_by_section
, route_free
);
780 hashmap_free_with_destructor(network
->nexthops_by_section
, nexthop_free
);
781 hashmap_free_with_destructor(network
->bridge_fdb_entries_by_section
, bridge_fdb_free
);
782 hashmap_free_with_destructor(network
->bridge_mdb_entries_by_section
, bridge_mdb_free
);
783 ordered_hashmap_free_with_destructor(network
->neighbors_by_section
, neighbor_free
);
784 hashmap_free_with_destructor(network
->address_labels_by_section
, address_label_free
);
785 hashmap_free_with_destructor(network
->prefixes_by_section
, prefix_free
);
786 hashmap_free_with_destructor(network
->route_prefixes_by_section
, route_prefix_free
);
787 hashmap_free_with_destructor(network
->pref64_prefixes_by_section
, pref64_prefix_free
);
788 hashmap_free_with_destructor(network
->rules_by_section
, routing_policy_rule_free
);
789 hashmap_free_with_destructor(network
->dhcp_static_leases_by_section
, dhcp_static_lease_free
);
790 ordered_hashmap_free_with_destructor(network
->sr_iov_by_section
, sr_iov_free
);
791 hashmap_free_with_destructor(network
->qdiscs_by_section
, qdisc_free
);
792 hashmap_free_with_destructor(network
->tclasses_by_section
, tclass_free
);
794 return mfree(network
);
797 DEFINE_TRIVIAL_REF_UNREF_FUNC(Network
, network
, network_free
);
799 int network_get_by_name(Manager
*manager
, const char *name
, Network
**ret
) {
806 network
= ordered_hashmap_get(manager
->networks
, name
);
815 bool network_has_static_ipv6_configurations(Network
*network
) {
824 ORDERED_HASHMAP_FOREACH(address
, network
->addresses_by_section
)
825 if (address
->family
== AF_INET6
)
828 HASHMAP_FOREACH(route
, network
->routes_by_section
)
829 if (route
->family
== AF_INET6
)
832 HASHMAP_FOREACH(fdb
, network
->bridge_fdb_entries_by_section
)
833 if (fdb
->family
== AF_INET6
)
836 HASHMAP_FOREACH(mdb
, network
->bridge_mdb_entries_by_section
)
837 if (mdb
->family
== AF_INET6
)
840 ORDERED_HASHMAP_FOREACH(neighbor
, network
->neighbors_by_section
)
841 if (neighbor
->family
== AF_INET6
)
844 if (!hashmap_isempty(network
->address_labels_by_section
))
847 if (!hashmap_isempty(network
->prefixes_by_section
))
850 if (!hashmap_isempty(network
->route_prefixes_by_section
))
853 if (!hashmap_isempty(network
->pref64_prefixes_by_section
))
859 int config_parse_stacked_netdev(
861 const char *filename
,
864 unsigned section_line
,
871 _cleanup_free_
char *name
= NULL
;
872 NetDevKind kind
= ltype
;
873 Hashmap
**h
= ASSERT_PTR(data
);
889 _NETDEV_KIND_TUNNEL
));
891 if (!ifname_valid(rvalue
)) {
892 log_syntax(unit
, LOG_WARNING
, filename
, line
, 0,
893 "Invalid netdev name in %s=, ignoring assignment: %s", lvalue
, rvalue
);
897 name
= strdup(rvalue
);
901 r
= hashmap_ensure_put(h
, &string_hash_ops
, name
, INT_TO_PTR(kind
));
905 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
906 "Cannot add NetDev '%s' to network, ignoring assignment: %m", name
);
908 log_syntax(unit
, LOG_DEBUG
, filename
, line
, r
,
909 "NetDev '%s' specified twice, ignoring.", name
);
916 int config_parse_domains(
918 const char *filename
,
921 unsigned section_line
,
928 Network
*n
= ASSERT_PTR(userdata
);
935 if (isempty(rvalue
)) {
936 n
->search_domains
= ordered_set_free(n
->search_domains
);
937 n
->route_domains
= ordered_set_free(n
->route_domains
);
941 for (const char *p
= rvalue
;;) {
942 _cleanup_free_
char *w
= NULL
, *normalized
= NULL
;
946 r
= extract_first_word(&p
, &w
, NULL
, 0);
950 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
951 "Failed to extract search or route domain, ignoring: %s", rvalue
);
957 is_route
= w
[0] == '~';
958 domain
= is_route
? w
+ 1 : w
;
960 if (dns_name_is_root(domain
) || streq(domain
, "*")) {
961 /* If the root domain appears as is, or the special token "*" is found, we'll
962 * consider this as routing domain, unconditionally. */
964 domain
= "."; /* make sure we don't allow empty strings, thus write the root
967 r
= dns_name_normalize(domain
, 0, &normalized
);
969 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
970 "'%s' is not a valid domain name, ignoring.", domain
);
976 if (is_localhost(domain
)) {
977 log_syntax(unit
, LOG_WARNING
, filename
, line
, 0,
978 "'localhost' domain may not be configured as search or route domain, ignoring assignment: %s",
984 OrderedSet
**set
= is_route
? &n
->route_domains
: &n
->search_domains
;
985 r
= ordered_set_put_strdup(set
, domain
);
993 int config_parse_timezone(
995 const char *filename
,
998 unsigned section_line
,
1005 char **tz
= ASSERT_PTR(data
);
1012 if (isempty(rvalue
)) {
1017 r
= verify_timezone(rvalue
, LOG_WARNING
);
1019 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
1020 "Timezone is not valid, ignoring assignment: %s", rvalue
);
1024 return free_and_strdup_warn(tz
, rvalue
);
1027 int config_parse_dns(
1029 const char *filename
,
1031 const char *section
,
1032 unsigned section_line
,
1039 Network
*n
= ASSERT_PTR(userdata
);
1046 if (isempty(rvalue
)) {
1047 for (unsigned i
= 0; i
< n
->n_dns
; i
++)
1048 in_addr_full_free(n
->dns
[i
]);
1049 n
->dns
= mfree(n
->dns
);
1054 for (const char *p
= rvalue
;;) {
1055 _cleanup_(in_addr_full_freep
) struct in_addr_full
*dns
= NULL
;
1056 _cleanup_free_
char *w
= NULL
;
1057 struct in_addr_full
**m
;
1059 r
= extract_first_word(&p
, &w
, NULL
, 0);
1063 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
1064 "Invalid syntax, ignoring: %s", rvalue
);
1070 r
= in_addr_full_new_from_string(w
, &dns
);
1072 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
1073 "Failed to parse dns server address, ignoring: %s", w
);
1077 if (IN_SET(dns
->port
, 53, 853))
1080 m
= reallocarray(n
->dns
, n
->n_dns
+ 1, sizeof(struct in_addr_full
*));
1084 m
[n
->n_dns
++] = TAKE_PTR(dns
);
1089 int config_parse_dnssec_negative_trust_anchors(
1091 const char *filename
,
1093 const char *section
,
1094 unsigned section_line
,
1101 Set
**nta
= ASSERT_PTR(data
);
1108 if (isempty(rvalue
)) {
1109 *nta
= set_free_free(*nta
);
1113 for (const char *p
= rvalue
;;) {
1114 _cleanup_free_
char *w
= NULL
;
1116 r
= extract_first_word(&p
, &w
, NULL
, 0);
1120 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
1121 "Failed to extract negative trust anchor domain, ignoring: %s", rvalue
);
1127 r
= dns_name_is_valid(w
);
1129 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
1130 "%s is not a valid domain name, ignoring.", w
);
1134 r
= set_ensure_consume(nta
, &dns_name_hash_ops
, TAKE_PTR(w
));
1140 int config_parse_ntp(
1142 const char *filename
,
1144 const char *section
,
1145 unsigned section_line
,
1152 char ***l
= ASSERT_PTR(data
);
1159 if (isempty(rvalue
)) {
1164 for (const char *p
= rvalue
;;) {
1165 _cleanup_free_
char *w
= NULL
;
1167 r
= extract_first_word(&p
, &w
, NULL
, 0);
1171 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
1172 "Failed to extract NTP server name, ignoring: %s", rvalue
);
1178 r
= dns_name_is_valid_or_address(w
);
1180 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
1181 "%s is not a valid domain name or IP address, ignoring.", w
);
1185 if (strv_length(*l
) > MAX_NTP_SERVERS
) {
1186 log_syntax(unit
, LOG_WARNING
, filename
, line
, 0,
1187 "More than %u NTP servers specified, ignoring \"%s\" and any subsequent entries.",
1188 MAX_NTP_SERVERS
, w
);
1192 r
= strv_consume(l
, TAKE_PTR(w
));
1198 int config_parse_required_for_online(
1200 const char *filename
,
1202 const char *section
,
1203 unsigned section_line
,
1210 Network
*network
= ASSERT_PTR(userdata
);
1211 LinkOperationalStateRange range
;
1212 bool required
= true;
1219 if (isempty(rvalue
)) {
1220 network
->required_for_online
= -1;
1221 network
->required_operstate_for_online
= LINK_OPERSTATE_RANGE_DEFAULT
;
1225 r
= parse_operational_state_range(rvalue
, &range
);
1227 r
= parse_boolean(rvalue
);
1229 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
1230 "Failed to parse %s= setting, ignoring assignment: %s",
1236 range
= LINK_OPERSTATE_RANGE_DEFAULT
;
1239 network
->required_for_online
= required
;
1240 network
->required_operstate_for_online
= range
;
1245 int config_parse_link_group(
1247 const char *filename
,
1249 const char *section
,
1250 unsigned section_line
,
1257 Network
*network
= ASSERT_PTR(userdata
);
1265 if (isempty(rvalue
)) {
1266 network
->group
= -1;
1270 r
= safe_atoi32(rvalue
, &group
);
1272 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
1273 "Failed to parse Group=, ignoring assignment: %s", rvalue
);
1278 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
1279 "Value of Group= must be in the range 0…2147483647, ignoring assignment: %s", rvalue
);
1283 network
->group
= group
;
1287 int config_parse_ignore_carrier_loss(
1289 const char *filename
,
1291 const char *section
,
1292 unsigned section_line
,
1299 Network
*network
= ASSERT_PTR(userdata
);
1307 if (isempty(rvalue
)) {
1308 network
->ignore_carrier_loss_set
= false;
1312 r
= parse_boolean(rvalue
);
1314 network
->ignore_carrier_loss_set
= true;
1315 network
->ignore_carrier_loss_usec
= r
> 0 ? USEC_INFINITY
: 0;
1319 r
= parse_sec(rvalue
, &usec
);
1321 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
1322 "Failed to parse %s=, ignoring assignment: %s", lvalue
, rvalue
);
1326 network
->ignore_carrier_loss_set
= true;
1327 network
->ignore_carrier_loss_usec
= usec
;
1331 DEFINE_CONFIG_PARSE_ENUM(config_parse_required_family_for_online
, link_required_address_family
, AddressFamily
,
1332 "Failed to parse RequiredFamilyForOnline= setting");
1334 DEFINE_CONFIG_PARSE_ENUM(config_parse_keep_configuration
, keep_configuration
, KeepConfiguration
,
1335 "Failed to parse KeepConfiguration= setting");
1337 static const char* const keep_configuration_table
[_KEEP_CONFIGURATION_MAX
] = {
1338 [KEEP_CONFIGURATION_NO
] = "no",
1339 [KEEP_CONFIGURATION_DHCP_ON_STOP
] = "dhcp-on-stop",
1340 [KEEP_CONFIGURATION_DHCP
] = "dhcp",
1341 [KEEP_CONFIGURATION_STATIC
] = "static",
1342 [KEEP_CONFIGURATION_YES
] = "yes",
1345 DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(keep_configuration
, KeepConfiguration
, KEEP_CONFIGURATION_YES
);
1347 static const char* const activation_policy_table
[_ACTIVATION_POLICY_MAX
] = {
1348 [ACTIVATION_POLICY_UP
] = "up",
1349 [ACTIVATION_POLICY_ALWAYS_UP
] = "always-up",
1350 [ACTIVATION_POLICY_MANUAL
] = "manual",
1351 [ACTIVATION_POLICY_ALWAYS_DOWN
] = "always-down",
1352 [ACTIVATION_POLICY_DOWN
] = "down",
1353 [ACTIVATION_POLICY_BOUND
] = "bound",
1356 DEFINE_STRING_TABLE_LOOKUP(activation_policy
, ActivationPolicy
);
1357 DEFINE_CONFIG_PARSE_ENUM(config_parse_activation_policy
, activation_policy
, ActivationPolicy
, "Failed to parse activation policy");