Process target responses, case preservation.

git-svn-id: file:///svn/unbound/trunk@365 be551aaa-1e26-0410-a405-d3ace91eadb9
This commit is contained in:
Wouter Wijngaards 2007-06-04 13:53:01 +00:00
parent 81ae42fde0
commit 5eef2381f0
9 changed files with 147 additions and 10 deletions

View file

@ -5,6 +5,8 @@
- do not touch qstate after worker_process_query because it may have - do not touch qstate after worker_process_query because it may have
been deleted by that routine. been deleted by that routine.
- Prime response state. - Prime response state.
- Process target response state.
- some memcmp changed to dname_compare for case preservation.
1 June 2007: Wouter 1 June 2007: Wouter
- normalize incoming messages. Like unbound-java, with CNAME chain - normalize incoming messages. Like unbound-java, with CNAME chain

View file

@ -102,14 +102,13 @@ delegpt_add_ns(struct delegpt* dp, struct region* region, uint8_t* name)
return 1; return 1;
} }
/** find name in deleg list */ struct delegpt_ns*
static struct delegpt_ns*
delegpt_find_ns(struct delegpt* dp, uint8_t* name, size_t namelen) delegpt_find_ns(struct delegpt* dp, uint8_t* name, size_t namelen)
{ {
struct delegpt_ns* p = dp->nslist; struct delegpt_ns* p = dp->nslist;
while(p) { while(p) {
if(namelen == p->namelen && if(namelen == p->namelen &&
memcmp(name, p->name, namelen) == 0) { query_dname_compare(name, p->name) == 0) {
return p; return p;
} }
p = p->next; p = p->next;
@ -320,3 +319,20 @@ delegpt_add_rrset_AAAA(struct delegpt* dp, struct region* region,
} }
return 1; return 1;
} }
int
delegpt_add_rrset(struct delegpt* dp, struct region* region,
struct ub_packed_rrset_key* rrset)
{
if(!rrset)
return 1;
if(ntohs(rrset->rk.type) == LDNS_RR_TYPE_NS)
return delegpt_rrset_add_ns(dp, region, rrset);
else if(ntohs(rrset->rk.type) == LDNS_RR_TYPE_A)
return delegpt_add_rrset_A(dp, region, rrset);
else if(ntohs(rrset->rk.type) == LDNS_RR_TYPE_AAAA)
return delegpt_add_rrset_AAAA(dp, region, rrset);
log_warn("Unknown rrset type added to delegpt");
return 1;
}

View file

@ -183,6 +183,16 @@ int delegpt_add_rrset_A(struct delegpt* dp, struct region* region,
int delegpt_add_rrset_AAAA(struct delegpt* dp, struct region* region, int delegpt_add_rrset_AAAA(struct delegpt* dp, struct region* region,
struct ub_packed_rrset_key* rrset); struct ub_packed_rrset_key* rrset);
/**
* Add any RRset to delegpt.
* @param dp: delegation point.
* @param region: where to allocate the info.
* @param rrset: RRset to add, NS, A, AAAA.
* @return 0 on alloc error.
*/
int delegpt_add_rrset(struct delegpt* dp, struct region* region,
struct ub_packed_rrset_key* rrset);
/** /**
* Add address to the delegation point. No servername is associated or checked. * Add address to the delegation point. No servername is associated or checked.
* @param dp: delegation point. * @param dp: delegation point.
@ -194,6 +204,16 @@ int delegpt_add_rrset_AAAA(struct delegpt* dp, struct region* region,
int delegpt_add_addr(struct delegpt* dp, struct region* region, int delegpt_add_addr(struct delegpt* dp, struct region* region,
struct sockaddr_storage* addr, socklen_t addrlen); struct sockaddr_storage* addr, socklen_t addrlen);
/**
* Find NS record in name list of delegation point.
* @param dp: delegation point.
* @param name: name of nameserver to look for, uncompressed wireformat.
* @param namelen: length of name.
* @return the ns structure or NULL if not found.
*/
struct delegpt_ns* delegpt_find_ns(struct delegpt* dp, uint8_t* name,
size_t namelen);
/** /**
* Print the delegation point to the log. For debugging. * Print the delegation point to the log. For debugging.
* @param dp: delegation point. * @param dp: delegation point.

View file

@ -1257,15 +1257,76 @@ processPrimeResponse(struct module_qstate* qstate, struct iter_qstate* iq,
return 0; return 0;
} }
#if 0 /**
/** TODO */ * Do final processing on responses to target queries. Events reach this
* state after the iterative resolution algorithm terminates. This state is
* responsible for reactiving the original event, and housekeeping related
* to received target responses (caching, updating the current delegation
* point, etc).
*
* @param qstate: query state.
* @param iq: iterator query state.
* @param id: module id.
* @return true if the event requires more (response) processing
* immediately, false if not. This particular state always returns
* false.
*/
static int static int
processTargetResponse(struct module_qstate* qstate, struct iter_qstate* iq, processTargetResponse(struct module_qstate* qstate, struct iter_qstate* iq,
struct iter_env* ie, int id) int id)
{ {
struct ub_packed_rrset_key* rrset;
struct delegpt_ns* dpns;
struct module_qstate* forq = qstate->parent;
struct iter_qstate* foriq;
log_assert(qstate->parent); /* fetch targets for a parent */
foriq = (struct iter_qstate*)forq->minfo[id];
qstate->ext_state[id] = module_finished;
/* check to see if parent event is still interested. */
if(iq->orig_qname)
dpns = delegpt_find_ns(foriq->dp, iq->orig_qname,
iq->orig_qnamelen);
else dpns = delegpt_find_ns(foriq->dp, qstate->qinfo.qname,
qstate->qinfo.qname_len);
if(!dpns) {
/* FIXME: maybe store this nameserver address in the cache
* anyways? */
/* If not, just stop processing this event */
return 0;
}
/* Tell the originating event that this target query has finished
* (regardless if it succeeded or not). */
foriq->num_target_queries--;
/* This response is relevant to the current query, so we
* add (attempt to add, anyway) this target(s) and reactivate
* the original event.
* NOTE: we could only look for the AnswerRRset if the
* response type was ANSWER. */
rrset = reply_find_answer_rrset(&qstate->qinfo, iq->response->rep);
if(rrset) {
/* if CNAMEs have been followed - add new NS to delegpt. */
if(!delegpt_find_ns(foriq->dp, rrset->rk.dname,
rrset->rk.dname_len)) {
if(!delegpt_add_ns(foriq->dp, forq->region,
rrset->rk.dname))
log_err("out of memory adding cnamed-ns");
}
if(!delegpt_add_rrset(foriq->dp, forq->region, rrset))
log_err("out of memory adding targets");
} else dpns->resolved = 1; /* fail the target */
log_assert(dpns->resolved); /* one way or another it is now done */
/* Reactivate the forEvent, now that it has either a new target or a
* failed target. */
foriq->state = QUERYTARGETS_STATE;
return 0; return 0;
} }
#if 0
/** TODO */ /** TODO */
static int static int
processFinished(struct module_qstate* qstate, struct iter_qstate* iq, processFinished(struct module_qstate* qstate, struct iter_qstate* iq,
@ -1314,10 +1375,10 @@ iter_handle(struct module_qstate* qstate, struct iter_qstate* iq,
case PRIME_RESP_STATE: case PRIME_RESP_STATE:
cont = processPrimeResponse(qstate, iq, id); cont = processPrimeResponse(qstate, iq, id);
break; break;
#if 0
case TARGET_RESP_STATE: case TARGET_RESP_STATE:
cont = processTargetResponse(qstate, iq, ie, id); cont = processTargetResponse(qstate, iq, id);
break; break;
#if 0
case FINISHED_STATE: case FINISHED_STATE:
cont = processFinished(qstate, iq, ie, id); cont = processFinished(qstate, iq, ie, id);
break; break;

View file

@ -42,6 +42,7 @@
#include "services/cache/infra.h" #include "services/cache/infra.h"
#include "util/storage/slabhash.h" #include "util/storage/slabhash.h"
#include "util/storage/lookup3.h" #include "util/storage/lookup3.h"
#include "util/data/dname.h"
#include "util/log.h" #include "util/log.h"
#include "util/net_help.h" #include "util/net_help.h"
#include "util/config_file.h" #include "util/config_file.h"
@ -312,7 +313,7 @@ infra_lame_compfunc(void* key1, void* key2)
return -1; return -1;
return 1; return 1;
} }
return memcmp(k1->zonename, k2->zonename, k1->namelen); return query_dname_compare(k1->zonename, k2->zonename);
} }
/** free key, lock and zonename */ /** free key, lock and zonename */

View file

@ -138,6 +138,7 @@ serviced_cmp(const void* key1, const void* key2)
if(q1->qbuflen > q2->qbuflen) if(q1->qbuflen > q2->qbuflen)
return 1; return 1;
log_assert(q1->qbuflen == q2->qbuflen); log_assert(q1->qbuflen == q2->qbuflen);
/* FIXME: will not detect alternate casing of qname */
if((r = memcmp(q1->qbuf, q2->qbuf, q1->qbuflen)) != 0) if((r = memcmp(q1->qbuf, q2->qbuf, q1->qbuflen)) != 0)
return r; return r;
if(q1->dnssec != q2->dnssec) { if(q1->dnssec != q2->dnssec) {

View file

@ -625,3 +625,29 @@ reply_info_copy(struct reply_info* rep, struct alloc_cache* alloc,
} }
return cp; return cp;
} }
struct ub_packed_rrset_key*
reply_find_answer_rrset(struct query_info* qinfo, struct reply_info* rep)
{
uint8_t* sname = qinfo->qname;
size_t snamelen = qinfo->qname_len;
size_t i;
for(i=0; i<rep->an_numrrsets; i++) {
struct ub_packed_rrset_key* s = rep->rrsets[i];
/* first match type, for query of qtype cname */
if(ntohs(s->rk.type) == qinfo->qtype &&
ntohs(s->rk.rrset_class) == qinfo->qclass &&
snamelen == s->rk.dname_len &&
query_dname_compare(sname, s->rk.dname) == 0) {
return s;
}
/* follow CNAME chain (if any) */
if(ntohs(s->rk.type) == LDNS_RR_TYPE_CNAME &&
ntohs(s->rk.rrset_class) == qinfo->qclass &&
snamelen == s->rk.dname_len &&
query_dname_compare(sname, s->rk.dname) == 0) {
get_cname_target(s, &sname, &snamelen);
}
}
return NULL;
}

