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