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