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