From: Wouter Wijngaards Date: Tue, 16 Jun 2009 12:03:41 +0000 (+0000) Subject: check messages taken from cache, also in iterator. X-Git-Tag: release-1.3.1~45 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=f39e5fe3a80b4fde05ec8b94d71a7487add7af9a;p=thirdparty%2Funbound.git check messages taken from cache, also in iterator. git-svn-id: file:///svn/unbound/trunk@1662 be551aaa-1e26-0410-a405-d3ace91eadb9 --- diff --git a/daemon/worker.c b/daemon/worker.c index bb966a0cc..a65867e99 100644 --- a/daemon/worker.c +++ b/daemon/worker.c @@ -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; ian_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; irrset_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) { diff --git a/doc/Changelog b/doc/Changelog index 26a8969da..4a805be9d 100644 --- a/doc/Changelog +++ b/doc/Changelog @@ -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. diff --git a/services/cache/dns.c b/services/cache/dns.c index 3cf43daa7..3712486d1 100644 --- a/services/cache/dns.c +++ b/services/cache/dns.c @@ -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; irep->rrset_count; i++) { msg->rep->rrsets[i] = packed_rrset_copy_region(r->rrsets[i], region, now); diff --git a/util/data/msgreply.c b/util/data/msgreply.c index 11ba08aa7..0db11ac90 100644 --- a/util/data/msgreply.c +++ b/util/data/msgreply.c @@ -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; ian_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; irrset_count; i++) { + if( ((struct packed_rrset_data*)rep->rrsets[i]->entry.data) + ->security != sec_status_secure ) + return 0; + } + return 1; +} diff --git a/util/data/msgreply.h b/util/data/msgreply.h index 87570e622..c14e9227c 100644 --- a/util/data/msgreply.h +++ b/util/data/msgreply.h @@ -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.