]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/resolve/resolved-link.c
resolved: rework what ResolveHostname() with family == AF_UNSPEC means
[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 local_multicast) {
519 _cleanup_free_ char *state = NULL;
520 LinkAddress *a;
521
522 assert(l);
523
524 /* A link is relevant for local multicast traffic if it isn't a loopback or pointopoint device, has a link
525 * beat, can do multicast and has at least one link-local (or better) IP address.
526 *
527 * A link is relevant for non-multicast traffic if it isn't a loopback device, has a link beat, and has at
528 * least one routable address.*/
529
530 if (l->flags & (IFF_LOOPBACK|IFF_DORMANT))
531 return false;
532
533 if ((l->flags & (IFF_UP|IFF_LOWER_UP)) != (IFF_UP|IFF_LOWER_UP))
534 return false;
535
536 if (local_multicast) {
537 if (l->flags & IFF_POINTOPOINT)
538 return false;
539
540 if ((l->flags & IFF_MULTICAST) != IFF_MULTICAST)
541 return false;
542 }
543
544 /* Check kernel operstate
545 * https://www.kernel.org/doc/Documentation/networking/operstates.txt */
546 if (!IN_SET(l->operstate, IF_OPER_UNKNOWN, IF_OPER_UP))
547 return false;
548
549 (void) sd_network_link_get_operational_state(l->ifindex, &state);
550 if (state && !STR_IN_SET(state, "unknown", "degraded", "routable"))
551 return false;
552
553 LIST_FOREACH(addresses, a, l->addresses)
554 if ((family == AF_UNSPEC || a->family == family) && link_address_relevant(a, local_multicast))
555 return true;
556
557 return false;
558 }
559
560 LinkAddress *link_find_address(Link *l, int family, const union in_addr_union *in_addr) {
561 LinkAddress *a;
562
563 assert(l);
564
565 LIST_FOREACH(addresses, a, l->addresses)
566 if (a->family == family && in_addr_equal(family, &a->in_addr, in_addr))
567 return a;
568
569 return NULL;
570 }
571
572 DnsServer* link_set_dns_server(Link *l, DnsServer *s) {
573 assert(l);
574
575 if (l->current_dns_server == s)
576 return s;
577
578 if (s)
579 log_info("Switching to DNS server %s for interface %s.", dns_server_string(s), l->name);
580
581 dns_server_unref(l->current_dns_server);
582 l->current_dns_server = dns_server_ref(s);
583
584 if (l->unicast_scope)
585 dns_cache_flush(&l->unicast_scope->cache);
586
587 return s;
588 }
589
590 DnsServer *link_get_dns_server(Link *l) {
591 assert(l);
592
593 if (!l->current_dns_server)
594 link_set_dns_server(l, l->dns_servers);
595
596 return l->current_dns_server;
597 }
598
599 void link_next_dns_server(Link *l) {
600 assert(l);
601
602 if (!l->current_dns_server)
603 return;
604
605 /* Change to the next one, but make sure to follow the linked
606 * list only if this server is actually still linked. */
607 if (l->current_dns_server->linked && l->current_dns_server->servers_next) {
608 link_set_dns_server(l, l->current_dns_server->servers_next);
609 return;
610 }
611
612 link_set_dns_server(l, l->dns_servers);
613 }
614
615 DnssecMode link_get_dnssec_mode(Link *l) {
616 assert(l);
617
618 if (l->dnssec_mode != _DNSSEC_MODE_INVALID)
619 return l->dnssec_mode;
620
621 return manager_get_dnssec_mode(l->manager);
622 }
623
624 bool link_dnssec_supported(Link *l) {
625 DnsServer *server;
626
627 assert(l);
628
629 if (link_get_dnssec_mode(l) == DNSSEC_NO)
630 return false;
631
632 server = link_get_dns_server(l);
633 if (server)
634 return dns_server_dnssec_supported(server);
635
636 return true;
637 }
638
639 int link_address_new(Link *l, LinkAddress **ret, int family, const union in_addr_union *in_addr) {
640 LinkAddress *a;
641
642 assert(l);
643 assert(in_addr);
644
645 a = new0(LinkAddress, 1);
646 if (!a)
647 return -ENOMEM;
648
649 a->family = family;
650 a->in_addr = *in_addr;
651
652 a->link = l;
653 LIST_PREPEND(addresses, l->addresses, a);
654
655 if (ret)
656 *ret = a;
657
658 return 0;
659 }
660
661 LinkAddress *link_address_free(LinkAddress *a) {
662 if (!a)
663 return NULL;
664
665 if (a->link) {
666 LIST_REMOVE(addresses, a->link->addresses, a);
667
668 if (a->llmnr_address_rr) {
669 if (a->family == AF_INET && a->link->llmnr_ipv4_scope)
670 dns_zone_remove_rr(&a->link->llmnr_ipv4_scope->zone, a->llmnr_address_rr);
671 else if (a->family == AF_INET6 && a->link->llmnr_ipv6_scope)
672 dns_zone_remove_rr(&a->link->llmnr_ipv6_scope->zone, a->llmnr_address_rr);
673 }
674
675 if (a->llmnr_ptr_rr) {
676 if (a->family == AF_INET && a->link->llmnr_ipv4_scope)
677 dns_zone_remove_rr(&a->link->llmnr_ipv4_scope->zone, a->llmnr_ptr_rr);
678 else if (a->family == AF_INET6 && a->link->llmnr_ipv6_scope)
679 dns_zone_remove_rr(&a->link->llmnr_ipv6_scope->zone, a->llmnr_ptr_rr);
680 }
681 }
682
683 dns_resource_record_unref(a->llmnr_address_rr);
684 dns_resource_record_unref(a->llmnr_ptr_rr);
685
686 free(a);
687 return NULL;
688 }
689
690 void link_address_add_rrs(LinkAddress *a, bool force_remove) {
691 int r;
692
693 assert(a);
694
695 if (a->family == AF_INET) {
696
697 if (!force_remove &&
698 link_address_relevant(a, true) &&
699 a->link->llmnr_ipv4_scope &&
700 a->link->llmnr_support == RESOLVE_SUPPORT_YES &&
701 a->link->manager->llmnr_support == RESOLVE_SUPPORT_YES) {
702
703 if (!a->link->manager->llmnr_host_ipv4_key) {
704 a->link->manager->llmnr_host_ipv4_key = dns_resource_key_new(DNS_CLASS_IN, DNS_TYPE_A, a->link->manager->llmnr_hostname);
705 if (!a->link->manager->llmnr_host_ipv4_key) {
706 r = -ENOMEM;
707 goto fail;
708 }
709 }
710
711 if (!a->llmnr_address_rr) {
712 a->llmnr_address_rr = dns_resource_record_new(a->link->manager->llmnr_host_ipv4_key);
713 if (!a->llmnr_address_rr) {
714 r = -ENOMEM;
715 goto fail;
716 }
717
718 a->llmnr_address_rr->a.in_addr = a->in_addr.in;
719 a->llmnr_address_rr->ttl = LLMNR_DEFAULT_TTL;
720 }
721
722 if (!a->llmnr_ptr_rr) {
723 r = dns_resource_record_new_reverse(&a->llmnr_ptr_rr, a->family, &a->in_addr, a->link->manager->llmnr_hostname);
724 if (r < 0)
725 goto fail;
726
727 a->llmnr_ptr_rr->ttl = LLMNR_DEFAULT_TTL;
728 }
729
730 r = dns_zone_put(&a->link->llmnr_ipv4_scope->zone, a->link->llmnr_ipv4_scope, a->llmnr_address_rr, true);
731 if (r < 0)
732 log_warning_errno(r, "Failed to add A record to LLMNR zone: %m");
733
734 r = dns_zone_put(&a->link->llmnr_ipv4_scope->zone, a->link->llmnr_ipv4_scope, a->llmnr_ptr_rr, false);
735 if (r < 0)
736 log_warning_errno(r, "Failed to add IPv6 PTR record to LLMNR zone: %m");
737 } else {
738 if (a->llmnr_address_rr) {
739 if (a->link->llmnr_ipv4_scope)
740 dns_zone_remove_rr(&a->link->llmnr_ipv4_scope->zone, a->llmnr_address_rr);
741 a->llmnr_address_rr = dns_resource_record_unref(a->llmnr_address_rr);
742 }
743
744 if (a->llmnr_ptr_rr) {
745 if (a->link->llmnr_ipv4_scope)
746 dns_zone_remove_rr(&a->link->llmnr_ipv4_scope->zone, a->llmnr_ptr_rr);
747 a->llmnr_ptr_rr = dns_resource_record_unref(a->llmnr_ptr_rr);
748 }
749 }
750 }
751
752 if (a->family == AF_INET6) {
753
754 if (!force_remove &&
755 link_address_relevant(a, true) &&
756 a->link->llmnr_ipv6_scope &&
757 a->link->llmnr_support == RESOLVE_SUPPORT_YES &&
758 a->link->manager->llmnr_support == RESOLVE_SUPPORT_YES) {
759
760 if (!a->link->manager->llmnr_host_ipv6_key) {
761 a->link->manager->llmnr_host_ipv6_key = dns_resource_key_new(DNS_CLASS_IN, DNS_TYPE_AAAA, a->link->manager->llmnr_hostname);
762 if (!a->link->manager->llmnr_host_ipv6_key) {
763 r = -ENOMEM;
764 goto fail;
765 }
766 }
767
768 if (!a->llmnr_address_rr) {
769 a->llmnr_address_rr = dns_resource_record_new(a->link->manager->llmnr_host_ipv6_key);
770 if (!a->llmnr_address_rr) {
771 r = -ENOMEM;
772 goto fail;
773 }
774
775 a->llmnr_address_rr->aaaa.in6_addr = a->in_addr.in6;
776 a->llmnr_address_rr->ttl = LLMNR_DEFAULT_TTL;
777 }
778
779 if (!a->llmnr_ptr_rr) {
780 r = dns_resource_record_new_reverse(&a->llmnr_ptr_rr, a->family, &a->in_addr, a->link->manager->llmnr_hostname);
781 if (r < 0)
782 goto fail;
783
784 a->llmnr_ptr_rr->ttl = LLMNR_DEFAULT_TTL;
785 }
786
787 r = dns_zone_put(&a->link->llmnr_ipv6_scope->zone, a->link->llmnr_ipv6_scope, a->llmnr_address_rr, true);
788 if (r < 0)
789 log_warning_errno(r, "Failed to add AAAA record to LLMNR zone: %m");
790
791 r = dns_zone_put(&a->link->llmnr_ipv6_scope->zone, a->link->llmnr_ipv6_scope, a->llmnr_ptr_rr, false);
792 if (r < 0)
793 log_warning_errno(r, "Failed to add IPv6 PTR record to LLMNR zone: %m");
794 } else {
795 if (a->llmnr_address_rr) {
796 if (a->link->llmnr_ipv6_scope)
797 dns_zone_remove_rr(&a->link->llmnr_ipv6_scope->zone, a->llmnr_address_rr);
798 a->llmnr_address_rr = dns_resource_record_unref(a->llmnr_address_rr);
799 }
800
801 if (a->llmnr_ptr_rr) {
802 if (a->link->llmnr_ipv6_scope)
803 dns_zone_remove_rr(&a->link->llmnr_ipv6_scope->zone, a->llmnr_ptr_rr);
804 a->llmnr_ptr_rr = dns_resource_record_unref(a->llmnr_ptr_rr);
805 }
806 }
807 }
808
809 return;
810
811 fail:
812 log_debug_errno(r, "Failed to update address RRs: %m");
813 }
814
815 int link_address_update_rtnl(LinkAddress *a, sd_netlink_message *m) {
816 int r;
817 assert(a);
818 assert(m);
819
820 r = sd_rtnl_message_addr_get_flags(m, &a->flags);
821 if (r < 0)
822 return r;
823
824 sd_rtnl_message_addr_get_scope(m, &a->scope);
825
826 link_allocate_scopes(a->link);
827 link_add_rrs(a->link, false);
828
829 return 0;
830 }
831
832 bool link_address_relevant(LinkAddress *a, bool local_multicast) {
833 assert(a);
834
835 if (a->flags & (IFA_F_DEPRECATED|IFA_F_TENTATIVE))
836 return false;
837
838 if (a->scope >= (local_multicast ? RT_SCOPE_HOST : RT_SCOPE_LINK))
839 return false;
840
841 return true;
842 }