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_domains(Link
*l
) {
381 _cleanup_strv_free_
char **domains
= NULL
;
387 r
= sd_network_link_get_domains(l
->ifindex
, &domains
);
389 /* networkd knows nothing about this interface, and that's fine. */
396 dns_search_domain_mark_all(l
->search_domains
);
398 STRV_FOREACH(i
, domains
) {
401 r
= dns_search_domain_find(l
->search_domains
, *i
, &d
);
406 dns_search_domain_move_back_and_unmark(d
);
408 r
= dns_search_domain_new(l
->manager
, NULL
, DNS_SEARCH_DOMAIN_LINK
, l
, *i
);
414 dns_search_domain_unlink_marked(l
->search_domains
);
418 dns_search_domain_unlink_all(l
->search_domains
);
422 static int link_is_unmanaged(Link
*l
) {
423 _cleanup_free_
char *state
= NULL
;
428 r
= sd_network_link_get_setup_state(l
->ifindex
, &state
);
434 return STR_IN_SET(state
, "pending", "unmanaged");
437 static void link_read_settings(Link
*l
) {
442 /* Read settings from networkd, except when networkd is not managing this interface. */
444 r
= link_is_unmanaged(l
);
446 log_warning_errno(r
, "Failed to determine whether interface %s is managed: %m", l
->name
);
451 /* If this link used to be managed, but is now unmanaged, flush all our settings -- but only once. */
453 link_flush_settings(l
);
455 l
->is_managed
= false;
459 l
->is_managed
= true;
461 r
= link_update_dns_servers(l
);
463 log_warning_errno(r
, "Failed to read DNS servers for interface %s, ignoring: %m", l
->name
);
465 r
= link_update_llmnr_support(l
);
467 log_warning_errno(r
, "Failed to read LLMNR support for interface %s, ignoring: %m", l
->name
);
469 r
= link_update_mdns_support(l
);
471 log_warning_errno(r
, "Failed to read mDNS support for interface %s, ignoring: %m", l
->name
);
473 r
= link_update_dnssec_mode(l
);
475 log_warning_errno(r
, "Failed to read DNSSEC mode for interface %s, ignoring: %m", l
->name
);
477 r
= link_update_dnssec_negative_trust_anchors(l
);
479 log_warning_errno(r
, "Failed to read DNSSEC negative trust anchors for interface %s, ignoring: %m", l
->name
);
481 r
= link_update_search_domains(l
);
483 log_warning_errno(r
, "Failed to read search domains for interface %s, ignoring: %m", l
->name
);
486 int link_update_monitor(Link
*l
) {
489 link_read_settings(l
);
490 link_allocate_scopes(l
);
491 link_add_rrs(l
, false);
496 bool link_relevant(Link
*l
, int family
, bool multicast
) {
497 _cleanup_free_
char *state
= NULL
;
502 /* A link is relevant for multicast traffic if it isn't a loopback or pointopoint device, has a link beat, can
503 * do multicast and has at least one relevant IP address */
505 if (l
->flags
& (IFF_LOOPBACK
|IFF_DORMANT
))
508 if ((l
->flags
& (IFF_UP
|IFF_LOWER_UP
)) != (IFF_UP
|IFF_LOWER_UP
))
512 if (l
->flags
& IFF_POINTOPOINT
)
515 if ((l
->flags
& IFF_MULTICAST
) != IFF_MULTICAST
)
519 /* Check kernel operstate
520 * https://www.kernel.org/doc/Documentation/networking/operstates.txt */
521 if (!IN_SET(l
->operstate
, IF_OPER_UNKNOWN
, IF_OPER_UP
))
524 (void) sd_network_link_get_operational_state(l
->ifindex
, &state
);
525 if (state
&& !STR_IN_SET(state
, "unknown", "degraded", "routable"))
528 LIST_FOREACH(addresses
, a
, l
->addresses
)
529 if ((family
== AF_UNSPEC
|| a
->family
== family
) && link_address_relevant(a
))
535 LinkAddress
*link_find_address(Link
*l
, int family
, const union in_addr_union
*in_addr
) {
540 LIST_FOREACH(addresses
, a
, l
->addresses
)
541 if (a
->family
== family
&& in_addr_equal(family
, &a
->in_addr
, in_addr
))
547 DnsServer
* link_set_dns_server(Link
*l
, DnsServer
*s
) {
550 if (l
->current_dns_server
== s
)
554 log_info("Switching to DNS server %s for interface %s.", dns_server_string(s
), l
->name
);
556 dns_server_unref(l
->current_dns_server
);
557 l
->current_dns_server
= dns_server_ref(s
);
559 if (l
->unicast_scope
)
560 dns_cache_flush(&l
->unicast_scope
->cache
);
565 DnsServer
*link_get_dns_server(Link
*l
) {
568 if (!l
->current_dns_server
)
569 link_set_dns_server(l
, l
->dns_servers
);
571 return l
->current_dns_server
;
574 void link_next_dns_server(Link
*l
) {
577 if (!l
->current_dns_server
)
580 /* Change to the next one, but make sure to follow the linked
581 * list only if this server is actually still linked. */
582 if (l
->current_dns_server
->linked
&& l
->current_dns_server
->servers_next
) {
583 link_set_dns_server(l
, l
->current_dns_server
->servers_next
);
587 link_set_dns_server(l
, l
->dns_servers
);
590 DnssecMode
link_get_dnssec_mode(Link
*l
) {
593 if (l
->dnssec_mode
!= _DNSSEC_MODE_INVALID
)
594 return l
->dnssec_mode
;
596 return manager_get_dnssec_mode(l
->manager
);
599 bool link_dnssec_supported(Link
*l
) {
604 if (link_get_dnssec_mode(l
) == DNSSEC_NO
)
607 server
= link_get_dns_server(l
);
609 return dns_server_dnssec_supported(server
);
614 int link_address_new(Link
*l
, LinkAddress
**ret
, int family
, const union in_addr_union
*in_addr
) {
620 a
= new0(LinkAddress
, 1);
625 a
->in_addr
= *in_addr
;
628 LIST_PREPEND(addresses
, l
->addresses
, a
);
636 LinkAddress
*link_address_free(LinkAddress
*a
) {
641 LIST_REMOVE(addresses
, a
->link
->addresses
, a
);
643 if (a
->llmnr_address_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_address_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_address_rr
);
650 if (a
->llmnr_ptr_rr
) {
651 if (a
->family
== AF_INET
&& a
->link
->llmnr_ipv4_scope
)
652 dns_zone_remove_rr(&a
->link
->llmnr_ipv4_scope
->zone
, a
->llmnr_ptr_rr
);
653 else if (a
->family
== AF_INET6
&& a
->link
->llmnr_ipv6_scope
)
654 dns_zone_remove_rr(&a
->link
->llmnr_ipv6_scope
->zone
, a
->llmnr_ptr_rr
);
658 dns_resource_record_unref(a
->llmnr_address_rr
);
659 dns_resource_record_unref(a
->llmnr_ptr_rr
);
665 void link_address_add_rrs(LinkAddress
*a
, bool force_remove
) {
670 if (a
->family
== AF_INET
) {
673 link_address_relevant(a
) &&
674 a
->link
->llmnr_ipv4_scope
&&
675 a
->link
->llmnr_support
== RESOLVE_SUPPORT_YES
&&
676 a
->link
->manager
->llmnr_support
== RESOLVE_SUPPORT_YES
) {
678 if (!a
->link
->manager
->llmnr_host_ipv4_key
) {
679 a
->link
->manager
->llmnr_host_ipv4_key
= dns_resource_key_new(DNS_CLASS_IN
, DNS_TYPE_A
, a
->link
->manager
->llmnr_hostname
);
680 if (!a
->link
->manager
->llmnr_host_ipv4_key
) {
686 if (!a
->llmnr_address_rr
) {
687 a
->llmnr_address_rr
= dns_resource_record_new(a
->link
->manager
->llmnr_host_ipv4_key
);
688 if (!a
->llmnr_address_rr
) {
693 a
->llmnr_address_rr
->a
.in_addr
= a
->in_addr
.in
;
694 a
->llmnr_address_rr
->ttl
= LLMNR_DEFAULT_TTL
;
697 if (!a
->llmnr_ptr_rr
) {
698 r
= dns_resource_record_new_reverse(&a
->llmnr_ptr_rr
, a
->family
, &a
->in_addr
, a
->link
->manager
->llmnr_hostname
);
702 a
->llmnr_ptr_rr
->ttl
= LLMNR_DEFAULT_TTL
;
705 r
= dns_zone_put(&a
->link
->llmnr_ipv4_scope
->zone
, a
->link
->llmnr_ipv4_scope
, a
->llmnr_address_rr
, true);
707 log_warning_errno(r
, "Failed to add A record to LLMNR zone: %m");
709 r
= dns_zone_put(&a
->link
->llmnr_ipv4_scope
->zone
, a
->link
->llmnr_ipv4_scope
, a
->llmnr_ptr_rr
, false);
711 log_warning_errno(r
, "Failed to add IPv6 PTR record to LLMNR zone: %m");
713 if (a
->llmnr_address_rr
) {
714 if (a
->link
->llmnr_ipv4_scope
)
715 dns_zone_remove_rr(&a
->link
->llmnr_ipv4_scope
->zone
, a
->llmnr_address_rr
);
716 a
->llmnr_address_rr
= dns_resource_record_unref(a
->llmnr_address_rr
);
719 if (a
->llmnr_ptr_rr
) {
720 if (a
->link
->llmnr_ipv4_scope
)
721 dns_zone_remove_rr(&a
->link
->llmnr_ipv4_scope
->zone
, a
->llmnr_ptr_rr
);
722 a
->llmnr_ptr_rr
= dns_resource_record_unref(a
->llmnr_ptr_rr
);
727 if (a
->family
== AF_INET6
) {
730 link_address_relevant(a
) &&
731 a
->link
->llmnr_ipv6_scope
&&
732 a
->link
->llmnr_support
== RESOLVE_SUPPORT_YES
&&
733 a
->link
->manager
->llmnr_support
== RESOLVE_SUPPORT_YES
) {
735 if (!a
->link
->manager
->llmnr_host_ipv6_key
) {
736 a
->link
->manager
->llmnr_host_ipv6_key
= dns_resource_key_new(DNS_CLASS_IN
, DNS_TYPE_AAAA
, a
->link
->manager
->llmnr_hostname
);
737 if (!a
->link
->manager
->llmnr_host_ipv6_key
) {
743 if (!a
->llmnr_address_rr
) {
744 a
->llmnr_address_rr
= dns_resource_record_new(a
->link
->manager
->llmnr_host_ipv6_key
);
745 if (!a
->llmnr_address_rr
) {
750 a
->llmnr_address_rr
->aaaa
.in6_addr
= a
->in_addr
.in6
;
751 a
->llmnr_address_rr
->ttl
= LLMNR_DEFAULT_TTL
;
754 if (!a
->llmnr_ptr_rr
) {
755 r
= dns_resource_record_new_reverse(&a
->llmnr_ptr_rr
, a
->family
, &a
->in_addr
, a
->link
->manager
->llmnr_hostname
);
759 a
->llmnr_ptr_rr
->ttl
= LLMNR_DEFAULT_TTL
;
762 r
= dns_zone_put(&a
->link
->llmnr_ipv6_scope
->zone
, a
->link
->llmnr_ipv6_scope
, a
->llmnr_address_rr
, true);
764 log_warning_errno(r
, "Failed to add AAAA record to LLMNR zone: %m");
766 r
= dns_zone_put(&a
->link
->llmnr_ipv6_scope
->zone
, a
->link
->llmnr_ipv6_scope
, a
->llmnr_ptr_rr
, false);
768 log_warning_errno(r
, "Failed to add IPv6 PTR record to LLMNR zone: %m");
770 if (a
->llmnr_address_rr
) {
771 if (a
->link
->llmnr_ipv6_scope
)
772 dns_zone_remove_rr(&a
->link
->llmnr_ipv6_scope
->zone
, a
->llmnr_address_rr
);
773 a
->llmnr_address_rr
= dns_resource_record_unref(a
->llmnr_address_rr
);
776 if (a
->llmnr_ptr_rr
) {
777 if (a
->link
->llmnr_ipv6_scope
)
778 dns_zone_remove_rr(&a
->link
->llmnr_ipv6_scope
->zone
, a
->llmnr_ptr_rr
);
779 a
->llmnr_ptr_rr
= dns_resource_record_unref(a
->llmnr_ptr_rr
);
787 log_debug_errno(r
, "Failed to update address RRs: %m");
790 int link_address_update_rtnl(LinkAddress
*a
, sd_netlink_message
*m
) {
795 r
= sd_rtnl_message_addr_get_flags(m
, &a
->flags
);
799 sd_rtnl_message_addr_get_scope(m
, &a
->scope
);
801 link_allocate_scopes(a
->link
);
802 link_add_rrs(a
->link
, false);
807 bool link_address_relevant(LinkAddress
*a
) {
810 if (a
->flags
& (IFA_F_DEPRECATED
|IFA_F_TENTATIVE
))
813 if (IN_SET(a
->scope
, RT_SCOPE_HOST
, RT_SCOPE_NOWHERE
))