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