Commit 3230429e authored by Evan Hunt's avatar Evan Hunt
Browse files

[master] limit recursion depth and iterative queries

4006.	[security]	A flaw in delegation handling could be exploited
			to put named into an infinite loop.  This has
			been addressed by placing limits on the number
			of levels of recursion named will allow (default 7),
			and the number of iterative queries that it will
			send (default 50) before terminating a recursive
			query (CVE-2014-8500).

			The recursion depth limit is configured via the
			"max-recursion-depth" option.  [RT #35780]
parent c325ff9c
4006. [security] A flaw in delegation handling could be exploited
to put named into an infinite loop. This has
been addressed by placing limits on the number
of levels of recursion named will allow (default 7),
and the number of iterative queries that it will
send (default 50) before terminating a recursive
query (CVE-2014-8500).
The recursion depth limit is configured via the
"max-recursion-depth" option. [RT #35780]
4005. [func] The buffer used for returning text from rndc
commands is now dynamically resizable, allowing
arbitrarily large amounts of text to be sent back
......
......@@ -15,8 +15,6 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: config.c,v 1.123 2012/01/06 23:46:41 tbox Exp $ */
/*! \file */
#include <config.h>
......@@ -176,6 +174,7 @@ options {\n\
dnssec-accept-expired no;\n\
clients-per-query 10;\n\
max-clients-per-query 100;\n\
max-recursion-depth 7;\n\
zero-no-soa-ttl-cache no;\n\
nsec3-test-zone no;\n\
allow-new-zones no;\n\
......
......@@ -15,8 +15,6 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: query.h,v 1.45 2011/01/13 04:59:24 tbox Exp $ */
#ifndef NAMED_QUERY_H
#define NAMED_QUERY_H 1
......
......@@ -3905,12 +3905,13 @@ query_prefetch(ns_client_t *client, dns_name_t *qname,
peeraddr = NULL;
ns_client_attach(client, &dummy);
options = client->query.fetchoptions | DNS_FETCHOPT_PREFETCH;
result = dns_resolver_createfetch2(client->view->resolver,
result = dns_resolver_createfetch3(client->view->resolver,
qname, rdataset->type, NULL, NULL,
NULL, peeraddr, client->message->id,
options, client->task,
prefetch_done, client, tmprdataset,
NULL, &client->query.prefetch);
options, 0, client->task,
prefetch_done, client,
tmprdataset, NULL,
&client->query.prefetch);
if (result != ISC_R_SUCCESS) {
query_putrdataset(client, &tmprdataset);
ns_client_detach(&dummy);
......@@ -4025,12 +4026,11 @@ query_recurse(ns_client_t *client, dns_rdatatype_t qtype, dns_name_t *qname,
peeraddr = &client->peeraddr;
else
peeraddr = NULL;
result = dns_resolver_createfetch2(client->view->resolver,
result = dns_resolver_createfetch3(client->view->resolver,
qname, qtype, qdomain, nameservers,
NULL, peeraddr, client->message->id,
client->query.fetchoptions,
client->task,
query_resume, client,
client->query.fetchoptions, 0,
client->task, query_resume, client,
rdataset, sigrdataset,
&client->query.fetch);
......
......@@ -3473,6 +3473,11 @@ configure_view(dns_view_t *view, dns_viewlist_t *viewlist,
cfg_obj_asuint32(obj),
max_clients_per_query);
obj = NULL;
result = ns_config_get(maps, "max-recursion-depth", &obj);
INSIST(result == ISC_R_SUCCESS);
dns_resolver_setmaxdepth(view->resolver, cfg_obj_asuint32(obj));
#ifdef ALLOW_FILTER_AAAA
obj = NULL;
result = ns_config_get(maps, "filter-aaaa-on-v4", &obj);
......
rm -f ns1/[1-9]*example.tld?.db
rm -f ns2/[1-9]*example.tld?.db
rm -f ns1/zones.conf
rm -f ns2/zones.conf
rm -f */root.db
rm -f ns3/tld1.db
rm -f ns4/tld2.db
/*
* Copyright (C) 2014 Internet Systems Consortium, Inc. ("ISC")
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
* REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
* INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
* LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
* OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
*/
controls { /* empty */ };
options {
query-source address 10.53.0.1;
notify-source 10.53.0.1;
transfer-source 10.53.0.1;
port 5300;
pid-file "named.pid";
listen-on { 10.53.0.1; };
listen-on-v6 { none; };
recursion no;
};
include "zones.conf";
// zone "tld1" { type master; file "tld1.db"; };
// zone "tld2" { type master; file "tld2.db"; };
/*
* Copyright (C) 2014 Internet Systems Consortium, Inc. ("ISC")
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
* REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
* INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
* LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
* OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
*/
controls { /* empty */ };
options {
query-source address 10.53.0.2;
notify-source 10.53.0.2;
transfer-source 10.53.0.2;
port 5300;
pid-file "named.pid";
listen-on { 10.53.0.2; };
listen-on-v6 { none; };
recursion no;
};
include "zones.conf";
/*
* Copyright (C) 2014 Internet Systems Consortium, Inc. ("ISC")
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
* REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
* INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
* LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
* OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
*/
controls { /* empty */ };
options {
query-source address 10.53.0.3;
notify-source 10.53.0.3;
transfer-source 10.53.0.3;
port 5300;
pid-file "named.pid";
listen-on { 10.53.0.3; };
listen-on-v6 { none; };
recursion no;
};
zone "." { type master; file "root.db"; };
zone "tld1" { type master; file "tld1.db"; };
/*
* Copyright (C) 2014 Internet Systems Consortium, Inc. ("ISC")
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
* REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
* INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
* LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
* OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
*/
controls { /* empty */ };
options {
query-source address 10.53.0.4;
notify-source 10.53.0.4;
transfer-source 10.53.0.4;
port 5300;
pid-file "named.pid";
listen-on { 10.53.0.4; };
listen-on-v6 { none; };
recursion no;
};
zone "tld2" { type master; file "tld2.db"; };
. 60 in ns ns.nil.
ns.nil. 60 in A 10.53.0.3
/*
* Copyright (C) 2014 Internet Systems Consortium, Inc. ("ISC")
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
* REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
* INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
* LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
* OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
*/
controls { /* empty */ };
options {
query-source address 10.53.0.5;
notify-source 10.53.0.5;
transfer-source 10.53.0.5;
port 5300;
pid-file "named.pid";
listen-on { 10.53.0.5; };
listen-on-v6 { none; };
};
zone "." { type hint; file "hints.db"; };
i=1
cat > ns3/root.db << EOF
. 60 in soa ns.nil. hostmaster.ns.nil. 1 0 0 0 0
. 60 in ns ns.nil.
ns.nil. 60 in a 10.53.0.3
tld1. 60 in ns ns.tld1.
ns.tld1. 60 in a 10.53.0.3
tld2. 60 in ns ns.tld2.
ns.tld2. 60 in a 10.53.0.4
EOF
cat > ns3/tld1.db << EOF
tld1. 60 in soa ns.tld1. hostmaster.ns.tld1. 1 0 0 0 0
tld1. 60 in ns ns.tld1.
ns.tld1. 60 in a 10.53.0.1
EOF
cat > ns4/tld2.db << EOF
tld2. 60 in soa ns.tld2. hostmaster.ns.tld4. 1 0 0 0 0
tld2. 60 in ns ns.tld2.
ns.tld2. 60 in a 10.53.0.1
EOF
: > ns1/zones.conf
: > ns2/zones.conf
while [ $i -lt 1000 ]
do
j=`expr $i + 1`
s=`expr $j % 2 + 1`
n=`expr $i % 2 + 1`
t=`expr $s + 2`
# i=1 j=2 s=1 n=2
# i=2 j=3 s=1 n=2
# i=3 j=4 s=1 n=2
cat > ns1/${i}example.tld${s}.db << EOF
${i}example.tld${s}. 60 in soa ns.${j}example.tld${n}. hostmaster 1 0 0 0 0
${i}example.tld${s}. 60 in ns ns.${j}example.tld${n}.
ns.${i}example.tld${s}. 60 in a 10.53.0.1
EOF
cat >> ns1/zones.conf << EOF
zone "${i}example.tld${s}" { type master; file "${i}example.tld${s}.db"; };
EOF
cat >> ns${t}/tld${s}.db << EOF
${i}example.tld${s}. 60 in ns ns.${j}example.tld${n}.
EOF
i=$j
done
j=`expr $i + 1`
s=`expr $j % 2 + 1`
n=`expr $s % 2 + 1`
t=`expr $s + 2`
cat > ns1/${i}example.tld${s}.db << EOF
${i}example.tld${s}. 60 in soa ns.${i}example.tld${s}. hostmaster 1 0 0 0 0
${i}example.tld${s}. 60 in ns ns.${i}example.tld${s}.
ns.${i}example.tld${s}. 60 in a 10.53.0.1
EOF
cat >> ns1/zones.conf << EOF
zone "${i}example.tld${s}" { type master; file "${i}example.tld${s}.db"; };
EOF
cat >> ns${t}/tld${s}.db << EOF
${i}example.tld${s}. 60 in ns ns.${i}example.tld${s}.
ns.${i}example.tld${s}. 60 in a 10.53.0.1
EOF
#!/bin/sh
#
# Copyright (C) 2014 Internet Systems Consortium, Inc. ("ISC")
#
# Permission to use, copy, modify, and/or distribute this software for any
# purpose with or without fee is hereby granted, provided that the above
# copyright notice and this permission notice appear in all copies.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
# AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
# INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
# LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
# PERFORMANCE OF THIS SOFTWARE.
SYSTEMTESTTOP=..
. $SYSTEMTESTTOP/conf.sh
status=0
n=0
n=`expr $n + 1`
echo "I: attempt lookup 1example.tld2 soa ($n)"
ret=0
$DIG +tcp 1example.tld1 soa @10.53.0.5 -p 5300 > dig.out.test$n
grep "status: SERVFAIL" dig.out.test$n > /dev/null || ret=1
if [ $ret != 0 ]; then echo "I:failed"; fi
status=`expr $status + $ret`
n=`expr $n + 1`
echo "I: attempt lookup 992example.tld2 soa ($n)"
ret=0
$DIG +tcp 992example.tld2 soa @10.53.0.5 -p 5300 > dig.out.test$n
grep "status: SERVFAIL" dig.out.test$n > /dev/null || ret=1
if [ $ret != 0 ]; then echo "I:failed"; fi
status=`expr $status + $ret`
n=`expr $n + 1`
echo "I: attempt lookup 993example.tld1 soa ($n)"
ret=0
$DIG +tcp 993example.tld1 soa @10.53.0.5 -p 5300 > dig.out.test$n
grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
if [ $ret != 0 ]; then echo "I:failed"; fi
status=`expr $status + $ret`
echo "I:exit status: $status"
exit $status
......@@ -4932,6 +4932,7 @@ badresp:1,adberr:0,findfail:0,valfail:0]
<optional> max-acache-size <replaceable>size_spec</replaceable> ; </optional>
<optional> clients-per-query <replaceable>number</replaceable> ; </optional>
<optional> max-clients-per-query <replaceable>number</replaceable> ; </optional>
<optional> max-recursion-depth <replaceable>number</replaceable> ; </optional>
<optional> masterfile-format
(<constant>text</constant>|<constant>raw</constant>|<constant>map</constant>) ; </optional>
<optional> masterfile-style
......@@ -9093,6 +9094,17 @@ avoid-v6-udp-ports { 40000; range 50000 60000; };
</listitem>
</varlistentry>
 
<varlistentry id="max-recursion-depth">
<term><command>max-recursion-depth</command></term>
<listitem>
<para>
Sets the maximum number of levels of recursion
permitted at any one time while resolving a name.
The default is 7.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><command>notify-delay</command></term>
<listitem>
......
......@@ -199,6 +199,7 @@ struct dns_adbfetch {
unsigned int magic;
dns_fetch_t *fetch;
dns_rdataset_t rdataset;
unsigned int depth;
};
/*%
......@@ -313,7 +314,7 @@ static inline void violate_locking_hierarchy(isc_mutex_t *, isc_mutex_t *);
static isc_boolean_t clean_namehooks(dns_adb_t *, dns_adbnamehooklist_t *);
static void clean_target(dns_adb_t *, dns_name_t *);
static void clean_finds_at_name(dns_adbname_t *, isc_eventtype_t,
unsigned int);
isc_uint32_t, unsigned int);
static isc_boolean_t check_expire_namehooks(dns_adbname_t *, isc_stdtime_t);
static isc_boolean_t check_expire_entry(dns_adb_t *, dns_adbentry_t **,
isc_stdtime_t);
......@@ -321,7 +322,7 @@ static void cancel_fetches_at_name(dns_adbname_t *);
static isc_result_t dbfind_name(dns_adbname_t *, isc_stdtime_t,
dns_rdatatype_t);
static isc_result_t fetch_name(dns_adbname_t *, isc_boolean_t,
dns_rdatatype_t);
unsigned int, dns_rdatatype_t);
static inline void check_exit(dns_adb_t *);
static void destroy(dns_adb_t *);
static isc_boolean_t shutdown_names(dns_adb_t *);
......@@ -1024,7 +1025,7 @@ kill_name(dns_adbname_t **n, isc_eventtype_t ev) {
* Clean up the name's various lists. These two are destructive
* in that they will always empty the list.
*/
clean_finds_at_name(name, ev, DNS_ADBFIND_ADDRESSMASK);
clean_finds_at_name(name, ev, 0, DNS_ADBFIND_ADDRESSMASK);
result4 = clean_namehooks(adb, &name->v4);
result6 = clean_namehooks(adb, &name->v6);
clean_target(adb, &name->target);
......@@ -1449,7 +1450,7 @@ event_free(isc_event_t *event) {
*/
static void
clean_finds_at_name(dns_adbname_t *name, isc_eventtype_t evtype,
unsigned int addrs)
isc_uint32_t qtotal, unsigned int addrs)
{
isc_event_t *ev;
isc_task_t *task;
......@@ -1509,6 +1510,7 @@ clean_finds_at_name(dns_adbname_t *name, isc_eventtype_t evtype,
ev->ev_sender = find;
find->result_v4 = find_err_map[name->fetch_err];
find->result_v6 = find_err_map[name->fetch6_err];
find->qtotal += qtotal;
ev->ev_type = evtype;
ev->ev_destroy = event_free;
ev->ev_destroy_arg = find;
......@@ -1884,6 +1886,7 @@ new_adbfind(dns_adb_t *adb) {
h->flags = 0;
h->result_v4 = ISC_R_UNEXPECTED;
h->result_v6 = ISC_R_UNEXPECTED;
h->qtotal = 0;
ISC_LINK_INIT(h, publink);
ISC_LINK_INIT(h, plink);
ISC_LIST_INIT(h->list);
......@@ -2864,6 +2867,19 @@ dns_adb_createfind(dns_adb_t *adb, isc_task_t *task, isc_taskaction_t action,
dns_rdatatype_t qtype, unsigned int options,
isc_stdtime_t now, dns_name_t *target,
in_port_t port, dns_adbfind_t **findp)
{
return (dns_adb_createfind2(adb, task, action, arg, name,
qname, qtype, options, now,
target, port, 0, findp));
}
isc_result_t
dns_adb_createfind2(dns_adb_t *adb, isc_task_t *task, isc_taskaction_t action,
void *arg, dns_name_t *name, dns_name_t *qname,
dns_rdatatype_t qtype, unsigned int options,
isc_stdtime_t now, dns_name_t *target,
in_port_t port, unsigned int depth,
dns_adbfind_t **findp)
{
dns_adbfind_t *find;
dns_adbname_t *adbname;
......@@ -3101,7 +3117,7 @@ dns_adb_createfind(dns_adb_t *adb, isc_task_t *task, isc_taskaction_t action,
* Start V4.
*/
if (WANT_INET(wanted_fetches) &&
fetch_name(adbname, start_at_zone,
fetch_name(adbname, start_at_zone, depth,
dns_rdatatype_a) == ISC_R_SUCCESS) {
DP(DEF_LEVEL, "dns_adb_createfind: "
"started A fetch for name %s (%p)",
......@@ -3112,7 +3128,7 @@ dns_adb_createfind(dns_adb_t *adb, isc_task_t *task, isc_taskaction_t action,
* Start V6.
*/
if (WANT_INET6(wanted_fetches) &&
fetch_name(adbname, start_at_zone,
fetch_name(adbname, start_at_zone, depth,
dns_rdatatype_aaaa) == ISC_R_SUCCESS) {
DP(DEF_LEVEL, "dns_adb_createfind: "
"started AAAA fetch for name %s (%p)",
......@@ -3744,6 +3760,7 @@ fetch_callback(isc_task_t *task, isc_event_t *ev) {
isc_result_t result;
unsigned int address_type;
isc_boolean_t want_check_exit = ISC_FALSE;
isc_uint32_t qtotal = 0;
UNUSED(task);
......@@ -3754,6 +3771,8 @@ fetch_callback(isc_task_t *task, isc_event_t *ev) {
adb = name->adb;
INSIST(DNS_ADB_VALID(adb));
qtotal = dev->qtotal;
bucket = name->lock_bucket;
LOCK(&adb->namelocks[bucket]);
......@@ -3871,6 +3890,12 @@ fetch_callback(isc_task_t *task, isc_event_t *ev) {
DP(DEF_LEVEL, "adb: fetch of '%s' %s failed: %s",
buf, address_type == DNS_ADBFIND_INET ? "A" : "AAAA",
dns_result_totext(dev->result));
/*
* Don't record a failure unless this is the initial
* fetch of a chain.
*/
if (fetch->depth > 1)
goto out;
/* XXXMLG Don't pound on bad servers. */
if (address_type == DNS_ADBFIND_INET) {
name->expire_v4 = ISC_MIN(name->expire_v4, now + 300);
......@@ -3902,15 +3927,14 @@ fetch_callback(isc_task_t *task, isc_event_t *ev) {
free_adbfetch(adb, &fetch);
isc_event_free(&ev);
clean_finds_at_name(name, ev_status, address_type);
clean_finds_at_name(name, ev_status, qtotal, address_type);
UNLOCK(&adb->namelocks[bucket]);
}
static isc_result_t
fetch_name(dns_adbname_t *adbname,
isc_boolean_t start_at_zone,
dns_rdatatype_t type)
fetch_name(dns_adbname_t *adbname, isc_boolean_t start_at_zone,
unsigned int depth, dns_rdatatype_t type)
{
isc_result_t result;
dns_adbfetch_t *fetch = NULL;
......@@ -3955,12 +3979,14 @@ fetch_name(dns_adbname_t *adbname,
result = ISC_R_NOMEMORY;
goto cleanup;
}
result = dns_resolver_createfetch(adb->view->resolver, &adbname->name,
type, name, nameservers, NULL,
options, adb->task, fetch_callback,
adbname, &fetch->rdataset, NULL,
&fetch->fetch);
fetch->depth = depth;
result = dns_resolver_createfetch3(adb->view->resolver, &adbname->name,
type, name, nameservers, NULL,
NULL, 0, options, depth, adb->task,
fetch_callback, adbname,
&fetch->rdataset, NULL,
&fetch->fetch);
if (result != ISC_R_SUCCESS)
goto cleanup;
......
......@@ -118,6 +118,8 @@ struct dns_adbfind {
isc_result_t result_v6; /*%< RO: v6 result */
ISC_LINK(dns_adbfind_t) publink; /*%< RW: client use */
isc_uint32_t qtotal;
/* Private */
isc_mutex_t lock; /* locks all below */
in_port_t port;
......@@ -336,6 +338,12 @@ dns_adb_createfind(dns_adb_t *adb, isc_task_t *task, isc_taskaction_t action,
dns_rdatatype_t qtype, unsigned int options,
isc_stdtime_t now, dns_name_t *target,
in_port_t port, dns_adbfind_t **find);
isc_result_t
dns_adb_createfind2(dns_adb_t *adb, isc_task_t *task, isc_taskaction_t action,
void *arg, dns_name_t *name, dns_name_t *qname,
dns_rdatatype_t qtype, unsigned int options,
isc_stdtime_t now, dns_name_t *target, in_port_t port,
unsigned int depth, dns_adbfind_t **find);
/*%<
* Main interface for clients. The adb will look up the name given in
* "name" and will build up a list of found addresses, and perhaps start
......
......@@ -82,6 +82,7 @@ typedef struct dns_fetchevent {
isc_sockaddr_t * client;
dns_messageid_t id;
isc_result_t vresult;
isc_uint32_t qtotal;
} dns_fetchevent_t;
/*
......@@ -278,6 +279,18 @@ dns_resolver_createfetch2(dns_resolver_t *res, dns_name_t *name,
dns_rdataset_t *rdataset,
dns_rdataset_t *sigrdataset,
dns_fetch_t **fetchp);
isc_result_t