]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/network/networkd-network.c
Merge pull request #13748 from jwrdegoede/hwdb-updates2
[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 if (network->dhcp_acd)
623 sd_ipv4acd_unref(network->dhcp_acd);
624
625 strv_free(network->ntp);
626 free(network->dns);
627 strv_free(network->sip);
628 ordered_set_free_free(network->search_domains);
629 ordered_set_free_free(network->route_domains);
630 strv_free(network->bind_carrier);
631
632 ordered_set_free_free(network->router_search_domains);
633 free(network->router_dns);
634 set_free_free(network->ndisc_black_listed_prefix);
635
636 free(network->bridge_name);
637 free(network->bond_name);
638 free(network->vrf_name);
639 hashmap_free_free_key(network->stacked_netdev_names);
640 netdev_unref(network->bridge);
641 netdev_unref(network->bond);
642 netdev_unref(network->vrf);
643 hashmap_free_with_destructor(network->stacked_netdevs, netdev_unref);
644
645 while ((route = network->static_routes))
646 route_free(route);
647
648 while ((nexthop = network->static_nexthops))
649 nexthop_free(nexthop);
650
651 while ((address = network->static_addresses))
652 address_free(address);
653
654 while ((fdb_entry = network->static_fdb_entries))
655 fdb_entry_free(fdb_entry);
656
657 while ((ipv6_proxy_ndp_address = network->ipv6_proxy_ndp_addresses))
658 ipv6_proxy_ndp_address_free(ipv6_proxy_ndp_address);
659
660 while ((neighbor = network->neighbors))
661 neighbor_free(neighbor);
662
663 while ((label = network->address_labels))
664 address_label_free(label);
665
666 while ((prefix = network->static_prefixes))
667 prefix_free(prefix);
668
669 while ((route_prefix = network->static_route_prefixes))
670 route_prefix_free(route_prefix);
671
672 while ((rule = network->rules))
673 routing_policy_rule_free(rule);
674
675 hashmap_free(network->addresses_by_section);
676 hashmap_free(network->routes_by_section);
677 hashmap_free(network->nexthops_by_section);
678 hashmap_free(network->fdb_entries_by_section);
679 hashmap_free(network->neighbors_by_section);
680 hashmap_free(network->address_labels_by_section);
681 hashmap_free(network->prefixes_by_section);
682 hashmap_free(network->route_prefixes_by_section);
683 hashmap_free(network->rules_by_section);
684 ordered_hashmap_free_with_destructor(network->qdiscs_by_section, qdisc_free);
685
686 if (network->manager &&
687 network->manager->duids_requesting_uuid)
688 set_remove(network->manager->duids_requesting_uuid, &network->duid);
689
690 free(network->name);
691
692 free(network->dhcp_server_timezone);
693 free(network->dhcp_server_dns);
694 free(network->dhcp_server_ntp);
695 free(network->dhcp_server_sip);
696
697 set_free_free(network->dnssec_negative_trust_anchors);
698
699 ordered_hashmap_free(network->dhcp_client_send_options);
700 ordered_hashmap_free(network->dhcp_server_send_options);
701
702 return mfree(network);
703 }
704
705 DEFINE_TRIVIAL_REF_UNREF_FUNC(Network, network, network_free);
706
707 int network_get_by_name(Manager *manager, const char *name, Network **ret) {
708 Network *network;
709
710 assert(manager);
711 assert(name);
712 assert(ret);
713
714 network = ordered_hashmap_get(manager->networks, name);
715 if (!network)
716 return -ENOENT;
717
718 *ret = network;
719
720 return 0;
721 }
722
723 int network_get(Manager *manager, sd_device *device,
724 const char *ifname, char * const *alternative_names, const struct ether_addr *address,
725 enum nl80211_iftype wlan_iftype, const char *ssid, const struct ether_addr *bssid,
726 Network **ret) {
727 Network *network;
728 Iterator i;
729
730 assert(manager);
731 assert(ret);
732
733 ORDERED_HASHMAP_FOREACH(network, manager->networks, i)
734 if (net_match_config(network->match_mac, network->match_path, network->match_driver,
735 network->match_type, network->match_name, network->match_property,
736 network->match_wlan_iftype, network->match_ssid, network->match_bssid,
737 device, address, ifname, alternative_names, wlan_iftype, ssid, bssid)) {
738 if (network->match_name && device) {
739 const char *attr;
740 uint8_t name_assign_type = NET_NAME_UNKNOWN;
741
742 if (sd_device_get_sysattr_value(device, "name_assign_type", &attr) >= 0)
743 (void) safe_atou8(attr, &name_assign_type);
744
745 if (name_assign_type == NET_NAME_ENUM)
746 log_warning("%s: found matching network '%s', based on potentially unpredictable ifname",
747 ifname, network->filename);
748 else
749 log_debug("%s: found matching network '%s'", ifname, network->filename);
750 } else
751 log_debug("%s: found matching network '%s'", ifname, network->filename);
752
753 *ret = network;
754 return 0;
755 }
756
757 *ret = NULL;
758
759 return -ENOENT;
760 }
761
762 int network_apply(Network *network, Link *link) {
763 assert(network);
764 assert(link);
765
766 link->network = network_ref(network);
767
768 if (network->n_dns > 0 ||
769 !strv_isempty(network->ntp) ||
770 !ordered_set_isempty(network->search_domains) ||
771 !ordered_set_isempty(network->route_domains))
772 link_dirty(link);
773
774 return 0;
775 }
776
777 bool network_has_static_ipv6_configurations(Network *network) {
778 Address *address;
779 Route *route;
780 FdbEntry *fdb;
781 Neighbor *neighbor;
782
783 assert(network);
784
785 LIST_FOREACH(addresses, address, network->static_addresses)
786 if (address->family == AF_INET6)
787 return true;
788
789 LIST_FOREACH(routes, route, network->static_routes)
790 if (route->family == AF_INET6)
791 return true;
792
793 LIST_FOREACH(static_fdb_entries, fdb, network->static_fdb_entries)
794 if (fdb->family == AF_INET6)
795 return true;
796
797 LIST_FOREACH(neighbors, neighbor, network->neighbors)
798 if (neighbor->family == AF_INET6)
799 return true;
800
801 if (!LIST_IS_EMPTY(network->address_labels))
802 return true;
803
804 if (!LIST_IS_EMPTY(network->static_prefixes))
805 return true;
806
807 return false;
808 }
809
810 int config_parse_stacked_netdev(const char *unit,
811 const char *filename,
812 unsigned line,
813 const char *section,
814 unsigned section_line,
815 const char *lvalue,
816 int ltype,
817 const char *rvalue,
818 void *data,
819 void *userdata) {
820 _cleanup_free_ char *name = NULL;
821 NetDevKind kind = ltype;
822 Hashmap **h = data;
823 int r;
824
825 assert(filename);
826 assert(lvalue);
827 assert(rvalue);
828 assert(data);
829 assert(IN_SET(kind,
830 NETDEV_KIND_VLAN, NETDEV_KIND_MACVLAN, NETDEV_KIND_MACVTAP,
831 NETDEV_KIND_IPVLAN, NETDEV_KIND_IPVTAP, NETDEV_KIND_VXLAN,
832 NETDEV_KIND_L2TP, NETDEV_KIND_MACSEC, _NETDEV_KIND_TUNNEL,
833 NETDEV_KIND_XFRM));
834
835 if (!ifname_valid(rvalue)) {
836 log_syntax(unit, LOG_ERR, filename, line, 0,
837 "Invalid netdev name in %s=, ignoring assignment: %s", lvalue, rvalue);
838 return 0;
839 }
840
841 name = strdup(rvalue);
842 if (!name)
843 return log_oom();
844
845 r = hashmap_ensure_allocated(h, &string_hash_ops);
846 if (r < 0)
847 return log_oom();
848
849 r = hashmap_put(*h, name, INT_TO_PTR(kind));
850 if (r < 0)
851 log_syntax(unit, LOG_ERR, filename, line, r,
852 "Cannot add NetDev '%s' to network, ignoring assignment: %m", name);
853 else if (r == 0)
854 log_syntax(unit, LOG_DEBUG, filename, line, r,
855 "NetDev '%s' specified twice, ignoring.", name);
856 else
857 name = NULL;
858
859 return 0;
860 }
861
862 int config_parse_domains(
863 const char *unit,
864 const char *filename,
865 unsigned line,
866 const char *section,
867 unsigned section_line,
868 const char *lvalue,
869 int ltype,
870 const char *rvalue,
871 void *data,
872 void *userdata) {
873
874 const char *p;
875 Network *n = data;
876 int r;
877
878 assert(n);
879 assert(lvalue);
880 assert(rvalue);
881
882 if (isempty(rvalue)) {
883 n->search_domains = ordered_set_free_free(n->search_domains);
884 n->route_domains = ordered_set_free_free(n->route_domains);
885 return 0;
886 }
887
888 p = rvalue;
889 for (;;) {
890 _cleanup_free_ char *w = NULL, *normalized = NULL;
891 const char *domain;
892 bool is_route;
893
894 r = extract_first_word(&p, &w, NULL, 0);
895 if (r < 0) {
896 log_syntax(unit, LOG_ERR, filename, line, r,
897 "Failed to extract search or route domain, ignoring: %s", rvalue);
898 break;
899 }
900 if (r == 0)
901 break;
902
903 is_route = w[0] == '~';
904 domain = is_route ? w + 1 : w;
905
906 if (dns_name_is_root(domain) || streq(domain, "*")) {
907 /* If the root domain appears as is, or the special token "*" is found, we'll
908 * consider this as routing domain, unconditionally. */
909 is_route = true;
910 domain = "."; /* make sure we don't allow empty strings, thus write the root
911 * domain as "." */
912 } else {
913 r = dns_name_normalize(domain, 0, &normalized);
914 if (r < 0) {
915 log_syntax(unit, LOG_ERR, filename, line, r,
916 "'%s' is not a valid domain name, ignoring.", domain);
917 continue;
918 }
919
920 domain = normalized;
921
922 if (is_localhost(domain)) {
923 log_syntax(unit, LOG_ERR, filename, line, 0,
924 "'localhost' domain may not be configured as search or route domain, ignoring assignment: %s",
925 domain);
926 continue;
927 }
928 }
929
930 OrderedSet **set = is_route ? &n->route_domains : &n->search_domains;
931 r = ordered_set_ensure_allocated(set, &string_hash_ops);
932 if (r < 0)
933 return r;
934
935 r = ordered_set_put_strdup(*set, domain);
936 if (r < 0)
937 return log_oom();
938 }
939
940 return 0;
941 }
942
943 int config_parse_ipv6token(
944 const char* unit,
945 const char *filename,
946 unsigned line,
947 const char *section,
948 unsigned section_line,
949 const char *lvalue,
950 int ltype,
951 const char *rvalue,
952 void *data,
953 void *userdata) {
954
955 union in_addr_union buffer;
956 struct in6_addr *token = data;
957 int r;
958
959 assert(filename);
960 assert(lvalue);
961 assert(rvalue);
962 assert(token);
963
964 r = in_addr_from_string(AF_INET6, rvalue, &buffer);
965 if (r < 0) {
966 log_syntax(unit, LOG_ERR, filename, line, r,
967 "Failed to parse IPv6 token, ignoring: %s", rvalue);
968 return 0;
969 }
970
971 if (in_addr_is_null(AF_INET6, &buffer)) {
972 log_syntax(unit, LOG_ERR, filename, line, 0,
973 "IPv6 token cannot be the ANY address, ignoring: %s", rvalue);
974 return 0;
975 }
976
977 if ((buffer.in6.s6_addr32[0] | buffer.in6.s6_addr32[1]) != 0) {
978 log_syntax(unit, LOG_ERR, filename, line, 0,
979 "IPv6 token cannot be longer than 64 bits, ignoring: %s", rvalue);
980 return 0;
981 }
982
983 *token = buffer.in6;
984
985 return 0;
986 }
987
988 static const char* const ipv6_privacy_extensions_table[_IPV6_PRIVACY_EXTENSIONS_MAX] = {
989 [IPV6_PRIVACY_EXTENSIONS_NO] = "no",
990 [IPV6_PRIVACY_EXTENSIONS_PREFER_PUBLIC] = "prefer-public",
991 [IPV6_PRIVACY_EXTENSIONS_YES] = "yes",
992 };
993
994 DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(ipv6_privacy_extensions, IPv6PrivacyExtensions,
995 IPV6_PRIVACY_EXTENSIONS_YES);
996
997 int config_parse_ipv6_privacy_extensions(
998 const char* unit,
999 const char *filename,
1000 unsigned line,
1001 const char *section,
1002 unsigned section_line,
1003 const char *lvalue,
1004 int ltype,
1005 const char *rvalue,
1006 void *data,
1007 void *userdata) {
1008
1009 IPv6PrivacyExtensions s, *ipv6_privacy_extensions = data;
1010
1011 assert(filename);
1012 assert(lvalue);
1013 assert(rvalue);
1014 assert(ipv6_privacy_extensions);
1015
1016 s = ipv6_privacy_extensions_from_string(rvalue);
1017 if (s < 0) {
1018 if (streq(rvalue, "kernel"))
1019 s = _IPV6_PRIVACY_EXTENSIONS_INVALID;
1020 else {
1021 log_syntax(unit, LOG_ERR, filename, line, 0,
1022 "Failed to parse IPv6 privacy extensions option, ignoring: %s", rvalue);
1023 return 0;
1024 }
1025 }
1026
1027 *ipv6_privacy_extensions = s;
1028
1029 return 0;
1030 }
1031
1032 int config_parse_hostname(
1033 const char *unit,
1034 const char *filename,
1035 unsigned line,
1036 const char *section,
1037 unsigned section_line,
1038 const char *lvalue,
1039 int ltype,
1040 const char *rvalue,
1041 void *data,
1042 void *userdata) {
1043
1044 _cleanup_free_ char *hn = NULL;
1045 char **hostname = data;
1046 int r;
1047
1048 assert(filename);
1049 assert(lvalue);
1050 assert(rvalue);
1051
1052 r = config_parse_string(unit, filename, line, section, section_line, lvalue, ltype, rvalue, &hn, userdata);
1053 if (r < 0)
1054 return r;
1055
1056 if (!hostname_is_valid(hn, false)) {
1057 log_syntax(unit, LOG_ERR, filename, line, 0,
1058 "Hostname is not valid, ignoring assignment: %s", rvalue);
1059 return 0;
1060 }
1061
1062 r = dns_name_is_valid(hn);
1063 if (r < 0) {
1064 log_syntax(unit, LOG_ERR, filename, line, r,
1065 "Failed to check validity of hostname '%s', ignoring assignment: %m", rvalue);
1066 return 0;
1067 }
1068 if (r == 0) {
1069 log_syntax(unit, LOG_ERR, filename, line, 0,
1070 "Hostname is not a valid DNS domain name, ignoring assignment: %s", rvalue);
1071 return 0;
1072 }
1073
1074 return free_and_replace(*hostname, hn);
1075 }
1076
1077 int config_parse_timezone(
1078 const char *unit,
1079 const char *filename,
1080 unsigned line,
1081 const char *section,
1082 unsigned section_line,
1083 const char *lvalue,
1084 int ltype,
1085 const char *rvalue,
1086 void *data,
1087 void *userdata) {
1088
1089 _cleanup_free_ char *tz = NULL;
1090 char **datap = data;
1091 int r;
1092
1093 assert(filename);
1094 assert(lvalue);
1095 assert(rvalue);
1096
1097 r = config_parse_string(unit, filename, line, section, section_line, lvalue, ltype, rvalue, &tz, userdata);
1098 if (r < 0)
1099 return r;
1100
1101 if (!timezone_is_valid(tz, LOG_ERR)) {
1102 log_syntax(unit, LOG_ERR, filename, line, 0,
1103 "Timezone is not valid, ignoring assignment: %s", rvalue);
1104 return 0;
1105 }
1106
1107 return free_and_replace(*datap, tz);
1108 }
1109
1110 int config_parse_dns(
1111 const char *unit,
1112 const char *filename,
1113 unsigned line,
1114 const char *section,
1115 unsigned section_line,
1116 const char *lvalue,
1117 int ltype,
1118 const char *rvalue,
1119 void *data,
1120 void *userdata) {
1121
1122 Network *n = userdata;
1123 int r;
1124
1125 assert(filename);
1126 assert(lvalue);
1127 assert(rvalue);
1128
1129 for (;;) {
1130 _cleanup_free_ char *w = NULL;
1131 union in_addr_union a;
1132 struct in_addr_data *m;
1133 int family;
1134
1135 r = extract_first_word(&rvalue, &w, NULL, 0);
1136 if (r == -ENOMEM)
1137 return log_oom();
1138 if (r < 0) {
1139 log_syntax(unit, LOG_ERR, filename, line, r,
1140 "Invalid syntax, ignoring: %s", rvalue);
1141 break;
1142 }
1143 if (r == 0)
1144 break;
1145
1146 r = in_addr_from_string_auto(w, &family, &a);
1147 if (r < 0) {
1148 log_syntax(unit, LOG_ERR, filename, line, r,
1149 "Failed to parse dns server address, ignoring: %s", w);
1150 continue;
1151 }
1152
1153 m = reallocarray(n->dns, n->n_dns + 1, sizeof(struct in_addr_data));
1154 if (!m)
1155 return log_oom();
1156
1157 m[n->n_dns++] = (struct in_addr_data) {
1158 .family = family,
1159 .address = a,
1160 };
1161
1162 n->dns = m;
1163 }
1164
1165 return 0;
1166 }
1167
1168 int config_parse_dnssec_negative_trust_anchors(
1169 const char *unit,
1170 const char *filename,
1171 unsigned line,
1172 const char *section,
1173 unsigned section_line,
1174 const char *lvalue,
1175 int ltype,
1176 const char *rvalue,
1177 void *data,
1178 void *userdata) {
1179
1180 const char *p = rvalue;
1181 Network *n = data;
1182 int r;
1183
1184 assert(n);
1185 assert(lvalue);
1186 assert(rvalue);
1187
1188 if (isempty(rvalue)) {
1189 n->dnssec_negative_trust_anchors = set_free_free(n->dnssec_negative_trust_anchors);
1190 return 0;
1191 }
1192
1193 for (;;) {
1194 _cleanup_free_ char *w = NULL;
1195
1196 r = extract_first_word(&p, &w, NULL, 0);
1197 if (r < 0) {
1198 log_syntax(unit, LOG_ERR, filename, line, r,
1199 "Failed to extract negative trust anchor domain, ignoring: %s", rvalue);
1200 break;
1201 }
1202 if (r == 0)
1203 break;
1204
1205 r = dns_name_is_valid(w);
1206 if (r <= 0) {
1207 log_syntax(unit, LOG_ERR, filename, line, r,
1208 "%s is not a valid domain name, ignoring.", w);
1209 continue;
1210 }
1211
1212 r = set_ensure_allocated(&n->dnssec_negative_trust_anchors, &dns_name_hash_ops);
1213 if (r < 0)
1214 return log_oom();
1215
1216 r = set_put(n->dnssec_negative_trust_anchors, w);
1217 if (r < 0)
1218 return log_oom();
1219 if (r > 0)
1220 w = NULL;
1221 }
1222
1223 return 0;
1224 }
1225
1226 int config_parse_ntp(
1227 const char *unit,
1228 const char *filename,
1229 unsigned line,
1230 const char *section,
1231 unsigned section_line,
1232 const char *lvalue,
1233 int ltype,
1234 const char *rvalue,
1235 void *data,
1236 void *userdata) {
1237
1238 char ***l = data;
1239 int r;
1240
1241 assert(l);
1242 assert(lvalue);
1243 assert(rvalue);
1244
1245 if (isempty(rvalue)) {
1246 *l = strv_free(*l);
1247 return 0;
1248 }
1249
1250 for (;;) {
1251 _cleanup_free_ char *w = NULL;
1252
1253 r = extract_first_word(&rvalue, &w, NULL, 0);
1254 if (r == -ENOMEM)
1255 return log_oom();
1256 if (r < 0) {
1257 log_syntax(unit, LOG_ERR, filename, line, r,
1258 "Failed to extract NTP server name, ignoring: %s", rvalue);
1259 break;
1260 }
1261 if (r == 0)
1262 break;
1263
1264 r = dns_name_is_valid_or_address(w);
1265 if (r <= 0) {
1266 log_syntax(unit, LOG_ERR, filename, line, r,
1267 "%s is not a valid domain name or IP address, ignoring.", w);
1268 continue;
1269 }
1270
1271 if (strv_length(*l) > MAX_NTP_SERVERS) {
1272 log_syntax(unit, LOG_WARNING, filename, line, 0,
1273 "More than %u NTP servers specified, ignoring \"%s\" and any subsequent entries.",
1274 MAX_NTP_SERVERS, w);
1275 break;
1276 }
1277
1278 r = strv_consume(l, TAKE_PTR(w));
1279 if (r < 0)
1280 return log_oom();
1281 }
1282
1283 return 0;
1284 }
1285
1286 int config_parse_required_for_online(
1287 const char *unit,
1288 const char *filename,
1289 unsigned line,
1290 const char *section,
1291 unsigned section_line,
1292 const char *lvalue,
1293 int ltype,
1294 const char *rvalue,
1295 void *data,
1296 void *userdata) {
1297
1298 Network *network = data;
1299 LinkOperationalState s;
1300 bool required = true;
1301 int r;
1302
1303 if (isempty(rvalue)) {
1304 network->required_for_online = true;
1305 network->required_operstate_for_online = LINK_OPERSTATE_DEGRADED;
1306 return 0;
1307 }
1308
1309 s = link_operstate_from_string(rvalue);
1310 if (s < 0) {
1311 r = parse_boolean(rvalue);
1312 if (r < 0) {
1313 log_syntax(unit, LOG_ERR, filename, line, r,
1314 "Failed to parse %s= setting, ignoring assignment: %s",
1315 lvalue, rvalue);
1316 return 0;
1317 }
1318
1319 required = r;
1320 s = LINK_OPERSTATE_DEGRADED;
1321 }
1322
1323 network->required_for_online = required;
1324 network->required_operstate_for_online = s;
1325
1326 return 0;
1327 }
1328
1329 DEFINE_CONFIG_PARSE_ENUM(config_parse_keep_configuration, keep_configuration, KeepConfiguration,
1330 "Failed to parse KeepConfiguration= setting");
1331
1332 static const char* const keep_configuration_table[_KEEP_CONFIGURATION_MAX] = {
1333 [KEEP_CONFIGURATION_NO] = "no",
1334 [KEEP_CONFIGURATION_DHCP_ON_STOP] = "dhcp-on-stop",
1335 [KEEP_CONFIGURATION_DHCP] = "dhcp",
1336 [KEEP_CONFIGURATION_STATIC] = "static",
1337 [KEEP_CONFIGURATION_YES] = "yes",
1338 };
1339
1340 DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(keep_configuration, KeepConfiguration, KEEP_CONFIGURATION_YES);