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