From: Evan Hunt Date: Thu, 1 Nov 2018 02:02:29 +0000 (-0700) Subject: refactor to support multiple module instances X-Git-Tag: v9.13.5~7^2~8 X-Git-Url: http://git.ipfire.org/gitweb/index.cgi?a=commitdiff_plain;h=b94945e60663fb2a3d6641ea41d720500fb39fb4;p=thirdparty%2Fbind9.git refactor to support multiple module instances - 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 --- diff --git a/bin/hooks/filter-aaaa.c b/bin/hooks/filter-aaaa.c index ccc161d7b0a..00846452629 100644 --- a/bin/hooks/filter-aaaa.c +++ b/bin/hooks/filter-aaaa.c @@ -46,6 +46,7 @@ #include #include #include +#include #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, ¶m_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); } diff --git a/bin/named/server.c b/bin/named/server.c index e4f1883edfb..b6a43df85db 100644 --- a/bin/named/server.c +++ b/bin/named/server.c @@ -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); diff --git a/lib/dns/include/dns/view.h b/lib/dns/include/dns/view.h index c80dc5da5ee..0fedb5d67fb 100644 --- a/lib/dns/include/dns/view.h +++ b/lib/dns/include/dns/view.h @@ -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') diff --git a/lib/dns/view.c b/lib/dns/view.c index 357f1026258..ca5900b3d2d 100644 --- a/lib/dns/view.c +++ b/lib/dns/view.c @@ -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)); } diff --git a/lib/ns/hooks.c b/lib/ns/hooks.c index bc43f86abb5..4573f6fc1eb 100644 --- a/lib/ns/hooks.c +++ b/lib/ns/hooks.c @@ -42,29 +42,19 @@ } \ } 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)); +} diff --git a/lib/ns/include/ns/hooks.h b/lib/ns/include/ns/hooks.h index fe710c30c3b..14af15d6950 100644 --- a/lib/ns/include/ns/hooks.h +++ b/lib/ns/include/ns/hooks.h @@ -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 */ diff --git a/lib/ns/include/ns/types.h b/lib/ns/include/ns/types.h index 06066e2942e..189c46bc793 100644 --- a/lib/ns/include/ns/types.h +++ b/lib/ns/include/ns/types.h @@ -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; diff --git a/lib/ns/win32/libns.def b/lib/ns/win32/libns.def index e870f859f1b..f5be0ac2904 100644 --- a/lib/ns/win32/libns.def +++ b/lib/ns/win32/libns.def @@ -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