]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
4542. [func] Allow rndc to manipulate redirect zones with using
authorMark Andrews <marka@isc.org>
Wed, 28 Dec 2016 00:36:31 +0000 (11:36 +1100)
committerMark Andrews <marka@isc.org>
Wed, 28 Dec 2016 00:36:31 +0000 (11:36 +1100)
                        -redirect as the zone name (use "-redirect." to
                        manipulate a zone named "-redirect"). [RT #43971]

CHANGES
bin/named/server.c
bin/rndc/rndc.docbook
bin/tests/system/addzone/tests.sh
doc/arm/notes.xml

diff --git a/CHANGES b/CHANGES
index c33f3f3d71f9c1450285f5ed6fa1df0ec1d71fa9..b186a8327091c329255e01455bdba8733b23aad5 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -1,3 +1,7 @@
+4542.  [func]          Allow rndc to manipulate redirect zones with using
+                       -redirect as the zone name (use "-redirect." to
+                       manipulate a zone named "-redirect"). [RT #43971]
+
 4541.  [bug]           rndc addzone should properly reject non master/slave
                        zones. [RT #43665]
 
index 27ffd36659228b4cc1186b87534a27427484976f..d95e29a0114986d7de0833cbb32d0511a5fbeb2c 100644 (file)
@@ -8917,6 +8917,7 @@ zone_from_args(ns_server_t *server, isc_lex_t *lex, const char *zonetxt,
        dns_rdataclass_t rdclass;
        char problem[DNS_NAME_FORMATSIZE + 500] = "";
        char zonebuf[DNS_NAME_FORMATSIZE];
+       isc_boolean_t redirect = ISC_FALSE;
 
        REQUIRE(zonep != NULL && *zonep == NULL);
 
@@ -8934,7 +8935,12 @@ zone_from_args(ns_server_t *server, isc_lex_t *lex, const char *zonetxt,
                return (ISC_R_SUCCESS);
 
        /* Copy zonetxt because it'll be overwritten by next_token() */
-       strlcpy(zonebuf, zonetxt, DNS_NAME_FORMATSIZE);
+       /* To locate a zone named "-redirect" use "-redirect." */
+       if (strcmp(zonetxt, "-redirect") == 0) {
+               redirect = ISC_TRUE;
+               strlcpy(zonebuf, ".", DNS_NAME_FORMATSIZE);
+       } else
+               strlcpy(zonebuf, zonetxt, DNS_NAME_FORMATSIZE);
        if (zonename != NULL)
                strlcpy(zonename, zonetxt, DNS_NAME_FORMATSIZE);
 
@@ -8956,17 +8962,35 @@ zone_from_args(ns_server_t *server, isc_lex_t *lex, const char *zonetxt,
                rdclass = dns_rdataclass_in;
 
        if (viewtxt == NULL) {
-               result = dns_viewlist_findzone(&server->viewlist, name,
-                                              ISC_TF(classtxt == NULL),
-                                              rdclass, zonep);
-               if (result == ISC_R_NOTFOUND)
-                       snprintf(problem, sizeof(problem),
-                                "no matching zone '%s' in any view",
-                                zonebuf);
-               else if (result == ISC_R_MULTIPLE)
-                       snprintf(problem, sizeof(problem),
-                                "zone '%s' was found in multiple views",
-                                zonebuf);
+               if (redirect) {
+                       result = dns_viewlist_find(&server->viewlist,
+                                                  "_default",
+                                                  dns_rdataclass_in,
+                                                  &view);
+                       if (result != ISC_R_SUCCESS ||
+                           view->redirect == NULL)
+                       {
+                               result = ISC_R_NOTFOUND;
+                               snprintf(problem, sizeof(problem),
+                                        "redirect zone not found in "
+                                        "_default view");
+                       } else {
+                               dns_zone_attach(view->redirect, zonep);
+                               result = ISC_R_SUCCESS;
+                       }
+               } else {
+                       result = dns_viewlist_findzone(&server->viewlist,
+                                         name, ISC_TF(classtxt == NULL),
+                                         rdclass, zonep);
+                       if (result == ISC_R_NOTFOUND)
+                               snprintf(problem, sizeof(problem),
+                                        "no matching zone '%s' in any view",
+                                        zonebuf);
+                       else if (result == ISC_R_MULTIPLE)
+                               snprintf(problem, sizeof(problem),
+                                        "zone '%s' was found in multiple "
+                                        "views", zonebuf);
+               }
        } else {
                result = dns_viewlist_find(&server->viewlist, viewtxt,
                                           rdclass, &view);
@@ -8976,7 +9000,15 @@ zone_from_args(ns_server_t *server, isc_lex_t *lex, const char *zonetxt,
                        goto report;
                }
 
-               result = dns_zt_find(view->zonetable, name, 0, NULL, zonep);
+               if (redirect) {
+                       if (view->redirect != NULL) {
+                               dns_zone_attach(view->redirect, zonep);
+                               result = ISC_R_SUCCESS;
+                       } else
+                               result = ISC_R_NOTFOUND;
+               } else 
+                       result = dns_zt_find(view->zonetable, name, 0,
+                                            NULL, zonep);
                if (result != ISC_R_SUCCESS)
                        snprintf(problem, sizeof(problem),
                                 "no matching zone '%s' in view '%s'",
@@ -11246,10 +11278,11 @@ migrate_nzf(dns_view_t *view) {
 static isc_result_t
 newzone_parse(ns_server_t *server, char *command, dns_view_t **viewp,
              cfg_obj_t **zoneconfp, const cfg_obj_t **zoneobjp,
-             isc_buffer_t **text)
+             isc_boolean_t *redirectp, isc_buffer_t **text)
 {
        isc_result_t result;
        isc_buffer_t argbuf;
+       isc_boolean_t redirect = ISC_FALSE;
        cfg_obj_t *zoneconf = NULL;
        const cfg_obj_t *zlist = NULL;
        const cfg_obj_t *zoneobj = NULL;
@@ -11263,6 +11296,7 @@ newzone_parse(ns_server_t *server, char *command, dns_view_t **viewp,
        REQUIRE(viewp != NULL && *viewp == NULL);
        REQUIRE(zoneobjp != NULL && *zoneobjp == NULL);
        REQUIRE(zoneconfp != NULL && *zoneconfp == NULL);
+       REQUIRE(redirectp != NULL);
 
        /* Try to parse the argument string */
        isc_buffer_init(&argbuf, command, (unsigned int) strlen(command));
@@ -11309,7 +11343,6 @@ newzone_parse(ns_server_t *server, char *command, dns_view_t **viewp,
 
        if (strcasecmp(cfg_obj_asstring(obj), "hint") == 0 ||
            strcasecmp(cfg_obj_asstring(obj), "forward") == 0 ||
-           strcasecmp(cfg_obj_asstring(obj), "redirect") == 0 ||
            strcasecmp(cfg_obj_asstring(obj), "delegation-only") == 0)
        {
                (void) putstr(text, "'");
@@ -11319,6 +11352,9 @@ newzone_parse(ns_server_t *server, char *command, dns_view_t **viewp,
                CHECK(ISC_R_FAILURE);
        }
 
+       if (strcasecmp(cfg_obj_asstring(obj), "redirect") == 0)
+               redirect = ISC_TRUE;
+
        /* Make sense of optional class argument */
        obj = cfg_tuple_get(zoneobj, "class");
        CHECK(ns_config_getclass(obj, dns_rdataclass_in, &rdclass));
@@ -11343,6 +11379,7 @@ newzone_parse(ns_server_t *server, char *command, dns_view_t **viewp,
        *viewp = view;
        *zoneobjp = zoneobj;
        *zoneconfp = zoneconf;
+       *redirectp = redirect;
 
        return (ISC_R_SUCCESS);
 
@@ -11420,7 +11457,7 @@ delete_zoneconf(dns_view_t *view, cfg_parser_t *pctx,
 static isc_result_t
 do_addzone(ns_server_t *server, ns_cfgctx_t *cfg, dns_view_t *view,
           dns_name_t *name, cfg_obj_t *zoneconf, const cfg_obj_t *zoneobj,
-          isc_buffer_t **text)
+          isc_boolean_t redirect, isc_buffer_t **text)
 {
        isc_result_t result, tresult;
        dns_zone_t *zone = NULL;
@@ -11434,7 +11471,11 @@ do_addzone(ns_server_t *server, ns_cfgctx_t *cfg, dns_view_t *view,
 #endif /* HAVE_LMDB */
 
        /* Zone shouldn't already exist */
-       result = dns_zt_find(view->zonetable, name, 0, NULL, &zone);
+       if (redirect) {
+               result = (view->redirect != NULL) ? ISC_R_SUCCESS :
+                                                   ISC_R_NOTFOUND;
+       } else
+               result = dns_zt_find(view->zonetable, name, 0, NULL, &zone);
        if (result == ISC_R_SUCCESS) {
                result = ISC_R_EXISTS;
                goto cleanup;
@@ -11491,7 +11532,12 @@ do_addzone(ns_server_t *server, ns_cfgctx_t *cfg, dns_view_t *view,
        }
 
        /* Is it there yet? */
-       CHECK(dns_zt_find(view->zonetable, name, 0, NULL, &zone));
+       if (redirect) {
+               if (view->redirect == NULL)
+                       CHECK(ISC_R_NOTFOUND);
+               dns_zone_attach(view->redirect, &zone);
+       } else
+               CHECK(dns_zt_find(view->zonetable, name, 0, NULL, &zone));
 
 #ifndef HAVE_LMDB
        /*
@@ -11565,7 +11611,7 @@ do_addzone(ns_server_t *server, ns_cfgctx_t *cfg, dns_view_t *view,
 static isc_result_t
 do_modzone(ns_server_t *server, ns_cfgctx_t *cfg, dns_view_t *view,
           dns_name_t *name, const char *zname, const cfg_obj_t *zoneobj,
-          isc_buffer_t **text)
+          isc_boolean_t redirect, isc_buffer_t **text)
 {
        isc_result_t result, tresult;
        dns_zone_t *zone = NULL;
@@ -11580,7 +11626,14 @@ do_modzone(ns_server_t *server, ns_cfgctx_t *cfg, dns_view_t *view,
 #endif /* HAVE_LMDB */
 
        /* Zone must already exist */
-       result = dns_zt_find(view->zonetable, name, 0, NULL, &zone);
+       if (redirect) {
+               if (view->redirect != NULL) {
+                       dns_zone_attach(view->redirect, &zone);
+                       result = ISC_R_SUCCESS;
+               } else
+                       result = ISC_R_NOTFOUND;
+       } else
+               result = dns_zt_find(view->zonetable, name, 0, NULL, &zone);
        if (result != ISC_R_SUCCESS)
                goto cleanup;
 
@@ -11640,7 +11693,14 @@ do_modzone(ns_server_t *server, ns_cfgctx_t *cfg, dns_view_t *view,
        }
 
        /* Is it there yet? */
-       CHECK(dns_zt_find(view->zonetable, name, 0, NULL, &zone));
+       if (redirect) {
+               if (view->redirect == NULL)
+                       CHECK(ISC_R_NOTFOUND);
+               dns_zone_attach(view->redirect, &zone);
+       } else
+               CHECK(dns_zt_find(view->zonetable, name, 0, NULL, &zone));
+       
+
 
 #ifndef HAVE_LMDB
        /* Remove old zone from configuration (and NZF file if applicable) */
@@ -11770,6 +11830,7 @@ isc_result_t
 ns_server_changezone(ns_server_t *server, char *command, isc_buffer_t **text) {
        isc_result_t result;
        isc_boolean_t addzone;
+       isc_boolean_t redirect = ISC_FALSE;
        ns_cfgctx_t *cfg = NULL;
        cfg_obj_t *zoneconf = NULL;
        const cfg_obj_t *zoneobj = NULL;
@@ -11787,7 +11848,7 @@ ns_server_changezone(ns_server_t *server, char *command, isc_buffer_t **text) {
        }
 
        CHECK(newzone_parse(server, command, &view, &zoneconf,
-                           &zoneobj, text));
+                           &zoneobj, &redirect, text));
 
        /* Are we accepting new zones in this view? */
 #ifdef HAVE_LMDB
@@ -11817,12 +11878,20 @@ ns_server_changezone(ns_server_t *server, char *command, isc_buffer_t **text) {
        dnsname = dns_fixedname_name(&fname);
        CHECK(dns_name_fromtext(dnsname, &buf, dns_rootname, 0, NULL));
 
+       if (redirect) {
+               if (!dns_name_equal(dnsname, dns_rootname)) {
+                       (void) putstr(text,
+                                     "redirect zones must be called \".\"");
+                       CHECK(ISC_R_FAILURE);
+               }
+       }
+
        if (addzone)
                CHECK(do_addzone(server, cfg, view, dnsname, zoneconf,
-                                zoneobj, text));
+                                zoneobj, redirect, text));
        else
                CHECK(do_modzone(server, cfg, view, dnsname, zonename,
-                                zoneobj, text));
+                                zoneobj, redirect, text));
 
        isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
                      NS_LOGMODULE_SERVER, ISC_LOG_INFO,
@@ -12054,7 +12123,10 @@ ns_server_delzone(ns_server_t *server, isc_lex_t *lex, isc_buffer_t **text) {
        }
 
        view = dns_zone_getview(zone);
-       CHECK(dns_zt_unmount(view->zonetable, zone));
+       if (dns_zone_gettype(zone) == dns_zone_redirect)
+               dns_zone_detach(&view->redirect);
+       else
+               CHECK(dns_zt_unmount(view->zonetable, zone));
 
        /* Send cleanup event */
        dz = isc_mem_get(ns_g_mctx, sizeof(*dz));
index f273519680e3e6d434bc4ac17ec36d3e3620c840..924ae7a1d1c7a30a3b17c0673e59299a583be972 100644 (file)
       </varlistentry>
 
     </variablelist>
+
+    <para>
+      <command>rndc</command> commands that specify zone names,
+      such as <command>reload</command>, <command>retransfer</command>
+      or <command>zonestatus</command>, can be ambiguous when applied
+      to zones of type <option>redirect</option>. Redirect zones are
+      always called ".", and can be confused with zones of type
+      <option>hint</option> or with slaved copies of the root zone.
+      To specify a redirect zone, use the special zone name
+      <userinput>-redirect</userinput>, without a trailing period.
+      (With a trailing period, this would specify a zone called
+      "-redirect".)
+    </para>
   </refsection>
 
   <refsection><info><title>LIMITATIONS</title></info>
index 6f3e1bbeff7869063bcb3bb204300421189e078f..d537e7fe67b51210bbb7c9ff6c04223eb2792687 100755 (executable)
@@ -306,18 +306,30 @@ n=`expr $n + 1`
 if [ $ret != 0 ]; then echo "I:failed"; fi
 status=`expr $status + $ret`
 
-echo "I:check that zone type 'redirect' (master) is properly rejected ($n)"
+echo "I:check that adding a 'master redirect' zone works ($n)"
 ret=0
-$RNDC -c ../common/rndc.conf -s 10.53.0.2 -p 9953 addzone '"." { type redirect; file "redirect.db"; };' > rndc.out.ns2.$n 2>&1 && ret=1
-grep "zones not supported by addzone" rndc.out.ns2.$n > /dev/null || ret=1
+$RNDC -c ../common/rndc.conf -s 10.53.0.2 -p 9953 addzone '"." { type redirect; file "redirect.db"; };' > rndc.out.ns2.$n 2>&1 || ret=1
 n=`expr $n + 1`
 if [ $ret != 0 ]; then echo "I:failed"; fi
 status=`expr $status + $ret`
 
-echo "I:check that zone type 'redirect' (slave) is properly rejected ($n)"
+echo "I:check that deleting a 'master redirect' zone works ($n)"
 ret=0
-$RNDC -c ../common/rndc.conf -s 10.53.0.2 -p 9953 addzone '"." { type redirect; masters { 1.2.3.4; }; file "redirect.bk"; };' > rndc.out.ns2.$n 2>&1 && ret=1
-grep "zones not supported by addzone" rndc.out.ns2.$n > /dev/null || ret=1
+$RNDC -c ../common/rndc.conf -s 10.53.0.2 -p 9953 delzone -redirect > rndc.out.ns2.$n 2>&1 || ret=1
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo "I:failed"; fi
+status=`expr $status + $ret`
+
+echo "I:check that adding a 'slave redirect' zone works ($n)"
+ret=0
+$RNDC -c ../common/rndc.conf -s 10.53.0.2 -p 9953 addzone '"." { type redirect; masters { 1.2.3.4; }; file "redirect.bk"; };' > rndc.out.ns2.$n 2>&1 || ret=1
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo "I:failed"; fi
+status=`expr $status + $ret`
+
+echo "I:check that deleting a 'slave redirect' zone works ($n)"
+ret=0
+$RNDC -c ../common/rndc.conf -s 10.53.0.2 -p 9953 delzone -redirect > rndc.out.ns2.$n 2>&1 || ret=1
 n=`expr $n + 1`
 if [ $ret != 0 ]; then echo "I:failed"; fi
 status=`expr $status + $ret`
index 0e813e516f66d4fb21bf8b1e6032b26cf530b34f..06c3f7c67d4be3df8f5e53babaee36d7398a145e 100644 (file)
          <userinput>local</userinput>.  [RT #42585]
        </para>
       </listitem>
+      <listitem>
+       <para>
+         Rndc commands can now manipulate redirect zones using "-redirect".
+         To manipulate a zone called "-redirect" reference it using absolute
+         name form ("-redirect.").
+       </para>
+      </listitem>
     </itemizedlist>
   </section>