]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/resolve/resolved-link.c
Merge pull request #2446 from keszybz/ask-password
[thirdparty/systemd.git] / src / resolve / resolved-link.c
1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3 /***
4 This file is part of systemd.
5
6 Copyright 2014 Lennart Poettering
7
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
12
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
17
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
20 ***/
21
22 #include <net/if.h>
23
24 #include "sd-network.h"
25
26 #include "alloc-util.h"
27 #include "missing.h"
28 #include "parse-util.h"
29 #include "resolved-link.h"
30 #include "string-util.h"
31 #include "strv.h"
32
33 int link_new(Manager *m, Link **ret, int ifindex) {
34 _cleanup_(link_freep) Link *l = NULL;
35 int r;
36
37 assert(m);
38 assert(ifindex > 0);
39
40 r = hashmap_ensure_allocated(&m->links, NULL);
41 if (r < 0)
42 return r;
43
44 l = new0(Link, 1);
45 if (!l)
46 return -ENOMEM;
47
48 l->ifindex = ifindex;
49 l->llmnr_support = RESOLVE_SUPPORT_YES;
50 l->mdns_support = RESOLVE_SUPPORT_NO;
51 l->dnssec_mode = _DNSSEC_MODE_INVALID;
52 l->operstate = IF_OPER_UNKNOWN;
53
54 r = hashmap_put(m->links, INT_TO_PTR(ifindex), l);
55 if (r < 0)
56 return r;
57
58 l->manager = m;
59
60 if (ret)
61 *ret = l;
62 l = NULL;
63
64 return 0;
65 }
66
67 void link_flush_settings(Link *l) {
68 assert(l);
69
70 l->llmnr_support = RESOLVE_SUPPORT_YES;
71 l->mdns_support = RESOLVE_SUPPORT_NO;
72 l->dnssec_mode = _DNSSEC_MODE_INVALID;
73
74 dns_server_unlink_all(l->dns_servers);
75 dns_search_domain_unlink_all(l->search_domains);
76
77 l->dnssec_negative_trust_anchors = set_free_free(l->dnssec_negative_trust_anchors);
78 }
79
80 Link *link_free(Link *l) {
81 if (!l)
82 return NULL;
83
84 link_flush_settings(l);
85
86 while (l->addresses)
87 (void) link_address_free(l->addresses);
88
89 if (l->manager)
90 hashmap_remove(l->manager->links, INT_TO_PTR(l->ifindex));
91
92 dns_scope_free(l->unicast_scope);
93 dns_scope_free(l->llmnr_ipv4_scope);
94 dns_scope_free(l->llmnr_ipv6_scope);
95 dns_scope_free(l->mdns_ipv4_scope);
96 dns_scope_free(l->mdns_ipv6_scope);
97
98 free(l);
99 return NULL;
100 }
101
102 void link_allocate_scopes(Link *l) {
103 int r;
104
105 assert(l);
106
107 if (link_relevant(l, AF_UNSPEC, false) &&
108 l->dns_servers) {
109 if (!l->unicast_scope) {
110 r = dns_scope_new(l->manager, &l->unicast_scope, l, DNS_PROTOCOL_DNS, AF_UNSPEC);
111 if (r < 0)
112 log_warning_errno(r, "Failed to allocate DNS scope: %m");
113 }
114 } else
115 l->unicast_scope = dns_scope_free(l->unicast_scope);
116
117 if (link_relevant(l, AF_INET, true) &&
118 l->llmnr_support != RESOLVE_SUPPORT_NO &&
119 l->manager->llmnr_support != RESOLVE_SUPPORT_NO) {
120 if (!l->llmnr_ipv4_scope) {
121 r = dns_scope_new(l->manager, &l->llmnr_ipv4_scope, l, DNS_PROTOCOL_LLMNR, AF_INET);
122 if (r < 0)
123 log_warning_errno(r, "Failed to allocate LLMNR IPv4 scope: %m");
124 }
125 } else
126 l->llmnr_ipv4_scope = dns_scope_free(l->llmnr_ipv4_scope);
127
128 if (link_relevant(l, AF_INET6, true) &&
129 l->llmnr_support != RESOLVE_SUPPORT_NO &&
130 l->manager->llmnr_support != RESOLVE_SUPPORT_NO &&
131 socket_ipv6_is_supported()) {
132 if (!l->llmnr_ipv6_scope) {
133 r = dns_scope_new(l->manager, &l->llmnr_ipv6_scope, l, DNS_PROTOCOL_LLMNR, AF_INET6);
134 if (r < 0)
135 log_warning_errno(r, "Failed to allocate LLMNR IPv6 scope: %m");
136 }
137 } else
138 l->llmnr_ipv6_scope = dns_scope_free(l->llmnr_ipv6_scope);
139
140 if (link_relevant(l, AF_INET, true) &&
141 l->mdns_support != RESOLVE_SUPPORT_NO &&
142 l->manager->mdns_support != RESOLVE_SUPPORT_NO) {
143 if (!l->mdns_ipv4_scope) {
144 r = dns_scope_new(l->manager, &l->mdns_ipv4_scope, l, DNS_PROTOCOL_MDNS, AF_INET);
145 if (r < 0)
146 log_warning_errno(r, "Failed to allocate mDNS IPv4 scope: %m");
147 }
148 } else
149 l->mdns_ipv4_scope = dns_scope_free(l->mdns_ipv4_scope);
150
151 if (link_relevant(l, AF_INET6, true) &&
152 l->mdns_support != RESOLVE_SUPPORT_NO &&
153 l->manager->mdns_support != RESOLVE_SUPPORT_NO) {
154 if (!l->mdns_ipv6_scope) {
155 r = dns_scope_new(l->manager, &l->mdns_ipv6_scope, l, DNS_PROTOCOL_MDNS, AF_INET6);
156 if (r < 0)
157 log_warning_errno(r, "Failed to allocate mDNS IPv6 scope: %m");
158 }
159 } else
160 l->mdns_ipv6_scope = dns_scope_free(l->mdns_ipv6_scope);
161 }
162
163 void link_add_rrs(Link *l, bool force_remove) {
164 LinkAddress *a;
165
166 LIST_FOREACH(addresses, a, l->addresses)
167 link_address_add_rrs(a, force_remove);
168 }
169
170 int link_update_rtnl(Link *l, sd_netlink_message *m) {
171 const char *n = NULL;
172 int r;
173
174 assert(l);
175 assert(m);
176
177 r = sd_rtnl_message_link_get_flags(m, &l->flags);
178 if (r < 0)
179 return r;
180
181 (void) sd_netlink_message_read_u32(m, IFLA_MTU, &l->mtu);
182 (void) sd_netlink_message_read_u8(m, IFLA_OPERSTATE, &l->operstate);
183
184 if (sd_netlink_message_read_string(m, IFLA_IFNAME, &n) >= 0) {
185 strncpy(l->name, n, sizeof(l->name)-1);
186 char_array_0(l->name);
187 }
188
189 link_allocate_scopes(l);
190 link_add_rrs(l, false);
191
192 return 0;
193 }
194
195 static int link_update_dns_servers(Link *l) {
196 _cleanup_strv_free_ char **nameservers = NULL;
197 char **nameserver;
198 int r;
199
200 assert(l);
201
202 r = sd_network_link_get_dns(l->ifindex, &nameservers);
203 if (r == -ENODATA) {
204 r = 0;
205 goto clear;
206 }
207 if (r < 0)
208 goto clear;
209
210 dns_server_mark_all(l->dns_servers);
211
212 STRV_FOREACH(nameserver, nameservers) {
213 union in_addr_union a;
214 DnsServer *s;
215 int family;
216
217 r = in_addr_from_string_auto(*nameserver, &family, &a);
218 if (r < 0)
219 goto clear;
220
221 s = dns_server_find(l->dns_servers, family, &a);
222 if (s)
223 dns_server_move_back_and_unmark(s);
224 else {
225 r = dns_server_new(l->manager, NULL, DNS_SERVER_LINK, l, family, &a);
226 if (r < 0)
227 goto clear;
228 }
229 }
230
231 dns_server_unlink_marked(l->dns_servers);
232 return 0;
233
234 clear:
235 dns_server_unlink_all(l->dns_servers);
236 return r;
237 }
238
239 static int link_update_llmnr_support(Link *l) {
240 _cleanup_free_ char *b = NULL;
241 int r;
242
243 assert(l);
244
245 r = sd_network_link_get_llmnr(l->ifindex, &b);
246 if (r == -ENODATA) {
247 r = 0;
248 goto clear;
249 }
250 if (r < 0)
251 goto clear;
252
253 l->llmnr_support = resolve_support_from_string(b);
254 if (l->llmnr_support < 0) {
255 r = -EINVAL;
256 goto clear;
257 }
258
259 return 0;
260
261 clear:
262 l->llmnr_support = RESOLVE_SUPPORT_YES;
263 return r;
264 }
265
266 static int link_update_mdns_support(Link *l) {
267 _cleanup_free_ char *b = NULL;
268 int r;
269
270 assert(l);
271
272 r = sd_network_link_get_mdns(l->ifindex, &b);
273 if (r == -ENODATA) {
274 r = 0;
275 goto clear;
276 }
277 if (r < 0)
278 goto clear;
279
280 l->mdns_support = resolve_support_from_string(b);
281 if (l->mdns_support < 0) {
282 r = -EINVAL;
283 goto clear;
284 }
285
286 return 0;
287
288 clear:
289 l->mdns_support = RESOLVE_SUPPORT_NO;
290 return r;
291 }
292
293 void link_set_dnssec_mode(Link *l, DnssecMode mode) {
294
295 assert(l);
296
297 if (l->dnssec_mode == mode)
298 return;
299
300 if ((l->dnssec_mode == _DNSSEC_MODE_INVALID) ||
301 (l->dnssec_mode == DNSSEC_NO && mode != DNSSEC_NO) ||
302 (l->dnssec_mode == DNSSEC_ALLOW_DOWNGRADE && mode == DNSSEC_YES)) {
303
304 /* When switching from non-DNSSEC mode to DNSSEC mode, flush the cache. Also when switching from the
305 * allow-downgrade mode to full DNSSEC mode, flush it too. */
306 if (l->unicast_scope)
307 dns_cache_flush(&l->unicast_scope->cache);
308 }
309
310 l->dnssec_mode = mode;
311 }
312
313 static int link_update_dnssec_mode(Link *l) {
314 _cleanup_free_ char *m = NULL;
315 DnssecMode mode;
316 int r;
317
318 assert(l);
319
320 r = sd_network_link_get_dnssec(l->ifindex, &m);
321 if (r == -ENODATA) {
322 r = 0;
323 goto clear;
324 }
325 if (r < 0)
326 goto clear;
327
328 mode = dnssec_mode_from_string(m);
329 if (mode < 0) {
330 r = -EINVAL;
331 goto clear;
332 }
333
334 link_set_dnssec_mode(l, mode);
335
336 return 0;
337
338 clear:
339 l->dnssec_mode = _DNSSEC_MODE_INVALID;
340 return r;
341 }
342
343 static int link_update_dnssec_negative_trust_anchors(Link *l) {
344 _cleanup_strv_free_ char **ntas = NULL;
345 _cleanup_set_free_free_ Set *ns = NULL;
346 char **i;
347 int r;
348
349 assert(l);
350
351 r = sd_network_link_get_dnssec_negative_trust_anchors(l->ifindex, &ntas);
352 if (r == -ENODATA) {
353 r = 0;
354 goto clear;
355 }
356 if (r < 0)
357 goto clear;
358
359 ns = set_new(&dns_name_hash_ops);
360 if (!ns)
361 return -ENOMEM;
362
363 STRV_FOREACH(i, ntas) {
364 r = set_put_strdup(ns, *i);
365 if (r < 0)
366 return r;
367 }
368
369 set_free_free(l->dnssec_negative_trust_anchors);
370 l->dnssec_negative_trust_anchors = ns;
371 ns = NULL;
372
373 return 0;
374
375 clear:
376 l->dnssec_negative_trust_anchors = set_free_free(l->dnssec_negative_trust_anchors);
377 return r;
378 }
379
380 static int link_update_search_domain_one(Link *l, const char *name, bool route_only) {
381 DnsSearchDomain *d;
382 int r;
383
384 r = dns_search_domain_find(l->search_domains, name, &d);
385 if (r < 0)
386 return r;
387 if (r > 0)
388 dns_search_domain_move_back_and_unmark(d);
389 else {
390 r = dns_search_domain_new(l->manager, &d, DNS_SEARCH_DOMAIN_LINK, l, name);
391 if (r < 0)
392 return r;
393 }
394
395 d->route_only = route_only;
396 return 0;
397 }
398
399 static int link_update_search_domains(Link *l) {
400 _cleanup_strv_free_ char **sdomains = NULL, **rdomains = NULL;
401 char **i;
402 int r, q;
403
404 assert(l);
405
406 r = sd_network_link_get_search_domains(l->ifindex, &sdomains);
407 if (r < 0 && r != -ENODATA)
408 goto clear;
409
410 q = sd_network_link_get_route_domains(l->ifindex, &rdomains);
411 if (q < 0 && q != -ENODATA) {
412 r = q;
413 goto clear;
414 }
415
416 if (r == -ENODATA && q == -ENODATA) {
417 /* networkd knows nothing about this interface, and that's fine. */
418 r = 0;
419 goto clear;
420 }
421
422 dns_search_domain_mark_all(l->search_domains);
423
424 STRV_FOREACH(i, sdomains) {
425 r = link_update_search_domain_one(l, *i, false);
426 if (r < 0)
427 goto clear;
428 }
429
430 STRV_FOREACH(i, rdomains) {
431 r = link_update_search_domain_one(l, *i, true);
432 if (r < 0)
433 goto clear;
434 }
435
436 dns_search_domain_unlink_marked(l->search_domains);
437 return 0;
438
439 clear:
440 dns_search_domain_unlink_all(l->search_domains);
441 return r;
442 }
443
444 static int link_is_unmanaged(Link *l) {
445 _cleanup_free_ char *state = NULL;
446 int r;
447
448 assert(l);
449
450 r = sd_network_link_get_setup_state(l->ifindex, &state);
451 if (r == -ENODATA)
452 return 1;
453 if (r < 0)
454 return r;
455
456 return STR_IN_SET(state, "pending", "unmanaged");
457 }
458
459 static void link_read_settings(Link *l) {
460 int r;
461
462 assert(l);
463
464 /* Read settings from networkd, except when networkd is not managing this interface. */
465
466 r = link_is_unmanaged(l);
467 if (r < 0) {
468 log_warning_errno(r, "Failed to determine whether interface %s is managed: %m", l->name);
469 return;
470 }
471 if (r > 0) {
472
473 /* If this link used to be managed, but is now unmanaged, flush all our settings -- but only once. */
474 if (l->is_managed)
475 link_flush_settings(l);
476
477 l->is_managed = false;
478 return;
479 }
480
481 l->is_managed = true;
482
483 r = link_update_dns_servers(l);
484 if (r < 0)
485 log_warning_errno(r, "Failed to read DNS servers for interface %s, ignoring: %m", l->name);
486
487 r = link_update_llmnr_support(l);
488 if (r < 0)
489 log_warning_errno(r, "Failed to read LLMNR support for interface %s, ignoring: %m", l->name);
490
491 r = link_update_mdns_support(l);
492 if (r < 0)
493 log_warning_errno(r, "Failed to read mDNS support for interface %s, ignoring: %m", l->name);
494
495 r = link_update_dnssec_mode(l);
496 if (r < 0)
497 log_warning_errno(r, "Failed to read DNSSEC mode for interface %s, ignoring: %m", l->name);
498
499 r = link_update_dnssec_negative_trust_anchors(l);
500 if (r < 0)
501 log_warning_errno(r, "Failed to read DNSSEC negative trust anchors for interface %s, ignoring: %m", l->name);
502
503 r = link_update_search_domains(l);
504 if (r < 0)
505 log_warning_errno(r, "Failed to read search domains for interface %s, ignoring: %m", l->name);
506 }
507
508 int link_update_monitor(Link *l) {
509 assert(l);
510
511 link_read_settings(l);
512 link_allocate_scopes(l);
513 link_add_rrs(l, false);
514
515 return 0;
516 }
517
518 bool link_relevant(Link *l, int family, bool multicast) {
519 _cleanup_free_ char *state = NULL;
520 LinkAddress *a;
521
522 assert(l);
523
524 /* A link is relevant for multicast traffic if it isn't a loopback or pointopoint device, has a link beat, can
525 * do multicast and has at least one relevant IP address */
526
527 if (l->flags & (IFF_LOOPBACK|IFF_DORMANT))
528 return false;
529
530 if ((l->flags & (IFF_UP|IFF_LOWER_UP)) != (IFF_UP|IFF_LOWER_UP))
531 return false;
532
533 if (multicast) {
534 if (l->flags & IFF_POINTOPOINT)
535 return false;
536
537 if ((l->flags & IFF_MULTICAST) != IFF_MULTICAST)
538 return false;
539 }
540
541 /* Check kernel operstate
542 * https://www.kernel.org/doc/Documentation/networking/operstates.txt */
543 if (!IN_SET(l->operstate, IF_OPER_UNKNOWN, IF_OPER_UP))
544 return false;
545
546 (void) sd_network_link_get_operational_state(l->ifindex, &state);
547 if (state && !STR_IN_SET(state, "unknown", "degraded", "routable"))
548 return false;
549
550 LIST_FOREACH(addresses, a, l->addresses)
551 if ((family == AF_UNSPEC || a->family == family) && link_address_relevant(a))
552 return true;
553
554 return false;
555 }
556
557 LinkAddress *link_find_address(Link *l, int family, const union in_addr_union *in_addr) {
558 LinkAddress *a;
559
560 assert(l);
561
562 LIST_FOREACH(addresses, a, l->addresses)
563 if (a->family == family && in_addr_equal(family, &a->in_addr, in_addr))
564 return a;
565
566 return NULL;
567 }
568
569 DnsServer* link_set_dns_server(Link *l, DnsServer *s) {
570 assert(l);
571
572 if (l->current_dns_server == s)
573 return s;
574
575 if (s)
576 log_info("Switching to DNS server %s for interface %s.", dns_server_string(s), l->name);
577
578 dns_server_unref(l->current_dns_server);
579 l->current_dns_server = dns_server_ref(s);
580
581 if (l->unicast_scope)
582 dns_cache_flush(&l->unicast_scope->cache);
583
584 return s;
585 }
586
587 DnsServer *link_get_dns_server(Link *l) {
588 assert(l);
589
590 if (!l->current_dns_server)
591 link_set_dns_server(l, l->dns_servers);
592
593 return l->current_dns_server;
594 }
595
596 void link_next_dns_server(Link *l) {
597 assert(l);
598
599 if (!l->current_dns_server)
600 return;
601
602 /* Change to the next one, but make sure to follow the linked
603 * list only if this server is actually still linked. */
604 if (l->current_dns_server->linked && l->current_dns_server->servers_next) {
605 link_set_dns_server(l, l->current_dns_server->servers_next);
606 return;
607 }
608
609 link_set_dns_server(l, l->dns_servers);
610 }
611
612 DnssecMode link_get_dnssec_mode(Link *l) {
613 assert(l);
614
615 if (l->dnssec_mode != _DNSSEC_MODE_INVALID)
616 return l->dnssec_mode;
617
618 return manager_get_dnssec_mode(l->manager);
619 }
620
621 bool link_dnssec_supported(Link *l) {
622 DnsServer *server;
623
624 assert(l);
625
626 if (link_get_dnssec_mode(l) == DNSSEC_NO)
627 return false;
628
629 server = link_get_dns_server(l);
630 if (server)
631 return dns_server_dnssec_supported(server);
632
633 return true;
634 }
635
636 int link_address_new(Link *l, LinkAddress **ret, int family, const union in_addr_union *in_addr) {
637 LinkAddress *a;
638
639 assert(l);
640 assert(in_addr);
641
642 a = new0(LinkAddress, 1);
643 if (!a)
644 return -ENOMEM;
645
646 a->family = family;
647 a->in_addr = *in_addr;
648
649 a->link = l;
650 LIST_PREPEND(addresses, l->addresses, a);
651
652 if (ret)
653 *ret = a;
654
655 return 0;
656 }
657
658 LinkAddress *link_address_free(LinkAddress *a) {
659 if (!a)
660 return NULL;
661
662 if (a->link) {
663 LIST_REMOVE(addresses, a->link->addresses, a);
664
665 if (a->llmnr_address_rr) {
666 if (a->family == AF_INET && a->link->llmnr_ipv4_scope)
667 dns_zone_remove_rr(&a->link->llmnr_ipv4_scope->zone, a->llmnr_address_rr);
668 else if (a->family == AF_INET6 && a->link->llmnr_ipv6_scope)
669 dns_zone_remove_rr(&a->link->llmnr_ipv6_scope->zone, a->llmnr_address_rr);
670 }
671
672 if (a->llmnr_ptr_rr) {
673 if (a->family == AF_INET && a->link->llmnr_ipv4_scope)
674 dns_zone_remove_rr(&a->link->llmnr_ipv4_scope->zone, a->llmnr_ptr_rr);
675 else if (a->family == AF_INET6 && a->link->llmnr_ipv6_scope)
676 dns_zone_remove_rr(&a->link->llmnr_ipv6_scope->zone, a->llmnr_ptr_rr);
677 }
678 }
679
680 dns_resource_record_unref(a->llmnr_address_rr);
681 dns_resource_record_unref(a->llmnr_ptr_rr);
682
683 free(a);
684 return NULL;
685 }
686
687 void link_address_add_rrs(LinkAddress *a, bool force_remove) {
688 int r;
689
690 assert(a);
691
692 if (a->family == AF_INET) {
693
694 if (!force_remove &&
695 link_address_relevant(a) &&
696 a->link->llmnr_ipv4_scope &&
697 a->link->llmnr_support == RESOLVE_SUPPORT_YES &&
698 a->link->manager->llmnr_support == RESOLVE_SUPPORT_YES) {
699
700 if (!a->link->manager->llmnr_host_ipv4_key) {
701 a->link->manager->llmnr_host_ipv4_key = dns_resource_key_new(DNS_CLASS_IN, DNS_TYPE_A, a->link->manager->llmnr_hostname);
702 if (!a->link->manager->llmnr_host_ipv4_key) {
703 r = -ENOMEM;
704 goto fail;
705 }
706 }
707
708 if (!a->llmnr_address_rr) {
709 a->llmnr_address_rr = dns_resource_record_new(a->link->manager->llmnr_host_ipv4_key);
710 if (!a->llmnr_address_rr) {
711 r = -ENOMEM;
712 goto fail;
713 }
714
715 a->llmnr_address_rr->a.in_addr = a->in_addr.in;
716 a->llmnr_address_rr->ttl = LLMNR_DEFAULT_TTL;
717 }
718
719 if (!a->llmnr_ptr_rr) {
720 r = dns_resource_record_new_reverse(&a->llmnr_ptr_rr, a->family, &a->in_addr, a->link->manager->llmnr_hostname);
721 if (r < 0)
722 goto fail;
723
724 a->llmnr_ptr_rr->ttl = LLMNR_DEFAULT_TTL;
725 }
726
727 r = dns_zone_put(&a->link->llmnr_ipv4_scope->zone, a->link->llmnr_ipv4_scope, a->llmnr_address_rr, true);
728 if (r < 0)
729 log_warning_errno(r, "Failed to add A record to LLMNR zone: %m");
730
731 r = dns_zone_put(&a->link->llmnr_ipv4_scope->zone, a->link->llmnr_ipv4_scope, a->llmnr_ptr_rr, false);
732 if (r < 0)
733 log_warning_errno(r, "Failed to add IPv6 PTR record to LLMNR zone: %m");
734 } else {
735 if (a->llmnr_address_rr) {
736 if (a->link->llmnr_ipv4_scope)
737 dns_zone_remove_rr(&a->link->llmnr_ipv4_scope->zone, a->llmnr_address_rr);
738 a->llmnr_address_rr = dns_resource_record_unref(a->llmnr_address_rr);
739 }
740
741 if (a->llmnr_ptr_rr) {
742 if (a->link->llmnr_ipv4_scope)
743 dns_zone_remove_rr(&a->link->llmnr_ipv4_scope->zone, a->llmnr_ptr_rr);
744 a->llmnr_ptr_rr = dns_resource_record_unref(a->llmnr_ptr_rr);
745 }
746 }
747 }
748
749 if (a->family == AF_INET6) {
750
751 if (!force_remove &&
752 link_address_relevant(a) &&
753 a->link->llmnr_ipv6_scope &&
754 a->link->llmnr_support == RESOLVE_SUPPORT_YES &&
755 a->link->manager->llmnr_support == RESOLVE_SUPPORT_YES) {
756
757 if (!a->link->manager->llmnr_host_ipv6_key) {
758 a->link->manager->llmnr_host_ipv6_key = dns_resource_key_new(DNS_CLASS_IN, DNS_TYPE_AAAA, a->link->manager->llmnr_hostname);
759 if (!a->link->manager->llmnr_host_ipv6_key) {
760 r = -ENOMEM;
761 goto fail;
762 }
763 }
764
765 if (!a->llmnr_address_rr) {
766 a->llmnr_address_rr = dns_resource_record_new(a->link->manager->llmnr_host_ipv6_key);
767 if (!a->llmnr_address_rr) {
768 r = -ENOMEM;
769 goto fail;
770 }
771
772 a->llmnr_address_rr->aaaa.in6_addr = a->in_addr.in6;
773 a->llmnr_address_rr->ttl = LLMNR_DEFAULT_TTL;
774 }
775
776 if (!a->llmnr_ptr_rr) {
777 r = dns_resource_record_new_reverse(&a->llmnr_ptr_rr, a->family, &a->in_addr, a->link->manager->llmnr_hostname);
778 if (r < 0)
779 goto fail;
780
781 a->llmnr_ptr_rr->ttl = LLMNR_DEFAULT_TTL;
782 }
783
784 r = dns_zone_put(&a->link->llmnr_ipv6_scope->zone, a->link->llmnr_ipv6_scope, a->llmnr_address_rr, true);
785 if (r < 0)
786 log_warning_errno(r, "Failed to add AAAA record to LLMNR zone: %m");
787
788 r = dns_zone_put(&a->link->llmnr_ipv6_scope->zone, a->link->llmnr_ipv6_scope, a->llmnr_ptr_rr, false);
789 if (r < 0)
790 log_warning_errno(r, "Failed to add IPv6 PTR record to LLMNR zone: %m");
791 } else {
792 if (a->llmnr_address_rr) {
793 if (a->link->llmnr_ipv6_scope)
794 dns_zone_remove_rr(&a->link->llmnr_ipv6_scope->zone, a->llmnr_address_rr);
795 a->llmnr_address_rr = dns_resource_record_unref(a->llmnr_address_rr);
796 }
797
798 if (a->llmnr_ptr_rr) {
799 if (a->link->llmnr_ipv6_scope)
800 dns_zone_remove_rr(&a->link->llmnr_ipv6_scope->zone, a->llmnr_ptr_rr);
801 a->llmnr_ptr_rr = dns_resource_record_unref(a->llmnr_ptr_rr);
802 }
803 }
804 }
805
806 return;
807
808 fail:
809 log_debug_errno(r, "Failed to update address RRs: %m");
810 }
811
812 int link_address_update_rtnl(LinkAddress *a, sd_netlink_message *m) {
813 int r;
814 assert(a);
815 assert(m);
816
817 r = sd_rtnl_message_addr_get_flags(m, &a->flags);
818 if (r < 0)
819 return r;
820
821 sd_rtnl_message_addr_get_scope(m, &a->scope);
822
823 link_allocate_scopes(a->link);
824 link_add_rrs(a->link, false);
825
826 return 0;
827 }
828
829 bool link_address_relevant(LinkAddress *a) {
830 assert(a);
831
832 if (a->flags & (IFA_F_DEPRECATED|IFA_F_TENTATIVE))
833 return false;
834
835 if (IN_SET(a->scope, RT_SCOPE_HOST, RT_SCOPE_NOWHERE))
836 return false;
837
838 return true;
839 }