]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/network/networkd-network.c
change req meson version
[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
YW
402 .dhcp6_use_address = true,
403 .dhcp6_use_dns = true,
38ba3da0 404 .dhcp6_use_hostname = true,
1536b7b2 405 .dhcp6_use_ntp = true,
4e26a5ba 406 .dhcp6_duid.type = _DUID_TYPE_INVALID,
caa8ca42 407
e502f94d 408 .dhcp6_pd = -1,
4afd9867 409 .dhcp6_pd_announce = true,
99e015e2 410 .dhcp6_pd_assign = true,
fec1b650 411 .dhcp6_pd_manage_temporary_address = true,
197aec7e 412 .dhcp6_pd_subnet_id = -1,
d0619f2c 413 .dhcp6_pd_route_metric = DHCP6PD_ROUTE_METRIC,
9efa8a3c 414
21b6b87e 415 .dhcp_server_bind_to_interface = true,
2a71d57f
LP
416 .dhcp_server_emit[SD_DHCP_LEASE_DNS].emit = true,
417 .dhcp_server_emit[SD_DHCP_LEASE_NTP].emit = true,
418 .dhcp_server_emit[SD_DHCP_LEASE_SIP].emit = true,
17f9c355
YW
419 .dhcp_server_emit_router = true,
420 .dhcp_server_emit_timezone = true,
421
71a5db49 422 .router_lifetime_usec = 30 * USEC_PER_MINUTE,
9fa25e07 423 .router_dns_lifetime_usec = 7 * USEC_PER_DAY,
17f9c355
YW
424 .router_emit_dns = true,
425 .router_emit_domains = true,
426
427 .use_bpdu = -1,
428 .hairpin = -1,
429 .fast_leave = -1,
430 .allow_port_to_be_root = -1,
431 .unicast_flood = -1,
7f15b714 432 .multicast_flood = -1,
d3aa8b49 433 .multicast_to_unicast = -1,
7f15b714
TJ
434 .neighbor_suppression = -1,
435 .learning = -1,
1087623b
SS
436 .bridge_proxy_arp = -1,
437 .bridge_proxy_arp_wifi = -1,
17f9c355 438 .priority = LINK_BRIDGE_PORT_PRIORITY_INVALID,
0fadb2a4 439 .multicast_router = _MULTICAST_ROUTER_INVALID,
17f9c355
YW
440
441 .lldp_mode = LLDP_MODE_ROUTERS_ONLY,
c01b9b87 442 .lldp_multicast_mode = _SD_LLDP_MULTICAST_MODE_INVALID,
17f9c355 443
7ece6f58 444 .dns_default_route = -1,
17f9c355
YW
445 .llmnr = RESOLVE_SUPPORT_YES,
446 .mdns = RESOLVE_SUPPORT_NO,
447 .dnssec_mode = _DNSSEC_MODE_INVALID,
448 .dns_over_tls_mode = _DNS_OVER_TLS_MODE_INVALID,
449
0321cea7 450 /* If LinkLocalAddressing= is not set, then set to ADDRESS_FAMILY_IPV6 later. */
2d792895 451 .link_local = _ADDRESS_FAMILY_INVALID,
6f6296b9 452 .ipv6ll_address_gen_mode = _IPV6_LINK_LOCAL_ADDRESS_GEN_MODE_INVALID,
17f9c355 453
94d76d07 454 .ipv4_accept_local = -1,
d75bf6cf 455 .ipv4_route_localnet = -1,
17f9c355 456 .ipv6_privacy_extensions = IPV6_PRIVACY_EXTENSIONS_NO,
17f9c355
YW
457 .ipv6_dad_transmits = -1,
458 .ipv6_hop_limit = -1,
459 .ipv6_proxy_ndp = -1,
17f9c355 460 .proxy_arp = -1,
db5756f3 461
7d93b92f 462 .ipv6_accept_ra = -1,
17f9c355 463 .ipv6_accept_ra_use_dns = true,
062c2eea
SS
464 .ipv6_accept_ra_use_autonomous_prefix = true,
465 .ipv6_accept_ra_use_onlink_prefix = true,
7d93b92f 466 .ipv6_accept_ra_use_mtu = true,
17f9c355 467 .ipv6_accept_ra_route_table = RT_TABLE_MAIN,
8ebafba9 468 .ipv6_accept_ra_route_metric = DHCP_ROUTE_METRIC,
cabe5711 469 .ipv6_accept_ra_start_dhcp6_client = IPV6_ACCEPT_RA_START_DHCP6_CLIENT_YES,
c423be28 470
52aa38f1 471 .can_termination = -1,
17f9c355 472 };
f579559b 473
4f9ff96a 474 r = config_parse_many(
8b8024f1 475 STRV_MAKE_CONST(filename), NETWORK_DIRS, dropin_dirname,
4f9ff96a
LP
476 "Match\0"
477 "Link\0"
518cd6b5 478 "SR-IOV\0"
4f9ff96a
LP
479 "Network\0"
480 "Address\0"
481 "Neighbor\0"
482 "IPv6AddressLabel\0"
483 "RoutingPolicyRule\0"
484 "Route\0"
485 "NextHop\0"
486 "DHCP\0" /* compat */
487 "DHCPv4\0"
488 "DHCPv6\0"
b209cff2 489 "DHCPv6PrefixDelegation\0"
4f9ff96a 490 "DHCPServer\0"
c517a49b 491 "DHCPServerStaticLease\0"
4f9ff96a
LP
492 "IPv6AcceptRA\0"
493 "IPv6NDPProxyAddress\0"
494 "Bridge\0"
495 "BridgeFDB\0"
3db468ea 496 "BridgeMDB\0"
4f9ff96a 497 "BridgeVLAN\0"
27ff0490 498 "IPv6SendRA\0"
4f9ff96a
LP
499 "IPv6PrefixDelegation\0"
500 "IPv6Prefix\0"
501 "IPv6RoutePrefix\0"
502 "LLDP\0"
503 "TrafficControlQueueingDiscipline\0"
504 "CAN\0"
505 "QDisc\0"
506 "BFIFO\0"
507 "CAKE\0"
508 "ControlledDelay\0"
509 "DeficitRoundRobinScheduler\0"
510 "DeficitRoundRobinSchedulerClass\0"
d474aa51 511 "EnhancedTransmissionSelection\0"
4f9ff96a
LP
512 "FairQueueing\0"
513 "FairQueueingControlledDelay\0"
8f6b6d70 514 "FlowQueuePIE\0"
4f9ff96a
LP
515 "GenericRandomEarlyDetection\0"
516 "HeavyHitterFilter\0"
517 "HierarchyTokenBucket\0"
518 "HierarchyTokenBucketClass\0"
519 "NetworkEmulator\0"
b12aaee5
SS
520 "PFIFO\0"
521 "PFIFOFast\0"
522 "PFIFOHeadDrop\0"
4f9ff96a 523 "PIE\0"
b12aaee5 524 "QuickFairQueueing\0"
4d7ddaf9 525 "QuickFairQueueingClass\0"
4f9ff96a
LP
526 "StochasticFairBlue\0"
527 "StochasticFairnessQueueing\0"
528 "TokenBucketFilter\0"
529 "TrivialLinkEqualizer\0",
530 config_item_perf_lookup, network_network_gperf_lookup,
531 CONFIG_PARSE_WARN,
532 network,
533 &network->timestamp);
102bc043 534 if (r < 0)
f579559b 535 return r;
f579559b 536
fa7cd711
YW
537 r = network_add_ipv4ll_route(network);
538 if (r < 0)
9202b567 539 return log_warning_errno(r, "%s: Failed to add IPv4LL route: %m", network->filename);
fa7cd711 540
5d5003ab
YW
541 r = network_add_default_route_on_device(network);
542 if (r < 0)
9202b567
YW
543 return log_warning_errno(r, "%s: Failed to add default route on device: %m",
544 network->filename);
5d5003ab 545
9202b567
YW
546 r = network_verify(network);
547 if (r == -ENOMEM)
548 return r;
549 if (r < 0)
7f06b3e1
YW
550 /* Ignore .network files that do not match the conditions. */
551 return 0;
552
9fa3e794 553 r = ordered_hashmap_ensure_put(networks, &string_hash_ops, network->name, network);
dbffab87
TG
554 if (r < 0)
555 return r;
556
b5b9b0e7 557 TAKE_PTR(network);
f579559b
TG
558 return 0;
559}
560
7f06b3e1 561int network_load(Manager *manager, OrderedHashmap **networks) {
477e73b5
ZJS
562 _cleanup_strv_free_ char **files = NULL;
563 char **f;
f579559b
TG
564 int r;
565
566 assert(manager);
567
7f06b3e1 568 ordered_hashmap_clear_with_destructor(*networks, network_unref);
f579559b 569
dc0d4078 570 r = conf_files_list_strv(&files, ".network", NULL, 0, NETWORK_DIRS);
f647962d
MS
571 if (r < 0)
572 return log_error_errno(r, "Failed to enumerate network files: %m");
f579559b 573
715d398e 574 STRV_FOREACH(f, files) {
7f06b3e1 575 r = network_load_one(manager, networks, *f);
f579559b 576 if (r < 0)
9202b567 577 return log_error_errno(r, "Failed to load %s: %m", *f);
f579559b
TG
578 }
579
f579559b
TG
580 return 0;
581}
582
7f06b3e1
YW
583int network_reload(Manager *manager) {
584 OrderedHashmap *new_networks = NULL;
585 Network *n, *old;
7f06b3e1
YW
586 int r;
587
588 assert(manager);
589
590 r = network_load(manager, &new_networks);
591 if (r < 0)
592 goto failure;
593
90e74a66 594 ORDERED_HASHMAP_FOREACH(n, new_networks) {
7f06b3e1
YW
595 r = network_get_by_name(manager, n->name, &old);
596 if (r < 0)
597 continue; /* The .network file is new. */
598
599 if (n->timestamp != old->timestamp)
600 continue; /* The .network file is modified. */
601
602 if (!streq(n->filename, old->filename))
603 continue;
604
605 r = ordered_hashmap_replace(new_networks, old->name, old);
606 if (r < 0)
607 goto failure;
608
609 network_ref(old);
610 network_unref(n);
611 }
612
613 ordered_hashmap_free_with_destructor(manager->networks, network_unref);
614 manager->networks = new_networks;
615
616 return 0;
617
618failure:
619 ordered_hashmap_free_with_destructor(new_networks, network_unref);
620
621 return r;
622}
623
35ac3b76 624static Network *network_free(Network *network) {
f579559b 625 if (!network)
35ac3b76 626 return NULL;
f579559b
TG
627
628 free(network->filename);
629
5722fb89 630 net_match_clear(&network->match);
c4f58dea 631 condition_free_list(network->conditions);
f579559b 632
11c38d3e
YA
633 free(network->dhcp_server_relay_agent_circuit_id);
634 free(network->dhcp_server_relay_agent_remote_id);
635
f579559b 636 free(network->description);
edb85f0d 637 free(network->dhcp_vendor_class_identifier);
7b8d23a9 638 free(network->dhcp_mudurl);
af1c0de0 639 strv_free(network->dhcp_user_class);
27cb34f5 640 free(network->dhcp_hostname);
d419ef02 641 free(network->dhcp_label);
6b000af4 642 set_free(network->dhcp_deny_listed_ip);
98ebef62 643 set_free(network->dhcp_allow_listed_ip);
5bc945be 644 set_free(network->dhcp_request_options);
35f6a5cb 645 set_free(network->dhcp6_request_options);
c106cc36 646 free(network->mac);
3175a8c2 647 free(network->dhcp6_mudurl);
f37f2a6b 648 strv_free(network->dhcp6_user_class);
ed0d1b2e 649 strv_free(network->dhcp6_vendor_class);
c106cc36 650
b0e39c82 651 strv_free(network->ntp);
e77bd3fd
YW
652 for (unsigned i = 0; i < network->n_dns; i++)
653 in_addr_full_free(network->dns[i]);
5512a963 654 free(network->dns);
5e276772
YW
655 ordered_set_free(network->search_domains);
656 ordered_set_free(network->route_domains);
0d4ad91d 657 strv_free(network->bind_carrier);
cdd7812b 658
5e276772 659 ordered_set_free(network->router_search_domains);
cdd7812b 660 free(network->router_dns);
c995fa02
YW
661 set_free(network->ndisc_deny_listed_router);
662 set_free(network->ndisc_allow_listed_router);
663 set_free(network->ndisc_deny_listed_prefix);
664 set_free(network->ndisc_allow_listed_prefix);
665 set_free(network->ndisc_deny_listed_route_prefix);
666 set_free(network->ndisc_allow_listed_route_prefix);
3bef724f 667
c0267a59 668 free(network->batadv_name);
cebe1257
YW
669 free(network->bridge_name);
670 free(network->bond_name);
671 free(network->vrf_name);
672 hashmap_free_free_key(network->stacked_netdev_names);
47e2dc31 673 netdev_unref(network->bridge);
47e2dc31 674 netdev_unref(network->bond);
6cb955c6 675 netdev_unref(network->vrf);
fa6f1e54 676 hashmap_free_with_destructor(network->stacked_netdevs, netdev_unref);
326cb406 677
d349f502 678 set_free_free(network->ipv6_proxy_ndp_addresses);
9cd9fc8f 679 ordered_hashmap_free_with_destructor(network->addresses_by_section, address_free);
2a54a044 680 hashmap_free_with_destructor(network->routes_by_section, route_free);
b82663dd 681 hashmap_free_with_destructor(network->nexthops_by_section, nexthop_free);
9671ae9d 682 hashmap_free_with_destructor(network->bridge_fdb_entries_by_section, bridge_fdb_free);
ff9e0783 683 hashmap_free_with_destructor(network->bridge_mdb_entries_by_section, bridge_mdb_free);
b0ba6938 684 hashmap_free_with_destructor(network->neighbors_by_section, neighbor_free);
d6a2a0f9 685 hashmap_free_with_destructor(network->address_labels_by_section, address_label_free);
ecb0e85e
YW
686 hashmap_free_with_destructor(network->prefixes_by_section, prefix_free);
687 hashmap_free_with_destructor(network->route_prefixes_by_section, route_prefix_free);
ca183bf8 688 hashmap_free_with_destructor(network->rules_by_section, routing_policy_rule_free);
c517a49b 689 hashmap_free_with_destructor(network->dhcp_static_leases_by_section, dhcp_static_lease_free);
518cd6b5 690 ordered_hashmap_free_with_destructor(network->sr_iov_by_section, sr_iov_free);
34658df2 691 ordered_hashmap_free_with_destructor(network->tc_by_section, traffic_control_free);
6ae115c1 692
dbffab87 693 free(network->name);
f579559b 694
8eb9058d 695 free(network->dhcp_server_timezone);
165d7c5c 696 free(network->dhcp_server_uplink_name);
63295b42 697 free(network->router_uplink_name);
2a71d57f 698
2324fd3a 699 for (sd_dhcp_lease_server_type_t t = 0; t < _SD_DHCP_LEASE_SERVER_TYPE_MAX; t++)
2a71d57f 700 free(network->dhcp_server_emit[t].addresses);
8eb9058d 701
8a516214
LP
702 set_free_free(network->dnssec_negative_trust_anchors);
703
c01b9b87 704 free(network->lldp_mudurl);
e9a8c550 705
0e96961d 706 ordered_hashmap_free(network->dhcp_client_send_options);
7354900d 707 ordered_hashmap_free(network->dhcp_client_send_vendor_options);
0e96961d 708 ordered_hashmap_free(network->dhcp_server_send_options);
7354900d 709 ordered_hashmap_free(network->dhcp_server_send_vendor_options);
1c3ec1cd 710 ordered_hashmap_free(network->dhcp6_client_send_options);
b4ccc5de 711 ordered_hashmap_free(network->dhcp6_client_send_vendor_options);
f5960e0a 712 set_free(network->dhcp6_pd_tokens);
3bac5fe6 713 set_free(network->ndisc_tokens);
cb29c156 714
35ac3b76 715 return mfree(network);
f579559b
TG
716}
717
35ac3b76
YW
718DEFINE_TRIVIAL_REF_UNREF_FUNC(Network, network, network_free);
719
dbffab87
TG
720int network_get_by_name(Manager *manager, const char *name, Network **ret) {
721 Network *network;
722
723 assert(manager);
724 assert(name);
725 assert(ret);
726
715d398e 727 network = ordered_hashmap_get(manager->networks, name);
dbffab87
TG
728 if (!network)
729 return -ENOENT;
730
731 *ret = network;
732
733 return 0;
734}
735
adfeee49 736bool network_has_static_ipv6_configurations(Network *network) {
439689c6 737 Address *address;
adfeee49 738 Route *route;
9671ae9d 739 BridgeFDB *fdb;
ff9e0783 740 BridgeMDB *mdb;
adfeee49 741 Neighbor *neighbor;
439689c6
SS
742
743 assert(network);
744
9cd9fc8f 745 ORDERED_HASHMAP_FOREACH(address, network->addresses_by_section)
439689c6
SS
746 if (address->family == AF_INET6)
747 return true;
adfeee49 748
2a54a044 749 HASHMAP_FOREACH(route, network->routes_by_section)
adfeee49
YW
750 if (route->family == AF_INET6)
751 return true;
752
9671ae9d 753 HASHMAP_FOREACH(fdb, network->bridge_fdb_entries_by_section)
adfeee49
YW
754 if (fdb->family == AF_INET6)
755 return true;
756
ff9e0783 757 HASHMAP_FOREACH(mdb, network->bridge_mdb_entries_by_section)
3db468ea
DM
758 if (mdb->family == AF_INET6)
759 return true;
760
b0ba6938 761 HASHMAP_FOREACH(neighbor, network->neighbors_by_section)
adfeee49
YW
762 if (neighbor->family == AF_INET6)
763 return true;
764
d6a2a0f9 765 if (!hashmap_isempty(network->address_labels_by_section))
adfeee49
YW
766 return true;
767
ecb0e85e 768 if (!hashmap_isempty(network->prefixes_by_section))
adfeee49 769 return true;
d30081c2
YW
770
771 if (!hashmap_isempty(network->route_prefixes_by_section))
772 return true;
439689c6
SS
773
774 return false;
775}
776
63481576
YW
777int config_parse_stacked_netdev(
778 const char *unit,
02b59d57
TG
779 const char *filename,
780 unsigned line,
781 const char *section,
782 unsigned section_line,
783 const char *lvalue,
784 int ltype,
785 const char *rvalue,
786 void *data,
787 void *userdata) {
63481576 788
95dba435
YW
789 _cleanup_free_ char *name = NULL;
790 NetDevKind kind = ltype;
cebe1257 791 Hashmap **h = data;
02b59d57
TG
792 int r;
793
794 assert(filename);
795 assert(lvalue);
796 assert(rvalue);
797 assert(data);
95dba435
YW
798 assert(IN_SET(kind,
799 NETDEV_KIND_VLAN, NETDEV_KIND_MACVLAN, NETDEV_KIND_MACVTAP,
69c317a0 800 NETDEV_KIND_IPVLAN, NETDEV_KIND_IPVTAP, NETDEV_KIND_VXLAN,
98d20a17 801 NETDEV_KIND_L2TP, NETDEV_KIND_MACSEC, _NETDEV_KIND_TUNNEL,
802 NETDEV_KIND_XFRM));
54abf461 803
cebe1257 804 if (!ifname_valid(rvalue)) {
d96edb2c 805 log_syntax(unit, LOG_WARNING, filename, line, 0,
3772cfde 806 "Invalid netdev name in %s=, ignoring assignment: %s", lvalue, rvalue);
54abf461
TG
807 return 0;
808 }
809
cebe1257
YW
810 name = strdup(rvalue);
811 if (!name)
812 return log_oom();
3e570042 813
6de530f2
SS
814 r = hashmap_ensure_put(h, &string_hash_ops, name, INT_TO_PTR(kind));
815 if (r == -ENOMEM)
cebe1257 816 return log_oom();
83ec4592 817 if (r < 0)
d96edb2c 818 log_syntax(unit, LOG_WARNING, filename, line, r,
83ec4592
ZJS
819 "Cannot add NetDev '%s' to network, ignoring assignment: %m", name);
820 else if (r == 0)
821 log_syntax(unit, LOG_DEBUG, filename, line, r,
822 "NetDev '%s' specified twice, ignoring.", name);
823 else
0c7bd7ec 824 TAKE_PTR(name);
47e2dc31 825
fe6b2d55
TG
826 return 0;
827}
7951dea2 828
3df9bec5
LP
829int config_parse_domains(
830 const char *unit,
831 const char *filename,
832 unsigned line,
833 const char *section,
834 unsigned section_line,
835 const char *lvalue,
836 int ltype,
837 const char *rvalue,
838 void *data,
839 void *userdata) {
840
5aafd5b1 841 Network *n = userdata;
6192b846
TG
842 int r;
843
5aafd5b1 844 assert(filename);
3df9bec5
LP
845 assert(lvalue);
846 assert(rvalue);
5aafd5b1 847 assert(n);
6192b846 848
3df9bec5 849 if (isempty(rvalue)) {
5e276772
YW
850 n->search_domains = ordered_set_free(n->search_domains);
851 n->route_domains = ordered_set_free(n->route_domains);
3df9bec5
LP
852 return 0;
853 }
67272d15 854
d96edb2c 855 for (const char *p = rvalue;;) {
3df9bec5
LP
856 _cleanup_free_ char *w = NULL, *normalized = NULL;
857 const char *domain;
858 bool is_route;
859
860 r = extract_first_word(&p, &w, NULL, 0);
d96edb2c
YW
861 if (r == -ENOMEM)
862 return log_oom();
3df9bec5 863 if (r < 0) {
d96edb2c 864 log_syntax(unit, LOG_WARNING, filename, line, r,
ab24039f 865 "Failed to extract search or route domain, ignoring: %s", rvalue);
d96edb2c 866 return 0;
3df9bec5
LP
867 }
868 if (r == 0)
d96edb2c 869 return 0;
3df9bec5
LP
870
871 is_route = w[0] == '~';
872 domain = is_route ? w + 1 : w;
873
874 if (dns_name_is_root(domain) || streq(domain, "*")) {
ab24039f
ZJS
875 /* If the root domain appears as is, or the special token "*" is found, we'll
876 * consider this as routing domain, unconditionally. */
3df9bec5 877 is_route = true;
ab24039f
ZJS
878 domain = "."; /* make sure we don't allow empty strings, thus write the root
879 * domain as "." */
3df9bec5 880 } else {
7470cc4c 881 r = dns_name_normalize(domain, 0, &normalized);
3df9bec5 882 if (r < 0) {
d96edb2c 883 log_syntax(unit, LOG_WARNING, filename, line, r,
ab24039f 884 "'%s' is not a valid domain name, ignoring.", domain);
3df9bec5
LP
885 continue;
886 }
887
888 domain = normalized;
889
890 if (is_localhost(domain)) {
d96edb2c 891 log_syntax(unit, LOG_WARNING, filename, line, 0,
ab24039f
ZJS
892 "'localhost' domain may not be configured as search or route domain, ignoring assignment: %s",
893 domain);
37de2509 894 continue;
3df9bec5 895 }
37de2509 896 }
40274ed6 897
5e2a51d5 898 OrderedSet **set = is_route ? &n->route_domains : &n->search_domains;
cf453507
YW
899 r = ordered_set_put_strdup(set, domain);
900 if (r == -EEXIST)
901 continue;
09451975
LP
902 if (r < 0)
903 return log_oom();
40274ed6 904 }
6192b846
TG
905}
906
1ac608c9
LP
907int config_parse_hostname(
908 const char *unit,
909 const char *filename,
910 unsigned line,
911 const char *section,
912 unsigned section_line,
913 const char *lvalue,
914 int ltype,
915 const char *rvalue,
916 void *data,
917 void *userdata) {
918
6528693a 919 char **hostname = data;
a7d0ef44
SS
920 int r;
921
922 assert(filename);
923 assert(lvalue);
924 assert(rvalue);
b40b8b06 925 assert(data);
a7d0ef44 926
b40b8b06
YW
927 if (isempty(rvalue)) {
928 *hostname = mfree(*hostname);
929 return 0;
930 }
a7d0ef44 931
b40b8b06 932 if (!hostname_is_valid(rvalue, 0)) {
d96edb2c 933 log_syntax(unit, LOG_WARNING, filename, line, 0,
ab24039f 934 "Hostname is not valid, ignoring assignment: %s", rvalue);
a7d0ef44
SS
935 return 0;
936 }
937
b40b8b06 938 r = dns_name_is_valid(rvalue);
6528693a 939 if (r < 0) {
d96edb2c 940 log_syntax(unit, LOG_WARNING, filename, line, r,
ab24039f 941 "Failed to check validity of hostname '%s', ignoring assignment: %m", rvalue);
6528693a
YW
942 return 0;
943 }
944 if (r == 0) {
d96edb2c 945 log_syntax(unit, LOG_WARNING, filename, line, 0,
ab24039f 946 "Hostname is not a valid DNS domain name, ignoring assignment: %s", rvalue);
6528693a
YW
947 return 0;
948 }
949
b40b8b06 950 return free_and_strdup_warn(hostname, rvalue);
a7d0ef44 951}
8eb9058d
LP
952
953int config_parse_timezone(
954 const char *unit,
955 const char *filename,
956 unsigned line,
957 const char *section,
958 unsigned section_line,
959 const char *lvalue,
960 int ltype,
961 const char *rvalue,
962 void *data,
963 void *userdata) {
964
b40b8b06 965 char **tz = data;
8eb9058d
LP
966 int r;
967
968 assert(filename);
969 assert(lvalue);
970 assert(rvalue);
b40b8b06 971 assert(data);
8eb9058d 972
b40b8b06
YW
973 if (isempty(rvalue)) {
974 *tz = mfree(*tz);
975 return 0;
976 }
8eb9058d 977
b40b8b06
YW
978 r = verify_timezone(rvalue, LOG_WARNING);
979 if (r < 0) {
980 log_syntax(unit, LOG_WARNING, filename, line, r,
ab24039f 981 "Timezone is not valid, ignoring assignment: %s", rvalue);
8eb9058d
LP
982 return 0;
983 }
984
b40b8b06 985 return free_and_strdup_warn(tz, rvalue);
8eb9058d 986}
1a04db0f 987
53253824
SS
988int config_parse_dns(
989 const char *unit,
990 const char *filename,
991 unsigned line,
992 const char *section,
993 unsigned section_line,
994 const char *lvalue,
995 int ltype,
996 const char *rvalue,
997 void *data,
998 void *userdata) {
999
1000 Network *n = userdata;
1001 int r;
1002
1003 assert(filename);
1004 assert(lvalue);
1005 assert(rvalue);
5aafd5b1 1006 assert(n);
53253824 1007
d96edb2c 1008 if (isempty(rvalue)) {
e77bd3fd
YW
1009 for (unsigned i = 0; i < n->n_dns; i++)
1010 in_addr_full_free(n->dns[i]);
d96edb2c
YW
1011 n->dns = mfree(n->dns);
1012 n->n_dns = 0;
1013 return 0;
1014 }
1015
1016 for (const char *p = rvalue;;) {
e77bd3fd 1017 _cleanup_(in_addr_full_freep) struct in_addr_full *dns = NULL;
53253824 1018 _cleanup_free_ char *w = NULL;
e77bd3fd 1019 struct in_addr_full **m;
53253824 1020
d96edb2c 1021 r = extract_first_word(&p, &w, NULL, 0);
53253824
SS
1022 if (r == -ENOMEM)
1023 return log_oom();
1024 if (r < 0) {
d96edb2c 1025 log_syntax(unit, LOG_WARNING, filename, line, r,
ab24039f 1026 "Invalid syntax, ignoring: %s", rvalue);
d96edb2c 1027 return 0;
53253824 1028 }
5512a963 1029 if (r == 0)
d96edb2c 1030 return 0;
53253824 1031
e77bd3fd 1032 r = in_addr_full_new_from_string(w, &dns);
53253824 1033 if (r < 0) {
d96edb2c 1034 log_syntax(unit, LOG_WARNING, filename, line, r,
ab24039f 1035 "Failed to parse dns server address, ignoring: %s", w);
53253824
SS
1036 continue;
1037 }
1038
e77bd3fd
YW
1039 if (IN_SET(dns->port, 53, 853))
1040 dns->port = 0;
1041
1042 m = reallocarray(n->dns, n->n_dns + 1, sizeof(struct in_addr_full*));
5512a963 1043 if (!m)
53253824
SS
1044 return log_oom();
1045
e77bd3fd 1046 m[n->n_dns++] = TAKE_PTR(dns);
5512a963 1047 n->dns = m;
53253824 1048 }
53253824
SS
1049}
1050
8a516214
LP
1051int config_parse_dnssec_negative_trust_anchors(
1052 const char *unit,
1053 const char *filename,
1054 unsigned line,
1055 const char *section,
1056 unsigned section_line,
1057 const char *lvalue,
1058 int ltype,
1059 const char *rvalue,
1060 void *data,
1061 void *userdata) {
1062
5aafd5b1 1063 Set **nta = data;
8a516214
LP
1064 int r;
1065
5aafd5b1 1066 assert(filename);
8a516214
LP
1067 assert(lvalue);
1068 assert(rvalue);
5aafd5b1 1069 assert(nta);
8a516214
LP
1070
1071 if (isempty(rvalue)) {
5aafd5b1 1072 *nta = set_free_free(*nta);
8a516214
LP
1073 return 0;
1074 }
1075
d96edb2c 1076 for (const char *p = rvalue;;) {
8a516214
LP
1077 _cleanup_free_ char *w = NULL;
1078
1079 r = extract_first_word(&p, &w, NULL, 0);
d96edb2c
YW
1080 if (r == -ENOMEM)
1081 return log_oom();
8a516214 1082 if (r < 0) {
d96edb2c 1083 log_syntax(unit, LOG_WARNING, filename, line, r,
ab24039f 1084 "Failed to extract negative trust anchor domain, ignoring: %s", rvalue);
d96edb2c 1085 return 0;
8a516214
LP
1086 }
1087 if (r == 0)
d96edb2c 1088 return 0;
8a516214
LP
1089
1090 r = dns_name_is_valid(w);
1091 if (r <= 0) {
d96edb2c 1092 log_syntax(unit, LOG_WARNING, filename, line, r,
ab24039f 1093 "%s is not a valid domain name, ignoring.", w);
8a516214
LP
1094 continue;
1095 }
1096
5aafd5b1 1097 r = set_ensure_consume(nta, &dns_name_hash_ops, TAKE_PTR(w));
8a516214
LP
1098 if (r < 0)
1099 return log_oom();
8a516214 1100 }
8a516214 1101}
b2a81c0b 1102
26575990
LP
1103int config_parse_ntp(
1104 const char *unit,
1105 const char *filename,
1106 unsigned line,
1107 const char *section,
1108 unsigned section_line,
1109 const char *lvalue,
1110 int ltype,
1111 const char *rvalue,
1112 void *data,
1113 void *userdata) {
1114
1115 char ***l = data;
1116 int r;
1117
5aafd5b1 1118 assert(filename);
26575990
LP
1119 assert(lvalue);
1120 assert(rvalue);
5aafd5b1 1121 assert(l);
26575990
LP
1122
1123 if (isempty(rvalue)) {
1124 *l = strv_free(*l);
1125 return 0;
1126 }
1127
d96edb2c 1128 for (const char *p = rvalue;;) {
26575990
LP
1129 _cleanup_free_ char *w = NULL;
1130
d96edb2c 1131 r = extract_first_word(&p, &w, NULL, 0);
26575990
LP
1132 if (r == -ENOMEM)
1133 return log_oom();
1134 if (r < 0) {
d96edb2c 1135 log_syntax(unit, LOG_WARNING, filename, line, r,
ab24039f 1136 "Failed to extract NTP server name, ignoring: %s", rvalue);
d96edb2c 1137 return 0;
26575990
LP
1138 }
1139 if (r == 0)
d96edb2c 1140 return 0;
26575990
LP
1141
1142 r = dns_name_is_valid_or_address(w);
1143 if (r <= 0) {
d96edb2c 1144 log_syntax(unit, LOG_WARNING, filename, line, r,
ab24039f 1145 "%s is not a valid domain name or IP address, ignoring.", w);
26575990 1146 continue;
af1c0de0
SS
1147 }
1148
c448459d
ZJS
1149 if (strv_length(*l) > MAX_NTP_SERVERS) {
1150 log_syntax(unit, LOG_WARNING, filename, line, 0,
1151 "More than %u NTP servers specified, ignoring \"%s\" and any subsequent entries.",
1152 MAX_NTP_SERVERS, w);
d96edb2c 1153 return 0;
c448459d
ZJS
1154 }
1155
1156 r = strv_consume(l, TAKE_PTR(w));
af1c0de0
SS
1157 if (r < 0)
1158 return log_oom();
af1c0de0 1159 }
af1c0de0
SS
1160}
1161
4ac77d63
YW
1162int config_parse_required_for_online(
1163 const char *unit,
1164 const char *filename,
1165 unsigned line,
1166 const char *section,
1167 unsigned section_line,
1168 const char *lvalue,
1169 int ltype,
1170 const char *rvalue,
1171 void *data,
1172 void *userdata) {
1173
5aafd5b1 1174 Network *network = userdata;
75cd4a5d 1175 LinkOperationalStateRange range;
4ac77d63
YW
1176 bool required = true;
1177 int r;
1178
5aafd5b1
YW
1179 assert(filename);
1180 assert(lvalue);
1181 assert(rvalue);
1182 assert(network);
1183
4ac77d63 1184 if (isempty(rvalue)) {
7c644a69 1185 network->required_for_online = -1;
75cd4a5d 1186 network->required_operstate_for_online = LINK_OPERSTATE_RANGE_DEFAULT;
4ac77d63
YW
1187 return 0;
1188 }
1189
75cd4a5d
DDM
1190 r = parse_operational_state_range(rvalue, &range);
1191 if (r < 0) {
4ac77d63
YW
1192 r = parse_boolean(rvalue);
1193 if (r < 0) {
d96edb2c 1194 log_syntax(unit, LOG_WARNING, filename, line, r,
4ac77d63
YW
1195 "Failed to parse %s= setting, ignoring assignment: %s",
1196 lvalue, rvalue);
1197 return 0;
1198 }
1199
1200 required = r;
75cd4a5d 1201 range = LINK_OPERSTATE_RANGE_DEFAULT;
4ac77d63
YW
1202 }
1203
1204 network->required_for_online = required;
75cd4a5d 1205 network->required_operstate_for_online = range;
4ac77d63
YW
1206
1207 return 0;
1208}
7da377ef 1209
f0c09831
YW
1210int config_parse_link_group(
1211 const char *unit,
1212 const char *filename,
1213 unsigned line,
1214 const char *section,
1215 unsigned section_line,
1216 const char *lvalue,
1217 int ltype,
1218 const char *rvalue,
1219 void *data,
1220 void *userdata) {
1221
1222 Network *network = userdata;
1223 int r;
1224
1225 assert(filename);
1226 assert(lvalue);
1227 assert(rvalue);
1228 assert(network);
1229
1230 if (isempty(rvalue)) {
1231 network->group = 0;
1232 network->group_set = false;
1233 return 0;
1234 }
1235
1236 r = safe_atou32(rvalue, &network->group);
1237 if (r < 0) {
1238 log_syntax(unit, LOG_WARNING, filename, line, r,
1239 "Failed to parse Group=, ignoring assignment: %s", rvalue);
1240 return 0;
1241 }
1242
1243 network->group_set = true;
1244 return 0;
1245}
1246
63295b42
YW
1247
1248int config_parse_uplink(
1249 const char *unit,
1250 const char *filename,
1251 unsigned line,
1252 const char *section,
1253 unsigned section_line,
1254 const char *lvalue,
1255 int ltype,
1256 const char *rvalue,
1257 void *data,
1258 void *userdata) {
1259
1260 Network *network = userdata;
1261 int *index, r;
1262 char **name;
1263
1264 assert(filename);
1265 assert(section);
1266 assert(lvalue);
1267 assert(rvalue);
1268
1269 if (streq(section, "DHCPServer")) {
1270 index = &network->dhcp_server_uplink_index;
1271 name = &network->dhcp_server_uplink_name;
1272 } else if (streq(section, "IPv6SendRA")) {
1273 index = &network->router_uplink_index;
1274 name = &network->router_uplink_name;
1275 } else
1276 assert_not_reached();
1277
1278 if (isempty(rvalue) || streq(rvalue, ":auto")) {
1279 *index = UPLINK_INDEX_AUTO;
1280 *name = mfree(*name);
1281 return 0;
1282 }
1283
1284 if (streq(rvalue, ":none")) {
1285 *index = UPLINK_INDEX_NONE;
1286 *name = mfree(*name);
1287 return 0;
1288 }
1289
1290 r = parse_ifindex(rvalue);
1291 if (r > 0) {
1292 *index = r;
1293 *name = mfree(*name);
1294 return 0;
1295 }
1296
1297 if (!ifname_valid_full(rvalue, IFNAME_VALID_ALTERNATIVE)) {
1298 log_syntax(unit, LOG_WARNING, filename, line, 0,
1299 "Invalid interface name in %s=, ignoring assignment: %s", lvalue, rvalue);
1300 return 0;
1301 }
1302
1303 /* The interface name will be resolved later. */
1304 r = free_and_strdup_warn(name, rvalue);
1305 if (r < 0)
1306 return r;
1307
1308 /* Note, if uplink_name is set, then uplink_index will be ignored. So, the below does not mean
1309 * an uplink interface will be selected automatically. */
1310 *index = UPLINK_INDEX_AUTO;
1311 return 0;
1312}
1313
8430841b
L
1314DEFINE_CONFIG_PARSE_ENUM(config_parse_required_family_for_online, link_required_address_family, AddressFamily,
1315 "Failed to parse RequiredFamilyForOnline= setting");
1316
7da377ef
SS
1317DEFINE_CONFIG_PARSE_ENUM(config_parse_keep_configuration, keep_configuration, KeepConfiguration,
1318 "Failed to parse KeepConfiguration= setting");
1319
1320static const char* const keep_configuration_table[_KEEP_CONFIGURATION_MAX] = {
95355a28
YW
1321 [KEEP_CONFIGURATION_NO] = "no",
1322 [KEEP_CONFIGURATION_DHCP_ON_STOP] = "dhcp-on-stop",
1323 [KEEP_CONFIGURATION_DHCP] = "dhcp",
1324 [KEEP_CONFIGURATION_STATIC] = "static",
1325 [KEEP_CONFIGURATION_YES] = "yes",
7da377ef
SS
1326};
1327
1328DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(keep_configuration, KeepConfiguration, KEEP_CONFIGURATION_YES);
6f6296b9
YW
1329
1330static const char* const ipv6_link_local_address_gen_mode_table[_IPV6_LINK_LOCAL_ADDRESS_GEN_MODE_MAX] = {
1331 [IPV6_LINK_LOCAL_ADDRESSS_GEN_MODE_EUI64] = "eui64",
1332 [IPV6_LINK_LOCAL_ADDRESSS_GEN_MODE_NONE] = "none",
1333 [IPV6_LINK_LOCAL_ADDRESSS_GEN_MODE_STABLE_PRIVACY] = "stable-privacy",
1334 [IPV6_LINK_LOCAL_ADDRESSS_GEN_MODE_RANDOM] = "random",
1335};
1336
1337DEFINE_STRING_TABLE_LOOKUP(ipv6_link_local_address_gen_mode, IPv6LinkLocalAddressGenMode);
1338DEFINE_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
1339
1340static const char* const activation_policy_table[_ACTIVATION_POLICY_MAX] = {
1341 [ACTIVATION_POLICY_UP] = "up",
1342 [ACTIVATION_POLICY_ALWAYS_UP] = "always-up",
1343 [ACTIVATION_POLICY_MANUAL] = "manual",
1344 [ACTIVATION_POLICY_ALWAYS_DOWN] = "always-down",
1345 [ACTIVATION_POLICY_DOWN] = "down",
1346 [ACTIVATION_POLICY_BOUND] = "bound",
1347};
1348
1349DEFINE_STRING_TABLE_LOOKUP(activation_policy, ActivationPolicy);
1350DEFINE_CONFIG_PARSE_ENUM(config_parse_activation_policy, activation_policy, ActivationPolicy, "Failed to parse activation policy");