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