]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/network/networkd-network.c
network: Fix "Unknown section 'DHCPv6PrefixDelegation'." message
[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"
518cd6b5 19#include "networkd-sriov.h"
6bedfcbb 20#include "parse-util.h"
b0c82192 21#include "path-lookup.h"
8a516214 22#include "set.h"
cebe1257 23#include "socket-util.h"
8fcde012 24#include "stat-util.h"
8b43440b 25#include "string-table.h"
07630cea 26#include "string-util.h"
700f1186 27#include "strv.h"
34658df2 28#include "tc.h"
07630cea 29#include "util.h"
f579559b 30
c448459d
ZJS
31/* Let's assume that anything above this number is a user misconfiguration. */
32#define MAX_NTP_SERVERS 128
33
add8d07d 34/* Set defaults following RFC7844 */
35void network_apply_anonymize_if_set(Network *network) {
36 if (!network->dhcp_anonymize)
37 return;
38 /* RFC7844 3.7
39 SHOULD NOT send the Host Name option */
40 network->dhcp_send_hostname = false;
41 /* RFC7844 section 3.:
42 MAY contain the Client Identifier option
43 Section 3.5:
44 clients MUST use client identifiers based solely
45 on the link-layer address */
46 /* NOTE: Using MAC, as it does not reveal extra information,
47 * and some servers might not answer if this option is not sent */
48 network->dhcp_client_identifier = DHCP_CLIENT_ID_MAC;
49 /* RFC 7844 3.10:
50 SHOULD NOT use the Vendor Class Identifier option */
727ba17f 51 network->dhcp_vendor_class_identifier = mfree(network->dhcp_vendor_class_identifier);
add8d07d 52 /* RFC7844 section 3.6.:
53 The client intending to protect its privacy SHOULD only request a
54 minimal number of options in the PRL and SHOULD also randomly shuffle
43bf2874 55 the ordering of option codes in the PRL. If this random ordering
add8d07d 56 cannot be implemented, the client MAY order the option codes in the
57 PRL by option code number (lowest to highest).
58 */
59 /* NOTE: dhcp_use_mtu is false by default,
60 * though it was not initiallized to any value in network_load_one.
61 * Maybe there should be another var called *send*?
62 * (to use the MTU sent by the server but to do not send
63 * the option in the PRL). */
64 network->dhcp_use_mtu = false;
28522b0d 65 /* NOTE: when Anonymize=yes, the PRL route options are sent by default,
66 * but this is needed to use them. */
67 network->dhcp_use_routes = true;
add8d07d 68 /* RFC7844 section 3.6.
69 * same comments as previous option */
70 network->dhcp_use_timezone = false;
71}
72
cebe1257
YW
73static int network_resolve_netdev_one(Network *network, const char *name, NetDevKind kind, NetDev **ret_netdev) {
74 const char *kind_string;
75 NetDev *netdev;
76 int r;
77
96db6412
YW
78 /* For test-networkd-conf, the check must be earlier than the assertions. */
79 if (!name)
80 return 0;
81
cebe1257
YW
82 assert(network);
83 assert(network->manager);
84 assert(network->filename);
85 assert(ret_netdev);
86
cebe1257
YW
87 if (kind == _NETDEV_KIND_TUNNEL)
88 kind_string = "tunnel";
89 else {
90 kind_string = netdev_kind_to_string(kind);
91 if (!kind_string)
92 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
93 "%s: Invalid NetDev kind of %s, ignoring assignment.",
94 network->filename, name);
95 }
96
97 r = netdev_get(network->manager, name, &netdev);
98 if (r < 0)
99 return log_error_errno(r, "%s: %s NetDev could not be found, ignoring assignment.",
100 network->filename, name);
101
102 if (netdev->kind != kind && !(kind == _NETDEV_KIND_TUNNEL &&
103 IN_SET(netdev->kind,
104 NETDEV_KIND_IPIP,
105 NETDEV_KIND_SIT,
106 NETDEV_KIND_GRE,
107 NETDEV_KIND_GRETAP,
108 NETDEV_KIND_IP6GRE,
109 NETDEV_KIND_IP6GRETAP,
110 NETDEV_KIND_VTI,
111 NETDEV_KIND_VTI6,
9282f75b
YW
112 NETDEV_KIND_IP6TNL,
113 NETDEV_KIND_ERSPAN)))
cebe1257
YW
114 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
115 "%s: NetDev %s is not a %s, ignoring assignment",
116 network->filename, name, kind_string);
117
118 *ret_netdev = netdev_ref(netdev);
119 return 1;
120}
121
122static int network_resolve_stacked_netdevs(Network *network) {
123 void *name, *kind;
124 Iterator i;
125 int r;
126
127 assert(network);
128
129 HASHMAP_FOREACH_KEY(kind, name, network->stacked_netdev_names, i) {
130 _cleanup_(netdev_unrefp) NetDev *netdev = NULL;
131
132 r = network_resolve_netdev_one(network, name, PTR_TO_INT(kind), &netdev);
133 if (r <= 0)
134 continue;
135
136 r = hashmap_ensure_allocated(&network->stacked_netdevs, &string_hash_ops);
137 if (r < 0)
138 return log_oom();
139
140 r = hashmap_put(network->stacked_netdevs, netdev->ifname, netdev);
141 if (r < 0)
142 return log_error_errno(r, "%s: Failed to add NetDev '%s' to network: %m",
143 network->filename, (const char *) name);
144
145 netdev = NULL;
146 }
147
148 return 0;
149}
150
96db6412 151int network_verify(Network *network) {
95081e08 152 RoutePrefix *route_prefix, *route_prefix_next;
564ca984 153 RoutingPolicyRule *rule, *rule_next;
fcbf4cb7
YW
154 Neighbor *neighbor, *neighbor_next;
155 AddressLabel *label, *label_next;
c16c7808 156 NextHop *nexthop, *nextnop_next;
564ca984
SS
157 Address *address, *address_next;
158 Prefix *prefix, *prefix_next;
159 Route *route, *route_next;
160 FdbEntry *fdb, *fdb_next;
34658df2 161 TrafficControl *tc;
518cd6b5 162 SRIOV *sr_iov;
8efb93f0 163 Iterator i;
0321cea7
YW
164
165 assert(network);
166 assert(network->filename);
167
4bb7cc82
YW
168 if (set_isempty(network->match_mac) && set_isempty(network->match_permanent_mac) &&
169 strv_isempty(network->match_path) && strv_isempty(network->match_driver) &&
170 strv_isempty(network->match_type) && strv_isempty(network->match_name) &&
25c86e4c
DDM
171 strv_isempty(network->match_property) && strv_isempty(network->match_wlan_iftype) &&
172 strv_isempty(network->match_ssid) && !network->conditions)
dade7349
ZJS
173 return log_warning_errno(SYNTHETIC_ERRNO(EINVAL),
174 "%s: No valid settings found in the [Match] section, ignoring file. "
175 "To match all interfaces, add Name=* in the [Match] section.",
176 network->filename);
84ea567e 177
cebe1257 178 /* skip out early if configuration does not match the environment */
a0b191b7 179 if (!condition_test_list(network->conditions, environ, NULL, NULL, NULL))
cebe1257 180 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL),
3772cfde
ZJS
181 "%s: Conditions in the file do not match the system environment, skipping.",
182 network->filename);
cebe1257
YW
183
184 (void) network_resolve_netdev_one(network, network->bond_name, NETDEV_KIND_BOND, &network->bond);
185 (void) network_resolve_netdev_one(network, network->bridge_name, NETDEV_KIND_BRIDGE, &network->bridge);
186 (void) network_resolve_netdev_one(network, network->vrf_name, NETDEV_KIND_VRF, &network->vrf);
187 (void) network_resolve_stacked_netdevs(network);
188
189 /* Free unnecessary entries. */
190 network->bond_name = mfree(network->bond_name);
191 network->bridge_name = mfree(network->bridge_name);
192 network->vrf_name = mfree(network->vrf_name);
193 network->stacked_netdev_names = hashmap_free_free_key(network->stacked_netdev_names);
194
0321cea7
YW
195 if (network->bond) {
196 /* Bonding slave does not support addressing. */
197 if (network->ipv6_accept_ra > 0) {
ab24039f
ZJS
198 log_warning("%s: Cannot enable IPv6AcceptRA= when Bond= is specified, disabling IPv6AcceptRA=.",
199 network->filename);
0321cea7
YW
200 network->ipv6_accept_ra = 0;
201 }
202 if (network->link_local >= 0 && network->link_local != ADDRESS_FAMILY_NO) {
ab24039f
ZJS
203 log_warning("%s: Cannot enable LinkLocalAddressing= when Bond= is specified, disabling LinkLocalAddressing=.",
204 network->filename);
0321cea7
YW
205 network->link_local = ADDRESS_FAMILY_NO;
206 }
207 if (network->dhcp != ADDRESS_FAMILY_NO) {
ab24039f
ZJS
208 log_warning("%s: Cannot enable DHCP= when Bond= is specified, disabling DHCP=.",
209 network->filename);
0321cea7
YW
210 network->dhcp = ADDRESS_FAMILY_NO;
211 }
212 if (network->dhcp_server) {
ab24039f
ZJS
213 log_warning("%s: Cannot enable DHCPServer= when Bond= is specified, disabling DHCPServer=.",
214 network->filename);
0321cea7
YW
215 network->dhcp_server = false;
216 }
217 if (network->n_static_addresses > 0) {
ab24039f
ZJS
218 log_warning("%s: Cannot set addresses when Bond= is specified, ignoring addresses.",
219 network->filename);
0321cea7
YW
220 while ((address = network->static_addresses))
221 address_free(address);
222 }
223 if (network->n_static_routes > 0) {
ab24039f
ZJS
224 log_warning("%s: Cannot set routes when Bond= is specified, ignoring routes.",
225 network->filename);
0321cea7
YW
226 while ((route = network->static_routes))
227 route_free(route);
228 }
229 }
230
231 if (network->link_local < 0)
8f191801
YW
232 network->link_local = network->bridge ? ADDRESS_FAMILY_NO : ADDRESS_FAMILY_IPV6;
233
44013aa4
YW
234 if (!FLAGS_SET(network->link_local, ADDRESS_FAMILY_IPV6)) {
235 if (network->ipv6_accept_ra > 0) {
236 log_warning("%s: IPv6AcceptRA= is enabled by the .network file but IPv6 link local addressing is disabled. "
237 "Disabling IPv6AcceptRA=.", network->filename);
238 network->ipv6_accept_ra = false;
239 }
240
241 if (FLAGS_SET(network->dhcp, ADDRESS_FAMILY_IPV6)) {
242 log_warning("%s: DHCPv6 client is enabled by the .network file but IPv6 link local addressing is disabled. "
243 "Disabling DHCPv6 client.", network->filename);
244 SET_FLAG(network->dhcp, ADDRESS_FAMILY_IPV6, false);
245 }
246
247 if (network->router_prefix_delegation != RADV_PREFIX_DELEGATION_NONE) {
248 log_warning("%s: IPv6PrefixDelegation= is enabled but IPv6 link local addressing is disabled. "
249 "Disabling IPv6PrefixDelegation=.", network->filename);
250 network->router_prefix_delegation = RADV_PREFIX_DELEGATION_NONE;
251 }
252 }
253
29e81083
YW
254 if (FLAGS_SET(network->link_local, ADDRESS_FAMILY_FALLBACK_IPV4) &&
255 !FLAGS_SET(network->dhcp, ADDRESS_FAMILY_IPV4)) {
256 log_warning("%s: fallback assignment of IPv4 link local address is enabled but DHCPv4 is disabled. "
257 "Disabling the fallback assignment.", network->filename);
258 SET_FLAG(network->link_local, ADDRESS_FAMILY_FALLBACK_IPV4, false);
259 }
260
8f191801
YW
261 if (network->ipv6_accept_ra < 0 && network->bridge)
262 network->ipv6_accept_ra = false;
0321cea7
YW
263
264 /* IPMasquerade=yes implies IPForward=yes */
265 if (network->ip_masquerade)
266 network->ip_forward |= ADDRESS_FAMILY_IPV4;
267
933c70a0 268 if (network->mtu > 0 && network->dhcp_use_mtu) {
0321cea7
YW
269 log_warning("%s: MTUBytes= in [Link] section and UseMTU= in [DHCP] section are set. "
270 "Disabling UseMTU=.", network->filename);
271 network->dhcp_use_mtu = false;
272 }
273
589397a2
DS
274 if (network->dhcp_use_gateway < 0)
275 network->dhcp_use_gateway = network->dhcp_use_routes;
276
bd0d471c
DS
277 if (network->ignore_carrier_loss < 0)
278 network->ignore_carrier_loss = network->configure_without_carrier;
279
7da377ef
SS
280 if (network->dhcp_critical >= 0) {
281 if (network->keep_configuration >= 0)
282 log_warning("%s: Both KeepConfiguration= and deprecated CriticalConnection= are set. "
283 "Ignoring CriticalConnection=.", network->filename);
284 else if (network->dhcp_critical)
285 /* CriticalConnection=yes also preserve foreign static configurations. */
286 network->keep_configuration = KEEP_CONFIGURATION_YES;
287 else
80060352 288 network->keep_configuration = KEEP_CONFIGURATION_NO;
7da377ef
SS
289 }
290
291 if (network->keep_configuration < 0)
80060352 292 network->keep_configuration = KEEP_CONFIGURATION_NO;
7da377ef 293
4bec2f23 294 LIST_FOREACH_SAFE(addresses, address, address_next, network->static_addresses)
fcbf4cb7 295 if (address_section_verify(address) < 0)
4bec2f23 296 address_free(address);
4bec2f23 297
fcbf4cb7
YW
298 LIST_FOREACH_SAFE(routes, route, route_next, network->static_routes)
299 if (route_section_verify(route, network) < 0)
4bec2f23 300 route_free(route);
0321cea7 301
c16c7808
SS
302 LIST_FOREACH_SAFE(nexthops, nexthop, nextnop_next, network->static_nexthops)
303 if (nexthop_section_verify(nexthop) < 0)
304 nexthop_free(nexthop);
305
fcbf4cb7
YW
306 LIST_FOREACH_SAFE(static_fdb_entries, fdb, fdb_next, network->static_fdb_entries)
307 if (section_is_invalid(fdb->section))
308 fdb_entry_free(fdb);
309
310 LIST_FOREACH_SAFE(neighbors, neighbor, neighbor_next, network->neighbors)
044d4b40 311 if (neighbor_section_verify(neighbor) < 0)
fcbf4cb7
YW
312 neighbor_free(neighbor);
313
314 LIST_FOREACH_SAFE(labels, label, label_next, network->address_labels)
315 if (section_is_invalid(label->section))
316 address_label_free(label);
317
318 LIST_FOREACH_SAFE(prefixes, prefix, prefix_next, network->static_prefixes)
319 if (section_is_invalid(prefix->section))
320 prefix_free(prefix);
321
95081e08
YW
322 LIST_FOREACH_SAFE(route_prefixes, route_prefix, route_prefix_next, network->static_route_prefixes)
323 if (section_is_invalid(route_prefix->section))
324 route_prefix_free(route_prefix);
714a199e 325
fcbf4cb7 326 LIST_FOREACH_SAFE(rules, rule, rule_next, network->rules)
0aabccc8 327 if (routing_policy_rule_section_verify(rule) < 0)
fcbf4cb7 328 routing_policy_rule_free(rule);
4912ab77 329
8efb93f0 330 bool has_root = false, has_clsact = false;
34658df2
YW
331 ORDERED_HASHMAP_FOREACH(tc, network->tc_by_section, i)
332 if (traffic_control_section_verify(tc, &has_root, &has_clsact) < 0)
333 traffic_control_free(tc);
8efb93f0 334
518cd6b5
SS
335 ORDERED_HASHMAP_FOREACH(sr_iov, network->sr_iov_by_section, i)
336 if (sr_iov_section_verify(sr_iov) < 0)
337 sr_iov_free(sr_iov);
338
0321cea7
YW
339 return 0;
340}
341
7f06b3e1 342int network_load_one(Manager *manager, OrderedHashmap **networks, const char *filename) {
838b2f7a 343 _cleanup_free_ char *fname = NULL, *name = NULL;
35ac3b76 344 _cleanup_(network_unrefp) Network *network = NULL;
f579559b 345 _cleanup_fclose_ FILE *file = NULL;
047a0dac 346 const char *dropin_dirname;
838b2f7a 347 char *d;
f579559b
TG
348 int r;
349
bf1bc670
TA
350 assert(manager);
351 assert(filename);
352
f579559b
TG
353 file = fopen(filename, "re");
354 if (!file) {
355 if (errno == ENOENT)
356 return 0;
1e7a0e21
LP
357
358 return -errno;
f579559b
TG
359 }
360
ed88bcfb
ZJS
361 if (null_or_empty_fd(fileno(file))) {
362 log_debug("Skipping empty file: %s", filename);
6916ec29
TG
363 return 0;
364 }
365
838b2f7a
YW
366 fname = strdup(filename);
367 if (!fname)
368 return log_oom();
369
370 name = strdup(basename(filename));
371 if (!name)
372 return log_oom();
373
374 d = strrchr(name, '.');
375 if (!d)
376 return -EINVAL;
377
378 *d = '\0';
379
380 dropin_dirname = strjoina(name, ".network.d");
381
17f9c355 382 network = new(Network, 1);
f579559b
TG
383 if (!network)
384 return log_oom();
385
17f9c355 386 *network = (Network) {
838b2f7a
YW
387 .filename = TAKE_PTR(fname),
388 .name = TAKE_PTR(name),
17f9c355 389
715d398e 390 .manager = manager,
35ac3b76
YW
391 .n_ref = 1,
392
17f9c355 393 .required_for_online = true,
75cd4a5d 394 .required_operstate_for_online = LINK_OPERSTATE_RANGE_DEFAULT,
17f9c355 395 .dhcp = ADDRESS_FAMILY_NO,
7da377ef 396 .dhcp_critical = -1,
17f9c355 397 .dhcp_use_ntp = true,
299d578f 398 .dhcp_use_sip = true,
17f9c355
YW
399 .dhcp_use_dns = true,
400 .dhcp_use_hostname = true,
401 .dhcp_use_routes = true,
589397a2 402 .dhcp_use_gateway = -1,
5238e957 403 /* NOTE: this var might be overwritten by network_apply_anonymize_if_set */
17f9c355 404 .dhcp_send_hostname = true,
5f3b5f19 405 .dhcp_send_release = true,
17f9c355
YW
406 /* To enable/disable RFC7844 Anonymity Profiles */
407 .dhcp_anonymize = false,
408 .dhcp_route_metric = DHCP_ROUTE_METRIC,
c9c908a6 409 /* NOTE: this var might be overwritten by network_apply_anonymize_if_set */
17f9c355
YW
410 .dhcp_client_identifier = DHCP_CLIENT_ID_DUID,
411 .dhcp_route_table = RT_TABLE_MAIN,
412 .dhcp_route_table_set = false,
413 /* NOTE: from man: UseMTU=... Defaults to false*/
414 .dhcp_use_mtu = false,
415 /* NOTE: from man: UseTimezone=... Defaults to "no".*/
416 .dhcp_use_timezone = false,
417 .rapid_commit = true,
418
1bf1bfd9 419 .dhcp6_route_metric = DHCP_ROUTE_METRIC,
caa8ca42
SS
420 .dhcp6_use_ntp = true,
421 .dhcp6_use_dns = true,
422
99e015e2
YW
423 .dhcp6_pd_subnet_id = -1,
424 .dhcp6_pd_assign = true,
9efa8a3c 425
2a71d57f
LP
426 .dhcp_server_emit[SD_DHCP_LEASE_DNS].emit = true,
427 .dhcp_server_emit[SD_DHCP_LEASE_NTP].emit = true,
428 .dhcp_server_emit[SD_DHCP_LEASE_SIP].emit = true,
429
17f9c355
YW
430 .dhcp_server_emit_router = true,
431 .dhcp_server_emit_timezone = true,
432
433 .router_emit_dns = true,
434 .router_emit_domains = true,
435
436 .use_bpdu = -1,
437 .hairpin = -1,
438 .fast_leave = -1,
439 .allow_port_to_be_root = -1,
440 .unicast_flood = -1,
7f15b714 441 .multicast_flood = -1,
d3aa8b49 442 .multicast_to_unicast = -1,
7f15b714
TJ
443 .neighbor_suppression = -1,
444 .learning = -1,
1087623b
SS
445 .bridge_proxy_arp = -1,
446 .bridge_proxy_arp_wifi = -1,
17f9c355 447 .priority = LINK_BRIDGE_PORT_PRIORITY_INVALID,
0fadb2a4 448 .multicast_router = _MULTICAST_ROUTER_INVALID,
17f9c355
YW
449
450 .lldp_mode = LLDP_MODE_ROUTERS_ONLY,
451
7ece6f58 452 .dns_default_route = -1,
17f9c355
YW
453 .llmnr = RESOLVE_SUPPORT_YES,
454 .mdns = RESOLVE_SUPPORT_NO,
455 .dnssec_mode = _DNSSEC_MODE_INVALID,
456 .dns_over_tls_mode = _DNS_OVER_TLS_MODE_INVALID,
457
0321cea7 458 /* If LinkLocalAddressing= is not set, then set to ADDRESS_FAMILY_IPV6 later. */
2d792895 459 .link_local = _ADDRESS_FAMILY_INVALID,
6f6296b9 460 .ipv6ll_address_gen_mode = _IPV6_LINK_LOCAL_ADDRESS_GEN_MODE_INVALID,
17f9c355 461
94d76d07
YW
462 .ipv4_accept_local = -1,
463
17f9c355
YW
464 .ipv6_privacy_extensions = IPV6_PRIVACY_EXTENSIONS_NO,
465 .ipv6_accept_ra = -1,
466 .ipv6_dad_transmits = -1,
467 .ipv6_hop_limit = -1,
468 .ipv6_proxy_ndp = -1,
469 .duid.type = _DUID_TYPE_INVALID,
470 .proxy_arp = -1,
471 .arp = -1,
472 .multicast = -1,
473 .allmulticast = -1,
474 .ipv6_accept_ra_use_dns = true,
062c2eea
SS
475 .ipv6_accept_ra_use_autonomous_prefix = true,
476 .ipv6_accept_ra_use_onlink_prefix = true,
17f9c355 477 .ipv6_accept_ra_route_table = RT_TABLE_MAIN,
d5fa3339 478 .ipv6_accept_ra_route_table_set = false,
d739fdde 479 .ipv6_accept_ra_start_dhcp6_client = true,
c423be28 480
bd0d471c
DS
481 .configure_without_carrier = false,
482 .ignore_carrier_loss = -1,
7da377ef 483 .keep_configuration = _KEEP_CONFIGURATION_INVALID,
c423be28 484 .can_triple_sampling = -1,
52aa38f1 485 .can_termination = -1,
afe42aef 486 .ip_service_type = -1,
17f9c355 487 };
f579559b 488
4f9ff96a
LP
489 r = config_parse_many(
490 filename, NETWORK_DIRS, dropin_dirname,
491 "Match\0"
492 "Link\0"
518cd6b5 493 "SR-IOV\0"
4f9ff96a
LP
494 "Network\0"
495 "Address\0"
496 "Neighbor\0"
497 "IPv6AddressLabel\0"
498 "RoutingPolicyRule\0"
499 "Route\0"
500 "NextHop\0"
501 "DHCP\0" /* compat */
502 "DHCPv4\0"
503 "DHCPv6\0"
b209cff2 504 "DHCPv6PrefixDelegation\0"
4f9ff96a
LP
505 "DHCPServer\0"
506 "IPv6AcceptRA\0"
507 "IPv6NDPProxyAddress\0"
508 "Bridge\0"
509 "BridgeFDB\0"
510 "BridgeVLAN\0"
511 "IPv6PrefixDelegation\0"
512 "IPv6Prefix\0"
513 "IPv6RoutePrefix\0"
514 "LLDP\0"
515 "TrafficControlQueueingDiscipline\0"
516 "CAN\0"
517 "QDisc\0"
518 "BFIFO\0"
519 "CAKE\0"
520 "ControlledDelay\0"
521 "DeficitRoundRobinScheduler\0"
522 "DeficitRoundRobinSchedulerClass\0"
d474aa51 523 "EnhancedTransmissionSelection\0"
4f9ff96a
LP
524 "FairQueueing\0"
525 "FairQueueingControlledDelay\0"
526 "GenericRandomEarlyDetection\0"
527 "HeavyHitterFilter\0"
528 "HierarchyTokenBucket\0"
529 "HierarchyTokenBucketClass\0"
530 "NetworkEmulator\0"
b12aaee5
SS
531 "PFIFO\0"
532 "PFIFOFast\0"
533 "PFIFOHeadDrop\0"
4f9ff96a 534 "PIE\0"
b12aaee5 535 "QuickFairQueueing\0"
4d7ddaf9 536 "QuickFairQueueingClass\0"
4f9ff96a
LP
537 "StochasticFairBlue\0"
538 "StochasticFairnessQueueing\0"
539 "TokenBucketFilter\0"
540 "TrivialLinkEqualizer\0",
541 config_item_perf_lookup, network_network_gperf_lookup,
542 CONFIG_PARSE_WARN,
543 network,
544 &network->timestamp);
102bc043 545 if (r < 0)
f579559b 546 return r;
f579559b 547
add8d07d 548 network_apply_anonymize_if_set(network);
549
fa7cd711
YW
550 r = network_add_ipv4ll_route(network);
551 if (r < 0)
552 log_warning_errno(r, "%s: Failed to add IPv4LL route, ignoring: %m", network->filename);
553
5d5003ab
YW
554 r = network_add_default_route_on_device(network);
555 if (r < 0)
556 log_warning_errno(r, "%s: Failed to add default route on device, ignoring: %m",
557 network->filename);
558
7f06b3e1
YW
559 if (network_verify(network) < 0)
560 /* Ignore .network files that do not match the conditions. */
561 return 0;
562
563 r = ordered_hashmap_ensure_allocated(networks, &string_hash_ops);
dbffab87
TG
564 if (r < 0)
565 return r;
566
7f06b3e1 567 r = ordered_hashmap_put(*networks, network->name, network);
dbffab87
TG
568 if (r < 0)
569 return r;
570
f579559b 571 network = NULL;
f579559b
TG
572 return 0;
573}
574
7f06b3e1 575int network_load(Manager *manager, OrderedHashmap **networks) {
477e73b5
ZJS
576 _cleanup_strv_free_ char **files = NULL;
577 char **f;
f579559b
TG
578 int r;
579
580 assert(manager);
581
7f06b3e1 582 ordered_hashmap_clear_with_destructor(*networks, network_unref);
f579559b 583
dc0d4078 584 r = conf_files_list_strv(&files, ".network", NULL, 0, NETWORK_DIRS);
f647962d
MS
585 if (r < 0)
586 return log_error_errno(r, "Failed to enumerate network files: %m");
f579559b 587
715d398e 588 STRV_FOREACH(f, files) {
7f06b3e1 589 r = network_load_one(manager, networks, *f);
f579559b 590 if (r < 0)
be711082 591 log_error_errno(r, "Failed to load %s, ignoring: %m", *f);
f579559b
TG
592 }
593
f579559b
TG
594 return 0;
595}
596
7f06b3e1
YW
597int network_reload(Manager *manager) {
598 OrderedHashmap *new_networks = NULL;
599 Network *n, *old;
600 Iterator i;
601 int r;
602
603 assert(manager);
604
605 r = network_load(manager, &new_networks);
606 if (r < 0)
607 goto failure;
608
609 ORDERED_HASHMAP_FOREACH(n, new_networks, i) {
610 r = network_get_by_name(manager, n->name, &old);
611 if (r < 0)
612 continue; /* The .network file is new. */
613
614 if (n->timestamp != old->timestamp)
615 continue; /* The .network file is modified. */
616
617 if (!streq(n->filename, old->filename))
618 continue;
619
620 r = ordered_hashmap_replace(new_networks, old->name, old);
621 if (r < 0)
622 goto failure;
623
624 network_ref(old);
625 network_unref(n);
626 }
627
628 ordered_hashmap_free_with_destructor(manager->networks, network_unref);
629 manager->networks = new_networks;
630
631 return 0;
632
633failure:
634 ordered_hashmap_free_with_destructor(new_networks, network_unref);
635
636 return r;
637}
638
35ac3b76 639static Network *network_free(Network *network) {
a0e5c15d 640 IPv6ProxyNDPAddress *ipv6_proxy_ndp_address;
95081e08 641 RoutePrefix *route_prefix;
bce67bbe 642 RoutingPolicyRule *rule;
95081e08 643 AddressLabel *label;
bce67bbe 644 FdbEntry *fdb_entry;
e4a71bf3 645 Neighbor *neighbor;
bce67bbe 646 Address *address;
c16c7808
SS
647 NextHop *nexthop;
648 Prefix *prefix;
bce67bbe 649 Route *route;
f579559b
TG
650
651 if (!network)
35ac3b76 652 return NULL;
f579559b
TG
653
654 free(network->filename);
655
e90d0374 656 set_free_free(network->match_mac);
4bb7cc82 657 set_free_free(network->match_permanent_mac);
5256e00e
TG
658 strv_free(network->match_path);
659 strv_free(network->match_driver);
660 strv_free(network->match_type);
661 strv_free(network->match_name);
44005bfb 662 strv_free(network->match_property);
78404d22 663 strv_free(network->match_wlan_iftype);
8d968fdd 664 strv_free(network->match_ssid);
277ba8d1 665 set_free_free(network->match_bssid);
c4f58dea 666 condition_free_list(network->conditions);
f579559b
TG
667
668 free(network->description);
edb85f0d 669 free(network->dhcp_vendor_class_identifier);
7b8d23a9 670 free(network->dhcp_mudurl);
af1c0de0 671 strv_free(network->dhcp_user_class);
27cb34f5 672 free(network->dhcp_hostname);
6b000af4 673 set_free(network->dhcp_deny_listed_ip);
98ebef62 674 set_free(network->dhcp_allow_listed_ip);
5bc945be 675 set_free(network->dhcp_request_options);
35f6a5cb 676 set_free(network->dhcp6_request_options);
c106cc36 677 free(network->mac);
3175a8c2 678 free(network->dhcp6_mudurl);
f37f2a6b 679 strv_free(network->dhcp6_user_class);
ed0d1b2e 680 strv_free(network->dhcp6_vendor_class);
c106cc36 681
0f3ff4ea
SS
682 if (network->dhcp_acd)
683 sd_ipv4acd_unref(network->dhcp_acd);
684
b0e39c82 685 strv_free(network->ntp);
e77bd3fd
YW
686 for (unsigned i = 0; i < network->n_dns; i++)
687 in_addr_full_free(network->dns[i]);
5512a963 688 free(network->dns);
5e2a51d5
ZJS
689 ordered_set_free_free(network->search_domains);
690 ordered_set_free_free(network->route_domains);
0d4ad91d 691 strv_free(network->bind_carrier);
cdd7812b 692
5e2a51d5 693 ordered_set_free_free(network->router_search_domains);
cdd7812b 694 free(network->router_dns);
6b000af4 695 set_free_free(network->ndisc_deny_listed_prefix);
3bef724f 696
cebe1257
YW
697 free(network->bridge_name);
698 free(network->bond_name);
699 free(network->vrf_name);
700 hashmap_free_free_key(network->stacked_netdev_names);
47e2dc31 701 netdev_unref(network->bridge);
47e2dc31 702 netdev_unref(network->bond);
6cb955c6 703 netdev_unref(network->vrf);
fa6f1e54 704 hashmap_free_with_destructor(network->stacked_netdevs, netdev_unref);
326cb406 705
f048a16b 706 while ((route = network->static_routes))
f579559b
TG
707 route_free(route);
708
c16c7808
SS
709 while ((nexthop = network->static_nexthops))
710 nexthop_free(nexthop);
711
f048a16b 712 while ((address = network->static_addresses))
f579559b
TG
713 address_free(address);
714
b98b483b
AR
715 while ((fdb_entry = network->static_fdb_entries))
716 fdb_entry_free(fdb_entry);
717
a0e5c15d
FK
718 while ((ipv6_proxy_ndp_address = network->ipv6_proxy_ndp_addresses))
719 ipv6_proxy_ndp_address_free(ipv6_proxy_ndp_address);
720
e4a71bf3
WKI
721 while ((neighbor = network->neighbors))
722 neighbor_free(neighbor);
723
95b74ef6
SS
724 while ((label = network->address_labels))
725 address_label_free(label);
726
057abfd8
PF
727 while ((prefix = network->static_prefixes))
728 prefix_free(prefix);
729
95081e08
YW
730 while ((route_prefix = network->static_route_prefixes))
731 route_prefix_free(route_prefix);
9be6ae77 732
bce67bbe
SS
733 while ((rule = network->rules))
734 routing_policy_rule_free(rule);
735
6ae115c1
TG
736 hashmap_free(network->addresses_by_section);
737 hashmap_free(network->routes_by_section);
c16c7808 738 hashmap_free(network->nexthops_by_section);
b98b483b 739 hashmap_free(network->fdb_entries_by_section);
e4a71bf3 740 hashmap_free(network->neighbors_by_section);
95b74ef6 741 hashmap_free(network->address_labels_by_section);
057abfd8 742 hashmap_free(network->prefixes_by_section);
9be6ae77 743 hashmap_free(network->route_prefixes_by_section);
bce67bbe 744 hashmap_free(network->rules_by_section);
518cd6b5 745 ordered_hashmap_free_with_destructor(network->sr_iov_by_section, sr_iov_free);
34658df2 746 ordered_hashmap_free_with_destructor(network->tc_by_section, traffic_control_free);
6ae115c1 747
7f06b3e1
YW
748 if (network->manager &&
749 network->manager->duids_requesting_uuid)
750 set_remove(network->manager->duids_requesting_uuid, &network->duid);
dbffab87
TG
751
752 free(network->name);
f579559b 753
8eb9058d 754 free(network->dhcp_server_timezone);
2a71d57f
LP
755
756 for (sd_dhcp_lease_server_type t = 0; t < _SD_DHCP_LEASE_SERVER_TYPE_MAX; t++)
757 free(network->dhcp_server_emit[t].addresses);
8eb9058d 758
8a516214
LP
759 set_free_free(network->dnssec_negative_trust_anchors);
760
e9a8c550
SS
761 free(network->lldp_mud);
762
0e96961d 763 ordered_hashmap_free(network->dhcp_client_send_options);
7354900d 764 ordered_hashmap_free(network->dhcp_client_send_vendor_options);
0e96961d 765 ordered_hashmap_free(network->dhcp_server_send_options);
7354900d 766 ordered_hashmap_free(network->dhcp_server_send_vendor_options);
2c621495 767 ordered_set_free(network->ipv6_tokens);
1c3ec1cd 768 ordered_hashmap_free(network->dhcp6_client_send_options);
b4ccc5de 769 ordered_hashmap_free(network->dhcp6_client_send_vendor_options);
cb29c156 770
35ac3b76 771 return mfree(network);
f579559b
TG
772}
773
35ac3b76
YW
774DEFINE_TRIVIAL_REF_UNREF_FUNC(Network, network, network_free);
775
dbffab87
TG
776int network_get_by_name(Manager *manager, const char *name, Network **ret) {
777 Network *network;
778
779 assert(manager);
780 assert(name);
781 assert(ret);
782
715d398e 783 network = ordered_hashmap_get(manager->networks, name);
dbffab87
TG
784 if (!network)
785 return -ENOENT;
786
787 *ret = network;
788
789 return 0;
790}
791
ef62949a 792int network_get(Manager *manager, unsigned short iftype, sd_device *device,
c643bda5
YW
793 const char *ifname, char * const *alternative_names, const char *driver,
794 const struct ether_addr *mac, const struct ether_addr *permanent_mac,
78404d22
YW
795 enum nl80211_iftype wlan_iftype, const char *ssid, const struct ether_addr *bssid,
796 Network **ret) {
51517f9e 797 Network *network;
715d398e 798 Iterator i;
f579559b
TG
799
800 assert(manager);
f579559b 801 assert(ret);
af3aa302 802
715d398e 803 ORDERED_HASHMAP_FOREACH(network, manager->networks, i)
4bb7cc82
YW
804 if (net_match_config(network->match_mac, network->match_permanent_mac,
805 network->match_path, network->match_driver,
44005bfb 806 network->match_type, network->match_name, network->match_property,
78404d22 807 network->match_wlan_iftype, network->match_ssid, network->match_bssid,
c643bda5 808 device, mac, permanent_mac, driver, iftype,
4bb7cc82 809 ifname, alternative_names, wlan_iftype, ssid, bssid)) {
24c083df 810 if (network->match_name && device) {
ca6038b8
TG
811 const char *attr;
812 uint8_t name_assign_type = NET_NAME_UNKNOWN;
813
51517f9e 814 if (sd_device_get_sysattr_value(device, "name_assign_type", &attr) >= 0)
dc751688 815 (void) safe_atou8(attr, &name_assign_type);
32bc8adc
TG
816
817 if (name_assign_type == NET_NAME_ENUM)
a2fae7bb
TG
818 log_warning("%s: found matching network '%s', based on potentially unpredictable ifname",
819 ifname, network->filename);
32bc8adc 820 else
a2fae7bb 821 log_debug("%s: found matching network '%s'", ifname, network->filename);
32bc8adc 822 } else
a2fae7bb 823 log_debug("%s: found matching network '%s'", ifname, network->filename);
32bc8adc 824
f579559b
TG
825 *ret = network;
826 return 0;
827 }
f579559b
TG
828
829 *ret = NULL;
830
831 return -ENOENT;
832}
833
7d342c03 834int network_apply(Network *network, Link *link) {
c4a03a56
TG
835 assert(network);
836 assert(link);
837
c9c908a6 838 link->network = network_ref(network);
f579559b 839
5512a963 840 if (network->n_dns > 0 ||
3df9bec5 841 !strv_isempty(network->ntp) ||
5e2a51d5
ZJS
842 !ordered_set_isempty(network->search_domains) ||
843 !ordered_set_isempty(network->route_domains))
84de38c5 844 link_dirty(link);
3bef724f 845
f579559b
TG
846 return 0;
847}
02b59d57 848
adfeee49 849bool network_has_static_ipv6_configurations(Network *network) {
439689c6 850 Address *address;
adfeee49
YW
851 Route *route;
852 FdbEntry *fdb;
853 Neighbor *neighbor;
439689c6
SS
854
855 assert(network);
856
adfeee49 857 LIST_FOREACH(addresses, address, network->static_addresses)
439689c6
SS
858 if (address->family == AF_INET6)
859 return true;
adfeee49
YW
860
861 LIST_FOREACH(routes, route, network->static_routes)
862 if (route->family == AF_INET6)
863 return true;
864
865 LIST_FOREACH(static_fdb_entries, fdb, network->static_fdb_entries)
866 if (fdb->family == AF_INET6)
867 return true;
868
869 LIST_FOREACH(neighbors, neighbor, network->neighbors)
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");