mirror of
https://github.com/isc-projects/bind9.git
synced 2026-04-15 22:09:31 -04:00
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
This commit is contained in:
parent
9df0bdc99c
commit
b94945e606
8 changed files with 283 additions and 219 deletions
|
|
@ -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,
|
||||
¶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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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')
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
}
|
||||
|
||||
|
|
|
|||
143
lib/ns/hooks.c
143
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));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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_hookmodule_unload_all(void);
|
||||
ns_modlist_create(isc_mem_t *mctx, ns_modlist_t **listp);
|
||||
/*%<
|
||||
* Unload all currently loaded hook modules.
|
||||
* 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_hooktable_free(isc_mem_t *mctx, void **tablep);
|
||||
/*%<
|
||||
* 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 */
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Reference in a new issue