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
->filename
);
129 if (net_match_is_empty(&network
->match
) && !network
->conditions
)
130 return log_warning_errno(SYNTHETIC_ERRNO(EINVAL
),
131 "%s: No valid settings found in the [Match] section, ignoring file. "
132 "To match all interfaces, add Name=* in the [Match] section.",
135 /* skip out early if configuration does not match the environment */
136 if (!condition_test_list(network
->conditions
, environ
, NULL
, NULL
, NULL
))
137 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL
),
138 "%s: Conditions in the file do not match the system environment, skipping.",
141 if (network
->keep_master
) {
142 if (network
->batadv_name
)
143 log_warning("%s: BatmanAdvanced= set with KeepMaster= enabled, ignoring BatmanAdvanced=.",
145 if (network
->bond_name
)
146 log_warning("%s: Bond= set with KeepMaster= enabled, ignoring Bond=.",
148 if (network
->bridge_name
)
149 log_warning("%s: Bridge= set with KeepMaster= enabled, ignoring Bridge=.",
151 if (network
->vrf_name
)
152 log_warning("%s: VRF= set with KeepMaster= enabled, ignoring VRF=.",
155 network
->batadv_name
= mfree(network
->batadv_name
);
156 network
->bond_name
= mfree(network
->bond_name
);
157 network
->bridge_name
= mfree(network
->bridge_name
);
158 network
->vrf_name
= mfree(network
->vrf_name
);
161 (void) network_resolve_netdev_one(network
, network
->batadv_name
, NETDEV_KIND_BATADV
, &network
->batadv
);
162 (void) network_resolve_netdev_one(network
, network
->bond_name
, NETDEV_KIND_BOND
, &network
->bond
);
163 (void) network_resolve_netdev_one(network
, network
->bridge_name
, NETDEV_KIND_BRIDGE
, &network
->bridge
);
164 (void) network_resolve_netdev_one(network
, network
->vrf_name
, NETDEV_KIND_VRF
, &network
->vrf
);
165 r
= network_resolve_stacked_netdevs(network
);
169 /* Free unnecessary entries. */
170 network
->batadv_name
= mfree(network
->batadv_name
);
171 network
->bond_name
= mfree(network
->bond_name
);
172 network
->bridge_name
= mfree(network
->bridge_name
);
173 network
->vrf_name
= mfree(network
->vrf_name
);
174 network
->stacked_netdev_names
= hashmap_free_free_key(network
->stacked_netdev_names
);
177 /* Bonding slave does not support addressing. */
178 if (network
->link_local
>= 0 && network
->link_local
!= ADDRESS_FAMILY_NO
) {
179 log_warning("%s: Cannot enable LinkLocalAddressing= when Bond= is specified, disabling LinkLocalAddressing=.",
181 network
->link_local
= ADDRESS_FAMILY_NO
;
183 if (network
->dhcp_server
) {
184 log_warning("%s: Cannot enable DHCPServer= when Bond= is specified, disabling DHCPServer=.",
186 network
->dhcp_server
= false;
188 if (!ordered_hashmap_isempty(network
->addresses_by_section
))
189 log_warning("%s: Cannot set addresses when Bond= is specified, ignoring addresses.",
191 if (!hashmap_isempty(network
->routes_by_section
))
192 log_warning("%s: Cannot set routes when Bond= is specified, ignoring routes.",
195 network
->addresses_by_section
= ordered_hashmap_free_with_destructor(network
->addresses_by_section
, address_free
);
196 network
->routes_by_section
= hashmap_free_with_destructor(network
->routes_by_section
, route_free
);
199 if (network
->link_local
< 0) {
200 network
->link_local
= ADDRESS_FAMILY_IPV6
;
202 if (network
->keep_master
|| network
->bridge
)
203 network
->link_local
= ADDRESS_FAMILY_NO
;
207 HASHMAP_FOREACH(netdev
, network
->stacked_netdevs
) {
210 if (netdev
->kind
== NETDEV_KIND_MACVLAN
)
212 else if (netdev
->kind
== NETDEV_KIND_MACVTAP
)
219 if (m
->mode
== NETDEV_MACVLAN_MODE_PASSTHRU
)
220 network
->link_local
= ADDRESS_FAMILY_NO
;
222 /* There won't be a passthru MACVLAN/MACVTAP if there's already one in another mode */
228 if (network
->ipv6ll_address_gen_mode
== IPV6_LINK_LOCAL_ADDRESSS_GEN_MODE_NONE
)
229 SET_FLAG(network
->link_local
, ADDRESS_FAMILY_IPV6
, false);
231 if (in6_addr_is_set(&network
->ipv6ll_stable_secret
) &&
232 network
->ipv6ll_address_gen_mode
< 0)
233 network
->ipv6ll_address_gen_mode
= IPV6_LINK_LOCAL_ADDRESSS_GEN_MODE_STABLE_PRIVACY
;
235 /* IPMasquerade implies IPForward */
236 network
->ip_forward
|= network
->ip_masquerade
;
238 network_adjust_ipv6_proxy_ndp(network
);
239 network_adjust_ipv6_accept_ra(network
);
240 network_adjust_dhcp(network
);
241 network_adjust_radv(network
);
242 network_adjust_bridge_vlan(network
);
244 if (network
->mtu
> 0 && network
->dhcp_use_mtu
) {
245 log_warning("%s: MTUBytes= in [Link] section and UseMTU= in [DHCP] section are set. "
246 "Disabling UseMTU=.", network
->filename
);
247 network
->dhcp_use_mtu
= false;
250 if (network
->dhcp_critical
>= 0) {
251 if (network
->keep_configuration
>= 0)
252 log_warning("%s: Both KeepConfiguration= and deprecated CriticalConnection= are set. "
253 "Ignoring CriticalConnection=.", network
->filename
);
254 else if (network
->dhcp_critical
)
255 /* CriticalConnection=yes also preserve foreign static configurations. */
256 network
->keep_configuration
= KEEP_CONFIGURATION_YES
;
258 network
->keep_configuration
= KEEP_CONFIGURATION_NO
;
261 if (!strv_isempty(network
->bind_carrier
)) {
262 if (!IN_SET(network
->activation_policy
, _ACTIVATION_POLICY_INVALID
, ACTIVATION_POLICY_BOUND
))
263 log_warning("%s: ActivationPolicy=bound is required with BindCarrier=. "
264 "Setting ActivationPolicy=bound.", network
->filename
);
265 network
->activation_policy
= ACTIVATION_POLICY_BOUND
;
266 } else if (network
->activation_policy
== ACTIVATION_POLICY_BOUND
) {
267 log_warning("%s: ActivationPolicy=bound requires BindCarrier=. "
268 "Ignoring ActivationPolicy=bound.", network
->filename
);
269 network
->activation_policy
= ACTIVATION_POLICY_UP
;
272 if (network
->activation_policy
== _ACTIVATION_POLICY_INVALID
)
273 network
->activation_policy
= ACTIVATION_POLICY_UP
;
275 if (network
->activation_policy
== ACTIVATION_POLICY_ALWAYS_UP
) {
276 if (network
->ignore_carrier_loss_set
&& network
->ignore_carrier_loss_usec
< USEC_INFINITY
)
277 log_warning("%s: IgnoreCarrierLoss=no or finite timespan conflicts with ActivationPolicy=always-up. "
278 "Setting IgnoreCarrierLoss=yes.", network
->filename
);
279 network
->ignore_carrier_loss_set
= true;
280 network
->ignore_carrier_loss_usec
= USEC_INFINITY
;
283 if (!network
->ignore_carrier_loss_set
) {
284 network
->ignore_carrier_loss_set
= true;
285 network
->ignore_carrier_loss_usec
= network
->configure_without_carrier
? USEC_INFINITY
: 0;
288 if (IN_SET(network
->activation_policy
, ACTIVATION_POLICY_DOWN
, ACTIVATION_POLICY_ALWAYS_DOWN
, ACTIVATION_POLICY_MANUAL
)) {
289 if (network
->required_for_online
< 0 ||
290 (network
->required_for_online
== true && network
->activation_policy
== ACTIVATION_POLICY_ALWAYS_DOWN
)) {
291 log_debug("%s: Setting RequiredForOnline=no because ActivationPolicy=%s.", network
->filename
,
292 activation_policy_to_string(network
->activation_policy
));
293 network
->required_for_online
= false;
294 } else if (network
->required_for_online
== true)
295 log_warning("%s: RequiredForOnline=yes and ActivationPolicy=%s, "
296 "this may cause a delay at boot.", network
->filename
,
297 activation_policy_to_string(network
->activation_policy
));
300 if (network
->required_for_online
< 0)
301 network
->required_for_online
= true;
303 if (network
->keep_configuration
< 0)
304 network
->keep_configuration
= KEEP_CONFIGURATION_NO
;
306 if (network
->ipv6_proxy_ndp
== 0 && !set_isempty(network
->ipv6_proxy_ndp_addresses
)) {
307 log_warning("%s: IPv6ProxyNDP= is disabled. Ignoring IPv6ProxyNDPAddress=.", network
->filename
);
308 network
->ipv6_proxy_ndp_addresses
= set_free_free(network
->ipv6_proxy_ndp_addresses
);
311 r
= network_drop_invalid_addresses(network
);
314 network_drop_invalid_routes(network
);
315 network_drop_invalid_nexthops(network
);
316 network_drop_invalid_bridge_fdb_entries(network
);
317 network_drop_invalid_bridge_mdb_entries(network
);
318 network_drop_invalid_neighbors(network
);
319 network_drop_invalid_address_labels(network
);
320 network_drop_invalid_prefixes(network
);
321 network_drop_invalid_route_prefixes(network
);
322 network_drop_invalid_routing_policy_rules(network
);
323 network_drop_invalid_traffic_control(network
);
324 network_drop_invalid_sr_iov(network
);
325 network_drop_invalid_static_leases(network
);
327 network_adjust_dhcp_server(network
);
332 int network_load_one(Manager
*manager
, OrderedHashmap
**networks
, const char *filename
) {
333 _cleanup_free_
char *fname
= NULL
, *name
= NULL
;
334 _cleanup_(network_unrefp
) Network
*network
= NULL
;
335 const char *dropin_dirname
;
342 r
= null_or_empty_path(filename
);
348 log_debug("Skipping empty file: %s", filename
);
352 fname
= strdup(filename
);
356 name
= strdup(basename(filename
));
360 d
= strrchr(name
, '.');
366 dropin_dirname
= strjoina(name
, ".network.d");
368 network
= new(Network
, 1);
372 *network
= (Network
) {
373 .filename
= TAKE_PTR(fname
),
374 .name
= TAKE_PTR(name
),
379 .required_for_online
= -1,
380 .required_operstate_for_online
= LINK_OPERSTATE_RANGE_DEFAULT
,
381 .activation_policy
= _ACTIVATION_POLICY_INVALID
,
387 .keep_configuration
= _KEEP_CONFIGURATION_INVALID
,
389 .dhcp_duid
.type
= _DUID_TYPE_INVALID
,
391 .dhcp_use_ntp
= true,
392 .dhcp_routes_to_ntp
= true,
393 .dhcp_use_sip
= true,
394 .dhcp_use_dns
= true,
395 .dhcp_routes_to_dns
= true,
396 .dhcp_use_hostname
= true,
397 .dhcp_use_routes
= true,
398 .dhcp_use_gateway
= -1,
399 .dhcp_send_hostname
= true,
400 .dhcp_send_release
= true,
401 .dhcp_route_metric
= DHCP_ROUTE_METRIC
,
402 .dhcp_client_identifier
= _DHCP_CLIENT_ID_INVALID
,
403 .dhcp_route_table
= RT_TABLE_MAIN
,
404 .dhcp_ip_service_type
= -1,
405 .dhcp_broadcast
= -1,
407 .dhcp6_use_address
= true,
408 .dhcp6_use_pd_prefix
= true,
409 .dhcp6_use_dns
= true,
410 .dhcp6_use_hostname
= true,
411 .dhcp6_use_ntp
= true,
412 .dhcp6_duid
.type
= _DUID_TYPE_INVALID
,
413 .dhcp6_client_start_mode
= _DHCP6_CLIENT_START_MODE_INVALID
,
416 .dhcp_pd_announce
= true,
417 .dhcp_pd_assign
= true,
418 .dhcp_pd_manage_temporary_address
= true,
419 .dhcp_pd_subnet_id
= -1,
420 .dhcp_pd_route_metric
= DHCP6PD_ROUTE_METRIC
,
422 .dhcp_server_bind_to_interface
= true,
423 .dhcp_server_emit
[SD_DHCP_LEASE_DNS
].emit
= true,
424 .dhcp_server_emit
[SD_DHCP_LEASE_NTP
].emit
= true,
425 .dhcp_server_emit
[SD_DHCP_LEASE_SIP
].emit
= true,
426 .dhcp_server_emit_router
= true,
427 .dhcp_server_emit_timezone
= true,
429 .router_lifetime_usec
= RADV_DEFAULT_ROUTER_LIFETIME_USEC
,
430 .router_dns_lifetime_usec
= RADV_DEFAULT_VALID_LIFETIME_USEC
,
431 .router_emit_dns
= true,
432 .router_emit_domains
= true,
437 .allow_port_to_be_root
= -1,
439 .multicast_flood
= -1,
440 .multicast_to_unicast
= -1,
441 .neighbor_suppression
= -1,
443 .bridge_proxy_arp
= -1,
444 .bridge_proxy_arp_wifi
= -1,
445 .priority
= LINK_BRIDGE_PORT_PRIORITY_INVALID
,
446 .multicast_router
= _MULTICAST_ROUTER_INVALID
,
448 .lldp_mode
= LLDP_MODE_ROUTERS_ONLY
,
449 .lldp_multicast_mode
= _SD_LLDP_MULTICAST_MODE_INVALID
,
451 .dns_default_route
= -1,
452 .llmnr
= RESOLVE_SUPPORT_YES
,
453 .mdns
= RESOLVE_SUPPORT_NO
,
454 .dnssec_mode
= _DNSSEC_MODE_INVALID
,
455 .dns_over_tls_mode
= _DNS_OVER_TLS_MODE_INVALID
,
457 /* If LinkLocalAddressing= is not set, then set to ADDRESS_FAMILY_IPV6 later. */
458 .link_local
= _ADDRESS_FAMILY_INVALID
,
459 .ipv6ll_address_gen_mode
= _IPV6_LINK_LOCAL_ADDRESS_GEN_MODE_INVALID
,
461 .ipv4_accept_local
= -1,
462 .ipv4_route_localnet
= -1,
463 .ipv6_privacy_extensions
= IPV6_PRIVACY_EXTENSIONS_NO
,
464 .ipv6_dad_transmits
= -1,
465 .ipv6_hop_limit
= -1,
466 .ipv6_proxy_ndp
= -1,
469 .ipv6_accept_ra
= -1,
470 .ipv6_accept_ra_use_dns
= true,
471 .ipv6_accept_ra_use_gateway
= true,
472 .ipv6_accept_ra_use_route_prefix
= true,
473 .ipv6_accept_ra_use_autonomous_prefix
= true,
474 .ipv6_accept_ra_use_onlink_prefix
= true,
475 .ipv6_accept_ra_use_mtu
= true,
476 .ipv6_accept_ra_route_table
= RT_TABLE_MAIN
,
477 .ipv6_accept_ra_route_metric
= DHCP_ROUTE_METRIC
,
478 .ipv6_accept_ra_start_dhcp6_client
= IPV6_ACCEPT_RA_START_DHCP6_CLIENT_YES
,
480 .can_termination
= -1,
482 .ipoib_mode
= _IP_OVER_INFINIBAND_MODE_INVALID
,
486 r
= config_parse_many(
487 STRV_MAKE_CONST(filename
), NETWORK_DIRS
, dropin_dirname
,
495 "RoutingPolicyRule\0"
498 "DHCP\0" /* compat */
501 "DHCPv6PrefixDelegation\0" /* compat */
502 "DHCPPrefixDelegation\0"
504 "DHCPServerStaticLease\0"
506 "IPv6NDPProxyAddress\0"
512 "IPv6PrefixDelegation\0"
516 "TrafficControlQueueingDiscipline\0"
522 "DeficitRoundRobinScheduler\0"
523 "DeficitRoundRobinSchedulerClass\0"
524 "EnhancedTransmissionSelection\0"
526 "FairQueueingControlledDelay\0"
528 "GenericRandomEarlyDetection\0"
529 "HeavyHitterFilter\0"
530 "HierarchyTokenBucket\0"
531 "HierarchyTokenBucketClass\0"
537 "QuickFairQueueing\0"
538 "QuickFairQueueingClass\0"
539 "StochasticFairBlue\0"
540 "StochasticFairnessQueueing\0"
541 "TokenBucketFilter\0"
542 "TrivialLinkEqualizer\0",
543 config_item_perf_lookup
, network_network_gperf_lookup
,
546 &network
->stats_by_path
);
550 r
= network_add_ipv4ll_route(network
);
552 return log_warning_errno(r
, "%s: Failed to add IPv4LL route: %m", network
->filename
);
554 r
= network_add_default_route_on_device(network
);
556 return log_warning_errno(r
, "%s: Failed to add default route on device: %m",
559 r
= network_verify(network
);
563 /* Ignore .network files that do not match the conditions. */
566 r
= ordered_hashmap_ensure_put(networks
, &string_hash_ops
, network
->name
, network
);
574 int network_load(Manager
*manager
, OrderedHashmap
**networks
) {
575 _cleanup_strv_free_
char **files
= NULL
;
581 ordered_hashmap_clear_with_destructor(*networks
, network_unref
);
583 r
= conf_files_list_strv(&files
, ".network", NULL
, 0, NETWORK_DIRS
);
585 return log_error_errno(r
, "Failed to enumerate network files: %m");
587 STRV_FOREACH(f
, files
) {
588 r
= network_load_one(manager
, networks
, *f
);
590 return log_error_errno(r
, "Failed to load %s: %m", *f
);
596 static bool stats_by_path_equal(Hashmap
*a
, Hashmap
*b
) {
597 struct stat
*st_a
, *st_b
;
603 if (hashmap_size(a
) != hashmap_size(b
))
606 HASHMAP_FOREACH_KEY(st_a
, path
, a
) {
607 st_b
= hashmap_get(b
, path
);
611 if (!stat_inode_unmodified(st_a
, st_b
))
618 int network_reload(Manager
*manager
) {
619 OrderedHashmap
*new_networks
= NULL
;
625 r
= network_load(manager
, &new_networks
);
629 ORDERED_HASHMAP_FOREACH(n
, new_networks
) {
630 r
= network_get_by_name(manager
, n
->name
, &old
);
632 log_debug("Found new .network file: %s", n
->filename
);
636 if (!stats_by_path_equal(n
->stats_by_path
, old
->stats_by_path
)) {
637 log_debug("Found updated .network file: %s", n
->filename
);
641 r
= ordered_hashmap_replace(new_networks
, old
->name
, old
);
649 ordered_hashmap_free_with_destructor(manager
->networks
, network_unref
);
650 manager
->networks
= new_networks
;
652 return manager_build_dhcp_pd_subnet_ids(manager
);
655 ordered_hashmap_free_with_destructor(new_networks
, network_unref
);
660 int manager_build_dhcp_pd_subnet_ids(Manager
*manager
) {
666 set_clear(manager
->dhcp_pd_subnet_ids
);
668 ORDERED_HASHMAP_FOREACH(n
, manager
->networks
) {
675 if (n
->dhcp_pd_subnet_id
< 0)
678 r
= set_ensure_put(&manager
->dhcp_pd_subnet_ids
, &uint64_hash_ops
, &n
->dhcp_pd_subnet_id
);
686 static Network
*network_free(Network
*network
) {
690 free(network
->filename
);
691 hashmap_free(network
->stats_by_path
);
693 net_match_clear(&network
->match
);
694 condition_free_list(network
->conditions
);
696 free(network
->dhcp_server_relay_agent_circuit_id
);
697 free(network
->dhcp_server_relay_agent_remote_id
);
699 free(network
->description
);
700 free(network
->dhcp_vendor_class_identifier
);
701 free(network
->dhcp_mudurl
);
702 strv_free(network
->dhcp_user_class
);
703 free(network
->dhcp_hostname
);
704 free(network
->dhcp_label
);
705 set_free(network
->dhcp_deny_listed_ip
);
706 set_free(network
->dhcp_allow_listed_ip
);
707 set_free(network
->dhcp_request_options
);
708 set_free(network
->dhcp6_request_options
);
709 free(network
->dhcp6_mudurl
);
710 strv_free(network
->dhcp6_user_class
);
711 strv_free(network
->dhcp6_vendor_class
);
713 strv_free(network
->ntp
);
714 for (unsigned i
= 0; i
< network
->n_dns
; i
++)
715 in_addr_full_free(network
->dns
[i
]);
717 ordered_set_free(network
->search_domains
);
718 ordered_set_free(network
->route_domains
);
719 strv_free(network
->bind_carrier
);
721 ordered_set_free(network
->router_search_domains
);
722 free(network
->router_dns
);
723 set_free(network
->ndisc_deny_listed_router
);
724 set_free(network
->ndisc_allow_listed_router
);
725 set_free(network
->ndisc_deny_listed_prefix
);
726 set_free(network
->ndisc_allow_listed_prefix
);
727 set_free(network
->ndisc_deny_listed_route_prefix
);
728 set_free(network
->ndisc_allow_listed_route_prefix
);
730 free(network
->batadv_name
);
731 free(network
->bridge_name
);
732 free(network
->bond_name
);
733 free(network
->vrf_name
);
734 hashmap_free_free_key(network
->stacked_netdev_names
);
735 netdev_unref(network
->bridge
);
736 netdev_unref(network
->bond
);
737 netdev_unref(network
->vrf
);
738 hashmap_free_with_destructor(network
->stacked_netdevs
, netdev_unref
);
740 set_free_free(network
->ipv6_proxy_ndp_addresses
);
741 ordered_hashmap_free_with_destructor(network
->addresses_by_section
, address_free
);
742 hashmap_free_with_destructor(network
->routes_by_section
, route_free
);
743 hashmap_free_with_destructor(network
->nexthops_by_section
, nexthop_free
);
744 hashmap_free_with_destructor(network
->bridge_fdb_entries_by_section
, bridge_fdb_free
);
745 hashmap_free_with_destructor(network
->bridge_mdb_entries_by_section
, bridge_mdb_free
);
746 hashmap_free_with_destructor(network
->neighbors_by_section
, neighbor_free
);
747 hashmap_free_with_destructor(network
->address_labels_by_section
, address_label_free
);
748 hashmap_free_with_destructor(network
->prefixes_by_section
, prefix_free
);
749 hashmap_free_with_destructor(network
->route_prefixes_by_section
, route_prefix_free
);
750 hashmap_free_with_destructor(network
->rules_by_section
, routing_policy_rule_free
);
751 hashmap_free_with_destructor(network
->dhcp_static_leases_by_section
, dhcp_static_lease_free
);
752 ordered_hashmap_free_with_destructor(network
->sr_iov_by_section
, sr_iov_free
);
753 ordered_hashmap_free_with_destructor(network
->tc_by_section
, traffic_control_free
);
757 free(network
->dhcp_server_timezone
);
758 free(network
->dhcp_server_uplink_name
);
759 free(network
->router_uplink_name
);
760 free(network
->dhcp_pd_uplink_name
);
762 for (sd_dhcp_lease_server_type_t t
= 0; t
< _SD_DHCP_LEASE_SERVER_TYPE_MAX
; t
++)
763 free(network
->dhcp_server_emit
[t
].addresses
);
765 set_free_free(network
->dnssec_negative_trust_anchors
);
767 free(network
->lldp_mudurl
);
769 ordered_hashmap_free(network
->dhcp_client_send_options
);
770 ordered_hashmap_free(network
->dhcp_client_send_vendor_options
);
771 ordered_hashmap_free(network
->dhcp_server_send_options
);
772 ordered_hashmap_free(network
->dhcp_server_send_vendor_options
);
773 ordered_hashmap_free(network
->dhcp6_client_send_options
);
774 ordered_hashmap_free(network
->dhcp6_client_send_vendor_options
);
775 set_free(network
->dhcp_pd_tokens
);
776 set_free(network
->ndisc_tokens
);
778 return mfree(network
);
781 DEFINE_TRIVIAL_REF_UNREF_FUNC(Network
, network
, network_free
);
783 int network_get_by_name(Manager
*manager
, const char *name
, Network
**ret
) {
790 network
= ordered_hashmap_get(manager
->networks
, name
);
799 bool network_has_static_ipv6_configurations(Network
*network
) {
808 ORDERED_HASHMAP_FOREACH(address
, network
->addresses_by_section
)
809 if (address
->family
== AF_INET6
)
812 HASHMAP_FOREACH(route
, network
->routes_by_section
)
813 if (route
->family
== AF_INET6
)
816 HASHMAP_FOREACH(fdb
, network
->bridge_fdb_entries_by_section
)
817 if (fdb
->family
== AF_INET6
)
820 HASHMAP_FOREACH(mdb
, network
->bridge_mdb_entries_by_section
)
821 if (mdb
->family
== AF_INET6
)
824 HASHMAP_FOREACH(neighbor
, network
->neighbors_by_section
)
825 if (neighbor
->family
== AF_INET6
)
828 if (!hashmap_isempty(network
->address_labels_by_section
))
831 if (!hashmap_isempty(network
->prefixes_by_section
))
834 if (!hashmap_isempty(network
->route_prefixes_by_section
))
840 int config_parse_stacked_netdev(
842 const char *filename
,
845 unsigned section_line
,
852 _cleanup_free_
char *name
= NULL
;
853 NetDevKind kind
= ltype
;
872 _NETDEV_KIND_TUNNEL
));
874 if (!ifname_valid(rvalue
)) {
875 log_syntax(unit
, LOG_WARNING
, filename
, line
, 0,
876 "Invalid netdev name in %s=, ignoring assignment: %s", lvalue
, rvalue
);
880 name
= strdup(rvalue
);
884 r
= hashmap_ensure_put(h
, &string_hash_ops
, name
, INT_TO_PTR(kind
));
888 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
889 "Cannot add NetDev '%s' to network, ignoring assignment: %m", name
);
891 log_syntax(unit
, LOG_DEBUG
, filename
, line
, r
,
892 "NetDev '%s' specified twice, ignoring.", name
);
899 int config_parse_domains(
901 const char *filename
,
904 unsigned section_line
,
911 Network
*n
= userdata
;
919 if (isempty(rvalue
)) {
920 n
->search_domains
= ordered_set_free(n
->search_domains
);
921 n
->route_domains
= ordered_set_free(n
->route_domains
);
925 for (const char *p
= rvalue
;;) {
926 _cleanup_free_
char *w
= NULL
, *normalized
= NULL
;
930 r
= extract_first_word(&p
, &w
, NULL
, 0);
934 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
935 "Failed to extract search or route domain, ignoring: %s", rvalue
);
941 is_route
= w
[0] == '~';
942 domain
= is_route
? w
+ 1 : w
;
944 if (dns_name_is_root(domain
) || streq(domain
, "*")) {
945 /* If the root domain appears as is, or the special token "*" is found, we'll
946 * consider this as routing domain, unconditionally. */
948 domain
= "."; /* make sure we don't allow empty strings, thus write the root
951 r
= dns_name_normalize(domain
, 0, &normalized
);
953 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
954 "'%s' is not a valid domain name, ignoring.", domain
);
960 if (is_localhost(domain
)) {
961 log_syntax(unit
, LOG_WARNING
, filename
, line
, 0,
962 "'localhost' domain may not be configured as search or route domain, ignoring assignment: %s",
968 OrderedSet
**set
= is_route
? &n
->route_domains
: &n
->search_domains
;
969 r
= ordered_set_put_strdup(set
, domain
);
977 int config_parse_hostname(
979 const char *filename
,
982 unsigned section_line
,
989 char **hostname
= data
;
997 if (isempty(rvalue
)) {
998 *hostname
= mfree(*hostname
);
1002 if (!hostname_is_valid(rvalue
, 0)) {
1003 log_syntax(unit
, LOG_WARNING
, filename
, line
, 0,
1004 "Hostname is not valid, ignoring assignment: %s", rvalue
);
1008 r
= dns_name_is_valid(rvalue
);
1010 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
1011 "Failed to check validity of hostname '%s', ignoring assignment: %m", rvalue
);
1015 log_syntax(unit
, LOG_WARNING
, filename
, line
, 0,
1016 "Hostname is not a valid DNS domain name, ignoring assignment: %s", rvalue
);
1020 return free_and_strdup_warn(hostname
, rvalue
);
1023 int config_parse_timezone(
1025 const char *filename
,
1027 const char *section
,
1028 unsigned section_line
,
1043 if (isempty(rvalue
)) {
1048 r
= verify_timezone(rvalue
, LOG_WARNING
);
1050 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
1051 "Timezone is not valid, ignoring assignment: %s", rvalue
);
1055 return free_and_strdup_warn(tz
, rvalue
);
1058 int config_parse_dns(
1060 const char *filename
,
1062 const char *section
,
1063 unsigned section_line
,
1070 Network
*n
= userdata
;
1078 if (isempty(rvalue
)) {
1079 for (unsigned i
= 0; i
< n
->n_dns
; i
++)
1080 in_addr_full_free(n
->dns
[i
]);
1081 n
->dns
= mfree(n
->dns
);
1086 for (const char *p
= rvalue
;;) {
1087 _cleanup_(in_addr_full_freep
) struct in_addr_full
*dns
= NULL
;
1088 _cleanup_free_
char *w
= NULL
;
1089 struct in_addr_full
**m
;
1091 r
= extract_first_word(&p
, &w
, NULL
, 0);
1095 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
1096 "Invalid syntax, ignoring: %s", rvalue
);
1102 r
= in_addr_full_new_from_string(w
, &dns
);
1104 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
1105 "Failed to parse dns server address, ignoring: %s", w
);
1109 if (IN_SET(dns
->port
, 53, 853))
1112 m
= reallocarray(n
->dns
, n
->n_dns
+ 1, sizeof(struct in_addr_full
*));
1116 m
[n
->n_dns
++] = TAKE_PTR(dns
);
1121 int config_parse_dnssec_negative_trust_anchors(
1123 const char *filename
,
1125 const char *section
,
1126 unsigned section_line
,
1141 if (isempty(rvalue
)) {
1142 *nta
= set_free_free(*nta
);
1146 for (const char *p
= rvalue
;;) {
1147 _cleanup_free_
char *w
= NULL
;
1149 r
= extract_first_word(&p
, &w
, NULL
, 0);
1153 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
1154 "Failed to extract negative trust anchor domain, ignoring: %s", rvalue
);
1160 r
= dns_name_is_valid(w
);
1162 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
1163 "%s is not a valid domain name, ignoring.", w
);
1167 r
= set_ensure_consume(nta
, &dns_name_hash_ops
, TAKE_PTR(w
));
1173 int config_parse_ntp(
1175 const char *filename
,
1177 const char *section
,
1178 unsigned section_line
,
1193 if (isempty(rvalue
)) {
1198 for (const char *p
= rvalue
;;) {
1199 _cleanup_free_
char *w
= NULL
;
1201 r
= extract_first_word(&p
, &w
, NULL
, 0);
1205 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
1206 "Failed to extract NTP server name, ignoring: %s", rvalue
);
1212 r
= dns_name_is_valid_or_address(w
);
1214 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
1215 "%s is not a valid domain name or IP address, ignoring.", w
);
1219 if (strv_length(*l
) > MAX_NTP_SERVERS
) {
1220 log_syntax(unit
, LOG_WARNING
, filename
, line
, 0,
1221 "More than %u NTP servers specified, ignoring \"%s\" and any subsequent entries.",
1222 MAX_NTP_SERVERS
, w
);
1226 r
= strv_consume(l
, TAKE_PTR(w
));
1232 int config_parse_required_for_online(
1234 const char *filename
,
1236 const char *section
,
1237 unsigned section_line
,
1244 Network
*network
= userdata
;
1245 LinkOperationalStateRange range
;
1246 bool required
= true;
1254 if (isempty(rvalue
)) {
1255 network
->required_for_online
= -1;
1256 network
->required_operstate_for_online
= LINK_OPERSTATE_RANGE_DEFAULT
;
1260 r
= parse_operational_state_range(rvalue
, &range
);
1262 r
= parse_boolean(rvalue
);
1264 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
1265 "Failed to parse %s= setting, ignoring assignment: %s",
1271 range
= LINK_OPERSTATE_RANGE_DEFAULT
;
1274 network
->required_for_online
= required
;
1275 network
->required_operstate_for_online
= range
;
1280 int config_parse_link_group(
1282 const char *filename
,
1284 const char *section
,
1285 unsigned section_line
,
1292 Network
*network
= userdata
;
1301 if (isempty(rvalue
)) {
1302 network
->group
= -1;
1306 r
= safe_atoi32(rvalue
, &group
);
1308 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
1309 "Failed to parse Group=, ignoring assignment: %s", rvalue
);
1314 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
1315 "Value of Group= must be in the range 0…2147483647, ignoring assignment: %s", rvalue
);
1319 network
->group
= group
;
1323 int config_parse_ignore_carrier_loss(
1325 const char *filename
,
1327 const char *section
,
1328 unsigned section_line
,
1335 Network
*network
= userdata
;
1344 if (isempty(rvalue
)) {
1345 network
->ignore_carrier_loss_set
= false;
1349 r
= parse_boolean(rvalue
);
1351 network
->ignore_carrier_loss_set
= true;
1352 network
->ignore_carrier_loss_usec
= r
> 0 ? USEC_INFINITY
: 0;
1356 r
= parse_sec(rvalue
, &usec
);
1358 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
1359 "Failed to parse %s=, ignoring assignment: %s", lvalue
, rvalue
);
1363 network
->ignore_carrier_loss_set
= true;
1364 network
->ignore_carrier_loss_usec
= usec
;
1368 DEFINE_CONFIG_PARSE_ENUM(config_parse_required_family_for_online
, link_required_address_family
, AddressFamily
,
1369 "Failed to parse RequiredFamilyForOnline= setting");
1371 DEFINE_CONFIG_PARSE_ENUM(config_parse_keep_configuration
, keep_configuration
, KeepConfiguration
,
1372 "Failed to parse KeepConfiguration= setting");
1374 static const char* const keep_configuration_table
[_KEEP_CONFIGURATION_MAX
] = {
1375 [KEEP_CONFIGURATION_NO
] = "no",
1376 [KEEP_CONFIGURATION_DHCP_ON_STOP
] = "dhcp-on-stop",
1377 [KEEP_CONFIGURATION_DHCP
] = "dhcp",
1378 [KEEP_CONFIGURATION_STATIC
] = "static",
1379 [KEEP_CONFIGURATION_YES
] = "yes",
1382 DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(keep_configuration
, KeepConfiguration
, KEEP_CONFIGURATION_YES
);
1384 static const char* const ipv6_link_local_address_gen_mode_table
[_IPV6_LINK_LOCAL_ADDRESS_GEN_MODE_MAX
] = {
1385 [IPV6_LINK_LOCAL_ADDRESSS_GEN_MODE_EUI64
] = "eui64",
1386 [IPV6_LINK_LOCAL_ADDRESSS_GEN_MODE_NONE
] = "none",
1387 [IPV6_LINK_LOCAL_ADDRESSS_GEN_MODE_STABLE_PRIVACY
] = "stable-privacy",
1388 [IPV6_LINK_LOCAL_ADDRESSS_GEN_MODE_RANDOM
] = "random",
1391 DEFINE_STRING_TABLE_LOOKUP(ipv6_link_local_address_gen_mode
, IPv6LinkLocalAddressGenMode
);
1392 DEFINE_CONFIG_PARSE_ENUM(config_parse_ipv6_link_local_address_gen_mode
, ipv6_link_local_address_gen_mode
, IPv6LinkLocalAddressGenMode
, "Failed to parse IPv6 link local address generation mode");
1394 static const char* const activation_policy_table
[_ACTIVATION_POLICY_MAX
] = {
1395 [ACTIVATION_POLICY_UP
] = "up",
1396 [ACTIVATION_POLICY_ALWAYS_UP
] = "always-up",
1397 [ACTIVATION_POLICY_MANUAL
] = "manual",
1398 [ACTIVATION_POLICY_ALWAYS_DOWN
] = "always-down",
1399 [ACTIVATION_POLICY_DOWN
] = "down",
1400 [ACTIVATION_POLICY_BOUND
] = "bound",
1403 DEFINE_STRING_TABLE_LOOKUP(activation_policy
, ActivationPolicy
);
1404 DEFINE_CONFIG_PARSE_ENUM(config_parse_activation_policy
, activation_policy
, ActivationPolicy
, "Failed to parse activation policy");