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