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