4253. [bug] Address fetch context reference count handling error

on socket error.  [RT#40945]
This commit is contained in:
Mark Andrews 2015-11-05 17:10:10 +11:00
parent e939674d53
commit 2f450fcd29
2 changed files with 57 additions and 43 deletions

View file

@ -1,3 +1,6 @@
4253. [bug] Address fetch context reference count handling error
on socket error. [RT#40945]
4252. [func] Add support for automating the generation CDS and
CDNSKEY rrsets to named and dnssec-signzone.
[RT #40424]

View file

@ -1787,8 +1787,7 @@ fctx_query(fetchctx_t *fctx, dns_adbaddrinfo_t *addrinfo,
}
query->dispentry = NULL;
fctx_increference(fctx);
query->fctx = fctx;
query->fctx = fctx; /* reference added by caller */
query->tsig = NULL;
query->tsigkey = NULL;
ISC_LINK_INIT(query, link);
@ -1842,11 +1841,6 @@ fctx_query(fetchctx_t *fctx, dns_adbaddrinfo_t *addrinfo,
if (query->dispatch != NULL)
dns_dispatch_detach(&query->dispatch);
LOCK(&res->buckets[fctx->bucketnum].lock);
INSIST(fctx->references > 1);
fctx->references--;
UNLOCK(&res->buckets[fctx->bucketnum].lock);
cleanup_query:
if (query->connects == 0) {
query->magic = 0;
@ -3661,6 +3655,8 @@ fctx_try(fetchctx_t *fctx, isc_boolean_t retrying, isc_boolean_t badcache) {
isc_result_t result;
dns_adbaddrinfo_t *addrinfo = NULL;
dns_resolver_t *res;
unsigned int bucketnum;
isc_boolean_t bucket_empty;
FCTXTRACE("try");
@ -3733,10 +3729,17 @@ fctx_try(fetchctx_t *fctx, isc_boolean_t retrying, isc_boolean_t badcache) {
}
}
bucketnum = fctx->bucketnum;
fctx_increference(fctx);
result = fctx_query(fctx, addrinfo, fctx->options);
if (result != ISC_R_SUCCESS)
if (result != ISC_R_SUCCESS) {
fctx_done(fctx, result, __LINE__);
else if (retrying)
LOCK(&res->buckets[bucketnum].lock);
bucket_empty = fctx_decreference(fctx);
UNLOCK(&res->buckets[bucketnum].lock);
if (bucket_empty)
empty_bucket(res);
} else if (retrying)
inc_stats(res, dns_resstatscounter_retry);
}
@ -7612,6 +7615,9 @@ resquery_response(isc_task_t *task, isc_event_t *event) {
isc_result_t broken_server;
badnstype_t broken_type = badns_response;
isc_boolean_t no_response;
unsigned int bucketnum;
dns_resolver_t *res;
isc_boolean_t bucket_empty;
#ifdef HAVE_DNSTAP
unsigned char zone[DNS_NAME_MAXWIRE];
dns_dtmsgtype_t dtmsgtype;
@ -7628,10 +7634,11 @@ resquery_response(isc_task_t *task, isc_event_t *event) {
QTRACE("response");
res = fctx->res;
if (isc_sockaddr_pf(&query->addrinfo->sockaddr) == PF_INET)
inc_stats(fctx->res, dns_resstatscounter_responsev4);
inc_stats(res, dns_resstatscounter_responsev4);
else
inc_stats(fctx->res, dns_resstatscounter_responsev6);
inc_stats(res, dns_resstatscounter_responsev6);
(void)isc_timer_touch(fctx->timer);
@ -7643,7 +7650,7 @@ resquery_response(isc_task_t *task, isc_event_t *event) {
finish = NULL;
no_response = ISC_FALSE;
if (fctx->res->exiting) {
if (res->exiting) {
result = ISC_R_SHUTTINGDOWN;
FCTXTRACE("resolver shutting down");
goto done;
@ -7757,7 +7764,7 @@ resquery_response(isc_task_t *task, isc_event_t *event) {
resend = ISC_TRUE;
add_bad_edns(fctx,
&query->addrinfo->sockaddr);
inc_stats(fctx->res,
inc_stats(res,
dns_resstatscounter_edns0fail);
} else {
broken_server = result;
@ -7781,8 +7788,7 @@ resquery_response(isc_task_t *task, isc_event_t *event) {
options |= DNS_FETCHOPT_NOEDNS0;
resend = ISC_TRUE;
add_bad_edns(fctx, &query->addrinfo->sockaddr);
inc_stats(fctx->res,
dns_resstatscounter_edns0fail);
inc_stats(res, dns_resstatscounter_edns0fail);
} else {
broken_server = DNS_R_UNEXPECTEDRCODE;
keep_trying = ISC_TRUE;
@ -7804,15 +7810,14 @@ resquery_response(isc_task_t *task, isc_event_t *event) {
DNS_LOGCATEGORY_RESOLVER,
DNS_LOGMODULE_PACKETS,
&dns_master_style_comment,
ISC_LOG_DEBUG(10),
fctx->res->mctx);
ISC_LOG_DEBUG(10), res->mctx);
#ifdef HAVE_DNSTAP
/*
* Log the response via dnstap.
*/
memset(&zr, 0, sizeof(zr));
result = dns_compress_init(&cctx, -1, fctx->res->mctx);
result = dns_compress_init(&cctx, -1, res->mctx);
if (result == ISC_R_SUCCESS) {
isc_buffer_init(&zb, zone, sizeof(zone));
dns_compress_setmethods(&cctx, DNS_COMPRESS_NONE);
@ -7827,8 +7832,7 @@ resquery_response(isc_task_t *task, isc_event_t *event) {
else
dtmsgtype = DNS_DTTYPE_RR;
dns_dt_send(fctx->res->view, dtmsgtype,
&query->addrinfo->sockaddr,
dns_dt_send(res->view, dtmsgtype, &query->addrinfo->sockaddr,
ISC_TF((query->options & DNS_FETCHOPT_TCP) != 0),
&zr, &query->start, NULL, &devent->buffer);
#endif /* HAVE_DNSTAP */
@ -7854,7 +7858,7 @@ resquery_response(isc_task_t *task, isc_event_t *event) {
* If the message is signed, check the signature. If not, this
* returns success anyway.
*/
result = dns_message_checksig(message, fctx->res->view);
result = dns_message_checksig(message, res->view);
if (result != ISC_R_SUCCESS) {
FCTXTRACE3("signature check failed", result);
goto done;
@ -7890,7 +7894,7 @@ resquery_response(isc_task_t *task, isc_event_t *event) {
DNS_LOGCATEGORY_RESOLVER,
DNS_LOGMODULE_RESOLVER,
ISC_LOG_DEBUG(3),
fctx->res->mctx);
res->mctx);
dns_adb_changeflags(fctx->adb, query->addrinfo,
DNS_FETCHOPT_NOEDNS0,
DNS_FETCHOPT_NOEDNS0);
@ -7914,8 +7918,7 @@ resquery_response(isc_task_t *task, isc_event_t *event) {
&query->addrinfo->sockaddr,
DNS_LOGCATEGORY_RESOLVER,
DNS_LOGMODULE_RESOLVER,
ISC_LOG_DEBUG(3),
fctx->res->mctx);
ISC_LOG_DEBUG(3), res->mctx);
dns_adb_changeflags(fctx->adb, query->addrinfo,
DNS_FETCHOPT_NOEDNS0,
DNS_FETCHOPT_NOEDNS0);
@ -7943,7 +7946,7 @@ resquery_response(isc_task_t *task, isc_event_t *event) {
truncated = ISC_TRUE;
if (truncated) {
inc_stats(fctx->res, dns_resstatscounter_truncated);
inc_stats(res, dns_resstatscounter_truncated);
if ((options & DNS_FETCHOPT_TCP) != 0) {
broken_server = DNS_R_TRUNCATEDTCP;
keep_trying = ISC_TRUE;
@ -7972,25 +7975,25 @@ resquery_response(isc_task_t *task, isc_event_t *event) {
if (message->rcode != dns_rcode_noerror) {
switch (message->rcode) {
case dns_rcode_nxdomain:
inc_stats(fctx->res, dns_resstatscounter_nxdomain);
inc_stats(res, dns_resstatscounter_nxdomain);
break;
case dns_rcode_servfail:
inc_stats(fctx->res, dns_resstatscounter_servfail);
inc_stats(res, dns_resstatscounter_servfail);
break;
case dns_rcode_formerr:
inc_stats(fctx->res, dns_resstatscounter_formerr);
inc_stats(res, dns_resstatscounter_formerr);
break;
case dns_rcode_refused:
inc_stats(fctx->res, dns_resstatscounter_refused);
inc_stats(res, dns_resstatscounter_refused);
break;
case dns_rcode_badvers:
inc_stats(fctx->res, dns_resstatscounter_badvers);
inc_stats(res, dns_resstatscounter_badvers);
break;
case dns_rcode_badcookie:
inc_stats(fctx->res, dns_resstatscounter_badcookie);
inc_stats(res, dns_resstatscounter_badcookie);
break;
default:
inc_stats(fctx->res, dns_resstatscounter_othererror);
inc_stats(res, dns_resstatscounter_othererror);
break;
}
}
@ -8039,7 +8042,7 @@ resquery_response(isc_task_t *task, isc_event_t *event) {
* Remember that they may not like EDNS0.
*/
add_bad_edns(fctx, &query->addrinfo->sockaddr);
inc_stats(fctx->res, dns_resstatscounter_edns0fail);
inc_stats(res, dns_resstatscounter_edns0fail);
} else if (message->rcode == dns_rcode_formerr) {
if (ISFORWARDER(query->addrinfo)) {
/*
@ -8174,13 +8177,13 @@ resquery_response(isc_task_t *task, isc_event_t *event) {
/*
* Is the server lame?
*/
if (fctx->res->lame_ttl != 0 && !ISFORWARDER(query->addrinfo) &&
if (res->lame_ttl != 0 && !ISFORWARDER(query->addrinfo) &&
is_lame(fctx)) {
inc_stats(fctx->res, dns_resstatscounter_lame);
inc_stats(res, dns_resstatscounter_lame);
log_lame(fctx, query->addrinfo);
result = dns_adb_marklame(fctx->adb, query->addrinfo,
&fctx->name, fctx->type,
now + fctx->res->lame_ttl);
now + res->lame_ttl);
if (result != ISC_R_SUCCESS)
isc_log_write(dns_lctx, DNS_LOGCATEGORY_RESOLVER,
DNS_LOGMODULE_RESOLVER, ISC_LOG_ERROR,
@ -8196,7 +8199,7 @@ resquery_response(isc_task_t *task, isc_event_t *event) {
* Enforce delegations only zones like NET and COM.
*/
if (!ISFORWARDER(query->addrinfo) &&
dns_view_isdelegationonly(fctx->res->view, &fctx->domain) &&
dns_view_isdelegationonly(res->view, &fctx->domain) &&
!dns_name_equal(&fctx->domain, &fctx->name) &&
fix_mustbedelegationornxdomain(message, fctx)) {
char namebuf[DNS_NAME_FORMATSIZE];
@ -8208,7 +8211,7 @@ resquery_response(isc_task_t *task, isc_event_t *event) {
dns_name_format(&fctx->name, namebuf, sizeof(namebuf));
dns_name_format(&fctx->domain, domainbuf, sizeof(domainbuf));
dns_rdatatype_format(fctx->type, typebuf, sizeof(typebuf));
dns_rdataclass_format(fctx->res->rdclass, classbuf,
dns_rdataclass_format(res->rdclass, classbuf,
sizeof(classbuf));
isc_sockaddr_format(&query->addrinfo->sockaddr, addrbuf,
sizeof(addrbuf));
@ -8220,7 +8223,7 @@ resquery_response(isc_task_t *task, isc_event_t *event) {
domainbuf, namebuf, typebuf, classbuf, addrbuf);
}
if ((fctx->res->options & DNS_RESOLVER_CHECKNAMES) != 0)
if ((res->options & DNS_RESOLVER_CHECKNAMES) != 0)
checknames(message);
/*
@ -8462,7 +8465,7 @@ resquery_response(isc_task_t *task, isc_event_t *event) {
name = &fctx->name;
else
name = &fctx->domain;
result = dns_view_findzonecut(fctx->res->view,
result = dns_view_findzonecut(res->view,
name, fname,
now, findoptions,
ISC_TRUE,
@ -8513,10 +8516,18 @@ resquery_response(isc_task_t *task, isc_event_t *event) {
* Resend (probably with changed options).
*/
FCTXTRACE("resend");
inc_stats(fctx->res, dns_resstatscounter_retry);
inc_stats(res, dns_resstatscounter_retry);
bucketnum = fctx->bucketnum;
fctx_increference(fctx);
result = fctx_query(fctx, addrinfo, options);
if (result != ISC_R_SUCCESS)
if (result != ISC_R_SUCCESS) {
fctx_done(fctx, result, __LINE__);
LOCK(&res->buckets[bucketnum].lock);
bucket_empty = fctx_decreference(fctx);
UNLOCK(&res->buckets[bucketnum].lock);
if (bucket_empty)
empty_bucket(res);
}
} else if (result == ISC_R_SUCCESS && !HAVE_ANSWER(fctx)) {
/*
* All has gone well so far, but we are waiting for the
@ -8543,7 +8554,7 @@ resquery_response(isc_task_t *task, isc_event_t *event) {
FCTXTRACE("suspending DS lookup to find parent's NS records");
result = dns_resolver_createfetch(fctx->res, &fctx->nsname,
result = dns_resolver_createfetch(res, &fctx->nsname,
dns_rdatatype_ns,
NULL, NULL, NULL,
fctx->options, task,