mirror of
https://github.com/isc-projects/bind9.git
synced 2026-05-28 04:34:54 -04:00
enable modules to store data in qctx
- added a 'hookdata' array to qctx to store pointers to up to 16 blobs of data which are allocated by modules as needed. each module is assigned an ID number as it's loaded, and this is the index into the hook data array. this is to be used for holding persistent state between calls to a hook module for a specific query. - instead of using qctx->filter_aaaa, we now use qctx->hookdata. (this was the last piece of filter-aaaa specific code outside the module.) - added hook points for qctx initialization and destruction. we get a filter-aaaa data pointer from the mempool when initializing and store it in the qctx->hookdata table; return to to the mempool when destroying the qctx. - link the view to the qctx so that detaching the client doesn't cause hooks to fail - added a qctx_destroy() function which must be called after qctx_init; this calls the QCTX_DESTROY hook and detaches the view - general cleanup and comments
This commit is contained in:
parent
9911c835d3
commit
81f58e2ea2
12 changed files with 357 additions and 185 deletions
|
|
@ -23,8 +23,8 @@
|
|||
#include <isccfg/grammar.h>
|
||||
#include <isccfg/namedconf.h>
|
||||
|
||||
#include <dns/acl.h>
|
||||
#include <dns/result.h>
|
||||
#include <dns/view.h>
|
||||
|
||||
#include <ns/client.h>
|
||||
#include <ns/hooks.h>
|
||||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -24,6 +24,9 @@ dlz <string> {
|
|||
dyndb <string> <quoted_string> {
|
||||
<unspecified-text> }; // may occur multiple times
|
||||
|
||||
hook ( query ) <string> [ { <unspecified-text> }
|
||||
]; // may occur multiple times
|
||||
|
||||
key <string> {
|
||||
algorithm <string>;
|
||||
secret <string>;
|
||||
|
|
@ -172,9 +175,9 @@ options {
|
|||
fetches-per-server <integer> [ ( drop | fail ) ];
|
||||
fetches-per-zone <integer> [ ( drop | fail ) ];
|
||||
files ( default | unlimited | <sizeval> );
|
||||
filter-aaaa { <address_match_element>; ... };
|
||||
filter-aaaa-on-v4 ( break-dnssec | <boolean> );
|
||||
filter-aaaa-on-v6 ( break-dnssec | <boolean> );
|
||||
filter-aaaa { <address_match_element>; ... }; // obsolete
|
||||
filter-aaaa-on-v4 <boolean>; // obsolete
|
||||
filter-aaaa-on-v6 <boolean>; // obsolete
|
||||
flush-zones-on-shutdown <boolean>;
|
||||
forward ( first | only );
|
||||
forwarders [ port <integer> ] [ dscp <integer> ] { ( <ipv4_address>
|
||||
|
|
@ -533,13 +536,15 @@ view <string> [ <class> ] {
|
|||
fetch-quota-params <integer> <fixedpoint> <fixedpoint> <fixedpoint>;
|
||||
fetches-per-server <integer> [ ( drop | fail ) ];
|
||||
fetches-per-zone <integer> [ ( drop | fail ) ];
|
||||
filter-aaaa { <address_match_element>; ... };
|
||||
filter-aaaa-on-v4 ( break-dnssec | <boolean> );
|
||||
filter-aaaa-on-v6 ( break-dnssec | <boolean> );
|
||||
filter-aaaa { <address_match_element>; ... }; // obsolete
|
||||
filter-aaaa-on-v4 <boolean>; // obsolete
|
||||
filter-aaaa-on-v6 <boolean>; // obsolete
|
||||
forward ( first | only );
|
||||
forwarders [ port <integer> ] [ dscp <integer> ] { ( <ipv4_address>
|
||||
| <ipv6_address> ) [ port <integer> ] [ dscp <integer> ]; ... };
|
||||
glue-cache <boolean>;
|
||||
hook ( query ) <string> [ {
|
||||
<unspecified-text> } ]; // may occur multiple times
|
||||
inline-signing <boolean>;
|
||||
ixfr-from-differences ( primary | master | secondary | slave |
|
||||
<boolean> );
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -27,12 +27,18 @@
|
|||
|
||||
#include <ns/types.h>
|
||||
|
||||
/*
|
||||
* 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 */
|
||||
|
|
|
|||
176
lib/ns/query.c
176
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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -360,7 +360,6 @@ my @enablelist = ("developer",
|
|||
"isc-spnego",
|
||||
"native-pkcs11",
|
||||
"openssl-hash",
|
||||
"filter-aaaa",
|
||||
"querytrace",
|
||||
"rpz-nsdname",
|
||||
"rpz-nsip");
|
||||
|
|
|
|||
Loading…
Reference in a new issue