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