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