]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/resolve/resolved-link.c
build-sys: use #if Y instead of #ifdef Y everywhere
[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 #if ! HAVE_GCRYPT
317 if (IN_SET(mode, DNSSEC_YES, 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 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_MULTICAST) != IFF_MULTICAST)
579 return false;
580 }
581
582 /* Check kernel operstate
583 * https://www.kernel.org/doc/Documentation/networking/operstates.txt */
584 if (!IN_SET(l->operstate, IF_OPER_UNKNOWN, IF_OPER_UP))
585 return false;
586
587 (void) sd_network_link_get_operational_state(l->ifindex, &state);
588 if (state && !STR_IN_SET(state, "unknown", "degraded", "routable"))
589 return false;
590
591 LIST_FOREACH(addresses, a, l->addresses)
592 if ((family == AF_UNSPEC || a->family == family) && link_address_relevant(a, local_multicast))
593 return true;
594
595 return false;
596 }
597
598 LinkAddress *link_find_address(Link *l, int family, const union in_addr_union *in_addr) {
599 LinkAddress *a;
600
601 assert(l);
602
603 LIST_FOREACH(addresses, a, l->addresses)
604 if (a->family == family && in_addr_equal(family, &a->in_addr, in_addr))
605 return a;
606
607 return NULL;
608 }
609
610 DnsServer* link_set_dns_server(Link *l, DnsServer *s) {
611 assert(l);
612
613 if (l->current_dns_server == s)
614 return s;
615
616 if (s)
617 log_debug("Switching to DNS server %s for interface %s.", dns_server_string(s), l->name);
618
619 dns_server_unref(l->current_dns_server);
620 l->current_dns_server = dns_server_ref(s);
621
622 if (l->unicast_scope)
623 dns_cache_flush(&l->unicast_scope->cache);
624
625 return s;
626 }
627
628 DnsServer *link_get_dns_server(Link *l) {
629 assert(l);
630
631 if (!l->current_dns_server)
632 link_set_dns_server(l, l->dns_servers);
633
634 return l->current_dns_server;
635 }
636
637 void link_next_dns_server(Link *l) {
638 assert(l);
639
640 if (!l->current_dns_server)
641 return;
642
643 /* Change to the next one, but make sure to follow the linked
644 * list only if this server is actually still linked. */
645 if (l->current_dns_server->linked && l->current_dns_server->servers_next) {
646 link_set_dns_server(l, l->current_dns_server->servers_next);
647 return;
648 }
649
650 link_set_dns_server(l, l->dns_servers);
651 }
652
653 DnssecMode link_get_dnssec_mode(Link *l) {
654 assert(l);
655
656 if (l->dnssec_mode != _DNSSEC_MODE_INVALID)
657 return l->dnssec_mode;
658
659 return manager_get_dnssec_mode(l->manager);
660 }
661
662 bool link_dnssec_supported(Link *l) {
663 DnsServer *server;
664
665 assert(l);
666
667 if (link_get_dnssec_mode(l) == DNSSEC_NO)
668 return false;
669
670 server = link_get_dns_server(l);
671 if (server)
672 return dns_server_dnssec_supported(server);
673
674 return true;
675 }
676
677 int link_address_new(Link *l, LinkAddress **ret, int family, const union in_addr_union *in_addr) {
678 LinkAddress *a;
679
680 assert(l);
681 assert(in_addr);
682
683 a = new0(LinkAddress, 1);
684 if (!a)
685 return -ENOMEM;
686
687 a->family = family;
688 a->in_addr = *in_addr;
689
690 a->link = l;
691 LIST_PREPEND(addresses, l->addresses, a);
692 l->n_addresses++;
693
694 if (ret)
695 *ret = a;
696
697 return 0;
698 }
699
700 LinkAddress *link_address_free(LinkAddress *a) {
701 if (!a)
702 return NULL;
703
704 if (a->link) {
705 LIST_REMOVE(addresses, a->link->addresses, a);
706
707 assert(a->link->n_addresses > 0);
708 a->link->n_addresses--;
709
710 if (a->llmnr_address_rr) {
711 if (a->family == AF_INET && a->link->llmnr_ipv4_scope)
712 dns_zone_remove_rr(&a->link->llmnr_ipv4_scope->zone, a->llmnr_address_rr);
713 else if (a->family == AF_INET6 && a->link->llmnr_ipv6_scope)
714 dns_zone_remove_rr(&a->link->llmnr_ipv6_scope->zone, a->llmnr_address_rr);
715 }
716
717 if (a->llmnr_ptr_rr) {
718 if (a->family == AF_INET && a->link->llmnr_ipv4_scope)
719 dns_zone_remove_rr(&a->link->llmnr_ipv4_scope->zone, a->llmnr_ptr_rr);
720 else if (a->family == AF_INET6 && a->link->llmnr_ipv6_scope)
721 dns_zone_remove_rr(&a->link->llmnr_ipv6_scope->zone, a->llmnr_ptr_rr);
722 }
723
724 if (a->mdns_address_rr) {
725 if (a->family == AF_INET && a->link->mdns_ipv4_scope)
726 dns_zone_remove_rr(&a->link->mdns_ipv4_scope->zone, a->mdns_address_rr);
727 else if (a->family == AF_INET6 && a->link->mdns_ipv6_scope)
728 dns_zone_remove_rr(&a->link->mdns_ipv6_scope->zone, a->mdns_address_rr);
729 }
730
731 if (a->mdns_ptr_rr) {
732 if (a->family == AF_INET && a->link->mdns_ipv4_scope)
733 dns_zone_remove_rr(&a->link->mdns_ipv4_scope->zone, a->mdns_ptr_rr);
734 else if (a->family == AF_INET6 && a->link->mdns_ipv6_scope)
735 dns_zone_remove_rr(&a->link->mdns_ipv6_scope->zone, a->mdns_ptr_rr);
736 }
737 }
738
739 dns_resource_record_unref(a->llmnr_address_rr);
740 dns_resource_record_unref(a->llmnr_ptr_rr);
741 dns_resource_record_unref(a->mdns_address_rr);
742 dns_resource_record_unref(a->mdns_ptr_rr);
743
744 return mfree(a);
745 }
746
747 void link_address_add_rrs(LinkAddress *a, bool force_remove) {
748 int r;
749
750 assert(a);
751
752 if (a->family == AF_INET) {
753
754 if (!force_remove &&
755 link_address_relevant(a, true) &&
756 a->link->llmnr_ipv4_scope &&
757 a->link->llmnr_support == RESOLVE_SUPPORT_YES &&
758 a->link->manager->llmnr_support == RESOLVE_SUPPORT_YES) {
759
760 if (!a->link->manager->llmnr_host_ipv4_key) {
761 a->link->manager->llmnr_host_ipv4_key = dns_resource_key_new(DNS_CLASS_IN, DNS_TYPE_A, a->link->manager->llmnr_hostname);
762 if (!a->link->manager->llmnr_host_ipv4_key) {
763 r = -ENOMEM;
764 goto fail;
765 }
766 }
767
768 if (!a->llmnr_address_rr) {
769 a->llmnr_address_rr = dns_resource_record_new(a->link->manager->llmnr_host_ipv4_key);
770 if (!a->llmnr_address_rr) {
771 r = -ENOMEM;
772 goto fail;
773 }
774
775 a->llmnr_address_rr->a.in_addr = a->in_addr.in;
776 a->llmnr_address_rr->ttl = LLMNR_DEFAULT_TTL;
777 }
778
779 if (!a->llmnr_ptr_rr) {
780 r = dns_resource_record_new_reverse(&a->llmnr_ptr_rr, a->family, &a->in_addr, a->link->manager->llmnr_hostname);
781 if (r < 0)
782 goto fail;
783
784 a->llmnr_ptr_rr->ttl = LLMNR_DEFAULT_TTL;
785 }
786
787 r = dns_zone_put(&a->link->llmnr_ipv4_scope->zone, a->link->llmnr_ipv4_scope, a->llmnr_address_rr, true);
788 if (r < 0)
789 log_warning_errno(r, "Failed to add A record to LLMNR zone: %m");
790
791 r = dns_zone_put(&a->link->llmnr_ipv4_scope->zone, a->link->llmnr_ipv4_scope, a->llmnr_ptr_rr, false);
792 if (r < 0)
793 log_warning_errno(r, "Failed to add IPv4 PTR record to LLMNR zone: %m");
794 } else {
795 if (a->llmnr_address_rr) {
796 if (a->link->llmnr_ipv4_scope)
797 dns_zone_remove_rr(&a->link->llmnr_ipv4_scope->zone, a->llmnr_address_rr);
798 a->llmnr_address_rr = dns_resource_record_unref(a->llmnr_address_rr);
799 }
800
801 if (a->llmnr_ptr_rr) {
802 if (a->link->llmnr_ipv4_scope)
803 dns_zone_remove_rr(&a->link->llmnr_ipv4_scope->zone, a->llmnr_ptr_rr);
804 a->llmnr_ptr_rr = dns_resource_record_unref(a->llmnr_ptr_rr);
805 }
806 }
807
808 if (!force_remove &&
809 link_address_relevant(a, true) &&
810 a->link->mdns_ipv4_scope &&
811 a->link->mdns_support == RESOLVE_SUPPORT_YES &&
812 a->link->manager->mdns_support == RESOLVE_SUPPORT_YES) {
813 if (!a->link->manager->mdns_host_ipv4_key) {
814 a->link->manager->mdns_host_ipv4_key = dns_resource_key_new(DNS_CLASS_IN, DNS_TYPE_A, a->link->manager->mdns_hostname);
815 if (!a->link->manager->mdns_host_ipv4_key) {
816 r = -ENOMEM;
817 goto fail;
818 }
819 }
820
821 if (!a->mdns_address_rr) {
822 a->mdns_address_rr = dns_resource_record_new(a->link->manager->mdns_host_ipv4_key);
823 if (!a->mdns_address_rr) {
824 r = -ENOMEM;
825 goto fail;
826 }
827
828 a->mdns_address_rr->a.in_addr = a->in_addr.in;
829 a->mdns_address_rr->ttl = MDNS_DEFAULT_TTL;
830 }
831
832 if (!a->mdns_ptr_rr) {
833 r = dns_resource_record_new_reverse(&a->mdns_ptr_rr, a->family, &a->in_addr, a->link->manager->mdns_hostname);
834 if (r < 0)
835 goto fail;
836
837 a->mdns_ptr_rr->ttl = MDNS_DEFAULT_TTL;
838 }
839
840 r = dns_zone_put(&a->link->mdns_ipv4_scope->zone, a->link->mdns_ipv4_scope, a->mdns_address_rr, true);
841 if (r < 0)
842 log_warning_errno(r, "Failed to add A record to MDNS zone: %m");
843
844 r = dns_zone_put(&a->link->mdns_ipv4_scope->zone, a->link->mdns_ipv4_scope, a->mdns_ptr_rr, false);
845 if (r < 0)
846 log_warning_errno(r, "Failed to add IPv4 PTR record to MDNS zone: %m");
847 } else {
848 if (a->mdns_address_rr) {
849 if (a->link->mdns_ipv4_scope)
850 dns_zone_remove_rr(&a->link->mdns_ipv4_scope->zone, a->mdns_address_rr);
851 a->mdns_address_rr = dns_resource_record_unref(a->mdns_address_rr);
852 }
853
854 if (a->mdns_ptr_rr) {
855 if (a->link->mdns_ipv4_scope)
856 dns_zone_remove_rr(&a->link->mdns_ipv4_scope->zone, a->mdns_ptr_rr);
857 a->mdns_ptr_rr = dns_resource_record_unref(a->mdns_ptr_rr);
858 }
859 }
860 }
861
862 if (a->family == AF_INET6) {
863
864 if (!force_remove &&
865 link_address_relevant(a, true) &&
866 a->link->llmnr_ipv6_scope &&
867 a->link->llmnr_support == RESOLVE_SUPPORT_YES &&
868 a->link->manager->llmnr_support == RESOLVE_SUPPORT_YES) {
869
870 if (!a->link->manager->llmnr_host_ipv6_key) {
871 a->link->manager->llmnr_host_ipv6_key = dns_resource_key_new(DNS_CLASS_IN, DNS_TYPE_AAAA, a->link->manager->llmnr_hostname);
872 if (!a->link->manager->llmnr_host_ipv6_key) {
873 r = -ENOMEM;
874 goto fail;
875 }
876 }
877
878 if (!a->llmnr_address_rr) {
879 a->llmnr_address_rr = dns_resource_record_new(a->link->manager->llmnr_host_ipv6_key);
880 if (!a->llmnr_address_rr) {
881 r = -ENOMEM;
882 goto fail;
883 }
884
885 a->llmnr_address_rr->aaaa.in6_addr = a->in_addr.in6;
886 a->llmnr_address_rr->ttl = LLMNR_DEFAULT_TTL;
887 }
888
889 if (!a->llmnr_ptr_rr) {
890 r = dns_resource_record_new_reverse(&a->llmnr_ptr_rr, a->family, &a->in_addr, a->link->manager->llmnr_hostname);
891 if (r < 0)
892 goto fail;
893
894 a->llmnr_ptr_rr->ttl = LLMNR_DEFAULT_TTL;
895 }
896
897 r = dns_zone_put(&a->link->llmnr_ipv6_scope->zone, a->link->llmnr_ipv6_scope, a->llmnr_address_rr, true);
898 if (r < 0)
899 log_warning_errno(r, "Failed to add AAAA record to LLMNR zone: %m");
900
901 r = dns_zone_put(&a->link->llmnr_ipv6_scope->zone, a->link->llmnr_ipv6_scope, a->llmnr_ptr_rr, false);
902 if (r < 0)
903 log_warning_errno(r, "Failed to add IPv6 PTR record to LLMNR zone: %m");
904 } else {
905 if (a->llmnr_address_rr) {
906 if (a->link->llmnr_ipv6_scope)
907 dns_zone_remove_rr(&a->link->llmnr_ipv6_scope->zone, a->llmnr_address_rr);
908 a->llmnr_address_rr = dns_resource_record_unref(a->llmnr_address_rr);
909 }
910
911 if (a->llmnr_ptr_rr) {
912 if (a->link->llmnr_ipv6_scope)
913 dns_zone_remove_rr(&a->link->llmnr_ipv6_scope->zone, a->llmnr_ptr_rr);
914 a->llmnr_ptr_rr = dns_resource_record_unref(a->llmnr_ptr_rr);
915 }
916 }
917
918 if (!force_remove &&
919 link_address_relevant(a, true) &&
920 a->link->mdns_ipv6_scope &&
921 a->link->mdns_support == RESOLVE_SUPPORT_YES &&
922 a->link->manager->mdns_support == RESOLVE_SUPPORT_YES) {
923
924 if (!a->link->manager->mdns_host_ipv6_key) {
925 a->link->manager->mdns_host_ipv6_key = dns_resource_key_new(DNS_CLASS_IN, DNS_TYPE_AAAA, a->link->manager->mdns_hostname);
926 if (!a->link->manager->mdns_host_ipv6_key) {
927 r = -ENOMEM;
928 goto fail;
929 }
930 }
931
932 if (!a->mdns_address_rr) {
933 a->mdns_address_rr = dns_resource_record_new(a->link->manager->mdns_host_ipv6_key);
934 if (!a->mdns_address_rr) {
935 r = -ENOMEM;
936 goto fail;
937 }
938
939 a->mdns_address_rr->aaaa.in6_addr = a->in_addr.in6;
940 a->mdns_address_rr->ttl = MDNS_DEFAULT_TTL;
941 }
942
943 if (!a->mdns_ptr_rr) {
944 r = dns_resource_record_new_reverse(&a->mdns_ptr_rr, a->family, &a->in_addr, a->link->manager->mdns_hostname);
945 if (r < 0)
946 goto fail;
947
948 a->mdns_ptr_rr->ttl = MDNS_DEFAULT_TTL;
949 }
950
951 r = dns_zone_put(&a->link->mdns_ipv6_scope->zone, a->link->mdns_ipv6_scope, a->mdns_address_rr, true);
952 if (r < 0)
953 log_warning_errno(r, "Failed to add AAAA record to MDNS zone: %m");
954
955 r = dns_zone_put(&a->link->mdns_ipv6_scope->zone, a->link->mdns_ipv6_scope, a->mdns_ptr_rr, false);
956 if (r < 0)
957 log_warning_errno(r, "Failed to add IPv6 PTR record to MDNS zone: %m");
958 } else {
959 if (a->mdns_address_rr) {
960 if (a->link->mdns_ipv6_scope)
961 dns_zone_remove_rr(&a->link->mdns_ipv6_scope->zone, a->mdns_address_rr);
962 a->mdns_address_rr = dns_resource_record_unref(a->mdns_address_rr);
963 }
964
965 if (a->mdns_ptr_rr) {
966 if (a->link->mdns_ipv6_scope)
967 dns_zone_remove_rr(&a->link->mdns_ipv6_scope->zone, a->mdns_ptr_rr);
968 a->mdns_ptr_rr = dns_resource_record_unref(a->mdns_ptr_rr);
969 }
970 }
971 }
972
973 return;
974
975 fail:
976 log_debug_errno(r, "Failed to update address RRs: %m");
977 }
978
979 int link_address_update_rtnl(LinkAddress *a, sd_netlink_message *m) {
980 int r;
981 assert(a);
982 assert(m);
983
984 r = sd_rtnl_message_addr_get_flags(m, &a->flags);
985 if (r < 0)
986 return r;
987
988 sd_rtnl_message_addr_get_scope(m, &a->scope);
989
990 link_allocate_scopes(a->link);
991 link_add_rrs(a->link, false);
992
993 return 0;
994 }
995
996 bool link_address_relevant(LinkAddress *a, bool local_multicast) {
997 assert(a);
998
999 if (a->flags & (IFA_F_DEPRECATED|IFA_F_TENTATIVE))
1000 return false;
1001
1002 if (a->scope >= (local_multicast ? RT_SCOPE_HOST : RT_SCOPE_LINK))
1003 return false;
1004
1005 return true;
1006 }
1007
1008 static bool link_needs_save(Link *l) {
1009 assert(l);
1010
1011 /* Returns true if any of the settings where set different from the default */
1012
1013 if (l->is_managed)
1014 return false;
1015
1016 if (l->llmnr_support != RESOLVE_SUPPORT_YES ||
1017 l->mdns_support != RESOLVE_SUPPORT_NO ||
1018 l->dnssec_mode != _DNSSEC_MODE_INVALID)
1019 return true;
1020
1021 if (l->dns_servers ||
1022 l->search_domains)
1023 return true;
1024
1025 if (!set_isempty(l->dnssec_negative_trust_anchors))
1026 return true;
1027
1028 return false;
1029 }
1030
1031 int link_save_user(Link *l) {
1032 _cleanup_free_ char *temp_path = NULL;
1033 _cleanup_fclose_ FILE *f = NULL;
1034 const char *v;
1035 int r;
1036
1037 assert(l);
1038 assert(l->state_file);
1039
1040 if (!link_needs_save(l)) {
1041 (void) unlink(l->state_file);
1042 return 0;
1043 }
1044
1045 r = mkdir_parents(l->state_file, 0700);
1046 if (r < 0)
1047 goto fail;
1048
1049 r = fopen_temporary(l->state_file, &f, &temp_path);
1050 if (r < 0)
1051 goto fail;
1052
1053 fputs_unlocked("# This is private data. Do not parse.\n", f);
1054
1055 v = resolve_support_to_string(l->llmnr_support);
1056 if (v)
1057 fprintf(f, "LLMNR=%s\n", v);
1058
1059 v = resolve_support_to_string(l->mdns_support);
1060 if (v)
1061 fprintf(f, "MDNS=%s\n", v);
1062
1063 v = dnssec_mode_to_string(l->dnssec_mode);
1064 if (v)
1065 fprintf(f, "DNSSEC=%s\n", v);
1066
1067 if (l->dns_servers) {
1068 DnsServer *server;
1069
1070 fputs_unlocked("SERVERS=", f);
1071 LIST_FOREACH(servers, server, l->dns_servers) {
1072
1073 if (server != l->dns_servers)
1074 fputc_unlocked(' ', f);
1075
1076 v = dns_server_string(server);
1077 if (!v) {
1078 r = -ENOMEM;
1079 goto fail;
1080 }
1081
1082 fputs_unlocked(v, f);
1083 }
1084 fputc_unlocked('\n', f);
1085 }
1086
1087 if (l->search_domains) {
1088 DnsSearchDomain *domain;
1089
1090 fputs_unlocked("DOMAINS=", f);
1091 LIST_FOREACH(domains, domain, l->search_domains) {
1092
1093 if (domain != l->search_domains)
1094 fputc_unlocked(' ', f);
1095
1096 if (domain->route_only)
1097 fputc_unlocked('~', f);
1098
1099 fputs_unlocked(DNS_SEARCH_DOMAIN_NAME(domain), f);
1100 }
1101 fputc_unlocked('\n', f);
1102 }
1103
1104 if (!set_isempty(l->dnssec_negative_trust_anchors)) {
1105 bool space = false;
1106 Iterator i;
1107 char *nta;
1108
1109 fputs_unlocked("NTAS=", f);
1110 SET_FOREACH(nta, l->dnssec_negative_trust_anchors, i) {
1111
1112 if (space)
1113 fputc_unlocked(' ', f);
1114
1115 fputs_unlocked(nta, f);
1116 space = true;
1117 }
1118 fputc_unlocked('\n', f);
1119 }
1120
1121 r = fflush_and_check(f);
1122 if (r < 0)
1123 goto fail;
1124
1125 if (rename(temp_path, l->state_file) < 0) {
1126 r = -errno;
1127 goto fail;
1128 }
1129
1130 return 0;
1131
1132 fail:
1133 (void) unlink(l->state_file);
1134
1135 if (temp_path)
1136 (void) unlink(temp_path);
1137
1138 return log_error_errno(r, "Failed to save link data %s: %m", l->state_file);
1139 }
1140
1141 int link_load_user(Link *l) {
1142 _cleanup_free_ char
1143 *llmnr = NULL,
1144 *mdns = NULL,
1145 *dnssec = NULL,
1146 *servers = NULL,
1147 *domains = NULL,
1148 *ntas = NULL;
1149
1150 ResolveSupport s;
1151 const char *p;
1152 int r;
1153
1154 assert(l);
1155 assert(l->state_file);
1156
1157 /* Try to load only a single time */
1158 if (l->loaded)
1159 return 0;
1160 l->loaded = true;
1161
1162 if (l->is_managed)
1163 return 0; /* if the device is managed, then networkd is our configuration source, not the bus API */
1164
1165 r = parse_env_file(l->state_file, NEWLINE,
1166 "LLMNR", &llmnr,
1167 "MDNS", &mdns,
1168 "DNSSEC", &dnssec,
1169 "SERVERS", &servers,
1170 "DOMAINS", &domains,
1171 "NTAS", &ntas,
1172 NULL);
1173 if (r == -ENOENT)
1174 return 0;
1175 if (r < 0)
1176 goto fail;
1177
1178 link_flush_settings(l);
1179
1180 /* If we can't recognize the LLMNR or MDNS setting we don't override the default */
1181 s = resolve_support_from_string(llmnr);
1182 if (s >= 0)
1183 l->llmnr_support = s;
1184
1185 s = resolve_support_from_string(mdns);
1186 if (s >= 0)
1187 l->mdns_support = s;
1188
1189 /* If we can't recognize the DNSSEC setting, then set it to invalid, so that the daemon default is used. */
1190 l->dnssec_mode = dnssec_mode_from_string(dnssec);
1191
1192 for (p = servers;;) {
1193 _cleanup_free_ char *word = NULL;
1194
1195 r = extract_first_word(&p, &word, NULL, 0);
1196 if (r < 0)
1197 goto fail;
1198 if (r == 0)
1199 break;
1200
1201 r = link_update_dns_server_one(l, word);
1202 if (r < 0) {
1203 log_debug_errno(r, "Failed to load DNS server '%s', ignoring: %m", word);
1204 continue;
1205 }
1206 }
1207
1208 for (p = domains;;) {
1209 _cleanup_free_ char *word = NULL;
1210 const char *n;
1211 bool is_route;
1212
1213 r = extract_first_word(&p, &word, NULL, 0);
1214 if (r < 0)
1215 goto fail;
1216 if (r == 0)
1217 break;
1218
1219 is_route = word[0] == '~';
1220 n = is_route ? word + 1 : word;
1221
1222 r = link_update_search_domain_one(l, n, is_route);
1223 if (r < 0) {
1224 log_debug_errno(r, "Failed to load search domain '%s', ignoring: %m", word);
1225 continue;
1226 }
1227 }
1228
1229 if (ntas) {
1230 _cleanup_set_free_free_ Set *ns = NULL;
1231
1232 ns = set_new(&dns_name_hash_ops);
1233 if (!ns) {
1234 r = -ENOMEM;
1235 goto fail;
1236 }
1237
1238 r = set_put_strsplit(ns, ntas, NULL, 0);
1239 if (r < 0)
1240 goto fail;
1241
1242 l->dnssec_negative_trust_anchors = ns;
1243 ns = NULL;
1244 }
1245
1246 return 0;
1247
1248 fail:
1249 return log_error_errno(r, "Failed to load link data %s: %m", l->state_file);
1250 }
1251
1252 void link_remove_user(Link *l) {
1253 assert(l);
1254 assert(l->state_file);
1255
1256 (void) unlink(l->state_file);
1257 }