]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
keep rpzs around until everything referencing it has gone
authorMark Andrews <marka@isc.org>
Thu, 1 Aug 2019 01:15:05 +0000 (11:15 +1000)
committerMark Andrews <marka@isc.org>
Thu, 1 Aug 2019 01:15:05 +0000 (11:15 +1000)
lib/dns/include/dns/rpz.h
lib/dns/rpz.c

index 0c403d8a9e27fe22c2cc612a779c0b7d9e57ae25..b4c0c19b55fe6c179c9bd9620184bdf52ab3584d 100644 (file)
@@ -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.
index b5763fab0a9504b14fdf688e3d71376c752fd243..391ea070d9ccccc9331bdf21adee5c338e4fcb4f 100644 (file)
@@ -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);