diff --git a/bin/named/server.c b/bin/named/server.c index f80ec23aff..4183786f63 100644 --- a/bin/named/server.c +++ b/bin/named/server.c @@ -3061,7 +3061,9 @@ configure_catz_zone(dns_view_t *view, const cfg_obj_t *config, name = dns_catz_entry_getname(entry); tresult = dns_view_findzone(pview, name, &dnszone); - RUNTIME_CHECK(tresult == ISC_R_SUCCESS); + if (tresult != ISC_R_SUCCESS) { + continue; + } dns_zone_setview(dnszone, view); dns_view_addzone(view, dnszone); diff --git a/bin/tests/system/catz/tests.sh b/bin/tests/system/catz/tests.sh index 00af67cf59..d3f6fd9f36 100644 --- a/bin/tests/system/catz/tests.sh +++ b/bin/tests/system/catz/tests.sh @@ -1555,5 +1555,129 @@ wait_for_soa @10.53.0.2 dom15.example. dig.out.test$n || ret=1 if [ $ret -ne 0 ]; then echo_i "failed"; fi status=$((status+ret)) +########################################################################## +echo_i "Testing recreation of a manually deleted zone after a reload" +n=$((n+1)) +echo_i "checking that dom16.example. is not served by primary ($n)" +ret=0 +wait_for_no_soa @10.53.0.1 dom16.example. dig.out.test$n || ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status+ret)) + +n=$((n+1)) +echo_i "Adding a domain dom16.example. to primary ns1 via RNDC ($n)" +ret=0 +echo "@ 3600 IN SOA . . 1 3600 3600 3600 3600" > ns1/dom16.example.db +echo "@ IN NS invalid." >> ns1/dom16.example.db +echo "@ IN A 192.0.2.1" >> ns1/dom16.example.db +rndccmd 10.53.0.1 addzone dom16.example. '{type primary; file "dom16.example.db";};' || ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status+ret)) + +n=$((n+1)) +echo_i "checking that dom16.example. is now served by primary ns1 ($n)" +ret=0 +wait_for_soa @10.53.0.1 dom16.example. dig.out.test$n || ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status+ret)) + +nextpart ns2/named.run >/dev/null + +n=$((n+1)) +echo_i "Adding domain dom16.example. to catalog1 zone with ns1 as primary ($n)" +ret=0 +$NSUPDATE -d <> nsupdate.out.test$n 2>&1 || ret=1 + server 10.53.0.1 ${PORT} + update add efe725d0cf430ffb113b9bcf59266f066a21216b.zones.catalog1.example. 3600 IN PTR dom16.example. + update add masters.efe725d0cf430ffb113b9bcf59266f066a21216b.zones.catalog1.example. 3600 IN A 10.53.0.1 + send +END +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status+ret)) + +n=$((n+1)) +echo_i "waiting for secondary to sync up ($n)" +ret=0 +wait_for_message ns2/named.run "catz: adding zone 'dom16.example' from catalog 'catalog1.example'" && +wait_for_message ns2/named.run "transfer of 'dom16.example/IN' from 10.53.0.1#${PORT}: Transfer status: success" || ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status+ret)) + +nextpart ns2/named.run >/dev/null + +n=$((n+1)) +echo_i "checking that dom16.example. is served by secondary and that it's the one from ns1 ($n)" +ret=0 +wait_for_a @10.53.0.2 dom16.example. dig.out.test$n || ret=1 +grep "192.0.2.1" dig.out.test$n > /dev/null || ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status+ret)) + +nextpart ns2/named.run >/dev/null + +echo_i "Deleting dom16.example. from secondary ns2 via RNDC ($n)" +ret=0 +rndccmd 10.53.0.2 delzone dom16.example. >/dev/null 2>&1 || ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status+ret)) + +n=$((n+1)) +echo_i "checking that dom16.example. is no longer served by secondary ($n)" +ret=0 +wait_for_no_soa @10.53.0.2 dom16.example. dig.out.test$n || ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status+ret)) + +nextpart ns2/named.run >/dev/null + +echo_i "Reloading secondary ns2 via RNDC ($n)" +ret=0 +rndccmd 10.53.0.2 reload >/dev/null 2>&1 || ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status+ret)) + +n=$((n+1)) +echo_i "waiting for secondary to sync up ($n)" +ret=0 +wait_for_message ns2/named.run "catz: update_from_db: new zone merged" || ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status+ret)) + +n=$((n+1)) +echo_i "checking that dom16.example. is served by secondary and that it's the one from ns1 ($n)" +ret=0 +wait_for_a @10.53.0.2 dom16.example. dig.out.test$n || ret=1 +grep "192.0.2.1" dig.out.test$n > /dev/null || ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status+ret)) + +nextpart ns2/named.run >/dev/null + +n=$((n+1)) +echo_i "Deleting domain dom16.example. from catalog1 ($n)" +ret=0 +$NSUPDATE -d <> nsupdate.out.test$n 2>&1 || ret=1 + server 10.53.0.1 ${PORT} + update delete efe725d0cf430ffb113b9bcf59266f066a21216b.zones.catalog1.example. 3600 IN PTR dom16.example. + update delete masters.efe725d0cf430ffb113b9bcf59266f066a21216b.zones.catalog1.example. 3600 IN A 10.53.0.1 + send +END +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status+ret)) + +n=$((n+1)) +echo_i "waiting for secondary to sync up ($n)" +ret=0 +wait_for_message ns2/named.run "catz: update_from_db: new zone merged" || ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status+ret)) + +n=$((n+1)) +echo_i "checking that dom16.example. is no longer served by secondary ($n)" +ret=0 +wait_for_no_soa @10.53.0.2 dom16.example. dig.out.test$n || ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status+ret)) + echo_i "exit status: $status" [ $status -eq 0 ] || exit 1 diff --git a/lib/dns/catz.c b/lib/dns/catz.c index f946d9dab6..6767d875f1 100644 --- a/lib/dns/catz.c +++ b/lib/dns/catz.c @@ -86,6 +86,11 @@ catz_process_zones_entry(dns_catz_zone_t *zone, dns_rdataset_t *value, static isc_result_t catz_process_zones_suboption(dns_catz_zone_t *zone, dns_rdataset_t *value, dns_label_t *mhash, dns_name_t *name); +static void +catz_entry_add_or_mod(dns_catz_zone_t *target, isc_ht_t *ht, unsigned char *key, + size_t keysize, dns_catz_entry_t *nentry, + dns_catz_entry_t *oentry, const char *msg, + const char *zname, const char *czname); /*% * Collection of catalog zones for a view @@ -443,6 +448,7 @@ dns_catz_zones_merge(dns_catz_zone_t *target, dns_catz_zone_t *newzone) { { dns_catz_entry_t *nentry = NULL; dns_catz_entry_t *oentry = NULL; + dns_zone_t *zone = NULL; unsigned char *key = NULL; size_t keysize; delcur = false; @@ -474,36 +480,34 @@ dns_catz_zones_merge(dns_catz_zone_t *target, dns_catz_zone_t *newzone) { result = isc_ht_find(target->entries, key, (uint32_t)keysize, (void **)&oentry); if (result != ISC_R_SUCCESS) { - result = isc_ht_add(toadd, key, (uint32_t)keysize, - nentry); - if (result != ISC_R_SUCCESS) { - isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL, - DNS_LOGMODULE_MASTER, - ISC_LOG_ERROR, - "catz: error adding zone '%s' " - "from catalog '%s' - %s", - zname, czname, - isc_result_totext(result)); - } + catz_entry_add_or_mod(target, toadd, key, keysize, + nentry, NULL, "adding", zname, + czname); continue; } - if (dns_catz_entry_cmp(oentry, nentry) != true) { - result = isc_ht_add(tomod, key, (uint32_t)keysize, - nentry); - if (result != ISC_R_SUCCESS) { - isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL, - DNS_LOGMODULE_MASTER, - ISC_LOG_ERROR, - "catz: error modifying zone '%s' " - "from catalog '%s' - %s", - zname, czname, - isc_result_totext(result)); - } + result = dns_zt_find(target->catzs->view->zonetable, + dns_catz_entry_getname(nentry), 0, NULL, + &zone); + if (result != ISC_R_SUCCESS) { + isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL, + DNS_LOGMODULE_MASTER, ISC_LOG_DEBUG(3), + "catz: zone '%s' was expected to exist " + "but can not be found, will be restored", + zname); + catz_entry_add_or_mod(target, toadd, key, keysize, + nentry, oentry, "adding", zname, + czname); + continue; + } + dns_zone_detach(&zone); + + if (dns_catz_entry_cmp(oentry, nentry) != true) { + catz_entry_add_or_mod(target, tomod, key, keysize, + nentry, oentry, "modifying", + zname, czname); + continue; } - dns_catz_entry_detach(target, &oentry); - result = isc_ht_delete(target->entries, key, (uint32_t)keysize); - RUNTIME_CHECK(result == ISC_R_SUCCESS); } RUNTIME_CHECK(result == ISC_R_NOMORE); isc_ht_iter_destroy(&iter1); @@ -1388,6 +1392,26 @@ catz_process_zones_suboption(dns_catz_zone_t *zone, dns_rdataset_t *value, return (ISC_R_FAILURE); } +static inline void +catz_entry_add_or_mod(dns_catz_zone_t *target, isc_ht_t *ht, unsigned char *key, + size_t keysize, dns_catz_entry_t *nentry, + dns_catz_entry_t *oentry, const char *msg, + const char *zname, const char *czname) { + isc_result_t result = isc_ht_add(ht, key, (uint32_t)keysize, nentry); + + if (result != ISC_R_SUCCESS) { + isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL, + DNS_LOGMODULE_MASTER, ISC_LOG_ERROR, + "catz: error %s zone '%s' from catalog '%s' - %s", + msg, zname, czname, isc_result_totext(result)); + } + if (oentry != NULL) { + dns_catz_entry_detach(target, &oentry); + result = isc_ht_delete(target->entries, key, (uint32_t)keysize); + RUNTIME_CHECK(result == ISC_R_SUCCESS); + } +} + static isc_result_t catz_process_value(dns_catz_zone_t *zone, dns_name_t *name, dns_rdataset_t *rdataset) {