auth_zone_delegpt(struct module_qstate* qstate, struct iter_qstate* iq,
	uint8_t* delname, size_t delnamelen)
{
	struct auth_zone* z;
	if(iq->auth_zone_avoid)
		return 1;
	if(!delname) {
		delname = iq->qchase.qname;
		delnamelen = iq->qchase.qname_len;
	}
	lock_rw_rdlock(&qstate->env->auth_zones->lock);
	z = auth_zones_find_zone(qstate->env->auth_zones, delname, delnamelen,
		qstate->qinfo.qclass);
	if(!z) {
		lock_rw_unlock(&qstate->env->auth_zones->lock);
		return 1;
	}
	lock_rw_rdlock(&z->lock);
	lock_rw_unlock(&qstate->env->auth_zones->lock);
	if(z->for_upstream) {
		if(iq->dp && query_dname_compare(z->name, iq->dp->name) == 0
			&& iq->dp->auth_dp && qstate->blacklist &&
			z->fallback_enabled) {
			/* cache is blacklisted and fallback, and we
			 * already have an auth_zone dp */
			if(verbosity>=VERB_ALGO) {
				char buf[255+1];
				dname_str(z->name, buf);
				verbose(VERB_ALGO, "auth_zone %s "
				  "fallback because cache blacklisted",
				  buf);
			}
			lock_rw_unlock(&z->lock);
			iq->dp = NULL;
			return 1;
		}
		if(iq->dp==NULL || dname_subdomain_c(z->name, iq->dp->name)) {
			struct delegpt* dp;
			if(qstate->blacklist && z->fallback_enabled) {
				/* cache is blacklisted because of a DNSSEC
				 * validation failure, and the zone allows
				 * fallback to the internet, query there. */
				if(verbosity>=VERB_ALGO) {
					char buf[255+1];
					dname_str(z->name, buf);
					verbose(VERB_ALGO, "auth_zone %s "
					  "fallback because cache blacklisted",
					  buf);
				}
				lock_rw_unlock(&z->lock);
				return 1;
			}
			dp = (struct delegpt*)regional_alloc_zero(
				qstate->region, sizeof(*dp));
			if(!dp) {
				log_err("alloc failure");
				if(z->fallback_enabled) {
					lock_rw_unlock(&z->lock);
					return 1; /* just fallback */
				}
				lock_rw_unlock(&z->lock);
				errinf(qstate, "malloc failure");
				return 0;
			}
			dp->name = regional_alloc_init(qstate->region,
				z->name, z->namelen);
			if(!dp->name) {
				log_err("alloc failure");
				if(z->fallback_enabled) {
					lock_rw_unlock(&z->lock);
					return 1; /* just fallback */
				}
				lock_rw_unlock(&z->lock);
				errinf(qstate, "malloc failure");
				return 0;
			}
			dp->namelen = z->namelen;
			dp->namelabs = z->namelabs;
			dp->auth_dp = 1;
			iq->dp = dp;
		}
	}

	lock_rw_unlock(&z->lock);
	return 1;
}
auth_zone_delegpt(struct module_qstate* qstate, struct iter_qstate* iq,
	uint8_t* delname, size_t delnamelen)
{
	struct auth_zone* z;
	if(iq->auth_zone_avoid)
		return 1;
	if(!delname) {
		delname = iq->qchase.qname;
		delnamelen = iq->qchase.qname_len;
	}
	lock_rw_rdlock(&qstate->env->auth_zones->lock);
	z = auth_zones_find_zone(qstate->env->auth_zones, delname, delnamelen,
		qstate->qinfo.qclass);
	if(!z) {
		lock_rw_unlock(&qstate->env->auth_zones->lock);
		return 1;
	}
	lock_rw_rdlock(&z->lock);
	lock_rw_unlock(&qstate->env->auth_zones->lock);
	if(z->for_upstream) {
		if(iq->dp && query_dname_compare(z->name, iq->dp->name) == 0
			&& iq->dp->auth_dp && qstate->blacklist &&
			z->fallback_enabled) {
			 
			if(verbosity>=VERB_ALGO) {
				char buf[255+1];
				dname_str(z->name, buf);
				verbose(VERB_ALGO, "auth_zone %s "
				  "fallback because cache blacklisted",
				  buf);
			}
			lock_rw_unlock(&z->lock);
			iq->dp = NULL;
			return 1;
		}
		if(iq->dp==NULL || dname_subdomain_c(z->name, iq->dp->name)) {
			struct delegpt* dp;
			if(qstate->blacklist && z->fallback_enabled) {
				 
				if(verbosity>=VERB_ALGO) {
					char buf[255+1];
					dname_str(z->name, buf);
					verbose(VERB_ALGO, "auth_zone %s "
					  "fallback because cache blacklisted",
					  buf);
				}
				lock_rw_unlock(&z->lock);
				return 1;
			}
			dp = (struct delegpt*)regional_alloc_zero(
				qstate->region, sizeof(*dp));
			if(!dp) {
				log_err("alloc failure");
				if(z->fallback_enabled) {
					lock_rw_unlock(&z->lock);
					return 1;  
				}
				lock_rw_unlock(&z->lock);
				errinf(qstate, "malloc failure");
				return 0;
			}
			dp->name = regional_alloc_init(qstate->region,
				z->name, z->namelen);
			if(!dp->name) {
				log_err("alloc failure");
				if(z->fallback_enabled) {
					lock_rw_unlock(&z->lock);
					return 1;  
				}
				lock_rw_unlock(&z->lock);
				errinf(qstate, "malloc failure");
				return 0;
			}
			dp->namelen = z->namelen;
			dp->namelabs = z->namelabs;
			dp->auth_dp = 1;
			iq->dp = dp;
		}
	}

	lock_rw_unlock(&z->lock);
	return 1;
}