]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/resolve/resolved-link.c
man/udevadm: remove superfluous --version from subcommands (#8549)
[thirdparty/systemd.git] / src / resolve / resolved-link.c
CommitLineData
53e1b683 1/* SPDX-License-Identifier: LGPL-2.1+ */
74b2466e
LP
2/***
3 This file is part of systemd.
4
5 Copyright 2014 Lennart Poettering
6
7 systemd is free software; you can redistribute it and/or modify it
8 under the terms of the GNU Lesser General Public License as published by
9 the Free Software Foundation; either version 2.1 of the License, or
10 (at your option) any later version.
11
12 systemd is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Lesser General Public License for more details.
16
17 You should have received a copy of the GNU Lesser General Public License
18 along with systemd; If not, see <http://www.gnu.org/licenses/>.
19***/
20
21#include <net/if.h>
0d536673 22#include <stdio_ext.h>
74b2466e
LP
23
24#include "sd-network.h"
07630cea 25
b5efdb8a 26#include "alloc-util.h"
943ef07c
LP
27#include "fd-util.h"
28#include "fileio.h"
ec2c5e43 29#include "missing.h"
943ef07c 30#include "mkdir.h"
6bedfcbb 31#include "parse-util.h"
74b2466e 32#include "resolved-link.h"
c6a8f6f6
YW
33#include "resolved-llmnr.h"
34#include "resolved-mdns.h"
07630cea
LP
35#include "string-util.h"
36#include "strv.h"
74b2466e
LP
37
38int link_new(Manager *m, Link **ret, int ifindex) {
39 _cleanup_(link_freep) Link *l = NULL;
40 int r;
41
42 assert(m);
43 assert(ifindex > 0);
44
d5099efc 45 r = hashmap_ensure_allocated(&m->links, NULL);
74b2466e
LP
46 if (r < 0)
47 return r;
48
49 l = new0(Link, 1);
50 if (!l)
51 return -ENOMEM;
52
53 l->ifindex = ifindex;
af49ca27 54 l->llmnr_support = RESOLVE_SUPPORT_YES;
ad6c0475
LP
55 l->mdns_support = RESOLVE_SUPPORT_NO;
56 l->dnssec_mode = _DNSSEC_MODE_INVALID;
6955a3ba 57 l->operstate = IF_OPER_UNKNOWN;
74b2466e 58
943ef07c
LP
59 if (asprintf(&l->state_file, "/run/systemd/resolve/netif/%i", ifindex) < 0)
60 return -ENOMEM;
61
74b2466e
LP
62 r = hashmap_put(m->links, INT_TO_PTR(ifindex), l);
63 if (r < 0)
64 return r;
65
66 l->manager = m;
67
68 if (ret)
69 *ret = l;
70 l = NULL;
71
72 return 0;
73}
74
97e5d693
LP
75void link_flush_settings(Link *l) {
76 assert(l);
77
78 l->llmnr_support = RESOLVE_SUPPORT_YES;
79 l->mdns_support = RESOLVE_SUPPORT_NO;
80 l->dnssec_mode = _DNSSEC_MODE_INVALID;
81
82 dns_server_unlink_all(l->dns_servers);
83 dns_search_domain_unlink_all(l->search_domains);
84
85 l->dnssec_negative_trust_anchors = set_free_free(l->dnssec_negative_trust_anchors);
86}
87
74b2466e 88Link *link_free(Link *l) {
74b2466e
LP
89 if (!l)
90 return NULL;
91
c3ae4188
DR
92 /* Send goodbye messages. */
93 dns_scope_announce(l->mdns_ipv4_scope, true);
94 dns_scope_announce(l->mdns_ipv6_scope, true);
95
97e5d693 96 link_flush_settings(l);
0eac4623 97
74b2466e 98 while (l->addresses)
97e5d693 99 (void) link_address_free(l->addresses);
74b2466e
LP
100
101 if (l->manager)
102 hashmap_remove(l->manager->links, INT_TO_PTR(l->ifindex));
103
104 dns_scope_free(l->unicast_scope);
1716f6dc
LP
105 dns_scope_free(l->llmnr_ipv4_scope);
106 dns_scope_free(l->llmnr_ipv6_scope);
b4f1862d
DM
107 dns_scope_free(l->mdns_ipv4_scope);
108 dns_scope_free(l->mdns_ipv6_scope);
74b2466e 109
943ef07c
LP
110 free(l->state_file);
111
6b430fdb 112 return mfree(l);
1716f6dc
LP
113}
114
97e5d693 115void link_allocate_scopes(Link *l) {
59c0fd0e 116 bool unicast_relevant;
1716f6dc
LP
117 int r;
118
119 assert(l);
120
59c0fd0e
LP
121 /* If a link that used to be relevant is no longer, or a link that did not use to be relevant now becomes
122 * relevant, let's reinit the learnt global DNS server information, since we might talk to different servers
123 * now, even if they have the same addresses as before. */
124
125 unicast_relevant = link_relevant(l, AF_UNSPEC, false);
126 if (unicast_relevant != l->unicast_relevant) {
127 l->unicast_relevant = unicast_relevant;
128
129 dns_server_reset_features_all(l->manager->fallback_dns_servers);
130 dns_server_reset_features_all(l->manager->dns_servers);
131 }
132
133 /* And now, allocate all scopes that makes sense now if we didn't have them yet, and drop those which we don't
134 * need anymore */
135
136 if (unicast_relevant && l->dns_servers) {
1716f6dc 137 if (!l->unicast_scope) {
59c0fd0e
LP
138 dns_server_reset_features_all(l->dns_servers);
139
1716f6dc
LP
140 r = dns_scope_new(l->manager, &l->unicast_scope, l, DNS_PROTOCOL_DNS, AF_UNSPEC);
141 if (r < 0)
da927ba9 142 log_warning_errno(r, "Failed to allocate DNS scope: %m");
1716f6dc
LP
143 }
144 } else
145 l->unicast_scope = dns_scope_free(l->unicast_scope);
146
dfc1091b 147 if (link_relevant(l, AF_INET, true) &&
af49ca27
LP
148 l->llmnr_support != RESOLVE_SUPPORT_NO &&
149 l->manager->llmnr_support != RESOLVE_SUPPORT_NO) {
1716f6dc
LP
150 if (!l->llmnr_ipv4_scope) {
151 r = dns_scope_new(l->manager, &l->llmnr_ipv4_scope, l, DNS_PROTOCOL_LLMNR, AF_INET);
152 if (r < 0)
da927ba9 153 log_warning_errno(r, "Failed to allocate LLMNR IPv4 scope: %m");
1716f6dc
LP
154 }
155 } else
156 l->llmnr_ipv4_scope = dns_scope_free(l->llmnr_ipv4_scope);
157
dfc1091b 158 if (link_relevant(l, AF_INET6, true) &&
af49ca27
LP
159 l->llmnr_support != RESOLVE_SUPPORT_NO &&
160 l->manager->llmnr_support != RESOLVE_SUPPORT_NO &&
db97a66a 161 socket_ipv6_is_supported()) {
1716f6dc
LP
162 if (!l->llmnr_ipv6_scope) {
163 r = dns_scope_new(l->manager, &l->llmnr_ipv6_scope, l, DNS_PROTOCOL_LLMNR, AF_INET6);
164 if (r < 0)
da927ba9 165 log_warning_errno(r, "Failed to allocate LLMNR IPv6 scope: %m");
1716f6dc
LP
166 }
167 } else
168 l->llmnr_ipv6_scope = dns_scope_free(l->llmnr_ipv6_scope);
b4f1862d 169
dfc1091b 170 if (link_relevant(l, AF_INET, true) &&
af49ca27
LP
171 l->mdns_support != RESOLVE_SUPPORT_NO &&
172 l->manager->mdns_support != RESOLVE_SUPPORT_NO) {
b4f1862d
DM
173 if (!l->mdns_ipv4_scope) {
174 r = dns_scope_new(l->manager, &l->mdns_ipv4_scope, l, DNS_PROTOCOL_MDNS, AF_INET);
175 if (r < 0)
176 log_warning_errno(r, "Failed to allocate mDNS IPv4 scope: %m");
177 }
178 } else
179 l->mdns_ipv4_scope = dns_scope_free(l->mdns_ipv4_scope);
180
dfc1091b 181 if (link_relevant(l, AF_INET6, true) &&
af49ca27
LP
182 l->mdns_support != RESOLVE_SUPPORT_NO &&
183 l->manager->mdns_support != RESOLVE_SUPPORT_NO) {
b4f1862d
DM
184 if (!l->mdns_ipv6_scope) {
185 r = dns_scope_new(l->manager, &l->mdns_ipv6_scope, l, DNS_PROTOCOL_MDNS, AF_INET6);
186 if (r < 0)
187 log_warning_errno(r, "Failed to allocate mDNS IPv6 scope: %m");
188 }
189 } else
190 l->mdns_ipv6_scope = dns_scope_free(l->mdns_ipv6_scope);
1716f6dc 191}
74b2466e 192
ec2c5e43 193void link_add_rrs(Link *l, bool force_remove) {
623a4c97 194 LinkAddress *a;
6db6a464 195 int r;
623a4c97
LP
196
197 LIST_FOREACH(addresses, a, l->addresses)
ec2c5e43 198 link_address_add_rrs(a, force_remove);
6db6a464
DR
199
200 if (!force_remove &&
201 l->mdns_support == RESOLVE_SUPPORT_YES &&
202 l->manager->mdns_support == RESOLVE_SUPPORT_YES) {
203
204 if (l->mdns_ipv4_scope) {
205 r = dns_scope_add_dnssd_services(l->mdns_ipv4_scope);
206 if (r < 0)
207 log_warning_errno(r, "Failed to add IPv4 DNS-SD services: %m");
208 }
209
210 if (l->mdns_ipv6_scope) {
211 r = dns_scope_add_dnssd_services(l->mdns_ipv6_scope);
212 if (r < 0)
213 log_warning_errno(r, "Failed to add IPv6 DNS-SD services: %m");
214 }
215
216 } else {
217
218 if (l->mdns_ipv4_scope) {
219 r = dns_scope_remove_dnssd_services(l->mdns_ipv4_scope);
220 if (r < 0)
221 log_warning_errno(r, "Failed to remove IPv4 DNS-SD services: %m");
222 }
223
224 if (l->mdns_ipv6_scope) {
225 r = dns_scope_remove_dnssd_services(l->mdns_ipv6_scope);
226 if (r < 0)
227 log_warning_errno(r, "Failed to remove IPv6 DNS-SD services: %m");
228 }
229 }
623a4c97
LP
230}
231
943ef07c 232int link_process_rtnl(Link *l, sd_netlink_message *m) {
1716f6dc 233 const char *n = NULL;
74b2466e
LP
234 int r;
235
236 assert(l);
237 assert(m);
238
239 r = sd_rtnl_message_link_get_flags(m, &l->flags);
240 if (r < 0)
241 return r;
242
6955a3ba
LP
243 (void) sd_netlink_message_read_u32(m, IFLA_MTU, &l->mtu);
244 (void) sd_netlink_message_read_u8(m, IFLA_OPERSTATE, &l->operstate);
1716f6dc 245
1c4baffc 246 if (sd_netlink_message_read_string(m, IFLA_IFNAME, &n) >= 0) {
cc7844e7 247 strncpy(l->name, n, sizeof(l->name)-1);
1716f6dc
LP
248 char_array_0(l->name);
249 }
250
251 link_allocate_scopes(l);
ec2c5e43 252 link_add_rrs(l, false);
623a4c97 253
74b2466e
LP
254 return 0;
255}
256
55e99f20
LP
257static int link_update_dns_server_one(Link *l, const char *name) {
258 union in_addr_union a;
259 DnsServer *s;
260 int family, r;
261
262 assert(l);
263 assert(name);
264
265 r = in_addr_from_string_auto(name, &family, &a);
266 if (r < 0)
267 return r;
268
269 s = dns_server_find(l->dns_servers, family, &a, 0);
270 if (s) {
271 dns_server_move_back_and_unmark(s);
272 return 0;
273 }
274
275 return dns_server_new(l->manager, NULL, DNS_SERVER_LINK, l, family, &a, 0);
276}
277
6073b6f2 278static int link_update_dns_servers(Link *l) {
6f4dedb2
TG
279 _cleanup_strv_free_ char **nameservers = NULL;
280 char **nameserver;
6f4dedb2 281 int r;
74b2466e
LP
282
283 assert(l);
284
d6731e4c 285 r = sd_network_link_get_dns(l->ifindex, &nameservers);
1ade96e9
LP
286 if (r == -ENODATA) {
287 r = 0;
288 goto clear;
289 }
6f4dedb2 290 if (r < 0)
74b2466e 291 goto clear;
74b2466e 292
4b95f179 293 dns_server_mark_all(l->dns_servers);
5cb36f41 294
6f4dedb2 295 STRV_FOREACH(nameserver, nameservers) {
55e99f20 296 r = link_update_dns_server_one(l, *nameserver);
6f4dedb2
TG
297 if (r < 0)
298 goto clear;
74b2466e
LP
299 }
300
4b95f179 301 dns_server_unlink_marked(l->dns_servers);
74b2466e
LP
302 return 0;
303
304clear:
4b95f179 305 dns_server_unlink_all(l->dns_servers);
74b2466e
LP
306 return r;
307}
308
19b50b5b
LP
309static int link_update_llmnr_support(Link *l) {
310 _cleanup_free_ char *b = NULL;
311 int r;
312
313 assert(l);
314
d6731e4c 315 r = sd_network_link_get_llmnr(l->ifindex, &b);
1ade96e9
LP
316 if (r == -ENODATA) {
317 r = 0;
318 goto clear;
319 }
19b50b5b
LP
320 if (r < 0)
321 goto clear;
322
af49ca27
LP
323 l->llmnr_support = resolve_support_from_string(b);
324 if (l->llmnr_support < 0) {
325 r = -EINVAL;
326 goto clear;
327 }
19b50b5b
LP
328
329 return 0;
330
331clear:
af49ca27 332 l->llmnr_support = RESOLVE_SUPPORT_YES;
19b50b5b
LP
333 return r;
334}
335
aaa297d4
LP
336static int link_update_mdns_support(Link *l) {
337 _cleanup_free_ char *b = NULL;
338 int r;
339
340 assert(l);
341
342 r = sd_network_link_get_mdns(l->ifindex, &b);
343 if (r == -ENODATA) {
344 r = 0;
345 goto clear;
346 }
347 if (r < 0)
348 goto clear;
349
350 l->mdns_support = resolve_support_from_string(b);
351 if (l->mdns_support < 0) {
352 r = -EINVAL;
353 goto clear;
354 }
355
356 return 0;
357
358clear:
359 l->mdns_support = RESOLVE_SUPPORT_NO;
360 return r;
361}
362
97e5d693
LP
363void link_set_dnssec_mode(Link *l, DnssecMode mode) {
364
365 assert(l);
366
349cc4a5 367#if ! HAVE_GCRYPT
3742095b 368 if (IN_SET(mode, DNSSEC_YES, DNSSEC_ALLOW_DOWNGRADE))
42303dcb
YW
369 log_warning("DNSSEC option for the link cannot be enabled or set to allow-downgrade when systemd-resolved is built without gcrypt support. Turning off DNSSEC support.");
370 return;
371#endif
372
97e5d693
LP
373 if (l->dnssec_mode == mode)
374 return;
375
376 if ((l->dnssec_mode == _DNSSEC_MODE_INVALID) ||
377 (l->dnssec_mode == DNSSEC_NO && mode != DNSSEC_NO) ||
378 (l->dnssec_mode == DNSSEC_ALLOW_DOWNGRADE && mode == DNSSEC_YES)) {
379
380 /* When switching from non-DNSSEC mode to DNSSEC mode, flush the cache. Also when switching from the
381 * allow-downgrade mode to full DNSSEC mode, flush it too. */
382 if (l->unicast_scope)
383 dns_cache_flush(&l->unicast_scope->cache);
384 }
385
386 l->dnssec_mode = mode;
387}
388
ad6c0475
LP
389static int link_update_dnssec_mode(Link *l) {
390 _cleanup_free_ char *m = NULL;
2e1bab34 391 DnssecMode mode;
ad6c0475
LP
392 int r;
393
394 assert(l);
395
396 r = sd_network_link_get_dnssec(l->ifindex, &m);
397 if (r == -ENODATA) {
398 r = 0;
399 goto clear;
400 }
401 if (r < 0)
402 goto clear;
403
2e1bab34
LP
404 mode = dnssec_mode_from_string(m);
405 if (mode < 0) {
ad6c0475
LP
406 r = -EINVAL;
407 goto clear;
408 }
409
97e5d693 410 link_set_dnssec_mode(l, mode);
2e1bab34 411
ad6c0475
LP
412 return 0;
413
414clear:
415 l->dnssec_mode = _DNSSEC_MODE_INVALID;
416 return r;
417}
418
8a516214
LP
419static int link_update_dnssec_negative_trust_anchors(Link *l) {
420 _cleanup_strv_free_ char **ntas = NULL;
421 _cleanup_set_free_free_ Set *ns = NULL;
8a516214
LP
422 int r;
423
424 assert(l);
425
426 r = sd_network_link_get_dnssec_negative_trust_anchors(l->ifindex, &ntas);
427 if (r == -ENODATA) {
428 r = 0;
429 goto clear;
430 }
431 if (r < 0)
432 goto clear;
433
434 ns = set_new(&dns_name_hash_ops);
435 if (!ns)
436 return -ENOMEM;
437
39f259e0
LP
438 r = set_put_strdupv(ns, ntas);
439 if (r < 0)
440 return r;
8a516214
LP
441
442 set_free_free(l->dnssec_negative_trust_anchors);
443 l->dnssec_negative_trust_anchors = ns;
444 ns = NULL;
445
446 return 0;
447
448clear:
449 l->dnssec_negative_trust_anchors = set_free_free(l->dnssec_negative_trust_anchors);
450 return r;
451}
452
ad44b56b
LP
453static int link_update_search_domain_one(Link *l, const char *name, bool route_only) {
454 DnsSearchDomain *d;
455 int r;
456
39f259e0
LP
457 assert(l);
458 assert(name);
459
ad44b56b
LP
460 r = dns_search_domain_find(l->search_domains, name, &d);
461 if (r < 0)
462 return r;
463 if (r > 0)
464 dns_search_domain_move_back_and_unmark(d);
465 else {
466 r = dns_search_domain_new(l->manager, &d, DNS_SEARCH_DOMAIN_LINK, l, name);
467 if (r < 0)
468 return r;
469 }
470
471 d->route_only = route_only;
472 return 0;
473}
474
a51c1048 475static int link_update_search_domains(Link *l) {
ad44b56b 476 _cleanup_strv_free_ char **sdomains = NULL, **rdomains = NULL;
a51c1048 477 char **i;
ad44b56b 478 int r, q;
bda2c408 479
a51c1048 480 assert(l);
bda2c408 481
ad44b56b
LP
482 r = sd_network_link_get_search_domains(l->ifindex, &sdomains);
483 if (r < 0 && r != -ENODATA)
484 goto clear;
485
486 q = sd_network_link_get_route_domains(l->ifindex, &rdomains);
487 if (q < 0 && q != -ENODATA) {
488 r = q;
489 goto clear;
490 }
491
492 if (r == -ENODATA && q == -ENODATA) {
1ade96e9
LP
493 /* networkd knows nothing about this interface, and that's fine. */
494 r = 0;
495 goto clear;
496 }
a51c1048
LP
497
498 dns_search_domain_mark_all(l->search_domains);
499
ad44b56b
LP
500 STRV_FOREACH(i, sdomains) {
501 r = link_update_search_domain_one(l, *i, false);
a51c1048
LP
502 if (r < 0)
503 goto clear;
ad44b56b 504 }
a51c1048 505
ad44b56b
LP
506 STRV_FOREACH(i, rdomains) {
507 r = link_update_search_domain_one(l, *i, true);
508 if (r < 0)
509 goto clear;
a51c1048
LP
510 }
511
512 dns_search_domain_unlink_marked(l->search_domains);
bda2c408 513 return 0;
a51c1048
LP
514
515clear:
516 dns_search_domain_unlink_all(l->search_domains);
517 return r;
bda2c408
TG
518}
519
b6274a0e 520static int link_is_managed(Link *l) {
97e5d693 521 _cleanup_free_ char *state = NULL;
a51c1048
LP
522 int r;
523
74b2466e
LP
524 assert(l);
525
97e5d693
LP
526 r = sd_network_link_get_setup_state(l->ifindex, &state);
527 if (r == -ENODATA)
b6274a0e 528 return 0;
97e5d693
LP
529 if (r < 0)
530 return r;
531
b6274a0e 532 return !STR_IN_SET(state, "pending", "unmanaged");
97e5d693
LP
533}
534
535static void link_read_settings(Link *l) {
536 int r;
537
538 assert(l);
539
540 /* Read settings from networkd, except when networkd is not managing this interface. */
541
b6274a0e 542 r = link_is_managed(l);
97e5d693
LP
543 if (r < 0) {
544 log_warning_errno(r, "Failed to determine whether interface %s is managed: %m", l->name);
545 return;
546 }
b6274a0e 547 if (r == 0) {
97e5d693 548
ccddd104 549 /* If this link used to be managed, but is now unmanaged, flush all our settings — but only once. */
97e5d693
LP
550 if (l->is_managed)
551 link_flush_settings(l);
552
553 l->is_managed = false;
554 return;
555 }
556
557 l->is_managed = true;
558
125ae29d
LP
559 r = link_update_dns_servers(l);
560 if (r < 0)
561 log_warning_errno(r, "Failed to read DNS servers for interface %s, ignoring: %m", l->name);
562
563 r = link_update_llmnr_support(l);
564 if (r < 0)
565 log_warning_errno(r, "Failed to read LLMNR support for interface %s, ignoring: %m", l->name);
566
567 r = link_update_mdns_support(l);
568 if (r < 0)
569 log_warning_errno(r, "Failed to read mDNS support for interface %s, ignoring: %m", l->name);
570
ad6c0475
LP
571 r = link_update_dnssec_mode(l);
572 if (r < 0)
573 log_warning_errno(r, "Failed to read DNSSEC mode for interface %s, ignoring: %m", l->name);
a51c1048 574
8a516214
LP
575 r = link_update_dnssec_negative_trust_anchors(l);
576 if (r < 0)
577 log_warning_errno(r, "Failed to read DNSSEC negative trust anchors for interface %s, ignoring: %m", l->name);
578
a51c1048
LP
579 r = link_update_search_domains(l);
580 if (r < 0)
581 log_warning_errno(r, "Failed to read search domains for interface %s, ignoring: %m", l->name);
97e5d693
LP
582}
583
943ef07c 584int link_update(Link *l) {
c6a8f6f6
YW
585 int r;
586
97e5d693 587 assert(l);
a51c1048 588
97e5d693 589 link_read_settings(l);
943ef07c 590 link_load_user(l);
c6a8f6f6
YW
591
592 if (l->llmnr_support != RESOLVE_SUPPORT_NO) {
593 r = manager_llmnr_start(l->manager);
594 if (r < 0)
595 return r;
596 }
597
598 if (l->mdns_support != RESOLVE_SUPPORT_NO) {
599 r = manager_mdns_start(l->manager);
600 if (r < 0)
601 return r;
602 }
603
ad6c0475 604 link_allocate_scopes(l);
ec2c5e43 605 link_add_rrs(l, false);
74b2466e
LP
606
607 return 0;
608}
609
011696f7 610bool link_relevant(Link *l, int family, bool local_multicast) {
1716f6dc 611 _cleanup_free_ char *state = NULL;
74b2466e
LP
612 LinkAddress *a;
613
614 assert(l);
615
c1edab7a 616 /* A link is relevant for local multicast traffic if it isn't a loopback device, has a link
011696f7
LP
617 * beat, can do multicast and has at least one link-local (or better) IP address.
618 *
619 * A link is relevant for non-multicast traffic if it isn't a loopback device, has a link beat, and has at
13e785f7 620 * least one routable address. */
ec2c5e43 621
dfc1091b 622 if (l->flags & (IFF_LOOPBACK|IFF_DORMANT))
ec2c5e43 623 return false;
74b2466e 624
dfc1091b 625 if ((l->flags & (IFF_UP|IFF_LOWER_UP)) != (IFF_UP|IFF_LOWER_UP))
74b2466e
LP
626 return false;
627
011696f7 628 if (local_multicast) {
dfc1091b
LP
629 if ((l->flags & IFF_MULTICAST) != IFF_MULTICAST)
630 return false;
631 }
632
6955a3ba
LP
633 /* Check kernel operstate
634 * https://www.kernel.org/doc/Documentation/networking/operstates.txt */
635 if (!IN_SET(l->operstate, IF_OPER_UNKNOWN, IF_OPER_UP))
636 return false;
637
638 (void) sd_network_link_get_operational_state(l->ifindex, &state);
1716f6dc 639 if (state && !STR_IN_SET(state, "unknown", "degraded", "routable"))
74b2466e
LP
640 return false;
641
642 LIST_FOREACH(addresses, a, l->addresses)
011696f7 643 if ((family == AF_UNSPEC || a->family == family) && link_address_relevant(a, local_multicast))
74b2466e
LP
644 return true;
645
646 return false;
647}
648
623a4c97 649LinkAddress *link_find_address(Link *l, int family, const union in_addr_union *in_addr) {
74b2466e
LP
650 LinkAddress *a;
651
652 assert(l);
653
1716f6dc
LP
654 LIST_FOREACH(addresses, a, l->addresses)
655 if (a->family == family && in_addr_equal(family, &a->in_addr, in_addr))
74b2466e 656 return a;
74b2466e
LP
657
658 return NULL;
659}
660
2c27fbca 661DnsServer* link_set_dns_server(Link *l, DnsServer *s) {
4e945a6f
LP
662 assert(l);
663
664 if (l->current_dns_server == s)
665 return s;
666
6cb08a89 667 if (s)
db8e1324 668 log_debug("Switching to DNS server %s for interface %s.", dns_server_string(s), l->name);
4e945a6f 669
0eac4623
LP
670 dns_server_unref(l->current_dns_server);
671 l->current_dns_server = dns_server_ref(s);
2c27fbca
LP
672
673 if (l->unicast_scope)
674 dns_cache_flush(&l->unicast_scope->cache);
675
4e945a6f
LP
676 return s;
677}
678
74b2466e
LP
679DnsServer *link_get_dns_server(Link *l) {
680 assert(l);
681
682 if (!l->current_dns_server)
4e945a6f 683 link_set_dns_server(l, l->dns_servers);
74b2466e
LP
684
685 return l->current_dns_server;
686}
687
688void link_next_dns_server(Link *l) {
689 assert(l);
690
74b2466e
LP
691 if (!l->current_dns_server)
692 return;
693
0eac4623
LP
694 /* Change to the next one, but make sure to follow the linked
695 * list only if this server is actually still linked. */
696 if (l->current_dns_server->linked && l->current_dns_server->servers_next) {
4e945a6f 697 link_set_dns_server(l, l->current_dns_server->servers_next);
74b2466e
LP
698 return;
699 }
700
4e945a6f 701 link_set_dns_server(l, l->dns_servers);
74b2466e
LP
702}
703
c69fa7e3
LP
704DnssecMode link_get_dnssec_mode(Link *l) {
705 assert(l);
706
707 if (l->dnssec_mode != _DNSSEC_MODE_INVALID)
708 return l->dnssec_mode;
709
710 return manager_get_dnssec_mode(l->manager);
711}
712
713bool link_dnssec_supported(Link *l) {
714 DnsServer *server;
715
716 assert(l);
717
718 if (link_get_dnssec_mode(l) == DNSSEC_NO)
719 return false;
720
721 server = link_get_dns_server(l);
722 if (server)
723 return dns_server_dnssec_supported(server);
724
725 return true;
726}
727
623a4c97 728int link_address_new(Link *l, LinkAddress **ret, int family, const union in_addr_union *in_addr) {
74b2466e
LP
729 LinkAddress *a;
730
731 assert(l);
732 assert(in_addr);
733
734 a = new0(LinkAddress, 1);
735 if (!a)
736 return -ENOMEM;
737
738 a->family = family;
739 a->in_addr = *in_addr;
740
741 a->link = l;
742 LIST_PREPEND(addresses, l->addresses, a);
bceaa99d 743 l->n_addresses++;
74b2466e
LP
744
745 if (ret)
746 *ret = a;
747
748 return 0;
749}
750
751LinkAddress *link_address_free(LinkAddress *a) {
752 if (!a)
753 return NULL;
754
623a4c97 755 if (a->link) {
74b2466e
LP
756 LIST_REMOVE(addresses, a->link->addresses, a);
757
bceaa99d
LP
758 assert(a->link->n_addresses > 0);
759 a->link->n_addresses--;
760
623a4c97 761 if (a->llmnr_address_rr) {
623a4c97
LP
762 if (a->family == AF_INET && a->link->llmnr_ipv4_scope)
763 dns_zone_remove_rr(&a->link->llmnr_ipv4_scope->zone, a->llmnr_address_rr);
764 else if (a->family == AF_INET6 && a->link->llmnr_ipv6_scope)
765 dns_zone_remove_rr(&a->link->llmnr_ipv6_scope->zone, a->llmnr_address_rr);
623a4c97
LP
766 }
767
768 if (a->llmnr_ptr_rr) {
769 if (a->family == AF_INET && a->link->llmnr_ipv4_scope)
770 dns_zone_remove_rr(&a->link->llmnr_ipv4_scope->zone, a->llmnr_ptr_rr);
771 else if (a->family == AF_INET6 && a->link->llmnr_ipv6_scope)
772 dns_zone_remove_rr(&a->link->llmnr_ipv6_scope->zone, a->llmnr_ptr_rr);
623a4c97 773 }
400cb36e
DR
774
775 if (a->mdns_address_rr) {
776 if (a->family == AF_INET && a->link->mdns_ipv4_scope)
777 dns_zone_remove_rr(&a->link->mdns_ipv4_scope->zone, a->mdns_address_rr);
778 else if (a->family == AF_INET6 && a->link->mdns_ipv6_scope)
779 dns_zone_remove_rr(&a->link->mdns_ipv6_scope->zone, a->mdns_address_rr);
780 }
781
782 if (a->mdns_ptr_rr) {
783 if (a->family == AF_INET && a->link->mdns_ipv4_scope)
784 dns_zone_remove_rr(&a->link->mdns_ipv4_scope->zone, a->mdns_ptr_rr);
785 else if (a->family == AF_INET6 && a->link->mdns_ipv6_scope)
786 dns_zone_remove_rr(&a->link->mdns_ipv6_scope->zone, a->mdns_ptr_rr);
787 }
623a4c97
LP
788 }
789
ec2c5e43
LP
790 dns_resource_record_unref(a->llmnr_address_rr);
791 dns_resource_record_unref(a->llmnr_ptr_rr);
400cb36e
DR
792 dns_resource_record_unref(a->mdns_address_rr);
793 dns_resource_record_unref(a->mdns_ptr_rr);
ec2c5e43 794
6b430fdb 795 return mfree(a);
74b2466e
LP
796}
797
ec2c5e43 798void link_address_add_rrs(LinkAddress *a, bool force_remove) {
623a4c97
LP
799 int r;
800
801 assert(a);
802
ec2c5e43 803 if (a->family == AF_INET) {
623a4c97 804
4e945a6f 805 if (!force_remove &&
011696f7 806 link_address_relevant(a, true) &&
4e945a6f 807 a->link->llmnr_ipv4_scope &&
af49ca27
LP
808 a->link->llmnr_support == RESOLVE_SUPPORT_YES &&
809 a->link->manager->llmnr_support == RESOLVE_SUPPORT_YES) {
4e945a6f 810
78c6a153
LP
811 if (!a->link->manager->llmnr_host_ipv4_key) {
812 a->link->manager->llmnr_host_ipv4_key = dns_resource_key_new(DNS_CLASS_IN, DNS_TYPE_A, a->link->manager->llmnr_hostname);
813 if (!a->link->manager->llmnr_host_ipv4_key) {
ec2c5e43
LP
814 r = -ENOMEM;
815 goto fail;
816 }
623a4c97 817 }
623a4c97 818
623a4c97 819 if (!a->llmnr_address_rr) {
78c6a153 820 a->llmnr_address_rr = dns_resource_record_new(a->link->manager->llmnr_host_ipv4_key);
ec2c5e43
LP
821 if (!a->llmnr_address_rr) {
822 r = -ENOMEM;
823 goto fail;
824 }
825
826 a->llmnr_address_rr->a.in_addr = a->in_addr.in;
827 a->llmnr_address_rr->ttl = LLMNR_DEFAULT_TTL;
623a4c97
LP
828 }
829
ec2c5e43 830 if (!a->llmnr_ptr_rr) {
78c6a153 831 r = dns_resource_record_new_reverse(&a->llmnr_ptr_rr, a->family, &a->in_addr, a->link->manager->llmnr_hostname);
ec2c5e43
LP
832 if (r < 0)
833 goto fail;
623a4c97 834
ec2c5e43
LP
835 a->llmnr_ptr_rr->ttl = LLMNR_DEFAULT_TTL;
836 }
623a4c97 837
ec2c5e43 838 r = dns_zone_put(&a->link->llmnr_ipv4_scope->zone, a->link->llmnr_ipv4_scope, a->llmnr_address_rr, true);
623a4c97 839 if (r < 0)
da927ba9 840 log_warning_errno(r, "Failed to add A record to LLMNR zone: %m");
623a4c97 841
ec2c5e43 842 r = dns_zone_put(&a->link->llmnr_ipv4_scope->zone, a->link->llmnr_ipv4_scope, a->llmnr_ptr_rr, false);
623a4c97 843 if (r < 0)
e372a138 844 log_warning_errno(r, "Failed to add IPv4 PTR record to LLMNR zone: %m");
623a4c97 845 } else {
ec2c5e43
LP
846 if (a->llmnr_address_rr) {
847 if (a->link->llmnr_ipv4_scope)
848 dns_zone_remove_rr(&a->link->llmnr_ipv4_scope->zone, a->llmnr_address_rr);
849 a->llmnr_address_rr = dns_resource_record_unref(a->llmnr_address_rr);
850 }
851
852 if (a->llmnr_ptr_rr) {
853 if (a->link->llmnr_ipv4_scope)
854 dns_zone_remove_rr(&a->link->llmnr_ipv4_scope->zone, a->llmnr_ptr_rr);
855 a->llmnr_ptr_rr = dns_resource_record_unref(a->llmnr_ptr_rr);
856 }
623a4c97 857 }
400cb36e
DR
858
859 if (!force_remove &&
860 link_address_relevant(a, true) &&
861 a->link->mdns_ipv4_scope &&
862 a->link->mdns_support == RESOLVE_SUPPORT_YES &&
863 a->link->manager->mdns_support == RESOLVE_SUPPORT_YES) {
864 if (!a->link->manager->mdns_host_ipv4_key) {
865 a->link->manager->mdns_host_ipv4_key = dns_resource_key_new(DNS_CLASS_IN, DNS_TYPE_A, a->link->manager->mdns_hostname);
866 if (!a->link->manager->mdns_host_ipv4_key) {
867 r = -ENOMEM;
868 goto fail;
869 }
870 }
871
872 if (!a->mdns_address_rr) {
873 a->mdns_address_rr = dns_resource_record_new(a->link->manager->mdns_host_ipv4_key);
874 if (!a->mdns_address_rr) {
875 r = -ENOMEM;
876 goto fail;
877 }
878
879 a->mdns_address_rr->a.in_addr = a->in_addr.in;
880 a->mdns_address_rr->ttl = MDNS_DEFAULT_TTL;
881 }
882
883 if (!a->mdns_ptr_rr) {
884 r = dns_resource_record_new_reverse(&a->mdns_ptr_rr, a->family, &a->in_addr, a->link->manager->mdns_hostname);
885 if (r < 0)
886 goto fail;
887
888 a->mdns_ptr_rr->ttl = MDNS_DEFAULT_TTL;
889 }
890
891 r = dns_zone_put(&a->link->mdns_ipv4_scope->zone, a->link->mdns_ipv4_scope, a->mdns_address_rr, true);
892 if (r < 0)
893 log_warning_errno(r, "Failed to add A record to MDNS zone: %m");
894
895 r = dns_zone_put(&a->link->mdns_ipv4_scope->zone, a->link->mdns_ipv4_scope, a->mdns_ptr_rr, false);
896 if (r < 0)
897 log_warning_errno(r, "Failed to add IPv4 PTR record to MDNS zone: %m");
898 } else {
899 if (a->mdns_address_rr) {
900 if (a->link->mdns_ipv4_scope)
901 dns_zone_remove_rr(&a->link->mdns_ipv4_scope->zone, a->mdns_address_rr);
902 a->mdns_address_rr = dns_resource_record_unref(a->mdns_address_rr);
903 }
904
905 if (a->mdns_ptr_rr) {
906 if (a->link->mdns_ipv4_scope)
907 dns_zone_remove_rr(&a->link->mdns_ipv4_scope->zone, a->mdns_ptr_rr);
908 a->mdns_ptr_rr = dns_resource_record_unref(a->mdns_ptr_rr);
909 }
910 }
623a4c97
LP
911 }
912
ec2c5e43 913 if (a->family == AF_INET6) {
623a4c97 914
4e945a6f 915 if (!force_remove &&
011696f7 916 link_address_relevant(a, true) &&
4e945a6f 917 a->link->llmnr_ipv6_scope &&
af49ca27
LP
918 a->link->llmnr_support == RESOLVE_SUPPORT_YES &&
919 a->link->manager->llmnr_support == RESOLVE_SUPPORT_YES) {
4e945a6f 920
78c6a153
LP
921 if (!a->link->manager->llmnr_host_ipv6_key) {
922 a->link->manager->llmnr_host_ipv6_key = dns_resource_key_new(DNS_CLASS_IN, DNS_TYPE_AAAA, a->link->manager->llmnr_hostname);
923 if (!a->link->manager->llmnr_host_ipv6_key) {
ec2c5e43
LP
924 r = -ENOMEM;
925 goto fail;
926 }
623a4c97 927 }
623a4c97 928
623a4c97 929 if (!a->llmnr_address_rr) {
78c6a153 930 a->llmnr_address_rr = dns_resource_record_new(a->link->manager->llmnr_host_ipv6_key);
ec2c5e43
LP
931 if (!a->llmnr_address_rr) {
932 r = -ENOMEM;
933 goto fail;
934 }
935
936 a->llmnr_address_rr->aaaa.in6_addr = a->in_addr.in6;
937 a->llmnr_address_rr->ttl = LLMNR_DEFAULT_TTL;
623a4c97
LP
938 }
939
ec2c5e43 940 if (!a->llmnr_ptr_rr) {
78c6a153 941 r = dns_resource_record_new_reverse(&a->llmnr_ptr_rr, a->family, &a->in_addr, a->link->manager->llmnr_hostname);
ec2c5e43
LP
942 if (r < 0)
943 goto fail;
623a4c97 944
ec2c5e43
LP
945 a->llmnr_ptr_rr->ttl = LLMNR_DEFAULT_TTL;
946 }
623a4c97 947
ec2c5e43 948 r = dns_zone_put(&a->link->llmnr_ipv6_scope->zone, a->link->llmnr_ipv6_scope, a->llmnr_address_rr, true);
623a4c97 949 if (r < 0)
da927ba9 950 log_warning_errno(r, "Failed to add AAAA record to LLMNR zone: %m");
623a4c97 951
ec2c5e43 952 r = dns_zone_put(&a->link->llmnr_ipv6_scope->zone, a->link->llmnr_ipv6_scope, a->llmnr_ptr_rr, false);
623a4c97 953 if (r < 0)
da927ba9 954 log_warning_errno(r, "Failed to add IPv6 PTR record to LLMNR zone: %m");
623a4c97 955 } else {
ec2c5e43
LP
956 if (a->llmnr_address_rr) {
957 if (a->link->llmnr_ipv6_scope)
958 dns_zone_remove_rr(&a->link->llmnr_ipv6_scope->zone, a->llmnr_address_rr);
959 a->llmnr_address_rr = dns_resource_record_unref(a->llmnr_address_rr);
960 }
961
962 if (a->llmnr_ptr_rr) {
963 if (a->link->llmnr_ipv6_scope)
964 dns_zone_remove_rr(&a->link->llmnr_ipv6_scope->zone, a->llmnr_ptr_rr);
965 a->llmnr_ptr_rr = dns_resource_record_unref(a->llmnr_ptr_rr);
966 }
623a4c97 967 }
400cb36e
DR
968
969 if (!force_remove &&
970 link_address_relevant(a, true) &&
971 a->link->mdns_ipv6_scope &&
972 a->link->mdns_support == RESOLVE_SUPPORT_YES &&
973 a->link->manager->mdns_support == RESOLVE_SUPPORT_YES) {
974
975 if (!a->link->manager->mdns_host_ipv6_key) {
976 a->link->manager->mdns_host_ipv6_key = dns_resource_key_new(DNS_CLASS_IN, DNS_TYPE_AAAA, a->link->manager->mdns_hostname);
977 if (!a->link->manager->mdns_host_ipv6_key) {
978 r = -ENOMEM;
979 goto fail;
980 }
981 }
982
983 if (!a->mdns_address_rr) {
984 a->mdns_address_rr = dns_resource_record_new(a->link->manager->mdns_host_ipv6_key);
985 if (!a->mdns_address_rr) {
986 r = -ENOMEM;
987 goto fail;
988 }
989
990 a->mdns_address_rr->aaaa.in6_addr = a->in_addr.in6;
991 a->mdns_address_rr->ttl = MDNS_DEFAULT_TTL;
992 }
993
994 if (!a->mdns_ptr_rr) {
995 r = dns_resource_record_new_reverse(&a->mdns_ptr_rr, a->family, &a->in_addr, a->link->manager->mdns_hostname);
996 if (r < 0)
997 goto fail;
998
999 a->mdns_ptr_rr->ttl = MDNS_DEFAULT_TTL;
1000 }
1001
1002 r = dns_zone_put(&a->link->mdns_ipv6_scope->zone, a->link->mdns_ipv6_scope, a->mdns_address_rr, true);
1003 if (r < 0)
1004 log_warning_errno(r, "Failed to add AAAA record to MDNS zone: %m");
1005
1006 r = dns_zone_put(&a->link->mdns_ipv6_scope->zone, a->link->mdns_ipv6_scope, a->mdns_ptr_rr, false);
1007 if (r < 0)
1008 log_warning_errno(r, "Failed to add IPv6 PTR record to MDNS zone: %m");
1009 } else {
1010 if (a->mdns_address_rr) {
1011 if (a->link->mdns_ipv6_scope)
1012 dns_zone_remove_rr(&a->link->mdns_ipv6_scope->zone, a->mdns_address_rr);
1013 a->mdns_address_rr = dns_resource_record_unref(a->mdns_address_rr);
1014 }
1015
1016 if (a->mdns_ptr_rr) {
1017 if (a->link->mdns_ipv6_scope)
1018 dns_zone_remove_rr(&a->link->mdns_ipv6_scope->zone, a->mdns_ptr_rr);
1019 a->mdns_ptr_rr = dns_resource_record_unref(a->mdns_ptr_rr);
1020 }
1021 }
623a4c97
LP
1022 }
1023
1024 return;
1025
1026fail:
da927ba9 1027 log_debug_errno(r, "Failed to update address RRs: %m");
623a4c97
LP
1028}
1029
1c4baffc 1030int link_address_update_rtnl(LinkAddress *a, sd_netlink_message *m) {
74b2466e
LP
1031 int r;
1032 assert(a);
1033 assert(m);
1034
1035 r = sd_rtnl_message_addr_get_flags(m, &a->flags);
1036 if (r < 0)
1037 return r;
1038
1716f6dc 1039 sd_rtnl_message_addr_get_scope(m, &a->scope);
74b2466e 1040
1716f6dc 1041 link_allocate_scopes(a->link);
ec2c5e43 1042 link_add_rrs(a->link, false);
623a4c97 1043
74b2466e
LP
1044 return 0;
1045}
1046
011696f7 1047bool link_address_relevant(LinkAddress *a, bool local_multicast) {
74b2466e
LP
1048 assert(a);
1049
7b85d72f 1050 if (a->flags & (IFA_F_DEPRECATED|IFA_F_TENTATIVE))
74b2466e
LP
1051 return false;
1052
011696f7 1053 if (a->scope >= (local_multicast ? RT_SCOPE_HOST : RT_SCOPE_LINK))
74b2466e
LP
1054 return false;
1055
1056 return true;
1057}
943ef07c
LP
1058
1059static bool link_needs_save(Link *l) {
1060 assert(l);
1061
1062 /* Returns true if any of the settings where set different from the default */
1063
1064 if (l->is_managed)
1065 return false;
1066
1067 if (l->llmnr_support != RESOLVE_SUPPORT_YES ||
1068 l->mdns_support != RESOLVE_SUPPORT_NO ||
1069 l->dnssec_mode != _DNSSEC_MODE_INVALID)
1070 return true;
1071
1072 if (l->dns_servers ||
1073 l->search_domains)
1074 return true;
1075
1076 if (!set_isempty(l->dnssec_negative_trust_anchors))
1077 return true;
1078
1079 return false;
1080}
1081
1082int link_save_user(Link *l) {
1083 _cleanup_free_ char *temp_path = NULL;
1084 _cleanup_fclose_ FILE *f = NULL;
1085 const char *v;
1086 int r;
1087
1088 assert(l);
1089 assert(l->state_file);
1090
1091 if (!link_needs_save(l)) {
1092 (void) unlink(l->state_file);
1093 return 0;
1094 }
1095
1096 r = mkdir_parents(l->state_file, 0700);
1097 if (r < 0)
1098 goto fail;
1099
1100 r = fopen_temporary(l->state_file, &f, &temp_path);
1101 if (r < 0)
1102 goto fail;
1103
0d536673
LP
1104 (void) __fsetlocking(f, FSETLOCKING_BYCALLER);
1105 (void) fchmod(fileno(f), 0644);
1106
1107 fputs("# This is private data. Do not parse.\n", f);
943ef07c
LP
1108
1109 v = resolve_support_to_string(l->llmnr_support);
1110 if (v)
1111 fprintf(f, "LLMNR=%s\n", v);
1112
1113 v = resolve_support_to_string(l->mdns_support);
1114 if (v)
1115 fprintf(f, "MDNS=%s\n", v);
1116
1117 v = dnssec_mode_to_string(l->dnssec_mode);
1118 if (v)
1119 fprintf(f, "DNSSEC=%s\n", v);
1120
1121 if (l->dns_servers) {
1122 DnsServer *server;
1123
0d536673 1124 fputs("SERVERS=", f);
943ef07c
LP
1125 LIST_FOREACH(servers, server, l->dns_servers) {
1126
1127 if (server != l->dns_servers)
0d536673 1128 fputc(' ', f);
943ef07c
LP
1129
1130 v = dns_server_string(server);
1131 if (!v) {
1132 r = -ENOMEM;
1133 goto fail;
1134 }
1135
0d536673 1136 fputs(v, f);
943ef07c 1137 }
0d536673 1138 fputc('\n', f);
943ef07c
LP
1139 }
1140
1141 if (l->search_domains) {
1142 DnsSearchDomain *domain;
1143
0d536673 1144 fputs("DOMAINS=", f);
943ef07c
LP
1145 LIST_FOREACH(domains, domain, l->search_domains) {
1146
1147 if (domain != l->search_domains)
0d536673 1148 fputc(' ', f);
943ef07c
LP
1149
1150 if (domain->route_only)
0d536673 1151 fputc('~', f);
943ef07c 1152
0d536673 1153 fputs(DNS_SEARCH_DOMAIN_NAME(domain), f);
943ef07c 1154 }
0d536673 1155 fputc('\n', f);
943ef07c
LP
1156 }
1157
1158 if (!set_isempty(l->dnssec_negative_trust_anchors)) {
1159 bool space = false;
1160 Iterator i;
1161 char *nta;
1162
0d536673 1163 fputs("NTAS=", f);
943ef07c
LP
1164 SET_FOREACH(nta, l->dnssec_negative_trust_anchors, i) {
1165
1166 if (space)
0d536673 1167 fputc(' ', f);
943ef07c 1168
0d536673 1169 fputs(nta, f);
943ef07c
LP
1170 space = true;
1171 }
0d536673 1172 fputc('\n', f);
943ef07c
LP
1173 }
1174
1175 r = fflush_and_check(f);
1176 if (r < 0)
1177 goto fail;
1178
1179 if (rename(temp_path, l->state_file) < 0) {
1180 r = -errno;
1181 goto fail;
1182 }
1183
1184 return 0;
1185
1186fail:
1187 (void) unlink(l->state_file);
1188
1189 if (temp_path)
1190 (void) unlink(temp_path);
1191
1192 return log_error_errno(r, "Failed to save link data %s: %m", l->state_file);
1193}
1194
1195int link_load_user(Link *l) {
1196 _cleanup_free_ char
1197 *llmnr = NULL,
1198 *mdns = NULL,
1199 *dnssec = NULL,
1200 *servers = NULL,
1201 *domains = NULL,
1202 *ntas = NULL;
1203
1204 ResolveSupport s;
c58bd76a 1205 const char *p;
943ef07c
LP
1206 int r;
1207
1208 assert(l);
1209 assert(l->state_file);
1210
1211 /* Try to load only a single time */
1212 if (l->loaded)
1213 return 0;
1214 l->loaded = true;
1215
1216 if (l->is_managed)
1217 return 0; /* if the device is managed, then networkd is our configuration source, not the bus API */
1218
1219 r = parse_env_file(l->state_file, NEWLINE,
1220 "LLMNR", &llmnr,
1221 "MDNS", &mdns,
1222 "DNSSEC", &dnssec,
1223 "SERVERS", &servers,
1224 "DOMAINS", &domains,
1225 "NTAS", &ntas,
1226 NULL);
1227 if (r == -ENOENT)
1228 return 0;
1229 if (r < 0)
1230 goto fail;
1231
1232 link_flush_settings(l);
1233
1234 /* If we can't recognize the LLMNR or MDNS setting we don't override the default */
1235 s = resolve_support_from_string(llmnr);
1236 if (s >= 0)
1237 l->llmnr_support = s;
1238
1239 s = resolve_support_from_string(mdns);
1240 if (s >= 0)
1241 l->mdns_support = s;
1242
1243 /* If we can't recognize the DNSSEC setting, then set it to invalid, so that the daemon default is used. */
1244 l->dnssec_mode = dnssec_mode_from_string(dnssec);
1245
c58bd76a
ZJS
1246 for (p = servers;;) {
1247 _cleanup_free_ char *word = NULL;
943ef07c 1248
c58bd76a
ZJS
1249 r = extract_first_word(&p, &word, NULL, 0);
1250 if (r < 0)
1251 goto fail;
1252 if (r == 0)
1253 break;
943ef07c 1254
c58bd76a
ZJS
1255 r = link_update_dns_server_one(l, word);
1256 if (r < 0) {
1257 log_debug_errno(r, "Failed to load DNS server '%s', ignoring: %m", word);
1258 continue;
943ef07c
LP
1259 }
1260 }
1261
c58bd76a
ZJS
1262 for (p = domains;;) {
1263 _cleanup_free_ char *word = NULL;
1264 const char *n;
1265 bool is_route;
943ef07c 1266
c58bd76a
ZJS
1267 r = extract_first_word(&p, &word, NULL, 0);
1268 if (r < 0)
1269 goto fail;
1270 if (r == 0)
1271 break;
943ef07c 1272
c58bd76a
ZJS
1273 is_route = word[0] == '~';
1274 n = is_route ? word + 1 : word;
943ef07c 1275
c58bd76a
ZJS
1276 r = link_update_search_domain_one(l, n, is_route);
1277 if (r < 0) {
1278 log_debug_errno(r, "Failed to load search domain '%s', ignoring: %m", word);
1279 continue;
943ef07c
LP
1280 }
1281 }
1282
1283 if (ntas) {
1284 _cleanup_set_free_free_ Set *ns = NULL;
1285
1286 ns = set_new(&dns_name_hash_ops);
1287 if (!ns) {
1288 r = -ENOMEM;
1289 goto fail;
1290 }
1291
1292 r = set_put_strsplit(ns, ntas, NULL, 0);
1293 if (r < 0)
1294 goto fail;
1295
1296 l->dnssec_negative_trust_anchors = ns;
1297 ns = NULL;
1298 }
1299
1300 return 0;
1301
1302fail:
1303 return log_error_errno(r, "Failed to load link data %s: %m", l->state_file);
1304}
1305
1306void link_remove_user(Link *l) {
1307 assert(l);
1308 assert(l->state_file);
1309
1310 (void) unlink(l->state_file);
1311}