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