]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/resolve/resolved-link.c
Merge pull request #3088 from keszybz/man
[thirdparty/systemd.git] / src / resolve / resolved-link.c
1 /***
2 This file is part of systemd.
3
4 Copyright 2014 Lennart Poettering
5
6 systemd is free software; you can redistribute it and/or modify it
7 under the terms of the GNU Lesser General Public License as published by
8 the Free Software Foundation; either version 2.1 of the License, or
9 (at your option) any later version.
10
11 systemd is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Lesser General Public License for more details.
15
16 You should have received a copy of the GNU Lesser General Public License
17 along with systemd; If not, see <http://www.gnu.org/licenses/>.
18 ***/
19
20 #include <net/if.h>
21
22 #include "sd-network.h"
23
24 #include "alloc-util.h"
25 #include "missing.h"
26 #include "parse-util.h"
27 #include "resolved-link.h"
28 #include "string-util.h"
29 #include "strv.h"
30
31 int link_new(Manager *m, Link **ret, int ifindex) {
32 _cleanup_(link_freep) Link *l = NULL;
33 int r;
34
35 assert(m);
36 assert(ifindex > 0);
37
38 r = hashmap_ensure_allocated(&m->links, NULL);
39 if (r < 0)
40 return r;
41
42 l = new0(Link, 1);
43 if (!l)
44 return -ENOMEM;
45
46 l->ifindex = ifindex;
47 l->llmnr_support = RESOLVE_SUPPORT_YES;
48 l->mdns_support = RESOLVE_SUPPORT_NO;
49 l->dnssec_mode = _DNSSEC_MODE_INVALID;
50 l->operstate = IF_OPER_UNKNOWN;
51
52 r = hashmap_put(m->links, INT_TO_PTR(ifindex), l);
53 if (r < 0)
54 return r;
55
56 l->manager = m;
57
58 if (ret)
59 *ret = l;
60 l = NULL;
61
62 return 0;
63 }
64
65 void link_flush_settings(Link *l) {
66 assert(l);
67
68 l->llmnr_support = RESOLVE_SUPPORT_YES;
69 l->mdns_support = RESOLVE_SUPPORT_NO;
70 l->dnssec_mode = _DNSSEC_MODE_INVALID;
71
72 dns_server_unlink_all(l->dns_servers);
73 dns_search_domain_unlink_all(l->search_domains);
74
75 l->dnssec_negative_trust_anchors = set_free_free(l->dnssec_negative_trust_anchors);
76 }
77
78 Link *link_free(Link *l) {
79 if (!l)
80 return NULL;
81
82 link_flush_settings(l);
83
84 while (l->addresses)
85 (void) link_address_free(l->addresses);
86
87 if (l->manager)
88 hashmap_remove(l->manager->links, INT_TO_PTR(l->ifindex));
89
90 dns_scope_free(l->unicast_scope);
91 dns_scope_free(l->llmnr_ipv4_scope);
92 dns_scope_free(l->llmnr_ipv6_scope);
93 dns_scope_free(l->mdns_ipv4_scope);
94 dns_scope_free(l->mdns_ipv6_scope);
95
96 free(l);
97 return NULL;
98 }
99
100 void link_allocate_scopes(Link *l) {
101 int r;
102
103 assert(l);
104
105 if (link_relevant(l, AF_UNSPEC, false) &&
106 l->dns_servers) {
107 if (!l->unicast_scope) {
108 r = dns_scope_new(l->manager, &l->unicast_scope, l, DNS_PROTOCOL_DNS, AF_UNSPEC);
109 if (r < 0)
110 log_warning_errno(r, "Failed to allocate DNS scope: %m");
111 }
112 } else
113 l->unicast_scope = dns_scope_free(l->unicast_scope);
114
115 if (link_relevant(l, AF_INET, true) &&
116 l->llmnr_support != RESOLVE_SUPPORT_NO &&
117 l->manager->llmnr_support != RESOLVE_SUPPORT_NO) {
118 if (!l->llmnr_ipv4_scope) {
119 r = dns_scope_new(l->manager, &l->llmnr_ipv4_scope, l, DNS_PROTOCOL_LLMNR, AF_INET);
120 if (r < 0)
121 log_warning_errno(r, "Failed to allocate LLMNR IPv4 scope: %m");
122 }
123 } else
124 l->llmnr_ipv4_scope = dns_scope_free(l->llmnr_ipv4_scope);
125
126 if (link_relevant(l, AF_INET6, true) &&
127 l->llmnr_support != RESOLVE_SUPPORT_NO &&
128 l->manager->llmnr_support != RESOLVE_SUPPORT_NO &&
129 socket_ipv6_is_supported()) {
130 if (!l->llmnr_ipv6_scope) {
131 r = dns_scope_new(l->manager, &l->llmnr_ipv6_scope, l, DNS_PROTOCOL_LLMNR, AF_INET6);
132 if (r < 0)
133 log_warning_errno(r, "Failed to allocate LLMNR IPv6 scope: %m");
134 }
135 } else
136 l->llmnr_ipv6_scope = dns_scope_free(l->llmnr_ipv6_scope);
137
138 if (link_relevant(l, AF_INET, true) &&
139 l->mdns_support != RESOLVE_SUPPORT_NO &&
140 l->manager->mdns_support != RESOLVE_SUPPORT_NO) {
141 if (!l->mdns_ipv4_scope) {
142 r = dns_scope_new(l->manager, &l->mdns_ipv4_scope, l, DNS_PROTOCOL_MDNS, AF_INET);
143 if (r < 0)
144 log_warning_errno(r, "Failed to allocate mDNS IPv4 scope: %m");
145 }
146 } else
147 l->mdns_ipv4_scope = dns_scope_free(l->mdns_ipv4_scope);
148
149 if (link_relevant(l, AF_INET6, true) &&
150 l->mdns_support != RESOLVE_SUPPORT_NO &&
151 l->manager->mdns_support != RESOLVE_SUPPORT_NO) {
152 if (!l->mdns_ipv6_scope) {
153 r = dns_scope_new(l->manager, &l->mdns_ipv6_scope, l, DNS_PROTOCOL_MDNS, AF_INET6);
154 if (r < 0)
155 log_warning_errno(r, "Failed to allocate mDNS IPv6 scope: %m");
156 }
157 } else
158 l->mdns_ipv6_scope = dns_scope_free(l->mdns_ipv6_scope);
159 }
160
161 void link_add_rrs(Link *l, bool force_remove) {
162 LinkAddress *a;
163
164 LIST_FOREACH(addresses, a, l->addresses)
165 link_address_add_rrs(a, force_remove);
166 }
167
168 int link_update_rtnl(Link *l, sd_netlink_message *m) {
169 const char *n = NULL;
170 int r;
171
172 assert(l);
173 assert(m);
174
175 r = sd_rtnl_message_link_get_flags(m, &l->flags);
176 if (r < 0)
177 return r;
178
179 (void) sd_netlink_message_read_u32(m, IFLA_MTU, &l->mtu);
180 (void) sd_netlink_message_read_u8(m, IFLA_OPERSTATE, &l->operstate);
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_domain_one(Link *l, const char *name, bool route_only) {
379 DnsSearchDomain *d;
380 int r;
381
382 r = dns_search_domain_find(l->search_domains, name, &d);
383 if (r < 0)
384 return r;
385 if (r > 0)
386 dns_search_domain_move_back_and_unmark(d);
387 else {
388 r = dns_search_domain_new(l->manager, &d, DNS_SEARCH_DOMAIN_LINK, l, name);
389 if (r < 0)
390 return r;
391 }
392
393 d->route_only = route_only;
394 return 0;
395 }
396
397 static int link_update_search_domains(Link *l) {
398 _cleanup_strv_free_ char **sdomains = NULL, **rdomains = NULL;
399 char **i;
400 int r, q;
401
402 assert(l);
403
404 r = sd_network_link_get_search_domains(l->ifindex, &sdomains);
405 if (r < 0 && r != -ENODATA)
406 goto clear;
407
408 q = sd_network_link_get_route_domains(l->ifindex, &rdomains);
409 if (q < 0 && q != -ENODATA) {
410 r = q;
411 goto clear;
412 }
413
414 if (r == -ENODATA && q == -ENODATA) {
415 /* networkd knows nothing about this interface, and that's fine. */
416 r = 0;
417 goto clear;
418 }
419
420 dns_search_domain_mark_all(l->search_domains);
421
422 STRV_FOREACH(i, sdomains) {
423 r = link_update_search_domain_one(l, *i, false);
424 if (r < 0)
425 goto clear;
426 }
427
428 STRV_FOREACH(i, rdomains) {
429 r = link_update_search_domain_one(l, *i, true);
430 if (r < 0)
431 goto clear;
432 }
433
434 dns_search_domain_unlink_marked(l->search_domains);
435 return 0;
436
437 clear:
438 dns_search_domain_unlink_all(l->search_domains);
439 return r;
440 }
441
442 static int link_is_unmanaged(Link *l) {
443 _cleanup_free_ char *state = NULL;
444 int r;
445
446 assert(l);
447
448 r = sd_network_link_get_setup_state(l->ifindex, &state);
449 if (r == -ENODATA)
450 return 1;
451 if (r < 0)
452 return r;
453
454 return STR_IN_SET(state, "pending", "unmanaged");
455 }
456
457 static void link_read_settings(Link *l) {
458 int r;
459
460 assert(l);
461
462 /* Read settings from networkd, except when networkd is not managing this interface. */
463
464 r = link_is_unmanaged(l);
465 if (r < 0) {
466 log_warning_errno(r, "Failed to determine whether interface %s is managed: %m", l->name);
467 return;
468 }
469 if (r > 0) {
470
471 /* If this link used to be managed, but is now unmanaged, flush all our settings — but only once. */
472 if (l->is_managed)
473 link_flush_settings(l);
474
475 l->is_managed = false;
476 return;
477 }
478
479 l->is_managed = true;
480
481 r = link_update_dns_servers(l);
482 if (r < 0)
483 log_warning_errno(r, "Failed to read DNS servers for interface %s, ignoring: %m", l->name);
484
485 r = link_update_llmnr_support(l);
486 if (r < 0)
487 log_warning_errno(r, "Failed to read LLMNR support for interface %s, ignoring: %m", l->name);
488
489 r = link_update_mdns_support(l);
490 if (r < 0)
491 log_warning_errno(r, "Failed to read mDNS support for interface %s, ignoring: %m", l->name);
492
493 r = link_update_dnssec_mode(l);
494 if (r < 0)
495 log_warning_errno(r, "Failed to read DNSSEC mode for interface %s, ignoring: %m", l->name);
496
497 r = link_update_dnssec_negative_trust_anchors(l);
498 if (r < 0)
499 log_warning_errno(r, "Failed to read DNSSEC negative trust anchors for interface %s, ignoring: %m", l->name);
500
501 r = link_update_search_domains(l);
502 if (r < 0)
503 log_warning_errno(r, "Failed to read search domains for interface %s, ignoring: %m", l->name);
504 }
505
506 int link_update_monitor(Link *l) {
507 assert(l);
508
509 link_read_settings(l);
510 link_allocate_scopes(l);
511 link_add_rrs(l, false);
512
513 return 0;
514 }
515
516 bool link_relevant(Link *l, int family, bool local_multicast) {
517 _cleanup_free_ char *state = NULL;
518 LinkAddress *a;
519
520 assert(l);
521
522 /* A link is relevant for local multicast traffic if it isn't a loopback or pointopoint device, has a link
523 * beat, can do multicast and has at least one link-local (or better) IP address.
524 *
525 * A link is relevant for non-multicast traffic if it isn't a loopback device, has a link beat, and has at
526 * least one routable address.*/
527
528 if (l->flags & (IFF_LOOPBACK|IFF_DORMANT))
529 return false;
530
531 if ((l->flags & (IFF_UP|IFF_LOWER_UP)) != (IFF_UP|IFF_LOWER_UP))
532 return false;
533
534 if (local_multicast) {
535 if (l->flags & IFF_POINTOPOINT)
536 return false;
537
538 if ((l->flags & IFF_MULTICAST) != IFF_MULTICAST)
539 return false;
540 }
541
542 /* Check kernel operstate
543 * https://www.kernel.org/doc/Documentation/networking/operstates.txt */
544 if (!IN_SET(l->operstate, IF_OPER_UNKNOWN, IF_OPER_UP))
545 return false;
546
547 (void) sd_network_link_get_operational_state(l->ifindex, &state);
548 if (state && !STR_IN_SET(state, "unknown", "degraded", "routable"))
549 return false;
550
551 LIST_FOREACH(addresses, a, l->addresses)
552 if ((family == AF_UNSPEC || a->family == family) && link_address_relevant(a, local_multicast))
553 return true;
554
555 return false;
556 }
557
558 LinkAddress *link_find_address(Link *l, int family, const union in_addr_union *in_addr) {
559 LinkAddress *a;
560
561 assert(l);
562
563 LIST_FOREACH(addresses, a, l->addresses)
564 if (a->family == family && in_addr_equal(family, &a->in_addr, in_addr))
565 return a;
566
567 return NULL;
568 }
569
570 DnsServer* link_set_dns_server(Link *l, DnsServer *s) {
571 assert(l);
572
573 if (l->current_dns_server == s)
574 return s;
575
576 if (s)
577 log_info("Switching to DNS server %s for interface %s.", dns_server_string(s), l->name);
578
579 dns_server_unref(l->current_dns_server);
580 l->current_dns_server = dns_server_ref(s);
581
582 if (l->unicast_scope)
583 dns_cache_flush(&l->unicast_scope->cache);
584
585 return s;
586 }
587
588 DnsServer *link_get_dns_server(Link *l) {
589 assert(l);
590
591 if (!l->current_dns_server)
592 link_set_dns_server(l, l->dns_servers);
593
594 return l->current_dns_server;
595 }
596
597 void link_next_dns_server(Link *l) {
598 assert(l);
599
600 if (!l->current_dns_server)
601 return;
602
603 /* Change to the next one, but make sure to follow the linked
604 * list only if this server is actually still linked. */
605 if (l->current_dns_server->linked && l->current_dns_server->servers_next) {
606 link_set_dns_server(l, l->current_dns_server->servers_next);
607 return;
608 }
609
610 link_set_dns_server(l, l->dns_servers);
611 }
612
613 DnssecMode link_get_dnssec_mode(Link *l) {
614 assert(l);
615
616 if (l->dnssec_mode != _DNSSEC_MODE_INVALID)
617 return l->dnssec_mode;
618
619 return manager_get_dnssec_mode(l->manager);
620 }
621
622 bool link_dnssec_supported(Link *l) {
623 DnsServer *server;
624
625 assert(l);
626
627 if (link_get_dnssec_mode(l) == DNSSEC_NO)
628 return false;
629
630 server = link_get_dns_server(l);
631 if (server)
632 return dns_server_dnssec_supported(server);
633
634 return true;
635 }
636
637 int link_address_new(Link *l, LinkAddress **ret, int family, const union in_addr_union *in_addr) {
638 LinkAddress *a;
639
640 assert(l);
641 assert(in_addr);
642
643 a = new0(LinkAddress, 1);
644 if (!a)
645 return -ENOMEM;
646
647 a->family = family;
648 a->in_addr = *in_addr;
649
650 a->link = l;
651 LIST_PREPEND(addresses, l->addresses, a);
652
653 if (ret)
654 *ret = a;
655
656 return 0;
657 }
658
659 LinkAddress *link_address_free(LinkAddress *a) {
660 if (!a)
661 return NULL;
662
663 if (a->link) {
664 LIST_REMOVE(addresses, a->link->addresses, a);
665
666 if (a->llmnr_address_rr) {
667 if (a->family == AF_INET && a->link->llmnr_ipv4_scope)
668 dns_zone_remove_rr(&a->link->llmnr_ipv4_scope->zone, a->llmnr_address_rr);
669 else if (a->family == AF_INET6 && a->link->llmnr_ipv6_scope)
670 dns_zone_remove_rr(&a->link->llmnr_ipv6_scope->zone, a->llmnr_address_rr);
671 }
672
673 if (a->llmnr_ptr_rr) {
674 if (a->family == AF_INET && a->link->llmnr_ipv4_scope)
675 dns_zone_remove_rr(&a->link->llmnr_ipv4_scope->zone, a->llmnr_ptr_rr);
676 else if (a->family == AF_INET6 && a->link->llmnr_ipv6_scope)
677 dns_zone_remove_rr(&a->link->llmnr_ipv6_scope->zone, a->llmnr_ptr_rr);
678 }
679 }
680
681 dns_resource_record_unref(a->llmnr_address_rr);
682 dns_resource_record_unref(a->llmnr_ptr_rr);
683
684 free(a);
685 return NULL;
686 }
687
688 void link_address_add_rrs(LinkAddress *a, bool force_remove) {
689 int r;
690
691 assert(a);
692
693 if (a->family == AF_INET) {
694
695 if (!force_remove &&
696 link_address_relevant(a, true) &&
697 a->link->llmnr_ipv4_scope &&
698 a->link->llmnr_support == RESOLVE_SUPPORT_YES &&
699 a->link->manager->llmnr_support == RESOLVE_SUPPORT_YES) {
700
701 if (!a->link->manager->llmnr_host_ipv4_key) {
702 a->link->manager->llmnr_host_ipv4_key = dns_resource_key_new(DNS_CLASS_IN, DNS_TYPE_A, a->link->manager->llmnr_hostname);
703 if (!a->link->manager->llmnr_host_ipv4_key) {
704 r = -ENOMEM;
705 goto fail;
706 }
707 }
708
709 if (!a->llmnr_address_rr) {
710 a->llmnr_address_rr = dns_resource_record_new(a->link->manager->llmnr_host_ipv4_key);
711 if (!a->llmnr_address_rr) {
712 r = -ENOMEM;
713 goto fail;
714 }
715
716 a->llmnr_address_rr->a.in_addr = a->in_addr.in;
717 a->llmnr_address_rr->ttl = LLMNR_DEFAULT_TTL;
718 }
719
720 if (!a->llmnr_ptr_rr) {
721 r = dns_resource_record_new_reverse(&a->llmnr_ptr_rr, a->family, &a->in_addr, a->link->manager->llmnr_hostname);
722 if (r < 0)
723 goto fail;
724
725 a->llmnr_ptr_rr->ttl = LLMNR_DEFAULT_TTL;
726 }
727
728 r = dns_zone_put(&a->link->llmnr_ipv4_scope->zone, a->link->llmnr_ipv4_scope, a->llmnr_address_rr, true);
729 if (r < 0)
730 log_warning_errno(r, "Failed to add A record to LLMNR zone: %m");
731
732 r = dns_zone_put(&a->link->llmnr_ipv4_scope->zone, a->link->llmnr_ipv4_scope, a->llmnr_ptr_rr, false);
733 if (r < 0)
734 log_warning_errno(r, "Failed to add IPv6 PTR record to LLMNR zone: %m");
735 } else {
736 if (a->llmnr_address_rr) {
737 if (a->link->llmnr_ipv4_scope)
738 dns_zone_remove_rr(&a->link->llmnr_ipv4_scope->zone, a->llmnr_address_rr);
739 a->llmnr_address_rr = dns_resource_record_unref(a->llmnr_address_rr);
740 }
741
742 if (a->llmnr_ptr_rr) {
743 if (a->link->llmnr_ipv4_scope)
744 dns_zone_remove_rr(&a->link->llmnr_ipv4_scope->zone, a->llmnr_ptr_rr);
745 a->llmnr_ptr_rr = dns_resource_record_unref(a->llmnr_ptr_rr);
746 }
747 }
748 }
749
750 if (a->family == AF_INET6) {
751
752 if (!force_remove &&
753 link_address_relevant(a, true) &&
754 a->link->llmnr_ipv6_scope &&
755 a->link->llmnr_support == RESOLVE_SUPPORT_YES &&
756 a->link->manager->llmnr_support == RESOLVE_SUPPORT_YES) {
757
758 if (!a->link->manager->llmnr_host_ipv6_key) {
759 a->link->manager->llmnr_host_ipv6_key = dns_resource_key_new(DNS_CLASS_IN, DNS_TYPE_AAAA, a->link->manager->llmnr_hostname);
760 if (!a->link->manager->llmnr_host_ipv6_key) {
761 r = -ENOMEM;
762 goto fail;
763 }
764 }
765
766 if (!a->llmnr_address_rr) {
767 a->llmnr_address_rr = dns_resource_record_new(a->link->manager->llmnr_host_ipv6_key);
768 if (!a->llmnr_address_rr) {
769 r = -ENOMEM;
770 goto fail;
771 }
772
773 a->llmnr_address_rr->aaaa.in6_addr = a->in_addr.in6;
774 a->llmnr_address_rr->ttl = LLMNR_DEFAULT_TTL;
775 }
776
777 if (!a->llmnr_ptr_rr) {
778 r = dns_resource_record_new_reverse(&a->llmnr_ptr_rr, a->family, &a->in_addr, a->link->manager->llmnr_hostname);
779 if (r < 0)
780 goto fail;
781
782 a->llmnr_ptr_rr->ttl = LLMNR_DEFAULT_TTL;
783 }
784
785 r = dns_zone_put(&a->link->llmnr_ipv6_scope->zone, a->link->llmnr_ipv6_scope, a->llmnr_address_rr, true);
786 if (r < 0)
787 log_warning_errno(r, "Failed to add AAAA record to LLMNR zone: %m");
788
789 r = dns_zone_put(&a->link->llmnr_ipv6_scope->zone, a->link->llmnr_ipv6_scope, a->llmnr_ptr_rr, false);
790 if (r < 0)
791 log_warning_errno(r, "Failed to add IPv6 PTR record to LLMNR zone: %m");
792 } else {
793 if (a->llmnr_address_rr) {
794 if (a->link->llmnr_ipv6_scope)
795 dns_zone_remove_rr(&a->link->llmnr_ipv6_scope->zone, a->llmnr_address_rr);
796 a->llmnr_address_rr = dns_resource_record_unref(a->llmnr_address_rr);
797 }
798
799 if (a->llmnr_ptr_rr) {
800 if (a->link->llmnr_ipv6_scope)
801 dns_zone_remove_rr(&a->link->llmnr_ipv6_scope->zone, a->llmnr_ptr_rr);
802 a->llmnr_ptr_rr = dns_resource_record_unref(a->llmnr_ptr_rr);
803 }
804 }
805 }
806
807 return;
808
809 fail:
810 log_debug_errno(r, "Failed to update address RRs: %m");
811 }
812
813 int link_address_update_rtnl(LinkAddress *a, sd_netlink_message *m) {
814 int r;
815 assert(a);
816 assert(m);
817
818 r = sd_rtnl_message_addr_get_flags(m, &a->flags);
819 if (r < 0)
820 return r;
821
822 sd_rtnl_message_addr_get_scope(m, &a->scope);
823
824 link_allocate_scopes(a->link);
825 link_add_rrs(a->link, false);
826
827 return 0;
828 }
829
830 bool link_address_relevant(LinkAddress *a, bool local_multicast) {
831 assert(a);
832
833 if (a->flags & (IFA_F_DEPRECATED|IFA_F_TENTATIVE))
834 return false;
835
836 if (a->scope >= (local_multicast ? RT_SCOPE_HOST : RT_SCOPE_LINK))
837 return false;
838
839 return true;
840 }