]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
use entirely local persistent data in modules
authorEvan Hunt <each@isc.org>
Wed, 19 Sep 2018 23:25:50 +0000 (16:25 -0700)
committerEvan Hunt <each@isc.org>
Thu, 6 Dec 2018 18:29:12 +0000 (10:29 -0800)
- eliminate qctx->hookdata and client->hookflags.
- use a memory pool to allocate data blobs in the filter-aaaa module,
  and associate them with the client address in a hash table
- instead of detaching the client in query_done(), mark it for deletion
  and then call ns_client_detach() from qctx_destroy(); this ensures
  that it will still exist when the QCTX_DESTROYED hook point is
  reached.

bin/hooks/filter-aaaa.c
bin/named/server.c
lib/ns/client.c
lib/ns/hooks.c
lib/ns/include/ns/client.h
lib/ns/include/ns/hooks.h
lib/ns/include/ns/query.h
lib/ns/query.c

index e70c6c2bb961cf9e6de2ef5105869e9e68c8454a..ff4218a18b963f70e5fc32236f4afe6f5a1d7d0e 100644 (file)
@@ -19,6 +19,7 @@
 
 #include <isc/buffer.h>
 #include <isc/hash.h>
+#include <isc/ht.h>
 #include <isc/lib.h>
 #include <isc/log.h>
 #include <isc/mem.h>
        } while (0)
 
 /*
- * Set up in the register function.
+ * Possible values for the settings of filter-aaaa-on-v4 and
+ * filter-aaaa-on-v6: "no" is NONE, "yes" is FILTER, "break-dnssec"
+ * is BREAK_DNSSEC.
+ */
+typedef enum {
+       NONE = 0,
+       FILTER = 1,
+       BREAK_DNSSEC = 2
+} filter_aaaa_t;
+
+/*
+ * Persistent data for use by this module. This will be associated
+ * with client object address in the hash table, and will remain
+ * accessible until the client object is detached.
  */
-static int module_id;
+typedef struct filter_data {
+       filter_aaaa_t mode;
+       uint32_t flags;
+} filter_data_t;
 
 /*
- * Hook data pool.
+ * Memory pool for use with persistent data.
  */
 static isc_mempool_t *datapool = NULL;
 
+/*
+ * Hash table associating a client object with its persistent data.
+ */
+static isc_ht_t *client_ht = NULL;
+
 /*
  * Per-client flags set by this module
  */
@@ -82,56 +104,51 @@ static isc_mempool_t *datapool = NULL;
  * be added to a hook table when this module is registered.
  */
 static bool
-filter_qctx_initialize(void *hookdata, void *cbdata, isc_result_t *resp);
+filter_qctx_initialize(void *arg, void *cbdata, isc_result_t *resp);
 static ns_hook_t filter_init = {
        .action = filter_qctx_initialize,
+       .action_data = &client_ht,
 };
 
 static bool
-filter_respond_begin(void *hookdata, void *cbdata, isc_result_t *resp);
+filter_respond_begin(void *arg, void *cbdata, isc_result_t *resp);
 static ns_hook_t filter_respbegin = {
        .action = filter_respond_begin,
+       .action_data = &client_ht,
 };
 
 static bool
-filter_respond_any_found(void *hookdata, void *cbdata, isc_result_t *resp);
+filter_respond_any_found(void *arg, void *cbdata, isc_result_t *resp);
 static ns_hook_t filter_respanyfound = {
        .action = filter_respond_any_found,
+       .action_data = &client_ht,
 };
 
 static bool
-filter_prep_response_begin(void *hookdata, void *cbdata, isc_result_t *resp);
+filter_prep_response_begin(void *arg, void *cbdata, isc_result_t *resp);
 static ns_hook_t filter_prepresp = {
        .action = filter_prep_response_begin,
+       .action_data = &client_ht,
 };
 
 static bool
-filter_query_done_send(void *hookdata, void *cbdata, isc_result_t *resp);
+filter_query_done_send(void *arg, void *cbdata, isc_result_t *resp);
 static ns_hook_t filter_donesend = {
        .action = filter_query_done_send,
+       .action_data = &client_ht,
 };
 
 static bool
