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