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