2
0
mirror of https://gitlab.isc.org/isc-projects/bind9 synced 2025-09-02 23:55:27 +00:00

Handle a missing zone when reloading a catalog zone

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.
This commit is contained in:
Aram Sargsyan
2021-09-24 17:42:12 +00:00
parent 2b5d3f125c
commit 94a5712801
3 changed files with 177 additions and 27 deletions

View File

@@ -3061,7 +3061,9 @@ configure_catz_zone(dns_view_t *view, const cfg_obj_t *config,
name = dns_catz_entry_getname(entry); name = dns_catz_entry_getname(entry);
tresult = dns_view_findzone(pview, name, &dnszone); 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_zone_setview(dnszone, view);
dns_view_addzone(view, dnszone); dns_view_addzone(view, dnszone);

View File

@@ -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 if [ $ret -ne 0 ]; then echo_i "failed"; fi
status=$((status+ret)) 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" echo_i "exit status: $status"
[ $status -eq 0 ] || exit 1 [ $status -eq 0 ] || exit 1

View File

@@ -86,6 +86,11 @@ catz_process_zones_entry(dns_catz_zone_t *zone, dns_rdataset_t *value,
static isc_result_t static isc_result_t
catz_process_zones_suboption(dns_catz_zone_t *zone, dns_rdataset_t *value, catz_process_zones_suboption(dns_catz_zone_t *zone, dns_rdataset_t *value,
dns_label_t *mhash, dns_name_t *name); 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 * 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 *nentry = NULL;
dns_catz_entry_t *oentry = NULL; dns_catz_entry_t *oentry = NULL;
dns_zone_t *zone = NULL;
unsigned char *key = NULL; unsigned char *key = NULL;
size_t keysize; size_t keysize;
delcur = false; 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, result = isc_ht_find(target->entries, key, (uint32_t)keysize,
(void **)&oentry); (void **)&oentry);
if (result != ISC_R_SUCCESS) { if (result != ISC_R_SUCCESS) {
result = isc_ht_add(toadd, key, (uint32_t)keysize, catz_entry_add_or_mod(target, toadd, key, keysize,
nentry); nentry, NULL, "adding", zname,
if (result != ISC_R_SUCCESS) { czname);
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));
}
continue; continue;
} }
if (dns_catz_entry_cmp(oentry, nentry) != true) { result = dns_zt_find(target->catzs->view->zonetable,
result = isc_ht_add(tomod, key, (uint32_t)keysize, dns_catz_entry_getname(nentry), 0, NULL,
nentry); &zone);
if (result != ISC_R_SUCCESS) { if (result != ISC_R_SUCCESS) {
isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL, isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
DNS_LOGMODULE_MASTER, DNS_LOGMODULE_MASTER, ISC_LOG_DEBUG(3),
ISC_LOG_ERROR, "catz: zone '%s' was expected to exist "
"catz: error modifying zone '%s' " "but can not be found, will be restored",
"from catalog '%s' - %s", zname);
zname, czname, catz_entry_add_or_mod(target, toadd, key, keysize,
isc_result_totext(result)); 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); RUNTIME_CHECK(result == ISC_R_NOMORE);
isc_ht_iter_destroy(&iter1); 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); 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 static isc_result_t
catz_process_value(dns_catz_zone_t *zone, dns_name_t *name, catz_process_value(dns_catz_zone_t *zone, dns_name_t *name,
dns_rdataset_t *rdataset) { dns_rdataset_t *rdataset) {