]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/resolve/resolved-link.c
Merge pull request #2424 from keszybz/journald-disk-usage
[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_domains(Link *l) {
381 _cleanup_strv_free_ char **domains = NULL;
382 char **i;
383 int r;
384
385 assert(l);
386
387 r = sd_network_link_get_domains(l->ifindex, &domains);
388 if (r == -ENODATA) {
389 /* networkd knows nothing about this interface, and that's fine. */
390 r = 0;
391 goto clear;
392 }
393 if (r < 0)
394 goto clear;
395
396 dns_search_domain_mark_all(l->search_domains);
397
398 STRV_FOREACH(i, domains) {
399 DnsSearchDomain *d;
400
401 r = dns_search_domain_find(l->search_domains, *i, &d);
402 if (r < 0)
403 goto clear;
404
405 if (r > 0)
406 dns_search_domain_move_back_and_unmark(d);
407 else {
408 r = dns_search_domain_new(l->manager, NULL, DNS_SEARCH_DOMAIN_LINK, l, *i);
409 if (r < 0)
410 goto clear;
411 }
412 }
413
414 dns_search_domain_unlink_marked(l->search_domains);
415 return 0;
416
417 clear:
418 dns_search_domain_unlink_all(l->search_domains);
419 return r;
420 }
421
422 static int link_is_unmanaged(Link *l) {
423 _cleanup_free_ char *state = NULL;
424 int r;
425
426 assert(l);
427
428 r = sd_network_link_get_setup_state(l->ifindex, &state);
429 if (r == -ENODATA)
430 return 1;
431 if (r < 0)
432 return r;
433
434 return STR_IN_SET(state, "pending", "unmanaged");
435 }
436
437 static void link_read_settings(Link *l) {
438 int r;
439
440 assert(l);
441
442 /* Read settings from networkd, except when networkd is not managing this interface. */
443
444 r = link_is_unmanaged(l);
445 if (r < 0) {
446 log_warning_errno(r, "Failed to determine whether interface %s is managed: %m", l->name);
447 return;
448 }
449 if (r > 0) {
450
451 /* If this link used to be managed, but is now unmanaged, flush all our settings -- but only once. */
452 if (l->is_managed)
453 link_flush_settings(l);
454
455 l->is_managed = false;
456 return;
457 }
458
459 l->is_managed = true;
460
461 r = link_update_dns_servers(l);
462 if (r < 0)
463 log_warning_errno(r, "Failed to read DNS servers for interface %s, ignoring: %m", l->name);
464
465 r = link_update_llmnr_support(l);
466 if (r < 0)
467 log_warning_errno(r, "Failed to read LLMNR support for interface %s, ignoring: %m", l->name);
468
469 r = link_update_mdns_support(l);
470 if (r < 0)
471 log_warning_errno(r, "Failed to read mDNS support for interface %s, ignoring: %m", l->name);
472
473 r = link_update_dnssec_mode(l);
474 if (r < 0)
475 log_warning_errno(r, "Failed to read DNSSEC mode for interface %s, ignoring: %m", l->name);
476
477 r = link_update_dnssec_negative_trust_anchors(l);
478 if (r < 0)
479 log_warning_errno(r, "Failed to read DNSSEC negative trust anchors for interface %s, ignoring: %m", l->name);
480
481 r = link_update_search_domains(l);
482 if (r < 0)
483 log_warning_errno(r, "Failed to read search domains for interface %s, ignoring: %m", l->name);
484 }
485
486 int link_update_monitor(Link *l) {
487 assert(l);
488
489 link_read_settings(l);
490 link_allocate_scopes(l);
491 link_add_rrs(l, false);
492
493 return 0;
494 }
495
496 bool link_relevant(Link *l, int family, bool multicast) {
497 _cleanup_free_ char *state = NULL;
498 LinkAddress *a;
499
500 assert(l);
501
502 /* A link is relevant for multicast traffic if it isn't a loopback or pointopoint device, has a link beat, can
503 * do multicast and has at least one relevant IP address */
504
505 if (l->flags & (IFF_LOOPBACK|IFF_DORMANT))
506 return false;
507
508 if ((l->flags & (IFF_UP|IFF_LOWER_UP)) != (IFF_UP|IFF_LOWER_UP))
509 return false;
510
511 if (multicast) {
512 if (l->flags & IFF_POINTOPOINT)
513 return false;
514
515 if ((l->flags & IFF_MULTICAST) != IFF_MULTICAST)
516 return false;
517 }
518
519 /* Check kernel operstate
520 * https://www.kernel.org/doc/Documentation/networking/operstates.txt */
521 if (!IN_SET(l->operstate, IF_OPER_UNKNOWN, IF_OPER_UP))
522 return false;
523
524 (void) sd_network_link_get_operational_state(l->ifindex, &state);
525 if (state && !STR_IN_SET(state, "unknown", "degraded", "routable"))
526 return false;
527
528 LIST_FOREACH(addresses, a, l->addresses)
529 if ((family == AF_UNSPEC || a->family == family) && link_address_relevant(a))
530 return true;
531
532 return false;
533 }
534
535 LinkAddress *link_find_address(Link *l, int family, const union in_addr_union *in_addr) {
536 LinkAddress *a;
537
538 assert(l);
539
540 LIST_FOREACH(addresses, a, l->addresses)
541 if (a->family == family && in_addr_equal(family, &a->in_addr, in_addr))
542 return a;
543
544 return NULL;
545 }
546
547 DnsServer* link_set_dns_server(Link *l, DnsServer *s) {
548 assert(l);
549
550 if (l->current_dns_server == s)
551 return s;
552
553 if (s)
554 log_info("Switching to DNS server %s for interface %s.", dns_server_string(s), l->name);
555
556 dns_server_unref(l->current_dns_server);
557 l->current_dns_server = dns_server_ref(s);
558
559 if (l->unicast_scope)
560 dns_cache_flush(&l->unicast_scope->cache);
561
562 return s;
563 }
564
565 DnsServer *link_get_dns_server(Link *l) {
566 assert(l);
567
568 if (!l->current_dns_server)
569 link_set_dns_server(l, l->dns_servers);
570
571 return l->current_dns_server;
572 }
573
574 void link_next_dns_server(Link *l) {
575 assert(l);
576
577 if (!l->current_dns_server)
578 return;
579
580 /* Change to the next one, but make sure to follow the linked
581 * list only if this server is actually still linked. */
582 if (l->current_dns_server->linked && l->current_dns_server->servers_next) {
583 link_set_dns_server(l, l->current_dns_server->servers_next);
584 return;
585 }
586
587 link_set_dns_server(l, l->dns_servers);
588 }
589
590 DnssecMode link_get_dnssec_mode(Link *l) {
591 assert(l);
592
593 if (l->dnssec_mode != _DNSSEC_MODE_INVALID)
594 return l->dnssec_mode;
595
596 return manager_get_dnssec_mode(l->manager);
597 }
598
599 bool link_dnssec_supported(Link *l) {
600 DnsServer *server;
601
602 assert(l);
603
604 if (link_get_dnssec_mode(l) == DNSSEC_NO)
605 return false;
606
607 server = link_get_dns_server(l);
608 if (server)
609 return dns_server_dnssec_supported(server);
610
611 return true;
612 }
613
614 int link_address_new(Link *l, LinkAddress **ret, int family, const union in_addr_union *in_addr) {
615 LinkAddress *a;
616
617 assert(l);
618 assert(in_addr);
619
620 a = new0(LinkAddress, 1);
621 if (!a)
622 return -ENOMEM;
623
624 a->family = family;
625 a->in_addr = *in_addr;
626
627 a->link = l;
628 LIST_PREPEND(addresses, l->addresses, a);
629
630 if (ret)
631 *ret = a;
632
633 return 0;
634 }
635
636 LinkAddress *link_address_free(LinkAddress *a) {
637 if (!a)
638 return NULL;
639
640 if (a->link) {
641 LIST_REMOVE(addresses, a->link->addresses, a);
642
643 if (a->llmnr_address_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_address_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_address_rr);
648 }
649
650 if (a->llmnr_ptr_rr) {
651 if (a->family == AF_INET && a->link->llmnr_ipv4_scope)
652 dns_zone_remove_rr(&a->link->llmnr_ipv4_scope->zone, a->llmnr_ptr_rr);
653 else if (a->family == AF_INET6 && a->link->llmnr_ipv6_scope)
654 dns_zone_remove_rr(&a->link->llmnr_ipv6_scope->zone, a->llmnr_ptr_rr);
655 }
656 }
657
658 dns_resource_record_unref(a->llmnr_address_rr);
659 dns_resource_record_unref(a->llmnr_ptr_rr);
660
661 free(a);
662 return NULL;
663 }
664
665 void link_address_add_rrs(LinkAddress *a, bool force_remove) {
666 int r;
667
668 assert(a);
669
670 if (a->family == AF_INET) {
671
672 if (!force_remove &&
673 link_address_relevant(a) &&
674 a->link->llmnr_ipv4_scope &&
675 a->link->llmnr_support == RESOLVE_SUPPORT_YES &&
676 a->link->manager->llmnr_support == RESOLVE_SUPPORT_YES) {
677
678 if (!a->link->manager->llmnr_host_ipv4_key) {
679 a->link->manager->llmnr_host_ipv4_key = dns_resource_key_new(DNS_CLASS_IN, DNS_TYPE_A, a->link->manager->llmnr_hostname);
680 if (!a->link->manager->llmnr_host_ipv4_key) {
681 r = -ENOMEM;
682 goto fail;
683 }
684 }
685
686 if (!a->llmnr_address_rr) {
687 a->llmnr_address_rr = dns_resource_record_new(a->link->manager->llmnr_host_ipv4_key);
688 if (!a->llmnr_address_rr) {
689 r = -ENOMEM;
690 goto fail;
691 }
692
693 a->llmnr_address_rr->a.in_addr = a->in_addr.in;
694 a->llmnr_address_rr->ttl = LLMNR_DEFAULT_TTL;
695 }
696
697 if (!a->llmnr_ptr_rr) {
698 r = dns_resource_record_new_reverse(&a->llmnr_ptr_rr, a->family, &a->in_addr, a->link->manager->llmnr_hostname);
699 if (r < 0)
700 goto fail;
701
702 a->llmnr_ptr_rr->ttl = LLMNR_DEFAULT_TTL;
703 }
704
705 r = dns_zone_put(&a->link->llmnr_ipv4_scope->zone, a->link->llmnr_ipv4_scope, a->llmnr_address_rr, true);
706 if (r < 0)
707 log_warning_errno(r, "Failed to add A record to LLMNR zone: %m");
708
709 r = dns_zone_put(&a->link->llmnr_ipv4_scope->zone, a->link->llmnr_ipv4_scope, a->llmnr_ptr_rr, false);
710 if (r < 0)
711 log_warning_errno(r, "Failed to add IPv6 PTR record to LLMNR zone: %m");
712 } else {
713 if (a->llmnr_address_rr) {
714 if (a->link->llmnr_ipv4_scope)
715 dns_zone_remove_rr(&a->link->llmnr_ipv4_scope->zone, a->llmnr_address_rr);
716 a->llmnr_address_rr = dns_resource_record_unref(a->llmnr_address_rr);
717 }
718
719 if (a->llmnr_ptr_rr) {
720 if (a->link->llmnr_ipv4_scope)
721 dns_zone_remove_rr(&a->link->llmnr_ipv4_scope->zone, a->llmnr_ptr_rr);
722 a->llmnr_ptr_rr = dns_resource_record_unref(a->llmnr_ptr_rr);
723 }
724 }
725 }
726
727 if (a->family == AF_INET6) {
728
729 if (!force_remove &&
730 link_address_relevant(a) &&
731 a->link->llmnr_ipv6_scope &&
732 a->link->llmnr_support == RESOLVE_SUPPORT_YES &&
733 a->link->manager->llmnr_support == RESOLVE_SUPPORT_YES) {
734
735 if (!a->link->manager->llmnr_host_ipv6_key) {
736 a->link->manager->llmnr_host_ipv6_key = dns_resource_key_new(DNS_CLASS_IN, DNS_TYPE_AAAA, a->link->manager->llmnr_hostname);
737 if (!a->link->manager->llmnr_host_ipv6_key) {
738 r = -ENOMEM;
739 goto fail;
740 }
741 }
742
743 if (!a->llmnr_address_rr) {
744 a->llmnr_address_rr = dns_resource_record_new(a->link->manager->llmnr_host_ipv6_key);
745 if (!a->llmnr_address_rr) {
746 r = -ENOMEM;
747 goto fail;
748 }
749
750 a->llmnr_address_rr->aaaa.in6_addr = a->in_addr.in6;
751 a->llmnr_address_rr->ttl = LLMNR_DEFAULT_TTL;
752 }
753
754 if (!a->llmnr_ptr_rr) {
755 r = dns_resource_record_new_reverse(&a->llmnr_ptr_rr, a->family, &a->in_addr, a->link->manager->llmnr_hostname);
756 if (r < 0)
757 goto fail;
758
759 a->llmnr_ptr_rr->ttl = LLMNR_DEFAULT_TTL;
760 }
761
762 r = dns_zone_put(&a->link->llmnr_ipv6_scope->zone, a->link->llmnr_ipv6_scope, a->llmnr_address_rr, true);
763 if (r < 0)
764 log_warning_errno(r, "Failed to add AAAA record to LLMNR zone: %m");
765
766 r = dns_zone_put(&a->link->llmnr_ipv6_scope->zone, a->link->llmnr_ipv6_scope, a->llmnr_ptr_rr, false);
767 if (r < 0)
768 log_warning_errno(r, "Failed to add IPv6 PTR record to LLMNR zone: %m");
769 } else {
770 if (a->llmnr_address_rr) {
771 if (a->link->llmnr_ipv6_scope)
772 dns_zone_remove_rr(&a->link->llmnr_ipv6_scope->zone, a->llmnr_address_rr);
773 a->llmnr_address_rr = dns_resource_record_unref(a->llmnr_address_rr);
774 }
775
776 if (a->llmnr_ptr_rr) {
777 if (a->link->llmnr_ipv6_scope)
778 dns_zone_remove_rr(&a->link->llmnr_ipv6_scope->zone, a->llmnr_ptr_rr);
779 a->llmnr_ptr_rr = dns_resource_record_unref(a->llmnr_ptr_rr);
780 }
781 }
782 }
783
784 return;
785
786 fail:
787 log_debug_errno(r, "Failed to update address RRs: %m");
788 }
789
790 int link_address_update_rtnl(LinkAddress *a, sd_netlink_message *m) {
791 int r;
792 assert(a);
793 assert(m);
794
795 r = sd_rtnl_message_addr_get_flags(m, &a->flags);
796 if (r < 0)
797 return r;
798
799 sd_rtnl_message_addr_get_scope(m, &a->scope);
800
801 link_allocate_scopes(a->link);
802 link_add_rrs(a->link, false);
803
804 return 0;
805 }
806
807 bool link_address_relevant(LinkAddress *a) {
808 assert(a);
809
810 if (a->flags & (IFA_F_DEPRECATED|IFA_F_TENTATIVE))
811 return false;
812
813 if (IN_SET(a->scope, RT_SCOPE_HOST, RT_SCOPE_NOWHERE))
814 return false;
815
816 return true;
817 }