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