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 local_multicast
) {
519 _cleanup_free_
char *state
= NULL
;
524 /* A link is relevant for local multicast traffic if it isn't a loopback or pointopoint device, has a link
525 * beat, can do multicast and has at least one link-local (or better) IP address.
527 * A link is relevant for non-multicast traffic if it isn't a loopback device, has a link beat, and has at
528 * least one routable address.*/
530 if (l
->flags
& (IFF_LOOPBACK
|IFF_DORMANT
))
533 if ((l
->flags
& (IFF_UP
|IFF_LOWER_UP
)) != (IFF_UP
|IFF_LOWER_UP
))
536 if (local_multicast
) {
537 if (l
->flags
& IFF_POINTOPOINT
)
540 if ((l
->flags
& IFF_MULTICAST
) != IFF_MULTICAST
)
544 /* Check kernel operstate
545 * https://www.kernel.org/doc/Documentation/networking/operstates.txt */
546 if (!IN_SET(l
->operstate
, IF_OPER_UNKNOWN
, IF_OPER_UP
))
549 (void) sd_network_link_get_operational_state(l
->ifindex
, &state
);
550 if (state
&& !STR_IN_SET(state
, "unknown", "degraded", "routable"))
553 LIST_FOREACH(addresses
, a
, l
->addresses
)
554 if ((family
== AF_UNSPEC
|| a
->family
== family
) && link_address_relevant(a
, local_multicast
))
560 LinkAddress
*link_find_address(Link
*l
, int family
, const union in_addr_union
*in_addr
) {
565 LIST_FOREACH(addresses
, a
, l
->addresses
)
566 if (a
->family
== family
&& in_addr_equal(family
, &a
->in_addr
, in_addr
))
572 DnsServer
* link_set_dns_server(Link
*l
, DnsServer
*s
) {
575 if (l
->current_dns_server
== s
)
579 log_info("Switching to DNS server %s for interface %s.", dns_server_string(s
), l
->name
);
581 dns_server_unref(l
->current_dns_server
);
582 l
->current_dns_server
= dns_server_ref(s
);
584 if (l
->unicast_scope
)
585 dns_cache_flush(&l
->unicast_scope
->cache
);
590 DnsServer
*link_get_dns_server(Link
*l
) {
593 if (!l
->current_dns_server
)
594 link_set_dns_server(l
, l
->dns_servers
);
596 return l
->current_dns_server
;
599 void link_next_dns_server(Link
*l
) {
602 if (!l
->current_dns_server
)
605 /* Change to the next one, but make sure to follow the linked
606 * list only if this server is actually still linked. */
607 if (l
->current_dns_server
->linked
&& l
->current_dns_server
->servers_next
) {
608 link_set_dns_server(l
, l
->current_dns_server
->servers_next
);
612 link_set_dns_server(l
, l
->dns_servers
);
615 DnssecMode
link_get_dnssec_mode(Link
*l
) {
618 if (l
->dnssec_mode
!= _DNSSEC_MODE_INVALID
)
619 return l
->dnssec_mode
;
621 return manager_get_dnssec_mode(l
->manager
);
624 bool link_dnssec_supported(Link
*l
) {
629 if (link_get_dnssec_mode(l
) == DNSSEC_NO
)
632 server
= link_get_dns_server(l
);
634 return dns_server_dnssec_supported(server
);
639 int link_address_new(Link
*l
, LinkAddress
**ret
, int family
, const union in_addr_union
*in_addr
) {
645 a
= new0(LinkAddress
, 1);
650 a
->in_addr
= *in_addr
;
653 LIST_PREPEND(addresses
, l
->addresses
, a
);
661 LinkAddress
*link_address_free(LinkAddress
*a
) {
666 LIST_REMOVE(addresses
, a
->link
->addresses
, a
);
668 if (a
->llmnr_address_rr
) {
669 if (a
->family
== AF_INET
&& a
->link
->llmnr_ipv4_scope
)
670 dns_zone_remove_rr(&a
->link
->llmnr_ipv4_scope
->zone
, a
->llmnr_address_rr
);
671 else if (a
->family
== AF_INET6
&& a
->link
->llmnr_ipv6_scope
)
672 dns_zone_remove_rr(&a
->link
->llmnr_ipv6_scope
->zone
, a
->llmnr_address_rr
);
675 if (a
->llmnr_ptr_rr
) {
676 if (a
->family
== AF_INET
&& a
->link
->llmnr_ipv4_scope
)
677 dns_zone_remove_rr(&a
->link
->llmnr_ipv4_scope
->zone
, a
->llmnr_ptr_rr
);
678 else if (a
->family
== AF_INET6
&& a
->link
->llmnr_ipv6_scope
)
679 dns_zone_remove_rr(&a
->link
->llmnr_ipv6_scope
->zone
, a
->llmnr_ptr_rr
);
683 dns_resource_record_unref(a
->llmnr_address_rr
);
684 dns_resource_record_unref(a
->llmnr_ptr_rr
);
690 void link_address_add_rrs(LinkAddress
*a
, bool force_remove
) {
695 if (a
->family
== AF_INET
) {
698 link_address_relevant(a
, true) &&
699 a
->link
->llmnr_ipv4_scope
&&
700 a
->link
->llmnr_support
== RESOLVE_SUPPORT_YES
&&
701 a
->link
->manager
->llmnr_support
== RESOLVE_SUPPORT_YES
) {
703 if (!a
->link
->manager
->llmnr_host_ipv4_key
) {
704 a
->link
->manager
->llmnr_host_ipv4_key
= dns_resource_key_new(DNS_CLASS_IN
, DNS_TYPE_A
, a
->link
->manager
->llmnr_hostname
);
705 if (!a
->link
->manager
->llmnr_host_ipv4_key
) {
711 if (!a
->llmnr_address_rr
) {
712 a
->llmnr_address_rr
= dns_resource_record_new(a
->link
->manager
->llmnr_host_ipv4_key
);
713 if (!a
->llmnr_address_rr
) {
718 a
->llmnr_address_rr
->a
.in_addr
= a
->in_addr
.in
;
719 a
->llmnr_address_rr
->ttl
= LLMNR_DEFAULT_TTL
;
722 if (!a
->llmnr_ptr_rr
) {
723 r
= dns_resource_record_new_reverse(&a
->llmnr_ptr_rr
, a
->family
, &a
->in_addr
, a
->link
->manager
->llmnr_hostname
);
727 a
->llmnr_ptr_rr
->ttl
= LLMNR_DEFAULT_TTL
;
730 r
= dns_zone_put(&a
->link
->llmnr_ipv4_scope
->zone
, a
->link
->llmnr_ipv4_scope
, a
->llmnr_address_rr
, true);
732 log_warning_errno(r
, "Failed to add A record to LLMNR zone: %m");
734 r
= dns_zone_put(&a
->link
->llmnr_ipv4_scope
->zone
, a
->link
->llmnr_ipv4_scope
, a
->llmnr_ptr_rr
, false);
736 log_warning_errno(r
, "Failed to add IPv6 PTR record to LLMNR zone: %m");
738 if (a
->llmnr_address_rr
) {
739 if (a
->link
->llmnr_ipv4_scope
)
740 dns_zone_remove_rr(&a
->link
->llmnr_ipv4_scope
->zone
, a
->llmnr_address_rr
);
741 a
->llmnr_address_rr
= dns_resource_record_unref(a
->llmnr_address_rr
);
744 if (a
->llmnr_ptr_rr
) {
745 if (a
->link
->llmnr_ipv4_scope
)
746 dns_zone_remove_rr(&a
->link
->llmnr_ipv4_scope
->zone
, a
->llmnr_ptr_rr
);
747 a
->llmnr_ptr_rr
= dns_resource_record_unref(a
->llmnr_ptr_rr
);
752 if (a
->family
== AF_INET6
) {
755 link_address_relevant(a
, true) &&
756 a
->link
->llmnr_ipv6_scope
&&
757 a
->link
->llmnr_support
== RESOLVE_SUPPORT_YES
&&
758 a
->link
->manager
->llmnr_support
== RESOLVE_SUPPORT_YES
) {
760 if (!a
->link
->manager
->llmnr_host_ipv6_key
) {
761 a
->link
->manager
->llmnr_host_ipv6_key
= dns_resource_key_new(DNS_CLASS_IN
, DNS_TYPE_AAAA
, a
->link
->manager
->llmnr_hostname
);
762 if (!a
->link
->manager
->llmnr_host_ipv6_key
) {
768 if (!a
->llmnr_address_rr
) {
769 a
->llmnr_address_rr
= dns_resource_record_new(a
->link
->manager
->llmnr_host_ipv6_key
);
770 if (!a
->llmnr_address_rr
) {
775 a
->llmnr_address_rr
->aaaa
.in6_addr
= a
->in_addr
.in6
;
776 a
->llmnr_address_rr
->ttl
= LLMNR_DEFAULT_TTL
;
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
);
784 a
->llmnr_ptr_rr
->ttl
= LLMNR_DEFAULT_TTL
;
787 r
= dns_zone_put(&a
->link
->llmnr_ipv6_scope
->zone
, a
->link
->llmnr_ipv6_scope
, a
->llmnr_address_rr
, true);
789 log_warning_errno(r
, "Failed to add AAAA record to LLMNR zone: %m");
791 r
= dns_zone_put(&a
->link
->llmnr_ipv6_scope
->zone
, a
->link
->llmnr_ipv6_scope
, a
->llmnr_ptr_rr
, false);
793 log_warning_errno(r
, "Failed to add IPv6 PTR record to LLMNR zone: %m");
795 if (a
->llmnr_address_rr
) {
796 if (a
->link
->llmnr_ipv6_scope
)
797 dns_zone_remove_rr(&a
->link
->llmnr_ipv6_scope
->zone
, a
->llmnr_address_rr
);
798 a
->llmnr_address_rr
= dns_resource_record_unref(a
->llmnr_address_rr
);
801 if (a
->llmnr_ptr_rr
) {
802 if (a
->link
->llmnr_ipv6_scope
)
803 dns_zone_remove_rr(&a
->link
->llmnr_ipv6_scope
->zone
, a
->llmnr_ptr_rr
);
804 a
->llmnr_ptr_rr
= dns_resource_record_unref(a
->llmnr_ptr_rr
);
812 log_debug_errno(r
, "Failed to update address RRs: %m");
815 int link_address_update_rtnl(LinkAddress
*a
, sd_netlink_message
*m
) {
820 r
= sd_rtnl_message_addr_get_flags(m
, &a
->flags
);
824 sd_rtnl_message_addr_get_scope(m
, &a
->scope
);
826 link_allocate_scopes(a
->link
);
827 link_add_rrs(a
->link
, false);
832 bool link_address_relevant(LinkAddress
*a
, bool local_multicast
) {
835 if (a
->flags
& (IFA_F_DEPRECATED
|IFA_F_TENTATIVE
))
838 if (a
->scope
>= (local_multicast
? RT_SCOPE_HOST
: RT_SCOPE_LINK
))