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