1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright 2014 Lennart Poettering
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
24 #include "sd-network.h"
26 #include "alloc-util.h"
28 #include "parse-util.h"
29 #include "resolved-link.h"
30 #include "string-util.h"
33 int link_new(Manager
*m
, Link
**ret
, int ifindex
) {
34 _cleanup_(link_freep
) Link
*l
= NULL
;
40 r
= hashmap_ensure_allocated(&m
->links
, NULL
);
49 l
->llmnr_support
= RESOLVE_SUPPORT_YES
;
50 l
->mdns_support
= RESOLVE_SUPPORT_NO
;
51 l
->dnssec_mode
= _DNSSEC_MODE_INVALID
;
53 r
= hashmap_put(m
->links
, INT_TO_PTR(ifindex
), l
);
66 void link_flush_settings(Link
*l
) {
69 l
->llmnr_support
= RESOLVE_SUPPORT_YES
;
70 l
->mdns_support
= RESOLVE_SUPPORT_NO
;
71 l
->dnssec_mode
= _DNSSEC_MODE_INVALID
;
73 dns_server_unlink_all(l
->dns_servers
);
74 dns_search_domain_unlink_all(l
->search_domains
);
76 l
->dnssec_negative_trust_anchors
= set_free_free(l
->dnssec_negative_trust_anchors
);
79 Link
*link_free(Link
*l
) {
83 link_flush_settings(l
);
86 (void) link_address_free(l
->addresses
);
89 hashmap_remove(l
->manager
->links
, INT_TO_PTR(l
->ifindex
));
91 dns_scope_free(l
->unicast_scope
);
92 dns_scope_free(l
->llmnr_ipv4_scope
);
93 dns_scope_free(l
->llmnr_ipv6_scope
);
94 dns_scope_free(l
->mdns_ipv4_scope
);
95 dns_scope_free(l
->mdns_ipv6_scope
);
101 void link_allocate_scopes(Link
*l
) {
106 if (link_relevant(l
, AF_UNSPEC
, false) &&
108 if (!l
->unicast_scope
) {
109 r
= dns_scope_new(l
->manager
, &l
->unicast_scope
, l
, DNS_PROTOCOL_DNS
, AF_UNSPEC
);
111 log_warning_errno(r
, "Failed to allocate DNS scope: %m");
114 l
->unicast_scope
= dns_scope_free(l
->unicast_scope
);
116 if (link_relevant(l
, AF_INET
, true) &&
117 l
->llmnr_support
!= RESOLVE_SUPPORT_NO
&&
118 l
->manager
->llmnr_support
!= RESOLVE_SUPPORT_NO
) {
119 if (!l
->llmnr_ipv4_scope
) {
120 r
= dns_scope_new(l
->manager
, &l
->llmnr_ipv4_scope
, l
, DNS_PROTOCOL_LLMNR
, AF_INET
);
122 log_warning_errno(r
, "Failed to allocate LLMNR IPv4 scope: %m");
125 l
->llmnr_ipv4_scope
= dns_scope_free(l
->llmnr_ipv4_scope
);
127 if (link_relevant(l
, AF_INET6
, true) &&
128 l
->llmnr_support
!= RESOLVE_SUPPORT_NO
&&
129 l
->manager
->llmnr_support
!= RESOLVE_SUPPORT_NO
&&
130 socket_ipv6_is_supported()) {
131 if (!l
->llmnr_ipv6_scope
) {
132 r
= dns_scope_new(l
->manager
, &l
->llmnr_ipv6_scope
, l
, DNS_PROTOCOL_LLMNR
, AF_INET6
);
134 log_warning_errno(r
, "Failed to allocate LLMNR IPv6 scope: %m");
137 l
->llmnr_ipv6_scope
= dns_scope_free(l
->llmnr_ipv6_scope
);
139 if (link_relevant(l
, AF_INET
, true) &&
140 l
->mdns_support
!= RESOLVE_SUPPORT_NO
&&
141 l
->manager
->mdns_support
!= RESOLVE_SUPPORT_NO
) {
142 if (!l
->mdns_ipv4_scope
) {
143 r
= dns_scope_new(l
->manager
, &l
->mdns_ipv4_scope
, l
, DNS_PROTOCOL_MDNS
, AF_INET
);
145 log_warning_errno(r
, "Failed to allocate mDNS IPv4 scope: %m");
148 l
->mdns_ipv4_scope
= dns_scope_free(l
->mdns_ipv4_scope
);
150 if (link_relevant(l
, AF_INET6
, true) &&
151 l
->mdns_support
!= RESOLVE_SUPPORT_NO
&&
152 l
->manager
->mdns_support
!= RESOLVE_SUPPORT_NO
) {
153 if (!l
->mdns_ipv6_scope
) {
154 r
= dns_scope_new(l
->manager
, &l
->mdns_ipv6_scope
, l
, DNS_PROTOCOL_MDNS
, AF_INET6
);
156 log_warning_errno(r
, "Failed to allocate mDNS IPv6 scope: %m");
159 l
->mdns_ipv6_scope
= dns_scope_free(l
->mdns_ipv6_scope
);
162 void link_add_rrs(Link
*l
, bool force_remove
) {
165 LIST_FOREACH(addresses
, a
, l
->addresses
)
166 link_address_add_rrs(a
, force_remove
);
169 int link_update_rtnl(Link
*l
, sd_netlink_message
*m
) {
170 const char *n
= NULL
;
176 r
= sd_rtnl_message_link_get_flags(m
, &l
->flags
);
180 sd_netlink_message_read_u32(m
, IFLA_MTU
, &l
->mtu
);
182 if (sd_netlink_message_read_string(m
, IFLA_IFNAME
, &n
) >= 0) {
183 strncpy(l
->name
, n
, sizeof(l
->name
)-1);
184 char_array_0(l
->name
);
187 link_allocate_scopes(l
);
188 link_add_rrs(l
, false);
193 static int link_update_dns_servers(Link
*l
) {
194 _cleanup_strv_free_
char **nameservers
= NULL
;
200 r
= sd_network_link_get_dns(l
->ifindex
, &nameservers
);
208 dns_server_mark_all(l
->dns_servers
);
210 STRV_FOREACH(nameserver
, nameservers
) {
211 union in_addr_union a
;
215 r
= in_addr_from_string_auto(*nameserver
, &family
, &a
);
219 s
= dns_server_find(l
->dns_servers
, family
, &a
);
221 dns_server_move_back_and_unmark(s
);
223 r
= dns_server_new(l
->manager
, NULL
, DNS_SERVER_LINK
, l
, family
, &a
);
229 dns_server_unlink_marked(l
->dns_servers
);
233 dns_server_unlink_all(l
->dns_servers
);
237 static int link_update_llmnr_support(Link
*l
) {
238 _cleanup_free_
char *b
= NULL
;
243 r
= sd_network_link_get_llmnr(l
->ifindex
, &b
);
251 l
->llmnr_support
= resolve_support_from_string(b
);
252 if (l
->llmnr_support
< 0) {
260 l
->llmnr_support
= RESOLVE_SUPPORT_YES
;
264 static int link_update_mdns_support(Link
*l
) {
265 _cleanup_free_
char *b
= NULL
;
270 r
= sd_network_link_get_mdns(l
->ifindex
, &b
);
278 l
->mdns_support
= resolve_support_from_string(b
);
279 if (l
->mdns_support
< 0) {
287 l
->mdns_support
= RESOLVE_SUPPORT_NO
;
291 void link_set_dnssec_mode(Link
*l
, DnssecMode mode
) {
295 if (l
->dnssec_mode
== mode
)
298 if ((l
->dnssec_mode
== _DNSSEC_MODE_INVALID
) ||
299 (l
->dnssec_mode
== DNSSEC_NO
&& mode
!= DNSSEC_NO
) ||
300 (l
->dnssec_mode
== DNSSEC_ALLOW_DOWNGRADE
&& mode
== DNSSEC_YES
)) {
302 /* When switching from non-DNSSEC mode to DNSSEC mode, flush the cache. Also when switching from the
303 * allow-downgrade mode to full DNSSEC mode, flush it too. */
304 if (l
->unicast_scope
)
305 dns_cache_flush(&l
->unicast_scope
->cache
);
308 l
->dnssec_mode
= mode
;
311 static int link_update_dnssec_mode(Link
*l
) {
312 _cleanup_free_
char *m
= NULL
;
318 r
= sd_network_link_get_dnssec(l
->ifindex
, &m
);
326 mode
= dnssec_mode_from_string(m
);
332 link_set_dnssec_mode(l
, mode
);
337 l
->dnssec_mode
= _DNSSEC_MODE_INVALID
;
341 static int link_update_dnssec_negative_trust_anchors(Link
*l
) {
342 _cleanup_strv_free_
char **ntas
= NULL
;
343 _cleanup_set_free_free_ Set
*ns
= NULL
;
349 r
= sd_network_link_get_dnssec_negative_trust_anchors(l
->ifindex
, &ntas
);
357 ns
= set_new(&dns_name_hash_ops
);
361 STRV_FOREACH(i
, ntas
) {
362 r
= set_put_strdup(ns
, *i
);
367 set_free_free(l
->dnssec_negative_trust_anchors
);
368 l
->dnssec_negative_trust_anchors
= ns
;
374 l
->dnssec_negative_trust_anchors
= set_free_free(l
->dnssec_negative_trust_anchors
);
378 static int link_update_search_domains(Link
*l
) {
379 _cleanup_strv_free_
char **domains
= NULL
;
385 r
= sd_network_link_get_domains(l
->ifindex
, &domains
);
387 /* networkd knows nothing about this interface, and that's fine. */
394 dns_search_domain_mark_all(l
->search_domains
);
396 STRV_FOREACH(i
, domains
) {
399 r
= dns_search_domain_find(l
->search_domains
, *i
, &d
);
404 dns_search_domain_move_back_and_unmark(d
);
406 r
= dns_search_domain_new(l
->manager
, NULL
, DNS_SEARCH_DOMAIN_LINK
, l
, *i
);
412 dns_search_domain_unlink_marked(l
->search_domains
);
416 dns_search_domain_unlink_all(l
->search_domains
);
420 static int link_is_unmanaged(Link
*l
) {
421 _cleanup_free_
char *state
= NULL
;
426 r
= sd_network_link_get_setup_state(l
->ifindex
, &state
);
432 return STR_IN_SET(state
, "pending", "unmanaged");
435 static void link_read_settings(Link
*l
) {
440 /* Read settings from networkd, except when networkd is not managing this interface. */
442 r
= link_is_unmanaged(l
);
444 log_warning_errno(r
, "Failed to determine whether interface %s is managed: %m", l
->name
);
449 /* If this link used to be managed, but is now unmanaged, flush all our settings -- but only once. */
451 link_flush_settings(l
);
453 l
->is_managed
= false;
457 l
->is_managed
= true;
459 r
= link_update_dns_servers(l
);
461 log_warning_errno(r
, "Failed to read DNS servers for interface %s, ignoring: %m", l
->name
);
463 r
= link_update_llmnr_support(l
);
465 log_warning_errno(r
, "Failed to read LLMNR support for interface %s, ignoring: %m", l
->name
);
467 r
= link_update_mdns_support(l
);
469 log_warning_errno(r
, "Failed to read mDNS support for interface %s, ignoring: %m", l
->name
);
471 r
= link_update_dnssec_mode(l
);
473 log_warning_errno(r
, "Failed to read DNSSEC mode for interface %s, ignoring: %m", l
->name
);
475 r
= link_update_dnssec_negative_trust_anchors(l
);
477 log_warning_errno(r
, "Failed to read DNSSEC negative trust anchors for interface %s, ignoring: %m", l
->name
);
479 r
= link_update_search_domains(l
);
481 log_warning_errno(r
, "Failed to read search domains for interface %s, ignoring: %m", l
->name
);
484 int link_update_monitor(Link
*l
) {
487 link_read_settings(l
);
488 link_allocate_scopes(l
);
489 link_add_rrs(l
, false);
494 bool link_relevant(Link
*l
, int family
, bool multicast
) {
495 _cleanup_free_
char *state
= NULL
;
500 /* A link is relevant for multicast traffic if it isn't a loopback or pointopoint device, has a link beat, can
501 * do multicast and has at least one relevant IP address */
503 if (l
->flags
& (IFF_LOOPBACK
|IFF_DORMANT
))
506 if ((l
->flags
& (IFF_UP
|IFF_LOWER_UP
)) != (IFF_UP
|IFF_LOWER_UP
))
510 if (l
->flags
& IFF_POINTOPOINT
)
513 if ((l
->flags
& IFF_MULTICAST
) != IFF_MULTICAST
)
517 sd_network_link_get_operational_state(l
->ifindex
, &state
);
518 if (state
&& !STR_IN_SET(state
, "unknown", "degraded", "routable"))
521 LIST_FOREACH(addresses
, a
, l
->addresses
)
522 if ((family
== AF_UNSPEC
|| a
->family
== family
) && link_address_relevant(a
))
528 LinkAddress
*link_find_address(Link
*l
, int family
, const union in_addr_union
*in_addr
) {
533 LIST_FOREACH(addresses
, a
, l
->addresses
)
534 if (a
->family
== family
&& in_addr_equal(family
, &a
->in_addr
, in_addr
))
540 DnsServer
* link_set_dns_server(Link
*l
, DnsServer
*s
) {
543 if (l
->current_dns_server
== s
)
547 log_info("Switching to DNS server %s for interface %s.", dns_server_string(s
), l
->name
);
549 dns_server_unref(l
->current_dns_server
);
550 l
->current_dns_server
= dns_server_ref(s
);
552 if (l
->unicast_scope
)
553 dns_cache_flush(&l
->unicast_scope
->cache
);
558 DnsServer
*link_get_dns_server(Link
*l
) {
561 if (!l
->current_dns_server
)
562 link_set_dns_server(l
, l
->dns_servers
);
564 return l
->current_dns_server
;
567 void link_next_dns_server(Link
*l
) {
570 if (!l
->current_dns_server
)
573 /* Change to the next one, but make sure to follow the linked
574 * list only if this server is actually still linked. */
575 if (l
->current_dns_server
->linked
&& l
->current_dns_server
->servers_next
) {
576 link_set_dns_server(l
, l
->current_dns_server
->servers_next
);
580 link_set_dns_server(l
, l
->dns_servers
);
583 DnssecMode
link_get_dnssec_mode(Link
*l
) {
586 if (l
->dnssec_mode
!= _DNSSEC_MODE_INVALID
)
587 return l
->dnssec_mode
;
589 return manager_get_dnssec_mode(l
->manager
);
592 bool link_dnssec_supported(Link
*l
) {
597 if (link_get_dnssec_mode(l
) == DNSSEC_NO
)
600 server
= link_get_dns_server(l
);
602 return dns_server_dnssec_supported(server
);
607 int link_address_new(Link
*l
, LinkAddress
**ret
, int family
, const union in_addr_union
*in_addr
) {
613 a
= new0(LinkAddress
, 1);
618 a
->in_addr
= *in_addr
;
621 LIST_PREPEND(addresses
, l
->addresses
, a
);
629 LinkAddress
*link_address_free(LinkAddress
*a
) {
634 LIST_REMOVE(addresses
, a
->link
->addresses
, a
);
636 if (a
->llmnr_address_rr
) {
637 if (a
->family
== AF_INET
&& a
->link
->llmnr_ipv4_scope
)
638 dns_zone_remove_rr(&a
->link
->llmnr_ipv4_scope
->zone
, a
->llmnr_address_rr
);
639 else if (a
->family
== AF_INET6
&& a
->link
->llmnr_ipv6_scope
)
640 dns_zone_remove_rr(&a
->link
->llmnr_ipv6_scope
->zone
, a
->llmnr_address_rr
);
643 if (a
->llmnr_ptr_rr
) {
644 if (a
->family
== AF_INET
&& a
->link
->llmnr_ipv4_scope
)
645 dns_zone_remove_rr(&a
->link
->llmnr_ipv4_scope
->zone
, a
->llmnr_ptr_rr
);
646 else if (a
->family
== AF_INET6
&& a
->link
->llmnr_ipv6_scope
)
647 dns_zone_remove_rr(&a
->link
->llmnr_ipv6_scope
->zone
, a
->llmnr_ptr_rr
);
651 dns_resource_record_unref(a
->llmnr_address_rr
);
652 dns_resource_record_unref(a
->llmnr_ptr_rr
);
658 void link_address_add_rrs(LinkAddress
*a
, bool force_remove
) {
663 if (a
->family
== AF_INET
) {
666 link_address_relevant(a
) &&
667 a
->link
->llmnr_ipv4_scope
&&
668 a
->link
->llmnr_support
== RESOLVE_SUPPORT_YES
&&
669 a
->link
->manager
->llmnr_support
== RESOLVE_SUPPORT_YES
) {
671 if (!a
->link
->manager
->llmnr_host_ipv4_key
) {
672 a
->link
->manager
->llmnr_host_ipv4_key
= dns_resource_key_new(DNS_CLASS_IN
, DNS_TYPE_A
, a
->link
->manager
->llmnr_hostname
);
673 if (!a
->link
->manager
->llmnr_host_ipv4_key
) {
679 if (!a
->llmnr_address_rr
) {
680 a
->llmnr_address_rr
= dns_resource_record_new(a
->link
->manager
->llmnr_host_ipv4_key
);
681 if (!a
->llmnr_address_rr
) {
686 a
->llmnr_address_rr
->a
.in_addr
= a
->in_addr
.in
;
687 a
->llmnr_address_rr
->ttl
= LLMNR_DEFAULT_TTL
;
690 if (!a
->llmnr_ptr_rr
) {
691 r
= dns_resource_record_new_reverse(&a
->llmnr_ptr_rr
, a
->family
, &a
->in_addr
, a
->link
->manager
->llmnr_hostname
);
695 a
->llmnr_ptr_rr
->ttl
= LLMNR_DEFAULT_TTL
;
698 r
= dns_zone_put(&a
->link
->llmnr_ipv4_scope
->zone
, a
->link
->llmnr_ipv4_scope
, a
->llmnr_address_rr
, true);
700 log_warning_errno(r
, "Failed to add A record to LLMNR zone: %m");
702 r
= dns_zone_put(&a
->link
->llmnr_ipv4_scope
->zone
, a
->link
->llmnr_ipv4_scope
, a
->llmnr_ptr_rr
, false);
704 log_warning_errno(r
, "Failed to add IPv6 PTR record to LLMNR zone: %m");
706 if (a
->llmnr_address_rr
) {
707 if (a
->link
->llmnr_ipv4_scope
)
708 dns_zone_remove_rr(&a
->link
->llmnr_ipv4_scope
->zone
, a
->llmnr_address_rr
);
709 a
->llmnr_address_rr
= dns_resource_record_unref(a
->llmnr_address_rr
);
712 if (a
->llmnr_ptr_rr
) {
713 if (a
->link
->llmnr_ipv4_scope
)
714 dns_zone_remove_rr(&a
->link
->llmnr_ipv4_scope
->zone
, a
->llmnr_ptr_rr
);
715 a
->llmnr_ptr_rr
= dns_resource_record_unref(a
->llmnr_ptr_rr
);
720 if (a
->family
== AF_INET6
) {
723 link_address_relevant(a
) &&
724 a
->link
->llmnr_ipv6_scope
&&
725 a
->link
->llmnr_support
== RESOLVE_SUPPORT_YES
&&
726 a
->link
->manager
->llmnr_support
== RESOLVE_SUPPORT_YES
) {
728 if (!a
->link
->manager
->llmnr_host_ipv6_key
) {
729 a
->link
->manager
->llmnr_host_ipv6_key
= dns_resource_key_new(DNS_CLASS_IN
, DNS_TYPE_AAAA
, a
->link
->manager
->llmnr_hostname
);
730 if (!a
->link
->manager
->llmnr_host_ipv6_key
) {
736 if (!a
->llmnr_address_rr
) {
737 a
->llmnr_address_rr
= dns_resource_record_new(a
->link
->manager
->llmnr_host_ipv6_key
);
738 if (!a
->llmnr_address_rr
) {
743 a
->llmnr_address_rr
->aaaa
.in6_addr
= a
->in_addr
.in6
;
744 a
->llmnr_address_rr
->ttl
= LLMNR_DEFAULT_TTL
;
747 if (!a
->llmnr_ptr_rr
) {
748 r
= dns_resource_record_new_reverse(&a
->llmnr_ptr_rr
, a
->family
, &a
->in_addr
, a
->link
->manager
->llmnr_hostname
);
752 a
->llmnr_ptr_rr
->ttl
= LLMNR_DEFAULT_TTL
;
755 r
= dns_zone_put(&a
->link
->llmnr_ipv6_scope
->zone
, a
->link
->llmnr_ipv6_scope
, a
->llmnr_address_rr
, true);
757 log_warning_errno(r
, "Failed to add AAAA record to LLMNR zone: %m");
759 r
= dns_zone_put(&a
->link
->llmnr_ipv6_scope
->zone
, a
->link
->llmnr_ipv6_scope
, a
->llmnr_ptr_rr
, false);
761 log_warning_errno(r
, "Failed to add IPv6 PTR record to LLMNR zone: %m");
763 if (a
->llmnr_address_rr
) {
764 if (a
->link
->llmnr_ipv6_scope
)
765 dns_zone_remove_rr(&a
->link
->llmnr_ipv6_scope
->zone
, a
->llmnr_address_rr
);
766 a
->llmnr_address_rr
= dns_resource_record_unref(a
->llmnr_address_rr
);
769 if (a
->llmnr_ptr_rr
) {
770 if (a
->link
->llmnr_ipv6_scope
)
771 dns_zone_remove_rr(&a
->link
->llmnr_ipv6_scope
->zone
, a
->llmnr_ptr_rr
);
772 a
->llmnr_ptr_rr
= dns_resource_record_unref(a
->llmnr_ptr_rr
);
780 log_debug_errno(r
, "Failed to update address RRs: %m");
783 int link_address_update_rtnl(LinkAddress
*a
, sd_netlink_message
*m
) {
788 r
= sd_rtnl_message_addr_get_flags(m
, &a
->flags
);
792 sd_rtnl_message_addr_get_scope(m
, &a
->scope
);
794 link_allocate_scopes(a
->link
);
795 link_add_rrs(a
->link
, false);
800 bool link_address_relevant(LinkAddress
*a
) {
803 if (a
->flags
& (IFA_F_DEPRECATED
|IFA_F_TENTATIVE
))
806 if (IN_SET(a
->scope
, RT_SCOPE_HOST
, RT_SCOPE_NOWHERE
))