]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/resolve/resolved-link.c
macro: introduce TAKE_PTR() macro
[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);
ae2a15bc 443 l->dnssec_negative_trust_anchors = TAKE_PTR(ns);
8a516214
LP
444
445 return 0;
446
447clear:
448 l->dnssec_negative_trust_anchors = set_free_free(l->dnssec_negative_trust_anchors);
449 return r;
450}
451
ad44b56b
LP
452static int link_update_search_domain_one(Link *l, const char *name, bool route_only) {
453 DnsSearchDomain *d;
454 int r;
455
39f259e0
LP
456 assert(l);
457 assert(name);
458
ad44b56b
LP
459 r = dns_search_domain_find(l->search_domains, name, &d);
460 if (r < 0)
461 return r;
462 if (r > 0)
463 dns_search_domain_move_back_and_unmark(d);
464 else {
465 r = dns_search_domain_new(l->manager, &d, DNS_SEARCH_DOMAIN_LINK, l, name);
466 if (r < 0)
467 return r;
468 }
469
470 d->route_only = route_only;
471 return 0;
472}
473
a51c1048 474static int link_update_search_domains(Link *l) {
ad44b56b 475 _cleanup_strv_free_ char **sdomains = NULL, **rdomains = NULL;
a51c1048 476 char **i;
ad44b56b 477 int r, q;
bda2c408 478
a51c1048 479 assert(l);
bda2c408 480
ad44b56b
LP
481 r = sd_network_link_get_search_domains(l->ifindex, &sdomains);
482 if (r < 0 && r != -ENODATA)
483 goto clear;
484
485 q = sd_network_link_get_route_domains(l->ifindex, &rdomains);
486 if (q < 0 && q != -ENODATA) {
487 r = q;
488 goto clear;
489 }
490
491 if (r == -ENODATA && q == -ENODATA) {
1ade96e9
LP
492 /* networkd knows nothing about this interface, and that's fine. */
493 r = 0;
494 goto clear;
495 }
a51c1048
LP
496
497 dns_search_domain_mark_all(l->search_domains);
498
ad44b56b
LP
499 STRV_FOREACH(i, sdomains) {
500 r = link_update_search_domain_one(l, *i, false);
a51c1048
LP
501 if (r < 0)
502 goto clear;
ad44b56b 503 }
a51c1048 504
ad44b56b
LP
505 STRV_FOREACH(i, rdomains) {
506 r = link_update_search_domain_one(l, *i, true);
507 if (r < 0)
508 goto clear;
a51c1048
LP
509 }
510
511 dns_search_domain_unlink_marked(l->search_domains);
bda2c408 512 return 0;
a51c1048
LP
513
514clear:
515 dns_search_domain_unlink_all(l->search_domains);
516 return r;
bda2c408
TG
517}
518
b6274a0e 519static int link_is_managed(Link *l) {
97e5d693 520 _cleanup_free_ char *state = NULL;
a51c1048
LP
521 int r;
522
74b2466e
LP
523 assert(l);
524
97e5d693
LP
525 r = sd_network_link_get_setup_state(l->ifindex, &state);
526 if (r == -ENODATA)
b6274a0e 527 return 0;
97e5d693
LP
528 if (r < 0)
529 return r;
530
b6274a0e 531 return !STR_IN_SET(state, "pending", "unmanaged");
97e5d693
LP
532}
533
534static void link_read_settings(Link *l) {
535 int r;
536
537 assert(l);
538
539 /* Read settings from networkd, except when networkd is not managing this interface. */
540
b6274a0e 541 r = link_is_managed(l);
97e5d693
LP
542 if (r < 0) {
543 log_warning_errno(r, "Failed to determine whether interface %s is managed: %m", l->name);
544 return;
545 }
b6274a0e 546 if (r == 0) {
97e5d693 547
ccddd104 548 /* If this link used to be managed, but is now unmanaged, flush all our settings — but only once. */
97e5d693
LP
549 if (l->is_managed)
550 link_flush_settings(l);
551
552 l->is_managed = false;
553 return;
554 }
555
556 l->is_managed = true;
557
125ae29d
LP
558 r = link_update_dns_servers(l);
559 if (r < 0)
560 log_warning_errno(r, "Failed to read DNS servers for interface %s, ignoring: %m", l->name);
561
562 r = link_update_llmnr_support(l);
563 if (r < 0)
564 log_warning_errno(r, "Failed to read LLMNR support for interface %s, ignoring: %m", l->name);
565
566 r = link_update_mdns_support(l);
567 if (r < 0)
568 log_warning_errno(r, "Failed to read mDNS support for interface %s, ignoring: %m", l->name);
569
ad6c0475
LP
570 r = link_update_dnssec_mode(l);
571 if (r < 0)
572 log_warning_errno(r, "Failed to read DNSSEC mode for interface %s, ignoring: %m", l->name);
a51c1048 573
8a516214
LP
574 r = link_update_dnssec_negative_trust_anchors(l);
575 if (r < 0)
576 log_warning_errno(r, "Failed to read DNSSEC negative trust anchors for interface %s, ignoring: %m", l->name);
577
a51c1048
LP
578 r = link_update_search_domains(l);
579 if (r < 0)
580 log_warning_errno(r, "Failed to read search domains for interface %s, ignoring: %m", l->name);
97e5d693
LP
581}
582
943ef07c 583int link_update(Link *l) {
c6a8f6f6
YW
584 int r;
585
97e5d693 586 assert(l);
a51c1048 587
97e5d693 588 link_read_settings(l);
943ef07c 589 link_load_user(l);
c6a8f6f6
YW
590
591 if (l->llmnr_support != RESOLVE_SUPPORT_NO) {
592 r = manager_llmnr_start(l->manager);
593 if (r < 0)
594 return r;
595 }
596
597 if (l->mdns_support != RESOLVE_SUPPORT_NO) {
598 r = manager_mdns_start(l->manager);
599 if (r < 0)
600 return r;
601 }
602
ad6c0475 603 link_allocate_scopes(l);
ec2c5e43 604 link_add_rrs(l, false);
74b2466e
LP
605
606 return 0;
607}
608
011696f7 609bool link_relevant(Link *l, int family, bool local_multicast) {
1716f6dc 610 _cleanup_free_ char *state = NULL;
74b2466e
LP
611 LinkAddress *a;
612
613 assert(l);
614
c1edab7a 615 /* A link is relevant for local multicast traffic if it isn't a loopback device, has a link
011696f7
LP
616 * beat, can do multicast and has at least one link-local (or better) IP address.
617 *
618 * A link is relevant for non-multicast traffic if it isn't a loopback device, has a link beat, and has at
13e785f7 619 * least one routable address. */
ec2c5e43 620
dfc1091b 621 if (l->flags & (IFF_LOOPBACK|IFF_DORMANT))
ec2c5e43 622 return false;
74b2466e 623
dfc1091b 624 if ((l->flags & (IFF_UP|IFF_LOWER_UP)) != (IFF_UP|IFF_LOWER_UP))
74b2466e
LP
625 return false;
626
011696f7 627 if (local_multicast) {
dfc1091b
LP
628 if ((l->flags & IFF_MULTICAST) != IFF_MULTICAST)
629 return false;
630 }
631
6955a3ba
LP
632 /* Check kernel operstate
633 * https://www.kernel.org/doc/Documentation/networking/operstates.txt */
634 if (!IN_SET(l->operstate, IF_OPER_UNKNOWN, IF_OPER_UP))
635 return false;
636
637 (void) sd_network_link_get_operational_state(l->ifindex, &state);
1716f6dc 638 if (state && !STR_IN_SET(state, "unknown", "degraded", "routable"))
74b2466e
LP
639 return false;
640
641 LIST_FOREACH(addresses, a, l->addresses)
011696f7 642 if ((family == AF_UNSPEC || a->family == family) && link_address_relevant(a, local_multicast))
74b2466e
LP
643 return true;
644
645 return false;
646}
647
623a4c97 648LinkAddress *link_find_address(Link *l, int family, const union in_addr_union *in_addr) {
74b2466e
LP
649 LinkAddress *a;
650
651 assert(l);
652
1716f6dc
LP
653 LIST_FOREACH(addresses, a, l->addresses)
654 if (a->family == family && in_addr_equal(family, &a->in_addr, in_addr))
74b2466e 655 return a;
74b2466e
LP
656
657 return NULL;
658}
659
2c27fbca 660DnsServer* link_set_dns_server(Link *l, DnsServer *s) {
4e945a6f
LP
661 assert(l);
662
663 if (l->current_dns_server == s)
664 return s;
665
6cb08a89 666 if (s)
db8e1324 667 log_debug("Switching to DNS server %s for interface %s.", dns_server_string(s), l->name);
4e945a6f 668
0eac4623
LP
669 dns_server_unref(l->current_dns_server);
670 l->current_dns_server = dns_server_ref(s);
2c27fbca
LP
671
672 if (l->unicast_scope)
673 dns_cache_flush(&l->unicast_scope->cache);
674
4e945a6f
LP
675 return s;
676}
677
74b2466e
LP
678DnsServer *link_get_dns_server(Link *l) {
679 assert(l);
680
681 if (!l->current_dns_server)
4e945a6f 682 link_set_dns_server(l, l->dns_servers);
74b2466e
LP
683
684 return l->current_dns_server;
685}
686
687void link_next_dns_server(Link *l) {
688 assert(l);
689
74b2466e
LP
690 if (!l->current_dns_server)
691 return;
692
0eac4623
LP
693 /* Change to the next one, but make sure to follow the linked
694 * list only if this server is actually still linked. */
695 if (l->current_dns_server->linked && l->current_dns_server->servers_next) {
4e945a6f 696 link_set_dns_server(l, l->current_dns_server->servers_next);
74b2466e
LP
697 return;
698 }
699
4e945a6f 700 link_set_dns_server(l, l->dns_servers);
74b2466e
LP
701}
702
c69fa7e3
LP
703DnssecMode link_get_dnssec_mode(Link *l) {
704 assert(l);
705
706 if (l->dnssec_mode != _DNSSEC_MODE_INVALID)
707 return l->dnssec_mode;
708
709 return manager_get_dnssec_mode(l->manager);
710}
711
712bool link_dnssec_supported(Link *l) {
713 DnsServer *server;
714
715 assert(l);
716
717 if (link_get_dnssec_mode(l) == DNSSEC_NO)
718 return false;
719
720 server = link_get_dns_server(l);
721 if (server)
722 return dns_server_dnssec_supported(server);
723
724 return true;
725}
726
623a4c97 727int link_address_new(Link *l, LinkAddress **ret, int family, const union in_addr_union *in_addr) {
74b2466e
LP
728 LinkAddress *a;
729
730 assert(l);
731 assert(in_addr);
732
733 a = new0(LinkAddress, 1);
734 if (!a)
735 return -ENOMEM;
736
737 a->family = family;
738 a->in_addr = *in_addr;
739
740 a->link = l;
741 LIST_PREPEND(addresses, l->addresses, a);
bceaa99d 742 l->n_addresses++;
74b2466e
LP
743
744 if (ret)
745 *ret = a;
746
747 return 0;
748}
749
750LinkAddress *link_address_free(LinkAddress *a) {
751 if (!a)
752 return NULL;
753
623a4c97 754 if (a->link) {
74b2466e
LP
755 LIST_REMOVE(addresses, a->link->addresses, a);
756
bceaa99d
LP
757 assert(a->link->n_addresses > 0);
758 a->link->n_addresses--;
759
623a4c97 760 if (a->llmnr_address_rr) {
623a4c97
LP
761 if (a->family == AF_INET && a->link->llmnr_ipv4_scope)
762 dns_zone_remove_rr(&a->link->llmnr_ipv4_scope->zone, a->llmnr_address_rr);
763 else if (a->family == AF_INET6 && a->link->llmnr_ipv6_scope)
764 dns_zone_remove_rr(&a->link->llmnr_ipv6_scope->zone, a->llmnr_address_rr);
623a4c97
LP
765 }
766
767 if (a->llmnr_ptr_rr) {
768 if (a->family == AF_INET && a->link->llmnr_ipv4_scope)
769 dns_zone_remove_rr(&a->link->llmnr_ipv4_scope->zone, a->llmnr_ptr_rr);
770 else if (a->family == AF_INET6 && a->link->llmnr_ipv6_scope)
771 dns_zone_remove_rr(&a->link->llmnr_ipv6_scope->zone, a->llmnr_ptr_rr);
623a4c97 772 }
400cb36e
DR
773
774 if (a->mdns_address_rr) {
775 if (a->family == AF_INET && a->link->mdns_ipv4_scope)
776 dns_zone_remove_rr(&a->link->mdns_ipv4_scope->zone, a->mdns_address_rr);
777 else if (a->family == AF_INET6 && a->link->mdns_ipv6_scope)
778 dns_zone_remove_rr(&a->link->mdns_ipv6_scope->zone, a->mdns_address_rr);
779 }
780
781 if (a->mdns_ptr_rr) {
782 if (a->family == AF_INET && a->link->mdns_ipv4_scope)
783 dns_zone_remove_rr(&a->link->mdns_ipv4_scope->zone, a->mdns_ptr_rr);
784 else if (a->family == AF_INET6 && a->link->mdns_ipv6_scope)
785 dns_zone_remove_rr(&a->link->mdns_ipv6_scope->zone, a->mdns_ptr_rr);
786 }
623a4c97
LP
787 }
788
ec2c5e43
LP
789 dns_resource_record_unref(a->llmnr_address_rr);
790 dns_resource_record_unref(a->llmnr_ptr_rr);
400cb36e
DR
791 dns_resource_record_unref(a->mdns_address_rr);
792 dns_resource_record_unref(a->mdns_ptr_rr);
ec2c5e43 793
6b430fdb 794 return mfree(a);
74b2466e
LP
795}
796
ec2c5e43 797void link_address_add_rrs(LinkAddress *a, bool force_remove) {
623a4c97
LP
798 int r;
799
800 assert(a);
801
ec2c5e43 802 if (a->family == AF_INET) {
623a4c97 803
4e945a6f 804 if (!force_remove &&
011696f7 805 link_address_relevant(a, true) &&
4e945a6f 806 a->link->llmnr_ipv4_scope &&
af49ca27
LP
807 a->link->llmnr_support == RESOLVE_SUPPORT_YES &&
808 a->link->manager->llmnr_support == RESOLVE_SUPPORT_YES) {
4e945a6f 809
78c6a153
LP
810 if (!a->link->manager->llmnr_host_ipv4_key) {
811 a->link->manager->llmnr_host_ipv4_key = dns_resource_key_new(DNS_CLASS_IN, DNS_TYPE_A, a->link->manager->llmnr_hostname);
812 if (!a->link->manager->llmnr_host_ipv4_key) {
ec2c5e43
LP
813 r = -ENOMEM;
814 goto fail;
815 }
623a4c97 816 }
623a4c97 817
623a4c97 818 if (!a->llmnr_address_rr) {
78c6a153 819 a->llmnr_address_rr = dns_resource_record_new(a->link->manager->llmnr_host_ipv4_key);
ec2c5e43
LP
820 if (!a->llmnr_address_rr) {
821 r = -ENOMEM;
822 goto fail;
823 }
824
825 a->llmnr_address_rr->a.in_addr = a->in_addr.in;
826 a->llmnr_address_rr->ttl = LLMNR_DEFAULT_TTL;
623a4c97
LP
827 }
828
ec2c5e43 829 if (!a->llmnr_ptr_rr) {
78c6a153 830 r = dns_resource_record_new_reverse(&a->llmnr_ptr_rr, a->family, &a->in_addr, a->link->manager->llmnr_hostname);
ec2c5e43
LP
831 if (r < 0)
832 goto fail;
623a4c97 833
ec2c5e43
LP
834 a->llmnr_ptr_rr->ttl = LLMNR_DEFAULT_TTL;
835 }
623a4c97 836
ec2c5e43 837 r = dns_zone_put(&a->link->llmnr_ipv4_scope->zone, a->link->llmnr_ipv4_scope, a->llmnr_address_rr, true);
623a4c97 838 if (r < 0)
da927ba9 839 log_warning_errno(r, "Failed to add A record to LLMNR zone: %m");
623a4c97 840
ec2c5e43 841 r = dns_zone_put(&a->link->llmnr_ipv4_scope->zone, a->link->llmnr_ipv4_scope, a->llmnr_ptr_rr, false);
623a4c97 842 if (r < 0)
e372a138 843 log_warning_errno(r, "Failed to add IPv4 PTR record to LLMNR zone: %m");
623a4c97 844 } else {
ec2c5e43
LP
845 if (a->llmnr_address_rr) {
846 if (a->link->llmnr_ipv4_scope)
847 dns_zone_remove_rr(&a->link->llmnr_ipv4_scope->zone, a->llmnr_address_rr);
848 a->llmnr_address_rr = dns_resource_record_unref(a->llmnr_address_rr);
849 }
850
851 if (a->llmnr_ptr_rr) {
852 if (a->link->llmnr_ipv4_scope)
853 dns_zone_remove_rr(&a->link->llmnr_ipv4_scope->zone, a->llmnr_ptr_rr);
854 a->llmnr_ptr_rr = dns_resource_record_unref(a->llmnr_ptr_rr);
855 }
623a4c97 856 }
400cb36e
DR
857
858 if (!force_remove &&
859 link_address_relevant(a, true) &&
860 a->link->mdns_ipv4_scope &&
861 a->link->mdns_support == RESOLVE_SUPPORT_YES &&
862 a->link->manager->mdns_support == RESOLVE_SUPPORT_YES) {
863 if (!a->link->manager->mdns_host_ipv4_key) {
864 a->link->manager->mdns_host_ipv4_key = dns_resource_key_new(DNS_CLASS_IN, DNS_TYPE_A, a->link->manager->mdns_hostname);
865 if (!a->link->manager->mdns_host_ipv4_key) {
866 r = -ENOMEM;
867 goto fail;
868 }
869 }
870
871 if (!a->mdns_address_rr) {
872 a->mdns_address_rr = dns_resource_record_new(a->link->manager->mdns_host_ipv4_key);
873 if (!a->mdns_address_rr) {
874 r = -ENOMEM;
875 goto fail;
876 }
877
878 a->mdns_address_rr->a.in_addr = a->in_addr.in;
879 a->mdns_address_rr->ttl = MDNS_DEFAULT_TTL;
880 }
881
882 if (!a->mdns_ptr_rr) {
883 r = dns_resource_record_new_reverse(&a->mdns_ptr_rr, a->family, &a->in_addr, a->link->manager->mdns_hostname);
884 if (r < 0)
885 goto fail;
886
887 a->mdns_ptr_rr->ttl = MDNS_DEFAULT_TTL;
888 }
889
890 r = dns_zone_put(&a->link->mdns_ipv4_scope->zone, a->link->mdns_ipv4_scope, a->mdns_address_rr, true);
891 if (r < 0)
892 log_warning_errno(r, "Failed to add A record to MDNS zone: %m");
893
894 r = dns_zone_put(&a->link->mdns_ipv4_scope->zone, a->link->mdns_ipv4_scope, a->mdns_ptr_rr, false);
895 if (r < 0)
896 log_warning_errno(r, "Failed to add IPv4 PTR record to MDNS zone: %m");
897 } else {
898 if (a->mdns_address_rr) {
899 if (a->link->mdns_ipv4_scope)
900 dns_zone_remove_rr(&a->link->mdns_ipv4_scope->zone, a->mdns_address_rr);
901 a->mdns_address_rr = dns_resource_record_unref(a->mdns_address_rr);
902 }
903
904 if (a->mdns_ptr_rr) {
905 if (a->link->mdns_ipv4_scope)
906 dns_zone_remove_rr(&a->link->mdns_ipv4_scope->zone, a->mdns_ptr_rr);
907 a->mdns_ptr_rr = dns_resource_record_unref(a->mdns_ptr_rr);
908 }
909 }
623a4c97
LP
910 }
911
ec2c5e43 912 if (a->family == AF_INET6) {
623a4c97 913
4e945a6f 914 if (!force_remove &&
011696f7 915 link_address_relevant(a, true) &&
4e945a6f 916 a->link->llmnr_ipv6_scope &&
af49ca27
LP
917 a->link->llmnr_support == RESOLVE_SUPPORT_YES &&
918 a->link->manager->llmnr_support == RESOLVE_SUPPORT_YES) {
4e945a6f 919
78c6a153
LP
920 if (!a->link->manager->llmnr_host_ipv6_key) {
921 a->link->manager->llmnr_host_ipv6_key = dns_resource_key_new(DNS_CLASS_IN, DNS_TYPE_AAAA, a->link->manager->llmnr_hostname);
922 if (!a->link->manager->llmnr_host_ipv6_key) {
ec2c5e43
LP
923 r = -ENOMEM;
924 goto fail;
925 }
623a4c97 926 }
623a4c97 927
623a4c97 928 if (!a->llmnr_address_rr) {
78c6a153 929 a->llmnr_address_rr = dns_resource_record_new(a->link->manager->llmnr_host_ipv6_key);
ec2c5e43
LP
930 if (!a->llmnr_address_rr) {
931 r = -ENOMEM;
932 goto fail;
933 }
934
935 a->llmnr_address_rr->aaaa.in6_addr = a->in_addr.in6;
936 a->llmnr_address_rr->ttl = LLMNR_DEFAULT_TTL;
623a4c97
LP
937 }
938
ec2c5e43 939 if (!a->llmnr_ptr_rr) {
78c6a153 940 r = dns_resource_record_new_reverse(&a->llmnr_ptr_rr, a->family, &a->in_addr, a->link->manager->llmnr_hostname);
ec2c5e43
LP
941 if (r < 0)
942 goto fail;
623a4c97 943
ec2c5e43
LP
944 a->llmnr_ptr_rr->ttl = LLMNR_DEFAULT_TTL;
945 }
623a4c97 946
ec2c5e43 947 r = dns_zone_put(&a->link->llmnr_ipv6_scope->zone, a->link->llmnr_ipv6_scope, a->llmnr_address_rr, true);
623a4c97 948 if (r < 0)
da927ba9 949 log_warning_errno(r, "Failed to add AAAA record to LLMNR zone: %m");
623a4c97 950
ec2c5e43 951 r = dns_zone_put(&a->link->llmnr_ipv6_scope->zone, a->link->llmnr_ipv6_scope, a->llmnr_ptr_rr, false);
623a4c97 952 if (r < 0)
da927ba9 953 log_warning_errno(r, "Failed to add IPv6 PTR record to LLMNR zone: %m");
623a4c97 954 } else {
ec2c5e43
LP
955 if (a->llmnr_address_rr) {
956 if (a->link->llmnr_ipv6_scope)
957 dns_zone_remove_rr(&a->link->llmnr_ipv6_scope->zone, a->llmnr_address_rr);
958 a->llmnr_address_rr = dns_resource_record_unref(a->llmnr_address_rr);
959 }
960
961 if (a->llmnr_ptr_rr) {
962 if (a->link->llmnr_ipv6_scope)
963 dns_zone_remove_rr(&a->link->llmnr_ipv6_scope->zone, a->llmnr_ptr_rr);
964 a->llmnr_ptr_rr = dns_resource_record_unref(a->llmnr_ptr_rr);
965 }
623a4c97 966 }
400cb36e
DR
967
968 if (!force_remove &&
969 link_address_relevant(a, true) &&
970 a->link->mdns_ipv6_scope &&
971 a->link->mdns_support == RESOLVE_SUPPORT_YES &&
972 a->link->manager->mdns_support == RESOLVE_SUPPORT_YES) {
973
974 if (!a->link->manager->mdns_host_ipv6_key) {
975 a->link->manager->mdns_host_ipv6_key = dns_resource_key_new(DNS_CLASS_IN, DNS_TYPE_AAAA, a->link->manager->mdns_hostname);
976 if (!a->link->manager->mdns_host_ipv6_key) {
977 r = -ENOMEM;
978 goto fail;
979 }
980 }
981
982 if (!a->mdns_address_rr) {
983 a->mdns_address_rr = dns_resource_record_new(a->link->manager->mdns_host_ipv6_key);
984 if (!a->mdns_address_rr) {
985 r = -ENOMEM;
986 goto fail;
987 }
988
989 a->mdns_address_rr->aaaa.in6_addr = a->in_addr.in6;
990 a->mdns_address_rr->ttl = MDNS_DEFAULT_TTL;
991 }
992
993 if (!a->mdns_ptr_rr) {
994 r = dns_resource_record_new_reverse(&a->mdns_ptr_rr, a->family, &a->in_addr, a->link->manager->mdns_hostname);
995 if (r < 0)
996 goto fail;
997
998 a->mdns_ptr_rr->ttl = MDNS_DEFAULT_TTL;
999 }
1000
1001 r = dns_zone_put(&a->link->mdns_ipv6_scope->zone, a->link->mdns_ipv6_scope, a->mdns_address_rr, true);
1002 if (r < 0)
1003 log_warning_errno(r, "Failed to add AAAA record to MDNS zone: %m");
1004
1005 r = dns_zone_put(&a->link->mdns_ipv6_scope->zone, a->link->mdns_ipv6_scope, a->mdns_ptr_rr, false);
1006 if (r < 0)
1007 log_warning_errno(r, "Failed to add IPv6 PTR record to MDNS zone: %m");
1008 } else {
1009 if (a->mdns_address_rr) {
1010 if (a->link->mdns_ipv6_scope)
1011 dns_zone_remove_rr(&a->link->mdns_ipv6_scope->zone, a->mdns_address_rr);
1012 a->mdns_address_rr = dns_resource_record_unref(a->mdns_address_rr);
1013 }
1014
1015 if (a->mdns_ptr_rr) {
1016 if (a->link->mdns_ipv6_scope)
1017 dns_zone_remove_rr(&a->link->mdns_ipv6_scope->zone, a->mdns_ptr_rr);
1018 a->mdns_ptr_rr = dns_resource_record_unref(a->mdns_ptr_rr);
1019 }
1020 }
623a4c97
LP
1021 }
1022
1023 return;
1024
1025fail:
da927ba9 1026 log_debug_errno(r, "Failed to update address RRs: %m");
623a4c97
LP
1027}
1028
1c4baffc 1029int link_address_update_rtnl(LinkAddress *a, sd_netlink_message *m) {
74b2466e
LP
1030 int r;
1031 assert(a);
1032 assert(m);
1033
1034 r = sd_rtnl_message_addr_get_flags(m, &a->flags);
1035 if (r < 0)
1036 return r;
1037
1716f6dc 1038 sd_rtnl_message_addr_get_scope(m, &a->scope);
74b2466e 1039
1716f6dc 1040 link_allocate_scopes(a->link);
ec2c5e43 1041 link_add_rrs(a->link, false);
623a4c97 1042
74b2466e
LP
1043 return 0;
1044}
1045
011696f7 1046bool link_address_relevant(LinkAddress *a, bool local_multicast) {
74b2466e
LP
1047 assert(a);
1048
7b85d72f 1049 if (a->flags & (IFA_F_DEPRECATED|IFA_F_TENTATIVE))
74b2466e
LP
1050 return false;
1051
011696f7 1052 if (a->scope >= (local_multicast ? RT_SCOPE_HOST : RT_SCOPE_LINK))
74b2466e
LP
1053 return false;
1054
1055 return true;
1056}
943ef07c
LP
1057
1058static bool link_needs_save(Link *l) {
1059 assert(l);
1060
1061 /* Returns true if any of the settings where set different from the default */
1062
1063 if (l->is_managed)
1064 return false;
1065
1066 if (l->llmnr_support != RESOLVE_SUPPORT_YES ||
1067 l->mdns_support != RESOLVE_SUPPORT_NO ||
1068 l->dnssec_mode != _DNSSEC_MODE_INVALID)
1069 return true;
1070
1071 if (l->dns_servers ||
1072 l->search_domains)
1073 return true;
1074
1075 if (!set_isempty(l->dnssec_negative_trust_anchors))
1076 return true;
1077
1078 return false;
1079}
1080
1081int link_save_user(Link *l) {
1082 _cleanup_free_ char *temp_path = NULL;
1083 _cleanup_fclose_ FILE *f = NULL;
1084 const char *v;
1085 int r;
1086
1087 assert(l);
1088 assert(l->state_file);
1089
1090 if (!link_needs_save(l)) {
1091 (void) unlink(l->state_file);
1092 return 0;
1093 }
1094
1095 r = mkdir_parents(l->state_file, 0700);
1096 if (r < 0)
1097 goto fail;
1098
1099 r = fopen_temporary(l->state_file, &f, &temp_path);
1100 if (r < 0)
1101 goto fail;
1102
0d536673
LP
1103 (void) __fsetlocking(f, FSETLOCKING_BYCALLER);
1104 (void) fchmod(fileno(f), 0644);
1105
1106 fputs("# This is private data. Do not parse.\n", f);
943ef07c
LP
1107
1108 v = resolve_support_to_string(l->llmnr_support);
1109 if (v)
1110 fprintf(f, "LLMNR=%s\n", v);
1111
1112 v = resolve_support_to_string(l->mdns_support);
1113 if (v)
1114 fprintf(f, "MDNS=%s\n", v);
1115
1116 v = dnssec_mode_to_string(l->dnssec_mode);
1117 if (v)
1118 fprintf(f, "DNSSEC=%s\n", v);
1119
1120 if (l->dns_servers) {
1121 DnsServer *server;
1122
0d536673 1123 fputs("SERVERS=", f);
943ef07c
LP
1124 LIST_FOREACH(servers, server, l->dns_servers) {
1125
1126 if (server != l->dns_servers)
0d536673 1127 fputc(' ', f);
943ef07c
LP
1128
1129 v = dns_server_string(server);
1130 if (!v) {
1131 r = -ENOMEM;
1132 goto fail;
1133 }
1134
0d536673 1135 fputs(v, f);
943ef07c 1136 }
0d536673 1137 fputc('\n', f);
943ef07c
LP
1138 }
1139
1140 if (l->search_domains) {
1141 DnsSearchDomain *domain;
1142
0d536673 1143 fputs("DOMAINS=", f);
943ef07c
LP
1144 LIST_FOREACH(domains, domain, l->search_domains) {
1145
1146 if (domain != l->search_domains)
0d536673 1147 fputc(' ', f);
943ef07c
LP
1148
1149 if (domain->route_only)
0d536673 1150 fputc('~', f);
943ef07c 1151
0d536673 1152 fputs(DNS_SEARCH_DOMAIN_NAME(domain), f);
943ef07c 1153 }
0d536673 1154 fputc('\n', f);
943ef07c
LP
1155 }
1156
1157 if (!set_isempty(l->dnssec_negative_trust_anchors)) {
1158 bool space = false;
1159 Iterator i;
1160 char *nta;
1161
0d536673 1162 fputs("NTAS=", f);
943ef07c
LP
1163 SET_FOREACH(nta, l->dnssec_negative_trust_anchors, i) {
1164
1165 if (space)
0d536673 1166 fputc(' ', f);
943ef07c 1167
0d536673 1168 fputs(nta, f);
943ef07c
LP
1169 space = true;
1170 }
0d536673 1171 fputc('\n', f);
943ef07c
LP
1172 }
1173
1174 r = fflush_and_check(f);
1175 if (r < 0)
1176 goto fail;
1177
1178 if (rename(temp_path, l->state_file) < 0) {
1179 r = -errno;
1180 goto fail;
1181 }
1182
1183 return 0;
1184
1185fail:
1186 (void) unlink(l->state_file);
1187
1188 if (temp_path)
1189 (void) unlink(temp_path);
1190
1191 return log_error_errno(r, "Failed to save link data %s: %m", l->state_file);
1192}
1193
1194int link_load_user(Link *l) {
1195 _cleanup_free_ char
1196 *llmnr = NULL,
1197 *mdns = NULL,
1198 *dnssec = NULL,
1199 *servers = NULL,
1200 *domains = NULL,
1201 *ntas = NULL;
1202
1203 ResolveSupport s;
c58bd76a 1204 const char *p;
943ef07c
LP
1205 int r;
1206
1207 assert(l);
1208 assert(l->state_file);
1209
1210 /* Try to load only a single time */
1211 if (l->loaded)
1212 return 0;
1213 l->loaded = true;
1214
1215 if (l->is_managed)
1216 return 0; /* if the device is managed, then networkd is our configuration source, not the bus API */
1217
1218 r = parse_env_file(l->state_file, NEWLINE,
1219 "LLMNR", &llmnr,
1220 "MDNS", &mdns,
1221 "DNSSEC", &dnssec,
1222 "SERVERS", &servers,
1223 "DOMAINS", &domains,
1224 "NTAS", &ntas,
1225 NULL);
1226 if (r == -ENOENT)
1227 return 0;
1228 if (r < 0)
1229 goto fail;
1230
1231 link_flush_settings(l);
1232
1233 /* If we can't recognize the LLMNR or MDNS setting we don't override the default */
1234 s = resolve_support_from_string(llmnr);
1235 if (s >= 0)
1236 l->llmnr_support = s;
1237
1238 s = resolve_support_from_string(mdns);
1239 if (s >= 0)
1240 l->mdns_support = s;
1241
1242 /* If we can't recognize the DNSSEC setting, then set it to invalid, so that the daemon default is used. */
1243 l->dnssec_mode = dnssec_mode_from_string(dnssec);
1244
c58bd76a
ZJS
1245 for (p = servers;;) {
1246 _cleanup_free_ char *word = NULL;
943ef07c 1247
c58bd76a
ZJS
1248 r = extract_first_word(&p, &word, NULL, 0);
1249 if (r < 0)
1250 goto fail;
1251 if (r == 0)
1252 break;
943ef07c 1253
c58bd76a
ZJS
1254 r = link_update_dns_server_one(l, word);
1255 if (r < 0) {
1256 log_debug_errno(r, "Failed to load DNS server '%s', ignoring: %m", word);
1257 continue;
943ef07c
LP
1258 }
1259 }
1260
c58bd76a
ZJS
1261 for (p = domains;;) {
1262 _cleanup_free_ char *word = NULL;
1263 const char *n;
1264 bool is_route;
943ef07c 1265
c58bd76a
ZJS
1266 r = extract_first_word(&p, &word, NULL, 0);
1267 if (r < 0)
1268 goto fail;
1269 if (r == 0)
1270 break;
943ef07c 1271
c58bd76a
ZJS
1272 is_route = word[0] == '~';
1273 n = is_route ? word + 1 : word;
943ef07c 1274
c58bd76a
ZJS
1275 r = link_update_search_domain_one(l, n, is_route);
1276 if (r < 0) {
1277 log_debug_errno(r, "Failed to load search domain '%s', ignoring: %m", word);
1278 continue;
943ef07c
LP
1279 }
1280 }
1281
1282 if (ntas) {
1283 _cleanup_set_free_free_ Set *ns = NULL;
1284
1285 ns = set_new(&dns_name_hash_ops);
1286 if (!ns) {
1287 r = -ENOMEM;
1288 goto fail;
1289 }
1290
1291 r = set_put_strsplit(ns, ntas, NULL, 0);
1292 if (r < 0)
1293 goto fail;
1294
ae2a15bc 1295 l->dnssec_negative_trust_anchors = TAKE_PTR(ns);
943ef07c
LP
1296 }
1297
1298 return 0;
1299
1300fail:
1301 return log_error_errno(r, "Failed to load link data %s: %m", l->state_file);
1302}
1303
1304void link_remove_user(Link *l) {
1305 assert(l);
1306 assert(l->state_file);
1307
1308 (void) unlink(l->state_file);
1309}