A. Schulze via Unbound-users:

Am 14.02.2017 um 15:00 schrieb W.C.A. Wijngaards via Unbound-users:
Unbound 1.6.1rc3 is available:

compiled Debian Jessie+Stretch without warnings.
"log-replies:yes" is cool :-)

Now, some days later, I like to announce the rc3 not only compile but also run fine:-)
Work without problems on my testlab systems...

On note:
I included again a patch that implement nsec_aggressiveuse [1]
Works as expected but only for nsec, not nsec3.

Andreas

[1] https://tools.ietf.org/html/draft-ietf-dnsop-nsec-aggressiveuse-07
Description: enable aggressive nsec use for nxdomain
URL: http://member.wide.ad.jp/~fujiwara/files/unbound.diff
Author: Fujiwara
---
This patch header follows DEP-3: http://dep.debian.net/deps/dep3/
Index: unbound-1.6.1~rc3/validator/val_neg.c
===================================================================
--- unbound-1.6.1~rc3.orig/validator/val_neg.c
+++ unbound-1.6.1~rc3/validator/val_neg.c
@@ -927,6 +927,107 @@ static int neg_closest_data(struct val_n
 	}
 }
 
+struct packed_rrset_data* val_neg_lookup(struct val_neg_cache* neg, uint8_t* qname, size_t len,
+        uint16_t qtype, uint16_t qclass, struct rrset_cache* rrset_cache, time_t now)
+{
+	/* lookup closest zone */
+	struct val_neg_zone* zone;
+	struct val_neg_data* data;
+	int labs;
+	struct ub_packed_rrset_key* nsec;
+	struct packed_rrset_data* d;
+	uint32_t flags;
+	uint8_t* wc;
+	struct query_info qinfo;
+	if(!neg) return NULL;
+
+	log_nametypeclass(VERB_ALGO, "negcache lookup", qname,
+		qtype, qclass);
+
+	labs = dname_count_labels(qname);
+	lock_basic_lock(&neg->lock);
+	zone = neg_closest_zone_parent(neg, qname, len, labs, qclass);
+	while(zone && !zone->in_use)
+		zone = zone->parent;
+	if(!zone) {
+		lock_basic_unlock(&neg->lock);
+		return NULL;
+	}
+	log_nametypeclass(VERB_ALGO, "negcache zone", zone->name, 0,
+		zone->dclass);
+
+	/* DLV is defined to use NSEC only */
+	if(zone->nsec3_hash) {
+		lock_basic_unlock(&neg->lock);
+		return NULL;
+	}
+
+	/* lookup closest data record */
+	(void)neg_closest_data(zone, qname, len, labs, &data);
+	while(data && !data->in_use)
+		data = data->parent;
+	if(!data) {
+		lock_basic_unlock(&neg->lock);
+		return NULL;
+	}
+	log_nametypeclass(VERB_ALGO, "negcache rr", data->name,
+		LDNS_RR_TYPE_NSEC, zone->dclass);
+
+	/* lookup rrset in rrset cache */
+	flags = 0;
+	if(query_dname_compare(data->name, zone->name) == 0)
+		flags = PACKED_RRSET_NSEC_AT_APEX;
+	nsec = rrset_cache_lookup(rrset_cache, data->name, data->len,
+		LDNS_RR_TYPE_NSEC, zone->dclass, flags, now, 0);
+
+	/* check if secure and TTL ok */
+	if(!nsec) {
+		lock_basic_unlock(&neg->lock);
+		return NULL;
+	}
+	d = (struct packed_rrset_data*)nsec->entry.data;
+	if(!d || now > d->ttl) {
+		lock_rw_unlock(&nsec->entry.lock);
+		/* delete data record if expired */
+		neg_delete_data(neg, data);
+		lock_basic_unlock(&neg->lock);
+		return NULL;
+	}
+	if(d->security != sec_status_secure) {
+		lock_rw_unlock(&nsec->entry.lock);
+		neg_delete_data(neg, data);
+		lock_basic_unlock(&neg->lock);
+		return NULL;
+	}
+	verbose(VERB_ALGO, "negcache got secure rrset");
+
+	/* check NSEC security */
+	/* check if NSEC proves no DLV type exists */
+	/* check if NSEC proves NXDOMAIN for qname */
+	qinfo.qname = qname;
+	qinfo.qtype = qtype;
+	qinfo.qclass = qclass;
+	if(!nsec_proves_nodata(nsec, &qinfo, &wc) &&
+		!val_nsec_proves_name_error(nsec, qname)) {
+		/* the NSEC is not a denial for the DLV */
+		lock_rw_unlock(&nsec->entry.lock);
+		lock_basic_unlock(&neg->lock);
+		verbose(VERB_ALGO, "negcache not proven");
+		return NULL;
+	}
+	/* so the NSEC was a NODATA proof, or NXDOMAIN proof. */
+
+	/* no need to check for wildcard NSEC; no wildcards in DLV repos */
+	/* no need to lookup SOA record for client; no response message */
+
+	lock_rw_unlock(&nsec->entry.lock);
+	/* if OK touch the LRU for neg_data element */
+	neg_lru_touch(neg, data);
+	lock_basic_unlock(&neg->lock);
+	verbose(VERB_ALGO, "negcache denial proven");
+	return nsec;
+}
+
 int val_neg_dlvlookup(struct val_neg_cache* neg, uint8_t* qname, size_t len,
         uint16_t qclass, struct rrset_cache* rrset_cache, time_t now)
 {
Index: unbound-1.6.1~rc3/validator/val_neg.h
===================================================================
--- unbound-1.6.1~rc3.orig/validator/val_neg.h
+++ unbound-1.6.1~rc3/validator/val_neg.h
@@ -231,6 +231,8 @@ void val_neg_addreferral(struct val_neg_
  */
 int val_neg_dlvlookup(struct val_neg_cache* neg, uint8_t* qname, size_t len,
 	uint16_t qclass, struct rrset_cache* rrset_cache, time_t now);
+struct packed_rrset_data* val_neg_lookup(struct val_neg_cache* neg, uint8_t* qname, size_t len,
+	uint16_t qtype, uint16_t qclass, struct rrset_cache* rrset_cache, time_t now);
 
 /**
  * For the given query, try to get a reply out of the negative cache.
Index: unbound-1.6.1~rc3/validator/validator.c
===================================================================
--- unbound-1.6.1~rc3.orig/validator/validator.c
+++ unbound-1.6.1~rc3/validator/validator.c
@@ -919,6 +919,9 @@ validate_nameerror_response(struct modul
 	/* Otherwise, we consider the message secure. */
 	verbose(VERB_ALGO, "successfully validated NAME ERROR response.");
 	chase_reply->security = sec_status_secure;
+
+	/* store NSECs into negative cache */
+	val_neg_addreply(ve->neg_cache, chase_reply);
 }
 
 /** 
@@ -2271,6 +2274,8 @@ val_operate(struct module_qstate* qstate
 {
 	struct val_env* ve = (struct val_env*)qstate->env->modinfo[id];
 	struct val_qstate* vq = (struct val_qstate*)qstate->minfo[id];
+	struct packed_rrset_data* nsec;
+
 	verbose(VERB_QUERY, "validator[module %d] operate: extstate:%s "
 		"event:%s", id, strextstate(qstate->ext_state[id]), 
 		strmodulevent(event));
@@ -2283,6 +2288,19 @@ val_operate(struct module_qstate* qstate
 	if(event == module_event_new || 
 		(event == module_event_pass && vq == NULL)) {
 
+		nsec = val_neg_lookup(ve->neg_cache, qstate->qinfo.qname,
+			qstate->qinfo.qname_len, qstate->qinfo.qtype,
+			qstate->qinfo.qclass,
+			qstate->env->rrset_cache, *qstate->env->now);
+
+		/* Aggressive NSEC caching */
+		if (nsec != NULL) {
+			qstate->return_rcode = LDNS_RCODE_NXDOMAIN;
+			qstate->return_msg = NULL;
+			qstate->ext_state[id] = module_finished;
+			return;
+		}
+
 		/* pass request to next module, to get it */
 		verbose(VERB_ALGO, "validator: pass to next module");
 		qstate->ext_state[id] = module_wait_module;

Reply via email to