From: JINMEI Tatuya Date: Mon, 12 Nov 2012 21:46:55 +0000 (-0800) Subject: [2420] extend RdataSet::find() to control whether to match sig-only RdataSets. X-Git-Tag: bind10-1.0.0-beta-release~52^2~1^2~2^2~13 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=d805ae680fc4fc5920c5bc50e2ae0817379df1cf;p=thirdparty%2Fkea.git [2420] extend RdataSet::find() to control whether to match sig-only RdataSets. and use it in zone data updater to preserve the previous behavior. --- diff --git a/src/lib/datasrc/memory/rdataset.h b/src/lib/datasrc/memory/rdataset.h index 84117b4c0f..ffa5075439 100644 --- a/src/lib/datasrc/memory/rdataset.h +++ b/src/lib/datasrc/memory/rdataset.h @@ -205,6 +205,11 @@ public: /// if not found in the entire list, it returns NULL. The head pointer /// can be NULL, in which case this function will simply return NULL. /// + /// By default, this method ignores an RdataSet that only contains an + /// RRSIG (i.e., missing the covered RdataSet); if the optional + /// sigonly_ok parameter is explicitly set to true, it matches such + /// RdataSet and returns it if found. + /// /// \note This function is defined as a (static) class method to /// clarify its an operation for \c RdataSet objects and to make the /// name shorter. But its implementation does not depend on private @@ -215,10 +220,14 @@ public: /// \param rdata_head A pointer to \c RdataSet from which the search /// starts. It can be NULL. /// \param type The RRType of \c RdataSet to find. + /// \param sigonly_ok Whether it should find an RdataSet that only has + /// RRSIG /// \return A pointer to the found \c RdataSet or NULL if none found. static const RdataSet* - find(const RdataSet* rdataset_head, const dns::RRType& type) { - return (find(rdataset_head, type)); + find(const RdataSet* rdataset_head, const dns::RRType& type, + bool sigonly_ok = false) + { + return (find(rdataset_head, type, sigonly_ok)); } /// \brief Find \c RdataSet of given RR type from a list (non const @@ -227,8 +236,10 @@ public: /// This is similar to the const version, except it takes and returns non /// const pointers. static RdataSet* - find(RdataSet* rdataset_head, const dns::RRType& type) { - return (find(rdataset_head, type)); + find(RdataSet* rdataset_head, const dns::RRType& type, + bool sigonly_ok = false) + { + return (find(rdataset_head, type, sigonly_ok)); } typedef boost::interprocess::offset_ptr RdataSetPtr; @@ -347,12 +358,14 @@ private: // Shared by both mutable and immutable versions of find() template static RdataSetType* - find(RdataSetType* rdataset_head, const dns::RRType& type) { + find(RdataSetType* rdataset_head, const dns::RRType& type, bool sigonly_ok) + { for (RdataSetType* rdataset = rdataset_head; rdataset != NULL; rdataset = rdataset->getNext()) // use getNext() for efficiency { - if (rdataset->type == type) { + if (rdataset->type == type && + (rdataset->getRdataCount() > 0 || sigonly_ok)) { return (rdataset); } } diff --git a/src/lib/datasrc/memory/zone_data_updater.cc b/src/lib/datasrc/memory/zone_data_updater.cc index 9e4e2444f0..e0f9bfc598 100644 --- a/src/lib/datasrc/memory/zone_data_updater.cc +++ b/src/lib/datasrc/memory/zone_data_updater.cc @@ -294,7 +294,7 @@ ZoneDataUpdater::addRdataSet(const Name& name, const RRType& rrtype, contextCheck(*rrset, rdataset_head); } - if (RdataSet::find(rdataset_head, rrtype) != NULL) { + if (RdataSet::find(rdataset_head, rrtype, true) != NULL) { isc_throw(AddError, "RRset of the type already exists: " << name << " (type: " << rrtype << ")"); diff --git a/src/lib/datasrc/tests/memory/rdataset_unittest.cc b/src/lib/datasrc/tests/memory/rdataset_unittest.cc index bf7bd3bd97..f5999999e2 100644 --- a/src/lib/datasrc/tests/memory/rdataset_unittest.cc +++ b/src/lib/datasrc/tests/memory/rdataset_unittest.cc @@ -40,6 +40,7 @@ using namespace isc::dns; using namespace isc::dns::rdata; using namespace isc::datasrc::memory; using namespace isc::testutils; +using isc::datasrc::memory::detail::SegmentObjectHolder; using boost::lexical_cast; namespace { @@ -135,6 +136,61 @@ TEST_F(RdataSetTest, getNext) { RdataSet::destroy(mem_sgmt_, rdataset, RRClass::IN()); } +TEST_F(RdataSetTest, find) { + // Create some RdataSets and make a chain of them. + SegmentObjectHolder holder1( + mem_sgmt_, + RdataSet::create(mem_sgmt_, encoder_, a_rrset_, ConstRRsetPtr()), + RRClass::IN()); + ConstRRsetPtr aaaa_rrset = + textToRRset("www.example.com. 1076895760 IN AAAA 2001:db8::1"); + SegmentObjectHolder holder2( + mem_sgmt_, + RdataSet::create(mem_sgmt_, encoder_, aaaa_rrset, ConstRRsetPtr()), + RRClass::IN()); + ConstRRsetPtr sigonly_rrset = + textToRRset("www.example.com. 1076895760 IN RRSIG " + "TXT 5 2 3600 20120814220826 20120715220826 " + "1234 example.com. FAKE"); + SegmentObjectHolder holder3( + mem_sgmt_, + RdataSet::create(mem_sgmt_, encoder_, ConstRRsetPtr(), sigonly_rrset), + RRClass::IN()); + + RdataSet* rdataset_a = holder1.get(); + RdataSet* rdataset_aaaa = holder2.get(); + RdataSet* rdataset_sigonly = holder3.get(); + RdataSet* rdataset_null = NULL; + rdataset_a->next = rdataset_aaaa; + rdataset_aaaa->next = rdataset_sigonly; + + // If a non-RRSIG part of rdataset exists for the given type, it will be + // returned regardless of the value of sigonly_ok. If it's RRSIG-only + // rdataset, it returns non NULL iff sigonly_ok is explicitly set to true. + EXPECT_EQ(rdataset_aaaa, RdataSet::find(rdataset_a, RRType::AAAA())); + EXPECT_EQ(rdataset_aaaa, RdataSet::find(rdataset_a, RRType::AAAA(), true)); + EXPECT_EQ(rdataset_aaaa, RdataSet::find(rdataset_a, RRType::AAAA(), false)); + + EXPECT_EQ(rdataset_null, RdataSet::find(rdataset_a, RRType::TXT())); + EXPECT_EQ(rdataset_sigonly, RdataSet::find(rdataset_a, RRType::TXT(), + true)); + EXPECT_EQ(rdataset_null, RdataSet::find(rdataset_a, RRType::TXT(), false)); + + // Same tests for the const version of find(). + const RdataSet* rdataset_a_const = holder1.get(); + EXPECT_EQ(rdataset_aaaa, RdataSet::find(rdataset_a_const, RRType::AAAA())); + EXPECT_EQ(rdataset_aaaa, RdataSet::find(rdataset_a_const, RRType::AAAA(), + true)); + EXPECT_EQ(rdataset_aaaa, RdataSet::find(rdataset_a_const, RRType::AAAA(), + false)); + + EXPECT_EQ(rdataset_null, RdataSet::find(rdataset_a_const, RRType::TXT())); + EXPECT_EQ(rdataset_sigonly, RdataSet::find(rdataset_a_const, RRType::TXT(), + true)); + EXPECT_EQ(rdataset_null, RdataSet::find(rdataset_a_const, RRType::TXT(), + false)); +} + // A helper function to create an RRset containing the given number of // unique RDATAs. ConstRRsetPtr diff --git a/src/lib/datasrc/tests/memory/zone_data_updater_unittest.cc b/src/lib/datasrc/tests/memory/zone_data_updater_unittest.cc index 7fed9522e9..60b942b0ab 100644 --- a/src/lib/datasrc/tests/memory/zone_data_updater_unittest.cc +++ b/src/lib/datasrc/tests/memory/zone_data_updater_unittest.cc @@ -94,7 +94,7 @@ TEST_F(ZoneDataUpdaterTest, rrisgOnly) { ZoneNode* node = getNode(mem_sgmt_, Name("www.example.org"), zone_data_); const RdataSet* rdset = node->getData(); ASSERT_NE(static_cast(NULL), rdset); - rdset = RdataSet::find(rdset, RRType::A()); + rdset = RdataSet::find(rdset, RRType::A(), true); ASSERT_NE(static_cast(NULL), rdset); EXPECT_EQ(0, rdset->getRdataCount()); EXPECT_EQ(1, rdset->getSigRdataCount());