#include <stdbool.h>
#include <isc/async.h>
+#include <isc/atomic.h>
#include <isc/base32.h>
#include <isc/counter.h>
#include <isc/helper.h>
VALATTR_MAXVALIDATIONS = 1 << 5, /*%< Max validations quota */
VALATTR_MAXVALIDATIONFAILS = 1 << 6, /*%< Max validation fails
quota */
+ VALATTR_OFFLOADED = 1 << 7, /*%< The ownership has been passed to
+ offloaded thread */
/*!
* NSEC proofs to be looked for.
#define FOUNDCLOSEST(val) ((val->attributes & VALATTR_FOUNDCLOSEST) != 0)
#define FOUNDOPTOUT(val) ((val->attributes & VALATTR_FOUNDOPTOUT) != 0)
-#define CANCELED(v) (((v)->attributes & VALATTR_CANCELED) != 0)
-#define COMPLETE(v) (((v)->attributes & VALATTR_COMPLETE) != 0)
+#define CANCELING(v) atomic_load(&(v)->canceling)
+#define CANCELED(v) (((v)->attributes & VALATTR_CANCELED) != 0)
+#define OFFLOADED(v) (((v)->attributes & VALATTR_OFFLOADED) != 0)
+#define COMPLETE(v) (((v)->attributes & VALATTR_COMPLETE) != 0)
#define NEGATIVE(r) (((r)->attributes & DNS_RDATASETATTR_NEGATIVE) != 0)
#define NXDOMAIN(r) (((r)->attributes & DNS_RDATASETATTR_NXDOMAIN) != 0)
validator_log(val, ISC_LOG_DEBUG(3), "in fetch_callback_dnskey");
dns_resolver_destroyfetch(&val->fetch);
- if (CANCELED(val)) {
+ if (CANCELED(val) || CANCELING(val)) {
result = ISC_R_CANCELED;
goto cleanup;
}
validator_log(val, ISC_LOG_DEBUG(3), "in fetch_callback_ds");
dns_resolver_destroyfetch(&val->fetch);
- if (CANCELED(val)) {
+ if (CANCELED(val) || CANCELING(val)) {
result = ISC_R_CANCELED;
goto cleanup;
}
val->subvalidator = NULL;
- if (CANCELED(val)) {
+ if (CANCELED(val) || CANCELING(val)) {
result = ISC_R_CANCELED;
goto cleanup;
}
val->subvalidator = NULL;
- if (CANCELED(val)) {
+ if (CANCELED(val) || CANCELING(val)) {
result = ISC_R_CANCELED;
goto cleanup;
}
val->subvalidator = NULL;
- if (CANCELED(val)) {
+ if (CANCELED(val) || CANCELING(val)) {
result = ISC_R_CANCELED;
goto cleanup;
}
val->subvalidator = NULL;
- if (CANCELED(val)) {
+ if (CANCELED(val) || CANCELING(val)) {
result = ISC_R_CANCELED;
goto cleanup;
}
static void
validate_answer_iter_done(dns_validator_t *val, isc_result_t result);
+static void
+validator_cancel_finish(dns_validator_t *validator);
+
static void
validate_answer_iter_start(dns_validator_t *val) {
isc_result_t result = ISC_R_SUCCESS;
* Caller must be holding the validator lock.
*/
- if (CANCELED(val)) {
+ val->attributes &= ~VALATTR_OFFLOADED;
+ if (CANCELING(val)) {
+ validator_cancel_finish(val);
result = ISC_R_CANCELED;
goto cleanup;
}
dns_validator_t *val = arg;
isc_result_t result;
- if (CANCELED(val)) {
+ val->attributes &= ~VALATTR_OFFLOADED;
+ if (CANCELING(val)) {
+ validator_cancel_finish(val);
result = ISC_R_CANCELED;
goto cleanup;
}
dns_validator_t *val = arg;
isc_result_t result = ISC_R_NOTFOUND;
- if (CANCELED(val)) {
+ if (CANCELED(val) || CANCELING(val)) {
val->result = ISC_R_CANCELED;
} else {
val->result = verify(val, val->key, &val->rdata,
validate_answer_signing_key_done(void *arg) {
dns_validator_t *val = arg;
- if (CANCELED(val)) {
+ val->attributes &= ~VALATTR_OFFLOADED;
+ if (CANCELING(val)) {
+ validator_cancel_finish(val);
val->result = ISC_R_CANCELED;
} else if (val->key != NULL) {
/* Process with next key if we selected one */
dns_validator_t *val = arg;
isc_result_t result;
- if (CANCELED(val)) {
+ val->attributes &= ~VALATTR_OFFLOADED;
+ if (CANCELING(val)) {
+ validator_cancel_finish(val);
result = ISC_R_CANCELED;
goto cleanup;
}
static void
resume_answer(void *arg) {
dns_validator_t *val = arg;
+
val->resume = true;
validate_answer_iter_start(val);
}
static isc_result_t
validate_helper_run(dns_validator_t *val, isc_job_cb cb) {
+ val->attributes |= VALATTR_OFFLOADED;
isc_helper_run(val->loop, cb, val);
return DNS_R_WAIT;
}
validate_dnskey_dsset_next(void *arg) {
dns_validator_t *val = arg;
- if (CANCELED(val)) {
+ if (CANCELED(val) || CANCELING(val)) {
val->result = ISC_R_CANCELED;
} else {
val->result = dns_rdataset_next(val->dsset);
dns_validator_t *val = arg;
isc_result_t result = val->result;
- if (CANCELED(val)) {
+ val->attributes &= ~VALATTR_OFFLOADED;
+ if (CANCELING(val)) {
+ validator_cancel_finish(val);
result = ISC_R_CANCELED;
}
validate_dnskey_dsset_first(dns_validator_t *val) {
isc_result_t result;
- if (CANCELED(val)) {
+ if (CANCELED(val) || CANCELING(val)) {
result = ISC_R_CANCELED;
} else {
result = dns_rdataset_first(val->dsset);
dns_keynode_t *keynode = NULL;
dns_rdata_ds_t ds;
- if (CANCELED(val)) {
+ if (CANCELED(val) || CANCELING(val)) {
result = ISC_R_CANCELED;
goto cleanup;
}
dns_validator_t *val = (dns_validator_t *)arg;
isc_result_t result = ISC_R_FAILURE;
- if (CANCELED(val)) {
+ if (CANCELED(val) || CANCELING(val)) {
result = ISC_R_CANCELED;
goto cleanup;
}
(void)validate_async_run(val, validator_start);
}
-void
-dns_validator_cancel(dns_validator_t *validator) {
- REQUIRE(VALID_VALIDATOR(validator));
- REQUIRE(validator->tid == isc_tid());
-
- validator_log(validator, ISC_LOG_DEBUG(3), "dns_validator_cancel");
+static void
+validator_cancel_finish(dns_validator_t *validator) {
+ validator_log(validator, ISC_LOG_DEBUG(3), "validator_cancel_finish");
- if (!CANCELED(validator)) {
+ if (CANCELING(validator) && !CANCELED(validator)) {
if (validator->fetch != NULL) {
dns_resolver_cancelfetch(validator->fetch);
}
}
}
+void
+dns_validator_cancel(dns_validator_t *validator) {
+ REQUIRE(VALID_VALIDATOR(validator));
+ REQUIRE(validator->tid == isc_tid());
+
+ validator_log(validator, ISC_LOG_DEBUG(3), "dns_validator_cancel");
+
+ atomic_store(&validator->canceling, true);
+
+ if (!OFFLOADED(validator)) {
+ validator_cancel_finish(validator);
+ }
+}
+
static void
destroy_validator(dns_validator_t *val) {
isc_mem_t *mctx = NULL;