struct val_neg_zone* parent)
{
int i;
- int tolabs = parent?parent->labs:-1;
+ int tolabs = parent?parent->labs:0;
struct val_neg_zone* zone, *prev = NULL, *first = NULL;
/* create the new subtree, i is labelcount of current creation */
uint8_t* nm, size_t nm_len, int labs, struct val_neg_data* parent)
{
int i;
- int tolabs = parent?parent->labs:-1;
+ int tolabs = parent?parent->labs:0;
struct val_neg_data* el, *first = NULL, *prev = NULL;
/* create the new subtree, i is labelcount of current creation */
}
walk = rbtree_next(&el->node);
- while( walk ) {
+ while(walk && walk != RBTREE_NULL) {
cur = (struct val_neg_data*)walk;
/* sanity check: must be larger than start */
- if(dname_canon_lab_cmp(el->name, el->labs,
- cur->name, cur->labs, &m) <= 0) {
+ if(dname_canon_lab_cmp(cur->name, cur->labs,
+ el->name, el->labs, &m) <= 0) {
/* r == 0 skip original record. */
/* r < 0 too small! */
walk = rbtree_next(walk);
d = (struct packed_rrset_data*)nsec->entry.data;
if(d->security != sec_status_secure)
return;
+ log_nametypeclass(VERB_ALGO, "negcache rr",
+ nsec->rk.dname, LDNS_RR_TYPE_NSEC, ntohs(nsec->rk.rrset_class));
/* find closest enclosing parent data that (still) exists */
parent = neg_closest_data_parent(zone, nm, nm_len, labs);
/* mem use */
neg->use += sizeof(struct val_neg_data) + p->len;
/* insert in tree */
+ p->zone = zone;
(void)rbtree_insert(&zone->tree, &p->node);
/* last one needs proper parent pointer */
if(np == NULL)
if(!soa)
return;
+ log_nametypeclass(VERB_ALGO, "negcache insert for zone",
+ soa->rk.dname, LDNS_RR_TYPE_SOA, ntohs(soa->rk.rrset_class));
+
/* ask for enough space to store all of it */
need = calc_data_need(rep) + calc_zone_need(soa);
lock_basic_lock(&neg->lock);
uint8_t* wc;
struct query_info qinfo;
if(!neg) return 0;
+
+ log_nametypeclass(VERB_ALGO, "negcache dlvlookup", qname,
+ LDNS_RR_TYPE_DLV, qclass);
labs = dname_count_labels(qname);
lock_basic_lock(&neg->lock);
lock_basic_unlock(&neg->lock);
return 0;
}
+ log_nametypeclass(VERB_ALGO, "negcache zone", zone->name, 0,
+ zone->dclass);
/* lookup closest data record */
(void)neg_closest_data(zone, qname, len, labs, &data);
lock_basic_unlock(&neg->lock);
return 0;
}
+ log_nametypeclass(VERB_ALGO, "negcache rr", data->name,
+ LDNS_RR_TYPE_NSEC, zone->dclass);
/* lookup rrset in rrset cache */
flags = 0;
return 0;
}
d = (struct packed_rrset_data*)nsec->entry.data;
- if(!d || d->ttl > now) {
+ 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 0;
}
+ verbose(VERB_ALGO, "negcache got secure rrset");
/* check NSEC security */
/* check if NSEC proves no DLV type exists */
/* 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 0;
}
/* so the NSEC was a NODATA proof, or NXDOMAIN proof. */
/* if OK touch the LRU for neg_data element */
neg_lru_touch(neg, data);
lock_basic_unlock(&neg->lock);
- return 0;
+ verbose(VERB_ALGO, "negcache DLV denial proven");
+ return 1;
}
#include "validator/val_utils.h"
#include "validator/val_nsec.h"
#include "validator/val_nsec3.h"
+#include "validator/val_neg.h"
#include "services/cache/dns.h"
#include "util/data/dname.h"
#include "util/module.h"
log_err("validator: error in trustanchors config");
return 0;
}
+ if(!val_env->neg_cache)
+ val_env->neg_cache = val_neg_create();
+ if(!val_env->neg_cache) {
+ log_err("out of memory");
+ return 0;
+ }
+ if(!val_neg_apply_cfg(val_env->neg_cache, cfg)) {
+ log_err("validator: error in negative cache config");
+ return 0;
+ }
val_env->date_override = cfg->val_date_override;
c = cfg_count_numbers(cfg->val_nsec3_key_iterations);
if(c < 1 || (c&1)) {
anchors_delete(env->anchors);
env->anchors = NULL;
key_cache_delete(val_env->kcache);
+ neg_cache_delete(val_env->neg_cache);
free(val_env->nsec3_keysize);
free(val_env->nsec3_maxiter);
free(val_env);
/* If we can find the name in the aggressive negative cache,
* give up; insecure is the answer */
- /* lookup, several places in the tree may qualify
- * between insecure_at and the lookup_name
- * Check proof thoroughly
- * TODO
- * return 1;
- */
+ if(val_neg_dlvlookup(ve->neg_cache, vq->dlv_lookup_name,
+ vq->dlv_lookup_name_len, vq->qchase.qclass,
+ qstate->env->rrset_cache, *qstate->env->now)) {
+ return 1;
+ }
/* perform a lookup for the DLV; with validation */
vq->state = VAL_DLVLOOKUP_STATE;
return 1;
}
+ /* check negative cache before making new request */
+ if(val_neg_dlvlookup(ve->neg_cache, vq->dlv_lookup_name,
+ vq->dlv_lookup_name_len, vq->qchase.qclass,
+ qstate->env->rrset_cache, *qstate->env->now)) {
+ vq->dlv_status = dlv_there_is_no_dlv;
+ /* continue with the insecure result we got */
+ vq->state = VAL_FINISHED_STATE;
+ return 1;
+ }
+
if(!generate_request(qstate, id, vq->dlv_lookup_name,
vq->dlv_lookup_name_len, LDNS_RR_TYPE_DLV,
vq->qchase.qclass, 0)) {
vq->dlv_status = dlv_success;
return;
}
+ /* store NSECs into negative cache */
+ val_neg_addreply(ve->neg_cache, msg->rep);
/* was the lookup a failure?
* if we have to go up into the DLV for a higher DLV anchor
if(!ve)
return 0;
return sizeof(*ve) + key_cache_get_mem(ve->kcache) +
+ val_neg_get_mem(ve->neg_cache) +
anchors_get_mem(env->anchors) +
sizeof(size_t)*2*ve->nsec3_keyiter_count;
}