]> git.ipfire.org Git - thirdparty/unbound.git/commitdiff
- Delete auth zone when removed from config.
authorWouter Wijngaards <wouter@nlnetlabs.nl>
Fri, 20 Apr 2018 14:40:07 +0000 (14:40 +0000)
committerWouter Wijngaards <wouter@nlnetlabs.nl>
Fri, 20 Apr 2018 14:40:07 +0000 (14:40 +0000)
git-svn-id: file:///svn/unbound/trunk@4642 be551aaa-1e26-0410-a405-d3ace91eadb9

doc/Changelog
services/authzone.c
services/authzone.h

index 452e4d31b4613cf87baecab3238a1b716bd886a1..b0cd34da4ad765604009db65f3ae5a74cc675234 100644 (file)
@@ -3,6 +3,7 @@
        - removed free from failed parse case.
        - Fix #4091: Fix that reload of auth-zone does not merge the zonefile
          with the previous contents.
+       - Delete auth zone when removed from config.
 
 19 April 2018: Wouter
        - Can set tls authentication with forward-addr: IP#tls.auth.name
index 56c4065a4da6a459ac688a07f57e8a5cfa500256..8c3259fc859ce7c36e63c8283dc78f40425e8103 100644 (file)
@@ -99,6 +99,8 @@ static void xfr_probe_send_or_end(struct auth_xfer* xfr,
  * or transfer task if nothing to probe, or false if already in progress */
 static int xfr_start_probe(struct auth_xfer* xfr, struct module_env* env,
        struct auth_master* spec);
+/** delete xfer structure (not its tree entry) */
+void auth_xfer_delete(struct auth_xfer* xfr);
 
 /** create new dns_msg */
 static struct dns_msg*
@@ -1827,6 +1829,7 @@ auth_zones_cfg(struct auth_zones* az, struct config_auth* c)
        lock_rw_unlock(&az->lock);
 
        /* set options */
+       z->zone_deleted = 0;
        if(!auth_zone_set_zonefile(z, c->zonefile)) {
                if(x) {
                        lock_basic_unlock(&x->lock);
@@ -1859,10 +1862,65 @@ auth_zones_cfg(struct auth_zones* az, struct config_auth* c)
        return 1;
 }
 
+/** set all auth zones deleted, then in auth_zones_cfg, it marks them
+ * as nondeleted (if they are still in the config), and then later
+ * we can find deleted zones */
+static void
+az_setall_deleted(struct auth_zones* az)
+{
+       struct auth_zone* z;
+       lock_rw_wrlock(&az->lock);
+       RBTREE_FOR(z, struct auth_zone*, &az->ztree) {
+               lock_rw_wrlock(&z->lock);
+               z->zone_deleted = 1;
+               lock_rw_unlock(&z->lock);
+       }
+       lock_rw_unlock(&az->lock);
+}
+
+/** find zones that are marked deleted and delete them.
+ * This is called from apply_cfg, and there are no threads and no
+ * workers, so the xfr can just be deleted. */
+static void
+az_delete_deleted_zones(struct auth_zones* az)
+{
+       struct auth_zone* z;
+       struct auth_zone* delete_list = NULL, *next;
+       struct auth_xfer* xfr;
+       lock_rw_wrlock(&az->lock);
+       RBTREE_FOR(z, struct auth_zone*, &az->ztree) {
+               lock_rw_wrlock(&z->lock);
+               if(z->zone_deleted) {
+                       /* we cannot alter the rbtree right now, but
+                        * we can put it on a linked list and then
+                        * delete it */
+                       z->delete_next = delete_list;
+                       delete_list = z;
+               }
+               lock_rw_unlock(&z->lock);
+       }
+       /* now we are out of the tree loop and we can loop and delete
+        * the zones */
+       z = delete_list;
+       while(z) {
+               next = z->delete_next;
+               xfr = auth_xfer_find(az, z->name, z->namelen, z->dclass);
+               if(xfr) {
+                       (void)rbtree_delete(&az->xtree, &xfr->node);
+                       auth_xfer_delete(xfr);
+               }
+               (void)rbtree_delete(&az->ztree, &z->node);
+               auth_zone_delete(z);
+               z = next;
+       }
+       lock_rw_unlock(&az->lock);
+}
+
 int auth_zones_apply_cfg(struct auth_zones* az, struct config_file* cfg,
        int setup)
 {
        struct config_auth* p;
+       az_setall_deleted(az);
        for(p = cfg->auths; p; p = p->next) {
                if(!p->name || p->name[0] == 0) {
                        log_warn("auth-zone without a name, skipped");
@@ -1873,6 +1931,7 @@ int auth_zones_apply_cfg(struct auth_zones* az, struct config_file* cfg,
                        return 0;
                }
        }
+       az_delete_deleted_zones(az);
        if(!auth_zones_read_zones(az))
                return 0;
        if(setup) {
index b57a5fcec383252564f1e2b681a0643ae7c2db07..8de18bf7311b2f2fc4158e8e6acda9e2d2bd374d 100644 (file)
@@ -126,6 +126,10 @@ struct auth_zone {
        /** for upstream: this zone answers queries that unbound intends to
         * send upstream. */
        int for_upstream;
+       /** zone has been deleted */
+       int zone_deleted;
+       /** deletelist pointer, unused normally except during delete */
+       struct auth_zone* delete_next;
 };
 
 /**