1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
3 /* Make sure the net/if.h header is included before any linux/ one */
5 #include <netinet/in.h>
6 #include <linux/netdevice.h>
9 #include "alloc-util.h"
10 #include "conf-files.h"
11 #include "conf-parser.h"
12 #include "dns-domain.h"
14 #include "hostname-util.h"
15 #include "in-addr-util.h"
16 #include "net-condition.h"
17 #include "netdev/macvlan.h"
18 #include "networkd-address-label.h"
19 #include "networkd-address.h"
20 #include "networkd-bridge-fdb.h"
21 #include "networkd-bridge-mdb.h"
22 #include "networkd-dhcp-common.h"
23 #include "networkd-dhcp-server-static-lease.h"
24 #include "networkd-ipv6-proxy-ndp.h"
25 #include "networkd-manager.h"
26 #include "networkd-ndisc.h"
27 #include "networkd-neighbor.h"
28 #include "networkd-network.h"
29 #include "networkd-nexthop.h"
30 #include "networkd-radv.h"
31 #include "networkd-route.h"
32 #include "networkd-routing-policy-rule.h"
33 #include "networkd-sriov.h"
34 #include "parse-util.h"
35 #include "path-lookup.h"
37 #include "radv-internal.h"
39 #include "socket-util.h"
40 #include "stat-util.h"
41 #include "string-table.h"
42 #include "string-util.h"
46 /* Let's assume that anything above this number is a user misconfiguration. */
47 #define MAX_NTP_SERVERS 128U
49 static int network_resolve_netdev_one(Network
*network
, const char *name
, NetDevKind kind
, NetDev
**ret
) {
50 const char *kind_string
;
54 /* For test-networkd-conf, the check must be earlier than the assertions. */
59 assert(network
->manager
);
60 assert(network
->filename
);
63 if (kind
== _NETDEV_KIND_TUNNEL
)
64 kind_string
= "tunnel";
66 kind_string
= netdev_kind_to_string(kind
);
68 return log_warning_errno(SYNTHETIC_ERRNO(EINVAL
),
69 "%s: Invalid NetDev kind of %s, ignoring assignment.",
70 network
->filename
, name
);
73 r
= netdev_get(network
->manager
, name
, &netdev
);
75 return log_warning_errno(r
, "%s: %s NetDev could not be found, ignoring assignment.",
76 network
->filename
, name
);
78 if (netdev
->kind
!= kind
&& !(kind
== _NETDEV_KIND_TUNNEL
&&
84 NETDEV_KIND_IP6GRETAP
,
90 return log_warning_errno(SYNTHETIC_ERRNO(EINVAL
),
91 "%s: NetDev %s is not a %s, ignoring assignment",
92 network
->filename
, name
, kind_string
);
94 *ret
= netdev_ref(netdev
);
98 static int network_resolve_stacked_netdevs(Network
*network
) {
104 HASHMAP_FOREACH_KEY(kind
, name
, network
->stacked_netdev_names
) {
105 _cleanup_(netdev_unrefp
) NetDev
*netdev
= NULL
;
107 if (network_resolve_netdev_one(network
, name
, PTR_TO_INT(kind
), &netdev
) <= 0)
110 r
= hashmap_ensure_put(&network
->stacked_netdevs
, &string_hash_ops
, netdev
->ifname
, netdev
);
114 log_warning_errno(r
, "%s: Failed to add NetDev '%s' to network, ignoring: %m",
115 network
->filename
, (const char *) name
);
123 int network_verify(Network
*network
) {
127 assert(network
->manager
);
128 assert(network
->filename
);
130 if (net_match_is_empty(&network
->match
) && !network
->conditions
)
131 return log_warning_errno(SYNTHETIC_ERRNO(EINVAL
),
132 "%s: No valid settings found in the [Match] section, ignoring file. "
133 "To match all interfaces, add Name=* in the [Match] section.",
136 /* skip out early if configuration does not match the environment */
137 if (!condition_test_list(network
->conditions
, environ
, NULL
, NULL
, NULL
))
138 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL
),
139 "%s: Conditions in the file do not match the system environment, skipping.",
142 if (network
->keep_master
) {
143 if (network
->batadv_name
)
144 log_warning("%s: BatmanAdvanced= set with KeepMaster= enabled, ignoring BatmanAdvanced=.",
146 if (network
->bond_name
)
147 log_warning("%s: Bond= set with KeepMaster= enabled, ignoring Bond=.",
149 if (network
->bridge_name
)
150 log_warning("%s: Bridge= set with KeepMaster= enabled, ignoring Bridge=.",
152 if (network
->vrf_name
)
153 log_warning("%s: VRF= set with KeepMaster= enabled, ignoring VRF=.",
156 network
->batadv_name
= mfree(network
->batadv_name
);
157 network
->bond_name
= mfree(network
->bond_name
);
158 network
->bridge_name
= mfree(network
->bridge_name
);
159 network
->vrf_name
= mfree(network
->vrf_name
);
162 (void) network_resolve_netdev_one(network
, network
->batadv_name
, NETDEV_KIND_BATADV
, &network
->batadv
);
163 (void) network_resolve_netdev_one(network
, network
->bond_name
, NETDEV_KIND_BOND
, &network
->bond
);
164 (void) network_resolve_netdev_one(network
, network
->bridge_name
, NETDEV_KIND_BRIDGE
, &network
->bridge
);
165 (void) network_resolve_netdev_one(network
, network
->vrf_name
, NETDEV_KIND_VRF
, &network
->vrf
);
166 r
= network_resolve_stacked_netdevs(network
);
170 /* Free unnecessary entries. */
171 network
->batadv_name
= mfree(network
->batadv_name
);
172 network
->bond_name
= mfree(network
->bond_name
);
173 network
->bridge_name
= mfree(network
->bridge_name
);
174 network
->vrf_name
= mfree(network
->vrf_name
);
175 network
->stacked_netdev_names
= hashmap_free_free_key(network
->stacked_netdev_names
);
178 /* Bonding slave does not support addressing. */
179 if (network
->link_local
>= 0 && network
->link_local
!= ADDRESS_FAMILY_NO
) {
180 log_warning("%s: Cannot enable LinkLocalAddressing= when Bond= is specified, disabling LinkLocalAddressing=.",
182 network
->link_local
= ADDRESS_FAMILY_NO
;
184 if (!ordered_hashmap_isempty(network
->addresses_by_section
))
185 log_warning("%s: Cannot set addresses when Bond= is specified, ignoring addresses.",
187 if (!hashmap_isempty(network
->routes_by_section
))
188 log_warning("%s: Cannot set routes when Bond= is specified, ignoring routes.",
191 network
->addresses_by_section
= ordered_hashmap_free(network
->addresses_by_section
);
192 network
->routes_by_section
= hashmap_free(network
->routes_by_section
);
195 if (network
->link_local
< 0) {
196 network
->link_local
= ADDRESS_FAMILY_IPV6
;
198 if (network
->keep_master
|| network
->bridge
)
199 network
->link_local
= ADDRESS_FAMILY_NO
;
203 HASHMAP_FOREACH(netdev
, network
->stacked_netdevs
) {
206 if (netdev
->kind
== NETDEV_KIND_MACVLAN
)
208 else if (netdev
->kind
== NETDEV_KIND_MACVTAP
)
213 if (m
->mode
== NETDEV_MACVLAN_MODE_PASSTHRU
)
214 network
->link_local
= ADDRESS_FAMILY_NO
;
216 /* There won't be a passthru MACVLAN/MACVTAP if there's already one in another mode */
222 if (network
->ipv6ll_address_gen_mode
== IPV6_LINK_LOCAL_ADDRESSS_GEN_MODE_NONE
)
223 SET_FLAG(network
->link_local
, ADDRESS_FAMILY_IPV6
, false);
225 if (in6_addr_is_set(&network
->ipv6ll_stable_secret
) &&
226 network
->ipv6ll_address_gen_mode
< 0)
227 network
->ipv6ll_address_gen_mode
= IPV6_LINK_LOCAL_ADDRESSS_GEN_MODE_STABLE_PRIVACY
;
229 network_adjust_ipv6_proxy_ndp(network
);
230 network_adjust_ndisc(network
);
231 network_adjust_dhcp(network
);
232 network_adjust_radv(network
);
233 network_adjust_bridge_vlan(network
);
235 if (network
->mtu
> 0 && network
->dhcp_use_mtu
) {
236 log_warning("%s: MTUBytes= in [Link] section and UseMTU= in [DHCP] section are set. "
237 "Disabling UseMTU=.", network
->filename
);
238 network
->dhcp_use_mtu
= false;
241 if (network
->dhcp_critical
>= 0) {
242 if (network
->keep_configuration
>= 0) {
243 if (network
->manager
->keep_configuration
< 0)
244 log_warning("%s: Both KeepConfiguration= and deprecated CriticalConnection= are set. "
245 "Ignoring CriticalConnection=.", network
->filename
);
246 } else if (network
->dhcp_critical
)
247 /* CriticalConnection=yes also preserve foreign static configurations. */
248 network
->keep_configuration
= KEEP_CONFIGURATION_YES
;
250 network
->keep_configuration
= KEEP_CONFIGURATION_NO
;
253 if (!strv_isempty(network
->bind_carrier
)) {
254 if (!IN_SET(network
->activation_policy
, _ACTIVATION_POLICY_INVALID
, ACTIVATION_POLICY_BOUND
))
255 log_warning("%s: ActivationPolicy=bound is required with BindCarrier=. "
256 "Setting ActivationPolicy=bound.", network
->filename
);
257 network
->activation_policy
= ACTIVATION_POLICY_BOUND
;
258 } else if (network
->activation_policy
== ACTIVATION_POLICY_BOUND
) {
259 log_warning("%s: ActivationPolicy=bound requires BindCarrier=. "
260 "Ignoring ActivationPolicy=bound.", network
->filename
);
261 network
->activation_policy
= ACTIVATION_POLICY_UP
;
264 if (network
->activation_policy
== _ACTIVATION_POLICY_INVALID
)
265 network
->activation_policy
= ACTIVATION_POLICY_UP
;
267 if (network
->activation_policy
== ACTIVATION_POLICY_ALWAYS_UP
) {
268 if (network
->ignore_carrier_loss_set
&& network
->ignore_carrier_loss_usec
< USEC_INFINITY
)
269 log_warning("%s: IgnoreCarrierLoss=no or finite timespan conflicts with ActivationPolicy=always-up. "
270 "Setting IgnoreCarrierLoss=yes.", network
->filename
);
271 network
->ignore_carrier_loss_set
= true;
272 network
->ignore_carrier_loss_usec
= USEC_INFINITY
;
275 if (!network
->ignore_carrier_loss_set
) /* Set implied default. */
276 network
->ignore_carrier_loss_usec
= network
->configure_without_carrier
? USEC_INFINITY
: 0;
278 if (IN_SET(network
->activation_policy
, ACTIVATION_POLICY_DOWN
, ACTIVATION_POLICY_ALWAYS_DOWN
, ACTIVATION_POLICY_MANUAL
)) {
279 if (network
->required_for_online
< 0 ||
280 (network
->required_for_online
== true && network
->activation_policy
== ACTIVATION_POLICY_ALWAYS_DOWN
)) {
281 log_debug("%s: Setting RequiredForOnline=no because ActivationPolicy=%s.", network
->filename
,
282 activation_policy_to_string(network
->activation_policy
));
283 network
->required_for_online
= false;
284 } else if (network
->required_for_online
== true)
285 log_warning("%s: RequiredForOnline=yes and ActivationPolicy=%s, "
286 "this may cause a delay at boot.", network
->filename
,
287 activation_policy_to_string(network
->activation_policy
));
290 if (network
->required_for_online
< 0)
291 network
->required_for_online
= true;
293 if (network
->keep_configuration
< 0)
294 network
->keep_configuration
= KEEP_CONFIGURATION_NO
;
296 if (network
->ipv6_proxy_ndp
== 0 && !set_isempty(network
->ipv6_proxy_ndp_addresses
)) {
297 log_warning("%s: IPv6ProxyNDP= is disabled. Ignoring IPv6ProxyNDPAddress=.", network
->filename
);
298 network
->ipv6_proxy_ndp_addresses
= set_free_free(network
->ipv6_proxy_ndp_addresses
);
301 r
= network_drop_invalid_addresses(network
);
303 return r
; /* network_drop_invalid_addresses() logs internally. */
304 network_drop_invalid_routes(network
);
305 r
= network_drop_invalid_nexthops(network
);
308 network_drop_invalid_bridge_fdb_entries(network
);
309 network_drop_invalid_bridge_mdb_entries(network
);
310 r
= network_drop_invalid_neighbors(network
);
313 network_drop_invalid_address_labels(network
);
314 network_drop_invalid_prefixes(network
);
315 network_drop_invalid_route_prefixes(network
);
316 network_drop_invalid_routing_policy_rules(network
);
317 network_drop_invalid_qdisc(network
);
318 network_drop_invalid_tclass(network
);
319 r
= sr_iov_drop_invalid_sections(UINT32_MAX
, network
->sr_iov_by_section
);
321 return r
; /* sr_iov_drop_invalid_sections() logs internally. */
322 network_drop_invalid_static_leases(network
);
327 int network_load_one(Manager
*manager
, OrderedHashmap
**networks
, const char *filename
) {
328 _cleanup_free_
char *fname
= NULL
, *name
= NULL
;
329 _cleanup_(network_unrefp
) Network
*network
= NULL
;
330 const char *dropin_dirname
;
337 r
= null_or_empty_path(filename
);
339 return log_warning_errno(r
, "Failed to check if \"%s\" is empty: %m", filename
);
341 log_debug("Skipping empty file: %s", filename
);
345 fname
= strdup(filename
);
349 name
= strdup(basename(filename
));
353 d
= strrchr(name
, '.');
355 return log_warning_errno(SYNTHETIC_ERRNO(EINVAL
), "Invalid file name: %s", filename
);
359 dropin_dirname
= strjoina(name
, ".network.d");
361 network
= new(Network
, 1);
365 *network
= (Network
) {
366 .filename
= TAKE_PTR(fname
),
367 .name
= TAKE_PTR(name
),
372 .required_for_online
= -1,
373 .required_operstate_for_online
= LINK_OPERSTATE_RANGE_INVALID
,
374 .activation_policy
= _ACTIVATION_POLICY_INVALID
,
381 .keep_configuration
= manager
->keep_configuration
,
383 .dhcp_duid
.type
= _DUID_TYPE_INVALID
,
385 .dhcp_use_ntp
= true,
386 .dhcp_routes_to_ntp
= true,
387 .dhcp_use_sip
= true,
388 .dhcp_use_captive_portal
= true,
389 .dhcp_use_dns
= true,
390 .dhcp_routes_to_dns
= true,
391 .dhcp_use_hostname
= true,
392 .dhcp_use_routes
= true,
393 .dhcp_use_gateway
= -1,
394 .dhcp_send_hostname
= true,
395 .dhcp_send_release
= true,
396 .dhcp_route_metric
= DHCP_ROUTE_METRIC
,
397 .dhcp_use_rapid_commit
= -1,
398 .dhcp_client_identifier
= _DHCP_CLIENT_ID_INVALID
,
399 .dhcp_route_table
= RT_TABLE_MAIN
,
400 .dhcp_ip_service_type
= -1,
401 .dhcp_broadcast
= -1,
402 .dhcp_ipv6_only_mode
= -1,
404 .dhcp6_use_address
= true,
405 .dhcp6_use_pd_prefix
= true,
406 .dhcp6_use_dns
= true,
407 .dhcp6_use_hostname
= true,
408 .dhcp6_use_ntp
= true,
409 .dhcp6_use_captive_portal
= true,
410 .dhcp6_use_rapid_commit
= true,
411 .dhcp6_send_hostname
= true,
412 .dhcp6_duid
.type
= _DUID_TYPE_INVALID
,
413 .dhcp6_client_start_mode
= _DHCP6_CLIENT_START_MODE_INVALID
,
414 .dhcp6_send_release
= true,
417 .dhcp_pd_announce
= true,
418 .dhcp_pd_assign
= true,
419 .dhcp_pd_manage_temporary_address
= true,
420 .dhcp_pd_subnet_id
= -1,
421 .dhcp_pd_route_metric
= DHCP6PD_ROUTE_METRIC
,
423 .dhcp_server_bind_to_interface
= true,
424 .dhcp_server_emit
[SD_DHCP_LEASE_DNS
].emit
= true,
425 .dhcp_server_emit
[SD_DHCP_LEASE_NTP
].emit
= true,
426 .dhcp_server_emit
[SD_DHCP_LEASE_SIP
].emit
= true,
427 .dhcp_server_emit_router
= true,
428 .dhcp_server_emit_timezone
= true,
429 .dhcp_server_rapid_commit
= true,
430 .dhcp_server_persist_leases
= -1,
432 .router_lifetime_usec
= RADV_DEFAULT_ROUTER_LIFETIME_USEC
,
433 .router_dns_lifetime_usec
= RADV_DEFAULT_VALID_LIFETIME_USEC
,
434 .router_emit_dns
= true,
435 .router_emit_domains
= true,
441 .allow_port_to_be_root
= -1,
443 .multicast_flood
= -1,
444 .multicast_to_unicast
= -1,
445 .neighbor_suppression
= -1,
447 .bridge_proxy_arp
= -1,
448 .bridge_proxy_arp_wifi
= -1,
449 .priority
= LINK_BRIDGE_PORT_PRIORITY_INVALID
,
450 .multicast_router
= _MULTICAST_ROUTER_INVALID
,
452 .bridge_vlan_pvid
= BRIDGE_VLAN_KEEP_PVID
,
454 .lldp_mode
= LLDP_MODE_ROUTERS_ONLY
,
455 .lldp_multicast_mode
= _SD_LLDP_MULTICAST_MODE_INVALID
,
457 .dns_default_route
= -1,
458 .llmnr
= RESOLVE_SUPPORT_YES
,
459 .mdns
= RESOLVE_SUPPORT_NO
,
460 .dnssec_mode
= _DNSSEC_MODE_INVALID
,
461 .dns_over_tls_mode
= _DNS_OVER_TLS_MODE_INVALID
,
463 /* If LinkLocalAddressing= is not set, then set to ADDRESS_FAMILY_IPV6 later. */
464 .link_local
= _ADDRESS_FAMILY_INVALID
,
465 .ipv6ll_address_gen_mode
= _IPV6_LINK_LOCAL_ADDRESS_GEN_MODE_INVALID
,
467 .ip_forwarding
= { -1, -1, },
468 .ipv4_accept_local
= -1,
469 .ipv4_route_localnet
= -1,
470 .ipv6_privacy_extensions
= _IPV6_PRIVACY_EXTENSIONS_INVALID
,
471 .ipv6_dad_transmits
= -1,
472 .ipv6_proxy_ndp
= -1,
474 .proxy_arp_pvlan
= -1,
475 .ipv4_rp_filter
= _IP_REVERSE_PATH_FILTER_INVALID
,
478 .ndisc_use_redirect
= true,
479 .ndisc_use_dns
= true,
480 .ndisc_use_gateway
= true,
481 .ndisc_use_captive_portal
= true,
482 .ndisc_use_route_prefix
= true,
483 .ndisc_use_autonomous_prefix
= true,
484 .ndisc_use_onlink_prefix
= true,
485 .ndisc_use_mtu
= true,
486 .ndisc_use_hop_limit
= true,
487 .ndisc_use_reachable_time
= true,
488 .ndisc_use_retransmission_time
= true,
489 .ndisc_route_table
= RT_TABLE_MAIN
,
490 .ndisc_route_metric_high
= IPV6RA_ROUTE_METRIC_HIGH
,
491 .ndisc_route_metric_medium
= IPV6RA_ROUTE_METRIC_MEDIUM
,
492 .ndisc_route_metric_low
= IPV6RA_ROUTE_METRIC_LOW
,
493 .ndisc_start_dhcp6_client
= IPV6_ACCEPT_RA_START_DHCP6_CLIENT_YES
,
495 .can_termination
= -1,
497 .ipoib_mode
= _IP_OVER_INFINIBAND_MODE_INVALID
,
501 r
= config_parse_many(
502 STRV_MAKE_CONST(filename
), NETWORK_DIRS
, dropin_dirname
, /* root = */ NULL
,
510 "RoutingPolicyRule\0"
513 "DHCP\0" /* compat */
516 "DHCPv6PrefixDelegation\0" /* compat */
517 "DHCPPrefixDelegation\0"
519 "DHCPServerStaticLease\0"
521 "IPv6NDPProxyAddress\0"
527 "IPv6PrefixDelegation\0"
532 "TrafficControlQueueingDiscipline\0"
538 "DeficitRoundRobinScheduler\0"
539 "DeficitRoundRobinSchedulerClass\0"
540 "EnhancedTransmissionSelection\0"
542 "FairQueueingControlledDelay\0"
544 "GenericRandomEarlyDetection\0"
545 "HeavyHitterFilter\0"
546 "HierarchyTokenBucket\0"
547 "HierarchyTokenBucketClass\0"
553 "QuickFairQueueing\0"
554 "QuickFairQueueingClass\0"
555 "StochasticFairBlue\0"
556 "StochasticFairnessQueueing\0"
557 "TokenBucketFilter\0"
558 "TrivialLinkEqualizer\0",
559 config_item_perf_lookup
, network_network_gperf_lookup
,
562 &network
->stats_by_path
,
565 return r
; /* config_parse_many() logs internally. */
567 r
= network_add_ipv4ll_route(network
);
569 return log_warning_errno(r
, "%s: Failed to add IPv4LL route: %m", network
->filename
);
571 r
= network_add_default_route_on_device(network
);
573 return log_warning_errno(r
, "%s: Failed to add default route on device: %m",
576 r
= network_verify(network
);
578 return r
; /* network_verify() logs internally. */
580 r
= ordered_hashmap_ensure_put(networks
, &string_hash_ops
, network
->name
, network
);
582 return log_warning_errno(r
, "%s: Failed to store configuration into hashmap: %m", filename
);
588 int network_load(Manager
*manager
, OrderedHashmap
**networks
) {
589 _cleanup_strv_free_
char **files
= NULL
;
594 ordered_hashmap_clear_with_destructor(*networks
, network_unref
);
596 r
= conf_files_list_strv(&files
, ".network", NULL
, 0, NETWORK_DIRS
);
598 return log_error_errno(r
, "Failed to enumerate network files: %m");
600 STRV_FOREACH(f
, files
)
601 (void) network_load_one(manager
, networks
, *f
);
606 int network_reload(Manager
*manager
) {
607 OrderedHashmap
*new_networks
= NULL
;
613 r
= network_load(manager
, &new_networks
);
617 ORDERED_HASHMAP_FOREACH(n
, new_networks
) {
618 r
= network_get_by_name(manager
, n
->name
, &old
);
620 log_debug("Found new .network file: %s", n
->filename
);
624 if (!stats_by_path_equal(n
->stats_by_path
, old
->stats_by_path
)) {
625 log_debug("Found updated .network file: %s", n
->filename
);
629 r
= ordered_hashmap_replace(new_networks
, old
->name
, old
);
637 ordered_hashmap_free_with_destructor(manager
->networks
, network_unref
);
638 manager
->networks
= new_networks
;
640 r
= manager_build_dhcp_pd_subnet_ids(manager
);
644 r
= manager_build_nexthop_ids(manager
);
651 ordered_hashmap_free_with_destructor(new_networks
, network_unref
);
656 int manager_build_dhcp_pd_subnet_ids(Manager
*manager
) {
662 set_clear(manager
->dhcp_pd_subnet_ids
);
664 ORDERED_HASHMAP_FOREACH(n
, manager
->networks
) {
671 if (n
->dhcp_pd_subnet_id
< 0)
674 r
= set_ensure_put(&manager
->dhcp_pd_subnet_ids
, &uint64_hash_ops
, &n
->dhcp_pd_subnet_id
);
682 static Network
*network_free(Network
*network
) {
687 free(network
->filename
);
688 free(network
->description
);
689 strv_free(network
->dropins
);
690 hashmap_free(network
->stats_by_path
);
693 net_match_clear(&network
->match
);
694 condition_free_list(network
->conditions
);
697 strv_free(network
->bind_carrier
);
700 strv_free(network
->ntp
);
703 for (unsigned i
= 0; i
< network
->n_dns
; i
++)
704 in_addr_full_free(network
->dns
[i
]);
706 ordered_set_free(network
->search_domains
);
707 ordered_set_free(network
->route_domains
);
708 set_free_free(network
->dnssec_negative_trust_anchors
);
711 free(network
->dhcp_server_relay_agent_circuit_id
);
712 free(network
->dhcp_server_relay_agent_remote_id
);
713 free(network
->dhcp_server_boot_server_name
);
714 free(network
->dhcp_server_boot_filename
);
715 free(network
->dhcp_server_timezone
);
716 free(network
->dhcp_server_uplink_name
);
717 for (sd_dhcp_lease_server_type_t t
= 0; t
< _SD_DHCP_LEASE_SERVER_TYPE_MAX
; t
++)
718 free(network
->dhcp_server_emit
[t
].addresses
);
719 ordered_hashmap_free(network
->dhcp_server_send_options
);
720 ordered_hashmap_free(network
->dhcp_server_send_vendor_options
);
723 free(network
->dhcp_vendor_class_identifier
);
724 free(network
->dhcp_mudurl
);
725 free(network
->dhcp_hostname
);
726 free(network
->dhcp_label
);
727 set_free(network
->dhcp_deny_listed_ip
);
728 set_free(network
->dhcp_allow_listed_ip
);
729 strv_free(network
->dhcp_user_class
);
730 set_free(network
->dhcp_request_options
);
731 ordered_hashmap_free(network
->dhcp_client_send_options
);
732 ordered_hashmap_free(network
->dhcp_client_send_vendor_options
);
733 free(network
->dhcp_netlabel
);
734 nft_set_context_clear(&network
->dhcp_nft_set_context
);
737 free(network
->dhcp6_mudurl
);
738 free(network
->dhcp6_hostname
);
739 strv_free(network
->dhcp6_user_class
);
740 strv_free(network
->dhcp6_vendor_class
);
741 set_free(network
->dhcp6_request_options
);
742 ordered_hashmap_free(network
->dhcp6_client_send_options
);
743 ordered_hashmap_free(network
->dhcp6_client_send_vendor_options
);
744 free(network
->dhcp6_netlabel
);
745 nft_set_context_clear(&network
->dhcp6_nft_set_context
);
748 free(network
->dhcp_pd_uplink_name
);
749 set_free(network
->dhcp_pd_tokens
);
750 free(network
->dhcp_pd_netlabel
);
751 nft_set_context_clear(&network
->dhcp_pd_nft_set_context
);
753 /* Router advertisement */
754 ordered_set_free(network
->router_search_domains
);
755 free(network
->router_dns
);
756 free(network
->router_uplink_name
);
759 set_free(network
->ndisc_deny_listed_router
);
760 set_free(network
->ndisc_allow_listed_router
);
761 set_free(network
->ndisc_deny_listed_prefix
);
762 set_free(network
->ndisc_allow_listed_prefix
);
763 set_free(network
->ndisc_deny_listed_route_prefix
);
764 set_free(network
->ndisc_allow_listed_route_prefix
);
765 set_free(network
->ndisc_tokens
);
766 free(network
->ndisc_netlabel
);
767 nft_set_context_clear(&network
->ndisc_nft_set_context
);
770 free(network
->lldp_mudurl
);
773 free(network
->batadv_name
);
774 free(network
->bridge_name
);
775 free(network
->bond_name
);
776 free(network
->vrf_name
);
777 hashmap_free_free_key(network
->stacked_netdev_names
);
778 netdev_unref(network
->bridge
);
779 netdev_unref(network
->bond
);
780 netdev_unref(network
->vrf
);
781 hashmap_free_with_destructor(network
->stacked_netdevs
, netdev_unref
);
784 set_free_free(network
->ipv6_proxy_ndp_addresses
);
785 ordered_hashmap_free(network
->addresses_by_section
);
786 hashmap_free(network
->routes_by_section
);
787 ordered_hashmap_free(network
->nexthops_by_section
);
788 hashmap_free_with_destructor(network
->bridge_fdb_entries_by_section
, bridge_fdb_free
);
789 hashmap_free_with_destructor(network
->bridge_mdb_entries_by_section
, bridge_mdb_free
);
790 ordered_hashmap_free(network
->neighbors_by_section
);
791 hashmap_free_with_destructor(network
->address_labels_by_section
, address_label_free
);
792 hashmap_free_with_destructor(network
->prefixes_by_section
, prefix_free
);
793 hashmap_free_with_destructor(network
->route_prefixes_by_section
, route_prefix_free
);
794 hashmap_free_with_destructor(network
->pref64_prefixes_by_section
, pref64_prefix_free
);
795 hashmap_free_with_destructor(network
->rules_by_section
, routing_policy_rule_free
);
796 hashmap_free_with_destructor(network
->dhcp_static_leases_by_section
, dhcp_static_lease_free
);
797 ordered_hashmap_free_with_destructor(network
->sr_iov_by_section
, sr_iov_free
);
798 hashmap_free_with_destructor(network
->qdiscs_by_section
, qdisc_free
);
799 hashmap_free_with_destructor(network
->tclasses_by_section
, tclass_free
);
801 return mfree(network
);
804 DEFINE_TRIVIAL_REF_UNREF_FUNC(Network
, network
, network_free
);
806 int network_get_by_name(Manager
*manager
, const char *name
, Network
**ret
) {
813 network
= ordered_hashmap_get(manager
->networks
, name
);
822 bool network_has_static_ipv6_configurations(Network
*network
) {
831 ORDERED_HASHMAP_FOREACH(address
, network
->addresses_by_section
)
832 if (address
->family
== AF_INET6
)
835 HASHMAP_FOREACH(route
, network
->routes_by_section
)
836 if (route
->family
== AF_INET6
)
839 HASHMAP_FOREACH(fdb
, network
->bridge_fdb_entries_by_section
)
840 if (fdb
->family
== AF_INET6
)
843 HASHMAP_FOREACH(mdb
, network
->bridge_mdb_entries_by_section
)
844 if (mdb
->family
== AF_INET6
)
847 ORDERED_HASHMAP_FOREACH(neighbor
, network
->neighbors_by_section
)
848 if (neighbor
->family
== AF_INET6
)
851 if (!hashmap_isempty(network
->address_labels_by_section
))
854 if (!hashmap_isempty(network
->prefixes_by_section
))
857 if (!hashmap_isempty(network
->route_prefixes_by_section
))
860 if (!hashmap_isempty(network
->pref64_prefixes_by_section
))
866 int config_parse_stacked_netdev(
868 const char *filename
,
871 unsigned section_line
,
878 _cleanup_free_
char *name
= NULL
;
879 NetDevKind kind
= ltype
;
880 Hashmap
**h
= ASSERT_PTR(data
);
896 _NETDEV_KIND_TUNNEL
));
898 if (!ifname_valid(rvalue
)) {
899 log_syntax(unit
, LOG_WARNING
, filename
, line
, 0,
900 "Invalid netdev name in %s=, ignoring assignment: %s", lvalue
, rvalue
);
904 name
= strdup(rvalue
);
908 r
= hashmap_ensure_put(h
, &string_hash_ops
, name
, INT_TO_PTR(kind
));
912 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
913 "Cannot add NetDev '%s' to network, ignoring assignment: %m", name
);
915 log_syntax(unit
, LOG_DEBUG
, filename
, line
, r
,
916 "NetDev '%s' specified twice, ignoring.", name
);
923 int config_parse_domains(
925 const char *filename
,
928 unsigned section_line
,
935 Network
*n
= ASSERT_PTR(userdata
);
942 if (isempty(rvalue
)) {
943 n
->search_domains
= ordered_set_free(n
->search_domains
);
944 n
->route_domains
= ordered_set_free(n
->route_domains
);
948 for (const char *p
= rvalue
;;) {
949 _cleanup_free_
char *w
= NULL
, *normalized
= NULL
;
953 r
= extract_first_word(&p
, &w
, NULL
, 0);
957 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
958 "Failed to extract search or route domain, ignoring: %s", rvalue
);
964 is_route
= w
[0] == '~';
965 domain
= is_route
? w
+ 1 : w
;
967 if (dns_name_is_root(domain
) || streq(domain
, "*")) {
968 /* If the root domain appears as is, or the special token "*" is found, we'll
969 * consider this as routing domain, unconditionally. */
971 domain
= "."; /* make sure we don't allow empty strings, thus write the root
974 r
= dns_name_normalize(domain
, 0, &normalized
);
976 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
977 "'%s' is not a valid domain name, ignoring.", domain
);
983 if (is_localhost(domain
)) {
984 log_syntax(unit
, LOG_WARNING
, filename
, line
, 0,
985 "'localhost' domain may not be configured as search or route domain, ignoring assignment: %s",
991 OrderedSet
**set
= is_route
? &n
->route_domains
: &n
->search_domains
;
992 r
= ordered_set_put_strdup(set
, domain
);
1000 int config_parse_timezone(
1002 const char *filename
,
1004 const char *section
,
1005 unsigned section_line
,
1012 char **tz
= ASSERT_PTR(data
);
1019 if (isempty(rvalue
)) {
1024 r
= verify_timezone(rvalue
, LOG_WARNING
);
1026 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
1027 "Timezone is not valid, ignoring assignment: %s", rvalue
);
1031 return free_and_strdup_warn(tz
, rvalue
);
1034 int config_parse_dns(
1036 const char *filename
,
1038 const char *section
,
1039 unsigned section_line
,
1046 Network
*n
= ASSERT_PTR(userdata
);
1053 if (isempty(rvalue
)) {
1054 for (unsigned i
= 0; i
< n
->n_dns
; i
++)
1055 in_addr_full_free(n
->dns
[i
]);
1056 n
->dns
= mfree(n
->dns
);
1061 for (const char *p
= rvalue
;;) {
1062 _cleanup_(in_addr_full_freep
) struct in_addr_full
*dns
= NULL
;
1063 _cleanup_free_
char *w
= NULL
;
1064 struct in_addr_full
**m
;
1066 r
= extract_first_word(&p
, &w
, NULL
, 0);
1070 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
1071 "Invalid syntax, ignoring: %s", rvalue
);
1077 r
= in_addr_full_new_from_string(w
, &dns
);
1079 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
1080 "Failed to parse dns server address, ignoring: %s", w
);
1084 if (IN_SET(dns
->port
, 53, 853))
1087 m
= reallocarray(n
->dns
, n
->n_dns
+ 1, sizeof(struct in_addr_full
*));
1091 m
[n
->n_dns
++] = TAKE_PTR(dns
);
1096 int config_parse_dnssec_negative_trust_anchors(
1098 const char *filename
,
1100 const char *section
,
1101 unsigned section_line
,
1108 Set
**nta
= ASSERT_PTR(data
);
1115 if (isempty(rvalue
)) {
1116 *nta
= set_free_free(*nta
);
1120 for (const char *p
= rvalue
;;) {
1121 _cleanup_free_
char *w
= NULL
;
1123 r
= extract_first_word(&p
, &w
, NULL
, 0);
1127 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
1128 "Failed to extract negative trust anchor domain, ignoring: %s", rvalue
);
1134 r
= dns_name_is_valid(w
);
1136 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
1137 "%s is not a valid domain name, ignoring.", w
);
1141 r
= set_ensure_consume(nta
, &dns_name_hash_ops
, TAKE_PTR(w
));
1147 int config_parse_ntp(
1149 const char *filename
,
1151 const char *section
,
1152 unsigned section_line
,
1159 char ***l
= ASSERT_PTR(data
);
1166 if (isempty(rvalue
)) {
1171 for (const char *p
= rvalue
;;) {
1172 _cleanup_free_
char *w
= NULL
;
1174 r
= extract_first_word(&p
, &w
, NULL
, 0);
1178 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
1179 "Failed to extract NTP server name, ignoring: %s", rvalue
);
1185 r
= dns_name_is_valid_or_address(w
);
1187 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
1188 "%s is not a valid domain name or IP address, ignoring.", w
);
1192 if (strv_length(*l
) > MAX_NTP_SERVERS
) {
1193 log_syntax(unit
, LOG_WARNING
, filename
, line
, 0,
1194 "More than %u NTP servers specified, ignoring \"%s\" and any subsequent entries.",
1195 MAX_NTP_SERVERS
, w
);
1199 r
= strv_consume(l
, TAKE_PTR(w
));
1205 int config_parse_required_for_online(
1207 const char *filename
,
1209 const char *section
,
1210 unsigned section_line
,
1217 Network
*network
= ASSERT_PTR(userdata
);
1224 if (isempty(rvalue
)) {
1225 network
->required_for_online
= -1;
1226 network
->required_operstate_for_online
= LINK_OPERSTATE_RANGE_INVALID
;
1230 r
= parse_operational_state_range(rvalue
, &network
->required_operstate_for_online
);
1232 r
= parse_boolean(rvalue
);
1234 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
1235 "Failed to parse %s= setting, ignoring assignment: %s",
1240 network
->required_for_online
= r
;
1241 network
->required_operstate_for_online
= LINK_OPERSTATE_RANGE_DEFAULT
;
1245 network
->required_for_online
= true;
1249 int config_parse_link_group(
1251 const char *filename
,
1253 const char *section
,
1254 unsigned section_line
,
1261 Network
*network
= ASSERT_PTR(userdata
);
1269 if (isempty(rvalue
)) {
1270 network
->group
= -1;
1274 r
= safe_atoi32(rvalue
, &group
);
1276 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
1277 "Failed to parse Group=, ignoring assignment: %s", rvalue
);
1282 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
1283 "Value of Group= must be in the range 0…2147483647, ignoring assignment: %s", rvalue
);
1287 network
->group
= group
;
1291 int config_parse_ignore_carrier_loss(
1293 const char *filename
,
1295 const char *section
,
1296 unsigned section_line
,
1303 Network
*network
= ASSERT_PTR(userdata
);
1311 if (isempty(rvalue
)) {
1312 network
->ignore_carrier_loss_set
= false;
1316 r
= parse_boolean(rvalue
);
1318 network
->ignore_carrier_loss_set
= true;
1319 network
->ignore_carrier_loss_usec
= r
> 0 ? USEC_INFINITY
: 0;
1323 r
= parse_sec(rvalue
, &usec
);
1325 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
1326 "Failed to parse %s=, ignoring assignment: %s", lvalue
, rvalue
);
1330 network
->ignore_carrier_loss_set
= true;
1331 network
->ignore_carrier_loss_usec
= usec
;
1335 DEFINE_CONFIG_PARSE_ENUM(config_parse_required_family_for_online
, link_required_address_family
, AddressFamily
,
1336 "Failed to parse RequiredFamilyForOnline= setting");
1338 DEFINE_CONFIG_PARSE_ENUM(config_parse_keep_configuration
, keep_configuration
, KeepConfiguration
,
1339 "Failed to parse KeepConfiguration= setting");
1341 static const char* const keep_configuration_table
[_KEEP_CONFIGURATION_MAX
] = {
1342 [KEEP_CONFIGURATION_NO
] = "no",
1343 [KEEP_CONFIGURATION_DHCP_ON_STOP
] = "dhcp-on-stop",
1344 [KEEP_CONFIGURATION_DHCP
] = "dhcp",
1345 [KEEP_CONFIGURATION_STATIC
] = "static",
1346 [KEEP_CONFIGURATION_YES
] = "yes",
1349 DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(keep_configuration
, KeepConfiguration
, KEEP_CONFIGURATION_YES
);
1351 static const char* const activation_policy_table
[_ACTIVATION_POLICY_MAX
] = {
1352 [ACTIVATION_POLICY_UP
] = "up",
1353 [ACTIVATION_POLICY_ALWAYS_UP
] = "always-up",
1354 [ACTIVATION_POLICY_MANUAL
] = "manual",
1355 [ACTIVATION_POLICY_ALWAYS_DOWN
] = "always-down",
1356 [ACTIVATION_POLICY_DOWN
] = "down",
1357 [ACTIVATION_POLICY_BOUND
] = "bound",
1360 DEFINE_STRING_TABLE_LOOKUP(activation_policy
, ActivationPolicy
);
1361 DEFINE_CONFIG_PARSE_ENUM(config_parse_activation_policy
, activation_policy
, ActivationPolicy
, "Failed to parse activation policy");