mirror of
https://github.com/NLnetLabs/unbound.git
synced 2025-12-20 23:00:56 -05:00
Process target responses, case preservation.
git-svn-id: file:///svn/unbound/trunk@365 be551aaa-1e26-0410-a405-d3ace91eadb9
This commit is contained in:
parent
81ae42fde0
commit
5eef2381f0
9 changed files with 147 additions and 10 deletions
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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.
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
3
services/cache/infra.c
vendored
3
services/cache/infra.c
vendored
|
|
@ -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 */
|
||||||
|
|
|
||||||
|
|
@ -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) {
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -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 */
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue