mirror of
https://github.com/isc-projects/bind9.git
synced 2026-05-28 04:34:54 -04:00
add a function for processing a list of configured plugins
Add a new libisccfg function, cfg_pluginlist_foreach(), which allows an arbitrary callback to be invoked for every "plugin" stanza present in a configuration object. Use this function for both loading plugins and checking their configuration in order to reduce duplication of configuration processing code present in bin/named/server.c and lib/bind9/check.c.
This commit is contained in:
parent
fd20f10d52
commit
4234968798
4 changed files with 169 additions and 77 deletions
|
|
@ -1535,45 +1535,6 @@ configure_dyndb(const cfg_obj_t *dyndb, isc_mem_t *mctx,
|
|||
name, isc_result_totext(result));
|
||||
return (result);
|
||||
}
|
||||
|
||||
static isc_result_t
|
||||
configure_plugin(dns_view_t *view, const cfg_obj_t *plugin,
|
||||
const cfg_obj_t *config)
|
||||
{
|
||||
isc_result_t result = ISC_R_SUCCESS;
|
||||
const cfg_obj_t *obj;
|
||||
const char *type, *library;
|
||||
const char *parameters = NULL;
|
||||
|
||||
/* Get the path to the plugin module. */
|
||||
obj = cfg_tuple_get(plugin, "type");
|
||||
type = cfg_obj_asstring(obj);
|
||||
|
||||
/* Only query plugins are supported currently. */
|
||||
if (strcasecmp(type, "query") != 0) {
|
||||
cfg_obj_log(obj, named_g_lctx, ISC_LOG_ERROR,
|
||||
"unsupported plugin type");
|
||||
return (ISC_R_FAILURE);
|
||||
}
|
||||
|
||||
library = cfg_obj_asstring(cfg_tuple_get(plugin, "library"));
|
||||
|
||||
obj = cfg_tuple_get(plugin, "parameters");
|
||||
if (obj != NULL && cfg_obj_isstring(obj)) {
|
||||
parameters = cfg_obj_asstring(obj);
|
||||
}
|
||||
result = ns_plugin_register(library, parameters, config,
|
||||
cfg_obj_file(obj), cfg_obj_line(obj),
|
||||
named_g_mctx, named_g_lctx,
|
||||
named_g_aclconfctx, view);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
|
||||
NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR,
|
||||
"%s: module configuration failed: %s",
|
||||
library, isc_result_totext(result));
|
||||
}
|
||||
return (result);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
|
@ -3686,6 +3647,35 @@ create_mapped_acl(void) {
|
|||
return (result);
|
||||
}
|
||||
|
||||
#ifdef HAVE_DLOPEN
|
||||
/*%
|
||||
* A callback for the cfg_pluginlist_foreach() call in configure_view() below.
|
||||
* If registering any plugin fails, registering subsequent ones is not
|
||||
* attempted.
|
||||
*/
|
||||
static isc_result_t
|
||||
register_one_plugin(const cfg_obj_t *config, const cfg_obj_t *obj,
|
||||
const char *plugin_path, const char *parameters,
|
||||
void *callback_data)
|
||||
{
|
||||
dns_view_t *view = callback_data;
|
||||
isc_result_t result;
|
||||
|
||||
result = ns_plugin_register(plugin_path, parameters, config,
|
||||
cfg_obj_file(obj), cfg_obj_line(obj),
|
||||
named_g_mctx, named_g_lctx,
|
||||
named_g_aclconfctx, view);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
|
||||
NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR,
|
||||
"%s: plugin configuration failed: %s",
|
||||
plugin_path, isc_result_totext(result));
|
||||
}
|
||||
|
||||
return (result);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Configure 'view' according to 'vconfig', taking defaults from 'config'
|
||||
* where values are missing in 'vconfig'.
|
||||
|
|
@ -5314,15 +5304,9 @@ configure_view(dns_view_t *view, dns_viewlist_t *viewlist,
|
|||
|
||||
ns_plugins_create(view->mctx, (ns_plugins_t **)&view->plugins);
|
||||
view->plugins_free = ns_plugins_free;
|
||||
}
|
||||
|
||||
for (element = cfg_list_first(plugin_list);
|
||||
element != NULL;
|
||||
element = cfg_list_next(element))
|
||||
{
|
||||
const cfg_obj_t *plugin = cfg_listelt_value(element);
|
||||
|
||||
CHECK(configure_plugin(view, plugin, config));
|
||||
CHECK(cfg_pluginlist_foreach(config, plugin_list, named_g_lctx,
|
||||
register_one_plugin, view));
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
|
|||
|
|
@ -3348,6 +3348,46 @@ check_rpz_catz(const char *rpz_catz, const cfg_obj_t *rpz_obj,
|
|||
return (result);
|
||||
}
|
||||
|
||||
#ifdef HAVE_DLOPEN
|
||||
/*%
|
||||
* Data structure used for the 'callback_data' argument to check_one_plugin().
|
||||
*/
|
||||
struct check_one_plugin_data {
|
||||
isc_mem_t *mctx;
|
||||
isc_log_t *lctx;
|
||||
cfg_aclconfctx_t *actx;
|
||||
isc_result_t *check_result;
|
||||
};
|
||||
|
||||
/*%
|
||||
* A callback for the cfg_pluginlist_foreach() call in check_viewconf() below.
|
||||
* Since the point is to check configuration of all plugins even when
|
||||
* processing some of them fails, always return ISC_R_SUCCESS and indicate any
|
||||
* check failures through the 'check_result' variable passed in via the
|
||||
* 'callback_data' structure.
|
||||
*/
|
||||
static isc_result_t
|
||||
check_one_plugin(const cfg_obj_t *config, const cfg_obj_t *obj,
|
||||
const char *plugin_path, const char *parameters,
|
||||
void *callback_data)
|
||||
{
|
||||
struct check_one_plugin_data *data = callback_data;
|
||||
isc_result_t result;
|
||||
|
||||
result = ns_plugin_check(plugin_path, parameters, config,
|
||||
cfg_obj_file(obj), cfg_obj_line(obj),
|
||||
data->mctx, data->lctx, data->actx);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
cfg_obj_log(obj, data->lctx, ISC_LOG_ERROR,
|
||||
"%s: plugin check failed: %s",
|
||||
plugin_path, isc_result_totext(result));
|
||||
*data->check_result = result;
|
||||
}
|
||||
|
||||
return (ISC_R_SUCCESS);
|
||||
}
|
||||
#endif
|
||||
|
||||
static isc_result_t
|
||||
check_viewconf(const cfg_obj_t *config, const cfg_obj_t *voptions,
|
||||
const char *viewname, dns_rdataclass_t vclass,
|
||||
|
|
@ -3677,39 +3717,18 @@ check_viewconf(const cfg_obj_t *config, const cfg_obj_t *voptions,
|
|||
}
|
||||
|
||||
#ifdef HAVE_DLOPEN
|
||||
for (element = cfg_list_first(plugin_list);
|
||||
element != NULL;
|
||||
element = cfg_list_next(element))
|
||||
{
|
||||
const cfg_obj_t *plugin = cfg_listelt_value(element);
|
||||
struct check_one_plugin_data check_one_plugin_data = {
|
||||
.mctx = mctx,
|
||||
.lctx = logctx,
|
||||
.actx = actx,
|
||||
.check_result = &tresult,
|
||||
};
|
||||
|
||||
const char *type, *library;
|
||||
const char *parameters = NULL;
|
||||
|
||||
/* Get the path to the plugin module. */
|
||||
obj = cfg_tuple_get(plugin, "type");
|
||||
type = cfg_obj_asstring(obj);
|
||||
|
||||
/* Only query plugins are supported currently. */
|
||||
if (strcasecmp(type, "query") != 0) {
|
||||
cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
|
||||
"unsupported plugin type");
|
||||
return (ISC_R_FAILURE);
|
||||
}
|
||||
|
||||
library = cfg_obj_asstring(cfg_tuple_get(plugin, "library"));
|
||||
|
||||
obj = cfg_tuple_get(plugin, "parameters");
|
||||
if (obj != NULL && cfg_obj_isstring(obj)) {
|
||||
parameters = cfg_obj_asstring(obj);
|
||||
}
|
||||
tresult = ns_plugin_check(library, parameters, config,
|
||||
cfg_obj_file(obj), cfg_obj_line(obj),
|
||||
mctx, logctx, actx);
|
||||
(void)cfg_pluginlist_foreach(config, plugin_list, logctx,
|
||||
check_one_plugin,
|
||||
&check_one_plugin_data);
|
||||
if (tresult != ISC_R_SUCCESS) {
|
||||
cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
|
||||
"%s: module check failed: %s",
|
||||
library, isc_result_totext(tresult));
|
||||
result = tresult;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -555,6 +555,47 @@ const char *
|
|||
cfg_map_nextclause(const cfg_type_t *map, const void **clauses,
|
||||
unsigned int *idx);
|
||||
|
||||
typedef isc_result_t
|
||||
(pluginlist_cb_t)(const cfg_obj_t *config, const cfg_obj_t *obj,
|
||||
const char *plugin_path, const char *parameters,
|
||||
void *callback_data);
|
||||
/*%<
|
||||
* Function prototype for the callback used with cfg_pluginlist_foreach().
|
||||
* Called once for each element of the list passed to cfg_pluginlist_foreach().
|
||||
* If this callback returns anything else than #ISC_R_SUCCESS, no further list
|
||||
* elements will be processed.
|
||||
*
|
||||
* \li 'config' - the 'config' object passed to cfg_pluginlist_foreach()
|
||||
* \li 'obj' - object representing the specific "plugin" stanza to be processed
|
||||
* \li 'plugin_path' - path to the shared object with plugin code
|
||||
* \li 'parameters' - configuration text for the plugin
|
||||
* \li 'callback_data' - the pointer passed to cfg_pluginlist_foreach()
|
||||
*/
|
||||
|
||||
isc_result_t
|
||||
cfg_pluginlist_foreach(const cfg_obj_t *config, const cfg_obj_t *list,
|
||||
isc_log_t *lctx, pluginlist_cb_t callback,
|
||||
void *callback_data);
|
||||
/*%<
|
||||
* For every "plugin" stanza present in 'list' (which in turn is a part of
|
||||
* 'config'), invoke the given 'callback', passing 'callback_data' to it along
|
||||
* with a fixed set of arguments (see the definition of the #pluginlist_cb_t
|
||||
* type). Use logging context 'lctx' for logging error messages. Interrupt
|
||||
* processing if 'callback' returns something else than #ISC_R_SUCCESS for any
|
||||
* element of 'list'.
|
||||
*
|
||||
* Requires:
|
||||
*
|
||||
* \li 'config' is not NULL
|
||||
* \li 'callback' is not NULL
|
||||
*
|
||||
* Returns:
|
||||
*
|
||||
* \li #ISC_R_SUCCESS if 'callback' returned #ISC_R_SUCCESS for all elements of
|
||||
* 'list'
|
||||
* \li first 'callback' return value which was not #ISC_R_SUCCESS otherwise
|
||||
*/
|
||||
|
||||
ISC_LANG_ENDDECLS
|
||||
|
||||
#endif /* ISCCFG_CFG_H */
|
||||
|
|
|
|||
|
|
@ -3457,3 +3457,51 @@ cfg_parser_mapadd(cfg_parser_t *pctx, cfg_obj_t *mapobj,
|
|||
|
||||
return (result);
|
||||
}
|
||||
|
||||
isc_result_t
|
||||
cfg_pluginlist_foreach(const cfg_obj_t *config, const cfg_obj_t *list,
|
||||
isc_log_t *lctx, pluginlist_cb_t *callback,
|
||||
void *callback_data)
|
||||
{
|
||||
isc_result_t result = ISC_R_SUCCESS;
|
||||
const cfg_listelt_t *element;
|
||||
|
||||
REQUIRE(config != NULL);
|
||||
REQUIRE(callback != NULL);
|
||||
|
||||
for (element = cfg_list_first(list);
|
||||
element != NULL;
|
||||
element = cfg_list_next(element))
|
||||
{
|
||||
const cfg_obj_t *plugin = cfg_listelt_value(element);
|
||||
const cfg_obj_t *obj;
|
||||
const char *type, *library;
|
||||
const char *parameters = NULL;
|
||||
|
||||
/* Get the path to the plugin module. */
|
||||
obj = cfg_tuple_get(plugin, "type");
|
||||
type = cfg_obj_asstring(obj);
|
||||
|
||||
/* Only query plugins are supported currently. */
|
||||
if (strcasecmp(type, "query") != 0) {
|
||||
cfg_obj_log(obj, lctx, ISC_LOG_ERROR,
|
||||
"unsupported plugin type");
|
||||
return (ISC_R_FAILURE);
|
||||
}
|
||||
|
||||
library = cfg_obj_asstring(cfg_tuple_get(plugin, "library"));
|
||||
|
||||
obj = cfg_tuple_get(plugin, "parameters");
|
||||
if (obj != NULL && cfg_obj_isstring(obj)) {
|
||||
parameters = cfg_obj_asstring(obj);
|
||||
}
|
||||
|
||||
result = callback(config, obj, library, parameters,
|
||||
callback_data);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return (result);
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue