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