]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
restore filter-aaaa syntax checking
authorEvan Hunt <each@isc.org>
Sat, 3 Nov 2018 06:28:25 +0000 (23:28 -0700)
committerEvan Hunt <each@isc.org>
Thu, 6 Dec 2018 18:29:12 +0000 (10:29 -0800)
- added functionality to check hook parameters in named-checkconf,
  and restored the checkconf tests that were removed from the
  filter-aaaa test.

22 files changed:
bin/check/Makefile.in
bin/check/named-checkconf.c
bin/check/named-checkconf.docbook
bin/hooks/filter-aaaa.c
bin/named/server.c
bin/tests/system/filter-aaaa/conf/bad1.conf [new file with mode: 0644]
bin/tests/system/filter-aaaa/conf/bad2.conf [new file with mode: 0644]
bin/tests/system/filter-aaaa/conf/bad3.conf [new file with mode: 0644]
bin/tests/system/filter-aaaa/conf/bad4.conf [new file with mode: 0644]
bin/tests/system/filter-aaaa/conf/bad5.conf [new file with mode: 0644]
bin/tests/system/filter-aaaa/conf/good1.conf [new file with mode: 0644]
bin/tests/system/filter-aaaa/conf/good2.conf [new file with mode: 0644]
bin/tests/system/filter-aaaa/conf/good3.conf [new file with mode: 0644]
bin/tests/system/filter-aaaa/conf/good4.conf [new file with mode: 0644]
bin/tests/system/filter-aaaa/conf/good5.conf [new file with mode: 0644]
bin/tests/system/filter-aaaa/tests.sh
lib/bind9/Makefile.in
lib/bind9/check.c
lib/bind9/include/bind9/check.h
lib/ns/hooks.c
lib/ns/include/ns/hooks.h
lib/ns/win32/libns.def

index b15cd90a7044dcf99fec1ab44a9527915c782478..8f009a4b81239726682472c76f02db22107c476b 100644 (file)
@@ -66,7 +66,7 @@ named-checkzone.@O@: named-checkzone.c
 named-checkconf@EXEEXT@: named-checkconf.@O@ check-tool.@O@ ${ISCDEPLIBS} \
                ${NSDEPENDLIBS} ${DNSDEPLIBS} ${ISCCFGDEPLIBS} ${BIND9DEPLIBS}
        export BASEOBJS="named-checkconf.@O@ check-tool.@O@"; \
-       export LIBS0="${NSLIBS} ${BIND9LIBS} ${ISCCFGLIBS} ${DNSLIBS}"; \
+       export LIBS0="${BIND9LIBS} ${NSLIBS} ${ISCCFGLIBS} ${DNSLIBS}"; \
        ${FINALBUILDCMD}
 
 named-checkzone@EXEEXT@: named-checkzone.@O@ check-tool.@O@ ${ISCDEPLIBS} \
index 753f5ba69c37a1bac0404335d606fe3cdec8b1e5..d5599ea133ec6b5c82c30f4b188cf1cf3804c9c1 100644 (file)
@@ -46,6 +46,8 @@
 
 static const char *program = "named-checkconf";
 
+static bool loadhooks = true;
+
 isc_log_t *logc = NULL;
 
 #define CHECK(r)\
