From: Remi Gacogne Date: Mon, 17 Dec 2018 13:53:07 +0000 (+0100) Subject: Use a bitset for NSEC(3) records with lots of types X-Git-Tag: rec-4.2.0-alpha1~54^2~4 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=27d4a65bf8d908b02ea84e662683d31b077306ab;p=thirdparty%2Fpdns.git Use a bitset for NSEC(3) records with lots of types --- diff --git a/pdns/dnsrecords.hh b/pdns/dnsrecords.hh index 353bbef31a..1d46aa08ec 100644 --- a/pdns/dnsrecords.hh +++ b/pdns/dnsrecords.hh @@ -542,6 +542,62 @@ public: struct soatimes d_st; }; +class NSECBitmap +{ +public: + bool isSet(uint16_t type) const + { + if (d_bitset) { + return d_bitset->test(type); + } + return d_set.count(type); + } + void set(uint16_t type) + { + if (!d_bitset) { + if (d_set.size() >= 200) { + migrateToBitSet(); + } + } + if (d_bitset) { + d_bitset->set(type); + } + else { + d_set.insert(type); + } + } + size_t count() const + { + if (d_bitset) { + return d_bitset->count(); + } + else { + return d_set.size(); + } + } + + void fromPacket(PacketReader& pr); + void toPacket(DNSPacketWriter& pw); + std::string getZoneRepresentation() const; + +private: + void migrateToBitSet() + { + d_bitset = std::unique_ptr>(new std::bitset<65536>()); + for (const auto& type : d_set) { + d_bitset->set(type); + } + d_set.clear(); + } + /* using a dynamic set is very efficient for a small number of + types covered (~200), but uses a lot of memory (up to 3MB) + when there are a lot of them. + So we start with the set, but allocate and switch to a bitset + if the number of covered types increases a lot */ + std::unique_ptr> d_bitset; + std::set d_set; +}; + class NSECRecordContent : public DNSRecordContent { public: @@ -558,9 +614,22 @@ public: { return QType::NSEC; } + bool isSet(uint16_t type) const + { + return d_bitmap.isSet(type); + } + void set(uint16_t type) + { + d_bitmap.set(type); + } + size_t numberOfTypesSet() const + { + return d_bitmap.count(); + } + DNSName d_next; - std::set d_set; private: + NSECBitmap d_bitmap; }; class NSEC3RecordContent : public DNSRecordContent @@ -580,15 +649,26 @@ public: uint16_t d_iterations{0}; string d_salt; string d_nexthash; - std::set d_set; uint16_t getType() const override { return QType::NSEC3; } - + bool isSet(uint16_t type) const + { + return d_bitmap.isSet(type); + } + void set(uint16_t type) + { + d_bitmap.set(type); + } + size_t numberOfTypesSet() const + { + return d_bitmap.count(); + } private: + NSECBitmap d_bitmap; }; diff --git a/pdns/nsec3dig.cc b/pdns/nsec3dig.cc index 82345f5329..ee7430471f 100644 --- a/pdns/nsec3dig.cc +++ b/pdns/nsec3dig.cc @@ -171,15 +171,18 @@ try { // cerr<<"got nsec3 ["<first.d_name<<"]"<first.d_content->getZoneRepresentation()< (*(i->first.d_content)); + const auto r = std::dynamic_pointer_cast(i->first.d_content); + if (!r) { + continue; + } // nsec3.insert(new nsec3() // cerr< parts; string sname=i->first.d_name.toString(); boost::split(parts, sname /* FIXME400 */, boost::is_any_of(".")); - nsec3s.insert(make_pair(toLower(parts[0]), toBase32Hex(r.d_nexthash))); - nsec3salt = r.d_salt; - nsec3iters = r.d_iterations; + nsec3s.insert(make_pair(toLower(parts[0]), toBase32Hex(r->d_nexthash))); + nsec3salt = r->d_salt; + nsec3iters = r->d_iterations; } else { diff --git a/pdns/nsecrecords.cc b/pdns/nsecrecords.cc index 20329cf1ea..8149a9346e 100644 --- a/pdns/nsecrecords.cc +++ b/pdns/nsecrecords.cc @@ -24,49 +24,23 @@ #endif #include "dnsrecords.hh" -void NSECRecordContent::report(void) +class NSECBitmapGenerator { - regist(1, 47, &make, &make, "NSEC"); -} - -std::shared_ptr NSECRecordContent::make(const string& content) -{ - return std::make_shared(content); -} - -NSECRecordContent::NSECRecordContent(const string& content, const string& zone) -{ - RecordTextReader rtr(content, DNSName(zone)); - rtr.xfrName(d_next); - - while(!rtr.eof()) { - uint16_t type; - rtr.xfrType(type); - d_set.insert(type); +public: + NSECBitmapGenerator(DNSPacketWriter& pw_): pw(pw_) + { } -} - -void NSECRecordContent::toPacket(DNSPacketWriter& pw) -{ - pw.xfrName(d_next); - - uint8_t res[34]; - set::const_iterator i; - int oldWindow = -1; - int window = 0; - int len = 0; - string tmp; - - for(i=d_set.begin(); i != d_set.end(); ++i){ - uint16_t bit = (*i)%256; - window = static_cast((*i) / 256); + void set(uint16_t type) + { + uint16_t bit = type % 256; + int window = static_cast(type / 256); if (window != oldWindow) { if (oldWindow > -1) { - res[0] = static_cast(oldWindow); - res[1] = static_cast(len); - tmp.assign(res, res+len+2); - pw.xfrBlob(tmp); + res[0] = static_cast(oldWindow); + res[1] = static_cast(len); + tmp.assign(res, res+len+2); + pw.xfrBlob(tmp); } memset(res, 0, 34); oldWindow = window; @@ -75,43 +49,150 @@ void NSECRecordContent::toPacket(DNSPacketWriter& pw) len=1+bit/8; } - res[0] = static_cast(window); - res[1] = static_cast(len); - tmp.assign(res, res+len+2); - pw.xfrBlob(tmp); + void finish() + { + res[0] = static_cast(oldWindow); + res[1] = static_cast(len); + if (len) { + tmp.assign(res, res+len+2); + pw.xfrBlob(tmp); + } + } + +private: + DNSPacketWriter& pw; + /* one byte for the window, + one for the length, + then the maximum of 32 bytes */ + uint8_t res[34]; + int oldWindow{-1}; + int len{0}; + string tmp; +}; + +void NSECBitmap::toPacket(DNSPacketWriter& pw) +{ + NSECBitmapGenerator nbg(pw); + if (d_bitset) { + size_t count = d_bitset->count(); + size_t found = 0; + for(size_t idx = 0; idx < 65535 && found < count; ++idx){ + if (!d_bitset->test(idx)) { + continue; + } + found++; + nbg.set(idx); + } + } + else { + for (const auto& type : d_set) { + nbg.set(type); + } + } + + nbg.finish(); } -std::shared_ptr NSECRecordContent::make(const DNSRecord &dr, PacketReader& pr) +void NSECBitmap::fromPacket(PacketReader& pr) { - auto ret=std::make_shared(); - pr.xfrName(ret->d_next); string bitmap; pr.xfrBlob(bitmap); - + // 00 06 20 00 00 00 00 03 -> NS RRSIG NSEC ( 2, 46, 47 ) counts from left - if(bitmap.empty()) - return ret; + if(bitmap.empty()) { + return; + } - if(bitmap.size() < 2) + if(bitmap.size() < 2) { throw MOADNSException("NSEC record with impossibly small bitmap"); + } for(unsigned int n = 0; n+1 < bitmap.size();) { unsigned int window=static_cast(bitmap[n++]); unsigned int blen=static_cast(bitmap[n++]); // end if zero padding and ensure packet length - if(window == 0 && blen == 0) break; - if(n + blen > bitmap.size()) + if(window == 0 && blen == 0) { + break; + } + + if(n + blen > bitmap.size()) { throw MOADNSException("NSEC record with bitmap length > packet length"); + } for(unsigned int k=0; k < blen; k++) { uint8_t val=bitmap[n++]; - for(int bit = 0; bit < 8 ; ++bit , val>>=1) + for(int bit = 0; bit < 8 ; ++bit , val>>=1) { if(val & 1) { - ret->d_set.insert((7-bit) + 8*(k) + 256*window); + set((7-bit) + 8*(k) + 256*window); } } + } + } +} + +string NSECBitmap::getZoneRepresentation() const +{ + string ret; + + if (d_bitset) { + size_t count = d_bitset->count(); + size_t found = 0; + for(size_t idx = 0; idx < 65535 && found < count; ++idx) { + if (!d_bitset->test(idx)) { + continue; + } + found++; + + ret+=" "; + ret+=DNSRecordContent::NumberToType(idx); + } + } + else { + for(const auto& type : d_set) { + ret+=" "; + ret+=DNSRecordContent::NumberToType(type); + } + } + + return ret; +} + +void NSECRecordContent::report(void) +{ + regist(1, 47, &make, &make, "NSEC"); +} + +std::shared_ptr NSECRecordContent::make(const string& content) +{ + return std::make_shared(content); +} + +NSECRecordContent::NSECRecordContent(const string& content, const string& zone) +{ + RecordTextReader rtr(content, DNSName(zone)); + rtr.xfrName(d_next); + + while(!rtr.eof()) { + uint16_t type; + rtr.xfrType(type); + set(type); } +} + +void NSECRecordContent::toPacket(DNSPacketWriter& pw) +{ + pw.xfrName(d_next); + d_bitmap.toPacket(pw); +} + +std::shared_ptr NSECRecordContent::make(const DNSRecord &dr, PacketReader& pr) +{ + auto ret=std::make_shared(); + pr.xfrName(ret->d_next); + + ret->d_bitmap.fromPacket(pr); + return ret; } @@ -120,13 +201,8 @@ string NSECRecordContent::getZoneRepresentation(bool noDot) const string ret; RecordTextWriter rtw(ret); rtw.xfrName(d_next); - - for(set::const_iterator i=d_set.begin(); i!=d_set.end(); ++i) { - ret+=" "; - ret+=NumberToType(*i); - } - - return ret; + + return ret + d_bitmap.getZoneRepresentation(); } ////// begin of NSEC3 @@ -154,7 +230,7 @@ NSEC3RecordContent::NSEC3RecordContent(const string& content, const string& zone while(!rtr.eof()) { uint16_t type; rtr.xfrType(type); - d_set.insert(type); + set(type); } } @@ -168,39 +244,8 @@ void NSEC3RecordContent::toPacket(DNSPacketWriter& pw) pw.xfr8BitInt(d_nexthash.length()); pw.xfrBlob(d_nexthash); - - uint8_t res[34]; - set::const_iterator i; - int oldWindow = -1; - int window = 0; - int len = 0; - string tmp; - - for(i=d_set.begin(); i != d_set.end(); ++i){ - uint16_t bit = (*i)%256; - window = static_cast((*i) / 256); - if (window != oldWindow) { - if (oldWindow > -1) { - res[0] = static_cast(oldWindow); - res[1] = static_cast(len); - tmp.assign(res, res+len+2); - pw.xfrBlob(tmp); - } - memset(res, 0, 34); - oldWindow = window; - } - res[2+bit/8] |= 1 << (7-(bit%8)); - len=1+bit/8; - } - - res[0] = static_cast(window); - res[1] = static_cast(len); - - if (len) { - tmp.assign(res, res+len+2); - pw.xfrBlob(tmp); - } + d_bitmap.toPacket(pw); } std::shared_ptr NSEC3RecordContent::make(const DNSRecord &dr, PacketReader& pr) @@ -215,35 +260,8 @@ std::shared_ptr NSEC3RecordContent::make(c pr.xfr8BitInt(len); pr.xfrBlob(ret->d_nexthash, len); - - string bitmap; - pr.xfrBlob(bitmap); - - // 00 06 20 00 00 00 00 03 -> NS RRSIG NSEC ( 2, 46, 47 ) counts from left - - if(bitmap.empty()) - return ret; - - if(bitmap.size() < 2) - throw MOADNSException("NSEC3 record with impossibly small bitmap"); - - for(unsigned int n = 0; n+1 < bitmap.size();) { - unsigned int window=static_cast(bitmap[n++]); - unsigned int innerlen=static_cast(bitmap[n++]); - - // end if zero padding and ensure packet length - if(window == 0&&innerlen == 0) break; - if(n+innerlen>bitmap.size()) - throw MOADNSException("NSEC record with bitmap length > packet length"); - for(unsigned int k=0; k < innerlen; k++) { - uint8_t val=bitmap[n++]; - for(int bit = 0; bit < 8 ; ++bit , val>>=1) - if(val & 1) { - ret->d_set.insert((7-bit) + 8*(k) + 256*window); - } - } - } + ret->d_bitmap.fromPacket(pr); return ret; } @@ -257,12 +275,8 @@ string NSEC3RecordContent::getZoneRepresentation(bool noDot) const rtw.xfrHexBlob(d_salt); rtw.xfrBase32HexBlob(d_nexthash); - for(set::const_iterator i=d_set.begin(); i!=d_set.end(); ++i) { - ret+=" "; - ret+=NumberToType(*i); - } - - return ret; + + return ret + d_bitmap.getZoneRepresentation(); } diff --git a/pdns/packethandler.cc b/pdns/packethandler.cc index c6680906c6..c319f3e17a 100644 --- a/pdns/packethandler.cc +++ b/pdns/packethandler.cc @@ -484,19 +484,19 @@ void PacketHandler::emitNSEC(DNSPacket *r, const SOAData& sd, const DNSName& nam NSECRecordContent nrc; nrc.d_next = next; - nrc.d_set.insert(QType::NSEC); - nrc.d_set.insert(QType::RRSIG); + nrc.set(QType::NSEC); + nrc.set(QType::RRSIG); if(sd.qname == name) { - nrc.d_set.insert(QType::SOA); // 1dfd8ad SOA can live outside the records table - nrc.d_set.insert(QType::DNSKEY); + nrc.set(QType::SOA); // 1dfd8ad SOA can live outside the records table + nrc.set(QType::DNSKEY); string publishCDNSKEY; d_dk.getFromMeta(name, "PUBLISH-CDNSKEY", publishCDNSKEY); if (publishCDNSKEY == "1") - nrc.d_set.insert(QType::CDNSKEY); + nrc.set(QType::CDNSKEY); string publishCDS; d_dk.getFromMeta(name, "PUBLISH-CDS", publishCDS); if (! publishCDS.empty()) - nrc.d_set.insert(QType::CDS); + nrc.set(QType::CDS); } DNSZoneRecord rr; @@ -505,17 +505,17 @@ void PacketHandler::emitNSEC(DNSPacket *r, const SOAData& sd, const DNSName& nam while(B.get(rr)) { #ifdef HAVE_LUA_RECORDS if(rr.dr.d_type == QType::LUA) - nrc.d_set.insert(getRR(rr.dr)->d_type); + nrc.set(getRR(rr.dr)->d_type); else #endif if(rr.dr.d_type == QType::NS || rr.auth) - nrc.d_set.insert(rr.dr.d_type); + nrc.set(rr.dr.d_type); } rr.dr.d_name = name; rr.dr.d_ttl = sd.default_ttl; rr.dr.d_type = QType::NSEC; - rr.dr.d_content = std::make_shared(nrc); + rr.dr.d_content = std::make_shared(std::move(nrc)); rr.dr.d_place = (mode == 5 ) ? DNSResourceRecord::ANSWER: DNSResourceRecord::AUTHORITY; rr.auth = true; @@ -535,38 +535,40 @@ void PacketHandler::emitNSEC3(DNSPacket *r, const SOAData& sd, const NSEC3PARAMR if(!name.empty()) { if (sd.qname == name) { - n3rc.d_set.insert(QType::SOA); // 1dfd8ad SOA can live outside the records table - n3rc.d_set.insert(QType::NSEC3PARAM); - n3rc.d_set.insert(QType::DNSKEY); + n3rc.set(QType::SOA); // 1dfd8ad SOA can live outside the records table + n3rc.set(QType::NSEC3PARAM); + n3rc.set(QType::DNSKEY); string publishCDNSKEY; d_dk.getFromMeta(name, "PUBLISH-CDNSKEY", publishCDNSKEY); if (publishCDNSKEY == "1") - n3rc.d_set.insert(QType::CDNSKEY); + n3rc.set(QType::CDNSKEY); string publishCDS; d_dk.getFromMeta(name, "PUBLISH-CDS", publishCDS); if (! publishCDS.empty()) - n3rc.d_set.insert(QType::CDS); + n3rc.set(QType::CDS); } B.lookup(QType(QType::ANY), name, NULL, sd.domain_id); while(B.get(rr)) { #ifdef HAVE_LUA_RECORDS if(rr.dr.d_type == QType::LUA) - n3rc.d_set.insert(getRR(rr.dr)->d_type); + n3rc.set(getRR(rr.dr)->d_type); else #endif if(rr.dr.d_type && (rr.dr.d_type == QType::NS || rr.auth)) // skip empty non-terminals - n3rc.d_set.insert(rr.dr.d_type); + n3rc.set(rr.dr.d_type); } } - if (n3rc.d_set.size() && !(n3rc.d_set.size() == 1 && n3rc.d_set.count(QType::NS))) - n3rc.d_set.insert(QType::RRSIG); + const auto numberOfTypesSet = n3rc.numberOfTypesSet(); + if (numberOfTypesSet != 0 && !(numberOfTypesSet == 1 && n3rc.isSet(QType::NS))) { + n3rc.set(QType::RRSIG); + } rr.dr.d_name = DNSName(toBase32Hex(namehash))+sd.qname; rr.dr.d_ttl = sd.default_ttl; rr.dr.d_type=QType::NSEC3; - rr.dr.d_content=std::make_shared(n3rc); + rr.dr.d_content=std::make_shared(std::move(n3rc)); rr.dr.d_place = (mode == 5 ) ? DNSResourceRecord::ANSWER: DNSResourceRecord::AUTHORITY; rr.auth = true; diff --git a/pdns/recursordist/test-syncres_cc.cc b/pdns/recursordist/test-syncres_cc.cc index 22655c1fbd..828a00b760 100644 --- a/pdns/recursordist/test-syncres_cc.cc +++ b/pdns/recursordist/test-syncres_cc.cc @@ -343,13 +343,15 @@ static void addNSECRecordToLW(const DNSName& domain, const DNSName& next, const { NSECRecordContent nrc; nrc.d_next = next; - nrc.d_set = types; + for (const auto& type : types) { + nrc.set(type); + } DNSRecord rec; rec.d_name = domain; rec.d_ttl = ttl; rec.d_type = QType::NSEC; - rec.d_content = std::make_shared(nrc); + rec.d_content = std::make_shared(std::move(nrc)); rec.d_place = DNSResourceRecord::AUTHORITY; records.push_back(rec); @@ -363,13 +365,15 @@ static void addNSEC3RecordToLW(const DNSName& hashedName, const std::string& has nrc.d_iterations = iterations; nrc.d_salt = salt; nrc.d_nexthash = hashedNext; - nrc.d_set = types; + for (const auto& type : types) { + nrc.set(type); + } DNSRecord rec; rec.d_name = hashedName; rec.d_ttl = ttl; rec.d_type = QType::NSEC3; - rec.d_content = std::make_shared(nrc); + rec.d_content = std::make_shared(std::move(nrc)); rec.d_place = DNSResourceRecord::AUTHORITY; records.push_back(rec); diff --git a/pdns/slavecommunicator.cc b/pdns/slavecommunicator.cc index ef52ff14d6..43c074362f 100644 --- a/pdns/slavecommunicator.cc +++ b/pdns/slavecommunicator.cc @@ -200,7 +200,7 @@ static bool processRecordForZS(const DNSName& domain, bool& firstNSEC3, DNSResou } else if (zs.optOutFlag != (ns3rc.d_flags & 1)) throw PDNSException("Zones with a mixture of Opt-Out NSEC3 RRs and non-Opt-Out NSEC3 RRs are not supported."); zs.optOutFlag = ns3rc.d_flags & 1; - if (ns3rc.d_set.count(QType::NS) && !(rr.qname==domain)) { + if (ns3rc.isSet(QType::NS) && !(rr.qname==domain)) { DNSName hashPart = rr.qname.makeRelative(domain); zs.secured.insert(hashPart); } diff --git a/pdns/tcpreceiver.cc b/pdns/tcpreceiver.cc index 9b45cdf39e..e04415c953 100644 --- a/pdns/tcpreceiver.cc +++ b/pdns/tcpreceiver.cc @@ -951,13 +951,17 @@ int TCPNameserver::doAXFR(const DNSName &target, shared_ptr q, int ou for(nsecxrepo_t::const_iterator iter = nsecxrepo.begin(); iter != nsecxrepo.end(); ++iter) { if(iter->second.d_auth) { NSEC3RecordContent n3rc; - n3rc.d_set = iter->second.d_set; - if (n3rc.d_set.size() && (n3rc.d_set.size() != 1 || !n3rc.d_set.count(QType::NS))) - n3rc.d_set.insert(QType::RRSIG); - n3rc.d_salt=ns3pr.d_salt; + for (const auto type : iter->second.d_set) { + n3rc.set(type); + } + const auto numberOfTypesSet = n3rc.numberOfTypesSet(); + if (numberOfTypesSet != 0 && (numberOfTypesSet != 1 || !n3rc.isSet(QType::NS))) { + n3rc.set(QType::RRSIG); + } + n3rc.d_salt = ns3pr.d_salt; n3rc.d_flags = ns3pr.d_flags; n3rc.d_iterations = ns3pr.d_iterations; - n3rc.d_algorithm = 1; // SHA1, fixed in PowerDNS for now + n3rc.d_algorithm = DNSSECKeeper::SHA1; // SHA1, fixed in PowerDNS for now nsecxrepo_t::const_iterator inext = iter; inext++; if(inext == nsecxrepo.end()) @@ -972,7 +976,7 @@ int TCPNameserver::doAXFR(const DNSName &target, shared_ptr q, int ou zrr.dr.d_name = iter->first+sd.qname; zrr.dr.d_ttl = sd.default_ttl; - zrr.dr.d_content = std::make_shared(n3rc); + zrr.dr.d_content = std::make_shared(std::move(n3rc)); zrr.dr.d_type = QType::NSEC3; zrr.dr.d_place = DNSResourceRecord::ANSWER; zrr.auth=true; @@ -995,9 +999,11 @@ int TCPNameserver::doAXFR(const DNSName &target, shared_ptr q, int ou } else for(nsecxrepo_t::const_iterator iter = nsecxrepo.begin(); iter != nsecxrepo.end(); ++iter) { NSECRecordContent nrc; - nrc.d_set = iter->second.d_set; - nrc.d_set.insert(QType::RRSIG); - nrc.d_set.insert(QType::NSEC); + for (const auto type : iter->second.d_set) { + nrc.set(type); + } + nrc.set(QType::RRSIG); + nrc.set(QType::NSEC); if(boost::next(iter) != nsecxrepo.end()) nrc.d_next = boost::next(iter)->first; @@ -1006,7 +1012,7 @@ int TCPNameserver::doAXFR(const DNSName &target, shared_ptr q, int ou zrr.dr.d_name = iter->first; zrr.dr.d_ttl = sd.default_ttl; - zrr.dr.d_content = std::make_shared(nrc); + zrr.dr.d_content = std::make_shared(std::move(nrc)); zrr.dr.d_type = QType::NSEC; zrr.dr.d_place = DNSResourceRecord::ANSWER; zrr.auth=true; diff --git a/pdns/validate.cc b/pdns/validate.cc index c081fe1556..c9d17c86e2 100644 --- a/pdns/validate.cc +++ b/pdns/validate.cc @@ -75,7 +75,7 @@ bool denialProvesNoDelegation(const DNSName& zone, const std::vector& } if (record.d_name == zone) { - return !nsec->d_set.count(QType::NS); + return !nsec->isSet(QType::NS); } if (isCoveredByNSEC(zone, record.d_name, nsec->d_next)) { @@ -95,7 +95,7 @@ bool denialProvesNoDelegation(const DNSName& zone, const std::vector& const string beginHash = fromBase32Hex(record.d_name.getRawLabels()[0]); if (beginHash == h) { - return !nsec3->d_set.count(QType::NS); + return !nsec3->isSet(QType::NS); } if (isCoveredByNSEC3Hash(h, beginHash, nsec3->d_nexthash)) { @@ -154,15 +154,15 @@ static DNSName getNSECOwnerName(const DNSName& initialOwner, const std::vector& nsec) { - return nsec->d_set.count(QType::NS) && - !nsec->d_set.count(QType::SOA) && + return nsec->isSet(QType::NS) && + !nsec->isSet(QType::SOA) && signer.countLabels() < owner.countLabels(); } static bool isNSEC3AncestorDelegation(const DNSName& signer, const DNSName& owner, const std::shared_ptr& nsec3) { - return nsec3->d_set.count(QType::NS) && - !nsec3->d_set.count(QType::SOA) && + return nsec3->isSet(QType::NS) && + !nsec3->isSet(QType::SOA) && signer.countLabels() < owner.countLabels(); } @@ -191,7 +191,7 @@ static bool provesNoDataWildCard(const DNSName& qname, const uint16_t qtype, con if (qname.isPartOf(wildcard)) { LOG("\tWildcard matches"); - if (qtype == 0 || !nsec->d_set.count(qtype)) { + if (qtype == 0 || !nsec->isSet(qtype)) { LOG(" and proves that the type did not exist"<d_set.count(qtype)) { + if (qtype == 0 || !nsec3->isSet(qtype)) { LOG(" and proves that the type did not exist"<d_set.count(QType::NS))<<", SOA is "<d_set.count(QType::SOA))<<", signer is "<isSet(QType::NS))<<", SOA is "<isSet(QType::SOA))<<", signer is "<d_set.count(qtype)) { + if (nsec->isSet(qtype)) { LOG("Does _not_ deny existence of type "<d_set.count(QType::CNAME)) { + if (nsec->isSet(QType::CNAME)) { LOG("However a CNAME exists"<d_set.count(QType::NS)) { + if (referralToUnsigned && qtype == QType::DS && !nsec->isSet(QType::NS)) { LOG("However, no NS record exists at this level!"<d_set.count(qtype)<<", next: "<d_next<isSet(qtype)<<", next: "<d_next<d_set.count(QType::NS))<<", SOA is "<d_set.count(QType::SOA))<<", signer is "<isSet(QType::NS))<<", SOA is "<isSet(QType::SOA))<<", signer is "<d_set.count(qtype)) { + if (nsec3->isSet(qtype)) { LOG("Does _not_ deny existence of type "<d_set.count(QType::CNAME)) { + if (nsec3->isSet(QType::CNAME)) { LOG("However a CNAME exists"<d_set.count(QType::NS)) { + if (referralToUnsigned && qtype == QType::DS && !nsec3->isSet(QType::NS)) { LOG("However, no NS record exists at this level!"<