]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/network/networkd-network.c
Merge pull request #20443 from yuwata/network-conf-parser-cleanups
[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-bridge-fdb.h"
19 #include "networkd-bridge-mdb.h"
20 #include "networkd-dhcp-common.h"
21 #include "networkd-dhcp-server-static-lease.h"
22 #include "networkd-dhcp-server.h"
23 #include "networkd-ipv6-proxy-ndp.h"
24 #include "networkd-manager.h"
25 #include "networkd-ndisc.h"
26 #include "networkd-neighbor.h"
27 #include "networkd-network.h"
28 #include "networkd-nexthop.h"
29 #include "networkd-radv.h"
30 #include "networkd-routing-policy-rule.h"
31 #include "networkd-sriov.h"
32 #include "parse-util.h"
33 #include "path-lookup.h"
34 #include "set.h"
35 #include "socket-util.h"
36 #include "stat-util.h"
37 #include "string-table.h"
38 #include "string-util.h"
39 #include "strv.h"
40 #include "tc.h"
41 #include "util.h"
42
43 /* Let's assume that anything above this number is a user misconfiguration. */
44 #define MAX_NTP_SERVERS 128
45
46 static int network_resolve_netdev_one(Network *network, const char *name, NetDevKind kind, NetDev **ret_netdev) {
47 const char *kind_string;
48 NetDev *netdev;
49 int r;
50
51 /* For test-networkd-conf, the check must be earlier than the assertions. */
52 if (!name)
53 return 0;
54
55 assert(network);
56 assert(network->manager);
57 assert(network->filename);
58 assert(ret_netdev);
59
60 if (kind == _NETDEV_KIND_TUNNEL)
61 kind_string = "tunnel";
62 else {
63 kind_string = netdev_kind_to_string(kind);
64 if (!kind_string)
65 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
66 "%s: Invalid NetDev kind of %s, ignoring assignment.",
67 network->filename, name);
68 }
69
70 r = netdev_get(network->manager, name, &netdev);
71 if (r < 0)
72 return log_error_errno(r, "%s: %s NetDev could not be found, ignoring assignment.",
73 network->filename, name);
74
75 if (netdev->kind != kind && !(kind == _NETDEV_KIND_TUNNEL &&
76 IN_SET(netdev->kind,
77 NETDEV_KIND_IPIP,
78 NETDEV_KIND_SIT,
79 NETDEV_KIND_GRE,
80 NETDEV_KIND_GRETAP,
81 NETDEV_KIND_IP6GRE,
82 NETDEV_KIND_IP6GRETAP,
83 NETDEV_KIND_VTI,
84 NETDEV_KIND_VTI6,
85 NETDEV_KIND_IP6TNL,
86 NETDEV_KIND_ERSPAN)))
87 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
88 "%s: NetDev %s is not a %s, ignoring assignment",
89 network->filename, name, kind_string);
90
91 *ret_netdev = netdev_ref(netdev);
92 return 1;
93 }
94
95 static int network_resolve_stacked_netdevs(Network *network) {
96 void *name, *kind;
97 int r;
98
99 assert(network);
100
101 HASHMAP_FOREACH_KEY(kind, name, network->stacked_netdev_names) {
102 _cleanup_(netdev_unrefp) NetDev *netdev = NULL;
103
104 r = network_resolve_netdev_one(network, name, PTR_TO_INT(kind), &netdev);
105 if (r <= 0)
106 continue;
107
108 r = hashmap_ensure_put(&network->stacked_netdevs, &string_hash_ops, netdev->ifname, netdev);
109 if (r == -ENOMEM)
110 return log_oom();
111 if (r < 0)
112 return log_error_errno(r, "%s: Failed to add NetDev '%s' to network: %m",
113 network->filename, (const char *) name);
114
115 netdev = NULL;
116 }
117
118 return 0;
119 }
120
121 int network_verify(Network *network) {
122 assert(network);
123 assert(network->filename);
124
125 if (net_match_is_empty(&network->match) && !network->conditions)
126 return log_warning_errno(SYNTHETIC_ERRNO(EINVAL),
127 "%s: No valid settings found in the [Match] section, ignoring file. "
128 "To match all interfaces, add Name=* in the [Match] section.",
129 network->filename);
130
131 /* skip out early if configuration does not match the environment */
132 if (!condition_test_list(network->conditions, environ, NULL, NULL, NULL))
133 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL),
134 "%s: Conditions in the file do not match the system environment, skipping.",
135 network->filename);
136
137 (void) network_resolve_netdev_one(network, network->batadv_name, NETDEV_KIND_BATADV, &network->batadv);
138 (void) network_resolve_netdev_one(network, network->bond_name, NETDEV_KIND_BOND, &network->bond);
139 (void) network_resolve_netdev_one(network, network->bridge_name, NETDEV_KIND_BRIDGE, &network->bridge);
140 (void) network_resolve_netdev_one(network, network->vrf_name, NETDEV_KIND_VRF, &network->vrf);
141 (void) network_resolve_stacked_netdevs(network);
142
143 /* Free unnecessary entries. */
144 network->batadv_name = mfree(network->batadv_name);
145 network->bond_name = mfree(network->bond_name);
146 network->bridge_name = mfree(network->bridge_name);
147 network->vrf_name = mfree(network->vrf_name);
148 network->stacked_netdev_names = hashmap_free_free_key(network->stacked_netdev_names);
149
150 if (network->bond) {
151 /* Bonding slave does not support addressing. */
152 if (network->link_local >= 0 && network->link_local != ADDRESS_FAMILY_NO) {
153 log_warning("%s: Cannot enable LinkLocalAddressing= when Bond= is specified, disabling LinkLocalAddressing=.",
154 network->filename);
155 network->link_local = ADDRESS_FAMILY_NO;
156 }
157 if (network->dhcp_server) {
158 log_warning("%s: Cannot enable DHCPServer= when Bond= is specified, disabling DHCPServer=.",
159 network->filename);
160 network->dhcp_server = false;
161 }
162 if (!ordered_hashmap_isempty(network->addresses_by_section))
163 log_warning("%s: Cannot set addresses when Bond= is specified, ignoring addresses.",
164 network->filename);
165 if (!hashmap_isempty(network->routes_by_section))
166 log_warning("%s: Cannot set routes when Bond= is specified, ignoring routes.",
167 network->filename);
168
169 network->addresses_by_section = ordered_hashmap_free_with_destructor(network->addresses_by_section, address_free);
170 network->routes_by_section = hashmap_free_with_destructor(network->routes_by_section, route_free);
171 }
172
173 if (network->link_local < 0)
174 network->link_local = network->bridge ? ADDRESS_FAMILY_NO : ADDRESS_FAMILY_IPV6;
175 if (network->ipv6ll_address_gen_mode == IPV6_LINK_LOCAL_ADDRESSS_GEN_MODE_NONE)
176 SET_FLAG(network->link_local, ADDRESS_FAMILY_IPV6, false);
177
178 if (in6_addr_is_set(&network->ipv6ll_stable_secret) &&
179 network->ipv6ll_address_gen_mode < 0)
180 network->ipv6ll_address_gen_mode = IPV6_LINK_LOCAL_ADDRESSS_GEN_MODE_STABLE_PRIVACY;
181
182 /* IPMasquerade implies IPForward */
183 network->ip_forward |= network->ip_masquerade;
184
185 network_adjust_ipv6_proxy_ndp(network);
186 network_adjust_ipv6_accept_ra(network);
187 network_adjust_dhcp(network);
188 network_adjust_radv(network);
189 network_adjust_bridge_vlan(network);
190
191 if (network->mtu > 0 && network->dhcp_use_mtu) {
192 log_warning("%s: MTUBytes= in [Link] section and UseMTU= in [DHCP] section are set. "
193 "Disabling UseMTU=.", network->filename);
194 network->dhcp_use_mtu = false;
195 }
196
197 if (network->dhcp_critical >= 0) {
198 if (network->keep_configuration >= 0)
199 log_warning("%s: Both KeepConfiguration= and deprecated CriticalConnection= are set. "
200 "Ignoring CriticalConnection=.", network->filename);
201 else if (network->dhcp_critical)
202 /* CriticalConnection=yes also preserve foreign static configurations. */
203 network->keep_configuration = KEEP_CONFIGURATION_YES;
204 else
205 network->keep_configuration = KEEP_CONFIGURATION_NO;
206 }
207
208 if (!strv_isempty(network->bind_carrier)) {
209 if (!IN_SET(network->activation_policy, _ACTIVATION_POLICY_INVALID, ACTIVATION_POLICY_BOUND))
210 log_warning("%s: ActivationPolicy=bound is required with BindCarrier=. "
211 "Setting ActivationPolicy=bound.", network->filename);
212 network->activation_policy = ACTIVATION_POLICY_BOUND;
213 } else if (network->activation_policy == ACTIVATION_POLICY_BOUND) {
214 log_warning("%s: ActivationPolicy=bound requires BindCarrier=. "
215 "Ignoring ActivationPolicy=bound.", network->filename);
216 network->activation_policy = ACTIVATION_POLICY_UP;
217 }
218
219 if (network->activation_policy == _ACTIVATION_POLICY_INVALID)
220 network->activation_policy = ACTIVATION_POLICY_UP;
221
222 if (network->activation_policy == ACTIVATION_POLICY_ALWAYS_UP) {
223 if (network->ignore_carrier_loss == false)
224 log_warning("%s: IgnoreCarrierLoss=false conflicts with ActivationPolicy=always-up. "
225 "Setting IgnoreCarrierLoss=true.", network->filename);
226 network->ignore_carrier_loss = true;
227 }
228
229 if (network->ignore_carrier_loss < 0)
230 network->ignore_carrier_loss = network->configure_without_carrier;
231
232 if (IN_SET(network->activation_policy, ACTIVATION_POLICY_DOWN, ACTIVATION_POLICY_ALWAYS_DOWN, ACTIVATION_POLICY_MANUAL)) {
233 if (network->required_for_online < 0 ||
234 (network->required_for_online == true && network->activation_policy == ACTIVATION_POLICY_ALWAYS_DOWN)) {
235 log_debug("%s: Setting RequiredForOnline=no because ActivationPolicy=%s.", network->filename,
236 activation_policy_to_string(network->activation_policy));
237 network->required_for_online = false;
238 } else if (network->required_for_online == true)
239 log_warning("%s: RequiredForOnline=yes and ActivationPolicy=%s, "
240 "this may cause a delay at boot.", network->filename,
241 activation_policy_to_string(network->activation_policy));
242 }
243
244 if (network->required_for_online < 0)
245 network->required_for_online = true;
246
247 if (network->keep_configuration < 0)
248 network->keep_configuration = KEEP_CONFIGURATION_NO;
249
250 if (network->ipv6_proxy_ndp == 0 && !set_isempty(network->ipv6_proxy_ndp_addresses)) {
251 log_warning("%s: IPv6ProxyNDP= is disabled. Ignoring IPv6ProxyNDPAddress=.", network->filename);
252 network->ipv6_proxy_ndp_addresses = set_free_free(network->ipv6_proxy_ndp_addresses);
253 }
254
255 network_drop_invalid_addresses(network);
256 network_drop_invalid_routes(network);
257 network_drop_invalid_nexthops(network);
258 network_drop_invalid_bridge_fdb_entries(network);
259 network_drop_invalid_bridge_mdb_entries(network);
260 network_drop_invalid_neighbors(network);
261 network_drop_invalid_address_labels(network);
262 network_drop_invalid_prefixes(network);
263 network_drop_invalid_route_prefixes(network);
264 network_drop_invalid_routing_policy_rules(network);
265 network_drop_invalid_traffic_control(network);
266 network_drop_invalid_sr_iov(network);
267 network_drop_invalid_static_leases(network);
268
269 network_adjust_dhcp_server(network);
270
271 return 0;
272 }
273
274 int network_load_one(Manager *manager, OrderedHashmap **networks, const char *filename) {
275 _cleanup_free_ char *fname = NULL, *name = NULL;
276 _cleanup_(network_unrefp) Network *network = NULL;
277 const char *dropin_dirname;
278 char *d;
279 int r;
280
281 assert(manager);
282 assert(filename);
283
284 r = null_or_empty_path(filename);
285 if (r == -ENOENT)
286 return 0;
287 if (r < 0)
288 return r;
289 if (r > 0) {
290 log_debug("Skipping empty file: %s", filename);
291 return 0;
292 }
293
294 fname = strdup(filename);
295 if (!fname)
296 return log_oom();
297
298 name = strdup(basename(filename));
299 if (!name)
300 return log_oom();
301
302 d = strrchr(name, '.');
303 if (!d)
304 return -EINVAL;
305
306 *d = '\0';
307
308 dropin_dirname = strjoina(name, ".network.d");
309
310 network = new(Network, 1);
311 if (!network)
312 return log_oom();
313
314 *network = (Network) {
315 .filename = TAKE_PTR(fname),
316 .name = TAKE_PTR(name),
317
318 .manager = manager,
319 .n_ref = 1,
320
321 .required_for_online = -1,
322 .required_operstate_for_online = LINK_OPERSTATE_RANGE_DEFAULT,
323 .activation_policy = _ACTIVATION_POLICY_INVALID,
324 .arp = -1,
325 .multicast = -1,
326 .allmulticast = -1,
327 .promiscuous = -1,
328
329 .ignore_carrier_loss = -1,
330 .keep_configuration = _KEEP_CONFIGURATION_INVALID,
331
332 .dhcp_duid.type = _DUID_TYPE_INVALID,
333 .dhcp_critical = -1,
334 .dhcp_use_ntp = true,
335 .dhcp_routes_to_ntp = true,
336 .dhcp_use_sip = true,
337 .dhcp_use_dns = true,
338 .dhcp_routes_to_dns = true,
339 .dhcp_use_hostname = true,
340 .dhcp_use_routes = true,
341 .dhcp_use_gateway = -1,
342 .dhcp_send_hostname = true,
343 .dhcp_send_release = true,
344 .dhcp_route_metric = DHCP_ROUTE_METRIC,
345 .dhcp_client_identifier = _DHCP_CLIENT_ID_INVALID,
346 .dhcp_route_table = RT_TABLE_MAIN,
347 .dhcp_ip_service_type = -1,
348 .dhcp_broadcast = -1,
349
350 .dhcp6_use_address = true,
351 .dhcp6_use_dns = true,
352 .dhcp6_use_hostname = true,
353 .dhcp6_use_ntp = true,
354 .dhcp6_rapid_commit = true,
355 .dhcp6_duid.type = _DUID_TYPE_INVALID,
356
357 .dhcp6_pd = -1,
358 .dhcp6_pd_announce = true,
359 .dhcp6_pd_assign = true,
360 .dhcp6_pd_manage_temporary_address = true,
361 .dhcp6_pd_subnet_id = -1,
362
363 .dhcp_server_bind_to_interface = true,
364 .dhcp_server_emit[SD_DHCP_LEASE_DNS].emit = true,
365 .dhcp_server_emit[SD_DHCP_LEASE_NTP].emit = true,
366 .dhcp_server_emit[SD_DHCP_LEASE_SIP].emit = true,
367 .dhcp_server_emit_router = true,
368 .dhcp_server_emit_timezone = true,
369
370 .router_lifetime_usec = 30 * USEC_PER_MINUTE,
371 .router_emit_dns = true,
372 .router_emit_domains = true,
373
374 .use_bpdu = -1,
375 .hairpin = -1,
376 .fast_leave = -1,
377 .allow_port_to_be_root = -1,
378 .unicast_flood = -1,
379 .multicast_flood = -1,
380 .multicast_to_unicast = -1,
381 .neighbor_suppression = -1,
382 .learning = -1,
383 .bridge_proxy_arp = -1,
384 .bridge_proxy_arp_wifi = -1,
385 .priority = LINK_BRIDGE_PORT_PRIORITY_INVALID,
386 .multicast_router = _MULTICAST_ROUTER_INVALID,
387
388 .lldp_mode = LLDP_MODE_ROUTERS_ONLY,
389
390 .dns_default_route = -1,
391 .llmnr = RESOLVE_SUPPORT_YES,
392 .mdns = RESOLVE_SUPPORT_NO,
393 .dnssec_mode = _DNSSEC_MODE_INVALID,
394 .dns_over_tls_mode = _DNS_OVER_TLS_MODE_INVALID,
395
396 /* If LinkLocalAddressing= is not set, then set to ADDRESS_FAMILY_IPV6 later. */
397 .link_local = _ADDRESS_FAMILY_INVALID,
398 .ipv6ll_address_gen_mode = _IPV6_LINK_LOCAL_ADDRESS_GEN_MODE_INVALID,
399
400 .ipv4_accept_local = -1,
401 .ipv4_route_localnet = -1,
402 .ipv6_privacy_extensions = IPV6_PRIVACY_EXTENSIONS_NO,
403 .ipv6_accept_ra = -1,
404 .ipv6_dad_transmits = -1,
405 .ipv6_hop_limit = -1,
406 .ipv6_proxy_ndp = -1,
407 .proxy_arp = -1,
408
409 .ipv6_accept_ra_use_dns = true,
410 .ipv6_accept_ra_use_autonomous_prefix = true,
411 .ipv6_accept_ra_use_onlink_prefix = true,
412 .ipv6_accept_ra_route_table = RT_TABLE_MAIN,
413 .ipv6_accept_ra_route_metric = DHCP_ROUTE_METRIC,
414 .ipv6_accept_ra_start_dhcp6_client = IPV6_ACCEPT_RA_START_DHCP6_CLIENT_YES,
415
416 .can_termination = -1,
417 };
418
419 r = config_parse_many(
420 STRV_MAKE_CONST(filename), NETWORK_DIRS, dropin_dirname,
421 "Match\0"
422 "Link\0"
423 "SR-IOV\0"
424 "Network\0"
425 "Address\0"
426 "Neighbor\0"
427 "IPv6AddressLabel\0"
428 "RoutingPolicyRule\0"
429 "Route\0"
430 "NextHop\0"
431 "DHCP\0" /* compat */
432 "DHCPv4\0"
433 "DHCPv6\0"
434 "DHCPv6PrefixDelegation\0"
435 "DHCPServer\0"
436 "DHCPServerStaticLease\0"
437 "IPv6AcceptRA\0"
438 "IPv6NDPProxyAddress\0"
439 "Bridge\0"
440 "BridgeFDB\0"
441 "BridgeMDB\0"
442 "BridgeVLAN\0"
443 "IPv6SendRA\0"
444 "IPv6PrefixDelegation\0"
445 "IPv6Prefix\0"
446 "IPv6RoutePrefix\0"
447 "LLDP\0"
448 "TrafficControlQueueingDiscipline\0"
449 "CAN\0"
450 "QDisc\0"
451 "BFIFO\0"
452 "CAKE\0"
453 "ControlledDelay\0"
454 "DeficitRoundRobinScheduler\0"
455 "DeficitRoundRobinSchedulerClass\0"
456 "EnhancedTransmissionSelection\0"
457 "FairQueueing\0"
458 "FairQueueingControlledDelay\0"
459 "FlowQueuePIE\0"
460 "GenericRandomEarlyDetection\0"
461 "HeavyHitterFilter\0"
462 "HierarchyTokenBucket\0"
463 "HierarchyTokenBucketClass\0"
464 "NetworkEmulator\0"
465 "PFIFO\0"
466 "PFIFOFast\0"
467 "PFIFOHeadDrop\0"
468 "PIE\0"
469 "QuickFairQueueing\0"
470 "QuickFairQueueingClass\0"
471 "StochasticFairBlue\0"
472 "StochasticFairnessQueueing\0"
473 "TokenBucketFilter\0"
474 "TrivialLinkEqualizer\0",
475 config_item_perf_lookup, network_network_gperf_lookup,
476 CONFIG_PARSE_WARN,
477 network,
478 &network->timestamp);
479 if (r < 0)
480 return r;
481
482 r = network_add_ipv4ll_route(network);
483 if (r < 0)
484 log_warning_errno(r, "%s: Failed to add IPv4LL route, ignoring: %m", network->filename);
485
486 r = network_add_default_route_on_device(network);
487 if (r < 0)
488 log_warning_errno(r, "%s: Failed to add default route on device, ignoring: %m",
489 network->filename);
490
491 if (network_verify(network) < 0)
492 /* Ignore .network files that do not match the conditions. */
493 return 0;
494
495 r = ordered_hashmap_ensure_put(networks, &string_hash_ops, network->name, network);
496 if (r < 0)
497 return r;
498
499 TAKE_PTR(network);
500 return 0;
501 }
502
503 int network_load(Manager *manager, OrderedHashmap **networks) {
504 _cleanup_strv_free_ char **files = NULL;
505 char **f;
506 int r;
507
508 assert(manager);
509
510 ordered_hashmap_clear_with_destructor(*networks, network_unref);
511
512 r = conf_files_list_strv(&files, ".network", NULL, 0, NETWORK_DIRS);
513 if (r < 0)
514 return log_error_errno(r, "Failed to enumerate network files: %m");
515
516 STRV_FOREACH(f, files) {
517 r = network_load_one(manager, networks, *f);
518 if (r < 0)
519 log_error_errno(r, "Failed to load %s, ignoring: %m", *f);
520 }
521
522 return 0;
523 }
524
525 int network_reload(Manager *manager) {
526 OrderedHashmap *new_networks = NULL;
527 Network *n, *old;
528 int r;
529
530 assert(manager);
531
532 r = network_load(manager, &new_networks);
533 if (r < 0)
534 goto failure;
535
536 ORDERED_HASHMAP_FOREACH(n, new_networks) {
537 r = network_get_by_name(manager, n->name, &old);
538 if (r < 0)
539 continue; /* The .network file is new. */
540
541 if (n->timestamp != old->timestamp)
542 continue; /* The .network file is modified. */
543
544 if (!streq(n->filename, old->filename))
545 continue;
546
547 r = ordered_hashmap_replace(new_networks, old->name, old);
548 if (r < 0)
549 goto failure;
550
551 network_ref(old);
552 network_unref(n);
553 }
554
555 ordered_hashmap_free_with_destructor(manager->networks, network_unref);
556 manager->networks = new_networks;
557
558 return 0;
559
560 failure:
561 ordered_hashmap_free_with_destructor(new_networks, network_unref);
562
563 return r;
564 }
565
566 static Network *network_free(Network *network) {
567 if (!network)
568 return NULL;
569
570 free(network->filename);
571
572 net_match_clear(&network->match);
573 condition_free_list(network->conditions);
574
575 free(network->dhcp_server_relay_agent_circuit_id);
576 free(network->dhcp_server_relay_agent_remote_id);
577
578 free(network->description);
579 free(network->dhcp_vendor_class_identifier);
580 free(network->dhcp_mudurl);
581 strv_free(network->dhcp_user_class);
582 free(network->dhcp_hostname);
583 free(network->dhcp_label);
584 set_free(network->dhcp_deny_listed_ip);
585 set_free(network->dhcp_allow_listed_ip);
586 set_free(network->dhcp_request_options);
587 set_free(network->dhcp6_request_options);
588 free(network->mac);
589 free(network->dhcp6_mudurl);
590 strv_free(network->dhcp6_user_class);
591 strv_free(network->dhcp6_vendor_class);
592
593 strv_free(network->ntp);
594 for (unsigned i = 0; i < network->n_dns; i++)
595 in_addr_full_free(network->dns[i]);
596 free(network->dns);
597 ordered_set_free(network->search_domains);
598 ordered_set_free(network->route_domains);
599 strv_free(network->bind_carrier);
600
601 ordered_set_free(network->router_search_domains);
602 free(network->router_dns);
603 set_free_free(network->ndisc_deny_listed_router);
604 set_free_free(network->ndisc_allow_listed_router);
605 set_free_free(network->ndisc_deny_listed_prefix);
606 set_free_free(network->ndisc_allow_listed_prefix);
607 set_free_free(network->ndisc_deny_listed_route_prefix);
608 set_free_free(network->ndisc_allow_listed_route_prefix);
609
610 free(network->batadv_name);
611 free(network->bridge_name);
612 free(network->bond_name);
613 free(network->vrf_name);
614 hashmap_free_free_key(network->stacked_netdev_names);
615 netdev_unref(network->bridge);
616 netdev_unref(network->bond);
617 netdev_unref(network->vrf);
618 hashmap_free_with_destructor(network->stacked_netdevs, netdev_unref);
619
620 set_free_free(network->ipv6_proxy_ndp_addresses);
621 ordered_hashmap_free_with_destructor(network->addresses_by_section, address_free);
622 hashmap_free_with_destructor(network->routes_by_section, route_free);
623 hashmap_free_with_destructor(network->nexthops_by_section, nexthop_free);
624 hashmap_free_with_destructor(network->bridge_fdb_entries_by_section, bridge_fdb_free);
625 hashmap_free_with_destructor(network->bridge_mdb_entries_by_section, bridge_mdb_free);
626 hashmap_free_with_destructor(network->neighbors_by_section, neighbor_free);
627 hashmap_free_with_destructor(network->address_labels_by_section, address_label_free);
628 hashmap_free_with_destructor(network->prefixes_by_section, prefix_free);
629 hashmap_free_with_destructor(network->route_prefixes_by_section, route_prefix_free);
630 hashmap_free_with_destructor(network->rules_by_section, routing_policy_rule_free);
631 hashmap_free_with_destructor(network->dhcp_static_leases_by_section, dhcp_static_lease_free);
632 ordered_hashmap_free_with_destructor(network->sr_iov_by_section, sr_iov_free);
633 ordered_hashmap_free_with_destructor(network->tc_by_section, traffic_control_free);
634
635 free(network->name);
636
637 free(network->dhcp_server_timezone);
638 free(network->dhcp_server_uplink_name);
639 free(network->router_uplink_name);
640
641 for (sd_dhcp_lease_server_type_t t = 0; t < _SD_DHCP_LEASE_SERVER_TYPE_MAX; t++)
642 free(network->dhcp_server_emit[t].addresses);
643
644 set_free_free(network->dnssec_negative_trust_anchors);
645
646 free(network->lldp_mud);
647
648 ordered_hashmap_free(network->dhcp_client_send_options);
649 ordered_hashmap_free(network->dhcp_client_send_vendor_options);
650 ordered_hashmap_free(network->dhcp_server_send_options);
651 ordered_hashmap_free(network->dhcp_server_send_vendor_options);
652 ordered_set_free(network->ipv6_tokens);
653 ordered_hashmap_free(network->dhcp6_client_send_options);
654 ordered_hashmap_free(network->dhcp6_client_send_vendor_options);
655
656 return mfree(network);
657 }
658
659 DEFINE_TRIVIAL_REF_UNREF_FUNC(Network, network, network_free);
660
661 int network_get_by_name(Manager *manager, const char *name, Network **ret) {
662 Network *network;
663
664 assert(manager);
665 assert(name);
666 assert(ret);
667
668 network = ordered_hashmap_get(manager->networks, name);
669 if (!network)
670 return -ENOENT;
671
672 *ret = network;
673
674 return 0;
675 }
676
677 bool network_has_static_ipv6_configurations(Network *network) {
678 Address *address;
679 Route *route;
680 BridgeFDB *fdb;
681 BridgeMDB *mdb;
682 Neighbor *neighbor;
683
684 assert(network);
685
686 ORDERED_HASHMAP_FOREACH(address, network->addresses_by_section)
687 if (address->family == AF_INET6)
688 return true;
689
690 HASHMAP_FOREACH(route, network->routes_by_section)
691 if (route->family == AF_INET6)
692 return true;
693
694 HASHMAP_FOREACH(fdb, network->bridge_fdb_entries_by_section)
695 if (fdb->family == AF_INET6)
696 return true;
697
698 HASHMAP_FOREACH(mdb, network->bridge_mdb_entries_by_section)
699 if (mdb->family == AF_INET6)
700 return true;
701
702 HASHMAP_FOREACH(neighbor, network->neighbors_by_section)
703 if (neighbor->family == AF_INET6)
704 return true;
705
706 if (!hashmap_isempty(network->address_labels_by_section))
707 return true;
708
709 if (!hashmap_isempty(network->prefixes_by_section))
710 return true;
711
712 if (!hashmap_isempty(network->route_prefixes_by_section))
713 return true;
714
715 return false;
716 }
717
718 int config_parse_stacked_netdev(
719 const char *unit,
720 const char *filename,
721 unsigned line,
722 const char *section,
723 unsigned section_line,
724 const char *lvalue,
725 int ltype,
726 const char *rvalue,
727 void *data,
728 void *userdata) {
729
730 _cleanup_free_ char *name = NULL;
731 NetDevKind kind = ltype;
732 Hashmap **h = data;
733 int r;
734
735 assert(filename);
736 assert(lvalue);
737 assert(rvalue);
738 assert(data);
739 assert(IN_SET(kind,
740 NETDEV_KIND_VLAN, NETDEV_KIND_MACVLAN, NETDEV_KIND_MACVTAP,
741 NETDEV_KIND_IPVLAN, NETDEV_KIND_IPVTAP, NETDEV_KIND_VXLAN,
742 NETDEV_KIND_L2TP, NETDEV_KIND_MACSEC, _NETDEV_KIND_TUNNEL,
743 NETDEV_KIND_XFRM));
744
745 if (!ifname_valid(rvalue)) {
746 log_syntax(unit, LOG_WARNING, filename, line, 0,
747 "Invalid netdev name in %s=, ignoring assignment: %s", lvalue, rvalue);
748 return 0;
749 }
750
751 name = strdup(rvalue);
752 if (!name)
753 return log_oom();
754
755 r = hashmap_ensure_put(h, &string_hash_ops, name, INT_TO_PTR(kind));
756 if (r == -ENOMEM)
757 return log_oom();
758 if (r < 0)
759 log_syntax(unit, LOG_WARNING, filename, line, r,
760 "Cannot add NetDev '%s' to network, ignoring assignment: %m", name);
761 else if (r == 0)
762 log_syntax(unit, LOG_DEBUG, filename, line, r,
763 "NetDev '%s' specified twice, ignoring.", name);
764 else
765 TAKE_PTR(name);
766
767 return 0;
768 }
769
770 int config_parse_domains(
771 const char *unit,
772 const char *filename,
773 unsigned line,
774 const char *section,
775 unsigned section_line,
776 const char *lvalue,
777 int ltype,
778 const char *rvalue,
779 void *data,
780 void *userdata) {
781
782 Network *n = userdata;
783 int r;
784
785 assert(filename);
786 assert(lvalue);
787 assert(rvalue);
788 assert(n);
789
790 if (isempty(rvalue)) {
791 n->search_domains = ordered_set_free(n->search_domains);
792 n->route_domains = ordered_set_free(n->route_domains);
793 return 0;
794 }
795
796 for (const char *p = rvalue;;) {
797 _cleanup_free_ char *w = NULL, *normalized = NULL;
798 const char *domain;
799 bool is_route;
800
801 r = extract_first_word(&p, &w, NULL, 0);
802 if (r == -ENOMEM)
803 return log_oom();
804 if (r < 0) {
805 log_syntax(unit, LOG_WARNING, filename, line, r,
806 "Failed to extract search or route domain, ignoring: %s", rvalue);
807 return 0;
808 }
809 if (r == 0)
810 return 0;
811
812 is_route = w[0] == '~';
813 domain = is_route ? w + 1 : w;
814
815 if (dns_name_is_root(domain) || streq(domain, "*")) {
816 /* If the root domain appears as is, or the special token "*" is found, we'll
817 * consider this as routing domain, unconditionally. */
818 is_route = true;
819 domain = "."; /* make sure we don't allow empty strings, thus write the root
820 * domain as "." */
821 } else {
822 r = dns_name_normalize(domain, 0, &normalized);
823 if (r < 0) {
824 log_syntax(unit, LOG_WARNING, filename, line, r,
825 "'%s' is not a valid domain name, ignoring.", domain);
826 continue;
827 }
828
829 domain = normalized;
830
831 if (is_localhost(domain)) {
832 log_syntax(unit, LOG_WARNING, filename, line, 0,
833 "'localhost' domain may not be configured as search or route domain, ignoring assignment: %s",
834 domain);
835 continue;
836 }
837 }
838
839 OrderedSet **set = is_route ? &n->route_domains : &n->search_domains;
840 r = ordered_set_put_strdup(set, domain);
841 if (r == -EEXIST)
842 continue;
843 if (r < 0)
844 return log_oom();
845 }
846 }
847
848 int config_parse_hostname(
849 const char *unit,
850 const char *filename,
851 unsigned line,
852 const char *section,
853 unsigned section_line,
854 const char *lvalue,
855 int ltype,
856 const char *rvalue,
857 void *data,
858 void *userdata) {
859
860 char **hostname = data;
861 int r;
862
863 assert(filename);
864 assert(lvalue);
865 assert(rvalue);
866 assert(data);
867
868 if (isempty(rvalue)) {
869 *hostname = mfree(*hostname);
870 return 0;
871 }
872
873 if (!hostname_is_valid(rvalue, 0)) {
874 log_syntax(unit, LOG_WARNING, filename, line, 0,
875 "Hostname is not valid, ignoring assignment: %s", rvalue);
876 return 0;
877 }
878
879 r = dns_name_is_valid(rvalue);
880 if (r < 0) {
881 log_syntax(unit, LOG_WARNING, filename, line, r,
882 "Failed to check validity of hostname '%s', ignoring assignment: %m", rvalue);
883 return 0;
884 }
885 if (r == 0) {
886 log_syntax(unit, LOG_WARNING, filename, line, 0,
887 "Hostname is not a valid DNS domain name, ignoring assignment: %s", rvalue);
888 return 0;
889 }
890
891 return free_and_strdup_warn(hostname, rvalue);
892 }
893
894 int config_parse_timezone(
895 const char *unit,
896 const char *filename,
897 unsigned line,
898 const char *section,
899 unsigned section_line,
900 const char *lvalue,
901 int ltype,
902 const char *rvalue,
903 void *data,
904 void *userdata) {
905
906 char **tz = data;
907 int r;
908
909 assert(filename);
910 assert(lvalue);
911 assert(rvalue);
912 assert(data);
913
914 if (isempty(rvalue)) {
915 *tz = mfree(*tz);
916 return 0;
917 }
918
919 r = verify_timezone(rvalue, LOG_WARNING);
920 if (r < 0) {
921 log_syntax(unit, LOG_WARNING, filename, line, r,
922 "Timezone is not valid, ignoring assignment: %s", rvalue);
923 return 0;
924 }
925
926 return free_and_strdup_warn(tz, rvalue);
927 }
928
929 int config_parse_dns(
930 const char *unit,
931 const char *filename,
932 unsigned line,
933 const char *section,
934 unsigned section_line,
935 const char *lvalue,
936 int ltype,
937 const char *rvalue,
938 void *data,
939 void *userdata) {
940
941 Network *n = userdata;
942 int r;
943
944 assert(filename);
945 assert(lvalue);
946 assert(rvalue);
947 assert(n);
948
949 if (isempty(rvalue)) {
950 for (unsigned i = 0; i < n->n_dns; i++)
951 in_addr_full_free(n->dns[i]);
952 n->dns = mfree(n->dns);
953 n->n_dns = 0;
954 return 0;
955 }
956
957 for (const char *p = rvalue;;) {
958 _cleanup_(in_addr_full_freep) struct in_addr_full *dns = NULL;
959 _cleanup_free_ char *w = NULL;
960 struct in_addr_full **m;
961
962 r = extract_first_word(&p, &w, NULL, 0);
963 if (r == -ENOMEM)
964 return log_oom();
965 if (r < 0) {
966 log_syntax(unit, LOG_WARNING, filename, line, r,
967 "Invalid syntax, ignoring: %s", rvalue);
968 return 0;
969 }
970 if (r == 0)
971 return 0;
972
973 r = in_addr_full_new_from_string(w, &dns);
974 if (r < 0) {
975 log_syntax(unit, LOG_WARNING, filename, line, r,
976 "Failed to parse dns server address, ignoring: %s", w);
977 continue;
978 }
979
980 if (IN_SET(dns->port, 53, 853))
981 dns->port = 0;
982
983 m = reallocarray(n->dns, n->n_dns + 1, sizeof(struct in_addr_full*));
984 if (!m)
985 return log_oom();
986
987 m[n->n_dns++] = TAKE_PTR(dns);
988 n->dns = m;
989 }
990 }
991
992 int config_parse_dnssec_negative_trust_anchors(
993 const char *unit,
994 const char *filename,
995 unsigned line,
996 const char *section,
997 unsigned section_line,
998 const char *lvalue,
999 int ltype,
1000 const char *rvalue,
1001 void *data,
1002 void *userdata) {
1003
1004 Set **nta = data;
1005 int r;
1006
1007 assert(filename);
1008 assert(lvalue);
1009 assert(rvalue);
1010 assert(nta);
1011
1012 if (isempty(rvalue)) {
1013 *nta = set_free_free(*nta);
1014 return 0;
1015 }
1016
1017 for (const char *p = rvalue;;) {
1018 _cleanup_free_ char *w = NULL;
1019
1020 r = extract_first_word(&p, &w, NULL, 0);
1021 if (r == -ENOMEM)
1022 return log_oom();
1023 if (r < 0) {
1024 log_syntax(unit, LOG_WARNING, filename, line, r,
1025 "Failed to extract negative trust anchor domain, ignoring: %s", rvalue);
1026 return 0;
1027 }
1028 if (r == 0)
1029 return 0;
1030
1031 r = dns_name_is_valid(w);
1032 if (r <= 0) {
1033 log_syntax(unit, LOG_WARNING, filename, line, r,
1034 "%s is not a valid domain name, ignoring.", w);
1035 continue;
1036 }
1037
1038 r = set_ensure_consume(nta, &dns_name_hash_ops, TAKE_PTR(w));
1039 if (r < 0)
1040 return log_oom();
1041 }
1042 }
1043
1044 int config_parse_ntp(
1045 const char *unit,
1046 const char *filename,
1047 unsigned line,
1048 const char *section,
1049 unsigned section_line,
1050 const char *lvalue,
1051 int ltype,
1052 const char *rvalue,
1053 void *data,
1054 void *userdata) {
1055
1056 char ***l = data;
1057 int r;
1058
1059 assert(filename);
1060 assert(lvalue);
1061 assert(rvalue);
1062 assert(l);
1063
1064 if (isempty(rvalue)) {
1065 *l = strv_free(*l);
1066 return 0;
1067 }
1068
1069 for (const char *p = rvalue;;) {
1070 _cleanup_free_ char *w = NULL;
1071
1072 r = extract_first_word(&p, &w, NULL, 0);
1073 if (r == -ENOMEM)
1074 return log_oom();
1075 if (r < 0) {
1076 log_syntax(unit, LOG_WARNING, filename, line, r,
1077 "Failed to extract NTP server name, ignoring: %s", rvalue);
1078 return 0;
1079 }
1080 if (r == 0)
1081 return 0;
1082
1083 r = dns_name_is_valid_or_address(w);
1084 if (r <= 0) {
1085 log_syntax(unit, LOG_WARNING, filename, line, r,
1086 "%s is not a valid domain name or IP address, ignoring.", w);
1087 continue;
1088 }
1089
1090 if (strv_length(*l) > MAX_NTP_SERVERS) {
1091 log_syntax(unit, LOG_WARNING, filename, line, 0,
1092 "More than %u NTP servers specified, ignoring \"%s\" and any subsequent entries.",
1093 MAX_NTP_SERVERS, w);
1094 return 0;
1095 }
1096
1097 r = strv_consume(l, TAKE_PTR(w));
1098 if (r < 0)
1099 return log_oom();
1100 }
1101 }
1102
1103 int config_parse_required_for_online(
1104 const char *unit,
1105 const char *filename,
1106 unsigned line,
1107 const char *section,
1108 unsigned section_line,
1109 const char *lvalue,
1110 int ltype,
1111 const char *rvalue,
1112 void *data,
1113 void *userdata) {
1114
1115 Network *network = userdata;
1116 LinkOperationalStateRange range;
1117 bool required = true;
1118 int r;
1119
1120 assert(filename);
1121 assert(lvalue);
1122 assert(rvalue);
1123 assert(network);
1124
1125 if (isempty(rvalue)) {
1126 network->required_for_online = -1;
1127 network->required_operstate_for_online = LINK_OPERSTATE_RANGE_DEFAULT;
1128 return 0;
1129 }
1130
1131 r = parse_operational_state_range(rvalue, &range);
1132 if (r < 0) {
1133 r = parse_boolean(rvalue);
1134 if (r < 0) {
1135 log_syntax(unit, LOG_WARNING, filename, line, r,
1136 "Failed to parse %s= setting, ignoring assignment: %s",
1137 lvalue, rvalue);
1138 return 0;
1139 }
1140
1141 required = r;
1142 range = LINK_OPERSTATE_RANGE_DEFAULT;
1143 }
1144
1145 network->required_for_online = required;
1146 network->required_operstate_for_online = range;
1147
1148 return 0;
1149 }
1150
1151 int config_parse_link_group(
1152 const char *unit,
1153 const char *filename,
1154 unsigned line,
1155 const char *section,
1156 unsigned section_line,
1157 const char *lvalue,
1158 int ltype,
1159 const char *rvalue,
1160 void *data,
1161 void *userdata) {
1162
1163 Network *network = userdata;
1164 int r;
1165
1166 assert(filename);
1167 assert(lvalue);
1168 assert(rvalue);
1169 assert(network);
1170
1171 if (isempty(rvalue)) {
1172 network->group = 0;
1173 network->group_set = false;
1174 return 0;
1175 }
1176
1177 r = safe_atou32(rvalue, &network->group);
1178 if (r < 0) {
1179 log_syntax(unit, LOG_WARNING, filename, line, r,
1180 "Failed to parse Group=, ignoring assignment: %s", rvalue);
1181 return 0;
1182 }
1183
1184 network->group_set = true;
1185 return 0;
1186 }
1187
1188
1189 int config_parse_uplink(
1190 const char *unit,
1191 const char *filename,
1192 unsigned line,
1193 const char *section,
1194 unsigned section_line,
1195 const char *lvalue,
1196 int ltype,
1197 const char *rvalue,
1198 void *data,
1199 void *userdata) {
1200
1201 Network *network = userdata;
1202 int *index, r;
1203 char **name;
1204
1205 assert(filename);
1206 assert(section);
1207 assert(lvalue);
1208 assert(rvalue);
1209
1210 if (streq(section, "DHCPServer")) {
1211 index = &network->dhcp_server_uplink_index;
1212 name = &network->dhcp_server_uplink_name;
1213 } else if (streq(section, "IPv6SendRA")) {
1214 index = &network->router_uplink_index;
1215 name = &network->router_uplink_name;
1216 } else
1217 assert_not_reached();
1218
1219 if (isempty(rvalue) || streq(rvalue, ":auto")) {
1220 *index = UPLINK_INDEX_AUTO;
1221 *name = mfree(*name);
1222 return 0;
1223 }
1224
1225 if (streq(rvalue, ":none")) {
1226 *index = UPLINK_INDEX_NONE;
1227 *name = mfree(*name);
1228 return 0;
1229 }
1230
1231 r = parse_ifindex(rvalue);
1232 if (r > 0) {
1233 *index = r;
1234 *name = mfree(*name);
1235 return 0;
1236 }
1237
1238 if (!ifname_valid_full(rvalue, IFNAME_VALID_ALTERNATIVE)) {
1239 log_syntax(unit, LOG_WARNING, filename, line, 0,
1240 "Invalid interface name in %s=, ignoring assignment: %s", lvalue, rvalue);
1241 return 0;
1242 }
1243
1244 /* The interface name will be resolved later. */
1245 r = free_and_strdup_warn(name, rvalue);
1246 if (r < 0)
1247 return r;
1248
1249 /* Note, if uplink_name is set, then uplink_index will be ignored. So, the below does not mean
1250 * an uplink interface will be selected automatically. */
1251 *index = UPLINK_INDEX_AUTO;
1252 return 0;
1253 }
1254
1255 DEFINE_CONFIG_PARSE_ENUM(config_parse_required_family_for_online, link_required_address_family, AddressFamily,
1256 "Failed to parse RequiredFamilyForOnline= setting");
1257
1258 DEFINE_CONFIG_PARSE_ENUM(config_parse_keep_configuration, keep_configuration, KeepConfiguration,
1259 "Failed to parse KeepConfiguration= setting");
1260
1261 static const char* const keep_configuration_table[_KEEP_CONFIGURATION_MAX] = {
1262 [KEEP_CONFIGURATION_NO] = "no",
1263 [KEEP_CONFIGURATION_DHCP_ON_STOP] = "dhcp-on-stop",
1264 [KEEP_CONFIGURATION_DHCP] = "dhcp",
1265 [KEEP_CONFIGURATION_STATIC] = "static",
1266 [KEEP_CONFIGURATION_YES] = "yes",
1267 };
1268
1269 DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(keep_configuration, KeepConfiguration, KEEP_CONFIGURATION_YES);
1270
1271 static const char* const ipv6_link_local_address_gen_mode_table[_IPV6_LINK_LOCAL_ADDRESS_GEN_MODE_MAX] = {
1272 [IPV6_LINK_LOCAL_ADDRESSS_GEN_MODE_EUI64] = "eui64",
1273 [IPV6_LINK_LOCAL_ADDRESSS_GEN_MODE_NONE] = "none",
1274 [IPV6_LINK_LOCAL_ADDRESSS_GEN_MODE_STABLE_PRIVACY] = "stable-privacy",
1275 [IPV6_LINK_LOCAL_ADDRESSS_GEN_MODE_RANDOM] = "random",
1276 };
1277
1278 DEFINE_STRING_TABLE_LOOKUP(ipv6_link_local_address_gen_mode, IPv6LinkLocalAddressGenMode);
1279 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");
1280
1281 static const char* const activation_policy_table[_ACTIVATION_POLICY_MAX] = {
1282 [ACTIVATION_POLICY_UP] = "up",
1283 [ACTIVATION_POLICY_ALWAYS_UP] = "always-up",
1284 [ACTIVATION_POLICY_MANUAL] = "manual",
1285 [ACTIVATION_POLICY_ALWAYS_DOWN] = "always-down",
1286 [ACTIVATION_POLICY_DOWN] = "down",
1287 [ACTIVATION_POLICY_BOUND] = "bound",
1288 };
1289
1290 DEFINE_STRING_TABLE_LOOKUP(activation_policy, ActivationPolicy);
1291 DEFINE_CONFIG_PARSE_ENUM(config_parse_activation_policy, activation_policy, ActivationPolicy, "Failed to parse activation policy");