]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/network/networkd-network.c
Merge pull request #12536 from poettering/rdrand-workaround-on-amd
[thirdparty/systemd.git] / src / network / networkd-network.c
1 /* SPDX-License-Identifier: LGPL-2.1+ */
2
3 #include <net/if.h>
4 #include <netinet/in.h>
5 #include <linux/netdevice.h>
6
7 #include "alloc-util.h"
8 #include "conf-files.h"
9 #include "conf-parser.h"
10 #include "dns-domain.h"
11 #include "fd-util.h"
12 #include "hostname-util.h"
13 #include "in-addr-util.h"
14 #include "network-internal.h"
15 #include "networkd-manager.h"
16 #include "networkd-network.h"
17 #include "parse-util.h"
18 #include "set.h"
19 #include "socket-util.h"
20 #include "stat-util.h"
21 #include "string-table.h"
22 #include "string-util.h"
23 #include "strv.h"
24 #include "util.h"
25
26 /* Let's assume that anything above this number is a user misconfiguration. */
27 #define MAX_NTP_SERVERS 128
28
29 /* Set defaults following RFC7844 */
30 void network_apply_anonymize_if_set(Network *network) {
31 if (!network->dhcp_anonymize)
32 return;
33 /* RFC7844 3.7
34 SHOULD NOT send the Host Name option */
35 network->dhcp_send_hostname = false;
36 /* RFC7844 section 3.:
37 MAY contain the Client Identifier option
38 Section 3.5:
39 clients MUST use client identifiers based solely
40 on the link-layer address */
41 /* NOTE: Using MAC, as it does not reveal extra information,
42 * and some servers might not answer if this option is not sent */
43 network->dhcp_client_identifier = DHCP_CLIENT_ID_MAC;
44 /* RFC 7844 3.10:
45 SHOULD NOT use the Vendor Class Identifier option */
46 network->dhcp_vendor_class_identifier = mfree(network->dhcp_vendor_class_identifier);
47 /* RFC7844 section 3.6.:
48 The client intending to protect its privacy SHOULD only request a
49 minimal number of options in the PRL and SHOULD also randomly shuffle
50 the ordering of option codes in the PRL. If this random ordering
51 cannot be implemented, the client MAY order the option codes in the
52 PRL by option code number (lowest to highest).
53 */
54 /* NOTE: dhcp_use_mtu is false by default,
55 * though it was not initiallized to any value in network_load_one.
56 * Maybe there should be another var called *send*?
57 * (to use the MTU sent by the server but to do not send
58 * the option in the PRL). */
59 network->dhcp_use_mtu = false;
60 /* NOTE: when Anonymize=yes, the PRL route options are sent by default,
61 * but this is needed to use them. */
62 network->dhcp_use_routes = true;
63 /* RFC7844 section 3.6.
64 * same comments as previous option */
65 network->dhcp_use_timezone = false;
66 }
67
68 static int network_resolve_netdev_one(Network *network, const char *name, NetDevKind kind, NetDev **ret_netdev) {
69 const char *kind_string;
70 NetDev *netdev;
71 int r;
72
73 /* For test-networkd-conf, the check must be earlier than the assertions. */
74 if (!name)
75 return 0;
76
77 assert(network);
78 assert(network->manager);
79 assert(network->filename);
80 assert(ret_netdev);
81
82 if (kind == _NETDEV_KIND_TUNNEL)
83 kind_string = "tunnel";
84 else {
85 kind_string = netdev_kind_to_string(kind);
86 if (!kind_string)
87 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
88 "%s: Invalid NetDev kind of %s, ignoring assignment.",
89 network->filename, name);
90 }
91
92 r = netdev_get(network->manager, name, &netdev);
93 if (r < 0)
94 return log_error_errno(r, "%s: %s NetDev could not be found, ignoring assignment.",
95 network->filename, name);
96
97 if (netdev->kind != kind && !(kind == _NETDEV_KIND_TUNNEL &&
98 IN_SET(netdev->kind,
99 NETDEV_KIND_IPIP,
100 NETDEV_KIND_SIT,
101 NETDEV_KIND_GRE,
102 NETDEV_KIND_GRETAP,
103 NETDEV_KIND_IP6GRE,
104 NETDEV_KIND_IP6GRETAP,
105 NETDEV_KIND_VTI,
106 NETDEV_KIND_VTI6,
107 NETDEV_KIND_IP6TNL,
108 NETDEV_KIND_ERSPAN)))
109 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
110 "%s: NetDev %s is not a %s, ignoring assignment",
111 network->filename, name, kind_string);
112
113 *ret_netdev = netdev_ref(netdev);
114 return 1;
115 }
116
117 static int network_resolve_stacked_netdevs(Network *network) {
118 void *name, *kind;
119 Iterator i;
120 int r;
121
122 assert(network);
123
124 HASHMAP_FOREACH_KEY(kind, name, network->stacked_netdev_names, i) {
125 _cleanup_(netdev_unrefp) NetDev *netdev = NULL;
126
127 r = network_resolve_netdev_one(network, name, PTR_TO_INT(kind), &netdev);
128 if (r <= 0)
129 continue;
130
131 r = hashmap_ensure_allocated(&network->stacked_netdevs, &string_hash_ops);
132 if (r < 0)
133 return log_oom();
134
135 r = hashmap_put(network->stacked_netdevs, netdev->ifname, netdev);
136 if (r < 0)
137 return log_error_errno(r, "%s: Failed to add NetDev '%s' to network: %m",
138 network->filename, (const char *) name);
139
140 netdev = NULL;
141 }
142
143 return 0;
144 }
145
146 static uint32_t network_get_stacked_netdevs_mtu(Network *network) {
147 uint32_t mtu = 0;
148 NetDev *dev;
149 Iterator i;
150
151 HASHMAP_FOREACH(dev, network->stacked_netdevs, i)
152 if (dev->kind == NETDEV_KIND_VLAN && dev->mtu > 0)
153 /* See vlan_dev_change_mtu() in kernel.
154 * Note that the additional 4bytes may not be necessary for all devices. */
155 mtu = MAX(mtu, dev->mtu + 4);
156
157 else if (dev->kind == NETDEV_KIND_MACVLAN && dev->mtu > mtu)
158 /* See macvlan_change_mtu() in kernel. */
159 mtu = dev->mtu;
160
161 return mtu;
162 }
163
164 int network_verify(Network *network) {
165 Address *address, *address_next;
166 Route *route, *route_next;
167 FdbEntry *fdb, *fdb_next;
168 Neighbor *neighbor, *neighbor_next;
169 AddressLabel *label, *label_next;
170 Prefix *prefix, *prefix_next;
171 RoutingPolicyRule *rule, *rule_next;
172 uint32_t mtu;
173
174 assert(network);
175 assert(network->filename);
176
177 if (set_isempty(network->match_mac) && strv_isempty(network->match_path) &&
178 strv_isempty(network->match_driver) && strv_isempty(network->match_type) &&
179 strv_isempty(network->match_name) && !network->conditions)
180 log_warning("%s: No valid settings found in the [Match] section. "
181 "The file will match all interfaces. "
182 "If that is intended, please add Name=* in the [Match] section.",
183 network->filename);
184
185 /* skip out early if configuration does not match the environment */
186 if (!condition_test_list(network->conditions, NULL, NULL, NULL))
187 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL),
188 "%s: Conditions in the file do not match the system environment, skipping.",
189 network->filename);
190
191 (void) network_resolve_netdev_one(network, network->bond_name, NETDEV_KIND_BOND, &network->bond);
192 (void) network_resolve_netdev_one(network, network->bridge_name, NETDEV_KIND_BRIDGE, &network->bridge);
193 (void) network_resolve_netdev_one(network, network->vrf_name, NETDEV_KIND_VRF, &network->vrf);
194 (void) network_resolve_stacked_netdevs(network);
195
196 /* Free unnecessary entries. */
197 network->bond_name = mfree(network->bond_name);
198 network->bridge_name = mfree(network->bridge_name);
199 network->vrf_name = mfree(network->vrf_name);
200 network->stacked_netdev_names = hashmap_free_free_key(network->stacked_netdev_names);
201
202 if (network->bond) {
203 /* Bonding slave does not support addressing. */
204 if (network->ipv6_accept_ra > 0) {
205 log_warning("%s: Cannot enable IPv6AcceptRA= when Bond= is specified, disabling IPv6AcceptRA=.",
206 network->filename);
207 network->ipv6_accept_ra = 0;
208 }
209 if (network->link_local >= 0 && network->link_local != ADDRESS_FAMILY_NO) {
210 log_warning("%s: Cannot enable LinkLocalAddressing= when Bond= is specified, disabling LinkLocalAddressing=.",
211 network->filename);
212 network->link_local = ADDRESS_FAMILY_NO;
213 }
214 if (network->dhcp != ADDRESS_FAMILY_NO) {
215 log_warning("%s: Cannot enable DHCP= when Bond= is specified, disabling DHCP=.",
216 network->filename);
217 network->dhcp = ADDRESS_FAMILY_NO;
218 }
219 if (network->dhcp_server) {
220 log_warning("%s: Cannot enable DHCPServer= when Bond= is specified, disabling DHCPServer=.",
221 network->filename);
222 network->dhcp_server = false;
223 }
224 if (network->n_static_addresses > 0) {
225 log_warning("%s: Cannot set addresses when Bond= is specified, ignoring addresses.",
226 network->filename);
227 while ((address = network->static_addresses))
228 address_free(address);
229 }
230 if (network->n_static_routes > 0) {
231 log_warning("%s: Cannot set routes when Bond= is specified, ignoring routes.",
232 network->filename);
233 while ((route = network->static_routes))
234 route_free(route);
235 }
236 }
237
238 if (network->link_local < 0)
239 network->link_local = network->bridge ? ADDRESS_FAMILY_NO : ADDRESS_FAMILY_IPV6;
240
241 if (FLAGS_SET(network->link_local, ADDRESS_FAMILY_FALLBACK_IPV4) &&
242 !FLAGS_SET(network->dhcp, ADDRESS_FAMILY_IPV4)) {
243 log_warning("%s: fallback assignment of IPv4 link local address is enabled but DHCPv4 is disabled. "
244 "Disabling the fallback assignment.", network->filename);
245 SET_FLAG(network->link_local, ADDRESS_FAMILY_FALLBACK_IPV4, false);
246 }
247
248 if (network->ipv6_accept_ra < 0 && network->bridge)
249 network->ipv6_accept_ra = false;
250
251 /* IPMasquerade=yes implies IPForward=yes */
252 if (network->ip_masquerade)
253 network->ip_forward |= ADDRESS_FAMILY_IPV4;
254
255 network->mtu_is_set = network->mtu > 0;
256 mtu = network_get_stacked_netdevs_mtu(network);
257 if (network->mtu < mtu) {
258 if (network->mtu_is_set)
259 log_notice("%s: Bumping MTUBytes= from %"PRIu32" to %"PRIu32" because of stacked device",
260 network->filename, network->mtu, mtu);
261 network->mtu = mtu;
262 }
263
264 if (network->mtu_is_set && network->dhcp_use_mtu) {
265 log_warning("%s: MTUBytes= in [Link] section and UseMTU= in [DHCP] section are set. "
266 "Disabling UseMTU=.", network->filename);
267 network->dhcp_use_mtu = false;
268 }
269
270 LIST_FOREACH_SAFE(addresses, address, address_next, network->static_addresses)
271 if (address_section_verify(address) < 0)
272 address_free(address);
273
274 LIST_FOREACH_SAFE(routes, route, route_next, network->static_routes)
275 if (route_section_verify(route, network) < 0)
276 route_free(route);
277
278 LIST_FOREACH_SAFE(static_fdb_entries, fdb, fdb_next, network->static_fdb_entries)
279 if (section_is_invalid(fdb->section))
280 fdb_entry_free(fdb);
281
282 LIST_FOREACH_SAFE(neighbors, neighbor, neighbor_next, network->neighbors)
283 if (section_is_invalid(neighbor->section))
284 neighbor_free(neighbor);
285
286 LIST_FOREACH_SAFE(labels, label, label_next, network->address_labels)
287 if (section_is_invalid(label->section))
288 address_label_free(label);
289
290 LIST_FOREACH_SAFE(prefixes, prefix, prefix_next, network->static_prefixes)
291 if (section_is_invalid(prefix->section))
292 prefix_free(prefix);
293
294 LIST_FOREACH_SAFE(rules, rule, rule_next, network->rules)
295 if (section_is_invalid(rule->section))
296 routing_policy_rule_free(rule);
297
298 return 0;
299 }
300
301 int network_load_one(Manager *manager, const char *filename) {
302 _cleanup_free_ char *fname = NULL, *name = NULL;
303 _cleanup_(network_unrefp) Network *network = NULL;
304 _cleanup_fclose_ FILE *file = NULL;
305 const char *dropin_dirname;
306 char *d;
307 int r;
308
309 assert(manager);
310 assert(filename);
311
312 file = fopen(filename, "re");
313 if (!file) {
314 if (errno == ENOENT)
315 return 0;
316
317 return -errno;
318 }
319
320 if (null_or_empty_fd(fileno(file))) {
321 log_debug("Skipping empty file: %s", filename);
322 return 0;
323 }
324
325 fname = strdup(filename);
326 if (!fname)
327 return log_oom();
328
329 name = strdup(basename(filename));
330 if (!name)
331 return log_oom();
332
333 d = strrchr(name, '.');
334 if (!d)
335 return -EINVAL;
336
337 *d = '\0';
338
339 dropin_dirname = strjoina(name, ".network.d");
340
341 network = new(Network, 1);
342 if (!network)
343 return log_oom();
344
345 *network = (Network) {
346 .filename = TAKE_PTR(fname),
347 .name = TAKE_PTR(name),
348
349 .manager = manager,
350 .n_ref = 1,
351
352 .required_for_online = true,
353 .required_operstate_for_online = LINK_OPERSTATE_DEGRADED,
354 .dhcp = ADDRESS_FAMILY_NO,
355 .dhcp_use_ntp = true,
356 .dhcp_use_dns = true,
357 .dhcp_use_hostname = true,
358 .dhcp_use_routes = true,
359 /* NOTE: this var might be overwritten by network_apply_anonymize_if_set */
360 .dhcp_send_hostname = true,
361 /* To enable/disable RFC7844 Anonymity Profiles */
362 .dhcp_anonymize = false,
363 .dhcp_route_metric = DHCP_ROUTE_METRIC,
364 /* NOTE: this var might be overwritten by network_apply_anonymize_if_set */
365 .dhcp_client_identifier = DHCP_CLIENT_ID_DUID,
366 .dhcp_route_table = RT_TABLE_MAIN,
367 .dhcp_route_table_set = false,
368 /* NOTE: from man: UseMTU=... Defaults to false*/
369 .dhcp_use_mtu = false,
370 /* NOTE: from man: UseTimezone=... Defaults to "no".*/
371 .dhcp_use_timezone = false,
372 .rapid_commit = true,
373
374 .dhcp_server_emit_dns = true,
375 .dhcp_server_emit_ntp = true,
376 .dhcp_server_emit_router = true,
377 .dhcp_server_emit_timezone = true,
378
379 .router_emit_dns = true,
380 .router_emit_domains = true,
381
382 .use_bpdu = -1,
383 .hairpin = -1,
384 .fast_leave = -1,
385 .allow_port_to_be_root = -1,
386 .unicast_flood = -1,
387 .multicast_flood = -1,
388 .multicast_to_unicast = -1,
389 .neighbor_suppression = -1,
390 .learning = -1,
391 .bridge_proxy_arp = -1,
392 .bridge_proxy_arp_wifi = -1,
393 .priority = LINK_BRIDGE_PORT_PRIORITY_INVALID,
394 .multicast_router = _MULTICAST_ROUTER_INVALID,
395
396 .lldp_mode = LLDP_MODE_ROUTERS_ONLY,
397
398 .dns_default_route = -1,
399 .llmnr = RESOLVE_SUPPORT_YES,
400 .mdns = RESOLVE_SUPPORT_NO,
401 .dnssec_mode = _DNSSEC_MODE_INVALID,
402 .dns_over_tls_mode = _DNS_OVER_TLS_MODE_INVALID,
403
404 /* If LinkLocalAddressing= is not set, then set to ADDRESS_FAMILY_IPV6 later. */
405 .link_local = _ADDRESS_FAMILY_BOOLEAN_INVALID,
406
407 .ipv6_privacy_extensions = IPV6_PRIVACY_EXTENSIONS_NO,
408 .ipv6_accept_ra = -1,
409 .ipv6_dad_transmits = -1,
410 .ipv6_hop_limit = -1,
411 .ipv6_proxy_ndp = -1,
412 .duid.type = _DUID_TYPE_INVALID,
413 .proxy_arp = -1,
414 .arp = -1,
415 .multicast = -1,
416 .allmulticast = -1,
417 .ipv6_accept_ra_use_dns = true,
418 .ipv6_accept_ra_use_autonomous_prefix = true,
419 .ipv6_accept_ra_use_onlink_prefix = true,
420 .ipv6_accept_ra_route_table = RT_TABLE_MAIN,
421 .ipv6_accept_ra_route_table_set = false,
422
423 .can_triple_sampling = -1,
424 };
425
426 r = config_parse_many(filename, NETWORK_DIRS, dropin_dirname,
427 "Match\0"
428 "Link\0"
429 "Network\0"
430 "Address\0"
431 "Neighbor\0"
432 "IPv6AddressLabel\0"
433 "RoutingPolicyRule\0"
434 "Route\0"
435 "DHCP\0"
436 "DHCPv4\0" /* compat */
437 "DHCPServer\0"
438 "IPv6AcceptRA\0"
439 "IPv6NDPProxyAddress\0"
440 "Bridge\0"
441 "BridgeFDB\0"
442 "BridgeVLAN\0"
443 "IPv6PrefixDelegation\0"
444 "IPv6Prefix\0"
445 "CAN\0",
446 config_item_perf_lookup, network_network_gperf_lookup,
447 CONFIG_PARSE_WARN, network);
448 if (r < 0)
449 return r;
450
451 network_apply_anonymize_if_set(network);
452
453 r = network_add_ipv4ll_route(network);
454 if (r < 0)
455 log_warning_errno(r, "%s: Failed to add IPv4LL route, ignoring: %m", network->filename);
456
457 r = ordered_hashmap_ensure_allocated(&manager->networks, &string_hash_ops);
458 if (r < 0)
459 return r;
460
461 r = ordered_hashmap_put(manager->networks, network->name, network);
462 if (r < 0)
463 return r;
464
465 if (network_verify(network) < 0)
466 return 0;
467
468 network = NULL;
469 return 0;
470 }
471
472 int network_load(Manager *manager) {
473 _cleanup_strv_free_ char **files = NULL;
474 char **f;
475 int r;
476
477 assert(manager);
478
479 ordered_hashmap_clear_with_destructor(manager->networks, network_unref);
480
481 r = conf_files_list_strv(&files, ".network", NULL, 0, NETWORK_DIRS);
482 if (r < 0)
483 return log_error_errno(r, "Failed to enumerate network files: %m");
484
485 STRV_FOREACH(f, files) {
486 r = network_load_one(manager, *f);
487 if (r < 0)
488 return r;
489 }
490
491 return 0;
492 }
493
494 static Network *network_free(Network *network) {
495 IPv6ProxyNDPAddress *ipv6_proxy_ndp_address;
496 RoutingPolicyRule *rule;
497 FdbEntry *fdb_entry;
498 Neighbor *neighbor;
499 AddressLabel *label;
500 Prefix *prefix;
501 Address *address;
502 Route *route;
503
504 if (!network)
505 return NULL;
506
507 free(network->filename);
508
509 set_free_free(network->match_mac);
510 strv_free(network->match_path);
511 strv_free(network->match_driver);
512 strv_free(network->match_type);
513 strv_free(network->match_name);
514 condition_free_list(network->conditions);
515
516 free(network->description);
517 free(network->dhcp_vendor_class_identifier);
518 strv_free(network->dhcp_user_class);
519 free(network->dhcp_hostname);
520 set_free(network->dhcp_black_listed_ip);
521 free(network->mac);
522
523 strv_free(network->ntp);
524 free(network->dns);
525 ordered_set_free_free(network->search_domains);
526 ordered_set_free_free(network->route_domains);
527 strv_free(network->bind_carrier);
528
529 ordered_set_free_free(network->router_search_domains);
530 free(network->router_dns);
531
532 free(network->bridge_name);
533 free(network->bond_name);
534 free(network->vrf_name);
535 hashmap_free_free_key(network->stacked_netdev_names);
536 netdev_unref(network->bridge);
537 netdev_unref(network->bond);
538 netdev_unref(network->vrf);
539 hashmap_free_with_destructor(network->stacked_netdevs, netdev_unref);
540
541 while ((route = network->static_routes))
542 route_free(route);
543
544 while ((address = network->static_addresses))
545 address_free(address);
546
547 while ((fdb_entry = network->static_fdb_entries))
548 fdb_entry_free(fdb_entry);
549
550 while ((ipv6_proxy_ndp_address = network->ipv6_proxy_ndp_addresses))
551 ipv6_proxy_ndp_address_free(ipv6_proxy_ndp_address);
552
553 while ((neighbor = network->neighbors))
554 neighbor_free(neighbor);
555
556 while ((label = network->address_labels))
557 address_label_free(label);
558
559 while ((prefix = network->static_prefixes))
560 prefix_free(prefix);
561
562 while ((rule = network->rules))
563 routing_policy_rule_free(rule);
564
565 hashmap_free(network->addresses_by_section);
566 hashmap_free(network->routes_by_section);
567 hashmap_free(network->fdb_entries_by_section);
568 hashmap_free(network->neighbors_by_section);
569 hashmap_free(network->address_labels_by_section);
570 hashmap_free(network->prefixes_by_section);
571 hashmap_free(network->rules_by_section);
572
573 if (network->manager) {
574 if (network->manager->networks && network->name)
575 ordered_hashmap_remove(network->manager->networks, network->name);
576
577 if (network->manager->duids_requesting_uuid)
578 set_remove(network->manager->duids_requesting_uuid, &network->duid);
579 }
580
581 free(network->name);
582
583 free(network->dhcp_server_timezone);
584 free(network->dhcp_server_dns);
585 free(network->dhcp_server_ntp);
586
587 set_free_free(network->dnssec_negative_trust_anchors);
588
589 return mfree(network);
590 }
591
592 DEFINE_TRIVIAL_REF_UNREF_FUNC(Network, network, network_free);
593
594 int network_get_by_name(Manager *manager, const char *name, Network **ret) {
595 Network *network;
596
597 assert(manager);
598 assert(name);
599 assert(ret);
600
601 network = ordered_hashmap_get(manager->networks, name);
602 if (!network)
603 return -ENOENT;
604
605 *ret = network;
606
607 return 0;
608 }
609
610 int network_get(Manager *manager, sd_device *device,
611 const char *ifname, const struct ether_addr *address,
612 Network **ret) {
613 const char *path = NULL, *driver = NULL, *devtype = NULL;
614 Network *network;
615 Iterator i;
616
617 assert(manager);
618 assert(ret);
619
620 if (device) {
621 (void) sd_device_get_property_value(device, "ID_PATH", &path);
622
623 (void) sd_device_get_property_value(device, "ID_NET_DRIVER", &driver);
624
625 (void) sd_device_get_devtype(device, &devtype);
626 }
627
628 ORDERED_HASHMAP_FOREACH(network, manager->networks, i)
629 if (net_match_config(network->match_mac, network->match_path,
630 network->match_driver, network->match_type,
631 network->match_name,
632 address, path, driver, devtype, ifname)) {
633 if (network->match_name && device) {
634 const char *attr;
635 uint8_t name_assign_type = NET_NAME_UNKNOWN;
636
637 if (sd_device_get_sysattr_value(device, "name_assign_type", &attr) >= 0)
638 (void) safe_atou8(attr, &name_assign_type);
639
640 if (name_assign_type == NET_NAME_ENUM)
641 log_warning("%s: found matching network '%s', based on potentially unpredictable ifname",
642 ifname, network->filename);
643 else
644 log_debug("%s: found matching network '%s'", ifname, network->filename);
645 } else
646 log_debug("%s: found matching network '%s'", ifname, network->filename);
647
648 *ret = network;
649 return 0;
650 }
651
652 *ret = NULL;
653
654 return -ENOENT;
655 }
656
657 int network_apply(Network *network, Link *link) {
658 assert(network);
659 assert(link);
660
661 link->network = network_ref(network);
662
663 if (network->n_dns > 0 ||
664 !strv_isempty(network->ntp) ||
665 !ordered_set_isempty(network->search_domains) ||
666 !ordered_set_isempty(network->route_domains))
667 link_dirty(link);
668
669 return 0;
670 }
671
672 bool network_has_static_ipv6_addresses(Network *network) {
673 Address *address;
674
675 assert(network);
676
677 LIST_FOREACH(addresses, address, network->static_addresses) {
678 if (address->family == AF_INET6)
679 return true;
680 }
681
682 return false;
683 }
684
685 int config_parse_stacked_netdev(const char *unit,
686 const char *filename,
687 unsigned line,
688 const char *section,
689 unsigned section_line,
690 const char *lvalue,
691 int ltype,
692 const char *rvalue,
693 void *data,
694 void *userdata) {
695 _cleanup_free_ char *name = NULL;
696 NetDevKind kind = ltype;
697 Hashmap **h = data;
698 int r;
699
700 assert(filename);
701 assert(lvalue);
702 assert(rvalue);
703 assert(data);
704 assert(IN_SET(kind,
705 NETDEV_KIND_VLAN, NETDEV_KIND_MACVLAN, NETDEV_KIND_MACVTAP,
706 NETDEV_KIND_IPVLAN, NETDEV_KIND_VXLAN, NETDEV_KIND_L2TP,
707 NETDEV_KIND_MACSEC, _NETDEV_KIND_TUNNEL));
708
709 if (!ifname_valid(rvalue)) {
710 log_syntax(unit, LOG_ERR, filename, line, 0,
711 "Invalid netdev name in %s=, ignoring assignment: %s", lvalue, rvalue);
712 return 0;
713 }
714
715 name = strdup(rvalue);
716 if (!name)
717 return log_oom();
718
719 r = hashmap_ensure_allocated(h, &string_hash_ops);
720 if (r < 0)
721 return log_oom();
722
723 r = hashmap_put(*h, name, INT_TO_PTR(kind));
724 if (r < 0)
725 log_syntax(unit, LOG_ERR, filename, line, r,
726 "Cannot add NetDev '%s' to network, ignoring assignment: %m", name);
727 else if (r == 0)
728 log_syntax(unit, LOG_DEBUG, filename, line, r,
729 "NetDev '%s' specified twice, ignoring.", name);
730 else
731 name = NULL;
732
733 return 0;
734 }
735
736 int config_parse_domains(
737 const char *unit,
738 const char *filename,
739 unsigned line,
740 const char *section,
741 unsigned section_line,
742 const char *lvalue,
743 int ltype,
744 const char *rvalue,
745 void *data,
746 void *userdata) {
747
748 const char *p;
749 Network *n = data;
750 int r;
751
752 assert(n);
753 assert(lvalue);
754 assert(rvalue);
755
756 if (isempty(rvalue)) {
757 n->search_domains = ordered_set_free_free(n->search_domains);
758 n->route_domains = ordered_set_free_free(n->route_domains);
759 return 0;
760 }
761
762 p = rvalue;
763 for (;;) {
764 _cleanup_free_ char *w = NULL, *normalized = NULL;
765 const char *domain;
766 bool is_route;
767
768 r = extract_first_word(&p, &w, NULL, 0);
769 if (r < 0) {
770 log_syntax(unit, LOG_ERR, filename, line, r,
771 "Failed to extract search or route domain, ignoring: %s", rvalue);
772 break;
773 }
774 if (r == 0)
775 break;
776
777 is_route = w[0] == '~';
778 domain = is_route ? w + 1 : w;
779
780 if (dns_name_is_root(domain) || streq(domain, "*")) {
781 /* If the root domain appears as is, or the special token "*" is found, we'll
782 * consider this as routing domain, unconditionally. */
783 is_route = true;
784 domain = "."; /* make sure we don't allow empty strings, thus write the root
785 * domain as "." */
786 } else {
787 r = dns_name_normalize(domain, 0, &normalized);
788 if (r < 0) {
789 log_syntax(unit, LOG_ERR, filename, line, r,
790 "'%s' is not a valid domain name, ignoring.", domain);
791 continue;
792 }
793
794 domain = normalized;
795
796 if (is_localhost(domain)) {
797 log_syntax(unit, LOG_ERR, filename, line, 0,
798 "'localhost' domain may not be configured as search or route domain, ignoring assignment: %s",
799 domain);
800 continue;
801 }
802 }
803
804 OrderedSet **set = is_route ? &n->route_domains : &n->search_domains;
805 r = ordered_set_ensure_allocated(set, &string_hash_ops);
806 if (r < 0)
807 return r;
808
809 r = ordered_set_put_strdup(*set, domain);
810 if (r < 0)
811 return log_oom();
812 }
813
814 return 0;
815 }
816
817 int config_parse_ipv4ll(
818 const char* unit,
819 const char *filename,
820 unsigned line,
821 const char *section,
822 unsigned section_line,
823 const char *lvalue,
824 int ltype,
825 const char *rvalue,
826 void *data,
827 void *userdata) {
828
829 AddressFamilyBoolean *link_local = data;
830 int r;
831
832 assert(filename);
833 assert(lvalue);
834 assert(rvalue);
835 assert(data);
836
837 /* Note that this is mostly like
838 * config_parse_address_family_boolean(), except that it
839 * applies only to IPv4 */
840
841 r = parse_boolean(rvalue);
842 if (r < 0) {
843 log_syntax(unit, LOG_ERR, filename, line, r,
844 "Failed to parse %s=%s, ignoring assignment. "
845 "Note that the setting %s= is deprecated, please use LinkLocalAddressing= instead.",
846 lvalue, rvalue, lvalue);
847 return 0;
848 }
849
850 SET_FLAG(*link_local, ADDRESS_FAMILY_IPV4, r);
851
852 log_syntax(unit, LOG_WARNING, filename, line, 0,
853 "%s=%s is deprecated, please use LinkLocalAddressing=%s instead.",
854 lvalue, rvalue, address_family_boolean_to_string(*link_local));
855
856 return 0;
857 }
858
859 int config_parse_dhcp(
860 const char* unit,
861 const char *filename,
862 unsigned line,
863 const char *section,
864 unsigned section_line,
865 const char *lvalue,
866 int ltype,
867 const char *rvalue,
868 void *data,
869 void *userdata) {
870
871 AddressFamilyBoolean *dhcp = data, s;
872
873 assert(filename);
874 assert(lvalue);
875 assert(rvalue);
876 assert(data);
877
878 /* Note that this is mostly like
879 * config_parse_address_family_boolean(), except that it
880 * understands some old names for the enum values */
881
882 s = address_family_boolean_from_string(rvalue);
883 if (s < 0) {
884
885 /* Previously, we had a slightly different enum here,
886 * support its values for compatibility. */
887
888 if (streq(rvalue, "none"))
889 s = ADDRESS_FAMILY_NO;
890 else if (streq(rvalue, "v4"))
891 s = ADDRESS_FAMILY_IPV4;
892 else if (streq(rvalue, "v6"))
893 s = ADDRESS_FAMILY_IPV6;
894 else if (streq(rvalue, "both"))
895 s = ADDRESS_FAMILY_YES;
896 else {
897 log_syntax(unit, LOG_ERR, filename, line, 0,
898 "Failed to parse DHCP option, ignoring: %s", rvalue);
899 return 0;
900 }
901
902 log_syntax(unit, LOG_WARNING, filename, line, 0,
903 "DHCP=%s is deprecated, please use DHCP=%s instead.",
904 rvalue, address_family_boolean_to_string(s));
905 }
906
907 *dhcp = s;
908 return 0;
909 }
910
911 static const char* const dhcp_client_identifier_table[_DHCP_CLIENT_ID_MAX] = {
912 [DHCP_CLIENT_ID_MAC] = "mac",
913 [DHCP_CLIENT_ID_DUID] = "duid",
914 [DHCP_CLIENT_ID_DUID_ONLY] = "duid-only",
915 };
916
917 DEFINE_PRIVATE_STRING_TABLE_LOOKUP_FROM_STRING(dhcp_client_identifier, DHCPClientIdentifier);
918 DEFINE_CONFIG_PARSE_ENUM(config_parse_dhcp_client_identifier, dhcp_client_identifier, DHCPClientIdentifier,
919 "Failed to parse client identifier type");
920
921 int config_parse_ipv6token(
922 const char* unit,
923 const char *filename,
924 unsigned line,
925 const char *section,
926 unsigned section_line,
927 const char *lvalue,
928 int ltype,
929 const char *rvalue,
930 void *data,
931 void *userdata) {
932
933 union in_addr_union buffer;
934 struct in6_addr *token = data;
935 int r;
936
937 assert(filename);
938 assert(lvalue);
939 assert(rvalue);
940 assert(token);
941
942 r = in_addr_from_string(AF_INET6, rvalue, &buffer);
943 if (r < 0) {
944 log_syntax(unit, LOG_ERR, filename, line, r,
945 "Failed to parse IPv6 token, ignoring: %s", rvalue);
946 return 0;
947 }
948
949 if (in_addr_is_null(AF_INET6, &buffer)) {
950 log_syntax(unit, LOG_ERR, filename, line, 0,
951 "IPv6 token cannot be the ANY address, ignoring: %s", rvalue);
952 return 0;
953 }
954
955 if ((buffer.in6.s6_addr32[0] | buffer.in6.s6_addr32[1]) != 0) {
956 log_syntax(unit, LOG_ERR, filename, line, 0,
957 "IPv6 token cannot be longer than 64 bits, ignoring: %s", rvalue);
958 return 0;
959 }
960
961 *token = buffer.in6;
962
963 return 0;
964 }
965
966 static const char* const ipv6_privacy_extensions_table[_IPV6_PRIVACY_EXTENSIONS_MAX] = {
967 [IPV6_PRIVACY_EXTENSIONS_NO] = "no",
968 [IPV6_PRIVACY_EXTENSIONS_PREFER_PUBLIC] = "prefer-public",
969 [IPV6_PRIVACY_EXTENSIONS_YES] = "yes",
970 };
971
972 DEFINE_STRING_TABLE_LOOKUP(ipv6_privacy_extensions, IPv6PrivacyExtensions);
973
974 int config_parse_ipv6_privacy_extensions(
975 const char* unit,
976 const char *filename,
977 unsigned line,
978 const char *section,
979 unsigned section_line,
980 const char *lvalue,
981 int ltype,
982 const char *rvalue,
983 void *data,
984 void *userdata) {
985
986 IPv6PrivacyExtensions *ipv6_privacy_extensions = data;
987 int k;
988
989 assert(filename);
990 assert(lvalue);
991 assert(rvalue);
992 assert(ipv6_privacy_extensions);
993
994 /* Our enum shall be a superset of booleans, hence first try
995 * to parse as boolean, and then as enum */
996
997 k = parse_boolean(rvalue);
998 if (k > 0)
999 *ipv6_privacy_extensions = IPV6_PRIVACY_EXTENSIONS_YES;
1000 else if (k == 0)
1001 *ipv6_privacy_extensions = IPV6_PRIVACY_EXTENSIONS_NO;
1002 else {
1003 IPv6PrivacyExtensions s;
1004
1005 s = ipv6_privacy_extensions_from_string(rvalue);
1006 if (s < 0) {
1007
1008 if (streq(rvalue, "kernel"))
1009 s = _IPV6_PRIVACY_EXTENSIONS_INVALID;
1010 else {
1011 log_syntax(unit, LOG_ERR, filename, line, 0,
1012 "Failed to parse IPv6 privacy extensions option, ignoring: %s", rvalue);
1013 return 0;
1014 }
1015 }
1016
1017 *ipv6_privacy_extensions = s;
1018 }
1019
1020 return 0;
1021 }
1022
1023 int config_parse_hostname(
1024 const char *unit,
1025 const char *filename,
1026 unsigned line,
1027 const char *section,
1028 unsigned section_line,
1029 const char *lvalue,
1030 int ltype,
1031 const char *rvalue,
1032 void *data,
1033 void *userdata) {
1034
1035 _cleanup_free_ char *hn = NULL;
1036 char **hostname = data;
1037 int r;
1038
1039 assert(filename);
1040 assert(lvalue);
1041 assert(rvalue);
1042
1043 r = config_parse_string(unit, filename, line, section, section_line, lvalue, ltype, rvalue, &hn, userdata);
1044 if (r < 0)
1045 return r;
1046
1047 if (!hostname_is_valid(hn, false)) {
1048 log_syntax(unit, LOG_ERR, filename, line, 0,
1049 "Hostname is not valid, ignoring assignment: %s", rvalue);
1050 return 0;
1051 }
1052
1053 r = dns_name_is_valid(hn);
1054 if (r < 0) {
1055 log_syntax(unit, LOG_ERR, filename, line, r,
1056 "Failed to check validity of hostname '%s', ignoring assignment: %m", rvalue);
1057 return 0;
1058 }
1059 if (r == 0) {
1060 log_syntax(unit, LOG_ERR, filename, line, 0,
1061 "Hostname is not a valid DNS domain name, ignoring assignment: %s", rvalue);
1062 return 0;
1063 }
1064
1065 return free_and_replace(*hostname, hn);
1066 }
1067
1068 int config_parse_timezone(
1069 const char *unit,
1070 const char *filename,
1071 unsigned line,
1072 const char *section,
1073 unsigned section_line,
1074 const char *lvalue,
1075 int ltype,
1076 const char *rvalue,
1077 void *data,
1078 void *userdata) {
1079
1080 _cleanup_free_ char *tz = NULL;
1081 char **datap = data;
1082 int r;
1083
1084 assert(filename);
1085 assert(lvalue);
1086 assert(rvalue);
1087
1088 r = config_parse_string(unit, filename, line, section, section_line, lvalue, ltype, rvalue, &tz, userdata);
1089 if (r < 0)
1090 return r;
1091
1092 if (!timezone_is_valid(tz, LOG_ERR)) {
1093 log_syntax(unit, LOG_ERR, filename, line, 0,
1094 "Timezone is not valid, ignoring assignment: %s", rvalue);
1095 return 0;
1096 }
1097
1098 return free_and_replace(*datap, tz);
1099 }
1100
1101 int config_parse_dhcp_server_dns(
1102 const char *unit,
1103 const char *filename,
1104 unsigned line,
1105 const char *section,
1106 unsigned section_line,
1107 const char *lvalue,
1108 int ltype,
1109 const char *rvalue,
1110 void *data,
1111 void *userdata) {
1112
1113 Network *n = data;
1114 const char *p = rvalue;
1115 int r;
1116
1117 assert(filename);
1118 assert(lvalue);
1119 assert(rvalue);
1120
1121 for (;;) {
1122 _cleanup_free_ char *w = NULL;
1123 union in_addr_union a;
1124 struct in_addr *m;
1125
1126 r = extract_first_word(&p, &w, NULL, 0);
1127 if (r == -ENOMEM)
1128 return log_oom();
1129 if (r < 0) {
1130 log_syntax(unit, LOG_ERR, filename, line, r,
1131 "Failed to extract word, ignoring: %s", rvalue);
1132 return 0;
1133 }
1134 if (r == 0)
1135 break;
1136
1137 r = in_addr_from_string(AF_INET, w, &a);
1138 if (r < 0) {
1139 log_syntax(unit, LOG_ERR, filename, line, r,
1140 "Failed to parse DNS server address '%s', ignoring assignment: %m", w);
1141 continue;
1142 }
1143
1144 m = reallocarray(n->dhcp_server_dns, n->n_dhcp_server_dns + 1, sizeof(struct in_addr));
1145 if (!m)
1146 return log_oom();
1147
1148 m[n->n_dhcp_server_dns++] = a.in;
1149 n->dhcp_server_dns = m;
1150 }
1151
1152 return 0;
1153 }
1154
1155 int config_parse_radv_dns(
1156 const char *unit,
1157 const char *filename,
1158 unsigned line,
1159 const char *section,
1160 unsigned section_line,
1161 const char *lvalue,
1162 int ltype,
1163 const char *rvalue,
1164 void *data,
1165 void *userdata) {
1166
1167 Network *n = data;
1168 const char *p = rvalue;
1169 int r;
1170
1171 assert(filename);
1172 assert(lvalue);
1173 assert(rvalue);
1174
1175 for (;;) {
1176 _cleanup_free_ char *w = NULL;
1177 union in_addr_union a;
1178
1179 r = extract_first_word(&p, &w, NULL, 0);
1180 if (r == -ENOMEM)
1181 return log_oom();
1182 if (r < 0) {
1183 log_syntax(unit, LOG_ERR, filename, line, r,
1184 "Failed to extract word, ignoring: %s", rvalue);
1185 return 0;
1186 }
1187 if (r == 0)
1188 break;
1189
1190 if (in_addr_from_string(AF_INET6, w, &a) >= 0) {
1191 struct in6_addr *m;
1192
1193 m = reallocarray(n->router_dns, n->n_router_dns + 1, sizeof(struct in6_addr));
1194 if (!m)
1195 return log_oom();
1196
1197 m[n->n_router_dns++] = a.in6;
1198 n->router_dns = m;
1199
1200 } else
1201 log_syntax(unit, LOG_ERR, filename, line, 0,
1202 "Failed to parse DNS server address, ignoring: %s", w);
1203 }
1204
1205 return 0;
1206 }
1207
1208 int config_parse_radv_search_domains(
1209 const char *unit,
1210 const char *filename,
1211 unsigned line,
1212 const char *section,
1213 unsigned section_line,
1214 const char *lvalue,
1215 int ltype,
1216 const char *rvalue,
1217 void *data,
1218 void *userdata) {
1219
1220 Network *n = data;
1221 const char *p = rvalue;
1222 int r;
1223
1224 assert(filename);
1225 assert(lvalue);
1226 assert(rvalue);
1227
1228 for (;;) {
1229 _cleanup_free_ char *w = NULL, *idna = NULL;
1230
1231 r = extract_first_word(&p, &w, NULL, 0);
1232 if (r == -ENOMEM)
1233 return log_oom();
1234 if (r < 0) {
1235 log_syntax(unit, LOG_ERR, filename, line, r,
1236 "Failed to extract word, ignoring: %s", rvalue);
1237 return 0;
1238 }
1239 if (r == 0)
1240 break;
1241
1242 r = dns_name_apply_idna(w, &idna);
1243 if (r < 0) {
1244 log_syntax(unit, LOG_ERR, filename, line, r,
1245 "Failed to apply IDNA to domain name '%s', ignoring: %m", w);
1246 continue;
1247 } else if (r == 0)
1248 /* transfer ownership to simplify subsequent operations */
1249 idna = TAKE_PTR(w);
1250
1251 r = ordered_set_ensure_allocated(&n->router_search_domains, &string_hash_ops);
1252 if (r < 0)
1253 return r;
1254
1255 r = ordered_set_consume(n->router_search_domains, TAKE_PTR(idna));
1256 if (r < 0)
1257 return r;
1258 }
1259
1260 return 0;
1261 }
1262
1263 int config_parse_dhcp_server_ntp(
1264 const char *unit,
1265 const char *filename,
1266 unsigned line,
1267 const char *section,
1268 unsigned section_line,
1269 const char *lvalue,
1270 int ltype,
1271 const char *rvalue,
1272 void *data,
1273 void *userdata) {
1274
1275 Network *n = data;
1276 const char *p = rvalue;
1277 int r;
1278
1279 assert(filename);
1280 assert(lvalue);
1281 assert(rvalue);
1282
1283 for (;;) {
1284 _cleanup_free_ char *w = NULL;
1285 union in_addr_union a;
1286 struct in_addr *m;
1287
1288 r = extract_first_word(&p, &w, NULL, 0);
1289 if (r == -ENOMEM)
1290 return log_oom();
1291 if (r < 0) {
1292 log_syntax(unit, LOG_ERR, filename, line, r,
1293 "Failed to extract word, ignoring: %s", rvalue);
1294 return 0;
1295 }
1296 if (r == 0)
1297 return 0;
1298
1299 r = in_addr_from_string(AF_INET, w, &a);
1300 if (r < 0) {
1301 log_syntax(unit, LOG_ERR, filename, line, r,
1302 "Failed to parse NTP server address '%s', ignoring: %m", w);
1303 continue;
1304 }
1305
1306 m = reallocarray(n->dhcp_server_ntp, n->n_dhcp_server_ntp + 1, sizeof(struct in_addr));
1307 if (!m)
1308 return log_oom();
1309
1310 m[n->n_dhcp_server_ntp++] = a.in;
1311 n->dhcp_server_ntp = m;
1312 }
1313 }
1314
1315 int config_parse_dns(
1316 const char *unit,
1317 const char *filename,
1318 unsigned line,
1319 const char *section,
1320 unsigned section_line,
1321 const char *lvalue,
1322 int ltype,
1323 const char *rvalue,
1324 void *data,
1325 void *userdata) {
1326
1327 Network *n = userdata;
1328 int r;
1329
1330 assert(filename);
1331 assert(lvalue);
1332 assert(rvalue);
1333
1334 for (;;) {
1335 _cleanup_free_ char *w = NULL;
1336 union in_addr_union a;
1337 struct in_addr_data *m;
1338 int family;
1339
1340 r = extract_first_word(&rvalue, &w, NULL, 0);
1341 if (r == -ENOMEM)
1342 return log_oom();
1343 if (r < 0) {
1344 log_syntax(unit, LOG_ERR, filename, line, r,
1345 "Invalid syntax, ignoring: %s", rvalue);
1346 break;
1347 }
1348 if (r == 0)
1349 break;
1350
1351 r = in_addr_from_string_auto(w, &family, &a);
1352 if (r < 0) {
1353 log_syntax(unit, LOG_ERR, filename, line, r,
1354 "Failed to parse dns server address, ignoring: %s", w);
1355 continue;
1356 }
1357
1358 m = reallocarray(n->dns, n->n_dns + 1, sizeof(struct in_addr_data));
1359 if (!m)
1360 return log_oom();
1361
1362 m[n->n_dns++] = (struct in_addr_data) {
1363 .family = family,
1364 .address = a,
1365 };
1366
1367 n->dns = m;
1368 }
1369
1370 return 0;
1371 }
1372
1373 int config_parse_dnssec_negative_trust_anchors(
1374 const char *unit,
1375 const char *filename,
1376 unsigned line,
1377 const char *section,
1378 unsigned section_line,
1379 const char *lvalue,
1380 int ltype,
1381 const char *rvalue,
1382 void *data,
1383 void *userdata) {
1384
1385 const char *p = rvalue;
1386 Network *n = data;
1387 int r;
1388
1389 assert(n);
1390 assert(lvalue);
1391 assert(rvalue);
1392
1393 if (isempty(rvalue)) {
1394 n->dnssec_negative_trust_anchors = set_free_free(n->dnssec_negative_trust_anchors);
1395 return 0;
1396 }
1397
1398 for (;;) {
1399 _cleanup_free_ char *w = NULL;
1400
1401 r = extract_first_word(&p, &w, NULL, 0);
1402 if (r < 0) {
1403 log_syntax(unit, LOG_ERR, filename, line, r,
1404 "Failed to extract negative trust anchor domain, ignoring: %s", rvalue);
1405 break;
1406 }
1407 if (r == 0)
1408 break;
1409
1410 r = dns_name_is_valid(w);
1411 if (r <= 0) {
1412 log_syntax(unit, LOG_ERR, filename, line, r,
1413 "%s is not a valid domain name, ignoring.", w);
1414 continue;
1415 }
1416
1417 r = set_ensure_allocated(&n->dnssec_negative_trust_anchors, &dns_name_hash_ops);
1418 if (r < 0)
1419 return log_oom();
1420
1421 r = set_put(n->dnssec_negative_trust_anchors, w);
1422 if (r < 0)
1423 return log_oom();
1424 if (r > 0)
1425 w = NULL;
1426 }
1427
1428 return 0;
1429 }
1430
1431 int config_parse_ntp(
1432 const char *unit,
1433 const char *filename,
1434 unsigned line,
1435 const char *section,
1436 unsigned section_line,
1437 const char *lvalue,
1438 int ltype,
1439 const char *rvalue,
1440 void *data,
1441 void *userdata) {
1442
1443 char ***l = data;
1444 int r;
1445
1446 assert(l);
1447 assert(lvalue);
1448 assert(rvalue);
1449
1450 if (isempty(rvalue)) {
1451 *l = strv_free(*l);
1452 return 0;
1453 }
1454
1455 for (;;) {
1456 _cleanup_free_ char *w = NULL;
1457
1458 r = extract_first_word(&rvalue, &w, NULL, 0);
1459 if (r == -ENOMEM)
1460 return log_oom();
1461 if (r < 0) {
1462 log_syntax(unit, LOG_ERR, filename, line, r,
1463 "Failed to extract NTP server name, ignoring: %s", rvalue);
1464 break;
1465 }
1466 if (r == 0)
1467 break;
1468
1469 r = dns_name_is_valid_or_address(w);
1470 if (r <= 0) {
1471 log_syntax(unit, LOG_ERR, filename, line, r,
1472 "%s is not a valid domain name or IP address, ignoring.", w);
1473 continue;
1474 }
1475
1476 if (strv_length(*l) > MAX_NTP_SERVERS) {
1477 log_syntax(unit, LOG_WARNING, filename, line, 0,
1478 "More than %u NTP servers specified, ignoring \"%s\" and any subsequent entries.",
1479 MAX_NTP_SERVERS, w);
1480 break;
1481 }
1482
1483 r = strv_consume(l, TAKE_PTR(w));
1484 if (r < 0)
1485 return log_oom();
1486 }
1487
1488 return 0;
1489 }
1490
1491 int config_parse_dhcp_user_class(
1492 const char *unit,
1493 const char *filename,
1494 unsigned line,
1495 const char *section,
1496 unsigned section_line,
1497 const char *lvalue,
1498 int ltype,
1499 const char *rvalue,
1500 void *data,
1501 void *userdata) {
1502
1503 char ***l = data;
1504 int r;
1505
1506 assert(l);
1507 assert(lvalue);
1508 assert(rvalue);
1509
1510 if (isempty(rvalue)) {
1511 *l = strv_free(*l);
1512 return 0;
1513 }
1514
1515 for (;;) {
1516 _cleanup_free_ char *w = NULL;
1517
1518 r = extract_first_word(&rvalue, &w, NULL, 0);
1519 if (r == -ENOMEM)
1520 return log_oom();
1521 if (r < 0) {
1522 log_syntax(unit, LOG_ERR, filename, line, r,
1523 "Failed to split user classes option, ignoring: %s", rvalue);
1524 break;
1525 }
1526 if (r == 0)
1527 break;
1528
1529 if (strlen(w) > 255) {
1530 log_syntax(unit, LOG_ERR, filename, line, 0,
1531 "%s length is not in the range 1-255, ignoring.", w);
1532 continue;
1533 }
1534
1535 r = strv_push(l, w);
1536 if (r < 0)
1537 return log_oom();
1538
1539 w = NULL;
1540 }
1541
1542 return 0;
1543 }
1544
1545 int config_parse_section_route_table(
1546 const char *unit,
1547 const char *filename,
1548 unsigned line,
1549 const char *section,
1550 unsigned section_line,
1551 const char *lvalue,
1552 int ltype,
1553 const char *rvalue,
1554 void *data,
1555 void *userdata) {
1556
1557 Network *network = data;
1558 uint32_t rt;
1559 int r;
1560
1561 assert(filename);
1562 assert(lvalue);
1563 assert(rvalue);
1564 assert(data);
1565
1566 r = safe_atou32(rvalue, &rt);
1567 if (r < 0) {
1568 log_syntax(unit, LOG_ERR, filename, line, r,
1569 "Failed to parse RouteTable=%s, ignoring assignment: %m", rvalue);
1570 return 0;
1571 }
1572
1573 if (streq_ptr(section, "DHCP")) {
1574 network->dhcp_route_table = rt;
1575 network->dhcp_route_table_set = true;
1576 } else { /* section is IPv6AcceptRA */
1577 network->ipv6_accept_ra_route_table = rt;
1578 network->ipv6_accept_ra_route_table_set = true;
1579 }
1580
1581 return 0;
1582 }
1583
1584 int config_parse_dhcp_max_attempts(
1585 const char *unit,
1586 const char *filename,
1587 unsigned line,
1588 const char *section,
1589 unsigned section_line,
1590 const char *lvalue,
1591 int ltype,
1592 const char *rvalue,
1593 void *data,
1594 void *userdata) {
1595
1596 Network *network = data;
1597 uint64_t a;
1598 int r;
1599
1600 assert(network);
1601 assert(lvalue);
1602 assert(rvalue);
1603
1604 if (isempty(rvalue)) {
1605 network->dhcp_max_attempts = 0;
1606 return 0;
1607 }
1608
1609 if (streq(rvalue, "infinity")) {
1610 network->dhcp_max_attempts = (uint64_t) -1;
1611 return 0;
1612 }
1613
1614 r = safe_atou64(rvalue, &a);
1615 if (r < 0) {
1616 log_syntax(unit, LOG_ERR, filename, line, r,
1617 "Failed to parse DHCP maximum attempts, ignoring: %s", rvalue);
1618 return 0;
1619 }
1620
1621 if (a == 0) {
1622 log_syntax(unit, LOG_ERR, filename, line, 0,
1623 "%s= must be positive integer or 'infinity', ignoring: %s", lvalue, rvalue);
1624 return 0;
1625 }
1626
1627 network->dhcp_max_attempts = a;
1628
1629 return 0;
1630 }
1631
1632 int config_parse_dhcp_black_listed_ip_address(
1633 const char *unit,
1634 const char *filename,
1635 unsigned line,
1636 const char *section,
1637 unsigned section_line,
1638 const char *lvalue,
1639 int ltype,
1640 const char *rvalue,
1641 void *data,
1642 void *userdata) {
1643
1644 Network *network = data;
1645 const char *p;
1646 int r;
1647
1648 assert(filename);
1649 assert(lvalue);
1650 assert(rvalue);
1651 assert(data);
1652
1653 if (isempty(rvalue)) {
1654 network->dhcp_black_listed_ip = set_free(network->dhcp_black_listed_ip);
1655 return 0;
1656 }
1657
1658 for (p = rvalue;;) {
1659 _cleanup_free_ char *n = NULL;
1660 union in_addr_union ip;
1661
1662 r = extract_first_word(&p, &n, NULL, 0);
1663 if (r < 0) {
1664 log_syntax(unit, LOG_ERR, filename, line, r,
1665 "Failed to parse DHCP black listed ip address, ignoring assignment: %s",
1666 rvalue);
1667 return 0;
1668 }
1669 if (r == 0)
1670 return 0;
1671
1672 r = in_addr_from_string(AF_INET, n, &ip);
1673 if (r < 0) {
1674 log_syntax(unit, LOG_ERR, filename, line, r,
1675 "DHCP black listed ip address is invalid, ignoring assignment: %s", n);
1676 continue;
1677 }
1678
1679 r = set_ensure_allocated(&network->dhcp_black_listed_ip, NULL);
1680 if (r < 0)
1681 return log_oom();
1682
1683 r = set_put(network->dhcp_black_listed_ip, UINT32_TO_PTR(ip.in.s_addr));
1684 if (r == -EEXIST) {
1685 log_syntax(unit, LOG_WARNING, filename, line, r,
1686 "DHCP black listed ip address is duplicated, ignoring assignment: %s", n);
1687 continue;
1688 }
1689 if (r < 0)
1690 log_syntax(unit, LOG_ERR, filename, line, r,
1691 "Failed to store DHCP black listed ip address '%s', ignoring assignment: %m", n);
1692 }
1693
1694 return 0;
1695 }
1696
1697 DEFINE_CONFIG_PARSE_ENUM(config_parse_dhcp_use_domains, dhcp_use_domains, DHCPUseDomains,
1698 "Failed to parse DHCP use domains setting");
1699
1700 static const char* const dhcp_use_domains_table[_DHCP_USE_DOMAINS_MAX] = {
1701 [DHCP_USE_DOMAINS_NO] = "no",
1702 [DHCP_USE_DOMAINS_ROUTE] = "route",
1703 [DHCP_USE_DOMAINS_YES] = "yes",
1704 };
1705
1706 DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(dhcp_use_domains, DHCPUseDomains, DHCP_USE_DOMAINS_YES);
1707
1708 int config_parse_iaid(const char *unit,
1709 const char *filename,
1710 unsigned line,
1711 const char *section,
1712 unsigned section_line,
1713 const char *lvalue,
1714 int ltype,
1715 const char *rvalue,
1716 void *data,
1717 void *userdata) {
1718 Network *network = data;
1719 uint32_t iaid;
1720 int r;
1721
1722 assert(filename);
1723 assert(lvalue);
1724 assert(rvalue);
1725 assert(network);
1726
1727 r = safe_atou32(rvalue, &iaid);
1728 if (r < 0) {
1729 log_syntax(unit, LOG_ERR, filename, line, r,
1730 "Unable to read IAID, ignoring assignment: %s", rvalue);
1731 return 0;
1732 }
1733
1734 network->iaid = iaid;
1735 network->iaid_set = true;
1736
1737 return 0;
1738 }
1739
1740 int config_parse_required_for_online(
1741 const char *unit,
1742 const char *filename,
1743 unsigned line,
1744 const char *section,
1745 unsigned section_line,
1746 const char *lvalue,
1747 int ltype,
1748 const char *rvalue,
1749 void *data,
1750 void *userdata) {
1751
1752 Network *network = data;
1753 LinkOperationalState s;
1754 bool required = true;
1755 int r;
1756
1757 if (isempty(rvalue)) {
1758 network->required_for_online = true;
1759 network->required_operstate_for_online = LINK_OPERSTATE_DEGRADED;
1760 return 0;
1761 }
1762
1763 s = link_operstate_from_string(rvalue);
1764 if (s < 0) {
1765 r = parse_boolean(rvalue);
1766 if (r < 0) {
1767 log_syntax(unit, LOG_ERR, filename, line, r,
1768 "Failed to parse %s= setting, ignoring assignment: %s",
1769 lvalue, rvalue);
1770 return 0;
1771 }
1772
1773 required = r;
1774 s = LINK_OPERSTATE_DEGRADED;
1775 }
1776
1777 network->required_for_online = required;
1778 network->required_operstate_for_online = s;
1779
1780 return 0;
1781 }