-filter_qctx_destroy(void *hookdata, void *cbdata, isc_result_t *resp);
+filter_qctx_destroy(void *arg, void *cbdata, isc_result_t *resp);
 ns_hook_t filter_destroy = {
        .action = filter_qctx_destroy,
+       .action_data = &client_ht,
 };
 
 /**
  ** Support for parsing of parameters and configuration of the module.
  **/
 
-/*
- * Possible values for the settings of filter-aaaa-on-v4 and
- * filter-aaaa-on-v6: "no" is NONE, "yes" is FILTER, "break-dnssec"
- * is BREAK_DNSSEC.
- */
-typedef enum {
-       NONE = 0,
-       FILTER = 1,
-       BREAK_DNSSEC = 2
-} filter_aaaa_t;
-
 /*
  * Values configured when the module is loaded.
  */
@@ -256,7 +273,7 @@ parse_parameters(const char *parameters, const void *cfg,
  * a hook table.
  */
 isc_result_t
-hook_register(const unsigned int modid, const char *parameters,
+hook_register(const char *parameters,
              const char *cfg_file, unsigned long cfg_line,
              const void *cfg, void *actx,
              ns_hookctx_t *hctx, ns_hooktable_t *hooktable, void **instp)
@@ -265,8 +282,6 @@ hook_register(const unsigned int modid, const char *parameters,
 
        UNUSED(instp);
 
-       module_id = modid;
-
        isc_log_write(hctx->lctx, NS_LOGCATEGORY_GENERAL,
                      NS_LOGMODULE_HOOKS, ISC_LOG_INFO,
                      "loading 'filter-aaaa' "
@@ -285,9 +300,11 @@ hook_register(const unsigned int modid, const char *parameters,
        ns_hook_add(hooktable, NS_QUERY_DONE_SEND, &filter_donesend);
        ns_hook_add(hooktable, NS_QUERY_QCTX_DESTROYED, &filter_destroy);
 
-       CHECK(isc_mempool_create(hctx->mctx, sizeof(filter_aaaa_t),
+       CHECK(isc_mempool_create(hctx->mctx, sizeof(filter_data_t),
                                 &datapool));
 
+       CHECK(isc_ht_init(&client_ht, hctx->mctx, 16));
+
        /*
         * Fill the mempool with 1K filter_aaaa state objects at
         * a time; ideally after a single allocation, the mempool will
@@ -318,6 +335,9 @@ void
 hook_destroy(void **instp) {
        UNUSED(instp);
 
+       if (client_ht != NULL) {
+               isc_ht_destroy(&client_ht);
+       }
        if (datapool != NULL) {
                isc_mempool_destroy(&datapool);
        }
@@ -369,25 +389,67 @@ is_v6_client(ns_client_t *client) {
        return (false);
 }
 
-/*
- * Shorthand to refer to the persistent data stored by this module in
- * the query context structure.
- */
-#define FILTER_MODE(qctx) ((filter_aaaa_t **) &qctx->hookdata[module_id])
+static filter_data_t *
+client_state_get(const query_ctx_t *qctx, isc_ht_t **htp) {
+       filter_data_t *client_state = NULL;
+       isc_result_t result;
+
+       result = isc_ht_find(*htp, (const unsigned char *)&qctx->client,
+                            sizeof(qctx->client), (void **)&client_state);
+
+       return (result == ISC_R_SUCCESS ? client_state : NULL);
+}
+
+static void
+client_state_create(const query_ctx_t *qctx, isc_ht_t **htp) {
+       filter_data_t *client_state;
+       isc_result_t result;
+
+       client_state = isc_mempool_get(datapool);
+       if (client_state == NULL) {
+               return;
+       }
+
+       client_state->mode = NONE;
+       client_state->flags = 0;
+
+       result = isc_ht_add(*htp, (const unsigned char *)&qctx->client,
+                           sizeof(qctx->client), client_state);
+       RUNTIME_CHECK(result == ISC_R_SUCCESS);
+}
+
+static void
+client_state_destroy(const query_ctx_t *qctx, isc_ht_t **htp) {
+       filter_data_t *client_state = client_state_get(qctx, htp);
+       isc_result_t result;
+
+       if (client_state == NULL) {
+               return;
+       }
+
+       result = isc_ht_delete(*htp, (const unsigned char *)&qctx->client,
+                              sizeof(qctx->client));
+       RUNTIME_CHECK(result == ISC_R_SUCCESS);
+
+       isc_mempool_put(datapool, client_state);
+}
 
 /*
- * Initialize hook data in the query context, fetching from a memory
- * pool.
+ * Initialize filter state, fetching it from a memory pool and storing it
+ * in a hash table keyed according to the client object; this enables
+ * us to retrieve persistent data related to a client query for as long
+ * as the object persists..
  */
 static bool
-filter_qctx_initialize(void *hookdata, void *cbdata, isc_result_t *resp) {
-       query_ctx_t *qctx = (query_ctx_t *) hookdata;
-       filter_aaaa_t **mode = FILTER_MODE(qctx);
-
-       UNUSED(cbdata);
-
-       *mode = isc_mempool_get(datapool);
-       **mode = NONE;
+filter_qctx_initialize(void *arg, void *cbdata, isc_result_t *resp) {
+       query_ctx_t *qctx = (query_ctx_t *) arg;
+       isc_ht_t **htp = (isc_ht_t **) cbdata;
+       filter_data_t *client_state;
+
+       client_state = client_state_get(qctx, htp);
+       if (client_state == NULL) {
+               client_state_create(qctx, htp);
+       }
 
        *resp = ISC_R_UNSET;
        return (false);
@@ -399,12 +461,15 @@ filter_qctx_initialize(void *hookdata, void *cbdata, isc_result_t *resp) {
  * filter-aaaa-on-v4 and filter-aaaa-on-v6.
  */
 static bool
-filter_prep_response_begin(void *hookdata, void *cbdata, isc_result_t *resp) {
-       query_ctx_t *qctx = (query_ctx_t *) hookdata;
-       filter_aaaa_t **mode = FILTER_MODE(qctx);
+filter_prep_response_begin(void *arg, void *cbdata, isc_result_t *resp) {
+       query_ctx_t *qctx = (query_ctx_t *) arg;
+       isc_ht_t **htp = (isc_ht_t **) cbdata;
+       filter_data_t *client_state = client_state_get(qctx, htp);
        isc_result_t result;
 
-       UNUSED(cbdata);
+       if (client_state == NULL) {
+               return (false);
+       }
 
        if (v4_aaaa != NONE || v6_aaaa != NONE) {
                result = ns_client_checkaclsilent(qctx->client, NULL,
@@ -413,12 +478,12 @@ filter_prep_response_begin(void *hookdata, void *cbdata, isc_result_t *resp) {
                    v4_aaaa != NONE &&
                    is_v4_client(qctx->client))
                {
-                       **mode = v4_aaaa;
+                       client_state->mode = v4_aaaa;
                } else if (result == ISC_R_SUCCESS &&
                           v6_aaaa != NONE &&
                           is_v6_client(qctx->client))
                {
-                       **mode = v6_aaaa;
+                       client_state->mode = v6_aaaa;
                }
        }
 
@@ -434,15 +499,18 @@ filter_prep_response_begin(void *hookdata, void *cbdata, isc_result_t *resp) {
  * queries; ANY queries are handled in query_filter_aaaa_any().)
  */
 static bool
-filter_respond_begin(void *hookdata, void *cbdata, isc_result_t *resp) {
-       query_ctx_t *qctx = (query_ctx_t *) hookdata;
-       filter_aaaa_t **mode = FILTER_MODE(qctx);
+filter_respond_begin(void *arg, void *cbdata, isc_result_t *resp) {
+       query_ctx_t *qctx = (query_ctx_t *) arg;
+       isc_ht_t **htp = (isc_ht_t **) cbdata;
+       filter_data_t *client_state = client_state_get(qctx, htp);
        isc_result_t result = ISC_R_UNSET;
 
-       UNUSED(cbdata);
+       if (client_state == NULL) {
+               return (false);
+       }
 
-       if (**mode != BREAK_DNSSEC &&
-           (**mode != FILTER ||
+       if (client_state->mode != BREAK_DNSSEC &&
+           (client_state->mode != FILTER ||
             (WANTDNSSEC(qctx->client) && qctx->sigrdataset != NULL &&
              dns_rdataset_isassociated(qctx->sigrdataset))))
        {
@@ -487,8 +555,7 @@ filter_respond_begin(void *hookdata, void *cbdata, isc_result_t *resp) {
                                qctx->sigrdataset->attributes |=
                                        DNS_RDATASETATTR_RENDERED;
                        }
-                       qctx->client->hookflags[module_id] |=
-                               FILTER_AAAA_FILTERED;
+                       client_state->flags |= FILTER_AAAA_FILTERED;
                } else if (!qctx->authoritative &&
                           RECURSIONOK(qctx->client) &&
                           (result == DNS_R_DELEGATION ||
@@ -507,15 +574,13 @@ filter_respond_begin(void *hookdata, void *cbdata, isc_result_t *resp) {
                                                  qctx->client->query.qname,
                                                  NULL, NULL, qctx->resuming);
                        if (result == ISC_R_SUCCESS) {
-                               qctx->client->hookflags[module_id] |=
-                                       FILTER_AAAA_RECURSING;
+                               client_state->flags |= FILTER_AAAA_RECURSING;
                                qctx->client->query.attributes |=
                                        NS_QUERYATTR_RECURSING;
                        }
                }
        } else if (qctx->qtype == dns_rdatatype_a &&
-                  ((qctx->client->hookflags[module_id] &
-                    FILTER_AAAA_RECURSING) != 0))
+                  (client_state->flags & FILTER_AAAA_RECURSING) != 0)
        {
                dns_rdataset_t *mrdataset = NULL;
                dns_rdataset_t *sigrdataset = NULL;
@@ -539,7 +604,7 @@ filter_respond_begin(void *hookdata, void *cbdata, isc_result_t *resp) {
                        sigrdataset->attributes |= DNS_RDATASETATTR_RENDERED;
                }
 
-               qctx->client->hookflags[module_id] &= ~FILTER_AAAA_RECURSING;
+               client_state->flags &= ~FILTER_AAAA_RECURSING;
 
                result = ns_query_done(qctx);
 
@@ -556,17 +621,20 @@ filter_respond_begin(void *hookdata, void *cbdata, isc_result_t *resp) {
  * When answering an ANY query, remove AAAA if A is present.
  */
 static bool
-filter_respond_any_found(void *hookdata, void *cbdata, isc_result_t *resp) {
-       query_ctx_t *qctx = (query_ctx_t *) hookdata;
-       filter_aaaa_t **mode = FILTER_MODE(qctx);
+filter_respond_any_found(void *arg, void *cbdata, isc_result_t *resp) {
+       query_ctx_t *qctx = (query_ctx_t *) arg;
+       isc_ht_t **htp = (isc_ht_t **) cbdata;
+       filter_data_t *client_state = client_state_get(qctx, htp);
        dns_name_t *name = NULL;
        dns_rdataset_t *aaaa = NULL, *aaaa_sig = NULL;
        dns_rdataset_t *a = NULL;
        bool have_a = true;
 
-       UNUSED(cbdata);
+       if (client_state == NULL) {
+               return (false);
+       }
 
-       if (**mode == NONE) {
+       if (client_state->mode == NONE) {
                *resp = ISC_R_UNSET;
                return (false);
        }
@@ -598,7 +666,7 @@ filter_respond_any_found(void *hookdata, void *cbdata, isc_result_t *resp) {
 
        if (have_a && aaaa != NULL &&
            (aaaa_sig == NULL || !WANTDNSSEC(qctx->client) ||
-            **mode == BREAK_DNSSEC))
+            client_state->mode == BREAK_DNSSEC))
        {
                qctx->client->message->flags &= ~DNS_MESSAGEFLAG_AD;
                aaaa->attributes |= DNS_RDATASETATTR_RENDERED;
@@ -617,14 +685,17 @@ filter_respond_any_found(void *hookdata, void *cbdata, isc_result_t *resp) {
  * section.
  */
 static bool
-filter_query_done_send(void *hookdata, void *cbdata, isc_result_t *resp) {
-       query_ctx_t *qctx = (query_ctx_t *) hookdata;
-       filter_aaaa_t **mode = FILTER_MODE(qctx);
+filter_query_done_send(void *arg, void *cbdata, isc_result_t *resp) {
+       query_ctx_t *qctx = (query_ctx_t *) arg;
+       isc_ht_t **htp = (isc_ht_t **) cbdata;
+       filter_data_t *client_state = client_state_get(qctx, htp);
        isc_result_t result;
 
-       UNUSED(cbdata);
+       if (client_state == NULL) {
+               return (false);
+       }
 
-       if (**mode == NONE) {
+       if (client_state->mode == NONE) {
                *resp = ISC_R_UNSET;
                return (false);
        }
@@ -658,7 +729,7 @@ filter_query_done_send(void *hookdata, void *cbdata, isc_result_t *resp) {
                                     dns_rdatatype_aaaa, &aaaa_sig);
 
                if (aaaa_sig == NULL || !WANTDNSSEC(qctx->client) ||
-                   **mode == BREAK_DNSSEC)
+                   client_state->mode == BREAK_DNSSEC)
                {
                        aaaa->attributes |= DNS_RDATASETATTR_RENDERED;
                        if (aaaa_sig != NULL) {
@@ -668,7 +739,7 @@ filter_query_done_send(void *hookdata, void *cbdata, isc_result_t *resp) {
                }
        }
 
-       if ((qctx->client->hookflags[module_id] & FILTER_AAAA_FILTERED) != 0) {
+       if ((client_state->flags & FILTER_AAAA_FILTERED) != 0) {
                result = dns_message_firstname(qctx->client->message,
                                               DNS_SECTION_AUTHORITY);
                while (result == ISC_R_SUCCESS) {
@@ -704,20 +775,20 @@ filter_query_done_send(void *hookdata, void *cbdata, isc_result_t *resp) {
 }
 
 /*
- * Return hook data to the mempool.
+ * If the client is being detached, then we can delete our persistent
+ * data from hash table and return it to the memory pool.
  */
 static bool
-filter_qctx_destroy(void *hookdata, void *cbdata, isc_result_t *resp) {
-       query_ctx_t *qctx = (query_ctx_t *) hookdata;
-       filter_aaaa_t **mode = FILTER_MODE(qctx);
-
-       UNUSED(cbdata);
+filter_qctx_destroy(void *arg, void *cbdata, isc_result_t *resp) {
+       query_ctx_t *qctx = (query_ctx_t *) arg;
+       isc_ht_t **htp = (isc_ht_t **) cbdata;
 
-       if (*mode != NULL) {
-               isc_mempool_put(datapool, *mode);
-               *mode = NULL;
+       if (!qctx->detach_client) {
+               return (false);
        }
 
+       client_state_destroy(qctx, htp);
+
        *resp = ISC_R_UNSET;
        return (false);
 }
index cd9ceb55ae6526766744eff1f8b1ffd3aa81703c..e4f1883edfb2baad327e22c17ce5fd5e61be659c 100644 (file)
@@ -1537,8 +1537,7 @@ configure_dyndb(const cfg_obj_t *dyndb, isc_mem_t *mctx,
 }
 
 static isc_result_t
-configure_hook(ns_hooktable_t *hooktable, const unsigned int modid,
-              const cfg_obj_t *hook,
+configure_hook(ns_hooktable_t *hooktable, const cfg_obj_t *hook,
               const cfg_obj_t *config, ns_hookctx_t *hctx)
 {
        isc_result_t result = ISC_R_SUCCESS;
@@ -1563,7 +1562,7 @@ configure_hook(ns_hooktable_t *hooktable, const unsigned int modid,
        if (obj != NULL && cfg_obj_isstring(obj)) {
                parameters = cfg_obj_asstring(obj);
        }
-       result = ns_hookmodule_load(library, modid, parameters,
+       result = ns_hookmodule_load(library, parameters,
                                    cfg_obj_file(obj), cfg_obj_line(obj),
                                    config, named_g_aclconfctx,
                                    hctx, hooktable);
@@ -3760,7 +3759,6 @@ configure_view(dns_view_t *view, dns_viewlist_t *viewlist,
        unsigned int resolver_param;
        dns_ntatable_t *ntatable = NULL;
        const char *qminmode = NULL;
-       unsigned int module_counter = 0;
 
        REQUIRE(DNS_VIEW_VALID(view));
 
@@ -5310,8 +5308,7 @@ configure_view(dns_view_t *view, dns_viewlist_t *viewlist,
 
 #ifdef HAVE_DLOPEN
        if (hook_list != NULL) {
-               const void *hashinit = isc_hash_get_initializer();
-               CHECK(ns_hook_createctx(mctx, hashinit, &hctx));
+               CHECK(ns_hook_createctx(mctx, &hctx));
 
                INSIST(view->hooktable == NULL);
                CHECK(ns_hooktable_create(view->mctx,
@@ -5325,20 +5322,7 @@ configure_view(dns_view_t *view, dns_viewlist_t *viewlist,
        {
                const cfg_obj_t *hook = cfg_listelt_value(element);
 
-               if (view->hooktable == NULL) {
-                       CHECK(ns_hooktable_create(view->mctx,
-                                 (ns_hooktable_t **) &view->hooktable));
-                       view->hooktable_free = ns_hooktable_free;
-               }
-
-               if (hctx == NULL) {
-                       CHECK(ns_hook_createctx(mctx, &hctx));
-               }
-
-               CHECK(configure_hook(view->hooktable, module_counter,
-                                    hook, config, hctx));
-
-               module_counter++;
+               CHECK(configure_hook(view->hooktable, hook, config, hctx));
        }
 #endif
 
index 1c45094833f023bc09cf78b073b5457bc383b6e9..36dbb1d2ab073529879a2ec243fbdd22b6b1d6d9 100644 (file)
@@ -3047,7 +3047,6 @@ client_create(ns_clientmgr_t *manager, ns_client_t **clientp) {
        ISC_QLINK_INIT(client, ilink);
        client->keytag = NULL;
        client->keytag_len = 0;
-       memset(client->hookflags, 0, sizeof(client->hookflags));
 
        /*
         * We call the init routines for the various kinds of client here,
index d94cfdfdcd156ab0c890422a11f5a33f42f33727..0f0abbf4ea530b2b027f056a34d36e1fb0c4fdc0 100644 (file)
@@ -339,8 +339,7 @@ unload_library(ns_hook_module_t **hmodp) {
 #endif /* HAVE_DLFCN_H */
 
 isc_result_t
-ns_hookmodule_load(const char *modpath, const unsigned int modid,
-                  const char *parameters,
+ns_hookmodule_load(const char *modpath, const char *parameters,
                   const char *cfg_file, unsigned long cfg_line,
                   const void *cfg, void *actx,
                   ns_hookctx_t *hctx, ns_hooktable_t *hooktable)
@@ -357,9 +356,8 @@ ns_hookmodule_load(const char *modpath, const unsigned int modid,
                      "loading module '%s'", modpath);
 
        CHECK(load_library(hctx->mctx, modpath, &hmod));
-       CHECK(hmod->register_func(modid, parameters, cfg_file, cfg_line,
-                                 cfg, actx, hctx, hooktable,
-                                 &hmod->inst));
+       CHECK(hmod->register_func(parameters, cfg_file, cfg_line,
+                                 cfg, actx, hctx, hooktable, &hmod->inst));
 
        ISC_LIST_APPEND(hook_modules, hmod, link);
 
index 6d030c3180d9ad861cd1f964ffc7bdf8bc7aef18..7d25eb93606c33fcd11232fd244984b0e0a00694 100644 (file)
@@ -170,12 +170,6 @@ struct ns_client {
        uint32_t                expire;
        unsigned char           *keytag;
        uint16_t                keytag_len;
-
-       /*%
-        * Allows a hook module to set flags
-        * that persist across recursion.
-        */
-       uint32_t                hookflags[NS_MAX_MODULES];
 };
 
 typedef ISC_QUEUE(ns_client_t) client_queue_t;
index f86364ac60bfec3b2224f99a35e1b5677b19deb4..e0418051ada53789279c1a8a06965c0efa76ff4a 100644 (file)
@@ -246,8 +246,7 @@ typedef struct ns_hookctx {
 #define NS_HOOK_AGE 0
 #endif
 
-typedef isc_result_t ns_hook_register_t(const unsigned int modid,
-                                       const char *parameters,
+typedef isc_result_t ns_hook_register_t(const char *parameters,
                                        const char *file,
                                        unsigned long line,
                                        const void *cfg,
@@ -302,8 +301,7 @@ ns_hook_destroyctx(ns_hookctx_t **hctxp);
  */
 
 isc_result_t
-ns_hookmodule_load(const char *modpath, const unsigned int modid,
-                  const char *parameters,
+ns_hookmodule_load(const char *modpath, const char *parameters,
                   const char *cfg_file, unsigned long cfg_line,
                   const void *cfg, void *actx,
                   ns_hookctx_t *hctx, ns_hooktable_t *hooktable);
index b3fc3a742c978da7c92e25391b91e9e9e386f2d7..5e38d48fb21c86d41f22937c43404aec0c3ed207 100644 (file)
 
 #include <ns/types.h>
 
-/*
- * Maximum number of query hook modules that can be configured;
- * more than this will overflow qctx->hookdata.
- */
-#define NS_MAX_MODULES 16
-
 /*% nameserver database version structure */
 typedef struct ns_dbversion {
        dns_db_t                        *db;
@@ -156,6 +150,8 @@ struct query_ctx {
        dns_fixedname_t dsname;                 /* name needing DS */
 
        ns_client_t *client;                    /* client object */
+       bool detach_client;                     /* client needs detaching */
+
        dns_fetchevent_t *event;                /* recursion event */
 
        dns_db_t *db;                           /* zone or cache database */
@@ -174,8 +170,6 @@ struct query_ctx {
 
        dns_view_t *view;                       /* client view */
 
-       void *hookdata[NS_MAX_MODULES];         /* data used by query hooks */
-
        isc_result_t result;                    /* query result */
        int line;                               /* line to report error */
 };
index 3dcf23e7cc0e87dfae0c9f14384a289895260621..e9b703805d56e76347f69d3112a715244d6d7a49 100644 (file)
@@ -4936,6 +4936,9 @@ qctx_destroy(query_ctx_t *qctx) {
        CALL_HOOK_NORETURN(NS_QUERY_QCTX_DESTROYED, qctx);
 
        dns_view_detach(&qctx->view);
+       if (qctx->detach_client) {
+               ns_client_detach(&qctx->client);
+       }
 }
 
 /*%
@@ -6915,9 +6918,9 @@ query_respond_any(query_ctx_t *qctx) {
        }
 
        /*
-        * If we're here, no matching rdatasets were found in
-        * cache. If we were searching for RRSIG/SIG, that
-        * may be okay, but otherwise something's gone wrong.
+        * If we're here, no matching rdatasets were found.  If we were
+        * searching for RRSIG/SIG, that may be okay, but otherwise
+        * something's gone wrong.
         */
        INSIST(qctx->qtype == dns_rdatatype_rrsig ||
               qctx->qtype == dns_rdatatype_sig);
@@ -10517,7 +10520,7 @@ ns_query_done(query_ctx_t *qctx) {
                        query_error(qctx->client, qctx->result, qctx->line);
                }
 
-               ns_client_detach(&qctx->client);
+               qctx->detach_client = true;
                return (qctx->result);
        }
 
@@ -10561,7 +10564,7 @@ ns_query_done(query_ctx_t *qctx) {
 
        query_send(qctx->client);
 
-       ns_client_detach(&qctx->client);
+       qctx->detach_client = true;
        return (qctx->result);
 
  cleanup: