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