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