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