]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/network/networkd-network.c
Merge pull request #12603 from ssahani/ndisc-blacklist
[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 set_free_free(network->ndisc_black_listed_prefix);
509
510 free(network->bridge_name);
511 free(network->bond_name);
512 free(network->vrf_name);
513 hashmap_free_free_key(network->stacked_netdev_names);
514 netdev_unref(network->bridge);
515 netdev_unref(network->bond);
516 netdev_unref(network->vrf);
517 hashmap_free_with_destructor(network->stacked_netdevs, netdev_unref);
518
519 while ((route = network->static_routes))
520 route_free(route);
521
522 while ((address = network->static_addresses))
523 address_free(address);
524
525 while ((fdb_entry = network->static_fdb_entries))
526 fdb_entry_free(fdb_entry);
527
528 while ((ipv6_proxy_ndp_address = network->ipv6_proxy_ndp_addresses))
529 ipv6_proxy_ndp_address_free(ipv6_proxy_ndp_address);
530
531 while ((neighbor = network->neighbors))
532 neighbor_free(neighbor);
533
534 while ((label = network->address_labels))
535 address_label_free(label);
536
537 while ((prefix = network->static_prefixes))
538 prefix_free(prefix);
539
540 while ((rule = network->rules))
541 routing_policy_rule_free(rule);
542
543 hashmap_free(network->addresses_by_section);
544 hashmap_free(network->routes_by_section);
545 hashmap_free(network->fdb_entries_by_section);
546 hashmap_free(network->neighbors_by_section);
547 hashmap_free(network->address_labels_by_section);
548 hashmap_free(network->prefixes_by_section);
549 hashmap_free(network->rules_by_section);
550
551 if (network->manager) {
552 if (network->manager->networks && network->name)
553 ordered_hashmap_remove(network->manager->networks, network->name);
554
555 if (network->manager->duids_requesting_uuid)
556 set_remove(network->manager->duids_requesting_uuid, &network->duid);
557 }
558
559 free(network->name);
560
561 free(network->dhcp_server_timezone);
562 free(network->dhcp_server_dns);
563 free(network->dhcp_server_ntp);
564
565 set_free_free(network->dnssec_negative_trust_anchors);
566
567 return mfree(network);
568 }
569
570 DEFINE_TRIVIAL_REF_UNREF_FUNC(Network, network, network_free);
571
572 int network_get_by_name(Manager *manager, const char *name, Network **ret) {
573 Network *network;
574
575 assert(manager);
576 assert(name);
577 assert(ret);
578
579 network = ordered_hashmap_get(manager->networks, name);
580 if (!network)
581 return -ENOENT;
582
583 *ret = network;
584
585 return 0;
586 }
587
588 int network_get(Manager *manager, sd_device *device,
589 const char *ifname, const struct ether_addr *address,
590 Network **ret) {
591 const char *path = NULL, *driver = NULL, *devtype = NULL;
592 Network *network;
593 Iterator i;
594
595 assert(manager);
596 assert(ret);
597
598 if (device) {
599 (void) sd_device_get_property_value(device, "ID_PATH", &path);
600
601 (void) sd_device_get_property_value(device, "ID_NET_DRIVER", &driver);
602
603 (void) sd_device_get_devtype(device, &devtype);
604 }
605
606 ORDERED_HASHMAP_FOREACH(network, manager->networks, i)
607 if (net_match_config(network->match_mac, network->match_path,
608 network->match_driver, network->match_type,
609 network->match_name,
610 address, path, driver, devtype, ifname)) {
611 if (network->match_name && device) {
612 const char *attr;
613 uint8_t name_assign_type = NET_NAME_UNKNOWN;
614
615 if (sd_device_get_sysattr_value(device, "name_assign_type", &attr) >= 0)
616 (void) safe_atou8(attr, &name_assign_type);
617
618 if (name_assign_type == NET_NAME_ENUM)
619 log_warning("%s: found matching network '%s', based on potentially unpredictable ifname",
620 ifname, network->filename);
621 else
622 log_debug("%s: found matching network '%s'", ifname, network->filename);
623 } else
624 log_debug("%s: found matching network '%s'", ifname, network->filename);
625
626 *ret = network;
627 return 0;
628 }
629
630 *ret = NULL;
631
632 return -ENOENT;
633 }
634
635 int network_apply(Network *network, Link *link) {
636 assert(network);
637 assert(link);
638
639 link->network = network_ref(network);
640
641 if (network->n_dns > 0 ||
642 !strv_isempty(network->ntp) ||
643 !ordered_set_isempty(network->search_domains) ||
644 !ordered_set_isempty(network->route_domains))
645 link_dirty(link);
646
647 return 0;
648 }
649
650 bool network_has_static_ipv6_addresses(Network *network) {
651 Address *address;
652
653 assert(network);
654
655 LIST_FOREACH(addresses, address, network->static_addresses) {
656 if (address->family == AF_INET6)
657 return true;
658 }
659
660 return false;
661 }
662
663 int config_parse_stacked_netdev(const char *unit,
664 const char *filename,
665 unsigned line,
666 const char *section,
667 unsigned section_line,
668 const char *lvalue,
669 int ltype,
670 const char *rvalue,
671 void *data,
672 void *userdata) {
673 _cleanup_free_ char *name = NULL;
674 NetDevKind kind = ltype;
675 Hashmap **h = data;
676 int r;
677
678 assert(filename);
679 assert(lvalue);
680 assert(rvalue);
681 assert(data);
682 assert(IN_SET(kind,
683 NETDEV_KIND_VLAN, NETDEV_KIND_MACVLAN, NETDEV_KIND_MACVTAP,
684 NETDEV_KIND_IPVLAN, NETDEV_KIND_IPVTAP, NETDEV_KIND_VXLAN,
685 NETDEV_KIND_L2TP, NETDEV_KIND_MACSEC, _NETDEV_KIND_TUNNEL));
686
687 if (!ifname_valid(rvalue)) {
688 log_syntax(unit, LOG_ERR, filename, line, 0,
689 "Invalid netdev name in %s=, ignoring assignment: %s", lvalue, rvalue);
690 return 0;
691 }
692
693 name = strdup(rvalue);
694 if (!name)
695 return log_oom();
696
697 r = hashmap_ensure_allocated(h, &string_hash_ops);
698 if (r < 0)
699 return log_oom();
700
701 r = hashmap_put(*h, name, INT_TO_PTR(kind));
702 if (r < 0)
703 log_syntax(unit, LOG_ERR, filename, line, r,
704 "Cannot add NetDev '%s' to network, ignoring assignment: %m", name);
705 else if (r == 0)
706 log_syntax(unit, LOG_DEBUG, filename, line, r,
707 "NetDev '%s' specified twice, ignoring.", name);
708 else
709 name = NULL;
710
711 return 0;
712 }
713
714 int config_parse_domains(
715 const char *unit,
716 const char *filename,
717 unsigned line,
718 const char *section,
719 unsigned section_line,
720 const char *lvalue,
721 int ltype,
722 const char *rvalue,
723 void *data,
724 void *userdata) {
725
726 const char *p;
727 Network *n = data;
728 int r;
729
730 assert(n);
731 assert(lvalue);
732 assert(rvalue);
733
734 if (isempty(rvalue)) {
735 n->search_domains = ordered_set_free_free(n->search_domains);
736 n->route_domains = ordered_set_free_free(n->route_domains);
737 return 0;
738 }
739
740 p = rvalue;
741 for (;;) {
742 _cleanup_free_ char *w = NULL, *normalized = NULL;
743 const char *domain;
744 bool is_route;
745
746 r = extract_first_word(&p, &w, NULL, 0);
747 if (r < 0) {
748 log_syntax(unit, LOG_ERR, filename, line, r,
749 "Failed to extract search or route domain, ignoring: %s", rvalue);
750 break;
751 }
752 if (r == 0)
753 break;
754
755 is_route = w[0] == '~';
756 domain = is_route ? w + 1 : w;
757
758 if (dns_name_is_root(domain) || streq(domain, "*")) {
759 /* If the root domain appears as is, or the special token "*" is found, we'll
760 * consider this as routing domain, unconditionally. */
761 is_route = true;
762 domain = "."; /* make sure we don't allow empty strings, thus write the root
763 * domain as "." */
764 } else {
765 r = dns_name_normalize(domain, 0, &normalized);
766 if (r < 0) {
767 log_syntax(unit, LOG_ERR, filename, line, r,
768 "'%s' is not a valid domain name, ignoring.", domain);
769 continue;
770 }
771
772 domain = normalized;
773
774 if (is_localhost(domain)) {
775 log_syntax(unit, LOG_ERR, filename, line, 0,
776 "'localhost' domain may not be configured as search or route domain, ignoring assignment: %s",
777 domain);
778 continue;
779 }
780 }
781
782 OrderedSet **set = is_route ? &n->route_domains : &n->search_domains;
783 r = ordered_set_ensure_allocated(set, &string_hash_ops);
784 if (r < 0)
785 return r;
786
787 r = ordered_set_put_strdup(*set, domain);
788 if (r < 0)
789 return log_oom();
790 }
791
792 return 0;
793 }
794
795 int config_parse_ipv4ll(
796 const char* unit,
797 const char *filename,
798 unsigned line,
799 const char *section,
800 unsigned section_line,
801 const char *lvalue,
802 int ltype,
803 const char *rvalue,
804 void *data,
805 void *userdata) {
806
807 AddressFamilyBoolean *link_local = data;
808 int r;
809
810 assert(filename);
811 assert(lvalue);
812 assert(rvalue);
813 assert(data);
814
815 /* Note that this is mostly like
816 * config_parse_address_family_boolean(), except that it
817 * applies only to IPv4 */
818
819 r = parse_boolean(rvalue);
820 if (r < 0) {
821 log_syntax(unit, LOG_ERR, filename, line, r,
822 "Failed to parse %s=%s, ignoring assignment. "
823 "Note that the setting %s= is deprecated, please use LinkLocalAddressing= instead.",
824 lvalue, rvalue, lvalue);
825 return 0;
826 }
827
828 SET_FLAG(*link_local, ADDRESS_FAMILY_IPV4, r);
829
830 log_syntax(unit, LOG_WARNING, filename, line, 0,
831 "%s=%s is deprecated, please use LinkLocalAddressing=%s instead.",
832 lvalue, rvalue, address_family_boolean_to_string(*link_local));
833
834 return 0;
835 }
836
837 int config_parse_dhcp(
838 const char* unit,
839 const char *filename,
840 unsigned line,
841 const char *section,
842 unsigned section_line,
843 const char *lvalue,
844 int ltype,
845 const char *rvalue,
846 void *data,
847 void *userdata) {
848
849 AddressFamilyBoolean *dhcp = data, s;
850
851 assert(filename);
852 assert(lvalue);
853 assert(rvalue);
854 assert(data);
855
856 /* Note that this is mostly like
857 * config_parse_address_family_boolean(), except that it
858 * understands some old names for the enum values */
859
860 s = address_family_boolean_from_string(rvalue);
861 if (s < 0) {
862
863 /* Previously, we had a slightly different enum here,
864 * support its values for compatibility. */
865
866 if (streq(rvalue, "none"))
867 s = ADDRESS_FAMILY_NO;
868 else if (streq(rvalue, "v4"))
869 s = ADDRESS_FAMILY_IPV4;
870 else if (streq(rvalue, "v6"))
871 s = ADDRESS_FAMILY_IPV6;
872 else if (streq(rvalue, "both"))
873 s = ADDRESS_FAMILY_YES;
874 else {
875 log_syntax(unit, LOG_ERR, filename, line, 0,
876 "Failed to parse DHCP option, ignoring: %s", rvalue);
877 return 0;
878 }
879
880 log_syntax(unit, LOG_WARNING, filename, line, 0,
881 "DHCP=%s is deprecated, please use DHCP=%s instead.",
882 rvalue, address_family_boolean_to_string(s));
883 }
884
885 *dhcp = s;
886 return 0;
887 }
888
889 static const char* const dhcp_client_identifier_table[_DHCP_CLIENT_ID_MAX] = {
890 [DHCP_CLIENT_ID_MAC] = "mac",
891 [DHCP_CLIENT_ID_DUID] = "duid",
892 [DHCP_CLIENT_ID_DUID_ONLY] = "duid-only",
893 };
894
895 DEFINE_PRIVATE_STRING_TABLE_LOOKUP_FROM_STRING(dhcp_client_identifier, DHCPClientIdentifier);
896 DEFINE_CONFIG_PARSE_ENUM(config_parse_dhcp_client_identifier, dhcp_client_identifier, DHCPClientIdentifier,
897 "Failed to parse client identifier type");
898
899 int config_parse_ipv6token(
900 const char* unit,
901 const char *filename,
902 unsigned line,
903 const char *section,
904 unsigned section_line,
905 const char *lvalue,
906 int ltype,
907 const char *rvalue,
908 void *data,
909 void *userdata) {
910
911 union in_addr_union buffer;
912 struct in6_addr *token = data;
913 int r;
914
915 assert(filename);
916 assert(lvalue);
917 assert(rvalue);
918 assert(token);
919
920 r = in_addr_from_string(AF_INET6, rvalue, &buffer);
921 if (r < 0) {
922 log_syntax(unit, LOG_ERR, filename, line, r,
923 "Failed to parse IPv6 token, ignoring: %s", rvalue);
924 return 0;
925 }
926
927 if (in_addr_is_null(AF_INET6, &buffer)) {
928 log_syntax(unit, LOG_ERR, filename, line, 0,
929 "IPv6 token cannot be the ANY address, ignoring: %s", rvalue);
930 return 0;
931 }
932
933 if ((buffer.in6.s6_addr32[0] | buffer.in6.s6_addr32[1]) != 0) {
934 log_syntax(unit, LOG_ERR, filename, line, 0,
935 "IPv6 token cannot be longer than 64 bits, ignoring: %s", rvalue);
936 return 0;
937 }
938
939 *token = buffer.in6;
940
941 return 0;
942 }
943
944 static const char* const ipv6_privacy_extensions_table[_IPV6_PRIVACY_EXTENSIONS_MAX] = {
945 [IPV6_PRIVACY_EXTENSIONS_NO] = "no",
946 [IPV6_PRIVACY_EXTENSIONS_PREFER_PUBLIC] = "prefer-public",
947 [IPV6_PRIVACY_EXTENSIONS_YES] = "yes",
948 };
949
950 DEFINE_STRING_TABLE_LOOKUP(ipv6_privacy_extensions, IPv6PrivacyExtensions);
951
952 int config_parse_ipv6_privacy_extensions(
953 const char* unit,
954 const char *filename,
955 unsigned line,
956 const char *section,
957 unsigned section_line,
958 const char *lvalue,
959 int ltype,
960 const char *rvalue,
961 void *data,
962 void *userdata) {
963
964 IPv6PrivacyExtensions *ipv6_privacy_extensions = data;
965 int k;
966
967 assert(filename);
968 assert(lvalue);
969 assert(rvalue);
970 assert(ipv6_privacy_extensions);
971
972 /* Our enum shall be a superset of booleans, hence first try
973 * to parse as boolean, and then as enum */
974
975 k = parse_boolean(rvalue);
976 if (k > 0)
977 *ipv6_privacy_extensions = IPV6_PRIVACY_EXTENSIONS_YES;
978 else if (k == 0)
979 *ipv6_privacy_extensions = IPV6_PRIVACY_EXTENSIONS_NO;
980 else {
981 IPv6PrivacyExtensions s;
982
983 s = ipv6_privacy_extensions_from_string(rvalue);
984 if (s < 0) {
985
986 if (streq(rvalue, "kernel"))
987 s = _IPV6_PRIVACY_EXTENSIONS_INVALID;
988 else {
989 log_syntax(unit, LOG_ERR, filename, line, 0,
990 "Failed to parse IPv6 privacy extensions option, ignoring: %s", rvalue);
991 return 0;
992 }
993 }
994
995 *ipv6_privacy_extensions = s;
996 }
997
998 return 0;
999 }
1000
1001 int config_parse_hostname(
1002 const char *unit,
1003 const char *filename,
1004 unsigned line,
1005 const char *section,
1006 unsigned section_line,
1007 const char *lvalue,
1008 int ltype,
1009 const char *rvalue,
1010 void *data,
1011 void *userdata) {
1012
1013 _cleanup_free_ char *hn = NULL;
1014 char **hostname = data;
1015 int r;
1016
1017 assert(filename);
1018 assert(lvalue);
1019 assert(rvalue);
1020
1021 r = config_parse_string(unit, filename, line, section, section_line, lvalue, ltype, rvalue, &hn, userdata);
1022 if (r < 0)
1023 return r;
1024
1025 if (!hostname_is_valid(hn, false)) {
1026 log_syntax(unit, LOG_ERR, filename, line, 0,
1027 "Hostname is not valid, ignoring assignment: %s", rvalue);
1028 return 0;
1029 }
1030
1031 r = dns_name_is_valid(hn);
1032 if (r < 0) {
1033 log_syntax(unit, LOG_ERR, filename, line, r,
1034 "Failed to check validity of hostname '%s', ignoring assignment: %m", rvalue);
1035 return 0;
1036 }
1037 if (r == 0) {
1038 log_syntax(unit, LOG_ERR, filename, line, 0,
1039 "Hostname is not a valid DNS domain name, ignoring assignment: %s", rvalue);
1040 return 0;
1041 }
1042
1043 return free_and_replace(*hostname, hn);
1044 }
1045
1046 int config_parse_timezone(
1047 const char *unit,
1048 const char *filename,
1049 unsigned line,
1050 const char *section,
1051 unsigned section_line,
1052 const char *lvalue,
1053 int ltype,
1054 const char *rvalue,
1055 void *data,
1056 void *userdata) {
1057
1058 _cleanup_free_ char *tz = NULL;
1059 char **datap = data;
1060 int r;
1061
1062 assert(filename);
1063 assert(lvalue);
1064 assert(rvalue);
1065
1066 r = config_parse_string(unit, filename, line, section, section_line, lvalue, ltype, rvalue, &tz, userdata);
1067 if (r < 0)
1068 return r;
1069
1070 if (!timezone_is_valid(tz, LOG_ERR)) {
1071 log_syntax(unit, LOG_ERR, filename, line, 0,
1072 "Timezone is not valid, ignoring assignment: %s", rvalue);
1073 return 0;
1074 }
1075
1076 return free_and_replace(*datap, tz);
1077 }
1078
1079 int config_parse_dhcp_server_dns(
1080 const char *unit,
1081 const char *filename,
1082 unsigned line,
1083 const char *section,
1084 unsigned section_line,
1085 const char *lvalue,
1086 int ltype,
1087 const char *rvalue,
1088 void *data,
1089 void *userdata) {
1090
1091 Network *n = data;
1092 const char *p = rvalue;
1093 int r;
1094
1095 assert(filename);
1096 assert(lvalue);
1097 assert(rvalue);
1098
1099 for (;;) {
1100 _cleanup_free_ char *w = NULL;
1101 union in_addr_union a;
1102 struct in_addr *m;
1103
1104 r = extract_first_word(&p, &w, NULL, 0);
1105 if (r == -ENOMEM)
1106 return log_oom();
1107 if (r < 0) {
1108 log_syntax(unit, LOG_ERR, filename, line, r,
1109 "Failed to extract word, ignoring: %s", rvalue);
1110 return 0;
1111 }
1112 if (r == 0)
1113 break;
1114
1115 r = in_addr_from_string(AF_INET, w, &a);
1116 if (r < 0) {
1117 log_syntax(unit, LOG_ERR, filename, line, r,
1118 "Failed to parse DNS server address '%s', ignoring assignment: %m", w);
1119 continue;
1120 }
1121
1122 m = reallocarray(n->dhcp_server_dns, n->n_dhcp_server_dns + 1, sizeof(struct in_addr));
1123 if (!m)
1124 return log_oom();
1125
1126 m[n->n_dhcp_server_dns++] = a.in;
1127 n->dhcp_server_dns = m;
1128 }
1129
1130 return 0;
1131 }
1132
1133 int config_parse_radv_dns(
1134 const char *unit,
1135 const char *filename,
1136 unsigned line,
1137 const char *section,
1138 unsigned section_line,
1139 const char *lvalue,
1140 int ltype,
1141 const char *rvalue,
1142 void *data,
1143 void *userdata) {
1144
1145 Network *n = data;
1146 const char *p = rvalue;
1147 int r;
1148
1149 assert(filename);
1150 assert(lvalue);
1151 assert(rvalue);
1152
1153 for (;;) {
1154 _cleanup_free_ char *w = NULL;
1155 union in_addr_union a;
1156
1157 r = extract_first_word(&p, &w, NULL, 0);
1158 if (r == -ENOMEM)
1159 return log_oom();
1160 if (r < 0) {
1161 log_syntax(unit, LOG_ERR, filename, line, r,
1162 "Failed to extract word, ignoring: %s", rvalue);
1163 return 0;
1164 }
1165 if (r == 0)
1166 break;
1167
1168 if (in_addr_from_string(AF_INET6, w, &a) >= 0) {
1169 struct in6_addr *m;
1170
1171 m = reallocarray(n->router_dns, n->n_router_dns + 1, sizeof(struct in6_addr));
1172 if (!m)
1173 return log_oom();
1174
1175 m[n->n_router_dns++] = a.in6;
1176 n->router_dns = m;
1177
1178 } else
1179 log_syntax(unit, LOG_ERR, filename, line, 0,
1180 "Failed to parse DNS server address, ignoring: %s", w);
1181 }
1182
1183 return 0;
1184 }
1185
1186 int config_parse_radv_search_domains(
1187 const char *unit,
1188 const char *filename,
1189 unsigned line,
1190 const char *section,
1191 unsigned section_line,
1192 const char *lvalue,
1193 int ltype,
1194 const char *rvalue,
1195 void *data,
1196 void *userdata) {
1197
1198 Network *n = data;
1199 const char *p = rvalue;
1200 int r;
1201
1202 assert(filename);
1203 assert(lvalue);
1204 assert(rvalue);
1205
1206 for (;;) {
1207 _cleanup_free_ char *w = NULL, *idna = NULL;
1208
1209 r = extract_first_word(&p, &w, NULL, 0);
1210 if (r == -ENOMEM)
1211 return log_oom();
1212 if (r < 0) {
1213 log_syntax(unit, LOG_ERR, filename, line, r,
1214 "Failed to extract word, ignoring: %s", rvalue);
1215 return 0;
1216 }
1217 if (r == 0)
1218 break;
1219
1220 r = dns_name_apply_idna(w, &idna);
1221 if (r < 0) {
1222 log_syntax(unit, LOG_ERR, filename, line, r,
1223 "Failed to apply IDNA to domain name '%s', ignoring: %m", w);
1224 continue;
1225 } else if (r == 0)
1226 /* transfer ownership to simplify subsequent operations */
1227 idna = TAKE_PTR(w);
1228
1229 r = ordered_set_ensure_allocated(&n->router_search_domains, &string_hash_ops);
1230 if (r < 0)
1231 return r;
1232
1233 r = ordered_set_consume(n->router_search_domains, TAKE_PTR(idna));
1234 if (r < 0)
1235 return r;
1236 }
1237
1238 return 0;
1239 }
1240
1241 int config_parse_dhcp_server_ntp(
1242 const char *unit,
1243 const char *filename,
1244 unsigned line,
1245 const char *section,
1246 unsigned section_line,
1247 const char *lvalue,
1248 int ltype,
1249 const char *rvalue,
1250 void *data,
1251 void *userdata) {
1252
1253 Network *n = data;
1254 const char *p = rvalue;
1255 int r;
1256
1257 assert(filename);
1258 assert(lvalue);
1259 assert(rvalue);
1260
1261 for (;;) {
1262 _cleanup_free_ char *w = NULL;
1263 union in_addr_union a;
1264 struct in_addr *m;
1265
1266 r = extract_first_word(&p, &w, NULL, 0);
1267 if (r == -ENOMEM)
1268 return log_oom();
1269 if (r < 0) {
1270 log_syntax(unit, LOG_ERR, filename, line, r,
1271 "Failed to extract word, ignoring: %s", rvalue);
1272 return 0;
1273 }
1274 if (r == 0)
1275 return 0;
1276
1277 r = in_addr_from_string(AF_INET, w, &a);
1278 if (r < 0) {
1279 log_syntax(unit, LOG_ERR, filename, line, r,
1280 "Failed to parse NTP server address '%s', ignoring: %m", w);
1281 continue;
1282 }
1283
1284 m = reallocarray(n->dhcp_server_ntp, n->n_dhcp_server_ntp + 1, sizeof(struct in_addr));
1285 if (!m)
1286 return log_oom();
1287
1288 m[n->n_dhcp_server_ntp++] = a.in;
1289 n->dhcp_server_ntp = m;
1290 }
1291 }
1292
1293 int config_parse_dns(
1294 const char *unit,
1295 const char *filename,
1296 unsigned line,
1297 const char *section,
1298 unsigned section_line,
1299 const char *lvalue,
1300 int ltype,
1301 const char *rvalue,
1302 void *data,
1303 void *userdata) {
1304
1305 Network *n = userdata;
1306 int r;
1307
1308 assert(filename);
1309 assert(lvalue);
1310 assert(rvalue);
1311
1312 for (;;) {
1313 _cleanup_free_ char *w = NULL;
1314 union in_addr_union a;
1315 struct in_addr_data *m;
1316 int family;
1317
1318 r = extract_first_word(&rvalue, &w, NULL, 0);
1319 if (r == -ENOMEM)
1320 return log_oom();
1321 if (r < 0) {
1322 log_syntax(unit, LOG_ERR, filename, line, r,
1323 "Invalid syntax, ignoring: %s", rvalue);
1324 break;
1325 }
1326 if (r == 0)
1327 break;
1328
1329 r = in_addr_from_string_auto(w, &family, &a);
1330 if (r < 0) {
1331 log_syntax(unit, LOG_ERR, filename, line, r,
1332 "Failed to parse dns server address, ignoring: %s", w);
1333 continue;
1334 }
1335
1336 m = reallocarray(n->dns, n->n_dns + 1, sizeof(struct in_addr_data));
1337 if (!m)
1338 return log_oom();
1339
1340 m[n->n_dns++] = (struct in_addr_data) {
1341 .family = family,
1342 .address = a,
1343 };
1344
1345 n->dns = m;
1346 }
1347
1348 return 0;
1349 }
1350
1351 int config_parse_dnssec_negative_trust_anchors(
1352 const char *unit,
1353 const char *filename,
1354 unsigned line,
1355 const char *section,
1356 unsigned section_line,
1357 const char *lvalue,
1358 int ltype,
1359 const char *rvalue,
1360 void *data,
1361 void *userdata) {
1362
1363 const char *p = rvalue;
1364 Network *n = data;
1365 int r;
1366
1367 assert(n);
1368 assert(lvalue);
1369 assert(rvalue);
1370
1371 if (isempty(rvalue)) {
1372 n->dnssec_negative_trust_anchors = set_free_free(n->dnssec_negative_trust_anchors);
1373 return 0;
1374 }
1375
1376 for (;;) {
1377 _cleanup_free_ char *w = NULL;
1378
1379 r = extract_first_word(&p, &w, NULL, 0);
1380 if (r < 0) {
1381 log_syntax(unit, LOG_ERR, filename, line, r,
1382 "Failed to extract negative trust anchor domain, ignoring: %s", rvalue);
1383 break;
1384 }
1385 if (r == 0)
1386 break;
1387
1388 r = dns_name_is_valid(w);
1389 if (r <= 0) {
1390 log_syntax(unit, LOG_ERR, filename, line, r,
1391 "%s is not a valid domain name, ignoring.", w);
1392 continue;
1393 }
1394
1395 r = set_ensure_allocated(&n->dnssec_negative_trust_anchors, &dns_name_hash_ops);
1396 if (r < 0)
1397 return log_oom();
1398
1399 r = set_put(n->dnssec_negative_trust_anchors, w);
1400 if (r < 0)
1401 return log_oom();
1402 if (r > 0)
1403 w = NULL;
1404 }
1405
1406 return 0;
1407 }
1408
1409 int config_parse_ntp(
1410 const char *unit,
1411 const char *filename,
1412 unsigned line,
1413 const char *section,
1414 unsigned section_line,
1415 const char *lvalue,
1416 int ltype,
1417 const char *rvalue,
1418 void *data,
1419 void *userdata) {
1420
1421 char ***l = data;
1422 int r;
1423
1424 assert(l);
1425 assert(lvalue);
1426 assert(rvalue);
1427
1428 if (isempty(rvalue)) {
1429 *l = strv_free(*l);
1430 return 0;
1431 }
1432
1433 for (;;) {
1434 _cleanup_free_ char *w = NULL;
1435
1436 r = extract_first_word(&rvalue, &w, NULL, 0);
1437 if (r == -ENOMEM)
1438 return log_oom();
1439 if (r < 0) {
1440 log_syntax(unit, LOG_ERR, filename, line, r,
1441 "Failed to extract NTP server name, ignoring: %s", rvalue);
1442 break;
1443 }
1444 if (r == 0)
1445 break;
1446
1447 r = dns_name_is_valid_or_address(w);
1448 if (r <= 0) {
1449 log_syntax(unit, LOG_ERR, filename, line, r,
1450 "%s is not a valid domain name or IP address, ignoring.", w);
1451 continue;
1452 }
1453
1454 if (strv_length(*l) > MAX_NTP_SERVERS) {
1455 log_syntax(unit, LOG_WARNING, filename, line, 0,
1456 "More than %u NTP servers specified, ignoring \"%s\" and any subsequent entries.",
1457 MAX_NTP_SERVERS, w);
1458 break;
1459 }
1460
1461 r = strv_consume(l, TAKE_PTR(w));
1462 if (r < 0)
1463 return log_oom();
1464 }
1465
1466 return 0;
1467 }
1468
1469 int config_parse_dhcp_user_class(
1470 const char *unit,
1471 const char *filename,
1472 unsigned line,
1473 const char *section,
1474 unsigned section_line,
1475 const char *lvalue,
1476 int ltype,
1477 const char *rvalue,
1478 void *data,
1479 void *userdata) {
1480
1481 char ***l = data;
1482 int r;
1483
1484 assert(l);
1485 assert(lvalue);
1486 assert(rvalue);
1487
1488 if (isempty(rvalue)) {
1489 *l = strv_free(*l);
1490 return 0;
1491 }
1492
1493 for (;;) {
1494 _cleanup_free_ char *w = NULL;
1495
1496 r = extract_first_word(&rvalue, &w, NULL, 0);
1497 if (r == -ENOMEM)
1498 return log_oom();
1499 if (r < 0) {
1500 log_syntax(unit, LOG_ERR, filename, line, r,
1501 "Failed to split user classes option, ignoring: %s", rvalue);
1502 break;
1503 }
1504 if (r == 0)
1505 break;
1506
1507 if (strlen(w) > 255) {
1508 log_syntax(unit, LOG_ERR, filename, line, 0,
1509 "%s length is not in the range 1-255, ignoring.", w);
1510 continue;
1511 }
1512
1513 r = strv_push(l, w);
1514 if (r < 0)
1515 return log_oom();
1516
1517 w = NULL;
1518 }
1519
1520 return 0;
1521 }
1522
1523 int config_parse_section_route_table(
1524 const char *unit,
1525 const char *filename,
1526 unsigned line,
1527 const char *section,
1528 unsigned section_line,
1529 const char *lvalue,
1530 int ltype,
1531 const char *rvalue,
1532 void *data,
1533 void *userdata) {
1534
1535 Network *network = data;
1536 uint32_t rt;
1537 int r;
1538
1539 assert(filename);
1540 assert(lvalue);
1541 assert(rvalue);
1542 assert(data);
1543
1544 r = safe_atou32(rvalue, &rt);
1545 if (r < 0) {
1546 log_syntax(unit, LOG_ERR, filename, line, r,
1547 "Failed to parse RouteTable=%s, ignoring assignment: %m", rvalue);
1548 return 0;
1549 }
1550
1551 if (streq_ptr(section, "DHCP")) {
1552 network->dhcp_route_table = rt;
1553 network->dhcp_route_table_set = true;
1554 } else { /* section is IPv6AcceptRA */
1555 network->ipv6_accept_ra_route_table = rt;
1556 network->ipv6_accept_ra_route_table_set = true;
1557 }
1558
1559 return 0;
1560 }
1561
1562 int config_parse_dhcp_max_attempts(
1563 const char *unit,
1564 const char *filename,
1565 unsigned line,
1566 const char *section,
1567 unsigned section_line,
1568 const char *lvalue,
1569 int ltype,
1570 const char *rvalue,
1571 void *data,
1572 void *userdata) {
1573
1574 Network *network = data;
1575 uint64_t a;
1576 int r;
1577
1578 assert(network);
1579 assert(lvalue);
1580 assert(rvalue);
1581
1582 if (isempty(rvalue)) {
1583 network->dhcp_max_attempts = 0;
1584 return 0;
1585 }
1586
1587 if (streq(rvalue, "infinity")) {
1588 network->dhcp_max_attempts = (uint64_t) -1;
1589 return 0;
1590 }
1591
1592 r = safe_atou64(rvalue, &a);
1593 if (r < 0) {
1594 log_syntax(unit, LOG_ERR, filename, line, r,
1595 "Failed to parse DHCP maximum attempts, ignoring: %s", rvalue);
1596 return 0;
1597 }
1598
1599 if (a == 0) {
1600 log_syntax(unit, LOG_ERR, filename, line, 0,
1601 "%s= must be positive integer or 'infinity', ignoring: %s", lvalue, rvalue);
1602 return 0;
1603 }
1604
1605 network->dhcp_max_attempts = a;
1606
1607 return 0;
1608 }
1609
1610 int config_parse_dhcp_black_listed_ip_address(
1611 const char *unit,
1612 const char *filename,
1613 unsigned line,
1614 const char *section,
1615 unsigned section_line,
1616 const char *lvalue,
1617 int ltype,
1618 const char *rvalue,
1619 void *data,
1620 void *userdata) {
1621
1622 Network *network = data;
1623 const char *p;
1624 int r;
1625
1626 assert(filename);
1627 assert(lvalue);
1628 assert(rvalue);
1629 assert(data);
1630
1631 if (isempty(rvalue)) {
1632 network->dhcp_black_listed_ip = set_free(network->dhcp_black_listed_ip);
1633 return 0;
1634 }
1635
1636 for (p = rvalue;;) {
1637 _cleanup_free_ char *n = NULL;
1638 union in_addr_union ip;
1639
1640 r = extract_first_word(&p, &n, NULL, 0);
1641 if (r < 0) {
1642 log_syntax(unit, LOG_ERR, filename, line, r,
1643 "Failed to parse DHCP black listed ip address, ignoring assignment: %s",
1644 rvalue);
1645 return 0;
1646 }
1647 if (r == 0)
1648 return 0;
1649
1650 r = in_addr_from_string(AF_INET, n, &ip);
1651 if (r < 0) {
1652 log_syntax(unit, LOG_ERR, filename, line, r,
1653 "DHCP black listed ip address is invalid, ignoring assignment: %s", n);
1654 continue;
1655 }
1656
1657 r = set_ensure_allocated(&network->dhcp_black_listed_ip, NULL);
1658 if (r < 0)
1659 return log_oom();
1660
1661 r = set_put(network->dhcp_black_listed_ip, UINT32_TO_PTR(ip.in.s_addr));
1662 if (r < 0)
1663 log_syntax(unit, LOG_ERR, filename, line, r,
1664 "Failed to store DHCP black listed ip address '%s', ignoring assignment: %m", n);
1665 }
1666
1667 return 0;
1668 }
1669
1670 DEFINE_CONFIG_PARSE_ENUM(config_parse_dhcp_use_domains, dhcp_use_domains, DHCPUseDomains,
1671 "Failed to parse DHCP use domains setting");
1672
1673 static const char* const dhcp_use_domains_table[_DHCP_USE_DOMAINS_MAX] = {
1674 [DHCP_USE_DOMAINS_NO] = "no",
1675 [DHCP_USE_DOMAINS_ROUTE] = "route",
1676 [DHCP_USE_DOMAINS_YES] = "yes",
1677 };
1678
1679 DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(dhcp_use_domains, DHCPUseDomains, DHCP_USE_DOMAINS_YES);
1680
1681 int config_parse_iaid(const char *unit,
1682 const char *filename,
1683 unsigned line,
1684 const char *section,
1685 unsigned section_line,
1686 const char *lvalue,
1687 int ltype,
1688 const char *rvalue,
1689 void *data,
1690 void *userdata) {
1691 Network *network = data;
1692 uint32_t iaid;
1693 int r;
1694
1695 assert(filename);
1696 assert(lvalue);
1697 assert(rvalue);
1698 assert(network);
1699
1700 r = safe_atou32(rvalue, &iaid);
1701 if (r < 0) {
1702 log_syntax(unit, LOG_ERR, filename, line, r,
1703 "Unable to read IAID, ignoring assignment: %s", rvalue);
1704 return 0;
1705 }
1706
1707 network->iaid = iaid;
1708 network->iaid_set = true;
1709
1710 return 0;
1711 }
1712
1713 int config_parse_required_for_online(
1714 const char *unit,
1715 const char *filename,
1716 unsigned line,
1717 const char *section,
1718 unsigned section_line,
1719 const char *lvalue,
1720 int ltype,
1721 const char *rvalue,
1722 void *data,
1723 void *userdata) {
1724
1725 Network *network = data;
1726 LinkOperationalState s;
1727 bool required = true;
1728 int r;
1729
1730 if (isempty(rvalue)) {
1731 network->required_for_online = true;
1732 network->required_operstate_for_online = LINK_OPERSTATE_DEGRADED;
1733 return 0;
1734 }
1735
1736 s = link_operstate_from_string(rvalue);
1737 if (s < 0) {
1738 r = parse_boolean(rvalue);
1739 if (r < 0) {
1740 log_syntax(unit, LOG_ERR, filename, line, r,
1741 "Failed to parse %s= setting, ignoring assignment: %s",
1742 lvalue, rvalue);
1743 return 0;
1744 }
1745
1746 required = r;
1747 s = LINK_OPERSTATE_DEGRADED;
1748 }
1749
1750 network->required_for_online = required;
1751 network->required_operstate_for_online = s;
1752
1753 return 0;
1754 }