/*
* Forward declarations of functions referenced in install_hooks().
*/
-static bool
+static ns_hookresult_t
filter_qctx_initialize(void *arg, void *cbdata, isc_result_t *resp);
-static bool
+static ns_hookresult_t
filter_respond_begin(void *arg, void *cbdata, isc_result_t *resp);
-static bool
+static ns_hookresult_t
filter_respond_any_found(void *arg, void *cbdata, isc_result_t *resp);
-static bool
+static ns_hookresult_t
filter_prep_response_begin(void *arg, void *cbdata, isc_result_t *resp);
-static bool
+static ns_hookresult_t
filter_query_done_send(void *arg, void *cbdata, isc_result_t *resp);
-static bool
+static ns_hookresult_t
filter_qctx_destroy(void *arg, void *cbdata, isc_result_t *resp);
/*%
* retrieve persistent data related to a client query for as long as the
* object persists.
*/
-static bool
+static ns_hookresult_t
filter_qctx_initialize(void *arg, void *cbdata, isc_result_t *resp) {
query_ctx_t *qctx = (query_ctx_t *) arg;
filter_instance_t *inst = (filter_instance_t *) cbdata;
client_state_create(qctx, inst);
}
- return (false);
+ return (NS_HOOK_CONTINUE);
}
/*
* the client address family and the settings of filter-aaaa-on-v4 and
* filter-aaaa-on-v6.
*/
-static bool
+static ns_hookresult_t
filter_prep_response_begin(void *arg, void *cbdata, isc_result_t *resp) {
query_ctx_t *qctx = (query_ctx_t *) arg;
filter_instance_t *inst = (filter_instance_t *) cbdata;
*resp = ISC_R_UNSET;
if (client_state == NULL) {
- return (false);
+ return (NS_HOOK_CONTINUE);
}
if (inst->v4_aaaa != NONE || inst->v6_aaaa != NONE) {
}
}
- return (false);
+ return (NS_HOOK_CONTINUE);
}
/*
* (This version is for processing answers to explicit AAAA queries; ANY
* queries are handled in filter_respond_any_found().)
*/
-static bool
+static ns_hookresult_t
filter_respond_begin(void *arg, void *cbdata, isc_result_t *resp) {
query_ctx_t *qctx = (query_ctx_t *) arg;
filter_instance_t *inst = (filter_instance_t *) cbdata;
*resp = ISC_R_UNSET;
if (client_state == NULL) {
- return (false);
+ return (NS_HOOK_CONTINUE);
}
if (client_state->mode != BREAK_DNSSEC &&
(WANTDNSSEC(qctx->client) && qctx->sigrdataset != NULL &&
dns_rdataset_isassociated(qctx->sigrdataset))))
{
- return (false);
+ return (NS_HOOK_CONTINUE);
}
if (qctx->qtype == dns_rdatatype_aaaa) {
*resp = result;
- return (true);
+ return (NS_HOOK_RETURN);
}
*resp = result;
- return (false);
+ return (NS_HOOK_CONTINUE);
}
/*
* When answering an ANY query, remove AAAA if A is present.
*/
-static bool
+static ns_hookresult_t
filter_respond_any_found(void *arg, void *cbdata, isc_result_t *resp) {
query_ctx_t *qctx = (query_ctx_t *) arg;
filter_instance_t *inst = (filter_instance_t *) cbdata;
process_section(&filter_answer);
}
- return (false);
+ return (NS_HOOK_CONTINUE);
}
/*
* hide NS in the authority section if AAAA was filtered in the answer
* section.
*/
-static bool
+static ns_hookresult_t
filter_query_done_send(void *arg, void *cbdata, isc_result_t *resp) {
query_ctx_t *qctx = (query_ctx_t *) arg;
filter_instance_t *inst = (filter_instance_t *) cbdata;
}
}
- return (false);
+ return (NS_HOOK_CONTINUE);
}
/*
* If the client is being detached, then we can delete our persistent data
* from hash table and return it to the memory pool.
*/
-static bool
+static ns_hookresult_t
filter_qctx_destroy(void *arg, void *cbdata, isc_result_t *resp) {
query_ctx_t *qctx = (query_ctx_t *) arg;
filter_instance_t *inst = (filter_instance_t *) cbdata;
*resp = ISC_R_UNSET;
if (!qctx->detach_client) {
- return (false);
+ return (NS_HOOK_CONTINUE);
}
client_state_destroy(qctx, inst);
- return (false);
+ return (NS_HOOK_CONTINUE);
}
*
* Hook actions are functions which:
*
- * - return a boolean value: if true is returned by the hook action, the
- * function into which the hook is inserted will return and no further hook
- * actions at the same hook point will be invoked; if false is returned by
- * the hook action and there are further hook actions set up at the same
- * hook point, they will be processed; if false is returned and there are
- * no further hook actions set up at the same hook point, execution of the
- * function into which the hook has been inserted will be resumed,
+ * - return an ns_hookresult_t value:
+ * - if NS_HOOK_RETURN is returned by the hook action, the function
+ * into which the hook is inserted will return and no further hook
+ * actions at the same hook point will be invoked,
+ * - if NS_HOOK_CONTINUE is returned by the hook action and there are
+ * further hook actions set up at the same hook point, they will be
+ * processed; if NS_HOOK_CONTINUE is returned and there are no
+ * further hook actions set up at the same hook point, execution of
+ * the function into which the hook has been inserted will be
+ * resumed.
*
* - accept three pointers as arguments:
* - a pointer specified by the special call at the hook insertion point,
* - a pointer specified upon inserting the action into the hook table,
* - a pointer to an isc_result_t value which will be returned by the
- * function into which the hook is inserted if the action returns true.
+ * function into which the hook is inserted if the action returns
+ * NS_HOOK_RETURN.
*
* In order for a hook action to be called for a given hook, a pointer to that
* action function (along with an optional pointer to action-specific data) has
* and the following hook action:
*
* ----------------------------------------------------------------------------
- * static bool
+ * static ns_hookresult_t
* cause_failure(void *hook_data, void *action_data, isc_result_t *resultp) {
* UNUSED(hook_data);
* UNUSED(action_data);
*
* *resultp = ISC_R_FAILURE;
*
- * return (true);
+ * return (NS_HOOK_RETURN);
* }
* ----------------------------------------------------------------------------
*
* ns_hook_add(..., NS_QUERY_FOO_BEGIN, &foo_fail);
* ----------------------------------------------------------------------------
*
- * then query_foo() would return ISC_R_FAILURE every time it is called due to
- * the cause_failure() hook action returning true and setting '*resultp' to
- * ISC_R_FAILURE. query_foo() would also never log the "Lorem ipsum dolor sit
- * amet..." message.
+ * then query_foo() would return ISC_R_FAILURE every time it is called due
+ * to the cause_failure() hook action returning NS_HOOK_RETURN and setting
+ * '*resultp' to ISC_R_FAILURE. query_foo() would also never log the
+ * "Lorem ipsum dolor sit amet..." message.
*
* Consider a different hook action:
*
* ----------------------------------------------------------------------------
- * static bool
+ * static ns_hookresult_t
* log_qtype(void *hook_data, void *action_data, isc_result_t *resultp) {
* query_ctx_t *qctx = (query_ctx_t *)hook_data;
* FILE *stream = (FILE *)action_data;
*
* fprintf(stream, "QTYPE=%u\n", qctx->qtype);
*
- * return (false);
+ * return (NS_HOOK_CONTINUE);
* }
* ----------------------------------------------------------------------------
*
* the hook action in 'hook_data' since it is specified in the CALL_HOOK() call
* inside query_foo() while stderr would be passed to the hook action in
* 'action_data' since it is specified in the ns_hook_t structure passed to
- * ns_hook_add(). As the hook action returns false, query_foo() would also be
- * logging the "Lorem ipsum dolor sit amet..." message before returning
- * ISC_R_COMPLETE.
+ * ns_hook_add(). As the hook action returns NS_HOOK_CONTINUE,
+ * query_foo() would also be logging the "Lorem ipsum dolor sit amet..."
+ * message before returning ISC_R_COMPLETE.
*/
/*!
NS_HOOKPOINTS_COUNT /* MUST BE LAST */
} ns_hookpoint_t;
-typedef bool
+/*
+ * Returned by a hook action to indicate how to proceed after it has
+ * been called: continue processing, or return immediately.
+ */
+typedef enum {
+ NS_HOOK_CONTINUE,
+ NS_HOOK_RETURN,
+} ns_hookresult_t;
+
+typedef ns_hookresult_t
(*ns_hook_action_t)(void *arg, void *data, isc_result_t *resultp);
typedef struct ns_hook {
}
/*
- * Call the specified hook function in every configured module that
- * implements that function. If any hook function returns 'true', we set
- * 'result' and terminate processing by jumping to the 'cleanup' tag.
+ * Call the specified hook function in every configured module that implements
+ * that function. If any hook function returns NS_HOOK_RETURN, we
+ * set 'result' and terminate processing by jumping to the 'cleanup' tag.
*
* (Note that a hook function may set the 'result' to ISC_R_SUCCESS but
* still terminate processing within the calling function. That's why this
* is a macro instead of an inline function; it needs to be able to use
* 'goto cleanup' regardless of the return value.)
*/
-#define CALL_HOOK(_id, _qctx) \
+#define CALL_HOOK(_id, _qctx) \
do { \
isc_result_t _res; \
ns_hooktable_t *_tab = get_hooktab(_qctx); \
ns_hook_action_t _func = _hook->action; \
void *_data = _hook->action_data; \
INSIST(_func != NULL); \
- if (_func(_qctx, _data, &_res)) { \
+ switch (_func(_qctx, _data, &_res)) { \
+ case NS_HOOK_CONTINUE: \
+ _hook = ISC_LIST_NEXT(_hook, link); \
+ break; \
+ case NS_HOOK_RETURN: \
result = _res; \
goto cleanup; \
- } else { \
- _hook = ISC_LIST_NEXT(_hook, link); \
+ default: \
+ INSIST(0); \
} \
} \
} while (false)
* "data". Causes execution to be interrupted at hook insertion
* point.
*/
-static bool
+static ns_hookresult_t
extract_qctx(void *arg, void *data, isc_result_t *resultp) {
query_ctx_t **qctxp;
query_ctx_t *qctx;
*qctxp = qctx;
*resultp = ISC_R_UNSET;
- return (true);
+ return (NS_HOOK_RETURN);
}
/*%
*qctxp = NULL;
}
-bool
+ns_hookresult_t
ns_test_hook_catch_call(void *arg, void *data, isc_result_t *resultp)
{
UNUSED(arg);
*resultp = ISC_R_UNSET;
- return (true);
+ return (NS_HOOK_RETURN);
}
/*
#include <ns/interfacemgr.h>
#include <ns/client.h>
+#include <ns/hooks.h>
typedef struct ns_test_id {
const char *description;
/*%
* A hook callback interrupting execution at given hook's insertion point.
*/
-bool
+ns_hookresult_t
ns_test_hook_catch_call(void *arg, void *data, isc_result_t *resultp);