]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
add hook statement to configuration parser
authorEvan Hunt <each@isc.org>
Sun, 12 Aug 2018 18:19:36 +0000 (11:19 -0700)
committerEvan Hunt <each@isc.org>
Thu, 6 Dec 2018 18:29:11 +0000 (10:29 -0800)
- allow multiple "hook" statements at global or view level
- add "optional bracketed text" type for optional parameter list
- load hook module from specified path rather than hardcoded path
- add a hooktable pointer (and a callback for freeing it) to the
  view structure
- change the hooktable functions so they no longer update ns__hook_table
  by default, and modify PROCESS_HOOK so it uses the view hooktable, if
  set, rather than ns__hook_table. (ns__hook_table is retained for
  use by unit tests.)
- update the filter-aaaa system test to load filter-aaaa.so
- add a prereq script to check for dlopen support before running
  the filter-aaaa system test

not yet done:
- configuration parameters are not being passed to the filter-aaaa
  module; the filter-aaaa ACL and filter-aaaa-on-{v4,v6} settings are
  still stored in dns_view

22 files changed:
bin/hooks/filter-aaaa.c
bin/named/server.c
bin/tests/system/filter-aaaa/ns1/named1.conf.in
bin/tests/system/filter-aaaa/ns1/named2.conf.in
bin/tests/system/filter-aaaa/ns2/named1.conf.in
bin/tests/system/filter-aaaa/ns2/named2.conf.in
bin/tests/system/filter-aaaa/ns3/named1.conf.in
bin/tests/system/filter-aaaa/ns3/named2.conf.in
bin/tests/system/filter-aaaa/ns4/named1.conf.in
bin/tests/system/filter-aaaa/ns4/named2.conf.in
bin/tests/system/filter-aaaa/ns5/named.conf.in
bin/tests/system/filter-aaaa/prereq.sh [new file with mode: 0644]
lib/dns/include/dns/view.h
lib/dns/view.c
lib/isccfg/include/isccfg/grammar.h
lib/isccfg/namedconf.c
lib/isccfg/parser.c
lib/ns/hooks.c
lib/ns/include/ns/hooks.h
lib/ns/query.c
lib/ns/tests/nstest.c
lib/ns/tests/query_test.c

index a0e8141fcf07ca0c028e044522b28fc92adaebb0..2f316dbc35d04ef73b6ace915ea088ef5abe6b13 100644 (file)
@@ -77,10 +77,19 @@ hook_register(const char *parameters, const char *file, unsigned long line,
        UNUSED(parameters);
        UNUSED(instp);
 
-       isc_log_write(hctx->lctx, NS_LOGCATEGORY_GENERAL,
-                     NS_LOGMODULE_HOOKS, ISC_LOG_INFO,
-                     "loading params for 'filter-aaaa' module from %s:%lu",
-                     file, line);
+       if (parameters != NULL) {
+               isc_log_write(hctx->lctx, NS_LOGCATEGORY_GENERAL,
+                             NS_LOGMODULE_HOOKS, ISC_LOG_INFO,
+                             "loading params for 'filter-aaaa' "
+                             "module from %s:%lu",
+                             file, line);
+       } else {
+               isc_log_write(hctx->lctx, NS_LOGCATEGORY_GENERAL,
+                             NS_LOGMODULE_HOOKS, ISC_LOG_INFO,
+                             "loading 'filter-aaaa' "
+                             "module from %s:%lu, no parameters",
+                             file, line);
+       }
 
        /*
         * TODO:
index 37282e9e09a4527b280344c3cc1133e503d99b59..c3da40ed25fd765f4a568df54c940d6a24effac6 100644 (file)
@@ -1535,6 +1535,50 @@ configure_dyndb(const cfg_obj_t *dyndb, isc_mem_t *mctx,
                              name, isc_result_totext(result));
        return (result);
 }
+
+static isc_result_t
+configure_hook(ns_hooktable_t *hooktable, const cfg_obj_t *hook,
+              ns_hookctx_t *hctx)
+{
+       isc_result_t result = ISC_R_SUCCESS;
+       const cfg_obj_t *obj;
+       const char *type, *library;
+
+       /* Get the path to the hook module. */
+       obj = cfg_tuple_get(hook, "type");
+       type = cfg_obj_asstring(obj);
+
+       /* Only query hooks are supported currently. */
+       if (strcasecmp(type, "query") != 0) {
+               cfg_obj_log(obj, named_g_lctx, ISC_LOG_ERROR,
+                           "unsupported hook type");
+               return (ISC_R_FAILURE);
+       }
+
+       library = cfg_obj_asstring(cfg_tuple_get(hook, "library"));
+
+       obj = cfg_tuple_get(hook, "parameters");
+       if (obj != NULL && cfg_obj_isstring(obj)) {
+               result = ns_hookmodule_load(library,
+                                           cfg_obj_asstring(obj),
+                                           cfg_obj_file(obj),
+                                           cfg_obj_line(obj),
+                                           hctx, hooktable);
+       } else {
+               result = ns_hookmodule_load(library, NULL,
+                                           cfg_obj_file(hook),
+                                           cfg_obj_line(hook),
+                                           hctx, hooktable);
+       }
+
+       if (result != ISC_R_SUCCESS) {
+               isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
+                             NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR,
+                             "%s: hook module configuration failed: %s",
+                             library, isc_result_totext(result));
+       }
+       return (result);
+}
 #endif
 
 
