2 This file is part of systemd.
4 Copyright 2014 Lennart Poettering
6 systemd is free software; you can redistribute it and/or modify it
7 under the terms of the GNU Lesser General Public License as published by
8 the Free Software Foundation; either version 2.1 of the License, or
9 (at your option) any later version.
11 systemd is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Lesser General Public License for more details.
16 You should have received a copy of the GNU Lesser General Public License
17 along with systemd; If not, see <http://www.gnu.org/licenses/>.
22 #include "sd-network.h"
24 #include "alloc-util.h"
26 #include "parse-util.h"
27 #include "resolved-link.h"
28 #include "string-util.h"
31 int link_new(Manager
*m
, Link
**ret
, int ifindex
) {
32 _cleanup_(link_freep
) Link
*l
= NULL
;
38 r
= hashmap_ensure_allocated(&m
->links
, NULL
);
47 l
->llmnr_support
= RESOLVE_SUPPORT_YES
;
48 l
->mdns_support
= RESOLVE_SUPPORT_NO
;
49 l
->dnssec_mode
= _DNSSEC_MODE_INVALID
;
50 l
->operstate
= IF_OPER_UNKNOWN
;
52 r
= hashmap_put(m
->links
, INT_TO_PTR(ifindex
), l
);
65 void link_flush_settings(Link
*l
) {
68 l
->llmnr_support
= RESOLVE_SUPPORT_YES
;
69 l
->mdns_support
= RESOLVE_SUPPORT_NO
;
70 l
->dnssec_mode
= _DNSSEC_MODE_INVALID
;
72 dns_server_unlink_all(l
->dns_servers
);
73 dns_search_domain_unlink_all(l
->search_domains
);
75 l
->dnssec_negative_trust_anchors
= set_free_free(l
->dnssec_negative_trust_anchors
);
78 Link
*link_free(Link
*l
) {
82 link_flush_settings(l
);
85 (void) link_address_free(l
->addresses
);
88 hashmap_remove(l
->manager
->links
, INT_TO_PTR(l
->ifindex
));
90 dns_scope_free(l
->unicast_scope
);
91 dns_scope_free(l
->llmnr_ipv4_scope
);
92 dns_scope_free(l
->llmnr_ipv6_scope
);
93 dns_scope_free(l
->mdns_ipv4_scope
);
94 dns_scope_free(l
->mdns_ipv6_scope
);
100 void link_allocate_scopes(Link
*l
) {
105 if (link_relevant(l
, AF_UNSPEC
, false) &&
107 if (!l
->unicast_scope
) {
108 r
= dns_scope_new(l
->manager
, &l
->unicast_scope
, l
, DNS_PROTOCOL_DNS
, AF_UNSPEC
);
110 log_warning_errno(r
, "Failed to allocate DNS scope: %m");
113 l
->unicast_scope
= dns_scope_free(l
->unicast_scope
);
115 if (link_relevant(l
, AF_INET
, true) &&
116 l
->llmnr_support
!= RESOLVE_SUPPORT_NO
&&
117 l
->manager
->llmnr_support
!= RESOLVE_SUPPORT_NO
) {
118 if (!l
->llmnr_ipv4_scope
) {
119 r
= dns_scope_new(l
->manager
, &l
->llmnr_ipv4_scope
, l
, DNS_PROTOCOL_LLMNR
, AF_INET
);
121 log_warning_errno(r
, "Failed to allocate LLMNR IPv4 scope: %m");
124 l
->llmnr_ipv4_scope
= dns_scope_free(l
->llmnr_ipv4_scope
);
126 if (link_relevant(l
, AF_INET6
, true) &&
127 l
->llmnr_support
!= RESOLVE_SUPPORT_NO
&&
128 l
->manager
->llmnr_support
!= RESOLVE_SUPPORT_NO
&&
129 socket_ipv6_is_supported()) {
130 if (!l
->llmnr_ipv6_scope
) {
131 r
= dns_scope_new(l
->manager
, &l
->llmnr_ipv6_scope
, l
, DNS_PROTOCOL_LLMNR
, AF_INET6
);
133 log_warning_errno(r
, "Failed to allocate LLMNR IPv6 scope: %m");
136 l
->llmnr_ipv6_scope
= dns_scope_free(l
->llmnr_ipv6_scope
);
138 if (link_relevant(l
, AF_INET
, true) &&
139 l
->mdns_support
!= RESOLVE_SUPPORT_NO
&&
140 l
->manager
->mdns_support
!= RESOLVE_SUPPORT_NO
) {
141 if (!l
->mdns_ipv4_scope
) {
142 r
= dns_scope_new(l
->manager
, &l
->mdns_ipv4_scope
, l
, DNS_PROTOCOL_MDNS
, AF_INET
);
144 log_warning_errno(r
, "Failed to allocate mDNS IPv4 scope: %m");
147 l
->mdns_ipv4_scope
= dns_scope_free(l
->mdns_ipv4_scope
);
149 if (link_relevant(l
, AF_INET6
, true) &&
150 l
->mdns_support
!= RESOLVE_SUPPORT_NO
&&
151 l
->manager
->mdns_support
!= RESOLVE_SUPPORT_NO
) {
152 if (!l
->mdns_ipv6_scope
) {
153 r
= dns_scope_new(l
->manager
, &l
->mdns_ipv6_scope
, l
, DNS_PROTOCOL_MDNS
, AF_INET6
);
155 log_warning_errno(r
, "Failed to allocate mDNS IPv6 scope: %m");
158 l
->mdns_ipv6_scope
= dns_scope_free(l
->mdns_ipv6_scope
);
161 void link_add_rrs(Link
*l
, bool force_remove
) {
164 LIST_FOREACH(addresses
, a
, l
->addresses
)
165 link_address_add_rrs(a
, force_remove
);
168 int link_update_rtnl(Link
*l
, sd_netlink_message
*m
) {
169 const char *n
= NULL
;
175 r
= sd_rtnl_message_link_get_flags(m
, &l
->flags
);
179 (void) sd_netlink_message_read_u32(m
, IFLA_MTU
, &l
->mtu
);
180 (void) sd_netlink_message_read_u8(m
, IFLA_OPERSTATE
, &l
->operstate
);
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_domain_one(Link
*l
, const char *name
, bool route_only
) {
382 r
= dns_search_domain_find(l
->search_domains
, name
, &d
);
386 dns_search_domain_move_back_and_unmark(d
);
388 r
= dns_search_domain_new(l
->manager
, &d
, DNS_SEARCH_DOMAIN_LINK
, l
, name
);
393 d
->route_only
= route_only
;
397 static int link_update_search_domains(Link
*l
) {
398 _cleanup_strv_free_
char **sdomains
= NULL
, **rdomains
= NULL
;
404 r
= sd_network_link_get_search_domains(l
->ifindex
, &sdomains
);
405 if (r
< 0 && r
!= -ENODATA
)
408 q
= sd_network_link_get_route_domains(l
->ifindex
, &rdomains
);
409 if (q
< 0 && q
!= -ENODATA
) {
414 if (r
== -ENODATA
&& q
== -ENODATA
) {
415 /* networkd knows nothing about this interface, and that's fine. */
420 dns_search_domain_mark_all(l
->search_domains
);
422 STRV_FOREACH(i
, sdomains
) {
423 r
= link_update_search_domain_one(l
, *i
, false);
428 STRV_FOREACH(i
, rdomains
) {
429 r
= link_update_search_domain_one(l
, *i
, true);
434 dns_search_domain_unlink_marked(l
->search_domains
);
438 dns_search_domain_unlink_all(l
->search_domains
);
442 static int link_is_unmanaged(Link
*l
) {
443 _cleanup_free_
char *state
= NULL
;
448 r
= sd_network_link_get_setup_state(l
->ifindex
, &state
);
454 return STR_IN_SET(state
, "pending", "unmanaged");
457 static void link_read_settings(Link
*l
) {
462 /* Read settings from networkd, except when networkd is not managing this interface. */
464 r
= link_is_unmanaged(l
);
466 log_warning_errno(r
, "Failed to determine whether interface %s is managed: %m", l
->name
);
471 /* If this link used to be managed, but is now unmanaged, flush all our settings -- but only once. */
473 link_flush_settings(l
);
475 l
->is_managed
= false;
479 l
->is_managed
= true;
481 r
= link_update_dns_servers(l
);
483 log_warning_errno(r
, "Failed to read DNS servers for interface %s, ignoring: %m", l
->name
);
485 r
= link_update_llmnr_support(l
);
487 log_warning_errno(r
, "Failed to read LLMNR support for interface %s, ignoring: %m", l
->name
);
489 r
= link_update_mdns_support(l
);
491 log_warning_errno(r
, "Failed to read mDNS support for interface %s, ignoring: %m", l
->name
);
493 r
= link_update_dnssec_mode(l
);
495 log_warning_errno(r
, "Failed to read DNSSEC mode for interface %s, ignoring: %m", l
->name
);
497 r
= link_update_dnssec_negative_trust_anchors(l
);
499 log_warning_errno(r
, "Failed to read DNSSEC negative trust anchors for interface %s, ignoring: %m", l
->name
);
501 r
= link_update_search_domains(l
);
503 log_warning_errno(r
, "Failed to read search domains for interface %s, ignoring: %m", l
->name
);
506 int link_update_monitor(Link
*l
) {
509 link_read_settings(l
);
510 link_allocate_scopes(l
);
511 link_add_rrs(l
, false);
516 bool link_relevant(Link
*l
, int family
, bool local_multicast
) {
517 _cleanup_free_
char *state
= NULL
;
522 /* A link is relevant for local multicast traffic if it isn't a loopback or pointopoint device, has a link
523 * beat, can do multicast and has at least one link-local (or better) IP address.
525 * A link is relevant for non-multicast traffic if it isn't a loopback device, has a link beat, and has at
526 * least one routable address.*/
528 if (l
->flags
& (IFF_LOOPBACK
|IFF_DORMANT
))
531 if ((l
->flags
& (IFF_UP
|IFF_LOWER_UP
)) != (IFF_UP
|IFF_LOWER_UP
))
534 if (local_multicast
) {
535 if (l
->flags
& IFF_POINTOPOINT
)
538 if ((l
->flags
& IFF_MULTICAST
) != IFF_MULTICAST
)
542 /* Check kernel operstate
543 * https://www.kernel.org/doc/Documentation/networking/operstates.txt */
544 if (!IN_SET(l
->operstate
, IF_OPER_UNKNOWN
, IF_OPER_UP
))
547 (void) sd_network_link_get_operational_state(l
->ifindex
, &state
);
548 if (state
&& !STR_IN_SET(state
, "unknown", "degraded", "routable"))
551 LIST_FOREACH(addresses
, a
, l
->addresses
)
552 if ((family
== AF_UNSPEC
|| a
->family
== family
) && link_address_relevant(a
, local_multicast
))
558 LinkAddress
*link_find_address(Link
*l
, int family
, const union in_addr_union
*in_addr
) {
563 LIST_FOREACH(addresses
, a
, l
->addresses
)
564 if (a
->family
== family
&& in_addr_equal(family
, &a
->in_addr
, in_addr
))
570 DnsServer
* link_set_dns_server(Link
*l
, DnsServer
*s
) {
573 if (l
->current_dns_server
== s
)
577 log_info("Switching to DNS server %s for interface %s.", dns_server_string(s
), l
->name
);
579 dns_server_unref(l
->current_dns_server
);
580 l
->current_dns_server
= dns_server_ref(s
);
582 if (l
->unicast_scope
)
583 dns_cache_flush(&l
->unicast_scope
->cache
);
588 DnsServer
*link_get_dns_server(Link
*l
) {
591 if (!l
->current_dns_server
)
592 link_set_dns_server(l
, l
->dns_servers
);
594 return l
->current_dns_server
;
597 void link_next_dns_server(Link
*l
) {
600 if (!l
->current_dns_server
)
603 /* Change to the next one, but make sure to follow the linked
604 * list only if this server is actually still linked. */
605 if (l
->current_dns_server
->linked
&& l
->current_dns_server
->servers_next
) {
606 link_set_dns_server(l
, l
->current_dns_server
->servers_next
);
610 link_set_dns_server(l
, l
->dns_servers
);
613 DnssecMode
link_get_dnssec_mode(Link
*l
) {
616 if (l
->dnssec_mode
!= _DNSSEC_MODE_INVALID
)
617 return l
->dnssec_mode
;
619 return manager_get_dnssec_mode(l
->manager
);
622 bool link_dnssec_supported(Link
*l
) {
627 if (link_get_dnssec_mode(l
) == DNSSEC_NO
)
630 server
= link_get_dns_server(l
);
632 return dns_server_dnssec_supported(server
);
637 int link_address_new(Link
*l
, LinkAddress
**ret
, int family
, const union in_addr_union
*in_addr
) {
643 a
= new0(LinkAddress
, 1);
648 a
->in_addr
= *in_addr
;
651 LIST_PREPEND(addresses
, l
->addresses
, a
);
659 LinkAddress
*link_address_free(LinkAddress
*a
) {
664 LIST_REMOVE(addresses
, a
->link
->addresses
, a
);
666 if (a
->llmnr_address_rr
) {
667 if (a
->family
== AF_INET
&& a
->link
->llmnr_ipv4_scope
)
668 dns_zone_remove_rr(&a
->link
->llmnr_ipv4_scope
->zone
, a
->llmnr_address_rr
);
669 else if (a
->family
== AF_INET6
&& a
->link
->llmnr_ipv6_scope
)
670 dns_zone_remove_rr(&a
->link
->llmnr_ipv6_scope
->zone
, a
->llmnr_address_rr
);
673 if (a
->llmnr_ptr_rr
) {
674 if (a
->family
== AF_INET
&& a
->link
->llmnr_ipv4_scope
)
675 dns_zone_remove_rr(&a
->link
->llmnr_ipv4_scope
->zone
, a
->llmnr_ptr_rr
);
676 else if (a
->family
== AF_INET6
&& a
->link
->llmnr_ipv6_scope
)
677 dns_zone_remove_rr(&a
->link
->llmnr_ipv6_scope
->zone
, a
->llmnr_ptr_rr
);
681 dns_resource_record_unref(a
->llmnr_address_rr
);
682 dns_resource_record_unref(a
->llmnr_ptr_rr
);
688 void link_address_add_rrs(LinkAddress
*a
, bool force_remove
) {
693 if (a
->family
== AF_INET
) {
696 link_address_relevant(a
, true) &&
697 a
->link
->llmnr_ipv4_scope
&&
698 a
->link
->llmnr_support
== RESOLVE_SUPPORT_YES
&&
699 a
->link
->manager
->llmnr_support
== RESOLVE_SUPPORT_YES
) {
701 if (!a
->link
->manager
->llmnr_host_ipv4_key
) {
702 a
->link
->manager
->llmnr_host_ipv4_key
= dns_resource_key_new(DNS_CLASS_IN
, DNS_TYPE_A
, a
->link
->manager
->llmnr_hostname
);
703 if (!a
->link
->manager
->llmnr_host_ipv4_key
) {
709 if (!a
->llmnr_address_rr
) {
710 a
->llmnr_address_rr
= dns_resource_record_new(a
->link
->manager
->llmnr_host_ipv4_key
);
711 if (!a
->llmnr_address_rr
) {
716 a
->llmnr_address_rr
->a
.in_addr
= a
->in_addr
.in
;
717 a
->llmnr_address_rr
->ttl
= LLMNR_DEFAULT_TTL
;
720 if (!a
->llmnr_ptr_rr
) {
721 r
= dns_resource_record_new_reverse(&a
->llmnr_ptr_rr
, a
->family
, &a
->in_addr
, a
->link
->manager
->llmnr_hostname
);
725 a
->llmnr_ptr_rr
->ttl
= LLMNR_DEFAULT_TTL
;
728 r
= dns_zone_put(&a
->link
->llmnr_ipv4_scope
->zone
, a
->link
->llmnr_ipv4_scope
, a
->llmnr_address_rr
, true);
730 log_warning_errno(r
, "Failed to add A record to LLMNR zone: %m");
732 r
= dns_zone_put(&a
->link
->llmnr_ipv4_scope
->zone
, a
->link
->llmnr_ipv4_scope
, a
->llmnr_ptr_rr
, false);
734 log_warning_errno(r
, "Failed to add IPv6 PTR record to LLMNR zone: %m");
736 if (a
->llmnr_address_rr
) {
737 if (a
->link
->llmnr_ipv4_scope
)
738 dns_zone_remove_rr(&a
->link
->llmnr_ipv4_scope
->zone
, a
->llmnr_address_rr
);
739 a
->llmnr_address_rr
= dns_resource_record_unref(a
->llmnr_address_rr
);
742 if (a
->llmnr_ptr_rr
) {
743 if (a
->link
->llmnr_ipv4_scope
)
744 dns_zone_remove_rr(&a
->link
->llmnr_ipv4_scope
->zone
, a
->llmnr_ptr_rr
);
745 a
->llmnr_ptr_rr
= dns_resource_record_unref(a
->llmnr_ptr_rr
);
750 if (a
->family
== AF_INET6
) {
753 link_address_relevant(a
, true) &&
754 a
->link
->llmnr_ipv6_scope
&&
755 a
->link
->llmnr_support
== RESOLVE_SUPPORT_YES
&&
756 a
->link
->manager
->llmnr_support
== RESOLVE_SUPPORT_YES
) {
758 if (!a
->link
->manager
->llmnr_host_ipv6_key
) {
759 a
->link
->manager
->llmnr_host_ipv6_key
= dns_resource_key_new(DNS_CLASS_IN
, DNS_TYPE_AAAA
, a
->link
->manager
->llmnr_hostname
);
760 if (!a
->link
->manager
->llmnr_host_ipv6_key
) {
766 if (!a
->llmnr_address_rr
) {
767 a
->llmnr_address_rr
= dns_resource_record_new(a
->link
->manager
->llmnr_host_ipv6_key
);
768 if (!a
->llmnr_address_rr
) {
773 a
->llmnr_address_rr
->aaaa
.in6_addr
= a
->in_addr
.in6
;
774 a
->llmnr_address_rr
->ttl
= LLMNR_DEFAULT_TTL
;
777 if (!a
->llmnr_ptr_rr
) {
778 r
= dns_resource_record_new_reverse(&a
->llmnr_ptr_rr
, a
->family
, &a
->in_addr
, a
->link
->manager
->llmnr_hostname
);
782 a
->llmnr_ptr_rr
->ttl
= LLMNR_DEFAULT_TTL
;
785 r
= dns_zone_put(&a
->link
->llmnr_ipv6_scope
->zone
, a
->link
->llmnr_ipv6_scope
, a
->llmnr_address_rr
, true);
787 log_warning_errno(r
, "Failed to add AAAA record to LLMNR zone: %m");
789 r
= dns_zone_put(&a
->link
->llmnr_ipv6_scope
->zone
, a
->link
->llmnr_ipv6_scope
, a
->llmnr_ptr_rr
, false);
791 log_warning_errno(r
, "Failed to add IPv6 PTR record to LLMNR zone: %m");
793 if (a
->llmnr_address_rr
) {
794 if (a
->link
->llmnr_ipv6_scope
)
795 dns_zone_remove_rr(&a
->link
->llmnr_ipv6_scope
->zone
, a
->llmnr_address_rr
);
796 a
->llmnr_address_rr
= dns_resource_record_unref(a
->llmnr_address_rr
);
799 if (a
->llmnr_ptr_rr
) {
800 if (a
->link
->llmnr_ipv6_scope
)
801 dns_zone_remove_rr(&a
->link
->llmnr_ipv6_scope
->zone
, a
->llmnr_ptr_rr
);
802 a
->llmnr_ptr_rr
= dns_resource_record_unref(a
->llmnr_ptr_rr
);
810 log_debug_errno(r
, "Failed to update address RRs: %m");
813 int link_address_update_rtnl(LinkAddress
*a
, sd_netlink_message
*m
) {
818 r
= sd_rtnl_message_addr_get_flags(m
, &a
->flags
);
822 sd_rtnl_message_addr_get_scope(m
, &a
->scope
);
824 link_allocate_scopes(a
->link
);
825 link_add_rrs(a
->link
, false);
830 bool link_address_relevant(LinkAddress
*a
, bool local_multicast
) {
833 if (a
->flags
& (IFA_F_DEPRECATED
|IFA_F_TENTATIVE
))
836 if (a
->scope
>= (local_multicast
? RT_SCOPE_HOST
: RT_SCOPE_LINK
))