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