diff --git a/lib/dns/include/dns/rpz.h b/lib/dns/include/dns/rpz.h index 0c403d8a9e..b4c0c19b55 100644 --- a/lib/dns/include/dns/rpz.h +++ b/lib/dns/include/dns/rpz.h @@ -247,6 +247,7 @@ struct dns_rpz_zones { isc_timermgr_t *timermgr; isc_task_t *updater; isc_refcount_t refs; + isc_refcount_t irefs; /* * One lock for short term read-only search that guarantees the * consistency of the pointers. diff --git a/lib/dns/rpz.c b/lib/dns/rpz.c index b5763fab0a..391ea070d9 100644 --- a/lib/dns/rpz.c +++ b/lib/dns/rpz.c @@ -170,7 +170,10 @@ struct dns_rpz_nm_data { }; static void -rpz_detach(dns_rpz_zone_t **rpzp, dns_rpz_zones_t *rpzs); +rpz_detach(dns_rpz_zone_t **rpzp); + +static void +rpz_detach_rpzs(dns_rpz_zones_t **rpzsp); #if 0 /* @@ -1447,6 +1450,7 @@ dns_rpz_new_zones(dns_rpz_zones_t **rpzsp, char *rps_cstr, isc_mutex_init(&zones->maint_lock); isc_refcount_init(&zones->refs, 1); + isc_refcount_init(&zones->irefs, 1); zones->rps_cstr = rps_cstr; zones->rps_cstr_size = rps_cstr_size; @@ -1480,7 +1484,9 @@ cleanup_task: dns_rbt_destroy(&zones->rbt); cleanup_rbt: - INSIST(isc_refcount_decrement(&zones->refs) > 0); + INSIST(isc_refcount_decrement(&zones->irefs) == 1); + isc_refcount_destroy(&zones->irefs); + INSIST(isc_refcount_decrement(&zones->refs) == 1); isc_refcount_destroy(&zones->refs); isc_mutex_destroy(&zones->maint_lock); @@ -1543,6 +1549,7 @@ dns_rpz_new_zone(dns_rpz_zones_t *rpzs, dns_rpz_zone_t **rpzp) { zone->updb = NULL; zone->updbversion = NULL; zone->updbit = NULL; + isc_refcount_increment(&rpzs->irefs); zone->rpzs = rpzs; zone->db_registered = false; zone->addsoa = true; @@ -1563,7 +1570,7 @@ cleanup_timer: INSIST(isc_refcount_decrement(&zone->refs) > 0); isc_refcount_destroy(&zone->refs); - isc_mem_put(zone->rpzs->mctx, zone, sizeof(*zone)); + isc_mem_put(rpzs->mctx, zone, sizeof(*zone)); return (result); } @@ -1983,7 +1990,7 @@ update_quantum(isc_task_t *task, isc_event_t *event) { isc_ht_destroy(&rpz->newnodes); dns_db_closeversion(rpz->updb, &rpz->updbversion, false); dns_db_detach(&rpz->updb); - rpz_detach(&rpz, rpz->rpzs); + rpz_detach(&rpz); } static void @@ -2023,7 +2030,7 @@ dns_rpz_update_from_db(dns_rpz_zone_t *rpz) { isc_ht_destroy(&rpz->newnodes); dns_db_closeversion(rpz->updb, &rpz->updbversion, false); dns_db_detach(&rpz->updb); - rpz_detach(&rpz, rpz->rpzs); + rpz_detach(&rpz); } /* @@ -2063,8 +2070,9 @@ cidr_free(dns_rpz_zones_t *rpzs) { * before discarding the overall rpz structure. */ static void -rpz_detach(dns_rpz_zone_t **rpzp, dns_rpz_zones_t *rpzs) { +rpz_detach(dns_rpz_zone_t **rpzp) { dns_rpz_zone_t *rpz; + dns_rpz_zones_t *rpzs; REQUIRE(rpzp != NULL && *rpzp != NULL); @@ -2077,6 +2085,9 @@ rpz_detach(dns_rpz_zone_t **rpzp, dns_rpz_zones_t *rpzs) { isc_refcount_destroy(&rpz->refs); + rpzs = rpz->rpzs; + rpz->rpzs = NULL; + if (dns_name_dynamic(&rpz->origin)) { dns_name_free(&rpz->origin, rpzs->mctx); } @@ -2129,7 +2140,9 @@ rpz_detach(dns_rpz_zone_t **rpzp, dns_rpz_zones_t *rpzs) { isc_timer_detach(&rpz->updatetimer); isc_ht_destroy(&rpz->nodes); + isc_mem_put(rpzs->mctx, rpz, sizeof(*rpz)); + rpz_detach_rpzs(&rpzs); } void @@ -2166,10 +2179,20 @@ dns_rpz_detach_rpzs(dns_rpz_zones_t **rpzsp) { dns_rpz_zone_t *rpz = rpzs->zones[rpz_num]; rpzs->zones[rpz_num] = NULL; if (rpz != NULL) { - rpz_detach(&rpz, rpzs); + rpz_detach(&rpz); } } + rpz_detach_rpzs(&rpzs); + } +} +static void +rpz_detach_rpzs(dns_rpz_zones_t **rpzsp) { + REQUIRE(rpzsp != NULL && *rpzsp != NULL); + dns_rpz_zones_t *rpzs = *rpzsp; + *rpzsp = NULL; + + if (isc_refcount_decrement(&rpzs->irefs) == 1) { if (rpzs->rps_cstr_size != 0) { #ifdef USE_DNSRPS librpz->client_detach(&rpzs->rps_client);