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