]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/network/networkd-network.c
Merge pull request #18990 from yuwata/network-dhcpv6-use-domains
[thirdparty/systemd.git] / src / network / networkd-network.c
1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
2
3 #include <net/if.h>
4 #include <netinet/in.h>
5 #include <linux/netdevice.h>
6 #include <unistd.h>
7
8 #include "alloc-util.h"
9 #include "conf-files.h"
10 #include "conf-parser.h"
11 #include "dns-domain.h"
12 #include "fd-util.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"
32 #include "set.h"
33 #include "socket-util.h"
34 #include "stat-util.h"
35 #include "string-table.h"
36 #include "string-util.h"
37 #include "strv.h"
38 #include "tc.h"
39 #include "util.h"
40
41 /* Let's assume that anything above this number is a user misconfiguration. */
42 #define MAX_NTP_SERVERS 128
43
44 /* Set defaults following RFC7844 */
45 void network_apply_anonymize_if_set(Network *network) {
46 if (!network->dhcp_anonymize)
47 return;
48 /* RFC7844 3.7
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
53 Section 3.5:
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;
59 /* RFC 7844 3.10:
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).
68 */
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;
81 }
82
83 static int network_resolve_netdev_one(Network *network, const char *name, NetDevKind kind, NetDev **ret_netdev) {
84 const char *kind_string;
85 NetDev *netdev;
86 int r;
87
88 /* For test-networkd-conf, the check must be earlier than the assertions. */
89 if (!name)
90 return 0;
91
92 assert(network);
93 assert(network->manager);
94 assert(network->filename);
95 assert(ret_netdev);
96
97 if (kind == _NETDEV_KIND_TUNNEL)
98 kind_string = "tunnel";
99 else {
100 kind_string = netdev_kind_to_string(kind);
101 if (!kind_string)
102 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
103 "%s: Invalid NetDev kind of %s, ignoring assignment.",
104 network->filename, name);
105 }
106
107 r = netdev_get(network->manager, name, &netdev);
108 if (r < 0)
109 return log_error_errno(r, "%s: %s NetDev could not be found, ignoring assignment.",
110 network->filename, name);
111
112 if (netdev->kind != kind && !(kind == _NETDEV_KIND_TUNNEL &&
113 IN_SET(netdev->kind,
114 NETDEV_KIND_IPIP,
115 NETDEV_KIND_SIT,
116 NETDEV_KIND_GRE,
117 NETDEV_KIND_GRETAP,
118 NETDEV_KIND_IP6GRE,
119 NETDEV_KIND_IP6GRETAP,
120 NETDEV_KIND_VTI,
121 NETDEV_KIND_VTI6,
122 NETDEV_KIND_IP6TNL,
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);
127
128 *ret_netdev = netdev_ref(netdev);
129 return 1;
130 }
131
132 static int network_resolve_stacked_netdevs(Network *network) {
133 void *name, *kind;
134 int r;
135
136 assert(network);
137
138 HASHMAP_FOREACH_KEY(kind, name, network->stacked_netdev_names) {
139 _cleanup_(netdev_unrefp) NetDev *netdev = NULL;
140
141 r = network_resolve_netdev_one(network, name, PTR_TO_INT(kind), &netdev);
142 if (r <= 0)
143 continue;
144
145 r = hashmap_ensure_put(&network->stacked_netdevs, &string_hash_ops, netdev->ifname, netdev);
146 if (r == -ENOMEM)
147 return log_oom();
148 if (r < 0)
149 return log_error_errno(r, "%s: Failed to add NetDev '%s' to network: %m",
150 network->filename, (const char *) name);
151
152 netdev = NULL;
153 }
154
155 return 0;
156 }
157
158 int network_verify(Network *network) {
159 assert(network);
160 assert(network->filename);
161
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.",
166 network->filename);
167
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.",
172 network->filename);
173
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);
179
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);
186
187 if (network->bond) {
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=.",
191 network->filename);
192 network->link_local = ADDRESS_FAMILY_NO;
193 }
194 if (network->dhcp_server) {
195 log_warning("%s: Cannot enable DHCPServer= when Bond= is specified, disabling DHCPServer=.",
196 network->filename);
197 network->dhcp_server = false;
198 }
199 if (!ordered_hashmap_isempty(network->addresses_by_section))
200 log_warning("%s: Cannot set addresses when Bond= is specified, ignoring addresses.",
201 network->filename);
202 if (!hashmap_isempty(network->routes_by_section))
203 log_warning("%s: Cannot set routes when Bond= is specified, ignoring routes.",
204 network->filename);
205
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);
208 }
209
210 if (network->link_local < 0)
211 network->link_local = network->bridge ? ADDRESS_FAMILY_NO : ADDRESS_FAMILY_IPV6;
212
213 /* IPMasquerade implies IPForward */
214 network->ip_forward |= network->ip_masquerade;
215
216 network_adjust_ipv6_accept_ra(network);
217 network_adjust_dhcp(network);
218 network_adjust_radv(network);
219
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;
224 }
225
226 if (network->dhcp_use_gateway < 0)
227 network->dhcp_use_gateway = network->dhcp_use_routes;
228
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;
236 else
237 network->keep_configuration = KEEP_CONFIGURATION_NO;
238 }
239
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;
249 }
250
251 if (network->activation_policy == _ACTIVATION_POLICY_INVALID)
252 network->activation_policy = ACTIVATION_POLICY_UP;
253
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;
259 }
260
261 if (network->ignore_carrier_loss < 0)
262 network->ignore_carrier_loss = network->configure_without_carrier;
263
264 if (network->keep_configuration < 0)
265 network->keep_configuration = KEEP_CONFIGURATION_NO;
266
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);
270 }
271
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);
284
285 return 0;
286 }
287
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;
292 char *d;
293 int r;
294
295 assert(manager);
296 assert(filename);
297
298 r = null_or_empty_path(filename);
299 if (r == -ENOENT)
300 return 0;
301 if (r < 0)
302 return r;
303 if (r > 0) {
304 log_debug("Skipping empty file: %s", filename);
305 return 0;
306 }
307
308 fname = strdup(filename);
309 if (!fname)
310 return log_oom();
311
312 name = strdup(basename(filename));
313 if (!name)
314 return log_oom();
315
316 d = strrchr(name, '.');
317 if (!d)
318 return -EINVAL;
319
320 *d = '\0';
321
322 dropin_dirname = strjoina(name, ".network.d");
323
324 network = new(Network, 1);
325 if (!network)
326 return log_oom();
327
328 *network = (Network) {
329 .filename = TAKE_PTR(fname),
330 .name = TAKE_PTR(name),
331
332 .manager = manager,
333 .n_ref = 1,
334
335 .required_for_online = true,
336 .required_operstate_for_online = LINK_OPERSTATE_RANGE_DEFAULT,
337 .activation_policy = _ACTIVATION_POLICY_INVALID,
338 .arp = -1,
339 .multicast = -1,
340 .allmulticast = -1,
341 .promiscuous = -1,
342
343 .configure_without_carrier = false,
344 .ignore_carrier_loss = -1,
345 .keep_configuration = _KEEP_CONFIGURATION_INVALID,
346
347 .dhcp = ADDRESS_FAMILY_NO,
348 .duid.type = _DUID_TYPE_INVALID,
349 .dhcp_critical = -1,
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,
371
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,
378
379 .dhcp6_pd = -1,
380 .dhcp6_pd_announce = true,
381 .dhcp6_pd_assign = true,
382 .dhcp6_pd_manage_temporary_address = true,
383 .dhcp6_pd_subnet_id = -1,
384
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,
388
389 .dhcp_server_emit_router = true,
390 .dhcp_server_emit_timezone = true,
391
392 .router_lifetime_usec = 30 * USEC_PER_MINUTE,
393 .router_emit_dns = true,
394 .router_emit_domains = true,
395
396 .use_bpdu = -1,
397 .hairpin = -1,
398 .fast_leave = -1,
399 .allow_port_to_be_root = -1,
400 .unicast_flood = -1,
401 .multicast_flood = -1,
402 .multicast_to_unicast = -1,
403 .neighbor_suppression = -1,
404 .learning = -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,
409
410 .lldp_mode = LLDP_MODE_ROUTERS_ONLY,
411
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,
417
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,
421
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,
429 .proxy_arp = -1,
430
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,
437
438 .can_triple_sampling = -1,
439 .can_berr_reporting = -1,
440 .can_termination = -1,
441 .can_listen_only = -1,
442 .can_fd_mode = -1,
443 .can_non_iso = -1,
444 };
445
446 r = config_parse_many(
447 STRV_MAKE_CONST(filename), NETWORK_DIRS, dropin_dirname,
448 "Match\0"
449 "Link\0"
450 "SR-IOV\0"
451 "Network\0"
452 "Address\0"
453 "Neighbor\0"
454 "IPv6AddressLabel\0"
455 "RoutingPolicyRule\0"
456 "Route\0"
457 "NextHop\0"
458 "DHCP\0" /* compat */
459 "DHCPv4\0"
460 "DHCPv6\0"
461 "DHCPv6PrefixDelegation\0"
462 "DHCPServer\0"
463 "IPv6AcceptRA\0"
464 "IPv6NDPProxyAddress\0"
465 "Bridge\0"
466 "BridgeFDB\0"
467 "BridgeMDB\0"
468 "BridgeVLAN\0"
469 "IPv6SendRA\0"
470 "IPv6PrefixDelegation\0"
471 "IPv6Prefix\0"
472 "IPv6RoutePrefix\0"
473 "LLDP\0"
474 "TrafficControlQueueingDiscipline\0"
475 "CAN\0"
476 "QDisc\0"
477 "BFIFO\0"
478 "CAKE\0"
479 "ControlledDelay\0"
480 "DeficitRoundRobinScheduler\0"
481 "DeficitRoundRobinSchedulerClass\0"
482 "EnhancedTransmissionSelection\0"
483 "FairQueueing\0"
484 "FairQueueingControlledDelay\0"
485 "FlowQueuePIE\0"
486 "GenericRandomEarlyDetection\0"
487 "HeavyHitterFilter\0"
488 "HierarchyTokenBucket\0"
489 "HierarchyTokenBucketClass\0"
490 "NetworkEmulator\0"
491 "PFIFO\0"
492 "PFIFOFast\0"
493 "PFIFOHeadDrop\0"
494 "PIE\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,
502 CONFIG_PARSE_WARN,
503 network,
504 &network->timestamp);
505 if (r < 0)
506 return r;
507
508 network_apply_anonymize_if_set(network);
509
510 r = network_add_ipv4ll_route(network);
511 if (r < 0)
512 log_warning_errno(r, "%s: Failed to add IPv4LL route, ignoring: %m", network->filename);
513
514 r = network_add_default_route_on_device(network);
515 if (r < 0)
516 log_warning_errno(r, "%s: Failed to add default route on device, ignoring: %m",
517 network->filename);
518
519 if (network_verify(network) < 0)
520 /* Ignore .network files that do not match the conditions. */
521 return 0;
522
523 r = ordered_hashmap_ensure_put(networks, &string_hash_ops, network->name, network);
524 if (r < 0)
525 return r;
526
527 TAKE_PTR(network);
528 return 0;
529 }
530
531 int network_load(Manager *manager, OrderedHashmap **networks) {
532 _cleanup_strv_free_ char **files = NULL;
533 char **f;
534 int r;
535
536 assert(manager);
537
538 ordered_hashmap_clear_with_destructor(*networks, network_unref);
539
540 r = conf_files_list_strv(&files, ".network", NULL, 0, NETWORK_DIRS);
541 if (r < 0)
542 return log_error_errno(r, "Failed to enumerate network files: %m");
543
544 STRV_FOREACH(f, files) {
545 r = network_load_one(manager, networks, *f);
546 if (r < 0)
547 log_error_errno(r, "Failed to load %s, ignoring: %m", *f);
548 }
549
550 return 0;
551 }
552
553 int network_reload(Manager *manager) {
554 OrderedHashmap *new_networks = NULL;
555 Network *n, *old;
556 int r;
557
558 assert(manager);
559
560 r = network_load(manager, &new_networks);
561 if (r < 0)
562 goto failure;
563
564 ORDERED_HASHMAP_FOREACH(n, new_networks) {
565 r = network_get_by_name(manager, n->name, &old);
566 if (r < 0)
567 continue; /* The .network file is new. */
568
569 if (n->timestamp != old->timestamp)
570 continue; /* The .network file is modified. */
571
572 if (!streq(n->filename, old->filename))
573 continue;
574
575 r = ordered_hashmap_replace(new_networks, old->name, old);
576 if (r < 0)
577 goto failure;
578
579 network_ref(old);
580 network_unref(n);
581 }
582
583 ordered_hashmap_free_with_destructor(manager->networks, network_unref);
584 manager->networks = new_networks;
585
586 return 0;
587
588 failure:
589 ordered_hashmap_free_with_destructor(new_networks, network_unref);
590
591 return r;
592 }
593
594 static Network *network_free(Network *network) {
595 if (!network)
596 return NULL;
597
598 free(network->filename);
599
600 net_match_clear(&network->match);
601 condition_free_list(network->conditions);
602
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);
612 free(network->mac);
613 free(network->dhcp6_mudurl);
614 strv_free(network->dhcp6_user_class);
615 strv_free(network->dhcp6_vendor_class);
616
617 strv_free(network->ntp);
618 for (unsigned i = 0; i < network->n_dns; i++)
619 in_addr_full_free(network->dns[i]);
620 free(network->dns);
621 ordered_set_free(network->search_domains);
622 ordered_set_free(network->route_domains);
623 strv_free(network->bind_carrier);
624
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);
633
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);
643
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);
657
658 if (network->manager &&
659 network->manager->duids_requesting_uuid)
660 set_remove(network->manager->duids_requesting_uuid, &network->duid);
661
662 free(network->name);
663
664 free(network->dhcp_server_timezone);
665
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);
668
669 set_free_free(network->dnssec_negative_trust_anchors);
670
671 free(network->lldp_mud);
672
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);
680
681 return mfree(network);
682 }
683
684 DEFINE_TRIVIAL_REF_UNREF_FUNC(Network, network, network_free);
685
686 int network_get_by_name(Manager *manager, const char *name, Network **ret) {
687 Network *network;
688
689 assert(manager);
690 assert(name);
691 assert(ret);
692
693 network = ordered_hashmap_get(manager->networks, name);
694 if (!network)
695 return -ENOENT;
696
697 *ret = network;
698
699 return 0;
700 }
701
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,
706 Network **ret) {
707 Network *network;
708
709 assert(manager);
710 assert(ret);
711
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) {
716 const char *attr;
717 uint8_t name_assign_type = NET_NAME_UNKNOWN;
718
719 if (sd_device_get_sysattr_value(device, "name_assign_type", &attr) >= 0)
720 (void) safe_atou8(attr, &name_assign_type);
721
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);
725 else
726 log_debug("%s: found matching network '%s'", ifname, network->filename);
727 } else
728 log_debug("%s: found matching network '%s'", ifname, network->filename);
729
730 *ret = network;
731 return 0;
732 }
733
734 *ret = NULL;
735
736 return -ENOENT;
737 }
738
739 bool network_has_static_ipv6_configurations(Network *network) {
740 Address *address;
741 Route *route;
742 FdbEntry *fdb;
743 MdbEntry *mdb;
744 Neighbor *neighbor;
745
746 assert(network);
747
748 ORDERED_HASHMAP_FOREACH(address, network->addresses_by_section)
749 if (address->family == AF_INET6)
750 return true;
751
752 HASHMAP_FOREACH(route, network->routes_by_section)
753 if (route->family == AF_INET6)
754 return true;
755
756 HASHMAP_FOREACH(fdb, network->fdb_entries_by_section)
757 if (fdb->family == AF_INET6)
758 return true;
759
760 HASHMAP_FOREACH(mdb, network->mdb_entries_by_section)
761 if (mdb->family == AF_INET6)
762 return true;
763
764 HASHMAP_FOREACH(neighbor, network->neighbors_by_section)
765 if (neighbor->family == AF_INET6)
766 return true;
767
768 if (!hashmap_isempty(network->address_labels_by_section))
769 return true;
770
771 if (!hashmap_isempty(network->prefixes_by_section))
772 return true;
773
774 if (!hashmap_isempty(network->route_prefixes_by_section))
775 return true;
776
777 return false;
778 }
779
780 int config_parse_stacked_netdev(const char *unit,
781 const char *filename,
782 unsigned line,
783 const char *section,
784 unsigned section_line,
785 const char *lvalue,
786 int ltype,
787 const char *rvalue,
788 void *data,
789 void *userdata) {
790 _cleanup_free_ char *name = NULL;
791 NetDevKind kind = ltype;
792 Hashmap **h = data;
793 int r;
794
795 assert(filename);
796 assert(lvalue);
797 assert(rvalue);
798 assert(data);
799 assert(IN_SET(kind,
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,
803 NETDEV_KIND_XFRM));
804
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);
808 return 0;
809 }
810
811 name = strdup(rvalue);
812 if (!name)
813 return log_oom();
814
815 r = hashmap_ensure_put(h, &string_hash_ops, name, INT_TO_PTR(kind));
816 if (r == -ENOMEM)
817 return log_oom();
818 if (r < 0)
819 log_syntax(unit, LOG_WARNING, filename, line, r,
820 "Cannot add NetDev '%s' to network, ignoring assignment: %m", name);
821 else if (r == 0)
822 log_syntax(unit, LOG_DEBUG, filename, line, r,
823 "NetDev '%s' specified twice, ignoring.", name);
824 else
825 TAKE_PTR(name);
826
827 return 0;
828 }
829
830 int config_parse_domains(
831 const char *unit,
832 const char *filename,
833 unsigned line,
834 const char *section,
835 unsigned section_line,
836 const char *lvalue,
837 int ltype,
838 const char *rvalue,
839 void *data,
840 void *userdata) {
841
842 Network *n = data;
843 int r;
844
845 assert(n);
846 assert(lvalue);
847 assert(rvalue);
848
849 if (isempty(rvalue)) {
850 n->search_domains = ordered_set_free(n->search_domains);
851 n->route_domains = ordered_set_free(n->route_domains);
852 return 0;
853 }
854
855 for (const char *p = rvalue;;) {
856 _cleanup_free_ char *w = NULL, *normalized = NULL;
857 const char *domain;
858 bool is_route;
859
860 r = extract_first_word(&p, &w, NULL, 0);
861 if (r == -ENOMEM)
862 return log_oom();
863 if (r < 0) {
864 log_syntax(unit, LOG_WARNING, filename, line, r,
865 "Failed to extract search or route domain, ignoring: %s", rvalue);
866 return 0;
867 }
868 if (r == 0)
869 return 0;
870
871 is_route = w[0] == '~';
872 domain = is_route ? w + 1 : w;
873
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. */
877 is_route = true;
878 domain = "."; /* make sure we don't allow empty strings, thus write the root
879 * domain as "." */
880 } else {
881 r = dns_name_normalize(domain, 0, &normalized);
882 if (r < 0) {
883 log_syntax(unit, LOG_WARNING, filename, line, r,
884 "'%s' is not a valid domain name, ignoring.", domain);
885 continue;
886 }
887
888 domain = normalized;
889
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",
893 domain);
894 continue;
895 }
896 }
897
898 OrderedSet **set = is_route ? &n->route_domains : &n->search_domains;
899 r = ordered_set_put_strdup(set, domain);
900 if (r == -EEXIST)
901 continue;
902 if (r < 0)
903 return log_oom();
904 }
905 }
906
907 int config_parse_hostname(
908 const char *unit,
909 const char *filename,
910 unsigned line,
911 const char *section,
912 unsigned section_line,
913 const char *lvalue,
914 int ltype,
915 const char *rvalue,
916 void *data,
917 void *userdata) {
918
919 _cleanup_free_ char *hn = NULL;
920 char **hostname = data;
921 int r;
922
923 assert(filename);
924 assert(lvalue);
925 assert(rvalue);
926
927 r = config_parse_string(unit, filename, line, section, section_line, lvalue, ltype, rvalue, &hn, userdata);
928 if (r < 0)
929 return r;
930
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);
934 return 0;
935 }
936
937 r = dns_name_is_valid(hn);
938 if (r < 0) {
939 log_syntax(unit, LOG_WARNING, filename, line, r,
940 "Failed to check validity of hostname '%s', ignoring assignment: %m", rvalue);
941 return 0;
942 }
943 if (r == 0) {
944 log_syntax(unit, LOG_WARNING, filename, line, 0,
945 "Hostname is not a valid DNS domain name, ignoring assignment: %s", rvalue);
946 return 0;
947 }
948
949 return free_and_replace(*hostname, hn);
950 }
951
952 int config_parse_timezone(
953 const char *unit,
954 const char *filename,
955 unsigned line,
956 const char *section,
957 unsigned section_line,
958 const char *lvalue,
959 int ltype,
960 const char *rvalue,
961 void *data,
962 void *userdata) {
963
964 _cleanup_free_ char *tz = NULL;
965 char **datap = data;
966 int r;
967
968 assert(filename);
969 assert(lvalue);
970 assert(rvalue);
971
972 r = config_parse_string(unit, filename, line, section, section_line, lvalue, ltype, rvalue, &tz, userdata);
973 if (r < 0)
974 return r;
975
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);
979 return 0;
980 }
981
982 return free_and_replace(*datap, tz);
983 }
984
985 int config_parse_dns(
986 const char *unit,
987 const char *filename,
988 unsigned line,
989 const char *section,
990 unsigned section_line,
991 const char *lvalue,
992 int ltype,
993 const char *rvalue,
994 void *data,
995 void *userdata) {
996
997 Network *n = userdata;
998 int r;
999
1000 assert(filename);
1001 assert(lvalue);
1002 assert(rvalue);
1003
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);
1008 n->n_dns = 0;
1009 return 0;
1010 }
1011
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;
1016
1017 r = extract_first_word(&p, &w, NULL, 0);
1018 if (r == -ENOMEM)
1019 return log_oom();
1020 if (r < 0) {
1021 log_syntax(unit, LOG_WARNING, filename, line, r,
1022 "Invalid syntax, ignoring: %s", rvalue);
1023 return 0;
1024 }
1025 if (r == 0)
1026 return 0;
1027
1028 r = in_addr_full_new_from_string(w, &dns);
1029 if (r < 0) {
1030 log_syntax(unit, LOG_WARNING, filename, line, r,
1031 "Failed to parse dns server address, ignoring: %s", w);
1032 continue;
1033 }
1034
1035 if (IN_SET(dns->port, 53, 853))
1036 dns->port = 0;
1037
1038 m = reallocarray(n->dns, n->n_dns + 1, sizeof(struct in_addr_full*));
1039 if (!m)
1040 return log_oom();
1041
1042 m[n->n_dns++] = TAKE_PTR(dns);
1043 n->dns = m;
1044 }
1045 }
1046
1047 int config_parse_dnssec_negative_trust_anchors(
1048 const char *unit,
1049 const char *filename,
1050 unsigned line,
1051 const char *section,
1052 unsigned section_line,
1053 const char *lvalue,
1054 int ltype,
1055 const char *rvalue,
1056 void *data,
1057 void *userdata) {
1058
1059 Network *n = data;
1060 int r;
1061
1062 assert(n);
1063 assert(lvalue);
1064 assert(rvalue);
1065
1066 if (isempty(rvalue)) {
1067 n->dnssec_negative_trust_anchors = set_free_free(n->dnssec_negative_trust_anchors);
1068 return 0;
1069 }
1070
1071 for (const char *p = rvalue;;) {
1072 _cleanup_free_ char *w = NULL;
1073
1074 r = extract_first_word(&p, &w, NULL, 0);
1075 if (r == -ENOMEM)
1076 return log_oom();
1077 if (r < 0) {
1078 log_syntax(unit, LOG_WARNING, filename, line, r,
1079 "Failed to extract negative trust anchor domain, ignoring: %s", rvalue);
1080 return 0;
1081 }
1082 if (r == 0)
1083 return 0;
1084
1085 r = dns_name_is_valid(w);
1086 if (r <= 0) {
1087 log_syntax(unit, LOG_WARNING, filename, line, r,
1088 "%s is not a valid domain name, ignoring.", w);
1089 continue;
1090 }
1091
1092 r = set_ensure_consume(&n->dnssec_negative_trust_anchors, &dns_name_hash_ops, TAKE_PTR(w));
1093 if (r < 0)
1094 return log_oom();
1095 }
1096 }
1097
1098 int config_parse_ntp(
1099 const char *unit,
1100 const char *filename,
1101 unsigned line,
1102 const char *section,
1103 unsigned section_line,
1104 const char *lvalue,
1105 int ltype,
1106 const char *rvalue,
1107 void *data,
1108 void *userdata) {
1109
1110 char ***l = data;
1111 int r;
1112
1113 assert(l);
1114 assert(lvalue);
1115 assert(rvalue);
1116
1117 if (isempty(rvalue)) {
1118 *l = strv_free(*l);
1119 return 0;
1120 }
1121
1122 for (const char *p = rvalue;;) {
1123 _cleanup_free_ char *w = NULL;
1124
1125 r = extract_first_word(&p, &w, NULL, 0);
1126 if (r == -ENOMEM)
1127 return log_oom();
1128 if (r < 0) {
1129 log_syntax(unit, LOG_WARNING, filename, line, r,
1130 "Failed to extract NTP server name, ignoring: %s", rvalue);
1131 return 0;
1132 }
1133 if (r == 0)
1134 return 0;
1135
1136 r = dns_name_is_valid_or_address(w);
1137 if (r <= 0) {
1138 log_syntax(unit, LOG_WARNING, filename, line, r,
1139 "%s is not a valid domain name or IP address, ignoring.", w);
1140 continue;
1141 }
1142
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);
1147 return 0;
1148 }
1149
1150 r = strv_consume(l, TAKE_PTR(w));
1151 if (r < 0)
1152 return log_oom();
1153 }
1154 }
1155
1156 int config_parse_required_for_online(
1157 const char *unit,
1158 const char *filename,
1159 unsigned line,
1160 const char *section,
1161 unsigned section_line,
1162 const char *lvalue,
1163 int ltype,
1164 const char *rvalue,
1165 void *data,
1166 void *userdata) {
1167
1168 Network *network = data;
1169 LinkOperationalStateRange range;
1170 bool required = true;
1171 int r;
1172
1173 if (isempty(rvalue)) {
1174 network->required_for_online = true;
1175 network->required_operstate_for_online = LINK_OPERSTATE_RANGE_DEFAULT;
1176 return 0;
1177 }
1178
1179 r = parse_operational_state_range(rvalue, &range);
1180 if (r < 0) {
1181 r = parse_boolean(rvalue);
1182 if (r < 0) {
1183 log_syntax(unit, LOG_WARNING, filename, line, r,
1184 "Failed to parse %s= setting, ignoring assignment: %s",
1185 lvalue, rvalue);
1186 return 0;
1187 }
1188
1189 required = r;
1190 range = LINK_OPERSTATE_RANGE_DEFAULT;
1191 }
1192
1193 network->required_for_online = required;
1194 network->required_operstate_for_online = range;
1195
1196 return 0;
1197 }
1198
1199 DEFINE_CONFIG_PARSE_ENUM(config_parse_keep_configuration, keep_configuration, KeepConfiguration,
1200 "Failed to parse KeepConfiguration= setting");
1201
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",
1208 };
1209
1210 DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(keep_configuration, KeepConfiguration, KEEP_CONFIGURATION_YES);
1211
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",
1217 };
1218
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");
1221
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",
1229 };
1230
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");