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/>.
22 #include <netinet/tcp.h>
25 #include "alloc-util.h"
26 #include "dns-domain.h"
28 #include "hostname-util.h"
30 #include "random-util.h"
31 #include "resolved-dns-scope.h"
32 #include "resolved-llmnr.h"
33 #include "socket-util.h"
36 #define MULTICAST_RATELIMIT_INTERVAL_USEC (1*USEC_PER_SEC)
37 #define MULTICAST_RATELIMIT_BURST 1000
39 /* After how much time to repeat LLMNR requests, see RFC 4795 Section 7 */
40 #define MULTICAST_RESEND_TIMEOUT_MIN_USEC (100 * USEC_PER_MSEC)
41 #define MULTICAST_RESEND_TIMEOUT_MAX_USEC (1 * USEC_PER_SEC)
43 int dns_scope_new(Manager
*m
, DnsScope
**ret
, Link
*l
, DnsProtocol protocol
, int family
) {
49 s
= new0(DnsScope
, 1);
55 s
->protocol
= protocol
;
57 s
->resend_timeout
= MULTICAST_RESEND_TIMEOUT_MIN_USEC
;
59 LIST_PREPEND(scopes
, m
->dns_scopes
, s
);
61 dns_scope_llmnr_membership(s
, true);
63 log_debug("New scope on link %s, protocol %s, family %s", l
? l
->name
: "*", dns_protocol_to_string(protocol
), family
== AF_UNSPEC
? "*" : af_to_name(family
));
65 /* Enforce ratelimiting for the multicast protocols */
66 RATELIMIT_INIT(s
->ratelimit
, MULTICAST_RATELIMIT_INTERVAL_USEC
, MULTICAST_RATELIMIT_BURST
);
72 DnsScope
* dns_scope_free(DnsScope
*s
) {
74 DnsResourceRecord
*rr
;
79 log_debug("Removing scope on link %s, protocol %s, family %s", s
->link
? s
->link
->name
: "*", dns_protocol_to_string(s
->protocol
), s
->family
== AF_UNSPEC
? "*" : af_to_name(s
->family
));
81 dns_scope_llmnr_membership(s
, false);
83 while ((t
= hashmap_steal_first(s
->transactions
))) {
84 /* Abort the transaction, but make sure it is not
85 * freed while we still look at it */
88 dns_transaction_complete(t
, DNS_TRANSACTION_ABORTED
);
91 dns_transaction_free(t
);
94 hashmap_free(s
->transactions
);
96 while ((rr
= ordered_hashmap_steal_first(s
->conflict_queue
)))
97 dns_resource_record_unref(rr
);
99 ordered_hashmap_free(s
->conflict_queue
);
100 sd_event_source_unref(s
->conflict_event_source
);
102 dns_cache_flush(&s
->cache
);
103 dns_zone_flush(&s
->zone
);
105 LIST_REMOVE(scopes
, s
->manager
->dns_scopes
, s
);
111 DnsServer
*dns_scope_get_dns_server(DnsScope
*s
) {
114 if (s
->protocol
!= DNS_PROTOCOL_DNS
)
118 return link_get_dns_server(s
->link
);
120 return manager_get_dns_server(s
->manager
);
123 void dns_scope_next_dns_server(DnsScope
*s
) {
126 if (s
->protocol
!= DNS_PROTOCOL_DNS
)
130 link_next_dns_server(s
->link
);
132 manager_next_dns_server(s
->manager
);
135 void dns_scope_packet_received(DnsScope
*s
, usec_t rtt
) {
138 if (rtt
<= s
->max_rtt
)
142 s
->resend_timeout
= MIN(MAX(MULTICAST_RESEND_TIMEOUT_MIN_USEC
, s
->max_rtt
* 2), MULTICAST_RESEND_TIMEOUT_MAX_USEC
);
145 void dns_scope_packet_lost(DnsScope
*s
, usec_t usec
) {
148 if (s
->resend_timeout
<= usec
)
149 s
->resend_timeout
= MIN(s
->resend_timeout
* 2, MULTICAST_RESEND_TIMEOUT_MAX_USEC
);
152 int dns_scope_emit(DnsScope
*s
, int fd
, DnsPacket
*p
) {
153 union in_addr_union addr
;
161 assert(p
->protocol
== s
->protocol
);
162 assert((s
->protocol
== DNS_PROTOCOL_DNS
) != (fd
< 0));
166 ifindex
= s
->link
->ifindex
;
168 mtu
= manager_find_mtu(s
->manager
);
170 switch (s
->protocol
) {
171 case DNS_PROTOCOL_DNS
:
172 if (DNS_PACKET_QDCOUNT(p
) > 1)
175 if (p
->size
> DNS_PACKET_UNICAST_SIZE_MAX
)
178 if (p
->size
+ UDP_PACKET_HEADER_SIZE
> mtu
)
181 r
= manager_write(s
->manager
, fd
, p
);
187 case DNS_PROTOCOL_LLMNR
:
188 if (DNS_PACKET_QDCOUNT(p
) > 1)
191 if (!ratelimit_test(&s
->ratelimit
))
197 if (family
== AF_INET
) {
198 addr
.in
= LLMNR_MULTICAST_IPV4_ADDRESS
;
199 fd
= manager_llmnr_ipv4_udp_fd(s
->manager
);
200 } else if (family
== AF_INET6
) {
201 addr
.in6
= LLMNR_MULTICAST_IPV6_ADDRESS
;
202 fd
= manager_llmnr_ipv6_udp_fd(s
->manager
);
204 return -EAFNOSUPPORT
;
208 r
= manager_send(s
->manager
, fd
, ifindex
, family
, &addr
, port
, p
);
215 return -EAFNOSUPPORT
;
221 static int dns_scope_socket(DnsScope
*s
, int type
, int family
, const union in_addr_union
*address
, uint16_t port
, DnsServer
**server
) {
222 DnsServer
*srv
= NULL
;
223 _cleanup_close_
int fd
= -1;
224 union sockaddr_union sa
= {};
226 static const int one
= 1;
230 assert((family
== AF_UNSPEC
) == !address
);
232 if (family
== AF_UNSPEC
) {
233 srv
= dns_scope_get_dns_server(s
);
237 sa
.sa
.sa_family
= srv
->family
;
238 if (srv
->family
== AF_INET
) {
239 sa
.in
.sin_port
= htobe16(port
);
240 sa
.in
.sin_addr
= srv
->address
.in
;
241 salen
= sizeof(sa
.in
);
242 } else if (srv
->family
== AF_INET6
) {
243 sa
.in6
.sin6_port
= htobe16(port
);
244 sa
.in6
.sin6_addr
= srv
->address
.in6
;
245 sa
.in6
.sin6_scope_id
= s
->link
? s
->link
->ifindex
: 0;
246 salen
= sizeof(sa
.in6
);
248 return -EAFNOSUPPORT
;
250 sa
.sa
.sa_family
= family
;
252 if (family
== AF_INET
) {
253 sa
.in
.sin_port
= htobe16(port
);
254 sa
.in
.sin_addr
= address
->in
;
255 salen
= sizeof(sa
.in
);
256 } else if (family
== AF_INET6
) {
257 sa
.in6
.sin6_port
= htobe16(port
);
258 sa
.in6
.sin6_addr
= address
->in6
;
259 sa
.in6
.sin6_scope_id
= s
->link
? s
->link
->ifindex
: 0;
260 salen
= sizeof(sa
.in6
);
262 return -EAFNOSUPPORT
;
265 fd
= socket(sa
.sa
.sa_family
, type
|SOCK_CLOEXEC
|SOCK_NONBLOCK
, 0);
269 if (type
== SOCK_STREAM
) {
270 r
= setsockopt(fd
, IPPROTO_TCP
, TCP_NODELAY
, &one
, sizeof(one
));
276 uint32_t ifindex
= htobe32(s
->link
->ifindex
);
278 if (sa
.sa
.sa_family
== AF_INET
) {
279 r
= setsockopt(fd
, IPPROTO_IP
, IP_UNICAST_IF
, &ifindex
, sizeof(ifindex
));
282 } else if (sa
.sa
.sa_family
== AF_INET6
) {
283 r
= setsockopt(fd
, IPPROTO_IPV6
, IPV6_UNICAST_IF
, &ifindex
, sizeof(ifindex
));
289 if (s
->protocol
== DNS_PROTOCOL_LLMNR
) {
290 /* RFC 4795, section 2.5 requires the TTL to be set to 1 */
292 if (sa
.sa
.sa_family
== AF_INET
) {
293 r
= setsockopt(fd
, IPPROTO_IP
, IP_TTL
, &one
, sizeof(one
));
296 } else if (sa
.sa
.sa_family
== AF_INET6
) {
297 r
= setsockopt(fd
, IPPROTO_IPV6
, IPV6_UNICAST_HOPS
, &one
, sizeof(one
));
303 r
= connect(fd
, &sa
.sa
, salen
);
304 if (r
< 0 && errno
!= EINPROGRESS
)
316 int dns_scope_udp_dns_socket(DnsScope
*s
, DnsServer
**server
) {
317 return dns_scope_socket(s
, SOCK_DGRAM
, AF_UNSPEC
, NULL
, 53, server
);
320 int dns_scope_tcp_socket(DnsScope
*s
, int family
, const union in_addr_union
*address
, uint16_t port
, DnsServer
**server
) {
321 return dns_scope_socket(s
, SOCK_STREAM
, family
, address
, port
, server
);
324 DnsScopeMatch
dns_scope_good_domain(DnsScope
*s
, int ifindex
, uint64_t flags
, const char *domain
) {
330 if (ifindex
!= 0 && (!s
->link
|| s
->link
->ifindex
!= ifindex
))
333 if ((SD_RESOLVED_FLAGS_MAKE(s
->protocol
, s
->family
) & flags
) == 0)
336 if (dns_name_root(domain
) != 0)
339 /* Never resolve any loopback hostname or IP address via DNS,
340 * LLMNR or mDNS. Instead, always rely on synthesized RRs for
342 if (is_localhost(domain
) ||
343 dns_name_endswith(domain
, "127.in-addr.arpa") > 0 ||
344 dns_name_equal(domain
, "1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa") > 0)
347 LIST_FOREACH(domains
, d
, dns_scope_get_search_domains(s
))
348 if (dns_name_endswith(domain
, d
->name
) > 0)
349 return DNS_SCOPE_YES
;
351 switch (s
->protocol
) {
352 case DNS_PROTOCOL_DNS
:
353 if (dns_name_endswith(domain
, "254.169.in-addr.arpa") == 0 &&
354 dns_name_endswith(domain
, "0.8.e.f.ip6.arpa") == 0 &&
355 dns_name_single_label(domain
) == 0)
356 return DNS_SCOPE_MAYBE
;
360 case DNS_PROTOCOL_MDNS
:
361 if ((s
->family
== AF_INET
&& dns_name_endswith(domain
, "in-addr.arpa") > 0) ||
362 (s
->family
== AF_INET6
&& dns_name_endswith(domain
, "ip6.arpa") > 0) ||
363 (dns_name_endswith(domain
, "local") > 0 && /* only resolve names ending in .local via mDNS */
364 dns_name_equal(domain
, "local") == 0 && /* but not the single-label "local" name itself */
365 manager_is_own_hostname(s
->manager
, domain
) <= 0)) /* never resolve the local hostname via mDNS */
366 return DNS_SCOPE_MAYBE
;
370 case DNS_PROTOCOL_LLMNR
:
371 if ((s
->family
== AF_INET
&& dns_name_endswith(domain
, "in-addr.arpa") > 0) ||
372 (s
->family
== AF_INET6
&& dns_name_endswith(domain
, "ip6.arpa") > 0) ||
373 (dns_name_single_label(domain
) > 0 && /* only resolve single label names via LLMNR */
374 !is_gateway_hostname(domain
) && /* don't resolve "gateway" with LLMNR, let nss-myhostname handle this */
375 manager_is_own_hostname(s
->manager
, domain
) <= 0)) /* never resolve the local hostname via LLMNR */
376 return DNS_SCOPE_MAYBE
;
381 assert_not_reached("Unknown scope protocol");
385 int dns_scope_good_key(DnsScope
*s
, DnsResourceKey
*key
) {
389 if (s
->protocol
== DNS_PROTOCOL_DNS
)
392 /* On mDNS and LLMNR, send A and AAAA queries only on the
393 * respective scopes */
395 if (s
->family
== AF_INET
&& key
->class == DNS_CLASS_IN
&& key
->type
== DNS_TYPE_AAAA
)
398 if (s
->family
== AF_INET6
&& key
->class == DNS_CLASS_IN
&& key
->type
== DNS_TYPE_A
)
404 int dns_scope_llmnr_membership(DnsScope
*s
, bool b
) {
409 if (s
->protocol
!= DNS_PROTOCOL_LLMNR
)
414 if (s
->family
== AF_INET
) {
415 struct ip_mreqn mreqn
= {
416 .imr_multiaddr
= LLMNR_MULTICAST_IPV4_ADDRESS
,
417 .imr_ifindex
= s
->link
->ifindex
,
420 fd
= manager_llmnr_ipv4_udp_fd(s
->manager
);
424 /* Always first try to drop membership before we add
425 * one. This is necessary on some devices, such as
428 (void) setsockopt(fd
, IPPROTO_IP
, IP_DROP_MEMBERSHIP
, &mreqn
, sizeof(mreqn
));
430 if (setsockopt(fd
, IPPROTO_IP
, b
? IP_ADD_MEMBERSHIP
: IP_DROP_MEMBERSHIP
, &mreqn
, sizeof(mreqn
)) < 0)
433 } else if (s
->family
== AF_INET6
) {
434 struct ipv6_mreq mreq
= {
435 .ipv6mr_multiaddr
= LLMNR_MULTICAST_IPV6_ADDRESS
,
436 .ipv6mr_interface
= s
->link
->ifindex
,
439 fd
= manager_llmnr_ipv6_udp_fd(s
->manager
);
444 (void) setsockopt(fd
, IPPROTO_IPV6
, IPV6_DROP_MEMBERSHIP
, &mreq
, sizeof(mreq
));
446 if (setsockopt(fd
, IPPROTO_IPV6
, b
? IPV6_ADD_MEMBERSHIP
: IPV6_DROP_MEMBERSHIP
, &mreq
, sizeof(mreq
)) < 0)
449 return -EAFNOSUPPORT
;
454 static int dns_scope_make_reply_packet(
464 _cleanup_(dns_packet_unrefp
) DnsPacket
*p
= NULL
;
471 if ((!q
|| q
->n_keys
<= 0)
472 && (!answer
|| answer
->n_rrs
<= 0)
473 && (!soa
|| soa
->n_rrs
<= 0))
476 r
= dns_packet_new(&p
, s
->protocol
, 0);
480 DNS_PACKET_HEADER(p
)->id
= id
;
481 DNS_PACKET_HEADER(p
)->flags
= htobe16(DNS_PACKET_MAKE_FLAGS(
493 for (i
= 0; i
< q
->n_keys
; i
++) {
494 r
= dns_packet_append_key(p
, q
->keys
[i
], NULL
);
499 DNS_PACKET_HEADER(p
)->qdcount
= htobe16(q
->n_keys
);
503 for (i
= 0; i
< answer
->n_rrs
; i
++) {
504 r
= dns_packet_append_rr(p
, answer
->items
[i
].rr
, NULL
);
509 DNS_PACKET_HEADER(p
)->ancount
= htobe16(answer
->n_rrs
);
513 for (i
= 0; i
< soa
->n_rrs
; i
++) {
514 r
= dns_packet_append_rr(p
, soa
->items
[i
].rr
, NULL
);
519 DNS_PACKET_HEADER(p
)->arcount
= htobe16(soa
->n_rrs
);
528 static void dns_scope_verify_conflicts(DnsScope
*s
, DnsPacket
*p
) {
535 for (n
= 0; n
< p
->question
->n_keys
; n
++)
536 dns_zone_verify_conflicts(&s
->zone
, p
->question
->keys
[n
]);
538 for (n
= 0; n
< p
->answer
->n_rrs
; n
++)
539 dns_zone_verify_conflicts(&s
->zone
, p
->answer
->items
[n
].rr
->key
);
542 void dns_scope_process_query(DnsScope
*s
, DnsStream
*stream
, DnsPacket
*p
) {
543 _cleanup_(dns_packet_unrefp
) DnsPacket
*reply
= NULL
;
544 _cleanup_(dns_answer_unrefp
) DnsAnswer
*answer
= NULL
, *soa
= NULL
;
545 DnsResourceKey
*key
= NULL
;
546 bool tentative
= false;
552 if (p
->protocol
!= DNS_PROTOCOL_LLMNR
)
555 if (p
->ipproto
== IPPROTO_UDP
) {
556 /* Don't accept UDP queries directed to anything but
557 * the LLMNR multicast addresses. See RFC 4795,
560 if (p
->family
== AF_INET
&& !in_addr_equal(AF_INET
, &p
->destination
, (union in_addr_union
*) &LLMNR_MULTICAST_IPV4_ADDRESS
))
563 if (p
->family
== AF_INET6
&& !in_addr_equal(AF_INET6
, &p
->destination
, (union in_addr_union
*) &LLMNR_MULTICAST_IPV6_ADDRESS
))
567 r
= dns_packet_extract(p
);
569 log_debug_errno(r
, "Failed to extract resources from incoming packet: %m");
573 if (DNS_PACKET_LLMNR_C(p
)) {
574 /* Somebody notified us about a possible conflict */
575 dns_scope_verify_conflicts(s
, p
);
579 assert(p
->question
->n_keys
== 1);
580 key
= p
->question
->keys
[0];
582 r
= dns_zone_lookup(&s
->zone
, key
, &answer
, &soa
, &tentative
);
584 log_debug_errno(r
, "Failed to lookup key: %m");
591 dns_answer_order_by_scope(answer
, in_addr_is_link_local(p
->family
, &p
->sender
) > 0);
593 r
= dns_scope_make_reply_packet(s
, DNS_PACKET_ID(p
), DNS_RCODE_SUCCESS
, p
->question
, answer
, soa
, tentative
, &reply
);
595 log_debug_errno(r
, "Failed to build reply packet: %m");
600 r
= dns_stream_write_packet(stream
, reply
);
602 if (!ratelimit_test(&s
->ratelimit
))
605 if (p
->family
== AF_INET
)
606 fd
= manager_llmnr_ipv4_udp_fd(s
->manager
);
607 else if (p
->family
== AF_INET6
)
608 fd
= manager_llmnr_ipv6_udp_fd(s
->manager
);
610 log_debug("Unknown protocol");
614 log_debug_errno(fd
, "Failed to get reply socket: %m");
618 /* Note that we always immediately reply to all LLMNR
619 * requests, and do not wait any time, since we
620 * verified uniqueness for all records. Also see RFC
621 * 4795, Section 2.7 */
623 r
= manager_send(s
->manager
, fd
, p
->ifindex
, p
->family
, &p
->sender
, p
->sender_port
, reply
);
627 log_debug_errno(r
, "Failed to send reply packet: %m");
632 DnsTransaction
*dns_scope_find_transaction(DnsScope
*scope
, DnsResourceKey
*key
, bool cache_ok
) {
638 /* Try to find an ongoing transaction that is a equal to the
639 * specified question */
640 t
= hashmap_get(scope
->transactions
, key
);
644 /* Refuse reusing transactions that completed based on cached
645 * data instead of a real packet, if that's requested. */
647 IN_SET(t
->state
, DNS_TRANSACTION_SUCCESS
, DNS_TRANSACTION_FAILURE
) &&
654 static int dns_scope_make_conflict_packet(
656 DnsResourceRecord
*rr
,
659 _cleanup_(dns_packet_unrefp
) DnsPacket
*p
= NULL
;
666 r
= dns_packet_new(&p
, s
->protocol
, 0);
670 DNS_PACKET_HEADER(p
)->flags
= htobe16(DNS_PACKET_MAKE_FLAGS(
680 random_bytes(&DNS_PACKET_HEADER(p
)->id
, sizeof(uint16_t));
681 DNS_PACKET_HEADER(p
)->qdcount
= htobe16(1);
682 DNS_PACKET_HEADER(p
)->arcount
= htobe16(1);
684 r
= dns_packet_append_key(p
, rr
->key
, NULL
);
688 r
= dns_packet_append_rr(p
, rr
, NULL
);
698 static int on_conflict_dispatch(sd_event_source
*es
, usec_t usec
, void *userdata
) {
699 DnsScope
*scope
= userdata
;
705 scope
->conflict_event_source
= sd_event_source_unref(scope
->conflict_event_source
);
708 _cleanup_(dns_resource_record_unrefp
) DnsResourceRecord
*rr
= NULL
;
709 _cleanup_(dns_packet_unrefp
) DnsPacket
*p
= NULL
;
711 rr
= ordered_hashmap_steal_first(scope
->conflict_queue
);
715 r
= dns_scope_make_conflict_packet(scope
, rr
, &p
);
717 log_error_errno(r
, "Failed to make conflict packet: %m");
721 r
= dns_scope_emit(scope
, -1, p
);
723 log_debug_errno(r
, "Failed to send conflict packet: %m");
729 int dns_scope_notify_conflict(DnsScope
*scope
, DnsResourceRecord
*rr
) {
736 /* We don't send these queries immediately. Instead, we queue
737 * them, and send them after some jitter delay. */
738 r
= ordered_hashmap_ensure_allocated(&scope
->conflict_queue
, &dns_resource_key_hash_ops
);
744 /* We only place one RR per key in the conflict
745 * messages, not all of them. That should be enough to
746 * indicate where there might be a conflict */
747 r
= ordered_hashmap_put(scope
->conflict_queue
, rr
->key
, rr
);
748 if (r
== -EEXIST
|| r
== 0)
751 return log_debug_errno(r
, "Failed to queue conflicting RR: %m");
753 dns_resource_record_ref(rr
);
755 if (scope
->conflict_event_source
)
758 random_bytes(&jitter
, sizeof(jitter
));
759 jitter
%= LLMNR_JITTER_INTERVAL_USEC
;
761 r
= sd_event_add_time(scope
->manager
->event
,
762 &scope
->conflict_event_source
,
763 clock_boottime_or_monotonic(),
764 now(clock_boottime_or_monotonic()) + jitter
,
765 LLMNR_JITTER_INTERVAL_USEC
,
766 on_conflict_dispatch
, scope
);
768 return log_debug_errno(r
, "Failed to add conflict dispatch event: %m");
773 void dns_scope_check_conflicts(DnsScope
*scope
, DnsPacket
*p
) {
780 if (p
->protocol
!= DNS_PROTOCOL_LLMNR
)
783 if (DNS_PACKET_RRCOUNT(p
) <= 0)
786 if (DNS_PACKET_LLMNR_C(p
) != 0)
789 if (DNS_PACKET_LLMNR_T(p
) != 0)
792 if (manager_our_packet(scope
->manager
, p
))
795 r
= dns_packet_extract(p
);
797 log_debug_errno(r
, "Failed to extract packet: %m");
801 log_debug("Checking for conflicts...");
803 for (i
= 0; i
< p
->answer
->n_rrs
; i
++) {
805 /* Check for conflicts against the local zone. If we
806 * found one, we won't check any further */
807 r
= dns_zone_check_conflicts(&scope
->zone
, p
->answer
->items
[i
].rr
);
811 /* Check for conflicts against the local cache. If so,
812 * send out an advisory query, to inform everybody */
813 r
= dns_cache_check_conflicts(&scope
->cache
, p
->answer
->items
[i
].rr
, p
->family
, &p
->sender
);
817 dns_scope_notify_conflict(scope
, p
->answer
->items
[i
].rr
);
821 void dns_scope_dump(DnsScope
*s
, FILE *f
) {
827 fputs("[Scope protocol=", f
);
828 fputs(dns_protocol_to_string(s
->protocol
), f
);
831 fputs(" interface=", f
);
832 fputs(s
->link
->name
, f
);
835 if (s
->family
!= AF_UNSPEC
) {
836 fputs(" family=", f
);
837 fputs(af_to_name(s
->family
), f
);
842 if (!dns_zone_is_empty(&s
->zone
)) {
844 dns_zone_dump(&s
->zone
, f
);
847 if (!dns_cache_is_empty(&s
->cache
)) {
848 fputs("CACHE:\n", f
);
849 dns_cache_dump(&s
->cache
, f
);
853 DnsSearchDomain
*dns_scope_get_search_domains(DnsScope
*s
) {
855 if (s
->protocol
!= DNS_PROTOCOL_DNS
)
859 return s
->link
->search_domains
;