]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
Handle a missing zone when reloading a catalog zone
authorAram Sargsyan <aram@isc.org>
Fri, 24 Sep 2021 17:42:12 +0000 (17:42 +0000)
committerAram Sargsyan <aram@isc.org>
Thu, 30 Sep 2021 20:15:19 +0000 (20:15 +0000)
Previously a missing/deleted zone which was referenced by a catalog
zone was causing a crash when doing a reload.

This commit will make `named` to ignore the fact that the zone is
missing, and make sure to restore it later on.

(cherry picked from commit 94a57128017257b9799daf1aaa751cfb13d7cab0)

bin/named/server.c
bin/tests/system/catz/tests.sh
lib/dns/catz.c

index ab3a24abdaac5c715c846b17aa0179e590a6d2dd..da5eed45b65e9fe929a9d8eebd007da0fd733892 100644 (file)
@@ -3054,7 +3054,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);
index c149eb0200b4d67ddb58a376df7d508c8508896d..d441d017c7f6b9824bb2e6efa385cb1e1e4ac289 100644 (file)
@@ -1556,5 +1556,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 <<END >> 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 <<END >> 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
index 41402dd3d18b7efb9cabb386bd8f358aa3bd73be..7688fe56c96ca20deb957d1335ee7bbb5ed1dc25 100644 (file)
@@ -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;
+               }
+
+               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) {
-                       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));
-                       }
+                       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);
@@ -1386,6 +1390,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) {