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