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