]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/network/networkd-network.c
network: move manager_rtnl_process_neighbor() to networkd-neighbor.c
[thirdparty/systemd.git] / src / network / networkd-network.c
CommitLineData
53e1b683 1/* SPDX-License-Identifier: LGPL-2.1+ */
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"
564ca984 15#include "networkd-dhcp-server.h"
fc2f9534 16#include "network-internal.h"
23f53b99 17#include "networkd-manager.h"
3ffd4af2 18#include "networkd-network.h"
75156ccb 19#include "networkd-nexthop.h"
ca183bf8 20#include "networkd-routing-policy-rule.h"
518cd6b5 21#include "networkd-sriov.h"
6bedfcbb 22#include "parse-util.h"
b0c82192 23#include "path-lookup.h"
8a516214 24#include "set.h"
cebe1257 25#include "socket-util.h"
8fcde012 26#include "stat-util.h"
8b43440b 27#include "string-table.h"
07630cea 28#include "string-util.h"
700f1186 29#include "strv.h"
34658df2 30#include "tc.h"
07630cea 31#include "util.h"
f579559b 32
c448459d
ZJS
33/* Let's assume that anything above this number is a user misconfiguration. */
34#define MAX_NTP_SERVERS 128
35
add8d07d 36/* Set defaults following RFC7844 */
37void network_apply_anonymize_if_set(Network *network) {
38 if (!network->dhcp_anonymize)
39 return;
40 /* RFC7844 3.7
41 SHOULD NOT send the Host Name option */
42 network->dhcp_send_hostname = false;
43 /* RFC7844 section 3.:
44 MAY contain the Client Identifier option
45 Section 3.5:
46 clients MUST use client identifiers based solely
47 on the link-layer address */
48 /* NOTE: Using MAC, as it does not reveal extra information,
49 * and some servers might not answer if this option is not sent */
50 network->dhcp_client_identifier = DHCP_CLIENT_ID_MAC;
51 /* RFC 7844 3.10:
52 SHOULD NOT use the Vendor Class Identifier option */
727ba17f 53 network->dhcp_vendor_class_identifier = mfree(network->dhcp_vendor_class_identifier);
add8d07d 54 /* RFC7844 section 3.6.:
55 The client intending to protect its privacy SHOULD only request a
56 minimal number of options in the PRL and SHOULD also randomly shuffle
43bf2874 57 the ordering of option codes in the PRL. If this random ordering
add8d07d 58 cannot be implemented, the client MAY order the option codes in the
59 PRL by option code number (lowest to highest).
60 */
61 /* NOTE: dhcp_use_mtu is false by default,
62 * though it was not initiallized to any value in network_load_one.
63 * Maybe there should be another var called *send*?
64 * (to use the MTU sent by the server but to do not send
65 * the option in the PRL). */
66 network->dhcp_use_mtu = false;
28522b0d 67 /* NOTE: when Anonymize=yes, the PRL route options are sent by default,
68 * but this is needed to use them. */
69 network->dhcp_use_routes = true;
add8d07d 70 /* RFC7844 section 3.6.
71 * same comments as previous option */
72 network->dhcp_use_timezone = false;
73}
74
cebe1257
YW
75static int network_resolve_netdev_one(Network *network, const char *name, NetDevKind kind, NetDev **ret_netdev) {
76 const char *kind_string;
77 NetDev *netdev;
78 int r;
79
96db6412
YW
80 /* For test-networkd-conf, the check must be earlier than the assertions. */
81 if (!name)
82 return 0;
83
cebe1257
YW
84 assert(network);
85 assert(network->manager);
86 assert(network->filename);
87 assert(ret_netdev);
88
cebe1257
YW
89 if (kind == _NETDEV_KIND_TUNNEL)
90 kind_string = "tunnel";
91 else {
92 kind_string = netdev_kind_to_string(kind);
93 if (!kind_string)
94 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
95 "%s: Invalid NetDev kind of %s, ignoring assignment.",
96 network->filename, name);
97 }
98
99 r = netdev_get(network->manager, name, &netdev);
100 if (r < 0)
101 return log_error_errno(r, "%s: %s NetDev could not be found, ignoring assignment.",
102 network->filename, name);
103
104 if (netdev->kind != kind && !(kind == _NETDEV_KIND_TUNNEL &&
105 IN_SET(netdev->kind,
106 NETDEV_KIND_IPIP,
107 NETDEV_KIND_SIT,
108 NETDEV_KIND_GRE,
109 NETDEV_KIND_GRETAP,
110 NETDEV_KIND_IP6GRE,
111 NETDEV_KIND_IP6GRETAP,
112 NETDEV_KIND_VTI,
113 NETDEV_KIND_VTI6,
9282f75b
YW
114 NETDEV_KIND_IP6TNL,
115 NETDEV_KIND_ERSPAN)))
cebe1257
YW
116 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
117 "%s: NetDev %s is not a %s, ignoring assignment",
118 network->filename, name, kind_string);
119
120 *ret_netdev = netdev_ref(netdev);
121 return 1;
122}
123
124static int network_resolve_stacked_netdevs(Network *network) {
125 void *name, *kind;
cebe1257
YW
126 int r;
127
128 assert(network);
129
90e74a66 130 HASHMAP_FOREACH_KEY(kind, name, network->stacked_netdev_names) {
cebe1257
YW
131 _cleanup_(netdev_unrefp) NetDev *netdev = NULL;
132
133 r = network_resolve_netdev_one(network, name, PTR_TO_INT(kind), &netdev);
134 if (r <= 0)
135 continue;
136
137 r = hashmap_ensure_allocated(&network->stacked_netdevs, &string_hash_ops);
138 if (r < 0)
139 return log_oom();
140
141 r = hashmap_put(network->stacked_netdevs, netdev->ifname, netdev);
142 if (r < 0)
143 return log_error_errno(r, "%s: Failed to add NetDev '%s' to network: %m",
144 network->filename, (const char *) name);
145
146 netdev = NULL;
147 }
148
149 return 0;
150}
151
96db6412 152int network_verify(Network *network) {
95081e08 153 RoutePrefix *route_prefix, *route_prefix_next;
fcbf4cb7
YW
154 Neighbor *neighbor, *neighbor_next;
155 AddressLabel *label, *label_next;
564ca984
SS
156 Address *address, *address_next;
157 Prefix *prefix, *prefix_next;
158 Route *route, *route_next;
159 FdbEntry *fdb, *fdb_next;
3db468ea 160 MdbEntry *mdb, *mdb_next;
34658df2 161 TrafficControl *tc;
518cd6b5 162 SRIOV *sr_iov;
0321cea7
YW
163
164 assert(network);
165 assert(network->filename);
166
4bb7cc82
YW
167 if (set_isempty(network->match_mac) && set_isempty(network->match_permanent_mac) &&
168 strv_isempty(network->match_path) && strv_isempty(network->match_driver) &&
169 strv_isempty(network->match_type) && strv_isempty(network->match_name) &&
25c86e4c
DDM
170 strv_isempty(network->match_property) && strv_isempty(network->match_wlan_iftype) &&
171 strv_isempty(network->match_ssid) && !network->conditions)
dade7349
ZJS
172 return log_warning_errno(SYNTHETIC_ERRNO(EINVAL),
173 "%s: No valid settings found in the [Match] section, ignoring file. "
174 "To match all interfaces, add Name=* in the [Match] section.",
175 network->filename);
84ea567e 176
cebe1257 177 /* skip out early if configuration does not match the environment */
a0b191b7 178 if (!condition_test_list(network->conditions, environ, NULL, NULL, NULL))
cebe1257 179 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL),
3772cfde
ZJS
180 "%s: Conditions in the file do not match the system environment, skipping.",
181 network->filename);
cebe1257
YW
182
183 (void) network_resolve_netdev_one(network, network->bond_name, NETDEV_KIND_BOND, &network->bond);
184 (void) network_resolve_netdev_one(network, network->bridge_name, NETDEV_KIND_BRIDGE, &network->bridge);
185 (void) network_resolve_netdev_one(network, network->vrf_name, NETDEV_KIND_VRF, &network->vrf);
186 (void) network_resolve_stacked_netdevs(network);
187
188 /* Free unnecessary entries. */
189 network->bond_name = mfree(network->bond_name);
190 network->bridge_name = mfree(network->bridge_name);
191 network->vrf_name = mfree(network->vrf_name);
192 network->stacked_netdev_names = hashmap_free_free_key(network->stacked_netdev_names);
193
0321cea7
YW
194 if (network->bond) {
195 /* Bonding slave does not support addressing. */
196 if (network->ipv6_accept_ra > 0) {
ab24039f
ZJS
197 log_warning("%s: Cannot enable IPv6AcceptRA= when Bond= is specified, disabling IPv6AcceptRA=.",
198 network->filename);
0321cea7
YW
199 network->ipv6_accept_ra = 0;
200 }
201 if (network->link_local >= 0 && network->link_local != ADDRESS_FAMILY_NO) {
ab24039f
ZJS
202 log_warning("%s: Cannot enable LinkLocalAddressing= when Bond= is specified, disabling LinkLocalAddressing=.",
203 network->filename);
0321cea7
YW
204 network->link_local = ADDRESS_FAMILY_NO;
205 }
206 if (network->dhcp != ADDRESS_FAMILY_NO) {
ab24039f
ZJS
207 log_warning("%s: Cannot enable DHCP= when Bond= is specified, disabling DHCP=.",
208 network->filename);
0321cea7
YW
209 network->dhcp = ADDRESS_FAMILY_NO;
210 }
211 if (network->dhcp_server) {
ab24039f
ZJS
212 log_warning("%s: Cannot enable DHCPServer= when Bond= is specified, disabling DHCPServer=.",
213 network->filename);
0321cea7
YW
214 network->dhcp_server = false;
215 }
216 if (network->n_static_addresses > 0) {
ab24039f
ZJS
217 log_warning("%s: Cannot set addresses when Bond= is specified, ignoring addresses.",
218 network->filename);
0321cea7
YW
219 while ((address = network->static_addresses))
220 address_free(address);
221 }
222 if (network->n_static_routes > 0) {
ab24039f
ZJS
223 log_warning("%s: Cannot set routes when Bond= is specified, ignoring routes.",
224 network->filename);
0321cea7
YW
225 while ((route = network->static_routes))
226 route_free(route);
227 }
228 }
229
230 if (network->link_local < 0)
8f191801
YW
231 network->link_local = network->bridge ? ADDRESS_FAMILY_NO : ADDRESS_FAMILY_IPV6;
232
44013aa4
YW
233 if (!FLAGS_SET(network->link_local, ADDRESS_FAMILY_IPV6)) {
234 if (network->ipv6_accept_ra > 0) {
235 log_warning("%s: IPv6AcceptRA= is enabled by the .network file but IPv6 link local addressing is disabled. "
236 "Disabling IPv6AcceptRA=.", network->filename);
237 network->ipv6_accept_ra = false;
238 }
239
240 if (FLAGS_SET(network->dhcp, ADDRESS_FAMILY_IPV6)) {
241 log_warning("%s: DHCPv6 client is enabled by the .network file but IPv6 link local addressing is disabled. "
242 "Disabling DHCPv6 client.", network->filename);
243 SET_FLAG(network->dhcp, ADDRESS_FAMILY_IPV6, false);
244 }
245
246 if (network->router_prefix_delegation != RADV_PREFIX_DELEGATION_NONE) {
247 log_warning("%s: IPv6PrefixDelegation= is enabled but IPv6 link local addressing is disabled. "
248 "Disabling IPv6PrefixDelegation=.", network->filename);
249 network->router_prefix_delegation = RADV_PREFIX_DELEGATION_NONE;
250 }
251 }
252
29e81083
YW
253 if (FLAGS_SET(network->link_local, ADDRESS_FAMILY_FALLBACK_IPV4) &&
254 !FLAGS_SET(network->dhcp, ADDRESS_FAMILY_IPV4)) {
255 log_warning("%s: fallback assignment of IPv4 link local address is enabled but DHCPv4 is disabled. "
256 "Disabling the fallback assignment.", network->filename);
257 SET_FLAG(network->link_local, ADDRESS_FAMILY_FALLBACK_IPV4, false);
258 }
259
8f191801
YW
260 if (network->ipv6_accept_ra < 0 && network->bridge)
261 network->ipv6_accept_ra = false;
0321cea7
YW
262
263 /* IPMasquerade=yes implies IPForward=yes */
264 if (network->ip_masquerade)
265 network->ip_forward |= ADDRESS_FAMILY_IPV4;
266
933c70a0 267 if (network->mtu > 0 && network->dhcp_use_mtu) {
0321cea7
YW
268 log_warning("%s: MTUBytes= in [Link] section and UseMTU= in [DHCP] section are set. "
269 "Disabling UseMTU=.", network->filename);
270 network->dhcp_use_mtu = false;
271 }
272
589397a2
DS
273 if (network->dhcp_use_gateway < 0)
274 network->dhcp_use_gateway = network->dhcp_use_routes;
275
bd0d471c
DS
276 if (network->ignore_carrier_loss < 0)
277 network->ignore_carrier_loss = network->configure_without_carrier;
278
7da377ef
SS
279 if (network->dhcp_critical >= 0) {
280 if (network->keep_configuration >= 0)
281 log_warning("%s: Both KeepConfiguration= and deprecated CriticalConnection= are set. "
282 "Ignoring CriticalConnection=.", network->filename);
283 else if (network->dhcp_critical)
284 /* CriticalConnection=yes also preserve foreign static configurations. */
285 network->keep_configuration = KEEP_CONFIGURATION_YES;
286 else
80060352 287 network->keep_configuration = KEEP_CONFIGURATION_NO;
7da377ef
SS
288 }
289
290 if (network->keep_configuration < 0)
80060352 291 network->keep_configuration = KEEP_CONFIGURATION_NO;
7da377ef 292
4bec2f23 293 LIST_FOREACH_SAFE(addresses, address, address_next, network->static_addresses)
fcbf4cb7 294 if (address_section_verify(address) < 0)
4bec2f23 295 address_free(address);
4bec2f23 296
fcbf4cb7
YW
297 LIST_FOREACH_SAFE(routes, route, route_next, network->static_routes)
298 if (route_section_verify(route, network) < 0)
4bec2f23 299 route_free(route);
0321cea7 300
0992f9fb 301 network_verify_nexthops(network);
c16c7808 302
fcbf4cb7
YW
303 LIST_FOREACH_SAFE(static_fdb_entries, fdb, fdb_next, network->static_fdb_entries)
304 if (section_is_invalid(fdb->section))
305 fdb_entry_free(fdb);
306
3db468ea
DM
307 LIST_FOREACH_SAFE(static_mdb_entries, mdb, mdb_next, network->static_mdb_entries)
308 if (mdb_entry_verify(mdb) < 0)
309 mdb_entry_free(mdb);
310
fcbf4cb7 311 LIST_FOREACH_SAFE(neighbors, neighbor, neighbor_next, network->neighbors)
044d4b40 312 if (neighbor_section_verify(neighbor) < 0)
fcbf4cb7
YW
313 neighbor_free(neighbor);
314
315 LIST_FOREACH_SAFE(labels, label, label_next, network->address_labels)
316 if (section_is_invalid(label->section))
317 address_label_free(label);
318
319 LIST_FOREACH_SAFE(prefixes, prefix, prefix_next, network->static_prefixes)
320 if (section_is_invalid(prefix->section))
321 prefix_free(prefix);
322
95081e08
YW
323 LIST_FOREACH_SAFE(route_prefixes, route_prefix, route_prefix_next, network->static_route_prefixes)
324 if (section_is_invalid(route_prefix->section))
325 route_prefix_free(route_prefix);
714a199e 326
50a3682f 327 network_verify_routing_policy_rules(network);
4912ab77 328
8efb93f0 329 bool has_root = false, has_clsact = false;
90e74a66 330 ORDERED_HASHMAP_FOREACH(tc, network->tc_by_section)
34658df2
YW
331 if (traffic_control_section_verify(tc, &has_root, &has_clsact) < 0)
332 traffic_control_free(tc);
8efb93f0 333
90e74a66 334 ORDERED_HASHMAP_FOREACH(sr_iov, network->sr_iov_by_section)
518cd6b5
SS
335 if (sr_iov_section_verify(sr_iov) < 0)
336 sr_iov_free(sr_iov);
337
0321cea7
YW
338 return 0;
339}
340
7f06b3e1 341int network_load_one(Manager *manager, OrderedHashmap **networks, const char *filename) {
838b2f7a 342 _cleanup_free_ char *fname = NULL, *name = NULL;
35ac3b76 343 _cleanup_(network_unrefp) Network *network = NULL;
f579559b 344 _cleanup_fclose_ FILE *file = NULL;
047a0dac 345 const char *dropin_dirname;
838b2f7a 346 char *d;
f579559b
TG
347 int r;
348
bf1bc670
TA
349 assert(manager);
350 assert(filename);
351
f579559b
TG
352 file = fopen(filename, "re");
353 if (!file) {
354 if (errno == ENOENT)
355 return 0;
1e7a0e21
LP
356
357 return -errno;
f579559b
TG
358 }
359
ed88bcfb
ZJS
360 if (null_or_empty_fd(fileno(file))) {
361 log_debug("Skipping empty file: %s", filename);
6916ec29
TG
362 return 0;
363 }
364
838b2f7a
YW
365 fname = strdup(filename);
366 if (!fname)
367 return log_oom();
368
369 name = strdup(basename(filename));
370 if (!name)
371 return log_oom();
372
373 d = strrchr(name, '.');
374 if (!d)
375 return -EINVAL;
376
377 *d = '\0';
378
379 dropin_dirname = strjoina(name, ".network.d");
380
17f9c355 381 network = new(Network, 1);
f579559b
TG
382 if (!network)
383 return log_oom();
384
17f9c355 385 *network = (Network) {
838b2f7a
YW
386 .filename = TAKE_PTR(fname),
387 .name = TAKE_PTR(name),
17f9c355 388
715d398e 389 .manager = manager,
35ac3b76
YW
390 .n_ref = 1,
391
17f9c355 392 .required_for_online = true,
75cd4a5d 393 .required_operstate_for_online = LINK_OPERSTATE_RANGE_DEFAULT,
17f9c355 394 .dhcp = ADDRESS_FAMILY_NO,
7da377ef 395 .dhcp_critical = -1,
17f9c355 396 .dhcp_use_ntp = true,
299d578f 397 .dhcp_use_sip = true,
17f9c355
YW
398 .dhcp_use_dns = true,
399 .dhcp_use_hostname = true,
400 .dhcp_use_routes = true,
589397a2 401 .dhcp_use_gateway = -1,
5238e957 402 /* NOTE: this var might be overwritten by network_apply_anonymize_if_set */
17f9c355 403 .dhcp_send_hostname = true,
5f3b5f19 404 .dhcp_send_release = true,
17f9c355
YW
405 /* To enable/disable RFC7844 Anonymity Profiles */
406 .dhcp_anonymize = false,
407 .dhcp_route_metric = DHCP_ROUTE_METRIC,
c9c908a6 408 /* NOTE: this var might be overwritten by network_apply_anonymize_if_set */
17f9c355
YW
409 .dhcp_client_identifier = DHCP_CLIENT_ID_DUID,
410 .dhcp_route_table = RT_TABLE_MAIN,
411 .dhcp_route_table_set = false,
412 /* NOTE: from man: UseMTU=... Defaults to false*/
413 .dhcp_use_mtu = false,
414 /* NOTE: from man: UseTimezone=... Defaults to "no".*/
415 .dhcp_use_timezone = false,
416 .rapid_commit = true,
417
1bf1bfd9 418 .dhcp6_route_metric = DHCP_ROUTE_METRIC,
caa8ca42
SS
419 .dhcp6_use_ntp = true,
420 .dhcp6_use_dns = true,
421
99e015e2
YW
422 .dhcp6_pd_subnet_id = -1,
423 .dhcp6_pd_assign = true,
9efa8a3c 424
2a71d57f
LP
425 .dhcp_server_emit[SD_DHCP_LEASE_DNS].emit = true,
426 .dhcp_server_emit[SD_DHCP_LEASE_NTP].emit = true,
427 .dhcp_server_emit[SD_DHCP_LEASE_SIP].emit = true,
428
17f9c355
YW
429 .dhcp_server_emit_router = true,
430 .dhcp_server_emit_timezone = true,
431
432 .router_emit_dns = true,
433 .router_emit_domains = true,
434
435 .use_bpdu = -1,
436 .hairpin = -1,
437 .fast_leave = -1,
438 .allow_port_to_be_root = -1,
439 .unicast_flood = -1,
7f15b714 440 .multicast_flood = -1,
d3aa8b49 441 .multicast_to_unicast = -1,
7f15b714
TJ
442 .neighbor_suppression = -1,
443 .learning = -1,
1087623b
SS
444 .bridge_proxy_arp = -1,
445 .bridge_proxy_arp_wifi = -1,
17f9c355 446 .priority = LINK_BRIDGE_PORT_PRIORITY_INVALID,
0fadb2a4 447 .multicast_router = _MULTICAST_ROUTER_INVALID,
17f9c355
YW
448
449 .lldp_mode = LLDP_MODE_ROUTERS_ONLY,
450
7ece6f58 451 .dns_default_route = -1,
17f9c355
YW
452 .llmnr = RESOLVE_SUPPORT_YES,
453 .mdns = RESOLVE_SUPPORT_NO,
454 .dnssec_mode = _DNSSEC_MODE_INVALID,
455 .dns_over_tls_mode = _DNS_OVER_TLS_MODE_INVALID,
456
0321cea7 457 /* If LinkLocalAddressing= is not set, then set to ADDRESS_FAMILY_IPV6 later. */
2d792895 458 .link_local = _ADDRESS_FAMILY_INVALID,
6f6296b9 459 .ipv6ll_address_gen_mode = _IPV6_LINK_LOCAL_ADDRESS_GEN_MODE_INVALID,
17f9c355 460
94d76d07
YW
461 .ipv4_accept_local = -1,
462
17f9c355
YW
463 .ipv6_privacy_extensions = IPV6_PRIVACY_EXTENSIONS_NO,
464 .ipv6_accept_ra = -1,
465 .ipv6_dad_transmits = -1,
466 .ipv6_hop_limit = -1,
467 .ipv6_proxy_ndp = -1,
468 .duid.type = _DUID_TYPE_INVALID,
469 .proxy_arp = -1,
470 .arp = -1,
471 .multicast = -1,
472 .allmulticast = -1,
473 .ipv6_accept_ra_use_dns = true,
062c2eea
SS
474 .ipv6_accept_ra_use_autonomous_prefix = true,
475 .ipv6_accept_ra_use_onlink_prefix = true,
17f9c355 476 .ipv6_accept_ra_route_table = RT_TABLE_MAIN,
d5fa3339 477 .ipv6_accept_ra_route_table_set = false,
d739fdde 478 .ipv6_accept_ra_start_dhcp6_client = true,
c423be28 479
bd0d471c
DS
480 .configure_without_carrier = false,
481 .ignore_carrier_loss = -1,
7da377ef 482 .keep_configuration = _KEEP_CONFIGURATION_INVALID,
c423be28 483 .can_triple_sampling = -1,
52aa38f1 484 .can_termination = -1,
f594b5fe
CG
485 .can_listen_only = -1,
486 .can_fd_mode = -1,
487 .can_non_iso = -1,
afe42aef 488 .ip_service_type = -1,
17f9c355 489 };
f579559b 490
4f9ff96a
LP
491 r = config_parse_many(
492 filename, NETWORK_DIRS, dropin_dirname,
493 "Match\0"
494 "Link\0"
518cd6b5 495 "SR-IOV\0"
4f9ff96a
LP
496 "Network\0"
497 "Address\0"
498 "Neighbor\0"
499 "IPv6AddressLabel\0"
500 "RoutingPolicyRule\0"
501 "Route\0"
502 "NextHop\0"
503 "DHCP\0" /* compat */
504 "DHCPv4\0"
505 "DHCPv6\0"
b209cff2 506 "DHCPv6PrefixDelegation\0"
4f9ff96a
LP
507 "DHCPServer\0"
508 "IPv6AcceptRA\0"
509 "IPv6NDPProxyAddress\0"
510 "Bridge\0"
511 "BridgeFDB\0"
3db468ea 512 "BridgeMDB\0"
4f9ff96a
LP
513 "BridgeVLAN\0"
514 "IPv6PrefixDelegation\0"
515 "IPv6Prefix\0"
516 "IPv6RoutePrefix\0"
517 "LLDP\0"
518 "TrafficControlQueueingDiscipline\0"
519 "CAN\0"
520 "QDisc\0"
521 "BFIFO\0"
522 "CAKE\0"
523 "ControlledDelay\0"
524 "DeficitRoundRobinScheduler\0"
525 "DeficitRoundRobinSchedulerClass\0"
d474aa51 526 "EnhancedTransmissionSelection\0"
4f9ff96a
LP
527 "FairQueueing\0"
528 "FairQueueingControlledDelay\0"
8f6b6d70 529 "FlowQueuePIE\0"
4f9ff96a
LP
530 "GenericRandomEarlyDetection\0"
531 "HeavyHitterFilter\0"
532 "HierarchyTokenBucket\0"
533 "HierarchyTokenBucketClass\0"
534 "NetworkEmulator\0"
b12aaee5
SS
535 "PFIFO\0"
536 "PFIFOFast\0"
537 "PFIFOHeadDrop\0"
4f9ff96a 538 "PIE\0"
b12aaee5 539 "QuickFairQueueing\0"
4d7ddaf9 540 "QuickFairQueueingClass\0"
4f9ff96a
LP
541 "StochasticFairBlue\0"
542 "StochasticFairnessQueueing\0"
543 "TokenBucketFilter\0"
544 "TrivialLinkEqualizer\0",
545 config_item_perf_lookup, network_network_gperf_lookup,
546 CONFIG_PARSE_WARN,
547 network,
548 &network->timestamp);
102bc043 549 if (r < 0)
f579559b 550 return r;
f579559b 551
add8d07d 552 network_apply_anonymize_if_set(network);
553
fa7cd711
YW
554 r = network_add_ipv4ll_route(network);
555 if (r < 0)
556 log_warning_errno(r, "%s: Failed to add IPv4LL route, ignoring: %m", network->filename);
557
5d5003ab
YW
558 r = network_add_default_route_on_device(network);
559 if (r < 0)
560 log_warning_errno(r, "%s: Failed to add default route on device, ignoring: %m",
561 network->filename);
562
7f06b3e1
YW
563 if (network_verify(network) < 0)
564 /* Ignore .network files that do not match the conditions. */
565 return 0;
566
567 r = ordered_hashmap_ensure_allocated(networks, &string_hash_ops);
dbffab87
TG
568 if (r < 0)
569 return r;
570
7f06b3e1 571 r = ordered_hashmap_put(*networks, network->name, network);
dbffab87
TG
572 if (r < 0)
573 return r;
574
f579559b 575 network = NULL;
f579559b
TG
576 return 0;
577}
578
7f06b3e1 579int network_load(Manager *manager, OrderedHashmap **networks) {
477e73b5
ZJS
580 _cleanup_strv_free_ char **files = NULL;
581 char **f;
f579559b
TG
582 int r;
583
584 assert(manager);
585
7f06b3e1 586 ordered_hashmap_clear_with_destructor(*networks, network_unref);
f579559b 587
dc0d4078 588 r = conf_files_list_strv(&files, ".network", NULL, 0, NETWORK_DIRS);
f647962d
MS
589 if (r < 0)
590 return log_error_errno(r, "Failed to enumerate network files: %m");
f579559b 591
715d398e 592 STRV_FOREACH(f, files) {
7f06b3e1 593 r = network_load_one(manager, networks, *f);
f579559b 594 if (r < 0)
be711082 595 log_error_errno(r, "Failed to load %s, ignoring: %m", *f);
f579559b
TG
596 }
597
f579559b
TG
598 return 0;
599}
600
7f06b3e1
YW
601int network_reload(Manager *manager) {
602 OrderedHashmap *new_networks = NULL;
603 Network *n, *old;
7f06b3e1
YW
604 int r;
605
606 assert(manager);
607
608 r = network_load(manager, &new_networks);
609 if (r < 0)
610 goto failure;
611
90e74a66 612 ORDERED_HASHMAP_FOREACH(n, new_networks) {
7f06b3e1
YW
613 r = network_get_by_name(manager, n->name, &old);
614 if (r < 0)
615 continue; /* The .network file is new. */
616
617 if (n->timestamp != old->timestamp)
618 continue; /* The .network file is modified. */
619
620 if (!streq(n->filename, old->filename))
621 continue;
622
623 r = ordered_hashmap_replace(new_networks, old->name, old);
624 if (r < 0)
625 goto failure;
626
627 network_ref(old);
628 network_unref(n);
629 }
630
631 ordered_hashmap_free_with_destructor(manager->networks, network_unref);
632 manager->networks = new_networks;
633
634 return 0;
635
636failure:
637 ordered_hashmap_free_with_destructor(new_networks, network_unref);
638
639 return r;
640}
641
35ac3b76 642static Network *network_free(Network *network) {
a0e5c15d 643 IPv6ProxyNDPAddress *ipv6_proxy_ndp_address;
95081e08 644 RoutePrefix *route_prefix;
95081e08 645 AddressLabel *label;
bce67bbe 646 FdbEntry *fdb_entry;
3db468ea 647 MdbEntry *mdb_entry;
e4a71bf3 648 Neighbor *neighbor;
bce67bbe 649 Address *address;
c16c7808 650 Prefix *prefix;
bce67bbe 651 Route *route;
f579559b
TG
652
653 if (!network)
35ac3b76 654 return NULL;
f579559b
TG
655
656 free(network->filename);
657
e90d0374 658 set_free_free(network->match_mac);
4bb7cc82 659 set_free_free(network->match_permanent_mac);
5256e00e
TG
660 strv_free(network->match_path);
661 strv_free(network->match_driver);
662 strv_free(network->match_type);
663 strv_free(network->match_name);
44005bfb 664 strv_free(network->match_property);
78404d22 665 strv_free(network->match_wlan_iftype);
8d968fdd 666 strv_free(network->match_ssid);
277ba8d1 667 set_free_free(network->match_bssid);
c4f58dea 668 condition_free_list(network->conditions);
f579559b
TG
669
670 free(network->description);
edb85f0d 671 free(network->dhcp_vendor_class_identifier);
7b8d23a9 672 free(network->dhcp_mudurl);
af1c0de0 673 strv_free(network->dhcp_user_class);
27cb34f5 674 free(network->dhcp_hostname);
6b000af4 675 set_free(network->dhcp_deny_listed_ip);
98ebef62 676 set_free(network->dhcp_allow_listed_ip);
5bc945be 677 set_free(network->dhcp_request_options);
35f6a5cb 678 set_free(network->dhcp6_request_options);
c106cc36 679 free(network->mac);
3175a8c2 680 free(network->dhcp6_mudurl);
f37f2a6b 681 strv_free(network->dhcp6_user_class);
ed0d1b2e 682 strv_free(network->dhcp6_vendor_class);
c106cc36 683
0f3ff4ea
SS
684 if (network->dhcp_acd)
685 sd_ipv4acd_unref(network->dhcp_acd);
686
b0e39c82 687 strv_free(network->ntp);
e77bd3fd
YW
688 for (unsigned i = 0; i < network->n_dns; i++)
689 in_addr_full_free(network->dns[i]);
5512a963 690 free(network->dns);
5e2a51d5
ZJS
691 ordered_set_free_free(network->search_domains);
692 ordered_set_free_free(network->route_domains);
0d4ad91d 693 strv_free(network->bind_carrier);
cdd7812b 694
5e2a51d5 695 ordered_set_free_free(network->router_search_domains);
cdd7812b 696 free(network->router_dns);
6b000af4 697 set_free_free(network->ndisc_deny_listed_prefix);
3bef724f 698
cebe1257
YW
699 free(network->bridge_name);
700 free(network->bond_name);
701 free(network->vrf_name);
702 hashmap_free_free_key(network->stacked_netdev_names);
47e2dc31 703 netdev_unref(network->bridge);
47e2dc31 704 netdev_unref(network->bond);
6cb955c6 705 netdev_unref(network->vrf);
fa6f1e54 706 hashmap_free_with_destructor(network->stacked_netdevs, netdev_unref);
326cb406 707
f048a16b 708 while ((route = network->static_routes))
f579559b
TG
709 route_free(route);
710
f048a16b 711 while ((address = network->static_addresses))
f579559b
TG
712 address_free(address);
713
b98b483b
AR
714 while ((fdb_entry = network->static_fdb_entries))
715 fdb_entry_free(fdb_entry);
716
3db468ea
DM
717 while ((mdb_entry = network->static_mdb_entries))
718 mdb_entry_free(mdb_entry);
719
a0e5c15d
FK
720 while ((ipv6_proxy_ndp_address = network->ipv6_proxy_ndp_addresses))
721 ipv6_proxy_ndp_address_free(ipv6_proxy_ndp_address);
722
e4a71bf3
WKI
723 while ((neighbor = network->neighbors))
724 neighbor_free(neighbor);
725
95b74ef6
SS
726 while ((label = network->address_labels))
727 address_label_free(label);
728
057abfd8
PF
729 while ((prefix = network->static_prefixes))
730 prefix_free(prefix);
731
95081e08
YW
732 while ((route_prefix = network->static_route_prefixes))
733 route_prefix_free(route_prefix);
9be6ae77 734
6ae115c1
TG
735 hashmap_free(network->addresses_by_section);
736 hashmap_free(network->routes_by_section);
b82663dd 737 hashmap_free_with_destructor(network->nexthops_by_section, nexthop_free);
b98b483b 738 hashmap_free(network->fdb_entries_by_section);
3db468ea 739 hashmap_free(network->mdb_entries_by_section);
e4a71bf3 740 hashmap_free(network->neighbors_by_section);
95b74ef6 741 hashmap_free(network->address_labels_by_section);
057abfd8 742 hashmap_free(network->prefixes_by_section);
9be6ae77 743 hashmap_free(network->route_prefixes_by_section);
ca183bf8 744 hashmap_free_with_destructor(network->rules_by_section, routing_policy_rule_free);
518cd6b5 745 ordered_hashmap_free_with_destructor(network->sr_iov_by_section, sr_iov_free);
34658df2 746 ordered_hashmap_free_with_destructor(network->tc_by_section, traffic_control_free);
6ae115c1 747
7f06b3e1
YW
748 if (network->manager &&
749 network->manager->duids_requesting_uuid)
750 set_remove(network->manager->duids_requesting_uuid, &network->duid);
dbffab87
TG
751
752 free(network->name);
f579559b 753
8eb9058d 754 free(network->dhcp_server_timezone);
2a71d57f
LP
755
756 for (sd_dhcp_lease_server_type t = 0; t < _SD_DHCP_LEASE_SERVER_TYPE_MAX; t++)
757 free(network->dhcp_server_emit[t].addresses);
8eb9058d 758
8a516214
LP
759 set_free_free(network->dnssec_negative_trust_anchors);
760
e9a8c550
SS
761 free(network->lldp_mud);
762
0e96961d 763 ordered_hashmap_free(network->dhcp_client_send_options);
7354900d 764 ordered_hashmap_free(network->dhcp_client_send_vendor_options);
0e96961d 765 ordered_hashmap_free(network->dhcp_server_send_options);
7354900d 766 ordered_hashmap_free(network->dhcp_server_send_vendor_options);
2c621495 767 ordered_set_free(network->ipv6_tokens);
1c3ec1cd 768 ordered_hashmap_free(network->dhcp6_client_send_options);
b4ccc5de 769 ordered_hashmap_free(network->dhcp6_client_send_vendor_options);
cb29c156 770
35ac3b76 771 return mfree(network);
f579559b
TG
772}
773
35ac3b76
YW
774DEFINE_TRIVIAL_REF_UNREF_FUNC(Network, network, network_free);
775
dbffab87
TG
776int network_get_by_name(Manager *manager, const char *name, Network **ret) {
777 Network *network;
778
779 assert(manager);
780 assert(name);
781 assert(ret);
782
715d398e 783 network = ordered_hashmap_get(manager->networks, name);
dbffab87
TG
784 if (!network)
785 return -ENOENT;
786
787 *ret = network;
788
789 return 0;
790}
791
ef62949a 792int network_get(Manager *manager, unsigned short iftype, sd_device *device,
c643bda5
YW
793 const char *ifname, char * const *alternative_names, const char *driver,
794 const struct ether_addr *mac, const struct ether_addr *permanent_mac,
78404d22
YW
795 enum nl80211_iftype wlan_iftype, const char *ssid, const struct ether_addr *bssid,
796 Network **ret) {
51517f9e 797 Network *network;
f579559b
TG
798
799 assert(manager);
f579559b 800 assert(ret);
af3aa302 801
90e74a66 802 ORDERED_HASHMAP_FOREACH(network, manager->networks)
4bb7cc82
YW
803 if (net_match_config(network->match_mac, network->match_permanent_mac,
804 network->match_path, network->match_driver,
44005bfb 805 network->match_type, network->match_name, network->match_property,
78404d22 806 network->match_wlan_iftype, network->match_ssid, network->match_bssid,
c643bda5 807 device, mac, permanent_mac, driver, iftype,
4bb7cc82 808 ifname, alternative_names, wlan_iftype, ssid, bssid)) {
24c083df 809 if (network->match_name && device) {
ca6038b8
TG
810 const char *attr;
811 uint8_t name_assign_type = NET_NAME_UNKNOWN;
812
51517f9e 813 if (sd_device_get_sysattr_value(device, "name_assign_type", &attr) >= 0)
dc751688 814 (void) safe_atou8(attr, &name_assign_type);
32bc8adc
TG
815
816 if (name_assign_type == NET_NAME_ENUM)
a2fae7bb
TG
817 log_warning("%s: found matching network '%s', based on potentially unpredictable ifname",
818 ifname, network->filename);
32bc8adc 819 else
a2fae7bb 820 log_debug("%s: found matching network '%s'", ifname, network->filename);
32bc8adc 821 } else
a2fae7bb 822 log_debug("%s: found matching network '%s'", ifname, network->filename);
32bc8adc 823
f579559b
TG
824 *ret = network;
825 return 0;
826 }
f579559b
TG
827
828 *ret = NULL;
829
830 return -ENOENT;
831}
832
7d342c03 833int network_apply(Network *network, Link *link) {
c4a03a56
TG
834 assert(network);
835 assert(link);
836
c9c908a6 837 link->network = network_ref(network);
f579559b 838
5512a963 839 if (network->n_dns > 0 ||
3df9bec5 840 !strv_isempty(network->ntp) ||
5e2a51d5
ZJS
841 !ordered_set_isempty(network->search_domains) ||
842 !ordered_set_isempty(network->route_domains))
84de38c5 843 link_dirty(link);
3bef724f 844
f579559b
TG
845 return 0;
846}
02b59d57 847
adfeee49 848bool network_has_static_ipv6_configurations(Network *network) {
439689c6 849 Address *address;
adfeee49
YW
850 Route *route;
851 FdbEntry *fdb;
3db468ea 852 MdbEntry *mdb;
adfeee49 853 Neighbor *neighbor;
439689c6
SS
854
855 assert(network);
856
adfeee49 857 LIST_FOREACH(addresses, address, network->static_addresses)
439689c6
SS
858 if (address->family == AF_INET6)
859 return true;
adfeee49
YW
860
861 LIST_FOREACH(routes, route, network->static_routes)
862 if (route->family == AF_INET6)
863 return true;
864
865 LIST_FOREACH(static_fdb_entries, fdb, network->static_fdb_entries)
866 if (fdb->family == AF_INET6)
867 return true;
868
3db468ea
DM
869 LIST_FOREACH(static_mdb_entries, mdb, network->static_mdb_entries)
870 if (mdb->family == AF_INET6)
871 return true;
872
adfeee49
YW
873 LIST_FOREACH(neighbors, neighbor, network->neighbors)
874 if (neighbor->family == AF_INET6)
875 return true;
876
877 if (!LIST_IS_EMPTY(network->address_labels))
878 return true;
879
880 if (!LIST_IS_EMPTY(network->static_prefixes))
881 return true;
439689c6
SS
882
883 return false;
884}
885
cebe1257 886int config_parse_stacked_netdev(const char *unit,
02b59d57
TG
887 const char *filename,
888 unsigned line,
889 const char *section,
890 unsigned section_line,
891 const char *lvalue,
892 int ltype,
893 const char *rvalue,
894 void *data,
895 void *userdata) {
95dba435
YW
896 _cleanup_free_ char *name = NULL;
897 NetDevKind kind = ltype;
cebe1257 898 Hashmap **h = data;
02b59d57
TG
899 int r;
900
901 assert(filename);
902 assert(lvalue);
903 assert(rvalue);
904 assert(data);
95dba435
YW
905 assert(IN_SET(kind,
906 NETDEV_KIND_VLAN, NETDEV_KIND_MACVLAN, NETDEV_KIND_MACVTAP,
69c317a0 907 NETDEV_KIND_IPVLAN, NETDEV_KIND_IPVTAP, NETDEV_KIND_VXLAN,
98d20a17 908 NETDEV_KIND_L2TP, NETDEV_KIND_MACSEC, _NETDEV_KIND_TUNNEL,
909 NETDEV_KIND_XFRM));
54abf461 910
cebe1257 911 if (!ifname_valid(rvalue)) {
d96edb2c 912 log_syntax(unit, LOG_WARNING, filename, line, 0,
3772cfde 913 "Invalid netdev name in %s=, ignoring assignment: %s", lvalue, rvalue);
54abf461
TG
914 return 0;
915 }
916
cebe1257
YW
917 name = strdup(rvalue);
918 if (!name)
919 return log_oom();
3e570042 920
cebe1257
YW
921 r = hashmap_ensure_allocated(h, &string_hash_ops);
922 if (r < 0)
923 return log_oom();
326cb406 924
cebe1257 925 r = hashmap_put(*h, name, INT_TO_PTR(kind));
83ec4592 926 if (r < 0)
d96edb2c 927 log_syntax(unit, LOG_WARNING, filename, line, r,
83ec4592
ZJS
928 "Cannot add NetDev '%s' to network, ignoring assignment: %m", name);
929 else if (r == 0)
930 log_syntax(unit, LOG_DEBUG, filename, line, r,
931 "NetDev '%s' specified twice, ignoring.", name);
932 else
933 name = NULL;
47e2dc31 934
fe6b2d55
TG
935 return 0;
936}
7951dea2 937
3df9bec5
LP
938int config_parse_domains(
939 const char *unit,
940 const char *filename,
941 unsigned line,
942 const char *section,
943 unsigned section_line,
944 const char *lvalue,
945 int ltype,
946 const char *rvalue,
947 void *data,
948 void *userdata) {
949
3df9bec5 950 Network *n = data;
6192b846
TG
951 int r;
952
3df9bec5
LP
953 assert(n);
954 assert(lvalue);
955 assert(rvalue);
6192b846 956
3df9bec5 957 if (isempty(rvalue)) {
5e2a51d5
ZJS
958 n->search_domains = ordered_set_free_free(n->search_domains);
959 n->route_domains = ordered_set_free_free(n->route_domains);
3df9bec5
LP
960 return 0;
961 }
67272d15 962
d96edb2c 963 for (const char *p = rvalue;;) {
3df9bec5
LP
964 _cleanup_free_ char *w = NULL, *normalized = NULL;
965 const char *domain;
966 bool is_route;
967
968 r = extract_first_word(&p, &w, NULL, 0);
d96edb2c
YW
969 if (r == -ENOMEM)
970 return log_oom();
3df9bec5 971 if (r < 0) {
d96edb2c 972 log_syntax(unit, LOG_WARNING, filename, line, r,
ab24039f 973 "Failed to extract search or route domain, ignoring: %s", rvalue);
d96edb2c 974 return 0;
3df9bec5
LP
975 }
976 if (r == 0)
d96edb2c 977 return 0;
3df9bec5
LP
978
979 is_route = w[0] == '~';
980 domain = is_route ? w + 1 : w;
981
982 if (dns_name_is_root(domain) || streq(domain, "*")) {
ab24039f
ZJS
983 /* If the root domain appears as is, or the special token "*" is found, we'll
984 * consider this as routing domain, unconditionally. */
3df9bec5 985 is_route = true;
ab24039f
ZJS
986 domain = "."; /* make sure we don't allow empty strings, thus write the root
987 * domain as "." */
3df9bec5 988 } else {
7470cc4c 989 r = dns_name_normalize(domain, 0, &normalized);
3df9bec5 990 if (r < 0) {
d96edb2c 991 log_syntax(unit, LOG_WARNING, filename, line, r,
ab24039f 992 "'%s' is not a valid domain name, ignoring.", domain);
3df9bec5
LP
993 continue;
994 }
995
996 domain = normalized;
997
998 if (is_localhost(domain)) {
d96edb2c 999 log_syntax(unit, LOG_WARNING, filename, line, 0,
ab24039f
ZJS
1000 "'localhost' domain may not be configured as search or route domain, ignoring assignment: %s",
1001 domain);
37de2509 1002 continue;
3df9bec5 1003 }
37de2509 1004 }
40274ed6 1005
5e2a51d5
ZJS
1006 OrderedSet **set = is_route ? &n->route_domains : &n->search_domains;
1007 r = ordered_set_ensure_allocated(set, &string_hash_ops);
1008 if (r < 0)
d96edb2c 1009 return log_oom();
5e2a51d5
ZJS
1010
1011 r = ordered_set_put_strdup(*set, domain);
09451975
LP
1012 if (r < 0)
1013 return log_oom();
40274ed6 1014 }
6192b846
TG
1015}
1016
60c35566 1017int config_parse_ipv6token(
7f77697a
TG
1018 const char* unit,
1019 const char *filename,
1020 unsigned line,
1021 const char *section,
1022 unsigned section_line,
1023 const char *lvalue,
1024 int ltype,
1025 const char *rvalue,
1026 void *data,
1027 void *userdata) {
1028
1029 union in_addr_union buffer;
1030 struct in6_addr *token = data;
1031 int r;
1032
1033 assert(filename);
1034 assert(lvalue);
1035 assert(rvalue);
1036 assert(token);
1037
1038 r = in_addr_from_string(AF_INET6, rvalue, &buffer);
1039 if (r < 0) {
d96edb2c 1040 log_syntax(unit, LOG_WARNING, filename, line, r,
ab24039f 1041 "Failed to parse IPv6 token, ignoring: %s", rvalue);
7f77697a
TG
1042 return 0;
1043 }
1044
c606db69 1045 if (in_addr_is_null(AF_INET6, &buffer)) {
d96edb2c 1046 log_syntax(unit, LOG_WARNING, filename, line, 0,
ab24039f 1047 "IPv6 token cannot be the ANY address, ignoring: %s", rvalue);
7f77697a
TG
1048 return 0;
1049 }
1050
1051 if ((buffer.in6.s6_addr32[0] | buffer.in6.s6_addr32[1]) != 0) {
d96edb2c 1052 log_syntax(unit, LOG_WARNING, filename, line, 0,
ab24039f 1053 "IPv6 token cannot be longer than 64 bits, ignoring: %s", rvalue);
7f77697a
TG
1054 return 0;
1055 }
1056
1057 *token = buffer.in6;
1058
1059 return 0;
1060}
8add5f79 1061
49092e22 1062static const char* const ipv6_privacy_extensions_table[_IPV6_PRIVACY_EXTENSIONS_MAX] = {
1f0d9695
LP
1063 [IPV6_PRIVACY_EXTENSIONS_NO] = "no",
1064 [IPV6_PRIVACY_EXTENSIONS_PREFER_PUBLIC] = "prefer-public",
1065 [IPV6_PRIVACY_EXTENSIONS_YES] = "yes",
49092e22
SS
1066};
1067
b146ad71
YW
1068DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(ipv6_privacy_extensions, IPv6PrivacyExtensions,
1069 IPV6_PRIVACY_EXTENSIONS_YES);
49092e22
SS
1070
1071int config_parse_ipv6_privacy_extensions(
1072 const char* unit,
1073 const char *filename,
1074 unsigned line,
1075 const char *section,
1076 unsigned section_line,
1077 const char *lvalue,
1078 int ltype,
1079 const char *rvalue,
1080 void *data,
1081 void *userdata) {
1082
b146ad71 1083 IPv6PrivacyExtensions s, *ipv6_privacy_extensions = data;
49092e22
SS
1084
1085 assert(filename);
1086 assert(lvalue);
1087 assert(rvalue);
1088 assert(ipv6_privacy_extensions);
1089
b146ad71
YW
1090 s = ipv6_privacy_extensions_from_string(rvalue);
1091 if (s < 0) {
1092 if (streq(rvalue, "kernel"))
1093 s = _IPV6_PRIVACY_EXTENSIONS_INVALID;
1094 else {
d96edb2c 1095 log_syntax(unit, LOG_WARNING, filename, line, 0,
b146ad71
YW
1096 "Failed to parse IPv6 privacy extensions option, ignoring: %s", rvalue);
1097 return 0;
49092e22 1098 }
49092e22
SS
1099 }
1100
b146ad71
YW
1101 *ipv6_privacy_extensions = s;
1102
49092e22
SS
1103 return 0;
1104}
a7d0ef44 1105
1ac608c9
LP
1106int config_parse_hostname(
1107 const char *unit,
1108 const char *filename,
1109 unsigned line,
1110 const char *section,
1111 unsigned section_line,
1112 const char *lvalue,
1113 int ltype,
1114 const char *rvalue,
1115 void *data,
1116 void *userdata) {
1117
6528693a
YW
1118 _cleanup_free_ char *hn = NULL;
1119 char **hostname = data;
a7d0ef44
SS
1120 int r;
1121
1122 assert(filename);
1123 assert(lvalue);
1124 assert(rvalue);
1125
1ac608c9 1126 r = config_parse_string(unit, filename, line, section, section_line, lvalue, ltype, rvalue, &hn, userdata);
a7d0ef44
SS
1127 if (r < 0)
1128 return r;
1129
1ac608c9 1130 if (!hostname_is_valid(hn, false)) {
d96edb2c 1131 log_syntax(unit, LOG_WARNING, filename, line, 0,
ab24039f 1132 "Hostname is not valid, ignoring assignment: %s", rvalue);
a7d0ef44
SS
1133 return 0;
1134 }
1135
6528693a
YW
1136 r = dns_name_is_valid(hn);
1137 if (r < 0) {
d96edb2c 1138 log_syntax(unit, LOG_WARNING, filename, line, r,
ab24039f 1139 "Failed to check validity of hostname '%s', ignoring assignment: %m", rvalue);
6528693a
YW
1140 return 0;
1141 }
1142 if (r == 0) {
d96edb2c 1143 log_syntax(unit, LOG_WARNING, filename, line, 0,
ab24039f 1144 "Hostname is not a valid DNS domain name, ignoring assignment: %s", rvalue);
6528693a
YW
1145 return 0;
1146 }
1147
1148 return free_and_replace(*hostname, hn);
a7d0ef44 1149}
8eb9058d
LP
1150
1151int config_parse_timezone(
1152 const char *unit,
1153 const char *filename,
1154 unsigned line,
1155 const char *section,
1156 unsigned section_line,
1157 const char *lvalue,
1158 int ltype,
1159 const char *rvalue,
1160 void *data,
1161 void *userdata) {
1162
19f9e4e2
YW
1163 _cleanup_free_ char *tz = NULL;
1164 char **datap = data;
8eb9058d
LP
1165 int r;
1166
1167 assert(filename);
1168 assert(lvalue);
1169 assert(rvalue);
1170
1171 r = config_parse_string(unit, filename, line, section, section_line, lvalue, ltype, rvalue, &tz, userdata);
1172 if (r < 0)
1173 return r;
1174
d96edb2c
YW
1175 if (!timezone_is_valid(tz, LOG_WARNING)) {
1176 log_syntax(unit, LOG_WARNING, filename, line, 0,
ab24039f 1177 "Timezone is not valid, ignoring assignment: %s", rvalue);
8eb9058d
LP
1178 return 0;
1179 }
1180
19f9e4e2 1181 return free_and_replace(*datap, tz);
8eb9058d 1182}
1a04db0f 1183
53253824
SS
1184int config_parse_dns(
1185 const char *unit,
1186 const char *filename,
1187 unsigned line,
1188 const char *section,
1189 unsigned section_line,
1190 const char *lvalue,
1191 int ltype,
1192 const char *rvalue,
1193 void *data,
1194 void *userdata) {
1195
1196 Network *n = userdata;
1197 int r;
1198
1199 assert(filename);
1200 assert(lvalue);
1201 assert(rvalue);
1202
d96edb2c 1203 if (isempty(rvalue)) {
e77bd3fd
YW
1204 for (unsigned i = 0; i < n->n_dns; i++)
1205 in_addr_full_free(n->dns[i]);
d96edb2c
YW
1206 n->dns = mfree(n->dns);
1207 n->n_dns = 0;
1208 return 0;
1209 }
1210
1211 for (const char *p = rvalue;;) {
e77bd3fd 1212 _cleanup_(in_addr_full_freep) struct in_addr_full *dns = NULL;
53253824 1213 _cleanup_free_ char *w = NULL;
e77bd3fd 1214 struct in_addr_full **m;
53253824 1215
d96edb2c 1216 r = extract_first_word(&p, &w, NULL, 0);
53253824
SS
1217 if (r == -ENOMEM)
1218 return log_oom();
1219 if (r < 0) {
d96edb2c 1220 log_syntax(unit, LOG_WARNING, filename, line, r,
ab24039f 1221 "Invalid syntax, ignoring: %s", rvalue);
d96edb2c 1222 return 0;
53253824 1223 }
5512a963 1224 if (r == 0)
d96edb2c 1225 return 0;
53253824 1226
e77bd3fd 1227 r = in_addr_full_new_from_string(w, &dns);
53253824 1228 if (r < 0) {
d96edb2c 1229 log_syntax(unit, LOG_WARNING, filename, line, r,
ab24039f 1230 "Failed to parse dns server address, ignoring: %s", w);
53253824
SS
1231 continue;
1232 }
1233
e77bd3fd
YW
1234 if (IN_SET(dns->port, 53, 853))
1235 dns->port = 0;
1236
1237 m = reallocarray(n->dns, n->n_dns + 1, sizeof(struct in_addr_full*));
5512a963 1238 if (!m)
53253824
SS
1239 return log_oom();
1240
e77bd3fd 1241 m[n->n_dns++] = TAKE_PTR(dns);
5512a963 1242 n->dns = m;
53253824 1243 }
53253824
SS
1244}
1245
8a516214
LP
1246int config_parse_dnssec_negative_trust_anchors(
1247 const char *unit,
1248 const char *filename,
1249 unsigned line,
1250 const char *section,
1251 unsigned section_line,
1252 const char *lvalue,
1253 int ltype,
1254 const char *rvalue,
1255 void *data,
1256 void *userdata) {
1257
8a516214
LP
1258 Network *n = data;
1259 int r;
1260
3df9bec5 1261 assert(n);
8a516214
LP
1262 assert(lvalue);
1263 assert(rvalue);
1264
1265 if (isempty(rvalue)) {
1266 n->dnssec_negative_trust_anchors = set_free_free(n->dnssec_negative_trust_anchors);
1267 return 0;
1268 }
1269
d96edb2c 1270 for (const char *p = rvalue;;) {
8a516214
LP
1271 _cleanup_free_ char *w = NULL;
1272
1273 r = extract_first_word(&p, &w, NULL, 0);
d96edb2c
YW
1274 if (r == -ENOMEM)
1275 return log_oom();
8a516214 1276 if (r < 0) {
d96edb2c 1277 log_syntax(unit, LOG_WARNING, filename, line, r,
ab24039f 1278 "Failed to extract negative trust anchor domain, ignoring: %s", rvalue);
d96edb2c 1279 return 0;
8a516214
LP
1280 }
1281 if (r == 0)
d96edb2c 1282 return 0;
8a516214
LP
1283
1284 r = dns_name_is_valid(w);
1285 if (r <= 0) {
d96edb2c 1286 log_syntax(unit, LOG_WARNING, filename, line, r,
ab24039f 1287 "%s is not a valid domain name, ignoring.", w);
8a516214
LP
1288 continue;
1289 }
1290
35e601d4 1291 r = set_ensure_consume(&n->dnssec_negative_trust_anchors, &dns_name_hash_ops, TAKE_PTR(w));
8a516214
LP
1292 if (r < 0)
1293 return log_oom();
8a516214 1294 }
8a516214 1295}
b2a81c0b 1296
26575990
LP
1297int config_parse_ntp(
1298 const char *unit,
1299 const char *filename,
1300 unsigned line,
1301 const char *section,
1302 unsigned section_line,
1303 const char *lvalue,
1304 int ltype,
1305 const char *rvalue,
1306 void *data,
1307 void *userdata) {
1308
1309 char ***l = data;
1310 int r;
1311
1312 assert(l);
1313 assert(lvalue);
1314 assert(rvalue);
1315
1316 if (isempty(rvalue)) {
1317 *l = strv_free(*l);
1318 return 0;
1319 }
1320
d96edb2c 1321 for (const char *p = rvalue;;) {
26575990
LP
1322 _cleanup_free_ char *w = NULL;
1323
d96edb2c 1324 r = extract_first_word(&p, &w, NULL, 0);
26575990
LP
1325 if (r == -ENOMEM)
1326 return log_oom();
1327 if (r < 0) {
d96edb2c 1328 log_syntax(unit, LOG_WARNING, filename, line, r,
ab24039f 1329 "Failed to extract NTP server name, ignoring: %s", rvalue);
d96edb2c 1330 return 0;
26575990
LP
1331 }
1332 if (r == 0)
d96edb2c 1333 return 0;
26575990
LP
1334
1335 r = dns_name_is_valid_or_address(w);
1336 if (r <= 0) {
d96edb2c 1337 log_syntax(unit, LOG_WARNING, filename, line, r,
ab24039f 1338 "%s is not a valid domain name or IP address, ignoring.", w);
26575990 1339 continue;
af1c0de0
SS
1340 }
1341
c448459d
ZJS
1342 if (strv_length(*l) > MAX_NTP_SERVERS) {
1343 log_syntax(unit, LOG_WARNING, filename, line, 0,
1344 "More than %u NTP servers specified, ignoring \"%s\" and any subsequent entries.",
1345 MAX_NTP_SERVERS, w);
d96edb2c 1346 return 0;
c448459d
ZJS
1347 }
1348
1349 r = strv_consume(l, TAKE_PTR(w));
af1c0de0
SS
1350 if (r < 0)
1351 return log_oom();
af1c0de0 1352 }
af1c0de0
SS
1353}
1354
4ac77d63
YW
1355int config_parse_required_for_online(
1356 const char *unit,
1357 const char *filename,
1358 unsigned line,
1359 const char *section,
1360 unsigned section_line,
1361 const char *lvalue,
1362 int ltype,
1363 const char *rvalue,
1364 void *data,
1365 void *userdata) {
1366
1367 Network *network = data;
75cd4a5d 1368 LinkOperationalStateRange range;
4ac77d63
YW
1369 bool required = true;
1370 int r;
1371
1372 if (isempty(rvalue)) {
1373 network->required_for_online = true;
75cd4a5d 1374 network->required_operstate_for_online = LINK_OPERSTATE_RANGE_DEFAULT;
4ac77d63
YW
1375 return 0;
1376 }
1377
75cd4a5d
DDM
1378 r = parse_operational_state_range(rvalue, &range);
1379 if (r < 0) {
4ac77d63
YW
1380 r = parse_boolean(rvalue);
1381 if (r < 0) {
d96edb2c 1382 log_syntax(unit, LOG_WARNING, filename, line, r,
4ac77d63
YW
1383 "Failed to parse %s= setting, ignoring assignment: %s",
1384 lvalue, rvalue);
1385 return 0;
1386 }
1387
1388 required = r;
75cd4a5d 1389 range = LINK_OPERSTATE_RANGE_DEFAULT;
4ac77d63
YW
1390 }
1391
1392 network->required_for_online = required;
75cd4a5d 1393 network->required_operstate_for_online = range;
4ac77d63
YW
1394
1395 return 0;
1396}
7da377ef
SS
1397
1398DEFINE_CONFIG_PARSE_ENUM(config_parse_keep_configuration, keep_configuration, KeepConfiguration,
1399 "Failed to parse KeepConfiguration= setting");
1400
1401static const char* const keep_configuration_table[_KEEP_CONFIGURATION_MAX] = {
95355a28
YW
1402 [KEEP_CONFIGURATION_NO] = "no",
1403 [KEEP_CONFIGURATION_DHCP_ON_STOP] = "dhcp-on-stop",
1404 [KEEP_CONFIGURATION_DHCP] = "dhcp",
1405 [KEEP_CONFIGURATION_STATIC] = "static",
1406 [KEEP_CONFIGURATION_YES] = "yes",
7da377ef
SS
1407};
1408
1409DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(keep_configuration, KeepConfiguration, KEEP_CONFIGURATION_YES);
6f6296b9
YW
1410
1411static const char* const ipv6_link_local_address_gen_mode_table[_IPV6_LINK_LOCAL_ADDRESS_GEN_MODE_MAX] = {
1412 [IPV6_LINK_LOCAL_ADDRESSS_GEN_MODE_EUI64] = "eui64",
1413 [IPV6_LINK_LOCAL_ADDRESSS_GEN_MODE_NONE] = "none",
1414 [IPV6_LINK_LOCAL_ADDRESSS_GEN_MODE_STABLE_PRIVACY] = "stable-privacy",
1415 [IPV6_LINK_LOCAL_ADDRESSS_GEN_MODE_RANDOM] = "random",
1416};
1417
1418DEFINE_STRING_TABLE_LOOKUP(ipv6_link_local_address_gen_mode, IPv6LinkLocalAddressGenMode);
1419DEFINE_CONFIG_PARSE_ENUM(config_parse_ipv6_link_local_address_gen_mode, ipv6_link_local_address_gen_mode, IPv6LinkLocalAddressGenMode, "Failed to parse IPv6 link local address generation mode");