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