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