@@ -3675,7 +3719,7 @@ configure_view(dns_view_t *view, dns_viewlist_t *viewlist,
        const cfg_obj_t *dlvobj = NULL;
        unsigned int dlzargc;
        char **dlzargv;
-       const cfg_obj_t *dyndb_list;
+       const cfg_obj_t *dyndb_list, *hook_list;
        const cfg_obj_t *disabled;
        const cfg_obj_t *obj, *obj2;
        const cfg_listelt_t *element;
@@ -5271,10 +5315,11 @@ configure_view(dns_view_t *view, dns_viewlist_t *viewlist,
         * Load DynDB modules.
         */
        dyndb_list = NULL;
-       if (voptions != NULL)
+       if (voptions != NULL) {
                (void)cfg_map_get(voptions, "dyndb", &dyndb_list);
-       else
+       } else {
                (void)cfg_map_get(config, "dyndb", &dyndb_list);
+       }
 
 #ifdef HAVE_DLOPEN
        for (element = cfg_list_first(dyndb_list);
@@ -5294,21 +5339,37 @@ configure_view(dns_view_t *view, dns_viewlist_t *viewlist,
 
                CHECK(configure_dyndb(dyndb, mctx, dctx));
        }
+#endif
 
        /*
-        * XXX:
-        * temporary! this forces loading of filter-aaaa.so from the
-        * current working directory, if present. later this will
-        * happen via configuration as dyndb does above. we don't
-        * bother checking whether it succeeded; if it doesn't,
-        * filter-aaaa simply won't work.
+        * Load hook modules.
         */
-       if (hctx == NULL) {
-               CHECK(ns_hook_createctx(mctx, &hctx));
+       hook_list = NULL;
+       if (voptions != NULL) {
+               (void)cfg_map_get(voptions, "hook", &hook_list);
+       } else {
+               (void)cfg_map_get(config, "hook", &hook_list);
+       }
+
+#ifdef HAVE_DLOPEN
+       for (element = cfg_list_first(hook_list);
+            element != NULL;
+            element = cfg_list_next(element))
+       {
+               const cfg_obj_t *hook = cfg_listelt_value(element);
+
+               if (view->hooktable == NULL) {
+                       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, hook, hctx));
        }
-       ns_hooktable_init(NULL);
-       (void) ns_hookmodule_load("/tmp/filter-aaaa.so", "", "<none>", 0,
-                                 hctx, NULL);
 #endif
 
        /*
index 55c1afe093962610af703987202ae53eb6cad90c..bde197748ec1cac88a38b9f5506a3916ebde3f2f 100644 (file)
@@ -25,6 +25,8 @@ options {
        minimal-responses no;
 };
 
+hook query "../../../../hooks/lib/filter-aaaa.so";
+
 key rndc_key {
        secret "1234abcd8765";
        algorithm hmac-sha256;
index 6cf9d0d333518293705cb917bf55c40804a835c8..8d29d583aa20fe0ae8294d6cdc82099dfb628a75 100644 (file)
@@ -25,6 +25,8 @@ options {
        minimal-responses no;
 };
 
+hook query "../../../../hooks/lib/filter-aaaa.so";
+
 key rndc_key {
        secret "1234abcd8765";
        algorithm hmac-sha256;
index 7b43a97a46182aa67a6d64b8b7fb2f5b8bd71b1c..5d8e06cdfd5515630571516aa549c5743b5d4714 100644 (file)
@@ -25,6 +25,8 @@ options {
        minimal-responses no;
 };
 
+hook query "../../../../hooks/lib/filter-aaaa.so";
+
 key rndc_key {
        secret "1234abcd8765";
        algorithm hmac-sha256;
index 6a6b9baef7c6deeee4e6fb067df4b790fbd2a50b..56e388ce49c22bf4d2472b9a93d84d35d7d63754 100644 (file)
@@ -25,6 +25,8 @@ options {
        minimal-responses no;
 };
 
+hook query "../../../../hooks/lib/filter-aaaa.so";
+
 key rndc_key {
        secret "1234abcd8765";
        algorithm hmac-sha256;
index 60c97d2aa67e28de57c51857295fd381f16d1e6a..b0f4ba0667abc95c6c3ee543346bff9cb0158673 100644 (file)
@@ -25,6 +25,8 @@ options {
        minimal-responses no;
 };
 
+hook query "../../../../hooks/lib/filter-aaaa.so";
+
 key rndc_key {
        secret "1234abcd8765";
        algorithm hmac-sha256;
index fd7b8c04d1c55a763fd815a937636179ea682133..847bdfe0d349d786ecd2f49767fda9d59a9dfeb4 100644 (file)
@@ -25,6 +25,8 @@ options {
        minimal-responses no;
 };
 
+hook query "../../../../hooks/lib/filter-aaaa.so";
+
 key rndc_key {
        secret "1234abcd8765";
        algorithm hmac-sha256;
index 3f7cbcb16e17f82a21d636bd241bb854ced601ab..915f55d44b9f2270aa8dd7ab27597c2abc9683a6 100644 (file)
@@ -25,6 +25,8 @@ options {
        minimal-responses no;
 };
 
+hook query "../../../../hooks/lib/filter-aaaa.so";
+
 key rndc_key {
        secret "1234abcd8765";
        algorithm hmac-sha256;
index 56a546e359953a801aca5e6f648eff01869628e6..c6818b8f7649511d6a1b4c5de673b021dc1a2b4c 100644 (file)
@@ -25,6 +25,8 @@ options {
        minimal-responses no;
 };
 
+hook query "../../../../hooks/lib/filter-aaaa.so";
+
 key rndc_key {
        secret "1234abcd8765";
        algorithm hmac-sha256;
index 47b3aff31aeb698c4f1bacb62032de273eee4a69..a27ee016d697604cf03985462f8270c746e05ae9 100644 (file)
@@ -30,6 +30,8 @@ options {
        minimal-responses no;
 };
 
+hook query "../../../../hooks/lib/filter-aaaa.so";
+
 key rndc_key {
        secret "1234abcd8765";
        algorithm hmac-sha256;
diff --git a/bin/tests/system/filter-aaaa/prereq.sh b/bin/tests/system/filter-aaaa/prereq.sh
new file mode 100644 (file)
index 0000000..7b8a7f4
--- /dev/null
@@ -0,0 +1,19 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+$FEATURETEST --have-dlopen ||  {
+        echo_i "dlopen() not supported - skipping filter-aaaa test"
+        exit 255
+}
+exit 0
index ad626593c01ee8056e8cf32b2c4f8e623fdc2b42..0032bd0dc0cb2653744a328b8a7b041236f46a8f 100644 (file)
@@ -238,6 +238,9 @@ struct dns_view {
        dns_dtenv_t                     *dtenv;         /* Dnstap environment */
        dns_dtmsgtype_t                 dttypes;        /* Dnstap message types
                                                           to log */
+
+       void                            *hooktable;     /* ns_hooktable */
+       void                            (*hooktable_free)(isc_mem_t *, void **);
 };
 
 #define DNS_VIEW_MAGIC                 ISC_MAGIC('V','i','e','w')
index 8820a95c6dbe450f7ecc7a97a4fd20c8f19fa631..05a656e9ef00343c21d35b2e1beee90dd9e6ef5d 100644 (file)
@@ -259,6 +259,9 @@ dns_view_create(isc_mem_t *mctx, dns_rdataclass_t rdclass,
        view->dtenv = NULL;
        view->dttypes = 0;
 
+       view->hooktable = NULL;
+       view->hooktable_free = NULL;
+
        isc_mutex_init(&view->new_zone_lock);
 
        result = dns_order_create(view->mctx, &view->order);
@@ -550,6 +553,9 @@ destroy(dns_view_t *view) {
        isc_mutex_destroy(&view->lock);
        isc_mem_free(view->mctx, view->nta_file);
        isc_mem_free(view->mctx, view->name);
+       if (view->hooktable != NULL && view->hooktable_free != NULL) {
+               view->hooktable_free(view->mctx, &view->hooktable);
+       }
        isc_mem_putanddetach(&view->mctx, view, sizeof(*view));
 }
 
index 93ff3df15677914740e77995f10ee0bdab24f644..f813f41bf22d0d2585d031b2b5bcf940269887ef 100644 (file)
@@ -302,6 +302,7 @@ LIBISCCFG_EXTERNAL_DATA extern cfg_type_t cfg_type_astring;
 LIBISCCFG_EXTERNAL_DATA extern cfg_type_t cfg_type_ustring;
 LIBISCCFG_EXTERNAL_DATA extern cfg_type_t cfg_type_sstring;
 LIBISCCFG_EXTERNAL_DATA extern cfg_type_t cfg_type_bracketed_text;
+LIBISCCFG_EXTERNAL_DATA extern cfg_type_t cfg_type_optional_bracketed_text;
 LIBISCCFG_EXTERNAL_DATA extern cfg_type_t cfg_type_sockaddr;
 LIBISCCFG_EXTERNAL_DATA extern cfg_type_t cfg_type_sockaddrdscp;
 LIBISCCFG_EXTERNAL_DATA extern cfg_type_t cfg_type_netaddr;
index 15ab4e580bfb37d2bc266e986932f39a3fe9cc4d..7a8f3a71f01e38977d0d1ba15de270c78dd78ab5 100644 (file)
@@ -109,6 +109,7 @@ static cfg_type_t cfg_type_dnstap;
 static cfg_type_t cfg_type_dnstapoutput;
 static cfg_type_t cfg_type_dyndb;
 static cfg_type_t cfg_type_filter_aaaa;
+static cfg_type_t cfg_type_hook;
 static cfg_type_t cfg_type_ixfrdifftype;
 static cfg_type_t cfg_type_key;
 static cfg_type_t cfg_type_logfile;
@@ -1007,6 +1008,7 @@ namedconf_or_view_clauses[] = {
        { "dyndb", &cfg_type_dyndb, CFG_CLAUSEFLAG_MULTI },
        { "key", &cfg_type_key, CFG_CLAUSEFLAG_MULTI },
        { "managed-keys", &cfg_type_managedkeys, CFG_CLAUSEFLAG_MULTI },
+       { "hook", &cfg_type_hook, CFG_CLAUSEFLAG_MULTI },
        { "server", &cfg_type_server, CFG_CLAUSEFLAG_MULTI },
        { "trusted-keys", &cfg_type_dnsseckeys, CFG_CLAUSEFLAG_MULTI },
        { "zone", &cfg_type_zone, CFG_CLAUSEFLAG_MULTI },
@@ -2394,6 +2396,29 @@ static cfg_type_t cfg_type_dyndb = {
         &cfg_rep_tuple, dyndb_fields
 };
 
+/*%
+ * The "hook" statement syntax.
+ * Currently only one hook type is supported: query.
+ */
+
+static const char *hook_enums[] = {
+       "query", NULL
+};
+static cfg_type_t cfg_type_hooktype = {
+       "hooktype", cfg_parse_enum, cfg_print_ustring, cfg_doc_enum,
+       &cfg_rep_string, hook_enums
+};
+static cfg_tuplefielddef_t hook_fields[] = {
+       { "type", &cfg_type_hooktype, 0 },
+       { "library", &cfg_type_astring, 0 },
+       { "parameters", &cfg_type_optional_bracketed_text, 0 },
+       { NULL, NULL, 0 }
+};
+static cfg_type_t cfg_type_hook = {
+       "hook", cfg_parse_tuple, cfg_print_tuple, cfg_doc_tuple,
+        &cfg_rep_tuple, hook_fields
+};
+
 /*%
  * Clauses that can be found within the 'key' statement.
  */
index 7211d9ef7661541d3e201fefe31ba2dcc409cc6a..233eb26b52fd2c9fe528686fd8d23a6b5f03d4e7 100644 (file)
@@ -1134,7 +1134,6 @@ doc_btext(cfg_printer_t *pctx, const cfg_type_t *type) {
        cfg_print_cstr(pctx, "{ <unspecified-text> }");
 }
 
-
 bool
 cfg_is_enum(const char *s, const char *const *enums) {
        const char * const *p;
@@ -1275,6 +1274,51 @@ LIBISCCFG_EXTERNAL_DATA cfg_type_t cfg_type_bracketed_text = {
        &cfg_rep_string, NULL
 };
 
+/*
+ * Optional bracketed text
+ */
+static isc_result_t
+parse_optional_btext(cfg_parser_t *pctx, const cfg_type_t *type,
+                    cfg_obj_t **ret)
+{
+       isc_result_t result;
+
+       UNUSED(type);
+
+       CHECK(cfg_peektoken(pctx, ISC_LEXOPT_BTEXT));
+       if (pctx->token.type == isc_tokentype_btext) {
+               CHECK(cfg_parse_obj(pctx, &cfg_type_bracketed_text, ret));
+       } else {
+               CHECK(cfg_parse_obj(pctx, &cfg_type_void, ret));
+       }
+ cleanup:
+       return (result);
+}
+
+static void
+print_optional_btext(cfg_printer_t *pctx, const cfg_obj_t *obj) {
+       if (obj->type == &cfg_type_void) {
+               return;
+       }
+
+       pctx->indent++;
+       cfg_print_cstr(pctx, "{");
+       cfg_print_chars(pctx, obj->value.string.base, obj->value.string.length);
+       print_close(pctx);
+}
+
+static void
+doc_optional_btext(cfg_printer_t *pctx, const cfg_type_t *type) {
+       UNUSED(type);
+
+       cfg_print_cstr(pctx, "[ { <unspecified-text> } ]");
+}
+
+cfg_type_t cfg_type_optional_bracketed_text = {
+       "optional_btext", parse_optional_btext, print_optional_btext,
+       doc_optional_btext, NULL, NULL
+};
+
 /*
  * Booleans
  */
@@ -1485,7 +1529,7 @@ print_list(cfg_printer_t *pctx, const cfg_obj_t *obj) {
 
 isc_result_t
 cfg_parse_bracketed_list(cfg_parser_t *pctx, const cfg_type_t *type,
-                    cfg_obj_t **ret)
+                        cfg_obj_t **ret)
 {
        isc_result_t result;
 
index 66438f6604f72e01176e8d2c1792057c1abfd1af..902cb8915c26fc8361a4d668e639b78ad8536697 100644 (file)
@@ -335,10 +335,6 @@ ns_hookmodule_load(const char *libname, const char *parameters,
        isc_result_t result;
        ns_hook_module_t *module = NULL;
 
-       if (hooktable == NULL) {
-               hooktable = ns__hook_table;
-       }
-
        REQUIRE(NS_HOOKCTX_VALID(hctx));
 
        isc_log_write(ns_lctx, NS_LOGCATEGORY_GENERAL,
@@ -420,27 +416,32 @@ ns_hooktable_init(ns_hooktable_t *hooktable) {
 
        RUNTIME_CHECK(isc_once_do(&once, init_modules) == ISC_R_SUCCESS);
 
-       if (hooktable == NULL) {
-               hooktable = ns__hook_table;
-       }
-
        for (i = 0; i < NS_QUERY_HOOKS_COUNT; i++) {
                ISC_LIST_INIT((*hooktable)[i]);
        }
 }
 
-ns_hooktable_t *
-ns_hooktable_save() {
-       return (ns__hook_table);
+isc_result_t
+ns_hooktable_create(isc_mem_t *mctx, ns_hooktable_t **tablep) {
+       ns_hooktable_t *hooktable;
+
+       REQUIRE(tablep != NULL && *tablep == NULL);
+
+       hooktable = isc_mem_get(mctx, sizeof(ns_hooktable_t));
+
+       ns_hooktable_init(hooktable);
+
+       *tablep = hooktable;
+
+       return (ISC_R_SUCCESS);
 }
 
 void
-ns_hooktable_reset(ns_hooktable_t *hooktable) {
-       if (hooktable != NULL) {
-               ns__hook_table = hooktable;
-       } else {
-               ns__hook_table = &hooktab;
-       }
+ns_hooktable_free(isc_mem_t *mctx, void **tablep) {
+       REQUIRE(tablep != NULL && *tablep != NULL);
+
+       isc_mem_put(mctx, *tablep, sizeof(ns_hooktable_t));
+       *tablep = NULL;
 }
 
 void
index 3001661a43cda6358a1871837ede6d177651c2ee..8c249274d151d151ef2b47a920e5ce070e61575a 100644 (file)
@@ -196,13 +196,13 @@ typedef struct ns_hook {
        ISC_LINK(struct ns_hook) link;
 } ns_hook_t;
 
-/*
- * ns__hook_table is a globally visible pointer to the active hook
- * table. It's initialized to point to 'hooktab', which is the default
- * global hook table.
- */
 typedef ISC_LIST(ns_hook_t) ns_hooklist_t;
 typedef ns_hooklist_t ns_hooktable_t[NS_QUERY_HOOKS_COUNT];
+
+/*
+ * ns__hook_table is a global hook table, which is used if view->hooktable
+ * is NULL.  It's intended only for use by unit tests.
+ */
 LIBNS_EXTERNAL_DATA extern ns_hooktable_t *ns__hook_table;
 
 /*!
@@ -281,7 +281,7 @@ typedef int ns_hook_version_t(unsigned int *flags);
  * true, we continue processing.
  */
 #define _NS_PROCESS_HOOK(table, id, data, ...)                         \
-       if (table != NULL) {                    \
+       if (table != NULL) {                                            \
                ns_hook_t *_hook = ISC_LIST_HEAD((*table)[id]);         \
                isc_result_t _result;                                   \
                                                                        \
@@ -298,9 +298,9 @@ typedef int ns_hook_version_t(unsigned int *flags);
                }                                                       \
        }
 
-#define NS_PROCESS_HOOK(table, id, data) \
+#define NS_PROCESS_HOOK(table, id, data, ...) \
        _NS_PROCESS_HOOK(table, id, data, _result)
-#define NS_PROCESS_HOOK_VOID(table, id, data) \
+#define NS_PROCESS_HOOK_VOID(table, id, data, ...) \
        _NS_PROCESS_HOOK(table, id, data)
 
 isc_result_t
@@ -321,8 +321,7 @@ ns_hook_add(ns_hooktable_t *hooktable, ns_hookpoint_t hookpoint,
            ns_hook_t *hook);
 /*%
  * Append hook function 'hook' to the list of hooks at 'hookpoint' in
- * 'hooktable'.  If 'hooktable' is NULL, the global hook table
- * ns__hook_table is used.
+ * 'hooktable'.
  *
  * Requires:
  *\li 'hook' is not NULL
@@ -331,26 +330,23 @@ ns_hook_add(ns_hooktable_t *hooktable, ns_hookpoint_t hookpoint,
  *
  */
 
-ns_hooktable_t *
-ns_hooktable_save(void);
+void
+ns_hooktable_init(ns_hooktable_t *hooktable);
 /*%
- * Returns a pointer to the current global hook table so it can
- * be restored after replacing it.
+ * Initialize a hook table.
  */
 
-void
-ns_hooktable_reset(ns_hooktable_t *hooktable);
+isc_result_t
+ns_hooktable_create(isc_mem_t *mctx, ns_hooktable_t **tablep);
 /*%
- * Set the global hooks table pointer to 'hooktable'.
- *
- * If 'hooktable' is NULL, restores the default global hook table.
+ * Allocate and initialize a hook table.
  */
 
 void
-ns_hooktable_init(ns_hooktable_t *hooktable);
+ns_hooktable_free(isc_mem_t *mctx, void **tablep);
 /*%
- * Initialize a hook table. If 'hooktable' is NULL, initialize
- * the global hooktable ns__hook_table.
+ * Free a hook table.
  */
 
+
 #endif /* NS_HOOKS_H */
index 93e1d8fdf44661da219c97ea8bb0c18e71b9d2d5..57d25f3f825b9681159f6047369d9778b5c82d9b 100644 (file)
@@ -238,10 +238,33 @@ static void
 log_noexistnodata(void *val, int level, const char *fmt, ...)
        ISC_FORMAT_PRINTF(3, 4);
 
-#define PROCESS_HOOK(...) \
-       NS_PROCESS_HOOK(ns__hook_table, __VA_ARGS__)
-#define PROCESS_HOOK_VOID(...) \
-       NS_PROCESS_HOOK_VOID(ns__hook_table, __VA_ARGS__)
+#define PROCESS_HOOK(_id, _qctx, ...)                                  \
+       do {                                                            \
+               ns_hooktable_t *_tab = ns__hook_table;                  \
+               query_ctx_t *_q = (_qctx);                              \
+               if (_q != NULL &&                                       \
+                   _q->client != NULL &&                               \
+                   _q->client->view != NULL &&                         \
+                   _q->client->view->hooktable != NULL)                \
+               {                                                       \
+                       _tab = _q->client->view->hooktable;             \
+               }                                                       \
+               NS_PROCESS_HOOK(_tab, _id, _q, __VA_ARGS__);            \
+       } while (false)
+
+#define PROCESS_HOOK_VOID(_id, _qctx, ...)                             \
+       do {                                                            \
+               ns_hooktable_t *_tab = ns__hook_table;                  \
+               query_ctx_t *_q = (_qctx);                              \
+               if (_q != NULL &&                                       \
+                   _q->client != NULL &&                               \
+                   _q->client->view != NULL &&                         \
+                   _q->client->view->hooktable != NULL)                \
+               {                                                       \
+                       _tab = _q->client->view->hooktable;             \
+               }                                                       \
+               NS_PROCESS_HOOK_VOID(_tab, _id, _q, __VA_ARGS__);       \
+       } while (false)
 
 /*
  * The functions defined below implement the query logic that previously lived
index f0a589ed15675f85e177f5fa630e35e61867fe5e..c6311ec39b37c5e4123d17afcb39e272b26c724a 100644 (file)
@@ -693,11 +693,12 @@ create_qctx_for_client(ns_client_t *client, query_ctx_t **qctxp) {
        ns_hooktable_init(&query_hooks);
        ns_hook_add(&query_hooks, NS_QUERY_SETUP_QCTX_INITIALIZED, &hook);
 
-       saved_hook_table = ns_hooktable_save();
+       saved_hook_table = ns__hook_table;
+       ns__hook_table = &query_hooks;
 
-       ns_hooktable_reset(&query_hooks);
        ns_query_start(client);
-       ns_hooktable_reset(saved_hook_table);
+
+       ns__hook_table = saved_hook_table;
 
        if (*qctxp == NULL) {
                return (ISC_R_NOMEMORY);
index d88de02f45a64a91280c4faeaea5fd5c98d28b1a..f8f59a23b3c23892c601e67e6f4a36d73d2ce89e 100644 (file)
@@ -84,6 +84,9 @@ static void
 run_sfcache_test(const ns__query_sfcache_test_params_t *test) {
        query_ctx_t *qctx = NULL;
        isc_result_t result;
+       ns_hook_t hook = {
+               .callback = ns_test_hook_catch_call,
+       };
 
        REQUIRE(test != NULL);
        REQUIRE(test->id.description != NULL);
@@ -93,14 +96,9 @@ run_sfcache_test(const ns__query_sfcache_test_params_t *test) {
        /*
         * Interrupt execution if ns_query_done() is called.
         */
-       ns_hook_t hook = {
-               .callback = ns_test_hook_catch_call,
-       };
-       ns_hooktable_t query_hooks;
 
-       ns_hooktable_init(&query_hooks);
-       ns_hook_add(&query_hooks, NS_QUERY_DONE_BEGIN, &hook);
-       ns_hooktable_reset(&query_hooks);
+       ns_hooktable_init(ns__hook_table);
+       ns_hook_add(ns__hook_table, NS_QUERY_DONE_BEGIN, &hook);
 
        /*
         * Construct a query context for a ./NS query with given flags.
@@ -283,6 +281,9 @@ static void
 run_start_test(const ns__query_start_test_params_t *test) {
        query_ctx_t *qctx = NULL;
        isc_result_t result;
+       ns_hook_t hook = {
+               .callback = ns_test_hook_catch_call,
+       };
 
        REQUIRE(test != NULL);
        REQUIRE(test->id.description != NULL);
@@ -294,16 +295,10 @@ run_start_test(const ns__query_start_test_params_t *test) {
        /*
         * Interrupt execution if query_lookup() or ns_query_done() is called.
         */
-       ns_hook_t hook = {
-               .callback = ns_test_hook_catch_call,
-       };
-       ns_hooktable_t query_hooks;
-
-       ns_hooktable_init(&query_hooks);
-       ns_hook_add(&query_hooks, NS_QUERY_LOOKUP_BEGIN, &hook);
-       ns_hook_add(&query_hooks, NS_QUERY_DONE_BEGIN, &hook);
 
-       ns_hooktable_reset(&query_hooks);
+       ns_hooktable_init(ns__hook_table);
+       ns_hook_add(ns__hook_table, NS_QUERY_LOOKUP_BEGIN, &hook);
+       ns_hook_add(ns__hook_table, NS_QUERY_DONE_BEGIN, &hook);
 
        /*
         * Construct a query context using the supplied parameters.