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