]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/network/networkd-network.c
core,udev,networkd: add ConditionKernelVersion=
[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
232 network->dhcp_server_emit_dns = true;
233 network->dhcp_server_emit_ntp = true;
234 network->dhcp_server_emit_router = true;
235 network->dhcp_server_emit_timezone = true;
236
237 network->router_emit_dns = true;
238 network->router_emit_domains = true;
239
240 network->use_bpdu = true;
241 network->allow_port_to_be_root = true;
242 network->unicast_flood = true;
243 network->priority = LINK_BRIDGE_PORT_PRIORITY_INVALID;
244
245 network->lldp_mode = LLDP_MODE_ROUTERS_ONLY;
246
247 network->llmnr = RESOLVE_SUPPORT_YES;
248 network->mdns = RESOLVE_SUPPORT_NO;
249 network->dnssec_mode = _DNSSEC_MODE_INVALID;
250
251 network->link_local = ADDRESS_FAMILY_IPV6;
252
253 network->ipv6_privacy_extensions = IPV6_PRIVACY_EXTENSIONS_NO;
254 network->ipv6_accept_ra = -1;
255 network->ipv6_dad_transmits = -1;
256 network->ipv6_hop_limit = -1;
257 network->ipv6_proxy_ndp = -1;
258 network->duid.type = _DUID_TYPE_INVALID;
259 network->proxy_arp = -1;
260 network->arp = -1;
261 network->ipv6_accept_ra_use_dns = true;
262 network->ipv6_accept_ra_route_table = RT_TABLE_MAIN;
263
264 dropin_dirname = strjoina(network->name, ".network.d");
265
266 r = config_parse_many(filename, network_dirs, dropin_dirname,
267 "Match\0"
268 "Link\0"
269 "Network\0"
270 "Address\0"
271 "IPv6AddressLabel\0"
272 "RoutingPolicyRule\0"
273 "Route\0"
274 "DHCP\0"
275 "DHCPv4\0" /* compat */
276 "DHCPServer\0"
277 "IPv6AcceptRA\0"
278 "IPv6NDPProxyAddress\0"
279 "Bridge\0"
280 "BridgeFDB\0"
281 "BridgeVLAN\0"
282 "IPv6PrefixDelegation\0"
283 "IPv6Prefix\0",
284 config_item_perf_lookup, network_network_gperf_lookup,
285 CONFIG_PARSE_WARN, network);
286 if (r < 0)
287 return r;
288
289 network_apply_anonymize_if_set(network);
290
291 /* IPMasquerade=yes implies IPForward=yes */
292 if (network->ip_masquerade)
293 network->ip_forward |= ADDRESS_FAMILY_IPV4;
294
295 LIST_PREPEND(networks, manager->networks, network);
296
297 r = hashmap_ensure_allocated(&manager->networks_by_name, &string_hash_ops);
298 if (r < 0)
299 return r;
300
301 r = hashmap_put(manager->networks_by_name, network->name, network);
302 if (r < 0)
303 return r;
304
305 LIST_FOREACH(routes, route, network->static_routes) {
306 if (!route->family) {
307 log_warning("Route section without Gateway field configured in %s. "
308 "Ignoring", filename);
309 return 0;
310 }
311 }
312
313 LIST_FOREACH(addresses, address, network->static_addresses) {
314 if (!address->family) {
315 log_warning("Address section without Address field configured in %s. "
316 "Ignoring", filename);
317 return 0;
318 }
319 }
320
321 network = NULL;
322
323 return 0;
324 }
325
326 int network_load(Manager *manager) {
327 Network *network;
328 _cleanup_strv_free_ char **files = NULL;
329 char **f;
330 int r;
331
332 assert(manager);
333
334 while ((network = manager->networks))
335 network_free(network);
336
337 r = conf_files_list_strv(&files, ".network", NULL, 0, network_dirs);
338 if (r < 0)
339 return log_error_errno(r, "Failed to enumerate network files: %m");
340
341 STRV_FOREACH_BACKWARDS(f, files) {
342 r = network_load_one(manager, *f);
343 if (r < 0)
344 return r;
345 }
346
347 return 0;
348 }
349
350 void network_free(Network *network) {
351 IPv6ProxyNDPAddress *ipv6_proxy_ndp_address;
352 RoutingPolicyRule *rule;
353 FdbEntry *fdb_entry;
354 AddressLabel *label;
355 Prefix *prefix;
356 Address *address;
357 NetDev *netdev;
358 Route *route;
359 Iterator i;
360
361 if (!network)
362 return;
363
364 free(network->filename);
365
366 free(network->match_mac);
367 strv_free(network->match_path);
368 strv_free(network->match_driver);
369 strv_free(network->match_type);
370 strv_free(network->match_name);
371
372 free(network->description);
373 free(network->dhcp_vendor_class_identifier);
374 free(network->dhcp_hostname);
375
376 free(network->mac);
377
378 strv_free(network->ntp);
379 free(network->dns);
380 strv_free(network->search_domains);
381 strv_free(network->route_domains);
382 strv_free(network->bind_carrier);
383
384 netdev_unref(network->bridge);
385 netdev_unref(network->bond);
386 netdev_unref(network->vrf);
387
388 HASHMAP_FOREACH(netdev, network->stacked_netdevs, i) {
389 hashmap_remove(network->stacked_netdevs, netdev->ifname);
390 netdev_unref(netdev);
391 }
392 hashmap_free(network->stacked_netdevs);
393
394 while ((route = network->static_routes))
395 route_free(route);
396
397 while ((address = network->static_addresses))
398 address_free(address);
399
400 while ((fdb_entry = network->static_fdb_entries))
401 fdb_entry_free(fdb_entry);
402
403 while ((ipv6_proxy_ndp_address = network->ipv6_proxy_ndp_addresses))
404 ipv6_proxy_ndp_address_free(ipv6_proxy_ndp_address);
405
406 while ((label = network->address_labels))
407 address_label_free(label);
408
409 while ((prefix = network->static_prefixes))
410 prefix_free(prefix);
411
412 while ((rule = network->rules))
413 routing_policy_rule_free(rule);
414
415 hashmap_free(network->addresses_by_section);
416 hashmap_free(network->routes_by_section);
417 hashmap_free(network->fdb_entries_by_section);
418 hashmap_free(network->address_labels_by_section);
419 hashmap_free(network->prefixes_by_section);
420 hashmap_free(network->rules_by_section);
421
422 if (network->manager) {
423 if (network->manager->networks)
424 LIST_REMOVE(networks, network->manager->networks, network);
425
426 if (network->manager->networks_by_name)
427 hashmap_remove(network->manager->networks_by_name, network->name);
428 }
429
430 free(network->name);
431
432 condition_free_list(network->match_host);
433 condition_free_list(network->match_virt);
434 condition_free_list(network->match_kernel_cmdline);
435 condition_free_list(network->match_kernel_version);
436 condition_free_list(network->match_arch);
437
438 free(network->dhcp_server_timezone);
439 free(network->dhcp_server_dns);
440 free(network->dhcp_server_ntp);
441
442 set_free_free(network->dnssec_negative_trust_anchors);
443
444 free(network);
445 }
446
447 int network_get_by_name(Manager *manager, const char *name, Network **ret) {
448 Network *network;
449
450 assert(manager);
451 assert(name);
452 assert(ret);
453
454 network = hashmap_get(manager->networks_by_name, name);
455 if (!network)
456 return -ENOENT;
457
458 *ret = network;
459
460 return 0;
461 }
462
463 int network_get(Manager *manager, struct udev_device *device,
464 const char *ifname, const struct ether_addr *address,
465 Network **ret) {
466 Network *network;
467 struct udev_device *parent;
468 const char *path = NULL, *parent_driver = NULL, *driver = NULL, *devtype = NULL;
469
470 assert(manager);
471 assert(ret);
472
473 if (device) {
474 path = udev_device_get_property_value(device, "ID_PATH");
475
476 parent = udev_device_get_parent(device);
477 if (parent)
478 parent_driver = udev_device_get_driver(parent);
479
480 driver = udev_device_get_property_value(device, "ID_NET_DRIVER");
481
482 devtype = udev_device_get_devtype(device);
483 }
484
485 LIST_FOREACH(networks, network, manager->networks) {
486 if (net_match_config(network->match_mac, network->match_path,
487 network->match_driver, network->match_type,
488 network->match_name, network->match_host,
489 network->match_virt, network->match_kernel_cmdline,
490 network->match_kernel_version, network->match_arch,
491 address, path, parent_driver, driver,
492 devtype, ifname)) {
493 if (network->match_name && device) {
494 const char *attr;
495 uint8_t name_assign_type = NET_NAME_UNKNOWN;
496
497 attr = udev_device_get_sysattr_value(device, "name_assign_type");
498 if (attr)
499 (void) safe_atou8(attr, &name_assign_type);
500
501 if (name_assign_type == NET_NAME_ENUM)
502 log_warning("%s: found matching network '%s', based on potentially unpredictable ifname",
503 ifname, network->filename);
504 else
505 log_debug("%s: found matching network '%s'", ifname, network->filename);
506 } else
507 log_debug("%s: found matching network '%s'", ifname, network->filename);
508
509 *ret = network;
510 return 0;
511 }
512 }
513
514 *ret = NULL;
515
516 return -ENOENT;
517 }
518
519 int network_apply(Network *network, Link *link) {
520 int r;
521
522 assert(network);
523 assert(link);
524
525 link->network = network;
526
527 if (network->ipv4ll_route) {
528 Route *route;
529
530 r = route_new_static(network, NULL, 0, &route);
531 if (r < 0)
532 return r;
533
534 r = inet_pton(AF_INET, "169.254.0.0", &route->dst.in);
535 if (r == 0)
536 return -EINVAL;
537 if (r < 0)
538 return -errno;
539
540 route->family = AF_INET;
541 route->dst_prefixlen = 16;
542 route->scope = RT_SCOPE_LINK;
543 route->priority = IPV4LL_ROUTE_METRIC;
544 route->protocol = RTPROT_STATIC;
545 }
546
547 if (network->n_dns > 0 ||
548 !strv_isempty(network->ntp) ||
549 !strv_isempty(network->search_domains) ||
550 !strv_isempty(network->route_domains))
551 link_dirty(link);
552
553 return 0;
554 }
555
556 bool network_has_static_ipv6_addresses(Network *network) {
557 Address *address;
558
559 assert(network);
560
561 LIST_FOREACH(addresses, address, network->static_addresses) {
562 if (address->family == AF_INET6)
563 return true;
564 }
565
566 return false;
567 }
568
569 int config_parse_netdev(const char *unit,
570 const char *filename,
571 unsigned line,
572 const char *section,
573 unsigned section_line,
574 const char *lvalue,
575 int ltype,
576 const char *rvalue,
577 void *data,
578 void *userdata) {
579 Network *network = userdata;
580 _cleanup_free_ char *kind_string = NULL;
581 char *p;
582 NetDev *netdev;
583 NetDevKind kind;
584 int r;
585
586 assert(filename);
587 assert(lvalue);
588 assert(rvalue);
589 assert(data);
590
591 kind_string = strdup(lvalue);
592 if (!kind_string)
593 return log_oom();
594
595 /* the keys are CamelCase versions of the kind */
596 for (p = kind_string; *p; p++)
597 *p = tolower(*p);
598
599 kind = netdev_kind_from_string(kind_string);
600 if (kind == _NETDEV_KIND_INVALID) {
601 log_syntax(unit, LOG_ERR, filename, line, 0, "Invalid NetDev kind: %s", lvalue);
602 return 0;
603 }
604
605 r = netdev_get(network->manager, rvalue, &netdev);
606 if (r < 0) {
607 log_syntax(unit, LOG_ERR, filename, line, r, "%s could not be found, ignoring assignment: %s", lvalue, rvalue);
608 return 0;
609 }
610
611 if (netdev->kind != kind) {
612 log_syntax(unit, LOG_ERR, filename, line, 0, "NetDev is not a %s, ignoring assignment: %s", lvalue, rvalue);
613 return 0;
614 }
615
616 switch (kind) {
617 case NETDEV_KIND_BRIDGE:
618 network->bridge = netdev;
619
620 break;
621 case NETDEV_KIND_BOND:
622 network->bond = netdev;
623
624 break;
625 case NETDEV_KIND_VRF:
626 network->vrf = netdev;
627
628 break;
629 case NETDEV_KIND_VLAN:
630 case NETDEV_KIND_MACVLAN:
631 case NETDEV_KIND_MACVTAP:
632 case NETDEV_KIND_IPVLAN:
633 case NETDEV_KIND_VXLAN:
634 case NETDEV_KIND_VCAN:
635 r = hashmap_put(network->stacked_netdevs, netdev->ifname, netdev);
636 if (r < 0) {
637 log_syntax(unit, LOG_ERR, filename, line, r, "Can not add NetDev '%s' to network: %m", rvalue);
638 return 0;
639 }
640
641 break;
642 default:
643 assert_not_reached("Can not parse NetDev");
644 }
645
646 netdev_ref(netdev);
647
648 return 0;
649 }
650
651 int config_parse_domains(
652 const char *unit,
653 const char *filename,
654 unsigned line,
655 const char *section,
656 unsigned section_line,
657 const char *lvalue,
658 int ltype,
659 const char *rvalue,
660 void *data,
661 void *userdata) {
662
663 const char *p;
664 Network *n = data;
665 int r;
666
667 assert(n);
668 assert(lvalue);
669 assert(rvalue);
670
671 if (isempty(rvalue)) {
672 n->search_domains = strv_free(n->search_domains);
673 n->route_domains = strv_free(n->route_domains);
674 return 0;
675 }
676
677 p = rvalue;
678 for (;;) {
679 _cleanup_free_ char *w = NULL, *normalized = NULL;
680 const char *domain;
681 bool is_route;
682
683 r = extract_first_word(&p, &w, NULL, 0);
684 if (r < 0) {
685 log_syntax(unit, LOG_ERR, filename, line, r, "Failed to extract search or route domain, ignoring: %s", rvalue);
686 break;
687 }
688 if (r == 0)
689 break;
690
691 is_route = w[0] == '~';
692 domain = is_route ? w + 1 : w;
693
694 if (dns_name_is_root(domain) || streq(domain, "*")) {
695 /* If the root domain appears as is, or the special token "*" is found, we'll consider this as
696 * routing domain, unconditionally. */
697 is_route = true;
698 domain = "."; /* make sure we don't allow empty strings, thus write the root domain as "." */
699
700 } else {
701 r = dns_name_normalize(domain, &normalized);
702 if (r < 0) {
703 log_syntax(unit, LOG_ERR, filename, line, r, "'%s' is not a valid domain name, ignoring.", domain);
704 continue;
705 }
706
707 domain = normalized;
708
709 if (is_localhost(domain)) {
710 log_syntax(unit, LOG_ERR, filename, line, 0, "'localhost' domain names may not be configure as search or route domains, ignoring assignment: %s", domain);
711 continue;
712 }
713 }
714
715 if (is_route) {
716 r = strv_extend(&n->route_domains, domain);
717 if (r < 0)
718 return log_oom();
719
720 } else {
721 r = strv_extend(&n->search_domains, domain);
722 if (r < 0)
723 return log_oom();
724 }
725 }
726
727 strv_uniq(n->route_domains);
728 strv_uniq(n->search_domains);
729
730 return 0;
731 }
732
733 int config_parse_tunnel(const char *unit,
734 const char *filename,
735 unsigned line,
736 const char *section,
737 unsigned section_line,
738 const char *lvalue,
739 int ltype,
740 const char *rvalue,
741 void *data,
742 void *userdata) {
743 Network *network = userdata;
744 NetDev *netdev;
745 int r;
746
747 assert(filename);
748 assert(lvalue);
749 assert(rvalue);
750 assert(data);
751
752 r = netdev_get(network->manager, rvalue, &netdev);
753 if (r < 0) {
754 log_syntax(unit, LOG_ERR, filename, line, r, "Tunnel is invalid, ignoring assignment: %s", rvalue);
755 return 0;
756 }
757
758 if (!IN_SET(netdev->kind,
759 NETDEV_KIND_IPIP,
760 NETDEV_KIND_SIT,
761 NETDEV_KIND_GRE,
762 NETDEV_KIND_GRETAP,
763 NETDEV_KIND_IP6GRE,
764 NETDEV_KIND_IP6GRETAP,
765 NETDEV_KIND_VTI,
766 NETDEV_KIND_VTI6,
767 NETDEV_KIND_IP6TNL)) {
768 log_syntax(unit, LOG_ERR, filename, line, 0,
769 "NetDev is not a tunnel, ignoring assignment: %s", rvalue);
770 return 0;
771 }
772
773 r = hashmap_put(network->stacked_netdevs, netdev->ifname, netdev);
774 if (r < 0) {
775 log_syntax(unit, LOG_ERR, filename, line, r, "Cannot add VLAN '%s' to network, ignoring: %m", rvalue);
776 return 0;
777 }
778
779 netdev_ref(netdev);
780
781 return 0;
782 }
783
784 int config_parse_ipv4ll(
785 const char* unit,
786 const char *filename,
787 unsigned line,
788 const char *section,
789 unsigned section_line,
790 const char *lvalue,
791 int ltype,
792 const char *rvalue,
793 void *data,
794 void *userdata) {
795
796 AddressFamilyBoolean *link_local = data;
797
798 assert(filename);
799 assert(lvalue);
800 assert(rvalue);
801 assert(data);
802
803 /* Note that this is mostly like
804 * config_parse_address_family_boolean(), except that it
805 * applies only to IPv4 */
806
807 SET_FLAG(*link_local, ADDRESS_FAMILY_IPV4, parse_boolean(rvalue));
808
809 return 0;
810 }
811
812 int config_parse_dhcp(
813 const char* unit,
814 const char *filename,
815 unsigned line,
816 const char *section,
817 unsigned section_line,
818 const char *lvalue,
819 int ltype,
820 const char *rvalue,
821 void *data,
822 void *userdata) {
823
824 AddressFamilyBoolean *dhcp = data, s;
825
826 assert(filename);
827 assert(lvalue);
828 assert(rvalue);
829 assert(data);
830
831 /* Note that this is mostly like
832 * config_parse_address_family_boolean(), except that it
833 * understands some old names for the enum values */
834
835 s = address_family_boolean_from_string(rvalue);
836 if (s < 0) {
837
838 /* Previously, we had a slightly different enum here,
839 * support its values for compatbility. */
840
841 if (streq(rvalue, "none"))
842 s = ADDRESS_FAMILY_NO;
843 else if (streq(rvalue, "v4"))
844 s = ADDRESS_FAMILY_IPV4;
845 else if (streq(rvalue, "v6"))
846 s = ADDRESS_FAMILY_IPV6;
847 else if (streq(rvalue, "both"))
848 s = ADDRESS_FAMILY_YES;
849 else {
850 log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse DHCP option, ignoring: %s", rvalue);
851 return 0;
852 }
853 }
854
855 *dhcp = s;
856 return 0;
857 }
858
859 static const char* const dhcp_client_identifier_table[_DHCP_CLIENT_ID_MAX] = {
860 [DHCP_CLIENT_ID_MAC] = "mac",
861 [DHCP_CLIENT_ID_DUID] = "duid"
862 };
863
864 DEFINE_PRIVATE_STRING_TABLE_LOOKUP_FROM_STRING(dhcp_client_identifier, DHCPClientIdentifier);
865 DEFINE_CONFIG_PARSE_ENUM(config_parse_dhcp_client_identifier, dhcp_client_identifier, DHCPClientIdentifier, "Failed to parse client identifier type");
866
867 int config_parse_ipv6token(
868 const char* unit,
869 const char *filename,
870 unsigned line,
871 const char *section,
872 unsigned section_line,
873 const char *lvalue,
874 int ltype,
875 const char *rvalue,
876 void *data,
877 void *userdata) {
878
879 union in_addr_union buffer;
880 struct in6_addr *token = data;
881 int r;
882
883 assert(filename);
884 assert(lvalue);
885 assert(rvalue);
886 assert(token);
887
888 r = in_addr_from_string(AF_INET6, rvalue, &buffer);
889 if (r < 0) {
890 log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse IPv6 token, ignoring: %s", rvalue);
891 return 0;
892 }
893
894 r = in_addr_is_null(AF_INET6, &buffer);
895 if (r != 0) {
896 log_syntax(unit, LOG_ERR, filename, line, r, "IPv6 token can not be the ANY address, ignoring: %s", rvalue);
897 return 0;
898 }
899
900 if ((buffer.in6.s6_addr32[0] | buffer.in6.s6_addr32[1]) != 0) {
901 log_syntax(unit, LOG_ERR, filename, line, 0, "IPv6 token can not be longer than 64 bits, ignoring: %s", rvalue);
902 return 0;
903 }
904
905 *token = buffer.in6;
906
907 return 0;
908 }
909
910 static const char* const ipv6_privacy_extensions_table[_IPV6_PRIVACY_EXTENSIONS_MAX] = {
911 [IPV6_PRIVACY_EXTENSIONS_NO] = "no",
912 [IPV6_PRIVACY_EXTENSIONS_PREFER_PUBLIC] = "prefer-public",
913 [IPV6_PRIVACY_EXTENSIONS_YES] = "yes",
914 };
915
916 DEFINE_STRING_TABLE_LOOKUP(ipv6_privacy_extensions, IPv6PrivacyExtensions);
917
918 int config_parse_ipv6_privacy_extensions(
919 const char* unit,
920 const char *filename,
921 unsigned line,
922 const char *section,
923 unsigned section_line,
924 const char *lvalue,
925 int ltype,
926 const char *rvalue,
927 void *data,
928 void *userdata) {
929
930 IPv6PrivacyExtensions *ipv6_privacy_extensions = data;
931 int k;
932
933 assert(filename);
934 assert(lvalue);
935 assert(rvalue);
936 assert(ipv6_privacy_extensions);
937
938 /* Our enum shall be a superset of booleans, hence first try
939 * to parse as boolean, and then as enum */
940
941 k = parse_boolean(rvalue);
942 if (k > 0)
943 *ipv6_privacy_extensions = IPV6_PRIVACY_EXTENSIONS_YES;
944 else if (k == 0)
945 *ipv6_privacy_extensions = IPV6_PRIVACY_EXTENSIONS_NO;
946 else {
947 IPv6PrivacyExtensions s;
948
949 s = ipv6_privacy_extensions_from_string(rvalue);
950 if (s < 0) {
951
952 if (streq(rvalue, "kernel"))
953 s = _IPV6_PRIVACY_EXTENSIONS_INVALID;
954 else {
955 log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse IPv6 privacy extensions option, ignoring: %s", rvalue);
956 return 0;
957 }
958 }
959
960 *ipv6_privacy_extensions = s;
961 }
962
963 return 0;
964 }
965
966 int config_parse_hostname(
967 const char *unit,
968 const char *filename,
969 unsigned line,
970 const char *section,
971 unsigned section_line,
972 const char *lvalue,
973 int ltype,
974 const char *rvalue,
975 void *data,
976 void *userdata) {
977
978 char **hostname = data, *hn = NULL;
979 int r;
980
981 assert(filename);
982 assert(lvalue);
983 assert(rvalue);
984
985 r = config_parse_string(unit, filename, line, section, section_line, lvalue, ltype, rvalue, &hn, userdata);
986 if (r < 0)
987 return r;
988
989 if (!hostname_is_valid(hn, false)) {
990 log_syntax(unit, LOG_ERR, filename, line, 0, "Hostname is not valid, ignoring assignment: %s", rvalue);
991 free(hn);
992 return 0;
993 }
994
995 free(*hostname);
996 *hostname = hostname_cleanup(hn);
997 return 0;
998 }
999
1000 int config_parse_timezone(
1001 const char *unit,
1002 const char *filename,
1003 unsigned line,
1004 const char *section,
1005 unsigned section_line,
1006 const char *lvalue,
1007 int ltype,
1008 const char *rvalue,
1009 void *data,
1010 void *userdata) {
1011
1012 char **datap = data, *tz = NULL;
1013 int r;
1014
1015 assert(filename);
1016 assert(lvalue);
1017 assert(rvalue);
1018
1019 r = config_parse_string(unit, filename, line, section, section_line, lvalue, ltype, rvalue, &tz, userdata);
1020 if (r < 0)
1021 return r;
1022
1023 if (!timezone_is_valid(tz)) {
1024 log_syntax(unit, LOG_ERR, filename, line, 0, "Timezone is not valid, ignoring assignment: %s", rvalue);
1025 free(tz);
1026 return 0;
1027 }
1028
1029 free(*datap);
1030 *datap = tz;
1031
1032 return 0;
1033 }
1034
1035 int config_parse_dhcp_server_dns(
1036 const char *unit,
1037 const char *filename,
1038 unsigned line,
1039 const char *section,
1040 unsigned section_line,
1041 const char *lvalue,
1042 int ltype,
1043 const char *rvalue,
1044 void *data,
1045 void *userdata) {
1046
1047 Network *n = data;
1048 const char *p = rvalue;
1049 int r;
1050
1051 assert(filename);
1052 assert(lvalue);
1053 assert(rvalue);
1054
1055 for (;;) {
1056 _cleanup_free_ char *w = NULL;
1057 struct in_addr a, *m;
1058
1059 r = extract_first_word(&p, &w, NULL, 0);
1060 if (r == -ENOMEM)
1061 return log_oom();
1062 if (r < 0) {
1063 log_syntax(unit, LOG_ERR, filename, line, r, "Failed to extract word, ignoring: %s", rvalue);
1064 return 0;
1065 }
1066 if (r == 0)
1067 break;
1068
1069 if (inet_pton(AF_INET, w, &a) <= 0) {
1070 log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse DNS server address, ignoring: %s", w);
1071 continue;
1072 }
1073
1074 m = realloc(n->dhcp_server_dns, (n->n_dhcp_server_dns + 1) * sizeof(struct in_addr));
1075 if (!m)
1076 return log_oom();
1077
1078 m[n->n_dhcp_server_dns++] = a;
1079 n->dhcp_server_dns = m;
1080 }
1081
1082 return 0;
1083 }
1084
1085 int config_parse_radv_dns(
1086 const char *unit,
1087 const char *filename,
1088 unsigned line,
1089 const char *section,
1090 unsigned section_line,
1091 const char *lvalue,
1092 int ltype,
1093 const char *rvalue,
1094 void *data,
1095 void *userdata) {
1096
1097 Network *n = data;
1098 const char *p = rvalue;
1099 int r;
1100
1101 assert(filename);
1102 assert(lvalue);
1103 assert(rvalue);
1104
1105 for (;;) {
1106 _cleanup_free_ char *w = NULL;
1107 union in_addr_union a;
1108
1109 r = extract_first_word(&p, &w, NULL, 0);
1110 if (r == -ENOMEM)
1111 return log_oom();
1112 if (r < 0) {
1113 log_syntax(unit, LOG_ERR, filename, line, r, "Failed to extract word, ignoring: %s", rvalue);
1114 return 0;
1115 }
1116 if (r == 0)
1117 break;
1118
1119 if (in_addr_from_string(AF_INET6, w, &a) >= 0) {
1120 struct in6_addr *m;
1121
1122 m = realloc(n->router_dns, (n->n_router_dns + 1) * sizeof(struct in6_addr));
1123 if (!m)
1124 return log_oom();
1125
1126 m[n->n_router_dns++] = a.in6;
1127 n->router_dns = m;
1128
1129 } else
1130 log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse DNS server address, ignoring: %s", w);
1131
1132 }
1133
1134 return 0;
1135 }
1136
1137 int config_parse_radv_search_domains(
1138 const char *unit,
1139 const char *filename,
1140 unsigned line,
1141 const char *section,
1142 unsigned section_line,
1143 const char *lvalue,
1144 int ltype,
1145 const char *rvalue,
1146 void *data,
1147 void *userdata) {
1148
1149 Network *n = data;
1150 const char *p = rvalue;
1151 int r;
1152
1153 assert(filename);
1154 assert(lvalue);
1155 assert(rvalue);
1156
1157 for (;;) {
1158 _cleanup_free_ char *w = NULL;
1159 _cleanup_free_ char *idna = NULL;
1160
1161 r = extract_first_word(&p, &w, NULL, 0);
1162 if (r == -ENOMEM)
1163 return log_oom();
1164 if (r < 0) {
1165 log_syntax(unit, LOG_ERR, filename, line, r, "Failed to extract word, ignoring: %s", rvalue);
1166 return 0;
1167 }
1168 if (r == 0)
1169 break;
1170
1171 r = dns_name_apply_idna(w, &idna);
1172 if (r > 0) {
1173 r = strv_push(&n->router_search_domains, idna);
1174 if (r >= 0)
1175 idna = NULL;
1176 } else if (r == 0) {
1177 r = strv_push(&n->router_search_domains, w);
1178 if (r >= 0)
1179 w = NULL;
1180 }
1181 }
1182
1183 return 0;
1184 }
1185
1186 int config_parse_dhcp_server_ntp(
1187 const char *unit,
1188 const char *filename,
1189 unsigned line,
1190 const char *section,
1191 unsigned section_line,
1192 const char *lvalue,
1193 int ltype,
1194 const char *rvalue,
1195 void *data,
1196 void *userdata) {
1197
1198 Network *n = data;
1199 const char *p = rvalue;
1200 int r;
1201
1202 assert(filename);
1203 assert(lvalue);
1204 assert(rvalue);
1205
1206 for (;;) {
1207 _cleanup_free_ char *w = NULL;
1208 struct in_addr a, *m;
1209
1210 r = extract_first_word(&p, &w, NULL, 0);
1211 if (r == -ENOMEM)
1212 return log_oom();
1213 if (r < 0) {
1214 log_syntax(unit, LOG_ERR, filename, line, r, "Failed to extract word, ignoring: %s", rvalue);
1215 return 0;
1216 }
1217 if (r == 0)
1218 return 0;
1219
1220 if (inet_pton(AF_INET, w, &a) <= 0) {
1221 log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse NTP server address, ignoring: %s", w);
1222 continue;
1223 }
1224
1225 m = realloc(n->dhcp_server_ntp, (n->n_dhcp_server_ntp + 1) * sizeof(struct in_addr));
1226 if (!m)
1227 return log_oom();
1228
1229 m[n->n_dhcp_server_ntp++] = a;
1230 n->dhcp_server_ntp = m;
1231 }
1232 }
1233
1234 int config_parse_dns(
1235 const char *unit,
1236 const char *filename,
1237 unsigned line,
1238 const char *section,
1239 unsigned section_line,
1240 const char *lvalue,
1241 int ltype,
1242 const char *rvalue,
1243 void *data,
1244 void *userdata) {
1245
1246 Network *n = userdata;
1247 int r;
1248
1249 assert(filename);
1250 assert(lvalue);
1251 assert(rvalue);
1252
1253 for (;;) {
1254 _cleanup_free_ char *w = NULL;
1255 union in_addr_union a;
1256 struct in_addr_data *m;
1257 int family;
1258
1259 r = extract_first_word(&rvalue, &w, NULL, 0);
1260 if (r == -ENOMEM)
1261 return log_oom();
1262 if (r < 0) {
1263 log_syntax(unit, LOG_ERR, filename, line, r, "Invalid syntax, ignoring: %s", rvalue);
1264 break;
1265 }
1266 if (r == 0)
1267 break;
1268
1269 r = in_addr_from_string_auto(w, &family, &a);
1270 if (r < 0) {
1271 log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse dns server address, ignoring: %s", w);
1272 continue;
1273 }
1274
1275 m = realloc(n->dns, (n->n_dns + 1) * sizeof(struct in_addr_data));
1276 if (!m)
1277 return log_oom();
1278
1279 m[n->n_dns++] = (struct in_addr_data) {
1280 .family = family,
1281 .address = a,
1282 };
1283
1284 n->dns = m;
1285 }
1286
1287 return 0;
1288 }
1289
1290 int config_parse_dnssec_negative_trust_anchors(
1291 const char *unit,
1292 const char *filename,
1293 unsigned line,
1294 const char *section,
1295 unsigned section_line,
1296 const char *lvalue,
1297 int ltype,
1298 const char *rvalue,
1299 void *data,
1300 void *userdata) {
1301
1302 const char *p = rvalue;
1303 Network *n = data;
1304 int r;
1305
1306 assert(n);
1307 assert(lvalue);
1308 assert(rvalue);
1309
1310 if (isempty(rvalue)) {
1311 n->dnssec_negative_trust_anchors = set_free_free(n->dnssec_negative_trust_anchors);
1312 return 0;
1313 }
1314
1315 for (;;) {
1316 _cleanup_free_ char *w = NULL;
1317
1318 r = extract_first_word(&p, &w, NULL, 0);
1319 if (r < 0) {
1320 log_syntax(unit, LOG_ERR, filename, line, r, "Failed to extract negative trust anchor domain, ignoring: %s", rvalue);
1321 break;
1322 }
1323 if (r == 0)
1324 break;
1325
1326 r = dns_name_is_valid(w);
1327 if (r <= 0) {
1328 log_syntax(unit, LOG_ERR, filename, line, r, "%s is not a valid domain name, ignoring.", w);
1329 continue;
1330 }
1331
1332 r = set_ensure_allocated(&n->dnssec_negative_trust_anchors, &dns_name_hash_ops);
1333 if (r < 0)
1334 return log_oom();
1335
1336 r = set_put(n->dnssec_negative_trust_anchors, w);
1337 if (r < 0)
1338 return log_oom();
1339 if (r > 0)
1340 w = NULL;
1341 }
1342
1343 return 0;
1344 }
1345
1346 int config_parse_ntp(
1347 const char *unit,
1348 const char *filename,
1349 unsigned line,
1350 const char *section,
1351 unsigned section_line,
1352 const char *lvalue,
1353 int ltype,
1354 const char *rvalue,
1355 void *data,
1356 void *userdata) {
1357
1358 char ***l = data;
1359 int r;
1360
1361 assert(l);
1362 assert(lvalue);
1363 assert(rvalue);
1364
1365 if (isempty(rvalue)) {
1366 *l = strv_free(*l);
1367 return 0;
1368 }
1369
1370 for (;;) {
1371 _cleanup_free_ char *w = NULL;
1372
1373 r = extract_first_word(&rvalue, &w, NULL, 0);
1374 if (r == -ENOMEM)
1375 return log_oom();
1376 if (r < 0) {
1377 log_syntax(unit, LOG_ERR, filename, line, r, "Failed to extract NTP server name, ignoring: %s", rvalue);
1378 break;
1379 }
1380 if (r == 0)
1381 break;
1382
1383 r = dns_name_is_valid_or_address(w);
1384 if (r <= 0) {
1385 log_syntax(unit, LOG_ERR, filename, line, r, "%s is not a valid domain name or IP address, ignoring.", w);
1386 continue;
1387 }
1388
1389 r = strv_push(l, w);
1390 if (r < 0)
1391 return log_oom();
1392
1393 w = NULL;
1394 }
1395
1396 return 0;
1397 }
1398
1399 int config_parse_dhcp_route_table(const char *unit,
1400 const char *filename,
1401 unsigned line,
1402 const char *section,
1403 unsigned section_line,
1404 const char *lvalue,
1405 int ltype,
1406 const char *rvalue,
1407 void *data,
1408 void *userdata) {
1409 Network *network = data;
1410 uint32_t rt;
1411 int r;
1412
1413 assert(filename);
1414 assert(lvalue);
1415 assert(rvalue);
1416 assert(data);
1417
1418 r = safe_atou32(rvalue, &rt);
1419 if (r < 0) {
1420 log_syntax(unit, LOG_ERR, filename, line, r,
1421 "Unable to read RouteTable, ignoring assignment: %s", rvalue);
1422 return 0;
1423 }
1424
1425 network->dhcp_route_table = rt;
1426 network->dhcp_route_table_set = true;
1427
1428 return 0;
1429 }
1430
1431 DEFINE_CONFIG_PARSE_ENUM(config_parse_dhcp_use_domains, dhcp_use_domains, DHCPUseDomains, "Failed to parse DHCP use domains setting");
1432
1433 static const char* const dhcp_use_domains_table[_DHCP_USE_DOMAINS_MAX] = {
1434 [DHCP_USE_DOMAINS_NO] = "no",
1435 [DHCP_USE_DOMAINS_ROUTE] = "route",
1436 [DHCP_USE_DOMAINS_YES] = "yes",
1437 };
1438
1439 DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(dhcp_use_domains, DHCPUseDomains, DHCP_USE_DOMAINS_YES);
1440
1441 DEFINE_CONFIG_PARSE_ENUM(config_parse_lldp_mode, lldp_mode, LLDPMode, "Failed to parse LLDP= setting.");
1442
1443 static const char* const lldp_mode_table[_LLDP_MODE_MAX] = {
1444 [LLDP_MODE_NO] = "no",
1445 [LLDP_MODE_YES] = "yes",
1446 [LLDP_MODE_ROUTERS_ONLY] = "routers-only",
1447 };
1448
1449 DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(lldp_mode, LLDPMode, LLDP_MODE_YES);