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