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