]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/network/networkd-network.c
Merge pull request #15911 from poettering/unit-name-tighten
[thirdparty/systemd.git] / src / network / networkd-network.c
1 /* SPDX-License-Identifier: LGPL-2.1+ */
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 "networkd-dhcp-server.h"
16 #include "network-internal.h"
17 #include "networkd-manager.h"
18 #include "networkd-network.h"
19 #include "parse-util.h"
20 #include "path-lookup.h"
21 #include "set.h"
22 #include "socket-util.h"
23 #include "stat-util.h"
24 #include "string-table.h"
25 #include "string-util.h"
26 #include "strv.h"
27 #include "tc.h"
28 #include "util.h"
29
30 /* Let's assume that anything above this number is a user misconfiguration. */
31 #define MAX_NTP_SERVERS 128
32
33 /* Set defaults following RFC7844 */
34 void network_apply_anonymize_if_set(Network *network) {
35 if (!network->dhcp_anonymize)
36 return;
37 /* RFC7844 3.7
38 SHOULD NOT send the Host Name option */
39 network->dhcp_send_hostname = false;
40 /* RFC7844 section 3.:
41 MAY contain the Client Identifier option
42 Section 3.5:
43 clients MUST use client identifiers based solely
44 on the link-layer address */
45 /* NOTE: Using MAC, as it does not reveal extra information,
46 * and some servers might not answer if this option is not sent */
47 network->dhcp_client_identifier = DHCP_CLIENT_ID_MAC;
48 /* RFC 7844 3.10:
49 SHOULD NOT use the Vendor Class Identifier option */
50 network->dhcp_vendor_class_identifier = mfree(network->dhcp_vendor_class_identifier);
51 /* RFC7844 section 3.6.:
52 The client intending to protect its privacy SHOULD only request a
53 minimal number of options in the PRL and SHOULD also randomly shuffle
54 the ordering of option codes in the PRL. If this random ordering
55 cannot be implemented, the client MAY order the option codes in the
56 PRL by option code number (lowest to highest).
57 */
58 /* NOTE: dhcp_use_mtu is false by default,
59 * though it was not initiallized to any value in network_load_one.
60 * Maybe there should be another var called *send*?
61 * (to use the MTU sent by the server but to do not send
62 * the option in the PRL). */
63 network->dhcp_use_mtu = false;
64 /* NOTE: when Anonymize=yes, the PRL route options are sent by default,
65 * but this is needed to use them. */
66 network->dhcp_use_routes = true;
67 /* RFC7844 section 3.6.
68 * same comments as previous option */
69 network->dhcp_use_timezone = false;
70 }
71
72 static int network_resolve_netdev_one(Network *network, const char *name, NetDevKind kind, NetDev **ret_netdev) {
73 const char *kind_string;
74 NetDev *netdev;
75 int r;
76
77 /* For test-networkd-conf, the check must be earlier than the assertions. */
78 if (!name)
79 return 0;
80
81 assert(network);
82 assert(network->manager);
83 assert(network->filename);
84 assert(ret_netdev);
85
86 if (kind == _NETDEV_KIND_TUNNEL)
87 kind_string = "tunnel";
88 else {
89 kind_string = netdev_kind_to_string(kind);
90 if (!kind_string)
91 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
92 "%s: Invalid NetDev kind of %s, ignoring assignment.",
93 network->filename, name);
94 }
95
96 r = netdev_get(network->manager, name, &netdev);
97 if (r < 0)
98 return log_error_errno(r, "%s: %s NetDev could not be found, ignoring assignment.",
99 network->filename, name);
100
101 if (netdev->kind != kind && !(kind == _NETDEV_KIND_TUNNEL &&
102 IN_SET(netdev->kind,
103 NETDEV_KIND_IPIP,
104 NETDEV_KIND_SIT,
105 NETDEV_KIND_GRE,
106 NETDEV_KIND_GRETAP,
107 NETDEV_KIND_IP6GRE,
108 NETDEV_KIND_IP6GRETAP,
109 NETDEV_KIND_VTI,
110 NETDEV_KIND_VTI6,
111 NETDEV_KIND_IP6TNL,
112 NETDEV_KIND_ERSPAN)))
113 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
114 "%s: NetDev %s is not a %s, ignoring assignment",
115 network->filename, name, kind_string);
116
117 *ret_netdev = netdev_ref(netdev);
118 return 1;
119 }
120
121 static int network_resolve_stacked_netdevs(Network *network) {
122 void *name, *kind;
123 Iterator i;
124 int r;
125
126 assert(network);
127
128 HASHMAP_FOREACH_KEY(kind, name, network->stacked_netdev_names, i) {
129 _cleanup_(netdev_unrefp) NetDev *netdev = NULL;
130
131 r = network_resolve_netdev_one(network, name, PTR_TO_INT(kind), &netdev);
132 if (r <= 0)
133 continue;
134
135 r = hashmap_ensure_allocated(&network->stacked_netdevs, &string_hash_ops);
136 if (r < 0)
137 return log_oom();
138
139 r = hashmap_put(network->stacked_netdevs, netdev->ifname, netdev);
140 if (r < 0)
141 return log_error_errno(r, "%s: Failed to add NetDev '%s' to network: %m",
142 network->filename, (const char *) name);
143
144 netdev = NULL;
145 }
146
147 return 0;
148 }
149
150 int network_verify(Network *network) {
151 RoutePrefix *route_prefix, *route_prefix_next;
152 RoutingPolicyRule *rule, *rule_next;
153 Neighbor *neighbor, *neighbor_next;
154 AddressLabel *label, *label_next;
155 NextHop *nexthop, *nextnop_next;
156 Address *address, *address_next;
157 Prefix *prefix, *prefix_next;
158 Route *route, *route_next;
159 FdbEntry *fdb, *fdb_next;
160 TrafficControl *tc;
161 Iterator i;
162
163 assert(network);
164 assert(network->filename);
165
166 if (set_isempty(network->match_mac) && set_isempty(network->match_permanent_mac) &&
167 strv_isempty(network->match_path) && strv_isempty(network->match_driver) &&
168 strv_isempty(network->match_type) && strv_isempty(network->match_name) &&
169 strv_isempty(network->match_property) && strv_isempty(network->match_ssid) && !network->conditions)
170 return log_warning_errno(SYNTHETIC_ERRNO(EINVAL),
171 "%s: No valid settings found in the [Match] section, ignoring file. "
172 "To match all interfaces, add Name=* in the [Match] section.",
173 network->filename);
174
175 /* skip out early if configuration does not match the environment */
176 if (!condition_test_list(network->conditions, environ, NULL, NULL, NULL))
177 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL),
178 "%s: Conditions in the file do not match the system environment, skipping.",
179 network->filename);
180
181 (void) network_resolve_netdev_one(network, network->bond_name, NETDEV_KIND_BOND, &network->bond);
182 (void) network_resolve_netdev_one(network, network->bridge_name, NETDEV_KIND_BRIDGE, &network->bridge);
183 (void) network_resolve_netdev_one(network, network->vrf_name, NETDEV_KIND_VRF, &network->vrf);
184 (void) network_resolve_stacked_netdevs(network);
185
186 /* Free unnecessary entries. */
187 network->bond_name = mfree(network->bond_name);
188 network->bridge_name = mfree(network->bridge_name);
189 network->vrf_name = mfree(network->vrf_name);
190 network->stacked_netdev_names = hashmap_free_free_key(network->stacked_netdev_names);
191
192 if (network->bond) {
193 /* Bonding slave does not support addressing. */
194 if (network->ipv6_accept_ra > 0) {
195 log_warning("%s: Cannot enable IPv6AcceptRA= when Bond= is specified, disabling IPv6AcceptRA=.",
196 network->filename);
197 network->ipv6_accept_ra = 0;
198 }
199 if (network->link_local >= 0 && network->link_local != ADDRESS_FAMILY_NO) {
200 log_warning("%s: Cannot enable LinkLocalAddressing= when Bond= is specified, disabling LinkLocalAddressing=.",
201 network->filename);
202 network->link_local = ADDRESS_FAMILY_NO;
203 }
204 if (network->dhcp != ADDRESS_FAMILY_NO) {
205 log_warning("%s: Cannot enable DHCP= when Bond= is specified, disabling DHCP=.",
206 network->filename);
207 network->dhcp = ADDRESS_FAMILY_NO;
208 }
209 if (network->dhcp_server) {
210 log_warning("%s: Cannot enable DHCPServer= when Bond= is specified, disabling DHCPServer=.",
211 network->filename);
212 network->dhcp_server = false;
213 }
214 if (network->n_static_addresses > 0) {
215 log_warning("%s: Cannot set addresses when Bond= is specified, ignoring addresses.",
216 network->filename);
217 while ((address = network->static_addresses))
218 address_free(address);
219 }
220 if (network->n_static_routes > 0) {
221 log_warning("%s: Cannot set routes when Bond= is specified, ignoring routes.",
222 network->filename);
223 while ((route = network->static_routes))
224 route_free(route);
225 }
226 }
227
228 if (network->link_local < 0)
229 network->link_local = network->bridge ? ADDRESS_FAMILY_NO : ADDRESS_FAMILY_IPV6;
230
231 if (!FLAGS_SET(network->link_local, ADDRESS_FAMILY_IPV6)) {
232 if (network->ipv6_accept_ra > 0) {
233 log_warning("%s: IPv6AcceptRA= is enabled by the .network file but IPv6 link local addressing is disabled. "
234 "Disabling IPv6AcceptRA=.", network->filename);
235 network->ipv6_accept_ra = false;
236 }
237
238 if (FLAGS_SET(network->dhcp, ADDRESS_FAMILY_IPV6)) {
239 log_warning("%s: DHCPv6 client is enabled by the .network file but IPv6 link local addressing is disabled. "
240 "Disabling DHCPv6 client.", network->filename);
241 SET_FLAG(network->dhcp, ADDRESS_FAMILY_IPV6, false);
242 }
243
244 if (network->router_prefix_delegation != RADV_PREFIX_DELEGATION_NONE) {
245 log_warning("%s: IPv6PrefixDelegation= is enabled but IPv6 link local addressing is disabled. "
246 "Disabling IPv6PrefixDelegation=.", network->filename);
247 network->router_prefix_delegation = RADV_PREFIX_DELEGATION_NONE;
248 }
249 }
250
251 if (FLAGS_SET(network->link_local, ADDRESS_FAMILY_FALLBACK_IPV4) &&
252 !FLAGS_SET(network->dhcp, ADDRESS_FAMILY_IPV4)) {
253 log_warning("%s: fallback assignment of IPv4 link local address is enabled but DHCPv4 is disabled. "
254 "Disabling the fallback assignment.", network->filename);
255 SET_FLAG(network->link_local, ADDRESS_FAMILY_FALLBACK_IPV4, false);
256 }
257
258 if (network->ipv6_accept_ra < 0 && network->bridge)
259 network->ipv6_accept_ra = false;
260
261 /* IPMasquerade=yes implies IPForward=yes */
262 if (network->ip_masquerade)
263 network->ip_forward |= ADDRESS_FAMILY_IPV4;
264
265 if (network->mtu > 0 && network->dhcp_use_mtu) {
266 log_warning("%s: MTUBytes= in [Link] section and UseMTU= in [DHCP] section are set. "
267 "Disabling UseMTU=.", network->filename);
268 network->dhcp_use_mtu = false;
269 }
270
271 if (network->dhcp_use_gateway < 0)
272 network->dhcp_use_gateway = network->dhcp_use_routes;
273
274 if (network->ignore_carrier_loss < 0)
275 network->ignore_carrier_loss = network->configure_without_carrier;
276
277 if (network->dhcp_critical >= 0) {
278 if (network->keep_configuration >= 0)
279 log_warning("%s: Both KeepConfiguration= and deprecated CriticalConnection= are set. "
280 "Ignoring CriticalConnection=.", network->filename);
281 else if (network->dhcp_critical)
282 /* CriticalConnection=yes also preserve foreign static configurations. */
283 network->keep_configuration = KEEP_CONFIGURATION_YES;
284 else
285 network->keep_configuration = KEEP_CONFIGURATION_NO;
286 }
287
288 if (network->keep_configuration < 0)
289 network->keep_configuration = KEEP_CONFIGURATION_NO;
290
291 LIST_FOREACH_SAFE(addresses, address, address_next, network->static_addresses)
292 if (address_section_verify(address) < 0)
293 address_free(address);
294
295 LIST_FOREACH_SAFE(routes, route, route_next, network->static_routes)
296 if (route_section_verify(route, network) < 0)
297 route_free(route);
298
299 LIST_FOREACH_SAFE(nexthops, nexthop, nextnop_next, network->static_nexthops)
300 if (nexthop_section_verify(nexthop) < 0)
301 nexthop_free(nexthop);
302
303 LIST_FOREACH_SAFE(static_fdb_entries, fdb, fdb_next, network->static_fdb_entries)
304 if (section_is_invalid(fdb->section))
305 fdb_entry_free(fdb);
306
307 LIST_FOREACH_SAFE(neighbors, neighbor, neighbor_next, network->neighbors)
308 if (neighbor_section_verify(neighbor) < 0)
309 neighbor_free(neighbor);
310
311 LIST_FOREACH_SAFE(labels, label, label_next, network->address_labels)
312 if (section_is_invalid(label->section))
313 address_label_free(label);
314
315 LIST_FOREACH_SAFE(prefixes, prefix, prefix_next, network->static_prefixes)
316 if (section_is_invalid(prefix->section))
317 prefix_free(prefix);
318
319 LIST_FOREACH_SAFE(route_prefixes, route_prefix, route_prefix_next, network->static_route_prefixes)
320 if (section_is_invalid(route_prefix->section))
321 route_prefix_free(route_prefix);
322
323 LIST_FOREACH_SAFE(rules, rule, rule_next, network->rules)
324 if (routing_policy_rule_section_verify(rule) < 0)
325 routing_policy_rule_free(rule);
326
327 bool has_root = false, has_clsact = false;
328 ORDERED_HASHMAP_FOREACH(tc, network->tc_by_section, i)
329 if (traffic_control_section_verify(tc, &has_root, &has_clsact) < 0)
330 traffic_control_free(tc);
331
332 return 0;
333 }
334
335 int network_load_one(Manager *manager, OrderedHashmap **networks, const char *filename) {
336 _cleanup_free_ char *fname = NULL, *name = NULL;
337 _cleanup_(network_unrefp) Network *network = NULL;
338 _cleanup_fclose_ FILE *file = NULL;
339 const char *dropin_dirname;
340 char *d;
341 int r;
342
343 assert(manager);
344 assert(filename);
345
346 file = fopen(filename, "re");
347 if (!file) {
348 if (errno == ENOENT)
349 return 0;
350
351 return -errno;
352 }
353
354 if (null_or_empty_fd(fileno(file))) {
355 log_debug("Skipping empty file: %s", filename);
356 return 0;
357 }
358
359 fname = strdup(filename);
360 if (!fname)
361 return log_oom();
362
363 name = strdup(basename(filename));
364 if (!name)
365 return log_oom();
366
367 d = strrchr(name, '.');
368 if (!d)
369 return -EINVAL;
370
371 *d = '\0';
372
373 dropin_dirname = strjoina(name, ".network.d");
374
375 network = new(Network, 1);
376 if (!network)
377 return log_oom();
378
379 *network = (Network) {
380 .filename = TAKE_PTR(fname),
381 .name = TAKE_PTR(name),
382
383 .manager = manager,
384 .n_ref = 1,
385
386 .required_for_online = true,
387 .required_operstate_for_online = LINK_OPERSTATE_RANGE_DEFAULT,
388 .dhcp = ADDRESS_FAMILY_NO,
389 .dhcp_critical = -1,
390 .dhcp_use_ntp = true,
391 .dhcp_use_sip = true,
392 .dhcp_use_dns = true,
393 .dhcp_use_hostname = true,
394 .dhcp_use_routes = true,
395 .dhcp_use_gateway = -1,
396 /* NOTE: this var might be overwritten by network_apply_anonymize_if_set */
397 .dhcp_send_hostname = true,
398 .dhcp_send_release = true,
399 /* To enable/disable RFC7844 Anonymity Profiles */
400 .dhcp_anonymize = false,
401 .dhcp_route_metric = DHCP_ROUTE_METRIC,
402 /* NOTE: this var might be overwritten by network_apply_anonymize_if_set */
403 .dhcp_client_identifier = DHCP_CLIENT_ID_DUID,
404 .dhcp_route_table = RT_TABLE_MAIN,
405 .dhcp_route_table_set = false,
406 /* NOTE: from man: UseMTU=... Defaults to false*/
407 .dhcp_use_mtu = false,
408 /* NOTE: from man: UseTimezone=... Defaults to "no".*/
409 .dhcp_use_timezone = false,
410 .rapid_commit = true,
411
412 .dhcp6_use_ntp = true,
413 .dhcp6_use_dns = true,
414
415 .dhcp_server_emit_dns = true,
416 .dhcp_server_emit_ntp = true,
417 .dhcp_server_emit_sip = true,
418 .dhcp_server_emit_router = true,
419 .dhcp_server_emit_timezone = true,
420
421 .router_prefix_subnet_id = -1,
422 .router_emit_dns = true,
423 .router_emit_domains = true,
424
425 .use_bpdu = -1,
426 .hairpin = -1,
427 .fast_leave = -1,
428 .allow_port_to_be_root = -1,
429 .unicast_flood = -1,
430 .multicast_flood = -1,
431 .multicast_to_unicast = -1,
432 .neighbor_suppression = -1,
433 .learning = -1,
434 .bridge_proxy_arp = -1,
435 .bridge_proxy_arp_wifi = -1,
436 .priority = LINK_BRIDGE_PORT_PRIORITY_INVALID,
437 .multicast_router = _MULTICAST_ROUTER_INVALID,
438
439 .lldp_mode = LLDP_MODE_ROUTERS_ONLY,
440
441 .dns_default_route = -1,
442 .llmnr = RESOLVE_SUPPORT_YES,
443 .mdns = RESOLVE_SUPPORT_NO,
444 .dnssec_mode = _DNSSEC_MODE_INVALID,
445 .dns_over_tls_mode = _DNS_OVER_TLS_MODE_INVALID,
446
447 /* If LinkLocalAddressing= is not set, then set to ADDRESS_FAMILY_IPV6 later. */
448 .link_local = _ADDRESS_FAMILY_INVALID,
449
450 .ipv6_privacy_extensions = IPV6_PRIVACY_EXTENSIONS_NO,
451 .ipv6_accept_ra = -1,
452 .ipv6_dad_transmits = -1,
453 .ipv6_hop_limit = -1,
454 .ipv6_proxy_ndp = -1,
455 .duid.type = _DUID_TYPE_INVALID,
456 .proxy_arp = -1,
457 .arp = -1,
458 .multicast = -1,
459 .allmulticast = -1,
460 .ipv6_accept_ra_use_dns = true,
461 .ipv6_accept_ra_use_autonomous_prefix = true,
462 .ipv6_accept_ra_use_onlink_prefix = true,
463 .ipv6_accept_ra_route_table = RT_TABLE_MAIN,
464 .ipv6_accept_ra_route_table_set = false,
465 .ipv6_accept_ra_start_dhcp6_client = true,
466
467 .configure_without_carrier = false,
468 .ignore_carrier_loss = -1,
469 .keep_configuration = _KEEP_CONFIGURATION_INVALID,
470 .ipv6_address_gen_mode = _LINK_IPV6_ADDRESS_GEN_MODE_INVALID,
471 .can_triple_sampling = -1,
472 .can_termination = -1,
473 .ip_service_type = -1,
474 };
475
476 r = config_parse_many(filename, NETWORK_DIRS, dropin_dirname,
477 "Match\0"
478 "Link\0"
479 "Network\0"
480 "Address\0"
481 "Neighbor\0"
482 "IPv6AddressLabel\0"
483 "RoutingPolicyRule\0"
484 "Route\0"
485 "NextHop\0"
486 "DHCP\0" /* compat */
487 "DHCPv4\0"
488 "DHCPv6\0"
489 "DHCPServer\0"
490 "IPv6AcceptRA\0"
491 "IPv6NDPProxyAddress\0"
492 "Bridge\0"
493 "BridgeFDB\0"
494 "BridgeVLAN\0"
495 "IPv6PrefixDelegation\0"
496 "IPv6Prefix\0"
497 "IPv6RoutePrefix\0"
498 "LLDP\0"
499 "TrafficControlQueueingDiscipline\0"
500 "CAN\0"
501 "QDisc\0"
502 "BFIFO\0"
503 "CAKE\0"
504 "ControlledDelay\0"
505 "DeficitRoundRobinScheduler\0"
506 "DeficitRoundRobinSchedulerClass\0"
507 "PFIFO\0"
508 "PFIFOFast\0"
509 "PFIFOHeadDrop\0"
510 "FairQueueing\0"
511 "FairQueueingControlledDelay\0"
512 "GenericRandomEarlyDetection\0"
513 "HeavyHitterFilter\0"
514 "HierarchyTokenBucket\0"
515 "HierarchyTokenBucketClass\0"
516 "NetworkEmulator\0"
517 "PIE\0"
518 "StochasticFairBlue\0"
519 "StochasticFairnessQueueing\0"
520 "TokenBucketFilter\0"
521 "TrivialLinkEqualizer\0",
522 config_item_perf_lookup, network_network_gperf_lookup,
523 CONFIG_PARSE_WARN, network);
524 if (r < 0)
525 return r;
526
527 network_apply_anonymize_if_set(network);
528
529 r = network_add_ipv4ll_route(network);
530 if (r < 0)
531 log_warning_errno(r, "%s: Failed to add IPv4LL route, ignoring: %m", network->filename);
532
533 r = network_add_default_route_on_device(network);
534 if (r < 0)
535 log_warning_errno(r, "%s: Failed to add default route on device, ignoring: %m",
536 network->filename);
537
538 struct stat stats;
539 if (stat(filename, &stats) < 0)
540 return -errno;
541 network->timestamp = timespec_load(&stats.st_mtim);
542
543 if (network_verify(network) < 0)
544 /* Ignore .network files that do not match the conditions. */
545 return 0;
546
547 r = ordered_hashmap_ensure_allocated(networks, &string_hash_ops);
548 if (r < 0)
549 return r;
550
551 r = ordered_hashmap_put(*networks, network->name, network);
552 if (r < 0)
553 return r;
554
555 network = NULL;
556 return 0;
557 }
558
559 int network_load(Manager *manager, OrderedHashmap **networks) {
560 _cleanup_strv_free_ char **files = NULL;
561 char **f;
562 int r;
563
564 assert(manager);
565
566 ordered_hashmap_clear_with_destructor(*networks, network_unref);
567
568 r = conf_files_list_strv(&files, ".network", NULL, 0, NETWORK_DIRS);
569 if (r < 0)
570 return log_error_errno(r, "Failed to enumerate network files: %m");
571
572 STRV_FOREACH(f, files) {
573 r = network_load_one(manager, networks, *f);
574 if (r < 0)
575 log_error_errno(r, "Failed to load %s, ignoring: %m", *f);
576 }
577
578 return 0;
579 }
580
581 int network_reload(Manager *manager) {
582 OrderedHashmap *new_networks = NULL;
583 Network *n, *old;
584 Iterator i;
585 int r;
586
587 assert(manager);
588
589 r = network_load(manager, &new_networks);
590 if (r < 0)
591 goto failure;
592
593 ORDERED_HASHMAP_FOREACH(n, new_networks, i) {
594 r = network_get_by_name(manager, n->name, &old);
595 if (r < 0)
596 continue; /* The .network file is new. */
597
598 if (n->timestamp != old->timestamp)
599 continue; /* The .network file is modified. */
600
601 if (!streq(n->filename, old->filename))
602 continue;
603
604 r = ordered_hashmap_replace(new_networks, old->name, old);
605 if (r < 0)
606 goto failure;
607
608 network_ref(old);
609 network_unref(n);
610 }
611
612 ordered_hashmap_free_with_destructor(manager->networks, network_unref);
613 manager->networks = new_networks;
614
615 return 0;
616
617 failure:
618 ordered_hashmap_free_with_destructor(new_networks, network_unref);
619
620 return r;
621 }
622
623 static Network *network_free(Network *network) {
624 IPv6ProxyNDPAddress *ipv6_proxy_ndp_address;
625 RoutePrefix *route_prefix;
626 RoutingPolicyRule *rule;
627 AddressLabel *label;
628 FdbEntry *fdb_entry;
629 Neighbor *neighbor;
630 Address *address;
631 NextHop *nexthop;
632 Prefix *prefix;
633 Route *route;
634
635 if (!network)
636 return NULL;
637
638 free(network->filename);
639
640 set_free_free(network->match_mac);
641 set_free_free(network->match_permanent_mac);
642 strv_free(network->match_path);
643 strv_free(network->match_driver);
644 strv_free(network->match_type);
645 strv_free(network->match_name);
646 strv_free(network->match_property);
647 strv_free(network->match_wlan_iftype);
648 strv_free(network->match_ssid);
649 set_free_free(network->match_bssid);
650 condition_free_list(network->conditions);
651
652 free(network->description);
653 free(network->dhcp_vendor_class_identifier);
654 free(network->dhcp_mudurl);
655 strv_free(network->dhcp_user_class);
656 free(network->dhcp_hostname);
657 set_free(network->dhcp_black_listed_ip);
658 set_free(network->dhcp_request_options);
659 set_free(network->dhcp6_request_options);
660 free(network->mac);
661 free(network->dhcp6_mudurl);
662 strv_free(network->dhcp6_user_class);
663 strv_free(network->dhcp6_vendor_class);
664
665 if (network->dhcp_acd)
666 sd_ipv4acd_unref(network->dhcp_acd);
667
668 strv_free(network->ntp);
669 free(network->dns);
670 strv_free(network->sip);
671 strv_free(network->smtp);
672 ordered_set_free_free(network->search_domains);
673 ordered_set_free_free(network->route_domains);
674 strv_free(network->bind_carrier);
675
676 ordered_set_free_free(network->router_search_domains);
677 free(network->router_dns);
678 set_free_free(network->ndisc_black_listed_prefix);
679
680 free(network->bridge_name);
681 free(network->bond_name);
682 free(network->vrf_name);
683 hashmap_free_free_key(network->stacked_netdev_names);
684 netdev_unref(network->bridge);
685 netdev_unref(network->bond);
686 netdev_unref(network->vrf);
687 hashmap_free_with_destructor(network->stacked_netdevs, netdev_unref);
688
689 while ((route = network->static_routes))
690 route_free(route);
691
692 while ((nexthop = network->static_nexthops))
693 nexthop_free(nexthop);
694
695 while ((address = network->static_addresses))
696 address_free(address);
697
698 while ((fdb_entry = network->static_fdb_entries))
699 fdb_entry_free(fdb_entry);
700
701 while ((ipv6_proxy_ndp_address = network->ipv6_proxy_ndp_addresses))
702 ipv6_proxy_ndp_address_free(ipv6_proxy_ndp_address);
703
704 while ((neighbor = network->neighbors))
705 neighbor_free(neighbor);
706
707 while ((label = network->address_labels))
708 address_label_free(label);
709
710 while ((prefix = network->static_prefixes))
711 prefix_free(prefix);
712
713 while ((route_prefix = network->static_route_prefixes))
714 route_prefix_free(route_prefix);
715
716 while ((rule = network->rules))
717 routing_policy_rule_free(rule);
718
719 hashmap_free(network->addresses_by_section);
720 hashmap_free(network->routes_by_section);
721 hashmap_free(network->nexthops_by_section);
722 hashmap_free(network->fdb_entries_by_section);
723 hashmap_free(network->neighbors_by_section);
724 hashmap_free(network->address_labels_by_section);
725 hashmap_free(network->prefixes_by_section);
726 hashmap_free(network->route_prefixes_by_section);
727 hashmap_free(network->rules_by_section);
728 ordered_hashmap_free_with_destructor(network->tc_by_section, traffic_control_free);
729
730 if (network->manager &&
731 network->manager->duids_requesting_uuid)
732 set_remove(network->manager->duids_requesting_uuid, &network->duid);
733
734 free(network->name);
735
736 free(network->dhcp_server_timezone);
737 free(network->dhcp_server_dns);
738 free(network->dhcp_server_ntp);
739 free(network->dhcp_server_sip);
740
741 set_free_free(network->dnssec_negative_trust_anchors);
742
743 free(network->lldp_mud);
744
745 ordered_hashmap_free(network->dhcp_client_send_options);
746 ordered_hashmap_free(network->dhcp_client_send_vendor_options);
747 ordered_hashmap_free(network->dhcp_server_send_options);
748 ordered_hashmap_free(network->dhcp_server_send_vendor_options);
749 ordered_hashmap_free(network->ipv6_tokens);
750
751 return mfree(network);
752 }
753
754 DEFINE_TRIVIAL_REF_UNREF_FUNC(Network, network, network_free);
755
756 int network_get_by_name(Manager *manager, const char *name, Network **ret) {
757 Network *network;
758
759 assert(manager);
760 assert(name);
761 assert(ret);
762
763 network = ordered_hashmap_get(manager->networks, name);
764 if (!network)
765 return -ENOENT;
766
767 *ret = network;
768
769 return 0;
770 }
771
772 int network_get(Manager *manager, unsigned short iftype, sd_device *device,
773 const char *ifname, char * const *alternative_names,
774 const struct ether_addr *address, const struct ether_addr *permanent_address,
775 enum nl80211_iftype wlan_iftype, const char *ssid, const struct ether_addr *bssid,
776 Network **ret) {
777 Network *network;
778 Iterator i;
779
780 assert(manager);
781 assert(ret);
782
783 ORDERED_HASHMAP_FOREACH(network, manager->networks, i)
784 if (net_match_config(network->match_mac, network->match_permanent_mac,
785 network->match_path, network->match_driver,
786 network->match_type, network->match_name, network->match_property,
787 network->match_wlan_iftype, network->match_ssid, network->match_bssid,
788 iftype, device, address, permanent_address,
789 ifname, alternative_names, wlan_iftype, ssid, bssid)) {
790 if (network->match_name && device) {
791 const char *attr;
792 uint8_t name_assign_type = NET_NAME_UNKNOWN;
793
794 if (sd_device_get_sysattr_value(device, "name_assign_type", &attr) >= 0)
795 (void) safe_atou8(attr, &name_assign_type);
796
797 if (name_assign_type == NET_NAME_ENUM)
798 log_warning("%s: found matching network '%s', based on potentially unpredictable ifname",
799 ifname, network->filename);
800 else
801 log_debug("%s: found matching network '%s'", ifname, network->filename);
802 } else
803 log_debug("%s: found matching network '%s'", ifname, network->filename);
804
805 *ret = network;
806 return 0;
807 }
808
809 *ret = NULL;
810
811 return -ENOENT;
812 }
813
814 int network_apply(Network *network, Link *link) {
815 assert(network);
816 assert(link);
817
818 link->network = network_ref(network);
819
820 if (network->n_dns > 0 ||
821 !strv_isempty(network->ntp) ||
822 !ordered_set_isempty(network->search_domains) ||
823 !ordered_set_isempty(network->route_domains))
824 link_dirty(link);
825
826 return 0;
827 }
828
829 bool network_has_static_ipv6_configurations(Network *network) {
830 Address *address;
831 Route *route;
832 FdbEntry *fdb;
833 Neighbor *neighbor;
834
835 assert(network);
836
837 LIST_FOREACH(addresses, address, network->static_addresses)
838 if (address->family == AF_INET6)
839 return true;
840
841 LIST_FOREACH(routes, route, network->static_routes)
842 if (route->family == AF_INET6)
843 return true;
844
845 LIST_FOREACH(static_fdb_entries, fdb, network->static_fdb_entries)
846 if (fdb->family == AF_INET6)
847 return true;
848
849 LIST_FOREACH(neighbors, neighbor, network->neighbors)
850 if (neighbor->family == AF_INET6)
851 return true;
852
853 if (!LIST_IS_EMPTY(network->address_labels))
854 return true;
855
856 if (!LIST_IS_EMPTY(network->static_prefixes))
857 return true;
858
859 return false;
860 }
861
862 int config_parse_stacked_netdev(const char *unit,
863 const char *filename,
864 unsigned line,
865 const char *section,
866 unsigned section_line,
867 const char *lvalue,
868 int ltype,
869 const char *rvalue,
870 void *data,
871 void *userdata) {
872 _cleanup_free_ char *name = NULL;
873 NetDevKind kind = ltype;
874 Hashmap **h = data;
875 int r;
876
877 assert(filename);
878 assert(lvalue);
879 assert(rvalue);
880 assert(data);
881 assert(IN_SET(kind,
882 NETDEV_KIND_VLAN, NETDEV_KIND_MACVLAN, NETDEV_KIND_MACVTAP,
883 NETDEV_KIND_IPVLAN, NETDEV_KIND_IPVTAP, NETDEV_KIND_VXLAN,
884 NETDEV_KIND_L2TP, NETDEV_KIND_MACSEC, _NETDEV_KIND_TUNNEL,
885 NETDEV_KIND_XFRM));
886
887 if (!ifname_valid(rvalue)) {
888 log_syntax(unit, LOG_ERR, filename, line, 0,
889 "Invalid netdev name in %s=, ignoring assignment: %s", lvalue, rvalue);
890 return 0;
891 }
892
893 name = strdup(rvalue);
894 if (!name)
895 return log_oom();
896
897 r = hashmap_ensure_allocated(h, &string_hash_ops);
898 if (r < 0)
899 return log_oom();
900
901 r = hashmap_put(*h, name, INT_TO_PTR(kind));
902 if (r < 0)
903 log_syntax(unit, LOG_ERR, filename, line, r,
904 "Cannot add NetDev '%s' to network, ignoring assignment: %m", name);
905 else if (r == 0)
906 log_syntax(unit, LOG_DEBUG, filename, line, r,
907 "NetDev '%s' specified twice, ignoring.", name);
908 else
909 name = NULL;
910
911 return 0;
912 }
913
914 int config_parse_domains(
915 const char *unit,
916 const char *filename,
917 unsigned line,
918 const char *section,
919 unsigned section_line,
920 const char *lvalue,
921 int ltype,
922 const char *rvalue,
923 void *data,
924 void *userdata) {
925
926 const char *p;
927 Network *n = data;
928 int r;
929
930 assert(n);
931 assert(lvalue);
932 assert(rvalue);
933
934 if (isempty(rvalue)) {
935 n->search_domains = ordered_set_free_free(n->search_domains);
936 n->route_domains = ordered_set_free_free(n->route_domains);
937 return 0;
938 }
939
940 p = rvalue;
941 for (;;) {
942 _cleanup_free_ char *w = NULL, *normalized = NULL;
943 const char *domain;
944 bool is_route;
945
946 r = extract_first_word(&p, &w, NULL, 0);
947 if (r < 0) {
948 log_syntax(unit, LOG_ERR, filename, line, r,
949 "Failed to extract search or route domain, ignoring: %s", rvalue);
950 break;
951 }
952 if (r == 0)
953 break;
954
955 is_route = w[0] == '~';
956 domain = is_route ? w + 1 : w;
957
958 if (dns_name_is_root(domain) || streq(domain, "*")) {
959 /* If the root domain appears as is, or the special token "*" is found, we'll
960 * consider this as routing domain, unconditionally. */
961 is_route = true;
962 domain = "."; /* make sure we don't allow empty strings, thus write the root
963 * domain as "." */
964 } else {
965 r = dns_name_normalize(domain, 0, &normalized);
966 if (r < 0) {
967 log_syntax(unit, LOG_ERR, filename, line, r,
968 "'%s' is not a valid domain name, ignoring.", domain);
969 continue;
970 }
971
972 domain = normalized;
973
974 if (is_localhost(domain)) {
975 log_syntax(unit, LOG_ERR, filename, line, 0,
976 "'localhost' domain may not be configured as search or route domain, ignoring assignment: %s",
977 domain);
978 continue;
979 }
980 }
981
982 OrderedSet **set = is_route ? &n->route_domains : &n->search_domains;
983 r = ordered_set_ensure_allocated(set, &string_hash_ops);
984 if (r < 0)
985 return r;
986
987 r = ordered_set_put_strdup(*set, domain);
988 if (r < 0)
989 return log_oom();
990 }
991
992 return 0;
993 }
994
995 int config_parse_ipv6token(
996 const char* unit,
997 const char *filename,
998 unsigned line,
999 const char *section,
1000 unsigned section_line,
1001 const char *lvalue,
1002 int ltype,
1003 const char *rvalue,
1004 void *data,
1005 void *userdata) {
1006
1007 union in_addr_union buffer;
1008 struct in6_addr *token = data;
1009 int r;
1010
1011 assert(filename);
1012 assert(lvalue);
1013 assert(rvalue);
1014 assert(token);
1015
1016 r = in_addr_from_string(AF_INET6, rvalue, &buffer);
1017 if (r < 0) {
1018 log_syntax(unit, LOG_ERR, filename, line, r,
1019 "Failed to parse IPv6 token, ignoring: %s", rvalue);
1020 return 0;
1021 }
1022
1023 if (in_addr_is_null(AF_INET6, &buffer)) {
1024 log_syntax(unit, LOG_ERR, filename, line, 0,
1025 "IPv6 token cannot be the ANY address, ignoring: %s", rvalue);
1026 return 0;
1027 }
1028
1029 if ((buffer.in6.s6_addr32[0] | buffer.in6.s6_addr32[1]) != 0) {
1030 log_syntax(unit, LOG_ERR, filename, line, 0,
1031 "IPv6 token cannot be longer than 64 bits, ignoring: %s", rvalue);
1032 return 0;
1033 }
1034
1035 *token = buffer.in6;
1036
1037 return 0;
1038 }
1039
1040 static const char* const ipv6_privacy_extensions_table[_IPV6_PRIVACY_EXTENSIONS_MAX] = {
1041 [IPV6_PRIVACY_EXTENSIONS_NO] = "no",
1042 [IPV6_PRIVACY_EXTENSIONS_PREFER_PUBLIC] = "prefer-public",
1043 [IPV6_PRIVACY_EXTENSIONS_YES] = "yes",
1044 };
1045
1046 DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(ipv6_privacy_extensions, IPv6PrivacyExtensions,
1047 IPV6_PRIVACY_EXTENSIONS_YES);
1048
1049 int config_parse_ipv6_privacy_extensions(
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 IPv6PrivacyExtensions s, *ipv6_privacy_extensions = data;
1062
1063 assert(filename);
1064 assert(lvalue);
1065 assert(rvalue);
1066 assert(ipv6_privacy_extensions);
1067
1068 s = ipv6_privacy_extensions_from_string(rvalue);
1069 if (s < 0) {
1070 if (streq(rvalue, "kernel"))
1071 s = _IPV6_PRIVACY_EXTENSIONS_INVALID;
1072 else {
1073 log_syntax(unit, LOG_ERR, filename, line, 0,
1074 "Failed to parse IPv6 privacy extensions option, ignoring: %s", rvalue);
1075 return 0;
1076 }
1077 }
1078
1079 *ipv6_privacy_extensions = s;
1080
1081 return 0;
1082 }
1083
1084 int config_parse_hostname(
1085 const char *unit,
1086 const char *filename,
1087 unsigned line,
1088 const char *section,
1089 unsigned section_line,
1090 const char *lvalue,
1091 int ltype,
1092 const char *rvalue,
1093 void *data,
1094 void *userdata) {
1095
1096 _cleanup_free_ char *hn = NULL;
1097 char **hostname = data;
1098 int r;
1099
1100 assert(filename);
1101 assert(lvalue);
1102 assert(rvalue);
1103
1104 r = config_parse_string(unit, filename, line, section, section_line, lvalue, ltype, rvalue, &hn, userdata);
1105 if (r < 0)
1106 return r;
1107
1108 if (!hostname_is_valid(hn, false)) {
1109 log_syntax(unit, LOG_ERR, filename, line, 0,
1110 "Hostname is not valid, ignoring assignment: %s", rvalue);
1111 return 0;
1112 }
1113
1114 r = dns_name_is_valid(hn);
1115 if (r < 0) {
1116 log_syntax(unit, LOG_ERR, filename, line, r,
1117 "Failed to check validity of hostname '%s', ignoring assignment: %m", rvalue);
1118 return 0;
1119 }
1120 if (r == 0) {
1121 log_syntax(unit, LOG_ERR, filename, line, 0,
1122 "Hostname is not a valid DNS domain name, ignoring assignment: %s", rvalue);
1123 return 0;
1124 }
1125
1126 return free_and_replace(*hostname, hn);
1127 }
1128
1129 int config_parse_timezone(
1130 const char *unit,
1131 const char *filename,
1132 unsigned line,
1133 const char *section,
1134 unsigned section_line,
1135 const char *lvalue,
1136 int ltype,
1137 const char *rvalue,
1138 void *data,
1139 void *userdata) {
1140
1141 _cleanup_free_ char *tz = NULL;
1142 char **datap = data;
1143 int r;
1144
1145 assert(filename);
1146 assert(lvalue);
1147 assert(rvalue);
1148
1149 r = config_parse_string(unit, filename, line, section, section_line, lvalue, ltype, rvalue, &tz, userdata);
1150 if (r < 0)
1151 return r;
1152
1153 if (!timezone_is_valid(tz, LOG_ERR)) {
1154 log_syntax(unit, LOG_ERR, filename, line, 0,
1155 "Timezone is not valid, ignoring assignment: %s", rvalue);
1156 return 0;
1157 }
1158
1159 return free_and_replace(*datap, tz);
1160 }
1161
1162 int config_parse_dns(
1163 const char *unit,
1164 const char *filename,
1165 unsigned line,
1166 const char *section,
1167 unsigned section_line,
1168 const char *lvalue,
1169 int ltype,
1170 const char *rvalue,
1171 void *data,
1172 void *userdata) {
1173
1174 Network *n = userdata;
1175 int r;
1176
1177 assert(filename);
1178 assert(lvalue);
1179 assert(rvalue);
1180
1181 for (;;) {
1182 _cleanup_free_ char *w = NULL;
1183 union in_addr_union a;
1184 struct in_addr_data *m;
1185 int family;
1186
1187 r = extract_first_word(&rvalue, &w, NULL, 0);
1188 if (r == -ENOMEM)
1189 return log_oom();
1190 if (r < 0) {
1191 log_syntax(unit, LOG_ERR, filename, line, r,
1192 "Invalid syntax, ignoring: %s", rvalue);
1193 break;
1194 }
1195 if (r == 0)
1196 break;
1197
1198 r = in_addr_from_string_auto(w, &family, &a);
1199 if (r < 0) {
1200 log_syntax(unit, LOG_ERR, filename, line, r,
1201 "Failed to parse dns server address, ignoring: %s", w);
1202 continue;
1203 }
1204
1205 m = reallocarray(n->dns, n->n_dns + 1, sizeof(struct in_addr_data));
1206 if (!m)
1207 return log_oom();
1208
1209 m[n->n_dns++] = (struct in_addr_data) {
1210 .family = family,
1211 .address = a,
1212 };
1213
1214 n->dns = m;
1215 }
1216
1217 return 0;
1218 }
1219
1220 int config_parse_dnssec_negative_trust_anchors(
1221 const char *unit,
1222 const char *filename,
1223 unsigned line,
1224 const char *section,
1225 unsigned section_line,
1226 const char *lvalue,
1227 int ltype,
1228 const char *rvalue,
1229 void *data,
1230 void *userdata) {
1231
1232 const char *p = rvalue;
1233 Network *n = data;
1234 int r;
1235
1236 assert(n);
1237 assert(lvalue);
1238 assert(rvalue);
1239
1240 if (isempty(rvalue)) {
1241 n->dnssec_negative_trust_anchors = set_free_free(n->dnssec_negative_trust_anchors);
1242 return 0;
1243 }
1244
1245 for (;;) {
1246 _cleanup_free_ char *w = NULL;
1247
1248 r = extract_first_word(&p, &w, NULL, 0);
1249 if (r < 0) {
1250 log_syntax(unit, LOG_ERR, filename, line, r,
1251 "Failed to extract negative trust anchor domain, ignoring: %s", rvalue);
1252 break;
1253 }
1254 if (r == 0)
1255 break;
1256
1257 r = dns_name_is_valid(w);
1258 if (r <= 0) {
1259 log_syntax(unit, LOG_ERR, filename, line, r,
1260 "%s is not a valid domain name, ignoring.", w);
1261 continue;
1262 }
1263
1264 r = set_ensure_allocated(&n->dnssec_negative_trust_anchors, &dns_name_hash_ops);
1265 if (r < 0)
1266 return log_oom();
1267
1268 r = set_put(n->dnssec_negative_trust_anchors, w);
1269 if (r < 0)
1270 return log_oom();
1271 if (r > 0)
1272 w = NULL;
1273 }
1274
1275 return 0;
1276 }
1277
1278 int config_parse_ntp(
1279 const char *unit,
1280 const char *filename,
1281 unsigned line,
1282 const char *section,
1283 unsigned section_line,
1284 const char *lvalue,
1285 int ltype,
1286 const char *rvalue,
1287 void *data,
1288 void *userdata) {
1289
1290 char ***l = data;
1291 int r;
1292
1293 assert(l);
1294 assert(lvalue);
1295 assert(rvalue);
1296
1297 if (isempty(rvalue)) {
1298 *l = strv_free(*l);
1299 return 0;
1300 }
1301
1302 for (;;) {
1303 _cleanup_free_ char *w = NULL;
1304
1305 r = extract_first_word(&rvalue, &w, NULL, 0);
1306 if (r == -ENOMEM)
1307 return log_oom();
1308 if (r < 0) {
1309 log_syntax(unit, LOG_ERR, filename, line, r,
1310 "Failed to extract NTP server name, ignoring: %s", rvalue);
1311 break;
1312 }
1313 if (r == 0)
1314 break;
1315
1316 r = dns_name_is_valid_or_address(w);
1317 if (r <= 0) {
1318 log_syntax(unit, LOG_ERR, filename, line, r,
1319 "%s is not a valid domain name or IP address, ignoring.", w);
1320 continue;
1321 }
1322
1323 if (strv_length(*l) > MAX_NTP_SERVERS) {
1324 log_syntax(unit, LOG_WARNING, filename, line, 0,
1325 "More than %u NTP servers specified, ignoring \"%s\" and any subsequent entries.",
1326 MAX_NTP_SERVERS, w);
1327 break;
1328 }
1329
1330 r = strv_consume(l, TAKE_PTR(w));
1331 if (r < 0)
1332 return log_oom();
1333 }
1334
1335 return 0;
1336 }
1337
1338 int config_parse_required_for_online(
1339 const char *unit,
1340 const char *filename,
1341 unsigned line,
1342 const char *section,
1343 unsigned section_line,
1344 const char *lvalue,
1345 int ltype,
1346 const char *rvalue,
1347 void *data,
1348 void *userdata) {
1349
1350 Network *network = data;
1351 LinkOperationalStateRange range;
1352 bool required = true;
1353 int r;
1354
1355 if (isempty(rvalue)) {
1356 network->required_for_online = true;
1357 network->required_operstate_for_online = LINK_OPERSTATE_RANGE_DEFAULT;
1358 return 0;
1359 }
1360
1361 r = parse_operational_state_range(rvalue, &range);
1362 if (r < 0) {
1363 r = parse_boolean(rvalue);
1364 if (r < 0) {
1365 log_syntax(unit, LOG_ERR, filename, line, r,
1366 "Failed to parse %s= setting, ignoring assignment: %s",
1367 lvalue, rvalue);
1368 return 0;
1369 }
1370
1371 required = r;
1372 range = LINK_OPERSTATE_RANGE_DEFAULT;
1373 }
1374
1375 network->required_for_online = required;
1376 network->required_operstate_for_online = range;
1377
1378 return 0;
1379 }
1380
1381 DEFINE_CONFIG_PARSE_ENUM(config_parse_keep_configuration, keep_configuration, KeepConfiguration,
1382 "Failed to parse KeepConfiguration= setting");
1383
1384 static const char* const keep_configuration_table[_KEEP_CONFIGURATION_MAX] = {
1385 [KEEP_CONFIGURATION_NO] = "no",
1386 [KEEP_CONFIGURATION_DHCP_ON_STOP] = "dhcp-on-stop",
1387 [KEEP_CONFIGURATION_DHCP] = "dhcp",
1388 [KEEP_CONFIGURATION_STATIC] = "static",
1389 [KEEP_CONFIGURATION_YES] = "yes",
1390 };
1391
1392 DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(keep_configuration, KeepConfiguration, KEEP_CONFIGURATION_YES);