diff --git a/CHANGES b/CHANGES index f2fa4f4fbe..7ef9c6af45 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,9 @@ +4380. [experimental] Added a "zone-directory" option to "catalog-zones" + syntax, allowing local masterfiles for slaves + that are provisioned by catalog zones to be stored + in a directory other than the server's working + directory. [RT #42527] + 4379. [bug] An INSIST could be triggered if a zone contains RRSIG records with expiry fields that loop using serial number arithmetic. [RT #40571] diff --git a/bin/named/server.c b/bin/named/server.c index 58ab7c06be..cd9ed0d17c 100644 --- a/bin/named/server.c +++ b/bin/named/server.c @@ -2367,6 +2367,11 @@ configure_catz_zone(dns_view_t *view, const cfg_obj_t *config, result = ns_config_getipandkeylist(config, obj, view->mctx, &opts->masters); + obj = cfg_tuple_get(catz_obj, "zone-directory"); + if (obj != NULL) + opts->zonedir = isc_mem_strdup(view->mctx, + cfg_obj_asstring(obj)); + obj = cfg_tuple_get(catz_obj, "in-memory"); if (obj != NULL && cfg_obj_isboolean(obj)) opts->in_memory = cfg_obj_asboolean(obj); diff --git a/bin/tests/system/catz/clean.sh b/bin/tests/system/catz/clean.sh index bf1b2d5aa9..9912e55dcd 100644 --- a/bin/tests/system/catz/clean.sh +++ b/bin/tests/system/catz/clean.sh @@ -17,7 +17,8 @@ rm -f nsupdate.out.* rm -f ns*/named.memstats rm -f ns*/named.run rm -f ns*/named.lock -rm -f ns{1,2}/*dom*example.db +rm -f ns1/*dom*example.db rm -f ns{1,2}/catalog.example.db +rm -rf ns2/zonedir rm -f ns*/*.jnl rm -f ns*/*.nzf diff --git a/bin/tests/system/catz/ns2/named.conf b/bin/tests/system/catz/ns2/named.conf index 4cd508d78b..a641a5c160 100644 --- a/bin/tests/system/catz/ns2/named.conf +++ b/bin/tests/system/catz/ns2/named.conf @@ -32,7 +32,10 @@ options { recursion no; serial-query-rate 100; catalog-zones { - zone "catalog.example" default-masters { 10.53.0.1; }; + zone "catalog.example" + default-masters { 10.53.0.1; } + in-memory no + zone-directory "zonedir"; }; }; diff --git a/bin/tests/system/catz/setup.sh b/bin/tests/system/catz/setup.sh index 8e0d3e8d86..7a3dbcdb7d 100644 --- a/bin/tests/system/catz/setup.sh +++ b/bin/tests/system/catz/setup.sh @@ -20,3 +20,4 @@ SYSTEMTESTTOP=.. $SHELL clean.sh cat ns1/catalog.example.db.in > ns1/catalog.example.db +mkdir ns2/zonedir diff --git a/bin/tests/system/catz/tests.sh b/bin/tests/system/catz/tests.sh index c72b99c690..4546d89ef3 100644 --- a/bin/tests/system/catz/tests.sh +++ b/bin/tests/system/catz/tests.sh @@ -301,5 +301,13 @@ grep "status: NOERROR" dig.out.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 zone-directory is populated ($n)" +ret=0 +[ -f "ns2/zonedir/__catz___default_catalog.example_dom3.example.db" ] || ret=1 +[ -f "ns2/zonedir/__catz___default_catalog.example_dom4.example.db" ] || ret=1 +if [ $ret != 0 ]; then echo "I:failed"; fi +status=`expr $status + $ret` + echo "I:exit status: $status" exit $status diff --git a/doc/arm/catz.xml b/doc/arm/catz.xml index 87cf5fbaec..6f19f90eb2 100644 --- a/doc/arm/catz.xml +++ b/doc/arm/catz.xml @@ -110,7 +110,11 @@ catalog-zones { - zone "catalog.example" default-masters { 10.53.0.1; } in-memory true min-update-interval 10; + zone "catalog.example" + default-masters { 10.53.0.1; } + in-memory no + zone-directory "catzones" + min-update-interval 10; }; @@ -119,6 +123,10 @@ catalog-zones { properly configured in the same view. In most configurations, it would be a slave zone. + + The options following the zone name are not required, and may be + specified in any order: + The option defines the default masters for member zones listed in a catalog zone. This can be overridden by @@ -134,6 +142,14 @@ catalog-zones { will be stored locally in a file whose name is automatically generated from the view name, catalog zone name, and member zone name. + + The option causes local copies of + member zones' master files (if is not set + to yes) to be stored in the specified directory. + The default is to store zone files in the server's working directory. + A non-absolute pathname in is + assumed to be relative to the working directory. + The option sets the minimum interval between processing of updates to catalog zones, in seconds. diff --git a/lib/dns/catz.c b/lib/dns/catz.c index 46b467962e..9364ff1fc0 100644 --- a/lib/dns/catz.c +++ b/lib/dns/catz.c @@ -96,12 +96,17 @@ dns_catz_options_init(dns_catz_options_t *options) { options->in_memory = ISC_FALSE; options->min_update_interval = 5; + options->zonedir = NULL; } void dns_catz_options_free(dns_catz_options_t *options, isc_mem_t *mctx) { if (options->masters.count > 0) dns_ipkeylist_clear(mctx, &options->masters); + if (options->zonedir != NULL) { + isc_mem_free(mctx, options->zonedir); + options->zonedir = NULL; + } } isc_result_t @@ -112,10 +117,17 @@ dns_catz_options_copy(isc_mem_t *mctx, const dns_catz_options_t *src, REQUIRE(dst != NULL); REQUIRE(dst->masters.count == 0); - if (src->masters.count != 0) { + if (src->masters.count != 0) dns_ipkeylist_copy(mctx, &src->masters, &dst->masters); + + if (dst->zonedir != NULL) { + isc_mem_free(mctx, dst->zonedir); + dst->zonedir = NULL; } + if (src->zonedir != NULL) + dst->zonedir = isc_mem_strdup(mctx, src->zonedir); + return (ISC_R_SUCCESS); } @@ -125,6 +137,8 @@ dns_catz_options_setdefault(isc_mem_t *mctx, const dns_catz_options_t *defaults, { if (opts->masters.count == 0) dns_catz_options_copy(mctx, defaults, opts); + else if (defaults->zonedir != NULL) + opts->zonedir = isc_mem_strdup(mctx, defaults->zonedir); /* This option is always taken from config, so it's always 'default' */ opts->in_memory = defaults->in_memory; @@ -234,7 +248,6 @@ dns_catz_entry_cmp(const dns_catz_entry_t *ea, const dns_catz_entry_t *eb) { return (ISC_TRUE); } - dns_name_t * dns_catz_zone_getname(dns_catz_zone_t *zone) { REQUIRE(zone != NULL); @@ -1072,6 +1085,7 @@ dns_catz_generate_masterfilename(dns_catz_zone_t *zone, dns_catz_entry_t *entry, isc_sha256_t sha256; isc_region_t r; isc_result_t result; + size_t rlen; REQUIRE(zone != NULL); REQUIRE(entry != NULL); @@ -1079,26 +1093,38 @@ dns_catz_generate_masterfilename(dns_catz_zone_t *zone, dns_catz_entry_t *entry, result = isc_buffer_allocate(zone->catzs->mctx, &tbuf, strlen(zone->catzs->view->name) + - 2*DNS_NAME_FORMATSIZE + 2); + 2 * DNS_NAME_FORMATSIZE + 2); if (result != ISC_R_SUCCESS) return (result); INSIST(tbuf != NULL); + isc_buffer_putstr(tbuf, zone->catzs->view->name); isc_buffer_putstr(tbuf, "_"); result = dns_name_totext(&zone->name, ISC_TRUE, tbuf); if (result != ISC_R_SUCCESS) goto cleanup; + isc_buffer_putstr(tbuf, "_"); result = dns_name_totext(&entry->name, ISC_TRUE, tbuf); if (result != ISC_R_SUCCESS) goto cleanup; - result = isc_buffer_reserve(buffer, strlen("__catz__") + - ISC_SHA256_DIGESTSTRINGLENGTH + - strlen(".db")); + /* __catz__.db */ + rlen = ISC_SHA256_DIGESTSTRINGLENGTH + 12; + + /* optionally prepend with / */ + if (entry->opts.zonedir != NULL) + rlen += strlen(entry->opts.zonedir) + 1; + + result = isc_buffer_reserve(buffer, rlen); if (result != ISC_R_SUCCESS) goto cleanup; + if (entry->opts.zonedir != NULL) { + isc_buffer_putstr(*buffer, entry->opts.zonedir); + isc_buffer_putstr(*buffer, "/"); + } + isc_buffer_usedregion(tbuf, &r); isc_buffer_putstr(*buffer, "__catz__"); if (tbuf->used > ISC_SHA256_DIGESTSTRINGLENGTH) { @@ -1110,11 +1136,13 @@ dns_catz_generate_masterfilename(dns_catz_zone_t *zone, dns_catz_entry_t *entry, } else { isc_buffer_copyregion(*buffer, &r); } + isc_buffer_putstr(*buffer, ".db"); result = ISC_R_SUCCESS; cleanup: - isc_buffer_free(&tbuf); + if (tbuf != NULL) + isc_buffer_free(&tbuf); return (result); } diff --git a/lib/dns/include/dns/catz.h b/lib/dns/include/dns/catz.h index 7cff8b9b33..73bd25028e 100644 --- a/lib/dns/include/dns/catz.h +++ b/lib/dns/include/dns/catz.h @@ -51,12 +51,15 @@ struct dns_catz_entry_options { /* * Options that can be overriden in catalog zone */ - /* masters definition */ + /* default-masters definition */ dns_ipkeylist_t masters; /* * Options that are only set in named.conf */ + /* zone-directory definition */ + char *zonedir; + /* zone should not be stored on disk (no 'file' statement in def */ isc_boolean_t in_memory; /* diff --git a/lib/isccfg/namedconf.c b/lib/isccfg/namedconf.c index a3ca7c8163..f45eec6483 100644 --- a/lib/isccfg/namedconf.c +++ b/lib/isccfg/namedconf.c @@ -1484,6 +1484,7 @@ static cfg_type_t cfg_type_catz_zone = { static cfg_tuplefielddef_t catz_zone_fields[] = { { "zone name", &cfg_type_catz_zone, 0 }, { "default-masters", &cfg_type_namesockaddrkeylist, 0 }, + { "zone-directory", &cfg_type_qstring, 0 }, { "in-memory", &cfg_type_boolean, 0 }, { "min-update-interval", &cfg_type_uint32, 0 }, { NULL, NULL, 0 }