mirror of
https://github.com/NLnetLabs/unbound.git
synced 2025-12-20 23:00:56 -05:00
DLV negative cache works.
git-svn-id: file:///svn/unbound/trunk@1200 be551aaa-1e26-0410-a405-d3ace91eadb9
This commit is contained in:
parent
a61d10f715
commit
a39a7704af
4 changed files with 61 additions and 13 deletions
|
|
@ -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.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue