1 /* SPDX-License-Identifier: LGPL-2.1+ */
3 This file is part of systemd.
5 Copyright 2014 Lennart Poettering
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.
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.
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/>.
22 #include <stdio_ext.h>
24 #include "sd-network.h"
26 #include "alloc-util.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"
38 int link_new(Manager
*m
, Link
**ret
, int ifindex
) {
39 _cleanup_(link_freep
) Link
*l
= NULL
;
45 r
= hashmap_ensure_allocated(&m
->links
, NULL
);
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
;
59 if (asprintf(&l
->state_file
, "/run/systemd/resolve/netif/%i", ifindex
) < 0)
62 r
= hashmap_put(m
->links
, INT_TO_PTR(ifindex
), l
);
75 void link_flush_settings(Link
*l
) {
78 l
->llmnr_support
= RESOLVE_SUPPORT_YES
;
79 l
->mdns_support
= RESOLVE_SUPPORT_NO
;
80 l
->dnssec_mode
= _DNSSEC_MODE_INVALID
;
82 dns_server_unlink_all(l
->dns_servers
);
83 dns_search_domain_unlink_all(l
->search_domains
);
85 l
->dnssec_negative_trust_anchors
= set_free_free(l
->dnssec_negative_trust_anchors
);
88 Link
*link_free(Link
*l
) {
92 /* Send goodbye messages. */
93 dns_scope_announce(l
->mdns_ipv4_scope
, true);
94 dns_scope_announce(l
->mdns_ipv6_scope
, true);
96 link_flush_settings(l
);
99 (void) link_address_free(l
->addresses
);
102 hashmap_remove(l
->manager
->links
, INT_TO_PTR(l
->ifindex
));
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
);
115 void link_allocate_scopes(Link
*l
) {
116 bool unicast_relevant
;
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. */
125 unicast_relevant
= link_relevant(l
, AF_UNSPEC
, false);
126 if (unicast_relevant
!= l
->unicast_relevant
) {
127 l
->unicast_relevant
= unicast_relevant
;
129 dns_server_reset_features_all(l
->manager
->fallback_dns_servers
);
130 dns_server_reset_features_all(l
->manager
->dns_servers
);
133 /* And now, allocate all scopes that makes sense now if we didn't have them yet, and drop those which we don't
136 if (unicast_relevant
&& l
->dns_servers
) {
137 if (!l
->unicast_scope
) {
138 dns_server_reset_features_all(l
->dns_servers
);
140 r
= dns_scope_new(l
->manager
, &l
->unicast_scope
, l
, DNS_PROTOCOL_DNS
, AF_UNSPEC
);
142 log_warning_errno(r
, "Failed to allocate DNS scope: %m");
145 l
->unicast_scope
= dns_scope_free(l
->unicast_scope
);
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
);
153 log_warning_errno(r
, "Failed to allocate LLMNR IPv4 scope: %m");
156 l
->llmnr_ipv4_scope
= dns_scope_free(l
->llmnr_ipv4_scope
);
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
);
165 log_warning_errno(r
, "Failed to allocate LLMNR IPv6 scope: %m");
168 l
->llmnr_ipv6_scope
= dns_scope_free(l
->llmnr_ipv6_scope
);
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
);
176 log_warning_errno(r
, "Failed to allocate mDNS IPv4 scope: %m");
179 l
->mdns_ipv4_scope
= dns_scope_free(l
->mdns_ipv4_scope
);
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
);
187 log_warning_errno(r
, "Failed to allocate mDNS IPv6 scope: %m");
190 l
->mdns_ipv6_scope
= dns_scope_free(l
->mdns_ipv6_scope
);
193 void link_add_rrs(Link
*l
, bool force_remove
) {
197 LIST_FOREACH(addresses
, a
, l
->addresses
)
198 link_address_add_rrs(a
, force_remove
);
201 l
->mdns_support
== RESOLVE_SUPPORT_YES
&&
202 l
->manager
->mdns_support
== RESOLVE_SUPPORT_YES
) {
204 if (l
->mdns_ipv4_scope
) {
205 r
= dns_scope_add_dnssd_services(l
->mdns_ipv4_scope
);
207 log_warning_errno(r
, "Failed to add IPv4 DNS-SD services: %m");
210 if (l
->mdns_ipv6_scope
) {
211 r
= dns_scope_add_dnssd_services(l
->mdns_ipv6_scope
);
213 log_warning_errno(r
, "Failed to add IPv6 DNS-SD services: %m");
218 if (l
->mdns_ipv4_scope
) {
219 r
= dns_scope_remove_dnssd_services(l
->mdns_ipv4_scope
);
221 log_warning_errno(r
, "Failed to remove IPv4 DNS-SD services: %m");
224 if (l
->mdns_ipv6_scope
) {
225 r
= dns_scope_remove_dnssd_services(l
->mdns_ipv6_scope
);
227 log_warning_errno(r
, "Failed to remove IPv6 DNS-SD services: %m");
232 int link_process_rtnl(Link
*l
, sd_netlink_message
*m
) {
233 const char *n
= NULL
;
239 r
= sd_rtnl_message_link_get_flags(m
, &l
->flags
);
243 (void) sd_netlink_message_read_u32(m
, IFLA_MTU
, &l
->mtu
);
244 (void) sd_netlink_message_read_u8(m
, IFLA_OPERSTATE
, &l
->operstate
);
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
);
251 link_allocate_scopes(l
);
252 link_add_rrs(l
, false);
257 static int link_update_dns_server_one(Link
*l
, const char *name
) {
258 union in_addr_union a
;
265 r
= in_addr_from_string_auto(name
, &family
, &a
);
269 s
= dns_server_find(l
->dns_servers
, family
, &a
, 0);
271 dns_server_move_back_and_unmark(s
);
275 return dns_server_new(l
->manager
, NULL
, DNS_SERVER_LINK
, l
, family
, &a
, 0);
278 static int link_update_dns_servers(Link
*l
) {
279 _cleanup_strv_free_
char **nameservers
= NULL
;
285 r
= sd_network_link_get_dns(l
->ifindex
, &nameservers
);
293 dns_server_mark_all(l
->dns_servers
);
295 STRV_FOREACH(nameserver
, nameservers
) {
296 r
= link_update_dns_server_one(l
, *nameserver
);
301 dns_server_unlink_marked(l
->dns_servers
);
305 dns_server_unlink_all(l
->dns_servers
);
309 static int link_update_llmnr_support(Link
*l
) {
310 _cleanup_free_
char *b
= NULL
;
315 r
= sd_network_link_get_llmnr(l
->ifindex
, &b
);
323 l
->llmnr_support
= resolve_support_from_string(b
);
324 if (l
->llmnr_support
< 0) {
332 l
->llmnr_support
= RESOLVE_SUPPORT_YES
;
336 static int link_update_mdns_support(Link
*l
) {
337 _cleanup_free_
char *b
= NULL
;
342 r
= sd_network_link_get_mdns(l
->ifindex
, &b
);
350 l
->mdns_support
= resolve_support_from_string(b
);
351 if (l
->mdns_support
< 0) {
359 l
->mdns_support
= RESOLVE_SUPPORT_NO
;
363 void link_set_dnssec_mode(Link
*l
, DnssecMode mode
) {
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.");
373 if (l
->dnssec_mode
== mode
)
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
)) {
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
);
386 l
->dnssec_mode
= mode
;
389 static int link_update_dnssec_mode(Link
*l
) {
390 _cleanup_free_
char *m
= NULL
;
396 r
= sd_network_link_get_dnssec(l
->ifindex
, &m
);
404 mode
= dnssec_mode_from_string(m
);
410 link_set_dnssec_mode(l
, mode
);
415 l
->dnssec_mode
= _DNSSEC_MODE_INVALID
;
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
;
426 r
= sd_network_link_get_dnssec_negative_trust_anchors(l
->ifindex
, &ntas
);
434 ns
= set_new(&dns_name_hash_ops
);
438 r
= set_put_strdupv(ns
, ntas
);
442 set_free_free(l
->dnssec_negative_trust_anchors
);
443 l
->dnssec_negative_trust_anchors
= TAKE_PTR(ns
);
448 l
->dnssec_negative_trust_anchors
= set_free_free(l
->dnssec_negative_trust_anchors
);
452 static int link_update_search_domain_one(Link
*l
, const char *name
, bool route_only
) {
459 r
= dns_search_domain_find(l
->search_domains
, name
, &d
);
463 dns_search_domain_move_back_and_unmark(d
);
465 r
= dns_search_domain_new(l
->manager
, &d
, DNS_SEARCH_DOMAIN_LINK
, l
, name
);
470 d
->route_only
= route_only
;
474 static int link_update_search_domains(Link
*l
) {
475 _cleanup_strv_free_
char **sdomains
= NULL
, **rdomains
= NULL
;
481 r
= sd_network_link_get_search_domains(l
->ifindex
, &sdomains
);
482 if (r
< 0 && r
!= -ENODATA
)
485 q
= sd_network_link_get_route_domains(l
->ifindex
, &rdomains
);
486 if (q
< 0 && q
!= -ENODATA
) {
491 if (r
== -ENODATA
&& q
== -ENODATA
) {
492 /* networkd knows nothing about this interface, and that's fine. */
497 dns_search_domain_mark_all(l
->search_domains
);
499 STRV_FOREACH(i
, sdomains
) {
500 r
= link_update_search_domain_one(l
, *i
, false);
505 STRV_FOREACH(i
, rdomains
) {
506 r
= link_update_search_domain_one(l
, *i
, true);
511 dns_search_domain_unlink_marked(l
->search_domains
);
515 dns_search_domain_unlink_all(l
->search_domains
);
519 static int link_is_managed(Link
*l
) {
520 _cleanup_free_
char *state
= NULL
;
525 r
= sd_network_link_get_setup_state(l
->ifindex
, &state
);
531 return !STR_IN_SET(state
, "pending", "unmanaged");
534 static void link_read_settings(Link
*l
) {
539 /* Read settings from networkd, except when networkd is not managing this interface. */
541 r
= link_is_managed(l
);
543 log_warning_errno(r
, "Failed to determine whether interface %s is managed: %m", l
->name
);
548 /* If this link used to be managed, but is now unmanaged, flush all our settings — but only once. */
550 link_flush_settings(l
);
552 l
->is_managed
= false;
556 l
->is_managed
= true;
558 r
= link_update_dns_servers(l
);
560 log_warning_errno(r
, "Failed to read DNS servers for interface %s, ignoring: %m", l
->name
);
562 r
= link_update_llmnr_support(l
);
564 log_warning_errno(r
, "Failed to read LLMNR support for interface %s, ignoring: %m", l
->name
);
566 r
= link_update_mdns_support(l
);
568 log_warning_errno(r
, "Failed to read mDNS support for interface %s, ignoring: %m", l
->name
);
570 r
= link_update_dnssec_mode(l
);
572 log_warning_errno(r
, "Failed to read DNSSEC mode for interface %s, ignoring: %m", l
->name
);
574 r
= link_update_dnssec_negative_trust_anchors(l
);
576 log_warning_errno(r
, "Failed to read DNSSEC negative trust anchors for interface %s, ignoring: %m", l
->name
);
578 r
= link_update_search_domains(l
);
580 log_warning_errno(r
, "Failed to read search domains for interface %s, ignoring: %m", l
->name
);
583 int link_update(Link
*l
) {
588 link_read_settings(l
);
591 if (l
->llmnr_support
!= RESOLVE_SUPPORT_NO
) {
592 r
= manager_llmnr_start(l
->manager
);
597 if (l
->mdns_support
!= RESOLVE_SUPPORT_NO
) {
598 r
= manager_mdns_start(l
->manager
);
603 link_allocate_scopes(l
);
604 link_add_rrs(l
, false);
609 bool link_relevant(Link
*l
, int family
, bool local_multicast
) {
610 _cleanup_free_
char *state
= NULL
;
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.
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. */
621 if (l
->flags
& (IFF_LOOPBACK
|IFF_DORMANT
))
624 if ((l
->flags
& (IFF_UP
|IFF_LOWER_UP
)) != (IFF_UP
|IFF_LOWER_UP
))
627 if (local_multicast
) {
628 if ((l
->flags
& IFF_MULTICAST
) != IFF_MULTICAST
)
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
))
637 (void) sd_network_link_get_operational_state(l
->ifindex
, &state
);
638 if (state
&& !STR_IN_SET(state
, "unknown", "degraded", "routable"))
641 LIST_FOREACH(addresses
, a
, l
->addresses
)
642 if ((family
== AF_UNSPEC
|| a
->family
== family
) && link_address_relevant(a
, local_multicast
))
648 LinkAddress
*link_find_address(Link
*l
, int family
, const union in_addr_union
*in_addr
) {
653 LIST_FOREACH(addresses
, a
, l
->addresses
)
654 if (a
->family
== family
&& in_addr_equal(family
, &a
->in_addr
, in_addr
))
660 DnsServer
* link_set_dns_server(Link
*l
, DnsServer
*s
) {
663 if (l
->current_dns_server
== s
)
667 log_debug("Switching to DNS server %s for interface %s.", dns_server_string(s
), l
->name
);
669 dns_server_unref(l
->current_dns_server
);
670 l
->current_dns_server
= dns_server_ref(s
);
672 if (l
->unicast_scope
)
673 dns_cache_flush(&l
->unicast_scope
->cache
);
678 DnsServer
*link_get_dns_server(Link
*l
) {
681 if (!l
->current_dns_server
)
682 link_set_dns_server(l
, l
->dns_servers
);
684 return l
->current_dns_server
;
687 void link_next_dns_server(Link
*l
) {
690 if (!l
->current_dns_server
)
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
);
700 link_set_dns_server(l
, l
->dns_servers
);
703 DnssecMode
link_get_dnssec_mode(Link
*l
) {
706 if (l
->dnssec_mode
!= _DNSSEC_MODE_INVALID
)
707 return l
->dnssec_mode
;
709 return manager_get_dnssec_mode(l
->manager
);
712 bool link_dnssec_supported(Link
*l
) {
717 if (link_get_dnssec_mode(l
) == DNSSEC_NO
)
720 server
= link_get_dns_server(l
);
722 return dns_server_dnssec_supported(server
);
727 int link_address_new(Link
*l
, LinkAddress
**ret
, int family
, const union in_addr_union
*in_addr
) {
733 a
= new0(LinkAddress
, 1);
738 a
->in_addr
= *in_addr
;
741 LIST_PREPEND(addresses
, l
->addresses
, a
);
750 LinkAddress
*link_address_free(LinkAddress
*a
) {
755 LIST_REMOVE(addresses
, a
->link
->addresses
, a
);
757 assert(a
->link
->n_addresses
> 0);
758 a
->link
->n_addresses
--;
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
);
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
);
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
);
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
);
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
);
797 void link_address_add_rrs(LinkAddress
*a
, bool force_remove
) {
802 if (a
->family
== AF_INET
) {
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
) {
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
) {
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
) {
825 a
->llmnr_address_rr
->a
.in_addr
= a
->in_addr
.in
;
826 a
->llmnr_address_rr
->ttl
= LLMNR_DEFAULT_TTL
;
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
);
834 a
->llmnr_ptr_rr
->ttl
= LLMNR_DEFAULT_TTL
;
837 r
= dns_zone_put(&a
->link
->llmnr_ipv4_scope
->zone
, a
->link
->llmnr_ipv4_scope
, a
->llmnr_address_rr
, true);
839 log_warning_errno(r
, "Failed to add A record to LLMNR zone: %m");
841 r
= dns_zone_put(&a
->link
->llmnr_ipv4_scope
->zone
, a
->link
->llmnr_ipv4_scope
, a
->llmnr_ptr_rr
, false);
843 log_warning_errno(r
, "Failed to add IPv4 PTR record to LLMNR zone: %m");
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
);
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
);
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
) {
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
) {
878 a
->mdns_address_rr
->a
.in_addr
= a
->in_addr
.in
;
879 a
->mdns_address_rr
->ttl
= MDNS_DEFAULT_TTL
;
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
);
887 a
->mdns_ptr_rr
->ttl
= MDNS_DEFAULT_TTL
;
890 r
= dns_zone_put(&a
->link
->mdns_ipv4_scope
->zone
, a
->link
->mdns_ipv4_scope
, a
->mdns_address_rr
, true);
892 log_warning_errno(r
, "Failed to add A record to MDNS zone: %m");
894 r
= dns_zone_put(&a
->link
->mdns_ipv4_scope
->zone
, a
->link
->mdns_ipv4_scope
, a
->mdns_ptr_rr
, false);
896 log_warning_errno(r
, "Failed to add IPv4 PTR record to MDNS zone: %m");
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
);
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
);
912 if (a
->family
== AF_INET6
) {
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
) {
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
) {
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
) {
935 a
->llmnr_address_rr
->aaaa
.in6_addr
= a
->in_addr
.in6
;
936 a
->llmnr_address_rr
->ttl
= LLMNR_DEFAULT_TTL
;
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
);
944 a
->llmnr_ptr_rr
->ttl
= LLMNR_DEFAULT_TTL
;
947 r
= dns_zone_put(&a
->link
->llmnr_ipv6_scope
->zone
, a
->link
->llmnr_ipv6_scope
, a
->llmnr_address_rr
, true);
949 log_warning_errno(r
, "Failed to add AAAA record to LLMNR zone: %m");
951 r
= dns_zone_put(&a
->link
->llmnr_ipv6_scope
->zone
, a
->link
->llmnr_ipv6_scope
, a
->llmnr_ptr_rr
, false);
953 log_warning_errno(r
, "Failed to add IPv6 PTR record to LLMNR zone: %m");
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
);
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
);
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
) {
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
) {
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
) {
989 a
->mdns_address_rr
->aaaa
.in6_addr
= a
->in_addr
.in6
;
990 a
->mdns_address_rr
->ttl
= MDNS_DEFAULT_TTL
;
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
);
998 a
->mdns_ptr_rr
->ttl
= MDNS_DEFAULT_TTL
;
1001 r
= dns_zone_put(&a
->link
->mdns_ipv6_scope
->zone
, a
->link
->mdns_ipv6_scope
, a
->mdns_address_rr
, true);
1003 log_warning_errno(r
, "Failed to add AAAA record to MDNS zone: %m");
1005 r
= dns_zone_put(&a
->link
->mdns_ipv6_scope
->zone
, a
->link
->mdns_ipv6_scope
, a
->mdns_ptr_rr
, false);
1007 log_warning_errno(r
, "Failed to add IPv6 PTR record to MDNS zone: %m");
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
);
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
);
1026 log_debug_errno(r
, "Failed to update address RRs: %m");
1029 int link_address_update_rtnl(LinkAddress
*a
, sd_netlink_message
*m
) {
1034 r
= sd_rtnl_message_addr_get_flags(m
, &a
->flags
);
1038 sd_rtnl_message_addr_get_scope(m
, &a
->scope
);
1040 link_allocate_scopes(a
->link
);
1041 link_add_rrs(a
->link
, false);
1046 bool link_address_relevant(LinkAddress
*a
, bool local_multicast
) {
1049 if (a
->flags
& (IFA_F_DEPRECATED
|IFA_F_TENTATIVE
))
1052 if (a
->scope
>= (local_multicast
? RT_SCOPE_HOST
: RT_SCOPE_LINK
))
1058 static bool link_needs_save(Link
*l
) {
1061 /* Returns true if any of the settings where set different from the default */
1066 if (l
->llmnr_support
!= RESOLVE_SUPPORT_YES
||
1067 l
->mdns_support
!= RESOLVE_SUPPORT_NO
||
1068 l
->dnssec_mode
!= _DNSSEC_MODE_INVALID
)
1071 if (l
->dns_servers
||
1075 if (!set_isempty(l
->dnssec_negative_trust_anchors
))
1081 int link_save_user(Link
*l
) {
1082 _cleanup_free_
char *temp_path
= NULL
;
1083 _cleanup_fclose_
FILE *f
= NULL
;
1088 assert(l
->state_file
);
1090 if (!link_needs_save(l
)) {
1091 (void) unlink(l
->state_file
);
1095 r
= mkdir_parents(l
->state_file
, 0700);
1099 r
= fopen_temporary(l
->state_file
, &f
, &temp_path
);
1103 (void) __fsetlocking(f
, FSETLOCKING_BYCALLER
);
1104 (void) fchmod(fileno(f
), 0644);
1106 fputs("# This is private data. Do not parse.\n", f
);
1108 v
= resolve_support_to_string(l
->llmnr_support
);
1110 fprintf(f
, "LLMNR=%s\n", v
);
1112 v
= resolve_support_to_string(l
->mdns_support
);
1114 fprintf(f
, "MDNS=%s\n", v
);
1116 v
= dnssec_mode_to_string(l
->dnssec_mode
);
1118 fprintf(f
, "DNSSEC=%s\n", v
);
1120 if (l
->dns_servers
) {
1123 fputs("SERVERS=", f
);
1124 LIST_FOREACH(servers
, server
, l
->dns_servers
) {
1126 if (server
!= l
->dns_servers
)
1129 v
= dns_server_string(server
);
1140 if (l
->search_domains
) {
1141 DnsSearchDomain
*domain
;
1143 fputs("DOMAINS=", f
);
1144 LIST_FOREACH(domains
, domain
, l
->search_domains
) {
1146 if (domain
!= l
->search_domains
)
1149 if (domain
->route_only
)
1152 fputs(DNS_SEARCH_DOMAIN_NAME(domain
), f
);
1157 if (!set_isempty(l
->dnssec_negative_trust_anchors
)) {
1163 SET_FOREACH(nta
, l
->dnssec_negative_trust_anchors
, i
) {
1174 r
= fflush_and_check(f
);
1178 if (rename(temp_path
, l
->state_file
) < 0) {
1186 (void) unlink(l
->state_file
);
1189 (void) unlink(temp_path
);
1191 return log_error_errno(r
, "Failed to save link data %s: %m", l
->state_file
);
1194 int link_load_user(Link
*l
) {
1208 assert(l
->state_file
);
1210 /* Try to load only a single time */
1216 return 0; /* if the device is managed, then networkd is our configuration source, not the bus API */
1218 r
= parse_env_file(l
->state_file
, NEWLINE
,
1222 "SERVERS", &servers
,
1223 "DOMAINS", &domains
,
1231 link_flush_settings(l
);
1233 /* If we can't recognize the LLMNR or MDNS setting we don't override the default */
1234 s
= resolve_support_from_string(llmnr
);
1236 l
->llmnr_support
= s
;
1238 s
= resolve_support_from_string(mdns
);
1240 l
->mdns_support
= s
;
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
);
1245 for (p
= servers
;;) {
1246 _cleanup_free_
char *word
= NULL
;
1248 r
= extract_first_word(&p
, &word
, NULL
, 0);
1254 r
= link_update_dns_server_one(l
, word
);
1256 log_debug_errno(r
, "Failed to load DNS server '%s', ignoring: %m", word
);
1261 for (p
= domains
;;) {
1262 _cleanup_free_
char *word
= NULL
;
1266 r
= extract_first_word(&p
, &word
, NULL
, 0);
1272 is_route
= word
[0] == '~';
1273 n
= is_route
? word
+ 1 : word
;
1275 r
= link_update_search_domain_one(l
, n
, is_route
);
1277 log_debug_errno(r
, "Failed to load search domain '%s', ignoring: %m", word
);
1283 _cleanup_set_free_free_ Set
*ns
= NULL
;
1285 ns
= set_new(&dns_name_hash_ops
);
1291 r
= set_put_strsplit(ns
, ntas
, NULL
, 0);
1295 l
->dnssec_negative_trust_anchors
= TAKE_PTR(ns
);
1301 return log_error_errno(r
, "Failed to load link data %s: %m", l
->state_file
);
1304 void link_remove_user(Link
*l
) {
1306 assert(l
->state_file
);
1308 (void) unlink(l
->state_file
);