From 5093e8d482d2052ee9a827c9ccfd36e6e1d3eea8 Mon Sep 17 00:00:00 2001 From: Mark Andrews Date: Wed, 28 Dec 2016 11:36:31 +1100 Subject: [PATCH] 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] --- CHANGES | 4 + bin/named/server.c | 122 ++++++++++++++++++++++++------ bin/rndc/rndc.docbook | 13 ++++ bin/tests/system/addzone/tests.sh | 24 ++++-- doc/arm/notes.xml | 7 ++ 5 files changed, 139 insertions(+), 31 deletions(-) diff --git a/CHANGES b/CHANGES index c33f3f3d71..b186a83270 100644 --- 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] diff --git a/bin/named/server.c b/bin/named/server.c index 27ffd36659..d95e29a011 100644 --- a/bin/named/server.c +++ b/bin/named/server.c @@ -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)); diff --git a/bin/rndc/rndc.docbook b/bin/rndc/rndc.docbook index f273519680..924ae7a1d1 100644 --- a/bin/rndc/rndc.docbook +++ b/bin/rndc/rndc.docbook @@ -968,6 +968,19 @@ + + + rndc commands that specify zone names, + such as reload, retransfer + or zonestatus, can be ambiguous when applied + to zones of type . Redirect zones are + always called ".", and can be confused with zones of type + or with slaved copies of the root zone. + To specify a redirect zone, use the special zone name + -redirect, without a trailing period. + (With a trailing period, this would specify a zone called + "-redirect".) + LIMITATIONS diff --git a/bin/tests/system/addzone/tests.sh b/bin/tests/system/addzone/tests.sh index 6f3e1bbeff..d537e7fe67 100755 --- a/bin/tests/system/addzone/tests.sh +++ b/bin/tests/system/addzone/tests.sh @@ -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` diff --git a/doc/arm/notes.xml b/doc/arm/notes.xml index 0e813e516f..06c3f7c67d 100644 --- a/doc/arm/notes.xml +++ b/doc/arm/notes.xml @@ -62,6 +62,13 @@ local. [RT #42585] + + + Rndc commands can now manipulate redirect zones using "-redirect". + To manipulate a zone called "-redirect" reference it using absolute + name form ("-redirect."). + +