- Fix that CD flag disables DNS64 processing, returning the DNSSEC

signed AAAA denial.


git-svn-id: file:///svn/unbound/trunk@3273 be551aaa-1e26-0410-a405-d3ace91eadb9
This commit is contained in:
Wouter Wijngaards 2014-11-18 15:15:57 +00:00
parent fcfbfe4030
commit b781f2d48d
19 changed files with 134 additions and 71 deletions

View file

@ -664,7 +664,7 @@ load_msg(SSL* ssl, sldns_buffer* buf, struct worker* worker)
if(!go_on)
return 1; /* skip this one, not all references satisfied */
if(!dns_cache_store(&worker->env, &qinf, &rep, 0, 0, 0, NULL)) {
if(!dns_cache_store(&worker->env, &qinf, &rep, 0, 0, 0, NULL, flags)) {
log_warn("error out of memory");
return 0;
}

View file

@ -1095,8 +1095,13 @@ do_cache_remove(struct worker* worker, uint8_t* nm, size_t nmlen,
k.qname_len = nmlen;
k.qtype = t;
k.qclass = c;
h = query_info_hash(&k);
h = query_info_hash(&k, 0);
slabhash_remove(worker->env.msg_cache, h, &k);
if(t == LDNS_RR_TYPE_AAAA) {
/* for AAAA also flush dns64 bit_cd packet */
h = query_info_hash(&k, BIT_CD);
slabhash_remove(worker->env.msg_cache, h, &k);
}
}
/** flush a type */

View file

@ -935,7 +935,7 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
&repinfo->addr, repinfo->addrlen);
goto send_reply;
}
h = query_info_hash(&qinfo);
h = query_info_hash(&qinfo, sldns_buffer_read_u16_at(c->buffer, 2));
if((e=slabhash_lookup(worker->env.msg_cache, h, &qinfo, 0))) {
/* answer from cache - we have acquired a readlock on it */
if(answer_from_cache(worker, &qinfo,

View file

@ -399,7 +399,7 @@ handle_ipv6_ptr(struct module_qstate* qstate, int id)
/* Create the new sub-query. */
fptr_ok(fptr_whitelist_modenv_attach_sub(qstate->env->attach_sub));
if(!(*qstate->env->attach_sub)(qstate, &qinfo, qstate->query_flags, 0,
if(!(*qstate->env->attach_sub)(qstate, &qinfo, qstate->query_flags, 0, 0,
&subq))
return module_error;
if (subq) {
@ -451,7 +451,7 @@ generate_type_A_query(struct module_qstate* qstate, int id)
/* Start the sub-query. */
fptr_ok(fptr_whitelist_modenv_attach_sub(qstate->env->attach_sub));
if(!(*qstate->env->attach_sub)(qstate, &qinfo, qstate->query_flags, 0,
&subq))
0, &subq))
{
verbose(VERB_ALGO, "dns64: sub-query creation failed");
return module_error;
@ -520,11 +520,13 @@ handle_event_moddone(struct module_qstate* qstate, int id)
*
* - An internal query.
* - A query for a record type other than AAAA.
* - CD FLAG was set on querier
* - An AAAA query for which an error was returned.
* - A successful AAAA query with an answer.
*/
if ( (enum dns64_qstate)qstate->minfo[id] == DNS64_INTERNAL_QUERY
|| qstate->qinfo.qtype != LDNS_RR_TYPE_AAAA
|| (qstate->query_flags & BIT_CD)
|| qstate->return_rcode != LDNS_RCODE_NOERROR
|| (qstate->return_msg &&
qstate->return_msg->rep &&
@ -813,7 +815,7 @@ dns64_inform_super(struct module_qstate* qstate, int id,
/* Store the generated response in cache. */
if (!dns_cache_store(super->env, &super->qinfo, super->return_msg->rep,
0, 0, 0, NULL))
0, 0, 0, NULL, super->query_flags))
log_err("out of memory");
}

View file

@ -1,3 +1,7 @@
18 November 2014: Wouter
- Fix that CD flag disables DNS64 processing, returning the DNSSEC
signed AAAA denial.
17 November 2014: Wouter
- Fix #627: SSL_CTX_load_verify_locations return code not properly
checked.

View file

@ -425,10 +425,10 @@ dns_copy_msg(struct dns_msg* from, struct regional* region)
void
iter_dns_store(struct module_env* env, struct query_info* msgqinf,
struct reply_info* msgrep, int is_referral, time_t leeway, int pside,
struct regional* region)
struct regional* region, uint16_t flags)
{
if(!dns_cache_store(env, msgqinf, msgrep, is_referral, leeway,
pside, region))
pside, region, flags))
log_err("out of memory: cannot store data in cache");
}
@ -457,7 +457,8 @@ causes_cycle(struct module_qstate* qstate, uint8_t* name, size_t namelen,
fptr_ok(fptr_whitelist_modenv_detect_cycle(
qstate->env->detect_cycle));
return (*qstate->env->detect_cycle)(qstate, &qinf,
(uint16_t)(BIT_RD|BIT_CD), qstate->is_priming);
(uint16_t)(BIT_RD|BIT_CD), qstate->is_priming,
qstate->is_valrec);
}
void

View file

@ -124,6 +124,7 @@ struct dns_msg* dns_copy_msg(struct dns_msg* from, struct regional* regional);
* @param pside: true if dp is parentside, thus message is 'fresh' and NS
* can be prefetch-updates.
* @param region: to copy modified (cache is better) rrs back to.
* @param flags: with BIT_CD for dns64 AAAA translated queries.
* @return void, because we are not interested in alloc errors,
* the iterator and validator can operate on the results in their
* scratch space (the qstate.region) and are not dependent on the cache.
@ -132,7 +133,7 @@ struct dns_msg* dns_copy_msg(struct dns_msg* from, struct regional* regional);
*/
void iter_dns_store(struct module_env* env, struct query_info* qinf,
struct reply_info* rep, int is_referral, time_t leeway, int pside,
struct regional* region);
struct regional* region, uint16_t flags);
/**
* Select randomly with n/m probability.

View file

@ -257,7 +257,7 @@ error_response_cache(struct module_qstate* qstate, int id, int rcode)
verbose(VERB_ALGO, "error response for prefetch in cache");
/* attempt to adjust the cache entry prefetch */
if(dns_cache_prefetch_adjust(qstate->env, &qstate->qinfo,
NORR_TTL))
NORR_TTL, qstate->query_flags))
return error_response(qstate, id, rcode);
/* if that fails (not in cache), fall through to store err */
}
@ -270,7 +270,8 @@ error_response_cache(struct module_qstate* qstate, int id, int rcode)
/* do not waste time trying to validate this servfail */
err.security = sec_status_indeterminate;
verbose(VERB_ALGO, "store error response in message cache");
iter_dns_store(qstate->env, &qstate->qinfo, &err, 0, 0, 0, NULL);
iter_dns_store(qstate->env, &qstate->qinfo, &err, 0, 0, 0, NULL,
qstate->query_flags);
return error_response(qstate, id, rcode);
}
@ -504,7 +505,8 @@ generate_sub_request(uint8_t* qname, size_t qnamelen, uint16_t qtype,
/* attach subquery, lookup existing or make a new one */
fptr_ok(fptr_whitelist_modenv_attach_sub(qstate->env->attach_sub));
if(!(*qstate->env->attach_sub)(qstate, &qinf, qflags, prime, &subq)) {
if(!(*qstate->env->attach_sub)(qstate, &qinf, qflags, prime, 0,
&subq)) {
return 0;
}
*subq_ret = subq;
@ -938,7 +940,8 @@ processInitRequest(struct module_qstate* qstate, struct iter_qstate* iq,
} else {
msg = dns_cache_lookup(qstate->env, iq->qchase.qname,
iq->qchase.qname_len, iq->qchase.qtype,
iq->qchase.qclass, qstate->region, qstate->env->scratch);
iq->qchase.qclass, qstate->query_flags,
qstate->region, qstate->env->scratch);
if(!msg && qstate->env->neg_cache) {
/* lookup in negative cache; may result in
* NOERROR/NODATA or NXDOMAIN answers that need validation */
@ -1991,7 +1994,7 @@ processQueryResponse(struct module_qstate* qstate, struct iter_qstate* iq,
iter_dns_store(qstate->env, &iq->response->qinfo,
iq->response->rep, 0, qstate->prefetch_leeway,
iq->dp&&iq->dp->has_parent_side_NS,
qstate->region);
qstate->region, qstate->query_flags);
/* close down outstanding requests to be discarded */
outbound_list_clear(&iq->outlist);
iq->num_current_queries = 0;
@ -2029,7 +2032,7 @@ processQueryResponse(struct module_qstate* qstate, struct iter_qstate* iq,
/* Store the referral under the current query */
/* no prefetch-leeway, since its not the answer */
iter_dns_store(qstate->env, &iq->response->qinfo,
iq->response->rep, 1, 0, 0, NULL);
iq->response->rep, 1, 0, 0, NULL, 0);
if(iq->store_parent_NS)
iter_store_parentside_NS(qstate->env,
iq->response->rep);
@ -2128,7 +2131,8 @@ processQueryResponse(struct module_qstate* qstate, struct iter_qstate* iq,
/* prefetchleeway applied because this updates answer parts */
iter_dns_store(qstate->env, &iq->response->qinfo,
iq->response->rep, 1, qstate->prefetch_leeway,
iq->dp&&iq->dp->has_parent_side_NS, NULL);
iq->dp&&iq->dp->has_parent_side_NS, NULL,
qstate->query_flags);
/* set the current request's qname to the new value. */
iq->qchase.qname = sname;
iq->qchase.qname_len = snamelen;
@ -2209,7 +2213,7 @@ processQueryResponse(struct module_qstate* qstate, struct iter_qstate* iq,
}
/**
* Return priming query results to interestes super querystates.
* Return priming query results to interested super querystates.
*
* Sets the delegation point and delegation message (not nonRD queries).
* This is a callback from walk_supers.
@ -2640,7 +2644,7 @@ processFinished(struct module_qstate* qstate, struct iter_qstate* iq,
iter_dns_store(qstate->env, &qstate->qinfo,
iq->response->rep, 0, qstate->prefetch_leeway,
iq->dp&&iq->dp->has_parent_side_NS,
qstate->region);
qstate->region, qstate->query_flags);
}
}
qstate->return_rcode = LDNS_RCODE_NOERROR;

View file

@ -67,7 +67,7 @@ int storeQueryInCache(struct module_qstate* qstate, struct query_info* qinfo, st
}
return dns_cache_store(qstate->env, qinfo, msgrep, is_referral,
qstate->prefetch_leeway, 0, NULL);
qstate->prefetch_leeway, 0, NULL, qstate->query_flags);
}
/* Invalidate the message associated with query_info stored in message cache */
@ -78,7 +78,7 @@ void invalidateQueryInCache(struct module_qstate* qstate, struct query_info* qin
struct reply_info *r;
size_t i, j;
h = query_info_hash(qinfo);
h = query_info_hash(qinfo, qstate->query_flags);
if ((e=slabhash_lookup(qstate->env->msg_cache, h, qinfo, 0)))
{
r = (struct reply_info*)(e->data);

34
services/cache/dns.c vendored
View file

@ -184,7 +184,7 @@ addr_to_additional(struct ub_packed_rrset_key* rrset, struct regional* region,
/** lookup message in message cache */
static struct msgreply_entry*
msg_cache_lookup(struct module_env* env, uint8_t* qname, size_t qnamelen,
uint16_t qtype, uint16_t qclass, time_t now, int wr)
uint16_t qtype, uint16_t qclass, uint16_t flags, time_t now, int wr)
{
struct lruhash_entry* e;
struct query_info k;
@ -194,7 +194,7 @@ msg_cache_lookup(struct module_env* env, uint8_t* qname, size_t qnamelen,
k.qname_len = qnamelen;
k.qtype = qtype;
k.qclass = qclass;
h = query_info_hash(&k);
h = query_info_hash(&k, flags);
e = slabhash_lookup(env->msg_cache, h, &k, wr);
if(!e) return NULL;
@ -226,8 +226,10 @@ find_add_addrs(struct module_env* env, uint16_t qclass,
addr_to_additional(akey, region, *msg, now);
lock_rw_unlock(&akey->entry.lock);
} else {
/* BIT_CD on false because delegpt lookup does
* not use dns64 translation */
neg = msg_cache_lookup(env, ns->name, ns->namelen,
LDNS_RR_TYPE_A, qclass, now, 0);
LDNS_RR_TYPE_A, qclass, 0, now, 0);
if(neg) {
delegpt_add_neg_msg(dp, neg);
lock_rw_unlock(&neg->entry.lock);
@ -244,8 +246,10 @@ find_add_addrs(struct module_env* env, uint16_t qclass,
addr_to_additional(akey, region, *msg, now);
lock_rw_unlock(&akey->entry.lock);
} else {
/* BIT_CD on false because delegpt lookup does
* not use dns64 translation */
neg = msg_cache_lookup(env, ns->name, ns->namelen,
LDNS_RR_TYPE_AAAA, qclass, now, 0);
LDNS_RR_TYPE_AAAA, qclass, 0, now, 0);
if(neg) {
delegpt_add_neg_msg(dp, neg);
lock_rw_unlock(&neg->entry.lock);
@ -276,8 +280,10 @@ cache_fill_missing(struct module_env* env, uint16_t qclass,
ns->name, LDNS_RR_TYPE_A, qclass);
lock_rw_unlock(&akey->entry.lock);
} else {
/* BIT_CD on false because delegpt lookup does
* not use dns64 translation */
neg = msg_cache_lookup(env, ns->name, ns->namelen,
LDNS_RR_TYPE_A, qclass, now, 0);
LDNS_RR_TYPE_A, qclass, 0, now, 0);
if(neg) {
delegpt_add_neg_msg(dp, neg);
lock_rw_unlock(&neg->entry.lock);
@ -294,8 +300,10 @@ cache_fill_missing(struct module_env* env, uint16_t qclass,
ns->name, LDNS_RR_TYPE_AAAA, qclass);
lock_rw_unlock(&akey->entry.lock);
} else {
/* BIT_CD on false because delegpt lookup does
* not use dns64 translation */
neg = msg_cache_lookup(env, ns->name, ns->namelen,
LDNS_RR_TYPE_AAAA, qclass, now, 0);
LDNS_RR_TYPE_AAAA, qclass, 0, now, 0);
if(neg) {
delegpt_add_neg_msg(dp, neg);
lock_rw_unlock(&neg->entry.lock);
@ -626,7 +634,7 @@ synth_dname_msg(struct ub_packed_rrset_key* rrset, struct regional* region,
struct dns_msg*
dns_cache_lookup(struct module_env* env,
uint8_t* qname, size_t qnamelen, uint16_t qtype, uint16_t qclass,
struct regional* region, struct regional* scratch)
uint16_t flags, struct regional* region, struct regional* scratch)
{
struct lruhash_entry* e;
struct query_info k;
@ -639,7 +647,7 @@ dns_cache_lookup(struct module_env* env,
k.qname_len = qnamelen;
k.qtype = qtype;
k.qclass = qclass;
h = query_info_hash(&k);
h = query_info_hash(&k, flags);
e = slabhash_lookup(env->msg_cache, h, &k, 0);
if(e) {
struct msgreply_entry* key = (struct msgreply_entry*)e->key;
@ -716,7 +724,7 @@ dns_cache_lookup(struct module_env* env,
if(env->cfg->harden_below_nxdomain)
while(!dname_is_root(k.qname)) {
dname_remove_label(&k.qname, &k.qname_len);
h = query_info_hash(&k);
h = query_info_hash(&k, flags);
e = slabhash_lookup(env->msg_cache, h, &k, 0);
if(e) {
struct reply_info* data = (struct reply_info*)e->data;
@ -741,7 +749,7 @@ dns_cache_lookup(struct module_env* env,
int
dns_cache_store(struct module_env* env, struct query_info* msgqinf,
struct reply_info* msgrep, int is_referral, time_t leeway, int pside,
struct regional* region)
struct regional* region, uint16_t flags)
{
struct reply_info* rep = NULL;
/* alloc, malloc properly (not in region, like msg is) */
@ -786,7 +794,7 @@ dns_cache_store(struct module_env* env, struct query_info* msgqinf,
* Not AA from cache. Not CD in cache (depends on client bit). */
rep->flags |= (BIT_RA | BIT_QR);
rep->flags &= ~(BIT_AA | BIT_CD);
h = query_info_hash(&qinf);
h = query_info_hash(&qinf, flags);
dns_cache_store_msg(env, &qinf, h, rep, leeway, pside, msgrep,
region);
/* qname is used inside query_info_entrysetup, and set to
@ -798,11 +806,11 @@ dns_cache_store(struct module_env* env, struct query_info* msgqinf,
int
dns_cache_prefetch_adjust(struct module_env* env, struct query_info* qinfo,
time_t adjust)
time_t adjust, uint16_t flags)
{
struct msgreply_entry* msg;
msg = msg_cache_lookup(env, qinfo->qname, qinfo->qname_len,
qinfo->qtype, qinfo->qclass, *env->now, 1);
qinfo->qtype, qinfo->qclass, flags, *env->now, 1);
if(msg) {
struct reply_info* rep = (struct reply_info*)msg->entry.data;
if(rep) {

View file

@ -79,11 +79,12 @@ struct dns_msg {
* can be updated to full TTL even in prefetch situations.
* @param region: region to allocate better entries from cache into.
* (used when is_referral is false).
* @param flags: flags with BIT_CD for AAAA queries in dns64 translation.
* @return 0 on alloc error (out of memory).
*/
int dns_cache_store(struct module_env* env, struct query_info* qinf,
struct reply_info* rep, int is_referral, time_t leeway, int pside,
struct regional* region);
struct regional* region, uint16_t flags);
/**
* Store message in the cache. Stores in message cache and rrset cache.
@ -132,6 +133,7 @@ struct delegpt* dns_cache_find_delegation(struct module_env* env,
* @param qnamelen: length of qname.
* @param qtype: query type.
* @param qclass: query class.
* @param flags: flags with BIT_CD for AAAA queries in dns64 translation.
* @param region: where to allocate result.
* @param scratch: where to allocate temporary data.
* @return new response message (alloced in region, rrsets do not have IDs).
@ -140,7 +142,7 @@ struct delegpt* dns_cache_find_delegation(struct module_env* env,
*/
struct dns_msg* dns_cache_lookup(struct module_env* env,
uint8_t* qname, size_t qnamelen, uint16_t qtype, uint16_t qclass,
struct regional* region, struct regional* scratch);
uint16_t flags, struct regional* region, struct regional* scratch);
/**
* find and add A and AAAA records for missing nameservers in delegpt
@ -186,9 +188,10 @@ int dns_msg_authadd(struct dns_msg* msg, struct regional* region,
* @param env: module environment with caches and time.
* @param qinfo: query info for the query that needs adjustment.
* @param adjust: time in seconds to add to the prefetch_leeway.
* @param flags: flags with BIT_CD for AAAA queries in dns64 translation.
* @return false if not in cache. true if added.
*/
int dns_cache_prefetch_adjust(struct module_env* env, struct query_info* qinfo,
time_t adjust);
time_t adjust, uint16_t flags);
#endif /* SERVICES_CACHE_DNS_H */

View file

@ -132,6 +132,11 @@ mesh_state_compare(const void* ap, const void* bp)
if(!a->s.is_priming && b->s.is_priming)
return 1;
if(a->s.is_valrec && !b->s.is_valrec)
return -1;
if(!a->s.is_valrec && b->s.is_valrec)
return 1;
if((a->s.query_flags&BIT_RD) && !(b->s.query_flags&BIT_RD))
return -1;
if(!(a->s.query_flags&BIT_RD) && (b->s.query_flags&BIT_RD))
@ -277,11 +282,7 @@ void mesh_new_client(struct mesh_area* mesh, struct query_info* qinfo,
uint16_t qflags, struct edns_data* edns, struct comm_reply* rep,
uint16_t qid)
{
/* do not use CD flag from user for mesh state, we want the CD-query
* to receive validation anyway, to protect out cache contents and
* avoid bad-data in this cache that a downstream validator cannot
* remove from this cache */
struct mesh_state* s = mesh_area_find(mesh, qinfo, qflags&BIT_RD, 0);
struct mesh_state* s = mesh_area_find(mesh, qinfo, qflags&BIT_RD, 0, 0);
int was_detached = 0;
int was_noreply = 0;
int added = 0;
@ -311,7 +312,7 @@ void mesh_new_client(struct mesh_area* mesh, struct query_info* qinfo,
#ifdef UNBOUND_DEBUG
struct rbnode_t* n;
#endif
s = mesh_state_create(mesh->env, qinfo, qflags&BIT_RD, 0);
s = mesh_state_create(mesh->env, qinfo, qflags&BIT_RD, 0, 0);
if(!s) {
log_err("mesh_state_create: out of memory; SERVFAIL");
error_encode(rep->c->buffer, LDNS_RCODE_SERVFAIL,
@ -375,7 +376,7 @@ mesh_new_callback(struct mesh_area* mesh, struct query_info* qinfo,
uint16_t qflags, struct edns_data* edns, sldns_buffer* buf,
uint16_t qid, mesh_cb_func_t cb, void* cb_arg)
{
struct mesh_state* s = mesh_area_find(mesh, qinfo, qflags&BIT_RD, 0);
struct mesh_state* s = mesh_area_find(mesh, qinfo, qflags&BIT_RD, 0, 0);
int was_detached = 0;
int was_noreply = 0;
int added = 0;
@ -386,7 +387,7 @@ mesh_new_callback(struct mesh_area* mesh, struct query_info* qinfo,
#ifdef UNBOUND_DEBUG
struct rbnode_t* n;
#endif
s = mesh_state_create(mesh->env, qinfo, qflags&BIT_RD, 0);
s = mesh_state_create(mesh->env, qinfo, qflags&BIT_RD, 0, 0);
if(!s) {
return 0;
}
@ -428,7 +429,7 @@ mesh_new_callback(struct mesh_area* mesh, struct query_info* qinfo,
void mesh_new_prefetch(struct mesh_area* mesh, struct query_info* qinfo,
uint16_t qflags, time_t leeway)
{
struct mesh_state* s = mesh_area_find(mesh, qinfo, qflags&BIT_RD, 0);
struct mesh_state* s = mesh_area_find(mesh, qinfo, qflags&BIT_RD, 0, 0);
#ifdef UNBOUND_DEBUG
struct rbnode_t* n;
#endif
@ -447,7 +448,7 @@ void mesh_new_prefetch(struct mesh_area* mesh, struct query_info* qinfo,
mesh->stats_dropped ++;
return;
}
s = mesh_state_create(mesh->env, qinfo, qflags&BIT_RD, 0);
s = mesh_state_create(mesh->env, qinfo, qflags&BIT_RD, 0, 0);
if(!s) {
log_err("prefetch mesh_state_create: out of memory");
return;
@ -496,7 +497,7 @@ void mesh_report_reply(struct mesh_area* mesh, struct outbound_entry* e,
struct mesh_state*
mesh_state_create(struct module_env* env, struct query_info* qinfo,
uint16_t qflags, int prime)
uint16_t qflags, int prime, int valrec)
{
struct regional* region = alloc_reg_obtain(env->alloc);
struct mesh_state* mstate;
@ -533,6 +534,7 @@ mesh_state_create(struct module_env* env, struct query_info* qinfo,
/* remove all weird bits from qflags */
mstate->s.query_flags = (qflags & (BIT_RD|BIT_CD));
mstate->s.is_priming = prime;
mstate->s.is_valrec = valrec;
mstate->s.reply = NULL;
mstate->s.region = region;
mstate->s.curmod = 0;
@ -679,12 +681,14 @@ void mesh_detach_subs(struct module_qstate* qstate)
}
int mesh_attach_sub(struct module_qstate* qstate, struct query_info* qinfo,
uint16_t qflags, int prime, struct module_qstate** newq)
uint16_t qflags, int prime, int valrec, struct module_qstate** newq)
{
/* find it, if not, create it */
struct mesh_area* mesh = qstate->env->mesh;
struct mesh_state* sub = mesh_area_find(mesh, qinfo, qflags, prime);
struct mesh_state* sub = mesh_area_find(mesh, qinfo, qflags, prime,
valrec);
int was_detached;
log_info("mesh attach sub: myvalrec is %d", qstate->is_valrec);
if(mesh_detect_cycle_found(qstate, sub)) {
verbose(VERB_ALGO, "attach failed, cycle detected");
return 0;
@ -694,7 +698,8 @@ int mesh_attach_sub(struct module_qstate* qstate, struct query_info* qinfo,
struct rbnode_t* n;
#endif
/* create a new one */
sub = mesh_state_create(qstate->env, qinfo, qflags, prime);
sub = mesh_state_create(qstate->env, qinfo, qflags, prime,
valrec);
if(!sub) {
log_err("mesh_attach_sub: out of memory");
return 0;
@ -941,13 +946,14 @@ void mesh_walk_supers(struct mesh_area* mesh, struct mesh_state* mstate)
}
struct mesh_state* mesh_area_find(struct mesh_area* mesh,
struct query_info* qinfo, uint16_t qflags, int prime)
struct query_info* qinfo, uint16_t qflags, int prime, int valrec)
{
struct mesh_state key;
struct mesh_state* result;
key.node.key = &key;
key.s.is_priming = prime;
key.s.is_valrec = valrec;
key.s.qinfo = *qinfo;
key.s.query_flags = qflags;
@ -1107,8 +1113,9 @@ mesh_log_list(struct mesh_area* mesh)
struct mesh_state* m;
int num = 0;
RBTREE_FOR(m, struct mesh_state*, &mesh->all) {
snprintf(buf, sizeof(buf), "%d%s%s%s%s%s mod%d %s%s",
snprintf(buf, sizeof(buf), "%d%s%s%s%s%s%s mod%d %s%s",
num++, (m->s.is_priming)?"p":"", /* prime */
(m->s.is_valrec)?"v":"", /* prime */
(m->s.query_flags&BIT_RD)?"RD":"",
(m->s.query_flags&BIT_CD)?"CD":"",
(m->super_set.count==0)?"d":"", /* detached */
@ -1178,10 +1185,11 @@ mesh_get_mem(struct mesh_area* mesh)
int
mesh_detect_cycle(struct module_qstate* qstate, struct query_info* qinfo,
uint16_t flags, int prime)
uint16_t flags, int prime, int valrec)
{
struct mesh_area* mesh = qstate->env->mesh;
struct mesh_state* dep_m = mesh_area_find(mesh, qinfo, flags, prime);
struct mesh_state* dep_m = mesh_area_find(mesh, qinfo, flags, prime,
valrec);
return mesh_detect_cycle_found(qstate, dep_m);
}

View file

@ -353,12 +353,13 @@ void mesh_detach_subs(struct module_qstate* qstate);
* @param qinfo: what to query for (copied).
* @param qflags: what flags to use (RD / CD flag or not).
* @param prime: if it is a (stub) priming query.
* @param valrec: if it is a validation recursion query (lookup of key, DS).
* @param newq: If the new subquery needs initialisation, it is returned,
* otherwise NULL is returned.
* @return: false on error, true if success (and init may be needed).
*/
int mesh_attach_sub(struct module_qstate* qstate, struct query_info* qinfo,
uint16_t qflags, int prime, struct module_qstate** newq);
uint16_t qflags, int prime, int valrec, struct module_qstate** newq);
/**
* Query state is done, send messages to reply entries.
@ -406,10 +407,12 @@ void mesh_state_delete(struct module_qstate* qstate);
* @param qinfo: query info that the mesh is for.
* @param qflags: flags for query (RD / CD flag).
* @param prime: if true, it is a priming query, set is_priming on mesh state.
* @param valrec: if true, it is a validation recursion query, and sets
* is_valrec on the mesh state.
* @return: new mesh state or NULL on allocation error.
*/
struct mesh_state* mesh_state_create(struct module_env* env,
struct query_info* qinfo, uint16_t qflags, int prime);
struct query_info* qinfo, uint16_t qflags, int prime, int valrec);
/**
* Cleanup a mesh state and its query state. Does not do rbtree or
@ -432,10 +435,11 @@ void mesh_delete_all(struct mesh_area* mesh);
* @param qinfo: what query
* @param qflags: if RD / CD bit is set or not.
* @param prime: if it is a priming query.
* @param valrec: if it is a validation-recursion query.
* @return: mesh state or NULL if not found.
*/
struct mesh_state* mesh_area_find(struct mesh_area* mesh,
struct query_info* qinfo, uint16_t qflags, int prime);
struct query_info* qinfo, uint16_t qflags, int prime, int valrec);
/**
* Setup attachment super/sub relation between super and sub mesh state.
@ -523,13 +527,14 @@ size_t mesh_get_mem(struct mesh_area* mesh);
* @param qinfo: query info for dependency.
* @param flags: query flags of dependency.
* @param prime: if dependency is a priming query or not.
* @param valrec: if it is a validation recursion query (lookup of key, DS).
* @return true if the name,type,class exists and the given qstate mesh exists
* as a dependency of that name. Thus if qstate becomes dependent on
* name,type,class then a cycle is created, this is return value 1.
* Too large to search is value 2 (also true).
*/
int mesh_detect_cycle(struct module_qstate* qstate, struct query_info* qinfo,
uint16_t flags, int prime);
uint16_t flags, int prime, int valrec);
/** compare two mesh_states */
int mesh_state_compare(const void* ap, const void* bp);

View file

@ -576,10 +576,12 @@ reply_info_delete(void* d, void* ATTR_UNUSED(arg))
}
hashvalue_t
query_info_hash(struct query_info *q)
query_info_hash(struct query_info *q, uint16_t flags)
{
hashvalue_t h = 0xab;
h = hashlittle(&q->qtype, sizeof(q->qtype), h);
if(q->qtype == LDNS_RR_TYPE_AAAA && (flags&BIT_CD))
h++;
h = hashlittle(&q->qclass, sizeof(q->qclass), h);
h = dname_query_hash(q->qname, h);
return h;

View file

@ -305,8 +305,9 @@ void query_entry_delete(void *q, void* arg);
/** delete reply_info data structure */
void reply_info_delete(void* d, void* arg);
/** calculate hash value of query_info, lowercases the qname */
hashvalue_t query_info_hash(struct query_info *q);
/** calculate hash value of query_info, lowercases the qname,
* uses CD flag for AAAA qtype */
hashvalue_t query_info_hash(struct query_info *q, uint16_t flags);
/**
* Setup query info entry

View file

@ -280,7 +280,7 @@ fptr_whitelist_modenv_detach_subs(void (*fptr)(
int
fptr_whitelist_modenv_attach_sub(int (*fptr)(
struct module_qstate* qstate, struct query_info* qinfo,
uint16_t qflags, int prime, struct module_qstate** newq))
uint16_t qflags, int prime, int valrec, struct module_qstate** newq))
{
if(fptr == &mesh_attach_sub) return 1;
return 0;
@ -296,7 +296,7 @@ fptr_whitelist_modenv_kill_sub(void (*fptr)(struct module_qstate* newq))
int
fptr_whitelist_modenv_detect_cycle(int (*fptr)(
struct module_qstate* qstate, struct query_info* qinfo,
uint16_t flags, int prime))
uint16_t flags, int prime, int valrec))
{
if(fptr == &mesh_detect_cycle) return 1;
return 0;

View file

@ -233,7 +233,7 @@ int fptr_whitelist_modenv_detach_subs(void (*fptr)(
*/
int fptr_whitelist_modenv_attach_sub(int (*fptr)(
struct module_qstate* qstate, struct query_info* qinfo,
uint16_t qflags, int prime, struct module_qstate** newq));
uint16_t qflags, int prime, int valrec, struct module_qstate** newq));
/**
* Check function pointer whitelist for module_env kill_sub callback values.
@ -251,7 +251,7 @@ int fptr_whitelist_modenv_kill_sub(void (*fptr)(struct module_qstate* newq));
*/
int fptr_whitelist_modenv_detect_cycle(int (*fptr)(
struct module_qstate* qstate, struct query_info* qinfo,
uint16_t flags, int prime));
uint16_t flags, int prime, int valrec));
/**
* Check function pointer whitelist for module init call values.

View file

@ -256,13 +256,14 @@ struct module_env {
* @param qinfo: what to query for (copied).
* @param qflags: what flags to use (RD, CD flag or not).
* @param prime: if it is a (stub) priming query.
* @param valrec: validation lookup recursion, does not need validation
* @param newq: If the new subquery needs initialisation, it is
* returned, otherwise NULL is returned.
* @return: false on error, true if success (and init may be needed).
*/
int (*attach_sub)(struct module_qstate* qstate,
struct query_info* qinfo, uint16_t qflags, int prime,
struct module_qstate** newq);
int valrec, struct module_qstate** newq);
/**
* Kill newly attached sub. If attach_sub returns newq for
@ -280,13 +281,15 @@ struct module_env {
* @param qinfo: query info for dependency.
* @param flags: query flags of dependency, RD/CD flags.
* @param prime: if dependency is a priming query or not.
* @param valrec: validation lookup recursion, does not need validation
* @return true if the name,type,class exists and the given
* qstate mesh exists as a dependency of that name. Thus
* if qstate becomes dependent on name,type,class then a
* cycle is created.
*/
int (*detect_cycle)(struct module_qstate* qstate,
struct query_info* qinfo, uint16_t flags, int prime);
struct query_info* qinfo, uint16_t flags, int prime,
int valrec);
/** region for temporary usage. May be cleared after operate() call. */
struct regional* scratch;
@ -397,6 +400,9 @@ struct module_qstate {
uint16_t query_flags;
/** if this is a (stub or root) priming query (with hints) */
int is_priming;
/** if this is a validation recursion query that does not get
* validation itself */
int is_valrec;
/** comm_reply contains server replies */
struct comm_reply* reply;

View file

@ -289,6 +289,11 @@ needs_validation(struct module_qstate* qstate, int ret_rc,
verbose(VERB_ALGO, "not validating response due to CD bit");
return 0;
}
if(qstate->is_valrec) {
verbose(VERB_ALGO, "not validating response, is valrec"
"(validation recursion lookup)");
return 0;
}
if(ret_rc != LDNS_RCODE_NOERROR || !ret_msg)
rcode = ret_rc;
@ -351,14 +356,20 @@ generate_request(struct module_qstate* qstate, int id, uint8_t* name,
struct val_qstate* vq = (struct val_qstate*)qstate->minfo[id];
struct module_qstate* newq;
struct query_info ask;
int valrec;
ask.qname = name;
ask.qname_len = namelen;
ask.qtype = qtype;
ask.qclass = qclass;
log_query_info(VERB_ALGO, "generate request", &ask);
fptr_ok(fptr_whitelist_modenv_attach_sub(qstate->env->attach_sub));
/* enable valrec flag to avoid recursion to the same validation
* routine, this lookup is simply a lookup. DLVs need validation */
if(qtype == LDNS_RR_TYPE_DLV)
valrec = 0;
else valrec = 1;
if(!(*qstate->env->attach_sub)(qstate, &ask,
(uint16_t)(BIT_RD|flags), 0, &newq)){
(uint16_t)(BIT_RD|flags), 0, valrec, &newq)){
log_err("Could not generate request: out of memory");
return 0;
}
@ -2005,14 +2016,16 @@ processFinished(struct module_qstate* qstate, struct val_qstate* vq,
/* if secure, this will override cache anyway, no need
* to check if from parentNS */
if(!dns_cache_store(qstate->env, &vq->orig_msg->qinfo,
vq->orig_msg->rep, 0, qstate->prefetch_leeway, 0, NULL)) {
vq->orig_msg->rep, 0, qstate->prefetch_leeway, 0, NULL,
qstate->query_flags)) {
log_err("out of memory caching validator results");
}
} else {
/* for a referral, store the verified RRsets */
/* and this does not get prefetched, so no leeway */
if(!dns_cache_store(qstate->env, &vq->orig_msg->qinfo,
vq->orig_msg->rep, 1, 0, 0, NULL)) {
vq->orig_msg->rep, 1, 0, 0, NULL,
qstate->query_flags)) {
log_err("out of memory caching validator results");
}
}