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