@@ -562,7 +564,7 @@ main(int argc, char **argv) {
        /*
         * Process memory debugging argument first.
         */
-#define CMDLINE_FLAGS "dhjlm:t:pvxz"
+#define CMDLINE_FLAGS "cdhjlm:t:pvxz"
        while ((c = isc_commandline_parse(argc, argv, CMDLINE_FLAGS)) != -1) {
                switch (c) {
                case 'm':
@@ -587,6 +589,10 @@ main(int argc, char **argv) {
 
        while ((c = isc_commandline_parse(argc, argv, CMDLINE_FLAGS)) != EOF) {
                switch (c) {
+               case 'c':
+                       loadhooks = false;
+                       break;
+
                case 'd':
                        debug++;
                        break;
@@ -677,9 +683,10 @@ main(int argc, char **argv) {
            ISC_R_SUCCESS)
                exit(1);
 
-       result = bind9_check_namedconf(config, logc, mctx);
-       if (result != ISC_R_SUCCESS)
+       result = bind9_check_namedconf(config, loadhooks, logc, mctx);
+       if (result != ISC_R_SUCCESS) {
                exit_status = 1;
+       }
 
        if (result == ISC_R_SUCCESS && (load_zones || list_zones)) {
                result = load_zones_fromconfig(config, mctx, list_zones);
index dea38896ceec7018234484dafba1ffa731ea5580..69f322c4d8ca3c5cbe1a2ff83ff36a11e4a7ae9c 100644 (file)
@@ -52,7 +52,7 @@
   <refsynopsisdiv>
     <cmdsynopsis sepchar=" ">
       <command>named-checkconf</command>
-      <arg choice="opt" rep="norepeat"><option>-hjlvz</option></arg>
+      <arg choice="opt" rep="norepeat"><option>-chjlvz</option></arg>
       <arg choice="opt" rep="norepeat"><option>-p</option>
        <arg choice="opt" rep="norepeat"><option>-x</option>
       </arg></arg>
         </listitem>
       </varlistentry>
 
+      <varlistentry>
+        <term>-c</term>
+        <listitem>
+          <para>
+           Check "core" configuration only. This suppresses the loading
+           of hook modules, and causes all parameters to
+           <command>hook</command> statements to be ignored.
+          </para>
+        </listitem>
+      </varlistentry>
+
       <varlistentry>
         <term>-p</term>
         <listitem>
index 00846452629bd09afd37e8182c88715d366f9d7e..50e5d473acc836578523cb1cc893fe9c22cd849e 100644 (file)
@@ -249,8 +249,52 @@ parse_filter_aaaa_on(const cfg_obj_t *param_obj, const char *param_name,
        return (result);
 }
 
+static isc_result_t
+check_syntax(cfg_obj_t *fmap, const void *cfg,
+            isc_mem_t *mctx, isc_log_t *lctx, void *actx)
+{
+       isc_result_t result = ISC_R_SUCCESS;
+       const cfg_obj_t *aclobj = NULL;
+       dns_acl_t *acl = NULL;
+       filter_aaaa_t f4 = NONE, f6 = NONE;
+
+       cfg_map_get(fmap, "filter-aaaa", &aclobj);
+       if (aclobj == NULL) {
+               return (result);
+       }
+
+       CHECK(cfg_acl_fromconfig(aclobj, (const cfg_obj_t *) cfg,
+                                lctx, (cfg_aclconfctx_t *) actx,
+                                mctx, 0, &acl));
+
+       CHECK(parse_filter_aaaa_on(fmap, "filter-aaaa-on-v4", &f4));
+       CHECK(parse_filter_aaaa_on(fmap, "filter-aaaa-on-v6", &f6));
+
+       if ((f4 != NONE || f6 != NONE) && dns_acl_isnone(acl)) {
+               cfg_obj_log(aclobj, lctx, ISC_LOG_WARNING,
+                           "\"filter-aaaa\" is 'none;' but "
+                           "either filter-aaaa-on-v4 or filter-aaaa-on-v6 "
+                           "is enabled");
+               result = ISC_R_FAILURE;
+       } else if (f4 == NONE && f6 == NONE && !dns_acl_isnone(acl)) {
+               cfg_obj_log(aclobj, lctx, ISC_LOG_WARNING,
+                           "\"filter-aaaa\" is set but "
+                           "neither filter-aaaa-on-v4 or filter-aaaa-on-v6 "
+                           "is enabled");
+               result = ISC_R_FAILURE;
+       }
+
+ cleanup:
+       if (acl != NULL) {
+               dns_acl_detach(&acl);
+       }
+
+       return (result);
+}
+
 static isc_result_t
 parse_parameters(filter_instance_t *inst, const char *parameters,
+                const char *cfg_file, unsigned long cfg_line,
                 const void *cfg, void *actx, ns_hookctx_t *hctx)
 {
        isc_result_t result = ISC_R_SUCCESS;
@@ -263,8 +307,10 @@ parse_parameters(filter_instance_t *inst, const char *parameters,
 
        isc_buffer_constinit(&b, parameters, strlen(parameters));
        isc_buffer_add(&b, strlen(parameters));
-       CHECK(cfg_parse_buffer(parser, &b, &cfg_type_parameters,
-                              &param_obj));
+       CHECK(cfg_parse_buffer4(parser, &b, cfg_file, cfg_line,
+                               &cfg_type_parameters, 0, &param_obj));
+
+       CHECK(check_syntax(param_obj, cfg, hctx->mctx, hctx->lctx, actx));
 
        CHECK(parse_filter_aaaa_on(param_obj, "filter-aaaa-on-v4",
                                   &inst->v4_aaaa));
@@ -323,7 +369,9 @@ hook_register(const char *parameters,
        isc_mem_attach(hctx->mctx, &inst->mctx);
 
        if (parameters != NULL) {
-               CHECK(parse_parameters(inst, parameters, cfg, actx, hctx));
+               CHECK(parse_parameters(inst, parameters,
+                                      cfg_file, cfg_line,
+                                      cfg, actx, hctx));
        }
 
        CHECK(isc_mempool_create(hctx->mctx, sizeof(filter_data_t),
@@ -358,6 +406,34 @@ hook_register(const char *parameters,
        return (result);
 }
 
+isc_result_t
+hook_check(const char *parameters, const char *cfg_file, unsigned long cfg_line,
+          const void *cfg, isc_mem_t *mctx, isc_log_t *lctx, void *actx)
+{
+       isc_result_t result = ISC_R_SUCCESS;
+       cfg_parser_t *parser = NULL;
+       cfg_obj_t *param_obj = NULL;
+       isc_buffer_t b;
+
+       CHECK(cfg_parser_create(mctx, lctx, &parser));
+
+       isc_buffer_constinit(&b, parameters, strlen(parameters));
+       isc_buffer_add(&b, strlen(parameters));
+       CHECK(cfg_parse_buffer4(parser, &b, cfg_file, cfg_line,
+                               &cfg_type_parameters, 0, &param_obj));
+
+       CHECK(check_syntax(param_obj, cfg, mctx, lctx, actx));
+
+ cleanup:
+       if (param_obj != NULL) {
+               cfg_obj_destroy(parser, &param_obj);
+       }
+       if (parser != NULL) {
+               cfg_parser_destroy(&parser);
+       }
+       return (result);
+}
+
 /*
  * Called by ns_module_unload(); frees memory allocated by
  * the module when it was registered.
index b6a43df85dbb1b3182914ab190e7c12b7b7fcc95..8204db5451cd047a8d63fd824a26de39934fbde9 100644 (file)
@@ -5308,7 +5308,7 @@ configure_view(dns_view_t *view, dns_viewlist_t *viewlist,
 
 #ifdef HAVE_DLOPEN
        if (hook_list != NULL) {
-               CHECK(ns_hook_createctx(mctx, &hctx));
+               CHECK(ns_hook_createctx(mctx, view, &hctx));
 
                INSIST(view->hooktable == NULL);
                CHECK(ns_hooktable_create(view->mctx,
@@ -8102,8 +8102,12 @@ load_configuration(const char *filename, named_server_t *server,
 
        /*
         * Check the validity of the configuration.
+        *
+        * (Ignore hook module parameters for now; they will be
+        * checked later when the modules are actually loaded and
+        * registered.)
         */
-       CHECK(bind9_check_namedconf(config, named_g_lctx, named_g_mctx));
+       CHECK(bind9_check_namedconf(config, false, named_g_lctx, named_g_mctx));
 
        /*
         * Fill in the maps array, used for resolving defaults.
diff --git a/bin/tests/system/filter-aaaa/conf/bad1.conf b/bin/tests/system/filter-aaaa/conf/bad1.conf
new file mode 100644 (file)
index 0000000..0107435
--- /dev/null
@@ -0,0 +1,15 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+hook query "../../../hooks/lib/filter-aaaa.so" {
+       filter-aaaa-on-v4 yes;
+       filter-aaaa { none; };
+};
diff --git a/bin/tests/system/filter-aaaa/conf/bad2.conf b/bin/tests/system/filter-aaaa/conf/bad2.conf
new file mode 100644 (file)
index 0000000..0db0bb8
--- /dev/null
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+hook query "../../../hooks/lib/filter-aaaa.so" {
+       /*
+        * While this matches the defaults, it is not a good configuration
+        * to have in named.conf as the two options contradict each other
+        * indicating a error on behalf of the operator.
+        *
+        * The default is to have filter-aaaa-on-v4 off, but if it is turned
+        * on then it applies to all IPv4 queries.  This results in
+        * contradictory defaults.
+        */
+       filter-aaaa-on-v4 no;
+       filter-aaaa { any; };
+};
diff --git a/bin/tests/system/filter-aaaa/conf/bad3.conf b/bin/tests/system/filter-aaaa/conf/bad3.conf
new file mode 100644 (file)
index 0000000..418c548
--- /dev/null
@@ -0,0 +1,17 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+view myview {
+       hook query "../../../hooks/lib/filter-aaaa.so" {
+               filter-aaaa-on-v4 no;
+               filter-aaaa { any; };
+       };
+};
diff --git a/bin/tests/system/filter-aaaa/conf/bad4.conf b/bin/tests/system/filter-aaaa/conf/bad4.conf
new file mode 100644 (file)
index 0000000..0357956
--- /dev/null
@@ -0,0 +1,17 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+view myview {
+       hook query "../../../hooks/lib/filter-aaaa.so" {
+               filter-aaaa-on-v4 yes;
+               filter-aaaa { none; };
+       };
+};
diff --git a/bin/tests/system/filter-aaaa/conf/bad5.conf b/bin/tests/system/filter-aaaa/conf/bad5.conf
new file mode 100644 (file)
index 0000000..ea807d3
--- /dev/null
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+plugin query "../../../plugins/lib/filter-aaaa.so" {
+       filter-aaaa-on-v4 yes;
+       filter-aaaa { 1.0.0.0/8; };
+};
+
+view myview {
+       match-clients { any; };
+};
diff --git a/bin/tests/system/filter-aaaa/conf/good1.conf b/bin/tests/system/filter-aaaa/conf/good1.conf
new file mode 100644 (file)
index 0000000..e5136a9
--- /dev/null
@@ -0,0 +1,14 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+hook query "../../../hooks/lib/filter-aaaa.so" {
+       filter-aaaa-on-v4 yes;
+};
diff --git a/bin/tests/system/filter-aaaa/conf/good2.conf b/bin/tests/system/filter-aaaa/conf/good2.conf
new file mode 100644 (file)
index 0000000..935e1f1
--- /dev/null
@@ -0,0 +1,14 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+hook query "../../../hooks/lib/filter-aaaa.so" {
+       filter-aaaa-on-v4 break-dnssec;
+};
diff --git a/bin/tests/system/filter-aaaa/conf/good3.conf b/bin/tests/system/filter-aaaa/conf/good3.conf
new file mode 100644 (file)
index 0000000..f92ad6b
--- /dev/null
@@ -0,0 +1,15 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+hook query "../../../hooks/lib/filter-aaaa.so" {
+       filter-aaaa-on-v4 break-dnssec;
+       filter-aaaa { 1.0.0.0/8; };
+};
diff --git a/bin/tests/system/filter-aaaa/conf/good4.conf b/bin/tests/system/filter-aaaa/conf/good4.conf
new file mode 100644 (file)
index 0000000..ea47560
--- /dev/null
@@ -0,0 +1,15 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+hook query "../../../hooks/lib/filter-aaaa.so" {
+       filter-aaaa-on-v4 yes;
+       filter-aaaa { 1.0.0.0/8; };
+};
diff --git a/bin/tests/system/filter-aaaa/conf/good5.conf b/bin/tests/system/filter-aaaa/conf/good5.conf
new file mode 100644 (file)
index 0000000..131c552
--- /dev/null
@@ -0,0 +1,17 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+view myview {
+       hook query "../../../hooks/lib/filter-aaaa.so" {
+               filter-aaaa-on-v4 yes;
+               filter-aaaa { 1.0.0.0/8; };
+       };
+};
index 4ff2ebe3a2054ac94c3370d473421e9eb8a73b1c..f9b4d882b9ea3fbeef02a1087f35f850139975e5 100644 (file)
@@ -20,6 +20,26 @@ rm -f dig.out.*
 DIGOPTS="+tcp +noadd +nosea +nostat +nocmd -p ${PORT}"
 RNDCCMD="$RNDC -c $SYSTEMTESTTOP/common/rndc.conf -p ${CONTROLPORT} -s"
 
+for conf in conf/good*.conf
+do
+       n=`expr $n + 1`
+       echo_i "checking that $conf is accepted ($n)"
+       ret=0
+       $CHECKCONF "$conf" || ret=1
+       if [ $ret != 0 ]; then echo_i "failed"; fi
+       status=`expr $status + $ret`
+done
+
+for conf in conf/bad*.conf
+do
+       n=`expr $n + 1`
+       echo_i "checking that $conf is rejected ($n)"
+       ret=0
+       $CHECKCONF "$conf" >/dev/null && ret=1
+       if [ $ret != 0 ]; then echo_i "failed"; fi
+       status=`expr $status + $ret`
+done
+
 #
 # Authoritative tests against:
 #      filter-aaaa-on-v4 yes;
index 5a9760c0e0cd54f97d4cba12ad2bca1e870dfb0b..b2441fb925d39caf50a1e4fc7da10829427a1ebc 100644 (file)
@@ -18,7 +18,7 @@ VERSION=@BIND9_VERSION@
 @BIND9_MAKE_INCLUDES@
 
 CINCLUDES =    -I. ${BIND9_INCLUDES} ${DNS_INCLUDES} ${ISC_INCLUDES} \
-               ${ISCCFG_INCLUDES} @OPENSSL_INCLUDES@
+               ${ISCCFG_INCLUDES} ${NS_INCLUDES} @OPENSSL_INCLUDES@
 
 CDEFINES =
 CWARNINGS =
@@ -26,6 +26,7 @@ CWARNINGS =
 ISCLIBS =      ../../lib/isc/libisc.@A@ @OPENSSL_LIBS@
 ISCCFGLIBS =    ../../lib/isccfg/libisccfg.@A@
 DNSLIBS =      ../../lib/dns/libdns.@A@ @DNS_CRYPTO_LIBS@
+NSLIBS =       ../../lib/ns/libns.@A@
 
 ISCDEPLIBS =   ../../lib/isc/libisc.@A@
 ISCCFGDEPLIBS =        ../../lib/isccfg/libisccfg.@A@
@@ -61,8 +62,8 @@ libbind9.la: ${OBJS} ${ISCCFGDEPLIBS} ${ISCDEPLIBS} ${DNSDEPLIBS}
        ${LIBTOOL_MODE_LINK} \
                ${CC} ${ALL_CFLAGS} ${LDFLAGS} -o libbind9.la -rpath ${libdir} \
                -version-info ${LIBINTERFACE}:${LIBREVISION}:${LIBAGE} \
-               ${OBJS} ${DNSLIBS} ${ISCCFGLIBS} ${ISCLIBS} @DNS_CRYPTO_LIBS@ \
-               ${LIBS}
+               ${OBJS} ${NSLIBS} ${DNSLIBS} ${ISCCFGLIBS} ${ISCLIBS} \
+               @DNS_CRYPTO_LIBS@ ${LIBS}
 
 timestamp: libbind9.@A@
        touch timestamp
index 4fac8e9b856ee2ba0068598213ea6d8ec7e0c1bb..efef37f00d0b5580687f67d99ed0971296897a97 100644 (file)
@@ -54,6 +54,8 @@
 #include <isccfg/grammar.h>
 #include <isccfg/namedconf.h>
 
+#include <ns/hooks.h>
+
 #include <bind9/check.h>
 
 static unsigned char dlviscorg_ndata[] = "\003dlv\003isc\003org";
@@ -3349,7 +3351,7 @@ check_rpz_catz(const char *rpz_catz, const cfg_obj_t *rpz_obj,
 static isc_result_t
 check_viewconf(const cfg_obj_t *config, const cfg_obj_t *voptions,
               const char *viewname, dns_rdataclass_t vclass,
-              isc_symtab_t *files, isc_symtab_t *inview,
+              isc_symtab_t *files, bool checkhooks, isc_symtab_t *inview,
               isc_log_t *logctx, isc_mem_t *mctx)
 {
        const cfg_obj_t *zones = NULL;
@@ -3365,6 +3367,7 @@ check_viewconf(const cfg_obj_t *config, const cfg_obj_t *voptions,
        const cfg_obj_t *obj;
        const cfg_obj_t *options = NULL;
        const cfg_obj_t *opts = NULL;
+       const cfg_obj_t *hook_list = NULL;
        bool enablednssec, enablevalidation;
        const char *valstr = "no";
        unsigned int tflags, mflags;
@@ -3662,6 +3665,56 @@ check_viewconf(const cfg_obj_t *config, const cfg_obj_t *voptions,
        if (tresult != ISC_R_SUCCESS)
                result = tresult;
 
+       /*
+        * Load hook modules.
+        */
+       if (checkhooks) {
+               if (voptions != NULL) {
+                       (void)cfg_map_get(voptions, "hook", &hook_list);
+               } else {
+                       (void)cfg_map_get(config, "hook", &hook_list);
+               }
+       }
+
+#ifdef HAVE_DLOPEN
+       for (element = cfg_list_first(hook_list);
+            element != NULL;
+            element = cfg_list_next(element))
+       {
+               const cfg_obj_t *hook = cfg_listelt_value(element);
+
+               const char *type, *library;
+               const char *parameters = NULL;
+
+               /* Get the path to the hook module. */
+               obj = cfg_tuple_get(hook, "type");
+               type = cfg_obj_asstring(obj);
+
+               /* Only query hooks are supported currently. */
+               if (strcasecmp(type, "query") != 0) {
+                       cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
+                                   "unsupported hook type");
+                       return (ISC_R_FAILURE);
+               }
+
+               library = cfg_obj_asstring(cfg_tuple_get(hook, "library"));
+
+               obj = cfg_tuple_get(hook, "parameters");
+               if (obj != NULL && cfg_obj_isstring(obj)) {
+                       parameters = cfg_obj_asstring(obj);
+               }
+               tresult = ns_module_check(library, parameters,
+                                         cfg_obj_file(obj), cfg_obj_line(obj),
+                                         config, mctx, logctx, actx);
+               if (tresult != ISC_R_SUCCESS) {
+                       cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
+                                   "%s: module check failed: %s",
+                                   library, isc_result_totext(tresult));
+                       result = tresult;
+               }
+       }
+#endif /* HAVE_DLOPEN */
+
  cleanup:
        if (symtab != NULL)
                isc_symtab_destroy(&symtab);
@@ -3916,8 +3969,8 @@ bind9_check_controls(const cfg_obj_t *config, isc_log_t *logctx,
 }
 
 isc_result_t
-bind9_check_namedconf(const cfg_obj_t *config, isc_log_t *logctx,
-                     isc_mem_t *mctx)
+bind9_check_namedconf(const cfg_obj_t *config, bool hooks,
+                     isc_log_t *logctx, isc_mem_t *mctx)
 {
        const cfg_obj_t *options = NULL;
        const cfg_obj_t *views = NULL;
@@ -3973,13 +4026,15 @@ bind9_check_namedconf(const cfg_obj_t *config, isc_log_t *logctx,
        }
 
        if (views == NULL) {
-               tresult = check_viewconf(config, NULL, NULL, dns_rdataclass_in,
-                                        files, inview, logctx, mctx);
+               tresult = check_viewconf(config, NULL, NULL,
+                                        dns_rdataclass_in, files,
+                                        hooks, inview, logctx, mctx);
                if (result == ISC_R_SUCCESS && tresult != ISC_R_SUCCESS) {
                        result = ISC_R_FAILURE;
                }
        } else {
                const cfg_obj_t *zones = NULL;
+               const cfg_obj_t *hooks = NULL;
 
                (void)cfg_map_get(config, "zone", &zones);
                if (zones != NULL) {
@@ -3988,6 +4043,14 @@ bind9_check_namedconf(const cfg_obj_t *config, isc_log_t *logctx,
                                    "all zones must be in views");
                        result = ISC_R_FAILURE;
                }
+
+               (void)cfg_map_get(config, "hook", &hooks);
+               if (hooks != NULL) {
+                       cfg_obj_log(hooks, logctx, ISC_LOG_ERROR,
+                                   "when using 'view' statements, "
+                                   "all hooks must be defined in views");
+                       result = ISC_R_FAILURE;
+               }
        }
 
        tresult = isc_symtab_create(mctx, 100, NULL, NULL, true, &symtab);
@@ -4051,8 +4114,9 @@ bind9_check_namedconf(const cfg_obj_t *config, isc_log_t *logctx,
                        }
                }
                if (tresult == ISC_R_SUCCESS)
-                       tresult = check_viewconf(config, voptions, key, vclass,
-                                                files, inview, logctx, mctx);
+                       tresult = check_viewconf(config, voptions, key,
+                                                vclass, files, hooks,
+                                                inview, logctx, mctx);
                if (tresult != ISC_R_SUCCESS)
                        result = ISC_R_FAILURE;
        }
index 92d4bdda71a947d53659572bfa1faf29c28b91f8..4d483fcfd479172a74b8ecd6da0d83f6cea77daa 100644 (file)
 ISC_LANG_BEGINDECLS
 
 isc_result_t
-bind9_check_namedconf(const cfg_obj_t *config, isc_log_t *logctx,
-                     isc_mem_t *mctx);
+bind9_check_namedconf(const cfg_obj_t *config, bool check_hooks,
+                     isc_log_t *logctx, isc_mem_t *mctx);
 /*%<
  * Check the syntactic validity of a configuration parse tree generated from
  * a named.conf file.
  *
+ * If 'check_hooks' is true, load hook modules and check the validity of their
+ * parameters as well.
+ *
  * Requires:
  *\li  config is a valid parse tree
  *
index 4573f6fc1ebd610d7d2c94ddd94477b29fadcf19..885b7fa25f2d20ac1d16ee4f8dd49a9ae00a680a 100644 (file)
@@ -30,6 +30,8 @@
 #include <isc/util.h>
 #include <isc/types.h>
 
+#include <dns/view.h>
+
 #include <ns/hooks.h>
 #include <ns/log.h>
 #include <ns/query.h>
@@ -47,6 +49,7 @@ struct ns_module {
        void                    *handle;
        void                    *inst;
        char                    *modpath;
+       ns_hook_check_t         *check_func;
        ns_hook_register_t      *register_func;
        ns_hook_destroy_t       *destroy_func;
        LINK(ns_module_t)       link;
@@ -97,6 +100,7 @@ load_library(isc_mem_t *mctx, const char *modpath, ns_module_t **hmodp) {
        isc_result_t result;
        void *handle = NULL;
        ns_module_t *hmod = NULL;
+       ns_hook_check_t *check_func = NULL;
        ns_hook_register_t *register_func = NULL;
        ns_hook_destroy_t *destroy_func = NULL;
        ns_hook_version_t *version_func = NULL;
@@ -104,7 +108,7 @@ load_library(isc_mem_t *mctx, const char *modpath, ns_module_t **hmodp) {
 
        REQUIRE(hmodp != NULL && *hmodp == NULL);
 
-       flags = RTLD_NOW | RTLD_LOCAL;
+       flags = RTLD_LAZY | RTLD_LOCAL;
 #ifdef RTLD_DEEPBIND
        flags |= RTLD_DEEPBIND;
 #endif
@@ -136,16 +140,19 @@ load_library(isc_mem_t *mctx, const char *modpath, ns_module_t **hmodp) {
                CHECK(ISC_R_FAILURE);
        }
 
+       CHECK(load_symbol(handle, modpath, "hook_check",
+                         (void **)&check_func));
        CHECK(load_symbol(handle, modpath, "hook_register",
                          (void **)&register_func));
        CHECK(load_symbol(handle, modpath, "hook_destroy",
                          (void **)&destroy_func));
 
        hmod = isc_mem_get(mctx, sizeof(*hmod));
-       hmod->mctx = NULL;
+       memset(hmod, 0, sizeof(*hmod));
        isc_mem_attach(mctx, &hmod->mctx);
        hmod->handle = handle;
        hmod->modpath = isc_mem_strdup(hmod->mctx, modpath);
+       hmod->check_func = check_func;
        hmod->register_func = register_func;
        hmod->destroy_func = destroy_func;
 
@@ -262,7 +269,7 @@ load_library(isc_mem_t *mctx, const char *modpath, ns_module_t **hmodp) {
                          (void **)&destroy_func));
 
        hmod = isc_mem_get(mctx, sizeof(*hmod));
-       hmod->mctx = NULL;
+       memset(hmod, 0, sizeof(*hmod));
        isc_mem_attach(mctx, &hmod->mctx);
        hmod->handle = handle;
        hmod->modpath = isc_mem_strdup(hmod->mctx, modpath);
@@ -377,7 +384,28 @@ cleanup:
 }
 
 isc_result_t
-ns_hook_createctx(isc_mem_t *mctx, ns_hookctx_t **hctxp) {
+ns_module_check(const char *modpath, const char *parameters,
+               const char *cfg_file, unsigned long cfg_line,
+               const void *cfg, isc_mem_t *mctx, isc_log_t *lctx, void *actx)
+{
+       isc_result_t result;
+       ns_module_t *hmod = NULL;
+
+       CHECK(load_library(mctx, modpath, &hmod));
+
+       result = hmod->check_func(parameters, cfg_file, cfg_line,
+                                 cfg, mctx, lctx, actx);
+
+cleanup:
+       if (hmod != NULL) {
+               unload_library(&hmod);
+       }
+
+       return (result);
+}
+
+isc_result_t
+ns_hook_createctx(isc_mem_t *mctx, dns_view_t *view, ns_hookctx_t **hctxp) {
        ns_hookctx_t *hctx = NULL;
 
        REQUIRE(hctxp != NULL && *hctxp == NULL);
@@ -386,6 +414,8 @@ ns_hook_createctx(isc_mem_t *mctx, ns_hookctx_t **hctxp) {
        memset(hctx, 0, sizeof(*hctx));
        hctx->lctx = ns_lctx;
 
+       dns_view_attach(view, &hctx->view);
+
        isc_mem_attach(mctx, &hctx->mctx);
        hctx->magic = NS_HOOKCTX_MAGIC;
 
@@ -405,6 +435,7 @@ ns_hook_destroyctx(ns_hookctx_t **hctxp) {
 
        hctx->magic = 0;
 
+       dns_view_detach(&hctx->view);
        isc_mem_putanddetach(&hctx->mctx, hctx, sizeof(*hctx));
 }
 
index 14af15d6950d6564f79493006ef6b8a02bb5a9b7..64f944a4f1f56ea4530796932bfeb7d234c3f013 100644 (file)
@@ -233,6 +233,7 @@ LIBNS_EXTERNAL_DATA extern ns_hooktable_t *ns__hook_table;
  */
 typedef struct ns_hookctx {
        unsigned int            magic;
+       dns_view_t              *view;
        isc_mem_t               *mctx;
        isc_log_t               *lctx;
 } ns_hookctx_t;
@@ -272,14 +273,23 @@ ns_hook_register_t(const char *parameters,
  *\li  Other errors are possible
  */
 
-typedef void ns_hook_destroy_t(void **instp);
+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(void);
+typedef isc_result_t
+ns_hook_check_t(const char *parameters, const char *file, unsigned long line,
+               const void *cfg, isc_mem_t *mctx, isc_log_t *lctx, void *actx);
+/*%<
+ * Check the validity of 'parameters'.
+ */
+
+typedef int
+ns_hook_version_t(void);
 /*%<
  * Return the API version number a hook module was compiled with.
  *
@@ -291,13 +301,13 @@ typedef int ns_hook_version_t(void);
 /*%
  * Prototypes for API functions to be defined in each module.
  */
+ns_hook_check_t hook_check;
 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);
-
+ns_hook_createctx(isc_mem_t *mctx, dns_view_t *view, ns_hookctx_t **hctxp);
 void
 ns_hook_destroyctx(ns_hookctx_t **hctxp);
 /*%<
@@ -327,6 +337,16 @@ ns_module_load(const char *modpath, const char *parameters,
  * created by the module's hook_register function.
  */
 
+isc_result_t
+ns_module_check(const char *modpath, const char *parameters,
+               const char *cfg_file, unsigned long cfg_line,
+               const void *cfg, isc_mem_t *mctx, isc_log_t *lctx, void *actx);
+/*%<
+ * Open the module at 'modpath' and check the validity of
+ * 'parameters', logging any errors or warnings found, then
+ * close it without configuring it.
+ */
+
 void
 ns_modlist_create(isc_mem_t *mctx, ns_modlist_t **listp);
 /*%<
index f5be0ac29042733ed15723339df22971b4dbb935..c7192933a67e96abeb976f9be92e8850a5bcdc87 100644 (file)
@@ -79,6 +79,7 @@ ns_log_init
 ns_log_setcontext
 ns_modlist_create
 ns_modlist_free
+ns_module_check
 ns_module_load
 ns_notify_start
 ns_query_cancel