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,
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) )) {
- 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.
}
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;
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 */
struct region;
struct msg_parse;
struct ub_randstate;
+struct query_info;
+struct reply_info;
/**
* Process config options and set iterator module state.
/**
* 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.
/* 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);
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
/* 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;
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) {