From: JINMEI Tatuya Date: Wed, 23 Jan 2013 04:56:47 +0000 (-0800) Subject: [2309] supported use_minttl part of findAtOrigin. X-Git-Tag: bind10-1.0.0-rc-release~25^2~10^2~13^2~4 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=6317823834dced610691841ee7c082249fa1f8fe;p=thirdparty%2Fkea.git [2309] supported use_minttl part of findAtOrigin. --- diff --git a/src/lib/datasrc/tests/database_unittest.cc b/src/lib/datasrc/tests/database_unittest.cc index 1032411d4a..3f81864055 100644 --- a/src/lib/datasrc/tests/database_unittest.cc +++ b/src/lib/datasrc/tests/database_unittest.cc @@ -1813,6 +1813,7 @@ doFindAtOriginTest(ZoneFinder& finder, ZoneFinder::Result expected_result, const std::vector& expected_rdatas, const std::vector& expected_sig_rdatas, + bool use_minttl = false, ZoneFinder::FindResultFlags expected_flags = ZoneFinder::RESULT_DEFAULT, const isc::dns::Name& expected_name = @@ -1822,7 +1823,7 @@ doFindAtOriginTest(ZoneFinder& finder, { SCOPED_TRACE("doFindOriginTest " + origin.toText() + " " + type.toText()); ConstZoneFinderContextPtr result = - finder.findAtOrigin(type, false, options); + finder.findAtOrigin(type, use_minttl, options); findTestCommon(finder, origin, type, result, expected_type, expected_ttl, expected_result, expected_rdatas, expected_sig_rdatas, expected_flags, expected_name, options); @@ -2182,7 +2183,7 @@ TYPED_TEST(DatabaseClientTest, findAtOrigin) { doFindAtOriginTest(*finder, this->zname_, RRType::NS(), RRType::NS(), this->rrttl_, ZoneFinder::SUCCESS, this->expected_rdatas_, this->expected_sig_rdatas_, - ZoneFinder::RESULT_DEFAULT, this->zname_, + false, ZoneFinder::RESULT_DEFAULT, this->zname_, ZoneFinder::FIND_DNSSEC); // Specified type of RR doesn't exist, no DNSSEC @@ -2203,7 +2204,7 @@ TYPED_TEST(DatabaseClientTest, findAtOrigin) { doFindAtOriginTest(*finder, this->zname_, RRType::TXT(), RRType::NSEC(), this->rrttl_, ZoneFinder::NXRRSET, this->expected_rdatas_, this->expected_sig_rdatas_, - ZoneFinder::RESULT_NSEC_SIGNED, + false, ZoneFinder::RESULT_NSEC_SIGNED, this->zname_, ZoneFinder::FIND_DNSSEC); // Specified type of RR doesn't exist, with DNSSEC, enabling NSEC3 @@ -2213,10 +2214,111 @@ TYPED_TEST(DatabaseClientTest, findAtOrigin) { doFindAtOriginTest(*finder, this->zname_, RRType::TXT(), RRType::TXT(), this->rrttl_, ZoneFinder::NXRRSET, this->expected_rdatas_, this->expected_sig_rdatas_, - ZoneFinder::RESULT_NSEC3_SIGNED, + false, ZoneFinder::RESULT_NSEC3_SIGNED, this->zname_, ZoneFinder::FIND_DNSSEC); } +TYPED_TEST(DatabaseClientTest, findAtOriginWithMinTTL) { + // First, replace the SOA of the test zone so that its RR TTL is larger + // than MINTTL (the original data are used in many places, so replacing + // them just for this doesn't make sense). + RRsetPtr old_soa(new RRset(this->zname_, this->qclass_, RRType::SOA(), + this->rrttl_)); + old_soa->addRdata(rdata::createRdata(RRType::SOA(), this->qclass_, + "ns1.example.org. admin.example.org. " + "1234 3600 1800 2419200 7200")); + + const string new_soa_rdata = "ns1.example.org. admin.example.org. " + "1234 3600 1800 2419200 1200"; + RRsetPtr new_soa(new RRset(this->zname_, this->qclass_, RRType::SOA(), + this->rrttl_)); + new_soa->addRdata(rdata::createRdata(RRType::SOA(), this->qclass_, + new_soa_rdata)); + + this->updater_ = this->client_->getUpdater(this->zname_, false); + this->updater_->deleteRRset(*old_soa); + this->updater_->addRRset(*new_soa); + this->updater_->commit(); + + ZoneFinderPtr finder = this->getFinder(); + + // Specify the use of min TTL, then the resulting TTL should be drived + // from the SOA MINTTL (which is smaller). + this->expected_rdatas_.push_back(new_soa_rdata); + doFindAtOriginTest(*finder, this->zname_, RRType::SOA(), RRType::SOA(), + RRTTL(1200), ZoneFinder::SUCCESS, + this->expected_rdatas_, this->expected_sig_rdatas_, + true); + + // If DNSSEC is requested, TTL of the RRSIG should also be the min. + this->expected_sig_rdatas_.push_back( + "SOA 5 3 3600 20000101000000 " + "20000201000000 12345 example.org. FAKEFAKEFAKE"); + doFindAtOriginTest(*finder, this->zname_, RRType::SOA(), RRType::SOA(), + RRTTL(1200), ZoneFinder::SUCCESS, + this->expected_rdatas_, this->expected_sig_rdatas_, + true, ZoneFinder::RESULT_DEFAULT, this->zname_, + ZoneFinder::FIND_DNSSEC); + + // Not really intended usage, but specify the use of min TTL for non SOA. + // It should still work as specified. + this->expected_rdatas_.clear(); + this->expected_sig_rdatas_.clear(); + this->expected_rdatas_.push_back("ns.example.com."); + doFindAtOriginTest(*finder, this->zname_, RRType::NS(), RRType::NS(), + RRTTL(1200), ZoneFinder::SUCCESS, + this->expected_rdatas_, this->expected_sig_rdatas_, + true); + + // If we don't request the use of min TTL, the original TTL will be used. + this->expected_rdatas_.clear(); + this->expected_rdatas_.push_back(new_soa_rdata); + doFindAtOriginTest(*finder, this->zname_, RRType::SOA(), RRType::SOA(), + this->rrttl_, ZoneFinder::SUCCESS, + this->expected_rdatas_, this->expected_sig_rdatas_); + + // If no RRset is returned, use_minttl doesn't matter (it shouldn't cause + // disruption) + this->expected_rdatas_.clear(); + doFindAtOriginTest(*finder, this->zname_, RRType::TXT(), this->qtype_, + this->rrttl_, ZoneFinder::NXRRSET, + this->expected_rdatas_, this->expected_sig_rdatas_, + true); + + // If it results in NXRRSET with NSEC, and if we specify the use of min + // TTL, the NSEC and RRSIG should have the min TTL (again, though, this + // use case is not really the intended one) + this->expected_rdatas_.push_back( + "acnamesig1.example.org. A NS RRSIG NSEC"); + this->expected_sig_rdatas_.push_back("NSEC 5 3 3600 20000101000000 " + "20000201000000 12345 example.org. " + "FAKEFAKEFAKE"); + doFindAtOriginTest(*finder, this->zname_, RRType::TXT(), RRType::NSEC(), + RRTTL(1200), ZoneFinder::NXRRSET, + this->expected_rdatas_, this->expected_sig_rdatas_, + true, ZoneFinder::RESULT_NSEC_SIGNED, + this->zname_, ZoneFinder::FIND_DNSSEC); +} + +TYPED_TEST(DatabaseClientTest, findAtOriginWithMinTTLBroken) { + // Similar to the previous case, but we intentionally remove the SOA + // (assuming the underlying data source doesn't complain about it). + // This will cause exception in subsequent findAtOrigin() with use_minttl + // being true. + RRsetPtr old_soa(new RRset(this->zname_, this->qclass_, RRType::SOA(), + this->rrttl_)); + old_soa->addRdata(rdata::createRdata(RRType::SOA(), this->qclass_, + "ns1.example.org. admin.example.org. " + "1234 3600 1800 2419200 7200")); + this->updater_ = this->client_->getUpdater(this->zname_, false); + this->updater_->deleteRRset(*old_soa); + this->updater_->commit(); + + EXPECT_THROW(this->getFinder()->findAtOrigin(RRType::NS(), true, + ZoneFinder::FIND_DEFAULT), + DataSourceError); +} + TYPED_TEST(DatabaseClientTest, findOutOfZone) { // If the query name is out-of-zone it should result in an exception boost::shared_ptr finder(this->getFinder()); diff --git a/src/lib/datasrc/zone_finder.cc b/src/lib/datasrc/zone_finder.cc index c0f0d41fc7..4e836cc3be 100644 --- a/src/lib/datasrc/zone_finder.cc +++ b/src/lib/datasrc/zone_finder.cc @@ -12,13 +12,14 @@ // OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR // PERFORMANCE OF THIS SOFTWARE. +#include +#include + #include #include #include #include -#include - using namespace std; using namespace isc::dns; using namespace isc::dns::rdata; @@ -26,11 +27,94 @@ using namespace isc::dns::rdata; namespace isc { namespace datasrc { +namespace { +// Identify zone's SOA and return its MINTTL in the form of RRTTL. +RRTTL +getMinTTL(ZoneFinder& finder, ConstRRsetPtr rrset) { + ConstRRsetPtr soa_rrset; + if (rrset->getType() == RRType::SOA()) { + // Shortcut: if we are looking at SOA itself (which should be the + // case in the expected scenario), we can simply use its RDATA. + soa_rrset = rrset; + } else { + soa_rrset = + finder.findAtOrigin(RRType::SOA(), false, + ZoneFinder::FIND_DEFAULT)->rrset; + } + + // In a valid zone there is one and only one SOA RR at the origin. + // Otherwise either zone data or the data source implementation is broken. + if (!soa_rrset || soa_rrset->getRdataCount() != 1) { + isc_throw(DataSourceError, "Zone " << rrset->getName().toText(true) + << "/" << rrset->getClass().toText() << " is broken: " + << (!soa_rrset ? "no SOA" : "empty SOA")); + } + + return (RRTTL(dynamic_cast( + soa_rrset->getRdataIterator()->getCurrent()). + getMinimum())); +} + +// Make a fresh copy of given RRset, just replacing RRTTL with the given one. +RRsetPtr +copyRRset(const AbstractRRset& rrset, const RRTTL& ttl) { + RRsetPtr rrset_copy(new RRset(rrset.getName(), rrset.getClass(), + rrset.getType(), ttl)); + for (RdataIteratorPtr rit = rrset.getRdataIterator(); + !rit->isLast(); + rit->next()) { + rrset_copy->addRdata(rit->getCurrent()); + } + + ConstRRsetPtr rrsig = rrset.getRRsig(); + if (rrsig) { + RRsetPtr rrsig_copy(new RRset(rrset.getName(), rrset.getClass(), + RRType::RRSIG(), ttl)); + for (RdataIteratorPtr rit = rrsig->getRdataIterator(); + !rit->isLast(); + rit->next()) { + rrsig_copy->addRdata(rit->getCurrent()); + } + rrset_copy->addRRsig(rrsig_copy); + } + + return (rrset_copy); +} +} + ZoneFinderContextPtr -ZoneFinder::findAtOrigin(const dns::RRType& type, bool /*use_minmtu*/, +ZoneFinder::findAtOrigin(const dns::RRType& type, bool use_minttl, FindOptions options) { - return (find(getOrigin(), type, options)); + ZoneFinderContextPtr context = find(getOrigin(), type, options); + + // If we are requested to use the min TTL and the RRset's RR TTL is larger + // than that, we need to make a copy of the RRset, replacing the TTL, + // and return a newly created context copying other parameters. + if (use_minttl && context->rrset) { + const AbstractRRset& rrset = *context->rrset; + const RRTTL min_ttl = getMinTTL(*this, context->rrset); + if (min_ttl < rrset.getTTL()) { + FindResultFlags flags_copy = RESULT_DEFAULT; + if (context->isWildcard()) { + flags_copy = flags_copy | RESULT_WILDCARD; + } + if (context->isNSECSigned()) { + flags_copy = flags_copy | RESULT_NSEC_SIGNED; + } else if (context->isNSEC3Signed()) { + flags_copy = flags_copy | RESULT_NSEC3_SIGNED; + } + + return (ZoneFinderContextPtr( + new GenericContext(*this, options, + ResultContext(context->code, + copyRRset(rrset, + min_ttl), + flags_copy)))); + } + } + + return (context); } isc::dns::ConstRRsetPtr diff --git a/src/lib/datasrc/zone_finder.h b/src/lib/datasrc/zone_finder.h index 27263b9aa2..f9a92006d1 100644 --- a/src/lib/datasrc/zone_finder.h +++ b/src/lib/datasrc/zone_finder.h @@ -584,7 +584,7 @@ public: /// This is an equivalent of a call to \c find() where the \c name /// parameter is the zone origin. virtual boost::shared_ptr findAtOrigin( - const isc::dns::RRType& type, bool use_minmtu, + const isc::dns::RRType& type, bool use_minttl, FindOptions options); ///