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