* \param ne A NegCacheEntry that is filled when there is a cache entry
* \return true if ne was filled out, false otherwise
*/
-bool NegCache::get(const DNSName& qname, const QType& qtype, const struct timeval& now, NegCacheEntry& ne) {
+bool NegCache::get(const DNSName& qname, const QType& qtype, const struct timeval& now, NegCacheEntry& ne, bool typeMustMatch) {
auto range = d_negcache.equal_range(tie(qname));
negcache_t::iterator ni = range.first;
while (ni != range.second) {
// We have an entry
- if (ni->d_qtype.getCode() == 0 || ni->d_qtype == qtype) {
+ if ((!typeMustMatch && ni->d_qtype.getCode() == 0) || ni->d_qtype == qtype) {
// We match the QType or the whole name is denied
if((uint32_t) now.tv_sec < ni->d_ttd) {
// Not expired
};
void add(const NegCacheEntry& ne);
- bool get(const DNSName& qname, const QType& qtype, const struct timeval& now, NegCacheEntry& ne);
+ bool get(const DNSName& qname, const QType& qtype, const struct timeval& now, NegCacheEntry& ne, bool typeMustMatch=false);
bool getRootNXTrust(const DNSName& qname, const struct timeval& now, NegCacheEntry& ne);
uint64_t count(const DNSName& qname) const;
uint64_t count(const DNSName& qname, const QType qtype) const;
BOOST_CHECK_EQUAL(ne.d_auth, auth);
}
+BOOST_AUTO_TEST_CASE(test_get_entry_exact_type) {
+ /* Add a full name negative entry to the cache and attempt to get an entry for
+ * the A record, asking only for an exact match.
+ */
+ DNSName qname("www2.powerdns.com");
+ DNSName auth("powerdns.com");
+
+ struct timeval now;
+ Utility::gettimeofday(&now, 0);
+
+ NegCache cache;
+ cache.add(genNegCacheEntry(qname, auth, now));
+
+ BOOST_CHECK_EQUAL(cache.size(), 1);
+
+ NegCache::NegCacheEntry ne;
+ bool ret = cache.get(qname, QType(1), now, ne, true);
+
+ BOOST_CHECK_EQUAL(ret, false);
+}
+
BOOST_AUTO_TEST_CASE(test_get_NODATA_entry) {
DNSName qname("www2.powerdns.com");
DNSName auth("powerdns.com");
}
else if (t_sstorage.negcache.get(qname, qtype, d_now, ne) &&
!(wasForwardedOrAuth && ne.d_auth != authname)) { // Only the authname nameserver can neg cache entries
- res = 0;
- sttl = ne.d_ttd - d_now.tv_sec;
- giveNegative = true;
- cachedState = ne.d_validationState;
- if(ne.d_qtype.getCode()) {
- LOG(prefix<<qname<<": "<<qtype.getName()<<" is negatively cached via '"<<ne.d_auth<<"' for another "<<sttl<<" seconds"<<endl);
- res = RCode::NoError;
- }
- else {
- LOG(prefix<<qname<<": Entire name '"<<qname<<"', is negatively cached via '"<<ne.d_auth<<"' for another "<<sttl<<" seconds"<<endl);
- res = RCode::NXDomain;
+
+ /* If we are looking for a DS, discard NXD if auth == qname
+ and ask for a specific denial instead */
+ if (qtype != QType::DS || ne.d_qtype.getCode() || ne.d_auth != qname ||
+ t_sstorage.negcache.get(qname, qtype, d_now, ne, true))
+ {
+ res = 0;
+ sttl = ne.d_ttd - d_now.tv_sec;
+ giveNegative = true;
+ cachedState = ne.d_validationState;
+ if(ne.d_qtype.getCode()) {
+ LOG(prefix<<qname<<": "<<qtype.getName()<<" is negatively cached via '"<<ne.d_auth<<"' for another "<<sttl<<" seconds"<<endl);
+ res = RCode::NoError;
+ }
+ else {
+ LOG(prefix<<qname<<": Entire name '"<<qname<<"', is negatively cached via '"<<ne.d_auth<<"' for another "<<sttl<<" seconds"<<endl);
+ res = RCode::NXDomain;
+ }
}
}