diff --git a/lib/ns/include/ns/client.h b/lib/ns/include/ns/client.h index 67c641b7cc3de953ecaa81a89eadd72429a7182c..bf3d85db0047ac9eace8213e4542f9d041af98e3 100644 --- a/lib/ns/include/ns/client.h +++ b/lib/ns/include/ns/client.h @@ -174,7 +174,6 @@ struct ns_client { isc_nmhandle_t *sendhandle; /* Waiting for send callback */ isc_nmhandle_t *reqhandle; /* Waiting for request callback (query, update, notify) */ - isc_nmhandle_t *fetchhandle; /* Waiting for recursive fetch */ isc_nmhandle_t *updatehandle; /* Waiting for update callback */ unsigned char *tcpbuf; dns_message_t *message; diff --git a/lib/ns/include/ns/query.h b/lib/ns/include/ns/query.h index a2f77d35f0677e51f373e61cbb6ddc9c28e1fb49..18d1b5c9b604abc670fb6781482680842af8a937 100644 --- a/lib/ns/include/ns/query.h +++ b/lib/ns/include/ns/query.h @@ -43,8 +43,10 @@ typedef struct ns_dbversion { * allows common code paths to differentiate between them */ typedef enum { + RECTYPE_NORMAL, RECTYPE_PREFETCH, RECTYPE_RPZ, + RECTYPE_HOOK, RECTYPE_COUNT, } ns_query_rectype_t; @@ -52,19 +54,27 @@ typedef enum { * Helper macros for accessing isc_nmhandle_t pointers for a specific recursion * a given client is associated with. */ +#define HANDLE_RECTYPE_NORMAL(client) \ + ((client)->query.recursions[RECTYPE_NORMAL].handle) #define HANDLE_RECTYPE_PREFETCH(client) \ ((client)->query.recursions[RECTYPE_PREFETCH].handle) #define HANDLE_RECTYPE_RPZ(client) \ ((client)->query.recursions[RECTYPE_RPZ].handle) +#define HANDLE_RECTYPE_HOOK(client) \ + ((client)->query.recursions[RECTYPE_HOOK].handle) /*% * Helper macros for accessing dns_fetch_t pointers for a specific recursion a * given client is associated with. */ +#define FETCH_RECTYPE_NORMAL(client) \ + ((client)->query.recursions[RECTYPE_NORMAL].fetch) #define FETCH_RECTYPE_PREFETCH(client) \ ((client)->query.recursions[RECTYPE_PREFETCH].fetch) #define FETCH_RECTYPE_RPZ(client) \ ((client)->query.recursions[RECTYPE_RPZ].fetch) +#define FETCH_RECTYPE_HOOK(client) \ + ((client)->query.recursions[RECTYPE_HOOK].fetch) /*% * nameserver recursion parameters, to uniquely identify a recursion @@ -94,7 +104,6 @@ struct ns_query { bool authdbset; bool isreferral; isc_mutex_t fetchlock; - dns_fetch_t *fetch; ns_hookasync_t *hookactx; dns_rpz_st_t *rpz_st; isc_bufferlist_t namebufs; diff --git a/lib/ns/query.c b/lib/ns/query.c index 0696eb35a272abc3a9d1aee7424b4fca9b221a8b..0504bb021c0156e1c1c0f5a1e5ac230392398029 100644 --- a/lib/ns/query.c +++ b/lib/ns/query.c @@ -660,10 +660,12 @@ ns_query_cancel(ns_client_t *client) { REQUIRE(NS_CLIENT_VALID(client)); LOCK(&client->query.fetchlock); - if (client->query.fetch != NULL) { - dns_resolver_cancelfetch(client->query.fetch); - - client->query.fetch = NULL; + for (int i = 0; i < RECTYPE_COUNT; i++) { + dns_fetch_t **fetchp = &client->query.recursions[i].fetch; + if (*fetchp != NULL) { + dns_resolver_cancelfetch(*fetchp); + *fetchp = NULL; + } } if (client->query.hookactx != NULL) { client->query.hookactx->cancel(client->query.hookactx); @@ -5961,9 +5963,11 @@ query_lookup(query_ctx_t *qctx) { qctx->client->query.dboptions &= ~DNS_DBFIND_STALETIMEOUT; qctx->options &= ~DNS_GETDB_STALEFIRST; - if (qctx->client->query.fetch != NULL) { + if (FETCH_RECTYPE_NORMAL(qctx->client) != NULL) + { dns_resolver_destroyfetch( - &qctx->client->query.fetch); + &FETCH_RECTYPE_NORMAL( + qctx->client)); } return (query_lookup(qctx)); } else { @@ -6163,22 +6167,22 @@ fetch_callback(isc_task_t *task, isc_event_t *event) { client->nodetach = false; LOCK(&client->query.fetchlock); - INSIST(client->query.fetch == devent->fetch || - client->query.fetch == NULL); + INSIST(FETCH_RECTYPE_NORMAL(client) == devent->fetch || + FETCH_RECTYPE_NORMAL(client) == NULL); if (QUERY_STALEPENDING(&client->query)) { /* * We've gotten an authoritative answer to a query that * was left pending after a stale timeout. We don't need * to do anything with it; free all the data and go home. */ - client->query.fetch = NULL; + FETCH_RECTYPE_NORMAL(client) = NULL; fetch_answered = true; - } else if (client->query.fetch != NULL) { + } else if (FETCH_RECTYPE_NORMAL(client) != NULL) { /* * This is the fetch we've been waiting for. */ - INSIST(devent->fetch == client->query.fetch); - client->query.fetch = NULL; + INSIST(FETCH_RECTYPE_NORMAL(client) == devent->fetch); + FETCH_RECTYPE_NORMAL(client) = NULL; /* * Update client->now. @@ -6208,7 +6212,7 @@ fetch_callback(isc_task_t *task, isc_event_t *event) { } UNLOCK(&client->manager->reclock); - isc_nmhandle_detach(&client->fetchhandle); + isc_nmhandle_detach(&HANDLE_RECTYPE_NORMAL(client)); client->query.attributes &= ~NS_QUERYATTR_RECURSING; client->state = NS_CLIENTSTATE_WORKING; @@ -6419,7 +6423,7 @@ ns_query_recurse(ns_client_t *client, dns_rdatatype_t qtype, dns_name_t *qname, * Invoke the resolver. */ REQUIRE(nameservers == NULL || nameservers->type == dns_rdatatype_ns); - REQUIRE(client->query.fetch == NULL); + REQUIRE(FETCH_RECTYPE_NORMAL(client) == NULL); rdataset = ns_client_newrdataset(client); @@ -6444,14 +6448,14 @@ ns_query_recurse(ns_client_t *client, dns_rdatatype_t qtype, dns_name_t *qname, client->query.fetchoptions |= DNS_FETCHOPT_TRYSTALE_ONTIMEOUT; } - isc_nmhandle_attach(client->handle, &client->fetchhandle); + isc_nmhandle_attach(client->handle, &HANDLE_RECTYPE_NORMAL(client)); result = dns_resolver_createfetch( client->view->resolver, qname, qtype, qdomain, nameservers, NULL, peeraddr, client->message->id, client->query.fetchoptions, 0, NULL, client->manager->task, fetch_callback, client, - rdataset, sigrdataset, &client->query.fetch); + rdataset, sigrdataset, &FETCH_RECTYPE_NORMAL(client)); if (result != ISC_R_SUCCESS) { - isc_nmhandle_detach(&client->fetchhandle); + isc_nmhandle_detach(&HANDLE_RECTYPE_NORMAL(client)); ns_client_putrdataset(client, &rdataset); if (sigrdataset != NULL) { ns_client_putrdataset(client, &sigrdataset); @@ -6692,12 +6696,11 @@ query_hookresume(isc_task_t *task, isc_event_t *event) { UNLOCK(&client->manager->reclock); /* - * This event is running under a client task, so it's safe to detach - * the fetch handle. And it should be done before resuming query - * processing below, since that may trigger another recursion or - * asynchronous hook event. + * The fetch handle should be detached before resuming query processing + * below, since that may trigger another recursion or asynchronous hook + * event. */ - isc_nmhandle_detach(&client->fetchhandle); + isc_nmhandle_detach(&HANDLE_RECTYPE_HOOK(client)); client->state = NS_CLIENTSTATE_WORKING; @@ -6813,7 +6816,7 @@ ns_query_hookasync(query_ctx_t *qctx, ns_query_starthookasync_t runasync, REQUIRE(NS_CLIENT_VALID(client)); REQUIRE(client->query.hookactx == NULL); - REQUIRE(client->query.fetch == NULL); + REQUIRE(FETCH_RECTYPE_NORMAL(client) == NULL); result = check_recursionquota(client); if (result != ISC_R_SUCCESS) { @@ -6836,12 +6839,11 @@ ns_query_hookasync(query_ctx_t *qctx, ns_query_starthookasync_t runasync, * attribute won't be checked anywhere. * * Hook-based asynchronous processing cannot coincide with normal - * recursion, so we can safely use fetchhandle here. Unlike in - * ns_query_recurse(), we attach to the handle only if 'runasync' - * succeeds. It should be safe since we're either in the client - * task or pausing it. + * recursion. Unlike in ns_query_recurse(), we attach to the handle + * only if 'runasync' succeeds. It should be safe since we're either in + * the client task or pausing it. */ - isc_nmhandle_attach(client->handle, &client->fetchhandle); + isc_nmhandle_attach(client->handle, &HANDLE_RECTYPE_HOOK(client)); return (ISC_R_SUCCESS); cleanup: @@ -7495,8 +7497,9 @@ query_usestale(query_ctx_t *qctx, isc_result_t result) { dns_db_attach(qctx->client->view->cachedb, &qctx->db); qctx->version = NULL; qctx->client->query.dboptions |= DNS_DBFIND_STALEOK; - if (qctx->client->query.fetch != NULL) { - dns_resolver_destroyfetch(&qctx->client->query.fetch); + if (FETCH_RECTYPE_NORMAL(qctx->client) != NULL) { + dns_resolver_destroyfetch( + &FETCH_RECTYPE_NORMAL(qctx->client)); } /* diff --git a/tests/ns/query_test.c b/tests/ns/query_test.c index dda2c07150dd3d68d4db9bbcb4a5fdae580a9b08..5636801b142b96d9c5afb67690434f7e814762e5 100644 --- a/tests/ns/query_test.c +++ b/tests/ns/query_test.c @@ -709,11 +709,11 @@ hook_async_common(void *arg, void *data, isc_result_t *resultp, } } else { /* - * Resume from the completion of async event. - * fetchhandle should have been detached so that we can start - * another async event or DNS recursive resolution. + * Resume from the completion of async event. The fetch handle + * should have been detached so that we can start another async + * event or DNS recursive resolution. */ - INSIST(qctx->client->fetchhandle == NULL); + INSIST(HANDLE_RECTYPE_HOOK(qctx->client) == NULL); asdata->async = false; switch (hookpoint) { case NS_QUERY_GOT_ANSWER_BEGIN: