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
);
106 strv_free(s
->domains
);
112 DnsServer
*dns_scope_get_dns_server(DnsScope
*s
) {
115 if (s
->protocol
!= DNS_PROTOCOL_DNS
)
119 return link_get_dns_server(s
->link
);
121 return manager_get_dns_server(s
->manager
);
124 void dns_scope_next_dns_server(DnsScope
*s
) {
127 if (s
->protocol
!= DNS_PROTOCOL_DNS
)
131 link_next_dns_server(s
->link
);
133 manager_next_dns_server(s
->manager
);
136 void dns_scope_packet_received(DnsScope
*s
, usec_t rtt
) {
139 if (rtt
> s
->max_rtt
) {
141 s
->resend_timeout
= MIN(MAX(MULTICAST_RESEND_TIMEOUT_MIN_USEC
, s
->max_rtt
* 2),
142 MULTICAST_RESEND_TIMEOUT_MAX_USEC
);
146 void dns_scope_packet_lost(DnsScope
*s
, usec_t usec
) {
149 if (s
->resend_timeout
<= usec
)
150 s
->resend_timeout
= MIN(s
->resend_timeout
* 2, MULTICAST_RESEND_TIMEOUT_MAX_USEC
);
153 int dns_scope_emit(DnsScope
*s
, int fd
, DnsPacket
*p
) {
154 union in_addr_union addr
;
162 assert(p
->protocol
== s
->protocol
);
163 assert((s
->protocol
== DNS_PROTOCOL_DNS
) != (fd
< 0));
167 ifindex
= s
->link
->ifindex
;
169 mtu
= manager_find_mtu(s
->manager
);
171 switch (s
->protocol
) {
172 case DNS_PROTOCOL_DNS
:
173 if (DNS_PACKET_QDCOUNT(p
) > 1)
176 if (p
->size
> DNS_PACKET_UNICAST_SIZE_MAX
)
179 if (p
->size
+ UDP_PACKET_HEADER_SIZE
> mtu
)
182 r
= manager_write(s
->manager
, fd
, p
);
188 case DNS_PROTOCOL_LLMNR
:
189 if (DNS_PACKET_QDCOUNT(p
) > 1)
192 if (!ratelimit_test(&s
->ratelimit
))
198 if (family
== AF_INET
) {
199 addr
.in
= LLMNR_MULTICAST_IPV4_ADDRESS
;
200 fd
= manager_llmnr_ipv4_udp_fd(s
->manager
);
201 } else if (family
== AF_INET6
) {
202 addr
.in6
= LLMNR_MULTICAST_IPV6_ADDRESS
;
203 fd
= manager_llmnr_ipv6_udp_fd(s
->manager
);
205 return -EAFNOSUPPORT
;
209 r
= manager_send(s
->manager
, fd
, ifindex
, family
, &addr
, port
, p
);
216 return -EAFNOSUPPORT
;
222 static int dns_scope_socket(DnsScope
*s
, int type
, int family
, const union in_addr_union
*address
, uint16_t port
, DnsServer
**server
) {
223 DnsServer
*srv
= NULL
;
224 _cleanup_close_
int fd
= -1;
225 union sockaddr_union sa
= {};
227 static const int one
= 1;
231 assert((family
== AF_UNSPEC
) == !address
);
233 if (family
== AF_UNSPEC
) {
234 srv
= dns_scope_get_dns_server(s
);
238 sa
.sa
.sa_family
= srv
->family
;
239 if (srv
->family
== AF_INET
) {
240 sa
.in
.sin_port
= htobe16(port
);
241 sa
.in
.sin_addr
= srv
->address
.in
;
242 salen
= sizeof(sa
.in
);
243 } else if (srv
->family
== AF_INET6
) {
244 sa
.in6
.sin6_port
= htobe16(port
);
245 sa
.in6
.sin6_addr
= srv
->address
.in6
;
246 sa
.in6
.sin6_scope_id
= s
->link
? s
->link
->ifindex
: 0;
247 salen
= sizeof(sa
.in6
);
249 return -EAFNOSUPPORT
;
251 sa
.sa
.sa_family
= family
;
253 if (family
== AF_INET
) {
254 sa
.in
.sin_port
= htobe16(port
);
255 sa
.in
.sin_addr
= address
->in
;
256 salen
= sizeof(sa
.in
);
257 } else if (family
== AF_INET6
) {
258 sa
.in6
.sin6_port
= htobe16(port
);
259 sa
.in6
.sin6_addr
= address
->in6
;
260 sa
.in6
.sin6_scope_id
= s
->link
? s
->link
->ifindex
: 0;
261 salen
= sizeof(sa
.in6
);
263 return -EAFNOSUPPORT
;
266 fd
= socket(sa
.sa
.sa_family
, type
|SOCK_CLOEXEC
|SOCK_NONBLOCK
, 0);
270 if (type
== SOCK_STREAM
) {
271 r
= setsockopt(fd
, IPPROTO_TCP
, TCP_NODELAY
, &one
, sizeof(one
));
277 uint32_t ifindex
= htobe32(s
->link
->ifindex
);
279 if (sa
.sa
.sa_family
== AF_INET
) {
280 r
= setsockopt(fd
, IPPROTO_IP
, IP_UNICAST_IF
, &ifindex
, sizeof(ifindex
));
283 } else if (sa
.sa
.sa_family
== AF_INET6
) {
284 r
= setsockopt(fd
, IPPROTO_IPV6
, IPV6_UNICAST_IF
, &ifindex
, sizeof(ifindex
));
290 if (s
->protocol
== DNS_PROTOCOL_LLMNR
) {
291 /* RFC 4795, section 2.5 requires the TTL to be set to 1 */
293 if (sa
.sa
.sa_family
== AF_INET
) {
294 r
= setsockopt(fd
, IPPROTO_IP
, IP_TTL
, &one
, sizeof(one
));
297 } else if (sa
.sa
.sa_family
== AF_INET6
) {
298 r
= setsockopt(fd
, IPPROTO_IPV6
, IPV6_UNICAST_HOPS
, &one
, sizeof(one
));
304 r
= connect(fd
, &sa
.sa
, salen
);
305 if (r
< 0 && errno
!= EINPROGRESS
)
317 int dns_scope_udp_dns_socket(DnsScope
*s
, DnsServer
**server
) {
318 return dns_scope_socket(s
, SOCK_DGRAM
, AF_UNSPEC
, NULL
, 53, server
);
321 int dns_scope_tcp_socket(DnsScope
*s
, int family
, const union in_addr_union
*address
, uint16_t port
, DnsServer
**server
) {
322 return dns_scope_socket(s
, SOCK_STREAM
, family
, address
, port
, server
);
325 DnsScopeMatch
dns_scope_good_domain(DnsScope
*s
, int ifindex
, uint64_t flags
, const char *domain
) {
331 if (ifindex
!= 0 && (!s
->link
|| s
->link
->ifindex
!= ifindex
))
334 if ((SD_RESOLVED_FLAGS_MAKE(s
->protocol
, s
->family
) & flags
) == 0)
337 if (dns_name_root(domain
) != 0)
340 /* Never resolve any loopback hostname or IP address via DNS,
341 * LLMNR or mDNS. Instead, always rely on synthesized RRs for
343 if (is_localhost(domain
) ||
344 dns_name_endswith(domain
, "127.in-addr.arpa") > 0 ||
345 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)
348 STRV_FOREACH(i
, s
->domains
)
349 if (dns_name_endswith(domain
, *i
) > 0)
350 return DNS_SCOPE_YES
;
352 switch (s
->protocol
) {
353 case DNS_PROTOCOL_DNS
:
354 if (dns_name_endswith(domain
, "254.169.in-addr.arpa") == 0 &&
355 dns_name_endswith(domain
, "0.8.e.f.ip6.arpa") == 0 &&
356 dns_name_single_label(domain
) == 0)
357 return DNS_SCOPE_MAYBE
;
361 case DNS_PROTOCOL_MDNS
:
362 if ((s
->family
== AF_INET
&& dns_name_endswith(domain
, "in-addr.arpa") > 0) ||
363 (s
->family
== AF_INET6
&& dns_name_endswith(domain
, "ip6.arpa") > 0) ||
364 (dns_name_endswith(domain
, "local") > 0 && /* only resolve names ending in .local via mDNS */
365 dns_name_equal(domain
, "local") == 0 && /* but not the single-label "local" name itself */
366 manager_is_own_hostname(s
->manager
, domain
) <= 0)) /* never resolve the local hostname via mDNS */
367 return DNS_SCOPE_MAYBE
;
371 case DNS_PROTOCOL_LLMNR
:
372 if ((s
->family
== AF_INET
&& dns_name_endswith(domain
, "in-addr.arpa") > 0) ||
373 (s
->family
== AF_INET6
&& dns_name_endswith(domain
, "ip6.arpa") > 0) ||
374 (dns_name_single_label(domain
) > 0 && /* only resolve single label names via LLMNR */
375 !is_gateway_hostname(domain
) && /* don't resolve "gateway" with LLMNR, let nss-myhostname handle this */
376 manager_is_own_hostname(s
->manager
, domain
) <= 0)) /* never resolve the local hostname via LLMNR */
377 return DNS_SCOPE_MAYBE
;
382 assert_not_reached("Unknown scope protocol");
386 int dns_scope_good_key(DnsScope
*s
, DnsResourceKey
*key
) {
390 if (s
->protocol
== DNS_PROTOCOL_DNS
)
393 /* On mDNS and LLMNR, send A and AAAA queries only on the
394 * respective scopes */
396 if (s
->family
== AF_INET
&& key
->class == DNS_CLASS_IN
&& key
->type
== DNS_TYPE_AAAA
)
399 if (s
->family
== AF_INET6
&& key
->class == DNS_CLASS_IN
&& key
->type
== DNS_TYPE_A
)
405 int dns_scope_llmnr_membership(DnsScope
*s
, bool b
) {
410 if (s
->protocol
!= DNS_PROTOCOL_LLMNR
)
415 if (s
->family
== AF_INET
) {
416 struct ip_mreqn mreqn
= {
417 .imr_multiaddr
= LLMNR_MULTICAST_IPV4_ADDRESS
,
418 .imr_ifindex
= s
->link
->ifindex
,
421 fd
= manager_llmnr_ipv4_udp_fd(s
->manager
);
425 /* Always first try to drop membership before we add
426 * one. This is necessary on some devices, such as
429 (void) setsockopt(fd
, IPPROTO_IP
, IP_DROP_MEMBERSHIP
, &mreqn
, sizeof(mreqn
));
431 if (setsockopt(fd
, IPPROTO_IP
, b
? IP_ADD_MEMBERSHIP
: IP_DROP_MEMBERSHIP
, &mreqn
, sizeof(mreqn
)) < 0)
434 } else if (s
->family
== AF_INET6
) {
435 struct ipv6_mreq mreq
= {
436 .ipv6mr_multiaddr
= LLMNR_MULTICAST_IPV6_ADDRESS
,
437 .ipv6mr_interface
= s
->link
->ifindex
,
440 fd
= manager_llmnr_ipv6_udp_fd(s
->manager
);
445 (void) setsockopt(fd
, IPPROTO_IPV6
, IPV6_DROP_MEMBERSHIP
, &mreq
, sizeof(mreq
));
447 if (setsockopt(fd
, IPPROTO_IPV6
, b
? IPV6_ADD_MEMBERSHIP
: IPV6_DROP_MEMBERSHIP
, &mreq
, sizeof(mreq
)) < 0)
450 return -EAFNOSUPPORT
;
455 static int dns_scope_make_reply_packet(
465 _cleanup_(dns_packet_unrefp
) DnsPacket
*p
= NULL
;
472 if ((!q
|| q
->n_keys
<= 0)
473 && (!answer
|| answer
->n_rrs
<= 0)
474 && (!soa
|| soa
->n_rrs
<= 0))
477 r
= dns_packet_new(&p
, s
->protocol
, 0);
481 DNS_PACKET_HEADER(p
)->id
= id
;
482 DNS_PACKET_HEADER(p
)->flags
= htobe16(DNS_PACKET_MAKE_FLAGS(
494 for (i
= 0; i
< q
->n_keys
; i
++) {
495 r
= dns_packet_append_key(p
, q
->keys
[i
], NULL
);
500 DNS_PACKET_HEADER(p
)->qdcount
= htobe16(q
->n_keys
);
504 for (i
= 0; i
< answer
->n_rrs
; i
++) {
505 r
= dns_packet_append_rr(p
, answer
->items
[i
].rr
, NULL
);
510 DNS_PACKET_HEADER(p
)->ancount
= htobe16(answer
->n_rrs
);
514 for (i
= 0; i
< soa
->n_rrs
; i
++) {
515 r
= dns_packet_append_rr(p
, soa
->items
[i
].rr
, NULL
);
520 DNS_PACKET_HEADER(p
)->arcount
= htobe16(soa
->n_rrs
);
529 static void dns_scope_verify_conflicts(DnsScope
*s
, DnsPacket
*p
) {
536 for (n
= 0; n
< p
->question
->n_keys
; n
++)
537 dns_zone_verify_conflicts(&s
->zone
, p
->question
->keys
[n
]);
539 for (n
= 0; n
< p
->answer
->n_rrs
; n
++)
540 dns_zone_verify_conflicts(&s
->zone
, p
->answer
->items
[n
].rr
->key
);
543 void dns_scope_process_query(DnsScope
*s
, DnsStream
*stream
, DnsPacket
*p
) {
544 _cleanup_(dns_packet_unrefp
) DnsPacket
*reply
= NULL
;
545 _cleanup_(dns_answer_unrefp
) DnsAnswer
*answer
= NULL
, *soa
= 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 r
= dns_zone_lookup(&s
->zone
, p
->question
, &answer
, &soa
, &tentative
);
581 log_debug_errno(r
, "Failed to lookup key: %m");
588 dns_answer_order_by_scope(answer
, in_addr_is_link_local(p
->family
, &p
->sender
) > 0);
590 r
= dns_scope_make_reply_packet(s
, DNS_PACKET_ID(p
), DNS_RCODE_SUCCESS
, p
->question
, answer
, soa
, tentative
, &reply
);
592 log_debug_errno(r
, "Failed to build reply packet: %m");
597 r
= dns_stream_write_packet(stream
, reply
);
599 if (!ratelimit_test(&s
->ratelimit
))
602 if (p
->family
== AF_INET
)
603 fd
= manager_llmnr_ipv4_udp_fd(s
->manager
);
604 else if (p
->family
== AF_INET6
)
605 fd
= manager_llmnr_ipv6_udp_fd(s
->manager
);
607 log_debug("Unknown protocol");
611 log_debug_errno(fd
, "Failed to get reply socket: %m");
615 /* Note that we always immediately reply to all LLMNR
616 * requests, and do not wait any time, since we
617 * verified uniqueness for all records. Also see RFC
618 * 4795, Section 2.7 */
620 r
= manager_send(s
->manager
, fd
, p
->ifindex
, p
->family
, &p
->sender
, p
->sender_port
, reply
);
624 log_debug_errno(r
, "Failed to send reply packet: %m");
629 DnsTransaction
*dns_scope_find_transaction(DnsScope
*scope
, DnsResourceKey
*key
, bool cache_ok
) {
635 /* Try to find an ongoing transaction that is a equal to the
636 * specified question */
637 t
= hashmap_get(scope
->transactions
, key
);
641 /* Refuse reusing transactions that completed based on cached
642 * data instead of a real packet, if that's requested. */
644 IN_SET(t
->state
, DNS_TRANSACTION_SUCCESS
, DNS_TRANSACTION_FAILURE
) &&
651 static int dns_scope_make_conflict_packet(
653 DnsResourceRecord
*rr
,
656 _cleanup_(dns_packet_unrefp
) DnsPacket
*p
= NULL
;
663 r
= dns_packet_new(&p
, s
->protocol
, 0);
667 DNS_PACKET_HEADER(p
)->flags
= htobe16(DNS_PACKET_MAKE_FLAGS(
677 random_bytes(&DNS_PACKET_HEADER(p
)->id
, sizeof(uint16_t));
678 DNS_PACKET_HEADER(p
)->qdcount
= htobe16(1);
679 DNS_PACKET_HEADER(p
)->arcount
= htobe16(1);
681 r
= dns_packet_append_key(p
, rr
->key
, NULL
);
685 r
= dns_packet_append_rr(p
, rr
, NULL
);
695 static int on_conflict_dispatch(sd_event_source
*es
, usec_t usec
, void *userdata
) {
696 DnsScope
*scope
= userdata
;
702 scope
->conflict_event_source
= sd_event_source_unref(scope
->conflict_event_source
);
705 _cleanup_(dns_resource_record_unrefp
) DnsResourceRecord
*rr
= NULL
;
706 _cleanup_(dns_packet_unrefp
) DnsPacket
*p
= NULL
;
708 rr
= ordered_hashmap_steal_first(scope
->conflict_queue
);
712 r
= dns_scope_make_conflict_packet(scope
, rr
, &p
);
714 log_error_errno(r
, "Failed to make conflict packet: %m");
718 r
= dns_scope_emit(scope
, -1, p
);
720 log_debug_errno(r
, "Failed to send conflict packet: %m");
726 int dns_scope_notify_conflict(DnsScope
*scope
, DnsResourceRecord
*rr
) {
733 /* We don't send these queries immediately. Instead, we queue
734 * them, and send them after some jitter delay. */
735 r
= ordered_hashmap_ensure_allocated(&scope
->conflict_queue
, &dns_resource_key_hash_ops
);
741 /* We only place one RR per key in the conflict
742 * messages, not all of them. That should be enough to
743 * indicate where there might be a conflict */
744 r
= ordered_hashmap_put(scope
->conflict_queue
, rr
->key
, rr
);
745 if (r
== -EEXIST
|| r
== 0)
748 return log_debug_errno(r
, "Failed to queue conflicting RR: %m");
750 dns_resource_record_ref(rr
);
752 if (scope
->conflict_event_source
)
755 random_bytes(&jitter
, sizeof(jitter
));
756 jitter
%= LLMNR_JITTER_INTERVAL_USEC
;
758 r
= sd_event_add_time(scope
->manager
->event
,
759 &scope
->conflict_event_source
,
760 clock_boottime_or_monotonic(),
761 now(clock_boottime_or_monotonic()) + jitter
,
762 LLMNR_JITTER_INTERVAL_USEC
,
763 on_conflict_dispatch
, scope
);
765 return log_debug_errno(r
, "Failed to add conflict dispatch event: %m");
770 void dns_scope_check_conflicts(DnsScope
*scope
, DnsPacket
*p
) {
777 if (p
->protocol
!= DNS_PROTOCOL_LLMNR
)
780 if (DNS_PACKET_RRCOUNT(p
) <= 0)
783 if (DNS_PACKET_LLMNR_C(p
) != 0)
786 if (DNS_PACKET_LLMNR_T(p
) != 0)
789 if (manager_our_packet(scope
->manager
, p
))
792 r
= dns_packet_extract(p
);
794 log_debug_errno(r
, "Failed to extract packet: %m");
798 log_debug("Checking for conflicts...");
800 for (i
= 0; i
< p
->answer
->n_rrs
; i
++) {
802 /* Check for conflicts against the local zone. If we
803 * found one, we won't check any further */
804 r
= dns_zone_check_conflicts(&scope
->zone
, p
->answer
->items
[i
].rr
);
808 /* Check for conflicts against the local cache. If so,
809 * send out an advisory query, to inform everybody */
810 r
= dns_cache_check_conflicts(&scope
->cache
, p
->answer
->items
[i
].rr
, p
->family
, &p
->sender
);
814 dns_scope_notify_conflict(scope
, p
->answer
->items
[i
].rr
);
818 void dns_scope_dump(DnsScope
*s
, FILE *f
) {
824 fputs("[Scope protocol=", f
);
825 fputs(dns_protocol_to_string(s
->protocol
), f
);
828 fputs(" interface=", f
);
829 fputs(s
->link
->name
, f
);
832 if (s
->family
!= AF_UNSPEC
) {
833 fputs(" family=", f
);
834 fputs(af_to_name(s
->family
), f
);
839 if (!dns_zone_is_empty(&s
->zone
)) {
841 dns_zone_dump(&s
->zone
, f
);
844 if (!dns_cache_is_empty(&s
->cache
)) {
845 fputs("CACHE:\n", f
);
846 dns_cache_dump(&s
->cache
, f
);