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