// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE.
+#include <exceptions/exceptions.h>
+
+#include <dns/rdata.h>
+#include <dns/rdataclass.h>
#include <dns/rrclass.h>
#include <dns/rrtype.h>
#include <dns/rrset.h>
#include <stdint.h>
#include <cstring>
+#include <typeinfo> // for bad_cast
#include <new> // for the placement new
using namespace isc::dns;
+using namespace isc::dns::rdata;
namespace isc {
namespace datasrc {
namespace memory {
+namespace {
+RRType
+getCoveredType(const Rdata& rdata) {
+ try {
+ const generic::RRSIG& rrsig_rdata =
+ dynamic_cast<const generic::RRSIG&>(rdata);
+ return (rrsig_rdata.typeCovered());
+ } catch (const std::bad_cast&) {
+ isc_throw(BadValue, "Non RRSIG is given where it's expected");
+ }
+}
+}
+
RdataSet*
RdataSet::create(util::MemorySegment& mem_sgmt, RdataEncoder& encoder,
ConstRRsetPtr rrset, ConstRRsetPtr sig_rrset)
{
- encoder.start(rrset->getClass(), rrset->getType());
- for (RdataIteratorPtr it = rrset->getRdataIterator();
- !it->isLast();
- it->next()) {
- encoder.addRdata(it->getCurrent());
+ if (!rrset && !sig_rrset) {
+ isc_throw(BadValue, "Both RRset and RRSIG are NULL");
+ }
+ if (rrset && rrset->getRdataCount() == 0) {
+ isc_throw(BadValue, "Empty RRset");
+ }
+ if (sig_rrset && sig_rrset->getRdataCount() == 0) {
+ isc_throw(BadValue, "Empty SIG RRset");
+ }
+ if (rrset && sig_rrset) {
+ if (rrset->getClass() != sig_rrset->getClass()) {
+ isc_throw(BadValue,
+ "RR class doesn't match between RRset and RRSIG");
+ }
+ }
+
+ const RRClass rrclass = rrset ? rrset->getClass() : sig_rrset->getClass();
+ const RRType rrtype = rrset ? rrset->getType() :
+ getCoveredType(sig_rrset->getRdataIterator()->getCurrent());
+ const RRTTL rrttl = rrset ? rrset->getTTL() : sig_rrset->getTTL();
+
+ encoder.start(rrclass, rrtype);
+ if (rrset) {
+ for (RdataIteratorPtr it = rrset->getRdataIterator();
+ !it->isLast();
+ it->next()) {
+ encoder.addRdata(it->getCurrent());
+ }
+ }
+ if (sig_rrset) {
+ for (RdataIteratorPtr it = sig_rrset->getRdataIterator();
+ !it->isLast();
+ it->next())
+ {
+ if (getCoveredType(it->getCurrent()) != rrtype) {
+ isc_throw(BadValue, "Type covered doesn't match");
+ }
+ encoder.addSIGRdata(it->getCurrent());
+ }
}
const size_t data_len = encoder.getStorageLength();
void* p = mem_sgmt.allocate(sizeof(RdataSet) + data_len);
- RdataSet* rdataset = new(p) RdataSet(rrset->getType(),
- rrset->getRdataCount(),
+ RdataSet* rdataset = new(p) RdataSet(rrtype,
+ rrset ? rrset->getRdataCount() : 0,
sig_rrset ?
sig_rrset->getRdataCount() : 0,
- rrset->getTTL());
+ rrttl);
encoder.encode(rdataset->getDataBuf(), data_len);
return (rdataset);
}
// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE.
+#include <exceptions/exceptions.h>
+
#include <util/buffer.h>
#include <util/memory_segment_local.h>
RdataSetTest() :
// 1076895760 = 0x40302010. Use this so we fill in all 8-bit "field"
// of the 32-bit TTL
- a_rrset_(textToRRset("www.example.com. 1076895760 IN A 192.0.2.1"))
+ a_rrset_(textToRRset("www.example.com. 1076895760 IN A 192.0.2.1")),
+ rrsig_rrset_(textToRRset("www.example.com. 1076895760 IN RRSIG "
+ "A 5 2 3600 20120814220826 20120715220826 "
+ "1234 example.com. FAKE"))
{}
void TearDown() {
EXPECT_TRUE(mem_sgmt_.allMemoryDeallocated());
}
- ConstRRsetPtr a_rrset_;
+ ConstRRsetPtr a_rrset_, rrsig_rrset_;
isc::util::MemorySegmentLocal mem_sgmt_;
RdataEncoder encoder_;
};
EXPECT_EQ(0, rdataset->getSigRdataCount());
RdataSet::destroy(mem_sgmt_, RRClass::IN(), rdataset);
}
+
+TEST_F(RdataSetTest, createWithRRSIG) {
+ // Normal case.
+ RdataSet* rdataset = RdataSet::create(mem_sgmt_, encoder_, a_rrset_,
+ rrsig_rrset_);
+ EXPECT_EQ(RRTTL(1076895760), restoreTTL(rdataset->getTTLData()));
+ EXPECT_EQ(1, rdataset->getSigRdataCount());
+ RdataSet::destroy(mem_sgmt_, RRClass::IN(), rdataset);
+
+ // Unusual case: TTL doesn't match. This implementation accepts that,
+ // using the TTL of the covered RRset.
+ ConstRRsetPtr rrsig_badttl(textToRRset(
+ "www.example.com. 3600 IN RRSIG "
+ "A 5 2 3600 20120814220826 "
+ "20120715220826 1234 example.com. FAKE"));
+ rdataset = RdataSet::create(mem_sgmt_, encoder_, a_rrset_, rrsig_badttl);
+ EXPECT_EQ(RRTTL(1076895760), restoreTTL(rdataset->getTTLData()));
+ RdataSet::destroy(mem_sgmt_, RRClass::IN(), rdataset);
+}
+
+TEST_F(RdataSetTest, createWithRRSIGOnly) {
+ // A rare, but allowed, case: RdataSet without the main RRset but with
+ // RRSIG.
+ RdataSet* rdataset = RdataSet::create(mem_sgmt_, encoder_, ConstRRsetPtr(),
+ rrsig_rrset_);
+ EXPECT_EQ(RRType::A(), rdataset->type); // type covered is used as type
+ EXPECT_EQ(RRTTL(1076895760), restoreTTL(rdataset->getTTLData()));
+ EXPECT_EQ(0, rdataset->getRdataCount());
+ EXPECT_EQ(1, rdataset->getSigRdataCount());
+ RdataSet::destroy(mem_sgmt_, RRClass::IN(), rdataset);
+}
+
+TEST_F(RdataSetTest, badCeate) {
+ // Neither the RRset nor RRSIG RRset is given
+ EXPECT_THROW(RdataSet::create(mem_sgmt_, encoder_, ConstRRsetPtr(),
+ ConstRRsetPtr()), isc::BadValue);
+
+ // Empty RRset (An RRset without RDATA)
+ ConstRRsetPtr empty_rrset(new RRset(Name("example.com"), RRClass::IN(),
+ RRType::A(), RRTTL(3600)));
+ EXPECT_THROW(RdataSet::create(mem_sgmt_, encoder_, empty_rrset,
+ ConstRRsetPtr()), isc::BadValue);
+ ConstRRsetPtr empty_rrsig(new RRset(Name("example.com"), RRClass::IN(),
+ RRType::RRSIG(), RRTTL(3600)));
+ EXPECT_THROW(RdataSet::create(mem_sgmt_, encoder_, ConstRRsetPtr(),
+ empty_rrsig), isc::BadValue);
+
+ // The RRset type and RRSIG's type covered don't match
+ ConstRRsetPtr bad_rrsig(textToRRset(
+ "www.example.com. 1076895760 IN RRSIG "
+ "NS 5 2 3600 20120814220826 20120715220826 "
+ "1234 example.com. FAKE"));
+ EXPECT_THROW(RdataSet::create(mem_sgmt_, encoder_, a_rrset_, bad_rrsig),
+ isc::BadValue);
+
+ // Pass non RRSIG for the sig parameter
+ EXPECT_THROW(RdataSet::create(mem_sgmt_, encoder_, a_rrset_, a_rrset_),
+ isc::BadValue);
+
+ // RR class doesn't match between RRset and RRSIG
+ ConstRRsetPtr badclass_rrsig(textToRRset(
+ "www.example.com. 1076895760 CH RRSIG "
+ "A 5 2 3600 20120814220826 "
+ "20120715220826 1234 example.com. FAKE",
+ RRClass::CH()));
+ EXPECT_THROW(RdataSet::create(mem_sgmt_, encoder_, a_rrset_,
+ badclass_rrsig),
+ isc::BadValue);
+}
}