mirror of
https://github.com/NLnetLabs/unbound.git
synced 2026-05-28 04:02:33 -04:00
working on trust of rrsets.
git-svn-id: file:///svn/unbound/trunk@281 be551aaa-1e26-0410-a405-d3ace91eadb9
This commit is contained in:
parent
caa76487f8
commit
44ef71ff6c
8 changed files with 162 additions and 13 deletions
|
|
@ -74,7 +74,7 @@ struct daemon {
|
|||
struct alloc_cache superalloc;
|
||||
/** the message cache, content is struct msgreply_entry* */
|
||||
struct slabhash* msg_cache;
|
||||
/** the rrset cache, content is struct struct ub_packed_rrset_key* */
|
||||
/** the rrset cache, content is struct ub_packed_rrset_key* */
|
||||
struct slabhash* rrset_cache;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -129,16 +129,66 @@ replyerror(int r, struct work_query* w)
|
|||
query_info_clear(&w->qinfo);
|
||||
}
|
||||
|
||||
/** see if rrset needs to be updated in the cache */
|
||||
static int
|
||||
need_to_update_rrset(struct packed_rrset_data* newd,
|
||||
struct packed_rrset_data* cached)
|
||||
{
|
||||
if( newd->trust > cached->trust )
|
||||
return 1;
|
||||
if( newd->ttl > cached->ttl &&
|
||||
rrsetdata_equal(newd, cached))
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** store rrsets in the rrset cache. */
|
||||
static void
|
||||
worker_store_rrsets(struct worker* worker, struct reply_info* rep)
|
||||
{
|
||||
struct lruhash_entry* e;
|
||||
size_t i;
|
||||
/* see if rrset already exists in cache, if not insert it. */
|
||||
/* if it does exist: */
|
||||
/* o if current RRset is more trustworthy - insert it */
|
||||
/* o see if TTL is better than TTL in cache. */
|
||||
/* if so, see if rrset+rdata is (exactly!) the same */
|
||||
/* if so, update TTL in cache. */
|
||||
for(i=0; i<rep->rrset_count; i++) {
|
||||
/* TODO: check if update really needed */
|
||||
rep->ref[i].key = rep->rrsets[i];
|
||||
rep->ref[i].id = rep->rrsets[i]->id;
|
||||
/* looks up item with a readlock - no editing! */
|
||||
if((e=slabhash_lookup(worker->daemon->rrset_cache,
|
||||
rep->rrsets[i]->entry.hash, rep->rrsets[i]->entry.key,
|
||||
0)) != 0) {
|
||||
struct packed_rrset_data* data =
|
||||
(struct packed_rrset_data*)e->data;
|
||||
struct packed_rrset_data* rd =
|
||||
(struct packed_rrset_data*)
|
||||
rep->rrsets[i]->entry.data;
|
||||
rep->ref[i].key = (struct ub_packed_rrset_key*)e->key;
|
||||
rep->ref[i].id = rep->rrsets[i]->id;
|
||||
/* found in cache, do checks above */
|
||||
if(!need_to_update_rrset(rd, data)) {
|
||||
lock_rw_unlock(&e->lock);
|
||||
ub_packed_rrset_parsedelete(rep->rrsets[i],
|
||||
&worker->alloc);
|
||||
rep->rrsets[i] = rep->ref[i].key;
|
||||
continue; /* use cached item instead */
|
||||
}
|
||||
if(rd->trust < data->trust)
|
||||
rd->trust = data->trust;
|
||||
lock_rw_unlock(&e->lock);
|
||||
/* small gap here, where entry is not locked.
|
||||
* possibly entry is updated with something else.
|
||||
* this is just too bad, its cache anyway. */
|
||||
/* use insert to update entry to manage lruhash
|
||||
* cache size values nicely. */
|
||||
}
|
||||
slabhash_insert(worker->daemon->rrset_cache,
|
||||
rep->rrsets[i]->entry.hash, &rep->rrsets[i]->entry,
|
||||
rep->rrsets[i]->entry.data, &worker->alloc);
|
||||
/* TODO store correct key and id */
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -192,7 +242,7 @@ worker_handle_reply(struct comm_point* c, void* arg, int error,
|
|||
}
|
||||
reply_info_set_ttls(rep, time(0));
|
||||
worker_store_rrsets(w->worker, rep);
|
||||
reply_info_fillref(rep);
|
||||
reply_info_sortref(rep);
|
||||
/* store msg in the cache */
|
||||
if(!(e = query_info_entrysetup(&qinf, rep, w->query_hash))) {
|
||||
query_info_clear(&qinf);
|
||||
|
|
|
|||
|
|
@ -3,6 +3,8 @@
|
|||
- config settings for rrset cache size and slabs.
|
||||
- hashtable insert takes argument so that a thread can use its own
|
||||
alloc cache to store released keys.
|
||||
- alloc cache special_release() locks if necessary.
|
||||
- rrset trustworthiness type added.
|
||||
|
||||
3 May 2007: Wouter
|
||||
- fill refs. Use new parse and encode to answer queries.
|
||||
|
|
|
|||
2
doc/TODO
2
doc/TODO
|
|
@ -16,3 +16,5 @@ o use rbtree to compress domain names in messages, sorted AXFRs of 16Kb
|
|||
start to send out compressed AXFRs then it becomes a problem.
|
||||
We can cap AXFR packets on 256 or 1024 domain names, for example.
|
||||
o speed up pkt domain name decompression loop detection using counter perhaps.
|
||||
o detect OS/400 pthreads implementation that allows upgrading to writelock
|
||||
on pthreads rwlocks and use it to examine-rd before storing-wr rrset cache.
|
||||
|
|
|
|||
|
|
@ -199,6 +199,7 @@ parse_rr_copy(ldns_buffer* pkt, struct rrset_parse* pset,
|
|||
data->ttl = MAX_TTL;
|
||||
data->count = pset->rr_count;
|
||||
data->rrsig_count = pset->rrsig_count;
|
||||
data->trust = rrset_trust_none;
|
||||
/* layout: struct - rr_len - rr_data - rdata - rrsig */
|
||||
data->rr_len = (size_t*)((uint8_t*)data +
|
||||
sizeof(struct packed_rrset_data));
|
||||
|
|
@ -246,6 +247,31 @@ parse_create_rrset(ldns_buffer* pkt, struct rrset_parse* pset,
|
|||
return 0;
|
||||
}
|
||||
|
||||
/** get trust value for rrset */
|
||||
static enum rrset_trust
|
||||
get_rrset_trust(struct reply_info* rep, size_t i)
|
||||
{
|
||||
uint16_t AA = rep->flags & BIT_AA;
|
||||
/* TODO: need scrubber that knows what zone the server serves, so that
|
||||
* it can check if AA bit is warranted.
|
||||
* it can check if rrset_trust_nonauth_ans_AA should be used */
|
||||
if(i < rep->an_numrrsets) {
|
||||
/* answer section */
|
||||
if(AA) return rrset_trust_ans_AA;
|
||||
else return rrset_trust_ans_noAA;
|
||||
|
||||
} else if(i < rep->an_numrrsets+rep->ns_numrrsets) {
|
||||
/* authority section */
|
||||
if(AA) return rrset_trust_auth_AA;
|
||||
else return rrset_trust_auth_noAA;
|
||||
} else {
|
||||
/* addit section */
|
||||
if(AA) return rrset_trust_add_AA;
|
||||
else return rrset_trust_add_noAA;
|
||||
}
|
||||
return rrset_trust_none;
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy and decompress rrs
|
||||
* @param pkt: the packet for compression pointer resolution.
|
||||
|
|
@ -288,6 +314,7 @@ parse_copy_decompress(ldns_buffer* pkt, struct msg_parse* msg,
|
|||
rep->rrsets[i]->entry.data = (void*)data;
|
||||
rep->rrsets[i]->entry.key = (void*)rep->rrsets[i];
|
||||
rep->rrsets[i]->entry.hash = pset->hash;
|
||||
data->trust = get_rrset_trust(rep, i);
|
||||
if(data->ttl < rep->ttl)
|
||||
rep->ttl = data->ttl;
|
||||
|
||||
|
|
@ -358,7 +385,7 @@ int reply_info_parse(ldns_buffer* pkt, struct alloc_cache* alloc,
|
|||
|
||||
/** helper compare function to sort in lock order */
|
||||
static int
|
||||
reply_info_fillref_cmp(const void* a, const void* b)
|
||||
reply_info_sortref_cmp(const void* a, const void* b)
|
||||
{
|
||||
if(a < b) return -1;
|
||||
if(a > b) return 1;
|
||||
|
|
@ -366,15 +393,10 @@ reply_info_fillref_cmp(const void* a, const void* b)
|
|||
}
|
||||
|
||||
void
|
||||
reply_info_fillref(struct reply_info* rep)
|
||||
reply_info_sortref(struct reply_info* rep)
|
||||
{
|
||||
size_t i;
|
||||
for(i=0; i<rep->rrset_count; i++) {
|
||||
rep->ref[i].key = rep->rrsets[i];
|
||||
rep->ref[i].id = rep->rrsets[i]->id;
|
||||
}
|
||||
qsort(&rep->ref[0], rep->rrset_count, sizeof(struct rrset_ref),
|
||||
reply_info_fillref_cmp);
|
||||
reply_info_sortref_cmp);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
|||
|
|
@ -192,10 +192,10 @@ int reply_info_parse(ldns_buffer* pkt, struct alloc_cache* alloc,
|
|||
struct query_info* qinf, struct reply_info** rep);
|
||||
|
||||
/**
|
||||
* Fills in the ref array based on the rest of the structure, the rrsets.
|
||||
* Sorts the ref array.
|
||||
* @param rep: reply info. rrsets must be filled in.
|
||||
*/
|
||||
void reply_info_fillref(struct reply_info* rep);
|
||||
void reply_info_sortref(struct reply_info* rep);
|
||||
|
||||
/**
|
||||
* Set TTLs inside the replyinfo to absolute values.
|
||||
|
|
|
|||
|
|
@ -117,3 +117,20 @@ rrset_data_delete(void* data, void* ATTR_UNUSED(userdata))
|
|||
struct packed_rrset_data* d = (struct packed_rrset_data*)data;
|
||||
free(d);
|
||||
}
|
||||
|
||||
int
|
||||
rrsetdata_equal(struct packed_rrset_data* d1, struct packed_rrset_data* d2)
|
||||
{
|
||||
size_t i;
|
||||
size_t total;
|
||||
if(d1->count != d2->count || d1->rrsig_count != d2->rrsig_count)
|
||||
return 0;
|
||||
total = d1->count + d1->rrsig_count;
|
||||
for(i=0; i<total; i++) {
|
||||
if(d1->rr_len[i] != d2->rr_len[i])
|
||||
return 0;
|
||||
if(memcmp(d1->rr_data[i], d2->rr_data[i], d1->rr_len[i]) != 0)
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -107,6 +107,51 @@ struct ub_packed_rrset_key {
|
|||
struct packed_rrset_key rk;
|
||||
};
|
||||
|
||||
/**
|
||||
* RRset trustworthiness. Bigger value is more trust. RFC 2181.
|
||||
* The rrset_trust_add_noAA, rrset_trust_auth_noAA, rrset_trust_add_AA,
|
||||
* are mentioned as the same trustworthiness in 2181, but split up here
|
||||
* for ease of processing.
|
||||
*
|
||||
* rrset_trust_nonauth_ans_AA, rrset_trust_ans_noAA
|
||||
* are also mentioned as the same trustworthiness in 2181, but split up here
|
||||
* for ease of processing.
|
||||
*
|
||||
* Added trust_none for a sane initial value, smaller than anything else.
|
||||
* Added validated and ultimate trust for keys and rrsig validated content.
|
||||
*/
|
||||
enum rrset_trust {
|
||||
/** initial value for trust */
|
||||
rrset_trust_none = 0,
|
||||
/** Additional information from non-authoritative answers */
|
||||
rrset_trust_add_noAA,
|
||||
/** Data from the authority section of a non-authoritative answer */
|
||||
rrset_trust_auth_noAA,
|
||||
/** Additional information from an authoritative answer */
|
||||
rrset_trust_add_AA,
|
||||
/** non-authoritative data from the answer section of authoritative
|
||||
* answers */
|
||||
rrset_trust_nonauth_ans_AA,
|
||||
/** Data from the answer section of a non-authoritative answer */
|
||||
rrset_trust_ans_noAA,
|
||||
/** Glue from a primary zone, or glue from a zone transfer */
|
||||
rrset_trust_glue,
|
||||
/** Data from the authority section of an authoritative answer */
|
||||
rrset_trust_auth_AA,
|
||||
/** The authoritative data included in the answer section of an
|
||||
* authoritative reply */
|
||||
rrset_trust_ans_AA,
|
||||
/** Data from a zone transfer, other than glue */
|
||||
rrset_trust_sec_noglue,
|
||||
/** Data from a primary zone file, other than glue data */
|
||||
rrset_trust_prim_noglue,
|
||||
/** DNSSEC(rfc4034) validated with trusted keys */
|
||||
rrset_trust_validated,
|
||||
/** ultimately trusted, no more trust is possible;
|
||||
* trusted keys from the unbound configuration setup. */
|
||||
rrset_trust_ultimate
|
||||
};
|
||||
|
||||
/**
|
||||
* RRset data.
|
||||
*
|
||||
|
|
@ -143,6 +188,8 @@ struct packed_rrset_data {
|
|||
size_t count;
|
||||
/** number of rrsigs, if 0 no rrsigs */
|
||||
size_t rrsig_count;
|
||||
/** the trustworthiness of the rrset data */
|
||||
enum rrset_trust trust;
|
||||
/** length of every rr's rdata, rr_len[i] is size of rr_data[i]. */
|
||||
size_t* rr_len;
|
||||
/** ttl of every rr. rr_ttl[i] ttl of rr i. */
|
||||
|
|
@ -194,6 +241,15 @@ size_t ub_rrset_sizefunc(void* key, void* data);
|
|||
*/
|
||||
int ub_rrset_compare(void* k1, void* k2);
|
||||
|
||||
/**
|
||||
* compare two rrset data structures.
|
||||
* Compared rdata and rrsigdata, not the trust or ttl value.
|
||||
* @param d1: data to compare.
|
||||
* @param d2: data to compare.
|
||||
* @return 1 if equal.
|
||||
*/
|
||||
int rrsetdata_equal(struct packed_rrset_data* d1, struct packed_rrset_data* d2);
|
||||
|
||||
/**
|
||||
* Old key to be deleted. RRset keys are recycled via alloc.
|
||||
* @param key: struct ub_packed_rrset_key*.
|
||||
|
|
|
|||
Loading…
Reference in a new issue