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"
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"
46 /* Let's assume that anything above this number is a user misconfiguration. */
47 #define MAX_NTP_SERVERS 128
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
);
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 network_drop_invalid_neighbors(network
);
321 network_drop_invalid_address_labels(network
);
322 network_drop_invalid_prefixes(network
);
323 network_drop_invalid_route_prefixes(network
);
324 network_drop_invalid_routing_policy_rules(network
);
325 network_drop_invalid_traffic_control(network
);
326 r
= sr_iov_drop_invalid_sections(UINT32_MAX
, network
->sr_iov_by_section
);
329 network_drop_invalid_static_leases(network
);
331 network_adjust_dhcp_server(network
);
336 int network_load_one(Manager
*manager
, OrderedHashmap
**networks
, const char *filename
) {
337 _cleanup_free_
char *fname
= NULL
, *name
= NULL
;
338 _cleanup_(network_unrefp
) Network
*network
= NULL
;
339 const char *dropin_dirname
;
346 r
= null_or_empty_path(filename
);
352 log_debug("Skipping empty file: %s", filename
);
356 fname
= strdup(filename
);
360 name
= strdup(basename(filename
));
364 d
= strrchr(name
, '.');
370 dropin_dirname
= strjoina(name
, ".network.d");
372 network
= new(Network
, 1);
376 *network
= (Network
) {
377 .filename
= TAKE_PTR(fname
),
378 .name
= TAKE_PTR(name
),
383 .required_for_online
= -1,
384 .required_operstate_for_online
= LINK_OPERSTATE_RANGE_DEFAULT
,
385 .activation_policy
= _ACTIVATION_POLICY_INVALID
,
391 .keep_configuration
= manager
->keep_configuration
,
393 .dhcp_duid
.type
= _DUID_TYPE_INVALID
,
395 .dhcp_use_ntp
= true,
396 .dhcp_routes_to_ntp
= true,
397 .dhcp_use_sip
= true,
398 .dhcp_use_dns
= true,
399 .dhcp_routes_to_dns
= true,
400 .dhcp_use_hostname
= true,
401 .dhcp_use_routes
= true,
402 .dhcp_use_gateway
= -1,
403 .dhcp_send_hostname
= true,
404 .dhcp_send_release
= true,
405 .dhcp_route_metric
= DHCP_ROUTE_METRIC
,
406 .dhcp_client_identifier
= _DHCP_CLIENT_ID_INVALID
,
407 .dhcp_route_table
= RT_TABLE_MAIN
,
408 .dhcp_ip_service_type
= -1,
409 .dhcp_broadcast
= -1,
411 .dhcp6_use_address
= true,
412 .dhcp6_use_pd_prefix
= true,
413 .dhcp6_use_dns
= true,
414 .dhcp6_use_hostname
= true,
415 .dhcp6_use_ntp
= true,
416 .dhcp6_duid
.type
= _DUID_TYPE_INVALID
,
417 .dhcp6_client_start_mode
= _DHCP6_CLIENT_START_MODE_INVALID
,
420 .dhcp_pd_announce
= true,
421 .dhcp_pd_assign
= true,
422 .dhcp_pd_manage_temporary_address
= true,
423 .dhcp_pd_subnet_id
= -1,
424 .dhcp_pd_route_metric
= DHCP6PD_ROUTE_METRIC
,
426 .dhcp_server_bind_to_interface
= true,
427 .dhcp_server_emit
[SD_DHCP_LEASE_DNS
].emit
= true,
428 .dhcp_server_emit
[SD_DHCP_LEASE_NTP
].emit
= true,
429 .dhcp_server_emit
[SD_DHCP_LEASE_SIP
].emit
= true,
430 .dhcp_server_emit_router
= true,
431 .dhcp_server_emit_timezone
= true,
433 .router_lifetime_usec
= RADV_DEFAULT_ROUTER_LIFETIME_USEC
,
434 .router_dns_lifetime_usec
= RADV_DEFAULT_VALID_LIFETIME_USEC
,
435 .router_emit_dns
= true,
436 .router_emit_domains
= true,
442 .allow_port_to_be_root
= -1,
444 .multicast_flood
= -1,
445 .multicast_to_unicast
= -1,
446 .neighbor_suppression
= -1,
448 .bridge_proxy_arp
= -1,
449 .bridge_proxy_arp_wifi
= -1,
450 .priority
= LINK_BRIDGE_PORT_PRIORITY_INVALID
,
451 .multicast_router
= _MULTICAST_ROUTER_INVALID
,
453 .lldp_mode
= LLDP_MODE_ROUTERS_ONLY
,
454 .lldp_multicast_mode
= _SD_LLDP_MULTICAST_MODE_INVALID
,
456 .dns_default_route
= -1,
457 .llmnr
= RESOLVE_SUPPORT_YES
,
458 .mdns
= RESOLVE_SUPPORT_NO
,
459 .dnssec_mode
= _DNSSEC_MODE_INVALID
,
460 .dns_over_tls_mode
= _DNS_OVER_TLS_MODE_INVALID
,
462 /* If LinkLocalAddressing= is not set, then set to ADDRESS_FAMILY_IPV6 later. */
463 .link_local
= _ADDRESS_FAMILY_INVALID
,
464 .ipv6ll_address_gen_mode
= _IPV6_LINK_LOCAL_ADDRESS_GEN_MODE_INVALID
,
466 .ipv4_accept_local
= -1,
467 .ipv4_route_localnet
= -1,
468 .ipv6_privacy_extensions
= IPV6_PRIVACY_EXTENSIONS_NO
,
469 .ipv6_dad_transmits
= -1,
470 .ipv6_hop_limit
= -1,
471 .ipv6_proxy_ndp
= -1,
474 .ipv6_accept_ra
= -1,
475 .ipv6_accept_ra_use_dns
= true,
476 .ipv6_accept_ra_use_gateway
= true,
477 .ipv6_accept_ra_use_route_prefix
= true,
478 .ipv6_accept_ra_use_autonomous_prefix
= true,
479 .ipv6_accept_ra_use_onlink_prefix
= true,
480 .ipv6_accept_ra_use_mtu
= true,
481 .ipv6_accept_ra_route_table
= RT_TABLE_MAIN
,
482 .ipv6_accept_ra_route_metric
= DHCP_ROUTE_METRIC
,
483 .ipv6_accept_ra_start_dhcp6_client
= IPV6_ACCEPT_RA_START_DHCP6_CLIENT_YES
,
485 .can_termination
= -1,
487 .ipoib_mode
= _IP_OVER_INFINIBAND_MODE_INVALID
,
491 r
= config_parse_many(
492 STRV_MAKE_CONST(filename
), NETWORK_DIRS
, dropin_dirname
,
500 "RoutingPolicyRule\0"
503 "DHCP\0" /* compat */
506 "DHCPv6PrefixDelegation\0" /* compat */
507 "DHCPPrefixDelegation\0"
509 "DHCPServerStaticLease\0"
511 "IPv6NDPProxyAddress\0"
517 "IPv6PrefixDelegation\0"
521 "TrafficControlQueueingDiscipline\0"
527 "DeficitRoundRobinScheduler\0"
528 "DeficitRoundRobinSchedulerClass\0"
529 "EnhancedTransmissionSelection\0"
531 "FairQueueingControlledDelay\0"
533 "GenericRandomEarlyDetection\0"
534 "HeavyHitterFilter\0"
535 "HierarchyTokenBucket\0"
536 "HierarchyTokenBucketClass\0"
542 "QuickFairQueueing\0"
543 "QuickFairQueueingClass\0"
544 "StochasticFairBlue\0"
545 "StochasticFairnessQueueing\0"
546 "TokenBucketFilter\0"
547 "TrivialLinkEqualizer\0",
548 config_item_perf_lookup
, network_network_gperf_lookup
,
551 &network
->stats_by_path
);
555 r
= network_add_ipv4ll_route(network
);
557 return log_warning_errno(r
, "%s: Failed to add IPv4LL route: %m", network
->filename
);
559 r
= network_add_default_route_on_device(network
);
561 return log_warning_errno(r
, "%s: Failed to add default route on device: %m",
564 r
= network_verify(network
);
568 /* Ignore .network files that do not match the conditions. */
571 r
= ordered_hashmap_ensure_put(networks
, &string_hash_ops
, network
->name
, network
);
579 int network_load(Manager
*manager
, OrderedHashmap
**networks
) {
580 _cleanup_strv_free_
char **files
= NULL
;
586 ordered_hashmap_clear_with_destructor(*networks
, network_unref
);
588 r
= conf_files_list_strv(&files
, ".network", NULL
, 0, NETWORK_DIRS
);
590 return log_error_errno(r
, "Failed to enumerate network files: %m");
592 STRV_FOREACH(f
, files
) {
593 r
= network_load_one(manager
, networks
, *f
);
595 return log_error_errno(r
, "Failed to load %s: %m", *f
);
601 static bool stats_by_path_equal(Hashmap
*a
, Hashmap
*b
) {
602 struct stat
*st_a
, *st_b
;
608 if (hashmap_size(a
) != hashmap_size(b
))
611 HASHMAP_FOREACH_KEY(st_a
, path
, a
) {
612 st_b
= hashmap_get(b
, path
);
616 if (!stat_inode_unmodified(st_a
, st_b
))
623 int network_reload(Manager
*manager
) {
624 OrderedHashmap
*new_networks
= NULL
;
630 r
= network_load(manager
, &new_networks
);
634 ORDERED_HASHMAP_FOREACH(n
, new_networks
) {
635 r
= network_get_by_name(manager
, n
->name
, &old
);
637 log_debug("Found new .network file: %s", n
->filename
);
641 if (!stats_by_path_equal(n
->stats_by_path
, old
->stats_by_path
)) {
642 log_debug("Found updated .network file: %s", n
->filename
);
646 r
= ordered_hashmap_replace(new_networks
, old
->name
, old
);
654 ordered_hashmap_free_with_destructor(manager
->networks
, network_unref
);
655 manager
->networks
= new_networks
;
657 return manager_build_dhcp_pd_subnet_ids(manager
);
660 ordered_hashmap_free_with_destructor(new_networks
, network_unref
);
665 int manager_build_dhcp_pd_subnet_ids(Manager
*manager
) {
671 set_clear(manager
->dhcp_pd_subnet_ids
);
673 ORDERED_HASHMAP_FOREACH(n
, manager
->networks
) {
680 if (n
->dhcp_pd_subnet_id
< 0)
683 r
= set_ensure_put(&manager
->dhcp_pd_subnet_ids
, &uint64_hash_ops
, &n
->dhcp_pd_subnet_id
);
691 static Network
*network_free(Network
*network
) {
695 free(network
->filename
);
696 hashmap_free(network
->stats_by_path
);
698 net_match_clear(&network
->match
);
699 condition_free_list(network
->conditions
);
701 free(network
->dhcp_server_relay_agent_circuit_id
);
702 free(network
->dhcp_server_relay_agent_remote_id
);
703 free(network
->dhcp_server_filename
);
705 free(network
->description
);
706 free(network
->dhcp_vendor_class_identifier
);
707 free(network
->dhcp_mudurl
);
708 strv_free(network
->dhcp_user_class
);
709 free(network
->dhcp_hostname
);
710 free(network
->dhcp_label
);
711 set_free(network
->dhcp_deny_listed_ip
);
712 set_free(network
->dhcp_allow_listed_ip
);
713 set_free(network
->dhcp_request_options
);
714 set_free(network
->dhcp6_request_options
);
715 free(network
->dhcp6_mudurl
);
716 strv_free(network
->dhcp6_user_class
);
717 strv_free(network
->dhcp6_vendor_class
);
719 strv_free(network
->ntp
);
720 for (unsigned i
= 0; i
< network
->n_dns
; i
++)
721 in_addr_full_free(network
->dns
[i
]);
723 ordered_set_free(network
->search_domains
);
724 ordered_set_free(network
->route_domains
);
725 strv_free(network
->bind_carrier
);
727 ordered_set_free(network
->router_search_domains
);
728 free(network
->router_dns
);
729 set_free(network
->ndisc_deny_listed_router
);
730 set_free(network
->ndisc_allow_listed_router
);
731 set_free(network
->ndisc_deny_listed_prefix
);
732 set_free(network
->ndisc_allow_listed_prefix
);
733 set_free(network
->ndisc_deny_listed_route_prefix
);
734 set_free(network
->ndisc_allow_listed_route_prefix
);
736 free(network
->batadv_name
);
737 free(network
->bridge_name
);
738 free(network
->bond_name
);
739 free(network
->vrf_name
);
740 hashmap_free_free_key(network
->stacked_netdev_names
);
741 netdev_unref(network
->bridge
);
742 netdev_unref(network
->bond
);
743 netdev_unref(network
->vrf
);
744 hashmap_free_with_destructor(network
->stacked_netdevs
, netdev_unref
);
746 set_free_free(network
->ipv6_proxy_ndp_addresses
);
747 ordered_hashmap_free_with_destructor(network
->addresses_by_section
, address_free
);
748 hashmap_free_with_destructor(network
->routes_by_section
, route_free
);
749 hashmap_free_with_destructor(network
->nexthops_by_section
, nexthop_free
);
750 hashmap_free_with_destructor(network
->bridge_fdb_entries_by_section
, bridge_fdb_free
);
751 hashmap_free_with_destructor(network
->bridge_mdb_entries_by_section
, bridge_mdb_free
);
752 hashmap_free_with_destructor(network
->neighbors_by_section
, neighbor_free
);
753 hashmap_free_with_destructor(network
->address_labels_by_section
, address_label_free
);
754 hashmap_free_with_destructor(network
->prefixes_by_section
, prefix_free
);
755 hashmap_free_with_destructor(network
->route_prefixes_by_section
, route_prefix_free
);
756 hashmap_free_with_destructor(network
->rules_by_section
, routing_policy_rule_free
);
757 hashmap_free_with_destructor(network
->dhcp_static_leases_by_section
, dhcp_static_lease_free
);
758 ordered_hashmap_free_with_destructor(network
->sr_iov_by_section
, sr_iov_free
);
759 hashmap_free_with_destructor(network
->tc_by_section
, traffic_control_free
);
763 free(network
->dhcp_server_timezone
);
764 free(network
->dhcp_server_uplink_name
);
765 free(network
->router_uplink_name
);
766 free(network
->dhcp_pd_uplink_name
);
768 for (sd_dhcp_lease_server_type_t t
= 0; t
< _SD_DHCP_LEASE_SERVER_TYPE_MAX
; t
++)
769 free(network
->dhcp_server_emit
[t
].addresses
);
771 set_free_free(network
->dnssec_negative_trust_anchors
);
773 free(network
->lldp_mudurl
);
775 ordered_hashmap_free(network
->dhcp_client_send_options
);
776 ordered_hashmap_free(network
->dhcp_client_send_vendor_options
);
777 ordered_hashmap_free(network
->dhcp_server_send_options
);
778 ordered_hashmap_free(network
->dhcp_server_send_vendor_options
);
779 ordered_hashmap_free(network
->dhcp6_client_send_options
);
780 ordered_hashmap_free(network
->dhcp6_client_send_vendor_options
);
781 set_free(network
->dhcp_pd_tokens
);
782 set_free(network
->ndisc_tokens
);
784 return mfree(network
);
787 DEFINE_TRIVIAL_REF_UNREF_FUNC(Network
, network
, network_free
);
789 int network_get_by_name(Manager
*manager
, const char *name
, Network
**ret
) {
796 network
= ordered_hashmap_get(manager
->networks
, name
);
805 bool network_has_static_ipv6_configurations(Network
*network
) {
814 ORDERED_HASHMAP_FOREACH(address
, network
->addresses_by_section
)
815 if (address
->family
== AF_INET6
)
818 HASHMAP_FOREACH(route
, network
->routes_by_section
)
819 if (route
->family
== AF_INET6
)
822 HASHMAP_FOREACH(fdb
, network
->bridge_fdb_entries_by_section
)
823 if (fdb
->family
== AF_INET6
)
826 HASHMAP_FOREACH(mdb
, network
->bridge_mdb_entries_by_section
)
827 if (mdb
->family
== AF_INET6
)
830 HASHMAP_FOREACH(neighbor
, network
->neighbors_by_section
)
831 if (neighbor
->family
== AF_INET6
)
834 if (!hashmap_isempty(network
->address_labels_by_section
))
837 if (!hashmap_isempty(network
->prefixes_by_section
))
840 if (!hashmap_isempty(network
->route_prefixes_by_section
))
846 int config_parse_stacked_netdev(
848 const char *filename
,
851 unsigned section_line
,
858 _cleanup_free_
char *name
= NULL
;
859 NetDevKind kind
= ltype
;
878 _NETDEV_KIND_TUNNEL
));
880 if (!ifname_valid(rvalue
)) {
881 log_syntax(unit
, LOG_WARNING
, filename
, line
, 0,
882 "Invalid netdev name in %s=, ignoring assignment: %s", lvalue
, rvalue
);
886 name
= strdup(rvalue
);
890 r
= hashmap_ensure_put(h
, &string_hash_ops
, name
, INT_TO_PTR(kind
));
894 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
895 "Cannot add NetDev '%s' to network, ignoring assignment: %m", name
);
897 log_syntax(unit
, LOG_DEBUG
, filename
, line
, r
,
898 "NetDev '%s' specified twice, ignoring.", name
);
905 int config_parse_domains(
907 const char *filename
,
910 unsigned section_line
,
917 Network
*n
= userdata
;
925 if (isempty(rvalue
)) {
926 n
->search_domains
= ordered_set_free(n
->search_domains
);
927 n
->route_domains
= ordered_set_free(n
->route_domains
);
931 for (const char *p
= rvalue
;;) {
932 _cleanup_free_
char *w
= NULL
, *normalized
= NULL
;
936 r
= extract_first_word(&p
, &w
, NULL
, 0);
940 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
941 "Failed to extract search or route domain, ignoring: %s", rvalue
);
947 is_route
= w
[0] == '~';
948 domain
= is_route
? w
+ 1 : w
;
950 if (dns_name_is_root(domain
) || streq(domain
, "*")) {
951 /* If the root domain appears as is, or the special token "*" is found, we'll
952 * consider this as routing domain, unconditionally. */
954 domain
= "."; /* make sure we don't allow empty strings, thus write the root
957 r
= dns_name_normalize(domain
, 0, &normalized
);
959 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
960 "'%s' is not a valid domain name, ignoring.", domain
);
966 if (is_localhost(domain
)) {
967 log_syntax(unit
, LOG_WARNING
, filename
, line
, 0,
968 "'localhost' domain may not be configured as search or route domain, ignoring assignment: %s",
974 OrderedSet
**set
= is_route
? &n
->route_domains
: &n
->search_domains
;
975 r
= ordered_set_put_strdup(set
, domain
);
983 int config_parse_hostname(
985 const char *filename
,
988 unsigned section_line
,
995 char **hostname
= data
;
1003 if (isempty(rvalue
)) {
1004 *hostname
= mfree(*hostname
);
1008 if (!hostname_is_valid(rvalue
, 0)) {
1009 log_syntax(unit
, LOG_WARNING
, filename
, line
, 0,
1010 "Hostname is not valid, ignoring assignment: %s", rvalue
);
1014 r
= dns_name_is_valid(rvalue
);
1016 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
1017 "Failed to check validity of hostname '%s', ignoring assignment: %m", rvalue
);
1021 log_syntax(unit
, LOG_WARNING
, filename
, line
, 0,
1022 "Hostname is not a valid DNS domain name, ignoring assignment: %s", rvalue
);
1026 return free_and_strdup_warn(hostname
, rvalue
);
1029 int config_parse_timezone(
1031 const char *filename
,
1033 const char *section
,
1034 unsigned section_line
,
1049 if (isempty(rvalue
)) {
1054 r
= verify_timezone(rvalue
, LOG_WARNING
);
1056 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
1057 "Timezone is not valid, ignoring assignment: %s", rvalue
);
1061 return free_and_strdup_warn(tz
, rvalue
);
1064 int config_parse_dns(
1066 const char *filename
,
1068 const char *section
,
1069 unsigned section_line
,
1076 Network
*n
= userdata
;
1084 if (isempty(rvalue
)) {
1085 for (unsigned i
= 0; i
< n
->n_dns
; i
++)
1086 in_addr_full_free(n
->dns
[i
]);
1087 n
->dns
= mfree(n
->dns
);
1092 for (const char *p
= rvalue
;;) {
1093 _cleanup_(in_addr_full_freep
) struct in_addr_full
*dns
= NULL
;
1094 _cleanup_free_
char *w
= NULL
;
1095 struct in_addr_full
**m
;
1097 r
= extract_first_word(&p
, &w
, NULL
, 0);
1101 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
1102 "Invalid syntax, ignoring: %s", rvalue
);
1108 r
= in_addr_full_new_from_string(w
, &dns
);
1110 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
1111 "Failed to parse dns server address, ignoring: %s", w
);
1115 if (IN_SET(dns
->port
, 53, 853))
1118 m
= reallocarray(n
->dns
, n
->n_dns
+ 1, sizeof(struct in_addr_full
*));
1122 m
[n
->n_dns
++] = TAKE_PTR(dns
);
1127 int config_parse_dnssec_negative_trust_anchors(
1129 const char *filename
,
1131 const char *section
,
1132 unsigned section_line
,
1147 if (isempty(rvalue
)) {
1148 *nta
= set_free_free(*nta
);
1152 for (const char *p
= rvalue
;;) {
1153 _cleanup_free_
char *w
= NULL
;
1155 r
= extract_first_word(&p
, &w
, NULL
, 0);
1159 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
1160 "Failed to extract negative trust anchor domain, ignoring: %s", rvalue
);
1166 r
= dns_name_is_valid(w
);
1168 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
1169 "%s is not a valid domain name, ignoring.", w
);
1173 r
= set_ensure_consume(nta
, &dns_name_hash_ops
, TAKE_PTR(w
));
1179 int config_parse_ntp(
1181 const char *filename
,
1183 const char *section
,
1184 unsigned section_line
,
1199 if (isempty(rvalue
)) {
1204 for (const char *p
= rvalue
;;) {
1205 _cleanup_free_
char *w
= NULL
;
1207 r
= extract_first_word(&p
, &w
, NULL
, 0);
1211 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
1212 "Failed to extract NTP server name, ignoring: %s", rvalue
);
1218 r
= dns_name_is_valid_or_address(w
);
1220 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
1221 "%s is not a valid domain name or IP address, ignoring.", w
);
1225 if (strv_length(*l
) > MAX_NTP_SERVERS
) {
1226 log_syntax(unit
, LOG_WARNING
, filename
, line
, 0,
1227 "More than %u NTP servers specified, ignoring \"%s\" and any subsequent entries.",
1228 MAX_NTP_SERVERS
, w
);
1232 r
= strv_consume(l
, TAKE_PTR(w
));
1238 int config_parse_required_for_online(
1240 const char *filename
,
1242 const char *section
,
1243 unsigned section_line
,
1250 Network
*network
= userdata
;
1251 LinkOperationalStateRange range
;
1252 bool required
= true;
1260 if (isempty(rvalue
)) {
1261 network
->required_for_online
= -1;
1262 network
->required_operstate_for_online
= LINK_OPERSTATE_RANGE_DEFAULT
;
1266 r
= parse_operational_state_range(rvalue
, &range
);
1268 r
= parse_boolean(rvalue
);
1270 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
1271 "Failed to parse %s= setting, ignoring assignment: %s",
1277 range
= LINK_OPERSTATE_RANGE_DEFAULT
;
1280 network
->required_for_online
= required
;
1281 network
->required_operstate_for_online
= range
;
1286 int config_parse_link_group(
1288 const char *filename
,
1290 const char *section
,
1291 unsigned section_line
,
1298 Network
*network
= userdata
;
1307 if (isempty(rvalue
)) {
1308 network
->group
= -1;
1312 r
= safe_atoi32(rvalue
, &group
);
1314 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
1315 "Failed to parse Group=, ignoring assignment: %s", rvalue
);
1320 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
1321 "Value of Group= must be in the range 0…2147483647, ignoring assignment: %s", rvalue
);
1325 network
->group
= group
;
1329 int config_parse_ignore_carrier_loss(
1331 const char *filename
,
1333 const char *section
,
1334 unsigned section_line
,
1341 Network
*network
= userdata
;
1350 if (isempty(rvalue
)) {
1351 network
->ignore_carrier_loss_set
= false;
1355 r
= parse_boolean(rvalue
);
1357 network
->ignore_carrier_loss_set
= true;
1358 network
->ignore_carrier_loss_usec
= r
> 0 ? USEC_INFINITY
: 0;
1362 r
= parse_sec(rvalue
, &usec
);
1364 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
1365 "Failed to parse %s=, ignoring assignment: %s", lvalue
, rvalue
);
1369 network
->ignore_carrier_loss_set
= true;
1370 network
->ignore_carrier_loss_usec
= usec
;
1374 DEFINE_CONFIG_PARSE_ENUM(config_parse_required_family_for_online
, link_required_address_family
, AddressFamily
,
1375 "Failed to parse RequiredFamilyForOnline= setting");
1377 DEFINE_CONFIG_PARSE_ENUM(config_parse_keep_configuration
, keep_configuration
, KeepConfiguration
,
1378 "Failed to parse KeepConfiguration= setting");
1380 static const char* const keep_configuration_table
[_KEEP_CONFIGURATION_MAX
] = {
1381 [KEEP_CONFIGURATION_NO
] = "no",
1382 [KEEP_CONFIGURATION_DHCP_ON_STOP
] = "dhcp-on-stop",
1383 [KEEP_CONFIGURATION_DHCP
] = "dhcp",
1384 [KEEP_CONFIGURATION_STATIC
] = "static",
1385 [KEEP_CONFIGURATION_YES
] = "yes",
1388 DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(keep_configuration
, KeepConfiguration
, KEEP_CONFIGURATION_YES
);
1390 static const char* const activation_policy_table
[_ACTIVATION_POLICY_MAX
] = {
1391 [ACTIVATION_POLICY_UP
] = "up",
1392 [ACTIVATION_POLICY_ALWAYS_UP
] = "always-up",
1393 [ACTIVATION_POLICY_MANUAL
] = "manual",
1394 [ACTIVATION_POLICY_ALWAYS_DOWN
] = "always-down",
1395 [ACTIVATION_POLICY_DOWN
] = "down",
1396 [ACTIVATION_POLICY_BOUND
] = "bound",
1399 DEFINE_STRING_TABLE_LOOKUP(activation_policy
, ActivationPolicy
);
1400 DEFINE_CONFIG_PARSE_ENUM(config_parse_activation_policy
, activation_policy
, ActivationPolicy
, "Failed to parse activation policy");