/** generate dns_msg from cached message */
static struct dns_msg*
-tomsg(struct module_env* env, struct msgreply_entry* e, struct reply_info* r,
+tomsg(struct module_env* env, struct query_info* q, struct reply_info* r,
struct regional* region, uint32_t now, struct regional* scratch)
{
struct dns_msg* msg;
size_t i;
if(now > r->ttl)
return NULL;
- msg = gen_dns_msg(region, &e->key, r->rrset_count);
+ msg = gen_dns_msg(region, q, r->rrset_count);
if(!msg)
return NULL;
msg->rep->flags = r->flags;
if(e) {
struct msgreply_entry* key = (struct msgreply_entry*)e->key;
struct reply_info* data = (struct reply_info*)e->data;
- struct dns_msg* msg = tomsg(env, key, data, region, now,
+ struct dns_msg* msg = tomsg(env, &key->key, data, region, now,
scratch);
if(msg) {
lock_rw_unlock(&e->lock);
}
lock_rw_unlock(&rrset->entry.lock);
}
+
+ /* stop downwards cache search on NXDOMAIN.
+ * Empty nonterminals are NOERROR, so an NXDOMAIN for foo
+ * means bla.foo also does not exist. The DNSSEC proofs are
+ * the same. We search upwards for NXDOMAINs. */
+ while(!dname_is_root(k.qname)) {
+ dname_remove_label(&k.qname, &k.qname_len);
+ h = query_info_hash(&k);
+ e = slabhash_lookup(env->msg_cache, h, &k, 0);
+ if(e) {
+ struct reply_info* data = (struct reply_info*)e->data;
+ struct dns_msg* msg;
+ if(FLAGS_GET_RCODE(data->flags) == LDNS_RCODE_NXDOMAIN
+ && data->security != sec_status_bogus
+ && (msg=tomsg(env, &k, data, region, now, scratch))){
+ lock_rw_unlock(&e->lock);
+ msg->qinfo.qname=qname;
+ msg->qinfo.qname_len=qnamelen;
+ /* check that DNSSEC really works out */
+ msg->rep->security = sec_status_unchecked;
+ return msg;
+ }
+ lock_rw_unlock(&e->lock);
+ }
+ }
+
return NULL;
}
--- /dev/null
+; config options
+server:
+ target-fetch-policy: "0 0 0 0 0"
+
+stub-zone:
+ name: "."
+ stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
+CONFIG_END
+
+SCENARIO_BEGIN Test stop cache search on nxdomain
+
+; K.ROOT-SERVERS.NET.
+RANGE_BEGIN 0 100
+ ADDRESS 193.0.14.129
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+. IN NS K.ROOT-SERVERS.NET.
+SECTION ADDITIONAL
+K.ROOT-SERVERS.NET. IN A 193.0.14.129
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NXDOMAIN
+SECTION QUESTION
+example.local. IN A
+SECTION AUTHORITY
+. 86400 IN SOA a.root-servers.net. nstld.verisign-grs.com. 2010111601 1800 900 604800 86400
+ENTRY_END
+RANGE_END
+
+STEP 1 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+example.local. IN A
+ENTRY_END
+
+; recursion happens here.
+STEP 10 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA NXDOMAIN
+SECTION QUESTION
+example.local. IN A
+SECTION AUTHORITY
+. 86400 IN SOA a.root-servers.net. nstld.verisign-grs.com. 2010111601 1800 900 604800 86400
+ENTRY_END
+
+STEP 20 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+foo.example.local. IN A
+ENTRY_END
+
+; this query does not get sent to K-ROOT.
+STEP 30 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA NXDOMAIN
+SECTION QUESTION
+foo.example.local. IN A
+SECTION AUTHORITY
+. 86400 IN SOA a.root-servers.net. nstld.verisign-grs.com. 2010111601 1800 900 604800 86400
+ENTRY_END
+
+SCENARIO_END