]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/network/networkd-network.c
Merge pull request #13494 from yuwata/dhcp6-delay
[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) && strv_isempty(network->match_property) &&
161 !network->conditions)
162 log_warning("%s: No valid settings found in the [Match] section. "
163 "The file will match all interfaces. "
164 "If that is intended, please add Name=* in the [Match] section.",
165 network->filename);
166
167 /* skip out early if configuration does not match the environment */
168 if (!condition_test_list(network->conditions, NULL, NULL, NULL))
169 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL),
170 "%s: Conditions in the file do not match the system environment, skipping.",
171 network->filename);
172
173 (void) network_resolve_netdev_one(network, network->bond_name, NETDEV_KIND_BOND, &network->bond);
174 (void) network_resolve_netdev_one(network, network->bridge_name, NETDEV_KIND_BRIDGE, &network->bridge);
175 (void) network_resolve_netdev_one(network, network->vrf_name, NETDEV_KIND_VRF, &network->vrf);
176 (void) network_resolve_stacked_netdevs(network);
177
178 /* Free unnecessary entries. */
179 network->bond_name = mfree(network->bond_name);
180 network->bridge_name = mfree(network->bridge_name);
181 network->vrf_name = mfree(network->vrf_name);
182 network->stacked_netdev_names = hashmap_free_free_key(network->stacked_netdev_names);
183
184 if (network->bond) {
185 /* Bonding slave does not support addressing. */
186 if (network->ipv6_accept_ra > 0) {
187 log_warning("%s: Cannot enable IPv6AcceptRA= when Bond= is specified, disabling IPv6AcceptRA=.",
188 network->filename);
189 network->ipv6_accept_ra = 0;
190 }
191 if (network->link_local >= 0 && network->link_local != ADDRESS_FAMILY_NO) {
192 log_warning("%s: Cannot enable LinkLocalAddressing= when Bond= is specified, disabling LinkLocalAddressing=.",
193 network->filename);
194 network->link_local = ADDRESS_FAMILY_NO;
195 }
196 if (network->dhcp != ADDRESS_FAMILY_NO) {
197 log_warning("%s: Cannot enable DHCP= when Bond= is specified, disabling DHCP=.",
198 network->filename);
199 network->dhcp = ADDRESS_FAMILY_NO;
200 }
201 if (network->dhcp_server) {
202 log_warning("%s: Cannot enable DHCPServer= when Bond= is specified, disabling DHCPServer=.",
203 network->filename);
204 network->dhcp_server = false;
205 }
206 if (network->n_static_addresses > 0) {
207 log_warning("%s: Cannot set addresses when Bond= is specified, ignoring addresses.",
208 network->filename);
209 while ((address = network->static_addresses))
210 address_free(address);
211 }
212 if (network->n_static_routes > 0) {
213 log_warning("%s: Cannot set routes when Bond= is specified, ignoring routes.",
214 network->filename);
215 while ((route = network->static_routes))
216 route_free(route);
217 }
218 }
219
220 if (network->link_local < 0)
221 network->link_local = network->bridge ? ADDRESS_FAMILY_NO : ADDRESS_FAMILY_IPV6;
222
223 if (!FLAGS_SET(network->link_local, ADDRESS_FAMILY_IPV6)) {
224 if (network->ipv6_accept_ra > 0) {
225 log_warning("%s: IPv6AcceptRA= is enabled by the .network file but IPv6 link local addressing is disabled. "
226 "Disabling IPv6AcceptRA=.", network->filename);
227 network->ipv6_accept_ra = false;
228 }
229
230 if (FLAGS_SET(network->dhcp, ADDRESS_FAMILY_IPV6)) {
231 log_warning("%s: DHCPv6 client is enabled by the .network file but IPv6 link local addressing is disabled. "
232 "Disabling DHCPv6 client.", network->filename);
233 SET_FLAG(network->dhcp, ADDRESS_FAMILY_IPV6, false);
234 }
235
236 if (network->router_prefix_delegation != RADV_PREFIX_DELEGATION_NONE) {
237 log_warning("%s: IPv6PrefixDelegation= is enabled but IPv6 link local addressing is disabled. "
238 "Disabling IPv6PrefixDelegation=.", network->filename);
239 network->router_prefix_delegation = RADV_PREFIX_DELEGATION_NONE;
240 }
241 }
242
243 if (FLAGS_SET(network->link_local, ADDRESS_FAMILY_FALLBACK_IPV4) &&
244 !FLAGS_SET(network->dhcp, ADDRESS_FAMILY_IPV4)) {
245 log_warning("%s: fallback assignment of IPv4 link local address is enabled but DHCPv4 is disabled. "
246 "Disabling the fallback assignment.", network->filename);
247 SET_FLAG(network->link_local, ADDRESS_FAMILY_FALLBACK_IPV4, false);
248 }
249
250 if (network->ipv6_accept_ra < 0 && network->bridge)
251 network->ipv6_accept_ra = false;
252
253 /* IPMasquerade=yes implies IPForward=yes */
254 if (network->ip_masquerade)
255 network->ip_forward |= ADDRESS_FAMILY_IPV4;
256
257 if (network->mtu > 0 && network->dhcp_use_mtu) {
258 log_warning("%s: MTUBytes= in [Link] section and UseMTU= in [DHCP] section are set. "
259 "Disabling UseMTU=.", network->filename);
260 network->dhcp_use_mtu = false;
261 }
262
263 if (network->dhcp_critical >= 0) {
264 if (network->keep_configuration >= 0)
265 log_warning("%s: Both KeepConfiguration= and deprecated CriticalConnection= are set. "
266 "Ignoring CriticalConnection=.", network->filename);
267 else if (network->dhcp_critical)
268 /* CriticalConnection=yes also preserve foreign static configurations. */
269 network->keep_configuration = KEEP_CONFIGURATION_YES;
270 else
271 /* For backward compatibility, we do not release DHCP addresses on manager stop. */
272 network->keep_configuration = KEEP_CONFIGURATION_DHCP_ON_STOP;
273 }
274
275 if (network->keep_configuration < 0)
276 /* For backward compatibility, we do not release DHCP addresses on manager stop. */
277 network->keep_configuration = KEEP_CONFIGURATION_DHCP_ON_STOP;
278
279 LIST_FOREACH_SAFE(addresses, address, address_next, network->static_addresses)
280 if (address_section_verify(address) < 0)
281 address_free(address);
282
283 LIST_FOREACH_SAFE(routes, route, route_next, network->static_routes)
284 if (route_section_verify(route, network) < 0)
285 route_free(route);
286
287 LIST_FOREACH_SAFE(static_fdb_entries, fdb, fdb_next, network->static_fdb_entries)
288 if (section_is_invalid(fdb->section))
289 fdb_entry_free(fdb);
290
291 LIST_FOREACH_SAFE(neighbors, neighbor, neighbor_next, network->neighbors)
292 if (neighbor_section_verify(neighbor) < 0)
293 neighbor_free(neighbor);
294
295 LIST_FOREACH_SAFE(labels, label, label_next, network->address_labels)
296 if (section_is_invalid(label->section))
297 address_label_free(label);
298
299 LIST_FOREACH_SAFE(prefixes, prefix, prefix_next, network->static_prefixes)
300 if (section_is_invalid(prefix->section))
301 prefix_free(prefix);
302
303 LIST_FOREACH_SAFE(rules, rule, rule_next, network->rules)
304 if (routing_policy_rule_section_verify(rule) < 0)
305 routing_policy_rule_free(rule);
306
307 return 0;
308 }
309
310 int network_load_one(Manager *manager, const char *filename) {
311 _cleanup_free_ char *fname = NULL, *name = NULL;
312 _cleanup_(network_unrefp) Network *network = NULL;
313 _cleanup_fclose_ FILE *file = NULL;
314 const char *dropin_dirname;
315 char *d;
316 int r;
317
318 assert(manager);
319 assert(filename);
320
321 file = fopen(filename, "re");
322 if (!file) {
323 if (errno == ENOENT)
324 return 0;
325
326 return -errno;
327 }
328
329 if (null_or_empty_fd(fileno(file))) {
330 log_debug("Skipping empty file: %s", filename);
331 return 0;
332 }
333
334 fname = strdup(filename);
335 if (!fname)
336 return log_oom();
337
338 name = strdup(basename(filename));
339 if (!name)
340 return log_oom();
341
342 d = strrchr(name, '.');
343 if (!d)
344 return -EINVAL;
345
346 *d = '\0';
347
348 dropin_dirname = strjoina(name, ".network.d");
349
350 network = new(Network, 1);
351 if (!network)
352 return log_oom();
353
354 *network = (Network) {
355 .filename = TAKE_PTR(fname),
356 .name = TAKE_PTR(name),
357
358 .manager = manager,
359 .n_ref = 1,
360
361 .required_for_online = true,
362 .required_operstate_for_online = LINK_OPERSTATE_DEGRADED,
363 .dhcp = ADDRESS_FAMILY_NO,
364 .dhcp_critical = -1,
365 .dhcp_use_ntp = true,
366 .dhcp_use_dns = true,
367 .dhcp_use_hostname = true,
368 .dhcp_use_routes = true,
369 /* NOTE: this var might be overwritten by network_apply_anonymize_if_set */
370 .dhcp_send_hostname = true,
371 /* To enable/disable RFC7844 Anonymity Profiles */
372 .dhcp_anonymize = false,
373 .dhcp_route_metric = DHCP_ROUTE_METRIC,
374 /* NOTE: this var might be overwritten by network_apply_anonymize_if_set */
375 .dhcp_client_identifier = DHCP_CLIENT_ID_DUID,
376 .dhcp_route_table = RT_TABLE_MAIN,
377 .dhcp_route_table_set = false,
378 /* NOTE: from man: UseMTU=... Defaults to false*/
379 .dhcp_use_mtu = false,
380 /* NOTE: from man: UseTimezone=... Defaults to "no".*/
381 .dhcp_use_timezone = false,
382 .rapid_commit = true,
383
384 .dhcp6_use_ntp = true,
385 .dhcp6_use_dns = true,
386
387 .dhcp_server_emit_dns = true,
388 .dhcp_server_emit_ntp = true,
389 .dhcp_server_emit_router = true,
390 .dhcp_server_emit_timezone = true,
391
392 .router_emit_dns = true,
393 .router_emit_domains = true,
394
395 .use_bpdu = -1,
396 .hairpin = -1,
397 .fast_leave = -1,
398 .allow_port_to_be_root = -1,
399 .unicast_flood = -1,
400 .multicast_flood = -1,
401 .multicast_to_unicast = -1,
402 .neighbor_suppression = -1,
403 .learning = -1,
404 .bridge_proxy_arp = -1,
405 .bridge_proxy_arp_wifi = -1,
406 .priority = LINK_BRIDGE_PORT_PRIORITY_INVALID,
407 .multicast_router = _MULTICAST_ROUTER_INVALID,
408
409 .lldp_mode = LLDP_MODE_ROUTERS_ONLY,
410
411 .dns_default_route = -1,
412 .llmnr = RESOLVE_SUPPORT_YES,
413 .mdns = RESOLVE_SUPPORT_NO,
414 .dnssec_mode = _DNSSEC_MODE_INVALID,
415 .dns_over_tls_mode = _DNS_OVER_TLS_MODE_INVALID,
416
417 /* If LinkLocalAddressing= is not set, then set to ADDRESS_FAMILY_IPV6 later. */
418 .link_local = _ADDRESS_FAMILY_INVALID,
419
420 .ipv6_privacy_extensions = IPV6_PRIVACY_EXTENSIONS_NO,
421 .ipv6_accept_ra = -1,
422 .ipv6_dad_transmits = -1,
423 .ipv6_hop_limit = -1,
424 .ipv6_proxy_ndp = -1,
425 .duid.type = _DUID_TYPE_INVALID,
426 .proxy_arp = -1,
427 .arp = -1,
428 .multicast = -1,
429 .allmulticast = -1,
430 .ipv6_accept_ra_use_dns = true,
431 .ipv6_accept_ra_use_autonomous_prefix = true,
432 .ipv6_accept_ra_use_onlink_prefix = true,
433 .ipv6_accept_ra_route_table = RT_TABLE_MAIN,
434 .ipv6_accept_ra_route_table_set = false,
435
436 .keep_configuration = _KEEP_CONFIGURATION_INVALID,
437
438 .can_triple_sampling = -1,
439 };
440
441 r = config_parse_many(filename, NETWORK_DIRS, dropin_dirname,
442 "Match\0"
443 "Link\0"
444 "Network\0"
445 "Address\0"
446 "Neighbor\0"
447 "IPv6AddressLabel\0"
448 "RoutingPolicyRule\0"
449 "Route\0"
450 "DHCP\0"
451 "DHCPv4\0" /* compat */
452 "DHCPv6\0"
453 "DHCPServer\0"
454 "IPv6AcceptRA\0"
455 "IPv6NDPProxyAddress\0"
456 "Bridge\0"
457 "BridgeFDB\0"
458 "BridgeVLAN\0"
459 "IPv6PrefixDelegation\0"
460 "IPv6Prefix\0"
461 "CAN\0",
462 config_item_perf_lookup, network_network_gperf_lookup,
463 CONFIG_PARSE_WARN, network);
464 if (r < 0)
465 return r;
466
467 network_apply_anonymize_if_set(network);
468
469 r = network_add_ipv4ll_route(network);
470 if (r < 0)
471 log_warning_errno(r, "%s: Failed to add IPv4LL route, ignoring: %m", network->filename);
472
473 r = network_add_default_route_on_device(network);
474 if (r < 0)
475 log_warning_errno(r, "%s: Failed to add default route on device, ignoring: %m",
476 network->filename);
477
478 r = ordered_hashmap_ensure_allocated(&manager->networks, &string_hash_ops);
479 if (r < 0)
480 return r;
481
482 r = ordered_hashmap_put(manager->networks, network->name, network);
483 if (r < 0)
484 return r;
485
486 if (network_verify(network) < 0)
487 return 0;
488
489 network = NULL;
490 return 0;
491 }
492
493 int network_load(Manager *manager) {
494 _cleanup_strv_free_ char **files = NULL;
495 char **f;
496 int r;
497
498 assert(manager);
499
500 ordered_hashmap_clear_with_destructor(manager->networks, network_unref);
501
502 r = conf_files_list_strv(&files, ".network", NULL, 0, NETWORK_DIRS);
503 if (r < 0)
504 return log_error_errno(r, "Failed to enumerate network files: %m");
505
506 STRV_FOREACH(f, files) {
507 r = network_load_one(manager, *f);
508 if (r < 0)
509 log_error_errno(r, "Failed to load %s, ignoring: %m", *f);
510 }
511
512 return 0;
513 }
514
515 static Network *network_free(Network *network) {
516 IPv6ProxyNDPAddress *ipv6_proxy_ndp_address;
517 RoutingPolicyRule *rule;
518 FdbEntry *fdb_entry;
519 Neighbor *neighbor;
520 AddressLabel *label;
521 Prefix *prefix;
522 Address *address;
523 Route *route;
524
525 if (!network)
526 return NULL;
527
528 free(network->filename);
529
530 set_free_free(network->match_mac);
531 strv_free(network->match_path);
532 strv_free(network->match_driver);
533 strv_free(network->match_type);
534 strv_free(network->match_name);
535 strv_free(network->match_property);
536 condition_free_list(network->conditions);
537
538 free(network->description);
539 free(network->dhcp_vendor_class_identifier);
540 strv_free(network->dhcp_user_class);
541 free(network->dhcp_hostname);
542 set_free(network->dhcp_black_listed_ip);
543 free(network->mac);
544
545 strv_free(network->ntp);
546 free(network->dns);
547 ordered_set_free_free(network->search_domains);
548 ordered_set_free_free(network->route_domains);
549 strv_free(network->bind_carrier);
550
551 ordered_set_free_free(network->router_search_domains);
552 free(network->router_dns);
553 set_free_free(network->ndisc_black_listed_prefix);
554
555 free(network->bridge_name);
556 free(network->bond_name);
557 free(network->vrf_name);
558 hashmap_free_free_key(network->stacked_netdev_names);
559 netdev_unref(network->bridge);
560 netdev_unref(network->bond);
561 netdev_unref(network->vrf);
562 hashmap_free_with_destructor(network->stacked_netdevs, netdev_unref);
563
564 while ((route = network->static_routes))
565 route_free(route);
566
567 while ((address = network->static_addresses))
568 address_free(address);
569
570 while ((fdb_entry = network->static_fdb_entries))
571 fdb_entry_free(fdb_entry);
572
573 while ((ipv6_proxy_ndp_address = network->ipv6_proxy_ndp_addresses))
574 ipv6_proxy_ndp_address_free(ipv6_proxy_ndp_address);
575
576 while ((neighbor = network->neighbors))
577 neighbor_free(neighbor);
578
579 while ((label = network->address_labels))
580 address_label_free(label);
581
582 while ((prefix = network->static_prefixes))
583 prefix_free(prefix);
584
585 while ((rule = network->rules))
586 routing_policy_rule_free(rule);
587
588 hashmap_free(network->addresses_by_section);
589 hashmap_free(network->routes_by_section);
590 hashmap_free(network->fdb_entries_by_section);
591 hashmap_free(network->neighbors_by_section);
592 hashmap_free(network->address_labels_by_section);
593 hashmap_free(network->prefixes_by_section);
594 hashmap_free(network->rules_by_section);
595
596 if (network->manager) {
597 if (network->manager->networks && network->name)
598 ordered_hashmap_remove(network->manager->networks, network->name);
599
600 if (network->manager->duids_requesting_uuid)
601 set_remove(network->manager->duids_requesting_uuid, &network->duid);
602 }
603
604 free(network->name);
605
606 free(network->dhcp_server_timezone);
607 free(network->dhcp_server_dns);
608 free(network->dhcp_server_ntp);
609
610 set_free_free(network->dnssec_negative_trust_anchors);
611
612 return mfree(network);
613 }
614
615 DEFINE_TRIVIAL_REF_UNREF_FUNC(Network, network, network_free);
616
617 int network_get_by_name(Manager *manager, const char *name, Network **ret) {
618 Network *network;
619
620 assert(manager);
621 assert(name);
622 assert(ret);
623
624 network = ordered_hashmap_get(manager->networks, name);
625 if (!network)
626 return -ENOENT;
627
628 *ret = network;
629
630 return 0;
631 }
632
633 int network_get(Manager *manager, sd_device *device,
634 const char *ifname, const struct ether_addr *address,
635 Network **ret) {
636 Network *network;
637 Iterator i;
638
639 assert(manager);
640 assert(ret);
641
642 ORDERED_HASHMAP_FOREACH(network, manager->networks, i)
643 if (net_match_config(network->match_mac, network->match_path, network->match_driver,
644 network->match_type, network->match_name, network->match_property,
645 device, address, ifname)) {
646 if (network->match_name && device) {
647 const char *attr;
648 uint8_t name_assign_type = NET_NAME_UNKNOWN;
649
650 if (sd_device_get_sysattr_value(device, "name_assign_type", &attr) >= 0)
651 (void) safe_atou8(attr, &name_assign_type);
652
653 if (name_assign_type == NET_NAME_ENUM)
654 log_warning("%s: found matching network '%s', based on potentially unpredictable ifname",
655 ifname, network->filename);
656 else
657 log_debug("%s: found matching network '%s'", ifname, network->filename);
658 } else
659 log_debug("%s: found matching network '%s'", ifname, network->filename);
660
661 *ret = network;
662 return 0;
663 }
664
665 *ret = NULL;
666
667 return -ENOENT;
668 }
669
670 int network_apply(Network *network, Link *link) {
671 assert(network);
672 assert(link);
673
674 link->network = network_ref(network);
675
676 if (network->n_dns > 0 ||
677 !strv_isempty(network->ntp) ||
678 !ordered_set_isempty(network->search_domains) ||
679 !ordered_set_isempty(network->route_domains))
680 link_dirty(link);
681
682 return 0;
683 }
684
685 bool network_has_static_ipv6_configurations(Network *network) {
686 Address *address;
687 Route *route;
688 FdbEntry *fdb;
689 Neighbor *neighbor;
690
691 assert(network);
692
693 LIST_FOREACH(addresses, address, network->static_addresses)
694 if (address->family == AF_INET6)
695 return true;
696
697 LIST_FOREACH(routes, route, network->static_routes)
698 if (route->family == AF_INET6)
699 return true;
700
701 LIST_FOREACH(static_fdb_entries, fdb, network->static_fdb_entries)
702 if (fdb->family == AF_INET6)
703 return true;
704
705 LIST_FOREACH(neighbors, neighbor, network->neighbors)
706 if (neighbor->family == AF_INET6)
707 return true;
708
709 if (!LIST_IS_EMPTY(network->address_labels))
710 return true;
711
712 if (!LIST_IS_EMPTY(network->static_prefixes))
713 return true;
714
715 return false;
716 }
717
718 int config_parse_stacked_netdev(const char *unit,
719 const char *filename,
720 unsigned line,
721 const char *section,
722 unsigned section_line,
723 const char *lvalue,
724 int ltype,
725 const char *rvalue,
726 void *data,
727 void *userdata) {
728 _cleanup_free_ char *name = NULL;
729 NetDevKind kind = ltype;
730 Hashmap **h = data;
731 int r;
732
733 assert(filename);
734 assert(lvalue);
735 assert(rvalue);
736 assert(data);
737 assert(IN_SET(kind,
738 NETDEV_KIND_VLAN, NETDEV_KIND_MACVLAN, NETDEV_KIND_MACVTAP,
739 NETDEV_KIND_IPVLAN, NETDEV_KIND_IPVTAP, NETDEV_KIND_VXLAN,
740 NETDEV_KIND_L2TP, NETDEV_KIND_MACSEC, _NETDEV_KIND_TUNNEL,
741 NETDEV_KIND_XFRM));
742
743 if (!ifname_valid(rvalue)) {
744 log_syntax(unit, LOG_ERR, filename, line, 0,
745 "Invalid netdev name in %s=, ignoring assignment: %s", lvalue, rvalue);
746 return 0;
747 }
748
749 name = strdup(rvalue);
750 if (!name)
751 return log_oom();
752
753 r = hashmap_ensure_allocated(h, &string_hash_ops);
754 if (r < 0)
755 return log_oom();
756
757 r = hashmap_put(*h, name, INT_TO_PTR(kind));
758 if (r < 0)
759 log_syntax(unit, LOG_ERR, filename, line, r,
760 "Cannot add NetDev '%s' to network, ignoring assignment: %m", name);
761 else if (r == 0)
762 log_syntax(unit, LOG_DEBUG, filename, line, r,
763 "NetDev '%s' specified twice, ignoring.", name);
764 else
765 name = NULL;
766
767 return 0;
768 }
769
770 int config_parse_domains(
771 const char *unit,
772 const char *filename,
773 unsigned line,
774 const char *section,
775 unsigned section_line,
776 const char *lvalue,
777 int ltype,
778 const char *rvalue,
779 void *data,
780 void *userdata) {
781
782 const char *p;
783 Network *n = data;
784 int r;
785
786 assert(n);
787 assert(lvalue);
788 assert(rvalue);
789
790 if (isempty(rvalue)) {
791 n->search_domains = ordered_set_free_free(n->search_domains);
792 n->route_domains = ordered_set_free_free(n->route_domains);
793 return 0;
794 }
795
796 p = rvalue;
797 for (;;) {
798 _cleanup_free_ char *w = NULL, *normalized = NULL;
799 const char *domain;
800 bool is_route;
801
802 r = extract_first_word(&p, &w, NULL, 0);
803 if (r < 0) {
804 log_syntax(unit, LOG_ERR, filename, line, r,
805 "Failed to extract search or route domain, ignoring: %s", rvalue);
806 break;
807 }
808 if (r == 0)
809 break;
810
811 is_route = w[0] == '~';
812 domain = is_route ? w + 1 : w;
813
814 if (dns_name_is_root(domain) || streq(domain, "*")) {
815 /* If the root domain appears as is, or the special token "*" is found, we'll
816 * consider this as routing domain, unconditionally. */
817 is_route = true;
818 domain = "."; /* make sure we don't allow empty strings, thus write the root
819 * domain as "." */
820 } else {
821 r = dns_name_normalize(domain, 0, &normalized);
822 if (r < 0) {
823 log_syntax(unit, LOG_ERR, filename, line, r,
824 "'%s' is not a valid domain name, ignoring.", domain);
825 continue;
826 }
827
828 domain = normalized;
829
830 if (is_localhost(domain)) {
831 log_syntax(unit, LOG_ERR, filename, line, 0,
832 "'localhost' domain may not be configured as search or route domain, ignoring assignment: %s",
833 domain);
834 continue;
835 }
836 }
837
838 OrderedSet **set = is_route ? &n->route_domains : &n->search_domains;
839 r = ordered_set_ensure_allocated(set, &string_hash_ops);
840 if (r < 0)
841 return r;
842
843 r = ordered_set_put_strdup(*set, domain);
844 if (r < 0)
845 return log_oom();
846 }
847
848 return 0;
849 }
850
851 int config_parse_ipv6token(
852 const char* unit,
853 const char *filename,
854 unsigned line,
855 const char *section,
856 unsigned section_line,
857 const char *lvalue,
858 int ltype,
859 const char *rvalue,
860 void *data,
861 void *userdata) {
862
863 union in_addr_union buffer;
864 struct in6_addr *token = data;
865 int r;
866
867 assert(filename);
868 assert(lvalue);
869 assert(rvalue);
870 assert(token);
871
872 r = in_addr_from_string(AF_INET6, rvalue, &buffer);
873 if (r < 0) {
874 log_syntax(unit, LOG_ERR, filename, line, r,
875 "Failed to parse IPv6 token, ignoring: %s", rvalue);
876 return 0;
877 }
878
879 if (in_addr_is_null(AF_INET6, &buffer)) {
880 log_syntax(unit, LOG_ERR, filename, line, 0,
881 "IPv6 token cannot be the ANY address, ignoring: %s", rvalue);
882 return 0;
883 }
884
885 if ((buffer.in6.s6_addr32[0] | buffer.in6.s6_addr32[1]) != 0) {
886 log_syntax(unit, LOG_ERR, filename, line, 0,
887 "IPv6 token cannot be longer than 64 bits, ignoring: %s", rvalue);
888 return 0;
889 }
890
891 *token = buffer.in6;
892
893 return 0;
894 }
895
896 static const char* const ipv6_privacy_extensions_table[_IPV6_PRIVACY_EXTENSIONS_MAX] = {
897 [IPV6_PRIVACY_EXTENSIONS_NO] = "no",
898 [IPV6_PRIVACY_EXTENSIONS_PREFER_PUBLIC] = "prefer-public",
899 [IPV6_PRIVACY_EXTENSIONS_YES] = "yes",
900 };
901
902 DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(ipv6_privacy_extensions, IPv6PrivacyExtensions,
903 IPV6_PRIVACY_EXTENSIONS_YES);
904
905 int config_parse_ipv6_privacy_extensions(
906 const char* unit,
907 const char *filename,
908 unsigned line,
909 const char *section,
910 unsigned section_line,
911 const char *lvalue,
912 int ltype,
913 const char *rvalue,
914 void *data,
915 void *userdata) {
916
917 IPv6PrivacyExtensions s, *ipv6_privacy_extensions = data;
918
919 assert(filename);
920 assert(lvalue);
921 assert(rvalue);
922 assert(ipv6_privacy_extensions);
923
924 s = ipv6_privacy_extensions_from_string(rvalue);
925 if (s < 0) {
926 if (streq(rvalue, "kernel"))
927 s = _IPV6_PRIVACY_EXTENSIONS_INVALID;
928 else {
929 log_syntax(unit, LOG_ERR, filename, line, 0,
930 "Failed to parse IPv6 privacy extensions option, ignoring: %s", rvalue);
931 return 0;
932 }
933 }
934
935 *ipv6_privacy_extensions = s;
936
937 return 0;
938 }
939
940 int config_parse_hostname(
941 const char *unit,
942 const char *filename,
943 unsigned line,
944 const char *section,
945 unsigned section_line,
946 const char *lvalue,
947 int ltype,
948 const char *rvalue,
949 void *data,
950 void *userdata) {
951
952 _cleanup_free_ char *hn = NULL;
953 char **hostname = data;
954 int r;
955
956 assert(filename);
957 assert(lvalue);
958 assert(rvalue);
959
960 r = config_parse_string(unit, filename, line, section, section_line, lvalue, ltype, rvalue, &hn, userdata);
961 if (r < 0)
962 return r;
963
964 if (!hostname_is_valid(hn, false)) {
965 log_syntax(unit, LOG_ERR, filename, line, 0,
966 "Hostname is not valid, ignoring assignment: %s", rvalue);
967 return 0;
968 }
969
970 r = dns_name_is_valid(hn);
971 if (r < 0) {
972 log_syntax(unit, LOG_ERR, filename, line, r,
973 "Failed to check validity of hostname '%s', ignoring assignment: %m", rvalue);
974 return 0;
975 }
976 if (r == 0) {
977 log_syntax(unit, LOG_ERR, filename, line, 0,
978 "Hostname is not a valid DNS domain name, ignoring assignment: %s", rvalue);
979 return 0;
980 }
981
982 return free_and_replace(*hostname, hn);
983 }
984
985 int config_parse_timezone(
986 const char *unit,
987 const char *filename,
988 unsigned line,
989 const char *section,
990 unsigned section_line,
991 const char *lvalue,
992 int ltype,
993 const char *rvalue,
994 void *data,
995 void *userdata) {
996
997 _cleanup_free_ char *tz = NULL;
998 char **datap = data;
999 int r;
1000
1001 assert(filename);
1002 assert(lvalue);
1003 assert(rvalue);
1004
1005 r = config_parse_string(unit, filename, line, section, section_line, lvalue, ltype, rvalue, &tz, userdata);
1006 if (r < 0)
1007 return r;
1008
1009 if (!timezone_is_valid(tz, LOG_ERR)) {
1010 log_syntax(unit, LOG_ERR, filename, line, 0,
1011 "Timezone is not valid, ignoring assignment: %s", rvalue);
1012 return 0;
1013 }
1014
1015 return free_and_replace(*datap, tz);
1016 }
1017
1018 int config_parse_dns(
1019 const char *unit,
1020 const char *filename,
1021 unsigned line,
1022 const char *section,
1023 unsigned section_line,
1024 const char *lvalue,
1025 int ltype,
1026 const char *rvalue,
1027 void *data,
1028 void *userdata) {
1029
1030 Network *n = userdata;
1031 int r;
1032
1033 assert(filename);
1034 assert(lvalue);
1035 assert(rvalue);
1036
1037 for (;;) {
1038 _cleanup_free_ char *w = NULL;
1039 union in_addr_union a;
1040 struct in_addr_data *m;
1041 int family;
1042
1043 r = extract_first_word(&rvalue, &w, NULL, 0);
1044 if (r == -ENOMEM)
1045 return log_oom();
1046 if (r < 0) {
1047 log_syntax(unit, LOG_ERR, filename, line, r,
1048 "Invalid syntax, ignoring: %s", rvalue);
1049 break;
1050 }
1051 if (r == 0)
1052 break;
1053
1054 r = in_addr_from_string_auto(w, &family, &a);
1055 if (r < 0) {
1056 log_syntax(unit, LOG_ERR, filename, line, r,
1057 "Failed to parse dns server address, ignoring: %s", w);
1058 continue;
1059 }
1060
1061 m = reallocarray(n->dns, n->n_dns + 1, sizeof(struct in_addr_data));
1062 if (!m)
1063 return log_oom();
1064
1065 m[n->n_dns++] = (struct in_addr_data) {
1066 .family = family,
1067 .address = a,
1068 };
1069
1070 n->dns = m;
1071 }
1072
1073 return 0;
1074 }
1075
1076 int config_parse_dnssec_negative_trust_anchors(
1077 const char *unit,
1078 const char *filename,
1079 unsigned line,
1080 const char *section,
1081 unsigned section_line,
1082 const char *lvalue,
1083 int ltype,
1084 const char *rvalue,
1085 void *data,
1086 void *userdata) {
1087
1088 const char *p = rvalue;
1089 Network *n = data;
1090 int r;
1091
1092 assert(n);
1093 assert(lvalue);
1094 assert(rvalue);
1095
1096 if (isempty(rvalue)) {
1097 n->dnssec_negative_trust_anchors = set_free_free(n->dnssec_negative_trust_anchors);
1098 return 0;
1099 }
1100
1101 for (;;) {
1102 _cleanup_free_ char *w = NULL;
1103
1104 r = extract_first_word(&p, &w, NULL, 0);
1105 if (r < 0) {
1106 log_syntax(unit, LOG_ERR, filename, line, r,
1107 "Failed to extract negative trust anchor domain, ignoring: %s", rvalue);
1108 break;
1109 }
1110 if (r == 0)
1111 break;
1112
1113 r = dns_name_is_valid(w);
1114 if (r <= 0) {
1115 log_syntax(unit, LOG_ERR, filename, line, r,
1116 "%s is not a valid domain name, ignoring.", w);
1117 continue;
1118 }
1119
1120 r = set_ensure_allocated(&n->dnssec_negative_trust_anchors, &dns_name_hash_ops);
1121 if (r < 0)
1122 return log_oom();
1123
1124 r = set_put(n->dnssec_negative_trust_anchors, w);
1125 if (r < 0)
1126 return log_oom();
1127 if (r > 0)
1128 w = NULL;
1129 }
1130
1131 return 0;
1132 }
1133
1134 int config_parse_ntp(
1135 const char *unit,
1136 const char *filename,
1137 unsigned line,
1138 const char *section,
1139 unsigned section_line,
1140 const char *lvalue,
1141 int ltype,
1142 const char *rvalue,
1143 void *data,
1144 void *userdata) {
1145
1146 char ***l = data;
1147 int r;
1148
1149 assert(l);
1150 assert(lvalue);
1151 assert(rvalue);
1152
1153 if (isempty(rvalue)) {
1154 *l = strv_free(*l);
1155 return 0;
1156 }
1157
1158 for (;;) {
1159 _cleanup_free_ char *w = NULL;
1160
1161 r = extract_first_word(&rvalue, &w, NULL, 0);
1162 if (r == -ENOMEM)
1163 return log_oom();
1164 if (r < 0) {
1165 log_syntax(unit, LOG_ERR, filename, line, r,
1166 "Failed to extract NTP server name, ignoring: %s", rvalue);
1167 break;
1168 }
1169 if (r == 0)
1170 break;
1171
1172 r = dns_name_is_valid_or_address(w);
1173 if (r <= 0) {
1174 log_syntax(unit, LOG_ERR, filename, line, r,
1175 "%s is not a valid domain name or IP address, ignoring.", w);
1176 continue;
1177 }
1178
1179 if (strv_length(*l) > MAX_NTP_SERVERS) {
1180 log_syntax(unit, LOG_WARNING, filename, line, 0,
1181 "More than %u NTP servers specified, ignoring \"%s\" and any subsequent entries.",
1182 MAX_NTP_SERVERS, w);
1183 break;
1184 }
1185
1186 r = strv_consume(l, TAKE_PTR(w));
1187 if (r < 0)
1188 return log_oom();
1189 }
1190
1191 return 0;
1192 }
1193
1194 int config_parse_required_for_online(
1195 const char *unit,
1196 const char *filename,
1197 unsigned line,
1198 const char *section,
1199 unsigned section_line,
1200 const char *lvalue,
1201 int ltype,
1202 const char *rvalue,
1203 void *data,
1204 void *userdata) {
1205
1206 Network *network = data;
1207 LinkOperationalState s;
1208 bool required = true;
1209 int r;
1210
1211 if (isempty(rvalue)) {
1212 network->required_for_online = true;
1213 network->required_operstate_for_online = LINK_OPERSTATE_DEGRADED;
1214 return 0;
1215 }
1216
1217 s = link_operstate_from_string(rvalue);
1218 if (s < 0) {
1219 r = parse_boolean(rvalue);
1220 if (r < 0) {
1221 log_syntax(unit, LOG_ERR, filename, line, r,
1222 "Failed to parse %s= setting, ignoring assignment: %s",
1223 lvalue, rvalue);
1224 return 0;
1225 }
1226
1227 required = r;
1228 s = LINK_OPERSTATE_DEGRADED;
1229 }
1230
1231 network->required_for_online = required;
1232 network->required_operstate_for_online = s;
1233
1234 return 0;
1235 }
1236
1237 DEFINE_CONFIG_PARSE_ENUM(config_parse_keep_configuration, keep_configuration, KeepConfiguration,
1238 "Failed to parse KeepConfiguration= setting");
1239
1240 static const char* const keep_configuration_table[_KEEP_CONFIGURATION_MAX] = {
1241 [KEEP_CONFIGURATION_NO] = "no",
1242 [KEEP_CONFIGURATION_DHCP_ON_STOP] = "dhcp-on-stop",
1243 [KEEP_CONFIGURATION_DHCP] = "dhcp",
1244 [KEEP_CONFIGURATION_STATIC] = "static",
1245 [KEEP_CONFIGURATION_YES] = "yes",
1246 };
1247
1248 DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(keep_configuration, KeepConfiguration, KEEP_CONFIGURATION_YES);