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