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