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
;
52 l
->operstate
= IF_OPER_UNKNOWN
;
54 r
= hashmap_put(m
->links
, INT_TO_PTR(ifindex
), l
);
67 void link_flush_settings(Link
*l
) {
70 l
->llmnr_support
= RESOLVE_SUPPORT_YES
;
71 l
->mdns_support
= RESOLVE_SUPPORT_NO
;
72 l
->dnssec_mode
= _DNSSEC_MODE_INVALID
;
74 dns_server_unlink_all(l
->dns_servers
);
75 dns_search_domain_unlink_all(l
->search_domains
);
77 l
->dnssec_negative_trust_anchors
= set_free_free(l
->dnssec_negative_trust_anchors
);
80 Link
*link_free(Link
*l
) {
84 link_flush_settings(l
);
87 (void) link_address_free(l
->addresses
);
90 hashmap_remove(l
->manager
->links
, INT_TO_PTR(l
->ifindex
));
92 dns_scope_free(l
->unicast_scope
);
93 dns_scope_free(l
->llmnr_ipv4_scope
);
94 dns_scope_free(l
->llmnr_ipv6_scope
);
95 dns_scope_free(l
->mdns_ipv4_scope
);
96 dns_scope_free(l
->mdns_ipv6_scope
);
102 void link_allocate_scopes(Link
*l
) {
107 if (link_relevant(l
, AF_UNSPEC
, false) &&
109 if (!l
->unicast_scope
) {
110 r
= dns_scope_new(l
->manager
, &l
->unicast_scope
, l
, DNS_PROTOCOL_DNS
, AF_UNSPEC
);
112 log_warning_errno(r
, "Failed to allocate DNS scope: %m");
115 l
->unicast_scope
= dns_scope_free(l
->unicast_scope
);
117 if (link_relevant(l
, AF_INET
, true) &&
118 l
->llmnr_support
!= RESOLVE_SUPPORT_NO
&&
119 l
->manager
->llmnr_support
!= RESOLVE_SUPPORT_NO
) {
120 if (!l
->llmnr_ipv4_scope
) {
121 r
= dns_scope_new(l
->manager
, &l
->llmnr_ipv4_scope
, l
, DNS_PROTOCOL_LLMNR
, AF_INET
);
123 log_warning_errno(r
, "Failed to allocate LLMNR IPv4 scope: %m");
126 l
->llmnr_ipv4_scope
= dns_scope_free(l
->llmnr_ipv4_scope
);
128 if (link_relevant(l
, AF_INET6
, true) &&
129 l
->llmnr_support
!= RESOLVE_SUPPORT_NO
&&
130 l
->manager
->llmnr_support
!= RESOLVE_SUPPORT_NO
&&
131 socket_ipv6_is_supported()) {
132 if (!l
->llmnr_ipv6_scope
) {
133 r
= dns_scope_new(l
->manager
, &l
->llmnr_ipv6_scope
, l
, DNS_PROTOCOL_LLMNR
, AF_INET6
);
135 log_warning_errno(r
, "Failed to allocate LLMNR IPv6 scope: %m");
138 l
->llmnr_ipv6_scope
= dns_scope_free(l
->llmnr_ipv6_scope
);
140 if (link_relevant(l
, AF_INET
, true) &&
141 l
->mdns_support
!= RESOLVE_SUPPORT_NO
&&
142 l
->manager
->mdns_support
!= RESOLVE_SUPPORT_NO
) {
143 if (!l
->mdns_ipv4_scope
) {
144 r
= dns_scope_new(l
->manager
, &l
->mdns_ipv4_scope
, l
, DNS_PROTOCOL_MDNS
, AF_INET
);
146 log_warning_errno(r
, "Failed to allocate mDNS IPv4 scope: %m");
149 l
->mdns_ipv4_scope
= dns_scope_free(l
->mdns_ipv4_scope
);
151 if (link_relevant(l
, AF_INET6
, true) &&
152 l
->mdns_support
!= RESOLVE_SUPPORT_NO
&&
153 l
->manager
->mdns_support
!= RESOLVE_SUPPORT_NO
) {
154 if (!l
->mdns_ipv6_scope
) {
155 r
= dns_scope_new(l
->manager
, &l
->mdns_ipv6_scope
, l
, DNS_PROTOCOL_MDNS
, AF_INET6
);
157 log_warning_errno(r
, "Failed to allocate mDNS IPv6 scope: %m");
160 l
->mdns_ipv6_scope
= dns_scope_free(l
->mdns_ipv6_scope
);
163 void link_add_rrs(Link
*l
, bool force_remove
) {
166 LIST_FOREACH(addresses
, a
, l
->addresses
)
167 link_address_add_rrs(a
, force_remove
);
170 int link_update_rtnl(Link
*l
, sd_netlink_message
*m
) {
171 const char *n
= NULL
;
177 r
= sd_rtnl_message_link_get_flags(m
, &l
->flags
);
181 (void) sd_netlink_message_read_u32(m
, IFLA_MTU
, &l
->mtu
);
182 (void) sd_netlink_message_read_u8(m
, IFLA_OPERSTATE
, &l
->operstate
);
184 if (sd_netlink_message_read_string(m
, IFLA_IFNAME
, &n
) >= 0) {
185 strncpy(l
->name
, n
, sizeof(l
->name
)-1);
186 char_array_0(l
->name
);
189 link_allocate_scopes(l
);
190 link_add_rrs(l
, false);
195 static int link_update_dns_servers(Link
*l
) {
196 _cleanup_strv_free_
char **nameservers
= NULL
;
202 r
= sd_network_link_get_dns(l
->ifindex
, &nameservers
);
210 dns_server_mark_all(l
->dns_servers
);
212 STRV_FOREACH(nameserver
, nameservers
) {
213 union in_addr_union a
;
217 r
= in_addr_from_string_auto(*nameserver
, &family
, &a
);
221 s
= dns_server_find(l
->dns_servers
, family
, &a
);
223 dns_server_move_back_and_unmark(s
);
225 r
= dns_server_new(l
->manager
, NULL
, DNS_SERVER_LINK
, l
, family
, &a
);
231 dns_server_unlink_marked(l
->dns_servers
);
235 dns_server_unlink_all(l
->dns_servers
);
239 static int link_update_llmnr_support(Link
*l
) {
240 _cleanup_free_
char *b
= NULL
;
245 r
= sd_network_link_get_llmnr(l
->ifindex
, &b
);
253 l
->llmnr_support
= resolve_support_from_string(b
);
254 if (l
->llmnr_support
< 0) {
262 l
->llmnr_support
= RESOLVE_SUPPORT_YES
;
266 static int link_update_mdns_support(Link
*l
) {
267 _cleanup_free_
char *b
= NULL
;
272 r
= sd_network_link_get_mdns(l
->ifindex
, &b
);
280 l
->mdns_support
= resolve_support_from_string(b
);
281 if (l
->mdns_support
< 0) {
289 l
->mdns_support
= RESOLVE_SUPPORT_NO
;
293 void link_set_dnssec_mode(Link
*l
, DnssecMode mode
) {
297 if (l
->dnssec_mode
== mode
)
300 if ((l
->dnssec_mode
== _DNSSEC_MODE_INVALID
) ||
301 (l
->dnssec_mode
== DNSSEC_NO
&& mode
!= DNSSEC_NO
) ||
302 (l
->dnssec_mode
== DNSSEC_ALLOW_DOWNGRADE
&& mode
== DNSSEC_YES
)) {
304 /* When switching from non-DNSSEC mode to DNSSEC mode, flush the cache. Also when switching from the
305 * allow-downgrade mode to full DNSSEC mode, flush it too. */
306 if (l
->unicast_scope
)
307 dns_cache_flush(&l
->unicast_scope
->cache
);
310 l
->dnssec_mode
= mode
;
313 static int link_update_dnssec_mode(Link
*l
) {
314 _cleanup_free_
char *m
= NULL
;
320 r
= sd_network_link_get_dnssec(l
->ifindex
, &m
);
328 mode
= dnssec_mode_from_string(m
);
334 link_set_dnssec_mode(l
, mode
);
339 l
->dnssec_mode
= _DNSSEC_MODE_INVALID
;
343 static int link_update_dnssec_negative_trust_anchors(Link
*l
) {
344 _cleanup_strv_free_
char **ntas
= NULL
;
345 _cleanup_set_free_free_ Set
*ns
= NULL
;
351 r
= sd_network_link_get_dnssec_negative_trust_anchors(l
->ifindex
, &ntas
);
359 ns
= set_new(&dns_name_hash_ops
);
363 STRV_FOREACH(i
, ntas
) {
364 r
= set_put_strdup(ns
, *i
);
369 set_free_free(l
->dnssec_negative_trust_anchors
);
370 l
->dnssec_negative_trust_anchors
= ns
;
376 l
->dnssec_negative_trust_anchors
= set_free_free(l
->dnssec_negative_trust_anchors
);
380 static int link_update_search_domain_one(Link
*l
, const char *name
, bool route_only
) {
384 r
= dns_search_domain_find(l
->search_domains
, name
, &d
);
388 dns_search_domain_move_back_and_unmark(d
);
390 r
= dns_search_domain_new(l
->manager
, &d
, DNS_SEARCH_DOMAIN_LINK
, l
, name
);
395 d
->route_only
= route_only
;
399 static int link_update_search_domains(Link
*l
) {
400 _cleanup_strv_free_
char **sdomains
= NULL
, **rdomains
= NULL
;
406 r
= sd_network_link_get_search_domains(l
->ifindex
, &sdomains
);
407 if (r
< 0 && r
!= -ENODATA
)
410 q
= sd_network_link_get_route_domains(l
->ifindex
, &rdomains
);
411 if (q
< 0 && q
!= -ENODATA
) {
416 if (r
== -ENODATA
&& q
== -ENODATA
) {
417 /* networkd knows nothing about this interface, and that's fine. */
422 dns_search_domain_mark_all(l
->search_domains
);
424 STRV_FOREACH(i
, sdomains
) {
425 r
= link_update_search_domain_one(l
, *i
, false);
430 STRV_FOREACH(i
, rdomains
) {
431 r
= link_update_search_domain_one(l
, *i
, true);
436 dns_search_domain_unlink_marked(l
->search_domains
);
440 dns_search_domain_unlink_all(l
->search_domains
);
444 static int link_is_unmanaged(Link
*l
) {
445 _cleanup_free_
char *state
= NULL
;
450 r
= sd_network_link_get_setup_state(l
->ifindex
, &state
);
456 return STR_IN_SET(state
, "pending", "unmanaged");
459 static void link_read_settings(Link
*l
) {
464 /* Read settings from networkd, except when networkd is not managing this interface. */
466 r
= link_is_unmanaged(l
);
468 log_warning_errno(r
, "Failed to determine whether interface %s is managed: %m", l
->name
);
473 /* If this link used to be managed, but is now unmanaged, flush all our settings -- but only once. */
475 link_flush_settings(l
);
477 l
->is_managed
= false;
481 l
->is_managed
= true;
483 r
= link_update_dns_servers(l
);
485 log_warning_errno(r
, "Failed to read DNS servers for interface %s, ignoring: %m", l
->name
);
487 r
= link_update_llmnr_support(l
);
489 log_warning_errno(r
, "Failed to read LLMNR support for interface %s, ignoring: %m", l
->name
);
491 r
= link_update_mdns_support(l
);
493 log_warning_errno(r
, "Failed to read mDNS support for interface %s, ignoring: %m", l
->name
);
495 r
= link_update_dnssec_mode(l
);
497 log_warning_errno(r
, "Failed to read DNSSEC mode for interface %s, ignoring: %m", l
->name
);
499 r
= link_update_dnssec_negative_trust_anchors(l
);
501 log_warning_errno(r
, "Failed to read DNSSEC negative trust anchors for interface %s, ignoring: %m", l
->name
);
503 r
= link_update_search_domains(l
);
505 log_warning_errno(r
, "Failed to read search domains for interface %s, ignoring: %m", l
->name
);
508 int link_update_monitor(Link
*l
) {
511 link_read_settings(l
);
512 link_allocate_scopes(l
);
513 link_add_rrs(l
, false);
518 bool link_relevant(Link
*l
, int family
, bool multicast
) {
519 _cleanup_free_
char *state
= NULL
;
524 /* A link is relevant for multicast traffic if it isn't a loopback or pointopoint device, has a link beat, can
525 * do multicast and has at least one relevant IP address */
527 if (l
->flags
& (IFF_LOOPBACK
|IFF_DORMANT
))
530 if ((l
->flags
& (IFF_UP
|IFF_LOWER_UP
)) != (IFF_UP
|IFF_LOWER_UP
))
534 if (l
->flags
& IFF_POINTOPOINT
)
537 if ((l
->flags
& IFF_MULTICAST
) != IFF_MULTICAST
)
541 /* Check kernel operstate
542 * https://www.kernel.org/doc/Documentation/networking/operstates.txt */
543 if (!IN_SET(l
->operstate
, IF_OPER_UNKNOWN
, IF_OPER_UP
))
546 (void) sd_network_link_get_operational_state(l
->ifindex
, &state
);
547 if (state
&& !STR_IN_SET(state
, "unknown", "degraded", "routable"))
550 LIST_FOREACH(addresses
, a
, l
->addresses
)
551 if ((family
== AF_UNSPEC
|| a
->family
== family
) && link_address_relevant(a
))
557 LinkAddress
*link_find_address(Link
*l
, int family
, const union in_addr_union
*in_addr
) {
562 LIST_FOREACH(addresses
, a
, l
->addresses
)
563 if (a
->family
== family
&& in_addr_equal(family
, &a
->in_addr
, in_addr
))
569 DnsServer
* link_set_dns_server(Link
*l
, DnsServer
*s
) {
572 if (l
->current_dns_server
== s
)
576 log_info("Switching to DNS server %s for interface %s.", dns_server_string(s
), l
->name
);
578 dns_server_unref(l
->current_dns_server
);
579 l
->current_dns_server
= dns_server_ref(s
);
581 if (l
->unicast_scope
)
582 dns_cache_flush(&l
->unicast_scope
->cache
);
587 DnsServer
*link_get_dns_server(Link
*l
) {
590 if (!l
->current_dns_server
)
591 link_set_dns_server(l
, l
->dns_servers
);
593 return l
->current_dns_server
;
596 void link_next_dns_server(Link
*l
) {
599 if (!l
->current_dns_server
)
602 /* Change to the next one, but make sure to follow the linked
603 * list only if this server is actually still linked. */
604 if (l
->current_dns_server
->linked
&& l
->current_dns_server
->servers_next
) {
605 link_set_dns_server(l
, l
->current_dns_server
->servers_next
);
609 link_set_dns_server(l
, l
->dns_servers
);
612 DnssecMode
link_get_dnssec_mode(Link
*l
) {
615 if (l
->dnssec_mode
!= _DNSSEC_MODE_INVALID
)
616 return l
->dnssec_mode
;
618 return manager_get_dnssec_mode(l
->manager
);
621 bool link_dnssec_supported(Link
*l
) {
626 if (link_get_dnssec_mode(l
) == DNSSEC_NO
)
629 server
= link_get_dns_server(l
);
631 return dns_server_dnssec_supported(server
);
636 int link_address_new(Link
*l
, LinkAddress
**ret
, int family
, const union in_addr_union
*in_addr
) {
642 a
= new0(LinkAddress
, 1);
647 a
->in_addr
= *in_addr
;
650 LIST_PREPEND(addresses
, l
->addresses
, a
);
658 LinkAddress
*link_address_free(LinkAddress
*a
) {
663 LIST_REMOVE(addresses
, a
->link
->addresses
, a
);
665 if (a
->llmnr_address_rr
) {
666 if (a
->family
== AF_INET
&& a
->link
->llmnr_ipv4_scope
)
667 dns_zone_remove_rr(&a
->link
->llmnr_ipv4_scope
->zone
, a
->llmnr_address_rr
);
668 else if (a
->family
== AF_INET6
&& a
->link
->llmnr_ipv6_scope
)
669 dns_zone_remove_rr(&a
->link
->llmnr_ipv6_scope
->zone
, a
->llmnr_address_rr
);
672 if (a
->llmnr_ptr_rr
) {
673 if (a
->family
== AF_INET
&& a
->link
->llmnr_ipv4_scope
)
674 dns_zone_remove_rr(&a
->link
->llmnr_ipv4_scope
->zone
, a
->llmnr_ptr_rr
);
675 else if (a
->family
== AF_INET6
&& a
->link
->llmnr_ipv6_scope
)
676 dns_zone_remove_rr(&a
->link
->llmnr_ipv6_scope
->zone
, a
->llmnr_ptr_rr
);
680 dns_resource_record_unref(a
->llmnr_address_rr
);
681 dns_resource_record_unref(a
->llmnr_ptr_rr
);
687 void link_address_add_rrs(LinkAddress
*a
, bool force_remove
) {
692 if (a
->family
== AF_INET
) {
695 link_address_relevant(a
) &&
696 a
->link
->llmnr_ipv4_scope
&&
697 a
->link
->llmnr_support
== RESOLVE_SUPPORT_YES
&&
698 a
->link
->manager
->llmnr_support
== RESOLVE_SUPPORT_YES
) {
700 if (!a
->link
->manager
->llmnr_host_ipv4_key
) {
701 a
->link
->manager
->llmnr_host_ipv4_key
= dns_resource_key_new(DNS_CLASS_IN
, DNS_TYPE_A
, a
->link
->manager
->llmnr_hostname
);
702 if (!a
->link
->manager
->llmnr_host_ipv4_key
) {
708 if (!a
->llmnr_address_rr
) {
709 a
->llmnr_address_rr
= dns_resource_record_new(a
->link
->manager
->llmnr_host_ipv4_key
);
710 if (!a
->llmnr_address_rr
) {
715 a
->llmnr_address_rr
->a
.in_addr
= a
->in_addr
.in
;
716 a
->llmnr_address_rr
->ttl
= LLMNR_DEFAULT_TTL
;
719 if (!a
->llmnr_ptr_rr
) {
720 r
= dns_resource_record_new_reverse(&a
->llmnr_ptr_rr
, a
->family
, &a
->in_addr
, a
->link
->manager
->llmnr_hostname
);
724 a
->llmnr_ptr_rr
->ttl
= LLMNR_DEFAULT_TTL
;
727 r
= dns_zone_put(&a
->link
->llmnr_ipv4_scope
->zone
, a
->link
->llmnr_ipv4_scope
, a
->llmnr_address_rr
, true);
729 log_warning_errno(r
, "Failed to add A record to LLMNR zone: %m");
731 r
= dns_zone_put(&a
->link
->llmnr_ipv4_scope
->zone
, a
->link
->llmnr_ipv4_scope
, a
->llmnr_ptr_rr
, false);
733 log_warning_errno(r
, "Failed to add IPv6 PTR record to LLMNR zone: %m");
735 if (a
->llmnr_address_rr
) {
736 if (a
->link
->llmnr_ipv4_scope
)
737 dns_zone_remove_rr(&a
->link
->llmnr_ipv4_scope
->zone
, a
->llmnr_address_rr
);
738 a
->llmnr_address_rr
= dns_resource_record_unref(a
->llmnr_address_rr
);
741 if (a
->llmnr_ptr_rr
) {
742 if (a
->link
->llmnr_ipv4_scope
)
743 dns_zone_remove_rr(&a
->link
->llmnr_ipv4_scope
->zone
, a
->llmnr_ptr_rr
);
744 a
->llmnr_ptr_rr
= dns_resource_record_unref(a
->llmnr_ptr_rr
);
749 if (a
->family
== AF_INET6
) {
752 link_address_relevant(a
) &&
753 a
->link
->llmnr_ipv6_scope
&&
754 a
->link
->llmnr_support
== RESOLVE_SUPPORT_YES
&&
755 a
->link
->manager
->llmnr_support
== RESOLVE_SUPPORT_YES
) {
757 if (!a
->link
->manager
->llmnr_host_ipv6_key
) {
758 a
->link
->manager
->llmnr_host_ipv6_key
= dns_resource_key_new(DNS_CLASS_IN
, DNS_TYPE_AAAA
, a
->link
->manager
->llmnr_hostname
);
759 if (!a
->link
->manager
->llmnr_host_ipv6_key
) {
765 if (!a
->llmnr_address_rr
) {
766 a
->llmnr_address_rr
= dns_resource_record_new(a
->link
->manager
->llmnr_host_ipv6_key
);
767 if (!a
->llmnr_address_rr
) {
772 a
->llmnr_address_rr
->aaaa
.in6_addr
= a
->in_addr
.in6
;
773 a
->llmnr_address_rr
->ttl
= LLMNR_DEFAULT_TTL
;
776 if (!a
->llmnr_ptr_rr
) {
777 r
= dns_resource_record_new_reverse(&a
->llmnr_ptr_rr
, a
->family
, &a
->in_addr
, a
->link
->manager
->llmnr_hostname
);
781 a
->llmnr_ptr_rr
->ttl
= LLMNR_DEFAULT_TTL
;
784 r
= dns_zone_put(&a
->link
->llmnr_ipv6_scope
->zone
, a
->link
->llmnr_ipv6_scope
, a
->llmnr_address_rr
, true);
786 log_warning_errno(r
, "Failed to add AAAA record to LLMNR zone: %m");
788 r
= dns_zone_put(&a
->link
->llmnr_ipv6_scope
->zone
, a
->link
->llmnr_ipv6_scope
, a
->llmnr_ptr_rr
, false);
790 log_warning_errno(r
, "Failed to add IPv6 PTR record to LLMNR zone: %m");
792 if (a
->llmnr_address_rr
) {
793 if (a
->link
->llmnr_ipv6_scope
)
794 dns_zone_remove_rr(&a
->link
->llmnr_ipv6_scope
->zone
, a
->llmnr_address_rr
);
795 a
->llmnr_address_rr
= dns_resource_record_unref(a
->llmnr_address_rr
);
798 if (a
->llmnr_ptr_rr
) {
799 if (a
->link
->llmnr_ipv6_scope
)
800 dns_zone_remove_rr(&a
->link
->llmnr_ipv6_scope
->zone
, a
->llmnr_ptr_rr
);
801 a
->llmnr_ptr_rr
= dns_resource_record_unref(a
->llmnr_ptr_rr
);
809 log_debug_errno(r
, "Failed to update address RRs: %m");
812 int link_address_update_rtnl(LinkAddress
*a
, sd_netlink_message
*m
) {
817 r
= sd_rtnl_message_addr_get_flags(m
, &a
->flags
);
821 sd_rtnl_message_addr_get_scope(m
, &a
->scope
);
823 link_allocate_scopes(a
->link
);
824 link_add_rrs(a
->link
, false);
829 bool link_address_relevant(LinkAddress
*a
) {
832 if (a
->flags
& (IFA_F_DEPRECATED
|IFA_F_TENTATIVE
))
835 if (IN_SET(a
->scope
, RT_SCOPE_HOST
, RT_SCOPE_NOWHERE
))