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 "networkd-address-label.h"
17 #include "networkd-address.h"
18 #include "networkd-dhcp-common.h"
19 #include "networkd-dhcp-server.h"
20 #include "networkd-fdb.h"
21 #include "networkd-manager.h"
22 #include "networkd-mdb.h"
23 #include "networkd-ndisc.h"
24 #include "networkd-neighbor.h"
25 #include "networkd-network.h"
26 #include "networkd-nexthop.h"
27 #include "networkd-radv.h"
28 #include "networkd-routing-policy-rule.h"
29 #include "networkd-sriov.h"
30 #include "parse-util.h"
31 #include "path-lookup.h"
33 #include "socket-util.h"
34 #include "stat-util.h"
35 #include "string-table.h"
36 #include "string-util.h"
41 /* Let's assume that anything above this number is a user misconfiguration. */
42 #define MAX_NTP_SERVERS 128
44 /* Set defaults following RFC7844 */
45 void network_apply_anonymize_if_set(Network
*network
) {
46 if (!network
->dhcp_anonymize
)
49 SHOULD NOT send the Host Name option */
50 network
->dhcp_send_hostname
= false;
51 /* RFC7844 section 3.:
52 MAY contain the Client Identifier option
54 clients MUST use client identifiers based solely
55 on the link-layer address */
56 /* NOTE: Using MAC, as it does not reveal extra information,
57 * and some servers might not answer if this option is not sent */
58 network
->dhcp_client_identifier
= DHCP_CLIENT_ID_MAC
;
60 SHOULD NOT use the Vendor Class Identifier option */
61 network
->dhcp_vendor_class_identifier
= mfree(network
->dhcp_vendor_class_identifier
);
62 /* RFC7844 section 3.6.:
63 The client intending to protect its privacy SHOULD only request a
64 minimal number of options in the PRL and SHOULD also randomly shuffle
65 the ordering of option codes in the PRL. If this random ordering
66 cannot be implemented, the client MAY order the option codes in the
67 PRL by option code number (lowest to highest).
69 /* NOTE: dhcp_use_mtu is false by default,
70 * though it was not initiallized to any value in network_load_one.
71 * Maybe there should be another var called *send*?
72 * (to use the MTU sent by the server but to do not send
73 * the option in the PRL). */
74 network
->dhcp_use_mtu
= false;
75 /* NOTE: when Anonymize=yes, the PRL route options are sent by default,
76 * but this is needed to use them. */
77 network
->dhcp_use_routes
= true;
78 /* RFC7844 section 3.6.
79 * same comments as previous option */
80 network
->dhcp_use_timezone
= false;
83 static int network_resolve_netdev_one(Network
*network
, const char *name
, NetDevKind kind
, NetDev
**ret_netdev
) {
84 const char *kind_string
;
88 /* For test-networkd-conf, the check must be earlier than the assertions. */
93 assert(network
->manager
);
94 assert(network
->filename
);
97 if (kind
== _NETDEV_KIND_TUNNEL
)
98 kind_string
= "tunnel";
100 kind_string
= netdev_kind_to_string(kind
);
102 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
),
103 "%s: Invalid NetDev kind of %s, ignoring assignment.",
104 network
->filename
, name
);
107 r
= netdev_get(network
->manager
, name
, &netdev
);
109 return log_error_errno(r
, "%s: %s NetDev could not be found, ignoring assignment.",
110 network
->filename
, name
);
112 if (netdev
->kind
!= kind
&& !(kind
== _NETDEV_KIND_TUNNEL
&&
119 NETDEV_KIND_IP6GRETAP
,
123 NETDEV_KIND_ERSPAN
)))
124 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
),
125 "%s: NetDev %s is not a %s, ignoring assignment",
126 network
->filename
, name
, kind_string
);
128 *ret_netdev
= netdev_ref(netdev
);
132 static int network_resolve_stacked_netdevs(Network
*network
) {
138 HASHMAP_FOREACH_KEY(kind
, name
, network
->stacked_netdev_names
) {
139 _cleanup_(netdev_unrefp
) NetDev
*netdev
= NULL
;
141 r
= network_resolve_netdev_one(network
, name
, PTR_TO_INT(kind
), &netdev
);
145 r
= hashmap_ensure_put(&network
->stacked_netdevs
, &string_hash_ops
, netdev
->ifname
, netdev
);
149 return log_error_errno(r
, "%s: Failed to add NetDev '%s' to network: %m",
150 network
->filename
, (const char *) name
);
158 int network_verify(Network
*network
) {
160 assert(network
->filename
);
162 if (net_match_is_empty(&network
->match
) && !network
->conditions
)
163 return log_warning_errno(SYNTHETIC_ERRNO(EINVAL
),
164 "%s: No valid settings found in the [Match] section, ignoring file. "
165 "To match all interfaces, add Name=* in the [Match] section.",
168 /* skip out early if configuration does not match the environment */
169 if (!condition_test_list(network
->conditions
, environ
, NULL
, NULL
, NULL
))
170 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL
),
171 "%s: Conditions in the file do not match the system environment, skipping.",
174 (void) network_resolve_netdev_one(network
, network
->batadv_name
, NETDEV_KIND_BATADV
, &network
->batadv
);
175 (void) network_resolve_netdev_one(network
, network
->bond_name
, NETDEV_KIND_BOND
, &network
->bond
);
176 (void) network_resolve_netdev_one(network
, network
->bridge_name
, NETDEV_KIND_BRIDGE
, &network
->bridge
);
177 (void) network_resolve_netdev_one(network
, network
->vrf_name
, NETDEV_KIND_VRF
, &network
->vrf
);
178 (void) network_resolve_stacked_netdevs(network
);
180 /* Free unnecessary entries. */
181 network
->batadv_name
= mfree(network
->batadv_name
);
182 network
->bond_name
= mfree(network
->bond_name
);
183 network
->bridge_name
= mfree(network
->bridge_name
);
184 network
->vrf_name
= mfree(network
->vrf_name
);
185 network
->stacked_netdev_names
= hashmap_free_free_key(network
->stacked_netdev_names
);
188 /* Bonding slave does not support addressing. */
189 if (network
->link_local
>= 0 && network
->link_local
!= ADDRESS_FAMILY_NO
) {
190 log_warning("%s: Cannot enable LinkLocalAddressing= when Bond= is specified, disabling LinkLocalAddressing=.",
192 network
->link_local
= ADDRESS_FAMILY_NO
;
194 if (network
->dhcp_server
) {
195 log_warning("%s: Cannot enable DHCPServer= when Bond= is specified, disabling DHCPServer=.",
197 network
->dhcp_server
= false;
199 if (!ordered_hashmap_isempty(network
->addresses_by_section
))
200 log_warning("%s: Cannot set addresses when Bond= is specified, ignoring addresses.",
202 if (!hashmap_isempty(network
->routes_by_section
))
203 log_warning("%s: Cannot set routes when Bond= is specified, ignoring routes.",
206 network
->addresses_by_section
= ordered_hashmap_free_with_destructor(network
->addresses_by_section
, address_free
);
207 network
->routes_by_section
= hashmap_free_with_destructor(network
->routes_by_section
, route_free
);
210 if (network
->link_local
< 0)
211 network
->link_local
= network
->bridge
? ADDRESS_FAMILY_NO
: ADDRESS_FAMILY_IPV6
;
213 /* IPMasquerade implies IPForward */
214 network
->ip_forward
|= network
->ip_masquerade
;
216 network_adjust_ipv6_accept_ra(network
);
217 network_adjust_dhcp(network
);
218 network_adjust_radv(network
);
220 if (network
->mtu
> 0 && network
->dhcp_use_mtu
) {
221 log_warning("%s: MTUBytes= in [Link] section and UseMTU= in [DHCP] section are set. "
222 "Disabling UseMTU=.", network
->filename
);
223 network
->dhcp_use_mtu
= false;
226 if (network
->dhcp_use_gateway
< 0)
227 network
->dhcp_use_gateway
= network
->dhcp_use_routes
;
229 if (network
->dhcp_critical
>= 0) {
230 if (network
->keep_configuration
>= 0)
231 log_warning("%s: Both KeepConfiguration= and deprecated CriticalConnection= are set. "
232 "Ignoring CriticalConnection=.", network
->filename
);
233 else if (network
->dhcp_critical
)
234 /* CriticalConnection=yes also preserve foreign static configurations. */
235 network
->keep_configuration
= KEEP_CONFIGURATION_YES
;
237 network
->keep_configuration
= KEEP_CONFIGURATION_NO
;
240 if (!strv_isempty(network
->bind_carrier
)) {
241 if (!IN_SET(network
->activation_policy
, _ACTIVATION_POLICY_INVALID
, ACTIVATION_POLICY_BOUND
))
242 log_warning("%s: ActivationPolicy=bound is required with BindCarrier=. "
243 "Setting ActivationPolicy=bound.", network
->filename
);
244 network
->activation_policy
= ACTIVATION_POLICY_BOUND
;
245 } else if (network
->activation_policy
== ACTIVATION_POLICY_BOUND
) {
246 log_warning("%s: ActivationPolicy=bound requires BindCarrier=. "
247 "Ignoring ActivationPolicy=bound.", network
->filename
);
248 network
->activation_policy
= ACTIVATION_POLICY_UP
;
251 if (network
->activation_policy
== _ACTIVATION_POLICY_INVALID
)
252 network
->activation_policy
= ACTIVATION_POLICY_UP
;
254 if (network
->activation_policy
== ACTIVATION_POLICY_ALWAYS_UP
) {
255 if (network
->ignore_carrier_loss
== false)
256 log_warning("%s: IgnoreCarrierLoss=false conflicts with ActivationPolicy=always-up. "
257 "Setting IgnoreCarrierLoss=true.", network
->filename
);
258 network
->ignore_carrier_loss
= true;
261 if (network
->ignore_carrier_loss
< 0)
262 network
->ignore_carrier_loss
= network
->configure_without_carrier
;
264 if (network
->keep_configuration
< 0)
265 network
->keep_configuration
= KEEP_CONFIGURATION_NO
;
267 if (network
->ipv6_proxy_ndp
== 0 && !set_isempty(network
->ipv6_proxy_ndp_addresses
)) {
268 log_warning("%s: IPv6ProxyNDP= is disabled. Ignoring IPv6ProxyNDPAddress=.", network
->filename
);
269 network
->ipv6_proxy_ndp_addresses
= set_free_free(network
->ipv6_proxy_ndp_addresses
);
272 network_drop_invalid_addresses(network
);
273 network_drop_invalid_routes(network
);
274 network_drop_invalid_nexthops(network
);
275 network_drop_invalid_fdb_entries(network
);
276 network_drop_invalid_mdb_entries(network
);
277 network_drop_invalid_neighbors(network
);
278 network_drop_invalid_address_labels(network
);
279 network_drop_invalid_prefixes(network
);
280 network_drop_invalid_route_prefixes(network
);
281 network_drop_invalid_routing_policy_rules(network
);
282 network_drop_invalid_traffic_control(network
);
283 network_drop_invalid_sr_iov(network
);
288 int network_load_one(Manager
*manager
, OrderedHashmap
**networks
, const char *filename
) {
289 _cleanup_free_
char *fname
= NULL
, *name
= NULL
;
290 _cleanup_(network_unrefp
) Network
*network
= NULL
;
291 const char *dropin_dirname
;
298 r
= null_or_empty_path(filename
);
304 log_debug("Skipping empty file: %s", filename
);
308 fname
= strdup(filename
);
312 name
= strdup(basename(filename
));
316 d
= strrchr(name
, '.');
322 dropin_dirname
= strjoina(name
, ".network.d");
324 network
= new(Network
, 1);
328 *network
= (Network
) {
329 .filename
= TAKE_PTR(fname
),
330 .name
= TAKE_PTR(name
),
335 .required_for_online
= true,
336 .required_operstate_for_online
= LINK_OPERSTATE_RANGE_DEFAULT
,
337 .activation_policy
= _ACTIVATION_POLICY_INVALID
,
343 .configure_without_carrier
= false,
344 .ignore_carrier_loss
= -1,
345 .keep_configuration
= _KEEP_CONFIGURATION_INVALID
,
347 .dhcp
= ADDRESS_FAMILY_NO
,
348 .duid
.type
= _DUID_TYPE_INVALID
,
350 .dhcp_use_ntp
= true,
351 .dhcp_use_sip
= true,
352 .dhcp_use_dns
= true,
353 .dhcp_use_hostname
= true,
354 .dhcp_use_routes
= true,
355 .dhcp_use_gateway
= -1,
356 /* NOTE: this var might be overwritten by network_apply_anonymize_if_set */
357 .dhcp_send_hostname
= true,
358 .dhcp_send_release
= true,
359 /* To enable/disable RFC7844 Anonymity Profiles */
360 .dhcp_anonymize
= false,
361 .dhcp_route_metric
= DHCP_ROUTE_METRIC
,
362 /* NOTE: this var might be overwritten by network_apply_anonymize_if_set */
363 .dhcp_client_identifier
= DHCP_CLIENT_ID_DUID
,
364 .dhcp_route_table
= RT_TABLE_MAIN
,
365 .dhcp_route_table_set
= false,
366 /* NOTE: from man: UseMTU=... Defaults to false*/
367 .dhcp_use_mtu
= false,
368 /* NOTE: from man: UseTimezone=... Defaults to "no".*/
369 .dhcp_use_timezone
= false,
370 .dhcp_ip_service_type
= -1,
372 .dhcp6_use_address
= true,
373 .dhcp6_use_dns
= true,
374 .dhcp6_use_hostname
= true,
375 .dhcp6_use_ntp
= true,
376 .dhcp6_rapid_commit
= true,
377 .dhcp6_route_metric
= DHCP_ROUTE_METRIC
,
380 .dhcp6_pd_announce
= true,
381 .dhcp6_pd_assign
= true,
382 .dhcp6_pd_manage_temporary_address
= true,
383 .dhcp6_pd_subnet_id
= -1,
385 .dhcp_server_emit
[SD_DHCP_LEASE_DNS
].emit
= true,
386 .dhcp_server_emit
[SD_DHCP_LEASE_NTP
].emit
= true,
387 .dhcp_server_emit
[SD_DHCP_LEASE_SIP
].emit
= true,
389 .dhcp_server_emit_router
= true,
390 .dhcp_server_emit_timezone
= true,
392 .router_lifetime_usec
= 30 * USEC_PER_MINUTE
,
393 .router_emit_dns
= true,
394 .router_emit_domains
= true,
399 .allow_port_to_be_root
= -1,
401 .multicast_flood
= -1,
402 .multicast_to_unicast
= -1,
403 .neighbor_suppression
= -1,
405 .bridge_proxy_arp
= -1,
406 .bridge_proxy_arp_wifi
= -1,
407 .priority
= LINK_BRIDGE_PORT_PRIORITY_INVALID
,
408 .multicast_router
= _MULTICAST_ROUTER_INVALID
,
410 .lldp_mode
= LLDP_MODE_ROUTERS_ONLY
,
412 .dns_default_route
= -1,
413 .llmnr
= RESOLVE_SUPPORT_YES
,
414 .mdns
= RESOLVE_SUPPORT_NO
,
415 .dnssec_mode
= _DNSSEC_MODE_INVALID
,
416 .dns_over_tls_mode
= _DNS_OVER_TLS_MODE_INVALID
,
418 /* If LinkLocalAddressing= is not set, then set to ADDRESS_FAMILY_IPV6 later. */
419 .link_local
= _ADDRESS_FAMILY_INVALID
,
420 .ipv6ll_address_gen_mode
= _IPV6_LINK_LOCAL_ADDRESS_GEN_MODE_INVALID
,
422 .ipv4_accept_local
= -1,
423 .ipv4_route_localnet
= -1,
424 .ipv6_privacy_extensions
= IPV6_PRIVACY_EXTENSIONS_NO
,
425 .ipv6_accept_ra
= -1,
426 .ipv6_dad_transmits
= -1,
427 .ipv6_hop_limit
= -1,
428 .ipv6_proxy_ndp
= -1,
431 .ipv6_accept_ra_use_dns
= true,
432 .ipv6_accept_ra_use_autonomous_prefix
= true,
433 .ipv6_accept_ra_use_onlink_prefix
= true,
434 .ipv6_accept_ra_route_table
= RT_TABLE_MAIN
,
435 .ipv6_accept_ra_route_table_set
= false,
436 .ipv6_accept_ra_start_dhcp6_client
= IPV6_ACCEPT_RA_START_DHCP6_CLIENT_YES
,
438 .can_triple_sampling
= -1,
439 .can_berr_reporting
= -1,
440 .can_termination
= -1,
441 .can_listen_only
= -1,
446 r
= config_parse_many(
447 STRV_MAKE_CONST(filename
), NETWORK_DIRS
, dropin_dirname
,
455 "RoutingPolicyRule\0"
458 "DHCP\0" /* compat */
461 "DHCPv6PrefixDelegation\0"
464 "IPv6NDPProxyAddress\0"
470 "IPv6PrefixDelegation\0"
474 "TrafficControlQueueingDiscipline\0"
480 "DeficitRoundRobinScheduler\0"
481 "DeficitRoundRobinSchedulerClass\0"
482 "EnhancedTransmissionSelection\0"
484 "FairQueueingControlledDelay\0"
486 "GenericRandomEarlyDetection\0"
487 "HeavyHitterFilter\0"
488 "HierarchyTokenBucket\0"
489 "HierarchyTokenBucketClass\0"
495 "QuickFairQueueing\0"
496 "QuickFairQueueingClass\0"
497 "StochasticFairBlue\0"
498 "StochasticFairnessQueueing\0"
499 "TokenBucketFilter\0"
500 "TrivialLinkEqualizer\0",
501 config_item_perf_lookup
, network_network_gperf_lookup
,
504 &network
->timestamp
);
508 network_apply_anonymize_if_set(network
);
510 r
= network_add_ipv4ll_route(network
);
512 log_warning_errno(r
, "%s: Failed to add IPv4LL route, ignoring: %m", network
->filename
);
514 r
= network_add_default_route_on_device(network
);
516 log_warning_errno(r
, "%s: Failed to add default route on device, ignoring: %m",
519 if (network_verify(network
) < 0)
520 /* Ignore .network files that do not match the conditions. */
523 r
= ordered_hashmap_ensure_put(networks
, &string_hash_ops
, network
->name
, network
);
531 int network_load(Manager
*manager
, OrderedHashmap
**networks
) {
532 _cleanup_strv_free_
char **files
= NULL
;
538 ordered_hashmap_clear_with_destructor(*networks
, network_unref
);
540 r
= conf_files_list_strv(&files
, ".network", NULL
, 0, NETWORK_DIRS
);
542 return log_error_errno(r
, "Failed to enumerate network files: %m");
544 STRV_FOREACH(f
, files
) {
545 r
= network_load_one(manager
, networks
, *f
);
547 log_error_errno(r
, "Failed to load %s, ignoring: %m", *f
);
553 int network_reload(Manager
*manager
) {
554 OrderedHashmap
*new_networks
= NULL
;
560 r
= network_load(manager
, &new_networks
);
564 ORDERED_HASHMAP_FOREACH(n
, new_networks
) {
565 r
= network_get_by_name(manager
, n
->name
, &old
);
567 continue; /* The .network file is new. */
569 if (n
->timestamp
!= old
->timestamp
)
570 continue; /* The .network file is modified. */
572 if (!streq(n
->filename
, old
->filename
))
575 r
= ordered_hashmap_replace(new_networks
, old
->name
, old
);
583 ordered_hashmap_free_with_destructor(manager
->networks
, network_unref
);
584 manager
->networks
= new_networks
;
589 ordered_hashmap_free_with_destructor(new_networks
, network_unref
);
594 static Network
*network_free(Network
*network
) {
598 free(network
->filename
);
600 net_match_clear(&network
->match
);
601 condition_free_list(network
->conditions
);
603 free(network
->description
);
604 free(network
->dhcp_vendor_class_identifier
);
605 free(network
->dhcp_mudurl
);
606 strv_free(network
->dhcp_user_class
);
607 free(network
->dhcp_hostname
);
608 set_free(network
->dhcp_deny_listed_ip
);
609 set_free(network
->dhcp_allow_listed_ip
);
610 set_free(network
->dhcp_request_options
);
611 set_free(network
->dhcp6_request_options
);
613 free(network
->dhcp6_mudurl
);
614 strv_free(network
->dhcp6_user_class
);
615 strv_free(network
->dhcp6_vendor_class
);
617 strv_free(network
->ntp
);
618 for (unsigned i
= 0; i
< network
->n_dns
; i
++)
619 in_addr_full_free(network
->dns
[i
]);
621 ordered_set_free(network
->search_domains
);
622 ordered_set_free(network
->route_domains
);
623 strv_free(network
->bind_carrier
);
625 ordered_set_free(network
->router_search_domains
);
626 free(network
->router_dns
);
627 set_free_free(network
->ndisc_deny_listed_router
);
628 set_free_free(network
->ndisc_allow_listed_router
);
629 set_free_free(network
->ndisc_deny_listed_prefix
);
630 set_free_free(network
->ndisc_allow_listed_prefix
);
631 set_free_free(network
->ndisc_deny_listed_route_prefix
);
632 set_free_free(network
->ndisc_allow_listed_route_prefix
);
634 free(network
->batadv_name
);
635 free(network
->bridge_name
);
636 free(network
->bond_name
);
637 free(network
->vrf_name
);
638 hashmap_free_free_key(network
->stacked_netdev_names
);
639 netdev_unref(network
->bridge
);
640 netdev_unref(network
->bond
);
641 netdev_unref(network
->vrf
);
642 hashmap_free_with_destructor(network
->stacked_netdevs
, netdev_unref
);
644 set_free_free(network
->ipv6_proxy_ndp_addresses
);
645 ordered_hashmap_free_with_destructor(network
->addresses_by_section
, address_free
);
646 hashmap_free_with_destructor(network
->routes_by_section
, route_free
);
647 hashmap_free_with_destructor(network
->nexthops_by_section
, nexthop_free
);
648 hashmap_free_with_destructor(network
->fdb_entries_by_section
, fdb_entry_free
);
649 hashmap_free_with_destructor(network
->mdb_entries_by_section
, mdb_entry_free
);
650 hashmap_free_with_destructor(network
->neighbors_by_section
, neighbor_free
);
651 hashmap_free_with_destructor(network
->address_labels_by_section
, address_label_free
);
652 hashmap_free_with_destructor(network
->prefixes_by_section
, prefix_free
);
653 hashmap_free_with_destructor(network
->route_prefixes_by_section
, route_prefix_free
);
654 hashmap_free_with_destructor(network
->rules_by_section
, routing_policy_rule_free
);
655 ordered_hashmap_free_with_destructor(network
->sr_iov_by_section
, sr_iov_free
);
656 ordered_hashmap_free_with_destructor(network
->tc_by_section
, traffic_control_free
);
658 if (network
->manager
&&
659 network
->manager
->duids_requesting_uuid
)
660 set_remove(network
->manager
->duids_requesting_uuid
, &network
->duid
);
664 free(network
->dhcp_server_timezone
);
666 for (sd_dhcp_lease_server_type_t t
= 0; t
< _SD_DHCP_LEASE_SERVER_TYPE_MAX
; t
++)
667 free(network
->dhcp_server_emit
[t
].addresses
);
669 set_free_free(network
->dnssec_negative_trust_anchors
);
671 free(network
->lldp_mud
);
673 ordered_hashmap_free(network
->dhcp_client_send_options
);
674 ordered_hashmap_free(network
->dhcp_client_send_vendor_options
);
675 ordered_hashmap_free(network
->dhcp_server_send_options
);
676 ordered_hashmap_free(network
->dhcp_server_send_vendor_options
);
677 ordered_set_free(network
->ipv6_tokens
);
678 ordered_hashmap_free(network
->dhcp6_client_send_options
);
679 ordered_hashmap_free(network
->dhcp6_client_send_vendor_options
);
681 return mfree(network
);
684 DEFINE_TRIVIAL_REF_UNREF_FUNC(Network
, network
, network_free
);
686 int network_get_by_name(Manager
*manager
, const char *name
, Network
**ret
) {
693 network
= ordered_hashmap_get(manager
->networks
, name
);
702 int network_get(Manager
*manager
, unsigned short iftype
, sd_device
*device
,
703 const char *ifname
, char * const *alternative_names
, const char *driver
,
704 const struct ether_addr
*mac
, const struct ether_addr
*permanent_mac
,
705 enum nl80211_iftype wlan_iftype
, const char *ssid
, const struct ether_addr
*bssid
,
712 ORDERED_HASHMAP_FOREACH(network
, manager
->networks
)
713 if (net_match_config(&network
->match
, device
, mac
, permanent_mac
, driver
, iftype
,
714 ifname
, alternative_names
, wlan_iftype
, ssid
, bssid
)) {
715 if (network
->match
.ifname
&& device
) {
717 uint8_t name_assign_type
= NET_NAME_UNKNOWN
;
719 if (sd_device_get_sysattr_value(device
, "name_assign_type", &attr
) >= 0)
720 (void) safe_atou8(attr
, &name_assign_type
);
722 if (name_assign_type
== NET_NAME_ENUM
)
723 log_warning("%s: found matching network '%s', based on potentially unpredictable ifname",
724 ifname
, network
->filename
);
726 log_debug("%s: found matching network '%s'", ifname
, network
->filename
);
728 log_debug("%s: found matching network '%s'", ifname
, network
->filename
);
739 bool network_has_static_ipv6_configurations(Network
*network
) {
748 ORDERED_HASHMAP_FOREACH(address
, network
->addresses_by_section
)
749 if (address
->family
== AF_INET6
)
752 HASHMAP_FOREACH(route
, network
->routes_by_section
)
753 if (route
->family
== AF_INET6
)
756 HASHMAP_FOREACH(fdb
, network
->fdb_entries_by_section
)
757 if (fdb
->family
== AF_INET6
)
760 HASHMAP_FOREACH(mdb
, network
->mdb_entries_by_section
)
761 if (mdb
->family
== AF_INET6
)
764 HASHMAP_FOREACH(neighbor
, network
->neighbors_by_section
)
765 if (neighbor
->family
== AF_INET6
)
768 if (!hashmap_isempty(network
->address_labels_by_section
))
771 if (!hashmap_isempty(network
->prefixes_by_section
))
774 if (!hashmap_isempty(network
->route_prefixes_by_section
))
780 int config_parse_stacked_netdev(const char *unit
,
781 const char *filename
,
784 unsigned section_line
,
790 _cleanup_free_
char *name
= NULL
;
791 NetDevKind kind
= ltype
;
800 NETDEV_KIND_VLAN
, NETDEV_KIND_MACVLAN
, NETDEV_KIND_MACVTAP
,
801 NETDEV_KIND_IPVLAN
, NETDEV_KIND_IPVTAP
, NETDEV_KIND_VXLAN
,
802 NETDEV_KIND_L2TP
, NETDEV_KIND_MACSEC
, _NETDEV_KIND_TUNNEL
,
805 if (!ifname_valid(rvalue
)) {
806 log_syntax(unit
, LOG_WARNING
, filename
, line
, 0,
807 "Invalid netdev name in %s=, ignoring assignment: %s", lvalue
, rvalue
);
811 name
= strdup(rvalue
);
815 r
= hashmap_ensure_put(h
, &string_hash_ops
, name
, INT_TO_PTR(kind
));
819 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
820 "Cannot add NetDev '%s' to network, ignoring assignment: %m", name
);
822 log_syntax(unit
, LOG_DEBUG
, filename
, line
, r
,
823 "NetDev '%s' specified twice, ignoring.", name
);
830 int config_parse_domains(
832 const char *filename
,
835 unsigned section_line
,
849 if (isempty(rvalue
)) {
850 n
->search_domains
= ordered_set_free(n
->search_domains
);
851 n
->route_domains
= ordered_set_free(n
->route_domains
);
855 for (const char *p
= rvalue
;;) {
856 _cleanup_free_
char *w
= NULL
, *normalized
= NULL
;
860 r
= extract_first_word(&p
, &w
, NULL
, 0);
864 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
865 "Failed to extract search or route domain, ignoring: %s", rvalue
);
871 is_route
= w
[0] == '~';
872 domain
= is_route
? w
+ 1 : w
;
874 if (dns_name_is_root(domain
) || streq(domain
, "*")) {
875 /* If the root domain appears as is, or the special token "*" is found, we'll
876 * consider this as routing domain, unconditionally. */
878 domain
= "."; /* make sure we don't allow empty strings, thus write the root
881 r
= dns_name_normalize(domain
, 0, &normalized
);
883 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
884 "'%s' is not a valid domain name, ignoring.", domain
);
890 if (is_localhost(domain
)) {
891 log_syntax(unit
, LOG_WARNING
, filename
, line
, 0,
892 "'localhost' domain may not be configured as search or route domain, ignoring assignment: %s",
898 OrderedSet
**set
= is_route
? &n
->route_domains
: &n
->search_domains
;
899 r
= ordered_set_put_strdup(set
, domain
);
907 int config_parse_hostname(
909 const char *filename
,
912 unsigned section_line
,
919 _cleanup_free_
char *hn
= NULL
;
920 char **hostname
= data
;
927 r
= config_parse_string(unit
, filename
, line
, section
, section_line
, lvalue
, ltype
, rvalue
, &hn
, userdata
);
931 if (!hostname_is_valid(hn
, 0)) {
932 log_syntax(unit
, LOG_WARNING
, filename
, line
, 0,
933 "Hostname is not valid, ignoring assignment: %s", rvalue
);
937 r
= dns_name_is_valid(hn
);
939 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
940 "Failed to check validity of hostname '%s', ignoring assignment: %m", rvalue
);
944 log_syntax(unit
, LOG_WARNING
, filename
, line
, 0,
945 "Hostname is not a valid DNS domain name, ignoring assignment: %s", rvalue
);
949 return free_and_replace(*hostname
, hn
);
952 int config_parse_timezone(
954 const char *filename
,
957 unsigned section_line
,
964 _cleanup_free_
char *tz
= NULL
;
972 r
= config_parse_string(unit
, filename
, line
, section
, section_line
, lvalue
, ltype
, rvalue
, &tz
, userdata
);
976 if (!timezone_is_valid(tz
, LOG_WARNING
)) {
977 log_syntax(unit
, LOG_WARNING
, filename
, line
, 0,
978 "Timezone is not valid, ignoring assignment: %s", rvalue
);
982 return free_and_replace(*datap
, tz
);
985 int config_parse_dns(
987 const char *filename
,
990 unsigned section_line
,
997 Network
*n
= userdata
;
1004 if (isempty(rvalue
)) {
1005 for (unsigned i
= 0; i
< n
->n_dns
; i
++)
1006 in_addr_full_free(n
->dns
[i
]);
1007 n
->dns
= mfree(n
->dns
);
1012 for (const char *p
= rvalue
;;) {
1013 _cleanup_(in_addr_full_freep
) struct in_addr_full
*dns
= NULL
;
1014 _cleanup_free_
char *w
= NULL
;
1015 struct in_addr_full
**m
;
1017 r
= extract_first_word(&p
, &w
, NULL
, 0);
1021 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
1022 "Invalid syntax, ignoring: %s", rvalue
);
1028 r
= in_addr_full_new_from_string(w
, &dns
);
1030 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
1031 "Failed to parse dns server address, ignoring: %s", w
);
1035 if (IN_SET(dns
->port
, 53, 853))
1038 m
= reallocarray(n
->dns
, n
->n_dns
+ 1, sizeof(struct in_addr_full
*));
1042 m
[n
->n_dns
++] = TAKE_PTR(dns
);
1047 int config_parse_dnssec_negative_trust_anchors(
1049 const char *filename
,
1051 const char *section
,
1052 unsigned section_line
,
1066 if (isempty(rvalue
)) {
1067 n
->dnssec_negative_trust_anchors
= set_free_free(n
->dnssec_negative_trust_anchors
);
1071 for (const char *p
= rvalue
;;) {
1072 _cleanup_free_
char *w
= NULL
;
1074 r
= extract_first_word(&p
, &w
, NULL
, 0);
1078 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
1079 "Failed to extract negative trust anchor domain, ignoring: %s", rvalue
);
1085 r
= dns_name_is_valid(w
);
1087 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
1088 "%s is not a valid domain name, ignoring.", w
);
1092 r
= set_ensure_consume(&n
->dnssec_negative_trust_anchors
, &dns_name_hash_ops
, TAKE_PTR(w
));
1098 int config_parse_ntp(
1100 const char *filename
,
1102 const char *section
,
1103 unsigned section_line
,
1117 if (isempty(rvalue
)) {
1122 for (const char *p
= rvalue
;;) {
1123 _cleanup_free_
char *w
= NULL
;
1125 r
= extract_first_word(&p
, &w
, NULL
, 0);
1129 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
1130 "Failed to extract NTP server name, ignoring: %s", rvalue
);
1136 r
= dns_name_is_valid_or_address(w
);
1138 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
1139 "%s is not a valid domain name or IP address, ignoring.", w
);
1143 if (strv_length(*l
) > MAX_NTP_SERVERS
) {
1144 log_syntax(unit
, LOG_WARNING
, filename
, line
, 0,
1145 "More than %u NTP servers specified, ignoring \"%s\" and any subsequent entries.",
1146 MAX_NTP_SERVERS
, w
);
1150 r
= strv_consume(l
, TAKE_PTR(w
));
1156 int config_parse_required_for_online(
1158 const char *filename
,
1160 const char *section
,
1161 unsigned section_line
,
1168 Network
*network
= data
;
1169 LinkOperationalStateRange range
;
1170 bool required
= true;
1173 if (isempty(rvalue
)) {
1174 network
->required_for_online
= true;
1175 network
->required_operstate_for_online
= LINK_OPERSTATE_RANGE_DEFAULT
;
1179 r
= parse_operational_state_range(rvalue
, &range
);
1181 r
= parse_boolean(rvalue
);
1183 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
1184 "Failed to parse %s= setting, ignoring assignment: %s",
1190 range
= LINK_OPERSTATE_RANGE_DEFAULT
;
1193 network
->required_for_online
= required
;
1194 network
->required_operstate_for_online
= range
;
1199 DEFINE_CONFIG_PARSE_ENUM(config_parse_keep_configuration
, keep_configuration
, KeepConfiguration
,
1200 "Failed to parse KeepConfiguration= setting");
1202 static const char* const keep_configuration_table
[_KEEP_CONFIGURATION_MAX
] = {
1203 [KEEP_CONFIGURATION_NO
] = "no",
1204 [KEEP_CONFIGURATION_DHCP_ON_STOP
] = "dhcp-on-stop",
1205 [KEEP_CONFIGURATION_DHCP
] = "dhcp",
1206 [KEEP_CONFIGURATION_STATIC
] = "static",
1207 [KEEP_CONFIGURATION_YES
] = "yes",
1210 DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(keep_configuration
, KeepConfiguration
, KEEP_CONFIGURATION_YES
);
1212 static const char* const ipv6_link_local_address_gen_mode_table
[_IPV6_LINK_LOCAL_ADDRESS_GEN_MODE_MAX
] = {
1213 [IPV6_LINK_LOCAL_ADDRESSS_GEN_MODE_EUI64
] = "eui64",
1214 [IPV6_LINK_LOCAL_ADDRESSS_GEN_MODE_NONE
] = "none",
1215 [IPV6_LINK_LOCAL_ADDRESSS_GEN_MODE_STABLE_PRIVACY
] = "stable-privacy",
1216 [IPV6_LINK_LOCAL_ADDRESSS_GEN_MODE_RANDOM
] = "random",
1219 DEFINE_STRING_TABLE_LOOKUP(ipv6_link_local_address_gen_mode
, IPv6LinkLocalAddressGenMode
);
1220 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");
1222 static const char* const activation_policy_table
[_ACTIVATION_POLICY_MAX
] = {
1223 [ACTIVATION_POLICY_UP
] = "up",
1224 [ACTIVATION_POLICY_ALWAYS_UP
] = "always-up",
1225 [ACTIVATION_POLICY_MANUAL
] = "manual",
1226 [ACTIVATION_POLICY_ALWAYS_DOWN
] = "always-down",
1227 [ACTIVATION_POLICY_DOWN
] = "down",
1228 [ACTIVATION_POLICY_BOUND
] = "bound",
1231 DEFINE_STRING_TABLE_LOOKUP(activation_policy
, ActivationPolicy
);
1232 DEFINE_CONFIG_PARSE_ENUM(config_parse_activation_policy
, activation_policy
, ActivationPolicy
, "Failed to parse activation policy");