]> git.ipfire.org Git - thirdparty/unbound.git/commitdiff
working on trust of rrsets.
authorWouter Wijngaards <wouter@nlnetlabs.nl>
Fri, 4 May 2007 10:10:52 +0000 (10:10 +0000)
committerWouter Wijngaards <wouter@nlnetlabs.nl>
Fri, 4 May 2007 10:10:52 +0000 (10:10 +0000)
git-svn-id: file:///svn/unbound/trunk@281 be551aaa-1e26-0410-a405-d3ace91eadb9

daemon/daemon.h
daemon/worker.c
doc/Changelog
doc/TODO
util/data/msgreply.c
util/data/msgreply.h
util/data/packed_rrset.c
util/data/packed_rrset.h

index 8eee819b5794ef0d49c3dc3b97a4ff29241bd4de..2979f65f86ff2ebc0e09c39fa0447caa347d17f9 100644 (file)
@@ -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;
 };
 
index 8c770be9730b2e9e5795bdf39d0372e12e61f4fd..a5cde258a9bd18d6c6749664e8347bfcc639940d 100644 (file)
@@ -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);
index a54c1c303940d604d52345acfbbd075ee220c69b..faa53bebb267d0c21668990398c2fa3f3e5eaac9 100644 (file)
@@ -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.
index 8f639e1c4f50f3e569f22c5e1e1e54073b567d3b..40d013547ce66285d047493ccdcf0b1a440f7fd4 100644 (file)
--- a/doc/TODO
+++ b/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.
index 4d39058b7f45bfc0c81641a40b4c682bdf82fc21..8dc0687cde23a8485ac1978e7c595628bc14c294 100644 (file)
@@ -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 
index a3e6b0d90cfcf16e7e20610c5cbaf5ffd17c5eab..e356d0d1fc8c2c7dd4293b44e79a4baab8950d19 100644 (file)
@@ -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.
index 7c7a8c12fae2955d06c0cec39fd09e082f3f66f1..0308157c9473dca28b1d6eadbaf9d27e41cbcdee 100644 (file)
@@ -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;
+}
index ce0ba8689b3eaa358cb8825496e9bafd4a22686e..068ccf7aa58639240ee89bb09a80c4b913216a63 100644 (file)
@@ -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*.