DLV negative cache works.

git-svn-id: file:///svn/unbound/trunk@1200 be551aaa-1e26-0410-a405-d3ace91eadb9
This commit is contained in:
Wouter Wijngaards 2008-08-21 10:43:45 +00:00
parent a61d10f715
commit a39a7704af
4 changed files with 61 additions and 13 deletions

View file

@ -1,3 +1,7 @@
21 August 2008: Wouter
- negative cache code linked into validator, for DLV use.
negative cache works for DLV.
20 August 2008: Wouter 20 August 2008: Wouter
- negative cache code, reviewed. - negative cache code, reviewed.

View file

@ -464,7 +464,7 @@ static struct val_neg_zone* neg_zone_chain(
struct val_neg_zone* parent) struct val_neg_zone* parent)
{ {
int i; int i;
int tolabs = parent?parent->labs:-1; int tolabs = parent?parent->labs:0;
struct val_neg_zone* zone, *prev = NULL, *first = NULL; struct val_neg_zone* zone, *prev = NULL, *first = NULL;
/* create the new subtree, i is labelcount of current creation */ /* create the new subtree, i is labelcount of current creation */
@ -612,7 +612,7 @@ static struct val_neg_data* neg_data_chain(
uint8_t* nm, size_t nm_len, int labs, struct val_neg_data* parent) uint8_t* nm, size_t nm_len, int labs, struct val_neg_data* parent)
{ {
int i; int i;
int tolabs = parent?parent->labs:-1; int tolabs = parent?parent->labs:0;
struct val_neg_data* el, *first = NULL, *prev = NULL; struct val_neg_data* el, *first = NULL, *prev = NULL;
/* create the new subtree, i is labelcount of current creation */ /* create the new subtree, i is labelcount of current creation */
@ -680,11 +680,11 @@ static void wipeout(struct val_neg_cache* neg, struct val_neg_zone* zone,
} }
walk = rbtree_next(&el->node); walk = rbtree_next(&el->node);
while( walk ) { while(walk && walk != RBTREE_NULL) {
cur = (struct val_neg_data*)walk; cur = (struct val_neg_data*)walk;
/* sanity check: must be larger than start */ /* sanity check: must be larger than start */
if(dname_canon_lab_cmp(el->name, el->labs, if(dname_canon_lab_cmp(cur->name, cur->labs,
cur->name, cur->labs, &m) <= 0) { el->name, el->labs, &m) <= 0) {
/* r == 0 skip original record. */ /* r == 0 skip original record. */
/* r < 0 too small! */ /* r < 0 too small! */
walk = rbtree_next(walk); walk = rbtree_next(walk);
@ -738,6 +738,8 @@ static void neg_insert_data(struct val_neg_cache* neg,
d = (struct packed_rrset_data*)nsec->entry.data; d = (struct packed_rrset_data*)nsec->entry.data;
if(d->security != sec_status_secure) if(d->security != sec_status_secure)
return; 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 */ /* find closest enclosing parent data that (still) exists */
parent = neg_closest_data_parent(zone, nm, nm_len, labs); parent = neg_closest_data_parent(zone, nm, nm_len, labs);
@ -766,6 +768,7 @@ static void neg_insert_data(struct val_neg_cache* neg,
/* mem use */ /* mem use */
neg->use += sizeof(struct val_neg_data) + p->len; neg->use += sizeof(struct val_neg_data) + p->len;
/* insert in tree */ /* insert in tree */
p->zone = zone;
(void)rbtree_insert(&zone->tree, &p->node); (void)rbtree_insert(&zone->tree, &p->node);
/* last one needs proper parent pointer */ /* last one needs proper parent pointer */
if(np == NULL) if(np == NULL)
@ -806,6 +809,9 @@ void val_neg_addreply(struct val_neg_cache* neg, struct reply_info* rep)
if(!soa) if(!soa)
return; 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 */ /* ask for enough space to store all of it */
need = calc_data_need(rep) + calc_zone_need(soa); need = calc_data_need(rep) + calc_zone_need(soa);
lock_basic_lock(&neg->lock); lock_basic_lock(&neg->lock);
@ -875,6 +881,9 @@ int val_neg_dlvlookup(struct val_neg_cache* neg, uint8_t* qname, size_t len,
uint8_t* wc; uint8_t* wc;
struct query_info qinfo; struct query_info qinfo;
if(!neg) return 0; if(!neg) return 0;
log_nametypeclass(VERB_ALGO, "negcache dlvlookup", qname,
LDNS_RR_TYPE_DLV, qclass);
labs = dname_count_labels(qname); labs = dname_count_labels(qname);
lock_basic_lock(&neg->lock); lock_basic_lock(&neg->lock);
@ -885,6 +894,8 @@ int val_neg_dlvlookup(struct val_neg_cache* neg, uint8_t* qname, size_t len,
lock_basic_unlock(&neg->lock); lock_basic_unlock(&neg->lock);
return 0; return 0;
} }
log_nametypeclass(VERB_ALGO, "negcache zone", zone->name, 0,
zone->dclass);
/* lookup closest data record */ /* lookup closest data record */
(void)neg_closest_data(zone, qname, len, labs, &data); (void)neg_closest_data(zone, qname, len, labs, &data);
@ -894,6 +905,8 @@ int val_neg_dlvlookup(struct val_neg_cache* neg, uint8_t* qname, size_t len,
lock_basic_unlock(&neg->lock); lock_basic_unlock(&neg->lock);
return 0; return 0;
} }
log_nametypeclass(VERB_ALGO, "negcache rr", data->name,
LDNS_RR_TYPE_NSEC, zone->dclass);
/* lookup rrset in rrset cache */ /* lookup rrset in rrset cache */
flags = 0; flags = 0;
@ -908,7 +921,7 @@ int val_neg_dlvlookup(struct val_neg_cache* neg, uint8_t* qname, size_t len,
return 0; return 0;
} }
d = (struct packed_rrset_data*)nsec->entry.data; d = (struct packed_rrset_data*)nsec->entry.data;
if(!d || d->ttl > now) { if(!d || now > d->ttl) {
lock_rw_unlock(&nsec->entry.lock); lock_rw_unlock(&nsec->entry.lock);
/* delete data record if expired */ /* delete data record if expired */
neg_delete_data(neg, data); neg_delete_data(neg, data);
@ -921,6 +934,7 @@ int val_neg_dlvlookup(struct val_neg_cache* neg, uint8_t* qname, size_t len,
lock_basic_unlock(&neg->lock); lock_basic_unlock(&neg->lock);
return 0; return 0;
} }
verbose(VERB_ALGO, "negcache got secure rrset");
/* check NSEC security */ /* check NSEC security */
/* check if NSEC proves no DLV type exists */ /* check if NSEC proves no DLV type exists */
@ -933,6 +947,7 @@ int val_neg_dlvlookup(struct val_neg_cache* neg, uint8_t* qname, size_t len,
/* the NSEC is not a denial for the DLV */ /* the NSEC is not a denial for the DLV */
lock_rw_unlock(&nsec->entry.lock); lock_rw_unlock(&nsec->entry.lock);
lock_basic_unlock(&neg->lock); lock_basic_unlock(&neg->lock);
verbose(VERB_ALGO, "negcache not proven");
return 0; return 0;
} }
/* so the NSEC was a NODATA proof, or NXDOMAIN proof. */ /* so the NSEC was a NODATA proof, or NXDOMAIN proof. */
@ -944,5 +959,6 @@ int val_neg_dlvlookup(struct val_neg_cache* neg, uint8_t* qname, size_t len,
/* if OK touch the LRU for neg_data element */ /* if OK touch the LRU for neg_data element */
neg_lru_touch(neg, data); neg_lru_touch(neg, data);
lock_basic_unlock(&neg->lock); lock_basic_unlock(&neg->lock);
return 0; verbose(VERB_ALGO, "negcache DLV denial proven");
return 1;
} }

View file

@ -47,6 +47,7 @@
#include "validator/val_utils.h" #include "validator/val_utils.h"
#include "validator/val_nsec.h" #include "validator/val_nsec.h"
#include "validator/val_nsec3.h" #include "validator/val_nsec3.h"
#include "validator/val_neg.h"
#include "services/cache/dns.h" #include "services/cache/dns.h"
#include "util/data/dname.h" #include "util/data/dname.h"
#include "util/module.h" #include "util/module.h"
@ -120,6 +121,16 @@ val_apply_cfg(struct module_env* env, struct val_env* val_env,
log_err("validator: error in trustanchors config"); log_err("validator: error in trustanchors config");
return 0; 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; val_env->date_override = cfg->val_date_override;
c = cfg_count_numbers(cfg->val_nsec3_key_iterations); c = cfg_count_numbers(cfg->val_nsec3_key_iterations);
if(c < 1 || (c&1)) { if(c < 1 || (c&1)) {
@ -164,6 +175,7 @@ val_deinit(struct module_env* env, int id)
anchors_delete(env->anchors); anchors_delete(env->anchors);
env->anchors = NULL; env->anchors = NULL;
key_cache_delete(val_env->kcache); key_cache_delete(val_env->kcache);
neg_cache_delete(val_env->neg_cache);
free(val_env->nsec3_keysize); free(val_env->nsec3_keysize);
free(val_env->nsec3_maxiter); free(val_env->nsec3_maxiter);
free(val_env); free(val_env);
@ -1575,12 +1587,11 @@ val_dlv_init(struct module_qstate* qstate, struct val_qstate* vq,
/* If we can find the name in the aggressive negative cache, /* If we can find the name in the aggressive negative cache,
* give up; insecure is the answer */ * give up; insecure is the answer */
/* lookup, several places in the tree may qualify if(val_neg_dlvlookup(ve->neg_cache, vq->dlv_lookup_name,
* between insecure_at and the lookup_name vq->dlv_lookup_name_len, vq->qchase.qclass,
* Check proof thoroughly qstate->env->rrset_cache, *qstate->env->now)) {
* TODO return 1;
* return 1; }
*/
/* perform a lookup for the DLV; with validation */ /* perform a lookup for the DLV; with validation */
vq->state = VAL_DLVLOOKUP_STATE; vq->state = VAL_DLVLOOKUP_STATE;
@ -1798,6 +1809,16 @@ processDLVLookup(struct module_qstate* qstate, struct val_qstate* vq,
return 1; 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, if(!generate_request(qstate, id, vq->dlv_lookup_name,
vq->dlv_lookup_name_len, LDNS_RR_TYPE_DLV, vq->dlv_lookup_name_len, LDNS_RR_TYPE_DLV,
vq->qchase.qclass, 0)) { vq->qchase.qclass, 0)) {
@ -2383,6 +2404,8 @@ process_dlv_response(struct module_qstate* qstate, struct val_qstate* vq,
vq->dlv_status = dlv_success; vq->dlv_status = dlv_success;
return; return;
} }
/* store NSECs into negative cache */
val_neg_addreply(ve->neg_cache, msg->rep);
/* was the lookup a failure? /* was the lookup a failure?
* if we have to go up into the DLV for a higher DLV anchor * if we have to go up into the DLV for a higher DLV anchor
@ -2460,6 +2483,7 @@ val_get_mem(struct module_env* env, int id)
if(!ve) if(!ve)
return 0; return 0;
return sizeof(*ve) + key_cache_get_mem(ve->kcache) + return sizeof(*ve) + key_cache_get_mem(ve->kcache) +
val_neg_get_mem(ve->neg_cache) +
anchors_get_mem(env->anchors) + anchors_get_mem(env->anchors) +
sizeof(size_t)*2*ve->nsec3_keyiter_count; sizeof(size_t)*2*ve->nsec3_keyiter_count;
} }

View file

@ -48,6 +48,7 @@
struct val_anchors; struct val_anchors;
struct key_cache; struct key_cache;
struct key_entry_key; struct key_entry_key;
struct val_neg_cache;
/** /**
* This is the TTL to use when a trust anchor fails to prime. A trust anchor * This is the TTL to use when a trust anchor fails to prime. A trust anchor
@ -63,6 +64,9 @@ struct val_env {
* end up here after being primed. */ * end up here after being primed. */
struct key_cache* kcache; struct key_cache* kcache;
/** aggressive negative cache. index into NSECs in rrset cache. */
struct val_neg_cache* neg_cache;
/** for debug testing a fixed validation date can be entered. /** for debug testing a fixed validation date can be entered.
* if 0, current time is used for rrsig validation */ * if 0, current time is used for rrsig validation */
int32_t date_override; int32_t date_override;