]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/network/networkd-network.c
network: introduce link_get_use_domains()
[thirdparty/systemd.git] / src / network / networkd-network.c
CommitLineData
db9ecf05 1/* SPDX-License-Identifier: LGPL-2.1-or-later */
f579559b 2
edda10f2 3/* Make sure the net/if.h header is included before any linux/ one */
9aa5d8ba
YW
4#include <net/if.h>
5#include <netinet/in.h>
01234e1f 6#include <linux/netdevice.h>
a0b191b7 7#include <unistd.h>
69a93e7d 8
b5efdb8a 9#include "alloc-util.h"
f579559b
TG
10#include "conf-files.h"
11#include "conf-parser.h"
37de2509 12#include "dns-domain.h"
3ffd4af2 13#include "fd-util.h"
07630cea 14#include "hostname-util.h"
88295a05 15#include "in-addr-util.h"
7e19cc54 16#include "net-condition.h"
c918b70a 17#include "netdev/macvlan.h"
fb486c90 18#include "networkd-address-label.h"
093e3533 19#include "networkd-address.h"
9671ae9d 20#include "networkd-bridge-fdb.h"
ff9e0783 21#include "networkd-bridge-mdb.h"
22d37e5d 22#include "networkd-dhcp-common.h"
c517a49b 23#include "networkd-dhcp-server-static-lease.h"
14d9ab9d 24#include "networkd-ipv6-proxy-ndp.h"
23f53b99 25#include "networkd-manager.h"
3773eb54 26#include "networkd-ndisc.h"
1939ebeb 27#include "networkd-neighbor.h"
3ffd4af2 28#include "networkd-network.h"
75156ccb 29#include "networkd-nexthop.h"
b5ce4047 30#include "networkd-radv.h"
3b6a3bde 31#include "networkd-route.h"
ca183bf8 32#include "networkd-routing-policy-rule.h"
518cd6b5 33#include "networkd-sriov.h"
6bedfcbb 34#include "parse-util.h"
b0c82192 35#include "path-lookup.h"
3a67b8bb 36#include "qdisc.h"
4f1ac4a3 37#include "radv-internal.h"
8a516214 38#include "set.h"
cebe1257 39#include "socket-util.h"
8fcde012 40#include "stat-util.h"
8b43440b 41#include "string-table.h"
07630cea 42#include "string-util.h"
700f1186 43#include "strv.h"
3a67b8bb 44#include "tclass.h"
f579559b 45
c448459d 46/* Let's assume that anything above this number is a user misconfiguration. */
63b98386 47#define MAX_NTP_SERVERS 128U
c448459d 48
8f9bdeab 49static int network_resolve_netdev_one(Network *network, const char *name, NetDevKind kind, NetDev **ret) {
cebe1257
YW
50 const char *kind_string;
51 NetDev *netdev;
52 int r;
53
96db6412
YW
54 /* For test-networkd-conf, the check must be earlier than the assertions. */
55 if (!name)
56 return 0;
57
cebe1257
YW
58 assert(network);
59 assert(network->manager);
60 assert(network->filename);
8f9bdeab 61 assert(ret);
cebe1257 62
cebe1257
YW
63 if (kind == _NETDEV_KIND_TUNNEL)
64 kind_string = "tunnel";
65 else {
66 kind_string = netdev_kind_to_string(kind);
67 if (!kind_string)
8f9bdeab
YW
68 return log_warning_errno(SYNTHETIC_ERRNO(EINVAL),
69 "%s: Invalid NetDev kind of %s, ignoring assignment.",
70 network->filename, name);
cebe1257
YW
71 }
72
73 r = netdev_get(network->manager, name, &netdev);
74 if (r < 0)
8f9bdeab
YW
75 return log_warning_errno(r, "%s: %s NetDev could not be found, ignoring assignment.",
76 network->filename, name);
cebe1257
YW
77
78 if (netdev->kind != kind && !(kind == _NETDEV_KIND_TUNNEL &&
79 IN_SET(netdev->kind,
bc945c2b 80 NETDEV_KIND_ERSPAN,
cebe1257
YW
81 NETDEV_KIND_GRE,
82 NETDEV_KIND_GRETAP,
83 NETDEV_KIND_IP6GRE,
84 NETDEV_KIND_IP6GRETAP,
9282f75b 85 NETDEV_KIND_IP6TNL,
bc945c2b
YW
86 NETDEV_KIND_IPIP,
87 NETDEV_KIND_SIT,
88 NETDEV_KIND_VTI,
89 NETDEV_KIND_VTI6)))
8f9bdeab
YW
90 return log_warning_errno(SYNTHETIC_ERRNO(EINVAL),
91 "%s: NetDev %s is not a %s, ignoring assignment",
92 network->filename, name, kind_string);
cebe1257 93
8f9bdeab 94 *ret = netdev_ref(netdev);
cebe1257
YW
95 return 1;
96}
97
98static int network_resolve_stacked_netdevs(Network *network) {
99 void *name, *kind;
cebe1257
YW
100 int r;
101
102 assert(network);
103
90e74a66 104 HASHMAP_FOREACH_KEY(kind, name, network->stacked_netdev_names) {
cebe1257
YW
105 _cleanup_(netdev_unrefp) NetDev *netdev = NULL;
106
8f9bdeab 107 if (network_resolve_netdev_one(network, name, PTR_TO_INT(kind), &netdev) <= 0)
cebe1257
YW
108 continue;
109
dcd46cc4
SS
110 r = hashmap_ensure_put(&network->stacked_netdevs, &string_hash_ops, netdev->ifname, netdev);
111 if (r == -ENOMEM)
cebe1257 112 return log_oom();
cebe1257 113 if (r < 0)
8f9bdeab
YW
114 log_warning_errno(r, "%s: Failed to add NetDev '%s' to network, ignoring: %m",
115 network->filename, (const char *) name);
cebe1257
YW
116
117 netdev = NULL;
118 }
119
120 return 0;
121}
122
96db6412 123int network_verify(Network *network) {
50783f91
YW
124 int r;
125
0321cea7 126 assert(network);
ea853de5 127 assert(network->manager);
0321cea7
YW
128 assert(network->filename);
129
5722fb89 130 if (net_match_is_empty(&network->match) && !network->conditions)
dade7349
ZJS
131 return log_warning_errno(SYNTHETIC_ERRNO(EINVAL),
132 "%s: No valid settings found in the [Match] section, ignoring file. "
133 "To match all interfaces, add Name=* in the [Match] section.",
134 network->filename);
84ea567e 135
cebe1257 136 /* skip out early if configuration does not match the environment */
a0b191b7 137 if (!condition_test_list(network->conditions, environ, NULL, NULL, NULL))
cebe1257 138 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL),
3772cfde
ZJS
139 "%s: Conditions in the file do not match the system environment, skipping.",
140 network->filename);
cebe1257 141
57aef9d7
YW
142 if (network->keep_master) {
143 if (network->batadv_name)
144 log_warning("%s: BatmanAdvanced= set with KeepMaster= enabled, ignoring BatmanAdvanced=.",
145 network->filename);
146 if (network->bond_name)
147 log_warning("%s: Bond= set with KeepMaster= enabled, ignoring Bond=.",
148 network->filename);
149 if (network->bridge_name)
150 log_warning("%s: Bridge= set with KeepMaster= enabled, ignoring Bridge=.",
151 network->filename);
152 if (network->vrf_name)
153 log_warning("%s: VRF= set with KeepMaster= enabled, ignoring VRF=.",
154 network->filename);
155
156 network->batadv_name = mfree(network->batadv_name);
157 network->bond_name = mfree(network->bond_name);
158 network->bridge_name = mfree(network->bridge_name);
159 network->vrf_name = mfree(network->vrf_name);
160 }
161
c0267a59 162 (void) network_resolve_netdev_one(network, network->batadv_name, NETDEV_KIND_BATADV, &network->batadv);
cebe1257
YW
163 (void) network_resolve_netdev_one(network, network->bond_name, NETDEV_KIND_BOND, &network->bond);
164 (void) network_resolve_netdev_one(network, network->bridge_name, NETDEV_KIND_BRIDGE, &network->bridge);
165 (void) network_resolve_netdev_one(network, network->vrf_name, NETDEV_KIND_VRF, &network->vrf);
8f9bdeab
YW
166 r = network_resolve_stacked_netdevs(network);
167 if (r < 0)
168 return r;
cebe1257
YW
169
170 /* Free unnecessary entries. */
c0267a59 171 network->batadv_name = mfree(network->batadv_name);
cebe1257
YW
172 network->bond_name = mfree(network->bond_name);
173 network->bridge_name = mfree(network->bridge_name);
174 network->vrf_name = mfree(network->vrf_name);
175 network->stacked_netdev_names = hashmap_free_free_key(network->stacked_netdev_names);
176
0321cea7
YW
177 if (network->bond) {
178 /* Bonding slave does not support addressing. */
0321cea7 179 if (network->link_local >= 0 && network->link_local != ADDRESS_FAMILY_NO) {
ab24039f
ZJS
180 log_warning("%s: Cannot enable LinkLocalAddressing= when Bond= is specified, disabling LinkLocalAddressing=.",
181 network->filename);
0321cea7
YW
182 network->link_local = ADDRESS_FAMILY_NO;
183 }
9cd9fc8f 184 if (!ordered_hashmap_isempty(network->addresses_by_section))
ab24039f
ZJS
185 log_warning("%s: Cannot set addresses when Bond= is specified, ignoring addresses.",
186 network->filename);
2a54a044 187 if (!hashmap_isempty(network->routes_by_section))
ab24039f
ZJS
188 log_warning("%s: Cannot set routes when Bond= is specified, ignoring routes.",
189 network->filename);
9cd9fc8f 190
ebd96906 191 network->addresses_by_section = ordered_hashmap_free(network->addresses_by_section);
74c301b9 192 network->routes_by_section = hashmap_free(network->routes_by_section);
0321cea7
YW
193 }
194
c918b70a
TY
195 if (network->link_local < 0) {
196 network->link_local = ADDRESS_FAMILY_IPV6;
197
57aef9d7 198 if (network->keep_master || network->bridge)
c918b70a
TY
199 network->link_local = ADDRESS_FAMILY_NO;
200 else {
201 NetDev *netdev;
202
203 HASHMAP_FOREACH(netdev, network->stacked_netdevs) {
204 MacVlan *m;
205
206 if (netdev->kind == NETDEV_KIND_MACVLAN)
207 m = MACVLAN(netdev);
208 else if (netdev->kind == NETDEV_KIND_MACVTAP)
209 m = MACVTAP(netdev);
210 else
211 continue;
212
213 if (m->mode == NETDEV_MACVLAN_MODE_PASSTHRU)
214 network->link_local = ADDRESS_FAMILY_NO;
215
216 /* There won't be a passthru MACVLAN/MACVTAP if there's already one in another mode */
217 break;
218 }
219 }
220 }
221
75d5abd2
YW
222 if (network->ipv6ll_address_gen_mode == IPV6_LINK_LOCAL_ADDRESSS_GEN_MODE_NONE)
223 SET_FLAG(network->link_local, ADDRESS_FAMILY_IPV6, false);
8f191801 224
9e1432d5
YW
225 if (in6_addr_is_set(&network->ipv6ll_stable_secret) &&
226 network->ipv6ll_address_gen_mode < 0)
227 network->ipv6ll_address_gen_mode = IPV6_LINK_LOCAL_ADDRESSS_GEN_MODE_STABLE_PRIVACY;
228
14d9ab9d 229 network_adjust_ipv6_proxy_ndp(network);
52672db3 230 network_adjust_ndisc(network);
22d37e5d 231 network_adjust_dhcp(network);
69e0f833 232 network_adjust_radv(network);
5546870e 233 network_adjust_bridge_vlan(network);
3773eb54 234
933c70a0 235 if (network->mtu > 0 && network->dhcp_use_mtu) {
0321cea7
YW
236 log_warning("%s: MTUBytes= in [Link] section and UseMTU= in [DHCP] section are set. "
237 "Disabling UseMTU=.", network->filename);
238 network->dhcp_use_mtu = false;
239 }
240
7da377ef 241 if (network->dhcp_critical >= 0) {
ea853de5
YW
242 if (network->keep_configuration >= 0) {
243 if (network->manager->keep_configuration < 0)
244 log_warning("%s: Both KeepConfiguration= and deprecated CriticalConnection= are set. "
245 "Ignoring CriticalConnection=.", network->filename);
246 } else if (network->dhcp_critical)
7da377ef
SS
247 /* CriticalConnection=yes also preserve foreign static configurations. */
248 network->keep_configuration = KEEP_CONFIGURATION_YES;
249 else
80060352 250 network->keep_configuration = KEEP_CONFIGURATION_NO;
7da377ef
SS
251 }
252
61135582
DS
253 if (!strv_isempty(network->bind_carrier)) {
254 if (!IN_SET(network->activation_policy, _ACTIVATION_POLICY_INVALID, ACTIVATION_POLICY_BOUND))
255 log_warning("%s: ActivationPolicy=bound is required with BindCarrier=. "
256 "Setting ActivationPolicy=bound.", network->filename);
257 network->activation_policy = ACTIVATION_POLICY_BOUND;
258 } else if (network->activation_policy == ACTIVATION_POLICY_BOUND) {
259 log_warning("%s: ActivationPolicy=bound requires BindCarrier=. "
260 "Ignoring ActivationPolicy=bound.", network->filename);
261 network->activation_policy = ACTIVATION_POLICY_UP;
262 }
263
264 if (network->activation_policy == _ACTIVATION_POLICY_INVALID)
265 network->activation_policy = ACTIVATION_POLICY_UP;
266
267 if (network->activation_policy == ACTIVATION_POLICY_ALWAYS_UP) {
6706ce2f
YW
268 if (network->ignore_carrier_loss_set && network->ignore_carrier_loss_usec < USEC_INFINITY)
269 log_warning("%s: IgnoreCarrierLoss=no or finite timespan conflicts with ActivationPolicy=always-up. "
270 "Setting IgnoreCarrierLoss=yes.", network->filename);
271 network->ignore_carrier_loss_set = true;
272 network->ignore_carrier_loss_usec = USEC_INFINITY;
61135582
DS
273 }
274
27438545 275 if (!network->ignore_carrier_loss_set) /* Set implied default. */
6706ce2f 276 network->ignore_carrier_loss_usec = network->configure_without_carrier ? USEC_INFINITY : 0;
61135582 277
7c644a69
DS
278 if (IN_SET(network->activation_policy, ACTIVATION_POLICY_DOWN, ACTIVATION_POLICY_ALWAYS_DOWN, ACTIVATION_POLICY_MANUAL)) {
279 if (network->required_for_online < 0 ||
280 (network->required_for_online == true && network->activation_policy == ACTIVATION_POLICY_ALWAYS_DOWN)) {
281 log_debug("%s: Setting RequiredForOnline=no because ActivationPolicy=%s.", network->filename,
282 activation_policy_to_string(network->activation_policy));
283 network->required_for_online = false;
284 } else if (network->required_for_online == true)
285 log_warning("%s: RequiredForOnline=yes and ActivationPolicy=%s, "
286 "this may cause a delay at boot.", network->filename,
287 activation_policy_to_string(network->activation_policy));
288 }
289
290 if (network->required_for_online < 0)
291 network->required_for_online = true;
292
7da377ef 293 if (network->keep_configuration < 0)
80060352 294 network->keep_configuration = KEEP_CONFIGURATION_NO;
7da377ef 295
87851e0f
YW
296 if (network->ipv6_proxy_ndp == 0 && !set_isempty(network->ipv6_proxy_ndp_addresses)) {
297 log_warning("%s: IPv6ProxyNDP= is disabled. Ignoring IPv6ProxyNDPAddress=.", network->filename);
298 network->ipv6_proxy_ndp_addresses = set_free_free(network->ipv6_proxy_ndp_addresses);
299 }
300
50783f91
YW
301 r = network_drop_invalid_addresses(network);
302 if (r < 0)
61ec7bea 303 return r; /* network_drop_invalid_addresses() logs internally. */
13ffa39f 304 network_drop_invalid_routes(network);
015b2432
YW
305 r = network_drop_invalid_nexthops(network);
306 if (r < 0)
307 return r;
9671ae9d 308 network_drop_invalid_bridge_fdb_entries(network);
ff9e0783 309 network_drop_invalid_bridge_mdb_entries(network);
aa9626ee
YW
310 r = network_drop_invalid_neighbors(network);
311 if (r < 0)
312 return r;
13ffa39f
YW
313 network_drop_invalid_address_labels(network);
314 network_drop_invalid_prefixes(network);
315 network_drop_invalid_route_prefixes(network);
316 network_drop_invalid_routing_policy_rules(network);
3a67b8bb
YW
317 network_drop_invalid_qdisc(network);
318 network_drop_invalid_tclass(network);
41ce9d76 319 r = sr_iov_drop_invalid_sections(UINT32_MAX, network->sr_iov_by_section);
e217e22a 320 if (r < 0)
61ec7bea 321 return r; /* sr_iov_drop_invalid_sections() logs internally. */
c517a49b 322 network_drop_invalid_static_leases(network);
518cd6b5 323
0321cea7
YW
324 return 0;
325}
326
7f06b3e1 327int network_load_one(Manager *manager, OrderedHashmap **networks, const char *filename) {
838b2f7a 328 _cleanup_free_ char *fname = NULL, *name = NULL;
35ac3b76 329 _cleanup_(network_unrefp) Network *network = NULL;
047a0dac 330 const char *dropin_dirname;
838b2f7a 331 char *d;
f579559b
TG
332 int r;
333
bf1bc670
TA
334 assert(manager);
335 assert(filename);
336
4e54a17d 337 r = null_or_empty_path(filename);
4e54a17d 338 if (r < 0)
61ec7bea 339 return log_warning_errno(r, "Failed to check if \"%s\" is empty: %m", filename);
4e54a17d 340 if (r > 0) {
ed88bcfb 341 log_debug("Skipping empty file: %s", filename);
6916ec29
TG
342 return 0;
343 }
344
838b2f7a
YW
345 fname = strdup(filename);
346 if (!fname)
347 return log_oom();
348
349 name = strdup(basename(filename));
350 if (!name)
351 return log_oom();
352
353 d = strrchr(name, '.');
354 if (!d)
61ec7bea 355 return log_warning_errno(SYNTHETIC_ERRNO(EINVAL), "Invalid file name: %s", filename);
838b2f7a
YW
356
357 *d = '\0';
358
359 dropin_dirname = strjoina(name, ".network.d");
360
17f9c355 361 network = new(Network, 1);
f579559b
TG
362 if (!network)
363 return log_oom();
364
17f9c355 365 *network = (Network) {
838b2f7a
YW
366 .filename = TAKE_PTR(fname),
367 .name = TAKE_PTR(name),
17f9c355 368
715d398e 369 .manager = manager,
35ac3b76
YW
370 .n_ref = 1,
371
7c644a69 372 .required_for_online = -1,
3255bda6 373 .required_operstate_for_online = LINK_OPERSTATE_RANGE_INVALID,
61135582 374 .activation_policy = _ACTIVATION_POLICY_INVALID,
cee68339 375 .group = -1,
db5756f3
YW
376 .arp = -1,
377 .multicast = -1,
378 .allmulticast = -1,
937e305e 379 .promiscuous = -1,
db5756f3 380
ea853de5 381 .keep_configuration = manager->keep_configuration,
db5756f3 382
7a169cb4
YW
383 .compat_dhcp_use_domains = _USE_DOMAINS_INVALID,
384
4e26a5ba 385 .dhcp_duid.type = _DUID_TYPE_INVALID,
7da377ef 386 .dhcp_critical = -1,
17f9c355 387 .dhcp_use_ntp = true,
d7b04506 388 .dhcp_routes_to_ntp = true,
299d578f 389 .dhcp_use_sip = true,
edb88a72 390 .dhcp_use_captive_portal = true,
17f9c355 391 .dhcp_use_dns = true,
70570306 392 .dhcp_routes_to_dns = true,
7a169cb4 393 .dhcp_use_domains = _USE_DOMAINS_INVALID,
17f9c355
YW
394 .dhcp_use_hostname = true,
395 .dhcp_use_routes = true,
589397a2 396 .dhcp_use_gateway = -1,
17f9c355 397 .dhcp_send_hostname = true,
5f3b5f19 398 .dhcp_send_release = true,
17f9c355 399 .dhcp_route_metric = DHCP_ROUTE_METRIC,
cf289b14 400 .dhcp_use_rapid_commit = -1,
f90635f1 401 .dhcp_client_identifier = _DHCP_CLIENT_ID_INVALID,
17f9c355 402 .dhcp_route_table = RT_TABLE_MAIN,
db5756f3 403 .dhcp_ip_service_type = -1,
e70eca9b 404 .dhcp_broadcast = -1,
fc35a9f8 405 .dhcp_ipv6_only_mode = -1,
17f9c355 406
1536b7b2 407 .dhcp6_use_address = true,
0f5ef9b6 408 .dhcp6_use_pd_prefix = true,
1536b7b2 409 .dhcp6_use_dns = true,
7a169cb4 410 .dhcp6_use_domains = _USE_DOMAINS_INVALID,
38ba3da0 411 .dhcp6_use_hostname = true,
1536b7b2 412 .dhcp6_use_ntp = true,
a75feb55 413 .dhcp6_use_captive_portal = true,
50ee1fec 414 .dhcp6_use_rapid_commit = true,
b90480c8 415 .dhcp6_send_hostname = true,
4e26a5ba 416 .dhcp6_duid.type = _DUID_TYPE_INVALID,
0e45721e 417 .dhcp6_client_start_mode = _DHCP6_CLIENT_START_MODE_INVALID,
b895aa5f 418 .dhcp6_send_release = true,
caa8ca42 419
a27588d4
YW
420 .dhcp_pd = -1,
421 .dhcp_pd_announce = true,
422 .dhcp_pd_assign = true,
423 .dhcp_pd_manage_temporary_address = true,
424 .dhcp_pd_subnet_id = -1,
425 .dhcp_pd_route_metric = DHCP6PD_ROUTE_METRIC,
9efa8a3c 426
21b6b87e 427 .dhcp_server_bind_to_interface = true,
2a71d57f
LP
428 .dhcp_server_emit[SD_DHCP_LEASE_DNS].emit = true,
429 .dhcp_server_emit[SD_DHCP_LEASE_NTP].emit = true,
430 .dhcp_server_emit[SD_DHCP_LEASE_SIP].emit = true,
17f9c355
YW
431 .dhcp_server_emit_router = true,
432 .dhcp_server_emit_timezone = true,
1fa0a4ef 433 .dhcp_server_rapid_commit = true,
a3ed665a 434 .dhcp_server_persist_leases = -1,
17f9c355 435
4f1ac4a3 436 .router_lifetime_usec = RADV_DEFAULT_ROUTER_LIFETIME_USEC,
c9e2c2da 437 .router_dns_lifetime_usec = RADV_DEFAULT_VALID_LIFETIME_USEC,
17f9c355
YW
438 .router_emit_dns = true,
439 .router_emit_domains = true,
440
441 .use_bpdu = -1,
442 .hairpin = -1,
97f27f8a 443 .isolated = -1,
17f9c355
YW
444 .fast_leave = -1,
445 .allow_port_to_be_root = -1,
446 .unicast_flood = -1,
7f15b714 447 .multicast_flood = -1,
d3aa8b49 448 .multicast_to_unicast = -1,
7f15b714
TJ
449 .neighbor_suppression = -1,
450 .learning = -1,
1087623b
SS
451 .bridge_proxy_arp = -1,
452 .bridge_proxy_arp_wifi = -1,
17f9c355 453 .priority = LINK_BRIDGE_PORT_PRIORITY_INVALID,
0fadb2a4 454 .multicast_router = _MULTICAST_ROUTER_INVALID,
17f9c355 455
228693af 456 .bridge_vlan_pvid = BRIDGE_VLAN_KEEP_PVID,
0b8d501c 457
17f9c355 458 .lldp_mode = LLDP_MODE_ROUTERS_ONLY,
c01b9b87 459 .lldp_multicast_mode = _SD_LLDP_MULTICAST_MODE_INVALID,
17f9c355 460
7ece6f58 461 .dns_default_route = -1,
17f9c355
YW
462 .llmnr = RESOLVE_SUPPORT_YES,
463 .mdns = RESOLVE_SUPPORT_NO,
464 .dnssec_mode = _DNSSEC_MODE_INVALID,
465 .dns_over_tls_mode = _DNS_OVER_TLS_MODE_INVALID,
466
0321cea7 467 /* If LinkLocalAddressing= is not set, then set to ADDRESS_FAMILY_IPV6 later. */
2d792895 468 .link_local = _ADDRESS_FAMILY_INVALID,
6f6296b9 469 .ipv6ll_address_gen_mode = _IPV6_LINK_LOCAL_ADDRESS_GEN_MODE_INVALID,
17f9c355 470
3976c430 471 .ip_forwarding = { -1, -1, },
94d76d07 472 .ipv4_accept_local = -1,
d75bf6cf 473 .ipv4_route_localnet = -1,
932ef6ec 474 .ipv6_privacy_extensions = _IPV6_PRIVACY_EXTENSIONS_INVALID,
17f9c355 475 .ipv6_dad_transmits = -1,
17f9c355 476 .ipv6_proxy_ndp = -1,
17f9c355 477 .proxy_arp = -1,
b4959550 478 .proxy_arp_pvlan = -1,
9c72e8f8 479 .ipv4_rp_filter = _IP_REVERSE_PATH_FILTER_INVALID,
db5756f3 480
52672db3 481 .ndisc = -1,
6df00594 482 .ndisc_use_redirect = true,
52672db3
YW
483 .ndisc_use_dns = true,
484 .ndisc_use_gateway = true,
485 .ndisc_use_captive_portal = true,
486 .ndisc_use_route_prefix = true,
487 .ndisc_use_autonomous_prefix = true,
488 .ndisc_use_onlink_prefix = true,
489 .ndisc_use_mtu = true,
490 .ndisc_use_hop_limit = true,
491 .ndisc_use_reachable_time = true,
492 .ndisc_use_retransmission_time = true,
52672db3
YW
493 .ndisc_route_table = RT_TABLE_MAIN,
494 .ndisc_route_metric_high = IPV6RA_ROUTE_METRIC_HIGH,
495 .ndisc_route_metric_medium = IPV6RA_ROUTE_METRIC_MEDIUM,
496 .ndisc_route_metric_low = IPV6RA_ROUTE_METRIC_LOW,
497 .ndisc_start_dhcp6_client = IPV6_ACCEPT_RA_START_DHCP6_CLIENT_YES,
c423be28 498
52aa38f1 499 .can_termination = -1,
72e65e6f
YW
500
501 .ipoib_mode = _IP_OVER_INFINIBAND_MODE_INVALID,
502 .ipoib_umcast = -1,
17f9c355 503 };
f579559b 504
4f9ff96a 505 r = config_parse_many(
947f59ba 506 STRV_MAKE_CONST(filename), NETWORK_DIRS, dropin_dirname, /* root = */ NULL,
4f9ff96a
LP
507 "Match\0"
508 "Link\0"
518cd6b5 509 "SR-IOV\0"
4f9ff96a
LP
510 "Network\0"
511 "Address\0"
512 "Neighbor\0"
513 "IPv6AddressLabel\0"
514 "RoutingPolicyRule\0"
515 "Route\0"
516 "NextHop\0"
517 "DHCP\0" /* compat */
518 "DHCPv4\0"
519 "DHCPv6\0"
a27588d4
YW
520 "DHCPv6PrefixDelegation\0" /* compat */
521 "DHCPPrefixDelegation\0"
4f9ff96a 522 "DHCPServer\0"
c517a49b 523 "DHCPServerStaticLease\0"
4f9ff96a
LP
524 "IPv6AcceptRA\0"
525 "IPv6NDPProxyAddress\0"
526 "Bridge\0"
527 "BridgeFDB\0"
3db468ea 528 "BridgeMDB\0"
4f9ff96a 529 "BridgeVLAN\0"
27ff0490 530 "IPv6SendRA\0"
4f9ff96a
LP
531 "IPv6PrefixDelegation\0"
532 "IPv6Prefix\0"
533 "IPv6RoutePrefix\0"
1925f829 534 "IPv6PREF64Prefix\0"
4f9ff96a
LP
535 "LLDP\0"
536 "TrafficControlQueueingDiscipline\0"
537 "CAN\0"
538 "QDisc\0"
539 "BFIFO\0"
540 "CAKE\0"
541 "ControlledDelay\0"
542 "DeficitRoundRobinScheduler\0"
543 "DeficitRoundRobinSchedulerClass\0"
d474aa51 544 "EnhancedTransmissionSelection\0"
4f9ff96a
LP
545 "FairQueueing\0"
546 "FairQueueingControlledDelay\0"
8f6b6d70 547 "FlowQueuePIE\0"
4f9ff96a
LP
548 "GenericRandomEarlyDetection\0"
549 "HeavyHitterFilter\0"
550 "HierarchyTokenBucket\0"
551 "HierarchyTokenBucketClass\0"
552 "NetworkEmulator\0"
b12aaee5
SS
553 "PFIFO\0"
554 "PFIFOFast\0"
555 "PFIFOHeadDrop\0"
4f9ff96a 556 "PIE\0"
b12aaee5 557 "QuickFairQueueing\0"
4d7ddaf9 558 "QuickFairQueueingClass\0"
4f9ff96a
LP
559 "StochasticFairBlue\0"
560 "StochasticFairnessQueueing\0"
561 "TokenBucketFilter\0"
562 "TrivialLinkEqualizer\0",
563 config_item_perf_lookup, network_network_gperf_lookup,
564 CONFIG_PARSE_WARN,
565 network,
ead3a3fc 566 &network->stats_by_path,
a2640646 567 &network->dropins);
102bc043 568 if (r < 0)
61ec7bea 569 return r; /* config_parse_many() logs internally. */
f579559b 570
fa7cd711
YW
571 r = network_add_ipv4ll_route(network);
572 if (r < 0)
9202b567 573 return log_warning_errno(r, "%s: Failed to add IPv4LL route: %m", network->filename);
fa7cd711 574
5d5003ab
YW
575 r = network_add_default_route_on_device(network);
576 if (r < 0)
9202b567
YW
577 return log_warning_errno(r, "%s: Failed to add default route on device: %m",
578 network->filename);
5d5003ab 579
9202b567 580 r = network_verify(network);
9202b567 581 if (r < 0)
61ec7bea 582 return r; /* network_verify() logs internally. */
7f06b3e1 583
9fa3e794 584 r = ordered_hashmap_ensure_put(networks, &string_hash_ops, network->name, network);
dbffab87 585 if (r < 0)
61ec7bea 586 return log_warning_errno(r, "%s: Failed to store configuration into hashmap: %m", filename);
dbffab87 587
b5b9b0e7 588 TAKE_PTR(network);
f579559b
TG
589 return 0;
590}
591
7f06b3e1 592int network_load(Manager *manager, OrderedHashmap **networks) {
477e73b5 593 _cleanup_strv_free_ char **files = NULL;
f579559b
TG
594 int r;
595
596 assert(manager);
597
7f06b3e1 598 ordered_hashmap_clear_with_destructor(*networks, network_unref);
f579559b 599
dc0d4078 600 r = conf_files_list_strv(&files, ".network", NULL, 0, NETWORK_DIRS);
f647962d
MS
601 if (r < 0)
602 return log_error_errno(r, "Failed to enumerate network files: %m");
f579559b 603
036a8d50
YW
604 STRV_FOREACH(f, files)
605 (void) network_load_one(manager, networks, *f);
f579559b 606
f579559b
TG
607 return 0;
608}
609
7f06b3e1
YW
610int network_reload(Manager *manager) {
611 OrderedHashmap *new_networks = NULL;
612 Network *n, *old;
7f06b3e1
YW
613 int r;
614
615 assert(manager);
616
617 r = network_load(manager, &new_networks);
618 if (r < 0)
619 goto failure;
620
90e74a66 621 ORDERED_HASHMAP_FOREACH(n, new_networks) {
7f06b3e1 622 r = network_get_by_name(manager, n->name, &old);
8524db50
YW
623 if (r < 0) {
624 log_debug("Found new .network file: %s", n->filename);
625 continue;
626 }
7f06b3e1 627
8524db50
YW
628 if (!stats_by_path_equal(n->stats_by_path, old->stats_by_path)) {
629 log_debug("Found updated .network file: %s", n->filename);
7f06b3e1 630 continue;
8524db50 631 }
7f06b3e1
YW
632
633 r = ordered_hashmap_replace(new_networks, old->name, old);
634 if (r < 0)
635 goto failure;
636
637 network_ref(old);
638 network_unref(n);
639 }
640
641 ordered_hashmap_free_with_destructor(manager->networks, network_unref);
642 manager->networks = new_networks;
643
fb126bb1
YW
644 r = manager_build_dhcp_pd_subnet_ids(manager);
645 if (r < 0)
646 return r;
647
648 r = manager_build_nexthop_ids(manager);
649 if (r < 0)
650 return r;
651
652 return 0;
7f06b3e1
YW
653
654failure:
655 ordered_hashmap_free_with_destructor(new_networks, network_unref);
656
657 return r;
658}
659
a27588d4 660int manager_build_dhcp_pd_subnet_ids(Manager *manager) {
1a4ca0e2
YW
661 Network *n;
662 int r;
663
664 assert(manager);
665
a27588d4 666 set_clear(manager->dhcp_pd_subnet_ids);
1a4ca0e2
YW
667
668 ORDERED_HASHMAP_FOREACH(n, manager->networks) {
669 if (n->unmanaged)
670 continue;
671
a27588d4 672 if (!n->dhcp_pd)
1a4ca0e2
YW
673 continue;
674
a27588d4 675 if (n->dhcp_pd_subnet_id < 0)
1a4ca0e2
YW
676 continue;
677
a27588d4 678 r = set_ensure_put(&manager->dhcp_pd_subnet_ids, &uint64_hash_ops, &n->dhcp_pd_subnet_id);
1a4ca0e2
YW
679 if (r < 0)
680 return r;
681 }
682
683 return 0;
684}
685
35ac3b76 686static Network *network_free(Network *network) {
f579559b 687 if (!network)
35ac3b76 688 return NULL;
f579559b 689
54e0cfc4 690 free(network->name);
f579559b 691 free(network->filename);
54e0cfc4 692 free(network->description);
a2640646 693 strv_free(network->dropins);
8524db50 694 hashmap_free(network->stats_by_path);
f579559b 695
54e0cfc4 696 /* conditions */
5722fb89 697 net_match_clear(&network->match);
c4f58dea 698 condition_free_list(network->conditions);
f579559b 699
54e0cfc4
YW
700 /* link settings */
701 strv_free(network->bind_carrier);
702
703 /* NTP */
704 strv_free(network->ntp);
705
706 /* DNS */
707 for (unsigned i = 0; i < network->n_dns; i++)
708 in_addr_full_free(network->dns[i]);
709 free(network->dns);
710 ordered_set_free(network->search_domains);
711 ordered_set_free(network->route_domains);
712 set_free_free(network->dnssec_negative_trust_anchors);
713
714 /* DHCP server */
11c38d3e
YA
715 free(network->dhcp_server_relay_agent_circuit_id);
716 free(network->dhcp_server_relay_agent_remote_id);
6278e428
YW
717 free(network->dhcp_server_boot_server_name);
718 free(network->dhcp_server_boot_filename);
54e0cfc4
YW
719 free(network->dhcp_server_timezone);
720 free(network->dhcp_server_uplink_name);
721 for (sd_dhcp_lease_server_type_t t = 0; t < _SD_DHCP_LEASE_SERVER_TYPE_MAX; t++)
722 free(network->dhcp_server_emit[t].addresses);
723 ordered_hashmap_free(network->dhcp_server_send_options);
724 ordered_hashmap_free(network->dhcp_server_send_vendor_options);
11c38d3e 725
54e0cfc4 726 /* DHCP client */
edb85f0d 727 free(network->dhcp_vendor_class_identifier);
7b8d23a9 728 free(network->dhcp_mudurl);
27cb34f5 729 free(network->dhcp_hostname);
d419ef02 730 free(network->dhcp_label);
6b000af4 731 set_free(network->dhcp_deny_listed_ip);
98ebef62 732 set_free(network->dhcp_allow_listed_ip);
54e0cfc4 733 strv_free(network->dhcp_user_class);
5bc945be 734 set_free(network->dhcp_request_options);
54e0cfc4
YW
735 ordered_hashmap_free(network->dhcp_client_send_options);
736 ordered_hashmap_free(network->dhcp_client_send_vendor_options);
4b3590c3 737 free(network->dhcp_netlabel);
fc289dd0 738 nft_set_context_clear(&network->dhcp_nft_set_context);
54e0cfc4
YW
739
740 /* DHCPv6 client */
3175a8c2 741 free(network->dhcp6_mudurl);
9968ca32 742 free(network->dhcp6_hostname);
f37f2a6b 743 strv_free(network->dhcp6_user_class);
ed0d1b2e 744 strv_free(network->dhcp6_vendor_class);
54e0cfc4
YW
745 set_free(network->dhcp6_request_options);
746 ordered_hashmap_free(network->dhcp6_client_send_options);
747 ordered_hashmap_free(network->dhcp6_client_send_vendor_options);
4b3590c3 748 free(network->dhcp6_netlabel);
fc289dd0 749 nft_set_context_clear(&network->dhcp6_nft_set_context);
c106cc36 750
54e0cfc4
YW
751 /* DHCP PD */
752 free(network->dhcp_pd_uplink_name);
753 set_free(network->dhcp_pd_tokens);
4b3590c3 754 free(network->dhcp_pd_netlabel);
fc289dd0 755 nft_set_context_clear(&network->dhcp_pd_nft_set_context);
cdd7812b 756
54e0cfc4 757 /* Router advertisement */
5e276772 758 ordered_set_free(network->router_search_domains);
cdd7812b 759 free(network->router_dns);
54e0cfc4
YW
760 free(network->router_uplink_name);
761
762 /* NDisc */
c995fa02
YW
763 set_free(network->ndisc_deny_listed_router);
764 set_free(network->ndisc_allow_listed_router);
765 set_free(network->ndisc_deny_listed_prefix);
766 set_free(network->ndisc_allow_listed_prefix);
767 set_free(network->ndisc_deny_listed_route_prefix);
768 set_free(network->ndisc_allow_listed_route_prefix);
54e0cfc4 769 set_free(network->ndisc_tokens);
4b3590c3 770 free(network->ndisc_netlabel);
fc289dd0 771 nft_set_context_clear(&network->ndisc_nft_set_context);
3bef724f 772
54e0cfc4
YW
773 /* LLDP */
774 free(network->lldp_mudurl);
775
776 /* netdev */
c0267a59 777 free(network->batadv_name);
cebe1257
YW
778 free(network->bridge_name);
779 free(network->bond_name);
780 free(network->vrf_name);
781 hashmap_free_free_key(network->stacked_netdev_names);
47e2dc31 782 netdev_unref(network->bridge);
47e2dc31 783 netdev_unref(network->bond);
6cb955c6 784 netdev_unref(network->vrf);
fa6f1e54 785 hashmap_free_with_destructor(network->stacked_netdevs, netdev_unref);
326cb406 786
54e0cfc4 787 /* static configs */
d349f502 788 set_free_free(network->ipv6_proxy_ndp_addresses);
ebd96906 789 ordered_hashmap_free(network->addresses_by_section);
74c301b9 790 hashmap_free(network->routes_by_section);
59ac53a6 791 ordered_hashmap_free(network->nexthops_by_section);
9671ae9d 792 hashmap_free_with_destructor(network->bridge_fdb_entries_by_section, bridge_fdb_free);
ff9e0783 793 hashmap_free_with_destructor(network->bridge_mdb_entries_by_section, bridge_mdb_free);
2a75f23b 794 ordered_hashmap_free(network->neighbors_by_section);
d6a2a0f9 795 hashmap_free_with_destructor(network->address_labels_by_section, address_label_free);
ecb0e85e
YW
796 hashmap_free_with_destructor(network->prefixes_by_section, prefix_free);
797 hashmap_free_with_destructor(network->route_prefixes_by_section, route_prefix_free);
1925f829 798 hashmap_free_with_destructor(network->pref64_prefixes_by_section, pref64_prefix_free);
ca183bf8 799 hashmap_free_with_destructor(network->rules_by_section, routing_policy_rule_free);
c517a49b 800 hashmap_free_with_destructor(network->dhcp_static_leases_by_section, dhcp_static_lease_free);
518cd6b5 801 ordered_hashmap_free_with_destructor(network->sr_iov_by_section, sr_iov_free);
3a67b8bb
YW
802 hashmap_free_with_destructor(network->qdiscs_by_section, qdisc_free);
803 hashmap_free_with_destructor(network->tclasses_by_section, tclass_free);
6ae115c1 804
35ac3b76 805 return mfree(network);
f579559b
TG
806}
807
35ac3b76
YW
808DEFINE_TRIVIAL_REF_UNREF_FUNC(Network, network, network_free);
809
dbffab87
TG
810int network_get_by_name(Manager *manager, const char *name, Network **ret) {
811 Network *network;
812
813 assert(manager);
814 assert(name);
815 assert(ret);
816
715d398e 817 network = ordered_hashmap_get(manager->networks, name);
dbffab87
TG
818 if (!network)
819 return -ENOENT;
820
821 *ret = network;
822
823 return 0;
824}
825
adfeee49 826bool network_has_static_ipv6_configurations(Network *network) {
439689c6 827 Address *address;
adfeee49 828 Route *route;
9671ae9d 829 BridgeFDB *fdb;
ff9e0783 830 BridgeMDB *mdb;
adfeee49 831 Neighbor *neighbor;
439689c6
SS
832
833 assert(network);
834
9cd9fc8f 835 ORDERED_HASHMAP_FOREACH(address, network->addresses_by_section)
439689c6
SS
836 if (address->family == AF_INET6)
837 return true;
adfeee49 838
2a54a044 839 HASHMAP_FOREACH(route, network->routes_by_section)
adfeee49
YW
840 if (route->family == AF_INET6)
841 return true;
842
9671ae9d 843 HASHMAP_FOREACH(fdb, network->bridge_fdb_entries_by_section)
adfeee49
YW
844 if (fdb->family == AF_INET6)
845 return true;
846
ff9e0783 847 HASHMAP_FOREACH(mdb, network->bridge_mdb_entries_by_section)
3db468ea
DM
848 if (mdb->family == AF_INET6)
849 return true;
850
aa9626ee 851 ORDERED_HASHMAP_FOREACH(neighbor, network->neighbors_by_section)
adfeee49
YW
852 if (neighbor->family == AF_INET6)
853 return true;
854
d6a2a0f9 855 if (!hashmap_isempty(network->address_labels_by_section))
adfeee49
YW
856 return true;
857
ecb0e85e 858 if (!hashmap_isempty(network->prefixes_by_section))
adfeee49 859 return true;
d30081c2
YW
860
861 if (!hashmap_isempty(network->route_prefixes_by_section))
862 return true;
439689c6 863
1925f829
SS
864 if (!hashmap_isempty(network->pref64_prefixes_by_section))
865 return true;
866
439689c6
SS
867 return false;
868}
869
63481576
YW
870int config_parse_stacked_netdev(
871 const char *unit,
02b59d57
TG
872 const char *filename,
873 unsigned line,
874 const char *section,
875 unsigned section_line,
876 const char *lvalue,
877 int ltype,
878 const char *rvalue,
879 void *data,
880 void *userdata) {
63481576 881
95dba435
YW
882 _cleanup_free_ char *name = NULL;
883 NetDevKind kind = ltype;
99534007 884 Hashmap **h = ASSERT_PTR(data);
02b59d57
TG
885 int r;
886
887 assert(filename);
888 assert(lvalue);
889 assert(rvalue);
95dba435 890 assert(IN_SET(kind,
b90d0f83 891 NETDEV_KIND_IPOIB,
bc945c2b
YW
892 NETDEV_KIND_IPVLAN,
893 NETDEV_KIND_IPVTAP,
bc945c2b
YW
894 NETDEV_KIND_MACSEC,
895 NETDEV_KIND_MACVLAN,
896 NETDEV_KIND_MACVTAP,
897 NETDEV_KIND_VLAN,
898 NETDEV_KIND_VXLAN,
899 NETDEV_KIND_XFRM,
900 _NETDEV_KIND_TUNNEL));
54abf461 901
cebe1257 902 if (!ifname_valid(rvalue)) {
d96edb2c 903 log_syntax(unit, LOG_WARNING, filename, line, 0,
3772cfde 904 "Invalid netdev name in %s=, ignoring assignment: %s", lvalue, rvalue);
54abf461
TG
905 return 0;
906 }
907
cebe1257
YW
908 name = strdup(rvalue);
909 if (!name)
910 return log_oom();
3e570042 911
6de530f2
SS
912 r = hashmap_ensure_put(h, &string_hash_ops, name, INT_TO_PTR(kind));
913 if (r == -ENOMEM)
cebe1257 914 return log_oom();
83ec4592 915 if (r < 0)
d96edb2c 916 log_syntax(unit, LOG_WARNING, filename, line, r,
83ec4592
ZJS
917 "Cannot add NetDev '%s' to network, ignoring assignment: %m", name);
918 else if (r == 0)
919 log_syntax(unit, LOG_DEBUG, filename, line, r,
920 "NetDev '%s' specified twice, ignoring.", name);
921 else
0c7bd7ec 922 TAKE_PTR(name);
47e2dc31 923
fe6b2d55
TG
924 return 0;
925}
7951dea2 926
8eb9058d
LP
927int config_parse_timezone(
928 const char *unit,
929 const char *filename,
930 unsigned line,
931 const char *section,
932 unsigned section_line,
933 const char *lvalue,
934 int ltype,
935 const char *rvalue,
936 void *data,
937 void *userdata) {
938
99534007 939 char **tz = ASSERT_PTR(data);
8eb9058d
LP
940 int r;
941
942 assert(filename);
943 assert(lvalue);
944 assert(rvalue);
945
b40b8b06
YW
946 if (isempty(rvalue)) {
947 *tz = mfree(*tz);
948 return 0;
949 }
8eb9058d 950
b40b8b06
YW
951 r = verify_timezone(rvalue, LOG_WARNING);
952 if (r < 0) {
953 log_syntax(unit, LOG_WARNING, filename, line, r,
ab24039f 954 "Timezone is not valid, ignoring assignment: %s", rvalue);
8eb9058d
LP
955 return 0;
956 }
957
b40b8b06 958 return free_and_strdup_warn(tz, rvalue);
8eb9058d 959}
1a04db0f 960
26575990
LP
961int config_parse_ntp(
962 const char *unit,
963 const char *filename,
964 unsigned line,
965 const char *section,
966 unsigned section_line,
967 const char *lvalue,
968 int ltype,
969 const char *rvalue,
970 void *data,
971 void *userdata) {
972
99534007 973 char ***l = ASSERT_PTR(data);
26575990
LP
974 int r;
975
5aafd5b1 976 assert(filename);
26575990
LP
977 assert(lvalue);
978 assert(rvalue);
979
980 if (isempty(rvalue)) {
981 *l = strv_free(*l);
982 return 0;
983 }
984
d96edb2c 985 for (const char *p = rvalue;;) {
26575990
LP
986 _cleanup_free_ char *w = NULL;
987
d96edb2c 988 r = extract_first_word(&p, &w, NULL, 0);
26575990
LP
989 if (r == -ENOMEM)
990 return log_oom();
991 if (r < 0) {
d96edb2c 992 log_syntax(unit, LOG_WARNING, filename, line, r,
ab24039f 993 "Failed to extract NTP server name, ignoring: %s", rvalue);
d96edb2c 994 return 0;
26575990
LP
995 }
996 if (r == 0)
d96edb2c 997 return 0;
26575990
LP
998
999 r = dns_name_is_valid_or_address(w);
1000 if (r <= 0) {
d96edb2c 1001 log_syntax(unit, LOG_WARNING, filename, line, r,
ab24039f 1002 "%s is not a valid domain name or IP address, ignoring.", w);
26575990 1003 continue;
af1c0de0
SS
1004 }
1005
c448459d
ZJS
1006 if (strv_length(*l) > MAX_NTP_SERVERS) {
1007 log_syntax(unit, LOG_WARNING, filename, line, 0,
1008 "More than %u NTP servers specified, ignoring \"%s\" and any subsequent entries.",
1009 MAX_NTP_SERVERS, w);
d96edb2c 1010 return 0;
c448459d
ZJS
1011 }
1012
1013 r = strv_consume(l, TAKE_PTR(w));
af1c0de0
SS
1014 if (r < 0)
1015 return log_oom();
af1c0de0 1016 }
af1c0de0
SS
1017}
1018
4ac77d63
YW
1019int config_parse_required_for_online(
1020 const char *unit,
1021 const char *filename,
1022 unsigned line,
1023 const char *section,
1024 unsigned section_line,
1025 const char *lvalue,
1026 int ltype,
1027 const char *rvalue,
1028 void *data,
1029 void *userdata) {
1030
99534007 1031 Network *network = ASSERT_PTR(userdata);
4ac77d63
YW
1032 int r;
1033
5aafd5b1
YW
1034 assert(filename);
1035 assert(lvalue);
1036 assert(rvalue);
5aafd5b1 1037
4ac77d63 1038 if (isempty(rvalue)) {
7c644a69 1039 network->required_for_online = -1;
3255bda6 1040 network->required_operstate_for_online = LINK_OPERSTATE_RANGE_INVALID;
4ac77d63
YW
1041 return 0;
1042 }
1043
ba04f957 1044 r = parse_operational_state_range(rvalue, &network->required_operstate_for_online);
75cd4a5d 1045 if (r < 0) {
4ac77d63
YW
1046 r = parse_boolean(rvalue);
1047 if (r < 0) {
d96edb2c 1048 log_syntax(unit, LOG_WARNING, filename, line, r,
4ac77d63
YW
1049 "Failed to parse %s= setting, ignoring assignment: %s",
1050 lvalue, rvalue);
1051 return 0;
1052 }
1053
ba04f957
YW
1054 network->required_for_online = r;
1055 network->required_operstate_for_online = LINK_OPERSTATE_RANGE_DEFAULT;
1056 return 0;
4ac77d63
YW
1057 }
1058
ba04f957 1059 network->required_for_online = true;
4ac77d63
YW
1060 return 0;
1061}
7da377ef 1062
f0c09831
YW
1063int config_parse_link_group(
1064 const char *unit,
1065 const char *filename,
1066 unsigned line,
1067 const char *section,
1068 unsigned section_line,
1069 const char *lvalue,
1070 int ltype,
1071 const char *rvalue,
1072 void *data,
1073 void *userdata) {
1074
99534007 1075 Network *network = ASSERT_PTR(userdata);
f0c09831 1076 int r;
10af8bb2 1077 int32_t group;
f0c09831
YW
1078
1079 assert(filename);
1080 assert(lvalue);
1081 assert(rvalue);
f0c09831
YW
1082
1083 if (isempty(rvalue)) {
10af8bb2 1084 network->group = -1;
f0c09831
YW
1085 return 0;
1086 }
1087
10af8bb2 1088 r = safe_atoi32(rvalue, &group);
f0c09831
YW
1089 if (r < 0) {
1090 log_syntax(unit, LOG_WARNING, filename, line, r,
1091 "Failed to parse Group=, ignoring assignment: %s", rvalue);
1092 return 0;
1093 }
1094
10af8bb2
SB
1095 if (group < 0) {
1096 log_syntax(unit, LOG_WARNING, filename, line, r,
1097 "Value of Group= must be in the range 0…2147483647, ignoring assignment: %s", rvalue);
1098 return 0;
1099 }
1100
1101 network->group = group;
f0c09831
YW
1102 return 0;
1103}
1104
6706ce2f
YW
1105int config_parse_ignore_carrier_loss(
1106 const char *unit,
1107 const char *filename,
1108 unsigned line,
1109 const char *section,
1110 unsigned section_line,
1111 const char *lvalue,
1112 int ltype,
1113 const char *rvalue,
1114 void *data,
1115 void *userdata) {
1116
99534007 1117 Network *network = ASSERT_PTR(userdata);
6706ce2f
YW
1118 usec_t usec;
1119 int r;
1120
1121 assert(filename);
1122 assert(lvalue);
1123 assert(rvalue);
6706ce2f
YW
1124
1125 if (isempty(rvalue)) {
1126 network->ignore_carrier_loss_set = false;
1127 return 0;
1128 }
1129
1130 r = parse_boolean(rvalue);
1131 if (r >= 0) {
1132 network->ignore_carrier_loss_set = true;
1133 network->ignore_carrier_loss_usec = r > 0 ? USEC_INFINITY : 0;
1134 return 0;
1135 }
1136
1137 r = parse_sec(rvalue, &usec);
1138 if (r < 0) {
1139 log_syntax(unit, LOG_WARNING, filename, line, r,
1140 "Failed to parse %s=, ignoring assignment: %s", lvalue, rvalue);
1141 return 0;
1142 }
1143
1144 network->ignore_carrier_loss_set = true;
1145 network->ignore_carrier_loss_usec = usec;
1146 return 0;
1147}
1148
8430841b
L
1149DEFINE_CONFIG_PARSE_ENUM(config_parse_required_family_for_online, link_required_address_family, AddressFamily,
1150 "Failed to parse RequiredFamilyForOnline= setting");
1151
7da377ef
SS
1152DEFINE_CONFIG_PARSE_ENUM(config_parse_keep_configuration, keep_configuration, KeepConfiguration,
1153 "Failed to parse KeepConfiguration= setting");
1154
1155static const char* const keep_configuration_table[_KEEP_CONFIGURATION_MAX] = {
95355a28
YW
1156 [KEEP_CONFIGURATION_NO] = "no",
1157 [KEEP_CONFIGURATION_DHCP_ON_STOP] = "dhcp-on-stop",
1158 [KEEP_CONFIGURATION_DHCP] = "dhcp",
1159 [KEEP_CONFIGURATION_STATIC] = "static",
1160 [KEEP_CONFIGURATION_YES] = "yes",
7da377ef
SS
1161};
1162
1163DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(keep_configuration, KeepConfiguration, KEEP_CONFIGURATION_YES);
6f6296b9 1164
61135582
DS
1165static const char* const activation_policy_table[_ACTIVATION_POLICY_MAX] = {
1166 [ACTIVATION_POLICY_UP] = "up",
1167 [ACTIVATION_POLICY_ALWAYS_UP] = "always-up",
1168 [ACTIVATION_POLICY_MANUAL] = "manual",
1169 [ACTIVATION_POLICY_ALWAYS_DOWN] = "always-down",
1170 [ACTIVATION_POLICY_DOWN] = "down",
1171 [ACTIVATION_POLICY_BOUND] = "bound",
1172};
1173
1174DEFINE_STRING_TABLE_LOOKUP(activation_policy, ActivationPolicy);
1175DEFINE_CONFIG_PARSE_ENUM(config_parse_activation_policy, activation_policy, ActivationPolicy, "Failed to parse activation policy");