@@ -672,173 +672,151 @@ vector<ComboAddress> PacketHandler::getIPAddressFor(const DNSName &target, const
672672 return ret;
673673}
674674
675- void PacketHandler::emitNSEC (std::unique_ptr<DNSPacket>& r, const DNSName& name, const DNSName& next, int mode)
675+ // Common part to NSEC and NSEC3 to compute the QType bitmap in the NSEC
676+ // or NSEC3 response, part 1.
677+ void PacketHandler::computeNSECbitmap1 (NSECBitmap& bitmap)
676678{
677- NSECRecordContent nrc;
678- nrc.d_next = next;
679-
680- nrc.set (QType::NSEC );
681- nrc.set (QType::RRSIG );
682- if (d_sd.qname () == name) {
683- nrc.set (QType::SOA ); // 1dfd8ad SOA can live outside the records table
684- if (!isPresigned ()) {
685- auto keyset = d_dk.getKeys (d_sd.zonename );
686- for (const auto & value: keyset) {
687- if (value.second .published ) {
688- nrc.set (QType::DNSKEY );
689- string publishCDNSKEY;
690- d_dk.getPublishCDNSKEY (d_sd.zonename , publishCDNSKEY);
691- if (! publishCDNSKEY.empty ())
692- nrc.set (QType::CDNSKEY );
693- string publishCDS;
694- d_dk.getPublishCDS (d_sd.zonename , publishCDS);
695- if (! publishCDS.empty ())
696- nrc.set (QType::CDS );
697- break ;
679+ bitmap.set (QType::SOA ); // 1dfd8ad SOA can live outside the records table
680+ if (!isPresigned ()) {
681+ auto keyset = d_dk.getKeys (d_sd.zonename );
682+ for (const auto & value: keyset) {
683+ if (value.second .published ) {
684+ bitmap.set (QType::DNSKEY );
685+ string publishCDNSKEY;
686+ d_dk.getPublishCDNSKEY (d_sd.zonename , publishCDNSKEY);
687+ if (!publishCDNSKEY.empty ()) {
688+ bitmap.set (QType::CDNSKEY );
689+ }
690+ string publishCDS;
691+ d_dk.getPublishCDS (d_sd.zonename , publishCDS);
692+ if (!publishCDS.empty ()) {
693+ bitmap.set (QType::CDS );
698694 }
695+ break ;
699696 }
700697 }
701698 }
699+ }
702700
703- DNSZoneRecord rr;
701+ // Common part to NSEC and NSEC3 to compute the QType bitmap in the NSEC
702+ // or NSEC3 response, part 2.
703+ domainid_t PacketHandler::computeNSECbitmap2 (NSECBitmap& bitmap, const DNSName& name, bool includeENT)
704+ {
705+ DNSZoneRecord rec;
704706#ifdef HAVE_LUA_RECORDS
705707 bool first{true };
706708 bool doLua{false };
707709#endif
708710
709711 B.lookup (QType (QType::ANY ), name, d_sd.domain_id );
710- while (B.get (rr )) {
712+ while (B.get (rec )) {
711713#ifdef HAVE_LUA_RECORDS
712- if (rr .dr .d_type == QType::LUA && first && !isPresigned ()) {
714+ if (rec .dr .d_type == QType::LUA && first && !isPresigned ()) {
713715 first = false ;
714716 doLua = doLuaRecords ();
715717 }
716718
717- if (rr.dr .d_type == QType::LUA && doLua) {
718- nrc.set (getRR<LUARecordContent>(rr.dr )->d_type );
719+ if (rec.dr .d_type == QType::LUA && doLua) {
720+ bitmap.set (getRR<LUARecordContent>(rec.dr )->d_type );
721+ continue ;
719722 }
720- else
721723#endif
722- if (d_doExpandALIAS && rr.dr .d_type == QType::ALIAS ) {
724+
725+ if (d_doExpandALIAS && rec.dr .d_type == QType::ALIAS ) {
723726 // Set the A and AAAA in the NSEC bitmap so aggressive NSEC
724727 // does not falsely deny the type for this name.
725728 // This does NOT add the ALIAS to the bitmap, as that record cannot
726729 // be requested.
727730 if (!isPresigned ()) {
728- nrc .set (QType::A);
729- nrc .set (QType::AAAA );
731+ bitmap .set (QType::A);
732+ bitmap .set (QType::AAAA );
730733 }
731734 }
732- else if ((rr .dr .d_type == QType::DNSKEY || rr .dr .d_type == QType::CDS || rr .dr .d_type == QType::CDNSKEY ) && !isPresigned () && !::arg ().mustDo (" direct-dnskey" )) {
735+ else if ((rec .dr .d_type == QType::DNSKEY || rec .dr .d_type == QType::CDS || rec .dr .d_type == QType::CDNSKEY ) && !isPresigned () && !::arg ().mustDo (" direct-dnskey" )) {
733736 continue ;
734737 }
735- else if (rr.dr .d_type == QType::NS || rr.auth ) {
736- nrc.set (rr.dr .d_type );
738+ else if (rec.dr .d_type == QType::NS || rec.auth ) {
739+ // skip empty non-terminals unless explicitly requested
740+ if (rec.dr .d_type != QType::ENT || includeENT) {
741+ bitmap.set (rec.dr .d_type );
742+ }
737743 }
738744 }
739745
740- rr.dr .d_name = name;
741- rr.dr .d_ttl = d_sd.getNegativeTTL ();
742- rr.dr .d_type = QType::NSEC ;
743- rr.dr .setContent (std::make_shared<NSECRecordContent>(std::move (nrc)));
744- rr.dr .d_place = (mode == 5 ) ? DNSResourceRecord::ANSWER : DNSResourceRecord::AUTHORITY ;
745- rr.auth = true ;
746+ // Callers need a proper domain id value to put in the NSEC or NSEC3 record
747+ // they're building, for the sake of addRRSigs() later.
748+ return rec.domain_id ;
749+ }
746750
747- r->addRecord (std::move (rr));
751+ void PacketHandler::emitNSEC (std::unique_ptr<DNSPacket>& r, const DNSName& name, const DNSName& next, int mode)
752+ {
753+ NSECBitmap bitmap;
754+ if (d_sd.qname () == name) {
755+ computeNSECbitmap1 (bitmap);
756+ }
757+
758+ DNSZoneRecord rec;
759+ rec.domain_id = computeNSECbitmap2 (bitmap, name, true );
760+
761+ NSECRecordContent nrc;
762+ nrc.d_next = next;
763+ nrc.set (bitmap);
764+ nrc.set (QType::NSEC );
765+ nrc.set (QType::RRSIG );
766+
767+ rec.dr .d_name = name;
768+ rec.dr .d_ttl = d_sd.getNegativeTTL ();
769+ rec.dr .d_type = QType::NSEC ;
770+ rec.dr .setContent (std::make_shared<NSECRecordContent>(std::move (nrc)));
771+ rec.dr .d_place = (mode == 5 ) ? DNSResourceRecord::ANSWER : DNSResourceRecord::AUTHORITY ;
772+ rec.auth = true ;
773+
774+ r->addRecord (std::move (rec));
748775}
749776
750777void PacketHandler::emitNSEC3 (DNSPacket& p, std::unique_ptr<DNSPacket>& r, const NSEC3PARAMRecordContent& ns3prc, const DNSName& name, const string& namehash, const string& nexthash, int mode) // NOLINT(readability-identifier-length)
751778{
752- NSEC3RecordContent n3rc;
753- n3rc.d_algorithm = ns3prc.d_algorithm ;
754- n3rc.d_flags = ns3prc.d_flags ;
755- n3rc.d_iterations = ns3prc.d_iterations ;
756- n3rc.d_salt = ns3prc.d_salt ;
757- n3rc.d_nexthash = nexthash;
758-
759- DNSZoneRecord rr;
779+ NSECBitmap bitmap;
780+ DNSZoneRecord rec;
760781
761- if (!name.empty ()) {
782+ if (!name.empty ()) {
762783 if (d_sd.qname () == name) {
763- n3rc.set (QType::SOA ); // 1dfd8ad SOA can live outside the records table
764- n3rc.set (QType::NSEC3PARAM );
765- if (!isPresigned ()) {
766- auto keyset = d_dk.getKeys (d_sd.zonename );
767- for (const auto & value: keyset) {
768- if (value.second .published ) {
769- n3rc.set (QType::DNSKEY );
770- string publishCDNSKEY;
771- d_dk.getPublishCDNSKEY (d_sd.zonename , publishCDNSKEY);
772- if (! publishCDNSKEY.empty ())
773- n3rc.set (QType::CDNSKEY );
774- string publishCDS;
775- d_dk.getPublishCDS (d_sd.zonename , publishCDS);
776- if (! publishCDS.empty ())
777- n3rc.set (QType::CDS );
778- break ;
779- }
780- }
781- }
782- } else if (mode == 6 ) {
784+ bitmap.set (QType::NSEC3PARAM );
785+ computeNSECbitmap1 (bitmap);
786+ bitmap.set (QType::SOA ); // 1dfd8ad SOA can live outside the records table
787+ } else if (mode == 6 ) {
783788 if (p.qtype .getCode () != QType::CDS ) {
784- n3rc .set (QType::CDS );
789+ bitmap .set (QType::CDS );
785790 }
786791 if (p.qtype .getCode () != QType::CDNSKEY ) {
787- n3rc .set (QType::CDNSKEY );
792+ bitmap .set (QType::CDNSKEY );
788793 }
789794 }
790795
791- #ifdef HAVE_LUA_RECORDS
792- bool first{true };
793- bool doLua{false };
794- #endif
795-
796- B.lookup (QType (QType::ANY ), name, d_sd.domain_id );
797- while (B.get (rr)) {
798- #ifdef HAVE_LUA_RECORDS
799- if (rr.dr .d_type == QType::LUA && first && !isPresigned ()) {
800- first = false ;
801- doLua = doLuaRecords ();
802- }
803-
804- if (rr.dr .d_type == QType::LUA && doLua) {
805- n3rc.set (getRR<LUARecordContent>(rr.dr )->d_type );
806- }
807- else
808- #endif
809- if (d_doExpandALIAS && rr.dr .d_type == QType::ALIAS ) {
810- // Set the A and AAAA in the NSEC3 bitmap so aggressive NSEC
811- // does not falsely deny the type for this name.
812- // This does NOT add the ALIAS to the bitmap, as that record cannot
813- // be requested.
814- if (!isPresigned ()) {
815- n3rc.set (QType::A);
816- n3rc.set (QType::AAAA );
817- }
818- }
819- else if ((rr.dr .d_type == QType::DNSKEY || rr.dr .d_type == QType::CDS || rr.dr .d_type == QType::CDNSKEY ) && !isPresigned () && !::arg ().mustDo (" direct-dnskey" )) {
820- continue ;
821- }
822- else if (rr.dr .d_type && (rr.dr .d_type == QType::NS || rr.auth )) {
823- // skip empty non-terminals
824- n3rc.set (rr.dr .d_type );
825- }
826- }
796+ rec.domain_id = computeNSECbitmap2 (bitmap, name, false ); // skip empty non-terminals
827797 }
828798
799+ NSEC3RecordContent n3rc;
800+ n3rc.d_algorithm = ns3prc.d_algorithm ;
801+ n3rc.d_flags = ns3prc.d_flags ;
802+ n3rc.d_iterations = ns3prc.d_iterations ;
803+ n3rc.d_salt = ns3prc.d_salt ;
804+ n3rc.d_nexthash = nexthash;
805+
806+ n3rc.set (bitmap);
829807 const auto numberOfTypesSet = n3rc.numberOfTypesSet ();
830808 if (numberOfTypesSet != 0 && !(numberOfTypesSet == 1 && n3rc.isSet (QType::NS ))) {
831809 n3rc.set (QType::RRSIG );
832810 }
833811
834- rr .dr .d_name = DNSName (toBase32Hex (namehash))+d_sd.qname ();
835- rr .dr .d_ttl = d_sd.getNegativeTTL ();
836- rr .dr .d_type =QType::NSEC3 ;
837- rr .dr .setContent (std::make_shared<NSEC3RecordContent>(std::move (n3rc)));
838- rr .dr .d_place = (mode == 5 ) ? DNSResourceRecord::ANSWER : DNSResourceRecord::AUTHORITY ;
839- rr .auth = true ;
812+ rec .dr .d_name = DNSName (toBase32Hex (namehash))+d_sd.qname ();
813+ rec .dr .d_ttl = d_sd.getNegativeTTL ();
814+ rec .dr .d_type =QType::NSEC3 ;
815+ rec .dr .setContent (std::make_shared<NSEC3RecordContent>(std::move (n3rc)));
816+ rec .dr .d_place = (mode == 5 ) ? DNSResourceRecord::ANSWER : DNSResourceRecord::AUTHORITY ;
817+ rec .auth = true ;
840818
841- r->addRecord (std::move (rr ));
819+ r->addRecord (std::move (rec ));
842820}
843821
844822/*
0 commit comments