#include <stdint.h>
#include <string.h>
+#include <isc/async.h>
#include <isc/hex.h>
#include <isc/mem.h>
#include <isc/once.h>
static void
qctx_destroy(query_ctx_t *qctx);
-static isc_result_t
+static void
query_setup(ns_client_t *client, dns_rdatatype_t qtype);
static isc_result_t
* ns__query_start() again with the same query context. Resuming from
* recursion is handled by query_resume().
*/
-static isc_result_t
+static void
query_setup(ns_client_t *client, dns_rdatatype_t qtype) {
isc_result_t result = ISC_R_UNSET;
query_ctx_t qctx;
*/
result = ns__query_sfcache(&qctx);
if (result != ISC_R_COMPLETE) {
- qctx_destroy(&qctx);
- return (result);
+ goto cleanup;
}
- result = ns__query_start(&qctx);
+ (void)ns__query_start(&qctx);
cleanup:
qctx_destroy(&qctx);
- return (result);
}
static bool
return (result);
}
+static void
+async_restart(void *arg) {
+ query_ctx_t *qctx = arg;
+ ns_client_t *client = qctx->client;
+
+ ns__query_start(qctx);
+
+ qctx_clean(qctx);
+ qctx_freedata(qctx);
+ qctx_destroy(qctx);
+ isc_mem_put(client->manager->mctx, qctx, sizeof(*qctx));
+}
+
/*
* Allocate buffers in 'qctx' used to store query results.
*
} else {
switch (rev->hookpoint) {
case NS_QUERY_SETUP:
- (void)query_setup(client, qctx->qtype);
+ query_setup(client, qctx->qtype);
break;
case NS_QUERY_START_BEGIN:
(void)ns__query_start(qctx);
result = query_zerottl_refetch(qctx);
if (result != ISC_R_COMPLETE) {
- return (result);
+ goto cleanup;
}
/*
result = dns_rdataset_first(trdataset);
if (result != ISC_R_SUCCESS) {
dns_message_puttempname(qctx->client->message, &tname);
- return (ns_query_done(qctx));
+ (void)ns_query_done(qctx);
+ goto cleanup;
}
dns_rdataset_current(trdataset, &rdata);
result = dns_rdataset_first(trdataset);
if (result != ISC_R_SUCCESS) {
dns_message_puttempname(qctx->client->message, &tname);
- return (ns_query_done(qctx));
+ (void)ns_query_done(qctx);
+ goto cleanup;
}
dns_rdataset_current(trdataset, &rdata);
qctx->client->message->rcode = dns_rcode_yxdomain;
}
if (result != ISC_R_SUCCESS) {
- return (ns_query_done(qctx));
+ (void)ns_query_done(qctx);
+ goto cleanup;
}
ns_client_keepname(qctx->client, qctx->fname, qctx->dbuf);
result = query_zerottl_refetch(qctx);
if (result != ISC_R_COMPLETE) {
- return (result);
+ goto cleanup;
}
return (query_respond(qctx));
* Do we need to restart the query (e.g. for CNAME chaining)?
*/
if (qctx->want_restart && qctx->client->query.restarts < MAX_RESTARTS) {
+ query_ctx_t *saved_qctx = NULL;
qctx->client->query.restarts++;
- return (ns__query_start(qctx));
+ saved_qctx = isc_mem_get(qctx->client->manager->mctx,
+ sizeof(*saved_qctx));
+ qctx_save(qctx, saved_qctx);
+ isc_async_run(qctx->client->manager->loop, async_restart,
+ saved_qctx);
+ return (DNS_R_CONTINUE);
}
if (qctx->result != ISC_R_SUCCESS &&
message->flags |= DNS_MESSAGEFLAG_AD;
}
- (void)query_setup(client, qtype);
+ query_setup(client, qtype);
}