From: Wouter Wijngaards Date: Thu, 19 Jul 2007 15:16:39 +0000 (+0000) Subject: cname chain caching (part). X-Git-Tag: release-0.4~26 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=1d6715544a423b950b7054b35ba2525a5f210a01;p=thirdparty%2Funbound.git cname chain caching (part). git-svn-id: file:///svn/unbound/trunk@440 be551aaa-1e26-0410-a405-d3ace91eadb9 --- diff --git a/daemon/worker.c b/daemon/worker.c index 9af063128..1dd6cdb5d 100644 --- a/daemon/worker.c +++ b/daemon/worker.c @@ -222,6 +222,12 @@ worker_handle_control_cmd(struct comm_point* c, void* arg, int error, return 0; } +/** check cname chain in cache reply */ +static int +check_cache_chain(struct reply_info* rep) { + return 1; +} + /** answer query from the cache */ static int answer_from_cache(struct worker* worker, struct lruhash_entry* e, uint16_t id, @@ -246,6 +252,17 @@ answer_from_cache(struct worker* worker, struct lruhash_entry* e, uint16_t id, if(!rrset_array_lock(rep->ref, rep->rrset_count, timenow)) return 0; /* locked and ids and ttls are OK. */ + /* check CNAME chain (if any) */ + 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)) { + rrset_array_unlock_touch(worker->env.rrset_cache, + worker->scratchpad, rep->ref, rep->rrset_count); + region_free_all(worker->scratchpad); + return 0; + } + } if(!reply_info_answer_encode(&mrentry->key, rep, id, flags, repinfo->c->buffer, timenow, 1, worker->scratchpad, udpsize, edns, (int)(edns->bits & EDNS_DO) )) { diff --git a/doc/Changelog b/doc/Changelog index e84d93a71..18e7dada7 100644 --- a/doc/Changelog +++ b/doc/Changelog @@ -3,6 +3,7 @@ - fixup of deadlock warnings, yield cpu in checklock code so that freebsd scheduler selects correct process to run. - added identity and version config options and replies. + - store cname messages complete answers. 18 July 2007: Wouter - do not query addresses, 127.0.0.1, and ::1 by default. diff --git a/iterator/iter_utils.c b/iterator/iter_utils.c index 53f3c3343..656b58f5c 100644 --- a/iterator/iter_utils.c +++ b/iterator/iter_utils.c @@ -293,11 +293,12 @@ dns_copy_msg(struct dns_msg* from, struct region* region) } int -iter_dns_store(struct module_env* env, struct dns_msg* msg, int is_referral) +iter_dns_store(struct module_env* env, struct query_info* msgqinf, + struct reply_info* msgrep, int is_referral) { struct reply_info* rep = NULL; /* alloc, malloc properly (not in region, like msg is) */ - rep = reply_info_copy(msg->rep, env->alloc, NULL); + rep = reply_info_copy(msgrep, env->alloc, NULL); if(!rep) return 0; @@ -322,10 +323,10 @@ iter_dns_store(struct module_env* env, struct dns_msg* msg, int is_referral) struct query_info qinf; hashvalue_t h; - qinf = msg->qinfo; - qinf.qname = memdup(msg->qinfo.qname, msg->qinfo.qname_len); + qinf = *msgqinf; + qinf.qname = memdup(msgqinf->qname, msgqinf->qname_len); if(!qinf.qname) { - reply_info_parsedelete(msg->rep, env->alloc); + reply_info_parsedelete(rep, env->alloc); return 0; } /* fixup flags to be sensible for a reply based on the cache */ diff --git a/iterator/iter_utils.h b/iterator/iter_utils.h index dacd95478..2531ad37f 100644 --- a/iterator/iter_utils.h +++ b/iterator/iter_utils.h @@ -50,6 +50,8 @@ struct delegpt; struct region; struct msg_parse; struct ub_randstate; +struct query_info; +struct reply_info; /** * Process config options and set iterator module state. @@ -98,13 +100,14 @@ struct dns_msg* dns_copy_msg(struct dns_msg* from, struct region* region); /** * Allocate a dns_msg with malloc/alloc structure and store in dns cache. * @param env: environment, with alloc structure and dns cache. - * @param msg: dns_msg from dns_alloc_msg for example. + * @param qinf: query info, the query for which answer is stored. + * @param rep: reply in dns_msg from dns_alloc_msg for example. * @param is_referral: If true, then the given message to be stored is a * referral. The cache implementation may use this as a hint. * @return 0 on alloc error (out of memory). */ -int iter_dns_store(struct module_env* env, struct dns_msg* msg, - int is_referral); +int iter_dns_store(struct module_env* env, struct query_info* qinf, + struct reply_info* rep, int is_referral); /** * Select randomly with n/m probability. diff --git a/iterator/iterator.c b/iterator/iterator.c index 5f339ed86..44641923d 100644 --- a/iterator/iterator.c +++ b/iterator/iterator.c @@ -1053,13 +1053,8 @@ processQueryResponse(struct module_qstate* qstate, struct iter_qstate* iq, /* ANSWER type responses terminate the query algorithm, * so they sent on their */ verbose(VERB_DETAIL, "query response was ANSWER"); - - /* FIXME: there is a question about whether this gets - * stored under the original query or most recent query. - * The original query would reduce cache work, but you - * need to apply the prependList before caching, and - * also cache under the latest query. */ - if(!iter_dns_store(qstate->env, iq->response, 0)) + if(!iter_dns_store(qstate->env, &iq->response->qinfo, + iq->response->rep, 0)) return error_response(qstate, id, LDNS_RCODE_SERVFAIL); /* close down outstanding requests to be discarded */ outbound_list_clear(&iq->outlist); @@ -1073,7 +1068,8 @@ processQueryResponse(struct module_qstate* qstate, struct iter_qstate* iq, verbose(VERB_DETAIL, "query response was REFERRAL"); /* Store the referral under the current query */ - if(!iter_dns_store(qstate->env, iq->response, 1)) + if(!iter_dns_store(qstate->env, &iq->response->qinfo, + iq->response->rep, 1)) return error_response(qstate, id, LDNS_RCODE_SERVFAIL); /* Reset the event state, setting the current delegation @@ -1111,7 +1107,8 @@ processQueryResponse(struct module_qstate* qstate, struct iter_qstate* iq, /* cache the CNAME response under the current query */ /* NOTE : set referral=1, so that rrsets get stored but not * the partial query answer (CNAME only). */ - if(!iter_dns_store(qstate->env, iq->response, 1)) + if(!iter_dns_store(qstate->env, &iq->response->qinfo, + iq->response->rep, 1)) return error_response(qstate, id, LDNS_RCODE_SERVFAIL); /* set the current request's qname to the new value. */ iq->qchase.qname = sname; @@ -1347,6 +1344,10 @@ processFinished(struct module_qstate* qstate, struct iter_qstate* iq, log_err("prepend rrsets: out of memory"); return error_response(qstate, id, LDNS_RCODE_SERVFAIL); } + /* store message with the finished prepended items */ + if(!iter_dns_store(qstate->env, &qstate->qinfo, + iq->response->rep, 0)) + return error_response(qstate, id, LDNS_RCODE_SERVFAIL); } if(query_dname_compare(qstate->qinfo.qname, iq->response->qinfo.qname) == 0) {