2018-08-03 14:16:41 -07:00
|
|
|
/*
|
|
|
|
* Copyright (C) Internet Systems Consortium, Inc. ("ISC")
|
|
|
|
*
|
|
|
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
|
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
|
|
*
|
|
|
|
* See the COPYRIGHT file distributed with this work for additional
|
|
|
|
* information regarding copyright ownership.
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*! \file */
|
|
|
|
|
2019-02-12 15:59:54 +01:00
|
|
|
#include <errno.h>
|
|
|
|
#include <stdio.h>
|
2018-08-03 14:16:41 -07:00
|
|
|
#include <string.h>
|
|
|
|
|
|
|
|
#if HAVE_DLFCN_H
|
|
|
|
#include <dlfcn.h>
|
|
|
|
#elif _WIN32
|
|
|
|
#include <windows.h>
|
|
|
|
#endif
|
|
|
|
|
2019-02-12 15:59:54 +01:00
|
|
|
#include <isc/errno.h>
|
2018-09-14 12:32:36 -07:00
|
|
|
#include <isc/list.h>
|
|
|
|
#include <isc/log.h>
|
2018-08-03 14:16:41 -07:00
|
|
|
#include <isc/mem.h>
|
|
|
|
#include <isc/mutex.h>
|
2019-02-12 15:59:54 +01:00
|
|
|
#include <isc/print.h>
|
2018-08-03 14:16:41 -07:00
|
|
|
#include <isc/result.h>
|
2018-09-14 12:32:36 -07:00
|
|
|
#include <isc/platform.h>
|
2018-08-03 14:16:41 -07:00
|
|
|
#include <isc/util.h>
|
2018-09-14 12:32:36 -07:00
|
|
|
#include <isc/types.h>
|
2018-08-03 14:16:41 -07:00
|
|
|
|
2018-11-02 23:28:25 -07:00
|
|
|
#include <dns/view.h>
|
|
|
|
|
2018-08-03 14:16:41 -07:00
|
|
|
#include <ns/hooks.h>
|
|
|
|
#include <ns/log.h>
|
2018-09-14 12:32:36 -07:00
|
|
|
#include <ns/query.h>
|
2018-08-03 14:16:41 -07:00
|
|
|
|
|
|
|
#define CHECK(op) \
|
2018-09-14 12:32:36 -07:00
|
|
|
do { \
|
|
|
|
result = (op); \
|
|
|
|
if (result != ISC_R_SUCCESS) { \
|
|
|
|
goto cleanup; \
|
|
|
|
} \
|
2018-08-03 14:16:41 -07:00
|
|
|
} while (0)
|
|
|
|
|
2018-11-30 15:32:03 -08:00
|
|
|
struct ns_plugin {
|
2018-10-31 19:02:29 -07:00
|
|
|
isc_mem_t *mctx;
|
|
|
|
void *handle;
|
|
|
|
void *inst;
|
|
|
|
char *modpath;
|
2018-11-30 15:32:03 -08:00
|
|
|
ns_plugin_check_t *check_func;
|
|
|
|
ns_plugin_register_t *register_func;
|
|
|
|
ns_plugin_destroy_t *destroy_func;
|
|
|
|
LINK(ns_plugin_t) link;
|
2018-08-03 14:16:41 -07:00
|
|
|
};
|
|
|
|
|
2018-09-14 12:32:36 -07:00
|
|
|
static ns_hooklist_t default_hooktable[NS_HOOKPOINTS_COUNT];
|
|
|
|
LIBNS_EXTERNAL_DATA ns_hooktable_t *ns__hook_table = &default_hooktable;
|
2018-08-03 14:16:41 -07:00
|
|
|
|
2019-02-12 15:59:54 +01:00
|
|
|
isc_result_t
|
|
|
|
ns_plugin_expandpath(const char *src, char *dst, size_t dstsize) {
|
|
|
|
int result;
|
|
|
|
|
|
|
|
#ifndef WIN32
|
|
|
|
/*
|
|
|
|
* On Unix systems, differentiate between paths and filenames.
|
|
|
|
*/
|
|
|
|
if (strchr(src, '/') != NULL) {
|
|
|
|
/*
|
|
|
|
* 'src' is an absolute or relative path. Copy it verbatim.
|
|
|
|
*/
|
|
|
|
result = snprintf(dst, dstsize, "%s", src);
|
|
|
|
} else {
|
|
|
|
/*
|
|
|
|
* 'src' is a filename. Prepend default plugin directory path.
|
|
|
|
*/
|
|
|
|
result = snprintf(dst, dstsize, "%s/%s", NAMED_PLUGINDIR, src);
|
|
|
|
}
|
|
|
|
#else
|
|
|
|
/*
|
|
|
|
* On Windows, always copy 'src' do 'dst'.
|
|
|
|
*/
|
|
|
|
result = snprintf(dst, dstsize, "%s", src);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
if (result < 0) {
|
|
|
|
return (isc_errno_toresult(errno));
|
|
|
|
} else if ((size_t)result >= dstsize) {
|
|
|
|
return (ISC_R_NOSPACE);
|
|
|
|
} else {
|
|
|
|
return (ISC_R_SUCCESS);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-08-03 14:16:41 -07:00
|
|
|
#if HAVE_DLFCN_H && HAVE_DLOPEN
|
|
|
|
static isc_result_t
|
2018-09-14 12:32:36 -07:00
|
|
|
load_symbol(void *handle, const char *modpath,
|
2018-08-03 14:16:41 -07:00
|
|
|
const char *symbol_name, void **symbolp)
|
|
|
|
{
|
2018-09-19 23:38:23 -07:00
|
|
|
void *symbol = NULL;
|
2018-08-03 14:16:41 -07:00
|
|
|
|
|
|
|
REQUIRE(handle != NULL);
|
|
|
|
REQUIRE(symbolp != NULL && *symbolp == NULL);
|
|
|
|
|
2018-09-14 12:32:36 -07:00
|
|
|
/*
|
|
|
|
* Clear any pre-existing error conditions before running dlsym().
|
|
|
|
* (In this case, we expect dlsym() to return non-NULL values
|
|
|
|
* and will always return an error if it returns NULL, but
|
|
|
|
* this ensures that we'll report the correct error condition
|
|
|
|
* if there is one.)
|
|
|
|
*/
|
|
|
|
dlerror();
|
2018-08-03 14:16:41 -07:00
|
|
|
symbol = dlsym(handle, symbol_name);
|
|
|
|
if (symbol == NULL) {
|
2018-09-14 12:32:36 -07:00
|
|
|
const char *errmsg = dlerror();
|
2018-08-03 14:16:41 -07:00
|
|
|
if (errmsg == NULL) {
|
|
|
|
errmsg = "returned function pointer is NULL";
|
|
|
|
}
|
|
|
|
isc_log_write(ns_lctx, NS_LOGCATEGORY_GENERAL,
|
|
|
|
NS_LOGMODULE_HOOKS, ISC_LOG_ERROR,
|
2018-09-14 12:32:36 -07:00
|
|
|
"failed to look up symbol %s in "
|
2018-11-30 15:32:03 -08:00
|
|
|
"plugin '%s': %s",
|
2018-09-14 12:32:36 -07:00
|
|
|
symbol_name, modpath, errmsg);
|
2018-08-03 14:16:41 -07:00
|
|
|
return (ISC_R_FAILURE);
|
|
|
|
}
|
|
|
|
|
|
|
|
*symbolp = symbol;
|
|
|
|
|
|
|
|
return (ISC_R_SUCCESS);
|
|
|
|
}
|
|
|
|
|
|
|
|
static isc_result_t
|
2018-11-30 15:32:03 -08:00
|
|
|
load_plugin(isc_mem_t *mctx, const char *modpath, ns_plugin_t **pluginp) {
|
2018-08-03 14:16:41 -07:00
|
|
|
isc_result_t result;
|
|
|
|
void *handle = NULL;
|
2018-11-30 15:32:03 -08:00
|
|
|
ns_plugin_t *plugin = NULL;
|
|
|
|
ns_plugin_check_t *check_func = NULL;
|
|
|
|
ns_plugin_register_t *register_func = NULL;
|
|
|
|
ns_plugin_destroy_t *destroy_func = NULL;
|
|
|
|
ns_plugin_version_t *version_func = NULL;
|
2018-08-03 14:16:41 -07:00
|
|
|
int version, flags;
|
|
|
|
|
2018-11-30 15:32:03 -08:00
|
|
|
REQUIRE(pluginp != NULL && *pluginp == NULL);
|
2018-08-03 14:16:41 -07:00
|
|
|
|
2018-11-02 23:28:25 -07:00
|
|
|
flags = RTLD_LAZY | RTLD_LOCAL;
|
2018-12-19 12:24:59 +01:00
|
|
|
#if defined(RTLD_DEEPBIND) && !__SANITIZE_ADDRESS__
|
2018-08-03 14:16:41 -07:00
|
|
|
flags |= RTLD_DEEPBIND;
|
|
|
|
#endif
|
|
|
|
|
2018-09-14 12:32:36 -07:00
|
|
|
handle = dlopen(modpath, flags);
|
2018-08-03 14:16:41 -07:00
|
|
|
if (handle == NULL) {
|
2018-09-14 12:32:36 -07:00
|
|
|
const char *errmsg = dlerror();
|
|
|
|
if (errmsg == NULL) {
|
|
|
|
errmsg = "unknown error";
|
|
|
|
}
|
|
|
|
isc_log_write(ns_lctx, NS_LOGCATEGORY_GENERAL,
|
|
|
|
NS_LOGMODULE_HOOKS, ISC_LOG_ERROR,
|
2018-11-30 15:32:03 -08:00
|
|
|
"failed to dlopen() plugin '%s': %s",
|
2018-09-14 12:32:36 -07:00
|
|
|
modpath, errmsg);
|
|
|
|
return (ISC_R_FAILURE);
|
2018-08-03 14:16:41 -07:00
|
|
|
}
|
|
|
|
|
2018-11-30 15:32:03 -08:00
|
|
|
CHECK(load_symbol(handle, modpath, "plugin_version",
|
2018-08-03 14:16:41 -07:00
|
|
|
(void **)&version_func));
|
|
|
|
|
2018-09-14 12:32:36 -07:00
|
|
|
version = version_func();
|
2018-11-30 15:32:03 -08:00
|
|
|
if (version < (NS_PLUGIN_VERSION - NS_PLUGIN_AGE) ||
|
|
|
|
version > NS_PLUGIN_VERSION)
|
2018-08-03 14:16:41 -07:00
|
|
|
{
|
|
|
|
isc_log_write(ns_lctx, NS_LOGCATEGORY_GENERAL,
|
|
|
|
NS_LOGMODULE_HOOKS, ISC_LOG_ERROR,
|
2018-11-30 15:32:03 -08:00
|
|
|
"plugin API version mismatch: %d/%d",
|
|
|
|
version, NS_PLUGIN_VERSION);
|
2018-08-03 14:16:41 -07:00
|
|
|
CHECK(ISC_R_FAILURE);
|
|
|
|
}
|
|
|
|
|
2018-11-30 15:32:03 -08:00
|
|
|
CHECK(load_symbol(handle, modpath, "plugin_check",
|
2018-11-02 23:28:25 -07:00
|
|
|
(void **)&check_func));
|
2018-11-30 15:32:03 -08:00
|
|
|
CHECK(load_symbol(handle, modpath, "plugin_register",
|
2018-08-03 14:16:41 -07:00
|
|
|
(void **)®ister_func));
|
2018-11-30 15:32:03 -08:00
|
|
|
CHECK(load_symbol(handle, modpath, "plugin_destroy",
|
2018-08-03 14:16:41 -07:00
|
|
|
(void **)&destroy_func));
|
|
|
|
|
2018-11-30 15:32:03 -08:00
|
|
|
plugin = isc_mem_get(mctx, sizeof(*plugin));
|
|
|
|
memset(plugin, 0, sizeof(*plugin));
|
|
|
|
isc_mem_attach(mctx, &plugin->mctx);
|
|
|
|
plugin->handle = handle;
|
|
|
|
plugin->modpath = isc_mem_strdup(plugin->mctx, modpath);
|
|
|
|
plugin->check_func = check_func;
|
|
|
|
plugin->register_func = register_func;
|
|
|
|
plugin->destroy_func = destroy_func;
|
2018-08-03 14:16:41 -07:00
|
|
|
|
2018-11-30 15:32:03 -08:00
|
|
|
ISC_LINK_INIT(plugin, link);
|
2018-08-03 14:16:41 -07:00
|
|
|
|
2018-11-30 15:32:03 -08:00
|
|
|
*pluginp = plugin;
|
|
|
|
plugin = NULL;
|
2018-08-03 14:16:41 -07:00
|
|
|
|
|
|
|
cleanup:
|
|
|
|
if (result != ISC_R_SUCCESS) {
|
|
|
|
isc_log_write(ns_lctx, NS_LOGCATEGORY_GENERAL,
|
|
|
|
NS_LOGMODULE_HOOKS, ISC_LOG_ERROR,
|
|
|
|
"failed to dynamically load "
|
2018-11-30 15:32:03 -08:00
|
|
|
"plugin '%s': %s", modpath,
|
2018-09-14 12:32:36 -07:00
|
|
|
isc_result_totext(result));
|
2018-08-03 14:16:41 -07:00
|
|
|
|
2018-11-30 15:32:03 -08:00
|
|
|
if (plugin != NULL) {
|
|
|
|
isc_mem_putanddetach(&plugin->mctx, plugin,
|
|
|
|
sizeof(*plugin));
|
2018-08-03 14:16:41 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
if (handle != NULL) {
|
2018-09-14 12:32:36 -07:00
|
|
|
(void) dlclose(handle);
|
2018-08-03 14:16:41 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return (result);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2018-11-30 15:32:03 -08:00
|
|
|
unload_plugin(ns_plugin_t **pluginp) {
|
|
|
|
ns_plugin_t *plugin = NULL;
|
2018-08-03 14:16:41 -07:00
|
|
|
|
2018-11-30 15:32:03 -08:00
|
|
|
REQUIRE(pluginp != NULL && *pluginp != NULL);
|
2018-08-03 14:16:41 -07:00
|
|
|
|
2018-11-30 15:32:03 -08:00
|
|
|
plugin = *pluginp;
|
|
|
|
*pluginp = NULL;
|
2018-08-03 14:16:41 -07:00
|
|
|
|
2018-10-31 19:02:29 -07:00
|
|
|
isc_log_write(ns_lctx, NS_LOGCATEGORY_GENERAL,
|
2019-03-06 08:31:07 +01:00
|
|
|
NS_LOGMODULE_HOOKS, ISC_LOG_DEBUG(1),
|
2018-11-30 15:32:03 -08:00
|
|
|
"unloading plugin '%s'", plugin->modpath);
|
2018-10-31 19:02:29 -07:00
|
|
|
|
2018-11-30 15:32:03 -08:00
|
|
|
if (plugin->inst != NULL) {
|
|
|
|
plugin->destroy_func(&plugin->inst);
|
2018-10-31 19:02:29 -07:00
|
|
|
}
|
2018-11-30 15:32:03 -08:00
|
|
|
if (plugin->handle != NULL) {
|
|
|
|
(void) dlclose(plugin->handle);
|
2018-08-03 14:16:41 -07:00
|
|
|
}
|
2018-11-30 15:32:03 -08:00
|
|
|
if (plugin->modpath != NULL) {
|
|
|
|
isc_mem_free(plugin->mctx, plugin->modpath);
|
2018-08-03 14:16:41 -07:00
|
|
|
}
|
|
|
|
|
2018-11-30 15:32:03 -08:00
|
|
|
isc_mem_putanddetach(&plugin->mctx, plugin, sizeof(*plugin));
|
2018-08-03 14:16:41 -07:00
|
|
|
}
|
|
|
|
#elif _WIN32
|
|
|
|
static isc_result_t
|
2018-09-14 12:32:36 -07:00
|
|
|
load_symbol(HMODULE handle, const char *modpath,
|
2018-08-03 14:16:41 -07:00
|
|
|
const char *symbol_name, void **symbolp)
|
|
|
|
{
|
2018-09-19 23:38:23 -07:00
|
|
|
void *symbol = NULL;
|
2018-08-03 14:16:41 -07:00
|
|
|
|
|
|
|
REQUIRE(handle != NULL);
|
|
|
|
REQUIRE(symbolp != NULL && *symbolp == NULL);
|
|
|
|
|
|
|
|
symbol = GetProcAddress(handle, symbol_name);
|
|
|
|
if (symbol == NULL) {
|
|
|
|
int errstatus = GetLastError();
|
|
|
|
isc_log_write(ns_lctx, NS_LOGCATEGORY_GENERAL,
|
|
|
|
NS_LOGMODULE_HOOKS, ISC_LOG_ERROR,
|
|
|
|
"failed to look up symbol %s in "
|
2018-11-30 15:32:03 -08:00
|
|
|
"plugin '%s': %d",
|
2018-09-14 12:32:36 -07:00
|
|
|
symbol_name, modpath, errstatus);
|
2018-08-03 14:16:41 -07:00
|
|
|
return (ISC_R_FAILURE);
|
|
|
|
}
|
|
|
|
|
|
|
|
*symbolp = symbol;
|
|
|
|
|
|
|
|
return (ISC_R_SUCCESS);
|
|
|
|
}
|
|
|
|
|
|
|
|
static isc_result_t
|
2018-11-30 15:32:03 -08:00
|
|
|
load_plugin(isc_mem_t *mctx, const char *modpath, ns_plugin_t **pluginp) {
|
2018-08-03 14:16:41 -07:00
|
|
|
isc_result_t result;
|
|
|
|
HMODULE handle;
|
2018-11-30 15:32:03 -08:00
|
|
|
ns_plugin_t *plugin = NULL;
|
|
|
|
ns_plugin_register_t *register_func = NULL;
|
|
|
|
ns_plugin_destroy_t *destroy_func = NULL;
|
|
|
|
ns_plugin_version_t *version_func = NULL;
|
2018-08-03 14:16:41 -07:00
|
|
|
int version;
|
|
|
|
|
2018-11-30 15:32:03 -08:00
|
|
|
REQUIRE(pluginp != NULL && *pluginp == NULL);
|
2018-08-03 14:16:41 -07:00
|
|
|
|
2018-09-14 12:32:36 -07:00
|
|
|
handle = LoadLibraryA(modpath);
|
2018-08-03 14:16:41 -07:00
|
|
|
if (handle == NULL) {
|
|
|
|
CHECK(ISC_R_FAILURE);
|
|
|
|
}
|
|
|
|
|
2018-11-30 15:32:03 -08:00
|
|
|
CHECK(load_symbol(handle, modpath, "plugin_version",
|
2018-08-03 14:16:41 -07:00
|
|
|
(void **)&version_func));
|
|
|
|
|
2019-02-12 15:59:54 +01:00
|
|
|
version = version_func();
|
2018-11-30 15:32:03 -08:00
|
|
|
if (version < (NS_PLUGIN_VERSION - NS_PLUGIN_AGE) ||
|
|
|
|
version > NS_PLUGIN_VERSION)
|
2018-08-03 14:16:41 -07:00
|
|
|
{
|
|
|
|
isc_log_write(ns_lctx, NS_LOGCATEGORY_GENERAL,
|
|
|
|
NS_LOGMODULE_HOOKS, ISC_LOG_ERROR,
|
2018-11-30 15:32:03 -08:00
|
|
|
"plugin API version mismatch: %d/%d",
|
|
|
|
version, NS_PLUGIN_VERSION);
|
2018-08-03 14:16:41 -07:00
|
|
|
CHECK(ISC_R_FAILURE);
|
|
|
|
}
|
|
|
|
|
2018-11-30 15:32:03 -08:00
|
|
|
CHECK(load_symbol(handle, modpath, "plugin_register",
|
2018-08-03 14:16:41 -07:00
|
|
|
(void **)®ister_func));
|
2018-11-30 15:32:03 -08:00
|
|
|
CHECK(load_symbol(handle, modpath, "plugin_destroy",
|
2018-08-03 14:16:41 -07:00
|
|
|
(void **)&destroy_func));
|
|
|
|
|
2018-11-30 15:32:03 -08:00
|
|
|
plugin = isc_mem_get(mctx, sizeof(*plugin));
|
|
|
|
memset(plugin, 0, sizeof(*plugin));
|
|
|
|
isc_mem_attach(mctx, &plugin->mctx);
|
|
|
|
plugin->handle = handle;
|
|
|
|
plugin->modpath = isc_mem_strdup(plugin->mctx, modpath);
|
|
|
|
plugin->register_func = register_func;
|
|
|
|
plugin->destroy_func = destroy_func;
|
2018-08-03 14:16:41 -07:00
|
|
|
|
2018-11-30 15:32:03 -08:00
|
|
|
ISC_LINK_INIT(plugin, link);
|
2018-08-03 14:16:41 -07:00
|
|
|
|
2018-11-30 15:32:03 -08:00
|
|
|
*pluginp = plugin;
|
|
|
|
plugin = NULL;
|
2018-08-03 14:16:41 -07:00
|
|
|
|
|
|
|
cleanup:
|
|
|
|
if (result != ISC_R_SUCCESS) {
|
|
|
|
isc_log_write(ns_lctx, NS_LOGCATEGORY_GENERAL,
|
|
|
|
NS_LOGMODULE_HOOKS, ISC_LOG_ERROR,
|
|
|
|
"failed to dynamically load "
|
2018-11-30 15:32:03 -08:00
|
|
|
"plugin '%s': %d (%s)", modpath,
|
2018-08-03 14:16:41 -07:00
|
|
|
GetLastError(), isc_result_totext(result));
|
2018-09-14 12:32:36 -07:00
|
|
|
|
2018-11-30 15:32:03 -08:00
|
|
|
if (plugin != NULL) {
|
|
|
|
isc_mem_putanddetach(&plugin->mctx, plugin,
|
|
|
|
sizeof(*plugin));
|
2018-08-03 14:16:41 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
if (handle != NULL) {
|
|
|
|
FreeLibrary(handle);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return (result);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2018-11-30 15:32:03 -08:00
|
|
|
unload_plugin(ns_plugin_t **pluginp) {
|
|
|
|
ns_plugin_t *plugin = NULL;
|
2018-08-03 14:16:41 -07:00
|
|
|
|
2018-11-30 15:32:03 -08:00
|
|
|
REQUIRE(pluginp != NULL && *pluginp != NULL);
|
2018-08-03 14:16:41 -07:00
|
|
|
|
2018-11-30 15:32:03 -08:00
|
|
|
plugin = *pluginp;
|
|
|
|
*pluginp = NULL;
|
2018-08-03 14:16:41 -07:00
|
|
|
|
2018-10-31 19:02:29 -07:00
|
|
|
isc_log_write(ns_lctx, NS_LOGCATEGORY_GENERAL,
|
2019-03-06 08:31:07 +01:00
|
|
|
NS_LOGMODULE_HOOKS, ISC_LOG_DEBUG(1),
|
2018-11-30 15:32:03 -08:00
|
|
|
"unloading plugin '%s'", plugin->modpath);
|
2018-10-31 19:02:29 -07:00
|
|
|
|
2018-11-30 15:32:03 -08:00
|
|
|
if (plugin->inst != NULL) {
|
|
|
|
plugin->destroy_func(&plugin->inst);
|
2018-10-31 19:02:29 -07:00
|
|
|
}
|
2018-11-30 15:32:03 -08:00
|
|
|
if (plugin->handle != NULL) {
|
|
|
|
FreeLibrary(plugin->handle);
|
2018-08-03 14:16:41 -07:00
|
|
|
}
|
|
|
|
|
2018-11-30 15:32:03 -08:00
|
|
|
if (plugin->modpath != NULL) {
|
|
|
|
isc_mem_free(plugin->mctx, plugin->modpath);
|
2018-08-03 14:16:41 -07:00
|
|
|
}
|
|
|
|
|
2018-11-30 15:32:03 -08:00
|
|
|
isc_mem_putanddetach(&plugin->mctx, plugin, sizeof(*plugin));
|
2018-08-03 14:16:41 -07:00
|
|
|
}
|
|
|
|
#else /* HAVE_DLFCN_H || _WIN32 */
|
|
|
|
static isc_result_t
|
2018-11-30 15:32:03 -08:00
|
|
|
load_plugin(isc_mem_t *mctx, const char *modpath, ns_plugin_t **pluginp) {
|
2018-08-03 14:16:41 -07:00
|
|
|
UNUSED(mctx);
|
2018-09-14 12:32:36 -07:00
|
|
|
UNUSED(modpath);
|
2018-11-30 15:32:03 -08:00
|
|
|
UNUSED(pluginp);
|
2018-08-03 14:16:41 -07:00
|
|
|
|
|
|
|
isc_log_write(ns_lctx, NS_LOGCATEGORY_GENERAL,
|
|
|
|
NS_LOGMODULE_HOOKS, ISC_LOG_ERROR,
|
2018-11-30 15:32:03 -08:00
|
|
|
"plugin support is not implemented");
|
2018-08-03 14:16:41 -07:00
|
|
|
|
|
|
|
return (ISC_R_NOTIMPLEMENTED);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2018-11-30 15:32:03 -08:00
|
|
|
unload_plugin(ns_plugin_t **pluginp) {
|
|
|
|
UNUSED(pluginp);
|
2018-08-03 14:16:41 -07:00
|
|
|
}
|
|
|
|
#endif /* HAVE_DLFCN_H */
|
|
|
|
|
|
|
|
isc_result_t
|
2018-11-30 15:32:03 -08:00
|
|
|
ns_plugin_register(const char *modpath, const char *parameters,
|
|
|
|
const void *cfg, const char *cfg_file,
|
|
|
|
unsigned long cfg_line,
|
|
|
|
isc_mem_t *mctx, isc_log_t *lctx, void *actx,
|
|
|
|
dns_view_t *view)
|
2018-08-03 14:16:41 -07:00
|
|
|
{
|
|
|
|
isc_result_t result;
|
2018-11-30 15:32:03 -08:00
|
|
|
ns_plugin_t *plugin = NULL;
|
2018-08-03 14:16:41 -07:00
|
|
|
|
2018-11-30 10:12:04 -08:00
|
|
|
REQUIRE(mctx != NULL);
|
|
|
|
REQUIRE(lctx != NULL);
|
|
|
|
REQUIRE(view != NULL);
|
2018-08-03 14:16:41 -07:00
|
|
|
|
|
|
|
isc_log_write(ns_lctx, NS_LOGCATEGORY_GENERAL,
|
|
|
|
NS_LOGMODULE_HOOKS, ISC_LOG_INFO,
|
2018-11-30 15:32:03 -08:00
|
|
|
"loading plugin '%s'", modpath);
|
2018-08-03 14:16:41 -07:00
|
|
|
|
2018-11-30 15:32:03 -08:00
|
|
|
CHECK(load_plugin(mctx, modpath, &plugin));
|
2018-10-31 19:02:29 -07:00
|
|
|
|
|
|
|
isc_log_write(ns_lctx, NS_LOGCATEGORY_GENERAL,
|
|
|
|
NS_LOGMODULE_HOOKS, ISC_LOG_INFO,
|
2018-11-30 15:32:03 -08:00
|
|
|
"registering plugin '%s'", modpath);
|
2018-10-31 19:02:29 -07:00
|
|
|
|
2018-11-30 15:32:03 -08:00
|
|
|
CHECK(plugin->register_func(parameters, cfg, cfg_file, cfg_line,
|
|
|
|
mctx, lctx, actx, view->hooktable,
|
|
|
|
&plugin->inst));
|
2018-08-03 14:16:41 -07:00
|
|
|
|
2018-11-30 15:32:03 -08:00
|
|
|
ISC_LIST_APPEND(*(ns_plugins_t *)view->plugins, plugin, link);
|
2018-08-03 14:16:41 -07:00
|
|
|
|
|
|
|
cleanup:
|
2018-11-30 15:32:03 -08:00
|
|
|
if (result != ISC_R_SUCCESS && plugin != NULL) {
|
|
|
|
unload_plugin(&plugin);
|
2018-08-03 14:16:41 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
return (result);
|
|
|
|
}
|
|
|
|
|
2018-08-10 19:32:12 -07:00
|
|
|
isc_result_t
|
2018-11-30 15:32:03 -08:00
|
|
|
ns_plugin_check(const char *modpath, const char *parameters,
|
2018-11-30 10:12:04 -08:00
|
|
|
const void *cfg, const char *cfg_file, unsigned long cfg_line,
|
|
|
|
isc_mem_t *mctx, isc_log_t *lctx, void *actx)
|
2018-11-02 23:28:25 -07:00
|
|
|
{
|
|
|
|
isc_result_t result;
|
2018-11-30 15:32:03 -08:00
|
|
|
ns_plugin_t *plugin = NULL;
|
2018-11-02 23:28:25 -07:00
|
|
|
|
2018-11-30 15:32:03 -08:00
|
|
|
CHECK(load_plugin(mctx, modpath, &plugin));
|
2018-11-02 23:28:25 -07:00
|
|
|
|
2018-11-30 15:32:03 -08:00
|
|
|
result = plugin->check_func(parameters, cfg, cfg_file, cfg_line,
|
2018-11-30 10:12:04 -08:00
|
|
|
mctx, lctx, actx);
|
2018-11-02 23:28:25 -07:00
|
|
|
|
|
|
|
cleanup:
|
2018-11-30 15:32:03 -08:00
|
|
|
if (plugin != NULL) {
|
|
|
|
unload_plugin(&plugin);
|
2018-11-02 23:28:25 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
return (result);
|
|
|
|
}
|
|
|
|
|
2018-08-03 14:16:41 -07:00
|
|
|
void
|
|
|
|
ns_hooktable_init(ns_hooktable_t *hooktable) {
|
|
|
|
int i;
|
|
|
|
|
2018-09-14 12:32:36 -07:00
|
|
|
for (i = 0; i < NS_HOOKPOINTS_COUNT; i++) {
|
2018-08-03 14:16:41 -07:00
|
|
|
ISC_LIST_INIT((*hooktable)[i]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-08-12 11:19:36 -07:00
|
|
|
isc_result_t
|
|
|
|
ns_hooktable_create(isc_mem_t *mctx, ns_hooktable_t **tablep) {
|
2018-09-19 23:38:23 -07:00
|
|
|
ns_hooktable_t *hooktable = NULL;
|
2018-08-12 11:19:36 -07:00
|
|
|
|
|
|
|
REQUIRE(tablep != NULL && *tablep == NULL);
|
|
|
|
|
2018-09-14 12:32:36 -07:00
|
|
|
hooktable = isc_mem_get(mctx, sizeof(*hooktable));
|
2018-08-12 11:19:36 -07:00
|
|
|
|
|
|
|
ns_hooktable_init(hooktable);
|
|
|
|
|
|
|
|
*tablep = hooktable;
|
|
|
|
|
|
|
|
return (ISC_R_SUCCESS);
|
2018-08-03 14:16:41 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2018-08-12 11:19:36 -07:00
|
|
|
ns_hooktable_free(isc_mem_t *mctx, void **tablep) {
|
2018-09-19 23:38:23 -07:00
|
|
|
ns_hooktable_t *table = NULL;
|
|
|
|
ns_hook_t *hook = NULL, *next = NULL;
|
|
|
|
int i = 0;
|
2018-09-14 12:32:36 -07:00
|
|
|
|
2018-08-12 11:19:36 -07:00
|
|
|
REQUIRE(tablep != NULL && *tablep != NULL);
|
|
|
|
|
2018-09-14 12:32:36 -07:00
|
|
|
table = *tablep;
|
2018-08-12 11:19:36 -07:00
|
|
|
*tablep = NULL;
|
2018-09-19 23:38:23 -07:00
|
|
|
|
|
|
|
for (i = 0; i < NS_HOOKPOINTS_COUNT; i++) {
|
|
|
|
for (hook = ISC_LIST_HEAD((*table)[i]);
|
|
|
|
hook != NULL;
|
|
|
|
hook = next)
|
|
|
|
{
|
|
|
|
next = ISC_LIST_NEXT(hook, link);
|
|
|
|
ISC_LIST_UNLINK((*table)[i], hook, link);
|
|
|
|
if (hook->mctx != NULL) {
|
|
|
|
isc_mem_putanddetach(&hook->mctx,
|
|
|
|
hook, sizeof(*hook));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-09-14 12:32:36 -07:00
|
|
|
isc_mem_put(mctx, table, sizeof(*table));
|
2018-08-03 14:16:41 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2018-09-19 23:38:23 -07:00
|
|
|
ns_hook_add(ns_hooktable_t *hooktable, isc_mem_t *mctx,
|
|
|
|
ns_hookpoint_t hookpoint, const ns_hook_t *hook)
|
2018-08-03 14:16:41 -07:00
|
|
|
{
|
2018-09-19 23:38:23 -07:00
|
|
|
ns_hook_t *copy = NULL;
|
|
|
|
|
|
|
|
REQUIRE(hooktable != NULL);
|
|
|
|
REQUIRE(mctx != NULL);
|
2018-09-14 12:32:36 -07:00
|
|
|
REQUIRE(hookpoint < NS_HOOKPOINTS_COUNT);
|
2018-08-03 14:16:41 -07:00
|
|
|
REQUIRE(hook != NULL);
|
|
|
|
|
2018-09-19 23:38:23 -07:00
|
|
|
copy = isc_mem_get(mctx, sizeof(*copy));
|
|
|
|
memset(copy, 0, sizeof(*copy));
|
|
|
|
|
|
|
|
copy->action = hook->action;
|
|
|
|
copy->action_data = hook->action_data;
|
|
|
|
isc_mem_attach(mctx, ©->mctx);
|
2018-08-03 14:16:41 -07:00
|
|
|
|
2018-09-19 23:38:23 -07:00
|
|
|
ISC_LINK_INIT(copy, link);
|
|
|
|
ISC_LIST_APPEND((*hooktable)[hookpoint], copy, link);
|
2018-08-03 14:16:41 -07:00
|
|
|
}
|
2018-10-31 19:02:29 -07:00
|
|
|
|
|
|
|
void
|
2018-11-30 15:32:03 -08:00
|
|
|
ns_plugins_create(isc_mem_t *mctx, ns_plugins_t **listp) {
|
|
|
|
ns_plugins_t *plugins = NULL;
|
2018-10-31 19:02:29 -07:00
|
|
|
|
|
|
|
REQUIRE(listp != NULL && *listp == NULL);
|
|
|
|
|
2018-11-30 15:32:03 -08:00
|
|
|
plugins = isc_mem_get(mctx, sizeof(*plugins));
|
|
|
|
memset(plugins, 0, sizeof(*plugins));
|
|
|
|
ISC_LIST_INIT(*plugins);
|
2018-10-31 19:02:29 -07:00
|
|
|
|
2018-11-30 15:32:03 -08:00
|
|
|
*listp = plugins;
|
2018-10-31 19:02:29 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2018-11-30 15:32:03 -08:00
|
|
|
ns_plugins_free(isc_mem_t *mctx, void **listp) {
|
|
|
|
ns_plugins_t *list = NULL;
|
|
|
|
ns_plugin_t *plugin = NULL, *next = NULL;
|
2018-10-31 19:02:29 -07:00
|
|
|
|
|
|
|
REQUIRE(listp != NULL && *listp != NULL);
|
|
|
|
|
|
|
|
list = *listp;
|
|
|
|
*listp = NULL;
|
|
|
|
|
2018-11-30 15:32:03 -08:00
|
|
|
for (plugin = ISC_LIST_HEAD(*list);
|
|
|
|
plugin != NULL;
|
|
|
|
plugin = next)
|
2018-10-31 19:02:29 -07:00
|
|
|
{
|
2018-11-30 15:32:03 -08:00
|
|
|
next = ISC_LIST_NEXT(plugin, link);
|
|
|
|
ISC_LIST_UNLINK(*list, plugin, link);
|
|
|
|
unload_plugin(&plugin);
|
2018-10-31 19:02:29 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
isc_mem_put(mctx, list, sizeof(*list));
|
|
|
|
}
|