]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
refactor to support multiple module instances
authorEvan Hunt <each@isc.org>
Thu, 1 Nov 2018 02:02:29 +0000 (19:02 -0700)
committerEvan Hunt <each@isc.org>
Thu, 6 Dec 2018 18:29:12 +0000 (10:29 -0800)
- use a per-view module list instead of global hook_modules
- create an 'instance' pointer when registering modules, store it in
  the module structure, and use it as action_data when calling
  hook functions - this enables multiple module instances to be set
  up in parallel
- also some nomenclature changes and cleanup

bin/hooks/filter-aaaa.c
bin/named/server.c
lib/dns/include/dns/view.h
lib/dns/view.c
lib/ns/hooks.c
lib/ns/include/ns/hooks.h
lib/ns/include/ns/types.h
lib/ns/win32/libns.def

index ccc161d7b0ab684d251b7125f909580ba345e932..00846452629bd09afd37e8182c88715d366f9d7e 100644 (file)
@@ -46,6 +46,7 @@
 #include <dns/rdataset.h>
 #include <dns/result.h>
 #include <dns/types.h>
+#include <dns/view.h>
 
 #define CHECK(op)                                              \
        do {                                                    \
@@ -76,15 +77,27 @@ typedef struct filter_data {
        uint32_t flags;
 } filter_data_t;
 
-/*
- * Memory pool for use with persistent data.
- */
-static isc_mempool_t *datapool = NULL;
+typedef struct filter_instance {
+       ns_module_t *module;
+       isc_mem_t *mctx;
 
-/*
- * Hash table associating a client object with its persistent data.
- */
-static isc_ht_t *client_ht = NULL;
+       /*
+        * Memory pool for use with persistent data.
+        */
+       isc_mempool_t *datapool;
+
+       /*
+        * Hash table associating a client object with its persistent data.
+        */
+       isc_ht_t *ht;
+
+       /*
+        * Values configured when the module is loaded.
+        */
+       filter_aaaa_t v4_aaaa;
+       filter_aaaa_t v6_aaaa;
+       dns_acl_t *aaaa_acl;
+} filter_instance_t;
 
 /*
  * Per-client flags set by this module
@@ -100,62 +113,79 @@ static isc_ht_t *client_ht = NULL;
                                  NS_QUERYATTR_RECURSIONOK) != 0)
 
 /*
- * Hook registration structures: pointers to these structures will
- * be added to a hook table when this module is registered.
+ * Forward declarations of functions referenced in install_hooks().
  */
 static bool
 filter_qctx_initialize(void *arg, void *cbdata, isc_result_t *resp);
-static const ns_hook_t filter_init = {
-       .action = filter_qctx_initialize,
-       .action_data = &client_ht,
-};
-
 static bool
 filter_respond_begin(void *arg, void *cbdata, isc_result_t *resp);
-static const ns_hook_t filter_respbegin = {
-       .action = filter_respond_begin,
-       .action_data = &client_ht,
-};
-
 static bool
 filter_respond_any_found(void *arg, void *cbdata, isc_result_t *resp);
-static const ns_hook_t filter_respanyfound = {
-       .action = filter_respond_any_found,
-       .action_data = &client_ht,
-};
-
 static bool
 filter_prep_response_begin(void *arg, void *cbdata, isc_result_t *resp);
-static const ns_hook_t filter_prepresp = {
-       .action = filter_prep_response_begin,
-       .action_data = &client_ht,
-};
-
 static bool
 filter_query_done_send(void *arg, void *cbdata, isc_result_t *resp);
-static const ns_hook_t filter_donesend = {
-       .action = filter_query_done_send,
-       .action_data = &client_ht,
-};
-
 static bool
 filter_qctx_destroy(void *arg, void *cbdata, isc_result_t *resp);
-static const ns_hook_t filter_destroy = {
-       .action = filter_qctx_destroy,
-       .action_data = &client_ht,
-};
+
+/*%
+ * Register the functions to be called at each hook point in 'hooktable', using
+ * memory context 'mctx' for allocating copies of stack-allocated structures
+ * passed to ns_hook_add().  Make sure 'inst' will be passed as the 'cbdata'
+ * argument to every callback.
+ */
+static void
+install_hooks(ns_hooktable_t *hooktable, isc_mem_t *mctx,
+             filter_instance_t *inst)
+{
+       const ns_hook_t filter_init = {
+               .action = filter_qctx_initialize,
+               .action_data = inst,
+       };
+
+       const ns_hook_t filter_respbegin = {
+               .action = filter_respond_begin,
+               .action_data = inst,
+       };
+
+       const ns_hook_t filter_respanyfound = {
+               .action = filter_respond_any_found,
+               .action_data = inst,
+       };
+
+       const ns_hook_t filter_prepresp = {
+               .action = filter_prep_response_begin,
+               .action_data = inst,
+       };
+
+       const ns_hook_t filter_donesend = {
+               .action = filter_query_done_send,
+               .action_data = inst,
+       };
+
+       const ns_hook_t filter_destroy = {
+               .action = filter_qctx_destroy,
+               .action_data = inst,
+       };
+
+       ns_hook_add(hooktable, mctx, -
+                   NS_QUERY_QCTX_INITIALIZED, &filter_init);
+       ns_hook_add(hooktable, mctx,
+                   NS_QUERY_RESPOND_BEGIN, &filter_respbegin);
+       ns_hook_add(hooktable, mctx,
+                   NS_QUERY_RESPOND_ANY_FOUND, &filter_respanyfound);
+       ns_hook_add(hooktable, mctx,
+                   NS_QUERY_PREP_RESPONSE_BEGIN, &filter_prepresp);
+       ns_hook_add(hooktable, mctx,
+                   NS_QUERY_DONE_SEND, &filter_donesend);
+       ns_hook_add(hooktable, mctx,
+                   NS_QUERY_QCTX_DESTROYED, &filter_destroy);
+}
 
 /**
  ** Support for parsing of parameters and configuration of the module.
  **/
 
-/*
- * Values configured when the module is loaded.
- */
-static filter_aaaa_t v4_aaaa = NONE;
-static filter_aaaa_t v6_aaaa = NONE;
-static dns_acl_t *aaaa_acl = NULL;
-
 /*
  * Support for parsing of parameters.
  */
@@ -220,8 +250,8 @@ parse_filter_aaaa_on(const cfg_obj_t *param_obj, const char *param_name,
 }
 
 static isc_result_t
-parse_parameters(const char *parameters, const void *cfg,
-                void *actx, ns_hookctx_t *hctx)
+parse_parameters(filter_instance_t *inst, const char *parameters,
+                const void *cfg, void *actx, ns_hookctx_t *hctx)
 {
        isc_result_t result = ISC_R_SUCCESS;
        cfg_parser_t *parser = NULL;
@@ -236,18 +266,18 @@ parse_parameters(const char *parameters, const void *cfg,
        CHECK(cfg_parse_buffer(parser, &b, &cfg_type_parameters,
                               &param_obj));
 
-       CHECK(parse_filter_aaaa_on(param_obj, "filter-aaaa-on-v4", &v4_aaaa));
-       CHECK(parse_filter_aaaa_on(param_obj, "filter-aaaa-on-v6", &v6_aaaa));
+       CHECK(parse_filter_aaaa_on(param_obj, "filter-aaaa-on-v4",
+                                  &inst->v4_aaaa));
+       CHECK(parse_filter_aaaa_on(param_obj, "filter-aaaa-on-v6",
+                                  &inst->v6_aaaa));
 
-       obj = NULL;
        result = cfg_map_get(param_obj, "filter-aaaa", &obj);
        if (result == ISC_R_SUCCESS) {
                CHECK(cfg_acl_fromconfig(obj, (const cfg_obj_t *) cfg,
-                                        hctx->lctx,
-                                        (cfg_aclconfctx_t *) actx,
-                                        hctx->mctx, 0, &aaaa_acl));
+                                        hctx->lctx, (cfg_aclconfctx_t *) actx,
+                                        hctx->mctx, 0, &inst->aaaa_acl));
        } else {
-               CHECK(dns_acl_any(hctx->mctx, &aaaa_acl));
+               CHECK(dns_acl_any(hctx->mctx, &inst->aaaa_acl));
        }
 
  cleanup:
@@ -269,46 +299,36 @@ parse_parameters(const char *parameters, const void *cfg,
  **/
 
 /*
- * Called by ns_hookmodule_load() to register hook functions into
+ * Called by ns_module_load() to register hook functions into
  * a hook table.
  */
 isc_result_t
 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)
+             const void *cfg, void *actx, ns_hookctx_t *hctx,
+             ns_hooktable_t *hooktable, void **instp)
 {
+       filter_instance_t *inst = NULL;
        isc_result_t result;
 
-       UNUSED(instp);
 
        isc_log_write(hctx->lctx, NS_LOGCATEGORY_GENERAL,
                      NS_LOGMODULE_HOOKS, ISC_LOG_INFO,
-                     "loading 'filter-aaaa' "
+                     "registering 'filter-aaaa' "
                      "module from %s:%lu, %s parameters",
                      cfg_file, cfg_line, parameters != NULL ? "with" : "no");
 
+       inst = isc_mem_get(hctx->mctx, sizeof(*inst));
+       memset(inst, 0, sizeof(*inst));
+       isc_mem_attach(hctx->mctx, &inst->mctx);
+
        if (parameters != NULL) {
-               CHECK(parse_parameters(parameters, cfg, actx, hctx));
+               CHECK(parse_parameters(inst, parameters, cfg, actx, hctx));
        }
 
-       ns_hook_add(hooktable, hctx->mctx, NS_QUERY_QCTX_INITIALIZED,
-                   &filter_init);
-       ns_hook_add(hooktable, hctx->mctx, NS_QUERY_RESPOND_BEGIN,
-                   &filter_respbegin);
-       ns_hook_add(hooktable, hctx->mctx, NS_QUERY_RESPOND_ANY_FOUND,
-                   &filter_respanyfound);
-       ns_hook_add(hooktable, hctx->mctx, NS_QUERY_PREP_RESPONSE_BEGIN,
-                   &filter_prepresp);
-       ns_hook_add(hooktable, hctx->mctx, NS_QUERY_DONE_SEND,
-                   &filter_donesend);
-       ns_hook_add(hooktable, hctx->mctx, NS_QUERY_QCTX_DESTROYED,
-                   &filter_destroy);
-
        CHECK(isc_mempool_create(hctx->mctx, sizeof(filter_data_t),
-                                &datapool));
-
-       CHECK(isc_ht_init(&client_ht, hctx->mctx, 16));
+                                &inst->datapool));
+       CHECK(isc_ht_init(&inst->ht, hctx->mctx, 16));
 
        /*
         * Fill the mempool with 1K filter_aaaa state objects at
@@ -320,36 +340,45 @@ hook_register(const char *parameters,
         * so that they'll always be returned to the pool and not
         * freed until the pool is destroyed on shutdown.
         */
