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
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'.
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
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,
}
#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);
-
- 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);
+ struct check_one_plugin_data check_one_plugin_data = {
+ .mctx = mctx,
+ .lctx = logctx,
+ .actx = actx,
+ .check_result = &tresult,
+ };
+
+ (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;
}
}
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 */
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);
+}