summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorbrad <brad@openbsd.org>2014-11-20 01:15:19 +0000
committerbrad <brad@openbsd.org>2014-11-20 01:15:19 +0000
commit57dceb2ad237b1be94c59b1f61603df290bce807 (patch)
treebb15ccd94f4111e581c1dd2e8c9f9342242b702c
parentFix two minibugs reported by Thomas Klausner <wiz at NetBSD>: (diff)
downloadwireguard-openbsd-57dceb2ad237b1be94c59b1f61603df290bce807.tar.xz
wireguard-openbsd-57dceb2ad237b1be94c59b1f61603df290bce807.zip
Merge in some commits from upstream..
- Removed 'increased limit open files' log message that is written to console. It is only written on verbosity 4 and higher. This keeps system bootup console cleaner. - Fix #627: SSL_CTX_load_verify_locations return code not properly checked. - Fix that CD flag disables DNS64 processing, returning the DNSSEC signed AAAA denial. - Fix cdflag dns64 processing. ok sthen@
-rw-r--r--usr.sbin/unbound/daemon/cachedump.c2
-rw-r--r--usr.sbin/unbound/daemon/remote.c7
-rw-r--r--usr.sbin/unbound/daemon/unbound.c2
-rw-r--r--usr.sbin/unbound/daemon/worker.c2
-rw-r--r--usr.sbin/unbound/dns64/dns64.c8
-rw-r--r--usr.sbin/unbound/iterator/iter_utils.c7
-rw-r--r--usr.sbin/unbound/iterator/iter_utils.h3
-rw-r--r--usr.sbin/unbound/iterator/iterator.c27
-rw-r--r--usr.sbin/unbound/services/cache/dns.c34
-rw-r--r--usr.sbin/unbound/services/cache/dns.h9
-rw-r--r--usr.sbin/unbound/services/mesh.c43
-rw-r--r--usr.sbin/unbound/services/mesh.h13
-rw-r--r--usr.sbin/unbound/util/data/msgreply.c4
-rw-r--r--usr.sbin/unbound/util/data/msgreply.h5
-rw-r--r--usr.sbin/unbound/util/fptr_wlist.c4
-rw-r--r--usr.sbin/unbound/util/fptr_wlist.h4
-rw-r--r--usr.sbin/unbound/util/module.h10
-rw-r--r--usr.sbin/unbound/util/net_help.c2
-rw-r--r--usr.sbin/unbound/validator/validator.c31
19 files changed, 143 insertions, 74 deletions
diff --git a/usr.sbin/unbound/daemon/cachedump.c b/usr.sbin/unbound/daemon/cachedump.c
index cf5b1a12c9a..20a46ae4dff 100644
--- a/usr.sbin/unbound/daemon/cachedump.c
+++ b/usr.sbin/unbound/daemon/cachedump.c
@@ -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;
}
diff --git a/usr.sbin/unbound/daemon/remote.c b/usr.sbin/unbound/daemon/remote.c
index 88ea063f21f..ecb2ab403c4 100644
--- a/usr.sbin/unbound/daemon/remote.c
+++ b/usr.sbin/unbound/daemon/remote.c
@@ -1094,8 +1094,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 */
diff --git a/usr.sbin/unbound/daemon/unbound.c b/usr.sbin/unbound/daemon/unbound.c
index a53fe954db2..5ded5a964cc 100644
--- a/usr.sbin/unbound/daemon/unbound.c
+++ b/usr.sbin/unbound/daemon/unbound.c
@@ -287,7 +287,7 @@ checkrlimits(struct config_file* cfg)
#ifdef HAVE_SETRLIMIT
}
#endif
- log_warn("increased limit(open files) from %u to %u",
+ verbose(VERB_ALGO, "increased limit(open files) from %u to %u",
(unsigned)avail, (unsigned)total+10);
}
#else
diff --git a/usr.sbin/unbound/daemon/worker.c b/usr.sbin/unbound/daemon/worker.c
index f9067621385..59ae9dfcefc 100644
--- a/usr.sbin/unbound/daemon/worker.c
+++ b/usr.sbin/unbound/daemon/worker.c
@@ -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,
diff --git a/usr.sbin/unbound/dns64/dns64.c b/usr.sbin/unbound/dns64/dns64.c
index 963e727fed7..eaaa26f7c91 100644
--- a/usr.sbin/unbound/dns64/dns64.c
+++ b/usr.sbin/unbound/dns64/dns64.c
@@ -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");
}
diff --git a/usr.sbin/unbound/iterator/iter_utils.c b/usr.sbin/unbound/iterator/iter_utils.c
index 4148c1268f7..9d0aa698f99 100644
--- a/usr.sbin/unbound/iterator/iter_utils.c
+++ b/usr.sbin/unbound/iterator/iter_utils.c
@@ -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
diff --git a/usr.sbin/unbound/iterator/iter_utils.h b/usr.sbin/unbound/iterator/iter_utils.h
index abdc68f3cd4..d7c2b68afa2 100644
--- a/usr.sbin/unbound/iterator/iter_utils.h
+++ b/usr.sbin/unbound/iterator/iter_utils.h
@@ -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.
diff --git a/usr.sbin/unbound/iterator/iterator.c b/usr.sbin/unbound/iterator/iterator.c
index df5f645cc28..843948a2e30 100644
--- a/usr.sbin/unbound/iterator/iterator.c
+++ b/usr.sbin/unbound/iterator/iterator.c
@@ -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);
}
@@ -486,6 +487,7 @@ generate_sub_request(uint8_t* qname, size_t qnamelen, uint16_t qtype,
uint16_t qflags = 0; /* OPCODE QUERY, no flags */
struct query_info qinf;
int prime = (finalstate == PRIME_RESP_STATE)?1:0;
+ int valrec = 0;
qinf.qname = qname;
qinf.qname_len = qnamelen;
qinf.qtype = qtype;
@@ -499,12 +501,15 @@ generate_sub_request(uint8_t* qname, size_t qnamelen, uint16_t qtype,
* the resolution chain, which might have a validator. We are
* uninterested in validating things not on the direct resolution
* path. */
- if(!v)
+ if(!v) {
qflags |= BIT_CD;
+ valrec = 1;
+ }
/* 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, valrec,
+ &subq)) {
return 0;
}
*subq_ret = subq;
@@ -938,7 +943,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 +1997,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 +2035,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 +2134,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 +2216,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 +2647,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;
diff --git a/usr.sbin/unbound/services/cache/dns.c b/usr.sbin/unbound/services/cache/dns.c
index c663b8e8b9a..4692744a15d 100644
--- a/usr.sbin/unbound/services/cache/dns.c
+++ b/usr.sbin/unbound/services/cache/dns.c
@@ -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) {
diff --git a/usr.sbin/unbound/services/cache/dns.h b/usr.sbin/unbound/services/cache/dns.h
index 05a3e629654..69796c2eb20 100644
--- a/usr.sbin/unbound/services/cache/dns.h
+++ b/usr.sbin/unbound/services/cache/dns.h
@@ -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 */
diff --git a/usr.sbin/unbound/services/mesh.c b/usr.sbin/unbound/services/mesh.c
index bc711d9b3ed..a69aced223e 100644
--- a/usr.sbin/unbound/services/mesh.c
+++ b/usr.sbin/unbound/services/mesh.c
@@ -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|BIT_CD), 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|BIT_CD), 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|BIT_CD), 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|BIT_CD), 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|BIT_CD), 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|BIT_CD), 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,11 +681,12 @@ 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;
if(mesh_detect_cycle_found(qstate, sub)) {
verbose(VERB_ALGO, "attach failed, cycle detected");
@@ -694,7 +697,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 +945,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 +1112,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 +1184,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);
}
diff --git a/usr.sbin/unbound/services/mesh.h b/usr.sbin/unbound/services/mesh.h
index fbfbbcb4a94..086e39094e8 100644
--- a/usr.sbin/unbound/services/mesh.h
+++ b/usr.sbin/unbound/services/mesh.h
@@ -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);
diff --git a/usr.sbin/unbound/util/data/msgreply.c b/usr.sbin/unbound/util/data/msgreply.c
index 126e7bef45b..0d2565753ba 100644
--- a/usr.sbin/unbound/util/data/msgreply.c
+++ b/usr.sbin/unbound/util/data/msgreply.c
@@ -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;
diff --git a/usr.sbin/unbound/util/data/msgreply.h b/usr.sbin/unbound/util/data/msgreply.h
index ccbd0d74838..e8d6d762e01 100644
--- a/usr.sbin/unbound/util/data/msgreply.h
+++ b/usr.sbin/unbound/util/data/msgreply.h
@@ -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
diff --git a/usr.sbin/unbound/util/fptr_wlist.c b/usr.sbin/unbound/util/fptr_wlist.c
index 3a5fc5f0611..5a77432c775 100644
--- a/usr.sbin/unbound/util/fptr_wlist.c
+++ b/usr.sbin/unbound/util/fptr_wlist.c
@@ -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;
diff --git a/usr.sbin/unbound/util/fptr_wlist.h b/usr.sbin/unbound/util/fptr_wlist.h
index 62692ba8b53..10de5d81677 100644
--- a/usr.sbin/unbound/util/fptr_wlist.h
+++ b/usr.sbin/unbound/util/fptr_wlist.h
@@ -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.
diff --git a/usr.sbin/unbound/util/module.h b/usr.sbin/unbound/util/module.h
index f95ff6dc837..b9dde36e2f3 100644
--- a/usr.sbin/unbound/util/module.h
+++ b/usr.sbin/unbound/util/module.h
@@ -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;
diff --git a/usr.sbin/unbound/util/net_help.c b/usr.sbin/unbound/util/net_help.c
index 49ce677f4aa..8c2bac7372f 100644
--- a/usr.sbin/unbound/util/net_help.c
+++ b/usr.sbin/unbound/util/net_help.c
@@ -699,7 +699,7 @@ void* connect_sslctx_create(char* key, char* pem, char* verifypem)
}
}
if(verifypem && verifypem[0]) {
- if(!SSL_CTX_load_verify_locations(ctx, verifypem, NULL) != 1) {
+ if(!SSL_CTX_load_verify_locations(ctx, verifypem, NULL)) {
log_crypto_err("error in SSL_CTX verify");
SSL_CTX_free(ctx);
return NULL;
diff --git a/usr.sbin/unbound/validator/validator.c b/usr.sbin/unbound/validator/validator.c
index aefa26a2794..9d5d5c39025 100644
--- a/usr.sbin/unbound/validator/validator.c
+++ b/usr.sbin/unbound/validator/validator.c
@@ -283,12 +283,25 @@ needs_validation(struct module_qstate* qstate, int ret_rc,
{
int rcode;
- /* If the CD bit is on in the original request, then we don't bother to
- * validate anything.*/
+ /* If the CD bit is on in the original request, then you could think
+ * that we don't bother to validate anything.
+ * But this is signalled internally with the valrec flag.
+ * User queries are validated with BIT_CD to make our cache clean
+ * so that bogus messages get retried by the upstream also for
+ * downstream validators that set BIT_CD.
+ * For DNS64 bit_cd signals no dns64 processing, but we want to
+ * provide validation there too */
+ /*
if(qstate->query_flags & BIT_CD) {
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 +364,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 +2024,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");
}
}