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"
47 /* Let's assume that anything above this number is a user misconfiguration. */
48 #define MAX_NTP_SERVERS 128U
50 static int network_resolve_netdev_one(Network
*network
, const char *name
, NetDevKind kind
, NetDev
**ret
) {
51 const char *kind_string
;
55 /* For test-networkd-conf, the check must be earlier than the assertions. */
60 assert(network
->manager
);
61 assert(network
->filename
);
64 if (kind
== _NETDEV_KIND_TUNNEL
)
65 kind_string
= "tunnel";
67 kind_string
= netdev_kind_to_string(kind
);
69 return log_warning_errno(SYNTHETIC_ERRNO(EINVAL
),
70 "%s: Invalid NetDev kind of %s, ignoring assignment.",
71 network
->filename
, name
);
74 r
= netdev_get(network
->manager
, name
, &netdev
);
76 return log_warning_errno(r
, "%s: %s NetDev could not be found, ignoring assignment.",
77 network
->filename
, name
);
79 if (netdev
->kind
!= kind
&& !(kind
== _NETDEV_KIND_TUNNEL
&&
85 NETDEV_KIND_IP6GRETAP
,
91 return log_warning_errno(SYNTHETIC_ERRNO(EINVAL
),
92 "%s: NetDev %s is not a %s, ignoring assignment",
93 network
->filename
, name
, kind_string
);
95 *ret
= netdev_ref(netdev
);
99 static int network_resolve_stacked_netdevs(Network
*network
) {
105 HASHMAP_FOREACH_KEY(kind
, name
, network
->stacked_netdev_names
) {
106 _cleanup_(netdev_unrefp
) NetDev
*netdev
= NULL
;
108 if (network_resolve_netdev_one(network
, name
, PTR_TO_INT(kind
), &netdev
) <= 0)
111 r
= hashmap_ensure_put(&network
->stacked_netdevs
, &string_hash_ops
, netdev
->ifname
, netdev
);
115 log_warning_errno(r
, "%s: Failed to add NetDev '%s' to network, ignoring: %m",
116 network
->filename
, (const char *) name
);
124 int network_verify(Network
*network
) {
128 assert(network
->manager
);
129 assert(network
->filename
);
131 if (net_match_is_empty(&network
->match
) && !network
->conditions
)
132 return log_warning_errno(SYNTHETIC_ERRNO(EINVAL
),
133 "%s: No valid settings found in the [Match] section, ignoring file. "
134 "To match all interfaces, add Name=* in the [Match] section.",
137 /* skip out early if configuration does not match the environment */
138 if (!condition_test_list(network
->conditions
, environ
, NULL
, NULL
, NULL
))
139 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL
),
140 "%s: Conditions in the file do not match the system environment, skipping.",
143 if (network
->keep_master
) {
144 if (network
->batadv_name
)
145 log_warning("%s: BatmanAdvanced= set with KeepMaster= enabled, ignoring BatmanAdvanced=.",
147 if (network
->bond_name
)
148 log_warning("%s: Bond= set with KeepMaster= enabled, ignoring Bond=.",
150 if (network
->bridge_name
)
151 log_warning("%s: Bridge= set with KeepMaster= enabled, ignoring Bridge=.",
153 if (network
->vrf_name
)
154 log_warning("%s: VRF= set with KeepMaster= enabled, ignoring VRF=.",
157 network
->batadv_name
= mfree(network
->batadv_name
);
158 network
->bond_name
= mfree(network
->bond_name
);
159 network
->bridge_name
= mfree(network
->bridge_name
);
160 network
->vrf_name
= mfree(network
->vrf_name
);
163 (void) network_resolve_netdev_one(network
, network
->batadv_name
, NETDEV_KIND_BATADV
, &network
->batadv
);
164 (void) network_resolve_netdev_one(network
, network
->bond_name
, NETDEV_KIND_BOND
, &network
->bond
);
165 (void) network_resolve_netdev_one(network
, network
->bridge_name
, NETDEV_KIND_BRIDGE
, &network
->bridge
);
166 (void) network_resolve_netdev_one(network
, network
->vrf_name
, NETDEV_KIND_VRF
, &network
->vrf
);
167 r
= network_resolve_stacked_netdevs(network
);
171 /* Free unnecessary entries. */
172 network
->batadv_name
= mfree(network
->batadv_name
);
173 network
->bond_name
= mfree(network
->bond_name
);
174 network
->bridge_name
= mfree(network
->bridge_name
);
175 network
->vrf_name
= mfree(network
->vrf_name
);
176 network
->stacked_netdev_names
= hashmap_free_free_key(network
->stacked_netdev_names
);
179 /* Bonding slave does not support addressing. */
180 if (network
->link_local
>= 0 && network
->link_local
!= ADDRESS_FAMILY_NO
) {
181 log_warning("%s: Cannot enable LinkLocalAddressing= when Bond= is specified, disabling LinkLocalAddressing=.",
183 network
->link_local
= ADDRESS_FAMILY_NO
;
185 if (network
->dhcp_server
) {
186 log_warning("%s: Cannot enable DHCPServer= when Bond= is specified, disabling DHCPServer=.",
188 network
->dhcp_server
= false;
190 if (!ordered_hashmap_isempty(network
->addresses_by_section
))
191 log_warning("%s: Cannot set addresses when Bond= is specified, ignoring addresses.",
193 if (!hashmap_isempty(network
->routes_by_section
))
194 log_warning("%s: Cannot set routes when Bond= is specified, ignoring routes.",
197 network
->addresses_by_section
= ordered_hashmap_free_with_destructor(network
->addresses_by_section
, address_free
);
198 network
->routes_by_section
= hashmap_free_with_destructor(network
->routes_by_section
, route_free
);
201 if (network
->link_local
< 0) {
202 network
->link_local
= ADDRESS_FAMILY_IPV6
;
204 if (network
->keep_master
|| network
->bridge
)
205 network
->link_local
= ADDRESS_FAMILY_NO
;
209 HASHMAP_FOREACH(netdev
, network
->stacked_netdevs
) {
212 if (netdev
->kind
== NETDEV_KIND_MACVLAN
)
214 else if (netdev
->kind
== NETDEV_KIND_MACVTAP
)
221 if (m
->mode
== NETDEV_MACVLAN_MODE_PASSTHRU
)
222 network
->link_local
= ADDRESS_FAMILY_NO
;
224 /* There won't be a passthru MACVLAN/MACVTAP if there's already one in another mode */
230 if (network
->ipv6ll_address_gen_mode
== IPV6_LINK_LOCAL_ADDRESSS_GEN_MODE_NONE
)
231 SET_FLAG(network
->link_local
, ADDRESS_FAMILY_IPV6
, false);
233 if (in6_addr_is_set(&network
->ipv6ll_stable_secret
) &&
234 network
->ipv6ll_address_gen_mode
< 0)
235 network
->ipv6ll_address_gen_mode
= IPV6_LINK_LOCAL_ADDRESSS_GEN_MODE_STABLE_PRIVACY
;
237 /* IPMasquerade implies IPForward */
238 network
->ip_forward
|= network
->ip_masquerade
;
240 network_adjust_ipv6_proxy_ndp(network
);
241 network_adjust_ipv6_accept_ra(network
);
242 network_adjust_dhcp(network
);
243 network_adjust_radv(network
);
244 network_adjust_bridge_vlan(network
);
246 if (network
->mtu
> 0 && network
->dhcp_use_mtu
) {
247 log_warning("%s: MTUBytes= in [Link] section and UseMTU= in [DHCP] section are set. "
248 "Disabling UseMTU=.", network
->filename
);
249 network
->dhcp_use_mtu
= false;
252 if (network
->dhcp_critical
>= 0) {
253 if (network
->keep_configuration
>= 0) {
254 if (network
->manager
->keep_configuration
< 0)
255 log_warning("%s: Both KeepConfiguration= and deprecated CriticalConnection= are set. "
256 "Ignoring CriticalConnection=.", network
->filename
);
257 } else if (network
->dhcp_critical
)
258 /* CriticalConnection=yes also preserve foreign static configurations. */
259 network
->keep_configuration
= KEEP_CONFIGURATION_YES
;
261 network
->keep_configuration
= KEEP_CONFIGURATION_NO
;
264 if (!strv_isempty(network
->bind_carrier
)) {
265 if (!IN_SET(network
->activation_policy
, _ACTIVATION_POLICY_INVALID
, ACTIVATION_POLICY_BOUND
))
266 log_warning("%s: ActivationPolicy=bound is required with BindCarrier=. "
267 "Setting ActivationPolicy=bound.", network
->filename
);
268 network
->activation_policy
= ACTIVATION_POLICY_BOUND
;
269 } else if (network
->activation_policy
== ACTIVATION_POLICY_BOUND
) {
270 log_warning("%s: ActivationPolicy=bound requires BindCarrier=. "
271 "Ignoring ActivationPolicy=bound.", network
->filename
);
272 network
->activation_policy
= ACTIVATION_POLICY_UP
;
275 if (network
->activation_policy
== _ACTIVATION_POLICY_INVALID
)
276 network
->activation_policy
= ACTIVATION_POLICY_UP
;
278 if (network
->activation_policy
== ACTIVATION_POLICY_ALWAYS_UP
) {
279 if (network
->ignore_carrier_loss_set
&& network
->ignore_carrier_loss_usec
< USEC_INFINITY
)
280 log_warning("%s: IgnoreCarrierLoss=no or finite timespan conflicts with ActivationPolicy=always-up. "
281 "Setting IgnoreCarrierLoss=yes.", network
->filename
);
282 network
->ignore_carrier_loss_set
= true;
283 network
->ignore_carrier_loss_usec
= USEC_INFINITY
;
286 if (!network
->ignore_carrier_loss_set
) {
287 network
->ignore_carrier_loss_set
= true;
288 network
->ignore_carrier_loss_usec
= network
->configure_without_carrier
? USEC_INFINITY
: 0;
291 if (IN_SET(network
->activation_policy
, ACTIVATION_POLICY_DOWN
, ACTIVATION_POLICY_ALWAYS_DOWN
, ACTIVATION_POLICY_MANUAL
)) {
292 if (network
->required_for_online
< 0 ||
293 (network
->required_for_online
== true && network
->activation_policy
== ACTIVATION_POLICY_ALWAYS_DOWN
)) {
294 log_debug("%s: Setting RequiredForOnline=no because ActivationPolicy=%s.", network
->filename
,
295 activation_policy_to_string(network
->activation_policy
));
296 network
->required_for_online
= false;
297 } else if (network
->required_for_online
== true)
298 log_warning("%s: RequiredForOnline=yes and ActivationPolicy=%s, "
299 "this may cause a delay at boot.", network
->filename
,
300 activation_policy_to_string(network
->activation_policy
));
303 if (network
->required_for_online
< 0)
304 network
->required_for_online
= true;
306 if (network
->keep_configuration
< 0)
307 network
->keep_configuration
= KEEP_CONFIGURATION_NO
;
309 if (network
->ipv6_proxy_ndp
== 0 && !set_isempty(network
->ipv6_proxy_ndp_addresses
)) {
310 log_warning("%s: IPv6ProxyNDP= is disabled. Ignoring IPv6ProxyNDPAddress=.", network
->filename
);
311 network
->ipv6_proxy_ndp_addresses
= set_free_free(network
->ipv6_proxy_ndp_addresses
);
314 r
= network_drop_invalid_addresses(network
);
316 return r
; /* network_drop_invalid_addresses() logs internally. */
317 network_drop_invalid_routes(network
);
318 network_drop_invalid_nexthops(network
);
319 network_drop_invalid_bridge_fdb_entries(network
);
320 network_drop_invalid_bridge_mdb_entries(network
);
321 network_drop_invalid_neighbors(network
);
322 network_drop_invalid_address_labels(network
);
323 network_drop_invalid_prefixes(network
);
324 network_drop_invalid_route_prefixes(network
);
325 network_drop_invalid_routing_policy_rules(network
);
326 network_drop_invalid_qdisc(network
);
327 network_drop_invalid_tclass(network
);
328 r
= sr_iov_drop_invalid_sections(UINT32_MAX
, network
->sr_iov_by_section
);
330 return r
; /* sr_iov_drop_invalid_sections() logs internally. */
331 network_drop_invalid_static_leases(network
);
333 network_adjust_dhcp_server(network
);
338 int network_load_one(Manager
*manager
, OrderedHashmap
**networks
, const char *filename
) {
339 _cleanup_free_
char *fname
= NULL
, *name
= NULL
;
340 _cleanup_(network_unrefp
) Network
*network
= NULL
;
341 const char *dropin_dirname
;
348 r
= null_or_empty_path(filename
);
350 return log_warning_errno(r
, "Failed to check if \"%s\" is empty: %m", filename
);
352 log_debug("Skipping empty file: %s", filename
);
356 fname
= strdup(filename
);
360 name
= strdup(basename(filename
));
364 d
= strrchr(name
, '.');
366 return log_warning_errno(SYNTHETIC_ERRNO(EINVAL
), "Invalid file name: %s", filename
);
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
,
392 .keep_configuration
= manager
->keep_configuration
,
394 .dhcp_duid
.type
= _DUID_TYPE_INVALID
,
396 .dhcp_use_ntp
= true,
397 .dhcp_routes_to_ntp
= true,
398 .dhcp_use_sip
= true,
399 .dhcp_use_dns
= true,
400 .dhcp_routes_to_dns
= true,
401 .dhcp_use_hostname
= true,
402 .dhcp_use_routes
= true,
403 .dhcp_use_gateway
= -1,
404 .dhcp_send_hostname
= true,
405 .dhcp_send_release
= true,
406 .dhcp_route_metric
= DHCP_ROUTE_METRIC
,
407 .dhcp_client_identifier
= _DHCP_CLIENT_ID_INVALID
,
408 .dhcp_route_table
= RT_TABLE_MAIN
,
409 .dhcp_ip_service_type
= -1,
410 .dhcp_broadcast
= -1,
412 .dhcp6_use_address
= true,
413 .dhcp6_use_pd_prefix
= true,
414 .dhcp6_use_dns
= true,
415 .dhcp6_use_hostname
= true,
416 .dhcp6_use_ntp
= true,
417 .dhcp6_use_rapid_commit
= true,
418 .dhcp6_duid
.type
= _DUID_TYPE_INVALID
,
419 .dhcp6_client_start_mode
= _DHCP6_CLIENT_START_MODE_INVALID
,
422 .dhcp_pd_announce
= true,
423 .dhcp_pd_assign
= true,
424 .dhcp_pd_manage_temporary_address
= true,
425 .dhcp_pd_subnet_id
= -1,
426 .dhcp_pd_route_metric
= DHCP6PD_ROUTE_METRIC
,
428 .dhcp_server_bind_to_interface
= true,
429 .dhcp_server_emit
[SD_DHCP_LEASE_DNS
].emit
= true,
430 .dhcp_server_emit
[SD_DHCP_LEASE_NTP
].emit
= true,
431 .dhcp_server_emit
[SD_DHCP_LEASE_SIP
].emit
= true,
432 .dhcp_server_emit_router
= true,
433 .dhcp_server_emit_timezone
= true,
435 .router_lifetime_usec
= RADV_DEFAULT_ROUTER_LIFETIME_USEC
,
436 .router_dns_lifetime_usec
= RADV_DEFAULT_VALID_LIFETIME_USEC
,
437 .router_emit_dns
= true,
438 .router_emit_domains
= true,
444 .allow_port_to_be_root
= -1,
446 .multicast_flood
= -1,
447 .multicast_to_unicast
= -1,
448 .neighbor_suppression
= -1,
450 .bridge_proxy_arp
= -1,
451 .bridge_proxy_arp_wifi
= -1,
452 .priority
= LINK_BRIDGE_PORT_PRIORITY_INVALID
,
453 .multicast_router
= _MULTICAST_ROUTER_INVALID
,
455 .lldp_mode
= LLDP_MODE_ROUTERS_ONLY
,
456 .lldp_multicast_mode
= _SD_LLDP_MULTICAST_MODE_INVALID
,
458 .dns_default_route
= -1,
459 .llmnr
= RESOLVE_SUPPORT_YES
,
460 .mdns
= RESOLVE_SUPPORT_NO
,
461 .dnssec_mode
= _DNSSEC_MODE_INVALID
,
462 .dns_over_tls_mode
= _DNS_OVER_TLS_MODE_INVALID
,
464 /* If LinkLocalAddressing= is not set, then set to ADDRESS_FAMILY_IPV6 later. */
465 .link_local
= _ADDRESS_FAMILY_INVALID
,
466 .ipv6ll_address_gen_mode
= _IPV6_LINK_LOCAL_ADDRESS_GEN_MODE_INVALID
,
468 .ipv4_accept_local
= -1,
469 .ipv4_route_localnet
= -1,
470 .ipv6_privacy_extensions
= IPV6_PRIVACY_EXTENSIONS_NO
,
471 .ipv6_dad_transmits
= -1,
472 .ipv6_hop_limit
= -1,
473 .ipv6_proxy_ndp
= -1,
476 .ipv6_accept_ra
= -1,
477 .ipv6_accept_ra_use_dns
= true,
478 .ipv6_accept_ra_use_gateway
= true,
479 .ipv6_accept_ra_use_route_prefix
= true,
480 .ipv6_accept_ra_use_autonomous_prefix
= true,
481 .ipv6_accept_ra_use_onlink_prefix
= true,
482 .ipv6_accept_ra_use_mtu
= true,
483 .ipv6_accept_ra_route_table
= RT_TABLE_MAIN
,
484 .ipv6_accept_ra_route_metric
= DHCP_ROUTE_METRIC
,
485 .ipv6_accept_ra_start_dhcp6_client
= IPV6_ACCEPT_RA_START_DHCP6_CLIENT_YES
,
487 .can_termination
= -1,
489 .ipoib_mode
= _IP_OVER_INFINIBAND_MODE_INVALID
,
493 r
= config_parse_many(
494 STRV_MAKE_CONST(filename
), NETWORK_DIRS
, dropin_dirname
,
502 "RoutingPolicyRule\0"
505 "DHCP\0" /* compat */
508 "DHCPv6PrefixDelegation\0" /* compat */
509 "DHCPPrefixDelegation\0"
511 "DHCPServerStaticLease\0"
513 "IPv6NDPProxyAddress\0"
519 "IPv6PrefixDelegation\0"
523 "TrafficControlQueueingDiscipline\0"
529 "DeficitRoundRobinScheduler\0"
530 "DeficitRoundRobinSchedulerClass\0"
531 "EnhancedTransmissionSelection\0"
533 "FairQueueingControlledDelay\0"
535 "GenericRandomEarlyDetection\0"
536 "HeavyHitterFilter\0"
537 "HierarchyTokenBucket\0"
538 "HierarchyTokenBucketClass\0"
544 "QuickFairQueueing\0"
545 "QuickFairQueueingClass\0"
546 "StochasticFairBlue\0"
547 "StochasticFairnessQueueing\0"
548 "TokenBucketFilter\0"
549 "TrivialLinkEqualizer\0",
550 config_item_perf_lookup
, network_network_gperf_lookup
,
553 &network
->stats_by_path
,
556 return r
; /* config_parse_many() logs internally. */
558 r
= network_add_ipv4ll_route(network
);
560 return log_warning_errno(r
, "%s: Failed to add IPv4LL route: %m", network
->filename
);
562 r
= network_add_default_route_on_device(network
);
564 return log_warning_errno(r
, "%s: Failed to add default route on device: %m",
567 r
= network_verify(network
);
569 return r
; /* network_verify() logs internally. */
571 r
= ordered_hashmap_ensure_put(networks
, &string_hash_ops
, network
->name
, network
);
573 return log_warning_errno(r
, "%s: Failed to store configuration into hashmap: %m", filename
);
579 int network_load(Manager
*manager
, OrderedHashmap
**networks
) {
580 _cleanup_strv_free_
char **files
= NULL
;
585 ordered_hashmap_clear_with_destructor(*networks
, network_unref
);
587 r
= conf_files_list_strv(&files
, ".network", NULL
, 0, NETWORK_DIRS
);
589 return log_error_errno(r
, "Failed to enumerate network files: %m");
591 STRV_FOREACH(f
, files
)
592 (void) network_load_one(manager
, networks
, *f
);
597 int network_reload(Manager
*manager
) {
598 OrderedHashmap
*new_networks
= NULL
;
604 r
= network_load(manager
, &new_networks
);
608 ORDERED_HASHMAP_FOREACH(n
, new_networks
) {
609 r
= network_get_by_name(manager
, n
->name
, &old
);
611 log_debug("Found new .network file: %s", n
->filename
);
615 if (!stats_by_path_equal(n
->stats_by_path
, old
->stats_by_path
)) {
616 log_debug("Found updated .network file: %s", n
->filename
);
620 r
= ordered_hashmap_replace(new_networks
, old
->name
, old
);
628 ordered_hashmap_free_with_destructor(manager
->networks
, network_unref
);
629 manager
->networks
= new_networks
;
631 return manager_build_dhcp_pd_subnet_ids(manager
);
634 ordered_hashmap_free_with_destructor(new_networks
, network_unref
);
639 int manager_build_dhcp_pd_subnet_ids(Manager
*manager
) {
645 set_clear(manager
->dhcp_pd_subnet_ids
);
647 ORDERED_HASHMAP_FOREACH(n
, manager
->networks
) {
654 if (n
->dhcp_pd_subnet_id
< 0)
657 r
= set_ensure_put(&manager
->dhcp_pd_subnet_ids
, &uint64_hash_ops
, &n
->dhcp_pd_subnet_id
);
665 static Network
*network_free(Network
*network
) {
670 free(network
->filename
);
671 free(network
->description
);
672 hashmap_free(network
->stats_by_path
);
675 net_match_clear(&network
->match
);
676 condition_free_list(network
->conditions
);
679 strv_free(network
->bind_carrier
);
682 strv_free(network
->ntp
);
685 for (unsigned i
= 0; i
< network
->n_dns
; i
++)
686 in_addr_full_free(network
->dns
[i
]);
688 ordered_set_free(network
->search_domains
);
689 ordered_set_free(network
->route_domains
);
690 set_free_free(network
->dnssec_negative_trust_anchors
);
693 free(network
->dhcp_server_relay_agent_circuit_id
);
694 free(network
->dhcp_server_relay_agent_remote_id
);
695 free(network
->dhcp_server_boot_server_name
);
696 free(network
->dhcp_server_boot_filename
);
697 free(network
->dhcp_server_timezone
);
698 free(network
->dhcp_server_uplink_name
);
699 for (sd_dhcp_lease_server_type_t t
= 0; t
< _SD_DHCP_LEASE_SERVER_TYPE_MAX
; t
++)
700 free(network
->dhcp_server_emit
[t
].addresses
);
701 ordered_hashmap_free(network
->dhcp_server_send_options
);
702 ordered_hashmap_free(network
->dhcp_server_send_vendor_options
);
705 free(network
->dhcp_vendor_class_identifier
);
706 free(network
->dhcp_mudurl
);
707 free(network
->dhcp_hostname
);
708 free(network
->dhcp_label
);
709 set_free(network
->dhcp_deny_listed_ip
);
710 set_free(network
->dhcp_allow_listed_ip
);
711 strv_free(network
->dhcp_user_class
);
712 set_free(network
->dhcp_request_options
);
713 ordered_hashmap_free(network
->dhcp_client_send_options
);
714 ordered_hashmap_free(network
->dhcp_client_send_vendor_options
);
715 free(network
->dhcp_netlabel
);
718 free(network
->dhcp6_mudurl
);
719 strv_free(network
->dhcp6_user_class
);
720 strv_free(network
->dhcp6_vendor_class
);
721 set_free(network
->dhcp6_request_options
);
722 ordered_hashmap_free(network
->dhcp6_client_send_options
);
723 ordered_hashmap_free(network
->dhcp6_client_send_vendor_options
);
724 free(network
->dhcp6_netlabel
);
727 free(network
->dhcp_pd_uplink_name
);
728 set_free(network
->dhcp_pd_tokens
);
729 free(network
->dhcp_pd_netlabel
);
731 /* Router advertisement */
732 ordered_set_free(network
->router_search_domains
);
733 free(network
->router_dns
);
734 free(network
->router_uplink_name
);
737 set_free(network
->ndisc_deny_listed_router
);
738 set_free(network
->ndisc_allow_listed_router
);
739 set_free(network
->ndisc_deny_listed_prefix
);
740 set_free(network
->ndisc_allow_listed_prefix
);
741 set_free(network
->ndisc_deny_listed_route_prefix
);
742 set_free(network
->ndisc_allow_listed_route_prefix
);
743 set_free(network
->ndisc_tokens
);
744 free(network
->ndisc_netlabel
);
747 free(network
->lldp_mudurl
);
750 free(network
->batadv_name
);
751 free(network
->bridge_name
);
752 free(network
->bond_name
);
753 free(network
->vrf_name
);
754 hashmap_free_free_key(network
->stacked_netdev_names
);
755 netdev_unref(network
->bridge
);
756 netdev_unref(network
->bond
);
757 netdev_unref(network
->vrf
);
758 hashmap_free_with_destructor(network
->stacked_netdevs
, netdev_unref
);
761 set_free_free(network
->ipv6_proxy_ndp_addresses
);
762 ordered_hashmap_free_with_destructor(network
->addresses_by_section
, address_free
);
763 hashmap_free_with_destructor(network
->routes_by_section
, route_free
);
764 hashmap_free_with_destructor(network
->nexthops_by_section
, nexthop_free
);
765 hashmap_free_with_destructor(network
->bridge_fdb_entries_by_section
, bridge_fdb_free
);
766 hashmap_free_with_destructor(network
->bridge_mdb_entries_by_section
, bridge_mdb_free
);
767 hashmap_free_with_destructor(network
->neighbors_by_section
, neighbor_free
);
768 hashmap_free_with_destructor(network
->address_labels_by_section
, address_label_free
);
769 hashmap_free_with_destructor(network
->prefixes_by_section
, prefix_free
);
770 hashmap_free_with_destructor(network
->route_prefixes_by_section
, route_prefix_free
);
771 hashmap_free_with_destructor(network
->rules_by_section
, routing_policy_rule_free
);
772 hashmap_free_with_destructor(network
->dhcp_static_leases_by_section
, dhcp_static_lease_free
);
773 ordered_hashmap_free_with_destructor(network
->sr_iov_by_section
, sr_iov_free
);
774 hashmap_free_with_destructor(network
->qdiscs_by_section
, qdisc_free
);
775 hashmap_free_with_destructor(network
->tclasses_by_section
, tclass_free
);
777 return mfree(network
);
780 DEFINE_TRIVIAL_REF_UNREF_FUNC(Network
, network
, network_free
);
782 int network_get_by_name(Manager
*manager
, const char *name
, Network
**ret
) {
789 network
= ordered_hashmap_get(manager
->networks
, name
);
798 bool network_has_static_ipv6_configurations(Network
*network
) {
807 ORDERED_HASHMAP_FOREACH(address
, network
->addresses_by_section
)
808 if (address
->family
== AF_INET6
)
811 HASHMAP_FOREACH(route
, network
->routes_by_section
)
812 if (route
->family
== AF_INET6
)
815 HASHMAP_FOREACH(fdb
, network
->bridge_fdb_entries_by_section
)
816 if (fdb
->family
== AF_INET6
)
819 HASHMAP_FOREACH(mdb
, network
->bridge_mdb_entries_by_section
)
820 if (mdb
->family
== AF_INET6
)
823 HASHMAP_FOREACH(neighbor
, network
->neighbors_by_section
)
824 if (neighbor
->family
== AF_INET6
)
827 if (!hashmap_isempty(network
->address_labels_by_section
))
830 if (!hashmap_isempty(network
->prefixes_by_section
))
833 if (!hashmap_isempty(network
->route_prefixes_by_section
))
839 int config_parse_stacked_netdev(
841 const char *filename
,
844 unsigned section_line
,
851 _cleanup_free_
char *name
= NULL
;
852 NetDevKind kind
= ltype
;
853 Hashmap
**h
= ASSERT_PTR(data
);
869 _NETDEV_KIND_TUNNEL
));
871 if (!ifname_valid(rvalue
)) {
872 log_syntax(unit
, LOG_WARNING
, filename
, line
, 0,
873 "Invalid netdev name in %s=, ignoring assignment: %s", lvalue
, rvalue
);
877 name
= strdup(rvalue
);
881 r
= hashmap_ensure_put(h
, &string_hash_ops
, name
, INT_TO_PTR(kind
));
885 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
886 "Cannot add NetDev '%s' to network, ignoring assignment: %m", name
);
888 log_syntax(unit
, LOG_DEBUG
, filename
, line
, r
,
889 "NetDev '%s' specified twice, ignoring.", name
);
896 int config_parse_domains(
898 const char *filename
,
901 unsigned section_line
,
908 Network
*n
= ASSERT_PTR(userdata
);
915 if (isempty(rvalue
)) {
916 n
->search_domains
= ordered_set_free(n
->search_domains
);
917 n
->route_domains
= ordered_set_free(n
->route_domains
);
921 for (const char *p
= rvalue
;;) {
922 _cleanup_free_
char *w
= NULL
, *normalized
= NULL
;
926 r
= extract_first_word(&p
, &w
, NULL
, 0);
930 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
931 "Failed to extract search or route domain, ignoring: %s", rvalue
);
937 is_route
= w
[0] == '~';
938 domain
= is_route
? w
+ 1 : w
;
940 if (dns_name_is_root(domain
) || streq(domain
, "*")) {
941 /* If the root domain appears as is, or the special token "*" is found, we'll
942 * consider this as routing domain, unconditionally. */
944 domain
= "."; /* make sure we don't allow empty strings, thus write the root
947 r
= dns_name_normalize(domain
, 0, &normalized
);
949 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
950 "'%s' is not a valid domain name, ignoring.", domain
);
956 if (is_localhost(domain
)) {
957 log_syntax(unit
, LOG_WARNING
, filename
, line
, 0,
958 "'localhost' domain may not be configured as search or route domain, ignoring assignment: %s",
964 OrderedSet
**set
= is_route
? &n
->route_domains
: &n
->search_domains
;
965 r
= ordered_set_put_strdup(set
, domain
);
973 int config_parse_timezone(
975 const char *filename
,
978 unsigned section_line
,
985 char **tz
= ASSERT_PTR(data
);
992 if (isempty(rvalue
)) {
997 r
= verify_timezone(rvalue
, LOG_WARNING
);
999 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
1000 "Timezone is not valid, ignoring assignment: %s", rvalue
);
1004 return free_and_strdup_warn(tz
, rvalue
);
1007 int config_parse_dns(
1009 const char *filename
,
1011 const char *section
,
1012 unsigned section_line
,
1019 Network
*n
= ASSERT_PTR(userdata
);
1026 if (isempty(rvalue
)) {
1027 for (unsigned i
= 0; i
< n
->n_dns
; i
++)
1028 in_addr_full_free(n
->dns
[i
]);
1029 n
->dns
= mfree(n
->dns
);
1034 for (const char *p
= rvalue
;;) {
1035 _cleanup_(in_addr_full_freep
) struct in_addr_full
*dns
= NULL
;
1036 _cleanup_free_
char *w
= NULL
;
1037 struct in_addr_full
**m
;
1039 r
= extract_first_word(&p
, &w
, NULL
, 0);
1043 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
1044 "Invalid syntax, ignoring: %s", rvalue
);
1050 r
= in_addr_full_new_from_string(w
, &dns
);
1052 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
1053 "Failed to parse dns server address, ignoring: %s", w
);
1057 if (IN_SET(dns
->port
, 53, 853))
1060 m
= reallocarray(n
->dns
, n
->n_dns
+ 1, sizeof(struct in_addr_full
*));
1064 m
[n
->n_dns
++] = TAKE_PTR(dns
);
1069 int config_parse_dnssec_negative_trust_anchors(
1071 const char *filename
,
1073 const char *section
,
1074 unsigned section_line
,
1081 Set
**nta
= ASSERT_PTR(data
);
1088 if (isempty(rvalue
)) {
1089 *nta
= set_free_free(*nta
);
1093 for (const char *p
= rvalue
;;) {
1094 _cleanup_free_
char *w
= NULL
;
1096 r
= extract_first_word(&p
, &w
, NULL
, 0);
1100 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
1101 "Failed to extract negative trust anchor domain, ignoring: %s", rvalue
);
1107 r
= dns_name_is_valid(w
);
1109 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
1110 "%s is not a valid domain name, ignoring.", w
);
1114 r
= set_ensure_consume(nta
, &dns_name_hash_ops
, TAKE_PTR(w
));
1120 int config_parse_ntp(
1122 const char *filename
,
1124 const char *section
,
1125 unsigned section_line
,
1132 char ***l
= ASSERT_PTR(data
);
1139 if (isempty(rvalue
)) {
1144 for (const char *p
= rvalue
;;) {
1145 _cleanup_free_
char *w
= NULL
;
1147 r
= extract_first_word(&p
, &w
, NULL
, 0);
1151 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
1152 "Failed to extract NTP server name, ignoring: %s", rvalue
);
1158 r
= dns_name_is_valid_or_address(w
);
1160 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
1161 "%s is not a valid domain name or IP address, ignoring.", w
);
1165 if (strv_length(*l
) > MAX_NTP_SERVERS
) {
1166 log_syntax(unit
, LOG_WARNING
, filename
, line
, 0,
1167 "More than %u NTP servers specified, ignoring \"%s\" and any subsequent entries.",
1168 MAX_NTP_SERVERS
, w
);
1172 r
= strv_consume(l
, TAKE_PTR(w
));
1178 int config_parse_required_for_online(
1180 const char *filename
,
1182 const char *section
,
1183 unsigned section_line
,
1190 Network
*network
= ASSERT_PTR(userdata
);
1191 LinkOperationalStateRange range
;
1192 bool required
= true;
1199 if (isempty(rvalue
)) {
1200 network
->required_for_online
= -1;
1201 network
->required_operstate_for_online
= LINK_OPERSTATE_RANGE_DEFAULT
;
1205 r
= parse_operational_state_range(rvalue
, &range
);
1207 r
= parse_boolean(rvalue
);
1209 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
1210 "Failed to parse %s= setting, ignoring assignment: %s",
1216 range
= LINK_OPERSTATE_RANGE_DEFAULT
;
1219 network
->required_for_online
= required
;
1220 network
->required_operstate_for_online
= range
;
1225 int config_parse_link_group(
1227 const char *filename
,
1229 const char *section
,
1230 unsigned section_line
,
1237 Network
*network
= ASSERT_PTR(userdata
);
1245 if (isempty(rvalue
)) {
1246 network
->group
= -1;
1250 r
= safe_atoi32(rvalue
, &group
);
1252 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
1253 "Failed to parse Group=, ignoring assignment: %s", rvalue
);
1258 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
1259 "Value of Group= must be in the range 0…2147483647, ignoring assignment: %s", rvalue
);
1263 network
->group
= group
;
1267 int config_parse_ignore_carrier_loss(
1269 const char *filename
,
1271 const char *section
,
1272 unsigned section_line
,
1279 Network
*network
= ASSERT_PTR(userdata
);
1287 if (isempty(rvalue
)) {
1288 network
->ignore_carrier_loss_set
= false;
1292 r
= parse_boolean(rvalue
);
1294 network
->ignore_carrier_loss_set
= true;
1295 network
->ignore_carrier_loss_usec
= r
> 0 ? USEC_INFINITY
: 0;
1299 r
= parse_sec(rvalue
, &usec
);
1301 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
1302 "Failed to parse %s=, ignoring assignment: %s", lvalue
, rvalue
);
1306 network
->ignore_carrier_loss_set
= true;
1307 network
->ignore_carrier_loss_usec
= usec
;
1311 DEFINE_CONFIG_PARSE_ENUM(config_parse_required_family_for_online
, link_required_address_family
, AddressFamily
,
1312 "Failed to parse RequiredFamilyForOnline= setting");
1314 DEFINE_CONFIG_PARSE_ENUM(config_parse_keep_configuration
, keep_configuration
, KeepConfiguration
,
1315 "Failed to parse KeepConfiguration= setting");
1317 static const char* const keep_configuration_table
[_KEEP_CONFIGURATION_MAX
] = {
1318 [KEEP_CONFIGURATION_NO
] = "no",
1319 [KEEP_CONFIGURATION_DHCP_ON_STOP
] = "dhcp-on-stop",
1320 [KEEP_CONFIGURATION_DHCP
] = "dhcp",
1321 [KEEP_CONFIGURATION_STATIC
] = "static",
1322 [KEEP_CONFIGURATION_YES
] = "yes",
1325 DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(keep_configuration
, KeepConfiguration
, KEEP_CONFIGURATION_YES
);
1327 static const char* const activation_policy_table
[_ACTIVATION_POLICY_MAX
] = {
1328 [ACTIVATION_POLICY_UP
] = "up",
1329 [ACTIVATION_POLICY_ALWAYS_UP
] = "always-up",
1330 [ACTIVATION_POLICY_MANUAL
] = "manual",
1331 [ACTIVATION_POLICY_ALWAYS_DOWN
] = "always-down",
1332 [ACTIVATION_POLICY_DOWN
] = "down",
1333 [ACTIVATION_POLICY_BOUND
] = "bound",
1336 DEFINE_STRING_TABLE_LOOKUP(activation_policy
, ActivationPolicy
);
1337 DEFINE_CONFIG_PARSE_ENUM(config_parse_activation_policy
, activation_policy
, ActivationPolicy
, "Failed to parse activation policy");