]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/network/networkd-network.c
network: rename AddressFamilyBoolean -> AddressFamily
[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_addresses(Network *network) {
666 Address *address;
667
668 assert(network);
669
670 LIST_FOREACH(addresses, address, network->static_addresses) {
671 if (address->family == AF_INET6)
672 return true;
673 }
674
675 return false;
676 }
677
678 int config_parse_stacked_netdev(const char *unit,
679 const char *filename,
680 unsigned line,
681 const char *section,
682 unsigned section_line,
683 const char *lvalue,
684 int ltype,
685 const char *rvalue,
686 void *data,
687 void *userdata) {
688 _cleanup_free_ char *name = NULL;
689 NetDevKind kind = ltype;
690 Hashmap **h = data;
691 int r;
692
693 assert(filename);
694 assert(lvalue);
695 assert(rvalue);
696 assert(data);
697 assert(IN_SET(kind,
698 NETDEV_KIND_VLAN, NETDEV_KIND_MACVLAN, NETDEV_KIND_MACVTAP,
699 NETDEV_KIND_IPVLAN, NETDEV_KIND_IPVTAP, NETDEV_KIND_VXLAN,
700 NETDEV_KIND_L2TP, NETDEV_KIND_MACSEC, _NETDEV_KIND_TUNNEL,
701 NETDEV_KIND_XFRM));
702
703 if (!ifname_valid(rvalue)) {
704 log_syntax(unit, LOG_ERR, filename, line, 0,
705 "Invalid netdev name in %s=, ignoring assignment: %s", lvalue, rvalue);
706 return 0;
707 }
708
709 name = strdup(rvalue);
710 if (!name)
711 return log_oom();
712
713 r = hashmap_ensure_allocated(h, &string_hash_ops);
714 if (r < 0)
715 return log_oom();
716
717 r = hashmap_put(*h, name, INT_TO_PTR(kind));
718 if (r < 0)
719 log_syntax(unit, LOG_ERR, filename, line, r,
720 "Cannot add NetDev '%s' to network, ignoring assignment: %m", name);
721 else if (r == 0)
722 log_syntax(unit, LOG_DEBUG, filename, line, r,
723 "NetDev '%s' specified twice, ignoring.", name);
724 else
725 name = NULL;
726
727 return 0;
728 }
729
730 int config_parse_domains(
731 const char *unit,
732 const char *filename,
733 unsigned line,
734 const char *section,
735 unsigned section_line,
736 const char *lvalue,
737 int ltype,
738 const char *rvalue,
739 void *data,
740 void *userdata) {
741
742 const char *p;
743 Network *n = data;
744 int r;
745
746 assert(n);
747 assert(lvalue);
748 assert(rvalue);
749
750 if (isempty(rvalue)) {
751 n->search_domains = ordered_set_free_free(n->search_domains);
752 n->route_domains = ordered_set_free_free(n->route_domains);
753 return 0;
754 }
755
756 p = rvalue;
757 for (;;) {
758 _cleanup_free_ char *w = NULL, *normalized = NULL;
759 const char *domain;
760 bool is_route;
761
762 r = extract_first_word(&p, &w, NULL, 0);
763 if (r < 0) {
764 log_syntax(unit, LOG_ERR, filename, line, r,
765 "Failed to extract search or route domain, ignoring: %s", rvalue);
766 break;
767 }
768 if (r == 0)
769 break;
770
771 is_route = w[0] == '~';
772 domain = is_route ? w + 1 : w;
773
774 if (dns_name_is_root(domain) || streq(domain, "*")) {
775 /* If the root domain appears as is, or the special token "*" is found, we'll
776 * consider this as routing domain, unconditionally. */
777 is_route = true;
778 domain = "."; /* make sure we don't allow empty strings, thus write the root
779 * domain as "." */
780 } else {
781 r = dns_name_normalize(domain, 0, &normalized);
782 if (r < 0) {
783 log_syntax(unit, LOG_ERR, filename, line, r,
784 "'%s' is not a valid domain name, ignoring.", domain);
785 continue;
786 }
787
788 domain = normalized;
789
790 if (is_localhost(domain)) {
791 log_syntax(unit, LOG_ERR, filename, line, 0,
792 "'localhost' domain may not be configured as search or route domain, ignoring assignment: %s",
793 domain);
794 continue;
795 }
796 }
797
798 OrderedSet **set = is_route ? &n->route_domains : &n->search_domains;
799 r = ordered_set_ensure_allocated(set, &string_hash_ops);
800 if (r < 0)
801 return r;
802
803 r = ordered_set_put_strdup(*set, domain);
804 if (r < 0)
805 return log_oom();
806 }
807
808 return 0;
809 }
810
811 int config_parse_ipv6token(
812 const char* unit,
813 const char *filename,
814 unsigned line,
815 const char *section,
816 unsigned section_line,
817 const char *lvalue,
818 int ltype,
819 const char *rvalue,
820 void *data,
821 void *userdata) {
822
823 union in_addr_union buffer;
824 struct in6_addr *token = data;
825 int r;
826
827 assert(filename);
828 assert(lvalue);
829 assert(rvalue);
830 assert(token);
831
832 r = in_addr_from_string(AF_INET6, rvalue, &buffer);
833 if (r < 0) {
834 log_syntax(unit, LOG_ERR, filename, line, r,
835 "Failed to parse IPv6 token, ignoring: %s", rvalue);
836 return 0;
837 }
838
839 if (in_addr_is_null(AF_INET6, &buffer)) {
840 log_syntax(unit, LOG_ERR, filename, line, 0,
841 "IPv6 token cannot be the ANY address, ignoring: %s", rvalue);
842 return 0;
843 }
844
845 if ((buffer.in6.s6_addr32[0] | buffer.in6.s6_addr32[1]) != 0) {
846 log_syntax(unit, LOG_ERR, filename, line, 0,
847 "IPv6 token cannot be longer than 64 bits, ignoring: %s", rvalue);
848 return 0;
849 }
850
851 *token = buffer.in6;
852
853 return 0;
854 }
855
856 static const char* const ipv6_privacy_extensions_table[_IPV6_PRIVACY_EXTENSIONS_MAX] = {
857 [IPV6_PRIVACY_EXTENSIONS_NO] = "no",
858 [IPV6_PRIVACY_EXTENSIONS_PREFER_PUBLIC] = "prefer-public",
859 [IPV6_PRIVACY_EXTENSIONS_YES] = "yes",
860 };
861
862 DEFINE_STRING_TABLE_LOOKUP(ipv6_privacy_extensions, IPv6PrivacyExtensions);
863
864 int config_parse_ipv6_privacy_extensions(
865 const char* unit,
866 const char *filename,
867 unsigned line,
868 const char *section,
869 unsigned section_line,
870 const char *lvalue,
871 int ltype,
872 const char *rvalue,
873 void *data,
874 void *userdata) {
875
876 IPv6PrivacyExtensions *ipv6_privacy_extensions = data;
877 int k;
878
879 assert(filename);
880 assert(lvalue);
881 assert(rvalue);
882 assert(ipv6_privacy_extensions);
883
884 /* Our enum shall be a superset of booleans, hence first try
885 * to parse as boolean, and then as enum */
886
887 k = parse_boolean(rvalue);
888 if (k > 0)
889 *ipv6_privacy_extensions = IPV6_PRIVACY_EXTENSIONS_YES;
890 else if (k == 0)
891 *ipv6_privacy_extensions = IPV6_PRIVACY_EXTENSIONS_NO;
892 else {
893 IPv6PrivacyExtensions s;
894
895 s = ipv6_privacy_extensions_from_string(rvalue);
896 if (s < 0) {
897
898 if (streq(rvalue, "kernel"))
899 s = _IPV6_PRIVACY_EXTENSIONS_INVALID;
900 else {
901 log_syntax(unit, LOG_ERR, filename, line, 0,
902 "Failed to parse IPv6 privacy extensions option, ignoring: %s", rvalue);
903 return 0;
904 }
905 }
906
907 *ipv6_privacy_extensions = s;
908 }
909
910 return 0;
911 }
912
913 int config_parse_hostname(
914 const char *unit,
915 const char *filename,
916 unsigned line,
917 const char *section,
918 unsigned section_line,
919 const char *lvalue,
920 int ltype,
921 const char *rvalue,
922 void *data,
923 void *userdata) {
924
925 _cleanup_free_ char *hn = NULL;
926 char **hostname = data;
927 int r;
928
929 assert(filename);
930 assert(lvalue);
931 assert(rvalue);
932
933 r = config_parse_string(unit, filename, line, section, section_line, lvalue, ltype, rvalue, &hn, userdata);
934 if (r < 0)
935 return r;
936
937 if (!hostname_is_valid(hn, false)) {
938 log_syntax(unit, LOG_ERR, filename, line, 0,
939 "Hostname is not valid, ignoring assignment: %s", rvalue);
940 return 0;
941 }
942
943 r = dns_name_is_valid(hn);
944 if (r < 0) {
945 log_syntax(unit, LOG_ERR, filename, line, r,
946 "Failed to check validity of hostname '%s', ignoring assignment: %m", rvalue);
947 return 0;
948 }
949 if (r == 0) {
950 log_syntax(unit, LOG_ERR, filename, line, 0,
951 "Hostname is not a valid DNS domain name, ignoring assignment: %s", rvalue);
952 return 0;
953 }
954
955 return free_and_replace(*hostname, hn);
956 }
957
958 int config_parse_timezone(
959 const char *unit,
960 const char *filename,
961 unsigned line,
962 const char *section,
963 unsigned section_line,
964 const char *lvalue,
965 int ltype,
966 const char *rvalue,
967 void *data,
968 void *userdata) {
969
970 _cleanup_free_ char *tz = NULL;
971 char **datap = data;
972 int r;
973
974 assert(filename);
975 assert(lvalue);
976 assert(rvalue);
977
978 r = config_parse_string(unit, filename, line, section, section_line, lvalue, ltype, rvalue, &tz, userdata);
979 if (r < 0)
980 return r;
981
982 if (!timezone_is_valid(tz, LOG_ERR)) {
983 log_syntax(unit, LOG_ERR, filename, line, 0,
984 "Timezone is not valid, ignoring assignment: %s", rvalue);
985 return 0;
986 }
987
988 return free_and_replace(*datap, tz);
989 }
990
991 int config_parse_dns(
992 const char *unit,
993 const char *filename,
994 unsigned line,
995 const char *section,
996 unsigned section_line,
997 const char *lvalue,
998 int ltype,
999 const char *rvalue,
1000 void *data,
1001 void *userdata) {
1002
1003 Network *n = userdata;
1004 int r;
1005
1006 assert(filename);
1007 assert(lvalue);
1008 assert(rvalue);
1009
1010 for (;;) {
1011 _cleanup_free_ char *w = NULL;
1012 union in_addr_union a;
1013 struct in_addr_data *m;
1014 int family;
1015
1016 r = extract_first_word(&rvalue, &w, NULL, 0);
1017 if (r == -ENOMEM)
1018 return log_oom();
1019 if (r < 0) {
1020 log_syntax(unit, LOG_ERR, filename, line, r,
1021 "Invalid syntax, ignoring: %s", rvalue);
1022 break;
1023 }
1024 if (r == 0)
1025 break;
1026
1027 r = in_addr_from_string_auto(w, &family, &a);
1028 if (r < 0) {
1029 log_syntax(unit, LOG_ERR, filename, line, r,
1030 "Failed to parse dns server address, ignoring: %s", w);
1031 continue;
1032 }
1033
1034 m = reallocarray(n->dns, n->n_dns + 1, sizeof(struct in_addr_data));
1035 if (!m)
1036 return log_oom();
1037
1038 m[n->n_dns++] = (struct in_addr_data) {
1039 .family = family,
1040 .address = a,
1041 };
1042
1043 n->dns = m;
1044 }
1045
1046 return 0;
1047 }
1048
1049 int config_parse_dnssec_negative_trust_anchors(
1050 const char *unit,
1051 const char *filename,
1052 unsigned line,
1053 const char *section,
1054 unsigned section_line,
1055 const char *lvalue,
1056 int ltype,
1057 const char *rvalue,
1058 void *data,
1059 void *userdata) {
1060
1061 const char *p = rvalue;
1062 Network *n = data;
1063 int r;
1064
1065 assert(n);
1066 assert(lvalue);
1067 assert(rvalue);
1068
1069 if (isempty(rvalue)) {
1070 n->dnssec_negative_trust_anchors = set_free_free(n->dnssec_negative_trust_anchors);
1071 return 0;
1072 }
1073
1074 for (;;) {
1075 _cleanup_free_ char *w = NULL;
1076
1077 r = extract_first_word(&p, &w, NULL, 0);
1078 if (r < 0) {
1079 log_syntax(unit, LOG_ERR, filename, line, r,
1080 "Failed to extract negative trust anchor domain, ignoring: %s", rvalue);
1081 break;
1082 }
1083 if (r == 0)
1084 break;
1085
1086 r = dns_name_is_valid(w);
1087 if (r <= 0) {
1088 log_syntax(unit, LOG_ERR, filename, line, r,
1089 "%s is not a valid domain name, ignoring.", w);
1090 continue;
1091 }
1092
1093 r = set_ensure_allocated(&n->dnssec_negative_trust_anchors, &dns_name_hash_ops);
1094 if (r < 0)
1095 return log_oom();
1096
1097 r = set_put(n->dnssec_negative_trust_anchors, w);
1098 if (r < 0)
1099 return log_oom();
1100 if (r > 0)
1101 w = NULL;
1102 }
1103
1104 return 0;
1105 }
1106
1107 int config_parse_ntp(
1108 const char *unit,
1109 const char *filename,
1110 unsigned line,
1111 const char *section,
1112 unsigned section_line,
1113 const char *lvalue,
1114 int ltype,
1115 const char *rvalue,
1116 void *data,
1117 void *userdata) {
1118
1119 char ***l = data;
1120 int r;
1121
1122 assert(l);
1123 assert(lvalue);
1124 assert(rvalue);
1125
1126 if (isempty(rvalue)) {
1127 *l = strv_free(*l);
1128 return 0;
1129 }
1130
1131 for (;;) {
1132 _cleanup_free_ char *w = NULL;
1133
1134 r = extract_first_word(&rvalue, &w, NULL, 0);
1135 if (r == -ENOMEM)
1136 return log_oom();
1137 if (r < 0) {
1138 log_syntax(unit, LOG_ERR, filename, line, r,
1139 "Failed to extract NTP server name, ignoring: %s", rvalue);
1140 break;
1141 }
1142 if (r == 0)
1143 break;
1144
1145 r = dns_name_is_valid_or_address(w);
1146 if (r <= 0) {
1147 log_syntax(unit, LOG_ERR, filename, line, r,
1148 "%s is not a valid domain name or IP address, ignoring.", w);
1149 continue;
1150 }
1151
1152 if (strv_length(*l) > MAX_NTP_SERVERS) {
1153 log_syntax(unit, LOG_WARNING, filename, line, 0,
1154 "More than %u NTP servers specified, ignoring \"%s\" and any subsequent entries.",
1155 MAX_NTP_SERVERS, w);
1156 break;
1157 }
1158
1159 r = strv_consume(l, TAKE_PTR(w));
1160 if (r < 0)
1161 return log_oom();
1162 }
1163
1164 return 0;
1165 }
1166
1167 int config_parse_required_for_online(
1168 const char *unit,
1169 const char *filename,
1170 unsigned line,
1171 const char *section,
1172 unsigned section_line,
1173 const char *lvalue,
1174 int ltype,
1175 const char *rvalue,
1176 void *data,
1177 void *userdata) {
1178
1179 Network *network = data;
1180 LinkOperationalState s;
1181 bool required = true;
1182 int r;
1183
1184 if (isempty(rvalue)) {
1185 network->required_for_online = true;
1186 network->required_operstate_for_online = LINK_OPERSTATE_DEGRADED;
1187 return 0;
1188 }
1189
1190 s = link_operstate_from_string(rvalue);
1191 if (s < 0) {
1192 r = parse_boolean(rvalue);
1193 if (r < 0) {
1194 log_syntax(unit, LOG_ERR, filename, line, r,
1195 "Failed to parse %s= setting, ignoring assignment: %s",
1196 lvalue, rvalue);
1197 return 0;
1198 }
1199
1200 required = r;
1201 s = LINK_OPERSTATE_DEGRADED;
1202 }
1203
1204 network->required_for_online = required;
1205 network->required_operstate_for_online = s;
1206
1207 return 0;
1208 }
1209
1210 DEFINE_CONFIG_PARSE_ENUM(config_parse_keep_configuration, keep_configuration, KeepConfiguration,
1211 "Failed to parse KeepConfiguration= setting");
1212
1213 static const char* const keep_configuration_table[_KEEP_CONFIGURATION_MAX] = {
1214 [KEEP_CONFIGURATION_NO] = "no",
1215 [KEEP_CONFIGURATION_DHCP_ON_STOP] = "dhcp-on-stop",
1216 [KEEP_CONFIGURATION_DHCP] = "dhcp",
1217 [KEEP_CONFIGURATION_STATIC] = "static",
1218 [KEEP_CONFIGURATION_YES] = "yes",
1219 };
1220
1221 DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(keep_configuration, KeepConfiguration, KEEP_CONFIGURATION_YES);