View file

@ -290,4 +290,14 @@ struct msgreply_entry* query_info_entrysetup(struct query_info* q,
struct reply_info* reply_info_copy(struct reply_info* rep, struct reply_info* reply_info_copy(struct reply_info* rep,
struct alloc_cache* alloc, struct region* region); struct alloc_cache* alloc, struct region* region);
/**
* Find answer rrset in reply, the one matching qinfo. Follows CNAMEs, so the
* result may have a different owner name.
* @param qinfo: what to look for.
* @param rep: looks in answer section of this message.
* @return: pointer to rrset, or NULL if not found.
*/
struct ub_packed_rrset_key* reply_find_answer_rrset(struct query_info* qinfo,
struct reply_info* rep);
#endif /* UTIL_DATA_MSGREPLY_H */ #endif /* UTIL_DATA_MSGREPLY_H */

View file

@ -105,7 +105,7 @@ ub_rrset_compare(void* k1, void* k2)
return -1; return -1;
return 1; return 1;
} }
if((c=memcmp(key1->rk.dname, key2->rk.dname, key1->rk.dname_len)) != 0) if((c=query_dname_compare(key1->rk.dname, key2->rk.dname)) != 0)
return c; return c;
if(key1->rk.rrset_class != key2->rk.rrset_class) { if(key1->rk.rrset_class != key2->rk.rrset_class) {
if(key1->rk.rrset_class < key2->rk.rrset_class) if(key1->rk.rrset_class < key2->rk.rrset_class)