]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
[master] new-zones-directory option
authorEvan Hunt <each@isc.org>
Mon, 24 Apr 2017 06:16:53 +0000 (23:16 -0700)
committerEvan Hunt <each@isc.org>
Mon, 24 Apr 2017 06:16:53 +0000 (23:16 -0700)
4610. [func] The "new-zones-directory" option specifies the
location of NZF or NZD files for storing
configuration of zones added by "rndc addzone".
Thanks to Petr Menšík. [RT #44853]

15 files changed:
CHANGES
bin/named/server.c
bin/rndc/rndc.docbook
bin/tests/system/addzone/clean.sh
bin/tests/system/addzone/ns2/named3.conf [new file with mode: 0644]
bin/tests/system/addzone/setup.sh
bin/tests/system/addzone/tests.sh
doc/arm/Bv9ARM-book.xml
doc/arm/notes.xml
lib/dns/include/dns/view.h
lib/dns/view.c
lib/isc/tests/file_test.c
lib/isc/unix/file.c
lib/isc/win32/file.c
lib/isccfg/namedconf.c

diff --git a/CHANGES b/CHANGES
index e4bb0011c519ea4be0a2964205b18925811d73d3..e36a0be0aa0703524a6fde33291ef015316da583 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -1,3 +1,8 @@
+4610.  [func]          The "new-zones-directory" option specifies the
+                       location of NZF or NZD files for storing 
+                       configuration of zones added by "rndc addzone".
+                       Thanks to Petr Menšík. [RT #44853]
+
 4609.  [cleanup]       Rearrange makefiles to enable parallel execution
                        (i.e. "make -j"). [RT #45078]
 
index e7cebcdcc3c03945be25ae622539275253f0fbb6..d11baaaaf00d28a9c2b37f35b6f11cf968b1c945 100644 (file)
@@ -5642,7 +5642,6 @@ configure_zone(const cfg_obj_t *config, const cfg_obj_t *zconfig,
 /*
  * Configure built-in zone for storing managed-key data.
  */
-
 static isc_result_t
 add_keydata_zone(dns_view_t *view, const char *directory, isc_mem_t *mctx) {
        isc_result_t result;
@@ -6630,6 +6629,8 @@ setup_newzones(dns_view_t *view, cfg_obj_t *config, cfg_obj_t *vconfig,
        const cfg_obj_t *maps[4];
        const cfg_obj_t *options = NULL, *voptions = NULL;
        const cfg_obj_t *nz = NULL;
+       const cfg_obj_t *nzdir = NULL;
+       const char *dir = NULL;
        int i = 0;
 
        REQUIRE (config != NULL);
@@ -6647,6 +6648,22 @@ setup_newzones(dns_view_t *view, cfg_obj_t *config, cfg_obj_t *vconfig,
        result = ns_config_get(maps, "allow-new-zones", &nz);
        if (result == ISC_R_SUCCESS)
                allow = cfg_obj_asboolean(nz);
+       result = ns_config_get(maps, "new-zones-directory", &nzdir);
+       if (result == ISC_R_SUCCESS) {
+               dir = cfg_obj_asstring(nzdir);
+               if (dir != NULL) {
+                       result = isc_file_isdirectory(dir);
+               }
+               if (result != ISC_R_SUCCESS) {
+                       isc_log_write(ns_g_lctx, DNS_LOGCATEGORY_SECURITY,
+                                     NS_LOGMODULE_SERVER, ISC_LOG_ERROR,
+                                     "invalid new-zones-directory %s: %s",
+                                     dir, isc_result_totext(result));
+                       return (result);
+               }
+
+               dns_view_setnewzonedir(view, dir);
+       }
 
        /*
         * A non-empty catalog-zones statement implies allow-new-zones
@@ -6677,7 +6694,7 @@ setup_newzones(dns_view_t *view, cfg_obj_t *config, cfg_obj_t *vconfig,
 
        memset(nzcfg, 0, sizeof(*nzcfg));
 
-       result = dns_view_setnewzones(view, allow, nzcfg,
+       result = dns_view_setnewzones(view, ISC_TRUE, nzcfg,
                                      newzone_cfgctx_destroy);
        if (result != ISC_R_SUCCESS) {
                isc_mem_free(view->mctx, nzcfg);
@@ -11038,7 +11055,8 @@ nzf_writeconf(const cfg_obj_t *config, dns_view_t *view) {
        char tmp[1024];
        isc_result_t result;
 
-       result = isc_file_template("", "nzf-XXXXXXXX", tmp, sizeof(tmp));
+       result = isc_file_template(view->new_zone_file, "nzf-XXXXXXXX",
+                                  tmp, sizeof(tmp));
        if (result == ISC_R_SUCCESS)
                result = isc_file_openunique(tmp, &fp);
        if (result != ISC_R_SUCCESS)
index 0aa32e9da9f92b171df8b714a82860372e146fc2..58ae28c6a53d51faf8be7fdda4053afcdcd0827b 100644 (file)
          </para>
          <para>
            The configuration is saved in a file called
-           <filename><replaceable>name</replaceable>.nzf</filename>,
-           where <replaceable>name</replaceable> is the
-           name of the view, or if it contains characters
-           that are incompatible with use as a file name, a
-           cryptographic hash generated from the name
-           of the view.
+           <filename><replaceable>viewname</replaceable>.nzf</filename>
+           (or, if <command>named</command> is compiled with
+           liblmdb, an LMDB database file called 
+           <filename><replaceable>viewname</replaceable>.nzd</filename>).
+           <replaceable>viewname</replaceable> is the
+           name of the view, unless the view name contains characters
+           that are incompatible with use as a file name, in which case
+           a cryptographic hash of the view name is used instead.
            When <command>named</command> is
            restarted, the file will be loaded into the view
            configuration, so that zones that were added
index ee57d0a10e3c8afd4b297f7a23c06f9d746a2935..f47b83cffff940d3b920c4d2489c7aa73cd45d9f 100644 (file)
@@ -14,16 +14,17 @@ rm -f showzone.out*
 rm -f zonestatus.out*
 rm -f ns2/named.conf
 rm -f */named.memstats
-rm -f ns1/*.nzf
-rm -f ns1/*.nzf~
+rm -f ns1/*.nzf ns1/*.nzf~
 rm -f ns1/*.nzd ns1/*.nzd-lock
-rm -f ns2/*.nzf
-rm -f ns2/*.nzf~
+rm -f ns2/*.nzf ns2/*.nzf~
 rm -f ns2/*.nzd ns2/*.nzd-lock
+rm -f ns3/*.nzf ns3/*.nzf~
+rm -f ns3/*.nzd ns3/*.nzd-lock
 rm -f ns2/core*
 rm -f ns2/inline.db.jbk
 rm -f ns2/inline.db.signed
 rm -f ns2/inlineslave.bk*
+rm -rf ns2/new-zones
 rm -f ns*/named.lock
 rm -f ns*/named.run
 rm -f ns2/nzf-*
@@ -31,3 +32,4 @@ rm -f ns1/redirect.db
 rm -f ns2/redirect.db
 rm -f ns2/redirect.bk
 rm -f ns3/redirect.db
+
diff --git a/bin/tests/system/addzone/ns2/named3.conf b/bin/tests/system/addzone/ns2/named3.conf
new file mode 100644 (file)
index 0000000..920a1e5
--- /dev/null
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2010, 2011, 2016  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/.
+ */
+
+controls { /* empty */ };
+
+include "../../common/controls.conf";
+
+options {
+       port 5300;
+       pid-file "named.pid";
+       listen-on { 10.53.0.2; 10.53.0.4; 10.53.0.5; };
+       listen-on-v6 { none; };
+       recursion no;
+       new-zones-directory "new-zones";
+};
+
+view internal {
+       match-clients { 10.53.0.2; };
+       allow-new-zones no;
+       recursion yes;
+
+       response-policy { zone "policy"; };
+
+       zone "." {
+               type hint;
+               file "../../common/root.hint";
+       };
+
+       zone "policy" {
+               type master;
+               file "normal.db";
+       };
+};
+
+view directory {
+       match-clients { 10.53.0.5; };
+       allow-new-zones yes;
+
+       zone "." {
+               type hint;
+               file "../../common/root.hint";
+       };
+};
+
+view external {
+       match-clients { any; };
+       allow-new-zones yes;
+
+       zone "." {
+               type hint;
+               file "../../common/root.hint";
+       };
+};
+
+# This view is only here to test that configuration context is cleaned
+# up correctly when using multiple named ACLs (regression test for RT #22739)
+acl match { none; };
+acl nobody { none; };
+view extra {
+       match-clients { match; };
+       allow-new-zones yes;
+       allow-transfer { nobody; };
+       allow-query { nobody; };
+       allow-recursion { nobody; };
+};
index 22df7755ca738b756c0eda12a8c43291cd389b30..a07e0788cd81866a13ed124e61a9681418074ed0 100644 (file)
@@ -16,3 +16,4 @@ cp -f ns2/redirect.db.1 ns2/redirect.db
 cp -f ns3/redirect.db.1 ns3/redirect.db
 cp -f ns2/named1.conf ns2/named.conf
 cp -f ns2/default.nzf.in ns2/3bf305731dd26307.nzf
+mkdir ns2/new-zones
index aa90235f0d3032cb9d2afdb596b20e88641e7bec..765408a4e09e4834760634448c1bad0f3617992a 100755 (executable)
@@ -551,6 +551,87 @@ n=`expr $n + 1`
 if [ $ret != 0 ]; then echo "I:failed"; fi
 status=`expr $status + $ret`
 
+echo "I:adding new zone again to external view ($n)"
+ret=0
+$RNDC -c ../common/rndc.conf -s 10.53.0.2 -p 9953 addzone 'added.example in external { type master; file "added.db"; };' 2>&1 | sed 's/^/I:ns2 /'
+$DIG +norec $DIGOPTS @10.53.0.2 -b 10.53.0.2 a.added.example a > dig.out.ns2.int.$n || ret=1
+grep 'status: NOERROR' dig.out.ns2.int.$n > /dev/null || ret=1
+$DIG +norec $DIGOPTS @10.53.0.4 -b 10.53.0.4 a.added.example a > dig.out.ns2.ext.$n || ret=1
+grep 'status: NOERROR' dig.out.ns2.ext.$n > /dev/null || ret=1
+grep '^a.added.example' dig.out.ns2.ext.$n > /dev/null || ret=1
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo "I:failed"; fi
+status=`expr $status + $ret`
+
+echo "I:reconfiguring server with multiple views and new-zones-directory"
+rm -f ns2/named.conf
+cp -f ns2/named3.conf ns2/named.conf
+$RNDC -c ../common/rndc.conf -s 10.53.0.2 -p 9953 reconfig 2>&1 | sed 's/^/I:ns2 /'
+sleep 5
+
+echo "I:checking new zone is still loaded after dir change ($n)"
+ret=0
+$DIG +norec $DIGOPTS @10.53.0.4 -b 10.53.0.4 a.added.example a > dig.out.ns2.ext.$n || ret=1
+grep 'status: NOERROR' dig.out.ns2.ext.$n > /dev/null || ret=1
+grep '^a.added.example' dig.out.ns2.ext.$n > /dev/null || ret=1
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo "I:failed"; fi
+status=`expr $status + $ret`
+
+echo "I:deleting newly added zone from external ($n)"
+ret=0
+$RNDC -c ../common/rndc.conf -s 10.53.0.2 -p 9953 delzone 'added.example in external' 2>&1 | sed 's/^/I:ns2 /'
+$DIG $DIGOPTS @10.53.0.4 -b 10.53.0.4 a.added.example a > dig.out.ns2.$n || ret=1
+grep 'status: REFUSED' dig.out.ns2.$n > /dev/null || ret=1
+grep '^a.added.example' dig.out.ns2.$n > /dev/null && ret=1
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo "I:failed"; fi
+status=`expr $status + $ret`
+
+echo "I:adding new zone to directory view ($n)"
+ret=0
+$DIG +norec $DIGOPTS @10.53.0.2 -b 10.53.0.2 a.added.example a > dig.out.ns2.intpre.$n || ret=1
+grep 'status: NOERROR' dig.out.ns2.intpre.$n > /dev/null || ret=1
+$DIG +norec $DIGOPTS @10.53.0.4 -b 10.53.0.4 a.added.example a > dig.out.ns2.extpre.$n || ret=1
+grep 'status: REFUSED' dig.out.ns2.extpre.$n > /dev/null || ret=1
+$DIG +norec $DIGOPTS @10.53.0.5 -b 10.53.0.5 a.added.example a > dig.out.ns2.dirpre.$n || ret=1
+grep 'status: REFUSED' dig.out.ns2.dirpre.$n > /dev/null || ret=1
+$RNDC -c ../common/rndc.conf -s 10.53.0.2 -p 9953 addzone 'added.example in directory { type master; file "added.db"; };' 2>&1 | sed 's/^/I:ns2 /'
+$DIG +norec $DIGOPTS @10.53.0.2 -b 10.53.0.2 a.added.example a > dig.out.ns2.int.$n || ret=1
+grep 'status: NOERROR' dig.out.ns2.int.$n > /dev/null || ret=1
+$DIG +norec $DIGOPTS @10.53.0.4 -b 10.53.0.4 a.added.example a > dig.out.ns2.ext.$n || ret=1
+grep 'status: REFUSED' dig.out.ns2.ext.$n > /dev/null || ret=1
+$DIG +norec $DIGOPTS @10.53.0.5 -b 10.53.0.5 a.added.example a > dig.out.ns2.dir.$n || ret=1
+grep 'status: NOERROR' dig.out.ns2.dir.$n > /dev/null || ret=1
+grep '^a.added.example' dig.out.ns2.dir.$n > /dev/null || ret=1
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo "I:failed"; fi
+status=`expr $status + $ret`
+
+if [ -n "$NZD" ]; then
+    echo "I:checking NZD file was created in new-zones-directory ($n)"
+    expect=ns2/new-zones/directory.nzd
+else
+    echo "I:checking NZF file was created in new-zones-directory ($n)"
+    expect=ns2/new-zones/directory.nzf
+fi
+$RNDC -c ../common/rndc.conf -s 10.53.0.2 -p 9953 sync 'added.example IN directory' 2>&1 | sed 's/^/I:ns2 /'
+sleep 2
+[ -e "$expect" ] || ret=1
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo "I:failed"; fi
+status=`expr $status + $ret`
+
+echo "I:deleting newly added zone from directory ($n)"
+ret=0
+$RNDC -c ../common/rndc.conf -s 10.53.0.2 -p 9953 delzone 'added.example in directory' 2>&1 | sed 's/^/I:ns2 /'
+$DIG $DIGOPTS @10.53.0.5 -b 10.53.0.5 a.added.example a > dig.out.ns2.$n || ret=1
+grep 'status: REFUSED' dig.out.ns2.$n > /dev/null || ret=1
+grep '^a.added.example' dig.out.ns2.$n > /dev/null && ret=1
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo "I:failed"; fi
+status=`expr $status + $ret`
+
 echo "I:ensure the configuration context is cleaned up correctly ($n)"
 ret=0
 $RNDC -c ../common/rndc.conf -s 10.53.0.2 -p 9953 reconfig > /dev/null 2>&1 || ret=1
index cf0bb519f9bbdeb21dca7a3b1ea23ff1b02a2b12..166d67a24fb6a865f80ea2e6a3ad4fe598ffc567 100644 (file)
@@ -4432,6 +4432,7 @@ badresp:1,adberr:0,findfail:0,valfail:0]
   [ <command>geoip-directory</command> <replaceable>path_name</replaceable> ; ]
   [ <command>key-directory</command> <replaceable>path_name</replaceable> ; ]
   [ <command>managed-keys-directory</command> <replaceable>path_name</replaceable> ; ]
+  [ <command>new-zones-directory</command> <replaceable>path_name</replaceable> ; ]
   [ <command>named-xfer</command> <replaceable>path_name</replaceable> ; ]
   [ <command>tkey-gssapi-keytab</command> <replaceable>path_name</replaceable> ; ]
   [ <command>tkey-gssapi-credential</command> <replaceable>principal</replaceable> ; ]
@@ -5113,6 +5114,17 @@ badresp:1,adberr:0,findfail:0,valfail:0]
            </listitem>
          </varlistentry>
 
+         <varlistentry>
+           <term><command>new-zones-directory</command></term>
+           <listitem>
+             <para>
+               Specifies the directory in which to store the configuration
+               parameters for zones added via <command>rndc addzone</command>.
+               By default, this is the working directory.
+             </para>
+           </listitem>
+         </varlistentry>
+
          <varlistentry>
            <term><command>named-xfer</command></term>
            <listitem>
@@ -5928,6 +5940,20 @@ options {
                  added at runtime via <command>rndc addzone</command>.
                  The default is <userinput>no</userinput>.
                </para>
+               <para>
+                 Newly added zones' configuration parameters
+                 are stored so that they can persist after the
+                 server is restarted.  The configuration information
+                 is saved in a file called
+                 <filename><replaceable>viewname</replaceable>.nzf</filename>
+                 (or, if <command>named</command> is compiled with
+                 liblmdb, in an LMDB database file called 
+                 <filename><replaceable>viewname</replaceable>.nzd</filename>).
+                 <replaceable>viewname</replaceable> is the name of the
+                 view, unless the view name contains characters that are
+                 incompatible with use as a file name, in which case a
+                 cryptographic hash of the view name is used instead.
+               </para>
              </listitem>
            </varlistentry>
 
index c5486ed960839a60d0667e4fcc1811cffd282345..d35280abd8fff99ef52d1f3c69dd05b3ea2f1e40 100644 (file)
@@ -1,7 +1,9 @@
 <!DOCTYPE book [
 <!ENTITY Scaron "&#x160;">
+<!ENTITY scaron "&#x161;">
 <!ENTITY ccaron "&#x10D;">
 <!ENTITY aacute "&#x0E1;">
+<!ENTITY iacute "&#x0ED;">
 <!ENTITY mdash "&#8212;">
 <!ENTITY ouml "&#xf6;">]>
 <!--
 
   <section xml:id="relnotes_features"><info><title>New Features</title></info>
     <itemizedlist>
+      <listitem>
+        <para>
+         The <command>new-zones-directory</command> option allows
+         <command>named</command> to store configuration parameters
+         for zones added via <command>rndc addzone</command> in a
+         location other than the working directory. Thanks to Petr
+         Men&scaron;&iacute;k of Red Hat for the contribution.
+         [RT #44853]
+       </para>
+      </listitem>
       <listitem>
         <para>
          Many aspects of <command>named</command> have been modified
index f08c3d853693ff008b572541f99e2f5456294cd9..846eee6ebc785795609acfe78c68f4c997bcc7db 100644 (file)
@@ -208,8 +208,9 @@ struct dns_view {
         * XXX: This should be a pointer to an opaque type that
         * named implements.
         */
+       char *                          new_zone_dir;
        char *                          new_zone_file;
-       char *                          new_zone_db;
+       char *                          new_zone_db;
        void *                          new_zone_dbenv;
        void *                          new_zone_config;
        void                            (*cfg_destroy)(void **);
@@ -1238,6 +1239,19 @@ dns_view_setnewzones(dns_view_t *view, isc_boolean_t allow, void *cfgctx,
  * \li ISC_R_NOSPACE
  */
 
+void
+dns_view_setnewzonedir(dns_view_t *view, const char *dir);
+const char *
+dns_view_getnewzonedir(dns_view_t *view);
+/*%<
+ * Set/get the path to the directory in which NZF or NZD files should
+ * be stored. If the path was previously set to a non-NULL value,
+ * the previous value is freed.
+ *
+ * Requires:
+ * \li 'view' is valid.
+ */
+
 void
 dns_view_restorekeyring(dns_view_t *view);
 
index 3c3f4aa502e8f643ae80aa744e26d5aa1b1b12bc..8f465b66587536baffc9d7b408d6e618ddd636a1 100644 (file)
@@ -232,6 +232,7 @@ dns_view_create(isc_mem_t *mctx, dns_rdataclass_t rdclass,
        view->sendcookie = ISC_TRUE;
        view->requireservercookie = ISC_FALSE;
        view->trust_anchor_telemetry = ISC_TRUE;
+       view->new_zone_dir = NULL;
        view->new_zone_file = NULL;
        view->new_zone_db = NULL;
        view->new_zone_dbenv = NULL;
@@ -507,6 +508,10 @@ destroy(dns_view_t *view) {
                isc_mem_free(view->mctx, view->new_zone_file);
                view->new_zone_file = NULL;
        }
+       if (view->new_zone_dir != NULL) {
+               isc_mem_free(view->mctx, view->new_zone_dir);
+               view->new_zone_dir = NULL;
+       }
 #ifdef HAVE_LMDB
        if (view->new_zone_dbenv != NULL)
                mdb_env_close((MDB_env *) view->new_zone_dbenv);
@@ -1974,6 +1979,56 @@ dns_view_untrust(dns_view_t *view, const dns_name_t *keyname,
        dst_key_free(&key);
 }
 
+/*
+ * Create path to a directory and a filename contructed from viewname.
+ * This is a front-end to isc_file_sanitize(), allowing backward
+ * compatibility to older versions when a file couldn't be expected
+ * to be in the specified directory but might be in the current working
+ * directory instead.
+ *
+ * It first tests for the existence of a file <viewname>.<suffix> in
+ * 'directory'. If the file does not exist, it checks again in the
+ * current working directory. If it does not exist there either,
+ * return the path inside the directory.
+ *
+ * Returns ISC_R_SUCCESS if a path to an existing file is found or
+ * a new path is created; returns ISC_R_NOSPACE if the path won't
+ * fit in 'buflen'.
+ */
+static isc_result_t
+nz_legacy(const char *directory, const char *viewname,
+         const char *suffix, char *buffer, size_t buflen)
+{
+       isc_result_t result;
+       char newbuf[PATH_MAX];
+
+       result = isc_file_sanitize(directory, viewname, suffix,
+                                  buffer, buflen);
+       if (result != ISC_R_SUCCESS) {
+               return (result);
+       } else if (directory == NULL || isc_file_exists(buffer)) {
+               return (ISC_R_SUCCESS);
+       } else {
+               /* Save buffer */
+               strlcpy(newbuf, buffer, sizeof(newbuf));
+       }
+
+       /*
+        * It isn't in the specified directory; check CWD.
+        */
+       result = isc_file_sanitize(NULL, viewname, suffix, buffer, buflen);
+       if (result != ISC_R_SUCCESS || isc_file_exists(buffer)) {
+               return (result);
+       }
+
+       /*
+        * File does not exist in either 'directory' or CWD,
+        * so use the path in 'directory'.
+        */
+       strlcpy(buffer, newbuf, buflen);
+       return (ISC_R_SUCCESS);
+}
+
 isc_result_t
 dns_view_setnewzones(dns_view_t *view, isc_boolean_t allow, void *cfgctx,
                     void (*cfg_destroy)(void **))
@@ -2010,18 +2065,19 @@ dns_view_setnewzones(dns_view_t *view, isc_boolean_t allow, void *cfgctx,
                view->cfg_destroy = NULL;
        }
 
-       if (!allow)
+       if (!allow) {
                return (ISC_R_SUCCESS);
+       }
 
-       result = isc_file_sanitize(NULL, view->name, "nzf",
-                                  buffer, sizeof(buffer));
+       result = nz_legacy(view->new_zone_dir, view->name, "nzf",
+                          buffer, sizeof(buffer));
        if (result != ISC_R_SUCCESS)
                goto out;
        view->new_zone_file = isc_mem_strdup(view->mctx, buffer);
 
 #ifdef HAVE_LMDB
-       result = isc_file_sanitize(NULL, view->name, "nzd",
-                                  buffer, sizeof(buffer));
+       result = nz_legacy(view->new_zone_dir, view->name, "nzd",
+                          buffer, sizeof(buffer));
        if (result != ISC_R_SUCCESS)
                goto out;
        view->new_zone_db = isc_mem_strdup(view->mctx, buffer);
@@ -2068,6 +2124,29 @@ dns_view_setnewzones(dns_view_t *view, isc_boolean_t allow, void *cfgctx,
        return (result);
 }
 
+void
+dns_view_setnewzonedir(dns_view_t *view, const char *dir) {
+       REQUIRE(DNS_VIEW_VALID(view));
+
+       if (view->new_zone_dir != NULL) {
+               isc_mem_free(view->mctx, view->new_zone_dir);
+               view->new_zone_dir = NULL;
+       }
+
+       if (dir == NULL) {
+               return;
+       }
+
+       view->new_zone_dir = isc_mem_strdup(view->mctx, dir);
+}
+
+const char *
+dns_view_getnewzonedir(dns_view_t *view) {
+       REQUIRE(DNS_VIEW_VALID(view));
+
+       return (view->new_zone_dir);
+}
+
 isc_result_t
 dns_view_searchdlz(dns_view_t *view, const dns_name_t *name,
                   unsigned int minlabels, dns_clientinfomethods_t *methods,
index 6c7f8268b9fd4ed20e9855bcddecffb172832f70..061db7c02039f43a03d48347c0d6f366a8362357 100644 (file)
@@ -77,11 +77,57 @@ ATF_TC_BODY(isc_file_sanitize, tc) {
        unlink(F(SHA));
 }
 
+ATF_TC(isc_file_template);
+ATF_TC_HEAD(isc_file_template, tc) {
+       atf_tc_set_md_var(tc, "descr", "file template");
+}
+
+ATF_TC_BODY(isc_file_template, tc) {
+       isc_result_t result;
+       char buf[1024];
+
+       ATF_CHECK(chdir(TESTS) != -1);
+
+       result = isc_file_template("/absolute/path", "file-XXXXXXXX",
+                                  buf, sizeof(buf));
+       ATF_CHECK_EQ(result, ISC_R_SUCCESS);
+       ATF_CHECK_STREQ(buf, "/absolute/file-XXXXXXXX");
+
+       result = isc_file_template("relative/path", "file-XXXXXXXX",
+                                  buf, sizeof(buf));
+       ATF_CHECK_EQ(result, ISC_R_SUCCESS);
+       ATF_CHECK_STREQ(buf, "relative/file-XXXXXXXX");
+
+       result = isc_file_template("/trailing/slash/", "file-XXXXXXXX",
+                                  buf, sizeof(buf));
+       ATF_CHECK_EQ(result, ISC_R_SUCCESS);
+       ATF_CHECK_STREQ(buf, "/trailing/slash/file-XXXXXXXX");
+
+       result = isc_file_template("relative/trailing/slash/", "file-XXXXXXXX",
+                                  buf, sizeof(buf));
+       ATF_CHECK_EQ(result, ISC_R_SUCCESS);
+       ATF_CHECK_STREQ(buf, "relative/trailing/slash/file-XXXXXXXX");
+
+       result = isc_file_template("/", "file-XXXXXXXX", buf, sizeof(buf));
+       ATF_CHECK_EQ(result, ISC_R_SUCCESS);
+       ATF_CHECK_STREQ(buf, "/file-XXXXXXXX");
+
+       result = isc_file_template("noslash", "file-XXXXXXXX",
+                                  buf, sizeof(buf));
+       ATF_CHECK_EQ(result, ISC_R_SUCCESS);
+       ATF_CHECK_STREQ(buf, "file-XXXXXXXX");
+
+       result = isc_file_template(NULL, "file-XXXXXXXX", buf, sizeof(buf));
+       ATF_CHECK_EQ(result, ISC_R_SUCCESS);
+       ATF_CHECK_STREQ(buf, "file-XXXXXXXX");
+}
+
 /*
  * Main
  */
 ATF_TP_ADD_TCS(tp) {
        ATF_TP_ADD_TC(tp, isc_file_sanitize);
+       ATF_TP_ADD_TC(tp, isc_file_template);
        return (atf_no_error());
 }
 
index 02c7800f2c8e2d7f569626acc612796d473ce231..5655fa51dbb7743d93dd57cf7d16fd5c49f8d17b 100644 (file)
@@ -221,10 +221,12 @@ isc_file_template(const char *path, const char *templet, char *buf,
 {
        const char *s;
 
-       REQUIRE(path != NULL);
        REQUIRE(templet != NULL);
        REQUIRE(buf != NULL);
 
+       if (path == NULL)
+               path = "";
+
        s = strrchr(templet, '/');
        if (s != NULL)
                templet = s + 1;
index 884c78f3e7c876fec1c0554ac409f16fec9f5526..b5e20e22bedb5ca1dfd9a2255d1f6adc816427db 100644 (file)
@@ -324,6 +324,9 @@ isc_file_template(const char *path, const char *templet, char *buf,
        REQUIRE(templet != NULL);
        REQUIRE(buf != NULL);
 
+       if (path == NULL)
+               path = "";
+
        s = strrchr(templet, '\\');
        if (s != NULL)
                templet = s + 1;
index 0b763af7c6b54f84cfbd9bfc6008d742db014d44..2045190a26c23ab8a5356698c11d2d5bf6a5de69 100644 (file)
@@ -1896,6 +1896,7 @@ view_clauses[] = {
        { "min-roots", &cfg_type_uint32, CFG_CLAUSEFLAG_NOTIMP },
        { "minimal-any", &cfg_type_boolean, 0 },
        { "minimal-responses", &cfg_type_minimal, 0 },
+       { "new-zones-directory", &cfg_type_qstring, 0 },
        { "nta-recheck", &cfg_type_ttlval, 0 },
        { "nta-lifetime", &cfg_type_ttlval, 0 },
        { "nxdomain-redirect", &cfg_type_astring, 0 },