diff --git a/bin/hooks/filter-aaaa.c b/bin/hooks/filter-aaaa.c index 6bd1cdc9d8..fa964fab69 100644 --- a/bin/hooks/filter-aaaa.c +++ b/bin/hooks/filter-aaaa.c @@ -23,8 +23,8 @@ #include #include +#include #include -#include #include #include @@ -38,9 +38,15 @@ goto cleanup; \ } while (0) -ns_hook_destroy_t hook_destroy; -ns_hook_register_t hook_register; -ns_hook_version_t hook_version; +/* + * Set up in the register function. + */ +static int module_id; + +/* + * Hook data pool. + */ +static isc_mempool_t *datapool = NULL; /* * Per-client flags set by this module @@ -48,56 +54,90 @@ ns_hook_version_t hook_version; #define FILTER_AAAA_RECURSING 0x0001 /* Recursing for A */ #define FILTER_AAAA_FILTERED 0x0002 /* AAAA was removed from answer */ - -/*% Want DNSSEC? */ -#define WANTDNSSEC(c) (((c)->attributes & \ - NS_CLIENTATTR_WANTDNSSEC) != 0) -/*% Recursion OK? */ -#define RECURSIONOK(c) (((c)->query.attributes & \ +/* + * Client attribute tests. + */ +#define WANTDNSSEC(c) (((c)->attributes & NS_CLIENTATTR_WANTDNSSEC) != 0) +#define RECURSIONOK(c) (((c)->query.attributes & \ NS_QUERYATTR_RECURSIONOK) != 0) +/* + * Hook registration structures: pointers to these structures will + * be added to a hook table when this module is registered. + */ +static bool +filter_qctx_initialize(void *hookdata, void *cbdata, isc_result_t *resp); +static ns_hook_t filter_init = { + .callback = filter_qctx_initialize, +}; + static bool filter_respond_begin(void *hookdata, void *cbdata, isc_result_t *resp); +static ns_hook_t filter_respbegin = { + .callback = filter_respond_begin, +}; static bool filter_respond_any_found(void *hookdata, void *cbdata, isc_result_t *resp); +static ns_hook_t filter_respanyfound = { + .callback = filter_respond_any_found, +}; static bool filter_prep_response_begin(void *hookdata, void *cbdata, isc_result_t *resp); +static ns_hook_t filter_prepresp = { + .callback = filter_prep_response_begin, +}; static bool filter_query_done_send(void *hookdata, void *cbdata, isc_result_t *resp); - -ns_hook_t filter_respbegin = { - .callback = filter_respond_begin, -}; -ns_hook_t filter_respanyfound = { - .callback = filter_respond_any_found, -}; -ns_hook_t filter_prepresp = { - .callback = filter_prep_response_begin, -}; -ns_hook_t filter_donesend = { +static ns_hook_t filter_donesend = { .callback = filter_query_done_send, }; -/* - * Configuration support. - */ +static bool +filter_qctx_destroy(void *hookdata, void *cbdata, isc_result_t *resp); +ns_hook_t filter_destroy = { + .callback = filter_qctx_destroy, +}; -static dns_aaaa_t v4_aaaa; -static dns_aaaa_t v6_aaaa; +/** + ** Support for parsing of parameters and configuration of the module. + **/ + +/* + * Possible values for the settings of filter-aaaa-on-v4 and + * filter-aaaa-on-v6: "no" is NONE, "yes" is FILTER, "break-dnssec" + * is BREAK_DNSSEC. + */ +typedef enum { + NONE = 0, + FILTER = 1, + BREAK_DNSSEC = 2 +} filter_aaaa_t; + +/* + * Values configured when the module is loaded. + */ +static filter_aaaa_t v4_aaaa = NONE; +static filter_aaaa_t v6_aaaa = NONE; static dns_acl_t *aaaa_acl = NULL; +/* + * Support for parsing of parameters. + */ static const char *filter_aaaa_enums[] = { "break-dnssec", NULL }; + static isc_result_t parse_filter_aaaa(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) { return (cfg_parse_enum_or_other(pctx, type, &cfg_type_boolean, ret)); } + static void doc_filter_aaaa(cfg_printer_t *pctx, const cfg_type_t *type) { cfg_doc_enum_or_other(pctx, type, &cfg_type_boolean); } + static cfg_type_t cfg_type_filter_aaaa = { "filter_aaaa", parse_filter_aaaa, cfg_print_ustring, doc_filter_aaaa, &cfg_rep_string, filter_aaaa_enums, @@ -121,7 +161,7 @@ static cfg_type_t cfg_type_parameters = { static isc_result_t parse_filter_aaaa_on(const cfg_obj_t *param_obj, const char *param_name, - dns_aaaa_t *dstp) + filter_aaaa_t *dstp) { const cfg_obj_t *obj = NULL; isc_result_t result; @@ -133,12 +173,12 @@ parse_filter_aaaa_on(const cfg_obj_t *param_obj, const char *param_name, if (cfg_obj_isboolean(obj)) { if (cfg_obj_asboolean(obj)) { - *dstp = dns_aaaa_filter; + *dstp = FILTER; } else { - *dstp = dns_aaaa_ok; + *dstp = NONE; } } else if (strcasecmp(cfg_obj_asstring(obj), "break-dnssec") == 0) { - *dstp = dns_aaaa_break_dnssec; + *dstp = BREAK_DNSSEC; } else { result = ISC_R_UNEXPECTED; } @@ -187,16 +227,33 @@ parse_parameters(const char *parameters, const void *cfg, return (result); } +/** + ** Mandatory hook API functions. + **/ + /* - * Mandatory hook API functions. + * Prototypes for the hook module API functions defined below. + */ +ns_hook_destroy_t hook_destroy; +ns_hook_register_t hook_register; +ns_hook_version_t hook_version; + +/* + * Called by ns_hookmodule_load() to register hook functions into + * a hook table. */ isc_result_t -hook_register(const char *parameters, const char *file, unsigned long line, - const void *cfg, void *actx, ns_hookctx_t *hctx, - ns_hooktable_t *hooktable, void **instp) +hook_register(const unsigned int modid, const char *parameters, + const char *file, unsigned long line, + const void *cfg, void *actx, + ns_hookctx_t *hctx, ns_hooktable_t *hooktable, void **instp) { + isc_result_t result; + UNUSED(instp); + module_id = modid; + if (parameters != NULL) { isc_log_write(hctx->lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_HOOKS, ISC_LOG_INFO, @@ -204,7 +261,7 @@ hook_register(const char *parameters, const char *file, unsigned long line, "module from %s:%lu", file, line); - parse_parameters(parameters, cfg, actx, hctx); + CHECK(parse_parameters(parameters, cfg, actx, hctx)); } else { isc_log_write(hctx->lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_HOOKS, ISC_LOG_INFO, @@ -213,28 +270,50 @@ hook_register(const char *parameters, const char *file, unsigned long line, file, line); } - ns_hook_add(hooktable, NS_QUERY_RESPOND_BEGIN, - &filter_respbegin); + ns_hook_add(hooktable, NS_QUERY_QCTX_INITIALIZED, &filter_init); + ns_hook_add(hooktable, NS_QUERY_RESPOND_BEGIN, &filter_respbegin); ns_hook_add(hooktable, NS_QUERY_RESPOND_ANY_FOUND, &filter_respanyfound); - ns_hook_add(hooktable, NS_QUERY_PREP_RESPONSE_BEGIN, - &filter_prepresp); - ns_hook_add(hooktable, NS_QUERY_DONE_SEND, - &filter_donesend); + ns_hook_add(hooktable, NS_QUERY_PREP_RESPONSE_BEGIN, &filter_prepresp); + ns_hook_add(hooktable, NS_QUERY_DONE_SEND, &filter_donesend); + ns_hook_add(hooktable, NS_QUERY_QCTX_DESTROYED, &filter_destroy); + + CHECK(isc_mempool_create(hctx->mctx, sizeof(filter_aaaa_t), + &datapool)); /* - * TODO: - * Set up a serial number that can be used for accessing - * data blobs in qctx, client, view; - * return an instance pointer for later destruction + * Fill the mempool with 1K filter_aaaa state objects at + * a time; ideally after a single allocation, the mempool will + * have enough to handle all the simultaneous queries the system + * requires and it won't be necessary to allocate more. + * + * We don't set any limit on the number of free state objects + * so that they'll always be returned to the pool and not + * freed until the pool is destroyed on shutdown. */ - return (ISC_R_SUCCESS); + isc_mempool_setfillcount(datapool, 1024); + isc_mempool_setfreemax(datapool, UINT_MAX); + + cleanup: + if (result != ISC_R_SUCCESS) { + if (datapool != NULL) { + isc_mempool_destroy(&datapool); + } + } + return (result); } +/* + * Called by ns_hookmodule_cleanup(); frees memory allocated by + * the module when it was registered. + */ void hook_destroy(void **instp) { UNUSED(instp); + if (datapool != NULL) { + isc_mempool_destroy(&datapool); + } if (aaaa_acl != NULL) { dns_acl_detach(&aaaa_acl); } @@ -242,6 +321,9 @@ hook_destroy(void **instp) { return; } +/* + * Returns hook module API version for compatibility checks. + */ int hook_version(unsigned int *flags) { UNUSED(flags); @@ -249,6 +331,10 @@ hook_version(unsigned int *flags) { return (NS_HOOK_VERSION); } +/** + ** "filter-aaaa" feature implementation begins here + **/ + /* * Check whether this is a V4 client. */ @@ -279,31 +365,55 @@ is_v6_client(ns_client_t *client) { } /* - * The filter-aaaa-on-v4 option suppresses AAAAs for IPv4 - * clients if there is an A; filter-aaaa-on-v6 option does - * the same for IPv6 clients. + * Shorthand to refer to the persistent data stored by this module in + * the query context structure. + */ +#define FILTER_MODE(qctx) ((filter_aaaa_t **) &qctx->hookdata[module_id]) + +/* + * Initialize hook data in the query context, fetching from a memory + * pool. + */ +static bool +filter_qctx_initialize(void *hookdata, void *cbdata, isc_result_t *resp) { + query_ctx_t *qctx = (query_ctx_t *) hookdata; + filter_aaaa_t **mode = FILTER_MODE(qctx); + + UNUSED(cbdata); + + *mode = isc_mempool_get(datapool); + **mode = NONE; + + *resp = ISC_R_UNSET; + return (false); +} + +/* + * Determine whether this client should have AAAA filtered nor not, + * based on the client address family and the settings of + * filter-aaaa-on-v4 and filter-aaaa-on-v6. */ static bool filter_prep_response_begin(void *hookdata, void *cbdata, isc_result_t *resp) { query_ctx_t *qctx = (query_ctx_t *) hookdata; + filter_aaaa_t **mode = FILTER_MODE(qctx); isc_result_t result; UNUSED(cbdata); - qctx->filter_aaaa = dns_aaaa_ok; - if (v4_aaaa != dns_aaaa_ok || v6_aaaa != dns_aaaa_ok) { + if (v4_aaaa != NONE || v6_aaaa != NONE) { result = ns_client_checkaclsilent(qctx->client, NULL, aaaa_acl, true); if (result == ISC_R_SUCCESS && - v4_aaaa != dns_aaaa_ok && + v4_aaaa != NONE && is_v4_client(qctx->client)) { - qctx->filter_aaaa = v4_aaaa; + **mode = v4_aaaa; } else if (result == ISC_R_SUCCESS && - v6_aaaa != dns_aaaa_ok && + v6_aaaa != NONE && is_v6_client(qctx->client)) { - qctx->filter_aaaa = v6_aaaa; + **mode = v6_aaaa; } } @@ -312,19 +422,22 @@ filter_prep_response_begin(void *hookdata, void *cbdata, isc_result_t *resp) { } /* - * Optionally hide AAAA rrsets if there is a matching A. + * Hide AAAA rrsets if there is a matching A. Trigger recursion if + * necessary to find out whether an A exists. + * * (This version is for processing answers to explicit AAAA * queries; ANY queries are handled in query_filter_aaaa_any().) */ static bool filter_respond_begin(void *hookdata, void *cbdata, isc_result_t *resp) { query_ctx_t *qctx = (query_ctx_t *) hookdata; + filter_aaaa_t **mode = FILTER_MODE(qctx); isc_result_t result = ISC_R_UNSET; UNUSED(cbdata); - if (qctx->filter_aaaa != dns_aaaa_break_dnssec && - (qctx->filter_aaaa != dns_aaaa_filter || + if (**mode != BREAK_DNSSEC && + (**mode != FILTER || (WANTDNSSEC(qctx->client) && qctx->sigrdataset != NULL && dns_rdataset_isassociated(qctx->sigrdataset)))) { @@ -368,7 +481,8 @@ filter_respond_begin(void *hookdata, void *cbdata, isc_result_t *resp) { qctx->sigrdataset->attributes |= DNS_RDATASETATTR_RENDERED; } - qctx->client->hookflags |= FILTER_AAAA_FILTERED; + qctx->client->hookflags[module_id] |= + FILTER_AAAA_FILTERED; } else if (!qctx->authoritative && RECURSIONOK(qctx->client) && (result == DNS_R_DELEGATION || @@ -387,14 +501,15 @@ filter_respond_begin(void *hookdata, void *cbdata, isc_result_t *resp) { qctx->client->query.qname, NULL, NULL, qctx->resuming); if (result == ISC_R_SUCCESS) { - qctx->client->hookflags |= + qctx->client->hookflags[module_id] |= FILTER_AAAA_RECURSING; qctx->client->query.attributes |= NS_QUERYATTR_RECURSING; } } } else if (qctx->qtype == dns_rdatatype_a && - ((qctx->client->hookflags & FILTER_AAAA_RECURSING) != 0)) + ((qctx->client->hookflags[module_id] & + FILTER_AAAA_RECURSING) != 0)) { dns_rdataset_t *mrdataset = NULL; @@ -417,22 +532,26 @@ filter_respond_begin(void *hookdata, void *cbdata, isc_result_t *resp) { sigrdataset->attributes |= DNS_RDATASETATTR_RENDERED; } - qctx->client->hookflags &= ~FILTER_AAAA_RECURSING; + qctx->client->hookflags[module_id] &= ~FILTER_AAAA_RECURSING; result = ns_query_done(qctx); *resp = result; - return (true); + return (true); } *resp = result; return (false); } +/* + * When answering an ANY query, remove AAAA if A is present. + */ static bool filter_respond_any_found(void *hookdata, void *cbdata, isc_result_t *resp) { query_ctx_t *qctx = (query_ctx_t *) hookdata; + filter_aaaa_t **mode = FILTER_MODE(qctx); dns_name_t *name = NULL; dns_rdataset_t *aaaa = NULL, *aaaa_sig = NULL; dns_rdataset_t *a = NULL; @@ -440,7 +559,7 @@ filter_respond_any_found(void *hookdata, void *cbdata, isc_result_t *resp) { UNUSED(cbdata); - if (qctx->filter_aaaa == dns_aaaa_ok) { + if (**mode == NONE) { *resp = ISC_R_UNSET; return (false); } @@ -472,7 +591,7 @@ filter_respond_any_found(void *hookdata, void *cbdata, isc_result_t *resp) { if (have_a && aaaa != NULL && (aaaa_sig == NULL || !WANTDNSSEC(qctx->client) || - qctx->filter_aaaa == dns_aaaa_break_dnssec)) + **mode == BREAK_DNSSEC)) { aaaa->attributes |= DNS_RDATASETATTR_RENDERED; if (aaaa_sig != NULL) { @@ -492,11 +611,12 @@ filter_respond_any_found(void *hookdata, void *cbdata, isc_result_t *resp) { static bool filter_query_done_send(void *hookdata, void *cbdata, isc_result_t *resp) { query_ctx_t *qctx = (query_ctx_t *) hookdata; + filter_aaaa_t **mode = FILTER_MODE(qctx); isc_result_t result; UNUSED(cbdata); - if (qctx->filter_aaaa == dns_aaaa_ok) { + if (**mode == NONE) { *resp = ISC_R_UNSET; return (false); } @@ -530,7 +650,7 @@ filter_query_done_send(void *hookdata, void *cbdata, isc_result_t *resp) { dns_rdatatype_aaaa, &aaaa_sig); if (aaaa_sig == NULL || !WANTDNSSEC(qctx->client) || - qctx->filter_aaaa == dns_aaaa_break_dnssec) + **mode == BREAK_DNSSEC) { aaaa->attributes |= DNS_RDATASETATTR_RENDERED; if (aaaa_sig != NULL) { @@ -540,7 +660,7 @@ filter_query_done_send(void *hookdata, void *cbdata, isc_result_t *resp) { } } - if ((qctx->client->hookflags & FILTER_AAAA_FILTERED) != 0) { + if ((qctx->client->hookflags[module_id] & FILTER_AAAA_FILTERED) != 0) { result = dns_message_firstname(qctx->client->message, DNS_SECTION_AUTHORITY); while (result == ISC_R_SUCCESS) { @@ -572,3 +692,22 @@ filter_query_done_send(void *hookdata, void *cbdata, isc_result_t *resp) { *resp = ISC_R_UNSET; return (false); } + +/* + * Return hook data to the mempool. + */ +static bool +filter_qctx_destroy(void *hookdata, void *cbdata, isc_result_t *resp) { + query_ctx_t *qctx = (query_ctx_t *) hookdata; + filter_aaaa_t **mode = FILTER_MODE(qctx); + + UNUSED(cbdata); + + if (*mode != NULL) { + isc_mempool_put(datapool, *mode); + *mode = NULL; + } + + *resp = ISC_R_UNSET; + return (false); +} diff --git a/bin/named/server.c b/bin/named/server.c index a6a55bd11b..0fa0f7da31 100644 --- a/bin/named/server.c +++ b/bin/named/server.c @@ -1537,7 +1537,8 @@ configure_dyndb(const cfg_obj_t *dyndb, isc_mem_t *mctx, } static isc_result_t -configure_hook(ns_hooktable_t *hooktable, const cfg_obj_t *hook, +configure_hook(ns_hooktable_t *hooktable, const unsigned int modid, + const cfg_obj_t *hook, const cfg_obj_t *config, ns_hookctx_t *hctx) { isc_result_t result = ISC_R_SUCCESS; @@ -1559,7 +1560,7 @@ configure_hook(ns_hooktable_t *hooktable, const cfg_obj_t *hook, obj = cfg_tuple_get(hook, "parameters"); if (obj != NULL && cfg_obj_isstring(obj)) { - result = ns_hookmodule_load(library, + result = ns_hookmodule_load(library, modid, cfg_obj_asstring(obj), cfg_obj_file(obj), cfg_obj_line(obj), @@ -1567,7 +1568,7 @@ configure_hook(ns_hooktable_t *hooktable, const cfg_obj_t *hook, named_g_aclconfctx, hctx, hooktable); } else { - result = ns_hookmodule_load(library, NULL, + result = ns_hookmodule_load(library, modid, NULL, cfg_obj_file(hook), cfg_obj_line(hook), config, @@ -3768,6 +3769,7 @@ configure_view(dns_view_t *view, dns_viewlist_t *viewlist, unsigned int resolver_param; dns_ntatable_t *ntatable = NULL; const char *qminmode = NULL; + unsigned int module_counter = 0; REQUIRE(DNS_VIEW_VALID(view)); @@ -5332,7 +5334,10 @@ configure_view(dns_view_t *view, dns_viewlist_t *viewlist, CHECK(ns_hook_createctx(mctx, &hctx)); } - CHECK(configure_hook(view->hooktable, hook, config, hctx)); + CHECK(configure_hook(view->hooktable, module_counter, + hook, config, hctx)); + + module_counter++; } #endif diff --git a/doc/misc/options b/doc/misc/options index 371ae55664..1b54aeda19 100644 --- a/doc/misc/options +++ b/doc/misc/options @@ -24,6 +24,9 @@ dlz { dyndb { }; // may occur multiple times +hook ( query ) [ { } + ]; // may occur multiple times + key { algorithm ; secret ; @@ -172,9 +175,9 @@ options { fetches-per-server [ ( drop | fail ) ]; fetches-per-zone [ ( drop | fail ) ]; files ( default | unlimited | ); - filter-aaaa { ; ... }; - filter-aaaa-on-v4 ( break-dnssec | ); - filter-aaaa-on-v6 ( break-dnssec | ); + filter-aaaa { ; ... }; // obsolete + filter-aaaa-on-v4 ; // obsolete + filter-aaaa-on-v6 ; // obsolete flush-zones-on-shutdown ; forward ( first | only ); forwarders [ port ] [ dscp ] { ( @@ -533,13 +536,15 @@ view [ ] { fetch-quota-params ; fetches-per-server [ ( drop | fail ) ]; fetches-per-zone [ ( drop | fail ) ]; - filter-aaaa { ; ... }; - filter-aaaa-on-v4 ( break-dnssec | ); - filter-aaaa-on-v6 ( break-dnssec | ); + filter-aaaa { ; ... }; // obsolete + filter-aaaa-on-v4 ; // obsolete + filter-aaaa-on-v6 ; // obsolete forward ( first | only ); forwarders [ port ] [ dscp ] { ( | ) [ port ] [ dscp ]; ... }; glue-cache ; + hook ( query ) [ { + } ]; // may occur multiple times inline-signing ; ixfr-from-differences ( primary | master | secondary | slave | ); diff --git a/lib/dns/include/dns/types.h b/lib/dns/include/dns/types.h index c2e64287c1..17c605e69a 100644 --- a/lib/dns/include/dns/types.h +++ b/lib/dns/include/dns/types.h @@ -216,12 +216,6 @@ typedef enum { dns_masterformat_map = 3 } dns_masterformat_t; -typedef enum { - dns_aaaa_ok = 0, - dns_aaaa_filter = 1, - dns_aaaa_break_dnssec = 2 -} dns_aaaa_t; - /* * These are generated by gen.c. */ diff --git a/lib/ns/client.c b/lib/ns/client.c index 525cad499d..7739905d04 100644 --- a/lib/ns/client.c +++ b/lib/ns/client.c @@ -3047,7 +3047,7 @@ client_create(ns_clientmgr_t *manager, ns_client_t **clientp) { ISC_QLINK_INIT(client, ilink); client->keytag = NULL; client->keytag_len = 0; - client->hookflags = 0; + memset(client->hookflags, 0, sizeof(client->hookflags)); /* * We call the init routines for the various kinds of client here, diff --git a/lib/ns/hooks.c b/lib/ns/hooks.c index 6835617b4c..7f0ab4d4a2 100644 --- a/lib/ns/hooks.c +++ b/lib/ns/hooks.c @@ -328,7 +328,8 @@ unload_library(ns_hook_module_t **hmodp) { #endif /* HAVE_DLFCN_H */ isc_result_t -ns_hookmodule_load(const char *libname, const char *parameters, +ns_hookmodule_load(const char *libname, const unsigned int modid, + const char *parameters, const char *file, unsigned long line, const void *cfg, void *actx, ns_hookctx_t *hctx, ns_hooktable_t *hooktable) @@ -343,7 +344,7 @@ ns_hookmodule_load(const char *libname, const char *parameters, "loading module '%s'", libname); CHECK(load_library(hctx->mctx, libname, &module)); - CHECK(module->register_func(parameters, file, line, + CHECK(module->register_func(modid, parameters, file, line, cfg, actx, hctx, hooktable, &module->inst)); diff --git a/lib/ns/include/ns/client.h b/lib/ns/include/ns/client.h index 12845141fb..ea209d6b5f 100644 --- a/lib/ns/include/ns/client.h +++ b/lib/ns/include/ns/client.h @@ -175,7 +175,7 @@ struct ns_client { * Allows a hook module to set flags * that persist across recursion. */ - uint32_t hookflags; + uint32_t hookflags[NS_MAX_MODULES]; }; typedef ISC_QUEUE(ns_client_t) client_queue_t; diff --git a/lib/ns/include/ns/hooks.h b/lib/ns/include/ns/hooks.h index f89201a48b..95f9aca183 100644 --- a/lib/ns/include/ns/hooks.h +++ b/lib/ns/include/ns/hooks.h @@ -163,7 +163,8 @@ */ typedef enum { - NS_QUERY_SETUP_QCTX_INITIALIZED, + NS_QUERY_QCTX_INITIALIZED, + NS_QUERY_QCTX_DESTROYED, NS_QUERY_START_BEGIN, NS_QUERY_LOOKUP_BEGIN, NS_QUERY_RESUME_BEGIN, @@ -235,7 +236,8 @@ typedef struct ns_hookctx { #define NS_HOOK_AGE 0 #endif -typedef isc_result_t ns_hook_register_t(const char *parameters, +typedef isc_result_t ns_hook_register_t(const unsigned int modid, + const char *parameters, const char *file, unsigned long line, const void *cfg, @@ -312,7 +314,8 @@ void ns_hook_destroyctx(ns_hookctx_t **hctxp); isc_result_t -ns_hookmodule_load(const char *libname, const char *parameters, +ns_hookmodule_load(const char *libname, const unsigned int modid, + const char *parameters, const char *file, unsigned long line, const void *cfg, void *actx, ns_hookctx_t *hctx, ns_hooktable_t *hooktable); diff --git a/lib/ns/include/ns/query.h b/lib/ns/include/ns/query.h index 853c7e5a90..987dfe804d 100644 --- a/lib/ns/include/ns/query.h +++ b/lib/ns/include/ns/query.h @@ -27,12 +27,18 @@ #include +/* + * Maximum number of query hook modules that can be configured; + * more than this will overflow qctx->hookdata. + */ +#define NS_MAX_MODULES 16 + /*% nameserver database version structure */ typedef struct ns_dbversion { dns_db_t *db; dns_dbversion_t *version; - bool acl_checked; - bool queryok; + bool acl_checked; + bool queryok; ISC_LINK(struct ns_dbversion) link; } ns_dbversion_t; @@ -52,7 +58,7 @@ typedef struct ns_query_recparam { struct ns_query { unsigned int attributes; unsigned int restarts; - bool timerset; + bool timerset; dns_name_t * qname; dns_name_t * origqname; dns_rdatatype_t qtype; @@ -61,8 +67,8 @@ struct ns_query { dns_db_t * gluedb; dns_db_t * authdb; dns_zone_t * authzone; - bool authdbset; - bool isreferral; + bool authdbset; + bool isreferral; isc_mutex_t fetchlock; dns_fetch_t * fetch; dns_fetch_t * prefetch; @@ -72,7 +78,7 @@ struct ns_query { ISC_LIST(ns_dbversion_t) freeversions; dns_rdataset_t * dns64_aaaa; dns_rdataset_t * dns64_sigaaaa; - bool * dns64_aaaaok; + bool * dns64_aaaaok; unsigned int dns64_aaaaoklen; unsigned int dns64_options; unsigned int dns64_ttl; @@ -87,8 +93,8 @@ struct ns_query { isc_result_t result; dns_rdataset_t * rdataset; dns_rdataset_t * sigrdataset; - bool authoritative; - bool is_zone; + bool authoritative; + bool is_zone; } redirect; ns_query_recparam_t recparam; @@ -166,7 +172,9 @@ struct query_ctx { dns_rpz_st_t *rpz_st; /* RPZ state */ dns_zone_t *zone; /* zone to search */ - dns_aaaa_t filter_aaaa; /* AAAA filtering */ + dns_view_t *view; /* client view */ + + void *hookdata[NS_MAX_MODULES]; /* data used by query hooks */ isc_result_t result; /* query result */ int line; /* line to report error */ @@ -254,12 +262,4 @@ ns__query_start(query_ctx_t *qctx); * (Must not be used outside this module and its associated unit tests.) */ -void -ns__query_inithooks(void); -/* - * XXX: - * Temporary function used to initialize the filter-aaaa hooks, - * which are currently hard-coded rather than loaded as a module. - */ - #endif /* NS_QUERY_H */ diff --git a/lib/ns/query.c b/lib/ns/query.c index a83730c362..dcfa5cc368 100644 --- a/lib/ns/query.c +++ b/lib/ns/query.c @@ -243,11 +243,10 @@ log_noexistnodata(void *val, int level, const char *fmt, ...) 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) \ + _q->view != NULL && \ + _q->view->hooktable != NULL) \ { \ - _tab = _q->client->view->hooktable; \ + _tab = _q->view->hooktable; \ } \ NS_PROCESS_HOOK(_tab, _id, _q, __VA_ARGS__); \ } while (false) @@ -257,11 +256,10 @@ log_noexistnodata(void *val, int level, const char *fmt, ...) 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) \ + _q->view != NULL && \ + _q->view->hooktable != NULL) \ { \ - _tab = _q->client->view->hooktable; \ + _tab = _q->view->hooktable; \ } \ NS_PROCESS_HOOK_VOID(_tab, _id, _q, __VA_ARGS__); \ } while (false) @@ -329,7 +327,8 @@ log_noexistnodata(void *val, int level, const char *fmt, ...) * return it to the client. * * (XXX: This description omits several special cases including - * DNS64, filter-aaaa, RPZ, RRL, and the SERVFAIL cache.) + * DNS64, RPZ, RRL, and the SERVFAIL cache. It also doesn't discuss + * query hook modules.) */ static void @@ -1460,7 +1459,7 @@ query_additional_cb(void *arg, const dns_name_t *name, dns_rdatatype_t qtype) { * If we want only minimal responses and are here, then it must * be for glue. */ - if (client->view->minimalresponses == dns_minimal_yes) { + if (qctx->view->minimalresponses == dns_minimal_yes) { goto try_glue; } @@ -1517,7 +1516,7 @@ query_additional_cb(void *arg, const dns_name_t *name, dns_rdatatype_t qtype) { */ try_cache: - if (!client->view->recursion) { + if (!qctx->view->recursion) { goto try_glue; } @@ -1546,7 +1545,7 @@ query_additional_cb(void *arg, const dns_name_t *name, dns_rdatatype_t qtype) { client->now, &node, fname, &cm, &ci, rdataset, sigrdataset); - dns_cache_updatestats(client->view->cache, result); + dns_cache_updatestats(qctx->view->cache, result); if (!WANTDNSSEC(client)) { ns_client_putrdataset(client, &sigrdataset); } @@ -1892,9 +1891,11 @@ query_setorder(query_ctx_t *qctx, dns_name_t *name, dns_rdataset_t *rdataset) { CTRACE(ISC_LOG_DEBUG(3), "query_setorder"); - if (client->view->order != NULL) { + UNUSED(client); + + if (qctx->view->order != NULL) { rdataset->attributes |= - dns_order_find(qctx->client->view->order, + dns_order_find(qctx->view->order, name, rdataset->type, rdataset->rdclass); } @@ -1917,7 +1918,7 @@ query_additional(query_ctx_t *qctx, dns_rdataset_t *rdataset) { /* * Try to process glue directly. */ - if (client->view->use_glue_cache && + if (qctx->view->use_glue_cache && (rdataset->type == dns_rdatatype_ns) && (client->query.gluedb != NULL) && dns_db_iszone(client->query.gluedb)) @@ -4800,6 +4801,9 @@ redirect2(ns_client_t *client, dns_name_t *name, dns_rdataset_t *rdataset, * Initialize query context 'qctx'. Run by query_setup() when * first handling a client query, and by query_resume() when * returning from recursion. + * + * Whenever this function is called, qctx_destroy() must be called + * when leaving the scope or freeing the qctx. */ static void qctx_init(ns_client_t *client, dns_fetchevent_t *event, @@ -4808,10 +4812,13 @@ qctx_init(ns_client_t *client, dns_fetchevent_t *event, REQUIRE(qctx != NULL); REQUIRE(client != NULL); + memset(qctx, 0, sizeof(query_ctx_t)); + /* Set this first so CCTRACE will work */ qctx->client = client; + dns_view_attach(client->view, &qctx->view); - CCTRACE(ISC_LOG_DEBUG(3), "qctx_create"); + CCTRACE(ISC_LOG_DEBUG(3), "qctx_init"); qctx->event = event; qctx->qtype = qctx->type = qtype; @@ -4835,12 +4842,13 @@ qctx_init(ns_client_t *client, dns_fetchevent_t *event, qctx->options = 0; qctx->resuming = false; qctx->is_zone = false; - qctx->findcoveringnsec = client->view->synthfromdnssec; + qctx->findcoveringnsec = qctx->view->synthfromdnssec; qctx->is_staticstub_zone = false; qctx->nxrewrite = false; qctx->answer_has_ns = false; qctx->authoritative = false; - qctx->filter_aaaa = dns_aaaa_ok; + + PROCESS_HOOK_VOID(NS_QUERY_QCTX_INITIALIZED, qctx); } /*% @@ -4903,6 +4911,12 @@ qctx_freedata(query_ctx_t *qctx) { } } +static void +qctx_destroy(query_ctx_t *qctx) { + PROCESS_HOOK_VOID(NS_QUERY_QCTX_DESTROYED, qctx); + dns_view_detach(&qctx->view); +} + /*% * Log detailed information about the query immediately after * the client request or a return from recursion. @@ -4962,17 +4976,18 @@ query_setup(ns_client_t *client, dns_rdatatype_t qtype) { qctx.type = dns_rdatatype_any; } - PROCESS_HOOK(NS_QUERY_SETUP_QCTX_INITIALIZED, &qctx); - /* * Check SERVFAIL cache */ result = ns__query_sfcache(&qctx); if (result != ISC_R_COMPLETE) { + qctx_destroy(&qctx); return (result); } - return (ns__query_start(&qctx)); + result = ns__query_start(&qctx); + qctx_destroy(&qctx); + return (result); } static bool @@ -5061,7 +5076,7 @@ ns__query_start(query_ctx_t *qctx) { * If we require a server cookie then send back BADCOOKIE * before we have done too much work. */ - if (!TCP(qctx->client) && qctx->client->view->requireservercookie && + if (!TCP(qctx->client) && qctx->view->requireservercookie && WANTCOOKIE(qctx->client) && !HAVECOOKIE(qctx->client)) { qctx->client->message->flags &= ~DNS_MESSAGEFLAG_AA; @@ -5070,7 +5085,7 @@ ns__query_start(query_ctx_t *qctx) { return (ns_query_done(qctx)); } - if (qctx->client->view->checknames && + if (qctx->view->checknames && !dns_rdata_checkowner(qctx->client->query.qname, qctx->client->message->rdclass, qctx->qtype, false)) @@ -5095,7 +5110,7 @@ ns__query_start(query_ctx_t *qctx) { /* * Setup for root key sentinel processing. */ - if (qctx->client->view->root_key_sentinel && + if (qctx->view->root_key_sentinel && qctx->client->query.restarts == 0 && (qctx->qtype == dns_rdatatype_a || qctx->qtype == dns_rdatatype_aaaa) && @@ -5340,7 +5355,7 @@ query_lookup(query_ctx_t *qctx) { } if (!qctx->is_zone) { - dns_cache_updatestats(qctx->client->view->cache, result); + dns_cache_updatestats(qctx->view->cache, result); } if ((qctx->client->query.dboptions & DNS_DBFIND_STALEOK) != 0) { @@ -5351,8 +5366,7 @@ query_lookup(query_ctx_t *qctx) { if (dns_rdataset_isassociated(qctx->rdataset) && dns_rdataset_count(qctx->rdataset) > 0 && STALE(qctx->rdataset)) { - qctx->rdataset->ttl = - qctx->client->view->staleanswerttl; + qctx->rdataset->ttl = qctx->view->staleanswerttl; success = true; } else { success = false; @@ -5443,6 +5457,10 @@ fetch_callback(isc_task_t *task, isc_event_t *event) { } else { query_ctx_t qctx; + /* + * Initalize a new qctx and use it to resume + * from recursion. + */ qctx_init(client, devent, 0, &qctx); query_trace(&qctx); @@ -5460,6 +5478,8 @@ fetch_callback(isc_task_t *task, isc_event_t *event) { errorloglevel, false); } } + + qctx_destroy(&qctx); } dns_resolver_destroyfetch(&fetch); @@ -5802,7 +5822,7 @@ query_resume(query_ctx_t *qctx) { /* * Has response policy changed out from under us? */ - if (qctx->rpz_st->rpz_ver != qctx->client->view->rpzs->rpz_ver) + if (qctx->rpz_st->rpz_ver != qctx->view->rpzs->rpz_ver) { ns_client_log(qctx->client, NS_LOGCATEGORY_CLIENT, NS_LOGMODULE_QUERY, @@ -5810,7 +5830,7 @@ query_resume(query_ctx_t *qctx) { "query_resume: RPZ settings " "out of date " "(rpz_ver %d, expected %d)", - qctx->client->view->rpzs->rpz_ver, + qctx->view->rpzs->rpz_ver, qctx->rpz_st->rpz_ver); QUERY_ERROR(qctx, DNS_R_SERVFAIL); return (ns_query_done(qctx)); @@ -5896,13 +5916,13 @@ ns__query_sfcache(query_ctx_t *qctx) { failcache = false; } else { failcache = - dns_badcache_find(qctx->client->view->failcache, + dns_badcache_find(qctx->view->failcache, qctx->client->query.qname, qctx->qtype, &flags, &qctx->client->tnow); } #else - failcache = dns_badcache_find(qctx->client->view->failcache, + failcache = dns_badcache_find(qctx->view->failcache, qctx->client->query.qname, qctx->qtype, &flags, &qctx->client->tnow); @@ -5959,20 +5979,26 @@ query_checkrrl(query_ctx_t *qctx, isc_result_t result) { * is set when we are called the second time preventing the * response being dropped. */ - ns_client_log(qctx->client, DNS_LOGCATEGORY_RRL, NS_LOGMODULE_QUERY, - ISC_LOG_DEBUG(99), "rrl=%p, HAVECOOKIE=%u, result=%s, " + ns_client_log(qctx->client, DNS_LOGCATEGORY_RRL, + NS_LOGMODULE_QUERY, ISC_LOG_DEBUG(99), + "rrl=%p, HAVECOOKIE=%u, result=%s, " "fname=%p(%u), is_zone=%u, RECURSIONOK=%u, " "query.rpz_st=%p(%u), RRL_CHECKED=%u\n", qctx->client->view->rrl, HAVECOOKIE(qctx->client), isc_result_toid(result), qctx->fname, - qctx->fname?dns_name_isabsolute(qctx->fname) : 0, + qctx->fname != NULL + ? dns_name_isabsolute(qctx->fname) + : 0, qctx->is_zone, RECURSIONOK(qctx->client), qctx->client->query.rpz_st, - qctx->client->query.rpz_st ? - (qctx->client->query.rpz_st->state & DNS_RPZ_REWRITTEN) != 0 : 0, - (qctx->client->query.attributes & NS_QUERYATTR_RRL_CHECKED) != 0); + qctx->client->query.rpz_st != NULL + ? ((qctx->client->query.rpz_st->state & + DNS_RPZ_REWRITTEN) != 0) + : 0, + (qctx->client->query.attributes & + NS_QUERYATTR_RRL_CHECKED) != 0); - if (qctx->client->view->rrl != NULL && + if (qctx->view->rrl != NULL && !HAVECOOKIE(qctx->client) && ((qctx->fname != NULL && dns_name_isabsolute(qctx->fname)) || (result == ISC_R_NOTFOUND && !RECURSIONOK(qctx->client))) && @@ -6043,7 +6069,7 @@ query_checkrrl(query_ctx_t *qctx, isc_result_t result) { resp_result = ISC_R_SUCCESS; } - rrl_result = dns_rrl(qctx->client->view, + rrl_result = dns_rrl(qctx->view, &qctx->client->peeraddr, TCP(qctx->client), qctx->client->message->rdclass, @@ -6068,7 +6094,7 @@ query_checkrrl(query_ctx_t *qctx, isc_result_t result) { "%s", log_buf); } - if (!qctx->client->view->rrl->log_only) { + if (!qctx->view->rrl->log_only) { if (rrl_result == DNS_RRL_RESULT_DROP) { /* * These will also be counted in @@ -6370,7 +6396,7 @@ has_ta(query_ctx_t *qctx) { dns_keynode_t *keynode = NULL; isc_result_t result; - result = dns_view_getsecroots(qctx->client->view, &keytable); + result = dns_view_getsecroots(qctx->view, &keytable); if (result != ISC_R_SUCCESS) { return (false); } @@ -6739,7 +6765,7 @@ query_respond_any(query_ctx_t *qctx) { * ANY queries. */ dns_rdataset_disassociate(qctx->rdataset); - } else if (qctx->client->view->minimal_any && + } else if (qctx->view->minimal_any && !TCP(qctx->client) && !WANTDNSSEC(qctx->client) && qctx->qtype == dns_rdatatype_any && (qctx->rdataset->type == dns_rdatatype_sig || @@ -6748,7 +6774,7 @@ query_respond_any(query_ctx_t *qctx) { CCTRACE(ISC_LOG_DEBUG(5), "query_respond_any: " "minimal-any skip signature"); dns_rdataset_disassociate(qctx->rdataset); - } else if (qctx->client->view->minimal_any && + } else if (qctx->view->minimal_any && !TCP(qctx->client) && onetype != 0 && qctx->rdataset->type != onetype && qctx->rdataset->covers != onetype) @@ -6996,7 +7022,7 @@ query_respond(query_ctx_t *qctx) { INSIST(qctx->client->query.dns64_aaaaok == NULL); if (qctx->qtype == dns_rdatatype_aaaa && !qctx->dns64_exclude && - !ISC_LIST_EMPTY(qctx->client->view->dns64) && + !ISC_LIST_EMPTY(qctx->view->dns64) && qctx->client->message->rdclass == dns_rdataclass_in && !dns64_aaaaok(qctx->client, qctx->rdataset, qctx->sigrdataset)) { @@ -7473,14 +7499,14 @@ query_notfound(query_ctx_t *qctx) { * If the cache doesn't even have the root NS, * try to get that from the hints DB. */ - if (qctx->client->view->hints != NULL) { + if (qctx->view->hints != NULL) { dns_clientinfomethods_t cm; dns_clientinfo_t ci; dns_clientinfomethods_init(&cm, ns_client_sourceip); dns_clientinfo_init(&ci, qctx->client, NULL); - dns_db_attach(qctx->client->view->hints, &qctx->db); + dns_db_attach(qctx->view->hints, &qctx->db); result = dns_db_findext(qctx->db, dns_rootname, NULL, dns_rdatatype_ns, 0, qctx->client->now, &qctx->node, @@ -7665,7 +7691,7 @@ query_zone_delegation(query_ctx_t *qctx) { SAVE(qctx->zversion, qctx->version); SAVE(qctx->zrdataset, qctx->rdataset); SAVE(qctx->zsigrdataset, qctx->sigrdataset); - dns_db_attach(qctx->client->view->cachedb, &qctx->db); + dns_db_attach(qctx->view->cachedb, &qctx->db); qctx->is_zone = false; return (query_lookup(qctx)); @@ -7986,7 +8012,7 @@ query_nodata(query_ctx_t *qctx, isc_result_t result) { #endif } else if ((result == DNS_R_NXRRSET || result == DNS_R_NCACHENXRRSET) && - !ISC_LIST_EMPTY(qctx->client->view->dns64) && + !ISC_LIST_EMPTY(qctx->view->dns64) && qctx->client->message->rdclass == dns_rdataclass_in && qctx->qtype == dns_rdatatype_aaaa) { @@ -8530,7 +8556,7 @@ query_synthwildcard(query_ctx_t *qctx, dns_rdataset_t *rdataset, dns_name_t *name = NULL; isc_buffer_t *dbuf, b; isc_result_t result; - dns_rdataset_t *clone = NULL, *sigclone = NULL; + dns_rdataset_t *cloneset = NULL, *clonesigset = NULL; dns_rdataset_t **sigrdatasetp; /* @@ -8556,29 +8582,29 @@ query_synthwildcard(query_ctx_t *qctx, dns_rdataset_t *rdataset, } dns_name_copy(qctx->client->query.qname, name, NULL); - clone = ns_client_newrdataset(qctx->client); - if (clone == NULL) { + cloneset = ns_client_newrdataset(qctx->client); + if (cloneset == NULL) { result = ISC_R_NOMEMORY; goto cleanup; } - dns_rdataset_clone(rdataset, clone); + dns_rdataset_clone(rdataset, cloneset); /* * Add answer RRset. Omit the RRSIG if DNSSEC was not requested. */ if (WANTDNSSEC(qctx->client)) { - sigclone = ns_client_newrdataset(qctx->client); - if (sigclone == NULL) { + clonesigset = ns_client_newrdataset(qctx->client); + if (clonesigset == NULL) { result = ISC_R_NOMEMORY; goto cleanup; } - dns_rdataset_clone(sigrdataset, sigclone); - sigrdatasetp = &sigclone; + dns_rdataset_clone(sigrdataset, clonesigset); + sigrdatasetp = &clonesigset; } else { sigrdatasetp = NULL; } - query_addrrset(qctx, &name, &clone, sigrdatasetp, + query_addrrset(qctx, &name, &cloneset, sigrdatasetp, dbuf, DNS_SECTION_ANSWER); if (WANTDNSSEC(qctx->client)) { @@ -8597,11 +8623,11 @@ cleanup: if (name != NULL) { ns_client_releasename(qctx->client, &name); } - if (clone != NULL) { - ns_client_putrdataset(qctx->client, &clone); + if (cloneset != NULL) { + ns_client_putrdataset(qctx->client, &cloneset); } - if (sigclone != NULL) { - ns_client_putrdataset(qctx->client, &sigclone); + if (clonesigset != NULL) { + ns_client_putrdataset(qctx->client, &clonesigset); } return (result); } @@ -8684,7 +8710,7 @@ query_synthnxdomain(query_ctx_t *qctx, dns_ttl_t ttl; isc_buffer_t *dbuf, b; isc_result_t result; - dns_rdataset_t *clone = NULL, *sigclone = NULL; + dns_rdataset_t *cloneset = NULL, *clonesigset = NULL; /* * Detemine the correct TTL to use for the SOA and RRSIG @@ -8749,20 +8775,20 @@ query_synthnxdomain(query_ctx_t *qctx, dns_name_copy(nowild, name, NULL); - clone = ns_client_newrdataset(qctx->client); - sigclone = ns_client_newrdataset(qctx->client); - if (clone == NULL || sigclone == NULL) { + cloneset = ns_client_newrdataset(qctx->client); + clonesigset = ns_client_newrdataset(qctx->client); + if (cloneset == NULL || clonesigset == NULL) { result = ISC_R_NOMEMORY; goto cleanup; } - dns_rdataset_clone(nowildrdataset, clone); - dns_rdataset_clone(signowildrdataset, sigclone); + dns_rdataset_clone(nowildrdataset, cloneset); + dns_rdataset_clone(signowildrdataset, clonesigset); /* * Add NOWILDCARD proof. */ - query_addrrset(qctx, &name, &clone, &sigclone, + query_addrrset(qctx, &name, &cloneset, &clonesigset, dbuf, DNS_SECTION_AUTHORITY); } @@ -8774,11 +8800,11 @@ cleanup: if (name != NULL) { ns_client_releasename(qctx->client, &name); } - if (clone != NULL) { - ns_client_putrdataset(qctx->client, &clone); + if (cloneset != NULL) { + ns_client_putrdataset(qctx->client, &cloneset); } - if (sigclone != NULL) { - ns_client_putrdataset(qctx->client, &sigclone); + if (clonesigset != NULL) { + ns_client_putrdataset(qctx->client, &clonesigset); } return (result); } @@ -8895,7 +8921,7 @@ query_coveringnsec(query_ctx_t *qctx) { if (qctx->type == dns_rdatatype_any) { /* XXX not yet */ goto cleanup; } - if (!ISC_LIST_EMPTY(qctx->client->view->dns64) && + if (!ISC_LIST_EMPTY(qctx->view->dns64) && (qctx->type == dns_rdatatype_a || qctx->type == dns_rdatatype_aaaa)) /* XXX not yet */ { @@ -8959,7 +8985,7 @@ query_coveringnsec(query_ctx_t *qctx) { if (qctx->type == dns_rdatatype_any) { /* XXX not yet */ goto cleanup; } - if (!ISC_LIST_EMPTY(qctx->client->view->dns64) && + if (!ISC_LIST_EMPTY(qctx->view->dns64) && (qctx->type == dns_rdatatype_a || qctx->type == dns_rdatatype_aaaa)) /* XXX not yet */ { @@ -10452,7 +10478,7 @@ ns_query_done(query_ctx_t *qctx) { query_glueanswer(qctx); if (qctx->client->message->rcode == dns_rcode_nxdomain && - qctx->client->view->auth_nxdomain == true) + qctx->view->auth_nxdomain == true) { qctx->client->message->flags |= DNS_MESSAGEFLAG_AA; } diff --git a/lib/ns/tests/nstest.c b/lib/ns/tests/nstest.c index c6311ec39b..355d175865 100644 --- a/lib/ns/tests/nstest.c +++ b/lib/ns/tests/nstest.c @@ -691,7 +691,7 @@ 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); + ns_hook_add(&query_hooks, NS_QUERY_QCTX_INITIALIZED, &hook); saved_hook_table = ns__hook_table; ns__hook_table = &query_hooks; diff --git a/win32utils/Configure b/win32utils/Configure index 40cddb9708..568386bafa 100644 --- a/win32utils/Configure +++ b/win32utils/Configure @@ -360,7 +360,6 @@ my @enablelist = ("developer", "isc-spnego", "native-pkcs11", "openssl-hash", - "filter-aaaa", "querytrace", "rpz-nsdname", "rpz-nsip");