]> git.ipfire.org Git - thirdparty/unbound.git/commitdiff
- rpz-zone-load, optimise rpz_insert_local_zones_trigger to remove second
authorW.C.A. Wijngaards <wouter@nlnetlabs.nl>
Wed, 28 Jan 2026 10:48:53 +0000 (11:48 +0100)
committerW.C.A. Wijngaards <wouter@nlnetlabs.nl>
Wed, 28 Jan 2026 10:48:53 +0000 (11:48 +0100)
  local zones tree lookup for non local data cases.

daemon/remote.c
libunbound/libunbound.c
services/localzone.c
services/localzone.h
services/rpz.c
testcode/unitmain.c

index 702aa5f4e29ebbf72d3111a96867f8060fa729c7..8600a996576fa54b2b5cf0bc6f9372b1d6d5dc55 100644 (file)
@@ -1339,7 +1339,7 @@ perform_zone_add(RES* ssl, struct local_zones* zones, char* arg)
                return 1;
        }
        if(!local_zones_add_zone(zones, nm, nmlen,
-               nmlabs, LDNS_RR_CLASS_IN, t)) {
+               nmlabs, LDNS_RR_CLASS_IN, t, NULL)) {
                lock_rw_unlock(&zones->lock);
                ssl_printf(ssl, "error out of memory\n");
                return 0;
index 9c6a3e309717076e3f895e2336c48f818d816d30..673ad6ec86fa7875c3a2b045529060d1fb7ca87e 100644 (file)
@@ -1385,7 +1385,7 @@ int ub_ctx_zone_add(struct ub_ctx* ctx, const char *zone_name,
                return UB_NOERROR;
        }
        if(!local_zones_add_zone(ctx->local_zones, nm, nmlen, nmlabs, 
-               LDNS_RR_CLASS_IN, t)) {
+               LDNS_RR_CLASS_IN, t, NULL)) {
                lock_rw_unlock(&ctx->local_zones->lock);
                return UB_NOMEM;
        }
