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