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