]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/network/networkd-network.c
Merge pull request #18007 from fw-strlen/ipv6_masq_and_dnat
[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->bond_name, NETDEV_KIND_BOND, &network->bond);
175 (void) network_resolve_netdev_one(network, network->bridge_name, NETDEV_KIND_BRIDGE, &network->bridge);
176 (void) network_resolve_netdev_one(network, network->vrf_name, NETDEV_KIND_VRF, &network->vrf);
177 (void) network_resolve_stacked_netdevs(network);
178
179 /* Free unnecessary entries. */
180 network->bond_name = mfree(network->bond_name);
181 network->bridge_name = mfree(network->bridge_name);
182 network->vrf_name = mfree(network->vrf_name);
183 network->stacked_netdev_names = hashmap_free_free_key(network->stacked_netdev_names);
184
185 if (network->bond) {
186 /* Bonding slave does not support addressing. */
187 if (network->link_local >= 0 && network->link_local != ADDRESS_FAMILY_NO) {
188 log_warning("%s: Cannot enable LinkLocalAddressing= when Bond= is specified, disabling LinkLocalAddressing=.",
189 network->filename);
190 network->link_local = ADDRESS_FAMILY_NO;
191 }
192 if (network->dhcp_server) {
193 log_warning("%s: Cannot enable DHCPServer= when Bond= is specified, disabling DHCPServer=.",
194 network->filename);
195 network->dhcp_server = false;
196 }
197 if (!ordered_hashmap_isempty(network->addresses_by_section))
198 log_warning("%s: Cannot set addresses when Bond= is specified, ignoring addresses.",
199 network->filename);
200 if (!hashmap_isempty(network->routes_by_section))
201 log_warning("%s: Cannot set routes when Bond= is specified, ignoring routes.",
202 network->filename);
203
204 network->addresses_by_section = ordered_hashmap_free_with_destructor(network->addresses_by_section, address_free);
205 network->routes_by_section = hashmap_free_with_destructor(network->routes_by_section, route_free);
206 }
207
208 if (network->link_local < 0)
209 network->link_local = network->bridge ? ADDRESS_FAMILY_NO : ADDRESS_FAMILY_IPV6;
210
211 /* IPMasquerade implies IPForward */
212 network->ip_forward |= network->ip_masquerade;
213
214 network_adjust_ipv6_accept_ra(network);
215 network_adjust_dhcp(network);
216 network_adjust_radv(network);
217
218 if (network->mtu > 0 && network->dhcp_use_mtu) {
219 log_warning("%s: MTUBytes= in [Link] section and UseMTU= in [DHCP] section are set. "
220 "Disabling UseMTU=.", network->filename);
221 network->dhcp_use_mtu = false;
222 }
223
224 if (network->dhcp_use_gateway < 0)
225 network->dhcp_use_gateway = network->dhcp_use_routes;
226
227 if (network->dhcp_critical >= 0) {
228 if (network->keep_configuration >= 0)
229 log_warning("%s: Both KeepConfiguration= and deprecated CriticalConnection= are set. "
230 "Ignoring CriticalConnection=.", network->filename);
231 else if (network->dhcp_critical)
232 /* CriticalConnection=yes also preserve foreign static configurations. */
233 network->keep_configuration = KEEP_CONFIGURATION_YES;
234 else
235 network->keep_configuration = KEEP_CONFIGURATION_NO;
236 }
237
238 if (!strv_isempty(network->bind_carrier)) {
239 if (!IN_SET(network->activation_policy, _ACTIVATION_POLICY_INVALID, ACTIVATION_POLICY_BOUND))
240 log_warning("%s: ActivationPolicy=bound is required with BindCarrier=. "
241 "Setting ActivationPolicy=bound.", network->filename);
242 network->activation_policy = ACTIVATION_POLICY_BOUND;
243 } else if (network->activation_policy == ACTIVATION_POLICY_BOUND) {
244 log_warning("%s: ActivationPolicy=bound requires BindCarrier=. "
245 "Ignoring ActivationPolicy=bound.", network->filename);
246 network->activation_policy = ACTIVATION_POLICY_UP;
247 }
248
249 if (network->activation_policy == _ACTIVATION_POLICY_INVALID)
250 network->activation_policy = ACTIVATION_POLICY_UP;
251
252 if (network->activation_policy == ACTIVATION_POLICY_ALWAYS_UP) {
253 if (network->ignore_carrier_loss == false)
254 log_warning("%s: IgnoreCarrierLoss=false conflicts with ActivationPolicy=always-up. "
255 "Setting IgnoreCarrierLoss=true.", network->filename);
256 network->ignore_carrier_loss = true;
257 }
258
259 if (network->ignore_carrier_loss < 0)
260 network->ignore_carrier_loss = network->configure_without_carrier;
261
262 if (network->keep_configuration < 0)
263 network->keep_configuration = KEEP_CONFIGURATION_NO;
264
265 if (network->ipv6_proxy_ndp == 0 && !set_isempty(network->ipv6_proxy_ndp_addresses)) {
266 log_warning("%s: IPv6ProxyNDP= is disabled. Ignoring IPv6ProxyNDPAddress=.", network->filename);
267 network->ipv6_proxy_ndp_addresses = set_free_free(network->ipv6_proxy_ndp_addresses);
268 }
269
270 network_drop_invalid_addresses(network);
271 network_drop_invalid_routes(network);
272 network_drop_invalid_nexthops(network);
273 network_drop_invalid_fdb_entries(network);
274 network_drop_invalid_mdb_entries(network);
275 network_drop_invalid_neighbors(network);
276 network_drop_invalid_address_labels(network);
277 network_drop_invalid_prefixes(network);
278 network_drop_invalid_route_prefixes(network);
279 network_drop_invalid_routing_policy_rules(network);
280 network_drop_invalid_traffic_control(network);
281 network_drop_invalid_sr_iov(network);
282
283 return 0;
284 }
285
286 int network_load_one(Manager *manager, OrderedHashmap **networks, const char *filename) {
287 _cleanup_free_ char *fname = NULL, *name = NULL;
288 _cleanup_(network_unrefp) Network *network = NULL;
289 _cleanup_fclose_ FILE *file = NULL;
290 const char *dropin_dirname;
291 char *d;
292 int r;
293
294 assert(manager);
295 assert(filename);
296
297 file = fopen(filename, "re");
298 if (!file) {
299 if (errno == ENOENT)
300 return 0;
301
302 return -errno;
303 }
304
305 if (null_or_empty_fd(fileno(file))) {
306 log_debug("Skipping empty file: %s", filename);
307 return 0;
308 }
309
310 fname = strdup(filename);
311 if (!fname)
312 return log_oom();
313
314 name = strdup(basename(filename));
315 if (!name)
316 return log_oom();
317
318 d = strrchr(name, '.');
319 if (!d)
320 return -EINVAL;
321
322 *d = '\0';
323
324 dropin_dirname = strjoina(name, ".network.d");
325
326 network = new(Network, 1);
327 if (!network)
328 return log_oom();
329
330 *network = (Network) {
331 .filename = TAKE_PTR(fname),
332 .name = TAKE_PTR(name),
333
334 .manager = manager,
335 .n_ref = 1,
336
337 .required_for_online = true,
338 .required_operstate_for_online = LINK_OPERSTATE_RANGE_DEFAULT,
339 .activation_policy = _ACTIVATION_POLICY_INVALID,
340 .arp = -1,
341 .multicast = -1,
342 .allmulticast = -1,
343 .promiscuous = -1,
344
345 .configure_without_carrier = false,
346 .ignore_carrier_loss = -1,
347 .keep_configuration = _KEEP_CONFIGURATION_INVALID,
348
349 .dhcp = ADDRESS_FAMILY_NO,
350 .duid.type = _DUID_TYPE_INVALID,
351 .dhcp_critical = -1,
352 .dhcp_use_ntp = true,
353 .dhcp_use_sip = true,
354 .dhcp_use_dns = true,
355 .dhcp_use_hostname = true,
356 .dhcp_use_routes = true,
357 .dhcp_use_gateway = -1,
358 /* NOTE: this var might be overwritten by network_apply_anonymize_if_set */
359 .dhcp_send_hostname = true,
360 .dhcp_send_release = true,
361 /* To enable/disable RFC7844 Anonymity Profiles */
362 .dhcp_anonymize = false,
363 .dhcp_route_metric = DHCP_ROUTE_METRIC,
364 /* NOTE: this var might be overwritten by network_apply_anonymize_if_set */
365 .dhcp_client_identifier = DHCP_CLIENT_ID_DUID,
366 .dhcp_route_table = RT_TABLE_MAIN,
367 .dhcp_route_table_set = false,
368 /* NOTE: from man: UseMTU=... Defaults to false*/
369 .dhcp_use_mtu = false,
370 /* NOTE: from man: UseTimezone=... Defaults to "no".*/
371 .dhcp_use_timezone = false,
372 .dhcp_ip_service_type = -1,
373
374 .dhcp6_use_address = true,
375 .dhcp6_use_dns = true,
376 .dhcp6_use_fqdn = true,
377 .dhcp6_use_ntp = true,
378 .dhcp6_rapid_commit = true,
379 .dhcp6_route_metric = DHCP_ROUTE_METRIC,
380
381 .dhcp6_pd = -1,
382 .dhcp6_pd_announce = true,
383 .dhcp6_pd_assign = true,
384 .dhcp6_pd_manage_temporary_address = true,
385 .dhcp6_pd_subnet_id = -1,
386
387 .dhcp_server_emit[SD_DHCP_LEASE_DNS].emit = true,
388 .dhcp_server_emit[SD_DHCP_LEASE_NTP].emit = true,
389 .dhcp_server_emit[SD_DHCP_LEASE_SIP].emit = true,
390
391 .dhcp_server_emit_router = true,
392 .dhcp_server_emit_timezone = true,
393
394 .router_lifetime_usec = 30 * USEC_PER_MINUTE,
395 .router_emit_dns = true,
396 .router_emit_domains = true,
397
398 .use_bpdu = -1,
399 .hairpin = -1,
400 .fast_leave = -1,
401 .allow_port_to_be_root = -1,
402 .unicast_flood = -1,
403 .multicast_flood = -1,
404 .multicast_to_unicast = -1,
405 .neighbor_suppression = -1,
406 .learning = -1,
407 .bridge_proxy_arp = -1,
408 .bridge_proxy_arp_wifi = -1,
409 .priority = LINK_BRIDGE_PORT_PRIORITY_INVALID,
410 .multicast_router = _MULTICAST_ROUTER_INVALID,
411
412 .lldp_mode = LLDP_MODE_ROUTERS_ONLY,
413
414 .dns_default_route = -1,
415 .llmnr = RESOLVE_SUPPORT_YES,
416 .mdns = RESOLVE_SUPPORT_NO,
417 .dnssec_mode = _DNSSEC_MODE_INVALID,
418 .dns_over_tls_mode = _DNS_OVER_TLS_MODE_INVALID,
419
420 /* If LinkLocalAddressing= is not set, then set to ADDRESS_FAMILY_IPV6 later. */
421 .link_local = _ADDRESS_FAMILY_INVALID,
422 .ipv6ll_address_gen_mode = _IPV6_LINK_LOCAL_ADDRESS_GEN_MODE_INVALID,
423
424 .ipv4_accept_local = -1,
425 .ipv6_privacy_extensions = IPV6_PRIVACY_EXTENSIONS_NO,
426 .ipv6_accept_ra = -1,
427 .ipv6_dad_transmits = -1,
428 .ipv6_hop_limit = -1,
429 .ipv6_proxy_ndp = -1,
430 .proxy_arp = -1,
431
432 .ipv6_accept_ra_use_dns = true,
433 .ipv6_accept_ra_use_autonomous_prefix = true,
434 .ipv6_accept_ra_use_onlink_prefix = true,
435 .ipv6_accept_ra_route_table = RT_TABLE_MAIN,
436 .ipv6_accept_ra_route_table_set = false,
437 .ipv6_accept_ra_start_dhcp6_client = IPV6_ACCEPT_RA_START_DHCP6_CLIENT_YES,
438
439 .can_triple_sampling = -1,
440 .can_berr_reporting = -1,
441 .can_termination = -1,
442 .can_listen_only = -1,
443 .can_fd_mode = -1,
444 .can_non_iso = -1,
445 };
446
447 r = config_parse_many(
448 filename, NETWORK_DIRS, dropin_dirname,
449 "Match\0"
450 "Link\0"
451 "SR-IOV\0"
452 "Network\0"
453 "Address\0"
454 "Neighbor\0"
455 "IPv6AddressLabel\0"
456 "RoutingPolicyRule\0"
457 "Route\0"
458 "NextHop\0"
459 "DHCP\0" /* compat */
460 "DHCPv4\0"
461 "DHCPv6\0"
462 "DHCPv6PrefixDelegation\0"
463 "DHCPServer\0"
464 "IPv6AcceptRA\0"
465 "IPv6NDPProxyAddress\0"
466 "Bridge\0"
467 "BridgeFDB\0"
468 "BridgeMDB\0"
469 "BridgeVLAN\0"
470 "IPv6SendRA\0"
471 "IPv6PrefixDelegation\0"
472 "IPv6Prefix\0"
473 "IPv6RoutePrefix\0"
474 "LLDP\0"
475 "TrafficControlQueueingDiscipline\0"
476 "CAN\0"
477 "QDisc\0"
478 "BFIFO\0"
479 "CAKE\0"
480 "ControlledDelay\0"
481 "DeficitRoundRobinScheduler\0"
482 "DeficitRoundRobinSchedulerClass\0"
483 "EnhancedTransmissionSelection\0"
484 "FairQueueing\0"
485 "FairQueueingControlledDelay\0"
486 "FlowQueuePIE\0"
487 "GenericRandomEarlyDetection\0"
488 "HeavyHitterFilter\0"
489 "HierarchyTokenBucket\0"
490 "HierarchyTokenBucketClass\0"
491 "NetworkEmulator\0"
492 "PFIFO\0"
493 "PFIFOFast\0"
494 "PFIFOHeadDrop\0"
495 "PIE\0"
496 "QuickFairQueueing\0"
497 "QuickFairQueueingClass\0"
498 "StochasticFairBlue\0"
499 "StochasticFairnessQueueing\0"
500 "TokenBucketFilter\0"
501 "TrivialLinkEqualizer\0",
502 config_item_perf_lookup, network_network_gperf_lookup,
503 CONFIG_PARSE_WARN,
504 network,
505 &network->timestamp);
506 if (r < 0)
507 return r;
508
509 network_apply_anonymize_if_set(network);
510
511 r = network_add_ipv4ll_route(network);
512 if (r < 0)
513 log_warning_errno(r, "%s: Failed to add IPv4LL route, ignoring: %m", network->filename);
514
515 r = network_add_default_route_on_device(network);
516 if (r < 0)
517 log_warning_errno(r, "%s: Failed to add default route on device, ignoring: %m",
518 network->filename);
519
520 if (network_verify(network) < 0)
521 /* Ignore .network files that do not match the conditions. */
522 return 0;
523
524 r = ordered_hashmap_ensure_put(networks, &string_hash_ops, network->name, network);
525 if (r < 0)
526 return r;
527
528 TAKE_PTR(network);
529 return 0;
530 }
531
532 int network_load(Manager *manager, OrderedHashmap **networks) {
533 _cleanup_strv_free_ char **files = NULL;
534 char **f;
535 int r;
536
537 assert(manager);
538
539 ordered_hashmap_clear_with_destructor(*networks, network_unref);
540
541 r = conf_files_list_strv(&files, ".network", NULL, 0, NETWORK_DIRS);
542 if (r < 0)
543 return log_error_errno(r, "Failed to enumerate network files: %m");
544
545 STRV_FOREACH(f, files) {
546 r = network_load_one(manager, networks, *f);
547 if (r < 0)
548 log_error_errno(r, "Failed to load %s, ignoring: %m", *f);
549 }
550
551 return 0;
552 }
553
554 int network_reload(Manager *manager) {
555 OrderedHashmap *new_networks = NULL;
556 Network *n, *old;
557 int r;
558
559 assert(manager);
560
561 r = network_load(manager, &new_networks);
562 if (r < 0)
563 goto failure;
564
565 ORDERED_HASHMAP_FOREACH(n, new_networks) {
566 r = network_get_by_name(manager, n->name, &old);
567 if (r < 0)
568 continue; /* The .network file is new. */
569
570 if (n->timestamp != old->timestamp)
571 continue; /* The .network file is modified. */
572
573 if (!streq(n->filename, old->filename))
574 continue;
575
576 r = ordered_hashmap_replace(new_networks, old->name, old);
577 if (r < 0)
578 goto failure;
579
580 network_ref(old);
581 network_unref(n);
582 }
583
584 ordered_hashmap_free_with_destructor(manager->networks, network_unref);
585 manager->networks = new_networks;
586
587 return 0;
588
589 failure:
590 ordered_hashmap_free_with_destructor(new_networks, network_unref);
591
592 return r;
593 }
594
595 static Network *network_free(Network *network) {
596 if (!network)
597 return NULL;
598
599 free(network->filename);
600
601 net_match_clear(&network->match);
602 condition_free_list(network->conditions);
603
604 free(network->description);
605 free(network->dhcp_vendor_class_identifier);
606 free(network->dhcp_mudurl);
607 strv_free(network->dhcp_user_class);
608 free(network->dhcp_hostname);
609 set_free(network->dhcp_deny_listed_ip);
610 set_free(network->dhcp_allow_listed_ip);
611 set_free(network->dhcp_request_options);
612 set_free(network->dhcp6_request_options);
613 free(network->mac);
614 free(network->dhcp6_mudurl);
615 strv_free(network->dhcp6_user_class);
616 strv_free(network->dhcp6_vendor_class);
617
618 strv_free(network->ntp);
619 for (unsigned i = 0; i < network->n_dns; i++)
620 in_addr_full_free(network->dns[i]);
621 free(network->dns);
622 ordered_set_free(network->search_domains);
623 ordered_set_free(network->route_domains);
624 strv_free(network->bind_carrier);
625
626 ordered_set_free(network->router_search_domains);
627 free(network->router_dns);
628 set_free_free(network->ndisc_deny_listed_router);
629 set_free_free(network->ndisc_allow_listed_router);
630 set_free_free(network->ndisc_deny_listed_prefix);
631 set_free_free(network->ndisc_allow_listed_prefix);
632 set_free_free(network->ndisc_deny_listed_route_prefix);
633 set_free_free(network->ndisc_allow_listed_route_prefix);
634
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 = 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_ensure_allocated(set, &string_hash_ops_free);
900 if (r < 0)
901 return log_oom();
902
903 r = ordered_set_put_strdup(*set, domain);
904 if (r < 0)
905 return log_oom();
906 }
907 }
908
909 int config_parse_hostname(
910 const char *unit,
911 const char *filename,
912 unsigned line,
913 const char *section,
914 unsigned section_line,
915 const char *lvalue,
916 int ltype,
917 const char *rvalue,
918 void *data,
919 void *userdata) {
920
921 _cleanup_free_ char *hn = NULL;
922 char **hostname = data;
923 int r;
924
925 assert(filename);
926 assert(lvalue);
927 assert(rvalue);
928
929 r = config_parse_string(unit, filename, line, section, section_line, lvalue, ltype, rvalue, &hn, userdata);
930 if (r < 0)
931 return r;
932
933 if (!hostname_is_valid(hn, 0)) {
934 log_syntax(unit, LOG_WARNING, filename, line, 0,
935 "Hostname is not valid, ignoring assignment: %s", rvalue);
936 return 0;
937 }
938
939 r = dns_name_is_valid(hn);
940 if (r < 0) {
941 log_syntax(unit, LOG_WARNING, filename, line, r,
942 "Failed to check validity of hostname '%s', ignoring assignment: %m", rvalue);
943 return 0;
944 }
945 if (r == 0) {
946 log_syntax(unit, LOG_WARNING, filename, line, 0,
947 "Hostname is not a valid DNS domain name, ignoring assignment: %s", rvalue);
948 return 0;
949 }
950
951 return free_and_replace(*hostname, hn);
952 }
953
954 int config_parse_timezone(
955 const char *unit,
956 const char *filename,
957 unsigned line,
958 const char *section,
959 unsigned section_line,
960 const char *lvalue,
961 int ltype,
962 const char *rvalue,
963 void *data,
964 void *userdata) {
965
966 _cleanup_free_ char *tz = NULL;
967 char **datap = data;
968 int r;
969
970 assert(filename);
971 assert(lvalue);
972 assert(rvalue);
973
974 r = config_parse_string(unit, filename, line, section, section_line, lvalue, ltype, rvalue, &tz, userdata);
975 if (r < 0)
976 return r;
977
978 if (!timezone_is_valid(tz, LOG_WARNING)) {
979 log_syntax(unit, LOG_WARNING, filename, line, 0,
980 "Timezone is not valid, ignoring assignment: %s", rvalue);
981 return 0;
982 }
983
984 return free_and_replace(*datap, tz);
985 }
986
987 int config_parse_dns(
988 const char *unit,
989 const char *filename,
990 unsigned line,
991 const char *section,
992 unsigned section_line,
993 const char *lvalue,
994 int ltype,
995 const char *rvalue,
996 void *data,
997 void *userdata) {
998
999 Network *n = userdata;
1000 int r;
1001
1002 assert(filename);
1003 assert(lvalue);
1004 assert(rvalue);
1005
1006 if (isempty(rvalue)) {
1007 for (unsigned i = 0; i < n->n_dns; i++)
1008 in_addr_full_free(n->dns[i]);
1009 n->dns = mfree(n->dns);
1010 n->n_dns = 0;
1011 return 0;
1012 }
1013
1014 for (const char *p = rvalue;;) {
1015 _cleanup_(in_addr_full_freep) struct in_addr_full *dns = NULL;
1016 _cleanup_free_ char *w = NULL;
1017 struct in_addr_full **m;
1018
1019 r = extract_first_word(&p, &w, NULL, 0);
1020 if (r == -ENOMEM)
1021 return log_oom();
1022 if (r < 0) {
1023 log_syntax(unit, LOG_WARNING, filename, line, r,
1024 "Invalid syntax, ignoring: %s", rvalue);
1025 return 0;
1026 }
1027 if (r == 0)
1028 return 0;
1029
1030 r = in_addr_full_new_from_string(w, &dns);
1031 if (r < 0) {
1032 log_syntax(unit, LOG_WARNING, filename, line, r,
1033 "Failed to parse dns server address, ignoring: %s", w);
1034 continue;
1035 }
1036
1037 if (IN_SET(dns->port, 53, 853))
1038 dns->port = 0;
1039
1040 m = reallocarray(n->dns, n->n_dns + 1, sizeof(struct in_addr_full*));
1041 if (!m)
1042 return log_oom();
1043
1044 m[n->n_dns++] = TAKE_PTR(dns);
1045 n->dns = m;
1046 }
1047 }
1048
1049 int config_parse_dnssec_negative_trust_anchors(
1050 const char *unit,
1051 const char *filename,
1052 unsigned line,
1053 const char *section,
1054 unsigned section_line,
1055 const char *lvalue,
1056 int ltype,
1057 const char *rvalue,
1058 void *data,
1059 void *userdata) {
1060
1061 Network *n = data;
1062 int r;
1063
1064 assert(n);
1065 assert(lvalue);
1066 assert(rvalue);
1067
1068 if (isempty(rvalue)) {
1069 n->dnssec_negative_trust_anchors = set_free_free(n->dnssec_negative_trust_anchors);
1070 return 0;
1071 }
1072
1073 for (const char *p = rvalue;;) {
1074 _cleanup_free_ char *w = NULL;
1075
1076 r = extract_first_word(&p, &w, NULL, 0);
1077 if (r == -ENOMEM)
1078 return log_oom();
1079 if (r < 0) {
1080 log_syntax(unit, LOG_WARNING, filename, line, r,
1081 "Failed to extract negative trust anchor domain, ignoring: %s", rvalue);
1082 return 0;
1083 }
1084 if (r == 0)
1085 return 0;
1086
1087 r = dns_name_is_valid(w);
1088 if (r <= 0) {
1089 log_syntax(unit, LOG_WARNING, filename, line, r,
1090 "%s is not a valid domain name, ignoring.", w);
1091 continue;
1092 }
1093
1094 r = set_ensure_consume(&n->dnssec_negative_trust_anchors, &dns_name_hash_ops, TAKE_PTR(w));
1095 if (r < 0)
1096 return log_oom();
1097 }
1098 }
1099
1100 int config_parse_ntp(
1101 const char *unit,
1102 const char *filename,
1103 unsigned line,
1104 const char *section,
1105 unsigned section_line,
1106 const char *lvalue,
1107 int ltype,
1108 const char *rvalue,
1109 void *data,
1110 void *userdata) {
1111
1112 char ***l = data;
1113 int r;
1114
1115 assert(l);
1116 assert(lvalue);
1117 assert(rvalue);
1118
1119 if (isempty(rvalue)) {
1120 *l = strv_free(*l);
1121 return 0;
1122 }
1123
1124 for (const char *p = rvalue;;) {
1125 _cleanup_free_ char *w = NULL;
1126
1127 r = extract_first_word(&p, &w, NULL, 0);
1128 if (r == -ENOMEM)
1129 return log_oom();
1130 if (r < 0) {
1131 log_syntax(unit, LOG_WARNING, filename, line, r,
1132 "Failed to extract NTP server name, ignoring: %s", rvalue);
1133 return 0;
1134 }
1135 if (r == 0)
1136 return 0;
1137
1138 r = dns_name_is_valid_or_address(w);
1139 if (r <= 0) {
1140 log_syntax(unit, LOG_WARNING, filename, line, r,
1141 "%s is not a valid domain name or IP address, ignoring.", w);
1142 continue;
1143 }
1144
1145 if (strv_length(*l) > MAX_NTP_SERVERS) {
1146 log_syntax(unit, LOG_WARNING, filename, line, 0,
1147 "More than %u NTP servers specified, ignoring \"%s\" and any subsequent entries.",
1148 MAX_NTP_SERVERS, w);
1149 return 0;
1150 }
1151
1152 r = strv_consume(l, TAKE_PTR(w));
1153 if (r < 0)
1154 return log_oom();
1155 }
1156 }
1157
1158 int config_parse_required_for_online(
1159 const char *unit,
1160 const char *filename,
1161 unsigned line,
1162 const char *section,
1163 unsigned section_line,
1164 const char *lvalue,
1165 int ltype,
1166 const char *rvalue,
1167 void *data,
1168 void *userdata) {
1169
1170 Network *network = data;
1171 LinkOperationalStateRange range;
1172 bool required = true;
1173 int r;
1174
1175 if (isempty(rvalue)) {
1176 network->required_for_online = true;
1177 network->required_operstate_for_online = LINK_OPERSTATE_RANGE_DEFAULT;
1178 return 0;
1179 }
1180
1181 r = parse_operational_state_range(rvalue, &range);
1182 if (r < 0) {
1183 r = parse_boolean(rvalue);
1184 if (r < 0) {
1185 log_syntax(unit, LOG_WARNING, filename, line, r,
1186 "Failed to parse %s= setting, ignoring assignment: %s",
1187 lvalue, rvalue);
1188 return 0;
1189 }
1190
1191 required = r;
1192 range = LINK_OPERSTATE_RANGE_DEFAULT;
1193 }
1194
1195 network->required_for_online = required;
1196 network->required_operstate_for_online = range;
1197
1198 return 0;
1199 }
1200
1201 DEFINE_CONFIG_PARSE_ENUM(config_parse_keep_configuration, keep_configuration, KeepConfiguration,
1202 "Failed to parse KeepConfiguration= setting");
1203
1204 static const char* const keep_configuration_table[_KEEP_CONFIGURATION_MAX] = {
1205 [KEEP_CONFIGURATION_NO] = "no",
1206 [KEEP_CONFIGURATION_DHCP_ON_STOP] = "dhcp-on-stop",
1207 [KEEP_CONFIGURATION_DHCP] = "dhcp",
1208 [KEEP_CONFIGURATION_STATIC] = "static",
1209 [KEEP_CONFIGURATION_YES] = "yes",
1210 };
1211
1212 DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(keep_configuration, KeepConfiguration, KEEP_CONFIGURATION_YES);
1213
1214 static const char* const ipv6_link_local_address_gen_mode_table[_IPV6_LINK_LOCAL_ADDRESS_GEN_MODE_MAX] = {
1215 [IPV6_LINK_LOCAL_ADDRESSS_GEN_MODE_EUI64] = "eui64",
1216 [IPV6_LINK_LOCAL_ADDRESSS_GEN_MODE_NONE] = "none",
1217 [IPV6_LINK_LOCAL_ADDRESSS_GEN_MODE_STABLE_PRIVACY] = "stable-privacy",
1218 [IPV6_LINK_LOCAL_ADDRESSS_GEN_MODE_RANDOM] = "random",
1219 };
1220
1221 DEFINE_STRING_TABLE_LOOKUP(ipv6_link_local_address_gen_mode, IPv6LinkLocalAddressGenMode);
1222 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");
1223
1224 static const char* const activation_policy_table[_ACTIVATION_POLICY_MAX] = {
1225 [ACTIVATION_POLICY_UP] = "up",
1226 [ACTIVATION_POLICY_ALWAYS_UP] = "always-up",
1227 [ACTIVATION_POLICY_MANUAL] = "manual",
1228 [ACTIVATION_POLICY_ALWAYS_DOWN] = "always-down",
1229 [ACTIVATION_POLICY_DOWN] = "down",
1230 [ACTIVATION_POLICY_BOUND] = "bound",
1231 };
1232
1233 DEFINE_STRING_TABLE_LOOKUP(activation_policy, ActivationPolicy);
1234 DEFINE_CONFIG_PARSE_ENUM(config_parse_activation_policy, activation_policy, ActivationPolicy, "Failed to parse activation policy");