index 867e0c47cc68da160474a37e5e947b7c555e7b9e..18d8a64f0ba3dffb06e998dde02f30c26055a1ff 100644 (file)
@@ -2231,7 +2231,7 @@ set_kiddo_parents(struct local_zone* z, struct local_zone* match,
 
 struct local_zone* local_zones_add_zone(struct local_zones* zones,
        uint8_t* name, size_t len, int labs, uint16_t dclass,
-       enum localzone_type tp)
+       enum localzone_type tp, int* duplicate)
 {
        int exact;
        /* create */
@@ -2239,6 +2239,7 @@ struct local_zone* local_zones_add_zone(struct local_zones* zones,
        struct local_zone* z = local_zone_create(name, len, labs, tp, dclass);
        if(!z) {
                free(name);
+               if(duplicate) *duplicate = 0;
                return NULL;
        }
        lock_rw_wrlock(&z->lock);
@@ -2252,8 +2253,14 @@ struct local_zone* local_zones_add_zone(struct local_zones* zones,
        if(exact||!rbtree_insert(&zones->ztree, &z->node)) {
                /* duplicate entry! */
                lock_rw_unlock(&z->lock);
+               if(duplicate) {
+                       *duplicate = 1;
+                       z->name = NULL; /* Do not delete the name in
+                               local_zone_delete. */
+               }
                local_zone_delete(z);
-               log_err("internal: duplicate entry in local_zones_add_zone");
+               if(duplicate == NULL)
+                       log_err("internal: duplicate entry in local_zones_add_zone");
                return NULL;
        }
 
@@ -2297,7 +2304,7 @@ local_zones_add_RR(struct local_zones* zones, const char* rr)
        z = local_zones_lookup(zones, rr_name, len, labs, rr_class, rr_type);
        if(!z) {
                z = local_zones_add_zone(zones, rr_name, len, labs, rr_class,
-                       local_zone_transparent);
+                       local_zone_transparent, NULL);
                if(!z) {
                        lock_rw_unlock(&zones->lock);
                        return 0;
index 6c5db2fb95ffe9f1a72243fb9ee01a651f27be9e..611185a00187e55e9db8560ef491d61a161241f8 100644 (file)
@@ -403,11 +403,17 @@ local_zones_find_le(struct local_zones* zones,
  * @param labs: labelcount of name.
  * @param dclass: class to add.
  * @param tp: type.
+ * @param duplicate: Allows to check if a NULL return from the function is a
+ *     memory error, or a duplicate entry. Pass NULL to have it not returned,
+ *     the name is freed on errors, and for a duplicate a log message is
+ *     printed. Pass not NULL, and when the error is a duplicate, the function
+ *     returns NULL, and the variable is set true. The name is not freed
+ *     when there is a duplicate, no error is printed by this function.
  * @return local_zone or NULL on error, caller must printout memory error.
  */
 struct local_zone* local_zones_add_zone(struct local_zones* zones, 
        uint8_t* name, size_t len, int labs, uint16_t dclass, 
-       enum localzone_type tp);
+       enum localzone_type tp, int* duplicate);
 
 /**
  * Delete a zone. Caller must hold the zones lock.
index cc8e663a2929eaef2bcd19bcd5bf39f3939d3928..43ae97328239d6fa6ee4e4d858d0d49bdfc17129 100644 (file)
@@ -698,6 +698,34 @@ rpz_insert_local_zones_trigger(struct local_zones* lz, uint8_t* dname,
                return;
        }
 
+       /* For not a local-data action.
+        * Insert the zone, then detect a duplicate, instead of find it first,
+        * for speed of searching the tree once. */
+       if(a != RPZ_LOCAL_DATA_ACTION) {
+               int duplicate = 0;
+               lock_rw_wrlock(&lz->lock);
+               tp = rpz_action_to_localzone_type(a);
+               z = local_zones_add_zone(lz, dname, dnamelen,
+                                        dnamelabs, rrclass, tp, &duplicate);
+               if(z == NULL) {
+                       if(duplicate) {
+                               char* rrstr = dname_rdata_to_str(dname, dnamelen, rrtype,
+                                       rrclass, ttl, rdata, rdata_len);
+                               verbose(VERB_ALGO, "rpz: skipping duplicate record: %s", rrstr);
+                               free(rrstr);
+                               free(dname);
+                               lock_rw_unlock(&lz->lock);
+                               return;
+                       }
+                       log_warn("rpz: create failed, out of memory");
+                       lock_rw_unlock(&lz->lock);
+                       /* dname will be free'd in failed local_zone_create() */
+                       return;
+               }
+               lock_rw_unlock(&lz->lock);
+               return;
+       }
+
        lock_rw_wrlock(&lz->lock);
        /* exact match */
        z = local_zones_find(lz, dname, dnamelen, dnamelabs, LDNS_RR_CLASS_IN);
@@ -713,7 +741,7 @@ rpz_insert_local_zones_trigger(struct local_zones* lz, uint8_t* dname,
        if(z == NULL) {
                tp = rpz_action_to_localzone_type(a);
                z = local_zones_add_zone(lz, dname, dnamelen,
-                                        dnamelabs, rrclass, tp);
+                                        dnamelabs, rrclass, tp, NULL);
                if(z == NULL) {
                        log_warn("rpz: create failed");
                        lock_rw_unlock(&lz->lock);
index 79ce45f395598da3a0f3f7c683919b77ba8f20e7..bbbf6750b69489ca85213955392610fb2df26aa6 100644 (file)
@@ -1265,7 +1265,7 @@ static void localzone_parents_test(void)
                nmlabs = dname_count_size_labels(nm, &nmlen);
                lock_rw_wrlock(&z2->lock);
                local_zones_add_zone(z2, nm, nmlen, nmlabs, LDNS_RR_CLASS_IN,
-                       local_zone_always_nxdomain);
+                       local_zone_always_nxdomain, NULL);
                lock_rw_unlock(&z2->lock);
        }
        /* The trees should be the same, iterate and check the nodes */