-       isc_mempool_setfillcount(datapool, 1024);
-       isc_mempool_setfreemax(datapool, UINT_MAX);
+       isc_mempool_setfillcount(inst->datapool, 1024);
+       isc_mempool_setfreemax(inst->datapool, UINT_MAX);
+
+       /*
+        * Set hook points in the view's hooktable.
+        */
+       install_hooks(hooktable, hctx->mctx, inst);
+
+       *instp = inst;
 
  cleanup:
-       if (result != ISC_R_SUCCESS) {
-               if (datapool != NULL) {
-                       isc_mempool_destroy(&datapool);
-               }
+       if (result != ISC_R_SUCCESS && inst != NULL) {
+               hook_destroy((void **) &inst);
        }
+
        return (result);
 }
 
 /*
- * Called by ns_hookmodule_unload_all(); frees memory allocated by
+ * Called by ns_module_unload(); frees memory allocated by
  * the module when it was registered.
  */
 void
 hook_destroy(void **instp) {
-       UNUSED(instp);
+       filter_instance_t *inst = (filter_instance_t *) *instp;
 
-       if (client_ht != NULL) {
-               isc_ht_destroy(&client_ht);
+       if (inst->ht != NULL) {
+               isc_ht_destroy(&inst->ht);
        }
-       if (datapool != NULL) {
-               isc_mempool_destroy(&datapool);
+       if (inst->datapool != NULL) {
+               isc_mempool_destroy(&inst->datapool);
        }
-       if (aaaa_acl != NULL) {
-               dns_acl_detach(&aaaa_acl);
+       if (inst->aaaa_acl != NULL) {
+               dns_acl_detach(&inst->aaaa_acl);
        }
 
+       isc_mem_putanddetach(&inst->mctx, inst, sizeof(*inst));
+       *instp = NULL;
+
        return;
 }
 
@@ -407,22 +436,22 @@ is_v6_client(ns_client_t *client) {
 }
 
 static filter_data_t *
-client_state_get(const query_ctx_t *qctx, isc_ht_t **htp) {
+client_state_get(const query_ctx_t *qctx, filter_instance_t *inst) {
        filter_data_t *client_state = NULL;
        isc_result_t result;
 
-       result = isc_ht_find(*htp, (const unsigned char *)&qctx->client,
+       result = isc_ht_find(inst->ht, (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) {
+client_state_create(const query_ctx_t *qctx, filter_instance_t *inst) {
        filter_data_t *client_state;
        isc_result_t result;
 
-       client_state = isc_mempool_get(datapool);
+       client_state = isc_mempool_get(inst->datapool);
        if (client_state == NULL) {
                return;
        }
@@ -430,25 +459,25 @@ client_state_create(const query_ctx_t *qctx, isc_ht_t **htp) {
        client_state->mode = NONE;
        client_state->flags = 0;
 
-       result = isc_ht_add(*htp, (const unsigned char *)&qctx->client,
+       result = isc_ht_add(inst->ht, (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);
+client_state_destroy(const query_ctx_t *qctx, filter_instance_t *inst) {
+       filter_data_t *client_state = client_state_get(qctx, inst);
        isc_result_t result;
 
        if (client_state == NULL) {
                return;
        }
 
-       result = isc_ht_delete(*htp, (const unsigned char *)&qctx->client,
+       result = isc_ht_delete(inst->ht, (const unsigned char *)&qctx->client,
                               sizeof(qctx->client));
        RUNTIME_CHECK(result == ISC_R_SUCCESS);
 
-       isc_mempool_put(datapool, client_state);
+       isc_mempool_put(inst->datapool, client_state);
 }
 
 /*%
@@ -570,14 +599,14 @@ process_section(const section_filter_t *filter) {
 static bool
 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_instance_t *inst = (filter_instance_t *) cbdata;
        filter_data_t *client_state;
 
        *resp = ISC_R_UNSET;
 
-       client_state = client_state_get(qctx, htp);
+       client_state = client_state_get(qctx, inst);
        if (client_state == NULL) {
-               client_state_create(qctx, htp);
+               client_state_create(qctx, inst);
        }
 
        return (false);
@@ -591,8 +620,8 @@ filter_qctx_initialize(void *arg, void *cbdata, isc_result_t *resp) {
 static bool
 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);
+       filter_instance_t *inst = (filter_instance_t *) cbdata;
+       filter_data_t *client_state = client_state_get(qctx, inst);
        isc_result_t result;
 
        *resp = ISC_R_UNSET;
@@ -601,19 +630,19 @@ filter_prep_response_begin(void *arg, void *cbdata, isc_result_t *resp) {
                return (false);
        }
 
-       if (v4_aaaa != NONE || v6_aaaa != NONE) {
+       if (inst->v4_aaaa != NONE || inst->v6_aaaa != NONE) {
                result = ns_client_checkaclsilent(qctx->client, NULL,
-                                                 aaaa_acl, true);
+                                                 inst->aaaa_acl, true);
                if (result == ISC_R_SUCCESS &&
-                   v4_aaaa != NONE &&
+                   inst->v4_aaaa != NONE &&
                    is_v4_client(qctx->client))
                {
-                       client_state->mode = v4_aaaa;
+                       client_state->mode = inst->v4_aaaa;
                } else if (result == ISC_R_SUCCESS &&
-                          v6_aaaa != NONE &&
+                          inst->v6_aaaa != NONE &&
                           is_v6_client(qctx->client))
                {
-                       client_state->mode = v6_aaaa;
+                       client_state->mode = inst->v6_aaaa;
                }
        }
 
@@ -630,8 +659,8 @@ filter_prep_response_begin(void *arg, void *cbdata, isc_result_t *resp) {
 static bool
 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);
+       filter_instance_t *inst = (filter_instance_t *) cbdata;
+       filter_data_t *client_state = client_state_get(qctx, inst);
        isc_result_t result = ISC_R_UNSET;
 
        *resp = ISC_R_UNSET;
@@ -734,8 +763,8 @@ filter_respond_begin(void *arg, void *cbdata, isc_result_t *resp) {
 static bool
 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);
+       filter_instance_t *inst = (filter_instance_t *) cbdata;
+       filter_data_t *client_state = client_state_get(qctx, inst);
 
        *resp = ISC_R_UNSET;
 
@@ -769,8 +798,8 @@ filter_respond_any_found(void *arg, void *cbdata, isc_result_t *resp) {
 static bool
 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);
+       filter_instance_t *inst = (filter_instance_t *) cbdata;
+       filter_data_t *client_state = client_state_get(qctx, inst);
 
        *resp = ISC_R_UNSET;
 
@@ -805,7 +834,7 @@ filter_query_done_send(void *arg, void *cbdata, isc_result_t *resp) {
 static bool
 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;
+       filter_instance_t *inst = (filter_instance_t *) cbdata;
 
        *resp = ISC_R_UNSET;
 
@@ -813,7 +842,7 @@ filter_qctx_destroy(void *arg, void *cbdata, isc_result_t *resp) {
                return (false);
        }
 
-       client_state_destroy(qctx, htp);
+       client_state_destroy(qctx, inst);
 
        return (false);
 }
index e4f1883edfb2baad327e22c17ce5fd5e61be659c..b6a43df85dbb1b3182914ab190e7c12b7b7fcc95 100644 (file)
@@ -1537,7 +1537,7 @@ configure_dyndb(const cfg_obj_t *dyndb, isc_mem_t *mctx,
 }
 
 static isc_result_t
-configure_hook(ns_hooktable_t *hooktable, const cfg_obj_t *hook,
+configure_hook(dns_view_t *view, const cfg_obj_t *hook,
               const cfg_obj_t *config, ns_hookctx_t *hctx)
 {
        isc_result_t result = ISC_R_SUCCESS;
@@ -1562,14 +1562,14 @@ configure_hook(ns_hooktable_t *hooktable, const cfg_obj_t *hook,
        if (obj != NULL && cfg_obj_isstring(obj)) {
                parameters = cfg_obj_asstring(obj);
        }
-       result = ns_hookmodule_load(library, parameters,
-                                   cfg_obj_file(obj), cfg_obj_line(obj),
-                                   config, named_g_aclconfctx,
-                                   hctx, hooktable);
+       result = ns_module_load(library, parameters,
+                               cfg_obj_file(obj), cfg_obj_line(obj),
+                               config, named_g_aclconfctx,
+                               hctx, view->modlist, view->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",
+                             "%s: module configuration failed: %s",
                              library, isc_result_totext(result));
        }
        return (result);
@@ -5314,6 +5314,9 @@ configure_view(dns_view_t *view, dns_viewlist_t *viewlist,
                CHECK(ns_hooktable_create(view->mctx,
                                  (ns_hooktable_t **) &view->hooktable));
                view->hooktable_free = ns_hooktable_free;
+
+               ns_modlist_create(view->mctx, (ns_modlist_t **)&view->modlist);
+               view->modlist_free = ns_modlist_free;
        }
 
        for (element = cfg_list_first(hook_list);
@@ -5322,7 +5325,7 @@ configure_view(dns_view_t *view, dns_viewlist_t *viewlist,
        {
                const cfg_obj_t *hook = cfg_listelt_value(element);
 
-               CHECK(configure_hook(view->hooktable, hook, config, hctx));
+               CHECK(configure_hook(view, hook, config, hctx));
        }
 #endif
 
@@ -8062,10 +8065,9 @@ load_configuration(const char *filename, named_server_t *server,
        CHECK(cfg_aclconfctx_create(named_g_mctx, &named_g_aclconfctx));
 
        /*
-        * Shut down all dyndb and hook module instances.
+        * Shut down all dyndb instances.
         */
        dns_dyndb_cleanup(false);
-       ns_hookmodule_unload_all();
 
        /*
         * Parse the global default pseudo-config file.
@@ -9547,10 +9549,9 @@ shutdown_server(isc_task_t *task, isc_event_t *event) {
        }
 
        /*
-        * Shut down all dyndb and hook module instances.
+        * Shut down all dyndb instances.
         */
        dns_dyndb_cleanup(true);
-       ns_hookmodule_unload_all();
 
        while ((nsc = ISC_LIST_HEAD(server->cachelist)) != NULL) {
                ISC_LIST_UNLINK(server->cachelist, nsc, link);
index c80dc5da5ee0caa6e99b1a8a2874c408d25b06f4..0fedb5d67fb2e25a9cca7266ace94120c49827a3 100644 (file)
@@ -236,8 +236,14 @@ struct dns_view {
        dns_dtmsgtype_t                 dttypes;        /* Dnstap message types
                                                           to log */
 
+       /* Registered module instances */
+       void                            *modlist;
+       void                            (*modlist_free)(isc_mem_t *, void **);
+
+       /* Hook table */
        void                            *hooktable;     /* ns_hooktable */
        void                            (*hooktable_free)(isc_mem_t *, void **);
+
 };
 
 #define DNS_VIEW_MAGIC                 ISC_MAGIC('V','i','e','w')
index 357f1026258a7caecbae0ba24f28f0130bf991d2..ca5900b3d2d68537f01e3bf271b5bac2479053bb 100644 (file)
@@ -256,6 +256,8 @@ dns_view_create(isc_mem_t *mctx, dns_rdataclass_t rdclass,
        view->dtenv = NULL;
        view->dttypes = 0;
 
+       view->modlist = NULL;
+       view->modlist_free = NULL;
        view->hooktable = NULL;
        view->hooktable_free = NULL;
 
@@ -551,6 +553,9 @@ destroy(dns_view_t *view) {
        if (view->hooktable != NULL && view->hooktable_free != NULL) {
                view->hooktable_free(view->mctx, &view->hooktable);
        }
+       if (view->modlist != NULL && view->modlist_free != NULL) {
+               view->modlist_free(view->mctx, &view->modlist);
+       }
        isc_mem_putanddetach(&view->mctx, view, sizeof(*view));
 }
 
index bc43f86abb5300337f50063e3051b520e33ef044..4573f6fc1ebd610d7d2c94ddd94477b29fadcf19 100644 (file)
                }                                               \
        } while (0)
 
-typedef struct ns_hook_module ns_hook_module_t;
-struct ns_hook_module {
-       isc_mem_t                       *mctx;
-       void                            *handle;
-       char                            *modpath;
-       ns_hook_register_t              *register_func;
-       ns_hook_destroy_t               *destroy_func;
-       void                            *inst;
-       LINK(ns_hook_module_t)          link;
+struct ns_module {
+       isc_mem_t               *mctx;
+       void                    *handle;
+       void                    *inst;
+       char                    *modpath;
+       ns_hook_register_t      *register_func;
+       ns_hook_destroy_t       *destroy_func;
+       LINK(ns_module_t)       link;
 };
 
 static ns_hooklist_t default_hooktable[NS_HOOKPOINTS_COUNT];
 LIBNS_EXTERNAL_DATA ns_hooktable_t *ns__hook_table = &default_hooktable;
 
-/*
- * List of hook modules.
- *
- * These are stored here so they can be cleaned up on shutdown.
- * (The order in which they are stored is not important.)
- */
-static ISC_LIST(ns_hook_module_t) hook_modules;
-static bool hook_modules_initialized = false;
-
 #if HAVE_DLFCN_H && HAVE_DLOPEN
 static isc_result_t
 load_symbol(void *handle, const char *modpath,
@@ -103,10 +93,10 @@ load_symbol(void *handle, const char *modpath,
 }
 
 static isc_result_t
-load_library(isc_mem_t *mctx, const char *modpath, ns_hook_module_t **hmodp) {
+load_library(isc_mem_t *mctx, const char *modpath, ns_module_t **hmodp) {
        isc_result_t result;
        void *handle = NULL;
-       ns_hook_module_t *hmod = NULL;
+       ns_module_t *hmod = NULL;
        ns_hook_register_t *register_func = NULL;
        ns_hook_destroy_t *destroy_func = NULL;
        ns_hook_version_t *version_func = NULL;
@@ -158,7 +148,6 @@ load_library(isc_mem_t *mctx, const char *modpath, ns_hook_module_t **hmodp) {
        hmod->modpath = isc_mem_strdup(hmod->mctx, modpath);
        hmod->register_func = register_func;
        hmod->destroy_func = destroy_func;
-       hmod->inst = NULL;
 
        ISC_LINK_INIT(hmod, link);
 
@@ -186,14 +175,21 @@ cleanup:
 }
 
 static void
-unload_library(ns_hook_module_t **hmodp) {
-       ns_hook_module_t *hmod = NULL;
+unload_library(ns_module_t **hmodp) {
+       ns_module_t *hmod = NULL;
 
        REQUIRE(hmodp != NULL && *hmodp != NULL);
 
        hmod = *hmodp;
        *hmodp = NULL;
 
+       isc_log_write(ns_lctx, NS_LOGCATEGORY_GENERAL,
+                     NS_LOGMODULE_HOOKS, ISC_LOG_INFO,
+                     "unloading module '%s'", hmod->modpath);
+
+       if (hmod->inst != NULL) {
+               hmod->destroy_func(&hmod->inst);
+       }
        if (hmod->handle != NULL) {
                (void) dlclose(hmod->handle);
        }
@@ -230,10 +226,10 @@ load_symbol(HMODULE handle, const char *modpath,
 }
 
 static isc_result_t
-load_library(isc_mem_t *mctx, const char *modpath, ns_hook_module_t **hmodp) {
+load_library(isc_mem_t *mctx, const char *modpath, ns_module_t **hmodp) {
        isc_result_t result;
        HMODULE handle;
-       ns_hook_module_t *hmod = NULL;
+       ns_module_t *hmod = NULL;
        ns_hook_register_t *register_func = NULL;
        ns_hook_destroy_t *destroy_func = NULL;
        ns_hook_version_t *version_func = NULL;
@@ -272,7 +268,6 @@ load_library(isc_mem_t *mctx, const char *modpath, ns_hook_module_t **hmodp) {
        hmod->modpath = isc_mem_strdup(hmod->mctx, modpath);
        hmod->register_func = register_func;
        hmod->destroy_func = destroy_func;
-       hmod->inst = NULL;
 
        ISC_LINK_INIT(hmod, link);
 
@@ -300,14 +295,21 @@ cleanup:
 }
 
 static void
-unload_library(ns_hook_module_t **hmodp) {
-       ns_hook_module_t *hmod = NULL;
+unload_library(ns_module_t **hmodp) {
+       ns_module_t *hmod = NULL;
 
        REQUIRE(hmodp != NULL && *hmodp != NULL);
 
        hmod = *hmodp;
        *hmodp = NULL;
 
+       isc_log_write(ns_lctx, NS_LOGCATEGORY_GENERAL,
+                     NS_LOGMODULE_HOOKS, ISC_LOG_INFO,
+                     "unloading module '%s'", hmod->modpath);
+
+       if (hmod->inst != NULL) {
+               hmod->destroy_func(&hmod->inst);
+       }
        if (hmod->handle != NULL) {
                FreeLibrary(hmod->handle);
        }
@@ -320,7 +322,7 @@ unload_library(ns_hook_module_t **hmodp) {
 }
 #else  /* HAVE_DLFCN_H || _WIN32 */
 static isc_result_t
-load_library(isc_mem_t *mctx, const char *modpath, ns_hook_module_t **hmodp) {
+load_library(isc_mem_t *mctx, const char *modpath, ns_module_t **hmodp) {
        UNUSED(mctx);
        UNUSED(modpath);
        UNUSED(hmodp);
@@ -333,22 +335,22 @@ load_library(isc_mem_t *mctx, const char *modpath, ns_hook_module_t **hmodp) {
 }
 
 static void
-unload_library(ns_hook_module_t **hmodp) {
+unload_library(ns_module_t **hmodp) {
        UNUSED(hmodp);
 }
 #endif /* HAVE_DLFCN_H */
 
 isc_result_t
-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)
+ns_module_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_modlist_t *modlist, ns_hooktable_t *hooktable)
 {
        isc_result_t result;
-       ns_hook_module_t *hmod = NULL;
+       ns_module_t *hmod = NULL;
 
-       REQUIRE(hook_modules_initialized);
        REQUIRE(NS_HOOKCTX_VALID(hctx));
+       REQUIRE(modlist != NULL);
        REQUIRE(hooktable != NULL);
 
        isc_log_write(ns_lctx, NS_LOGCATEGORY_GENERAL,
@@ -356,10 +358,15 @@ ns_hookmodule_load(const char *modpath, const char *parameters,
                      "loading module '%s'", modpath);
 
        CHECK(load_library(hctx->mctx, modpath, &hmod));
+
+       isc_log_write(ns_lctx, NS_LOGCATEGORY_GENERAL,
+                     NS_LOGMODULE_HOOKS, ISC_LOG_INFO,
+                     "registering module '%s'", modpath);
+
        CHECK(hmod->register_func(parameters, cfg_file, cfg_line,
                                  cfg, actx, hctx, hooktable, &hmod->inst));
 
-       ISC_LIST_APPEND(hook_modules, hmod, link);
+       ISC_LIST_APPEND(*modlist, hmod, link);
 
 cleanup:
        if (result != ISC_R_SUCCESS && hmod != NULL) {
@@ -369,28 +376,6 @@ cleanup:
        return (result);
 }
 
-void
-ns_hookmodule_unload_all(void) {
-       ns_hook_module_t *hmod = NULL, *prev = NULL;
-
-       if (!hook_modules_initialized) {
-               return;
-       }
-
-       hmod = ISC_LIST_TAIL(hook_modules);
-       while (hmod != NULL) {
-               prev = ISC_LIST_PREV(hmod, link);
-               ISC_LIST_UNLINK(hook_modules, hmod, link);
-               isc_log_write(ns_lctx, NS_LOGCATEGORY_GENERAL,
-                             NS_LOGMODULE_HOOKS, ISC_LOG_INFO,
-                             "unloading module '%s'", hmod->modpath);
-               hmod->destroy_func(&hmod->inst);
-               ENSURE(hmod->inst == NULL);
-               unload_library(&hmod);
-               hmod = prev;
-       }
-}
-
 isc_result_t
 ns_hook_createctx(isc_mem_t *mctx, ns_hookctx_t **hctxp) {
        ns_hookctx_t *hctx = NULL;
@@ -427,11 +412,6 @@ void
 ns_hooktable_init(ns_hooktable_t *hooktable) {
        int i;
 
-       if (!hook_modules_initialized) {
-               ISC_LIST_INIT(hook_modules);
-               hook_modules_initialized = true;
-       }
-
        for (i = 0; i < NS_HOOKPOINTS_COUNT; i++) {
                ISC_LIST_INIT((*hooktable)[i]);
        }
@@ -501,3 +481,38 @@ ns_hook_add(ns_hooktable_t *hooktable, isc_mem_t *mctx,
        ISC_LINK_INIT(copy, link);
        ISC_LIST_APPEND((*hooktable)[hookpoint], copy, link);
 }
+
+void
+ns_modlist_create(isc_mem_t *mctx, ns_modlist_t **listp) {
+       ns_modlist_t *modlist = NULL;
+
+       REQUIRE(listp != NULL && *listp == NULL);
+
+       modlist = isc_mem_get(mctx, sizeof(*modlist));
+       memset(modlist, 0, sizeof(*modlist));
+       ISC_LIST_INIT(*modlist);
+
+       *listp = modlist;
+}
+
+void
+ns_modlist_free(isc_mem_t *mctx, void **listp) {
+       ns_modlist_t *list = NULL;
+       ns_module_t *hmod = NULL, *next = NULL;
+
+       REQUIRE(listp != NULL && *listp != NULL);
+
+       list = *listp;
+       *listp = NULL;
+
+       for (hmod = ISC_LIST_HEAD(*list);
+            hmod != NULL;
+            hmod = next)
+       {
+               next = ISC_LIST_NEXT(hmod, link);
+               ISC_LIST_UNLINK(*list, hmod, link);
+               unload_library(&hmod);
+       }
+
+       isc_mem_put(mctx, list, sizeof(*list));
+}
index fe710c30c3b494eb43983c236e13dcd66a8bdab0..14af15d6950d6564f79493006ef6b8a02bb5a9b7 100644 (file)
@@ -253,14 +253,11 @@ typedef struct ns_hookctx {
 #define NS_HOOK_AGE 0
 #endif
 
-typedef isc_result_t ns_hook_register_t(const char *parameters,
-                                       const char *file,
-                                       unsigned long line,
-                                       const void *cfg,
-                                       void *actx,
-                                       ns_hookctx_t *hctx,
-                                       ns_hooktable_t *hooktable,
-                                       void **instp);
+typedef isc_result_t
+ns_hook_register_t(const char *parameters,
+                  const char *file, unsigned long line,
+                  const void *cfg, void *actx, ns_hookctx_t *hctx,
+                  ns_hooktable_t *hooktable, void **instp);
 /*%<
  * Called when registering a new module.
  *
@@ -308,13 +305,13 @@ ns_hook_destroyctx(ns_hookctx_t **hctxp);
  */
 
 isc_result_t
-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);
+ns_module_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_modlist_t *modlist, ns_hooktable_t *hooktable);
 /*%<
- * Load the hook module specified from the file 'modpath', using
- * parameters 'parameters'.
+ * Load the module specified from the file 'modpath', and
+ * register an instance using 'parameters'.
  *
  * 'cfg_file' and 'cfg_line' specify the location of the hook module
  * declaration in the configuration file.
@@ -325,12 +322,27 @@ ns_hookmodule_load(const char *modpath, const char *parameters,
  *
  * 'hctx' is the hook context and 'hooktable' is the hook table
  * into which hook points should be registered.
+ *
+ * 'instp' will be left pointing to the instance of the module
+ * created by the module's hook_register function.
+ */
+
+void
+ns_modlist_create(isc_mem_t *mctx, ns_modlist_t **listp);
+/*%<
+ * Create and initialize a module list.
+ */
+
+void
+ns_modlist_free(isc_mem_t *mctx, void **listp);
+/*%<
+ * Close each module in a module list, then free the list object.
  */
 
 void
-ns_hookmodule_unload_all(void);
+ns_hooktable_free(isc_mem_t *mctx, void **tablep);
 /*%<
- * Unload all currently loaded hook modules.
+ * Free a hook table.
  */
 
 void
@@ -362,11 +374,4 @@ ns_hooktable_create(isc_mem_t *mctx, ns_hooktable_t **tablep);
 /*%<
  * Allocate and initialize a hook table.
  */
-
-void
-ns_hooktable_free(isc_mem_t *mctx, void **tablep);
-/*%<
- * Free a hook table.
- */
-
 #endif /* NS_HOOKS_H */
index 06066e2942e46be0de9d21259a7f714e1d402dea..189c46bc793fb2e9f24229d62dd3d6baaa2388cb 100644 (file)
@@ -18,6 +18,8 @@ typedef struct ns_altsecret           ns_altsecret_t;
 typedef ISC_LIST(ns_altsecret_t)       ns_altsecretlist_t;
 typedef struct ns_client               ns_client_t;
 typedef struct ns_clientmgr            ns_clientmgr_t;
+typedef struct ns_module               ns_module_t;
+typedef ISC_LIST(ns_module_t)          ns_modlist_t;
 typedef struct ns_interface            ns_interface_t;
 typedef struct ns_interfacemgr         ns_interfacemgr_t;
 typedef struct ns_query                        ns_query_t;
index e870f859f1b2eeee9c0a64102eb24e542a5606f8..f5be0ac29042733ed15723339df22971b4dbb935 100644 (file)
@@ -46,8 +46,6 @@ ns_clientmgr_destroy
 ns_hook_add
 ns_hook_createctx
 ns_hook_destroyctx
-ns_hookmodule_load
-ns_hookmodule_unload_all
 ns_hooktable_create
 ns_hooktable_free
 ns_hooktable_init
@@ -79,6 +77,9 @@ ns_listenlist_default
 ns_listenlist_detach
 ns_log_init
 ns_log_setcontext
+ns_modlist_create
+ns_modlist_free
+ns_module_load
 ns_notify_start
 ns_query_cancel
 ns_query_done