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