diff --git a/doc/Changelog b/doc/Changelog index 7dd3c6afa..ac9c8a97c 100644 --- a/doc/Changelog +++ b/doc/Changelog @@ -3,6 +3,8 @@ - find NS rrset more cleanly for qtype NS. - Moved changes to 1.2.0 for release. Thanks to Mark Zealey for reporting and logs. + - 1.2.1 feature: stops resolving AAAAs promiscuously when they + are in the negative cache. 12 January 2009: Wouter - fixed bug in infrastructure lameness cache, did not lowercase diff --git a/iterator/iter_delegpt.c b/iterator/iter_delegpt.c index 0c5f02b99..13bcdad47 100644 --- a/iterator/iter_delegpt.c +++ b/iterator/iter_delegpt.c @@ -423,3 +423,23 @@ delegpt_add_rrset(struct delegpt* dp, struct regional* region, log_warn("Unknown rrset type added to delegpt"); return 1; } + +void delegpt_add_neg_msg(struct delegpt* dp, struct msgreply_entry* msg) +{ + struct reply_info* rep = (struct reply_info*)msg->entry.data; + if(!rep) return; + + /* if error or no answers */ + if(FLAGS_GET_RCODE(rep->flags) != 0 || rep->an_numrrsets == 0) { + struct delegpt_ns* ns = delegpt_find_ns(dp, msg->key.qname, + msg->key.qname_len); + if(ns) { + if(msg->key.qtype == LDNS_RR_TYPE_A) + ns->got4 = 1; + else if(msg->key.qtype == LDNS_RR_TYPE_AAAA) + ns->got6 = 1; + if(ns->got4 && ns->got6) + ns->resolved = 1; + } + } +} diff --git a/iterator/iter_delegpt.h b/iterator/iter_delegpt.h index f164a6fab..4445c1b0a 100644 --- a/iterator/iter_delegpt.h +++ b/iterator/iter_delegpt.h @@ -48,6 +48,7 @@ struct delegpt_ns; struct delegpt_addr; struct dns_msg; struct ub_packed_rrset_key; +struct msgreply_entry; /** * Delegation Point. @@ -299,4 +300,11 @@ size_t delegpt_count_missing_targets(struct delegpt* dp); struct delegpt* delegpt_from_message(struct dns_msg* msg, struct regional* regional); +/** + * Add negative message to delegation point. + * @param dp: delegation point. + * @param msg: the message added, marks off A or AAAA from an NS entry. + */ +void delegpt_add_neg_msg(struct delegpt* dp, struct msgreply_entry* msg); + #endif /* ITERATOR_ITER_DELEGPT_H */ diff --git a/services/cache/dns.c b/services/cache/dns.c index c1928a96b..2164dd3b0 100644 --- a/services/cache/dns.c +++ b/services/cache/dns.c @@ -142,6 +142,30 @@ 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, uint32_t now, int wr) +{ + struct lruhash_entry* e; + struct query_info k; + hashvalue_t h; + + k.qname = qname; + k.qname_len = qnamelen; + k.qtype = qtype; + k.qclass = qclass; + h = query_info_hash(&k); + e = slabhash_lookup(env->msg_cache, h, &k, wr); + + if(!e) return NULL; + if( now > ((struct reply_info*)e->data)->ttl ) { + lock_rw_unlock(&e->lock); + return NULL; + } + return (struct msgreply_entry*)e->key; +} + /** find and add A and AAAA records for nameservers in delegpt */ static int find_add_addrs(struct module_env* env, uint16_t qclass, @@ -149,6 +173,7 @@ find_add_addrs(struct module_env* env, uint16_t qclass, struct dns_msg** msg) { struct delegpt_ns* ns; + struct msgreply_entry* neg; struct ub_packed_rrset_key* akey; for(ns = dp->nslist; ns; ns = ns->next) { akey = rrset_cache_lookup(env->rrset_cache, ns->name, @@ -161,6 +186,13 @@ find_add_addrs(struct module_env* env, uint16_t qclass, if(msg) addr_to_additional(akey, region, *msg, now); lock_rw_unlock(&akey->entry.lock); + } else { + neg = msg_cache_lookup(env, ns->name, ns->namelen, + LDNS_RR_TYPE_A, qclass, now, 0); + if(neg) { + delegpt_add_neg_msg(dp, neg); + lock_rw_unlock(&neg->entry.lock); + } } akey = rrset_cache_lookup(env->rrset_cache, ns->name, ns->namelen, LDNS_RR_TYPE_AAAA, qclass, 0, now, 0); @@ -172,6 +204,13 @@ find_add_addrs(struct module_env* env, uint16_t qclass, if(msg) addr_to_additional(akey, region, *msg, now); lock_rw_unlock(&akey->entry.lock); + } else { + neg = msg_cache_lookup(env, ns->name, ns->namelen, + LDNS_RR_TYPE_AAAA, qclass, now, 0); + if(neg) { + delegpt_add_neg_msg(dp, neg); + lock_rw_unlock(&neg->entry.lock); + } } } return 1; @@ -183,6 +222,7 @@ cache_fill_missing(struct module_env* env, uint16_t qclass, struct regional* region, struct delegpt* dp) { struct delegpt_ns* ns; + struct msgreply_entry* neg; struct ub_packed_rrset_key* akey; uint32_t now = *env->now; for(ns = dp->nslist; ns; ns = ns->next) { @@ -198,6 +238,13 @@ cache_fill_missing(struct module_env* env, uint16_t qclass, log_nametypeclass(VERB_ALGO, "found in cache", ns->name, LDNS_RR_TYPE_A, qclass); lock_rw_unlock(&akey->entry.lock); + } else { + neg = msg_cache_lookup(env, ns->name, ns->namelen, + LDNS_RR_TYPE_A, qclass, now, 0); + if(neg) { + delegpt_add_neg_msg(dp, neg); + lock_rw_unlock(&neg->entry.lock); + } } akey = rrset_cache_lookup(env->rrset_cache, ns->name, ns->namelen, LDNS_RR_TYPE_AAAA, qclass, 0, now, 0); @@ -209,6 +256,13 @@ cache_fill_missing(struct module_env* env, uint16_t qclass, log_nametypeclass(VERB_ALGO, "found in cache", ns->name, LDNS_RR_TYPE_AAAA, qclass); lock_rw_unlock(&akey->entry.lock); + } else { + neg = msg_cache_lookup(env, ns->name, ns->namelen, + LDNS_RR_TYPE_AAAA, qclass, now, 0); + if(neg) { + delegpt_add_neg_msg(dp, neg); + lock_rw_unlock(&neg->entry.lock); + } } } return 1;