From: Mark Andrews Date: Mon, 8 Jan 2007 01:37:53 +0000 (+0000) Subject: 2126. [bug] Serialise validation of type ANY responses. [RT #16555] X-Git-Tag: v9.4.0rc2~14 X-Git-Url: http://git.ipfire.org/gitweb/?a=commitdiff_plain;h=9aefa7e50864004e6a99ae4a1754946261d3d290;p=thirdparty%2Fbind9.git 2126. [bug] Serialise validation of type ANY responses. [RT #16555] --- diff --git a/CHANGES b/CHANGES index 862679b6201..f78e19913f1 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,5 @@ +2126. [bug] Serialise validation of type ANY responses. [RT #16555] + 2125. [bug] dns_zone_getzeronosoattl() REQUIRE failure if DLZ was defined. [RT #16574] diff --git a/lib/dns/include/dns/validator.h b/lib/dns/include/dns/validator.h index a202b548a74..96d125f3854 100644 --- a/lib/dns/include/dns/validator.h +++ b/lib/dns/include/dns/validator.h @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: validator.h,v 1.27.18.6 2005/11/03 00:58:00 marka Exp $ */ +/* $Id: validator.h,v 1.27.18.7 2007/01/08 01:37:53 marka Exp $ */ #ifndef DNS_VALIDATOR_H #define DNS_VALIDATOR_H 1 @@ -144,6 +144,7 @@ struct dns_validator { * dns_validator_create() options. */ #define DNS_VALIDATOR_DLV 1U +#define DNS_VALIDATOR_DEFER 2U ISC_LANG_BEGINDECLS @@ -191,6 +192,15 @@ dns_validator_create(dns_view_t *view, dns_name_t *name, dns_rdatatype_t type, * the answer by looking for a appopriate DLV RRset. */ +void +dns_validator_send(dns_validator_t *validator); +/*%< + * Send a deferred validation request + * + * Requires: + * 'validator' to points to a valid DNSSEC validator. + */ + void dns_validator_cancel(dns_validator_t *validator); /*%< diff --git a/lib/dns/resolver.c b/lib/dns/resolver.c index cfaf24b06a2..7693878e716 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.54 2007/01/08 00:45:11 marka Exp $ */ +/* $Id: resolver.c,v 1.284.18.55 2007/01/08 01:37:53 marka Exp $ */ /*! \file */ @@ -387,6 +387,9 @@ valcreate(fetchctx_t *fctx, dns_adbaddrinfo_t *addrinfo, dns_name_t *name, valarg->fctx = fctx; valarg->addrinfo = addrinfo; + if (!ISC_LIST_EMPTY(fctx->validators)) + INSIST((valoptions & DNS_VALIDATOR_DEFER) != 0); + result = dns_validator_create(fctx->res->view, name, type, rdataset, sigrdataset, fctx->rmessage, valoptions, task, validated, valarg, @@ -1029,6 +1032,8 @@ fctx_query(fetchctx_t *fctx, dns_adbaddrinfo_t *addrinfo, if (result != ISC_R_SUCCESS) return (result); + INSIST(ISC_LIST_EMPTY(fctx->validators)); + dns_message_reset(fctx->rmessage, DNS_MESSAGE_INTENTPARSE); query = isc_mem_get(res->buckets[fctx->bucketnum].mctx, @@ -3290,13 +3295,21 @@ maybe_destroy(fetchctx_t *fctx) { unsigned int bucketnum; isc_boolean_t bucket_empty = ISC_FALSE; dns_resolver_t *res = fctx->res; + dns_validator_t *validator; REQUIRE(SHUTTINGDOWN(fctx)); - if (fctx->pending != 0 || fctx->nqueries != 0 || - !ISC_LIST_EMPTY(fctx->validators)) + if (fctx->pending != 0 || fctx->nqueries != 0) return; + for (validator = ISC_LIST_HEAD(fctx->validators); + validator != NULL; + validator = ISC_LIST_HEAD(fctx->validators)) { + ISC_LIST_UNLINK(fctx->validators, validator, link); + dns_validator_cancel(validator); + dns_validator_destroy(&validator); + } + bucketnum = fctx->bucketnum; LOCK(&res->buckets[bucketnum].lock); if (fctx->references == 0) @@ -3431,7 +3444,9 @@ validated(isc_task_t *task, isc_event_t *event) { add_bad(fctx, &addrinfo->sockaddr, result); isc_event_free(&event); UNLOCK(&fctx->res->buckets[fctx->bucketnum].lock); - if (sentresponse) + if (!ISC_LIST_EMPTY(fctx->validators)) + dns_validator_send(ISC_LIST_HEAD(fctx->validators)); + else if (sentresponse) fctx_done(fctx, result); /* Locks bucket. */ else fctx_try(fctx); /* Locks bucket. */ @@ -3530,6 +3545,7 @@ validated(isc_task_t *task, isc_event_t *event) { * be validated. */ UNLOCK(&fctx->res->buckets[fctx->bucketnum].lock); + dns_validator_send(ISC_LIST_HEAD(fctx->validators)); goto cleanup_event; } @@ -3842,6 +3858,13 @@ cache_name(fetchctx_t *fctx, dns_name_t *name, dns_adbaddrinfo_t *addrinfo, rdataset, sigrdataset, valoptions, task); + /* + * Defer any further validations. + * This prevents multiple validators + * from manipulating fctx->rmessage + * simultaniously. + */ + valoptions |= DNS_VALIDATOR_DEFER; } } else if (CHAINING(rdataset)) { if (rdataset->type == dns_rdatatype_cname) diff --git a/lib/dns/validator.c b/lib/dns/validator.c index 7a3229af16b..deeb07aa047 100644 --- a/lib/dns/validator.c +++ b/lib/dns/validator.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: validator.c,v 1.119.18.27 2006/12/07 06:50:34 marka Exp $ */ +/* $Id: validator.c,v 1.119.18.28 2007/01/08 01:37:53 marka Exp $ */ /*! \file */ @@ -2877,7 +2877,8 @@ dns_validator_create(dns_view_t *view, dns_name_t *name, dns_rdatatype_t type, ISC_LINK_INIT(val, link); val->magic = VALIDATOR_MAGIC; - isc_task_send(task, ISC_EVENT_PTR(&event)); + if ((options & DNS_VALIDATOR_DEFER) == 0) + isc_task_send(task, ISC_EVENT_PTR(&event)); *validatorp = val; @@ -2894,6 +2895,21 @@ dns_validator_create(dns_view_t *view, dns_name_t *name, dns_rdatatype_t type, return (result); } +void +dns_validator_send(dns_validator_t *validator) { + isc_event_t *event; + REQUIRE(VALID_VALIDATOR(validator)); + + LOCK(&validator->lock); + + INSIST((validator->options & DNS_VALIDATOR_DEFER) != 0); + event = (isc_event_t *)validator->event; + validator->options &= ~DNS_VALIDATOR_DEFER; + UNLOCK(&validator->lock); + + isc_task_send(validator->task, ISC_EVENT_PTR(&event)); +} + void dns_validator_cancel(dns_validator_t *validator) { REQUIRE(VALID_VALIDATOR(validator)); @@ -2908,6 +2924,12 @@ dns_validator_cancel(dns_validator_t *validator) { if (validator->subvalidator != NULL) dns_validator_cancel(validator->subvalidator); + if ((validator->options & DNS_VALIDATOR_DEFER) != 0) { + isc_task_t *task = validator->event->ev_sender; + validator->options &= ~DNS_VALIDATOR_DEFER; + isc_event_free((isc_event_t **)&validator->event); + isc_task_detach(&task); + } } UNLOCK(&validator->lock); }