1 /* SPDX-License-Identifier: LGPL-2.1+ */
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 "networkd-dhcp-server.h"
16 #include "network-internal.h"
17 #include "networkd-address-label.h"
18 #include "networkd-address.h"
19 #include "networkd-fdb.h"
20 #include "networkd-manager.h"
21 #include "networkd-mdb.h"
22 #include "networkd-neighbor.h"
23 #include "networkd-network.h"
24 #include "networkd-nexthop.h"
25 #include "networkd-radv.h"
26 #include "networkd-routing-policy-rule.h"
27 #include "networkd-sriov.h"
28 #include "parse-util.h"
29 #include "path-lookup.h"
31 #include "socket-util.h"
32 #include "stat-util.h"
33 #include "string-table.h"
34 #include "string-util.h"
39 /* Let's assume that anything above this number is a user misconfiguration. */
40 #define MAX_NTP_SERVERS 128
42 /* Set defaults following RFC7844 */
43 void network_apply_anonymize_if_set(Network
*network
) {
44 if (!network
->dhcp_anonymize
)
47 SHOULD NOT send the Host Name option */
48 network
->dhcp_send_hostname
= false;
49 /* RFC7844 section 3.:
50 MAY contain the Client Identifier option
52 clients MUST use client identifiers based solely
53 on the link-layer address */
54 /* NOTE: Using MAC, as it does not reveal extra information,
55 * and some servers might not answer if this option is not sent */
56 network
->dhcp_client_identifier
= DHCP_CLIENT_ID_MAC
;
58 SHOULD NOT use the Vendor Class Identifier option */
59 network
->dhcp_vendor_class_identifier
= mfree(network
->dhcp_vendor_class_identifier
);
60 /* RFC7844 section 3.6.:
61 The client intending to protect its privacy SHOULD only request a
62 minimal number of options in the PRL and SHOULD also randomly shuffle
63 the ordering of option codes in the PRL. If this random ordering
64 cannot be implemented, the client MAY order the option codes in the
65 PRL by option code number (lowest to highest).
67 /* NOTE: dhcp_use_mtu is false by default,
68 * though it was not initiallized to any value in network_load_one.
69 * Maybe there should be another var called *send*?
70 * (to use the MTU sent by the server but to do not send
71 * the option in the PRL). */
72 network
->dhcp_use_mtu
= false;
73 /* NOTE: when Anonymize=yes, the PRL route options are sent by default,
74 * but this is needed to use them. */
75 network
->dhcp_use_routes
= true;
76 /* RFC7844 section 3.6.
77 * same comments as previous option */
78 network
->dhcp_use_timezone
= false;
81 static int network_resolve_netdev_one(Network
*network
, const char *name
, NetDevKind kind
, NetDev
**ret_netdev
) {
82 const char *kind_string
;
86 /* For test-networkd-conf, the check must be earlier than the assertions. */
91 assert(network
->manager
);
92 assert(network
->filename
);
95 if (kind
== _NETDEV_KIND_TUNNEL
)
96 kind_string
= "tunnel";
98 kind_string
= netdev_kind_to_string(kind
);
100 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
),
101 "%s: Invalid NetDev kind of %s, ignoring assignment.",
102 network
->filename
, name
);
105 r
= netdev_get(network
->manager
, name
, &netdev
);
107 return log_error_errno(r
, "%s: %s NetDev could not be found, ignoring assignment.",
108 network
->filename
, name
);
110 if (netdev
->kind
!= kind
&& !(kind
== _NETDEV_KIND_TUNNEL
&&
117 NETDEV_KIND_IP6GRETAP
,
121 NETDEV_KIND_ERSPAN
)))
122 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
),
123 "%s: NetDev %s is not a %s, ignoring assignment",
124 network
->filename
, name
, kind_string
);
126 *ret_netdev
= netdev_ref(netdev
);
130 static int network_resolve_stacked_netdevs(Network
*network
) {
136 HASHMAP_FOREACH_KEY(kind
, name
, network
->stacked_netdev_names
) {
137 _cleanup_(netdev_unrefp
) NetDev
*netdev
= NULL
;
139 r
= network_resolve_netdev_one(network
, name
, PTR_TO_INT(kind
), &netdev
);
143 r
= hashmap_ensure_allocated(&network
->stacked_netdevs
, &string_hash_ops
);
147 r
= hashmap_put(network
->stacked_netdevs
, 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
) {
163 assert(network
->filename
);
165 if (set_isempty(network
->match_mac
) && set_isempty(network
->match_permanent_mac
) &&
166 strv_isempty(network
->match_path
) && strv_isempty(network
->match_driver
) &&
167 strv_isempty(network
->match_type
) && strv_isempty(network
->match_name
) &&
168 strv_isempty(network
->match_property
) && strv_isempty(network
->match_wlan_iftype
) &&
169 strv_isempty(network
->match_ssid
) && !network
->conditions
)
170 return log_warning_errno(SYNTHETIC_ERRNO(EINVAL
),
171 "%s: No valid settings found in the [Match] section, ignoring file. "
172 "To match all interfaces, add Name=* in the [Match] section.",
175 /* skip out early if configuration does not match the environment */
176 if (!condition_test_list(network
->conditions
, environ
, NULL
, NULL
, NULL
))
177 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL
),
178 "%s: Conditions in the file do not match the system environment, skipping.",
181 (void) network_resolve_netdev_one(network
, network
->bond_name
, NETDEV_KIND_BOND
, &network
->bond
);
182 (void) network_resolve_netdev_one(network
, network
->bridge_name
, NETDEV_KIND_BRIDGE
, &network
->bridge
);
183 (void) network_resolve_netdev_one(network
, network
->vrf_name
, NETDEV_KIND_VRF
, &network
->vrf
);
184 (void) network_resolve_stacked_netdevs(network
);
186 /* Free unnecessary entries. */
187 network
->bond_name
= mfree(network
->bond_name
);
188 network
->bridge_name
= mfree(network
->bridge_name
);
189 network
->vrf_name
= mfree(network
->vrf_name
);
190 network
->stacked_netdev_names
= hashmap_free_free_key(network
->stacked_netdev_names
);
193 /* Bonding slave does not support addressing. */
194 if (network
->ipv6_accept_ra
> 0) {
195 log_warning("%s: Cannot enable IPv6AcceptRA= when Bond= is specified, disabling IPv6AcceptRA=.",
197 network
->ipv6_accept_ra
= 0;
199 if (network
->link_local
>= 0 && network
->link_local
!= ADDRESS_FAMILY_NO
) {
200 log_warning("%s: Cannot enable LinkLocalAddressing= when Bond= is specified, disabling LinkLocalAddressing=.",
202 network
->link_local
= ADDRESS_FAMILY_NO
;
204 if (network
->dhcp
!= ADDRESS_FAMILY_NO
) {
205 log_warning("%s: Cannot enable DHCP= when Bond= is specified, disabling DHCP=.",
207 network
->dhcp
= ADDRESS_FAMILY_NO
;
209 if (network
->dhcp_server
) {
210 log_warning("%s: Cannot enable DHCPServer= when Bond= is specified, disabling DHCPServer=.",
212 network
->dhcp_server
= false;
214 if (!ordered_hashmap_isempty(network
->addresses_by_section
))
215 log_warning("%s: Cannot set addresses when Bond= is specified, ignoring addresses.",
217 if (!hashmap_isempty(network
->routes_by_section
))
218 log_warning("%s: Cannot set routes when Bond= is specified, ignoring routes.",
221 network
->addresses_by_section
= ordered_hashmap_free_with_destructor(network
->addresses_by_section
, address_free
);
222 network
->routes_by_section
= hashmap_free_with_destructor(network
->routes_by_section
, route_free
);
225 if (network
->link_local
< 0)
226 network
->link_local
= network
->bridge
? ADDRESS_FAMILY_NO
: ADDRESS_FAMILY_IPV6
;
228 if (!FLAGS_SET(network
->link_local
, ADDRESS_FAMILY_IPV6
)) {
229 if (network
->ipv6_accept_ra
> 0) {
230 log_warning("%s: IPv6AcceptRA= is enabled by the .network file but IPv6 link local addressing is disabled. "
231 "Disabling IPv6AcceptRA=.", network
->filename
);
232 network
->ipv6_accept_ra
= false;
235 if (FLAGS_SET(network
->dhcp
, ADDRESS_FAMILY_IPV6
)) {
236 log_warning("%s: DHCPv6 client is enabled by the .network file but IPv6 link local addressing is disabled. "
237 "Disabling DHCPv6 client.", network
->filename
);
238 SET_FLAG(network
->dhcp
, ADDRESS_FAMILY_IPV6
, false);
241 if (network
->router_prefix_delegation
!= RADV_PREFIX_DELEGATION_NONE
) {
242 log_warning("%s: IPv6PrefixDelegation= is enabled but IPv6 link local addressing is disabled. "
243 "Disabling IPv6PrefixDelegation=.", network
->filename
);
244 network
->router_prefix_delegation
= RADV_PREFIX_DELEGATION_NONE
;
248 if (FLAGS_SET(network
->link_local
, ADDRESS_FAMILY_FALLBACK_IPV4
) &&
249 !FLAGS_SET(network
->dhcp
, ADDRESS_FAMILY_IPV4
)) {
250 log_warning("%s: fallback assignment of IPv4 link local address is enabled but DHCPv4 is disabled. "
251 "Disabling the fallback assignment.", network
->filename
);
252 SET_FLAG(network
->link_local
, ADDRESS_FAMILY_FALLBACK_IPV4
, false);
255 if (network
->ipv6_accept_ra
< 0 && network
->bridge
)
256 network
->ipv6_accept_ra
= false;
258 /* IPMasquerade=yes implies IPForward=yes */
259 if (network
->ip_masquerade
)
260 network
->ip_forward
|= ADDRESS_FAMILY_IPV4
;
262 if (network
->mtu
> 0 && network
->dhcp_use_mtu
) {
263 log_warning("%s: MTUBytes= in [Link] section and UseMTU= in [DHCP] section are set. "
264 "Disabling UseMTU=.", network
->filename
);
265 network
->dhcp_use_mtu
= false;
268 if (network
->dhcp_use_gateway
< 0)
269 network
->dhcp_use_gateway
= network
->dhcp_use_routes
;
271 if (network
->ignore_carrier_loss
< 0)
272 network
->ignore_carrier_loss
= network
->configure_without_carrier
;
274 if (network
->dhcp_critical
>= 0) {
275 if (network
->keep_configuration
>= 0)
276 log_warning("%s: Both KeepConfiguration= and deprecated CriticalConnection= are set. "
277 "Ignoring CriticalConnection=.", network
->filename
);
278 else if (network
->dhcp_critical
)
279 /* CriticalConnection=yes also preserve foreign static configurations. */
280 network
->keep_configuration
= KEEP_CONFIGURATION_YES
;
282 network
->keep_configuration
= KEEP_CONFIGURATION_NO
;
285 if (network
->keep_configuration
< 0)
286 network
->keep_configuration
= KEEP_CONFIGURATION_NO
;
288 if (network
->ipv6_proxy_ndp
== 0 && !set_isempty(network
->ipv6_proxy_ndp_addresses
)) {
289 log_warning("%s: IPv6ProxyNDP= is disabled. Ignoring IPv6ProxyNDPAddress=.", network
->filename
);
290 network
->ipv6_proxy_ndp_addresses
= set_free_free(network
->ipv6_proxy_ndp_addresses
);
293 network_verify_addresses(network
);
294 network_verify_routes(network
);
295 network_verify_nexthops(network
);
296 network_verify_fdb_entries(network
);
297 network_verify_mdb_entries(network
);
298 network_verify_neighbors(network
);
299 network_verify_address_labels(network
);
300 network_verify_prefixes(network
);
301 network_verify_route_prefixes(network
);
302 network_verify_routing_policy_rules(network
);
304 bool has_root
= false, has_clsact
= false;
305 ORDERED_HASHMAP_FOREACH(tc
, network
->tc_by_section
)
306 if (traffic_control_section_verify(tc
, &has_root
, &has_clsact
) < 0)
307 traffic_control_free(tc
);
309 ORDERED_HASHMAP_FOREACH(sr_iov
, network
->sr_iov_by_section
)
310 if (sr_iov_section_verify(sr_iov
) < 0)
316 int network_load_one(Manager
*manager
, OrderedHashmap
**networks
, const char *filename
) {
317 _cleanup_free_
char *fname
= NULL
, *name
= NULL
;
318 _cleanup_(network_unrefp
) Network
*network
= NULL
;
319 _cleanup_fclose_
FILE *file
= NULL
;
320 const char *dropin_dirname
;
327 file
= fopen(filename
, "re");
335 if (null_or_empty_fd(fileno(file
))) {
336 log_debug("Skipping empty file: %s", filename
);
340 fname
= strdup(filename
);
344 name
= strdup(basename(filename
));
348 d
= strrchr(name
, '.');
354 dropin_dirname
= strjoina(name
, ".network.d");
356 network
= new(Network
, 1);
360 *network
= (Network
) {
361 .filename
= TAKE_PTR(fname
),
362 .name
= TAKE_PTR(name
),
367 .required_for_online
= true,
368 .required_operstate_for_online
= LINK_OPERSTATE_RANGE_DEFAULT
,
369 .dhcp
= ADDRESS_FAMILY_NO
,
371 .dhcp_use_ntp
= true,
372 .dhcp_use_sip
= true,
373 .dhcp_use_dns
= true,
374 .dhcp_use_hostname
= true,
375 .dhcp_use_routes
= true,
376 .dhcp_use_gateway
= -1,
377 /* NOTE: this var might be overwritten by network_apply_anonymize_if_set */
378 .dhcp_send_hostname
= true,
379 .dhcp_send_release
= true,
380 /* To enable/disable RFC7844 Anonymity Profiles */
381 .dhcp_anonymize
= false,
382 .dhcp_route_metric
= DHCP_ROUTE_METRIC
,
383 /* NOTE: this var might be overwritten by network_apply_anonymize_if_set */
384 .dhcp_client_identifier
= DHCP_CLIENT_ID_DUID
,
385 .dhcp_route_table
= RT_TABLE_MAIN
,
386 .dhcp_route_table_set
= false,
387 /* NOTE: from man: UseMTU=... Defaults to false*/
388 .dhcp_use_mtu
= false,
389 /* NOTE: from man: UseTimezone=... Defaults to "no".*/
390 .dhcp_use_timezone
= false,
391 .rapid_commit
= true,
393 .dhcp6_route_metric
= DHCP_ROUTE_METRIC
,
394 .dhcp6_use_ntp
= true,
395 .dhcp6_use_dns
= true,
397 .dhcp6_pd_subnet_id
= -1,
398 .dhcp6_pd_assign
= true,
400 .dhcp_server_emit
[SD_DHCP_LEASE_DNS
].emit
= true,
401 .dhcp_server_emit
[SD_DHCP_LEASE_NTP
].emit
= true,
402 .dhcp_server_emit
[SD_DHCP_LEASE_SIP
].emit
= true,
404 .dhcp_server_emit_router
= true,
405 .dhcp_server_emit_timezone
= true,
407 .router_emit_dns
= true,
408 .router_emit_domains
= true,
413 .allow_port_to_be_root
= -1,
415 .multicast_flood
= -1,
416 .multicast_to_unicast
= -1,
417 .neighbor_suppression
= -1,
419 .bridge_proxy_arp
= -1,
420 .bridge_proxy_arp_wifi
= -1,
421 .priority
= LINK_BRIDGE_PORT_PRIORITY_INVALID
,
422 .multicast_router
= _MULTICAST_ROUTER_INVALID
,
424 .lldp_mode
= LLDP_MODE_ROUTERS_ONLY
,
426 .dns_default_route
= -1,
427 .llmnr
= RESOLVE_SUPPORT_YES
,
428 .mdns
= RESOLVE_SUPPORT_NO
,
429 .dnssec_mode
= _DNSSEC_MODE_INVALID
,
430 .dns_over_tls_mode
= _DNS_OVER_TLS_MODE_INVALID
,
432 /* If LinkLocalAddressing= is not set, then set to ADDRESS_FAMILY_IPV6 later. */
433 .link_local
= _ADDRESS_FAMILY_INVALID
,
434 .ipv6ll_address_gen_mode
= _IPV6_LINK_LOCAL_ADDRESS_GEN_MODE_INVALID
,
436 .ipv4_accept_local
= -1,
438 .ipv6_privacy_extensions
= IPV6_PRIVACY_EXTENSIONS_NO
,
439 .ipv6_accept_ra
= -1,
440 .ipv6_dad_transmits
= -1,
441 .ipv6_hop_limit
= -1,
442 .ipv6_proxy_ndp
= -1,
443 .duid
.type
= _DUID_TYPE_INVALID
,
448 .ipv6_accept_ra_use_dns
= true,
449 .ipv6_accept_ra_use_autonomous_prefix
= true,
450 .ipv6_accept_ra_use_onlink_prefix
= true,
451 .ipv6_accept_ra_route_table
= RT_TABLE_MAIN
,
452 .ipv6_accept_ra_route_table_set
= false,
453 .ipv6_accept_ra_start_dhcp6_client
= true,
455 .configure_without_carrier
= false,
456 .ignore_carrier_loss
= -1,
457 .keep_configuration
= _KEEP_CONFIGURATION_INVALID
,
458 .can_triple_sampling
= -1,
459 .can_termination
= -1,
460 .can_listen_only
= -1,
463 .ip_service_type
= -1,
466 r
= config_parse_many(
467 filename
, NETWORK_DIRS
, dropin_dirname
,
475 "RoutingPolicyRule\0"
478 "DHCP\0" /* compat */
481 "DHCPv6PrefixDelegation\0"
484 "IPv6NDPProxyAddress\0"
489 "IPv6PrefixDelegation\0"
493 "TrafficControlQueueingDiscipline\0"
499 "DeficitRoundRobinScheduler\0"
500 "DeficitRoundRobinSchedulerClass\0"
501 "EnhancedTransmissionSelection\0"
503 "FairQueueingControlledDelay\0"
505 "GenericRandomEarlyDetection\0"
506 "HeavyHitterFilter\0"
507 "HierarchyTokenBucket\0"
508 "HierarchyTokenBucketClass\0"
514 "QuickFairQueueing\0"
515 "QuickFairQueueingClass\0"
516 "StochasticFairBlue\0"
517 "StochasticFairnessQueueing\0"
518 "TokenBucketFilter\0"
519 "TrivialLinkEqualizer\0",
520 config_item_perf_lookup
, network_network_gperf_lookup
,
523 &network
->timestamp
);
527 network_apply_anonymize_if_set(network
);
529 r
= network_add_ipv4ll_route(network
);
531 log_warning_errno(r
, "%s: Failed to add IPv4LL route, ignoring: %m", network
->filename
);
533 r
= network_add_default_route_on_device(network
);
535 log_warning_errno(r
, "%s: Failed to add default route on device, ignoring: %m",
538 if (network_verify(network
) < 0)
539 /* Ignore .network files that do not match the conditions. */
542 r
= ordered_hashmap_ensure_allocated(networks
, &string_hash_ops
);
546 r
= ordered_hashmap_put(*networks
, network
->name
, network
);
554 int network_load(Manager
*manager
, OrderedHashmap
**networks
) {
555 _cleanup_strv_free_
char **files
= NULL
;
561 ordered_hashmap_clear_with_destructor(*networks
, network_unref
);
563 r
= conf_files_list_strv(&files
, ".network", NULL
, 0, NETWORK_DIRS
);
565 return log_error_errno(r
, "Failed to enumerate network files: %m");
567 STRV_FOREACH(f
, files
) {
568 r
= network_load_one(manager
, networks
, *f
);
570 log_error_errno(r
, "Failed to load %s, ignoring: %m", *f
);
576 int network_reload(Manager
*manager
) {
577 OrderedHashmap
*new_networks
= NULL
;
583 r
= network_load(manager
, &new_networks
);
587 ORDERED_HASHMAP_FOREACH(n
, new_networks
) {
588 r
= network_get_by_name(manager
, n
->name
, &old
);
590 continue; /* The .network file is new. */
592 if (n
->timestamp
!= old
->timestamp
)
593 continue; /* The .network file is modified. */
595 if (!streq(n
->filename
, old
->filename
))
598 r
= ordered_hashmap_replace(new_networks
, old
->name
, old
);
606 ordered_hashmap_free_with_destructor(manager
->networks
, network_unref
);
607 manager
->networks
= new_networks
;
612 ordered_hashmap_free_with_destructor(new_networks
, network_unref
);
617 static Network
*network_free(Network
*network
) {
621 free(network
->filename
);
623 set_free_free(network
->match_mac
);
624 set_free_free(network
->match_permanent_mac
);
625 strv_free(network
->match_path
);
626 strv_free(network
->match_driver
);
627 strv_free(network
->match_type
);
628 strv_free(network
->match_name
);
629 strv_free(network
->match_property
);
630 strv_free(network
->match_wlan_iftype
);
631 strv_free(network
->match_ssid
);
632 set_free_free(network
->match_bssid
);
633 condition_free_list(network
->conditions
);
635 free(network
->description
);
636 free(network
->dhcp_vendor_class_identifier
);
637 free(network
->dhcp_mudurl
);
638 strv_free(network
->dhcp_user_class
);
639 free(network
->dhcp_hostname
);
640 set_free(network
->dhcp_deny_listed_ip
);
641 set_free(network
->dhcp_allow_listed_ip
);
642 set_free(network
->dhcp_request_options
);
643 set_free(network
->dhcp6_request_options
);
645 free(network
->dhcp6_mudurl
);
646 strv_free(network
->dhcp6_user_class
);
647 strv_free(network
->dhcp6_vendor_class
);
649 if (network
->dhcp_acd
)
650 sd_ipv4acd_unref(network
->dhcp_acd
);
652 strv_free(network
->ntp
);
653 for (unsigned i
= 0; i
< network
->n_dns
; i
++)
654 in_addr_full_free(network
->dns
[i
]);
656 ordered_set_free_free(network
->search_domains
);
657 ordered_set_free_free(network
->route_domains
);
658 strv_free(network
->bind_carrier
);
660 ordered_set_free_free(network
->router_search_domains
);
661 free(network
->router_dns
);
662 set_free_free(network
->ndisc_deny_listed_prefix
);
664 free(network
->bridge_name
);
665 free(network
->bond_name
);
666 free(network
->vrf_name
);
667 hashmap_free_free_key(network
->stacked_netdev_names
);
668 netdev_unref(network
->bridge
);
669 netdev_unref(network
->bond
);
670 netdev_unref(network
->vrf
);
671 hashmap_free_with_destructor(network
->stacked_netdevs
, netdev_unref
);
673 set_free_free(network
->ipv6_proxy_ndp_addresses
);
674 ordered_hashmap_free_with_destructor(network
->addresses_by_section
, address_free
);
675 hashmap_free_with_destructor(network
->routes_by_section
, route_free
);
676 hashmap_free_with_destructor(network
->nexthops_by_section
, nexthop_free
);
677 hashmap_free_with_destructor(network
->fdb_entries_by_section
, fdb_entry_free
);
678 hashmap_free_with_destructor(network
->mdb_entries_by_section
, mdb_entry_free
);
679 hashmap_free_with_destructor(network
->neighbors_by_section
, neighbor_free
);
680 hashmap_free_with_destructor(network
->address_labels_by_section
, address_label_free
);
681 hashmap_free_with_destructor(network
->prefixes_by_section
, prefix_free
);
682 hashmap_free_with_destructor(network
->route_prefixes_by_section
, route_prefix_free
);
683 hashmap_free_with_destructor(network
->rules_by_section
, routing_policy_rule_free
);
684 ordered_hashmap_free_with_destructor(network
->sr_iov_by_section
, sr_iov_free
);
685 ordered_hashmap_free_with_destructor(network
->tc_by_section
, traffic_control_free
);
687 if (network
->manager
&&
688 network
->manager
->duids_requesting_uuid
)
689 set_remove(network
->manager
->duids_requesting_uuid
, &network
->duid
);
693 free(network
->dhcp_server_timezone
);
695 for (sd_dhcp_lease_server_type t
= 0; t
< _SD_DHCP_LEASE_SERVER_TYPE_MAX
; t
++)
696 free(network
->dhcp_server_emit
[t
].addresses
);
698 set_free_free(network
->dnssec_negative_trust_anchors
);
700 free(network
->lldp_mud
);
702 ordered_hashmap_free(network
->dhcp_client_send_options
);
703 ordered_hashmap_free(network
->dhcp_client_send_vendor_options
);
704 ordered_hashmap_free(network
->dhcp_server_send_options
);
705 ordered_hashmap_free(network
->dhcp_server_send_vendor_options
);
706 ordered_set_free(network
->ipv6_tokens
);
707 ordered_hashmap_free(network
->dhcp6_client_send_options
);
708 ordered_hashmap_free(network
->dhcp6_client_send_vendor_options
);
710 return mfree(network
);
713 DEFINE_TRIVIAL_REF_UNREF_FUNC(Network
, network
, network_free
);
715 int network_get_by_name(Manager
*manager
, const char *name
, Network
**ret
) {
722 network
= ordered_hashmap_get(manager
->networks
, name
);
731 int network_get(Manager
*manager
, unsigned short iftype
, sd_device
*device
,
732 const char *ifname
, char * const *alternative_names
, const char *driver
,
733 const struct ether_addr
*mac
, const struct ether_addr
*permanent_mac
,
734 enum nl80211_iftype wlan_iftype
, const char *ssid
, const struct ether_addr
*bssid
,
741 ORDERED_HASHMAP_FOREACH(network
, manager
->networks
)
742 if (net_match_config(network
->match_mac
, network
->match_permanent_mac
,
743 network
->match_path
, network
->match_driver
,
744 network
->match_type
, network
->match_name
, network
->match_property
,
745 network
->match_wlan_iftype
, network
->match_ssid
, network
->match_bssid
,
746 device
, mac
, permanent_mac
, driver
, iftype
,
747 ifname
, alternative_names
, wlan_iftype
, ssid
, bssid
)) {
748 if (network
->match_name
&& device
) {
750 uint8_t name_assign_type
= NET_NAME_UNKNOWN
;
752 if (sd_device_get_sysattr_value(device
, "name_assign_type", &attr
) >= 0)
753 (void) safe_atou8(attr
, &name_assign_type
);
755 if (name_assign_type
== NET_NAME_ENUM
)
756 log_warning("%s: found matching network '%s', based on potentially unpredictable ifname",
757 ifname
, network
->filename
);
759 log_debug("%s: found matching network '%s'", ifname
, network
->filename
);
761 log_debug("%s: found matching network '%s'", ifname
, network
->filename
);
772 int network_apply(Network
*network
, Link
*link
) {
776 link
->network
= network_ref(network
);
778 if (network
->n_dns
> 0 ||
779 !strv_isempty(network
->ntp
) ||
780 !ordered_set_isempty(network
->search_domains
) ||
781 !ordered_set_isempty(network
->route_domains
))
787 bool network_has_static_ipv6_configurations(Network
*network
) {
796 ORDERED_HASHMAP_FOREACH(address
, network
->addresses_by_section
)
797 if (address
->family
== AF_INET6
)
800 HASHMAP_FOREACH(route
, network
->routes_by_section
)
801 if (route
->family
== AF_INET6
)
804 HASHMAP_FOREACH(fdb
, network
->fdb_entries_by_section
)
805 if (fdb
->family
== AF_INET6
)
808 HASHMAP_FOREACH(mdb
, network
->mdb_entries_by_section
)
809 if (mdb
->family
== AF_INET6
)
812 HASHMAP_FOREACH(neighbor
, network
->neighbors_by_section
)
813 if (neighbor
->family
== AF_INET6
)
816 if (!hashmap_isempty(network
->address_labels_by_section
))
819 if (!hashmap_isempty(network
->prefixes_by_section
))
822 if (!hashmap_isempty(network
->route_prefixes_by_section
))
828 int config_parse_stacked_netdev(const char *unit
,
829 const char *filename
,
832 unsigned section_line
,
838 _cleanup_free_
char *name
= NULL
;
839 NetDevKind kind
= ltype
;
848 NETDEV_KIND_VLAN
, NETDEV_KIND_MACVLAN
, NETDEV_KIND_MACVTAP
,
849 NETDEV_KIND_IPVLAN
, NETDEV_KIND_IPVTAP
, NETDEV_KIND_VXLAN
,
850 NETDEV_KIND_L2TP
, NETDEV_KIND_MACSEC
, _NETDEV_KIND_TUNNEL
,
853 if (!ifname_valid(rvalue
)) {
854 log_syntax(unit
, LOG_WARNING
, filename
, line
, 0,
855 "Invalid netdev name in %s=, ignoring assignment: %s", lvalue
, rvalue
);
859 name
= strdup(rvalue
);
863 r
= hashmap_ensure_allocated(h
, &string_hash_ops
);
867 r
= hashmap_put(*h
, name
, INT_TO_PTR(kind
));
869 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
870 "Cannot add NetDev '%s' to network, ignoring assignment: %m", name
);
872 log_syntax(unit
, LOG_DEBUG
, filename
, line
, r
,
873 "NetDev '%s' specified twice, ignoring.", name
);
880 int config_parse_domains(
882 const char *filename
,
885 unsigned section_line
,
899 if (isempty(rvalue
)) {
900 n
->search_domains
= ordered_set_free_free(n
->search_domains
);
901 n
->route_domains
= ordered_set_free_free(n
->route_domains
);
905 for (const char *p
= rvalue
;;) {
906 _cleanup_free_
char *w
= NULL
, *normalized
= NULL
;
910 r
= extract_first_word(&p
, &w
, NULL
, 0);
914 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
915 "Failed to extract search or route domain, ignoring: %s", rvalue
);
921 is_route
= w
[0] == '~';
922 domain
= is_route
? w
+ 1 : w
;
924 if (dns_name_is_root(domain
) || streq(domain
, "*")) {
925 /* If the root domain appears as is, or the special token "*" is found, we'll
926 * consider this as routing domain, unconditionally. */
928 domain
= "."; /* make sure we don't allow empty strings, thus write the root
931 r
= dns_name_normalize(domain
, 0, &normalized
);
933 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
934 "'%s' is not a valid domain name, ignoring.", domain
);
940 if (is_localhost(domain
)) {
941 log_syntax(unit
, LOG_WARNING
, filename
, line
, 0,
942 "'localhost' domain may not be configured as search or route domain, ignoring assignment: %s",
948 OrderedSet
**set
= is_route
? &n
->route_domains
: &n
->search_domains
;
949 r
= ordered_set_ensure_allocated(set
, &string_hash_ops
);
953 r
= ordered_set_put_strdup(*set
, domain
);
959 int config_parse_ipv6token(
961 const char *filename
,
964 unsigned section_line
,
971 union in_addr_union buffer
;
972 struct in6_addr
*token
= data
;
980 r
= in_addr_from_string(AF_INET6
, rvalue
, &buffer
);
982 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
983 "Failed to parse IPv6 token, ignoring: %s", rvalue
);
987 if (in_addr_is_null(AF_INET6
, &buffer
)) {
988 log_syntax(unit
, LOG_WARNING
, filename
, line
, 0,
989 "IPv6 token cannot be the ANY address, ignoring: %s", rvalue
);
993 if ((buffer
.in6
.s6_addr32
[0] | buffer
.in6
.s6_addr32
[1]) != 0) {
994 log_syntax(unit
, LOG_WARNING
, filename
, line
, 0,
995 "IPv6 token cannot be longer than 64 bits, ignoring: %s", rvalue
);
1004 static const char* const ipv6_privacy_extensions_table
[_IPV6_PRIVACY_EXTENSIONS_MAX
] = {
1005 [IPV6_PRIVACY_EXTENSIONS_NO
] = "no",
1006 [IPV6_PRIVACY_EXTENSIONS_PREFER_PUBLIC
] = "prefer-public",
1007 [IPV6_PRIVACY_EXTENSIONS_YES
] = "yes",
1010 DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(ipv6_privacy_extensions
, IPv6PrivacyExtensions
,
1011 IPV6_PRIVACY_EXTENSIONS_YES
);
1013 int config_parse_ipv6_privacy_extensions(
1015 const char *filename
,
1017 const char *section
,
1018 unsigned section_line
,
1025 IPv6PrivacyExtensions s
, *ipv6_privacy_extensions
= data
;
1030 assert(ipv6_privacy_extensions
);
1032 s
= ipv6_privacy_extensions_from_string(rvalue
);
1034 if (streq(rvalue
, "kernel"))
1035 s
= _IPV6_PRIVACY_EXTENSIONS_INVALID
;
1037 log_syntax(unit
, LOG_WARNING
, filename
, line
, 0,
1038 "Failed to parse IPv6 privacy extensions option, ignoring: %s", rvalue
);
1043 *ipv6_privacy_extensions
= s
;
1048 int config_parse_hostname(
1050 const char *filename
,
1052 const char *section
,
1053 unsigned section_line
,
1060 _cleanup_free_
char *hn
= NULL
;
1061 char **hostname
= data
;
1068 r
= config_parse_string(unit
, filename
, line
, section
, section_line
, lvalue
, ltype
, rvalue
, &hn
, userdata
);
1072 if (!hostname_is_valid(hn
, false)) {
1073 log_syntax(unit
, LOG_WARNING
, filename
, line
, 0,
1074 "Hostname is not valid, ignoring assignment: %s", rvalue
);
1078 r
= dns_name_is_valid(hn
);
1080 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
1081 "Failed to check validity of hostname '%s', ignoring assignment: %m", rvalue
);
1085 log_syntax(unit
, LOG_WARNING
, filename
, line
, 0,
1086 "Hostname is not a valid DNS domain name, ignoring assignment: %s", rvalue
);
1090 return free_and_replace(*hostname
, hn
);
1093 int config_parse_timezone(
1095 const char *filename
,
1097 const char *section
,
1098 unsigned section_line
,
1105 _cleanup_free_
char *tz
= NULL
;
1106 char **datap
= data
;
1113 r
= config_parse_string(unit
, filename
, line
, section
, section_line
, lvalue
, ltype
, rvalue
, &tz
, userdata
);
1117 if (!timezone_is_valid(tz
, LOG_WARNING
)) {
1118 log_syntax(unit
, LOG_WARNING
, filename
, line
, 0,
1119 "Timezone is not valid, ignoring assignment: %s", rvalue
);
1123 return free_and_replace(*datap
, tz
);
1126 int config_parse_dns(
1128 const char *filename
,
1130 const char *section
,
1131 unsigned section_line
,
1138 Network
*n
= userdata
;
1145 if (isempty(rvalue
)) {
1146 for (unsigned i
= 0; i
< n
->n_dns
; i
++)
1147 in_addr_full_free(n
->dns
[i
]);
1148 n
->dns
= mfree(n
->dns
);
1153 for (const char *p
= rvalue
;;) {
1154 _cleanup_(in_addr_full_freep
) struct in_addr_full
*dns
= NULL
;
1155 _cleanup_free_
char *w
= NULL
;
1156 struct in_addr_full
**m
;
1158 r
= extract_first_word(&p
, &w
, NULL
, 0);
1162 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
1163 "Invalid syntax, ignoring: %s", rvalue
);
1169 r
= in_addr_full_new_from_string(w
, &dns
);
1171 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
1172 "Failed to parse dns server address, ignoring: %s", w
);
1176 if (IN_SET(dns
->port
, 53, 853))
1179 m
= reallocarray(n
->dns
, n
->n_dns
+ 1, sizeof(struct in_addr_full
*));
1183 m
[n
->n_dns
++] = TAKE_PTR(dns
);
1188 int config_parse_dnssec_negative_trust_anchors(
1190 const char *filename
,
1192 const char *section
,
1193 unsigned section_line
,
1207 if (isempty(rvalue
)) {
1208 n
->dnssec_negative_trust_anchors
= set_free_free(n
->dnssec_negative_trust_anchors
);
1212 for (const char *p
= rvalue
;;) {
1213 _cleanup_free_
char *w
= NULL
;
1215 r
= extract_first_word(&p
, &w
, NULL
, 0);
1219 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
1220 "Failed to extract negative trust anchor domain, ignoring: %s", rvalue
);
1226 r
= dns_name_is_valid(w
);
1228 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
1229 "%s is not a valid domain name, ignoring.", w
);
1233 r
= set_ensure_consume(&n
->dnssec_negative_trust_anchors
, &dns_name_hash_ops
, TAKE_PTR(w
));
1239 int config_parse_ntp(
1241 const char *filename
,
1243 const char *section
,
1244 unsigned section_line
,
1258 if (isempty(rvalue
)) {
1263 for (const char *p
= rvalue
;;) {
1264 _cleanup_free_
char *w
= NULL
;
1266 r
= extract_first_word(&p
, &w
, NULL
, 0);
1270 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
1271 "Failed to extract NTP server name, ignoring: %s", rvalue
);
1277 r
= dns_name_is_valid_or_address(w
);
1279 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
1280 "%s is not a valid domain name or IP address, ignoring.", w
);
1284 if (strv_length(*l
) > MAX_NTP_SERVERS
) {
1285 log_syntax(unit
, LOG_WARNING
, filename
, line
, 0,
1286 "More than %u NTP servers specified, ignoring \"%s\" and any subsequent entries.",
1287 MAX_NTP_SERVERS
, w
);
1291 r
= strv_consume(l
, TAKE_PTR(w
));
1297 int config_parse_required_for_online(
1299 const char *filename
,
1301 const char *section
,
1302 unsigned section_line
,
1309 Network
*network
= data
;
1310 LinkOperationalStateRange range
;
1311 bool required
= true;
1314 if (isempty(rvalue
)) {
1315 network
->required_for_online
= true;
1316 network
->required_operstate_for_online
= LINK_OPERSTATE_RANGE_DEFAULT
;
1320 r
= parse_operational_state_range(rvalue
, &range
);
1322 r
= parse_boolean(rvalue
);
1324 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
1325 "Failed to parse %s= setting, ignoring assignment: %s",
1331 range
= LINK_OPERSTATE_RANGE_DEFAULT
;
1334 network
->required_for_online
= required
;
1335 network
->required_operstate_for_online
= range
;
1340 DEFINE_CONFIG_PARSE_ENUM(config_parse_keep_configuration
, keep_configuration
, KeepConfiguration
,
1341 "Failed to parse KeepConfiguration= setting");
1343 static const char* const keep_configuration_table
[_KEEP_CONFIGURATION_MAX
] = {
1344 [KEEP_CONFIGURATION_NO
] = "no",
1345 [KEEP_CONFIGURATION_DHCP_ON_STOP
] = "dhcp-on-stop",
1346 [KEEP_CONFIGURATION_DHCP
] = "dhcp",
1347 [KEEP_CONFIGURATION_STATIC
] = "static",
1348 [KEEP_CONFIGURATION_YES
] = "yes",
1351 DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(keep_configuration
, KeepConfiguration
, KEEP_CONFIGURATION_YES
);
1353 static const char* const ipv6_link_local_address_gen_mode_table
[_IPV6_LINK_LOCAL_ADDRESS_GEN_MODE_MAX
] = {
1354 [IPV6_LINK_LOCAL_ADDRESSS_GEN_MODE_EUI64
] = "eui64",
1355 [IPV6_LINK_LOCAL_ADDRESSS_GEN_MODE_NONE
] = "none",
1356 [IPV6_LINK_LOCAL_ADDRESSS_GEN_MODE_STABLE_PRIVACY
] = "stable-privacy",
1357 [IPV6_LINK_LOCAL_ADDRESSS_GEN_MODE_RANDOM
] = "random",
1360 DEFINE_STRING_TABLE_LOOKUP(ipv6_link_local_address_gen_mode
, IPv6LinkLocalAddressGenMode
);
1361 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");