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