local zones tree lookup for non local data cases.
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;
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;
}
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 */
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);
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;
}
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;
* @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.
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);
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);
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 */