]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/network/networkd-network.c
36d01283c0cb755b1fa5454cbf55a4ba17f0e5e6
[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 #include <unistd.h>
7
8 #include "alloc-util.h"
9 #include "conf-files.h"
10 #include "conf-parser.h"
11 #include "dns-domain.h"
12 #include "fd-util.h"
13 #include "hostname-util.h"
14 #include "in-addr-util.h"
15 #include "networkd-dhcp-server.h"
16 #include "network-internal.h"
17 #include "networkd-manager.h"
18 #include "networkd-network.h"
19 #include "networkd-sriov.h"
20 #include "parse-util.h"
21 #include "path-lookup.h"
22 #include "set.h"
23 #include "socket-util.h"
24 #include "stat-util.h"
25 #include "string-table.h"
26 #include "string-util.h"
27 #include "strv.h"
28 #include "tc.h"
29 #include "util.h"
30
31 /* Let's assume that anything above this number is a user misconfiguration. */
32 #define MAX_NTP_SERVERS 128
33
34 /* Set defaults following RFC7844 */
35 void network_apply_anonymize_if_set(Network *network) {
36 if (!network->dhcp_anonymize)
37 return;
38 /* RFC7844 3.7
39 SHOULD NOT send the Host Name option */
40 network->dhcp_send_hostname = false;
41 /* RFC7844 section 3.:
42 MAY contain the Client Identifier option
43 Section 3.5:
44 clients MUST use client identifiers based solely
45 on the link-layer address */
46 /* NOTE: Using MAC, as it does not reveal extra information,
47 * and some servers might not answer if this option is not sent */
48 network->dhcp_client_identifier = DHCP_CLIENT_ID_MAC;
49 /* RFC 7844 3.10:
50 SHOULD NOT use the Vendor Class Identifier option */
51 network->dhcp_vendor_class_identifier = mfree(network->dhcp_vendor_class_identifier);
52 /* RFC7844 section 3.6.:
53 The client intending to protect its privacy SHOULD only request a
54 minimal number of options in the PRL and SHOULD also randomly shuffle
55 the ordering of option codes in the PRL. If this random ordering
56 cannot be implemented, the client MAY order the option codes in the
57 PRL by option code number (lowest to highest).
58 */
59 /* NOTE: dhcp_use_mtu is false by default,
60 * though it was not initiallized to any value in network_load_one.
61 * Maybe there should be another var called *send*?
62 * (to use the MTU sent by the server but to do not send
63 * the option in the PRL). */
64 network->dhcp_use_mtu = false;
65 /* NOTE: when Anonymize=yes, the PRL route options are sent by default,
66 * but this is needed to use them. */
67 network->dhcp_use_routes = true;
68 /* RFC7844 section 3.6.
69 * same comments as previous option */
70 network->dhcp_use_timezone = false;
71 }
72
73 static int network_resolve_netdev_one(Network *network, const char *name, NetDevKind kind, NetDev **ret_netdev) {
74 const char *kind_string;
75 NetDev *netdev;
76 int r;
77
78 /* For test-networkd-conf, the check must be earlier than the assertions. */
79 if (!name)
80 return 0;
81
82 assert(network);
83 assert(network->manager);
84 assert(network->filename);
85 assert(ret_netdev);
86
87 if (kind == _NETDEV_KIND_TUNNEL)
88 kind_string = "tunnel";
89 else {
90 kind_string = netdev_kind_to_string(kind);
91 if (!kind_string)
92 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
93 "%s: Invalid NetDev kind of %s, ignoring assignment.",
94 network->filename, name);
95 }
96
97 r = netdev_get(network->manager, name, &netdev);
98 if (r < 0)
99 return log_error_errno(r, "%s: %s NetDev could not be found, ignoring assignment.",
100 network->filename, name);
101
102 if (netdev->kind != kind && !(kind == _NETDEV_KIND_TUNNEL &&
103 IN_SET(netdev->kind,
104 NETDEV_KIND_IPIP,
105 NETDEV_KIND_SIT,
106 NETDEV_KIND_GRE,
107 NETDEV_KIND_GRETAP,
108 NETDEV_KIND_IP6GRE,
109 NETDEV_KIND_IP6GRETAP,
110 NETDEV_KIND_VTI,
111 NETDEV_KIND_VTI6,
112 NETDEV_KIND_IP6TNL,
113 NETDEV_KIND_ERSPAN)))
114 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
115 "%s: NetDev %s is not a %s, ignoring assignment",
116 network->filename, name, kind_string);
117
118 *ret_netdev = netdev_ref(netdev);
119 return 1;
120 }
121
122 static int network_resolve_stacked_netdevs(Network *network) {
123 void *name, *kind;
124 int r;
125
126 assert(network);
127
128 HASHMAP_FOREACH_KEY(kind, name, network->stacked_netdev_names) {
129 _cleanup_(netdev_unrefp) NetDev *netdev = NULL;
130
131 r = network_resolve_netdev_one(network, name, PTR_TO_INT(kind), &netdev);
132 if (r <= 0)
133 continue;
134
135 r = hashmap_ensure_allocated(&network->stacked_netdevs, &string_hash_ops);
136 if (r < 0)
137 return log_oom();
138
139 r = hashmap_put(network->stacked_netdevs, netdev->ifname, netdev);
140 if (r < 0)
141 return log_error_errno(r, "%s: Failed to add NetDev '%s' to network: %m",
142 network->filename, (const char *) name);
143
144 netdev = NULL;
145 }
146
147 return 0;
148 }
149
150 int network_verify(Network *network) {
151 RoutePrefix *route_prefix, *route_prefix_next;
152 RoutingPolicyRule *rule, *rule_next;
153 Neighbor *neighbor, *neighbor_next;
154 AddressLabel *label, *label_next;
155 NextHop *nexthop, *nextnop_next;
156 Address *address, *address_next;
157 Prefix *prefix, *prefix_next;
158 Route *route, *route_next;
159 FdbEntry *fdb, *fdb_next;
160 MdbEntry *mdb, *mdb_next;
161 TrafficControl *tc;
162 SRIOV *sr_iov;
163
164 assert(network);
165 assert(network->filename);
166
167 if (set_isempty(network->match_mac) && set_isempty(network->match_permanent_mac) &&
168 strv_isempty(network->match_path) && strv_isempty(network->match_driver) &&
169 strv_isempty(network->match_type) && strv_isempty(network->match_name) &&
170 strv_isempty(network->match_property) && strv_isempty(network->match_wlan_iftype) &&
171 strv_isempty(network->match_ssid) && !network->conditions)
172 return log_warning_errno(SYNTHETIC_ERRNO(EINVAL),
173 "%s: No valid settings found in the [Match] section, ignoring file. "
174 "To match all interfaces, add Name=* in the [Match] section.",
175 network->filename);
176
177 /* skip out early if configuration does not match the environment */
178 if (!condition_test_list(network->conditions, environ, NULL, NULL, NULL))
179 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL),
180 "%s: Conditions in the file do not match the system environment, skipping.",
181 network->filename);
182
183 (void) network_resolve_netdev_one(network, network->bond_name, NETDEV_KIND_BOND, &network->bond);
184 (void) network_resolve_netdev_one(network, network->bridge_name, NETDEV_KIND_BRIDGE, &network->bridge);
185 (void) network_resolve_netdev_one(network, network->vrf_name, NETDEV_KIND_VRF, &network->vrf);
186 (void) network_resolve_stacked_netdevs(network);
187
188 /* Free unnecessary entries. */
189 network->bond_name = mfree(network->bond_name);
190 network->bridge_name = mfree(network->bridge_name);
191 network->vrf_name = mfree(network->vrf_name);
192 network->stacked_netdev_names = hashmap_free_free_key(network->stacked_netdev_names);
193
194 if (network->bond) {
195 /* Bonding slave does not support addressing. */
196 if (network->ipv6_accept_ra > 0) {
197 log_warning("%s: Cannot enable IPv6AcceptRA= when Bond= is specified, disabling IPv6AcceptRA=.",
198 network->filename);
199 network->ipv6_accept_ra = 0;
200 }
201 if (network->link_local >= 0 && network->link_local != ADDRESS_FAMILY_NO) {
202 log_warning("%s: Cannot enable LinkLocalAddressing= when Bond= is specified, disabling LinkLocalAddressing=.",
203 network->filename);
204 network->link_local = ADDRESS_FAMILY_NO;
205 }
206 if (network->dhcp != ADDRESS_FAMILY_NO) {
207 log_warning("%s: Cannot enable DHCP= when Bond= is specified, disabling DHCP=.",
208 network->filename);
209 network->dhcp = ADDRESS_FAMILY_NO;
210 }
211 if (network->dhcp_server) {
212 log_warning("%s: Cannot enable DHCPServer= when Bond= is specified, disabling DHCPServer=.",
213 network->filename);
214 network->dhcp_server = false;
215 }
216 if (network->n_static_addresses > 0) {
217 log_warning("%s: Cannot set addresses when Bond= is specified, ignoring addresses.",
218 network->filename);
219 while ((address = network->static_addresses))
220 address_free(address);
221 }
222 if (network->n_static_routes > 0) {
223 log_warning("%s: Cannot set routes when Bond= is specified, ignoring routes.",
224 network->filename);
225 while ((route = network->static_routes))
226 route_free(route);
227 }
228 }
229
230 if (network->link_local < 0)
231 network->link_local = network->bridge ? ADDRESS_FAMILY_NO : ADDRESS_FAMILY_IPV6;
232
233 if (!FLAGS_SET(network->link_local, ADDRESS_FAMILY_IPV6)) {
234 if (network->ipv6_accept_ra > 0) {
235 log_warning("%s: IPv6AcceptRA= is enabled by the .network file but IPv6 link local addressing is disabled. "
236 "Disabling IPv6AcceptRA=.", network->filename);
237 network->ipv6_accept_ra = false;
238 }
239
240 if (FLAGS_SET(network->dhcp, ADDRESS_FAMILY_IPV6)) {
241 log_warning("%s: DHCPv6 client is enabled by the .network file but IPv6 link local addressing is disabled. "
242 "Disabling DHCPv6 client.", network->filename);
243 SET_FLAG(network->dhcp, ADDRESS_FAMILY_IPV6, false);
244 }
245
246 if (network->router_prefix_delegation != RADV_PREFIX_DELEGATION_NONE) {
247 log_warning("%s: IPv6PrefixDelegation= is enabled but IPv6 link local addressing is disabled. "
248 "Disabling IPv6PrefixDelegation=.", network->filename);
249 network->router_prefix_delegation = RADV_PREFIX_DELEGATION_NONE;
250 }
251 }
252
253 if (FLAGS_SET(network->link_local, ADDRESS_FAMILY_FALLBACK_IPV4) &&
254 !FLAGS_SET(network->dhcp, ADDRESS_FAMILY_IPV4)) {
255 log_warning("%s: fallback assignment of IPv4 link local address is enabled but DHCPv4 is disabled. "
256 "Disabling the fallback assignment.", network->filename);
257 SET_FLAG(network->link_local, ADDRESS_FAMILY_FALLBACK_IPV4, false);
258 }
259
260 if (network->ipv6_accept_ra < 0 && network->bridge)
261 network->ipv6_accept_ra = false;
262
263 /* IPMasquerade=yes implies IPForward=yes */
264 if (network->ip_masquerade)
265 network->ip_forward |= ADDRESS_FAMILY_IPV4;
266
267 if (network->mtu > 0 && network->dhcp_use_mtu) {
268 log_warning("%s: MTUBytes= in [Link] section and UseMTU= in [DHCP] section are set. "
269 "Disabling UseMTU=.", network->filename);
270 network->dhcp_use_mtu = false;
271 }
272
273 if (network->dhcp_use_gateway < 0)
274 network->dhcp_use_gateway = network->dhcp_use_routes;
275
276 if (network->ignore_carrier_loss < 0)
277 network->ignore_carrier_loss = network->configure_without_carrier;
278
279 if (network->dhcp_critical >= 0) {
280 if (network->keep_configuration >= 0)
281 log_warning("%s: Both KeepConfiguration= and deprecated CriticalConnection= are set. "
282 "Ignoring CriticalConnection=.", network->filename);
283 else if (network->dhcp_critical)
284 /* CriticalConnection=yes also preserve foreign static configurations. */
285 network->keep_configuration = KEEP_CONFIGURATION_YES;
286 else
287 network->keep_configuration = KEEP_CONFIGURATION_NO;
288 }
289
290 if (network->keep_configuration < 0)
291 network->keep_configuration = KEEP_CONFIGURATION_NO;
292
293 LIST_FOREACH_SAFE(addresses, address, address_next, network->static_addresses)
294 if (address_section_verify(address) < 0)
295 address_free(address);
296
297 LIST_FOREACH_SAFE(routes, route, route_next, network->static_routes)
298 if (route_section_verify(route, network) < 0)
299 route_free(route);
300
301 LIST_FOREACH_SAFE(nexthops, nexthop, nextnop_next, network->static_nexthops)
302 if (nexthop_section_verify(nexthop) < 0)
303 nexthop_free(nexthop);
304
305 LIST_FOREACH_SAFE(static_fdb_entries, fdb, fdb_next, network->static_fdb_entries)
306 if (section_is_invalid(fdb->section))
307 fdb_entry_free(fdb);
308
309 if (!LIST_IS_EMPTY(network->static_mdb_entries) && !network->bridge) {
310 log_warning("%s: Cannot configure MDB entries on non-bridge port, ignoring [BridgeMDB] sections.",
311 network->filename);
312
313 while ((mdb = network->static_mdb_entries))
314 mdb_entry_free(mdb);
315 }
316
317 LIST_FOREACH_SAFE(static_mdb_entries, mdb, mdb_next, network->static_mdb_entries)
318 if (mdb_entry_verify(mdb) < 0)
319 mdb_entry_free(mdb);
320
321 LIST_FOREACH_SAFE(neighbors, neighbor, neighbor_next, network->neighbors)
322 if (neighbor_section_verify(neighbor) < 0)
323 neighbor_free(neighbor);
324
325 LIST_FOREACH_SAFE(labels, label, label_next, network->address_labels)
326 if (section_is_invalid(label->section))
327 address_label_free(label);
328
329 LIST_FOREACH_SAFE(prefixes, prefix, prefix_next, network->static_prefixes)
330 if (section_is_invalid(prefix->section))
331 prefix_free(prefix);
332
333 LIST_FOREACH_SAFE(route_prefixes, route_prefix, route_prefix_next, network->static_route_prefixes)
334 if (section_is_invalid(route_prefix->section))
335 route_prefix_free(route_prefix);
336
337 LIST_FOREACH_SAFE(rules, rule, rule_next, network->rules)
338 if (routing_policy_rule_section_verify(rule) < 0)
339 routing_policy_rule_free(rule);
340
341 bool has_root = false, has_clsact = false;
342 ORDERED_HASHMAP_FOREACH(tc, network->tc_by_section)
343 if (traffic_control_section_verify(tc, &has_root, &has_clsact) < 0)
344 traffic_control_free(tc);
345
346 ORDERED_HASHMAP_FOREACH(sr_iov, network->sr_iov_by_section)
347 if (sr_iov_section_verify(sr_iov) < 0)
348 sr_iov_free(sr_iov);
349
350 return 0;
351 }
352
353 int network_load_one(Manager *manager, OrderedHashmap **networks, const char *filename) {
354 _cleanup_free_ char *fname = NULL, *name = NULL;
355 _cleanup_(network_unrefp) Network *network = NULL;
356 _cleanup_fclose_ FILE *file = NULL;
357 const char *dropin_dirname;
358 char *d;
359 int r;
360
361 assert(manager);
362 assert(filename);
363
364 file = fopen(filename, "re");
365 if (!file) {
366 if (errno == ENOENT)
367 return 0;
368
369 return -errno;
370 }
371
372 if (null_or_empty_fd(fileno(file))) {
373 log_debug("Skipping empty file: %s", filename);
374 return 0;
375 }
376
377 fname = strdup(filename);
378 if (!fname)
379 return log_oom();
380
381 name = strdup(basename(filename));
382 if (!name)
383 return log_oom();
384
385 d = strrchr(name, '.');
386 if (!d)
387 return -EINVAL;
388
389 *d = '\0';
390
391 dropin_dirname = strjoina(name, ".network.d");
392
393 network = new(Network, 1);
394 if (!network)
395 return log_oom();
396
397 *network = (Network) {
398 .filename = TAKE_PTR(fname),
399 .name = TAKE_PTR(name),
400
401 .manager = manager,
402 .n_ref = 1,
403
404 .required_for_online = true,
405 .required_operstate_for_online = LINK_OPERSTATE_RANGE_DEFAULT,
406 .dhcp = ADDRESS_FAMILY_NO,
407 .dhcp_critical = -1,
408 .dhcp_use_ntp = true,
409 .dhcp_use_sip = true,
410 .dhcp_use_dns = true,
411 .dhcp_use_hostname = true,
412 .dhcp_use_routes = true,
413 .dhcp_use_gateway = -1,
414 /* NOTE: this var might be overwritten by network_apply_anonymize_if_set */
415 .dhcp_send_hostname = true,
416 .dhcp_send_release = true,
417 /* To enable/disable RFC7844 Anonymity Profiles */
418 .dhcp_anonymize = false,
419 .dhcp_route_metric = DHCP_ROUTE_METRIC,
420 /* NOTE: this var might be overwritten by network_apply_anonymize_if_set */
421 .dhcp_client_identifier = DHCP_CLIENT_ID_DUID,
422 .dhcp_route_table = RT_TABLE_MAIN,
423 .dhcp_route_table_set = false,
424 /* NOTE: from man: UseMTU=... Defaults to false*/
425 .dhcp_use_mtu = false,
426 /* NOTE: from man: UseTimezone=... Defaults to "no".*/
427 .dhcp_use_timezone = false,
428 .rapid_commit = true,
429
430 .dhcp6_route_metric = DHCP_ROUTE_METRIC,
431 .dhcp6_use_ntp = true,
432 .dhcp6_use_dns = true,
433
434 .dhcp6_pd_subnet_id = -1,
435 .dhcp6_pd_assign = true,
436
437 .dhcp_server_emit[SD_DHCP_LEASE_DNS].emit = true,
438 .dhcp_server_emit[SD_DHCP_LEASE_NTP].emit = true,
439 .dhcp_server_emit[SD_DHCP_LEASE_SIP].emit = true,
440
441 .dhcp_server_emit_router = true,
442 .dhcp_server_emit_timezone = true,
443
444 .router_emit_dns = true,
445 .router_emit_domains = true,
446
447 .use_bpdu = -1,
448 .hairpin = -1,
449 .fast_leave = -1,
450 .allow_port_to_be_root = -1,
451 .unicast_flood = -1,
452 .multicast_flood = -1,
453 .multicast_to_unicast = -1,
454 .neighbor_suppression = -1,
455 .learning = -1,
456 .bridge_proxy_arp = -1,
457 .bridge_proxy_arp_wifi = -1,
458 .priority = LINK_BRIDGE_PORT_PRIORITY_INVALID,
459 .multicast_router = _MULTICAST_ROUTER_INVALID,
460
461 .lldp_mode = LLDP_MODE_ROUTERS_ONLY,
462
463 .dns_default_route = -1,
464 .llmnr = RESOLVE_SUPPORT_YES,
465 .mdns = RESOLVE_SUPPORT_NO,
466 .dnssec_mode = _DNSSEC_MODE_INVALID,
467 .dns_over_tls_mode = _DNS_OVER_TLS_MODE_INVALID,
468
469 /* If LinkLocalAddressing= is not set, then set to ADDRESS_FAMILY_IPV6 later. */
470 .link_local = _ADDRESS_FAMILY_INVALID,
471 .ipv6ll_address_gen_mode = _IPV6_LINK_LOCAL_ADDRESS_GEN_MODE_INVALID,
472
473 .ipv4_accept_local = -1,
474
475 .ipv6_privacy_extensions = IPV6_PRIVACY_EXTENSIONS_NO,
476 .ipv6_accept_ra = -1,
477 .ipv6_dad_transmits = -1,
478 .ipv6_hop_limit = -1,
479 .ipv6_proxy_ndp = -1,
480 .duid.type = _DUID_TYPE_INVALID,
481 .proxy_arp = -1,
482 .arp = -1,
483 .multicast = -1,
484 .allmulticast = -1,
485 .ipv6_accept_ra_use_dns = true,
486 .ipv6_accept_ra_use_autonomous_prefix = true,
487 .ipv6_accept_ra_use_onlink_prefix = true,
488 .ipv6_accept_ra_route_table = RT_TABLE_MAIN,
489 .ipv6_accept_ra_route_table_set = false,
490 .ipv6_accept_ra_start_dhcp6_client = true,
491
492 .configure_without_carrier = false,
493 .ignore_carrier_loss = -1,
494 .keep_configuration = _KEEP_CONFIGURATION_INVALID,
495 .can_triple_sampling = -1,
496 .can_termination = -1,
497 .can_listen_only = -1,
498 .can_fd_mode = -1,
499 .can_non_iso = -1,
500 .ip_service_type = -1,
501 };
502
503 r = config_parse_many(
504 filename, NETWORK_DIRS, dropin_dirname,
505 "Match\0"
506 "Link\0"
507 "SR-IOV\0"
508 "Network\0"
509 "Address\0"
510 "Neighbor\0"
511 "IPv6AddressLabel\0"
512 "RoutingPolicyRule\0"
513 "Route\0"
514 "NextHop\0"
515 "DHCP\0" /* compat */
516 "DHCPv4\0"
517 "DHCPv6\0"
518 "DHCPv6PrefixDelegation\0"
519 "DHCPServer\0"
520 "IPv6AcceptRA\0"
521 "IPv6NDPProxyAddress\0"
522 "Bridge\0"
523 "BridgeFDB\0"
524 "BridgeMDB\0"
525 "BridgeVLAN\0"
526 "IPv6PrefixDelegation\0"
527 "IPv6Prefix\0"
528 "IPv6RoutePrefix\0"
529 "LLDP\0"
530 "TrafficControlQueueingDiscipline\0"
531 "CAN\0"
532 "QDisc\0"
533 "BFIFO\0"
534 "CAKE\0"
535 "ControlledDelay\0"
536 "DeficitRoundRobinScheduler\0"
537 "DeficitRoundRobinSchedulerClass\0"
538 "EnhancedTransmissionSelection\0"
539 "FairQueueing\0"
540 "FairQueueingControlledDelay\0"
541 "GenericRandomEarlyDetection\0"
542 "HeavyHitterFilter\0"
543 "HierarchyTokenBucket\0"
544 "HierarchyTokenBucketClass\0"
545 "NetworkEmulator\0"
546 "PFIFO\0"
547 "PFIFOFast\0"
548 "PFIFOHeadDrop\0"
549 "PIE\0"
550 "QuickFairQueueing\0"
551 "QuickFairQueueingClass\0"
552 "StochasticFairBlue\0"
553 "StochasticFairnessQueueing\0"
554 "TokenBucketFilter\0"
555 "TrivialLinkEqualizer\0",
556 config_item_perf_lookup, network_network_gperf_lookup,
557 CONFIG_PARSE_WARN,
558 network,
559 &network->timestamp);
560 if (r < 0)
561 return r;
562
563 network_apply_anonymize_if_set(network);
564
565 r = network_add_ipv4ll_route(network);
566 if (r < 0)
567 log_warning_errno(r, "%s: Failed to add IPv4LL route, ignoring: %m", network->filename);
568
569 r = network_add_default_route_on_device(network);
570 if (r < 0)
571 log_warning_errno(r, "%s: Failed to add default route on device, ignoring: %m",
572 network->filename);
573
574 if (network_verify(network) < 0)
575 /* Ignore .network files that do not match the conditions. */
576 return 0;
577
578 r = ordered_hashmap_ensure_allocated(networks, &string_hash_ops);
579 if (r < 0)
580 return r;
581
582 r = ordered_hashmap_put(*networks, network->name, network);
583 if (r < 0)
584 return r;
585
586 network = NULL;
587 return 0;
588 }
589
590 int network_load(Manager *manager, OrderedHashmap **networks) {
591 _cleanup_strv_free_ char **files = NULL;
592 char **f;
593 int r;
594
595 assert(manager);
596
597 ordered_hashmap_clear_with_destructor(*networks, network_unref);
598
599 r = conf_files_list_strv(&files, ".network", NULL, 0, NETWORK_DIRS);
600 if (r < 0)
601 return log_error_errno(r, "Failed to enumerate network files: %m");
602
603 STRV_FOREACH(f, files) {
604 r = network_load_one(manager, networks, *f);
605 if (r < 0)
606 log_error_errno(r, "Failed to load %s, ignoring: %m", *f);
607 }
608
609 return 0;
610 }
611
612 int network_reload(Manager *manager) {
613 OrderedHashmap *new_networks = NULL;
614 Network *n, *old;
615 int r;
616
617 assert(manager);
618
619 r = network_load(manager, &new_networks);
620 if (r < 0)
621 goto failure;
622
623 ORDERED_HASHMAP_FOREACH(n, new_networks) {
624 r = network_get_by_name(manager, n->name, &old);
625 if (r < 0)
626 continue; /* The .network file is new. */
627
628 if (n->timestamp != old->timestamp)
629 continue; /* The .network file is modified. */
630
631 if (!streq(n->filename, old->filename))
632 continue;
633
634 r = ordered_hashmap_replace(new_networks, old->name, old);
635 if (r < 0)
636 goto failure;
637
638 network_ref(old);
639 network_unref(n);
640 }
641
642 ordered_hashmap_free_with_destructor(manager->networks, network_unref);
643 manager->networks = new_networks;
644
645 return 0;
646
647 failure:
648 ordered_hashmap_free_with_destructor(new_networks, network_unref);
649
650 return r;
651 }
652
653 static Network *network_free(Network *network) {
654 IPv6ProxyNDPAddress *ipv6_proxy_ndp_address;
655 RoutePrefix *route_prefix;
656 RoutingPolicyRule *rule;
657 AddressLabel *label;
658 FdbEntry *fdb_entry;
659 MdbEntry *mdb_entry;
660 Neighbor *neighbor;
661 Address *address;
662 NextHop *nexthop;
663 Prefix *prefix;
664 Route *route;
665
666 if (!network)
667 return NULL;
668
669 free(network->filename);
670
671 set_free_free(network->match_mac);
672 set_free_free(network->match_permanent_mac);
673 strv_free(network->match_path);
674 strv_free(network->match_driver);
675 strv_free(network->match_type);
676 strv_free(network->match_name);
677 strv_free(network->match_property);
678 strv_free(network->match_wlan_iftype);
679 strv_free(network->match_ssid);
680 set_free_free(network->match_bssid);
681 condition_free_list(network->conditions);
682
683 free(network->description);
684 free(network->dhcp_vendor_class_identifier);
685 free(network->dhcp_mudurl);
686 strv_free(network->dhcp_user_class);
687 free(network->dhcp_hostname);
688 set_free(network->dhcp_deny_listed_ip);
689 set_free(network->dhcp_allow_listed_ip);
690 set_free(network->dhcp_request_options);
691 set_free(network->dhcp6_request_options);
692 free(network->mac);
693 free(network->dhcp6_mudurl);
694 strv_free(network->dhcp6_user_class);
695 strv_free(network->dhcp6_vendor_class);
696
697 if (network->dhcp_acd)
698 sd_ipv4acd_unref(network->dhcp_acd);
699
700 strv_free(network->ntp);
701 for (unsigned i = 0; i < network->n_dns; i++)
702 in_addr_full_free(network->dns[i]);
703 free(network->dns);
704 ordered_set_free_free(network->search_domains);
705 ordered_set_free_free(network->route_domains);
706 strv_free(network->bind_carrier);
707
708 ordered_set_free_free(network->router_search_domains);
709 free(network->router_dns);
710 set_free_free(network->ndisc_deny_listed_prefix);
711
712 free(network->bridge_name);
713 free(network->bond_name);
714 free(network->vrf_name);
715 hashmap_free_free_key(network->stacked_netdev_names);
716 netdev_unref(network->bridge);
717 netdev_unref(network->bond);
718 netdev_unref(network->vrf);
719 hashmap_free_with_destructor(network->stacked_netdevs, netdev_unref);
720
721 while ((route = network->static_routes))
722 route_free(route);
723
724 while ((nexthop = network->static_nexthops))
725 nexthop_free(nexthop);
726
727 while ((address = network->static_addresses))
728 address_free(address);
729
730 while ((fdb_entry = network->static_fdb_entries))
731 fdb_entry_free(fdb_entry);
732
733 while ((mdb_entry = network->static_mdb_entries))
734 mdb_entry_free(mdb_entry);
735
736 while ((ipv6_proxy_ndp_address = network->ipv6_proxy_ndp_addresses))
737 ipv6_proxy_ndp_address_free(ipv6_proxy_ndp_address);
738
739 while ((neighbor = network->neighbors))
740 neighbor_free(neighbor);
741
742 while ((label = network->address_labels))
743 address_label_free(label);
744
745 while ((prefix = network->static_prefixes))
746 prefix_free(prefix);
747
748 while ((route_prefix = network->static_route_prefixes))
749 route_prefix_free(route_prefix);
750
751 while ((rule = network->rules))
752 routing_policy_rule_free(rule);
753
754 hashmap_free(network->addresses_by_section);
755 hashmap_free(network->routes_by_section);
756 hashmap_free(network->nexthops_by_section);
757 hashmap_free(network->fdb_entries_by_section);
758 hashmap_free(network->mdb_entries_by_section);
759 hashmap_free(network->neighbors_by_section);
760 hashmap_free(network->address_labels_by_section);
761 hashmap_free(network->prefixes_by_section);
762 hashmap_free(network->route_prefixes_by_section);
763 hashmap_free(network->rules_by_section);
764 ordered_hashmap_free_with_destructor(network->sr_iov_by_section, sr_iov_free);
765 ordered_hashmap_free_with_destructor(network->tc_by_section, traffic_control_free);
766
767 if (network->manager &&
768 network->manager->duids_requesting_uuid)
769 set_remove(network->manager->duids_requesting_uuid, &network->duid);
770
771 free(network->name);
772
773 free(network->dhcp_server_timezone);
774
775 for (sd_dhcp_lease_server_type t = 0; t < _SD_DHCP_LEASE_SERVER_TYPE_MAX; t++)
776 free(network->dhcp_server_emit[t].addresses);
777
778 set_free_free(network->dnssec_negative_trust_anchors);
779
780 free(network->lldp_mud);
781
782 ordered_hashmap_free(network->dhcp_client_send_options);
783 ordered_hashmap_free(network->dhcp_client_send_vendor_options);
784 ordered_hashmap_free(network->dhcp_server_send_options);
785 ordered_hashmap_free(network->dhcp_server_send_vendor_options);
786 ordered_set_free(network->ipv6_tokens);
787 ordered_hashmap_free(network->dhcp6_client_send_options);
788 ordered_hashmap_free(network->dhcp6_client_send_vendor_options);
789
790 return mfree(network);
791 }
792
793 DEFINE_TRIVIAL_REF_UNREF_FUNC(Network, network, network_free);
794
795 int network_get_by_name(Manager *manager, const char *name, Network **ret) {
796 Network *network;
797
798 assert(manager);
799 assert(name);
800 assert(ret);
801
802 network = ordered_hashmap_get(manager->networks, name);
803 if (!network)
804 return -ENOENT;
805
806 *ret = network;
807
808 return 0;
809 }
810
811 int network_get(Manager *manager, unsigned short iftype, sd_device *device,
812 const char *ifname, char * const *alternative_names, const char *driver,
813 const struct ether_addr *mac, const struct ether_addr *permanent_mac,
814 enum nl80211_iftype wlan_iftype, const char *ssid, const struct ether_addr *bssid,
815 Network **ret) {
816 Network *network;
817
818 assert(manager);
819 assert(ret);
820
821 ORDERED_HASHMAP_FOREACH(network, manager->networks)
822 if (net_match_config(network->match_mac, network->match_permanent_mac,
823 network->match_path, network->match_driver,
824 network->match_type, network->match_name, network->match_property,
825 network->match_wlan_iftype, network->match_ssid, network->match_bssid,
826 device, mac, permanent_mac, driver, iftype,
827 ifname, alternative_names, wlan_iftype, ssid, bssid)) {
828 if (network->match_name && device) {
829 const char *attr;
830 uint8_t name_assign_type = NET_NAME_UNKNOWN;
831
832 if (sd_device_get_sysattr_value(device, "name_assign_type", &attr) >= 0)
833 (void) safe_atou8(attr, &name_assign_type);
834
835 if (name_assign_type == NET_NAME_ENUM)
836 log_warning("%s: found matching network '%s', based on potentially unpredictable ifname",
837 ifname, network->filename);
838 else
839 log_debug("%s: found matching network '%s'", ifname, network->filename);
840 } else
841 log_debug("%s: found matching network '%s'", ifname, network->filename);
842
843 *ret = network;
844 return 0;
845 }
846
847 *ret = NULL;
848
849 return -ENOENT;
850 }
851
852 int network_apply(Network *network, Link *link) {
853 assert(network);
854 assert(link);
855
856 link->network = network_ref(network);
857
858 if (network->n_dns > 0 ||
859 !strv_isempty(network->ntp) ||
860 !ordered_set_isempty(network->search_domains) ||
861 !ordered_set_isempty(network->route_domains))
862 link_dirty(link);
863
864 return 0;
865 }
866
867 bool network_has_static_ipv6_configurations(Network *network) {
868 Address *address;
869 Route *route;
870 FdbEntry *fdb;
871 MdbEntry *mdb;
872 Neighbor *neighbor;
873
874 assert(network);
875
876 LIST_FOREACH(addresses, address, network->static_addresses)
877 if (address->family == AF_INET6)
878 return true;
879
880 LIST_FOREACH(routes, route, network->static_routes)
881 if (route->family == AF_INET6)
882 return true;
883
884 LIST_FOREACH(static_fdb_entries, fdb, network->static_fdb_entries)
885 if (fdb->family == AF_INET6)
886 return true;
887
888 LIST_FOREACH(static_mdb_entries, mdb, network->static_mdb_entries)
889 if (mdb->family == AF_INET6)
890 return true;
891
892 LIST_FOREACH(neighbors, neighbor, network->neighbors)
893 if (neighbor->family == AF_INET6)
894 return true;
895
896 if (!LIST_IS_EMPTY(network->address_labels))
897 return true;
898
899 if (!LIST_IS_EMPTY(network->static_prefixes))
900 return true;
901
902 return false;
903 }
904
905 int config_parse_stacked_netdev(const char *unit,
906 const char *filename,
907 unsigned line,
908 const char *section,
909 unsigned section_line,
910 const char *lvalue,
911 int ltype,
912 const char *rvalue,
913 void *data,
914 void *userdata) {
915 _cleanup_free_ char *name = NULL;
916 NetDevKind kind = ltype;
917 Hashmap **h = data;
918 int r;
919
920 assert(filename);
921 assert(lvalue);
922 assert(rvalue);
923 assert(data);
924 assert(IN_SET(kind,
925 NETDEV_KIND_VLAN, NETDEV_KIND_MACVLAN, NETDEV_KIND_MACVTAP,
926 NETDEV_KIND_IPVLAN, NETDEV_KIND_IPVTAP, NETDEV_KIND_VXLAN,
927 NETDEV_KIND_L2TP, NETDEV_KIND_MACSEC, _NETDEV_KIND_TUNNEL,
928 NETDEV_KIND_XFRM));
929
930 if (!ifname_valid(rvalue)) {
931 log_syntax(unit, LOG_WARNING, filename, line, 0,
932 "Invalid netdev name in %s=, ignoring assignment: %s", lvalue, rvalue);
933 return 0;
934 }
935
936 name = strdup(rvalue);
937 if (!name)
938 return log_oom();
939
940 r = hashmap_ensure_allocated(h, &string_hash_ops);
941 if (r < 0)
942 return log_oom();
943
944 r = hashmap_put(*h, name, INT_TO_PTR(kind));
945 if (r < 0)
946 log_syntax(unit, LOG_WARNING, filename, line, r,
947 "Cannot add NetDev '%s' to network, ignoring assignment: %m", name);
948 else if (r == 0)
949 log_syntax(unit, LOG_DEBUG, filename, line, r,
950 "NetDev '%s' specified twice, ignoring.", name);
951 else
952 name = NULL;
953
954 return 0;
955 }
956
957 int config_parse_domains(
958 const char *unit,
959 const char *filename,
960 unsigned line,
961 const char *section,
962 unsigned section_line,
963 const char *lvalue,
964 int ltype,
965 const char *rvalue,
966 void *data,
967 void *userdata) {
968
969 Network *n = data;
970 int r;
971
972 assert(n);
973 assert(lvalue);
974 assert(rvalue);
975
976 if (isempty(rvalue)) {
977 n->search_domains = ordered_set_free_free(n->search_domains);
978 n->route_domains = ordered_set_free_free(n->route_domains);
979 return 0;
980 }
981
982 for (const char *p = rvalue;;) {
983 _cleanup_free_ char *w = NULL, *normalized = NULL;
984 const char *domain;
985 bool is_route;
986
987 r = extract_first_word(&p, &w, NULL, 0);
988 if (r == -ENOMEM)
989 return log_oom();
990 if (r < 0) {
991 log_syntax(unit, LOG_WARNING, filename, line, r,
992 "Failed to extract search or route domain, ignoring: %s", rvalue);
993 return 0;
994 }
995 if (r == 0)
996 return 0;
997
998 is_route = w[0] == '~';
999 domain = is_route ? w + 1 : w;
1000
1001 if (dns_name_is_root(domain) || streq(domain, "*")) {
1002 /* If the root domain appears as is, or the special token "*" is found, we'll
1003 * consider this as routing domain, unconditionally. */
1004 is_route = true;
1005 domain = "."; /* make sure we don't allow empty strings, thus write the root
1006 * domain as "." */
1007 } else {
1008 r = dns_name_normalize(domain, 0, &normalized);
1009 if (r < 0) {
1010 log_syntax(unit, LOG_WARNING, filename, line, r,
1011 "'%s' is not a valid domain name, ignoring.", domain);
1012 continue;
1013 }
1014
1015 domain = normalized;
1016
1017 if (is_localhost(domain)) {
1018 log_syntax(unit, LOG_WARNING, filename, line, 0,
1019 "'localhost' domain may not be configured as search or route domain, ignoring assignment: %s",
1020 domain);
1021 continue;
1022 }
1023 }
1024
1025 OrderedSet **set = is_route ? &n->route_domains : &n->search_domains;
1026 r = ordered_set_ensure_allocated(set, &string_hash_ops);
1027 if (r < 0)
1028 return log_oom();
1029
1030 r = ordered_set_put_strdup(*set, domain);
1031 if (r < 0)
1032 return log_oom();
1033 }
1034 }
1035
1036 int config_parse_ipv6token(
1037 const char* unit,
1038 const char *filename,
1039 unsigned line,
1040 const char *section,
1041 unsigned section_line,
1042 const char *lvalue,
1043 int ltype,
1044 const char *rvalue,
1045 void *data,
1046 void *userdata) {
1047
1048 union in_addr_union buffer;
1049 struct in6_addr *token = data;
1050 int r;
1051
1052 assert(filename);
1053 assert(lvalue);
1054 assert(rvalue);
1055 assert(token);
1056
1057 r = in_addr_from_string(AF_INET6, rvalue, &buffer);
1058 if (r < 0) {
1059 log_syntax(unit, LOG_WARNING, filename, line, r,
1060 "Failed to parse IPv6 token, ignoring: %s", rvalue);
1061 return 0;
1062 }
1063
1064 if (in_addr_is_null(AF_INET6, &buffer)) {
1065 log_syntax(unit, LOG_WARNING, filename, line, 0,
1066 "IPv6 token cannot be the ANY address, ignoring: %s", rvalue);
1067 return 0;
1068 }
1069
1070 if ((buffer.in6.s6_addr32[0] | buffer.in6.s6_addr32[1]) != 0) {
1071 log_syntax(unit, LOG_WARNING, filename, line, 0,
1072 "IPv6 token cannot be longer than 64 bits, ignoring: %s", rvalue);
1073 return 0;
1074 }
1075
1076 *token = buffer.in6;
1077
1078 return 0;
1079 }
1080
1081 static const char* const ipv6_privacy_extensions_table[_IPV6_PRIVACY_EXTENSIONS_MAX] = {
1082 [IPV6_PRIVACY_EXTENSIONS_NO] = "no",
1083 [IPV6_PRIVACY_EXTENSIONS_PREFER_PUBLIC] = "prefer-public",
1084 [IPV6_PRIVACY_EXTENSIONS_YES] = "yes",
1085 };
1086
1087 DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(ipv6_privacy_extensions, IPv6PrivacyExtensions,
1088 IPV6_PRIVACY_EXTENSIONS_YES);
1089
1090 int config_parse_ipv6_privacy_extensions(
1091 const char* unit,
1092 const char *filename,
1093 unsigned line,
1094 const char *section,
1095 unsigned section_line,
1096 const char *lvalue,
1097 int ltype,
1098 const char *rvalue,
1099 void *data,
1100 void *userdata) {
1101
1102 IPv6PrivacyExtensions s, *ipv6_privacy_extensions = data;
1103
1104 assert(filename);
1105 assert(lvalue);
1106 assert(rvalue);
1107 assert(ipv6_privacy_extensions);
1108
1109 s = ipv6_privacy_extensions_from_string(rvalue);
1110 if (s < 0) {
1111 if (streq(rvalue, "kernel"))
1112 s = _IPV6_PRIVACY_EXTENSIONS_INVALID;
1113 else {
1114 log_syntax(unit, LOG_WARNING, filename, line, 0,
1115 "Failed to parse IPv6 privacy extensions option, ignoring: %s", rvalue);
1116 return 0;
1117 }
1118 }
1119
1120 *ipv6_privacy_extensions = s;
1121
1122 return 0;
1123 }
1124
1125 int config_parse_hostname(
1126 const char *unit,
1127 const char *filename,
1128 unsigned line,
1129 const char *section,
1130 unsigned section_line,
1131 const char *lvalue,
1132 int ltype,
1133 const char *rvalue,
1134 void *data,
1135 void *userdata) {
1136
1137 _cleanup_free_ char *hn = NULL;
1138 char **hostname = data;
1139 int r;
1140
1141 assert(filename);
1142 assert(lvalue);
1143 assert(rvalue);
1144
1145 r = config_parse_string(unit, filename, line, section, section_line, lvalue, ltype, rvalue, &hn, userdata);
1146 if (r < 0)
1147 return r;
1148
1149 if (!hostname_is_valid(hn, false)) {
1150 log_syntax(unit, LOG_WARNING, filename, line, 0,
1151 "Hostname is not valid, ignoring assignment: %s", rvalue);
1152 return 0;
1153 }
1154
1155 r = dns_name_is_valid(hn);
1156 if (r < 0) {
1157 log_syntax(unit, LOG_WARNING, filename, line, r,
1158 "Failed to check validity of hostname '%s', ignoring assignment: %m", rvalue);
1159 return 0;
1160 }
1161 if (r == 0) {
1162 log_syntax(unit, LOG_WARNING, filename, line, 0,
1163 "Hostname is not a valid DNS domain name, ignoring assignment: %s", rvalue);
1164 return 0;
1165 }
1166
1167 return free_and_replace(*hostname, hn);
1168 }
1169
1170 int config_parse_timezone(
1171 const char *unit,
1172 const char *filename,
1173 unsigned line,
1174 const char *section,
1175 unsigned section_line,
1176 const char *lvalue,
1177 int ltype,
1178 const char *rvalue,
1179 void *data,
1180 void *userdata) {
1181
1182 _cleanup_free_ char *tz = NULL;
1183 char **datap = data;
1184 int r;
1185
1186 assert(filename);
1187 assert(lvalue);
1188 assert(rvalue);
1189
1190 r = config_parse_string(unit, filename, line, section, section_line, lvalue, ltype, rvalue, &tz, userdata);
1191 if (r < 0)
1192 return r;
1193
1194 if (!timezone_is_valid(tz, LOG_WARNING)) {
1195 log_syntax(unit, LOG_WARNING, filename, line, 0,
1196 "Timezone is not valid, ignoring assignment: %s", rvalue);
1197 return 0;
1198 }
1199
1200 return free_and_replace(*datap, tz);
1201 }
1202
1203 int config_parse_dns(
1204 const char *unit,
1205 const char *filename,
1206 unsigned line,
1207 const char *section,
1208 unsigned section_line,
1209 const char *lvalue,
1210 int ltype,
1211 const char *rvalue,
1212 void *data,
1213 void *userdata) {
1214
1215 Network *n = userdata;
1216 int r;
1217
1218 assert(filename);
1219 assert(lvalue);
1220 assert(rvalue);
1221
1222 if (isempty(rvalue)) {
1223 for (unsigned i = 0; i < n->n_dns; i++)
1224 in_addr_full_free(n->dns[i]);
1225 n->dns = mfree(n->dns);
1226 n->n_dns = 0;
1227 return 0;
1228 }
1229
1230 for (const char *p = rvalue;;) {
1231 _cleanup_(in_addr_full_freep) struct in_addr_full *dns = NULL;
1232 _cleanup_free_ char *w = NULL;
1233 struct in_addr_full **m;
1234
1235 r = extract_first_word(&p, &w, NULL, 0);
1236 if (r == -ENOMEM)
1237 return log_oom();
1238 if (r < 0) {
1239 log_syntax(unit, LOG_WARNING, filename, line, r,
1240 "Invalid syntax, ignoring: %s", rvalue);
1241 return 0;
1242 }
1243 if (r == 0)
1244 return 0;
1245
1246 r = in_addr_full_new_from_string(w, &dns);
1247 if (r < 0) {
1248 log_syntax(unit, LOG_WARNING, filename, line, r,
1249 "Failed to parse dns server address, ignoring: %s", w);
1250 continue;
1251 }
1252
1253 if (IN_SET(dns->port, 53, 853))
1254 dns->port = 0;
1255
1256 m = reallocarray(n->dns, n->n_dns + 1, sizeof(struct in_addr_full*));
1257 if (!m)
1258 return log_oom();
1259
1260 m[n->n_dns++] = TAKE_PTR(dns);
1261 n->dns = m;
1262 }
1263 }
1264
1265 int config_parse_dnssec_negative_trust_anchors(
1266 const char *unit,
1267 const char *filename,
1268 unsigned line,
1269 const char *section,
1270 unsigned section_line,
1271 const char *lvalue,
1272 int ltype,
1273 const char *rvalue,
1274 void *data,
1275 void *userdata) {
1276
1277 Network *n = data;
1278 int r;
1279
1280 assert(n);
1281 assert(lvalue);
1282 assert(rvalue);
1283
1284 if (isempty(rvalue)) {
1285 n->dnssec_negative_trust_anchors = set_free_free(n->dnssec_negative_trust_anchors);
1286 return 0;
1287 }
1288
1289 for (const char *p = rvalue;;) {
1290 _cleanup_free_ char *w = NULL;
1291
1292 r = extract_first_word(&p, &w, NULL, 0);
1293 if (r == -ENOMEM)
1294 return log_oom();
1295 if (r < 0) {
1296 log_syntax(unit, LOG_WARNING, filename, line, r,
1297 "Failed to extract negative trust anchor domain, ignoring: %s", rvalue);
1298 return 0;
1299 }
1300 if (r == 0)
1301 return 0;
1302
1303 r = dns_name_is_valid(w);
1304 if (r <= 0) {
1305 log_syntax(unit, LOG_WARNING, filename, line, r,
1306 "%s is not a valid domain name, ignoring.", w);
1307 continue;
1308 }
1309
1310 r = set_ensure_consume(&n->dnssec_negative_trust_anchors, &dns_name_hash_ops, TAKE_PTR(w));
1311 if (r < 0)
1312 return log_oom();
1313 }
1314 }
1315
1316 int config_parse_ntp(
1317 const char *unit,
1318 const char *filename,
1319 unsigned line,
1320 const char *section,
1321 unsigned section_line,
1322 const char *lvalue,
1323 int ltype,
1324 const char *rvalue,
1325 void *data,
1326 void *userdata) {
1327
1328 char ***l = data;
1329 int r;
1330
1331 assert(l);
1332 assert(lvalue);
1333 assert(rvalue);
1334
1335 if (isempty(rvalue)) {
1336 *l = strv_free(*l);
1337 return 0;
1338 }
1339
1340 for (const char *p = rvalue;;) {
1341 _cleanup_free_ char *w = NULL;
1342
1343 r = extract_first_word(&p, &w, NULL, 0);
1344 if (r == -ENOMEM)
1345 return log_oom();
1346 if (r < 0) {
1347 log_syntax(unit, LOG_WARNING, filename, line, r,
1348 "Failed to extract NTP server name, ignoring: %s", rvalue);
1349 return 0;
1350 }
1351 if (r == 0)
1352 return 0;
1353
1354 r = dns_name_is_valid_or_address(w);
1355 if (r <= 0) {
1356 log_syntax(unit, LOG_WARNING, filename, line, r,
1357 "%s is not a valid domain name or IP address, ignoring.", w);
1358 continue;
1359 }
1360
1361 if (strv_length(*l) > MAX_NTP_SERVERS) {
1362 log_syntax(unit, LOG_WARNING, filename, line, 0,
1363 "More than %u NTP servers specified, ignoring \"%s\" and any subsequent entries.",
1364 MAX_NTP_SERVERS, w);
1365 return 0;
1366 }
1367
1368 r = strv_consume(l, TAKE_PTR(w));
1369 if (r < 0)
1370 return log_oom();
1371 }
1372 }
1373
1374 int config_parse_required_for_online(
1375 const char *unit,
1376 const char *filename,
1377 unsigned line,
1378 const char *section,
1379 unsigned section_line,
1380 const char *lvalue,
1381 int ltype,
1382 const char *rvalue,
1383 void *data,
1384 void *userdata) {
1385
1386 Network *network = data;
1387 LinkOperationalStateRange range;
1388 bool required = true;
1389 int r;
1390
1391 if (isempty(rvalue)) {
1392 network->required_for_online = true;
1393 network->required_operstate_for_online = LINK_OPERSTATE_RANGE_DEFAULT;
1394 return 0;
1395 }
1396
1397 r = parse_operational_state_range(rvalue, &range);
1398 if (r < 0) {
1399 r = parse_boolean(rvalue);
1400 if (r < 0) {
1401 log_syntax(unit, LOG_WARNING, filename, line, r,
1402 "Failed to parse %s= setting, ignoring assignment: %s",
1403 lvalue, rvalue);
1404 return 0;
1405 }
1406
1407 required = r;
1408 range = LINK_OPERSTATE_RANGE_DEFAULT;
1409 }
1410
1411 network->required_for_online = required;
1412 network->required_operstate_for_online = range;
1413
1414 return 0;
1415 }
1416
1417 DEFINE_CONFIG_PARSE_ENUM(config_parse_keep_configuration, keep_configuration, KeepConfiguration,
1418 "Failed to parse KeepConfiguration= setting");
1419
1420 static const char* const keep_configuration_table[_KEEP_CONFIGURATION_MAX] = {
1421 [KEEP_CONFIGURATION_NO] = "no",
1422 [KEEP_CONFIGURATION_DHCP_ON_STOP] = "dhcp-on-stop",
1423 [KEEP_CONFIGURATION_DHCP] = "dhcp",
1424 [KEEP_CONFIGURATION_STATIC] = "static",
1425 [KEEP_CONFIGURATION_YES] = "yes",
1426 };
1427
1428 DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(keep_configuration, KeepConfiguration, KEEP_CONFIGURATION_YES);
1429
1430 static const char* const ipv6_link_local_address_gen_mode_table[_IPV6_LINK_LOCAL_ADDRESS_GEN_MODE_MAX] = {
1431 [IPV6_LINK_LOCAL_ADDRESSS_GEN_MODE_EUI64] = "eui64",
1432 [IPV6_LINK_LOCAL_ADDRESSS_GEN_MODE_NONE] = "none",
1433 [IPV6_LINK_LOCAL_ADDRESSS_GEN_MODE_STABLE_PRIVACY] = "stable-privacy",
1434 [IPV6_LINK_LOCAL_ADDRESSS_GEN_MODE_RANDOM] = "random",
1435 };
1436
1437 DEFINE_STRING_TABLE_LOOKUP(ipv6_link_local_address_gen_mode, IPv6LinkLocalAddressGenMode);
1438 DEFINE_CONFIG_PARSE_ENUM(config_parse_ipv6_link_local_address_gen_mode, ipv6_link_local_address_gen_mode, IPv6LinkLocalAddressGenMode, "Failed to parse IPv6 link local address generation mode");