VPATH = @srcdir@
top_srcdir = @top_srcdir@
-VERSION=@BIND9_VERSION@
-
-@BIND9_PRODUCT@
-
-@BIND9_DESCRIPTION@
-
-@BIND9_SRCID@
-
-@BIND9_CONFIGARGS@
-
@BIND9_MAKE_INCLUDES@
CINCLUDES = -I${srcdir}/include -I${srcdir}/unix/include -I. \
SO_OBJS = filter-aaaa.@O@
SO_SRCS = filter-aaaa.c
-OBJS =
-
CFLAGS = @CFLAGS@ @SO_CFLAGS@
SO_LDFLAGS = @LDFLAGS@ @SO_LDFLAGS@
#include <config.h>
+#include <inttypes.h>
+#include <stdbool.h>
+#include <string.h>
+
+#include <isc/buffer.h>
#include <isc/hash.h>
#include <isc/lib.h>
+#include <isc/log.h>
#include <isc/mem.h>
+#include <isc/netaddr.h>
#include <isc/result.h>
+#include <isc/types.h>
#include <isc/util.h>
#include <isccfg/aclconf.h>
+#include <isccfg/cfg.h>
#include <isccfg/grammar.h>
-#include <isccfg/namedconf.h>
-
-#include <dns/acl.h>
-#include <dns/result.h>
#include <ns/client.h>
#include <ns/hooks.h>
#include <ns/log.h>
#include <ns/query.h>
+#include <ns/types.h>
-#define CHECK(r) \
- do { \
- result = (r); \
- if (result != ISC_R_SUCCESS) \
- goto cleanup; \
+#include <dns/acl.h>
+#include <dns/db.h>
+#include <dns/enumtype.h>
+#include <dns/log.h>
+#include <dns/message.h>
+#include <dns/rdataset.h>
+#include <dns/result.h>
+#include <dns/types.h>
+
+#define CHECK(op) \
+ do { \
+ result = (op); \
+ if (result != ISC_R_SUCCESS) { \
+ goto cleanup; \
+ } \
} while (0)
/*
}
/**
- ** Mandatory hook API functions.
+ ** Mandatory hook API functions:
+ **
+ ** - hook_destroy
+ ** - hook_register
+ ** - hook_version
**/
-/*
- * 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 unsigned int modid, const char *parameters,
- const char *file, unsigned long line,
+ const char *cfg_file, unsigned long cfg_line,
const void *cfg, void *actx,
ns_hookctx_t *hctx, ns_hooktable_t *hooktable, void **instp)
{
module_id = modid;
- if (parameters != NULL) {
- isc_log_write(hctx->lctx, NS_LOGCATEGORY_GENERAL,
- NS_LOGMODULE_HOOKS, ISC_LOG_INFO,
- "loading params for 'filter-aaaa' "
- "module from %s:%lu",
- file, line);
+ isc_log_write(hctx->lctx, NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_HOOKS, ISC_LOG_INFO,
+ "loading 'filter-aaaa' "
+ "module from %s:%lu, %s parameters",
+ cfg_file, cfg_line, parameters != NULL ? "with" : "no");
+ if (parameters != NULL) {
CHECK(parse_parameters(parameters, cfg, actx, hctx));
- } else {
- isc_log_write(hctx->lctx, NS_LOGCATEGORY_GENERAL,
- NS_LOGMODULE_HOOKS, ISC_LOG_INFO,
- "loading 'filter-aaaa' "
- "module from %s:%lu, no parameters",
- file, line);
}
ns_hook_add(hooktable, NS_QUERY_QCTX_INITIALIZED, &filter_init);
}
/*
- * Called by ns_hookmodule_cleanup(); frees memory allocated by
+ * Called by ns_hookmodule_unload_all(); frees memory allocated by
* the module when it was registered.
*/
void
* Returns hook module API version for compatibility checks.
*/
int
-hook_version(unsigned int *flags) {
- UNUSED(flags);
-
+hook_version(void) {
return (NS_HOOK_VERSION);
}
/**
- ** "filter-aaaa" feature implementation begins here
+ ** "filter-aaaa" feature implementation begins here.
**/
/*
- * Check whether this is a V4 client.
+ * Check whether this is an IPv4 client.
*/
static bool
is_v4_client(ns_client_t *client) {
}
/*
- * Check whether this is a V6 client.
+ * Check whether this is an IPv6 client.
*/
static bool
is_v6_client(ns_client_t *client) {
}
/*
- * Determine whether this client should have AAAA filtered nor not,
+ * Determine whether this client should have AAAA filtered or not,
* based on the client address family and the settings of
* filter-aaaa-on-v4 and filter-aaaa-on-v6.
*/
* cached an A if it existed.
*/
if (result == ISC_R_SUCCESS) {
+ qctx->client->message->flags &= ~DNS_MESSAGEFLAG_AD;
qctx->rdataset->attributes |= DNS_RDATASETATTR_RENDERED;
if (qctx->sigrdataset != NULL &&
dns_rdataset_isassociated(qctx->sigrdataset))
((qctx->client->hookflags[module_id] &
FILTER_AAAA_RECURSING) != 0))
{
-
dns_rdataset_t *mrdataset = NULL;
dns_rdataset_t *sigrdataset = NULL;
dns_rdatatype_aaaa, 0,
NULL, &mrdataset);
if (result == ISC_R_SUCCESS) {
+ qctx->client->message->flags &= ~DNS_MESSAGEFLAG_AD;
mrdataset->attributes |= DNS_RDATASETATTR_RENDERED;
}
dns_rdatatype_aaaa,
NULL, &sigrdataset);
if (result == ISC_R_SUCCESS) {
+ qctx->client->message->flags &= ~DNS_MESSAGEFLAG_AD;
sigrdataset->attributes |= DNS_RDATASETATTR_RENDERED;
}
(aaaa_sig == NULL || !WANTDNSSEC(qctx->client) ||
**mode == BREAK_DNSSEC))
{
+ qctx->client->message->flags &= ~DNS_MESSAGEFLAG_AD;
aaaa->attributes |= DNS_RDATASETATTR_RENDERED;
if (aaaa_sig != NULL) {
aaaa_sig->attributes |= DNS_RDATASETATTR_RENDERED;
/*
* Hide AAAA rrsets in the additional section if there is a matching A,
- * and hide NS in the additional section if AAAA was filtered in the answer
+ * and hide NS in the authority section if AAAA was filtered in the answer
* section.
*/
static bool
result = dns_message_findtype(name, dns_rdatatype_ns,
0, &ns);
if (result == ISC_R_SUCCESS) {
+ qctx->client->message->flags &=
+ ~DNS_MESSAGEFLAG_AD;
ns->attributes |= DNS_RDATASETATTR_RENDERED;
}
to omit some IPv6 addresses when responding to clients.
</para>
<para>
- Until BIND 9.12, this feature was impleented natively in
+ Until BIND 9.12, this feature was implemented natively in
<command>named</command> and enabled with the
<command>filter-aaaa</command> ACL and the
<command>filter-aaaa-on-v4</command> and
isc_result_t result = ISC_R_SUCCESS;
const cfg_obj_t *obj;
const char *type, *library;
+ const char *parameters = NULL;
/* Get the path to the hook module. */
obj = cfg_tuple_get(hook, "type");
obj = cfg_tuple_get(hook, "parameters");
if (obj != NULL && cfg_obj_isstring(obj)) {
- result = ns_hookmodule_load(library, modid,
- cfg_obj_asstring(obj),
- cfg_obj_file(obj),
- cfg_obj_line(obj),
- config,
- named_g_aclconfctx,
- hctx, hooktable);
- } else {
- result = ns_hookmodule_load(library, modid, NULL,
- cfg_obj_file(hook),
- cfg_obj_line(hook),
- config,
- named_g_aclconfctx,
- hctx, hooktable);
+ parameters = cfg_obj_asstring(obj);
}
-
+ result = ns_hookmodule_load(library, modid, parameters,
+ cfg_obj_file(obj), cfg_obj_line(obj),
+ config, named_g_aclconfctx,
+ hctx, hooktable);
if (result != ISC_R_SUCCESS) {
isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR,
}
#ifdef HAVE_DLOPEN
+ if (hook_list != NULL) {
+ const void *hashinit = isc_hash_get_initializer();
+ CHECK(ns_hook_createctx(mctx, hashinit, &hctx));
+
+ INSIST(view->hooktable == NULL);
+ CHECK(ns_hooktable_create(view->mctx,
+ (ns_hooktable_t **) &view->hooktable));
+ view->hooktable_free = ns_hooktable_free;
+ }
+
for (element = cfg_list_first(hook_list);
element != NULL;
element = cfg_list_next(element))
const cfg_obj_t *hook = cfg_listelt_value(element);
if (view->hooktable == NULL) {
- ns_hooktable_create(view->mctx,
- (ns_hooktable_t **) &view->hooktable);
+ CHECK(ns_hooktable_create(view->mctx,
+ (ns_hooktable_t **) &view->hooktable));
view->hooktable_free = ns_hooktable_free;
}
* Shut down all dyndb and hook module instances.
*/
dns_dyndb_cleanup(false);
- ns_hookmodule_cleanup();
+ ns_hookmodule_unload_all();
/*
* Parse the global default pseudo-config file.
* Shut down all dyndb and hook module instances.
*/
dns_dyndb_cleanup(true);
- ns_hookmodule_cleanup();
+ ns_hookmodule_unload_all();
while ((nsc = ISC_LIST_HEAD(server->cachelist)) != NULL) {
ISC_LIST_UNLINK(server->cachelist, nsc, link);
rm -f dig.out.*
rm -f ns*/named.lock
rm -f ns*/managed-keys.bind*
+
+rm -f ns*/trusted.conf
+rm -f ns*/keygen.out
zonefile=signed.db.signed
outfile=signed.db.signed
-keyname1=`$KEYGEN -a $DEFAULT_ALGORITHM -b $DEFAULT_BITS -n zone $zone 2> /dev/null`
-keyname2=`$KEYGEN -f KSK -a $DEFAULT_ALGORITHM -b $DEFAULT_BITS -n zone $zone 2> /dev/null`
+$KEYGEN -a $DEFAULT_ALGORITHM $zone 2>&1 > /dev/null | cat_i
+$KEYGEN -f KSK -a $DEFAULT_ALGORITHM $zone 2>&1 > keygen.out | cat_i
+keyname=`cat keygen.out`
+rm -f keygen.out
-cat $infile $keyname1.key $keyname2.key >$zonefile
+keyfile_to_trusted_keys $keyname > trusted.conf
+cp trusted.conf ../ns2/trusted.conf
+cp trusted.conf ../ns3/trusted.conf
+cp trusted.conf ../ns5/trusted.conf
-$SIGNER -o $zone -f $outfile $zonefile > /dev/null 2> signer.err || cat signer.err
-echo_i "signed $zone"
+$SIGNER -S -o $zone -f $outfile $infile > /dev/null 2> signer.err || cat signer.err
+echo_i "signed zone '$zone'"
};
zone "." { type hint; file "hints"; };
+
+include "trusted.conf";
};
zone "." { type hint; file "hints"; };
+
+include "trusted.conf";
};
zone "." { type hint; file "hints"; };
+
+include "trusted.conf";
};
zone "." { type hint; file "hints"; };
+
+include "trusted.conf";
zonefile=signed.db.signed
outfile=signed.db.signed
-keyname1=`$KEYGEN -a $DEFAULT_ALGORITHM -b $DEFAULT_BITS -n zone $zone 2> /dev/null`
-keyname2=`$KEYGEN -f KSK -a $DEFAULT_ALGORITHM -b $DEFAULT_BITS -n zone $zone 2> /dev/null`
+$KEYGEN -a $DEFAULT_ALGORITHM $zone 2>&1 > /dev/null | cat_i
+$KEYGEN -f KSK -a $DEFAULT_ALGORITHM $zone 2>&1 > /dev/null | cat_i
-cat $infile $keyname1.key $keyname2.key >$zonefile
-
-$SIGNER -o $zone -f $outfile $zonefile > /dev/null 2> signer.err || cat signer.err
-echo_i "signed $zone"
+$SIGNER -S -o $zone -f $outfile $infile > /dev/null 2> signer.err || cat signer.err
+echo_i "signed zone '$zone'"
};
zone "." { type hint; file "hints"; };
+
+include "trusted.conf";
echo_i "skipped."
fi
-
#
# Authoritative tests against:
# filter-aaaa-on-v4 break-dnssec;
echo_i "checking that AAAA is returned when only AAAA record exists, signed, recursive ($n)"
ret=0
$DIG $DIGOPTS aaaa aaaa-only.signed -b 10.53.0.2 @10.53.0.2 > dig.out.ns2.test$n || ret=1
+grep "flags:.*ad.*QUERY" dig.out.ns2.test$n > /dev/null || ret=1
grep ::2 dig.out.ns2.test$n > /dev/null || ret=1
if [ $ret != 0 ]; then echo_i "failed"; fi
status=`expr $status + $ret`
ret=0
$DIG $DIGOPTS aaaa dual.signed -b 10.53.0.2 @10.53.0.2 > dig.out.ns2.test$n || ret=1
grep "ANSWER: 0" dig.out.ns2.test$n > /dev/null || ret=1
+grep "flags:.*ad.*QUERY" dig.out.ns2.test$n > /dev/null && ret=1
grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1
if [ $ret != 0 ]; then echo_i "failed"; fi
status=`expr $status + $ret`
ret=0
$DIG $DIGOPTS aaaa dual.unsigned -b 10.53.0.2 @10.53.0.2 > dig.out.ns2.test$n || ret=1
grep "ANSWER: 0" dig.out.ns2.test$n > /dev/null || ret=1
+grep "flags:.*ad.*QUERY" dig.out.ns2.test$n > /dev/null && ret=1
grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1
if [ $ret != 0 ]; then echo_i "failed"; fi
status=`expr $status + $ret`
echo_i "checking that AAAA is returned when both AAAA and A records exist, signed and DO set, recursive ($n)"
ret=0
$DIG $DIGOPTS aaaa dual.signed +dnssec -b 10.53.0.2 @10.53.0.2 > dig.out.ns2.test$n || ret=1
+grep "flags:.*ad.*QUERY" dig.out.ns2.test$n > /dev/null || ret=1
grep ::3 dig.out.ns2.test$n > /dev/null || ret=1
if [ $ret != 0 ]; then echo_i "failed"; fi
status=`expr $status + $ret`
ret=0
$DIG $DIGOPTS aaaa dual.unsigned +dnssec -b 10.53.0.2 @10.53.0.2 > dig.out.ns2.test$n || ret=1
grep "ANSWER: 0" dig.out.ns2.test$n > /dev/null || ret=1
+grep "flags:.*ad.*QUERY" dig.out.ns2.test$n > /dev/null && ret=1
grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1
if [ $ret != 0 ]; then echo_i "failed"; fi
status=`expr $status + $ret`
ret=0
$DIG $DIGOPTS any dual.signed +dnssec -b 10.53.0.2 @10.53.0.2 > dig.out.ns2.test$n || ret=1
grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1
+grep "flags:.*ad.*QUERY" dig.out.ns2.test$n > /dev/null || ret=1
grep ::3 dig.out.ns2.test$n > /dev/null || ret=1
grep "1.0.0.3" dig.out.ns2.test$n > /dev/null || ret=1
if [ $ret != 0 ]; then echo_i "failed"; fi
status=`expr $status + $ret`
n=`expr $n + 1`
-echo_i "checking that AAAA is omitted from additional section, qtype=MX, unsigned ($n)"
+echo_i "checking that AAAA is omitted from additional section, qtype=MX, unsigned, recursive ($n)"
ret=0
$DIG $DIGOPTS +add +dnssec mx unsigned -b 10.53.0.2 @10.53.0.2 > dig.out.ns2.test$n || ret=1
grep "^mx.unsigned.*AAAA" dig.out.ns2.test$n > /dev/null 2>&1 && ret=1
status=`expr $status + $ret`
n=`expr $n + 1`
-echo_i "checking that AAAA is included in additional section, qtype=MX, signed ($n)"
+echo_i "checking that AAAA is included in additional section, qtype=MX, signed, recursive ($n)"
ret=0
+# we need to prime the cache with addresses for the MX, since additional
+# section data won't be included unless it's validated, and that doesn't
+# necessarily happen otherwise.
+$DIG $DIGOPTS +dnssec mx.signed @10.53.0.2 > /dev/null
+$DIG $DIGOPTS +dnssec mx.signed aaaa @10.53.0.2 > /dev/null
$DIG $DIGOPTS +add +dnssec mx signed -b 10.53.0.2 @10.53.0.2 > dig.out.ns2.test$n || ret=1
grep "^mx.signed.*AAAA" dig.out.ns2.test$n > /dev/null 2>&1 || ret=1
+grep "flags:.*ad.*QUERY" dig.out.ns2.test$n > /dev/null || ret=1
if [ $ret != 0 ]; then echo_i "failed"; fi
status=`expr $status + $ret`
n=`expr $n + 1`
-echo_i "checking that AAAA is included in additional section, qtype=MX, unsigned, over IPv6 ($n)"
+echo_i "checking that AAAA is included in additional section, qtype=MX, unsigned, recursive, over IPv6 ($n)"
if $TESTSOCK6 fd92:7065:b8e:ffff::2
then
ret=0
echo_i "skipped."
fi
-
#
# Recursive tests against:
# filter-aaaa-on-v4 break-dnssec;
echo_i "checking that AAAA is returned when only AAAA record exists, signed, recursive with break-dnssec ($n)"
ret=0
$DIG $DIGOPTS aaaa aaaa-only.signed -b 10.53.0.3 @10.53.0.3 > dig.out.ns3.test$n || ret=1
+grep "flags:.*ad.*QUERY" dig.out.ns3.test$n > /dev/null || ret=1
grep ::2 dig.out.ns3.test$n > /dev/null || ret=1
if [ $ret != 0 ]; then echo_i "failed"; fi
status=`expr $status + $ret`
ret=0
$DIG $DIGOPTS aaaa dual.signed -b 10.53.0.3 @10.53.0.3 > dig.out.ns3.test$n || ret=1
grep "ANSWER: 0" dig.out.ns3.test$n > /dev/null || ret=1
+grep "flags:.*ad.*QUERY" dig.out.ns3.test$n > /dev/null && ret=1
grep "status: NOERROR" dig.out.ns3.test$n > /dev/null || ret=1
if [ $ret != 0 ]; then echo_i "failed"; fi
status=`expr $status + $ret`
ret=0
$DIG $DIGOPTS aaaa dual.unsigned -b 10.53.0.3 @10.53.0.3 > dig.out.ns3.test$n || ret=1
grep "ANSWER: 0" dig.out.ns3.test$n > /dev/null || ret=1
+grep "flags:.*ad.*QUERY" dig.out.ns3.test$n > /dev/null && ret=1
grep "status: NOERROR" dig.out.ns3.test$n > /dev/null || ret=1
if [ $ret != 0 ]; then echo_i "failed"; fi
status=`expr $status + $ret`
ret=0
$DIG $DIGOPTS aaaa dual.signed +dnssec -b 10.53.0.3 @10.53.0.3 > dig.out.ns3.test$n || ret=1
grep "ANSWER: 0" dig.out.ns3.test$n > /dev/null || ret=1
+grep "flags:.*ad.*QUERY" dig.out.ns3.test$n > /dev/null && ret=1
if [ $ret != 0 ]; then echo_i "failed"; fi
status=`expr $status + $ret`
ret=0
$DIG $DIGOPTS aaaa dual.unsigned +dnssec -b 10.53.0.3 @10.53.0.3 > dig.out.ns3.test$n || ret=1
grep "ANSWER: 0" dig.out.ns3.test$n > /dev/null || ret=1
+grep "flags:.*ad.*QUERY" dig.out.ns3.test$n > /dev/null && ret=1
grep "status: NOERROR" dig.out.ns3.test$n > /dev/null || ret=1
if [ $ret != 0 ]; then echo_i "failed"; fi
status=`expr $status + $ret`
ret=0
$DIG $DIGOPTS +add +dnssec mx signed -b 10.53.0.3 @10.53.0.3 > dig.out.ns3.test$n || ret=1
grep "^mx.signed.*AAAA" dig.out.ns3.test$n > /dev/null 2>&1 && ret=1
+grep "flags:.*ad.*QUERY" dig.out.ns3.test$n > /dev/null || ret=1
if [ $ret != 0 ]; then echo_i "failed"; fi
status=`expr $status + $ret`
echo_i "checking that AAAA is returned when only AAAA record exists, signed, recursive ($n)"
ret=0
$DIG $DIGOPTS aaaa aaaa-only.signed -b fd92:7065:b8e:ffff::2 @fd92:7065:b8e:ffff::2 > dig.out.ns2.test$n || ret=1
+grep "flags:.*ad.*QUERY" dig.out.ns2.test$n > /dev/null || ret=1
grep ::2 dig.out.ns2.test$n > /dev/null || ret=1
if [ $ret != 0 ]; then echo_i "failed"; fi
status=`expr $status + $ret`
ret=0
$DIG $DIGOPTS aaaa dual.signed -b fd92:7065:b8e:ffff::2 @fd92:7065:b8e:ffff::2 > dig.out.ns2.test$n || ret=1
grep "ANSWER: 0" dig.out.ns2.test$n > /dev/null || ret=1
+grep "flags:.*ad.*QUERY" dig.out.ns2.test$n > /dev/null && ret=1
grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1
if [ $ret != 0 ]; then echo_i "failed"; fi
status=`expr $status + $ret`
ret=0
$DIG $DIGOPTS aaaa dual.unsigned -b fd92:7065:b8e:ffff::2 @fd92:7065:b8e:ffff::2 > dig.out.ns2.test$n || ret=1
grep "ANSWER: 0" dig.out.ns2.test$n > /dev/null || ret=1
+grep "flags:.*ad.*QUERY" dig.out.ns2.test$n > /dev/null && ret=1
grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1
if [ $ret != 0 ]; then echo_i "failed"; fi
status=`expr $status + $ret`
echo_i "checking that AAAA is returned when both AAAA and A records exist, signed and DO set, recursive ($n)"
ret=0
$DIG $DIGOPTS aaaa dual.signed +dnssec -b fd92:7065:b8e:ffff::2 @fd92:7065:b8e:ffff::2 > dig.out.ns2.test$n || ret=1
+grep "flags:.*ad.*QUERY" dig.out.ns2.test$n > /dev/null || ret=1
grep ::3 dig.out.ns2.test$n > /dev/null || ret=1
if [ $ret != 0 ]; then echo_i "failed"; fi
status=`expr $status + $ret`
ret=0
$DIG $DIGOPTS aaaa dual.unsigned +dnssec -b fd92:7065:b8e:ffff::2 @fd92:7065:b8e:ffff::2 > dig.out.ns2.test$n || ret=1
grep "ANSWER: 0" dig.out.ns2.test$n > /dev/null || ret=1
+grep "flags:.*ad.*QUERY" dig.out.ns2.test$n > /dev/null && ret=1
grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1
if [ $ret != 0 ]; then echo_i "failed"; fi
status=`expr $status + $ret`
ret=0
$DIG $DIGOPTS any dual.signed +dnssec -b fd92:7065:b8e:ffff::2 @fd92:7065:b8e:ffff::2 > dig.out.ns2.test$n || ret=1
grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1
+grep "flags:.*ad.*QUERY" dig.out.ns2.test$n > /dev/null || ret=1
grep ::3 dig.out.ns2.test$n > /dev/null || ret=1
grep "1.0.0.3" dig.out.ns2.test$n > /dev/null || ret=1
if [ $ret != 0 ]; then echo_i "failed"; fi
ret=0
$DIG $DIGOPTS +add +dnssec mx signed -b fd92:7065:b8e:ffff::2 @fd92:7065:b8e:ffff::2 > dig.out.ns2.test$n || ret=1
grep "^mx.signed.*AAAA" dig.out.ns2.test$n > /dev/null 2>&1 || ret=1
+grep "flags:.*ad.*QUERY" dig.out.ns2.test$n > /dev/null || ret=1
if [ $ret != 0 ]; then echo_i "failed"; fi
status=`expr $status + $ret`
echo_i "checking that AAAA is returned when only AAAA record exists, signed, recursive with break-dnssec ($n)"
ret=0
$DIG $DIGOPTS aaaa aaaa-only.signed -b fd92:7065:b8e:ffff::3 @fd92:7065:b8e:ffff::3 > dig.out.ns3.test$n || ret=1
+grep "flags:.*ad.*QUERY" dig.out.ns3.test$n > /dev/null || ret=1
grep ::2 dig.out.ns3.test$n > /dev/null || ret=1
if [ $ret != 0 ]; then echo_i "failed"; fi
status=`expr $status + $ret`
ret=0
$DIG $DIGOPTS aaaa dual.signed -b fd92:7065:b8e:ffff::3 @fd92:7065:b8e:ffff::3 > dig.out.ns3.test$n || ret=1
grep "ANSWER: 0" dig.out.ns3.test$n > /dev/null || ret=1
+grep "flags:.*ad.*QUERY" dig.out.ns3.test$n > /dev/null && ret=1
grep "status: NOERROR" dig.out.ns3.test$n > /dev/null || ret=1
if [ $ret != 0 ]; then echo_i "failed"; fi
status=`expr $status + $ret`
ret=0
$DIG $DIGOPTS aaaa dual.unsigned -b fd92:7065:b8e:ffff::3 @fd92:7065:b8e:ffff::3 > dig.out.ns3.test$n || ret=1
grep "ANSWER: 0" dig.out.ns3.test$n > /dev/null || ret=1
+grep "flags:.*ad.*QUERY" dig.out.ns3.test$n > /dev/null && ret=1
grep "status: NOERROR" dig.out.ns3.test$n > /dev/null || ret=1
if [ $ret != 0 ]; then echo_i "failed"; fi
status=`expr $status + $ret`
ret=0
$DIG $DIGOPTS aaaa dual.signed +dnssec -b fd92:7065:b8e:ffff::3 @fd92:7065:b8e:ffff::3 > dig.out.ns3.test$n || ret=1
grep "ANSWER: 0" dig.out.ns3.test$n > /dev/null || ret=1
+grep "flags:.*ad.*QUERY" dig.out.ns3.test$n > /dev/null && ret=1
if [ $ret != 0 ]; then echo_i "failed"; fi
status=`expr $status + $ret`
ret=0
$DIG $DIGOPTS aaaa dual.unsigned +dnssec -b fd92:7065:b8e:ffff::3 @fd92:7065:b8e:ffff::3 > dig.out.ns3.test$n || ret=1
grep "ANSWER: 0" dig.out.ns3.test$n > /dev/null || ret=1
+grep "flags:.*ad.*QUERY" dig.out.ns3.test$n > /dev/null && ret=1
grep "status: NOERROR" dig.out.ns3.test$n > /dev/null || ret=1
if [ $ret != 0 ]; then echo_i "failed"; fi
status=`expr $status + $ret`
echo_i "checking that AAAA is omitted from additional section, qtype=MX, signed, recursive with break-dnssec ($n)"
ret=0
$DIG $DIGOPTS +add +dnssec mx signed -b fd92:7065:b8e:ffff::3 @fd92:7065:b8e:ffff::3 > dig.out.ns3.test$n || ret=1
+grep "flags:.*ad.*QUERY" dig.out.ns3.test$n > /dev/null || ret=1
grep "^mx.signed.*AAAA" dig.out.ns3.test$n > /dev/null 2>&1 && ret=1
if [ $ret != 0 ]; then echo_i "failed"; fi
status=`expr $status + $ret`
result = isc_taskmgr_excltask(adb->taskmgr, &adb->excl);
if (result != ISC_R_SUCCESS) {
DP(DEF_LEVEL, "adb: task-exclusive mode unavailable, "
- "intializing table sizes to %u\n",
+ "initializing table sizes to %u\n",
nbuckets[11]);
adb->nentries = nbuckets[11];
adb->nnames = nbuckets[11];
/*!
* \brief
- * Context for intializing a dyndb module.
+ * Context for initializing a dyndb module.
*
* This structure passes global server data to which a dyndb
* module will need access -- the server memory context, hash
&cfg_rep_string, NULL
};
-/*%
- * A bracketed address match list
- */
-
static cfg_type_t cfg_type_addrmatchelt;
static cfg_type_t cfg_type_negated;
NULL, NULL
};
+/*%
+ * A bracketed address match list
+ */
LIBISCCFG_EXTERNAL_DATA cfg_type_t cfg_type_bracketed_aml = {
"bracketed_aml", cfg_parse_bracketed_list, cfg_print_bracketed_list,
cfg_doc_bracketed_list, &cfg_rep_list, &cfg_type_addrmatchelt
REQUIRE((client->query.attributes & NS_QUERYATTR_NAMEBUFUSED) == 0);
CTRACE("ns_client_newname");
+
name = NULL;
result = dns_message_gettempname(client->message, &name);
if (result != ISC_R_SUCCESS) {
#include <windows.h>
#endif
+#include <isc/list.h>
+#include <isc/log.h>
#include <isc/mem.h>
#include <isc/mutex.h>
#include <isc/result.h>
-#include <isc/once.h>
+#include <isc/platform.h>
#include <isc/util.h>
+#include <isc/types.h>
#include <ns/hooks.h>
#include <ns/log.h>
+#include <ns/query.h>
#define CHECK(op) \
- do { result = (op); \
- if (result != ISC_R_SUCCESS) goto cleanup; \
+ do { \
+ result = (op); \
+ if (result != ISC_R_SUCCESS) { \
+ goto cleanup; \
+ } \
} while (0)
typedef struct ns_hook_module ns_hook_module_t;
struct ns_hook_module {
isc_mem_t *mctx;
void *handle;
- char *filename;
+ char *modpath;
ns_hook_register_t *register_func;
ns_hook_destroy_t *destroy_func;
void *inst;
LINK(ns_hook_module_t) link;
};
-static ns_hooklist_t hooktab[NS_QUERY_HOOKS_COUNT];
-LIBNS_EXTERNAL_DATA ns_hooktable_t *ns__hook_table = &hooktab;
+static ns_hooklist_t default_hooktable[NS_HOOKPOINTS_COUNT];
+LIBNS_EXTERNAL_DATA ns_hooktable_t *ns__hook_table = &default_hooktable;
/*
* List of hook modules.
* These are stored here so they can be cleaned up on shutdown.
* (The order in which they are stored is not important.)
*/
-static LIST(ns_hook_module_t) hook_modules;
-
-static isc_once_t once = ISC_ONCE_INIT;
-
-static void
-init_modules(void) {
- INIT_LIST(hook_modules);
-}
+static ISC_LIST(ns_hook_module_t) hook_modules;
+static bool hook_modules_initialized = false;
#if HAVE_DLFCN_H && HAVE_DLOPEN
static isc_result_t
-load_symbol(void *handle, const char *filename,
+load_symbol(void *handle, const char *modpath,
const char *symbol_name, void **symbolp)
{
- const char *errmsg;
void *symbol;
REQUIRE(handle != NULL);
REQUIRE(symbolp != NULL && *symbolp == NULL);
+ /*
+ * Clear any pre-existing error conditions before running dlsym().
+ * (In this case, we expect dlsym() to return non-NULL values
+ * and will always return an error if it returns NULL, but
+ * this ensures that we'll report the correct error condition
+ * if there is one.)
+ */
+ dlerror();
symbol = dlsym(handle, symbol_name);
if (symbol == NULL) {
- errmsg = dlerror();
+ const char *errmsg = dlerror();
if (errmsg == NULL) {
errmsg = "returned function pointer is NULL";
}
isc_log_write(ns_lctx, NS_LOGCATEGORY_GENERAL,
NS_LOGMODULE_HOOKS, ISC_LOG_ERROR,
- "failed to look upsymbol %s in "
+ "failed to look up symbol %s in "
"hook module '%s': %s",
- symbol_name, filename, errmsg);
+ symbol_name, modpath, errmsg);
return (ISC_R_FAILURE);
}
- dlerror();
*symbolp = symbol;
}
static isc_result_t
-load_library(isc_mem_t *mctx, const char *filename, ns_hook_module_t **hmodp) {
+load_library(isc_mem_t *mctx, const char *modpath, ns_hook_module_t **hmodp) {
isc_result_t result;
void *handle = NULL;
ns_hook_module_t *hmod = NULL;
REQUIRE(hmodp != NULL && *hmodp == NULL);
- flags = RTLD_NOW|RTLD_LOCAL;
+ flags = RTLD_NOW | RTLD_LOCAL;
#ifdef RTLD_DEEPBIND
flags |= RTLD_DEEPBIND;
#endif
- handle = dlopen(filename, flags);
+ handle = dlopen(modpath, flags);
if (handle == NULL) {
- CHECK(ISC_R_FAILURE);
+ const char *errmsg = dlerror();
+ if (errmsg == NULL) {
+ errmsg = "unknown error";
+ }
+ isc_log_write(ns_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_HOOKS, ISC_LOG_ERROR,
+ "failed to dlopen() hook module '%s': %s",
+ modpath, errmsg);
+ return (ISC_R_FAILURE);
}
- /* Clear dlerror */
- dlerror();
-
- CHECK(load_symbol(handle, filename, "hook_version",
+ CHECK(load_symbol(handle, modpath, "hook_version",
(void **)&version_func));
- version = version_func(NULL);
+ version = version_func();
if (version < (NS_HOOK_VERSION - NS_HOOK_AGE) ||
version > NS_HOOK_VERSION)
{
isc_log_write(ns_lctx, NS_LOGCATEGORY_GENERAL,
NS_LOGMODULE_HOOKS, ISC_LOG_ERROR,
- "driver API version mismatch: %d/%d",
+ "hook API version mismatch: %d/%d",
version, NS_HOOK_VERSION);
CHECK(ISC_R_FAILURE);
}
- CHECK(load_symbol(handle, filename, "hook_register",
+ CHECK(load_symbol(handle, modpath, "hook_register",
(void **)®ister_func));
- CHECK(load_symbol(handle, filename, "hook_destroy",
+ CHECK(load_symbol(handle, modpath, "hook_destroy",
(void **)&destroy_func));
hmod = isc_mem_get(mctx, sizeof(*hmod));
hmod->mctx = NULL;
isc_mem_attach(mctx, &hmod->mctx);
hmod->handle = handle;
+ hmod->modpath = isc_mem_strdup(hmod->mctx, modpath);
hmod->register_func = register_func;
hmod->destroy_func = destroy_func;
-
hmod->inst = NULL;
ISC_LINK_INIT(hmod, link);
isc_log_write(ns_lctx, NS_LOGCATEGORY_GENERAL,
NS_LOGMODULE_HOOKS, ISC_LOG_ERROR,
"failed to dynamically load "
- "module '%s': %s (%s)", filename,
- dlerror(), isc_result_totext(result));
+ "module '%s': %s", modpath,
+ isc_result_totext(result));
if (hmod != NULL) {
- isc_mem_putanddetach(&hmod->mctx, hmod,
- sizeof(*hmod));
+ isc_mem_putanddetach(&hmod->mctx, hmod, sizeof(*hmod));
}
if (handle != NULL) {
- dlclose(handle);
+ (void) dlclose(handle);
}
}
*hmodp = NULL;
if (hmod->handle != NULL) {
- dlclose(hmod->handle);
+ (void) dlclose(hmod->handle);
}
- if (hmod->filename != NULL) {
- isc_mem_free(hmod->mctx, hmod->filename);
+ if (hmod->modpath != NULL) {
+ isc_mem_free(hmod->mctx, hmod->modpath);
}
isc_mem_putanddetach(&hmod->mctx, hmod, sizeof(*hmod));
}
#elif _WIN32
static isc_result_t
-load_symbol(HMODULE handle, const char *filename,
+load_symbol(HMODULE handle, const char *modpath,
const char *symbol_name, void **symbolp)
{
void *symbol;
NS_LOGMODULE_HOOKS, ISC_LOG_ERROR,
"failed to look up symbol %s in "
"module '%s': %d",
- symbol_name, filename, errstatus);
+ symbol_name, modpath, errstatus);
return (ISC_R_FAILURE);
}
}
static isc_result_t
-load_library(isc_mem_t *mctx, const char *filename, ns_hook_module_t **hmodp) {
+load_library(isc_mem_t *mctx, const char *modpath, ns_hook_module_t **hmodp) {
isc_result_t result;
HMODULE handle;
ns_hook_module_t *hmod = NULL;
REQUIRE(hmodp != NULL && *hmodp == NULL);
- handle = LoadLibraryA(filename);
+ handle = LoadLibraryA(modpath);
if (handle == NULL) {
CHECK(ISC_R_FAILURE);
}
- CHECK(load_symbol(handle, filename, "hook_version",
+ CHECK(load_symbol(handle, modpath, "hook_version",
(void **)&version_func));
version = version_func(NULL);
{
isc_log_write(ns_lctx, NS_LOGCATEGORY_GENERAL,
NS_LOGMODULE_HOOKS, ISC_LOG_ERROR,
- "driver API version mismatch: %d/%d",
+ "hook API version mismatch: %d/%d",
version, NS_HOOK_VERSION);
CHECK(ISC_R_FAILURE);
}
- CHECK(load_symbol(handle, filename, "hook_register",
+ CHECK(load_symbol(handle, modpath, "hook_register",
(void **)®ister_func));
- CHECK(load_symbol(handle, filename, "hook_destroy",
+ CHECK(load_symbol(handle, modpath, "hook_destroy",
(void **)&destroy_func));
hmod = isc_mem_get(mctx, sizeof(*hmod));
hmod->mctx = NULL;
isc_mem_attach(mctx, &hmod->mctx);
hmod->handle = handle;
+ hmod->modpath = isc_mem_strdup(hmod->mctx, modpath);
hmod->register_func = register_func;
hmod->destroy_func = destroy_func;
-
hmod->inst = NULL;
ISC_LINK_INIT(hmod, link);
isc_log_write(ns_lctx, NS_LOGCATEGORY_GENERAL,
NS_LOGMODULE_HOOKS, ISC_LOG_ERROR,
"failed to dynamically load "
- "hook module '%s': %d (%s)", filename,
+ "hook module '%s': %d (%s)", modpath,
GetLastError(), isc_result_totext(result));
+
if (hmod != NULL) {
- isc_mem_putanddetach(&hmod->mctx, hmod,
- sizeof(*hmod));
+ isc_mem_putanddetach(&hmod->mctx, hmod, sizeof(*hmod));
}
if (handle != NULL) {
FreeLibrary(hmod->handle);
}
- if (hmod->filename != NULL) {
- isc_mem_free(hmod->mctx, hmod->filename);
+ if (hmod->modpath != NULL) {
+ isc_mem_free(hmod->mctx, hmod->modpath);
}
isc_mem_putanddetach(&hmod->mctx, hmod, sizeof(*hmod));
}
#else /* HAVE_DLFCN_H || _WIN32 */
static isc_result_t
-load_library(isc_mem_t *mctx, const char *filename, ns_hook_module_t **hmodp) {
+load_library(isc_mem_t *mctx, const char *modpath, ns_hook_module_t **hmodp) {
UNUSED(mctx);
- UNUSED(filename);
+ UNUSED(modpath);
UNUSED(hmodp);
isc_log_write(ns_lctx, NS_LOGCATEGORY_GENERAL,
NS_LOGMODULE_HOOKS, ISC_LOG_ERROR,
- "hook module support is not hmodlemented");
+ "hook module support is not implemented");
return (ISC_R_NOTIMPLEMENTED);
}
#endif /* HAVE_DLFCN_H */
isc_result_t
-ns_hookmodule_load(const char *libname, const unsigned int modid,
+ns_hookmodule_load(const char *modpath, const unsigned int modid,
const char *parameters,
- const char *file, unsigned long line,
+ const char *cfg_file, unsigned long cfg_line,
const void *cfg, void *actx,
ns_hookctx_t *hctx, ns_hooktable_t *hooktable)
{
isc_result_t result;
- ns_hook_module_t *module = NULL;
+ ns_hook_module_t *hmod = NULL;
+ REQUIRE(hook_modules_initialized);
REQUIRE(NS_HOOKCTX_VALID(hctx));
+ REQUIRE(hooktable != NULL);
isc_log_write(ns_lctx, NS_LOGCATEGORY_GENERAL,
NS_LOGMODULE_HOOKS, ISC_LOG_INFO,
- "loading module '%s'", libname);
+ "loading module '%s'", modpath);
- CHECK(load_library(hctx->mctx, libname, &module));
- CHECK(module->register_func(modid, parameters, file, line,
- cfg, actx, hctx, hooktable,
- &module->inst));
+ CHECK(load_library(hctx->mctx, modpath, &hmod));
+ CHECK(hmod->register_func(modid, parameters, cfg_file, cfg_line,
+ cfg, actx, hctx, hooktable,
+ &hmod->inst));
- APPEND(hook_modules, module, link);
- result = ISC_R_SUCCESS;
+ ISC_LIST_APPEND(hook_modules, hmod, link);
cleanup:
- if (result != ISC_R_SUCCESS && module != NULL) {
- unload_library(&module);
+ if (result != ISC_R_SUCCESS && hmod != NULL) {
+ unload_library(&hmod);
}
return (result);
}
void
-ns_hookmodule_cleanup(void) {
+ns_hookmodule_unload_all(void) {
ns_hook_module_t *hmod, *prev;
- RUNTIME_CHECK(isc_once_do(&once, init_modules) == ISC_R_SUCCESS);
+ if (!hook_modules_initialized) {
+ return;
+ }
hmod = ISC_LIST_TAIL(hook_modules);
while (hmod != NULL) {
- prev = PREV(hmod, link);
- UNLINK(hook_modules, hmod, link);
+ prev = ISC_LIST_PREV(hmod, link);
+ ISC_LIST_UNLINK(hook_modules, hmod, link);
isc_log_write(ns_lctx, NS_LOGCATEGORY_GENERAL,
NS_LOGMODULE_HOOKS, ISC_LOG_INFO,
- "unloading module '%s'", hmod->filename);
+ "unloading module '%s'", hmod->modpath);
hmod->destroy_func(&hmod->inst);
ENSURE(hmod->inst == NULL);
unload_library(&hmod);
hctx->magic = 0;
- hctx->lctx = NULL;
-
isc_mem_putanddetach(&hctx->mctx, hctx, sizeof(*hctx));
}
ns_hooktable_init(ns_hooktable_t *hooktable) {
int i;
- RUNTIME_CHECK(isc_once_do(&once, init_modules) == ISC_R_SUCCESS);
+ if (!hook_modules_initialized) {
+ ISC_LIST_INIT(hook_modules);
+ hook_modules_initialized = true;
+ }
- for (i = 0; i < NS_QUERY_HOOKS_COUNT; i++) {
+ for (i = 0; i < NS_HOOKPOINTS_COUNT; i++) {
ISC_LIST_INIT((*hooktable)[i]);
}
}
REQUIRE(tablep != NULL && *tablep == NULL);
- hooktable = isc_mem_get(mctx, sizeof(ns_hooktable_t));
+ hooktable = isc_mem_get(mctx, sizeof(*hooktable));
ns_hooktable_init(hooktable);
void
ns_hooktable_free(isc_mem_t *mctx, void **tablep) {
+ ns_hooktable_t *table;
+
REQUIRE(tablep != NULL && *tablep != NULL);
- isc_mem_put(mctx, *tablep, sizeof(ns_hooktable_t));
+ table = *tablep;
*tablep = NULL;
+ isc_mem_put(mctx, table, sizeof(*table));
}
void
ns_hook_add(ns_hooktable_t *hooktable, ns_hookpoint_t hookpoint,
ns_hook_t *hook)
{
- REQUIRE(hookpoint < NS_QUERY_HOOKS_COUNT);
+ REQUIRE(hookpoint < NS_HOOKPOINTS_COUNT);
REQUIRE(hook != NULL);
if (hooktable == NULL) {
#define NS_CLIENTATTR_WANTDNSSEC 0x00010 /*%< include dnssec records */
#define NS_CLIENTATTR_WANTNSID 0x00020 /*%< include nameserver ID */
/* Obsolete: NS_CLIENTATTR_FILTER_AAAA 0x00040 */
-/* Obsolete: define NS_CLIENTATTR_FILTER_AAAA_RC 0x00080 */
+/* Obsolete: NS_CLIENTATTR_FILTER_AAAA_RC 0x00080 */
#define NS_CLIENTATTR_WANTAD 0x00100 /*%< want AD in response if possible */
#define NS_CLIENTATTR_WANTCOOKIE 0x00200 /*%< return a COOKIE */
#define NS_CLIENTATTR_HAVECOOKIE 0x00400 /*%< has a valid COOKIE */
void
ns_client_putrdataset(ns_client_t *client, dns_rdataset_t **rdatasetp);
-/*%
+/*%<
* Get and release temporary rdatasets in the client message;
* used in query.c and in hook modules.
*/
isc_result_t
ns_client_newnamebuf(ns_client_t *client);
-/*%
+/*%<
* Allocate a name buffer for the client message.
*/
dns_name_t *
ns_client_newname(ns_client_t *client, isc_buffer_t *dbuf, isc_buffer_t *nbuf);
-/*%
+/*%<
* Get a temporary name for the client message.
*/
isc_buffer_t *
ns_client_getnamebuf(ns_client_t *client);
-/*%
+/*%<
* Get a name buffer from the pool, or allocate a new one if needed.
*/
void
ns_client_keepname(ns_client_t *client, dns_name_t *name, isc_buffer_t *dbuf);
-/*%
+/*%<
* Adjust buffer 'dbuf' to reflect that 'name' is using space in it,
* and set client attributes appropriately.
*/
void
ns_client_releasename(ns_client_t *client, dns_name_t **namep);
-/*%
+/*%<
* Release 'name' back to the pool of temporary names for the client
* message. If it is using a name buffer, relinquish its exclusive
* rights on the buffer.
isc_result_t
ns_client_newdbversion(ns_client_t *client, unsigned int n);
-/*%
+/*%<
* Allocate 'n' new database versions for use by client queries.
*/
ns_dbversion_t *
ns_client_getdbversion(ns_client_t *client);
-/*%
+/*%<
* Get a free database version for use by a client query, allocating
* a new one if necessary.
*/
ns_dbversion_t *
ns_client_findversion(ns_client_t *client, dns_db_t *db);
-/*%
+/*%<
* Find the correct database version to use with a client query.
* If we have already done a query related to the database 'db',
* make sure subsequent queries are from the same version;
* called this time and foo_bar() will return ISC_R_SUCCESS.
*/
+/*!
+ * Currently-defined hook points. So long as these are unique,
+ * the order in which they are declared is unimportant, but
+ * currently matches the order in which they are referenced in
+ * query.c.
+ */
typedef enum {
+ /* hookpoints from query.c */
NS_QUERY_QCTX_INITIALIZED,
NS_QUERY_QCTX_DESTROYED,
NS_QUERY_SETUP,
NS_QUERY_DONE_BEGIN,
NS_QUERY_DONE_SEND,
- NS_QUERY_HOOKS_COUNT /* MUST BE LAST */
+ /* XXX other files could be added later */
+
+ NS_HOOKPOINTS_COUNT /* MUST BE LAST */
} ns_hookpoint_t;
typedef bool
} ns_hook_t;
typedef ISC_LIST(ns_hook_t) ns_hooklist_t;
-typedef ns_hooklist_t ns_hooktable_t[NS_QUERY_HOOKS_COUNT];
+typedef ns_hooklist_t ns_hooktable_t[NS_HOOKPOINTS_COUNT];
-/*
+/*%
* ns__hook_table is a global hook table, which is used if view->hooktable
* is NULL. It's intended only for use by unit tests.
*/
LIBNS_EXTERNAL_DATA extern ns_hooktable_t *ns__hook_table;
/*!
- * Context for intializing a hook module.
+ * Context for initializing a hook module.
*
* This structure passes data to which a hook module will need
* access -- server memory context, hash initializer, log context, etc.
} ns_hookctx_t;
#define NS_HOOKCTX_MAGIC ISC_MAGIC('H', 'k', 'c', 'x')
-#define NS_HOOKCTX_VALID(d) ISC_MAGIC_VALID(d, NS_HOOKCTX_MAGIC)
+#define NS_HOOKCTX_VALID(h) ISC_MAGIC_VALID(h, NS_HOOKCTX_MAGIC)
+
/*
* API version
*
ns_hookctx_t *hctx,
ns_hooktable_t *hooktable,
void **instp);
-/*%
+/*%<
* Called when registering a new module.
*
* 'parameters' contains the module configuration text.
*/
typedef void ns_hook_destroy_t(void **instp);
-/*%
+/*%<
* Destroy a module instance.
*
* '*instp' must be set to NULL by the function before it returns.
*/
-typedef int ns_hook_version_t(unsigned int *flags);
-/*%
+typedef int ns_hook_version_t(void);
+/*%<
* Return the API version number a hook module was compiled with.
*
- * If the returned version number is no greater than than
+ * If the returned version number is no greater than
* NS_HOOK_VERSION, and no less than NS_HOOK_VERSION - NS_HOOK_AGE,
* then the module is API-compatible with named.
- *
- * 'flags' is currently unused and may be NULL, but could be used in
- * the future to pass back driver capabilities or other information.
*/
+/*%
+ * Prototypes for API functions to be defined in each module.
+ */
+ns_hook_destroy_t hook_destroy;
+ns_hook_register_t hook_register;
+ns_hook_version_t hook_version;
+
isc_result_t
ns_hook_createctx(isc_mem_t *mctx, ns_hookctx_t **hctxp);
void
ns_hook_destroyctx(ns_hookctx_t **hctxp);
+/*%<
+ * Create/destroy a hook module context.
+ */
isc_result_t
-ns_hookmodule_load(const char *libname, const unsigned int modid,
+ns_hookmodule_load(const char *modpath, const unsigned int modid,
const char *parameters,
- const char *file, unsigned long line,
+ const char *cfg_file, unsigned long cfg_line,
const void *cfg, void *actx,
ns_hookctx_t *hctx, ns_hooktable_t *hooktable);
+/*%<
+ * Load the hook module specified from the file 'modpath', using
+ * parameters 'parameters'.
+ *
+ * 'cfg_file' and 'cfg_line' specify the location of the hook module
+ * declaration in the configuration file.
+ *
+ * 'cfg' and 'actx' are the configuration context and ACL configuration
+ * context, respectively; they are passed as void * here in order to
+ * prevent this library from having a dependency on libisccfg).
+ *
+ * 'hctx' is the hook context and 'hooktable' is the hook table
+ * into which hook points should be registered.
+ */
+
void
-ns_hookmodule_cleanup(void);
+ns_hookmodule_unload_all(void);
+/*%<
+ * Unload all currently loaded hook modules.
+ */
void
ns_hook_add(ns_hooktable_t *hooktable, ns_hookpoint_t hookpoint,
ns_hook_t *hook);
-/*%
+/*%<
* Append hook function 'hook' to the list of hooks at 'hookpoint' in
* 'hooktable'.
*
void
ns_hooktable_init(ns_hooktable_t *hooktable);
-/*%
+/*%<
* Initialize a hook table.
*/
isc_result_t
ns_hooktable_create(isc_mem_t *mctx, ns_hooktable_t **tablep);
-/*%
+/*%<
* Allocate and initialize a hook table.
*/
void
ns_hooktable_free(isc_mem_t *mctx, void **tablep);
-/*%
+/*%<
* Free a hook table.
*/
-
#endif /* NS_HOOKS_H */
isc_result_t
ns__query_sfcache(query_ctx_t *qctx);
-/*%
+/*%<
* (Must not be used outside this module and its associated unit tests.)
*/
isc_result_t
ns__query_start(query_ctx_t *qctx);
-/*%
+/*%<
* (Must not be used outside this module and its associated unit tests.)
*/
* is a macro instead of an inline function; it needs to be able to use
* 'goto cleanup' regardless of the return value.)
*/
-#define PROCESS_HOOK(_id, _qctx) \
+#define CALL_HOOK(_id, _qctx) \
do { \
isc_result_t _res; \
ns_hooktable_t *_tab = get_hooktab(_qctx); \
* destruction calls which *must* run in every configured module.
*
* (This could be implemented as an inline void function, but is left as a
- * macro for symmetry with PROCESS_HOOK above.)
+ * macro for symmetry with CALL_HOOK above.)
*/
-#define PROCESS_ALL_HOOKS(_id, _qctx) \
+#define CALL_HOOK_NORETURN(_id, _qctx) \
do { \
isc_result_t _res; \
ns_hooktable_t *_tab = get_hooktab(_qctx); \
static void
query_setorder(query_ctx_t *qctx, dns_name_t *name, dns_rdataset_t *rdataset) {
ns_client_t *client = qctx->client;
+ dns_order_t *order = client->view->order;
CTRACE(ISC_LOG_DEBUG(3), "query_setorder");
UNUSED(client);
- if (qctx->view->order != NULL) {
- rdataset->attributes |=
- dns_order_find(qctx->view->order,
- name, rdataset->type,
- rdataset->rdclass);
+ if (order != NULL) {
+ rdataset->attributes |= dns_order_find(order, name,
+ rdataset->type,
+ rdataset->rdclass);
}
rdataset->attributes |= DNS_RDATASETATTR_LOADORDER;
};
/*
- * Handle glue and fetch any other needed additional data for 'rdataset'
+ * Handle glue and fetch any other needed additional data for 'rdataset'.
*/
static void
query_additional(query_ctx_t *qctx, dns_rdataset_t *rdataset) {
REQUIRE(qctx != NULL);
REQUIRE(client != NULL);
- memset(qctx, 0, sizeof(query_ctx_t));
+ memset(qctx, 0, sizeof(*qctx));
/* Set this first so CCTRACE will work */
qctx->client = client;
qctx->event = event;
qctx->qtype = qctx->type = qtype;
qctx->result = ISC_R_SUCCESS;
- qctx->fname = NULL;
- qctx->zfname = NULL;
- qctx->rdataset = NULL;
- qctx->zrdataset = NULL;
- qctx->sigrdataset = NULL;
- qctx->zsigrdataset = NULL;
- qctx->zversion = NULL;
- qctx->node = NULL;
- qctx->znode = NULL;
- qctx->db = NULL;
- qctx->zdb = NULL;
- qctx->version = NULL;
- qctx->zone = NULL;
- qctx->need_wildcardproof = false;
- qctx->redirected = false;
- qctx->dns64_exclude = qctx->dns64 = qctx->rpz = false;
- qctx->options = 0;
- qctx->resuming = false;
- qctx->is_zone = false;
qctx->findcoveringnsec = qctx->view->synthfromdnssec;
- qctx->is_staticstub_zone = false;
- qctx->nxrewrite = false;
- qctx->answer_has_ns = false;
- qctx->authoritative = false;
- PROCESS_ALL_HOOKS(NS_QUERY_QCTX_INITIALIZED, qctx);
+ CALL_HOOK_NORETURN(NS_QUERY_QCTX_INITIALIZED, qctx);
}
/*%
static void
qctx_destroy(query_ctx_t *qctx) {
- PROCESS_ALL_HOOKS(NS_QUERY_QCTX_DESTROYED, qctx);
+ CALL_HOOK_NORETURN(NS_QUERY_QCTX_DESTROYED, qctx);
dns_view_detach(&qctx->view);
}
qctx_init(client, NULL, qtype, &qctx);
query_trace(&qctx);
- PROCESS_HOOK(NS_QUERY_SETUP, &qctx);
+ CALL_HOOK(NS_QUERY_SETUP, &qctx);
/*
* If it's a SIG query, we'll iterate the node.
qctx->need_wildcardproof = false;
qctx->rpz = false;
- PROCESS_HOOK(NS_QUERY_START_BEGIN, qctx);
+ CALL_HOOK(NS_QUERY_START_BEGIN, qctx);
/*
* If we require a server cookie then send back BADCOOKIE
CCTRACE(ISC_LOG_DEBUG(3), "query_lookup");
- PROCESS_HOOK(NS_QUERY_LOOKUP_BEGIN, qctx);
+ CALL_HOOK(NS_QUERY_LOOKUP_BEGIN, qctx);
dns_clientinfomethods_init(&cm, ns_client_sourceip);
dns_clientinfo_init(&ci, qctx->client, NULL);
query_ctx_t qctx;
/*
- * Initalize a new qctx and use it to resume
+ * Initialize a new qctx and use it to resume
* from recursion.
*/
qctx_init(client, devent, 0, &qctx);
char tbuf[DNS_RDATATYPE_FORMATSIZE];
#endif
- PROCESS_HOOK(NS_QUERY_RESUME_BEGIN, qctx);
+ CALL_HOOK(NS_QUERY_RESUME_BEGIN, qctx);
qctx->want_restart = false;
CCTRACE(ISC_LOG_DEBUG(3), "query_gotanswer");
- PROCESS_HOOK(NS_QUERY_GOT_ANSWER_BEGIN, qctx);
+ CALL_HOOK(NS_QUERY_GOT_ANSWER_BEGIN, qctx);
if (query_checkrrl(qctx, result) != ISC_R_SUCCESS) {
return (ns_query_done(qctx));
isc_result_t result;
dns_rdatatype_t onetype = 0; /* type to use for minimal-any */
- PROCESS_HOOK(NS_QUERY_RESPOND_ANY_BEGIN, qctx);
+ CALL_HOOK(NS_QUERY_RESPOND_ANY_BEGIN, qctx);
result = dns_db_allrdatasets(qctx->db, qctx->node,
qctx->version, 0, &rdsiter);
}
if (found) {
- PROCESS_HOOK(NS_QUERY_RESPOND_ANY_FOUND, qctx);
+ CALL_HOOK(NS_QUERY_RESPOND_ANY_FOUND, qctx);
if (qctx->fname != NULL) {
dns_message_puttempname(qctx->client->message,
&qctx->fname);
}
} else {
- PROCESS_HOOK(NS_QUERY_RESPOND_ANY_NOT_FOUND, qctx);
+ CALL_HOOK(NS_QUERY_RESPOND_ANY_NOT_FOUND, qctx);
if (qctx->fname != NULL) {
dns_message_puttempname(qctx->client->message,
* other way to prevent that assertion, since the order in
* which hook modules are configured can't be enforced.)
*/
- PROCESS_HOOK(NS_QUERY_RESPOND_BEGIN, qctx);
+ CALL_HOOK(NS_QUERY_RESPOND_BEGIN, qctx);
if (WANTDNSSEC(qctx->client) && qctx->sigrdataset != NULL) {
sigrdatasetp = &qctx->sigrdataset;
query_notfound(query_ctx_t *qctx) {
isc_result_t result;
- PROCESS_HOOK(NS_QUERY_NOTFOUND_BEGIN, qctx);
+ CALL_HOOK(NS_QUERY_NOTFOUND_BEGIN, qctx);
INSIST(!qctx->is_zone);
dns_rdataset_t **sigrdatasetp = NULL;
bool detach = false;
- PROCESS_HOOK(NS_QUERY_PREP_DELEGATION_BEGIN, qctx);
+ CALL_HOOK(NS_QUERY_PREP_DELEGATION_BEGIN, qctx);
/*
* qctx->fname could be released in query_addrrset(), so save a copy of
query_zone_delegation(query_ctx_t *qctx) {
isc_result_t result;
- PROCESS_HOOK(NS_QUERY_ZONE_DELEGATION_BEGIN, qctx);
+ CALL_HOOK(NS_QUERY_ZONE_DELEGATION_BEGIN, qctx);
/*
* If the query type is DS, look to see if we are
query_delegation(query_ctx_t *qctx) {
isc_result_t result;
- PROCESS_HOOK(NS_QUERY_DELEGATION_BEGIN, qctx);
+ CALL_HOOK(NS_QUERY_DELEGATION_BEGIN, qctx);
qctx->authoritative = false;
query_nodata(query_ctx_t *qctx, isc_result_t res) {
isc_result_t result = res;
- PROCESS_HOOK(NS_QUERY_NODATA_BEGIN, qctx);
+ CALL_HOOK(NS_QUERY_NODATA_BEGIN, qctx);
#ifdef dns64_bis_return_excluded_addresses
if (qctx->dns64)
uint32_t ttl;
isc_result_t result;
- PROCESS_HOOK(NS_QUERY_NXDOMAIN_BEGIN, qctx);
+ CALL_HOOK(NS_QUERY_NXDOMAIN_BEGIN, qctx);
INSIST(qctx->is_zone || REDIRECT(qctx->client));
dns_rdata_t rdata = DNS_RDATA_INIT;
dns_rdata_cname_t cname;
- PROCESS_HOOK(NS_QUERY_CNAME_BEGIN, qctx);
+ CALL_HOOK(NS_QUERY_CNAME_BEGIN, qctx);
/*
* If we have a zero ttl from the cache refetch it.
isc_result_t result;
unsigned int nlabels;
- PROCESS_HOOK(NS_QUERY_DNAME_BEGIN, qctx);
+ CALL_HOOK(NS_QUERY_DNAME_BEGIN, qctx);
/*
* Compare the current qname to the found name. We need
*/
static isc_result_t
query_prepresponse(query_ctx_t *qctx) {
- isc_result_t result = ISC_R_SUCCESS;
+ isc_result_t result;
- PROCESS_HOOK(NS_QUERY_PREP_RESPONSE_BEGIN, qctx);
+ CALL_HOOK(NS_QUERY_PREP_RESPONSE_BEGIN, qctx);
if (WANTDNSSEC(qctx->client) &&
(qctx->fname->attributes & DNS_NAMEATTR_WILDCARD) != 0)
CCTRACE(ISC_LOG_DEBUG(3), "ns_query_done");
- PROCESS_HOOK(NS_QUERY_DONE_BEGIN, qctx);
+ CALL_HOOK(NS_QUERY_DONE_BEGIN, qctx);
/*
* General cleanup.
qctx->result = ISC_R_FAILURE;
}
- PROCESS_HOOK(NS_QUERY_DONE_SEND, qctx);
+ CALL_HOOK(NS_QUERY_DONE_SEND, qctx);
query_send(qctx->client);
ns_hook_add
ns_hook_createctx
ns_hook_destroyctx
-ns_hookmodule_cleanup
ns_hookmodule_load
+ns_hookmodule_unload_all
ns_hooktable_create
ns_hooktable_free
ns_hooktable_init