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