]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/network/networkd-network.c
add other worthy news
[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"
0f5bd7fe 474 "TrafficControlQueueingDiscipline\0"
06828bb6 475 "CAN\0",
23bb31aa 476 config_item_perf_lookup, network_network_gperf_lookup,
bcde742e 477 CONFIG_PARSE_WARN, network);
102bc043 478 if (r < 0)
f579559b 479 return r;
f579559b 480
add8d07d 481 network_apply_anonymize_if_set(network);
482
fa7cd711
YW
483 r = network_add_ipv4ll_route(network);
484 if (r < 0)
485 log_warning_errno(r, "%s: Failed to add IPv4LL route, ignoring: %m", network->filename);
486
5d5003ab
YW
487 r = network_add_default_route_on_device(network);
488 if (r < 0)
489 log_warning_errno(r, "%s: Failed to add default route on device, ignoring: %m",
490 network->filename);
491
7f06b3e1
YW
492 struct stat stats;
493 if (stat(filename, &stats) < 0)
494 return -errno;
495 network->timestamp = timespec_load(&stats.st_mtim);
496
497 if (network_verify(network) < 0)
498 /* Ignore .network files that do not match the conditions. */
499 return 0;
500
501 r = ordered_hashmap_ensure_allocated(networks, &string_hash_ops);
dbffab87
TG
502 if (r < 0)
503 return r;
504
7f06b3e1 505 r = ordered_hashmap_put(*networks, network->name, network);
dbffab87
TG
506 if (r < 0)
507 return r;
508
f579559b 509 network = NULL;
f579559b
TG
510 return 0;
511}
512
7f06b3e1 513int network_load(Manager *manager, OrderedHashmap **networks) {
477e73b5
ZJS
514 _cleanup_strv_free_ char **files = NULL;
515 char **f;
f579559b
TG
516 int r;
517
518 assert(manager);
519
7f06b3e1 520 ordered_hashmap_clear_with_destructor(*networks, network_unref);
f579559b 521
dc0d4078 522 r = conf_files_list_strv(&files, ".network", NULL, 0, NETWORK_DIRS);
f647962d
MS
523 if (r < 0)
524 return log_error_errno(r, "Failed to enumerate network files: %m");
f579559b 525
715d398e 526 STRV_FOREACH(f, files) {
7f06b3e1 527 r = network_load_one(manager, networks, *f);
f579559b 528 if (r < 0)
be711082 529 log_error_errno(r, "Failed to load %s, ignoring: %m", *f);
f579559b
TG
530 }
531
f579559b
TG
532 return 0;
533}
534
7f06b3e1
YW
535int network_reload(Manager *manager) {
536 OrderedHashmap *new_networks = NULL;
537 Network *n, *old;
538 Iterator i;
539 int r;
540
541 assert(manager);
542
543 r = network_load(manager, &new_networks);
544 if (r < 0)
545 goto failure;
546
547 ORDERED_HASHMAP_FOREACH(n, new_networks, i) {
548 r = network_get_by_name(manager, n->name, &old);
549 if (r < 0)
550 continue; /* The .network file is new. */
551
552 if (n->timestamp != old->timestamp)
553 continue; /* The .network file is modified. */
554
555 if (!streq(n->filename, old->filename))
556 continue;
557
558 r = ordered_hashmap_replace(new_networks, old->name, old);
559 if (r < 0)
560 goto failure;
561
562 network_ref(old);
563 network_unref(n);
564 }
565
566 ordered_hashmap_free_with_destructor(manager->networks, network_unref);
567 manager->networks = new_networks;
568
569 return 0;
570
571failure:
572 ordered_hashmap_free_with_destructor(new_networks, network_unref);
573
574 return r;
575}
576
35ac3b76 577static Network *network_free(Network *network) {
a0e5c15d 578 IPv6ProxyNDPAddress *ipv6_proxy_ndp_address;
bce67bbe
SS
579 RoutingPolicyRule *rule;
580 FdbEntry *fdb_entry;
e4a71bf3 581 Neighbor *neighbor;
95b74ef6 582 AddressLabel *label;
bce67bbe 583 Address *address;
c16c7808
SS
584 NextHop *nexthop;
585 Prefix *prefix;
bce67bbe 586 Route *route;
f579559b
TG
587
588 if (!network)
35ac3b76 589 return NULL;
f579559b
TG
590
591 free(network->filename);
592
e90d0374 593 set_free_free(network->match_mac);
5256e00e
TG
594 strv_free(network->match_path);
595 strv_free(network->match_driver);
596 strv_free(network->match_type);
597 strv_free(network->match_name);
44005bfb 598 strv_free(network->match_property);
78404d22 599 strv_free(network->match_wlan_iftype);
8d968fdd 600 strv_free(network->match_ssid);
277ba8d1 601 set_free_free(network->match_bssid);
c4f58dea 602 condition_free_list(network->conditions);
f579559b
TG
603
604 free(network->description);
edb85f0d 605 free(network->dhcp_vendor_class_identifier);
af1c0de0 606 strv_free(network->dhcp_user_class);
27cb34f5 607 free(network->dhcp_hostname);
727b5734 608 set_free(network->dhcp_black_listed_ip);
5bc945be 609 set_free(network->dhcp_request_options);
c106cc36
TG
610 free(network->mac);
611
b0e39c82 612 strv_free(network->ntp);
5512a963 613 free(network->dns);
299d578f 614 strv_free(network->sip);
5e2a51d5
ZJS
615 ordered_set_free_free(network->search_domains);
616 ordered_set_free_free(network->route_domains);
0d4ad91d 617 strv_free(network->bind_carrier);
cdd7812b 618
5e2a51d5 619 ordered_set_free_free(network->router_search_domains);
cdd7812b 620 free(network->router_dns);
e520ce64 621 set_free_free(network->ndisc_black_listed_prefix);
3bef724f 622
cebe1257
YW
623 free(network->bridge_name);
624 free(network->bond_name);
625 free(network->vrf_name);
626 hashmap_free_free_key(network->stacked_netdev_names);
47e2dc31 627 netdev_unref(network->bridge);
47e2dc31 628 netdev_unref(network->bond);
6cb955c6 629 netdev_unref(network->vrf);
fa6f1e54 630 hashmap_free_with_destructor(network->stacked_netdevs, netdev_unref);
326cb406 631
f048a16b 632 while ((route = network->static_routes))
f579559b
TG
633 route_free(route);
634
c16c7808
SS
635 while ((nexthop = network->static_nexthops))
636 nexthop_free(nexthop);
637
f048a16b 638 while ((address = network->static_addresses))
f579559b
TG
639 address_free(address);
640
b98b483b
AR
641 while ((fdb_entry = network->static_fdb_entries))
642 fdb_entry_free(fdb_entry);
643
a0e5c15d
FK
644 while ((ipv6_proxy_ndp_address = network->ipv6_proxy_ndp_addresses))
645 ipv6_proxy_ndp_address_free(ipv6_proxy_ndp_address);
646
e4a71bf3
WKI
647 while ((neighbor = network->neighbors))
648 neighbor_free(neighbor);
649
95b74ef6
SS
650 while ((label = network->address_labels))
651 address_label_free(label);
652
057abfd8
PF
653 while ((prefix = network->static_prefixes))
654 prefix_free(prefix);
655
bce67bbe
SS
656 while ((rule = network->rules))
657 routing_policy_rule_free(rule);
658
6ae115c1
TG
659 hashmap_free(network->addresses_by_section);
660 hashmap_free(network->routes_by_section);
c16c7808 661 hashmap_free(network->nexthops_by_section);
b98b483b 662 hashmap_free(network->fdb_entries_by_section);
e4a71bf3 663 hashmap_free(network->neighbors_by_section);
95b74ef6 664 hashmap_free(network->address_labels_by_section);
057abfd8 665 hashmap_free(network->prefixes_by_section);
bce67bbe 666 hashmap_free(network->rules_by_section);
0f5bd7fe 667 ordered_hashmap_free_with_destructor(network->qdiscs_by_section, qdisc_free);
6ae115c1 668
7f06b3e1
YW
669 if (network->manager &&
670 network->manager->duids_requesting_uuid)
671 set_remove(network->manager->duids_requesting_uuid, &network->duid);
dbffab87
TG
672
673 free(network->name);
f579559b 674
8eb9058d 675 free(network->dhcp_server_timezone);
1a04db0f
LP
676 free(network->dhcp_server_dns);
677 free(network->dhcp_server_ntp);
299d578f 678 free(network->dhcp_server_sip);
8eb9058d 679
8a516214
LP
680 set_free_free(network->dnssec_negative_trust_anchors);
681
cb29c156
SS
682 ordered_hashmap_free(network->dhcp_send_options);
683
35ac3b76 684 return mfree(network);
f579559b
TG
685}
686
35ac3b76
YW
687DEFINE_TRIVIAL_REF_UNREF_FUNC(Network, network, network_free);
688
dbffab87
TG
689int network_get_by_name(Manager *manager, const char *name, Network **ret) {
690 Network *network;
691
692 assert(manager);
693 assert(name);
694 assert(ret);
695
715d398e 696 network = ordered_hashmap_get(manager->networks, name);
dbffab87
TG
697 if (!network)
698 return -ENOENT;
699
700 *ret = network;
701
702 return 0;
703}
704
51517f9e 705int network_get(Manager *manager, sd_device *device,
505f8da7 706 const char *ifname, const struct ether_addr *address,
78404d22
YW
707 enum nl80211_iftype wlan_iftype, const char *ssid, const struct ether_addr *bssid,
708 Network **ret) {
51517f9e 709 Network *network;
715d398e 710 Iterator i;
f579559b
TG
711
712 assert(manager);
f579559b 713 assert(ret);
af3aa302 714
715d398e 715 ORDERED_HASHMAP_FOREACH(network, manager->networks, i)
44005bfb
YW
716 if (net_match_config(network->match_mac, network->match_path, network->match_driver,
717 network->match_type, network->match_name, network->match_property,
78404d22
YW
718 network->match_wlan_iftype, network->match_ssid, network->match_bssid,
719 device, address, ifname, wlan_iftype, ssid, bssid)) {
24c083df 720 if (network->match_name && device) {
ca6038b8
TG
721 const char *attr;
722 uint8_t name_assign_type = NET_NAME_UNKNOWN;
723
51517f9e 724 if (sd_device_get_sysattr_value(device, "name_assign_type", &attr) >= 0)
dc751688 725 (void) safe_atou8(attr, &name_assign_type);
32bc8adc
TG
726
727 if (name_assign_type == NET_NAME_ENUM)
a2fae7bb
TG
728 log_warning("%s: found matching network '%s', based on potentially unpredictable ifname",
729 ifname, network->filename);
32bc8adc 730 else
a2fae7bb 731 log_debug("%s: found matching network '%s'", ifname, network->filename);
32bc8adc 732 } else
a2fae7bb 733 log_debug("%s: found matching network '%s'", ifname, network->filename);
32bc8adc 734
f579559b
TG
735 *ret = network;
736 return 0;
737 }
f579559b
TG
738
739 *ret = NULL;
740
741 return -ENOENT;
742}
743
7d342c03 744int network_apply(Network *network, Link *link) {
c4a03a56
TG
745 assert(network);
746 assert(link);
747
c9c908a6 748 link->network = network_ref(network);
f579559b 749
5512a963 750 if (network->n_dns > 0 ||
3df9bec5 751 !strv_isempty(network->ntp) ||
5e2a51d5
ZJS
752 !ordered_set_isempty(network->search_domains) ||
753 !ordered_set_isempty(network->route_domains))
84de38c5 754 link_dirty(link);
3bef724f 755
f579559b
TG
756 return 0;
757}
02b59d57 758
adfeee49 759bool network_has_static_ipv6_configurations(Network *network) {
439689c6 760 Address *address;
adfeee49
YW
761 Route *route;
762 FdbEntry *fdb;
763 Neighbor *neighbor;
439689c6
SS
764
765 assert(network);
766
adfeee49 767 LIST_FOREACH(addresses, address, network->static_addresses)
439689c6
SS
768 if (address->family == AF_INET6)
769 return true;
adfeee49
YW
770
771 LIST_FOREACH(routes, route, network->static_routes)
772 if (route->family == AF_INET6)
773 return true;
774
775 LIST_FOREACH(static_fdb_entries, fdb, network->static_fdb_entries)
776 if (fdb->family == AF_INET6)
777 return true;
778
779 LIST_FOREACH(neighbors, neighbor, network->neighbors)
780 if (neighbor->family == AF_INET6)
781 return true;
782
783 if (!LIST_IS_EMPTY(network->address_labels))
784 return true;
785
786 if (!LIST_IS_EMPTY(network->static_prefixes))
787 return true;
439689c6
SS
788
789 return false;
790}
791
cebe1257 792int config_parse_stacked_netdev(const char *unit,
02b59d57
TG
793 const char *filename,
794 unsigned line,
795 const char *section,
796 unsigned section_line,
797 const char *lvalue,
798 int ltype,
799 const char *rvalue,
800 void *data,
801 void *userdata) {
95dba435
YW
802 _cleanup_free_ char *name = NULL;
803 NetDevKind kind = ltype;
cebe1257 804 Hashmap **h = data;
02b59d57
TG
805 int r;
806
807 assert(filename);
808 assert(lvalue);
809 assert(rvalue);
810 assert(data);
95dba435
YW
811 assert(IN_SET(kind,
812 NETDEV_KIND_VLAN, NETDEV_KIND_MACVLAN, NETDEV_KIND_MACVTAP,
69c317a0 813 NETDEV_KIND_IPVLAN, NETDEV_KIND_IPVTAP, NETDEV_KIND_VXLAN,
98d20a17 814 NETDEV_KIND_L2TP, NETDEV_KIND_MACSEC, _NETDEV_KIND_TUNNEL,
815 NETDEV_KIND_XFRM));
54abf461 816
cebe1257 817 if (!ifname_valid(rvalue)) {
3772cfde
ZJS
818 log_syntax(unit, LOG_ERR, filename, line, 0,
819 "Invalid netdev name in %s=, ignoring assignment: %s", lvalue, rvalue);
54abf461
TG
820 return 0;
821 }
822
cebe1257
YW
823 name = strdup(rvalue);
824 if (!name)
825 return log_oom();
3e570042 826
cebe1257
YW
827 r = hashmap_ensure_allocated(h, &string_hash_ops);
828 if (r < 0)
829 return log_oom();
326cb406 830
cebe1257 831 r = hashmap_put(*h, name, INT_TO_PTR(kind));
83ec4592 832 if (r < 0)
3772cfde 833 log_syntax(unit, LOG_ERR, filename, line, r,
83ec4592
ZJS
834 "Cannot add NetDev '%s' to network, ignoring assignment: %m", name);
835 else if (r == 0)
836 log_syntax(unit, LOG_DEBUG, filename, line, r,
837 "NetDev '%s' specified twice, ignoring.", name);
838 else
839 name = NULL;
47e2dc31 840
fe6b2d55
TG
841 return 0;
842}
7951dea2 843
3df9bec5
LP
844int config_parse_domains(
845 const char *unit,
846 const char *filename,
847 unsigned line,
848 const char *section,
849 unsigned section_line,
850 const char *lvalue,
851 int ltype,
852 const char *rvalue,
853 void *data,
854 void *userdata) {
855
856 const char *p;
857 Network *n = data;
6192b846
TG
858 int r;
859
3df9bec5
LP
860 assert(n);
861 assert(lvalue);
862 assert(rvalue);
6192b846 863
3df9bec5 864 if (isempty(rvalue)) {
5e2a51d5
ZJS
865 n->search_domains = ordered_set_free_free(n->search_domains);
866 n->route_domains = ordered_set_free_free(n->route_domains);
3df9bec5
LP
867 return 0;
868 }
67272d15 869
3df9bec5
LP
870 p = rvalue;
871 for (;;) {
872 _cleanup_free_ char *w = NULL, *normalized = NULL;
873 const char *domain;
874 bool is_route;
875
876 r = extract_first_word(&p, &w, NULL, 0);
877 if (r < 0) {
ab24039f
ZJS
878 log_syntax(unit, LOG_ERR, filename, line, r,
879 "Failed to extract search or route domain, ignoring: %s", rvalue);
3df9bec5
LP
880 break;
881 }
882 if (r == 0)
883 break;
884
885 is_route = w[0] == '~';
886 domain = is_route ? w + 1 : w;
887
888 if (dns_name_is_root(domain) || streq(domain, "*")) {
ab24039f
ZJS
889 /* If the root domain appears as is, or the special token "*" is found, we'll
890 * consider this as routing domain, unconditionally. */
3df9bec5 891 is_route = true;
ab24039f
ZJS
892 domain = "."; /* make sure we don't allow empty strings, thus write the root
893 * domain as "." */
3df9bec5 894 } else {
7470cc4c 895 r = dns_name_normalize(domain, 0, &normalized);
3df9bec5 896 if (r < 0) {
ab24039f
ZJS
897 log_syntax(unit, LOG_ERR, filename, line, r,
898 "'%s' is not a valid domain name, ignoring.", domain);
3df9bec5
LP
899 continue;
900 }
901
902 domain = normalized;
903
904 if (is_localhost(domain)) {
ab24039f
ZJS
905 log_syntax(unit, LOG_ERR, filename, line, 0,
906 "'localhost' domain may not be configured as search or route domain, ignoring assignment: %s",
907 domain);
37de2509 908 continue;
3df9bec5 909 }
37de2509 910 }
40274ed6 911
5e2a51d5
ZJS
912 OrderedSet **set = is_route ? &n->route_domains : &n->search_domains;
913 r = ordered_set_ensure_allocated(set, &string_hash_ops);
914 if (r < 0)
915 return r;
916
917 r = ordered_set_put_strdup(*set, domain);
09451975
LP
918 if (r < 0)
919 return log_oom();
40274ed6 920 }
f15b6e5a 921
6192b846
TG
922 return 0;
923}
924
60c35566 925int config_parse_ipv6token(
7f77697a
TG
926 const char* unit,
927 const char *filename,
928 unsigned line,
929 const char *section,
930 unsigned section_line,
931 const char *lvalue,
932 int ltype,
933 const char *rvalue,
934 void *data,
935 void *userdata) {
936
937 union in_addr_union buffer;
938 struct in6_addr *token = data;
939 int r;
940
941 assert(filename);
942 assert(lvalue);
943 assert(rvalue);
944 assert(token);
945
946 r = in_addr_from_string(AF_INET6, rvalue, &buffer);
947 if (r < 0) {
ab24039f
ZJS
948 log_syntax(unit, LOG_ERR, filename, line, r,
949 "Failed to parse IPv6 token, ignoring: %s", rvalue);
7f77697a
TG
950 return 0;
951 }
952
c606db69 953 if (in_addr_is_null(AF_INET6, &buffer)) {
ab24039f
ZJS
954 log_syntax(unit, LOG_ERR, filename, line, 0,
955 "IPv6 token cannot be the ANY address, ignoring: %s", rvalue);
7f77697a
TG
956 return 0;
957 }
958
959 if ((buffer.in6.s6_addr32[0] | buffer.in6.s6_addr32[1]) != 0) {
ab24039f
ZJS
960 log_syntax(unit, LOG_ERR, filename, line, 0,
961 "IPv6 token cannot be longer than 64 bits, ignoring: %s", rvalue);
7f77697a
TG
962 return 0;
963 }
964
965 *token = buffer.in6;
966
967 return 0;
968}
8add5f79 969
49092e22 970static const char* const ipv6_privacy_extensions_table[_IPV6_PRIVACY_EXTENSIONS_MAX] = {
1f0d9695
LP
971 [IPV6_PRIVACY_EXTENSIONS_NO] = "no",
972 [IPV6_PRIVACY_EXTENSIONS_PREFER_PUBLIC] = "prefer-public",
973 [IPV6_PRIVACY_EXTENSIONS_YES] = "yes",
49092e22
SS
974};
975
b146ad71
YW
976DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(ipv6_privacy_extensions, IPv6PrivacyExtensions,
977 IPV6_PRIVACY_EXTENSIONS_YES);
49092e22
SS
978
979int config_parse_ipv6_privacy_extensions(
980 const char* unit,
981 const char *filename,
982 unsigned line,
983 const char *section,
984 unsigned section_line,
985 const char *lvalue,
986 int ltype,
987 const char *rvalue,
988 void *data,
989 void *userdata) {
990
b146ad71 991 IPv6PrivacyExtensions s, *ipv6_privacy_extensions = data;
49092e22
SS
992
993 assert(filename);
994 assert(lvalue);
995 assert(rvalue);
996 assert(ipv6_privacy_extensions);
997
b146ad71
YW
998 s = ipv6_privacy_extensions_from_string(rvalue);
999 if (s < 0) {
1000 if (streq(rvalue, "kernel"))
1001 s = _IPV6_PRIVACY_EXTENSIONS_INVALID;
1002 else {
1003 log_syntax(unit, LOG_ERR, filename, line, 0,
1004 "Failed to parse IPv6 privacy extensions option, ignoring: %s", rvalue);
1005 return 0;
49092e22 1006 }
49092e22
SS
1007 }
1008
b146ad71
YW
1009 *ipv6_privacy_extensions = s;
1010
49092e22
SS
1011 return 0;
1012}
a7d0ef44 1013
1ac608c9
LP
1014int config_parse_hostname(
1015 const char *unit,
1016 const char *filename,
1017 unsigned line,
1018 const char *section,
1019 unsigned section_line,
1020 const char *lvalue,
1021 int ltype,
1022 const char *rvalue,
1023 void *data,
1024 void *userdata) {
1025
6528693a
YW
1026 _cleanup_free_ char *hn = NULL;
1027 char **hostname = data;
a7d0ef44
SS
1028 int r;
1029
1030 assert(filename);
1031 assert(lvalue);
1032 assert(rvalue);
1033
1ac608c9 1034 r = config_parse_string(unit, filename, line, section, section_line, lvalue, ltype, rvalue, &hn, userdata);
a7d0ef44
SS
1035 if (r < 0)
1036 return r;
1037
1ac608c9 1038 if (!hostname_is_valid(hn, false)) {
ab24039f
ZJS
1039 log_syntax(unit, LOG_ERR, filename, line, 0,
1040 "Hostname is not valid, ignoring assignment: %s", rvalue);
a7d0ef44
SS
1041 return 0;
1042 }
1043
6528693a
YW
1044 r = dns_name_is_valid(hn);
1045 if (r < 0) {
ab24039f
ZJS
1046 log_syntax(unit, LOG_ERR, filename, line, r,
1047 "Failed to check validity of hostname '%s', ignoring assignment: %m", rvalue);
6528693a
YW
1048 return 0;
1049 }
1050 if (r == 0) {
ab24039f
ZJS
1051 log_syntax(unit, LOG_ERR, filename, line, 0,
1052 "Hostname is not a valid DNS domain name, ignoring assignment: %s", rvalue);
6528693a
YW
1053 return 0;
1054 }
1055
1056 return free_and_replace(*hostname, hn);
a7d0ef44 1057}
8eb9058d
LP
1058
1059int config_parse_timezone(
1060 const char *unit,
1061 const char *filename,
1062 unsigned line,
1063 const char *section,
1064 unsigned section_line,
1065 const char *lvalue,
1066 int ltype,
1067 const char *rvalue,
1068 void *data,
1069 void *userdata) {
1070
19f9e4e2
YW
1071 _cleanup_free_ char *tz = NULL;
1072 char **datap = data;
8eb9058d
LP
1073 int r;
1074
1075 assert(filename);
1076 assert(lvalue);
1077 assert(rvalue);
1078
1079 r = config_parse_string(unit, filename, line, section, section_line, lvalue, ltype, rvalue, &tz, userdata);
1080 if (r < 0)
1081 return r;
1082
089fb865 1083 if (!timezone_is_valid(tz, LOG_ERR)) {
ab24039f
ZJS
1084 log_syntax(unit, LOG_ERR, filename, line, 0,
1085 "Timezone is not valid, ignoring assignment: %s", rvalue);
8eb9058d
LP
1086 return 0;
1087 }
1088
19f9e4e2 1089 return free_and_replace(*datap, tz);
8eb9058d 1090}
1a04db0f 1091
53253824
SS
1092int config_parse_dns(
1093 const char *unit,
1094 const char *filename,
1095 unsigned line,
1096 const char *section,
1097 unsigned section_line,
1098 const char *lvalue,
1099 int ltype,
1100 const char *rvalue,
1101 void *data,
1102 void *userdata) {
1103
1104 Network *n = userdata;
1105 int r;
1106
1107 assert(filename);
1108 assert(lvalue);
1109 assert(rvalue);
1110
1111 for (;;) {
1112 _cleanup_free_ char *w = NULL;
1113 union in_addr_union a;
5512a963 1114 struct in_addr_data *m;
53253824
SS
1115 int family;
1116
5512a963 1117 r = extract_first_word(&rvalue, &w, NULL, 0);
53253824
SS
1118 if (r == -ENOMEM)
1119 return log_oom();
1120 if (r < 0) {
ab24039f
ZJS
1121 log_syntax(unit, LOG_ERR, filename, line, r,
1122 "Invalid syntax, ignoring: %s", rvalue);
53253824
SS
1123 break;
1124 }
5512a963
LP
1125 if (r == 0)
1126 break;
53253824
SS
1127
1128 r = in_addr_from_string_auto(w, &family, &a);
1129 if (r < 0) {
ab24039f
ZJS
1130 log_syntax(unit, LOG_ERR, filename, line, r,
1131 "Failed to parse dns server address, ignoring: %s", w);
53253824
SS
1132 continue;
1133 }
1134
62d74c78 1135 m = reallocarray(n->dns, n->n_dns + 1, sizeof(struct in_addr_data));
5512a963 1136 if (!m)
53253824
SS
1137 return log_oom();
1138
5512a963
LP
1139 m[n->n_dns++] = (struct in_addr_data) {
1140 .family = family,
1141 .address = a,
1142 };
1143
1144 n->dns = m;
53253824
SS
1145 }
1146
1147 return 0;
1148}
1149
8a516214
LP
1150int config_parse_dnssec_negative_trust_anchors(
1151 const char *unit,
1152 const char *filename,
1153 unsigned line,
1154 const char *section,
1155 unsigned section_line,
1156 const char *lvalue,
1157 int ltype,
1158 const char *rvalue,
1159 void *data,
1160 void *userdata) {
1161
1162 const char *p = rvalue;
1163 Network *n = data;
1164 int r;
1165
3df9bec5 1166 assert(n);
8a516214
LP
1167 assert(lvalue);
1168 assert(rvalue);
1169
1170 if (isempty(rvalue)) {
1171 n->dnssec_negative_trust_anchors = set_free_free(n->dnssec_negative_trust_anchors);
1172 return 0;
1173 }
1174
1175 for (;;) {
1176 _cleanup_free_ char *w = NULL;
1177
1178 r = extract_first_word(&p, &w, NULL, 0);
1179 if (r < 0) {
ab24039f
ZJS
1180 log_syntax(unit, LOG_ERR, filename, line, r,
1181 "Failed to extract negative trust anchor domain, ignoring: %s", rvalue);
8a516214
LP
1182 break;
1183 }
1184 if (r == 0)
1185 break;
1186
1187 r = dns_name_is_valid(w);
1188 if (r <= 0) {
ab24039f
ZJS
1189 log_syntax(unit, LOG_ERR, filename, line, r,
1190 "%s is not a valid domain name, ignoring.", w);
8a516214
LP
1191 continue;
1192 }
1193
cbbf38ae
LP
1194 r = set_ensure_allocated(&n->dnssec_negative_trust_anchors, &dns_name_hash_ops);
1195 if (r < 0)
1196 return log_oom();
1197
8a516214
LP
1198 r = set_put(n->dnssec_negative_trust_anchors, w);
1199 if (r < 0)
1200 return log_oom();
1201 if (r > 0)
1202 w = NULL;
1203 }
1204
1205 return 0;
1206}
b2a81c0b 1207
26575990
LP
1208int config_parse_ntp(
1209 const char *unit,
1210 const char *filename,
1211 unsigned line,
1212 const char *section,
1213 unsigned section_line,
1214 const char *lvalue,
1215 int ltype,
1216 const char *rvalue,
1217 void *data,
1218 void *userdata) {
1219
1220 char ***l = data;
1221 int r;
1222
1223 assert(l);
1224 assert(lvalue);
1225 assert(rvalue);
1226
1227 if (isempty(rvalue)) {
1228 *l = strv_free(*l);
1229 return 0;
1230 }
1231
1232 for (;;) {
1233 _cleanup_free_ char *w = NULL;
1234
1235 r = extract_first_word(&rvalue, &w, NULL, 0);
1236 if (r == -ENOMEM)
1237 return log_oom();
1238 if (r < 0) {
ab24039f
ZJS
1239 log_syntax(unit, LOG_ERR, filename, line, r,
1240 "Failed to extract NTP server name, ignoring: %s", rvalue);
26575990
LP
1241 break;
1242 }
1243 if (r == 0)
1244 break;
1245
1246 r = dns_name_is_valid_or_address(w);
1247 if (r <= 0) {
ab24039f
ZJS
1248 log_syntax(unit, LOG_ERR, filename, line, r,
1249 "%s is not a valid domain name or IP address, ignoring.", w);
26575990 1250 continue;
af1c0de0
SS
1251 }
1252
c448459d
ZJS
1253 if (strv_length(*l) > MAX_NTP_SERVERS) {
1254 log_syntax(unit, LOG_WARNING, filename, line, 0,
1255 "More than %u NTP servers specified, ignoring \"%s\" and any subsequent entries.",
1256 MAX_NTP_SERVERS, w);
1257 break;
1258 }
1259
1260 r = strv_consume(l, TAKE_PTR(w));
af1c0de0
SS
1261 if (r < 0)
1262 return log_oom();
af1c0de0
SS
1263 }
1264
1265 return 0;
1266}
1267
4ac77d63
YW
1268int config_parse_required_for_online(
1269 const char *unit,
1270 const char *filename,
1271 unsigned line,
1272 const char *section,
1273 unsigned section_line,
1274 const char *lvalue,
1275 int ltype,
1276 const char *rvalue,
1277 void *data,
1278 void *userdata) {
1279
1280 Network *network = data;
1281 LinkOperationalState s;
1282 bool required = true;
1283 int r;
1284
1285 if (isempty(rvalue)) {
1286 network->required_for_online = true;
1287 network->required_operstate_for_online = LINK_OPERSTATE_DEGRADED;
1288 return 0;
1289 }
1290
1291 s = link_operstate_from_string(rvalue);
1292 if (s < 0) {
1293 r = parse_boolean(rvalue);
1294 if (r < 0) {
1295 log_syntax(unit, LOG_ERR, filename, line, r,
1296 "Failed to parse %s= setting, ignoring assignment: %s",
1297 lvalue, rvalue);
1298 return 0;
1299 }
1300
1301 required = r;
1302 s = LINK_OPERSTATE_DEGRADED;
1303 }
1304
1305 network->required_for_online = required;
1306 network->required_operstate_for_online = s;
1307
1308 return 0;
1309}
7da377ef
SS
1310
1311DEFINE_CONFIG_PARSE_ENUM(config_parse_keep_configuration, keep_configuration, KeepConfiguration,
1312 "Failed to parse KeepConfiguration= setting");
1313
1314static const char* const keep_configuration_table[_KEEP_CONFIGURATION_MAX] = {
95355a28
YW
1315 [KEEP_CONFIGURATION_NO] = "no",
1316 [KEEP_CONFIGURATION_DHCP_ON_STOP] = "dhcp-on-stop",
1317 [KEEP_CONFIGURATION_DHCP] = "dhcp",
1318 [KEEP_CONFIGURATION_STATIC] = "static",
1319 [KEEP_CONFIGURATION_YES] = "yes",
7da377ef
SS
1320};
1321
1322DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(keep_configuration, KeepConfiguration, KEEP_CONFIGURATION_YES);