mirror of
https://github.com/isc-projects/bind9.git
synced 2026-05-28 04:34:54 -04:00
add hook statement to configuration parser
- allow multiple "hook" statements at global or view level
- add "optional bracketed text" type for optional parameter list
- load hook module from specified path rather than hardcoded path
- add a hooktable pointer (and a callback for freeing it) to the
view structure
- change the hooktable functions so they no longer update ns__hook_table
by default, and modify PROCESS_HOOK so it uses the view hooktable, if
set, rather than ns__hook_table. (ns__hook_table is retained for
use by unit tests.)
- update the filter-aaaa system test to load filter-aaaa.so
- add a prereq script to check for dlopen support before running
the filter-aaaa system test
not yet done:
- configuration parameters are not being passed to the filter-aaaa
module; the filter-aaaa ACL and filter-aaaa-on-{v4,v6} settings are
still stored in dns_view
This commit is contained in:
parent
e2ac439e28
commit
d2f4644388
22 changed files with 289 additions and 87 deletions
|
|
@ -77,10 +77,19 @@ hook_register(const char *parameters, const char *file, unsigned long line,
|
|||
UNUSED(parameters);
|
||||
UNUSED(instp);
|
||||
|
||||
isc_log_write(hctx->lctx, NS_LOGCATEGORY_GENERAL,
|
||||
NS_LOGMODULE_HOOKS, ISC_LOG_INFO,
|
||||
"loading params for 'filter-aaaa' module from %s:%lu",
|
||||
file, line);
|
||||
if (parameters != NULL) {
|
||||
isc_log_write(hctx->lctx, NS_LOGCATEGORY_GENERAL,
|
||||
NS_LOGMODULE_HOOKS, ISC_LOG_INFO,
|
||||
"loading params for 'filter-aaaa' "
|
||||
"module from %s:%lu",
|
||||
file, line);
|
||||
} else {
|
||||
isc_log_write(hctx->lctx, NS_LOGCATEGORY_GENERAL,
|
||||
NS_LOGMODULE_HOOKS, ISC_LOG_INFO,
|
||||
"loading 'filter-aaaa' "
|
||||
"module from %s:%lu, no parameters",
|
||||
file, line);
|
||||
}
|
||||
|
||||
/*
|
||||
* TODO:
|
||||
|
|
|
|||
|
|
@ -1535,6 +1535,50 @@ configure_dyndb(const cfg_obj_t *dyndb, isc_mem_t *mctx,
|
|||
name, isc_result_totext(result));
|
||||
return (result);
|
||||
}
|
||||
|
||||
static isc_result_t
|
||||
configure_hook(ns_hooktable_t *hooktable, const cfg_obj_t *hook,
|
||||
ns_hookctx_t *hctx)
|
||||
{
|
||||
isc_result_t result = ISC_R_SUCCESS;
|
||||
const cfg_obj_t *obj;
|
||||
const char *type, *library;
|
||||
|
||||
/* Get the path to the hook module. */
|
||||
obj = cfg_tuple_get(hook, "type");
|
||||
type = cfg_obj_asstring(obj);
|
||||
|
||||
/* Only query hooks are supported currently. */
|
||||
if (strcasecmp(type, "query") != 0) {
|
||||
cfg_obj_log(obj, named_g_lctx, ISC_LOG_ERROR,
|
||||
"unsupported hook type");
|
||||
return (ISC_R_FAILURE);
|
||||
}
|
||||
|
||||
library = cfg_obj_asstring(cfg_tuple_get(hook, "library"));
|
||||
|
||||
obj = cfg_tuple_get(hook, "parameters");
|
||||
if (obj != NULL && cfg_obj_isstring(obj)) {
|
||||
result = ns_hookmodule_load(library,
|
||||
cfg_obj_asstring(obj),
|
||||
cfg_obj_file(obj),
|
||||
cfg_obj_line(obj),
|
||||
hctx, hooktable);
|
||||
} else {
|
||||
result = ns_hookmodule_load(library, NULL,
|
||||
cfg_obj_file(hook),
|
||||
cfg_obj_line(hook),
|
||||
hctx, 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",
|
||||
library, isc_result_totext(result));
|
||||
}
|
||||
return (result);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
|
@ -3675,7 +3719,7 @@ configure_view(dns_view_t *view, dns_viewlist_t *viewlist,
|
|||
const cfg_obj_t *dlvobj = NULL;
|
||||
unsigned int dlzargc;
|
||||
char **dlzargv;
|
||||
const cfg_obj_t *dyndb_list;
|
||||
const cfg_obj_t *dyndb_list, *hook_list;
|
||||
const cfg_obj_t *disabled;
|
||||
const cfg_obj_t *obj, *obj2;
|
||||
const cfg_listelt_t *element;
|
||||
|
|
@ -5271,10 +5315,11 @@ configure_view(dns_view_t *view, dns_viewlist_t *viewlist,
|
|||
* Load DynDB modules.
|
||||
*/
|
||||
dyndb_list = NULL;
|
||||
if (voptions != NULL)
|
||||
if (voptions != NULL) {
|
||||
(void)cfg_map_get(voptions, "dyndb", &dyndb_list);
|
||||
else
|
||||
} else {
|
||||
(void)cfg_map_get(config, "dyndb", &dyndb_list);
|
||||
}
|
||||
|
||||
#ifdef HAVE_DLOPEN
|
||||
for (element = cfg_list_first(dyndb_list);
|
||||
|
|
@ -5294,21 +5339,37 @@ configure_view(dns_view_t *view, dns_viewlist_t *viewlist,
|
|||
|
||||
CHECK(configure_dyndb(dyndb, mctx, dctx));
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* XXX:
|
||||
* temporary! this forces loading of filter-aaaa.so from the
|
||||
* current working directory, if present. later this will
|
||||
* happen via configuration as dyndb does above. we don't
|
||||
* bother checking whether it succeeded; if it doesn't,
|
||||
* filter-aaaa simply won't work.
|
||||
* Load hook modules.
|
||||
*/
|
||||
if (hctx == NULL) {
|
||||
CHECK(ns_hook_createctx(mctx, &hctx));
|
||||
hook_list = NULL;
|
||||
if (voptions != NULL) {
|
||||
(void)cfg_map_get(voptions, "hook", &hook_list);
|
||||
} else {
|
||||
(void)cfg_map_get(config, "hook", &hook_list);
|
||||
}
|
||||
|
||||
#ifdef HAVE_DLOPEN
|
||||
for (element = cfg_list_first(hook_list);
|
||||
element != NULL;
|
||||
element = cfg_list_next(element))
|
||||
{
|
||||
const cfg_obj_t *hook = cfg_listelt_value(element);
|
||||
|
||||
if (view->hooktable == NULL) {
|
||||
ns_hooktable_create(view->mctx,
|
||||
(ns_hooktable_t **) &view->hooktable);
|
||||
view->hooktable_free = ns_hooktable_free;
|
||||
}
|
||||
|
||||
if (hctx == NULL) {
|
||||
CHECK(ns_hook_createctx(mctx, &hctx));
|
||||
}
|
||||
|
||||
CHECK(configure_hook(view->hooktable, hook, hctx));
|
||||
}
|
||||
ns_hooktable_init(NULL);
|
||||
(void) ns_hookmodule_load("/tmp/filter-aaaa.so", "", "<none>", 0,
|
||||
hctx, NULL);
|
||||
#endif
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -25,6 +25,8 @@ options {
|
|||
minimal-responses no;
|
||||
};
|
||||
|
||||
hook query "../../../../hooks/lib/filter-aaaa.so";
|
||||
|
||||
key rndc_key {
|
||||
secret "1234abcd8765";
|
||||
algorithm hmac-sha256;
|
||||
|
|
|
|||
|
|
@ -25,6 +25,8 @@ options {
|
|||
minimal-responses no;
|
||||
};
|
||||
|
||||
hook query "../../../../hooks/lib/filter-aaaa.so";
|
||||
|
||||
key rndc_key {
|
||||
secret "1234abcd8765";
|
||||
algorithm hmac-sha256;
|
||||
|
|
|
|||
|
|
@ -25,6 +25,8 @@ options {
|
|||
minimal-responses no;
|
||||
};
|
||||
|
||||
hook query "../../../../hooks/lib/filter-aaaa.so";
|
||||
|
||||
key rndc_key {
|
||||
secret "1234abcd8765";
|
||||
algorithm hmac-sha256;
|
||||
|
|
|
|||
|
|
@ -25,6 +25,8 @@ options {
|
|||
minimal-responses no;
|
||||
};
|
||||
|
||||
hook query "../../../../hooks/lib/filter-aaaa.so";
|
||||
|
||||
key rndc_key {
|
||||
secret "1234abcd8765";
|
||||
algorithm hmac-sha256;
|
||||
|
|
|
|||
|
|
@ -25,6 +25,8 @@ options {
|
|||
minimal-responses no;
|
||||
};
|
||||
|
||||
hook query "../../../../hooks/lib/filter-aaaa.so";
|
||||
|
||||
key rndc_key {
|
||||
secret "1234abcd8765";
|
||||
algorithm hmac-sha256;
|
||||
|
|
|
|||
|
|
@ -25,6 +25,8 @@ options {
|
|||
minimal-responses no;
|
||||
};
|
||||
|
||||
hook query "../../../../hooks/lib/filter-aaaa.so";
|
||||
|
||||
key rndc_key {
|
||||
secret "1234abcd8765";
|
||||
algorithm hmac-sha256;
|
||||
|
|
|
|||
|
|
@ -25,6 +25,8 @@ options {
|
|||
minimal-responses no;
|
||||
};
|
||||
|
||||
hook query "../../../../hooks/lib/filter-aaaa.so";
|
||||
|
||||
key rndc_key {
|
||||
secret "1234abcd8765";
|
||||
algorithm hmac-sha256;
|
||||
|
|
|
|||
|
|
@ -25,6 +25,8 @@ options {
|
|||
minimal-responses no;
|
||||
};
|
||||
|
||||
hook query "../../../../hooks/lib/filter-aaaa.so";
|
||||
|
||||
key rndc_key {
|
||||
secret "1234abcd8765";
|
||||
algorithm hmac-sha256;
|
||||
|
|
|
|||
|
|
@ -30,6 +30,8 @@ options {
|
|||
minimal-responses no;
|
||||
};
|
||||
|
||||
hook query "../../../../hooks/lib/filter-aaaa.so";
|
||||
|
||||
key rndc_key {
|
||||
secret "1234abcd8765";
|
||||
algorithm hmac-sha256;
|
||||
|
|
|
|||
19
bin/tests/system/filter-aaaa/prereq.sh
Normal file
19
bin/tests/system/filter-aaaa/prereq.sh
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
#!/bin/sh
|
||||
#
|
||||
# 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.
|
||||
|
||||
SYSTEMTESTTOP=..
|
||||
. $SYSTEMTESTTOP/conf.sh
|
||||
|
||||
$FEATURETEST --have-dlopen || {
|
||||
echo_i "dlopen() not supported - skipping filter-aaaa test"
|
||||
exit 255
|
||||
}
|
||||
exit 0
|
||||
|
|
@ -238,6 +238,9 @@ struct dns_view {
|
|||
dns_dtenv_t *dtenv; /* Dnstap environment */
|
||||
dns_dtmsgtype_t dttypes; /* Dnstap message types
|
||||
to log */
|
||||
|
||||
void *hooktable; /* ns_hooktable */
|
||||
void (*hooktable_free)(isc_mem_t *, void **);
|
||||
};
|
||||
|
||||
#define DNS_VIEW_MAGIC ISC_MAGIC('V','i','e','w')
|
||||
|
|
|
|||
|
|
@ -259,6 +259,9 @@ dns_view_create(isc_mem_t *mctx, dns_rdataclass_t rdclass,
|
|||
view->dtenv = NULL;
|
||||
view->dttypes = 0;
|
||||
|
||||
view->hooktable = NULL;
|
||||
view->hooktable_free = NULL;
|
||||
|
||||
isc_mutex_init(&view->new_zone_lock);
|
||||
|
||||
result = dns_order_create(view->mctx, &view->order);
|
||||
|
|
@ -550,6 +553,9 @@ destroy(dns_view_t *view) {
|
|||
isc_mutex_destroy(&view->lock);
|
||||
isc_mem_free(view->mctx, view->nta_file);
|
||||
isc_mem_free(view->mctx, view->name);
|
||||
if (view->hooktable != NULL && view->hooktable_free != NULL) {
|
||||
view->hooktable_free(view->mctx, &view->hooktable);
|
||||
}
|
||||
isc_mem_putanddetach(&view->mctx, view, sizeof(*view));
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -302,6 +302,7 @@ LIBISCCFG_EXTERNAL_DATA extern cfg_type_t cfg_type_astring;
|
|||
LIBISCCFG_EXTERNAL_DATA extern cfg_type_t cfg_type_ustring;
|
||||
LIBISCCFG_EXTERNAL_DATA extern cfg_type_t cfg_type_sstring;
|
||||
LIBISCCFG_EXTERNAL_DATA extern cfg_type_t cfg_type_bracketed_text;
|
||||
LIBISCCFG_EXTERNAL_DATA extern cfg_type_t cfg_type_optional_bracketed_text;
|
||||
LIBISCCFG_EXTERNAL_DATA extern cfg_type_t cfg_type_sockaddr;
|
||||
LIBISCCFG_EXTERNAL_DATA extern cfg_type_t cfg_type_sockaddrdscp;
|
||||
LIBISCCFG_EXTERNAL_DATA extern cfg_type_t cfg_type_netaddr;
|
||||
|
|
|
|||
|
|
@ -109,6 +109,7 @@ static cfg_type_t cfg_type_dnstap;
|
|||
static cfg_type_t cfg_type_dnstapoutput;
|
||||
static cfg_type_t cfg_type_dyndb;
|
||||
static cfg_type_t cfg_type_filter_aaaa;
|
||||
static cfg_type_t cfg_type_hook;
|
||||
static cfg_type_t cfg_type_ixfrdifftype;
|
||||
static cfg_type_t cfg_type_key;
|
||||
static cfg_type_t cfg_type_logfile;
|
||||
|
|
@ -1007,6 +1008,7 @@ namedconf_or_view_clauses[] = {
|
|||
{ "dyndb", &cfg_type_dyndb, CFG_CLAUSEFLAG_MULTI },
|
||||
{ "key", &cfg_type_key, CFG_CLAUSEFLAG_MULTI },
|
||||
{ "managed-keys", &cfg_type_managedkeys, CFG_CLAUSEFLAG_MULTI },
|
||||
{ "hook", &cfg_type_hook, CFG_CLAUSEFLAG_MULTI },
|
||||
{ "server", &cfg_type_server, CFG_CLAUSEFLAG_MULTI },
|
||||
{ "trusted-keys", &cfg_type_dnsseckeys, CFG_CLAUSEFLAG_MULTI },
|
||||
{ "zone", &cfg_type_zone, CFG_CLAUSEFLAG_MULTI },
|
||||
|
|
@ -2394,6 +2396,29 @@ static cfg_type_t cfg_type_dyndb = {
|
|||
&cfg_rep_tuple, dyndb_fields
|
||||
};
|
||||
|
||||
/*%
|
||||
* The "hook" statement syntax.
|
||||
* Currently only one hook type is supported: query.
|
||||
*/
|
||||
|
||||
static const char *hook_enums[] = {
|
||||
"query", NULL
|
||||
};
|
||||
static cfg_type_t cfg_type_hooktype = {
|
||||
"hooktype", cfg_parse_enum, cfg_print_ustring, cfg_doc_enum,
|
||||
&cfg_rep_string, hook_enums
|
||||
};
|
||||
static cfg_tuplefielddef_t hook_fields[] = {
|
||||
{ "type", &cfg_type_hooktype, 0 },
|
||||
{ "library", &cfg_type_astring, 0 },
|
||||
{ "parameters", &cfg_type_optional_bracketed_text, 0 },
|
||||
{ NULL, NULL, 0 }
|
||||
};
|
||||
static cfg_type_t cfg_type_hook = {
|
||||
"hook", cfg_parse_tuple, cfg_print_tuple, cfg_doc_tuple,
|
||||
&cfg_rep_tuple, hook_fields
|
||||
};
|
||||
|
||||
/*%
|
||||
* Clauses that can be found within the 'key' statement.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -1134,7 +1134,6 @@ doc_btext(cfg_printer_t *pctx, const cfg_type_t *type) {
|
|||
cfg_print_cstr(pctx, "{ <unspecified-text> }");
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
cfg_is_enum(const char *s, const char *const *enums) {
|
||||
const char * const *p;
|
||||
|
|
@ -1275,6 +1274,51 @@ LIBISCCFG_EXTERNAL_DATA cfg_type_t cfg_type_bracketed_text = {
|
|||
&cfg_rep_string, NULL
|
||||
};
|
||||
|
||||
/*
|
||||
* Optional bracketed text
|
||||
*/
|
||||
static isc_result_t
|
||||
parse_optional_btext(cfg_parser_t *pctx, const cfg_type_t *type,
|
||||
cfg_obj_t **ret)
|
||||
{
|
||||
isc_result_t result;
|
||||
|
||||
UNUSED(type);
|
||||
|
||||
CHECK(cfg_peektoken(pctx, ISC_LEXOPT_BTEXT));
|
||||
if (pctx->token.type == isc_tokentype_btext) {
|
||||
CHECK(cfg_parse_obj(pctx, &cfg_type_bracketed_text, ret));
|
||||
} else {
|
||||
CHECK(cfg_parse_obj(pctx, &cfg_type_void, ret));
|
||||
}
|
||||
cleanup:
|
||||
return (result);
|
||||
}
|
||||
|
||||
static void
|
||||
print_optional_btext(cfg_printer_t *pctx, const cfg_obj_t *obj) {
|
||||
if (obj->type == &cfg_type_void) {
|
||||
return;
|
||||
}
|
||||
|
||||
pctx->indent++;
|
||||
cfg_print_cstr(pctx, "{");
|
||||
cfg_print_chars(pctx, obj->value.string.base, obj->value.string.length);
|
||||
print_close(pctx);
|
||||
}
|
||||
|
||||
static void
|
||||
doc_optional_btext(cfg_printer_t *pctx, const cfg_type_t *type) {
|
||||
UNUSED(type);
|
||||
|
||||
cfg_print_cstr(pctx, "[ { <unspecified-text> } ]");
|
||||
}
|
||||
|
||||
cfg_type_t cfg_type_optional_bracketed_text = {
|
||||
"optional_btext", parse_optional_btext, print_optional_btext,
|
||||
doc_optional_btext, NULL, NULL
|
||||
};
|
||||
|
||||
/*
|
||||
* Booleans
|
||||
*/
|
||||
|
|
@ -1485,7 +1529,7 @@ print_list(cfg_printer_t *pctx, const cfg_obj_t *obj) {
|
|||
|
||||
isc_result_t
|
||||
cfg_parse_bracketed_list(cfg_parser_t *pctx, const cfg_type_t *type,
|
||||
cfg_obj_t **ret)
|
||||
cfg_obj_t **ret)
|
||||
{
|
||||
isc_result_t result;
|
||||
|
||||
|
|
|
|||
|
|
@ -335,10 +335,6 @@ ns_hookmodule_load(const char *libname, const char *parameters,
|
|||
isc_result_t result;
|
||||
ns_hook_module_t *module = NULL;
|
||||
|
||||
if (hooktable == NULL) {
|
||||
hooktable = ns__hook_table;
|
||||
}
|
||||
|
||||
REQUIRE(NS_HOOKCTX_VALID(hctx));
|
||||
|
||||
isc_log_write(ns_lctx, NS_LOGCATEGORY_GENERAL,
|
||||
|
|
@ -420,27 +416,32 @@ ns_hooktable_init(ns_hooktable_t *hooktable) {
|
|||
|
||||
RUNTIME_CHECK(isc_once_do(&once, init_modules) == ISC_R_SUCCESS);
|
||||
|
||||
if (hooktable == NULL) {
|
||||
hooktable = ns__hook_table;
|
||||
}
|
||||
|
||||
for (i = 0; i < NS_QUERY_HOOKS_COUNT; i++) {
|
||||
ISC_LIST_INIT((*hooktable)[i]);
|
||||
}
|
||||
}
|
||||
|
||||
ns_hooktable_t *
|
||||
ns_hooktable_save() {
|
||||
return (ns__hook_table);
|
||||
isc_result_t
|
||||
ns_hooktable_create(isc_mem_t *mctx, ns_hooktable_t **tablep) {
|
||||
ns_hooktable_t *hooktable;
|
||||
|
||||
REQUIRE(tablep != NULL && *tablep == NULL);
|
||||
|
||||
hooktable = isc_mem_get(mctx, sizeof(ns_hooktable_t));
|
||||
|
||||
ns_hooktable_init(hooktable);
|
||||
|
||||
*tablep = hooktable;
|
||||
|
||||
return (ISC_R_SUCCESS);
|
||||
}
|
||||
|
||||
void
|
||||
ns_hooktable_reset(ns_hooktable_t *hooktable) {
|
||||
if (hooktable != NULL) {
|
||||
ns__hook_table = hooktable;
|
||||
} else {
|
||||
ns__hook_table = &hooktab;
|
||||
}
|
||||
ns_hooktable_free(isc_mem_t *mctx, void **tablep) {
|
||||
REQUIRE(tablep != NULL && *tablep != NULL);
|
||||
|
||||
isc_mem_put(mctx, *tablep, sizeof(ns_hooktable_t));
|
||||
*tablep = NULL;
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
|||
|
|
@ -196,13 +196,13 @@ typedef struct ns_hook {
|
|||
ISC_LINK(struct ns_hook) link;
|
||||
} ns_hook_t;
|
||||
|
||||
/*
|
||||
* ns__hook_table is a globally visible pointer to the active hook
|
||||
* table. It's initialized to point to 'hooktab', which is the default
|
||||
* global hook table.
|
||||
*/
|
||||
typedef ISC_LIST(ns_hook_t) ns_hooklist_t;
|
||||
typedef ns_hooklist_t ns_hooktable_t[NS_QUERY_HOOKS_COUNT];
|
||||
|
||||
/*
|
||||
* ns__hook_table is a global hook table, which is used if view->hooktable
|
||||
* is NULL. It's intended only for use by unit tests.
|
||||
*/
|
||||
LIBNS_EXTERNAL_DATA extern ns_hooktable_t *ns__hook_table;
|
||||
|
||||
/*!
|
||||
|
|
@ -281,7 +281,7 @@ typedef int ns_hook_version_t(unsigned int *flags);
|
|||
* true, we continue processing.
|
||||
*/
|
||||
#define _NS_PROCESS_HOOK(table, id, data, ...) \
|
||||
if (table != NULL) { \
|
||||
if (table != NULL) { \
|
||||
ns_hook_t *_hook = ISC_LIST_HEAD((*table)[id]); \
|
||||
isc_result_t _result; \
|
||||
\
|
||||
|
|
@ -298,9 +298,9 @@ typedef int ns_hook_version_t(unsigned int *flags);
|
|||
} \
|
||||
}
|
||||
|
||||
#define NS_PROCESS_HOOK(table, id, data) \
|
||||
#define NS_PROCESS_HOOK(table, id, data, ...) \
|
||||
_NS_PROCESS_HOOK(table, id, data, _result)
|
||||
#define NS_PROCESS_HOOK_VOID(table, id, data) \
|
||||
#define NS_PROCESS_HOOK_VOID(table, id, data, ...) \
|
||||
_NS_PROCESS_HOOK(table, id, data)
|
||||
|
||||
isc_result_t
|
||||
|
|
@ -321,8 +321,7 @@ ns_hook_add(ns_hooktable_t *hooktable, ns_hookpoint_t hookpoint,
|
|||
ns_hook_t *hook);
|
||||
/*%
|
||||
* Append hook function 'hook' to the list of hooks at 'hookpoint' in
|
||||
* 'hooktable'. If 'hooktable' is NULL, the global hook table
|
||||
* ns__hook_table is used.
|
||||
* 'hooktable'.
|
||||
*
|
||||
* Requires:
|
||||
*\li 'hook' is not NULL
|
||||
|
|
@ -331,26 +330,23 @@ ns_hook_add(ns_hooktable_t *hooktable, ns_hookpoint_t hookpoint,
|
|||
*
|
||||
*/
|
||||
|
||||
ns_hooktable_t *
|
||||
ns_hooktable_save(void);
|
||||
/*%
|
||||
* Returns a pointer to the current global hook table so it can
|
||||
* be restored after replacing it.
|
||||
*/
|
||||
|
||||
void
|
||||
ns_hooktable_reset(ns_hooktable_t *hooktable);
|
||||
/*%
|
||||
* Set the global hooks table pointer to 'hooktable'.
|
||||
*
|
||||
* If 'hooktable' is NULL, restores the default global hook table.
|
||||
*/
|
||||
|
||||
void
|
||||
ns_hooktable_init(ns_hooktable_t *hooktable);
|
||||
/*%
|
||||
* Initialize a hook table. If 'hooktable' is NULL, initialize
|
||||
* the global hooktable ns__hook_table.
|
||||
* Initialize a hook table.
|
||||
*/
|
||||
|
||||
isc_result_t
|
||||
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 */
|
||||
|
|
|
|||
|
|
@ -238,10 +238,33 @@ static void
|
|||
log_noexistnodata(void *val, int level, const char *fmt, ...)
|
||||
ISC_FORMAT_PRINTF(3, 4);
|
||||
|
||||
#define PROCESS_HOOK(...) \
|
||||
NS_PROCESS_HOOK(ns__hook_table, __VA_ARGS__)
|
||||
#define PROCESS_HOOK_VOID(...) \
|
||||
NS_PROCESS_HOOK_VOID(ns__hook_table, __VA_ARGS__)
|
||||
#define PROCESS_HOOK(_id, _qctx, ...) \
|
||||
do { \
|
||||
ns_hooktable_t *_tab = ns__hook_table; \
|
||||
query_ctx_t *_q = (_qctx); \
|
||||
if (_q != NULL && \
|
||||
_q->client != NULL && \
|
||||
_q->client->view != NULL && \
|
||||
_q->client->view->hooktable != NULL) \
|
||||
{ \
|
||||
_tab = _q->client->view->hooktable; \
|
||||
} \
|
||||
NS_PROCESS_HOOK(_tab, _id, _q, __VA_ARGS__); \
|
||||
} while (false)
|
||||
|
||||
#define PROCESS_HOOK_VOID(_id, _qctx, ...) \
|
||||
do { \
|
||||
ns_hooktable_t *_tab = ns__hook_table; \
|
||||
query_ctx_t *_q = (_qctx); \
|
||||
if (_q != NULL && \
|
||||
_q->client != NULL && \
|
||||
_q->client->view != NULL && \
|
||||
_q->client->view->hooktable != NULL) \
|
||||
{ \
|
||||
_tab = _q->client->view->hooktable; \
|
||||
} \
|
||||
NS_PROCESS_HOOK_VOID(_tab, _id, _q, __VA_ARGS__); \
|
||||
} while (false)
|
||||
|
||||
/*
|
||||
* The functions defined below implement the query logic that previously lived
|
||||
|
|
|
|||
|
|
@ -693,11 +693,12 @@ create_qctx_for_client(ns_client_t *client, query_ctx_t **qctxp) {
|
|||
ns_hooktable_init(&query_hooks);
|
||||
ns_hook_add(&query_hooks, NS_QUERY_SETUP_QCTX_INITIALIZED, &hook);
|
||||
|
||||
saved_hook_table = ns_hooktable_save();
|
||||
saved_hook_table = ns__hook_table;
|
||||
ns__hook_table = &query_hooks;
|
||||
|
||||
ns_hooktable_reset(&query_hooks);
|
||||
ns_query_start(client);
|
||||
ns_hooktable_reset(saved_hook_table);
|
||||
|
||||
ns__hook_table = saved_hook_table;
|
||||
|
||||
if (*qctxp == NULL) {
|
||||
return (ISC_R_NOMEMORY);
|
||||
|
|
|
|||
|
|
@ -84,6 +84,9 @@ static void
|
|||
run_sfcache_test(const ns__query_sfcache_test_params_t *test) {
|
||||
query_ctx_t *qctx = NULL;
|
||||
isc_result_t result;
|
||||
ns_hook_t hook = {
|
||||
.callback = ns_test_hook_catch_call,
|
||||
};
|
||||
|
||||
REQUIRE(test != NULL);
|
||||
REQUIRE(test->id.description != NULL);
|
||||
|
|
@ -93,14 +96,9 @@ run_sfcache_test(const ns__query_sfcache_test_params_t *test) {
|
|||
/*
|
||||
* Interrupt execution if ns_query_done() is called.
|
||||
*/
|
||||
ns_hook_t hook = {
|
||||
.callback = ns_test_hook_catch_call,
|
||||
};
|
||||
ns_hooktable_t query_hooks;
|
||||
|
||||
ns_hooktable_init(&query_hooks);
|
||||
ns_hook_add(&query_hooks, NS_QUERY_DONE_BEGIN, &hook);
|
||||
ns_hooktable_reset(&query_hooks);
|
||||
ns_hooktable_init(ns__hook_table);
|
||||
ns_hook_add(ns__hook_table, NS_QUERY_DONE_BEGIN, &hook);
|
||||
|
||||
/*
|
||||
* Construct a query context for a ./NS query with given flags.
|
||||
|
|
@ -283,6 +281,9 @@ static void
|
|||
run_start_test(const ns__query_start_test_params_t *test) {
|
||||
query_ctx_t *qctx = NULL;
|
||||
isc_result_t result;
|
||||
ns_hook_t hook = {
|
||||
.callback = ns_test_hook_catch_call,
|
||||
};
|
||||
|
||||
REQUIRE(test != NULL);
|
||||
REQUIRE(test->id.description != NULL);
|
||||
|
|
@ -294,16 +295,10 @@ run_start_test(const ns__query_start_test_params_t *test) {
|
|||
/*
|
||||
* Interrupt execution if query_lookup() or ns_query_done() is called.
|
||||
*/
|
||||
ns_hook_t hook = {
|
||||
.callback = ns_test_hook_catch_call,
|
||||
};
|
||||
ns_hooktable_t query_hooks;
|
||||
|
||||
ns_hooktable_init(&query_hooks);
|
||||
ns_hook_add(&query_hooks, NS_QUERY_LOOKUP_BEGIN, &hook);
|
||||
ns_hook_add(&query_hooks, NS_QUERY_DONE_BEGIN, &hook);
|
||||
|
||||
ns_hooktable_reset(&query_hooks);
|
||||
ns_hooktable_init(ns__hook_table);
|
||||
ns_hook_add(ns__hook_table, NS_QUERY_LOOKUP_BEGIN, &hook);
|
||||
ns_hook_add(ns__hook_table, NS_QUERY_DONE_BEGIN, &hook);
|
||||
|
||||
/*
|
||||
* Construct a query context using the supplied parameters.
|
||||
|
|
|
|||
Loading…
Reference in a new issue