mirror of
https://gitlab.isc.org/isc-projects/bind9
synced 2025-08-31 22:45:39 +00:00
Merge branch '3168-3-separate-all-recursions' into 'main'
[3/5] Separate all recursions See merge request isc-projects/bind9!5884
This commit is contained in:
@@ -174,7 +174,6 @@ struct ns_client {
|
|||||||
isc_nmhandle_t *sendhandle; /* Waiting for send callback */
|
isc_nmhandle_t *sendhandle; /* Waiting for send callback */
|
||||||
isc_nmhandle_t *reqhandle; /* Waiting for request callback
|
isc_nmhandle_t *reqhandle; /* Waiting for request callback
|
||||||
(query, update, notify) */
|
(query, update, notify) */
|
||||||
isc_nmhandle_t *fetchhandle; /* Waiting for recursive fetch */
|
|
||||||
isc_nmhandle_t *updatehandle; /* Waiting for update callback */
|
isc_nmhandle_t *updatehandle; /* Waiting for update callback */
|
||||||
unsigned char *tcpbuf;
|
unsigned char *tcpbuf;
|
||||||
dns_message_t *message;
|
dns_message_t *message;
|
||||||
|
@@ -43,8 +43,10 @@ typedef struct ns_dbversion {
|
|||||||
* allows common code paths to differentiate between them
|
* allows common code paths to differentiate between them
|
||||||
*/
|
*/
|
||||||
typedef enum {
|
typedef enum {
|
||||||
|
RECTYPE_NORMAL,
|
||||||
RECTYPE_PREFETCH,
|
RECTYPE_PREFETCH,
|
||||||
RECTYPE_RPZ,
|
RECTYPE_RPZ,
|
||||||
|
RECTYPE_HOOK,
|
||||||
RECTYPE_COUNT,
|
RECTYPE_COUNT,
|
||||||
} ns_query_rectype_t;
|
} ns_query_rectype_t;
|
||||||
|
|
||||||
@@ -52,19 +54,27 @@ typedef enum {
|
|||||||
* Helper macros for accessing isc_nmhandle_t pointers for a specific recursion
|
* Helper macros for accessing isc_nmhandle_t pointers for a specific recursion
|
||||||
* a given client is associated with.
|
* a given client is associated with.
|
||||||
*/
|
*/
|
||||||
|
#define HANDLE_RECTYPE_NORMAL(client) \
|
||||||
|
((client)->query.recursions[RECTYPE_NORMAL].handle)
|
||||||
#define HANDLE_RECTYPE_PREFETCH(client) \
|
#define HANDLE_RECTYPE_PREFETCH(client) \
|
||||||
((client)->query.recursions[RECTYPE_PREFETCH].handle)
|
((client)->query.recursions[RECTYPE_PREFETCH].handle)
|
||||||
#define HANDLE_RECTYPE_RPZ(client) \
|
#define HANDLE_RECTYPE_RPZ(client) \
|
||||||
((client)->query.recursions[RECTYPE_RPZ].handle)
|
((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
|
* Helper macros for accessing dns_fetch_t pointers for a specific recursion a
|
||||||
* given client is associated with.
|
* given client is associated with.
|
||||||
*/
|
*/
|
||||||
|
#define FETCH_RECTYPE_NORMAL(client) \
|
||||||
|
((client)->query.recursions[RECTYPE_NORMAL].fetch)
|
||||||
#define FETCH_RECTYPE_PREFETCH(client) \
|
#define FETCH_RECTYPE_PREFETCH(client) \
|
||||||
((client)->query.recursions[RECTYPE_PREFETCH].fetch)
|
((client)->query.recursions[RECTYPE_PREFETCH].fetch)
|
||||||
#define FETCH_RECTYPE_RPZ(client) \
|
#define FETCH_RECTYPE_RPZ(client) \
|
||||||
((client)->query.recursions[RECTYPE_RPZ].fetch)
|
((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
|
* nameserver recursion parameters, to uniquely identify a recursion
|
||||||
@@ -94,7 +104,6 @@ struct ns_query {
|
|||||||
bool authdbset;
|
bool authdbset;
|
||||||
bool isreferral;
|
bool isreferral;
|
||||||
isc_mutex_t fetchlock;
|
isc_mutex_t fetchlock;
|
||||||
dns_fetch_t *fetch;
|
|
||||||
ns_hookasync_t *hookactx;
|
ns_hookasync_t *hookactx;
|
||||||
dns_rpz_st_t *rpz_st;
|
dns_rpz_st_t *rpz_st;
|
||||||
isc_bufferlist_t namebufs;
|
isc_bufferlist_t namebufs;
|
||||||
|
@@ -660,10 +660,12 @@ ns_query_cancel(ns_client_t *client) {
|
|||||||
REQUIRE(NS_CLIENT_VALID(client));
|
REQUIRE(NS_CLIENT_VALID(client));
|
||||||
|
|
||||||
LOCK(&client->query.fetchlock);
|
LOCK(&client->query.fetchlock);
|
||||||
if (client->query.fetch != NULL) {
|
for (int i = 0; i < RECTYPE_COUNT; i++) {
|
||||||
dns_resolver_cancelfetch(client->query.fetch);
|
dns_fetch_t **fetchp = &client->query.recursions[i].fetch;
|
||||||
|
if (*fetchp != NULL) {
|
||||||
client->query.fetch = NULL;
|
dns_resolver_cancelfetch(*fetchp);
|
||||||
|
*fetchp = NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (client->query.hookactx != NULL) {
|
if (client->query.hookactx != NULL) {
|
||||||
client->query.hookactx->cancel(client->query.hookactx);
|
client->query.hookactx->cancel(client->query.hookactx);
|
||||||
@@ -5961,9 +5963,11 @@ query_lookup(query_ctx_t *qctx) {
|
|||||||
qctx->client->query.dboptions &=
|
qctx->client->query.dboptions &=
|
||||||
~DNS_DBFIND_STALETIMEOUT;
|
~DNS_DBFIND_STALETIMEOUT;
|
||||||
qctx->options &= ~DNS_GETDB_STALEFIRST;
|
qctx->options &= ~DNS_GETDB_STALEFIRST;
|
||||||
if (qctx->client->query.fetch != NULL) {
|
if (FETCH_RECTYPE_NORMAL(qctx->client) != NULL)
|
||||||
|
{
|
||||||
dns_resolver_destroyfetch(
|
dns_resolver_destroyfetch(
|
||||||
&qctx->client->query.fetch);
|
&FETCH_RECTYPE_NORMAL(
|
||||||
|
qctx->client));
|
||||||
}
|
}
|
||||||
return (query_lookup(qctx));
|
return (query_lookup(qctx));
|
||||||
} else {
|
} else {
|
||||||
@@ -6163,22 +6167,22 @@ fetch_callback(isc_task_t *task, isc_event_t *event) {
|
|||||||
client->nodetach = false;
|
client->nodetach = false;
|
||||||
|
|
||||||
LOCK(&client->query.fetchlock);
|
LOCK(&client->query.fetchlock);
|
||||||
INSIST(client->query.fetch == devent->fetch ||
|
INSIST(FETCH_RECTYPE_NORMAL(client) == devent->fetch ||
|
||||||
client->query.fetch == NULL);
|
FETCH_RECTYPE_NORMAL(client) == NULL);
|
||||||
if (QUERY_STALEPENDING(&client->query)) {
|
if (QUERY_STALEPENDING(&client->query)) {
|
||||||
/*
|
/*
|
||||||
* We've gotten an authoritative answer to a query that
|
* We've gotten an authoritative answer to a query that
|
||||||
* was left pending after a stale timeout. We don't need
|
* was left pending after a stale timeout. We don't need
|
||||||
* to do anything with it; free all the data and go home.
|
* to do anything with it; free all the data and go home.
|
||||||
*/
|
*/
|
||||||
client->query.fetch = NULL;
|
FETCH_RECTYPE_NORMAL(client) = NULL;
|
||||||
fetch_answered = true;
|
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.
|
* This is the fetch we've been waiting for.
|
||||||
*/
|
*/
|
||||||
INSIST(devent->fetch == client->query.fetch);
|
INSIST(FETCH_RECTYPE_NORMAL(client) == devent->fetch);
|
||||||
client->query.fetch = NULL;
|
FETCH_RECTYPE_NORMAL(client) = NULL;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Update client->now.
|
* Update client->now.
|
||||||
@@ -6208,7 +6212,7 @@ fetch_callback(isc_task_t *task, isc_event_t *event) {
|
|||||||
}
|
}
|
||||||
UNLOCK(&client->manager->reclock);
|
UNLOCK(&client->manager->reclock);
|
||||||
|
|
||||||
isc_nmhandle_detach(&client->fetchhandle);
|
isc_nmhandle_detach(&HANDLE_RECTYPE_NORMAL(client));
|
||||||
|
|
||||||
client->query.attributes &= ~NS_QUERYATTR_RECURSING;
|
client->query.attributes &= ~NS_QUERYATTR_RECURSING;
|
||||||
client->state = NS_CLIENTSTATE_WORKING;
|
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.
|
* Invoke the resolver.
|
||||||
*/
|
*/
|
||||||
REQUIRE(nameservers == NULL || nameservers->type == dns_rdatatype_ns);
|
REQUIRE(nameservers == NULL || nameservers->type == dns_rdatatype_ns);
|
||||||
REQUIRE(client->query.fetch == NULL);
|
REQUIRE(FETCH_RECTYPE_NORMAL(client) == NULL);
|
||||||
|
|
||||||
rdataset = ns_client_newrdataset(client);
|
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;
|
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(
|
result = dns_resolver_createfetch(
|
||||||
client->view->resolver, qname, qtype, qdomain, nameservers,
|
client->view->resolver, qname, qtype, qdomain, nameservers,
|
||||||
NULL, peeraddr, client->message->id, client->query.fetchoptions,
|
NULL, peeraddr, client->message->id, client->query.fetchoptions,
|
||||||
0, NULL, client->manager->task, fetch_callback, client,
|
0, NULL, client->manager->task, fetch_callback, client,
|
||||||
rdataset, sigrdataset, &client->query.fetch);
|
rdataset, sigrdataset, &FETCH_RECTYPE_NORMAL(client));
|
||||||
if (result != ISC_R_SUCCESS) {
|
if (result != ISC_R_SUCCESS) {
|
||||||
isc_nmhandle_detach(&client->fetchhandle);
|
isc_nmhandle_detach(&HANDLE_RECTYPE_NORMAL(client));
|
||||||
ns_client_putrdataset(client, &rdataset);
|
ns_client_putrdataset(client, &rdataset);
|
||||||
if (sigrdataset != NULL) {
|
if (sigrdataset != NULL) {
|
||||||
ns_client_putrdataset(client, &sigrdataset);
|
ns_client_putrdataset(client, &sigrdataset);
|
||||||
@@ -6692,12 +6696,11 @@ query_hookresume(isc_task_t *task, isc_event_t *event) {
|
|||||||
UNLOCK(&client->manager->reclock);
|
UNLOCK(&client->manager->reclock);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This event is running under a client task, so it's safe to detach
|
* The fetch handle should be detached before resuming query processing
|
||||||
* the fetch handle. And it should be done before resuming query
|
* below, since that may trigger another recursion or asynchronous hook
|
||||||
* processing below, since that may trigger another recursion or
|
* event.
|
||||||
* asynchronous hook event.
|
|
||||||
*/
|
*/
|
||||||
isc_nmhandle_detach(&client->fetchhandle);
|
isc_nmhandle_detach(&HANDLE_RECTYPE_HOOK(client));
|
||||||
|
|
||||||
client->state = NS_CLIENTSTATE_WORKING;
|
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(NS_CLIENT_VALID(client));
|
||||||
REQUIRE(client->query.hookactx == NULL);
|
REQUIRE(client->query.hookactx == NULL);
|
||||||
REQUIRE(client->query.fetch == NULL);
|
REQUIRE(FETCH_RECTYPE_NORMAL(client) == NULL);
|
||||||
|
|
||||||
result = check_recursionquota(client);
|
result = check_recursionquota(client);
|
||||||
if (result != ISC_R_SUCCESS) {
|
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.
|
* attribute won't be checked anywhere.
|
||||||
*
|
*
|
||||||
* Hook-based asynchronous processing cannot coincide with normal
|
* Hook-based asynchronous processing cannot coincide with normal
|
||||||
* recursion, so we can safely use fetchhandle here. Unlike in
|
* recursion. Unlike in ns_query_recurse(), we attach to the handle
|
||||||
* ns_query_recurse(), we attach to the handle only if 'runasync'
|
* only if 'runasync' succeeds. It should be safe since we're either in
|
||||||
* succeeds. It should be safe since we're either in the client
|
* the client task or pausing it.
|
||||||
* task or pausing it.
|
|
||||||
*/
|
*/
|
||||||
isc_nmhandle_attach(client->handle, &client->fetchhandle);
|
isc_nmhandle_attach(client->handle, &HANDLE_RECTYPE_HOOK(client));
|
||||||
return (ISC_R_SUCCESS);
|
return (ISC_R_SUCCESS);
|
||||||
|
|
||||||
cleanup:
|
cleanup:
|
||||||
@@ -7495,8 +7497,9 @@ query_usestale(query_ctx_t *qctx, isc_result_t result) {
|
|||||||
dns_db_attach(qctx->client->view->cachedb, &qctx->db);
|
dns_db_attach(qctx->client->view->cachedb, &qctx->db);
|
||||||
qctx->version = NULL;
|
qctx->version = NULL;
|
||||||
qctx->client->query.dboptions |= DNS_DBFIND_STALEOK;
|
qctx->client->query.dboptions |= DNS_DBFIND_STALEOK;
|
||||||
if (qctx->client->query.fetch != NULL) {
|
if (FETCH_RECTYPE_NORMAL(qctx->client) != NULL) {
|
||||||
dns_resolver_destroyfetch(&qctx->client->query.fetch);
|
dns_resolver_destroyfetch(
|
||||||
|
&FETCH_RECTYPE_NORMAL(qctx->client));
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@@ -709,11 +709,11 @@ hook_async_common(void *arg, void *data, isc_result_t *resultp,
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
/*
|
/*
|
||||||
* Resume from the completion of async event.
|
* Resume from the completion of async event. The fetch handle
|
||||||
* fetchhandle should have been detached so that we can start
|
* should have been detached so that we can start another async
|
||||||
* another async event or DNS recursive resolution.
|
* event or DNS recursive resolution.
|
||||||
*/
|
*/
|
||||||
INSIST(qctx->client->fetchhandle == NULL);
|
INSIST(HANDLE_RECTYPE_HOOK(qctx->client) == NULL);
|
||||||
asdata->async = false;
|
asdata->async = false;
|
||||||
switch (hookpoint) {
|
switch (hookpoint) {
|
||||||
case NS_QUERY_GOT_ANSWER_BEGIN:
|
case NS_QUERY_GOT_ANSWER_BEGIN:
|
||||||
|
Reference in New Issue
Block a user