]> git.ipfire.org Git - thirdparty/unbound.git/commitdiff
check messages taken from cache, also in iterator.
authorWouter Wijngaards <wouter@nlnetlabs.nl>
Tue, 16 Jun 2009 12:03:41 +0000 (12:03 +0000)
committerWouter Wijngaards <wouter@nlnetlabs.nl>
Tue, 16 Jun 2009 12:03:41 +0000 (12:03 +0000)
git-svn-id: file:///svn/unbound/trunk@1662 be551aaa-1e26-0410-a405-d3ace91eadb9

daemon/worker.c
doc/Changelog
services/cache/dns.c
util/data/msgreply.c
util/data/msgreply.h

index bb966a0cc8c7b19c15df9ba416f0eaf178814aae..a65867e998c6c1d56f410c93e412a70c743d9405 100644 (file)
@@ -496,43 +496,6 @@ answer_norec_from_cache(struct worker* worker, struct query_info* qinfo,
        return 1;
 }
 
-/** check cname chain in cache reply */
-static int
-check_cache_chain(struct reply_info* rep) {
-       /* check only answer section rrs for matching cname chain.
-        * the cache may return changed rdata, but owner names are untouched.*/
-       size_t i;
-       uint8_t* sname = rep->rrsets[0]->rk.dname;
-       size_t snamelen = rep->rrsets[0]->rk.dname_len;
-       for(i=0; i<rep->an_numrrsets; i++) {
-               uint16_t t = ntohs(rep->rrsets[i]->rk.type);
-               if(t == LDNS_RR_TYPE_DNAME)
-                       continue; /* skip dnames; note TTL 0 not cached */
-               /* verify that owner matches current sname */
-               if(query_dname_compare(sname, rep->rrsets[i]->rk.dname) != 0){
-                       /* cname chain broken */
-                       return 0;
-               }
-               /* if this is a cname; move on */
-               if(t == LDNS_RR_TYPE_CNAME) {
-                       get_cname_target(rep->rrsets[i], &sname, &snamelen);
-               }
-       }
-       return 1;
-}
-
-/** check security status in cache reply */
-static int
-all_rrsets_secure(struct reply_info* rep) {
-       size_t i;
-       for(i=0; i<rep->rrset_count; i++) {
-               if( ((struct packed_rrset_data*)rep->rrsets[i]->entry.data)
-                       ->security != sec_status_secure )
-                       return 0;
-       }
-       return 1;
-}
-
 /** answer query from the cache */
 static int
 answer_from_cache(struct worker* worker, struct query_info* qinfo,
@@ -558,7 +521,7 @@ answer_from_cache(struct worker* worker, struct query_info* qinfo,
        if(rep->an_numrrsets > 0 && (rep->rrsets[0]->rk.type == 
                htons(LDNS_RR_TYPE_CNAME) || rep->rrsets[0]->rk.type == 
                htons(LDNS_RR_TYPE_DNAME))) {
-               if(!check_cache_chain(rep)) {
+               if(!reply_check_cname_chain(rep)) {
                        /* cname chain invalid, redo iterator steps */
                        verbose(VERB_ALGO, "Cache reply: cname chain broken");
                bail_out:
@@ -590,7 +553,7 @@ answer_from_cache(struct worker* worker, struct query_info* qinfo,
                        "validation");
                goto bail_out; /* need to validate cache entry first */
        } else if(rep->security == sec_status_secure) {
-               if(all_rrsets_secure(rep))
+               if(reply_all_rrsets_secure(rep))
                        secure = 1;
                else    {
                        if(must_validate) {
index 26a8969da6c0fce967978afb868a8399e708abd9..4a805be9d27c85cc153e6006d1b795f596f2470c 100644 (file)
@@ -2,6 +2,9 @@
        - Fixup opportunistic target query generation to it does not
          generate queries that are known to fail.
        - Touchup on munin total memory report.
+       - messages picked out of the cache by the iterator are checked
+         if their cname chain is still correct and if validation status
+         has to be reexamined.
 
 15 June 2009: Wouter
        - iana portlist updated.
index 3cf43daa7f6aa07ab0024b62d3e24fed68c12999..3712486d1da1cc029eec6859420a29b896c6b361 100644 (file)
@@ -440,6 +440,18 @@ tomsg(struct module_env* env, struct msgreply_entry* e, struct reply_info* r,
         msg->rep->authoritative = r->authoritative;
        if(!rrset_array_lock(r->ref, r->rrset_count, now))
                return NULL;
+       if(r->an_numrrsets > 0 && (r->rrsets[0]->rk.type == htons(
+               LDNS_RR_TYPE_CNAME) || r->rrsets[0]->rk.type == htons(
+               LDNS_RR_TYPE_DNAME)) && !reply_check_cname_chain(r)) {
+               /* cname chain is now invalid, reconstruct msg */
+               rrset_array_unlock(r->ref, r->rrset_count);
+               return NULL;
+       }
+       if(r->security == sec_status_secure && !reply_all_rrsets_secure(r)) {
+               /* message rrsets have changed status, revalidate */
+               rrset_array_unlock(r->ref, r->rrset_count);
+               return NULL;
+       }
        for(i=0; i<msg->rep->rrset_count; i++) {
                msg->rep->rrsets[i] = packed_rrset_copy_region(r->rrsets[i], 
                        region, now);
index 11ba08aa774f1acf5456701c7d8232a530060fca..0db11ac90c9c468b646515bf657634a100bb7596 100644 (file)
@@ -790,3 +790,40 @@ log_query_info(enum verbosity_value v, const char* str,
 {
        log_nametypeclass(v, str, qinf->qname, qinf->qtype, qinf->qclass);
 }
+
+int
+reply_check_cname_chain(struct reply_info* rep) 
+{
+       /* check only answer section rrs for matching cname chain.
+        * the cache may return changed rdata, but owner names are untouched.*/
+       size_t i;
+       uint8_t* sname = rep->rrsets[0]->rk.dname;
+       size_t snamelen = rep->rrsets[0]->rk.dname_len;
+       for(i=0; i<rep->an_numrrsets; i++) {
+               uint16_t t = ntohs(rep->rrsets[i]->rk.type);
+               if(t == LDNS_RR_TYPE_DNAME)
+                       continue; /* skip dnames; note TTL 0 not cached */
+               /* verify that owner matches current sname */
+               if(query_dname_compare(sname, rep->rrsets[i]->rk.dname) != 0){
+                       /* cname chain broken */
+                       return 0;
+               }
+               /* if this is a cname; move on */
+               if(t == LDNS_RR_TYPE_CNAME) {
+                       get_cname_target(rep->rrsets[i], &sname, &snamelen);
+               }
+       }
+       return 1;
+}
+
+int
+reply_all_rrsets_secure(struct reply_info* rep) 
+{
+       size_t i;
+       for(i=0; i<rep->rrset_count; i++) {
+               if( ((struct packed_rrset_data*)rep->rrsets[i]->entry.data)
+                       ->security != sec_status_secure )
+               return 0;
+       }
+       return 1;
+}
index 87570e6226c312258a9ba32b25e4fc1b97663781..c14e9227cb516ba693bf04463ad0cce0485d6b57 100644 (file)
@@ -329,6 +329,21 @@ int parse_copy_decompress_rrset(ldns_buffer* pkt, struct msg_parse* msg,
 uint8_t* reply_find_final_cname_target(struct query_info* qinfo,
        struct reply_info* rep);
 
+/**
+ * Check if cname chain in cached reply is still valid.
+ * @param rep: reply to check.
+ * @return: true if valid, false if invalid.
+ */
+int reply_check_cname_chain(struct reply_info* rep);
+
+/**
+ * Check security status of all RRs in the message.
+ * @param rep: reply to check
+ * @return: true if all RRs are secure. False if not.
+ *    True if there are zero RRs.
+ */
+int reply_all_rrsets_secure(struct reply_info* rep);
+
 /**
  * Find answer rrset in reply, the one matching qinfo. Follows CNAMEs, so the
  * result may have a different owner name.