]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/resolve/resolved-link.c
Merge pull request #6274 from keszybz/etags-ctags
[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 "fd-util.h"
26 #include "fileio.h"
27 #include "missing.h"
28 #include "mkdir.h"
29 #include "parse-util.h"
30 #include "resolved-link.h"
31 #include "resolved-llmnr.h"
32 #include "resolved-mdns.h"
33 #include "string-util.h"
34 #include "strv.h"
35
36 int link_new(Manager *m, Link **ret, int ifindex) {
37 _cleanup_(link_freep) Link *l = NULL;
38 int r;
39
40 assert(m);
41 assert(ifindex > 0);
42
43 r = hashmap_ensure_allocated(&m->links, NULL);
44 if (r < 0)
45 return r;
46
47 l = new0(Link, 1);
48 if (!l)
49 return -ENOMEM;
50
51 l->ifindex = ifindex;
52 l->llmnr_support = RESOLVE_SUPPORT_YES;
53 l->mdns_support = RESOLVE_SUPPORT_NO;
54 l->dnssec_mode = _DNSSEC_MODE_INVALID;
55 l->operstate = IF_OPER_UNKNOWN;
56
57 if (asprintf(&l->state_file, "/run/systemd/resolve/netif/%i", ifindex) < 0)
58 return -ENOMEM;
59
60 r = hashmap_put(m->links, INT_TO_PTR(ifindex), l);
61 if (r < 0)
62 return r;
63
64 l->manager = m;
65
66 if (ret)
67 *ret = l;
68 l = NULL;
69
70 return 0;
71 }
72
73 void link_flush_settings(Link *l) {
74 assert(l);
75
76 l->llmnr_support = RESOLVE_SUPPORT_YES;
77 l->mdns_support = RESOLVE_SUPPORT_NO;
78 l->dnssec_mode = _DNSSEC_MODE_INVALID;
79
80 dns_server_unlink_all(l->dns_servers);
81 dns_search_domain_unlink_all(l->search_domains);
82
83 l->dnssec_negative_trust_anchors = set_free_free(l->dnssec_negative_trust_anchors);
84 }
85
86 Link *link_free(Link *l) {
87 if (!l)
88 return NULL;
89
90 /* Send goodbye messages. */
91 dns_scope_announce(l->mdns_ipv4_scope, true);
92 dns_scope_announce(l->mdns_ipv6_scope, true);
93
94 link_flush_settings(l);
95
96 while (l->addresses)
97 (void) link_address_free(l->addresses);
98
99 if (l->manager)
100 hashmap_remove(l->manager->links, INT_TO_PTR(l->ifindex));
101
102 dns_scope_free(l->unicast_scope);
103 dns_scope_free(l->llmnr_ipv4_scope);
104 dns_scope_free(l->llmnr_ipv6_scope);
105 dns_scope_free(l->mdns_ipv4_scope);
106 dns_scope_free(l->mdns_ipv6_scope);
107
108 free(l->state_file);
109
110 return mfree(l);
111 }
112
113 void link_allocate_scopes(Link *l) {
114 int r;
115
116 assert(l);
117
118 if (link_relevant(l, AF_UNSPEC, false) &&
119 l->dns_servers) {
120 if (!l->unicast_scope) {
121 r = dns_scope_new(l->manager, &l->unicast_scope, l, DNS_PROTOCOL_DNS, AF_UNSPEC);
122 if (r < 0)
123 log_warning_errno(r, "Failed to allocate DNS scope: %m");
124 }
125 } else
126 l->unicast_scope = dns_scope_free(l->unicast_scope);
127
128 if (link_relevant(l, AF_INET, true) &&
129 l->llmnr_support != RESOLVE_SUPPORT_NO &&
130 l->manager->llmnr_support != RESOLVE_SUPPORT_NO) {
131 if (!l->llmnr_ipv4_scope) {
132 r = dns_scope_new(l->manager, &l->llmnr_ipv4_scope, l, DNS_PROTOCOL_LLMNR, AF_INET);
133 if (r < 0)
134 log_warning_errno(r, "Failed to allocate LLMNR IPv4 scope: %m");
135 }
136 } else
137 l->llmnr_ipv4_scope = dns_scope_free(l->llmnr_ipv4_scope);
138
139 if (link_relevant(l, AF_INET6, true) &&
140 l->llmnr_support != RESOLVE_SUPPORT_NO &&
141 l->manager->llmnr_support != RESOLVE_SUPPORT_NO &&
142 socket_ipv6_is_supported()) {
143 if (!l->llmnr_ipv6_scope) {
144 r = dns_scope_new(l->manager, &l->llmnr_ipv6_scope, l, DNS_PROTOCOL_LLMNR, AF_INET6);
145 if (r < 0)
146 log_warning_errno(r, "Failed to allocate LLMNR IPv6 scope: %m");
147 }
148 } else
149 l->llmnr_ipv6_scope = dns_scope_free(l->llmnr_ipv6_scope);
150
151 if (link_relevant(l, AF_INET, true) &&
152 l->mdns_support != RESOLVE_SUPPORT_NO &&
153 l->manager->mdns_support != RESOLVE_SUPPORT_NO) {
154 if (!l->mdns_ipv4_scope) {
155 r = dns_scope_new(l->manager, &l->mdns_ipv4_scope, l, DNS_PROTOCOL_MDNS, AF_INET);
156 if (r < 0)
157 log_warning_errno(r, "Failed to allocate mDNS IPv4 scope: %m");
158 }
159 } else
160 l->mdns_ipv4_scope = dns_scope_free(l->mdns_ipv4_scope);
161
162 if (link_relevant(l, AF_INET6, true) &&
163 l->mdns_support != RESOLVE_SUPPORT_NO &&
164 l->manager->mdns_support != RESOLVE_SUPPORT_NO) {
165 if (!l->mdns_ipv6_scope) {
166 r = dns_scope_new(l->manager, &l->mdns_ipv6_scope, l, DNS_PROTOCOL_MDNS, AF_INET6);
167 if (r < 0)
168 log_warning_errno(r, "Failed to allocate mDNS IPv6 scope: %m");
169 }
170 } else
171 l->mdns_ipv6_scope = dns_scope_free(l->mdns_ipv6_scope);
172 }
173
174 void link_add_rrs(Link *l, bool force_remove) {
175 LinkAddress *a;
176
177 LIST_FOREACH(addresses, a, l->addresses)
178 link_address_add_rrs(a, force_remove);
179 }
180
181 int link_process_rtnl(Link *l, sd_netlink_message *m) {
182 const char *n = NULL;
183 int r;
184
185 assert(l);
186 assert(m);
187
188 r = sd_rtnl_message_link_get_flags(m, &l->flags);
189 if (r < 0)
190 return r;
191
192 (void) sd_netlink_message_read_u32(m, IFLA_MTU, &l->mtu);
193 (void) sd_netlink_message_read_u8(m, IFLA_OPERSTATE, &l->operstate);
194
195 if (sd_netlink_message_read_string(m, IFLA_IFNAME, &n) >= 0) {
196 strncpy(l->name, n, sizeof(l->name)-1);
197 char_array_0(l->name);
198 }
199
200 link_allocate_scopes(l);
201 link_add_rrs(l, false);
202
203 return 0;
204 }
205
206 static int link_update_dns_server_one(Link *l, const char *name) {
207 union in_addr_union a;
208 DnsServer *s;
209 int family, r;
210
211 assert(l);
212 assert(name);
213
214 r = in_addr_from_string_auto(name, &family, &a);
215 if (r < 0)
216 return r;
217
218 s = dns_server_find(l->dns_servers, family, &a, 0);
219 if (s) {
220 dns_server_move_back_and_unmark(s);
221 return 0;
222 }
223
224 return dns_server_new(l->manager, NULL, DNS_SERVER_LINK, l, family, &a, 0);
225 }
226
227 static int link_update_dns_servers(Link *l) {
228 _cleanup_strv_free_ char **nameservers = NULL;
229 char **nameserver;
230 int r;
231
232 assert(l);
233
234 r = sd_network_link_get_dns(l->ifindex, &nameservers);
235 if (r == -ENODATA) {
236 r = 0;
237 goto clear;
238 }
239 if (r < 0)
240 goto clear;
241
242 dns_server_mark_all(l->dns_servers);
243
244 STRV_FOREACH(nameserver, nameservers) {
245 r = link_update_dns_server_one(l, *nameserver);
246 if (r < 0)
247 goto clear;
248 }
249
250 dns_server_unlink_marked(l->dns_servers);
251 return 0;
252
253 clear:
254 dns_server_unlink_all(l->dns_servers);
255 return r;
256 }
257
258 static int link_update_llmnr_support(Link *l) {
259 _cleanup_free_ char *b = NULL;
260 int r;
261
262 assert(l);
263
264 r = sd_network_link_get_llmnr(l->ifindex, &b);
265 if (r == -ENODATA) {
266 r = 0;
267 goto clear;
268 }
269 if (r < 0)
270 goto clear;
271
272 l->llmnr_support = resolve_support_from_string(b);
273 if (l->llmnr_support < 0) {
274 r = -EINVAL;
275 goto clear;
276 }
277
278 return 0;
279
280 clear:
281 l->llmnr_support = RESOLVE_SUPPORT_YES;
282 return r;
283 }
284
285 static int link_update_mdns_support(Link *l) {
286 _cleanup_free_ char *b = NULL;
287 int r;
288
289 assert(l);
290
291 r = sd_network_link_get_mdns(l->ifindex, &b);
292 if (r == -ENODATA) {
293 r = 0;
294 goto clear;
295 }
296 if (r < 0)
297 goto clear;
298
299 l->mdns_support = resolve_support_from_string(b);
300 if (l->mdns_support < 0) {
301 r = -EINVAL;
302 goto clear;
303 }
304
305 return 0;
306
307 clear:
308 l->mdns_support = RESOLVE_SUPPORT_NO;
309 return r;
310 }
311
312 void link_set_dnssec_mode(Link *l, DnssecMode mode) {
313
314 assert(l);
315
316 #ifndef HAVE_GCRYPT
317 if (mode == DNSSEC_YES || mode == DNSSEC_ALLOW_DOWNGRADE)
318 log_warning("DNSSEC option for the link cannot be enabled or set to allow-downgrade when systemd-resolved is built without gcrypt support. Turning off DNSSEC support.");
319 return;
320 #endif
321
322 if (l->dnssec_mode == mode)
323 return;
324
325 if ((l->dnssec_mode == _DNSSEC_MODE_INVALID) ||
326 (l->dnssec_mode == DNSSEC_NO && mode != DNSSEC_NO) ||
327 (l->dnssec_mode == DNSSEC_ALLOW_DOWNGRADE && mode == DNSSEC_YES)) {
328
329 /* When switching from non-DNSSEC mode to DNSSEC mode, flush the cache. Also when switching from the
330 * allow-downgrade mode to full DNSSEC mode, flush it too. */
331 if (l->unicast_scope)
332 dns_cache_flush(&l->unicast_scope->cache);
333 }
334
335 l->dnssec_mode = mode;
336 }
337
338 static int link_update_dnssec_mode(Link *l) {
339 _cleanup_free_ char *m = NULL;
340 DnssecMode mode;
341 int r;
342
343 assert(l);
344
345 r = sd_network_link_get_dnssec(l->ifindex, &m);
346 if (r == -ENODATA) {
347 r = 0;
348 goto clear;
349 }
350 if (r < 0)
351 goto clear;
352
353 mode = dnssec_mode_from_string(m);
354 if (mode < 0) {
355 r = -EINVAL;
356 goto clear;
357 }
358
359 link_set_dnssec_mode(l, mode);
360
361 return 0;
362
363 clear:
364 l->dnssec_mode = _DNSSEC_MODE_INVALID;
365 return r;
366 }
367
368 static int link_update_dnssec_negative_trust_anchors(Link *l) {
369 _cleanup_strv_free_ char **ntas = NULL;
370 _cleanup_set_free_free_ Set *ns = NULL;
371 int r;
372
373 assert(l);
374
375 r = sd_network_link_get_dnssec_negative_trust_anchors(l->ifindex, &ntas);
376 if (r == -ENODATA) {
377 r = 0;
378 goto clear;
379 }
380 if (r < 0)
381 goto clear;
382
383 ns = set_new(&dns_name_hash_ops);
384 if (!ns)
385 return -ENOMEM;
386
387 r = set_put_strdupv(ns, ntas);
388 if (r < 0)
389 return r;
390
391 set_free_free(l->dnssec_negative_trust_anchors);
392 l->dnssec_negative_trust_anchors = ns;
393 ns = NULL;
394
395 return 0;
396
397 clear:
398 l->dnssec_negative_trust_anchors = set_free_free(l->dnssec_negative_trust_anchors);
399 return r;
400 }
401
402 static int link_update_search_domain_one(Link *l, const char *name, bool route_only) {
403 DnsSearchDomain *d;
404 int r;
405
406 assert(l);
407 assert(name);
408
409 r = dns_search_domain_find(l->search_domains, name, &d);
410 if (r < 0)
411 return r;
412 if (r > 0)
413 dns_search_domain_move_back_and_unmark(d);
414 else {
415 r = dns_search_domain_new(l->manager, &d, DNS_SEARCH_DOMAIN_LINK, l, name);
416 if (r < 0)
417 return r;
418 }
419
420 d->route_only = route_only;
421 return 0;
422 }
423
424 static int link_update_search_domains(Link *l) {
425 _cleanup_strv_free_ char **sdomains = NULL, **rdomains = NULL;
426 char **i;
427 int r, q;
428
429 assert(l);
430
431 r = sd_network_link_get_search_domains(l->ifindex, &sdomains);
432 if (r < 0 && r != -ENODATA)
433 goto clear;
434
435 q = sd_network_link_get_route_domains(l->ifindex, &rdomains);
436 if (q < 0 && q != -ENODATA) {
437 r = q;
438 goto clear;
439 }
440
441 if (r == -ENODATA && q == -ENODATA) {
442 /* networkd knows nothing about this interface, and that's fine. */
443 r = 0;
444 goto clear;
445 }
446
447 dns_search_domain_mark_all(l->search_domains);
448
449 STRV_FOREACH(i, sdomains) {
450 r = link_update_search_domain_one(l, *i, false);
451 if (r < 0)
452 goto clear;
453 }
454
455 STRV_FOREACH(i, rdomains) {
456 r = link_update_search_domain_one(l, *i, true);
457 if (r < 0)
458 goto clear;
459 }
460
461 dns_search_domain_unlink_marked(l->search_domains);
462 return 0;
463
464 clear:
465 dns_search_domain_unlink_all(l->search_domains);
466 return r;
467 }
468
469 static int link_is_managed(Link *l) {
470 _cleanup_free_ char *state = NULL;
471 int r;
472
473 assert(l);
474
475 r = sd_network_link_get_setup_state(l->ifindex, &state);
476 if (r == -ENODATA)
477 return 0;
478 if (r < 0)
479 return r;
480
481 return !STR_IN_SET(state, "pending", "unmanaged");
482 }
483
484 static void link_read_settings(Link *l) {
485 int r;
486
487 assert(l);
488
489 /* Read settings from networkd, except when networkd is not managing this interface. */
490
491 r = link_is_managed(l);
492 if (r < 0) {
493 log_warning_errno(r, "Failed to determine whether interface %s is managed: %m", l->name);
494 return;
495 }
496 if (r == 0) {
497
498 /* If this link used to be managed, but is now unmanaged, flush all our settings — but only once. */
499 if (l->is_managed)
500 link_flush_settings(l);
501
502 l->is_managed = false;
503 return;
504 }
505
506 l->is_managed = true;
507
508 r = link_update_dns_servers(l);
509 if (r < 0)
510 log_warning_errno(r, "Failed to read DNS servers for interface %s, ignoring: %m", l->name);
511
512 r = link_update_llmnr_support(l);
513 if (r < 0)
514 log_warning_errno(r, "Failed to read LLMNR support for interface %s, ignoring: %m", l->name);
515
516 r = link_update_mdns_support(l);
517 if (r < 0)
518 log_warning_errno(r, "Failed to read mDNS support for interface %s, ignoring: %m", l->name);
519
520 r = link_update_dnssec_mode(l);
521 if (r < 0)
522 log_warning_errno(r, "Failed to read DNSSEC mode for interface %s, ignoring: %m", l->name);
523
524 r = link_update_dnssec_negative_trust_anchors(l);
525 if (r < 0)
526 log_warning_errno(r, "Failed to read DNSSEC negative trust anchors for interface %s, ignoring: %m", l->name);
527
528 r = link_update_search_domains(l);
529 if (r < 0)
530 log_warning_errno(r, "Failed to read search domains for interface %s, ignoring: %m", l->name);
531 }
532
533 int link_update(Link *l) {
534 int r;
535
536 assert(l);
537
538 link_read_settings(l);
539 link_load_user(l);
540
541 if (l->llmnr_support != RESOLVE_SUPPORT_NO) {
542 r = manager_llmnr_start(l->manager);
543 if (r < 0)
544 return r;
545 }
546
547 if (l->mdns_support != RESOLVE_SUPPORT_NO) {
548 r = manager_mdns_start(l->manager);
549 if (r < 0)
550 return r;
551 }
552
553 link_allocate_scopes(l);
554 link_add_rrs(l, false);
555
556 return 0;
557 }
558
559 bool link_relevant(Link *l, int family, bool local_multicast) {
560 _cleanup_free_ char *state = NULL;
561 LinkAddress *a;
562
563 assert(l);
564
565 /* A link is relevant for local multicast traffic if it isn't a loopback or pointopoint device, has a link
566 * beat, can do multicast and has at least one link-local (or better) IP address.
567 *
568 * A link is relevant for non-multicast traffic if it isn't a loopback device, has a link beat, and has at
569 * least one routable address. */
570
571 if (l->flags & (IFF_LOOPBACK|IFF_DORMANT))
572 return false;
573
574 if ((l->flags & (IFF_UP|IFF_LOWER_UP)) != (IFF_UP|IFF_LOWER_UP))
575 return false;
576
577 if (local_multicast) {
578 if (l->flags & IFF_POINTOPOINT)
579 return false;
580
581 if ((l->flags & IFF_MULTICAST) != IFF_MULTICAST)
582 return false;
583 }
584
585 /* Check kernel operstate
586 * https://www.kernel.org/doc/Documentation/networking/operstates.txt */
587 if (!IN_SET(l->operstate, IF_OPER_UNKNOWN, IF_OPER_UP))
588 return false;
589
590 (void) sd_network_link_get_operational_state(l->ifindex, &state);
591 if (state && !STR_IN_SET(state, "unknown", "degraded", "routable"))
592 return false;
593
594 LIST_FOREACH(addresses, a, l->addresses)
595 if ((family == AF_UNSPEC || a->family == family) && link_address_relevant(a, local_multicast))
596 return true;
597
598 return false;
599 }
600
601 LinkAddress *link_find_address(Link *l, int family, const union in_addr_union *in_addr) {
602 LinkAddress *a;
603
604 assert(l);
605
606 LIST_FOREACH(addresses, a, l->addresses)
607 if (a->family == family && in_addr_equal(family, &a->in_addr, in_addr))
608 return a;
609
610 return NULL;
611 }
612
613 DnsServer* link_set_dns_server(Link *l, DnsServer *s) {
614 assert(l);
615
616 if (l->current_dns_server == s)
617 return s;
618
619 if (s)
620 log_debug("Switching to DNS server %s for interface %s.", dns_server_string(s), l->name);
621
622 dns_server_unref(l->current_dns_server);
623 l->current_dns_server = dns_server_ref(s);
624
625 if (l->unicast_scope)
626 dns_cache_flush(&l->unicast_scope->cache);
627
628 return s;
629 }
630
631 DnsServer *link_get_dns_server(Link *l) {
632 assert(l);
633
634 if (!l->current_dns_server)
635 link_set_dns_server(l, l->dns_servers);
636
637 return l->current_dns_server;
638 }
639
640 void link_next_dns_server(Link *l) {
641 assert(l);
642
643 if (!l->current_dns_server)
644 return;
645
646 /* Change to the next one, but make sure to follow the linked
647 * list only if this server is actually still linked. */
648 if (l->current_dns_server->linked && l->current_dns_server->servers_next) {
649 link_set_dns_server(l, l->current_dns_server->servers_next);
650 return;
651 }
652
653 link_set_dns_server(l, l->dns_servers);
654 }
655
656 DnssecMode link_get_dnssec_mode(Link *l) {
657 assert(l);
658
659 if (l->dnssec_mode != _DNSSEC_MODE_INVALID)
660 return l->dnssec_mode;
661
662 return manager_get_dnssec_mode(l->manager);
663 }
664
665 bool link_dnssec_supported(Link *l) {
666 DnsServer *server;
667
668 assert(l);
669
670 if (link_get_dnssec_mode(l) == DNSSEC_NO)
671 return false;
672
673 server = link_get_dns_server(l);
674 if (server)
675 return dns_server_dnssec_supported(server);
676
677 return true;
678 }
679
680 int link_address_new(Link *l, LinkAddress **ret, int family, const union in_addr_union *in_addr) {
681 LinkAddress *a;
682
683 assert(l);
684 assert(in_addr);
685
686 a = new0(LinkAddress, 1);
687 if (!a)
688 return -ENOMEM;
689
690 a->family = family;
691 a->in_addr = *in_addr;
692
693 a->link = l;
694 LIST_PREPEND(addresses, l->addresses, a);
695 l->n_addresses++;
696
697 if (ret)
698 *ret = a;
699
700 return 0;
701 }
702
703 LinkAddress *link_address_free(LinkAddress *a) {
704 if (!a)
705 return NULL;
706
707 if (a->link) {
708 LIST_REMOVE(addresses, a->link->addresses, a);
709
710 assert(a->link->n_addresses > 0);
711 a->link->n_addresses--;
712
713 if (a->llmnr_address_rr) {
714 if (a->family == AF_INET && a->link->llmnr_ipv4_scope)
715 dns_zone_remove_rr(&a->link->llmnr_ipv4_scope->zone, a->llmnr_address_rr);
716 else if (a->family == AF_INET6 && a->link->llmnr_ipv6_scope)
717 dns_zone_remove_rr(&a->link->llmnr_ipv6_scope->zone, a->llmnr_address_rr);
718 }
719
720 if (a->llmnr_ptr_rr) {
721 if (a->family == AF_INET && a->link->llmnr_ipv4_scope)
722 dns_zone_remove_rr(&a->link->llmnr_ipv4_scope->zone, a->llmnr_ptr_rr);
723 else if (a->family == AF_INET6 && a->link->llmnr_ipv6_scope)
724 dns_zone_remove_rr(&a->link->llmnr_ipv6_scope->zone, a->llmnr_ptr_rr);
725 }
726
727 if (a->mdns_address_rr) {
728 if (a->family == AF_INET && a->link->mdns_ipv4_scope)
729 dns_zone_remove_rr(&a->link->mdns_ipv4_scope->zone, a->mdns_address_rr);
730 else if (a->family == AF_INET6 && a->link->mdns_ipv6_scope)
731 dns_zone_remove_rr(&a->link->mdns_ipv6_scope->zone, a->mdns_address_rr);
732 }
733
734 if (a->mdns_ptr_rr) {
735 if (a->family == AF_INET && a->link->mdns_ipv4_scope)
736 dns_zone_remove_rr(&a->link->mdns_ipv4_scope->zone, a->mdns_ptr_rr);
737 else if (a->family == AF_INET6 && a->link->mdns_ipv6_scope)
738 dns_zone_remove_rr(&a->link->mdns_ipv6_scope->zone, a->mdns_ptr_rr);
739 }
740 }
741
742 dns_resource_record_unref(a->llmnr_address_rr);
743 dns_resource_record_unref(a->llmnr_ptr_rr);
744 dns_resource_record_unref(a->mdns_address_rr);
745 dns_resource_record_unref(a->mdns_ptr_rr);
746
747 return mfree(a);
748 }
749
750 void link_address_add_rrs(LinkAddress *a, bool force_remove) {
751 int r;
752
753 assert(a);
754
755 if (a->family == AF_INET) {
756
757 if (!force_remove &&
758 link_address_relevant(a, true) &&
759 a->link->llmnr_ipv4_scope &&
760 a->link->llmnr_support == RESOLVE_SUPPORT_YES &&
761 a->link->manager->llmnr_support == RESOLVE_SUPPORT_YES) {
762
763 if (!a->link->manager->llmnr_host_ipv4_key) {
764 a->link->manager->llmnr_host_ipv4_key = dns_resource_key_new(DNS_CLASS_IN, DNS_TYPE_A, a->link->manager->llmnr_hostname);
765 if (!a->link->manager->llmnr_host_ipv4_key) {
766 r = -ENOMEM;
767 goto fail;
768 }
769 }
770
771 if (!a->llmnr_address_rr) {
772 a->llmnr_address_rr = dns_resource_record_new(a->link->manager->llmnr_host_ipv4_key);
773 if (!a->llmnr_address_rr) {
774 r = -ENOMEM;
775 goto fail;
776 }
777
778 a->llmnr_address_rr->a.in_addr = a->in_addr.in;
779 a->llmnr_address_rr->ttl = LLMNR_DEFAULT_TTL;
780 }
781
782 if (!a->llmnr_ptr_rr) {
783 r = dns_resource_record_new_reverse(&a->llmnr_ptr_rr, a->family, &a->in_addr, a->link->manager->llmnr_hostname);
784 if (r < 0)
785 goto fail;
786
787 a->llmnr_ptr_rr->ttl = LLMNR_DEFAULT_TTL;
788 }
789
790 r = dns_zone_put(&a->link->llmnr_ipv4_scope->zone, a->link->llmnr_ipv4_scope, a->llmnr_address_rr, true);
791 if (r < 0)
792 log_warning_errno(r, "Failed to add A record to LLMNR zone: %m");
793
794 r = dns_zone_put(&a->link->llmnr_ipv4_scope->zone, a->link->llmnr_ipv4_scope, a->llmnr_ptr_rr, false);
795 if (r < 0)
796 log_warning_errno(r, "Failed to add IPv4 PTR record to LLMNR zone: %m");
797 } else {
798 if (a->llmnr_address_rr) {
799 if (a->link->llmnr_ipv4_scope)
800 dns_zone_remove_rr(&a->link->llmnr_ipv4_scope->zone, a->llmnr_address_rr);
801 a->llmnr_address_rr = dns_resource_record_unref(a->llmnr_address_rr);
802 }
803
804 if (a->llmnr_ptr_rr) {
805 if (a->link->llmnr_ipv4_scope)
806 dns_zone_remove_rr(&a->link->llmnr_ipv4_scope->zone, a->llmnr_ptr_rr);
807 a->llmnr_ptr_rr = dns_resource_record_unref(a->llmnr_ptr_rr);
808 }
809 }
810
811 if (!force_remove &&
812 link_address_relevant(a, true) &&
813 a->link->mdns_ipv4_scope &&
814 a->link->mdns_support == RESOLVE_SUPPORT_YES &&
815 a->link->manager->mdns_support == RESOLVE_SUPPORT_YES) {
816 if (!a->link->manager->mdns_host_ipv4_key) {
817 a->link->manager->mdns_host_ipv4_key = dns_resource_key_new(DNS_CLASS_IN, DNS_TYPE_A, a->link->manager->mdns_hostname);
818 if (!a->link->manager->mdns_host_ipv4_key) {
819 r = -ENOMEM;
820 goto fail;
821 }
822 }
823
824 if (!a->mdns_address_rr) {
825 a->mdns_address_rr = dns_resource_record_new(a->link->manager->mdns_host_ipv4_key);
826 if (!a->mdns_address_rr) {
827 r = -ENOMEM;
828 goto fail;
829 }
830
831 a->mdns_address_rr->a.in_addr = a->in_addr.in;
832 a->mdns_address_rr->ttl = MDNS_DEFAULT_TTL;
833 }
834
835 if (!a->mdns_ptr_rr) {
836 r = dns_resource_record_new_reverse(&a->mdns_ptr_rr, a->family, &a->in_addr, a->link->manager->mdns_hostname);
837 if (r < 0)
838 goto fail;
839
840 a->mdns_ptr_rr->ttl = MDNS_DEFAULT_TTL;
841 }
842
843 r = dns_zone_put(&a->link->mdns_ipv4_scope->zone, a->link->mdns_ipv4_scope, a->mdns_address_rr, true);
844 if (r < 0)
845 log_warning_errno(r, "Failed to add A record to MDNS zone: %m");
846
847 r = dns_zone_put(&a->link->mdns_ipv4_scope->zone, a->link->mdns_ipv4_scope, a->mdns_ptr_rr, false);
848 if (r < 0)
849 log_warning_errno(r, "Failed to add IPv4 PTR record to MDNS zone: %m");
850 } else {
851 if (a->mdns_address_rr) {
852 if (a->link->mdns_ipv4_scope)
853 dns_zone_remove_rr(&a->link->mdns_ipv4_scope->zone, a->mdns_address_rr);
854 a->mdns_address_rr = dns_resource_record_unref(a->mdns_address_rr);
855 }
856
857 if (a->mdns_ptr_rr) {
858 if (a->link->mdns_ipv4_scope)
859 dns_zone_remove_rr(&a->link->mdns_ipv4_scope->zone, a->mdns_ptr_rr);
860 a->mdns_ptr_rr = dns_resource_record_unref(a->mdns_ptr_rr);
861 }
862 }
863 }
864
865 if (a->family == AF_INET6) {
866
867 if (!force_remove &&
868 link_address_relevant(a, true) &&
869 a->link->llmnr_ipv6_scope &&
870 a->link->llmnr_support == RESOLVE_SUPPORT_YES &&
871 a->link->manager->llmnr_support == RESOLVE_SUPPORT_YES) {
872
873 if (!a->link->manager->llmnr_host_ipv6_key) {
874 a->link->manager->llmnr_host_ipv6_key = dns_resource_key_new(DNS_CLASS_IN, DNS_TYPE_AAAA, a->link->manager->llmnr_hostname);
875 if (!a->link->manager->llmnr_host_ipv6_key) {
876 r = -ENOMEM;
877 goto fail;
878 }
879 }
880
881 if (!a->llmnr_address_rr) {
882 a->llmnr_address_rr = dns_resource_record_new(a->link->manager->llmnr_host_ipv6_key);
883 if (!a->llmnr_address_rr) {
884 r = -ENOMEM;
885 goto fail;
886 }
887
888 a->llmnr_address_rr->aaaa.in6_addr = a->in_addr.in6;
889 a->llmnr_address_rr->ttl = LLMNR_DEFAULT_TTL;
890 }
891
892 if (!a->llmnr_ptr_rr) {
893 r = dns_resource_record_new_reverse(&a->llmnr_ptr_rr, a->family, &a->in_addr, a->link->manager->llmnr_hostname);
894 if (r < 0)
895 goto fail;
896
897 a->llmnr_ptr_rr->ttl = LLMNR_DEFAULT_TTL;
898 }
899
900 r = dns_zone_put(&a->link->llmnr_ipv6_scope->zone, a->link->llmnr_ipv6_scope, a->llmnr_address_rr, true);
901 if (r < 0)
902 log_warning_errno(r, "Failed to add AAAA record to LLMNR zone: %m");
903
904 r = dns_zone_put(&a->link->llmnr_ipv6_scope->zone, a->link->llmnr_ipv6_scope, a->llmnr_ptr_rr, false);
905 if (r < 0)
906 log_warning_errno(r, "Failed to add IPv6 PTR record to LLMNR zone: %m");
907 } else {
908 if (a->llmnr_address_rr) {
909 if (a->link->llmnr_ipv6_scope)
910 dns_zone_remove_rr(&a->link->llmnr_ipv6_scope->zone, a->llmnr_address_rr);
911 a->llmnr_address_rr = dns_resource_record_unref(a->llmnr_address_rr);
912 }
913
914 if (a->llmnr_ptr_rr) {
915 if (a->link->llmnr_ipv6_scope)
916 dns_zone_remove_rr(&a->link->llmnr_ipv6_scope->zone, a->llmnr_ptr_rr);
917 a->llmnr_ptr_rr = dns_resource_record_unref(a->llmnr_ptr_rr);
918 }
919 }
920
921 if (!force_remove &&
922 link_address_relevant(a, true) &&
923 a->link->mdns_ipv6_scope &&
924 a->link->mdns_support == RESOLVE_SUPPORT_YES &&
925 a->link->manager->mdns_support == RESOLVE_SUPPORT_YES) {
926
927 if (!a->link->manager->mdns_host_ipv6_key) {
928 a->link->manager->mdns_host_ipv6_key = dns_resource_key_new(DNS_CLASS_IN, DNS_TYPE_AAAA, a->link->manager->mdns_hostname);
929 if (!a->link->manager->mdns_host_ipv6_key) {
930 r = -ENOMEM;
931 goto fail;
932 }
933 }
934
935 if (!a->mdns_address_rr) {
936 a->mdns_address_rr = dns_resource_record_new(a->link->manager->mdns_host_ipv6_key);
937 if (!a->mdns_address_rr) {
938 r = -ENOMEM;
939 goto fail;
940 }
941
942 a->mdns_address_rr->aaaa.in6_addr = a->in_addr.in6;
943 a->mdns_address_rr->ttl = MDNS_DEFAULT_TTL;
944 }
945
946 if (!a->mdns_ptr_rr) {
947 r = dns_resource_record_new_reverse(&a->mdns_ptr_rr, a->family, &a->in_addr, a->link->manager->mdns_hostname);
948 if (r < 0)
949 goto fail;
950
951 a->mdns_ptr_rr->ttl = MDNS_DEFAULT_TTL;
952 }
953
954 r = dns_zone_put(&a->link->mdns_ipv6_scope->zone, a->link->mdns_ipv6_scope, a->mdns_address_rr, true);
955 if (r < 0)
956 log_warning_errno(r, "Failed to add AAAA record to MDNS zone: %m");
957
958 r = dns_zone_put(&a->link->mdns_ipv6_scope->zone, a->link->mdns_ipv6_scope, a->mdns_ptr_rr, false);
959 if (r < 0)
960 log_warning_errno(r, "Failed to add IPv6 PTR record to MDNS zone: %m");
961 } else {
962 if (a->mdns_address_rr) {
963 if (a->link->mdns_ipv6_scope)
964 dns_zone_remove_rr(&a->link->mdns_ipv6_scope->zone, a->mdns_address_rr);
965 a->mdns_address_rr = dns_resource_record_unref(a->mdns_address_rr);
966 }
967
968 if (a->mdns_ptr_rr) {
969 if (a->link->mdns_ipv6_scope)
970 dns_zone_remove_rr(&a->link->mdns_ipv6_scope->zone, a->mdns_ptr_rr);
971 a->mdns_ptr_rr = dns_resource_record_unref(a->mdns_ptr_rr);
972 }
973 }
974 }
975
976 return;
977
978 fail:
979 log_debug_errno(r, "Failed to update address RRs: %m");
980 }
981
982 int link_address_update_rtnl(LinkAddress *a, sd_netlink_message *m) {
983 int r;
984 assert(a);
985 assert(m);
986
987 r = sd_rtnl_message_addr_get_flags(m, &a->flags);
988 if (r < 0)
989 return r;
990
991 sd_rtnl_message_addr_get_scope(m, &a->scope);
992
993 link_allocate_scopes(a->link);
994 link_add_rrs(a->link, false);
995
996 return 0;
997 }
998
999 bool link_address_relevant(LinkAddress *a, bool local_multicast) {
1000 assert(a);
1001
1002 if (a->flags & (IFA_F_DEPRECATED|IFA_F_TENTATIVE))
1003 return false;
1004
1005 if (a->scope >= (local_multicast ? RT_SCOPE_HOST : RT_SCOPE_LINK))
1006 return false;
1007
1008 return true;
1009 }
1010
1011 static bool link_needs_save(Link *l) {
1012 assert(l);
1013
1014 /* Returns true if any of the settings where set different from the default */
1015
1016 if (l->is_managed)
1017 return false;
1018
1019 if (l->llmnr_support != RESOLVE_SUPPORT_YES ||
1020 l->mdns_support != RESOLVE_SUPPORT_NO ||
1021 l->dnssec_mode != _DNSSEC_MODE_INVALID)
1022 return true;
1023
1024 if (l->dns_servers ||
1025 l->search_domains)
1026 return true;
1027
1028 if (!set_isempty(l->dnssec_negative_trust_anchors))
1029 return true;
1030
1031 return false;
1032 }
1033
1034 int link_save_user(Link *l) {
1035 _cleanup_free_ char *temp_path = NULL;
1036 _cleanup_fclose_ FILE *f = NULL;
1037 const char *v;
1038 int r;
1039
1040 assert(l);
1041 assert(l->state_file);
1042
1043 if (!link_needs_save(l)) {
1044 (void) unlink(l->state_file);
1045 return 0;
1046 }
1047
1048 r = mkdir_parents(l->state_file, 0700);
1049 if (r < 0)
1050 goto fail;
1051
1052 r = fopen_temporary(l->state_file, &f, &temp_path);
1053 if (r < 0)
1054 goto fail;
1055
1056 fputs("# This is private data. Do not parse.\n", f);
1057
1058 v = resolve_support_to_string(l->llmnr_support);
1059 if (v)
1060 fprintf(f, "LLMNR=%s\n", v);
1061
1062 v = resolve_support_to_string(l->mdns_support);
1063 if (v)
1064 fprintf(f, "MDNS=%s\n", v);
1065
1066 v = dnssec_mode_to_string(l->dnssec_mode);
1067 if (v)
1068 fprintf(f, "DNSSEC=%s\n", v);
1069
1070 if (l->dns_servers) {
1071 DnsServer *server;
1072
1073 fputs("SERVERS=", f);
1074 LIST_FOREACH(servers, server, l->dns_servers) {
1075
1076 if (server != l->dns_servers)
1077 fputc(' ', f);
1078
1079 v = dns_server_string(server);
1080 if (!v) {
1081 r = -ENOMEM;
1082 goto fail;
1083 }
1084
1085 fputs(v, f);
1086 }
1087 fputc('\n', f);
1088 }
1089
1090 if (l->search_domains) {
1091 DnsSearchDomain *domain;
1092
1093 fputs("DOMAINS=", f);
1094 LIST_FOREACH(domains, domain, l->search_domains) {
1095
1096 if (domain != l->search_domains)
1097 fputc(' ', f);
1098
1099 if (domain->route_only)
1100 fputc('~', f);
1101
1102 fputs(DNS_SEARCH_DOMAIN_NAME(domain), f);
1103 }
1104 fputc('\n', f);
1105 }
1106
1107 if (!set_isempty(l->dnssec_negative_trust_anchors)) {
1108 bool space = false;
1109 Iterator i;
1110 char *nta;
1111
1112 fputs("NTAS=", f);
1113 SET_FOREACH(nta, l->dnssec_negative_trust_anchors, i) {
1114
1115 if (space)
1116 fputc(' ', f);
1117
1118 fputs(nta, f);
1119 space = true;
1120 }
1121 fputc('\n', f);
1122 }
1123
1124 r = fflush_and_check(f);
1125 if (r < 0)
1126 goto fail;
1127
1128 if (rename(temp_path, l->state_file) < 0) {
1129 r = -errno;
1130 goto fail;
1131 }
1132
1133 return 0;
1134
1135 fail:
1136 (void) unlink(l->state_file);
1137
1138 if (temp_path)
1139 (void) unlink(temp_path);
1140
1141 return log_error_errno(r, "Failed to save link data %s: %m", l->state_file);
1142 }
1143
1144 int link_load_user(Link *l) {
1145 _cleanup_free_ char
1146 *llmnr = NULL,
1147 *mdns = NULL,
1148 *dnssec = NULL,
1149 *servers = NULL,
1150 *domains = NULL,
1151 *ntas = NULL;
1152
1153 ResolveSupport s;
1154 const char *p;
1155 int r;
1156
1157 assert(l);
1158 assert(l->state_file);
1159
1160 /* Try to load only a single time */
1161 if (l->loaded)
1162 return 0;
1163 l->loaded = true;
1164
1165 if (l->is_managed)
1166 return 0; /* if the device is managed, then networkd is our configuration source, not the bus API */
1167
1168 r = parse_env_file(l->state_file, NEWLINE,
1169 "LLMNR", &llmnr,
1170 "MDNS", &mdns,
1171 "DNSSEC", &dnssec,
1172 "SERVERS", &servers,
1173 "DOMAINS", &domains,
1174 "NTAS", &ntas,
1175 NULL);
1176 if (r == -ENOENT)
1177 return 0;
1178 if (r < 0)
1179 goto fail;
1180
1181 link_flush_settings(l);
1182
1183 /* If we can't recognize the LLMNR or MDNS setting we don't override the default */
1184 s = resolve_support_from_string(llmnr);
1185 if (s >= 0)
1186 l->llmnr_support = s;
1187
1188 s = resolve_support_from_string(mdns);
1189 if (s >= 0)
1190 l->mdns_support = s;
1191
1192 /* If we can't recognize the DNSSEC setting, then set it to invalid, so that the daemon default is used. */
1193 l->dnssec_mode = dnssec_mode_from_string(dnssec);
1194
1195 for (p = servers;;) {
1196 _cleanup_free_ char *word = NULL;
1197
1198 r = extract_first_word(&p, &word, NULL, 0);
1199 if (r < 0)
1200 goto fail;
1201 if (r == 0)
1202 break;
1203
1204 r = link_update_dns_server_one(l, word);
1205 if (r < 0) {
1206 log_debug_errno(r, "Failed to load DNS server '%s', ignoring: %m", word);
1207 continue;
1208 }
1209 }
1210
1211 for (p = domains;;) {
1212 _cleanup_free_ char *word = NULL;
1213 const char *n;
1214 bool is_route;
1215
1216 r = extract_first_word(&p, &word, NULL, 0);
1217 if (r < 0)
1218 goto fail;
1219 if (r == 0)
1220 break;
1221
1222 is_route = word[0] == '~';
1223 n = is_route ? word + 1 : word;
1224
1225 r = link_update_search_domain_one(l, n, is_route);
1226 if (r < 0) {
1227 log_debug_errno(r, "Failed to load search domain '%s', ignoring: %m", word);
1228 continue;
1229 }
1230 }
1231
1232 if (ntas) {
1233 _cleanup_set_free_free_ Set *ns = NULL;
1234
1235 ns = set_new(&dns_name_hash_ops);
1236 if (!ns) {
1237 r = -ENOMEM;
1238 goto fail;
1239 }
1240
1241 r = set_put_strsplit(ns, ntas, NULL, 0);
1242 if (r < 0)
1243 goto fail;
1244
1245 l->dnssec_negative_trust_anchors = ns;
1246 ns = NULL;
1247 }
1248
1249 return 0;
1250
1251 fail:
1252 return log_error_errno(r, "Failed to load link data %s: %m", l->state_file);
1253 }
1254
1255 void link_remove_user(Link *l) {
1256 assert(l);
1257 assert(l->state_file);
1258
1259 (void) unlink(l->state_file);
1260 }