summaryrefslogtreecommitdiff
path: root/lib/dns/resolver.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/dns/resolver.c')
-rw-r--r--lib/dns/resolver.c335
1 files changed, 203 insertions, 132 deletions
diff --git a/lib/dns/resolver.c b/lib/dns/resolver.c
index cdf5788d7a3b..dc648c9c3673 100644
--- a/lib/dns/resolver.c
+++ b/lib/dns/resolver.c
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: resolver.c,v 1.284.18.66.8.4 2008/07/24 05:00:48 jinmei Exp $ */
+/* $Id: resolver.c,v 1.284.18.79 2008/10/17 22:02:13 jinmei Exp $ */
/*! \file */
@@ -121,6 +121,7 @@ typedef struct query {
isc_mem_t * mctx;
dns_dispatchmgr_t * dispatchmgr;
dns_dispatch_t * dispatch;
+ isc_boolean_t exclusivesocket;
dns_adbaddrinfo_t * addrinfo;
isc_socket_t * tcpsocket;
isc_time_t start;
@@ -213,7 +214,7 @@ struct fetchctx {
unsigned int restarts;
/*%
- * The number of timeouts that have occurred since we
+ * The number of timeouts that have occurred since we
* last successfully received a response packet. This
* is used for EDNS0 black hole detection.
*/
@@ -221,7 +222,7 @@ struct fetchctx {
/*%
* Look aside state for DS lookups.
*/
- dns_name_t nsname;
+ dns_name_t nsname;
dns_fetch_t * nsfetch;
dns_rdataset_t nsrrset;
@@ -296,8 +297,8 @@ struct dns_resolver {
unsigned int magic;
isc_mem_t * mctx;
isc_mutex_t lock;
- isc_mutex_t nlock;
- isc_mutex_t primelock;
+ isc_mutex_t nlock;
+ isc_mutex_t primelock;
dns_rdataclass_t rdclass;
isc_socketmgr_t * socketmgr;
isc_timermgr_t * timermgr;
@@ -307,7 +308,9 @@ struct dns_resolver {
unsigned int options;
dns_dispatchmgr_t * dispatchmgr;
dns_dispatch_t * dispatchv4;
+ isc_boolean_t exclusivev4;
dns_dispatch_t * dispatchv6;
+ isc_boolean_t exclusivev6;
unsigned int nbuckets;
fctxbucket_t * buckets;
isc_uint32_t lame_ttl;
@@ -331,7 +334,7 @@ struct dns_resolver {
isc_eventlist_t whenshutdown;
unsigned int activebuckets;
isc_boolean_t priming;
- unsigned int spillat;
+ unsigned int spillat; /* clients-per-query */
/* Locked by primelock. */
dns_fetch_t * primefetch;
/* Locked by nlock. */
@@ -369,8 +372,10 @@ static isc_result_t ncache_adderesult(dns_message_t *message,
isc_stdtime_t now, dns_ttl_t maxttl,
dns_rdataset_t *ardataset,
isc_result_t *eresultp);
-static void validated(isc_task_t *task, isc_event_t *event);
+static void validated(isc_task_t *task, isc_event_t *event);
static void maybe_destroy(fetchctx_t *fctx);
+static void add_bad(fetchctx_t *fctx, dns_adbaddrinfo_t *addrinfo,
+ isc_result_t reason);
static isc_result_t
valcreate(fetchctx_t *fctx, dns_adbaddrinfo_t *addrinfo, dns_name_t *name,
@@ -562,6 +567,7 @@ fctx_cancelquery(resquery_t **queryp, dns_dispatchevent_t **deventp,
unsigned int factor;
dns_adbfind_t *find;
dns_adbaddrinfo_t *addrinfo;
+ isc_socket_t *socket;
query = *queryp;
fctx = query->fctx;
@@ -643,35 +649,48 @@ fctx_cancelquery(resquery_t **queryp, dns_dispatchevent_t **deventp,
0, factor);
}
- if (query->dispentry != NULL)
- dns_dispatch_removeresponse(&query->dispentry, deventp);
-
- ISC_LIST_UNLINK(fctx->queries, query, link);
-
- if (query->tsig != NULL)
- isc_buffer_free(&query->tsig);
-
- if (query->tsigkey != NULL)
- dns_tsigkey_detach(&query->tsigkey);
-
/*
* Check for any outstanding socket events. If they exist, cancel
* them and let the event handlers finish the cleanup. The resolver
* only needs to worry about managing the connect and send events;
* the dispatcher manages the recv events.
*/
- if (RESQUERY_CONNECTING(query))
+ if (RESQUERY_CONNECTING(query)) {
/*
* Cancel the connect.
*/
- isc_socket_cancel(query->tcpsocket, NULL,
- ISC_SOCKCANCEL_CONNECT);
- else if (RESQUERY_SENDING(query))
+ if (query->tcpsocket != NULL) {
+ isc_socket_cancel(query->tcpsocket, NULL,
+ ISC_SOCKCANCEL_CONNECT);
+ } else if (query->dispentry != NULL) {
+ INSIST(query->exclusivesocket);
+ socket = dns_dispatch_getentrysocket(query->dispentry);
+ if (socket != NULL)
+ isc_socket_cancel(socket, NULL,
+ ISC_SOCKCANCEL_CONNECT);
+ }
+ } else if (RESQUERY_SENDING(query)) {
/*
* Cancel the pending send.
*/
- isc_socket_cancel(dns_dispatch_getsocket(query->dispatch),
- NULL, ISC_SOCKCANCEL_SEND);
+ if (query->exclusivesocket && query->dispentry != NULL)
+ socket = dns_dispatch_getentrysocket(query->dispentry);
+ else
+ socket = dns_dispatch_getsocket(query->dispatch);
+ if (socket != NULL)
+ isc_socket_cancel(socket, NULL, ISC_SOCKCANCEL_SEND);
+ }
+
+ if (query->dispentry != NULL)
+ dns_dispatch_removeresponse(&query->dispentry, deventp);
+
+ ISC_LIST_UNLINK(fctx->queries, query, link);
+
+ if (query->tsig != NULL)
+ isc_buffer_free(&query->tsig);
+
+ if (query->tsigkey != NULL)
+ dns_tsigkey_detach(&query->tsigkey);
if (query->dispatch != NULL)
dns_dispatch_detach(&query->dispatch);
@@ -777,6 +796,8 @@ fctx_sendevents(fetchctx_t *fctx, isc_result_t result) {
unsigned int count = 0;
isc_interval_t i;
isc_boolean_t logit = ISC_FALSE;
+ unsigned int old_spillat;
+ unsigned int new_spillat = 0; /* initialized to silence compiler warnings */
/*
* Caller must be holding the appropriate bucket lock.
@@ -800,7 +821,7 @@ fctx_sendevents(fetchctx_t *fctx, isc_result_t result) {
fctx->type == dns_rdatatype_any ||
fctx->type == dns_rdatatype_rrsig ||
fctx->type == dns_rdatatype_sig);
-
+
/*
* Negative results must be indicated in event->result.
*/
@@ -819,11 +840,15 @@ fctx_sendevents(fetchctx_t *fctx, isc_result_t result) {
(count < fctx->res->spillatmax || fctx->res->spillatmax == 0)) {
LOCK(&fctx->res->lock);
if (count == fctx->res->spillat && !fctx->res->exiting) {
+ old_spillat = fctx->res->spillat;
fctx->res->spillat += 5;
if (fctx->res->spillat > fctx->res->spillatmax &&
fctx->res->spillatmax != 0)
fctx->res->spillat = fctx->res->spillatmax;
- logit = ISC_TRUE;
+ new_spillat = fctx->res->spillat;
+ if (new_spillat != old_spillat) {
+ logit = ISC_TRUE;
+ }
isc_interval_set(&i, 20 * 60, 0);
result = isc_timer_reset(fctx->res->spillattimer,
isc_timertype_ticker, NULL,
@@ -835,7 +860,7 @@ fctx_sendevents(fetchctx_t *fctx, isc_result_t result) {
isc_log_write(dns_lctx, DNS_LOGCATEGORY_RESOLVER,
DNS_LOGMODULE_RESOLVER, ISC_LOG_NOTICE,
"clients-per-query increased to %u",
- count + 1);
+ new_spillat);
}
}
@@ -864,43 +889,25 @@ fctx_done(fetchctx_t *fctx, isc_result_t result) {
}
static void
-resquery_senddone(isc_task_t *task, isc_event_t *event) {
+process_sendevent(resquery_t *query, isc_event_t *event) {
isc_socketevent_t *sevent = (isc_socketevent_t *)event;
- resquery_t *query = event->ev_arg;
isc_boolean_t retry = ISC_FALSE;
isc_result_t result;
fetchctx_t *fctx;
- REQUIRE(event->ev_type == ISC_SOCKEVENT_SENDDONE);
-
- QTRACE("senddone");
-
- /*
- * XXXRTH
- *
- * Currently we don't wait for the senddone event before retrying
- * a query. This means that if we get really behind, we may end
- * up doing extra work!
- */
-
- UNUSED(task);
-
- INSIST(RESQUERY_SENDING(query));
-
- query->sends--;
fctx = query->fctx;
if (RESQUERY_CANCELED(query)) {
- if (query->sends == 0) {
+ if (query->sends == 0 && query->connects == 0) {
/*
* This query was canceled while the
- * isc_socket_sendto() was in progress.
+ * isc_socket_sendto/connect() was in progress.
*/
if (query->tcpsocket != NULL)
isc_socket_detach(&query->tcpsocket);
resquery_destroy(&query);
}
- } else
+ } else {
switch (sevent->result) {
case ISC_R_SUCCESS:
break;
@@ -914,6 +921,7 @@ resquery_senddone(isc_task_t *task, isc_event_t *event) {
/*
* No route to remote.
*/
+ add_bad(fctx, query->addrinfo, sevent->result);
fctx_cancelquery(&query, NULL, NULL, ISC_TRUE);
retry = ISC_TRUE;
break;
@@ -922,6 +930,7 @@ resquery_senddone(isc_task_t *task, isc_event_t *event) {
fctx_cancelquery(&query, NULL, NULL, ISC_FALSE);
break;
}
+ }
isc_event_free(&event);
@@ -939,9 +948,51 @@ resquery_senddone(isc_task_t *task, isc_event_t *event) {
}
}
+static void
+resquery_udpconnected(isc_task_t *task, isc_event_t *event) {
+ resquery_t *query = event->ev_arg;
+
+ REQUIRE(event->ev_type == ISC_SOCKEVENT_CONNECT);
+
+ QTRACE("udpconnected");
+
+ UNUSED(task);
+
+ INSIST(RESQUERY_CONNECTING(query));
+
+ query->connects--;
+
+ process_sendevent(query, event);
+}
+
+static void
+resquery_senddone(isc_task_t *task, isc_event_t *event) {
+ resquery_t *query = event->ev_arg;
+
+ REQUIRE(event->ev_type == ISC_SOCKEVENT_SENDDONE);
+
+ QTRACE("senddone");
+
+ /*
+ * XXXRTH
+ *
+ * Currently we don't wait for the senddone event before retrying
+ * a query. This means that if we get really behind, we may end
+ * up doing extra work!
+ */
+
+ UNUSED(task);
+
+ INSIST(RESQUERY_SENDING(query));
+
+ query->sends--;
+
+ process_sendevent(query, event);
+}
+
static inline isc_result_t
fctx_addopt(dns_message_t *message, unsigned int version, isc_uint16_t udpsize)
-{
+{
dns_rdataset_t *rdataset;
dns_rdatalist_t *rdatalist;
dns_rdata_t *rdata;
@@ -1001,9 +1052,9 @@ fctx_setretryinterval(fetchctx_t *fctx, unsigned int rtt) {
* list, and then we do exponential back-off.
*/
if (fctx->restarts < 3)
- us = 500000;
+ us = 800000;
else
- us = (500000 << (fctx->restarts - 2));
+ us = (800000 << (fctx->restarts - 2));
/*
* Double the round-trip time.
@@ -1077,6 +1128,7 @@ fctx_query(fetchctx_t *fctx, dns_adbaddrinfo_t *addrinfo,
*/
query->dispatchmgr = res->dispatchmgr;
query->dispatch = NULL;
+ query->exclusivesocket = ISC_FALSE;
query->tcpsocket = NULL;
if (res->view->peers != NULL) {
dns_peer_t *peer = NULL;
@@ -1159,53 +1211,21 @@ fctx_query(fetchctx_t *fctx, dns_adbaddrinfo_t *addrinfo,
if (result != ISC_R_SUCCESS)
goto cleanup_query;
} else {
- isc_sockaddr_t localaddr;
- unsigned int attrs, attrmask;
- dns_dispatch_t *disp_base;
-
- attrs = 0;
- attrs |= DNS_DISPATCHATTR_UDP;
- attrs |= DNS_DISPATCHATTR_RANDOMPORT;
-
- attrmask = 0;
- attrmask |= DNS_DISPATCHATTR_UDP;
- attrmask |= DNS_DISPATCHATTR_TCP;
- attrmask |= DNS_DISPATCHATTR_IPV4;
- attrmask |= DNS_DISPATCHATTR_IPV6;
-
switch (isc_sockaddr_pf(&addrinfo->sockaddr)) {
- case AF_INET:
- disp_base = res->dispatchv4;
- attrs |= DNS_DISPATCHATTR_IPV4;
+ case PF_INET:
+ dns_dispatch_attach(res->dispatchv4,
+ &query->dispatch);
+ query->exclusivesocket = res->exclusivev4;
break;
- case AF_INET6:
- disp_base = res->dispatchv6;
- attrs |= DNS_DISPATCHATTR_IPV6;
+ case PF_INET6:
+ dns_dispatch_attach(res->dispatchv6,
+ &query->dispatch);
+ query->exclusivesocket = res->exclusivev6;
break;
default:
result = ISC_R_NOTIMPLEMENTED;
goto cleanup_query;
}
-
- result = dns_dispatch_getlocaladdress(disp_base,
- &localaddr);
- if (result != ISC_R_SUCCESS)
- goto cleanup_query;
- if (isc_sockaddr_getport(&localaddr) == 0) {
- result = dns_dispatch_getudp(res->dispatchmgr,
- res->socketmgr,
- res->taskmgr,
- &localaddr,
- 4096, 1000, 32768,
- 16411, 16433,
- attrs, attrmask,
- &query->dispatch);
- if (result != ISC_R_SUCCESS)
- goto cleanup_query;
- } else {
- dns_dispatch_attach(disp_base,
- &query->dispatch);
- }
}
/*
* We should always have a valid dispatcher here. If we
@@ -1378,13 +1398,14 @@ resquery_send(resquery_t *query) {
/*
* Get a query id from the dispatch.
*/
- result = dns_dispatch_addresponse(query->dispatch,
- &query->addrinfo->sockaddr,
- task,
- resquery_response,
- query,
- &query->id,
- &query->dispentry);
+ result = dns_dispatch_addresponse2(query->dispatch,
+ &query->addrinfo->sockaddr,
+ task,
+ resquery_response,
+ query,
+ &query->id,
+ &query->dispentry,
+ res->socketmgr);
if (result != ISC_R_SUCCESS)
goto cleanup_temps;
@@ -1593,12 +1614,24 @@ resquery_send(resquery_t *query) {
*/
dns_message_reset(fctx->qmessage, DNS_MESSAGE_INTENTRENDER);
- socket = dns_dispatch_getsocket(query->dispatch);
+ if (query->exclusivesocket)
+ socket = dns_dispatch_getentrysocket(query->dispentry);
+ else
+ socket = dns_dispatch_getsocket(query->dispatch);
/*
* Send the query!
*/
- if ((query->options & DNS_FETCHOPT_TCP) == 0)
+ if ((query->options & DNS_FETCHOPT_TCP) == 0) {
address = &query->addrinfo->sockaddr;
+ if (query->exclusivesocket) {
+ result = isc_socket_connect(socket, address, task,
+ resquery_udpconnected,
+ query);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup_message;
+ query->connects++;
+ }
+ }
isc_buffer_usedregion(buffer, &r);
/*
@@ -1731,7 +1764,7 @@ resquery_connected(isc_task_t *task, isc_event_t *event) {
}
isc_event_free(&event);
-
+
if (retry) {
/*
* Behave as if the idle timer has expired. For TCP
@@ -1921,8 +1954,8 @@ add_bad(fetchctx_t *fctx, dns_adbaddrinfo_t *addrinfo, isc_result_t reason) {
if (reason == DNS_R_LAME) /* already logged */
return;
- if (reason == DNS_R_UNEXPECTEDRCODE &&
- fctx->rmessage->opcode == dns_rcode_servfail &&
+ if (reason == DNS_R_UNEXPECTEDRCODE &&
+ fctx->rmessage->rcode == dns_rcode_servfail &&
ISFORWARDER(addrinfo))
return;
@@ -2196,6 +2229,13 @@ fctx_getaddresses(fetchctx_t *fctx) {
}
while (sa != NULL) {
+ if ((isc_sockaddr_pf(sa) == AF_INET &&
+ fctx->res->dispatchv4 == NULL) ||
+ (isc_sockaddr_pf(sa) == AF_INET6 &&
+ fctx->res->dispatchv6 == NULL)) {
+ sa = ISC_LIST_NEXT(sa, link);
+ continue;
+ }
ai = NULL;
result = dns_adb_findaddrinfo(fctx->adb,
sa, &ai, 0); /* XXXMLG */
@@ -2366,7 +2406,7 @@ possibly_mark(fetchctx_t *fctx, dns_adbaddrinfo_t *addr)
isc_netaddr_fromsockaddr(&ipaddr, sa);
blackhole = dns_dispatchmgr_getblackhole(res->dispatchmgr);
(void) dns_peerlist_peerbyaddr(res->view->peers, &ipaddr, &peer);
-
+
if (blackhole != NULL) {
int match;
@@ -2799,7 +2839,7 @@ fctx_doshutdown(isc_task_t *task, isc_event_t *event) {
dns_validator_cancel(validator);
validator = ISC_LIST_NEXT(validator, link);
}
-
+
if (fctx->nsfetch != NULL)
dns_resolver_cancelfetch(fctx->nsfetch);
@@ -3252,9 +3292,9 @@ is_lame(fetchctx_t *fctx) {
static inline void
log_lame(fetchctx_t *fctx, dns_adbaddrinfo_t *addrinfo) {
char namebuf[DNS_NAME_FORMATSIZE];
- char domainbuf[DNS_NAME_FORMATSIZE];
+ char domainbuf[DNS_NAME_FORMATSIZE];
char addrbuf[ISC_SOCKADDR_FORMATSIZE];
-
+
dns_name_format(&fctx->name, namebuf, sizeof(namebuf));
dns_name_format(&fctx->domain, domainbuf, sizeof(domainbuf));
isc_sockaddr_format(&addrinfo->sockaddr, addrbuf, sizeof(addrbuf));
@@ -3822,9 +3862,9 @@ cache_name(fetchctx_t *fctx, dns_name_t *name, dns_adbaddrinfo_t *addrinfo,
sizeof(typebuf));
dns_rdataclass_format(rdataset->rdclass, classbuf,
sizeof(classbuf));
- isc_log_write(dns_lctx, DNS_LOGCATEGORY_RESOLVER,
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_RESOLVER,
DNS_LOGMODULE_RESOLVER, ISC_LOG_NOTICE,
- "check-names %s %s/%s/%s",
+ "check-names %s %s/%s/%s",
fail ? "failure" : "warning",
namebuf, typebuf, classbuf);
if (fail) {
@@ -4411,7 +4451,7 @@ chase_additional(fetchctx_t *fctx) {
again:
rescan = ISC_FALSE;
-
+
for (result = dns_message_firstname(fctx->rmessage, section);
result == ISC_R_SUCCESS;
result = dns_message_nextname(fctx->rmessage, section)) {
@@ -4491,7 +4531,7 @@ dname_target(dns_rdataset_t *rdataset, dns_name_t *qname, dns_name_t *oname,
return (DNS_R_FORMERR);
}
dns_fixedname_init(&prefix);
- dns_name_split(qname, nlabels, dns_fixedname_name(&prefix), NULL);
+ dns_name_split(qname, nlabels, dns_fixedname_name(&prefix), NULL);
dns_fixedname_init(fixeddname);
result = dns_name_concatenate(dns_fixedname_name(&prefix),
&dname.dname,
@@ -4650,7 +4690,7 @@ noanswer_response(fetchctx_t *fctx, dns_name_t *oqname,
}
/*
- * A negative response has a SOA record (Type 2)
+ * A negative response has a SOA record (Type 2)
* and a optional NS RRset (Type 1) or it has neither
* a SOA or a NS RRset (Type 3, handled above) or
* rcode is NXDOMAIN (handled above) in which case
@@ -5363,7 +5403,7 @@ checknamessection(dns_message_t *message, dns_section_t section) {
dns_name_t *name;
dns_rdata_t rdata = DNS_RDATA_INIT;
dns_rdataset_t *rdataset;
-
+
for (result = dns_message_firstname(message, section);
result == ISC_R_SUCCESS;
result = dns_message_nextname(message, section))
@@ -5382,7 +5422,7 @@ checknamessection(dns_message_t *message, dns_section_t section) {
ISC_FALSE) ||
!dns_rdata_checknames(&rdata, name, NULL))
{
- rdataset->attributes |=
+ rdataset->attributes |=
DNS_RDATASETATTR_CHECKNAMES;
}
dns_rdata_reset(&rdata);
@@ -5512,6 +5552,19 @@ resquery_response(isc_task_t *task, isc_event_t *event) {
* There's no hope for this query.
*/
keep_trying = ISC_TRUE;
+
+ /*
+ * If this is a network error on an exclusive query
+ * socket, mark the server as bad so that we won't try
+ * it for this fetch again.
+ */
+ if (query->exclusivesocket &&
+ (devent->result == ISC_R_HOSTUNREACH ||
+ devent->result == ISC_R_NETUNREACH ||
+ devent->result == ISC_R_CONNREFUSED ||
+ devent->result == ISC_R_CANCELED)) {
+ broken_server = devent->result;
+ }
}
goto done;
}
@@ -5662,12 +5715,17 @@ resquery_response(isc_task_t *task, isc_event_t *event) {
*/
if (message->rcode != dns_rcode_noerror &&
message->rcode != dns_rcode_nxdomain) {
- if ((message->rcode == dns_rcode_formerr ||
- message->rcode == dns_rcode_notimp ||
- message->rcode == dns_rcode_servfail) &&
+ if (((message->rcode == dns_rcode_formerr ||
+ message->rcode == dns_rcode_notimp) ||
+ (message->rcode == dns_rcode_servfail &&
+ dns_message_getopt(message) == NULL)) &&
(query->options & DNS_FETCHOPT_NOEDNS0) == 0) {
/*
* It's very likely they don't like EDNS0.
+ * If the response code is SERVFAIL, also check if the
+ * response contains an OPT RR and don't cache the
+ * failure since it can be returned for various other
+ * reasons.
*
* XXXRTH We should check if the question
* we're asking requires EDNS0, and
@@ -6154,7 +6212,7 @@ spillattimer_countdown(isc_task_t *task, isc_event_t *event) {
REQUIRE(VALID_RESOLVER(res));
UNUSED(task);
-
+
LOCK(&res->lock);
INSIST(!res->exiting);
if (res->spillat > res->spillatmin) {
@@ -6181,7 +6239,7 @@ isc_result_t
dns_resolver_create(dns_view_t *view,
isc_taskmgr_t *taskmgr, unsigned int ntasks,
isc_socketmgr_t *socketmgr,
- isc_timermgr_t *timermgr,
+ isc_timermgr_t *timermgr,
unsigned int options,
dns_dispatchmgr_t *dispatchmgr,
dns_dispatch_t *dispatchv4,
@@ -6193,6 +6251,7 @@ dns_resolver_create(dns_view_t *view,
unsigned int i, buckets_created = 0;
isc_task_t *task = NULL;
char name[16];
+ unsigned dispattr;
/*
* Create a resolver.
@@ -6259,11 +6318,20 @@ dns_resolver_create(dns_view_t *view,
}
res->dispatchv4 = NULL;
- if (dispatchv4 != NULL)
+ if (dispatchv4 != NULL) {
dns_dispatch_attach(dispatchv4, &res->dispatchv4);
+ dispattr = dns_dispatch_getattributes(dispatchv4);
+ res->exclusivev4 =
+ ISC_TF((dispattr & DNS_DISPATCHATTR_EXCLUSIVE) != 0);
+ }
+
res->dispatchv6 = NULL;
- if (dispatchv6 != NULL)
+ if (dispatchv6 != NULL) {
dns_dispatch_attach(dispatchv6, &res->dispatchv6);
+ dispattr = dns_dispatch_getattributes(dispatchv6);
+ res->exclusivev6 =
+ ISC_TF((dispattr & DNS_DISPATCHATTR_EXCLUSIVE) != 0);
+ }
res->references = 1;
res->exiting = ISC_FALSE;
@@ -6380,7 +6448,7 @@ prime_done(isc_task_t *task, isc_event_t *event) {
UNLOCK(&res->primelock);
UNLOCK(&res->lock);
-
+
if (fevent->result == ISC_R_SUCCESS &&
res->view->cache != NULL && res->view->hints != NULL) {
dns_cache_attachdb(res->view->cache, &db);
@@ -6546,12 +6614,12 @@ dns_resolver_shutdown(dns_resolver_t *res) {
fctx != NULL;
fctx = ISC_LIST_NEXT(fctx, link))
fctx_shutdown(fctx);
- if (res->dispatchv4 != NULL) {
+ if (res->dispatchv4 != NULL && !res->exclusivev4) {
sock = dns_dispatch_getsocket(res->dispatchv4);
isc_socket_cancel(sock, res->buckets[i].task,
ISC_SOCKCANCEL_ALL);
}
- if (res->dispatchv6 != NULL) {
+ if (res->dispatchv6 != NULL && !res->exclusivev6) {
sock = dns_dispatch_getsocket(res->dispatchv6);
isc_socket_cancel(sock, res->buckets[i].task,
ISC_SOCKCANCEL_ALL);
@@ -6665,6 +6733,7 @@ dns_resolver_createfetch2(dns_resolver_t *res, dns_name_t *name,
isc_event_t *event;
unsigned int count = 0;
unsigned int spillat;
+ unsigned int spillatmin;
UNUSED(forwarders);
@@ -6695,6 +6764,7 @@ dns_resolver_createfetch2(dns_resolver_t *res, dns_name_t *name,
LOCK(&res->lock);
spillat = res->spillat;
+ spillatmin = res->spillatmin;
UNLOCK(&res->lock);
LOCK(&res->buckets[bucketnum].lock);
@@ -6711,7 +6781,7 @@ dns_resolver_createfetch2(dns_resolver_t *res, dns_name_t *name,
break;
}
}
-
+
/*
* Is this a duplicate?
*/
@@ -6728,7 +6798,8 @@ dns_resolver_createfetch2(dns_resolver_t *res, dns_name_t *name,
count++;
}
}
- if (count >= res->spillatmin && res->spillatmin != 0) {
+ if (count >= spillatmin && spillatmin != 0) {
+ INSIST(fctx != NULL);
if (count >= spillat)
fctx->spilled = ISC_TRUE;
if (fctx->spilled) {
@@ -7004,7 +7075,7 @@ free_algorithm(void *node, void *arg) {
isc_mem_put(mctx, algorithms, *algorithms);
}
-
+
void
dns_resolver_reset_algorithms(dns_resolver_t *resolver) {
@@ -7048,7 +7119,7 @@ dns_resolver_disable_algorithm(dns_resolver_t *resolver, dns_name_t *name,
mask = 1 << (alg%8);
result = dns_rbt_addnode(resolver->algorithms, name, &node);
-
+
if (result == ISC_R_SUCCESS || result == ISC_R_EXISTS) {
algorithms = node->data;
if (algorithms == NULL || len > *algorithms) {
@@ -7064,7 +7135,7 @@ dns_resolver_disable_algorithm(dns_resolver_t *resolver, dns_name_t *name,
*new = len;
node->data = new;
if (algorithms != NULL)
- isc_mem_put(resolver->mctx, algorithms,
+ isc_mem_put(resolver->mctx, algorithms,
*algorithms);
} else
algorithms[len-1] |= mask;
@@ -7132,7 +7203,7 @@ dns_resolver_resetmustbesecure(dns_resolver_t *resolver) {
RWUNLOCK(&resolver->mbslock, isc_rwlocktype_write);
#endif
}
-
+
static isc_boolean_t yes = ISC_TRUE, no = ISC_FALSE;
isc_result_t
@@ -7152,7 +7223,7 @@ dns_resolver_setmustbesecure(dns_resolver_t *resolver, dns_name_t *name,
if (result != ISC_R_SUCCESS)
goto cleanup;
}
- result = dns_rbt_addname(resolver->mustbesecure, name,
+ result = dns_rbt_addname(resolver->mustbesecure, name,
value ? &yes : &no);
cleanup:
#if USE_MBSLOCK