]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/network/networkd-network.c
Merge pull request #10159 from poettering/killall-spree-kernel-thread
[thirdparty/systemd.git] / src / network / networkd-network.c
1 /* SPDX-License-Identifier: LGPL-2.1+ */
2
3 #include <ctype.h>
4 #include <net/if.h>
5
6 #include "alloc-util.h"
7 #include "conf-files.h"
8 #include "conf-parser.h"
9 #include "dns-domain.h"
10 #include "fd-util.h"
11 #include "hostname-util.h"
12 #include "in-addr-util.h"
13 #include "network-internal.h"
14 #include "networkd-manager.h"
15 #include "networkd-network.h"
16 #include "parse-util.h"
17 #include "set.h"
18 #include "stat-util.h"
19 #include "string-table.h"
20 #include "string-util.h"
21 #include "strv.h"
22 #include "util.h"
23
24 static void network_config_hash_func(const void *p, struct siphash *state) {
25 const NetworkConfigSection *c = p;
26
27 siphash24_compress(c->filename, strlen(c->filename), state);
28 siphash24_compress(&c->line, sizeof(c->line), state);
29 }
30
31 static int network_config_compare_func(const void *a, const void *b) {
32 const NetworkConfigSection *x = a, *y = b;
33 int r;
34
35 r = strcmp(x->filename, y->filename);
36 if (r != 0)
37 return r;
38
39 return CMP(x->line, y->line);
40 }
41
42 const struct hash_ops network_config_hash_ops = {
43 .hash = network_config_hash_func,
44 .compare = network_config_compare_func,
45 };
46
47 int network_config_section_new(const char *filename, unsigned line, NetworkConfigSection **s) {
48 NetworkConfigSection *cs;
49
50 cs = malloc0(offsetof(NetworkConfigSection, filename) + strlen(filename) + 1);
51 if (!cs)
52 return -ENOMEM;
53
54 strcpy(cs->filename, filename);
55 cs->line = line;
56
57 *s = TAKE_PTR(cs);
58
59 return 0;
60 }
61
62 void network_config_section_free(NetworkConfigSection *cs) {
63 free(cs);
64 }
65
66 /* Set defaults following RFC7844 */
67 void network_apply_anonymize_if_set(Network *network) {
68 if (!network->dhcp_anonymize)
69 return;
70 /* RFC7844 3.7
71 SHOULD NOT send the Host Name option */
72 network->dhcp_send_hostname = false;
73 /* RFC7844 section 3.:
74 MAY contain the Client Identifier option
75 Section 3.5:
76 clients MUST use client identifiers based solely
77 on the link-layer address */
78 /* NOTE: Using MAC, as it does not reveal extra information,
79 * and some servers might not answer if this option is not sent */
80 network->dhcp_client_identifier = DHCP_CLIENT_ID_MAC;
81 /* RFC 7844 3.10:
82 SHOULD NOT use the Vendor Class Identifier option */
83 network->dhcp_vendor_class_identifier = mfree(network->dhcp_vendor_class_identifier);
84 /* RFC7844 section 3.6.:
85 The client intending to protect its privacy SHOULD only request a
86 minimal number of options in the PRL and SHOULD also randomly shuffle
87 the ordering of option codes in the PRL. If this random ordering
88 cannot be implemented, the client MAY order the option codes in the
89 PRL by option code number (lowest to highest).
90 */
91 /* NOTE: dhcp_use_mtu is false by default,
92 * though it was not initiallized to any value in network_load_one.
93 * Maybe there should be another var called *send*?
94 * (to use the MTU sent by the server but to do not send
95 * the option in the PRL). */
96 network->dhcp_use_mtu = false;
97 /* NOTE: when Anonymize=yes, the PRL route options are sent by default,
98 * but this is needed to use them. */
99 network->dhcp_use_routes = true;
100 /* RFC7844 section 3.6.
101 * same comments as previous option */
102 network->dhcp_use_timezone = false;
103 }
104
105 static int network_load_one(Manager *manager, const char *filename) {
106 _cleanup_(network_freep) Network *network = NULL;
107 _cleanup_fclose_ FILE *file = NULL;
108 char *d;
109 const char *dropin_dirname;
110 Route *route;
111 Address *address;
112 int r;
113
114 assert(manager);
115 assert(filename);
116
117 file = fopen(filename, "re");
118 if (!file) {
119 if (errno == ENOENT)
120 return 0;
121
122 return -errno;
123 }
124
125 if (null_or_empty_fd(fileno(file))) {
126 log_debug("Skipping empty file: %s", filename);
127 return 0;
128 }
129
130 network = new0(Network, 1);
131 if (!network)
132 return log_oom();
133
134 network->manager = manager;
135
136 LIST_HEAD_INIT(network->static_addresses);
137 LIST_HEAD_INIT(network->static_routes);
138 LIST_HEAD_INIT(network->static_fdb_entries);
139 LIST_HEAD_INIT(network->ipv6_proxy_ndp_addresses);
140 LIST_HEAD_INIT(network->address_labels);
141 LIST_HEAD_INIT(network->static_prefixes);
142 LIST_HEAD_INIT(network->rules);
143
144 network->stacked_netdevs = hashmap_new(&string_hash_ops);
145 if (!network->stacked_netdevs)
146 return log_oom();
147
148 network->addresses_by_section = hashmap_new(&network_config_hash_ops);
149 if (!network->addresses_by_section)
150 return log_oom();
151
152 network->routes_by_section = hashmap_new(&network_config_hash_ops);
153 if (!network->routes_by_section)
154 return log_oom();
155
156 network->fdb_entries_by_section = hashmap_new(NULL);
157 if (!network->fdb_entries_by_section)
158 return log_oom();
159
160 network->address_labels_by_section = hashmap_new(&network_config_hash_ops);
161 if (!network->address_labels_by_section)
162 log_oom();
163
164 network->prefixes_by_section = hashmap_new(&network_config_hash_ops);
165 if (!network->prefixes_by_section)
166 return log_oom();
167
168 network->rules_by_section = hashmap_new(&network_config_hash_ops);
169 if (!network->rules_by_section)
170 return log_oom();
171
172 network->filename = strdup(filename);
173 if (!network->filename)
174 return log_oom();
175
176 network->name = strdup(basename(filename));
177 if (!network->name)
178 return log_oom();
179
180 d = strrchr(network->name, '.');
181 if (!d)
182 return -EINVAL;
183
184 assert(streq(d, ".network"));
185
186 *d = '\0';
187
188 network->required_for_online = true;
189 network->dhcp = ADDRESS_FAMILY_NO;
190 network->dhcp_use_ntp = true;
191 network->dhcp_use_dns = true;
192 network->dhcp_use_hostname = true;
193 network->dhcp_use_routes = true;
194 /* NOTE: this var might be overwriten by network_apply_anonymize_if_set */
195 network->dhcp_send_hostname = true;
196 /* To enable/disable RFC7844 Anonymity Profiles */
197 network->dhcp_anonymize = false;
198 network->dhcp_route_metric = DHCP_ROUTE_METRIC;
199 /* NOTE: this var might be overwrite by network_apply_anonymize_if_set */
200 network->dhcp_client_identifier = DHCP_CLIENT_ID_DUID;
201 network->dhcp_route_table = RT_TABLE_MAIN;
202 network->dhcp_route_table_set = false;
203 /* NOTE: from man: UseMTU=... Defaults to false*/
204 network->dhcp_use_mtu = false;
205 /* NOTE: from man: UseTimezone=... Defaults to "no".*/
206 network->dhcp_use_timezone = false;
207 network->rapid_commit = true;
208
209 network->dhcp_server_emit_dns = true;
210 network->dhcp_server_emit_ntp = true;
211 network->dhcp_server_emit_router = true;
212 network->dhcp_server_emit_timezone = true;
213
214 network->router_emit_dns = true;
215 network->router_emit_domains = true;
216
217 network->use_bpdu = -1;
218 network->hairpin = -1;
219 network->fast_leave = -1;
220 network->allow_port_to_be_root = -1;
221 network->unicast_flood = -1;
222 network->priority = LINK_BRIDGE_PORT_PRIORITY_INVALID;
223
224 network->lldp_mode = LLDP_MODE_ROUTERS_ONLY;
225
226 network->llmnr = RESOLVE_SUPPORT_YES;
227 network->mdns = RESOLVE_SUPPORT_NO;
228 network->dnssec_mode = _DNSSEC_MODE_INVALID;
229 network->dns_over_tls_mode = _DNS_OVER_TLS_MODE_INVALID;
230
231 network->link_local = ADDRESS_FAMILY_IPV6;
232
233 network->ipv6_privacy_extensions = IPV6_PRIVACY_EXTENSIONS_NO;
234 network->ipv6_accept_ra = -1;
235 network->ipv6_dad_transmits = -1;
236 network->ipv6_hop_limit = -1;
237 network->ipv6_proxy_ndp = -1;
238 network->duid.type = _DUID_TYPE_INVALID;
239 network->proxy_arp = -1;
240 network->arp = -1;
241 network->multicast = -1;
242 network->allmulticast = -1;
243 network->ipv6_accept_ra_use_dns = true;
244 network->ipv6_accept_ra_route_table = RT_TABLE_MAIN;
245 network->ipv6_mtu = 0;
246
247 dropin_dirname = strjoina(network->name, ".network.d");
248
249 r = config_parse_many(filename, network_dirs, dropin_dirname,
250 "Match\0"
251 "Link\0"
252 "Network\0"
253 "Address\0"
254 "IPv6AddressLabel\0"
255 "RoutingPolicyRule\0"
256 "Route\0"
257 "DHCP\0"
258 "DHCPv4\0" /* compat */
259 "DHCPServer\0"
260 "IPv6AcceptRA\0"
261 "IPv6NDPProxyAddress\0"
262 "Bridge\0"
263 "BridgeFDB\0"
264 "BridgeVLAN\0"
265 "IPv6PrefixDelegation\0"
266 "IPv6Prefix\0"
267 "CAN\0",
268 config_item_perf_lookup, network_network_gperf_lookup,
269 CONFIG_PARSE_WARN, network);
270 if (r < 0)
271 return r;
272
273 network_apply_anonymize_if_set(network);
274
275 /* IPMasquerade=yes implies IPForward=yes */
276 if (network->ip_masquerade)
277 network->ip_forward |= ADDRESS_FAMILY_IPV4;
278
279 if (network->mtu > 0 && network->dhcp_use_mtu) {
280 log_warning("MTUBytes= in [Link] section and UseMTU= in [DHCP] section are set in %s. "
281 "Disabling UseMTU=.", filename);
282 network->dhcp_use_mtu = false;
283 }
284
285 LIST_PREPEND(networks, manager->networks, network);
286
287 r = hashmap_ensure_allocated(&manager->networks_by_name, &string_hash_ops);
288 if (r < 0)
289 return r;
290
291 r = hashmap_put(manager->networks_by_name, network->name, network);
292 if (r < 0)
293 return r;
294
295 LIST_FOREACH(routes, route, network->static_routes) {
296 if (!route->family) {
297 log_warning("Route section without Gateway field configured in %s. "
298 "Ignoring", filename);
299 return 0;
300 }
301 }
302
303 LIST_FOREACH(addresses, address, network->static_addresses) {
304 if (!address->family) {
305 log_warning("Address section without Address field configured in %s. "
306 "Ignoring", filename);
307 return 0;
308 }
309 }
310
311 network = NULL;
312
313 return 0;
314 }
315
316 int network_load(Manager *manager) {
317 Network *network;
318 _cleanup_strv_free_ char **files = NULL;
319 char **f;
320 int r;
321
322 assert(manager);
323
324 while ((network = manager->networks))
325 network_free(network);
326
327 r = conf_files_list_strv(&files, ".network", NULL, 0, network_dirs);
328 if (r < 0)
329 return log_error_errno(r, "Failed to enumerate network files: %m");
330
331 STRV_FOREACH_BACKWARDS(f, files) {
332 r = network_load_one(manager, *f);
333 if (r < 0)
334 return r;
335 }
336
337 return 0;
338 }
339
340 void network_free(Network *network) {
341 IPv6ProxyNDPAddress *ipv6_proxy_ndp_address;
342 RoutingPolicyRule *rule;
343 FdbEntry *fdb_entry;
344 AddressLabel *label;
345 Prefix *prefix;
346 Address *address;
347 NetDev *netdev;
348 Route *route;
349 Iterator i;
350
351 if (!network)
352 return;
353
354 free(network->filename);
355
356 set_free_free(network->match_mac);
357 strv_free(network->match_path);
358 strv_free(network->match_driver);
359 strv_free(network->match_type);
360 strv_free(network->match_name);
361
362 free(network->description);
363 free(network->dhcp_vendor_class_identifier);
364 strv_free(network->dhcp_user_class);
365 free(network->dhcp_hostname);
366
367 free(network->mac);
368
369 strv_free(network->ntp);
370 free(network->dns);
371 strv_free(network->search_domains);
372 strv_free(network->route_domains);
373 strv_free(network->bind_carrier);
374
375 netdev_unref(network->bridge);
376 netdev_unref(network->bond);
377 netdev_unref(network->vrf);
378
379 HASHMAP_FOREACH(netdev, network->stacked_netdevs, i) {
380 hashmap_remove(network->stacked_netdevs, netdev->ifname);
381 netdev_unref(netdev);
382 }
383 hashmap_free(network->stacked_netdevs);
384
385 while ((route = network->static_routes))
386 route_free(route);
387
388 while ((address = network->static_addresses))
389 address_free(address);
390
391 while ((fdb_entry = network->static_fdb_entries))
392 fdb_entry_free(fdb_entry);
393
394 while ((ipv6_proxy_ndp_address = network->ipv6_proxy_ndp_addresses))
395 ipv6_proxy_ndp_address_free(ipv6_proxy_ndp_address);
396
397 while ((label = network->address_labels))
398 address_label_free(label);
399
400 while ((prefix = network->static_prefixes))
401 prefix_free(prefix);
402
403 while ((rule = network->rules))
404 routing_policy_rule_free(rule);
405
406 hashmap_free(network->addresses_by_section);
407 hashmap_free(network->routes_by_section);
408 hashmap_free(network->fdb_entries_by_section);
409 hashmap_free(network->address_labels_by_section);
410 hashmap_free(network->prefixes_by_section);
411 hashmap_free(network->rules_by_section);
412
413 if (network->manager) {
414 if (network->manager->networks)
415 LIST_REMOVE(networks, network->manager->networks, network);
416
417 if (network->manager->networks_by_name)
418 hashmap_remove(network->manager->networks_by_name, network->name);
419
420 if (network->manager->duids_requesting_uuid)
421 set_remove(network->manager->duids_requesting_uuid, &network->duid);
422 }
423
424 free(network->name);
425
426 condition_free_list(network->match_host);
427 condition_free_list(network->match_virt);
428 condition_free_list(network->match_kernel_cmdline);
429 condition_free_list(network->match_kernel_version);
430 condition_free_list(network->match_arch);
431
432 free(network->dhcp_server_timezone);
433 free(network->dhcp_server_dns);
434 free(network->dhcp_server_ntp);
435
436 set_free_free(network->dnssec_negative_trust_anchors);
437
438 free(network);
439 }
440
441 int network_get_by_name(Manager *manager, const char *name, Network **ret) {
442 Network *network;
443
444 assert(manager);
445 assert(name);
446 assert(ret);
447
448 network = hashmap_get(manager->networks_by_name, name);
449 if (!network)
450 return -ENOENT;
451
452 *ret = network;
453
454 return 0;
455 }
456
457 int network_get(Manager *manager, sd_device *device,
458 const char *ifname, const struct ether_addr *address,
459 Network **ret) {
460 const char *path = NULL, *parent_driver = NULL, *driver = NULL, *devtype = NULL;
461 sd_device *parent;
462 Network *network;
463
464 assert(manager);
465 assert(ret);
466
467 if (device) {
468 (void) sd_device_get_property_value(device, "ID_PATH", &path);
469
470 if (sd_device_get_parent(device, &parent) >= 0)
471 (void) sd_device_get_driver(parent, &parent_driver);
472
473 (void) sd_device_get_property_value(device, "ID_NET_DRIVER", &driver);
474
475 (void) sd_device_get_devtype(device, &devtype);
476 }
477
478 LIST_FOREACH(networks, network, manager->networks) {
479 if (net_match_config(network->match_mac, network->match_path,
480 network->match_driver, network->match_type,
481 network->match_name, network->match_host,
482 network->match_virt, network->match_kernel_cmdline,
483 network->match_kernel_version, network->match_arch,
484 address, path, parent_driver, driver,
485 devtype, ifname)) {
486 if (network->match_name && device) {
487 const char *attr;
488 uint8_t name_assign_type = NET_NAME_UNKNOWN;
489
490 if (sd_device_get_sysattr_value(device, "name_assign_type", &attr) >= 0)
491 (void) safe_atou8(attr, &name_assign_type);
492
493 if (name_assign_type == NET_NAME_ENUM)
494 log_warning("%s: found matching network '%s', based on potentially unpredictable ifname",
495 ifname, network->filename);
496 else
497 log_debug("%s: found matching network '%s'", ifname, network->filename);
498 } else
499 log_debug("%s: found matching network '%s'", ifname, network->filename);
500
501 *ret = network;
502 return 0;
503 }
504 }
505
506 *ret = NULL;
507
508 return -ENOENT;
509 }
510
511 int network_apply(Network *network, Link *link) {
512 int r;
513
514 assert(network);
515 assert(link);
516
517 link->network = network;
518
519 if (network->ipv4ll_route) {
520 Route *route;
521
522 r = route_new_static(network, NULL, 0, &route);
523 if (r < 0)
524 return r;
525
526 r = inet_pton(AF_INET, "169.254.0.0", &route->dst.in);
527 if (r == 0)
528 return -EINVAL;
529 if (r < 0)
530 return -errno;
531
532 route->family = AF_INET;
533 route->dst_prefixlen = 16;
534 route->scope = RT_SCOPE_LINK;
535 route->priority = IPV4LL_ROUTE_METRIC;
536 route->protocol = RTPROT_STATIC;
537 }
538
539 if (network->n_dns > 0 ||
540 !strv_isempty(network->ntp) ||
541 !strv_isempty(network->search_domains) ||
542 !strv_isempty(network->route_domains))
543 link_dirty(link);
544
545 return 0;
546 }
547
548 bool network_has_static_ipv6_addresses(Network *network) {
549 Address *address;
550
551 assert(network);
552
553 LIST_FOREACH(addresses, address, network->static_addresses) {
554 if (address->family == AF_INET6)
555 return true;
556 }
557
558 return false;
559 }
560
561 int config_parse_netdev(const char *unit,
562 const char *filename,
563 unsigned line,
564 const char *section,
565 unsigned section_line,
566 const char *lvalue,
567 int ltype,
568 const char *rvalue,
569 void *data,
570 void *userdata) {
571 Network *network = userdata;
572 _cleanup_free_ char *kind_string = NULL;
573 char *p;
574 NetDev *netdev;
575 NetDevKind kind;
576 int r;
577
578 assert(filename);
579 assert(lvalue);
580 assert(rvalue);
581 assert(data);
582
583 kind_string = strdup(lvalue);
584 if (!kind_string)
585 return log_oom();
586
587 /* the keys are CamelCase versions of the kind */
588 for (p = kind_string; *p; p++)
589 *p = tolower(*p);
590
591 kind = netdev_kind_from_string(kind_string);
592 if (kind == _NETDEV_KIND_INVALID) {
593 log_syntax(unit, LOG_ERR, filename, line, 0, "Invalid NetDev kind: %s", lvalue);
594 return 0;
595 }
596
597 r = netdev_get(network->manager, rvalue, &netdev);
598 if (r < 0) {
599 log_syntax(unit, LOG_ERR, filename, line, r, "%s could not be found, ignoring assignment: %s", lvalue, rvalue);
600 return 0;
601 }
602
603 if (netdev->kind != kind) {
604 log_syntax(unit, LOG_ERR, filename, line, 0, "NetDev is not a %s, ignoring assignment: %s", lvalue, rvalue);
605 return 0;
606 }
607
608 switch (kind) {
609 case NETDEV_KIND_BRIDGE:
610 network->bridge = netdev;
611
612 break;
613 case NETDEV_KIND_BOND:
614 network->bond = netdev;
615
616 break;
617 case NETDEV_KIND_VRF:
618 network->vrf = netdev;
619
620 break;
621 case NETDEV_KIND_VLAN:
622 case NETDEV_KIND_MACVLAN:
623 case NETDEV_KIND_MACVTAP:
624 case NETDEV_KIND_IPVLAN:
625 case NETDEV_KIND_VXLAN:
626 case NETDEV_KIND_VCAN:
627 r = hashmap_put(network->stacked_netdevs, netdev->ifname, netdev);
628 if (r < 0) {
629 log_syntax(unit, LOG_ERR, filename, line, r, "Cannot add NetDev '%s' to network: %m", rvalue);
630 return 0;
631 }
632
633 break;
634 default:
635 assert_not_reached("Cannot parse NetDev");
636 }
637
638 netdev_ref(netdev);
639
640 return 0;
641 }
642
643 int config_parse_domains(
644 const char *unit,
645 const char *filename,
646 unsigned line,
647 const char *section,
648 unsigned section_line,
649 const char *lvalue,
650 int ltype,
651 const char *rvalue,
652 void *data,
653 void *userdata) {
654
655 const char *p;
656 Network *n = data;
657 int r;
658
659 assert(n);
660 assert(lvalue);
661 assert(rvalue);
662
663 if (isempty(rvalue)) {
664 n->search_domains = strv_free(n->search_domains);
665 n->route_domains = strv_free(n->route_domains);
666 return 0;
667 }
668
669 p = rvalue;
670 for (;;) {
671 _cleanup_free_ char *w = NULL, *normalized = NULL;
672 const char *domain;
673 bool is_route;
674
675 r = extract_first_word(&p, &w, NULL, 0);
676 if (r < 0) {
677 log_syntax(unit, LOG_ERR, filename, line, r, "Failed to extract search or route domain, ignoring: %s", rvalue);
678 break;
679 }
680 if (r == 0)
681 break;
682
683 is_route = w[0] == '~';
684 domain = is_route ? w + 1 : w;
685
686 if (dns_name_is_root(domain) || streq(domain, "*")) {
687 /* If the root domain appears as is, or the special token "*" is found, we'll consider this as
688 * routing domain, unconditionally. */
689 is_route = true;
690 domain = "."; /* make sure we don't allow empty strings, thus write the root domain as "." */
691
692 } else {
693 r = dns_name_normalize(domain, &normalized);
694 if (r < 0) {
695 log_syntax(unit, LOG_ERR, filename, line, r, "'%s' is not a valid domain name, ignoring.", domain);
696 continue;
697 }
698
699 domain = normalized;
700
701 if (is_localhost(domain)) {
702 log_syntax(unit, LOG_ERR, filename, line, 0, "'localhost' domain names may not be configure as search or route domains, ignoring assignment: %s", domain);
703 continue;
704 }
705 }
706
707 if (is_route) {
708 r = strv_extend(&n->route_domains, domain);
709 if (r < 0)
710 return log_oom();
711
712 } else {
713 r = strv_extend(&n->search_domains, domain);
714 if (r < 0)
715 return log_oom();
716 }
717 }
718
719 strv_uniq(n->route_domains);
720 strv_uniq(n->search_domains);
721
722 return 0;
723 }
724
725 int config_parse_tunnel(const char *unit,
726 const char *filename,
727 unsigned line,
728 const char *section,
729 unsigned section_line,
730 const char *lvalue,
731 int ltype,
732 const char *rvalue,
733 void *data,
734 void *userdata) {
735 Network *network = userdata;
736 NetDev *netdev;
737 int r;
738
739 assert(filename);
740 assert(lvalue);
741 assert(rvalue);
742 assert(data);
743
744 r = netdev_get(network->manager, rvalue, &netdev);
745 if (r < 0) {
746 log_syntax(unit, LOG_ERR, filename, line, r, "Tunnel is invalid, ignoring assignment: %s", rvalue);
747 return 0;
748 }
749
750 if (!IN_SET(netdev->kind,
751 NETDEV_KIND_IPIP,
752 NETDEV_KIND_SIT,
753 NETDEV_KIND_GRE,
754 NETDEV_KIND_GRETAP,
755 NETDEV_KIND_IP6GRE,
756 NETDEV_KIND_IP6GRETAP,
757 NETDEV_KIND_VTI,
758 NETDEV_KIND_VTI6,
759 NETDEV_KIND_IP6TNL)) {
760 log_syntax(unit, LOG_ERR, filename, line, 0,
761 "NetDev is not a tunnel, ignoring assignment: %s", rvalue);
762 return 0;
763 }
764
765 r = hashmap_put(network->stacked_netdevs, netdev->ifname, netdev);
766 if (r < 0) {
767 log_syntax(unit, LOG_ERR, filename, line, r, "Cannot add VLAN '%s' to network, ignoring: %m", rvalue);
768 return 0;
769 }
770
771 netdev_ref(netdev);
772
773 return 0;
774 }
775
776 int config_parse_ipv4ll(
777 const char* unit,
778 const char *filename,
779 unsigned line,
780 const char *section,
781 unsigned section_line,
782 const char *lvalue,
783 int ltype,
784 const char *rvalue,
785 void *data,
786 void *userdata) {
787
788 AddressFamilyBoolean *link_local = data;
789
790 assert(filename);
791 assert(lvalue);
792 assert(rvalue);
793 assert(data);
794
795 /* Note that this is mostly like
796 * config_parse_address_family_boolean(), except that it
797 * applies only to IPv4 */
798
799 SET_FLAG(*link_local, ADDRESS_FAMILY_IPV4, parse_boolean(rvalue));
800
801 return 0;
802 }
803
804 int config_parse_dhcp(
805 const char* unit,
806 const char *filename,
807 unsigned line,
808 const char *section,
809 unsigned section_line,
810 const char *lvalue,
811 int ltype,
812 const char *rvalue,
813 void *data,
814 void *userdata) {
815
816 AddressFamilyBoolean *dhcp = data, s;
817
818 assert(filename);
819 assert(lvalue);
820 assert(rvalue);
821 assert(data);
822
823 /* Note that this is mostly like
824 * config_parse_address_family_boolean(), except that it
825 * understands some old names for the enum values */
826
827 s = address_family_boolean_from_string(rvalue);
828 if (s < 0) {
829
830 /* Previously, we had a slightly different enum here,
831 * support its values for compatbility. */
832
833 if (streq(rvalue, "none"))
834 s = ADDRESS_FAMILY_NO;
835 else if (streq(rvalue, "v4"))
836 s = ADDRESS_FAMILY_IPV4;
837 else if (streq(rvalue, "v6"))
838 s = ADDRESS_FAMILY_IPV6;
839 else if (streq(rvalue, "both"))
840 s = ADDRESS_FAMILY_YES;
841 else {
842 log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse DHCP option, ignoring: %s", rvalue);
843 return 0;
844 }
845 }
846
847 *dhcp = s;
848 return 0;
849 }
850
851 static const char* const dhcp_client_identifier_table[_DHCP_CLIENT_ID_MAX] = {
852 [DHCP_CLIENT_ID_MAC] = "mac",
853 [DHCP_CLIENT_ID_DUID] = "duid",
854 [DHCP_CLIENT_ID_DUID_ONLY] = "duid-only",
855 };
856
857 DEFINE_PRIVATE_STRING_TABLE_LOOKUP_FROM_STRING(dhcp_client_identifier, DHCPClientIdentifier);
858 DEFINE_CONFIG_PARSE_ENUM(config_parse_dhcp_client_identifier, dhcp_client_identifier, DHCPClientIdentifier, "Failed to parse client identifier type");
859
860 int config_parse_ipv6token(
861 const char* unit,
862 const char *filename,
863 unsigned line,
864 const char *section,
865 unsigned section_line,
866 const char *lvalue,
867 int ltype,
868 const char *rvalue,
869 void *data,
870 void *userdata) {
871
872 union in_addr_union buffer;
873 struct in6_addr *token = data;
874 int r;
875
876 assert(filename);
877 assert(lvalue);
878 assert(rvalue);
879 assert(token);
880
881 r = in_addr_from_string(AF_INET6, rvalue, &buffer);
882 if (r < 0) {
883 log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse IPv6 token, ignoring: %s", rvalue);
884 return 0;
885 }
886
887 r = in_addr_is_null(AF_INET6, &buffer);
888 if (r != 0) {
889 log_syntax(unit, LOG_ERR, filename, line, r, "IPv6 token cannot be the ANY address, ignoring: %s", rvalue);
890 return 0;
891 }
892
893 if ((buffer.in6.s6_addr32[0] | buffer.in6.s6_addr32[1]) != 0) {
894 log_syntax(unit, LOG_ERR, filename, line, 0, "IPv6 token cannot be longer than 64 bits, ignoring: %s", rvalue);
895 return 0;
896 }
897
898 *token = buffer.in6;
899
900 return 0;
901 }
902
903 static const char* const ipv6_privacy_extensions_table[_IPV6_PRIVACY_EXTENSIONS_MAX] = {
904 [IPV6_PRIVACY_EXTENSIONS_NO] = "no",
905 [IPV6_PRIVACY_EXTENSIONS_PREFER_PUBLIC] = "prefer-public",
906 [IPV6_PRIVACY_EXTENSIONS_YES] = "yes",
907 };
908
909 DEFINE_STRING_TABLE_LOOKUP(ipv6_privacy_extensions, IPv6PrivacyExtensions);
910
911 int config_parse_ipv6_privacy_extensions(
912 const char* unit,
913 const char *filename,
914 unsigned line,
915 const char *section,
916 unsigned section_line,
917 const char *lvalue,
918 int ltype,
919 const char *rvalue,
920 void *data,
921 void *userdata) {
922
923 IPv6PrivacyExtensions *ipv6_privacy_extensions = data;
924 int k;
925
926 assert(filename);
927 assert(lvalue);
928 assert(rvalue);
929 assert(ipv6_privacy_extensions);
930
931 /* Our enum shall be a superset of booleans, hence first try
932 * to parse as boolean, and then as enum */
933
934 k = parse_boolean(rvalue);
935 if (k > 0)
936 *ipv6_privacy_extensions = IPV6_PRIVACY_EXTENSIONS_YES;
937 else if (k == 0)
938 *ipv6_privacy_extensions = IPV6_PRIVACY_EXTENSIONS_NO;
939 else {
940 IPv6PrivacyExtensions s;
941
942 s = ipv6_privacy_extensions_from_string(rvalue);
943 if (s < 0) {
944
945 if (streq(rvalue, "kernel"))
946 s = _IPV6_PRIVACY_EXTENSIONS_INVALID;
947 else {
948 log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse IPv6 privacy extensions option, ignoring: %s", rvalue);
949 return 0;
950 }
951 }
952
953 *ipv6_privacy_extensions = s;
954 }
955
956 return 0;
957 }
958
959 int config_parse_hostname(
960 const char *unit,
961 const char *filename,
962 unsigned line,
963 const char *section,
964 unsigned section_line,
965 const char *lvalue,
966 int ltype,
967 const char *rvalue,
968 void *data,
969 void *userdata) {
970
971 _cleanup_free_ char *hn = NULL;
972 char **hostname = data;
973 int r;
974
975 assert(filename);
976 assert(lvalue);
977 assert(rvalue);
978
979 r = config_parse_string(unit, filename, line, section, section_line, lvalue, ltype, rvalue, &hn, userdata);
980 if (r < 0)
981 return r;
982
983 if (!hostname_is_valid(hn, false)) {
984 log_syntax(unit, LOG_ERR, filename, line, 0, "Hostname is not valid, ignoring assignment: %s", rvalue);
985 return 0;
986 }
987
988 r = dns_name_is_valid(hn);
989 if (r < 0) {
990 log_syntax(unit, LOG_ERR, filename, line, r, "Failed to check validity of hostname '%s', ignoring assignment: %m", rvalue);
991 return 0;
992 }
993 if (r == 0) {
994 log_syntax(unit, LOG_ERR, filename, line, 0, "Hostname is not a valid DNS domain name, ignoring assignment: %s", rvalue);
995 return 0;
996 }
997
998 return free_and_replace(*hostname, hn);
999 }
1000
1001 int config_parse_timezone(
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 _cleanup_free_ char *tz = NULL;
1014 char **datap = data;
1015 int r;
1016
1017 assert(filename);
1018 assert(lvalue);
1019 assert(rvalue);
1020
1021 r = config_parse_string(unit, filename, line, section, section_line, lvalue, ltype, rvalue, &tz, userdata);
1022 if (r < 0)
1023 return r;
1024
1025 if (!timezone_is_valid(tz, LOG_ERR)) {
1026 log_syntax(unit, LOG_ERR, filename, line, 0, "Timezone is not valid, ignoring assignment: %s", rvalue);
1027 return 0;
1028 }
1029
1030 return free_and_replace(*datap, tz);
1031 }
1032
1033 int config_parse_dhcp_server_dns(
1034 const char *unit,
1035 const char *filename,
1036 unsigned line,
1037 const char *section,
1038 unsigned section_line,
1039 const char *lvalue,
1040 int ltype,
1041 const char *rvalue,
1042 void *data,
1043 void *userdata) {
1044
1045 Network *n = data;
1046 const char *p = rvalue;
1047 int r;
1048
1049 assert(filename);
1050 assert(lvalue);
1051 assert(rvalue);
1052
1053 for (;;) {
1054 _cleanup_free_ char *w = NULL;
1055 struct in_addr a, *m;
1056
1057 r = extract_first_word(&p, &w, NULL, 0);
1058 if (r == -ENOMEM)
1059 return log_oom();
1060 if (r < 0) {
1061 log_syntax(unit, LOG_ERR, filename, line, r, "Failed to extract word, ignoring: %s", rvalue);
1062 return 0;
1063 }
1064 if (r == 0)
1065 break;
1066
1067 if (inet_pton(AF_INET, w, &a) <= 0) {
1068 log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse DNS server address, ignoring: %s", w);
1069 continue;
1070 }
1071
1072 m = reallocarray(n->dhcp_server_dns, n->n_dhcp_server_dns + 1, sizeof(struct in_addr));
1073 if (!m)
1074 return log_oom();
1075
1076 m[n->n_dhcp_server_dns++] = a;
1077 n->dhcp_server_dns = m;
1078 }
1079
1080 return 0;
1081 }
1082
1083 int config_parse_radv_dns(
1084 const char *unit,
1085 const char *filename,
1086 unsigned line,
1087 const char *section,
1088 unsigned section_line,
1089 const char *lvalue,
1090 int ltype,
1091 const char *rvalue,
1092 void *data,
1093 void *userdata) {
1094
1095 Network *n = data;
1096 const char *p = rvalue;
1097 int r;
1098
1099 assert(filename);
1100 assert(lvalue);
1101 assert(rvalue);
1102
1103 for (;;) {
1104 _cleanup_free_ char *w = NULL;
1105 union in_addr_union a;
1106
1107 r = extract_first_word(&p, &w, NULL, 0);
1108 if (r == -ENOMEM)
1109 return log_oom();
1110 if (r < 0) {
1111 log_syntax(unit, LOG_ERR, filename, line, r, "Failed to extract word, ignoring: %s", rvalue);
1112 return 0;
1113 }
1114 if (r == 0)
1115 break;
1116
1117 if (in_addr_from_string(AF_INET6, w, &a) >= 0) {
1118 struct in6_addr *m;
1119
1120 m = reallocarray(n->router_dns, n->n_router_dns + 1, sizeof(struct in6_addr));
1121 if (!m)
1122 return log_oom();
1123
1124 m[n->n_router_dns++] = a.in6;
1125 n->router_dns = m;
1126
1127 } else
1128 log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse DNS server address, ignoring: %s", w);
1129
1130 }
1131
1132 return 0;
1133 }
1134
1135 int config_parse_radv_search_domains(
1136 const char *unit,
1137 const char *filename,
1138 unsigned line,
1139 const char *section,
1140 unsigned section_line,
1141 const char *lvalue,
1142 int ltype,
1143 const char *rvalue,
1144 void *data,
1145 void *userdata) {
1146
1147 Network *n = data;
1148 const char *p = rvalue;
1149 int r;
1150
1151 assert(filename);
1152 assert(lvalue);
1153 assert(rvalue);
1154
1155 for (;;) {
1156 _cleanup_free_ char *w = NULL;
1157 _cleanup_free_ char *idna = NULL;
1158
1159 r = extract_first_word(&p, &w, NULL, 0);
1160 if (r == -ENOMEM)
1161 return log_oom();
1162 if (r < 0) {
1163 log_syntax(unit, LOG_ERR, filename, line, r, "Failed to extract word, ignoring: %s", rvalue);
1164 return 0;
1165 }
1166 if (r == 0)
1167 break;
1168
1169 r = dns_name_apply_idna(w, &idna);
1170 if (r > 0) {
1171 r = strv_push(&n->router_search_domains, idna);
1172 if (r >= 0)
1173 idna = NULL;
1174 } else if (r == 0) {
1175 r = strv_push(&n->router_search_domains, w);
1176 if (r >= 0)
1177 w = NULL;
1178 }
1179 }
1180
1181 return 0;
1182 }
1183
1184 int config_parse_dhcp_server_ntp(
1185 const char *unit,
1186 const char *filename,
1187 unsigned line,
1188 const char *section,
1189 unsigned section_line,
1190 const char *lvalue,
1191 int ltype,
1192 const char *rvalue,
1193 void *data,
1194 void *userdata) {
1195
1196 Network *n = data;
1197 const char *p = rvalue;
1198 int r;
1199
1200 assert(filename);
1201 assert(lvalue);
1202 assert(rvalue);
1203
1204 for (;;) {
1205 _cleanup_free_ char *w = NULL;
1206 struct in_addr a, *m;
1207
1208 r = extract_first_word(&p, &w, NULL, 0);
1209 if (r == -ENOMEM)
1210 return log_oom();
1211 if (r < 0) {
1212 log_syntax(unit, LOG_ERR, filename, line, r, "Failed to extract word, ignoring: %s", rvalue);
1213 return 0;
1214 }
1215 if (r == 0)
1216 return 0;
1217
1218 if (inet_pton(AF_INET, w, &a) <= 0) {
1219 log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse NTP server address, ignoring: %s", w);
1220 continue;
1221 }
1222
1223 m = reallocarray(n->dhcp_server_ntp, n->n_dhcp_server_ntp + 1, sizeof(struct in_addr));
1224 if (!m)
1225 return log_oom();
1226
1227 m[n->n_dhcp_server_ntp++] = a;
1228 n->dhcp_server_ntp = m;
1229 }
1230 }
1231
1232 int config_parse_dns(
1233 const char *unit,
1234 const char *filename,
1235 unsigned line,
1236 const char *section,
1237 unsigned section_line,
1238 const char *lvalue,
1239 int ltype,
1240 const char *rvalue,
1241 void *data,
1242 void *userdata) {
1243
1244 Network *n = userdata;
1245 int r;
1246
1247 assert(filename);
1248 assert(lvalue);
1249 assert(rvalue);
1250
1251 for (;;) {
1252 _cleanup_free_ char *w = NULL;
1253 union in_addr_union a;
1254 struct in_addr_data *m;
1255 int family;
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, "Invalid syntax, ignoring: %s", rvalue);
1262 break;
1263 }
1264 if (r == 0)
1265 break;
1266
1267 r = in_addr_from_string_auto(w, &family, &a);
1268 if (r < 0) {
1269 log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse dns server address, ignoring: %s", w);
1270 continue;
1271 }
1272
1273 m = reallocarray(n->dns, n->n_dns + 1, sizeof(struct in_addr_data));
1274 if (!m)
1275 return log_oom();
1276
1277 m[n->n_dns++] = (struct in_addr_data) {
1278 .family = family,
1279 .address = a,
1280 };
1281
1282 n->dns = m;
1283 }
1284
1285 return 0;
1286 }
1287
1288 int config_parse_dnssec_negative_trust_anchors(
1289 const char *unit,
1290 const char *filename,
1291 unsigned line,
1292 const char *section,
1293 unsigned section_line,
1294 const char *lvalue,
1295 int ltype,
1296 const char *rvalue,
1297 void *data,
1298 void *userdata) {
1299
1300 const char *p = rvalue;
1301 Network *n = data;
1302 int r;
1303
1304 assert(n);
1305 assert(lvalue);
1306 assert(rvalue);
1307
1308 if (isempty(rvalue)) {
1309 n->dnssec_negative_trust_anchors = set_free_free(n->dnssec_negative_trust_anchors);
1310 return 0;
1311 }
1312
1313 for (;;) {
1314 _cleanup_free_ char *w = NULL;
1315
1316 r = extract_first_word(&p, &w, NULL, 0);
1317 if (r < 0) {
1318 log_syntax(unit, LOG_ERR, filename, line, r, "Failed to extract negative trust anchor domain, ignoring: %s", rvalue);
1319 break;
1320 }
1321 if (r == 0)
1322 break;
1323
1324 r = dns_name_is_valid(w);
1325 if (r <= 0) {
1326 log_syntax(unit, LOG_ERR, filename, line, r, "%s is not a valid domain name, ignoring.", w);
1327 continue;
1328 }
1329
1330 r = set_ensure_allocated(&n->dnssec_negative_trust_anchors, &dns_name_hash_ops);
1331 if (r < 0)
1332 return log_oom();
1333
1334 r = set_put(n->dnssec_negative_trust_anchors, w);
1335 if (r < 0)
1336 return log_oom();
1337 if (r > 0)
1338 w = NULL;
1339 }
1340
1341 return 0;
1342 }
1343
1344 int config_parse_ntp(
1345 const char *unit,
1346 const char *filename,
1347 unsigned line,
1348 const char *section,
1349 unsigned section_line,
1350 const char *lvalue,
1351 int ltype,
1352 const char *rvalue,
1353 void *data,
1354 void *userdata) {
1355
1356 char ***l = data;
1357 int r;
1358
1359 assert(l);
1360 assert(lvalue);
1361 assert(rvalue);
1362
1363 if (isempty(rvalue)) {
1364 *l = strv_free(*l);
1365 return 0;
1366 }
1367
1368 for (;;) {
1369 _cleanup_free_ char *w = NULL;
1370
1371 r = extract_first_word(&rvalue, &w, NULL, 0);
1372 if (r == -ENOMEM)
1373 return log_oom();
1374 if (r < 0) {
1375 log_syntax(unit, LOG_ERR, filename, line, r, "Failed to extract NTP server name, ignoring: %s", rvalue);
1376 break;
1377 }
1378 if (r == 0)
1379 break;
1380
1381 r = dns_name_is_valid_or_address(w);
1382 if (r <= 0) {
1383 log_syntax(unit, LOG_ERR, filename, line, r, "%s is not a valid domain name or IP address, ignoring.", w);
1384 continue;
1385 }
1386
1387 r = strv_push(l, w);
1388 if (r < 0)
1389 return log_oom();
1390
1391 w = NULL;
1392 }
1393
1394 return 0;
1395 }
1396
1397 int config_parse_dhcp_user_class(
1398 const char *unit,
1399 const char *filename,
1400 unsigned line,
1401 const char *section,
1402 unsigned section_line,
1403 const char *lvalue,
1404 int ltype,
1405 const char *rvalue,
1406 void *data,
1407 void *userdata) {
1408
1409 char ***l = data;
1410 int r;
1411
1412 assert(l);
1413 assert(lvalue);
1414 assert(rvalue);
1415
1416 if (isempty(rvalue)) {
1417 *l = strv_free(*l);
1418 return 0;
1419 }
1420
1421 for (;;) {
1422 _cleanup_free_ char *w = NULL;
1423
1424 r = extract_first_word(&rvalue, &w, NULL, 0);
1425 if (r == -ENOMEM)
1426 return log_oom();
1427 if (r < 0) {
1428 log_syntax(unit, LOG_ERR, filename, line, r, "Failed to split user classes option, ignoring: %s", rvalue);
1429 break;
1430 }
1431 if (r == 0)
1432 break;
1433
1434 if (strlen(w) > 255) {
1435 log_syntax(unit, LOG_ERR, filename, line, r, "%s length is not in the range 1-255, ignoring.", w);
1436 continue;
1437 }
1438
1439 r = strv_push(l, w);
1440 if (r < 0)
1441 return log_oom();
1442
1443 w = NULL;
1444 }
1445
1446 return 0;
1447 }
1448
1449 int config_parse_dhcp_route_table(const char *unit,
1450 const char *filename,
1451 unsigned line,
1452 const char *section,
1453 unsigned section_line,
1454 const char *lvalue,
1455 int ltype,
1456 const char *rvalue,
1457 void *data,
1458 void *userdata) {
1459 Network *network = data;
1460 uint32_t rt;
1461 int r;
1462
1463 assert(filename);
1464 assert(lvalue);
1465 assert(rvalue);
1466 assert(data);
1467
1468 r = safe_atou32(rvalue, &rt);
1469 if (r < 0) {
1470 log_syntax(unit, LOG_ERR, filename, line, r,
1471 "Unable to read RouteTable, ignoring assignment: %s", rvalue);
1472 return 0;
1473 }
1474
1475 network->dhcp_route_table = rt;
1476 network->dhcp_route_table_set = true;
1477
1478 return 0;
1479 }
1480
1481 DEFINE_CONFIG_PARSE_ENUM(config_parse_dhcp_use_domains, dhcp_use_domains, DHCPUseDomains, "Failed to parse DHCP use domains setting");
1482
1483 static const char* const dhcp_use_domains_table[_DHCP_USE_DOMAINS_MAX] = {
1484 [DHCP_USE_DOMAINS_NO] = "no",
1485 [DHCP_USE_DOMAINS_ROUTE] = "route",
1486 [DHCP_USE_DOMAINS_YES] = "yes",
1487 };
1488
1489 DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(dhcp_use_domains, DHCPUseDomains, DHCP_USE_DOMAINS_YES);
1490
1491 DEFINE_CONFIG_PARSE_ENUM(config_parse_lldp_mode, lldp_mode, LLDPMode, "Failed to parse LLDP= setting.");
1492
1493 static const char* const lldp_mode_table[_LLDP_MODE_MAX] = {
1494 [LLDP_MODE_NO] = "no",
1495 [LLDP_MODE_YES] = "yes",
1496 [LLDP_MODE_ROUTERS_ONLY] = "routers-only",
1497 };
1498
1499 DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(lldp_mode, LLDPMode, LLDP_MODE_YES);