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