summaryrefslogtreecommitdiffstats
path: root/contrib/unbound/services/cache/dns.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/unbound/services/cache/dns.c')
-rw-r--r--contrib/unbound/services/cache/dns.c77
1 files changed, 75 insertions, 2 deletions
diff --git a/contrib/unbound/services/cache/dns.c b/contrib/unbound/services/cache/dns.c
index 4692744..ba81afd 100644
--- a/contrib/unbound/services/cache/dns.c
+++ b/contrib/unbound/services/cache/dns.c
@@ -50,7 +50,7 @@
#include "util/net_help.h"
#include "util/regional.h"
#include "util/config_file.h"
-#include "ldns/sbuffer.h"
+#include "sldns/sbuffer.h"
/** store rrsets in the rrset cache.
* @param env: module environment with caches.
@@ -366,6 +366,8 @@ dns_msg_create(uint8_t* qname, size_t qnamelen, uint16_t qtype,
sizeof(struct reply_info)-sizeof(struct rrset_ref));
if(!msg->rep)
return NULL;
+ if(capacity > RR_COUNT_MAX)
+ return NULL; /* integer overflow protection */
msg->rep->flags = BIT_QR; /* with QR, no AA */
msg->rep->qdcount = 1;
msg->rep->rrsets = (struct ub_packed_rrset_key**)
@@ -387,6 +389,18 @@ dns_msg_authadd(struct dns_msg* msg, struct regional* region,
return 1;
}
+/** add rrset to answer section */
+static int
+dns_msg_ansadd(struct dns_msg* msg, struct regional* region,
+ struct ub_packed_rrset_key* rrset, time_t now)
+{
+ if(!(msg->rep->rrsets[msg->rep->rrset_count++] =
+ packed_rrset_copy_region(rrset, region, now)))
+ return 0;
+ msg->rep->an_numrrsets++;
+ return 1;
+}
+
struct delegpt*
dns_cache_find_delegation(struct module_env* env, uint8_t* qname,
size_t qnamelen, uint16_t qtype, uint16_t qclass,
@@ -453,6 +467,8 @@ gen_dns_msg(struct regional* region, struct query_info* q, size_t num)
sizeof(struct reply_info) - sizeof(struct rrset_ref));
if(!msg->rep)
return NULL;
+ if(num > RR_COUNT_MAX)
+ return NULL; /* integer overflow protection */
msg->rep->rrsets = (struct ub_packed_rrset_key**)
regional_alloc(region,
num * sizeof(struct ub_packed_rrset_key*));
@@ -489,7 +505,7 @@ tomsg(struct module_env* env, struct query_info* q, struct reply_info* r,
return NULL;
if(r->an_numrrsets > 0 && (r->rrsets[0]->rk.type == htons(
LDNS_RR_TYPE_CNAME) || r->rrsets[0]->rk.type == htons(
- LDNS_RR_TYPE_DNAME)) && !reply_check_cname_chain(r)) {
+ LDNS_RR_TYPE_DNAME)) && !reply_check_cname_chain(q, r)) {
/* cname chain is now invalid, reconstruct msg */
rrset_array_unlock(r->ref, r->rrset_count);
return NULL;
@@ -631,6 +647,58 @@ synth_dname_msg(struct ub_packed_rrset_key* rrset, struct regional* region,
return msg;
}
+/** Fill TYPE_ANY response with some data from cache */
+static struct dns_msg*
+fill_any(struct module_env* env,
+ uint8_t* qname, size_t qnamelen, uint16_t qtype, uint16_t qclass,
+ struct regional* region)
+{
+ time_t now = *env->now;
+ struct dns_msg* msg = NULL;
+ uint16_t lookup[] = {LDNS_RR_TYPE_A, LDNS_RR_TYPE_AAAA,
+ LDNS_RR_TYPE_MX, LDNS_RR_TYPE_SOA, LDNS_RR_TYPE_NS, 0};
+ int i, num=5; /* number of RR types to look up */
+ log_assert(lookup[num] == 0);
+
+ for(i=0; i<num; i++) {
+ /* look up this RR for inclusion in type ANY response */
+ struct ub_packed_rrset_key* rrset = rrset_cache_lookup(
+ env->rrset_cache, qname, qnamelen, lookup[i],
+ qclass, 0, now, 0);
+ struct packed_rrset_data *d;
+ if(!rrset)
+ continue;
+
+ /* only if rrset from answer section */
+ d = (struct packed_rrset_data*)rrset->entry.data;
+ if(d->trust == rrset_trust_add_noAA ||
+ d->trust == rrset_trust_auth_noAA ||
+ d->trust == rrset_trust_add_AA ||
+ d->trust == rrset_trust_auth_AA) {
+ lock_rw_unlock(&rrset->entry.lock);
+ continue;
+ }
+
+ /* create msg if none */
+ if(!msg) {
+ msg = dns_msg_create(qname, qnamelen, qtype, qclass,
+ region, (size_t)(num-i));
+ if(!msg) {
+ lock_rw_unlock(&rrset->entry.lock);
+ return NULL;
+ }
+ }
+
+ /* add RRset to response */
+ if(!dns_msg_ansadd(msg, region, rrset, now)) {
+ lock_rw_unlock(&rrset->entry.lock);
+ return NULL;
+ }
+ lock_rw_unlock(&rrset->entry.lock);
+ }
+ return msg;
+}
+
struct dns_msg*
dns_cache_lookup(struct module_env* env,
uint8_t* qname, size_t qnamelen, uint16_t qtype, uint16_t qclass,
@@ -743,6 +811,11 @@ dns_cache_lookup(struct module_env* env,
}
}
+ /* fill common RR types for ANY response to avoid requery */
+ if(qtype == LDNS_RR_TYPE_ANY) {
+ return fill_any(env, qname, qnamelen, qtype, qclass, region);
+ }
+
return NULL;
}
OpenPOWER on IntegriCloud