* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: validator.h,v 1.18.12.11 2006/01/06 00:01:42 marka Exp $ */
+/* $Id: validator.h,v 1.18.12.11.6.1 2007/01/11 04:51:39 marka Exp $ */
#ifndef DNS_VALIDATOR_H
#define DNS_VALIDATOR_H 1
* dns_validator_create() options.
*/
#define DNS_VALIDATOR_DLV 1U
+#define DNS_VALIDATOR_DEFER 2U
ISC_LANG_BEGINDECLS
* 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);
/*%<
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: resolver.c,v 1.218.2.18.4.64 2006/08/31 03:57:11 marka Exp $ */
+/* $Id: resolver.c,v 1.218.2.18.4.64.4.1 2007/01/11 04:51:39 marka Exp $ */
#include <config.h>
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,
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->mctx, sizeof(*query));
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 || !ISC_LIST_EMPTY(fctx->validators))
+ if (fctx->pending != 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)
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. */
* be validated.
*/
UNLOCK(&fctx->res->buckets[fctx->bucketnum].lock);
+ dns_validator_send(ISC_LIST_HEAD(fctx->validators));
goto cleanup_event;
}
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)
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: validator.c,v 1.91.2.5.8.27 2006/02/26 23:03:52 marka Exp $ */
+/* $Id: validator.c,v 1.91.2.5.8.27.6.1 2007/01/11 04:51:39 marka Exp $ */
#include <config.h>
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;
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));
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);
}