1 /* SPDX-License-Identifier: LGPL-2.1+ */
4 #include <netinet/in.h>
5 #include <linux/netdevice.h>
7 #include "alloc-util.h"
8 #include "conf-files.h"
9 #include "conf-parser.h"
10 #include "dns-domain.h"
12 #include "hostname-util.h"
13 #include "in-addr-util.h"
14 #include "networkd-dhcp-server.h"
15 #include "network-internal.h"
16 #include "networkd-manager.h"
17 #include "networkd-network.h"
18 #include "parse-util.h"
19 #include "path-lookup.h"
21 #include "socket-util.h"
22 #include "stat-util.h"
23 #include "string-table.h"
24 #include "string-util.h"
29 /* Let's assume that anything above this number is a user misconfiguration. */
30 #define MAX_NTP_SERVERS 128
32 /* Set defaults following RFC7844 */
33 void network_apply_anonymize_if_set(Network
*network
) {
34 if (!network
->dhcp_anonymize
)
37 SHOULD NOT send the Host Name option */
38 network
->dhcp_send_hostname
= false;
39 /* RFC7844 section 3.:
40 MAY contain the Client Identifier option
42 clients MUST use client identifiers based solely
43 on the link-layer address */
44 /* NOTE: Using MAC, as it does not reveal extra information,
45 * and some servers might not answer if this option is not sent */
46 network
->dhcp_client_identifier
= DHCP_CLIENT_ID_MAC
;
48 SHOULD NOT use the Vendor Class Identifier option */
49 network
->dhcp_vendor_class_identifier
= mfree(network
->dhcp_vendor_class_identifier
);
50 /* RFC7844 section 3.6.:
51 The client intending to protect its privacy SHOULD only request a
52 minimal number of options in the PRL and SHOULD also randomly shuffle
53 the ordering of option codes in the PRL. If this random ordering
54 cannot be implemented, the client MAY order the option codes in the
55 PRL by option code number (lowest to highest).
57 /* NOTE: dhcp_use_mtu is false by default,
58 * though it was not initiallized to any value in network_load_one.
59 * Maybe there should be another var called *send*?
60 * (to use the MTU sent by the server but to do not send
61 * the option in the PRL). */
62 network
->dhcp_use_mtu
= false;
63 /* NOTE: when Anonymize=yes, the PRL route options are sent by default,
64 * but this is needed to use them. */
65 network
->dhcp_use_routes
= true;
66 /* RFC7844 section 3.6.
67 * same comments as previous option */
68 network
->dhcp_use_timezone
= false;
71 static int network_resolve_netdev_one(Network
*network
, const char *name
, NetDevKind kind
, NetDev
**ret_netdev
) {
72 const char *kind_string
;
76 /* For test-networkd-conf, the check must be earlier than the assertions. */
81 assert(network
->manager
);
82 assert(network
->filename
);
85 if (kind
== _NETDEV_KIND_TUNNEL
)
86 kind_string
= "tunnel";
88 kind_string
= netdev_kind_to_string(kind
);
90 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
),
91 "%s: Invalid NetDev kind of %s, ignoring assignment.",
92 network
->filename
, name
);
95 r
= netdev_get(network
->manager
, name
, &netdev
);
97 return log_error_errno(r
, "%s: %s NetDev could not be found, ignoring assignment.",
98 network
->filename
, name
);
100 if (netdev
->kind
!= kind
&& !(kind
== _NETDEV_KIND_TUNNEL
&&
107 NETDEV_KIND_IP6GRETAP
,
111 NETDEV_KIND_ERSPAN
)))
112 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
),
113 "%s: NetDev %s is not a %s, ignoring assignment",
114 network
->filename
, name
, kind_string
);
116 *ret_netdev
= netdev_ref(netdev
);
120 static int network_resolve_stacked_netdevs(Network
*network
) {
127 HASHMAP_FOREACH_KEY(kind
, name
, network
->stacked_netdev_names
, i
) {
128 _cleanup_(netdev_unrefp
) NetDev
*netdev
= NULL
;
130 r
= network_resolve_netdev_one(network
, name
, PTR_TO_INT(kind
), &netdev
);
134 r
= hashmap_ensure_allocated(&network
->stacked_netdevs
, &string_hash_ops
);
138 r
= hashmap_put(network
->stacked_netdevs
, netdev
->ifname
, netdev
);
140 return log_error_errno(r
, "%s: Failed to add NetDev '%s' to network: %m",
141 network
->filename
, (const char *) name
);
149 int network_verify(Network
*network
) {
150 RoutePrefix
*route_prefix
, *route_prefix_next
;
151 RoutingPolicyRule
*rule
, *rule_next
;
152 Neighbor
*neighbor
, *neighbor_next
;
153 AddressLabel
*label
, *label_next
;
154 NextHop
*nexthop
, *nextnop_next
;
155 Address
*address
, *address_next
;
156 Prefix
*prefix
, *prefix_next
;
157 Route
*route
, *route_next
;
158 FdbEntry
*fdb
, *fdb_next
;
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_ssid
) && !network
->conditions
)
169 return log_warning_errno(SYNTHETIC_ERRNO(EINVAL
),
170 "%s: No valid settings found in the [Match] section, ignoring file. "
171 "To match all interfaces, add Name=* in the [Match] section.",
174 /* skip out early if configuration does not match the environment */
175 if (!condition_test_list(network
->conditions
, NULL
, NULL
, NULL
))
176 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL
),
177 "%s: Conditions in the file do not match the system environment, skipping.",
180 (void) network_resolve_netdev_one(network
, network
->bond_name
, NETDEV_KIND_BOND
, &network
->bond
);
181 (void) network_resolve_netdev_one(network
, network
->bridge_name
, NETDEV_KIND_BRIDGE
, &network
->bridge
);
182 (void) network_resolve_netdev_one(network
, network
->vrf_name
, NETDEV_KIND_VRF
, &network
->vrf
);
183 (void) network_resolve_stacked_netdevs(network
);
185 /* Free unnecessary entries. */
186 network
->bond_name
= mfree(network
->bond_name
);
187 network
->bridge_name
= mfree(network
->bridge_name
);
188 network
->vrf_name
= mfree(network
->vrf_name
);
189 network
->stacked_netdev_names
= hashmap_free_free_key(network
->stacked_netdev_names
);
192 /* Bonding slave does not support addressing. */
193 if (network
->ipv6_accept_ra
> 0) {
194 log_warning("%s: Cannot enable IPv6AcceptRA= when Bond= is specified, disabling IPv6AcceptRA=.",
196 network
->ipv6_accept_ra
= 0;
198 if (network
->link_local
>= 0 && network
->link_local
!= ADDRESS_FAMILY_NO
) {
199 log_warning("%s: Cannot enable LinkLocalAddressing= when Bond= is specified, disabling LinkLocalAddressing=.",
201 network
->link_local
= ADDRESS_FAMILY_NO
;
203 if (network
->dhcp
!= ADDRESS_FAMILY_NO
) {
204 log_warning("%s: Cannot enable DHCP= when Bond= is specified, disabling DHCP=.",
206 network
->dhcp
= ADDRESS_FAMILY_NO
;
208 if (network
->dhcp_server
) {
209 log_warning("%s: Cannot enable DHCPServer= when Bond= is specified, disabling DHCPServer=.",
211 network
->dhcp_server
= false;
213 if (network
->n_static_addresses
> 0) {
214 log_warning("%s: Cannot set addresses when Bond= is specified, ignoring addresses.",
216 while ((address
= network
->static_addresses
))
217 address_free(address
);
219 if (network
->n_static_routes
> 0) {
220 log_warning("%s: Cannot set routes when Bond= is specified, ignoring routes.",
222 while ((route
= network
->static_routes
))
227 if (network
->link_local
< 0)
228 network
->link_local
= network
->bridge
? ADDRESS_FAMILY_NO
: ADDRESS_FAMILY_IPV6
;
230 if (!FLAGS_SET(network
->link_local
, ADDRESS_FAMILY_IPV6
)) {
231 if (network
->ipv6_accept_ra
> 0) {
232 log_warning("%s: IPv6AcceptRA= is enabled by the .network file but IPv6 link local addressing is disabled. "
233 "Disabling IPv6AcceptRA=.", network
->filename
);
234 network
->ipv6_accept_ra
= false;
237 if (FLAGS_SET(network
->dhcp
, ADDRESS_FAMILY_IPV6
)) {
238 log_warning("%s: DHCPv6 client is enabled by the .network file but IPv6 link local addressing is disabled. "
239 "Disabling DHCPv6 client.", network
->filename
);
240 SET_FLAG(network
->dhcp
, ADDRESS_FAMILY_IPV6
, false);
243 if (network
->router_prefix_delegation
!= RADV_PREFIX_DELEGATION_NONE
) {
244 log_warning("%s: IPv6PrefixDelegation= is enabled but IPv6 link local addressing is disabled. "
245 "Disabling IPv6PrefixDelegation=.", network
->filename
);
246 network
->router_prefix_delegation
= RADV_PREFIX_DELEGATION_NONE
;
250 if (FLAGS_SET(network
->link_local
, ADDRESS_FAMILY_FALLBACK_IPV4
) &&
251 !FLAGS_SET(network
->dhcp
, ADDRESS_FAMILY_IPV4
)) {
252 log_warning("%s: fallback assignment of IPv4 link local address is enabled but DHCPv4 is disabled. "
253 "Disabling the fallback assignment.", network
->filename
);
254 SET_FLAG(network
->link_local
, ADDRESS_FAMILY_FALLBACK_IPV4
, false);
257 if (network
->ipv6_accept_ra
< 0 && network
->bridge
)
258 network
->ipv6_accept_ra
= false;
260 /* IPMasquerade=yes implies IPForward=yes */
261 if (network
->ip_masquerade
)
262 network
->ip_forward
|= ADDRESS_FAMILY_IPV4
;
264 if (network
->mtu
> 0 && network
->dhcp_use_mtu
) {
265 log_warning("%s: MTUBytes= in [Link] section and UseMTU= in [DHCP] section are set. "
266 "Disabling UseMTU=.", network
->filename
);
267 network
->dhcp_use_mtu
= false;
270 if (network
->dhcp_critical
>= 0) {
271 if (network
->keep_configuration
>= 0)
272 log_warning("%s: Both KeepConfiguration= and deprecated CriticalConnection= are set. "
273 "Ignoring CriticalConnection=.", network
->filename
);
274 else if (network
->dhcp_critical
)
275 /* CriticalConnection=yes also preserve foreign static configurations. */
276 network
->keep_configuration
= KEEP_CONFIGURATION_YES
;
278 network
->keep_configuration
= KEEP_CONFIGURATION_NO
;
281 if (network
->keep_configuration
< 0)
282 network
->keep_configuration
= KEEP_CONFIGURATION_NO
;
284 LIST_FOREACH_SAFE(addresses
, address
, address_next
, network
->static_addresses
)
285 if (address_section_verify(address
) < 0)
286 address_free(address
);
288 LIST_FOREACH_SAFE(routes
, route
, route_next
, network
->static_routes
)
289 if (route_section_verify(route
, network
) < 0)
292 LIST_FOREACH_SAFE(nexthops
, nexthop
, nextnop_next
, network
->static_nexthops
)
293 if (nexthop_section_verify(nexthop
) < 0)
294 nexthop_free(nexthop
);
296 LIST_FOREACH_SAFE(static_fdb_entries
, fdb
, fdb_next
, network
->static_fdb_entries
)
297 if (section_is_invalid(fdb
->section
))
300 LIST_FOREACH_SAFE(neighbors
, neighbor
, neighbor_next
, network
->neighbors
)
301 if (neighbor_section_verify(neighbor
) < 0)
302 neighbor_free(neighbor
);
304 LIST_FOREACH_SAFE(labels
, label
, label_next
, network
->address_labels
)
305 if (section_is_invalid(label
->section
))
306 address_label_free(label
);
308 LIST_FOREACH_SAFE(prefixes
, prefix
, prefix_next
, network
->static_prefixes
)
309 if (section_is_invalid(prefix
->section
))
312 LIST_FOREACH_SAFE(route_prefixes
, route_prefix
, route_prefix_next
, network
->static_route_prefixes
)
313 if (section_is_invalid(route_prefix
->section
))
314 route_prefix_free(route_prefix
);
316 LIST_FOREACH_SAFE(rules
, rule
, rule_next
, network
->rules
)
317 if (routing_policy_rule_section_verify(rule
) < 0)
318 routing_policy_rule_free(rule
);
320 bool has_root
= false, has_clsact
= false;
321 ORDERED_HASHMAP_FOREACH(tc
, network
->tc_by_section
, i
)
322 if (traffic_control_section_verify(tc
, &has_root
, &has_clsact
) < 0)
323 traffic_control_free(tc
);
328 int network_load_one(Manager
*manager
, OrderedHashmap
**networks
, const char *filename
) {
329 _cleanup_free_
char *fname
= NULL
, *name
= NULL
;
330 _cleanup_(network_unrefp
) Network
*network
= NULL
;
331 _cleanup_fclose_
FILE *file
= NULL
;
332 const char *dropin_dirname
;
339 file
= fopen(filename
, "re");
347 if (null_or_empty_fd(fileno(file
))) {
348 log_debug("Skipping empty file: %s", filename
);
352 fname
= strdup(filename
);
356 name
= strdup(basename(filename
));
360 d
= strrchr(name
, '.');
366 dropin_dirname
= strjoina(name
, ".network.d");
368 network
= new(Network
, 1);
372 *network
= (Network
) {
373 .filename
= TAKE_PTR(fname
),
374 .name
= TAKE_PTR(name
),
379 .required_for_online
= true,
380 .required_operstate_for_online
= LINK_OPERSTATE_RANGE_DEFAULT
,
381 .dhcp
= ADDRESS_FAMILY_NO
,
383 .dhcp_use_ntp
= true,
384 .dhcp_use_sip
= true,
385 .dhcp_use_dns
= true,
386 .dhcp_use_hostname
= true,
387 .dhcp_use_routes
= true,
388 .dhcp_use_gateway
= true,
389 /* NOTE: this var might be overwritten by network_apply_anonymize_if_set */
390 .dhcp_send_hostname
= true,
391 .dhcp_send_release
= true,
392 /* To enable/disable RFC7844 Anonymity Profiles */
393 .dhcp_anonymize
= false,
394 .dhcp_route_metric
= DHCP_ROUTE_METRIC
,
395 /* NOTE: this var might be overwritten by network_apply_anonymize_if_set */
396 .dhcp_client_identifier
= DHCP_CLIENT_ID_DUID
,
397 .dhcp_route_table
= RT_TABLE_MAIN
,
398 .dhcp_route_table_set
= false,
399 /* NOTE: from man: UseMTU=... Defaults to false*/
400 .dhcp_use_mtu
= false,
401 /* NOTE: from man: UseTimezone=... Defaults to "no".*/
402 .dhcp_use_timezone
= false,
403 .rapid_commit
= true,
405 .dhcp6_use_ntp
= true,
406 .dhcp6_use_dns
= true,
408 .dhcp_server_emit_dns
= true,
409 .dhcp_server_emit_ntp
= true,
410 .dhcp_server_emit_sip
= true,
411 .dhcp_server_emit_router
= true,
412 .dhcp_server_emit_timezone
= true,
414 .router_emit_dns
= true,
415 .router_emit_domains
= true,
420 .allow_port_to_be_root
= -1,
422 .multicast_flood
= -1,
423 .multicast_to_unicast
= -1,
424 .neighbor_suppression
= -1,
426 .bridge_proxy_arp
= -1,
427 .bridge_proxy_arp_wifi
= -1,
428 .priority
= LINK_BRIDGE_PORT_PRIORITY_INVALID
,
429 .multicast_router
= _MULTICAST_ROUTER_INVALID
,
431 .lldp_mode
= LLDP_MODE_ROUTERS_ONLY
,
433 .dns_default_route
= -1,
434 .llmnr
= RESOLVE_SUPPORT_YES
,
435 .mdns
= RESOLVE_SUPPORT_NO
,
436 .dnssec_mode
= _DNSSEC_MODE_INVALID
,
437 .dns_over_tls_mode
= _DNS_OVER_TLS_MODE_INVALID
,
439 /* If LinkLocalAddressing= is not set, then set to ADDRESS_FAMILY_IPV6 later. */
440 .link_local
= _ADDRESS_FAMILY_INVALID
,
442 .ipv6_privacy_extensions
= IPV6_PRIVACY_EXTENSIONS_NO
,
443 .ipv6_accept_ra
= -1,
444 .ipv6_dad_transmits
= -1,
445 .ipv6_hop_limit
= -1,
446 .ipv6_proxy_ndp
= -1,
447 .duid
.type
= _DUID_TYPE_INVALID
,
452 .ipv6_accept_ra_use_dns
= true,
453 .ipv6_accept_ra_use_autonomous_prefix
= true,
454 .ipv6_accept_ra_use_onlink_prefix
= true,
455 .ipv6_accept_ra_route_table
= RT_TABLE_MAIN
,
456 .ipv6_accept_ra_route_table_set
= false,
457 .ipv6_accept_ra_start_dhcp6_client
= true,
459 .keep_configuration
= _KEEP_CONFIGURATION_INVALID
,
461 .can_triple_sampling
= -1,
462 .can_termination
= -1,
463 .ip_service_type
= -1,
466 r
= config_parse_many(filename
, NETWORK_DIRS
, dropin_dirname
,
473 "RoutingPolicyRule\0"
476 "DHCP\0" /* compat */
481 "IPv6NDPProxyAddress\0"
485 "IPv6PrefixDelegation\0"
488 "TrafficControlQueueingDiscipline\0"
494 "DeficitRoundRobinScheduler\0"
495 "DeficitRoundRobinSchedulerClass\0"
500 "FairQueueingControlledDelay\0"
501 "GenericRandomEarlyDetection\0"
502 "HeavyHitterFilter\0"
503 "HierarchyTokenBucket\0"
504 "HierarchyTokenBucketClass\0"
507 "StochasticFairBlue\0"
508 "StochasticFairnessQueueing\0"
509 "TokenBucketFilter\0"
510 "TrivialLinkEqualizer\0",
511 config_item_perf_lookup
, network_network_gperf_lookup
,
512 CONFIG_PARSE_WARN
, network
);
516 network_apply_anonymize_if_set(network
);
518 r
= network_add_ipv4ll_route(network
);
520 log_warning_errno(r
, "%s: Failed to add IPv4LL route, ignoring: %m", network
->filename
);
522 r
= network_add_default_route_on_device(network
);
524 log_warning_errno(r
, "%s: Failed to add default route on device, ignoring: %m",
528 if (stat(filename
, &stats
) < 0)
530 network
->timestamp
= timespec_load(&stats
.st_mtim
);
532 if (network_verify(network
) < 0)
533 /* Ignore .network files that do not match the conditions. */
536 r
= ordered_hashmap_ensure_allocated(networks
, &string_hash_ops
);
540 r
= ordered_hashmap_put(*networks
, network
->name
, network
);
548 int network_load(Manager
*manager
, OrderedHashmap
**networks
) {
549 _cleanup_strv_free_
char **files
= NULL
;
555 ordered_hashmap_clear_with_destructor(*networks
, network_unref
);
557 r
= conf_files_list_strv(&files
, ".network", NULL
, 0, NETWORK_DIRS
);
559 return log_error_errno(r
, "Failed to enumerate network files: %m");
561 STRV_FOREACH(f
, files
) {
562 r
= network_load_one(manager
, networks
, *f
);
564 log_error_errno(r
, "Failed to load %s, ignoring: %m", *f
);
570 int network_reload(Manager
*manager
) {
571 OrderedHashmap
*new_networks
= NULL
;
578 r
= network_load(manager
, &new_networks
);
582 ORDERED_HASHMAP_FOREACH(n
, new_networks
, i
) {
583 r
= network_get_by_name(manager
, n
->name
, &old
);
585 continue; /* The .network file is new. */
587 if (n
->timestamp
!= old
->timestamp
)
588 continue; /* The .network file is modified. */
590 if (!streq(n
->filename
, old
->filename
))
593 r
= ordered_hashmap_replace(new_networks
, old
->name
, old
);
601 ordered_hashmap_free_with_destructor(manager
->networks
, network_unref
);
602 manager
->networks
= new_networks
;
607 ordered_hashmap_free_with_destructor(new_networks
, network_unref
);
612 static Network
*network_free(Network
*network
) {
613 IPv6ProxyNDPAddress
*ipv6_proxy_ndp_address
;
614 RoutePrefix
*route_prefix
;
615 RoutingPolicyRule
*rule
;
627 free(network
->filename
);
629 set_free_free(network
->match_mac
);
630 set_free_free(network
->match_permanent_mac
);
631 strv_free(network
->match_path
);
632 strv_free(network
->match_driver
);
633 strv_free(network
->match_type
);
634 strv_free(network
->match_name
);
635 strv_free(network
->match_property
);
636 strv_free(network
->match_wlan_iftype
);
637 strv_free(network
->match_ssid
);
638 set_free_free(network
->match_bssid
);
639 condition_free_list(network
->conditions
);
641 free(network
->description
);
642 free(network
->dhcp_vendor_class_identifier
);
643 free(network
->dhcp_mudurl
);
644 strv_free(network
->dhcp_user_class
);
645 free(network
->dhcp_hostname
);
646 set_free(network
->dhcp_black_listed_ip
);
647 set_free(network
->dhcp_request_options
);
649 free(network
->dhcp6_mudurl
);
651 if (network
->dhcp_acd
)
652 sd_ipv4acd_unref(network
->dhcp_acd
);
654 strv_free(network
->ntp
);
656 strv_free(network
->sip
);
657 strv_free(network
->smtp
);
658 ordered_set_free_free(network
->search_domains
);
659 ordered_set_free_free(network
->route_domains
);
660 strv_free(network
->bind_carrier
);
662 ordered_set_free_free(network
->router_search_domains
);
663 free(network
->router_dns
);
664 set_free_free(network
->ndisc_black_listed_prefix
);
666 free(network
->bridge_name
);
667 free(network
->bond_name
);
668 free(network
->vrf_name
);
669 hashmap_free_free_key(network
->stacked_netdev_names
);
670 netdev_unref(network
->bridge
);
671 netdev_unref(network
->bond
);
672 netdev_unref(network
->vrf
);
673 hashmap_free_with_destructor(network
->stacked_netdevs
, netdev_unref
);
675 while ((route
= network
->static_routes
))
678 while ((nexthop
= network
->static_nexthops
))
679 nexthop_free(nexthop
);
681 while ((address
= network
->static_addresses
))
682 address_free(address
);
684 while ((fdb_entry
= network
->static_fdb_entries
))
685 fdb_entry_free(fdb_entry
);
687 while ((ipv6_proxy_ndp_address
= network
->ipv6_proxy_ndp_addresses
))
688 ipv6_proxy_ndp_address_free(ipv6_proxy_ndp_address
);
690 while ((neighbor
= network
->neighbors
))
691 neighbor_free(neighbor
);
693 while ((label
= network
->address_labels
))
694 address_label_free(label
);
696 while ((prefix
= network
->static_prefixes
))
699 while ((route_prefix
= network
->static_route_prefixes
))
700 route_prefix_free(route_prefix
);
702 while ((rule
= network
->rules
))
703 routing_policy_rule_free(rule
);
705 hashmap_free(network
->addresses_by_section
);
706 hashmap_free(network
->routes_by_section
);
707 hashmap_free(network
->nexthops_by_section
);
708 hashmap_free(network
->fdb_entries_by_section
);
709 hashmap_free(network
->neighbors_by_section
);
710 hashmap_free(network
->address_labels_by_section
);
711 hashmap_free(network
->prefixes_by_section
);
712 hashmap_free(network
->route_prefixes_by_section
);
713 hashmap_free(network
->rules_by_section
);
714 ordered_hashmap_free_with_destructor(network
->tc_by_section
, traffic_control_free
);
716 if (network
->manager
&&
717 network
->manager
->duids_requesting_uuid
)
718 set_remove(network
->manager
->duids_requesting_uuid
, &network
->duid
);
722 free(network
->dhcp_server_timezone
);
723 free(network
->dhcp_server_dns
);
724 free(network
->dhcp_server_ntp
);
725 free(network
->dhcp_server_sip
);
727 set_free_free(network
->dnssec_negative_trust_anchors
);
729 ordered_hashmap_free(network
->dhcp_client_send_options
);
730 ordered_hashmap_free(network
->dhcp_client_send_vendor_options
);
731 ordered_hashmap_free(network
->dhcp_server_send_options
);
732 ordered_hashmap_free(network
->dhcp_server_send_vendor_options
);
733 ordered_hashmap_free(network
->ipv6_tokens
);
735 return mfree(network
);
738 DEFINE_TRIVIAL_REF_UNREF_FUNC(Network
, network
, network_free
);
740 int network_get_by_name(Manager
*manager
, const char *name
, Network
**ret
) {
747 network
= ordered_hashmap_get(manager
->networks
, name
);
756 int network_get(Manager
*manager
, unsigned short iftype
, sd_device
*device
,
757 const char *ifname
, char * const *alternative_names
,
758 const struct ether_addr
*address
, const struct ether_addr
*permanent_address
,
759 enum nl80211_iftype wlan_iftype
, const char *ssid
, const struct ether_addr
*bssid
,
767 ORDERED_HASHMAP_FOREACH(network
, manager
->networks
, i
)
768 if (net_match_config(network
->match_mac
, network
->match_permanent_mac
,
769 network
->match_path
, network
->match_driver
,
770 network
->match_type
, network
->match_name
, network
->match_property
,
771 network
->match_wlan_iftype
, network
->match_ssid
, network
->match_bssid
,
772 iftype
, device
, address
, permanent_address
,
773 ifname
, alternative_names
, wlan_iftype
, ssid
, bssid
)) {
774 if (network
->match_name
&& device
) {
776 uint8_t name_assign_type
= NET_NAME_UNKNOWN
;
778 if (sd_device_get_sysattr_value(device
, "name_assign_type", &attr
) >= 0)
779 (void) safe_atou8(attr
, &name_assign_type
);
781 if (name_assign_type
== NET_NAME_ENUM
)
782 log_warning("%s: found matching network '%s', based on potentially unpredictable ifname",
783 ifname
, network
->filename
);
785 log_debug("%s: found matching network '%s'", ifname
, network
->filename
);
787 log_debug("%s: found matching network '%s'", ifname
, network
->filename
);
798 int network_apply(Network
*network
, Link
*link
) {
802 link
->network
= network_ref(network
);
804 if (network
->n_dns
> 0 ||
805 !strv_isempty(network
->ntp
) ||
806 !ordered_set_isempty(network
->search_domains
) ||
807 !ordered_set_isempty(network
->route_domains
))
813 bool network_has_static_ipv6_configurations(Network
*network
) {
821 LIST_FOREACH(addresses
, address
, network
->static_addresses
)
822 if (address
->family
== AF_INET6
)
825 LIST_FOREACH(routes
, route
, network
->static_routes
)
826 if (route
->family
== AF_INET6
)
829 LIST_FOREACH(static_fdb_entries
, fdb
, network
->static_fdb_entries
)
830 if (fdb
->family
== AF_INET6
)
833 LIST_FOREACH(neighbors
, neighbor
, network
->neighbors
)
834 if (neighbor
->family
== AF_INET6
)
837 if (!LIST_IS_EMPTY(network
->address_labels
))
840 if (!LIST_IS_EMPTY(network
->static_prefixes
))
846 int config_parse_stacked_netdev(const char *unit
,
847 const char *filename
,
850 unsigned section_line
,
856 _cleanup_free_
char *name
= NULL
;
857 NetDevKind kind
= ltype
;
866 NETDEV_KIND_VLAN
, NETDEV_KIND_MACVLAN
, NETDEV_KIND_MACVTAP
,
867 NETDEV_KIND_IPVLAN
, NETDEV_KIND_IPVTAP
, NETDEV_KIND_VXLAN
,
868 NETDEV_KIND_L2TP
, NETDEV_KIND_MACSEC
, _NETDEV_KIND_TUNNEL
,
871 if (!ifname_valid(rvalue
)) {
872 log_syntax(unit
, LOG_ERR
, filename
, line
, 0,
873 "Invalid netdev name in %s=, ignoring assignment: %s", lvalue
, rvalue
);
877 name
= strdup(rvalue
);
881 r
= hashmap_ensure_allocated(h
, &string_hash_ops
);
885 r
= hashmap_put(*h
, name
, INT_TO_PTR(kind
));
887 log_syntax(unit
, LOG_ERR
, filename
, line
, r
,
888 "Cannot add NetDev '%s' to network, ignoring assignment: %m", name
);
890 log_syntax(unit
, LOG_DEBUG
, filename
, line
, r
,
891 "NetDev '%s' specified twice, ignoring.", name
);
898 int config_parse_domains(
900 const char *filename
,
903 unsigned section_line
,
918 if (isempty(rvalue
)) {
919 n
->search_domains
= ordered_set_free_free(n
->search_domains
);
920 n
->route_domains
= ordered_set_free_free(n
->route_domains
);
926 _cleanup_free_
char *w
= NULL
, *normalized
= NULL
;
930 r
= extract_first_word(&p
, &w
, NULL
, 0);
932 log_syntax(unit
, LOG_ERR
, filename
, line
, r
,
933 "Failed to extract search or route domain, ignoring: %s", rvalue
);
939 is_route
= w
[0] == '~';
940 domain
= is_route
? w
+ 1 : w
;
942 if (dns_name_is_root(domain
) || streq(domain
, "*")) {
943 /* If the root domain appears as is, or the special token "*" is found, we'll
944 * consider this as routing domain, unconditionally. */
946 domain
= "."; /* make sure we don't allow empty strings, thus write the root
949 r
= dns_name_normalize(domain
, 0, &normalized
);
951 log_syntax(unit
, LOG_ERR
, filename
, line
, r
,
952 "'%s' is not a valid domain name, ignoring.", domain
);
958 if (is_localhost(domain
)) {
959 log_syntax(unit
, LOG_ERR
, filename
, line
, 0,
960 "'localhost' domain may not be configured as search or route domain, ignoring assignment: %s",
966 OrderedSet
**set
= is_route
? &n
->route_domains
: &n
->search_domains
;
967 r
= ordered_set_ensure_allocated(set
, &string_hash_ops
);
971 r
= ordered_set_put_strdup(*set
, domain
);
979 int config_parse_ipv6token(
981 const char *filename
,
984 unsigned section_line
,
991 union in_addr_union buffer
;
992 struct in6_addr
*token
= data
;
1000 r
= in_addr_from_string(AF_INET6
, rvalue
, &buffer
);
1002 log_syntax(unit
, LOG_ERR
, filename
, line
, r
,
1003 "Failed to parse IPv6 token, ignoring: %s", rvalue
);
1007 if (in_addr_is_null(AF_INET6
, &buffer
)) {
1008 log_syntax(unit
, LOG_ERR
, filename
, line
, 0,
1009 "IPv6 token cannot be the ANY address, ignoring: %s", rvalue
);
1013 if ((buffer
.in6
.s6_addr32
[0] | buffer
.in6
.s6_addr32
[1]) != 0) {
1014 log_syntax(unit
, LOG_ERR
, filename
, line
, 0,
1015 "IPv6 token cannot be longer than 64 bits, ignoring: %s", rvalue
);
1019 *token
= buffer
.in6
;
1024 static const char* const ipv6_privacy_extensions_table
[_IPV6_PRIVACY_EXTENSIONS_MAX
] = {
1025 [IPV6_PRIVACY_EXTENSIONS_NO
] = "no",
1026 [IPV6_PRIVACY_EXTENSIONS_PREFER_PUBLIC
] = "prefer-public",
1027 [IPV6_PRIVACY_EXTENSIONS_YES
] = "yes",
1030 DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(ipv6_privacy_extensions
, IPv6PrivacyExtensions
,
1031 IPV6_PRIVACY_EXTENSIONS_YES
);
1033 int config_parse_ipv6_privacy_extensions(
1035 const char *filename
,
1037 const char *section
,
1038 unsigned section_line
,
1045 IPv6PrivacyExtensions s
, *ipv6_privacy_extensions
= data
;
1050 assert(ipv6_privacy_extensions
);
1052 s
= ipv6_privacy_extensions_from_string(rvalue
);
1054 if (streq(rvalue
, "kernel"))
1055 s
= _IPV6_PRIVACY_EXTENSIONS_INVALID
;
1057 log_syntax(unit
, LOG_ERR
, filename
, line
, 0,
1058 "Failed to parse IPv6 privacy extensions option, ignoring: %s", rvalue
);
1063 *ipv6_privacy_extensions
= s
;
1068 int config_parse_hostname(
1070 const char *filename
,
1072 const char *section
,
1073 unsigned section_line
,
1080 _cleanup_free_
char *hn
= NULL
;
1081 char **hostname
= data
;
1088 r
= config_parse_string(unit
, filename
, line
, section
, section_line
, lvalue
, ltype
, rvalue
, &hn
, userdata
);
1092 if (!hostname_is_valid(hn
, false)) {
1093 log_syntax(unit
, LOG_ERR
, filename
, line
, 0,
1094 "Hostname is not valid, ignoring assignment: %s", rvalue
);
1098 r
= dns_name_is_valid(hn
);
1100 log_syntax(unit
, LOG_ERR
, filename
, line
, r
,
1101 "Failed to check validity of hostname '%s', ignoring assignment: %m", rvalue
);
1105 log_syntax(unit
, LOG_ERR
, filename
, line
, 0,
1106 "Hostname is not a valid DNS domain name, ignoring assignment: %s", rvalue
);
1110 return free_and_replace(*hostname
, hn
);
1113 int config_parse_timezone(
1115 const char *filename
,
1117 const char *section
,
1118 unsigned section_line
,
1125 _cleanup_free_
char *tz
= NULL
;
1126 char **datap
= data
;
1133 r
= config_parse_string(unit
, filename
, line
, section
, section_line
, lvalue
, ltype
, rvalue
, &tz
, userdata
);
1137 if (!timezone_is_valid(tz
, LOG_ERR
)) {
1138 log_syntax(unit
, LOG_ERR
, filename
, line
, 0,
1139 "Timezone is not valid, ignoring assignment: %s", rvalue
);
1143 return free_and_replace(*datap
, tz
);
1146 int config_parse_dns(
1148 const char *filename
,
1150 const char *section
,
1151 unsigned section_line
,
1158 Network
*n
= userdata
;
1166 _cleanup_free_
char *w
= NULL
;
1167 union in_addr_union a
;
1168 struct in_addr_data
*m
;
1171 r
= extract_first_word(&rvalue
, &w
, NULL
, 0);
1175 log_syntax(unit
, LOG_ERR
, filename
, line
, r
,
1176 "Invalid syntax, ignoring: %s", rvalue
);
1182 r
= in_addr_from_string_auto(w
, &family
, &a
);
1184 log_syntax(unit
, LOG_ERR
, filename
, line
, r
,
1185 "Failed to parse dns server address, ignoring: %s", w
);
1189 m
= reallocarray(n
->dns
, n
->n_dns
+ 1, sizeof(struct in_addr_data
));
1193 m
[n
->n_dns
++] = (struct in_addr_data
) {
1204 int config_parse_dnssec_negative_trust_anchors(
1206 const char *filename
,
1208 const char *section
,
1209 unsigned section_line
,
1216 const char *p
= rvalue
;
1224 if (isempty(rvalue
)) {
1225 n
->dnssec_negative_trust_anchors
= set_free_free(n
->dnssec_negative_trust_anchors
);
1230 _cleanup_free_
char *w
= NULL
;
1232 r
= extract_first_word(&p
, &w
, NULL
, 0);
1234 log_syntax(unit
, LOG_ERR
, filename
, line
, r
,
1235 "Failed to extract negative trust anchor domain, ignoring: %s", rvalue
);
1241 r
= dns_name_is_valid(w
);
1243 log_syntax(unit
, LOG_ERR
, filename
, line
, r
,
1244 "%s is not a valid domain name, ignoring.", w
);
1248 r
= set_ensure_allocated(&n
->dnssec_negative_trust_anchors
, &dns_name_hash_ops
);
1252 r
= set_put(n
->dnssec_negative_trust_anchors
, w
);
1262 int config_parse_ntp(
1264 const char *filename
,
1266 const char *section
,
1267 unsigned section_line
,
1281 if (isempty(rvalue
)) {
1287 _cleanup_free_
char *w
= NULL
;
1289 r
= extract_first_word(&rvalue
, &w
, NULL
, 0);
1293 log_syntax(unit
, LOG_ERR
, filename
, line
, r
,
1294 "Failed to extract NTP server name, ignoring: %s", rvalue
);
1300 r
= dns_name_is_valid_or_address(w
);
1302 log_syntax(unit
, LOG_ERR
, filename
, line
, r
,
1303 "%s is not a valid domain name or IP address, ignoring.", w
);
1307 if (strv_length(*l
) > MAX_NTP_SERVERS
) {
1308 log_syntax(unit
, LOG_WARNING
, filename
, line
, 0,
1309 "More than %u NTP servers specified, ignoring \"%s\" and any subsequent entries.",
1310 MAX_NTP_SERVERS
, w
);
1314 r
= strv_consume(l
, TAKE_PTR(w
));
1322 int config_parse_required_for_online(
1324 const char *filename
,
1326 const char *section
,
1327 unsigned section_line
,
1334 Network
*network
= data
;
1335 LinkOperationalStateRange range
;
1336 bool required
= true;
1339 if (isempty(rvalue
)) {
1340 network
->required_for_online
= true;
1341 network
->required_operstate_for_online
= LINK_OPERSTATE_RANGE_DEFAULT
;
1345 r
= parse_operational_state_range(rvalue
, &range
);
1347 r
= parse_boolean(rvalue
);
1349 log_syntax(unit
, LOG_ERR
, filename
, line
, r
,
1350 "Failed to parse %s= setting, ignoring assignment: %s",
1356 range
= LINK_OPERSTATE_RANGE_DEFAULT
;
1359 network
->required_for_online
= required
;
1360 network
->required_operstate_for_online
= range
;
1365 DEFINE_CONFIG_PARSE_ENUM(config_parse_keep_configuration
, keep_configuration
, KeepConfiguration
,
1366 "Failed to parse KeepConfiguration= setting");
1368 static const char* const keep_configuration_table
[_KEEP_CONFIGURATION_MAX
] = {
1369 [KEEP_CONFIGURATION_NO
] = "no",
1370 [KEEP_CONFIGURATION_DHCP_ON_STOP
] = "dhcp-on-stop",
1371 [KEEP_CONFIGURATION_DHCP
] = "dhcp",
1372 [KEEP_CONFIGURATION_STATIC
] = "static",
1373 [KEEP_CONFIGURATION_YES
] = "yes",
1376 DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(keep_configuration
, KeepConfiguration
, KEEP_CONFIGURATION_YES
);