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