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