return (AbstractRRset::toText());
}
+uint16_t
+BasicRRset::getLength() const {
+ uint16_t length = 0;
+ RdataIteratorPtr it = getRdataIterator();
+
+ if (it->isLast()) {
+ // empty rrsets are only allowed for classes ANY and NONE
+ if (getClass() != RRClass::ANY() &&
+ getClass() != RRClass::NONE()) {
+ isc_throw(EmptyRRset, "getLength() is attempted for an empty RRset");
+ }
+
+ // For an empty RRset, write the name, type, class and TTL once,
+ // followed by empty rdata.
+ length += getName().getLength();
+ length += 2; // TYPE field
+ length += 2; // CLASS field
+ length += 2; // TTL field
+ length += 2; // RDLENGTH field (=0 in wire format)
+
+ return (length);
+ }
+
+ do {
+ // This is a size_t as some of the following additions may
+ // overflow due to a programming mistake somewhere.
+ size_t rrlen = 0;
+
+ rrlen += getName().getLength();
+ rrlen += 2; // TYPE field
+ rrlen += 2; // CLASS field
+ rrlen += 2; // TTL field
+ rrlen += 2; // RDLENGTH field
+ rrlen += it->getCurrent().getLength();
+
+ assert(length + rrlen < 65536);
+ length += rrlen;
+
+ it->next();
+ } while (!it->isLast());
+
+ return (length);
+}
+
unsigned int
BasicRRset::toWire(OutputBuffer& buffer) const {
return (AbstractRRset::toWire(buffer));
}
}
+uint16_t
+RRset::getLength() const {
+ uint16_t length = BasicRRset::getLength();
+
+ if (rrsig_) {
+ const uint16_t rrsigs_length = rrsig_->getLength();
+ // the uint16_ts are promoted to ints during addition below, so
+ // it won't overflow a 16-bit register.
+ assert(length + rrsigs_length < 65536);
+ length += rrsigs_length;
+ }
+
+ return (length);
+}
+
unsigned int
RRset::toWire(OutputBuffer& buffer) const {
unsigned int rrs_written = BasicRRset::toWire(buffer);
/// \return The number of \c Rdata objects contained.
virtual unsigned int getRdataCount() const = 0;
+ /// \brief Get the wire format length of the \c AbstractRRset.
+ ///
+ /// This method returns the wire format length of the
+ /// \c AbstractRRset, which is calculated by summing the individual
+ /// lengths of the various fields that make up each RR.
+ ///
+ /// NOTE: When including name lengths, the allocation for
+ /// uncompressed name wire format representation is used.
+ ///
+ /// \return The length of the wire format representation of the
+ /// \c AbstractRRset.
+ /// \throw \c EmptyRRset if the \c AbstractRRset is empty.
+ virtual uint16_t getLength() const = 0;
+
/// \brief Returns the owner name of the \c RRset.
///
/// \return A reference to a \c Name class object corresponding to the
/// \return The number of \c Rdata objects contained.
virtual unsigned int getRdataCount() const;
+ /// \brief Get the wire format length of the \c BasicRRset.
+ ///
+ /// \return The length of the wire format representation of the
+ /// \c BasicRRset.
+ /// \throw \c EmptyRRset if the \c BasicRRset is empty.
+ virtual uint16_t getLength() const;
+
/// \brief Returns the owner name of the \c RRset.
///
/// This method never throws an exception.
virtual ~RRset();
+ /// \brief Get the wire format length of the \c RRset.
+ ///
+ /// \return The length of the wire format representation of the
+ /// \c RRset.
+ /// \throw \c EmptyRRset if the \c RRset is empty.
+ virtual uint16_t getLength() const;
+
/// \brief Render the RRset in the wire format with name compression and
/// truncation handling.
///
rrset_none_a_empty.toText());
}
+TEST_F(RRsetTest, getLength) {
+ // Empty RRset should throw
+ EXPECT_THROW(rrset_a_empty.getLength(), EmptyRRset);
+
+ // Unless it is type ANY or NONE:
+ // test.example.com = 1 + 4 + 1 + 7 + 1 + 3 + 1 = 18 octets
+ // TYPE field = 2 octets
+ // CLASS field = 2 octets
+ // TTL field = 2 octets
+ // RDLENGTH field = 2 octets
+ // Total = 18 + 2 + 2 + 2 + 2 = 26 octets
+ EXPECT_EQ(26, rrset_any_a_empty.getLength());
+ EXPECT_EQ(26, rrset_none_a_empty.getLength());
+
+ // RRset with single RDATA
+ // 26 (above) + 4 octets (A RDATA) = 30 octets
+ rrset_a_empty.addRdata(in::A("192.0.2.1"));
+ EXPECT_EQ(30, rrset_a_empty.getLength());
+
+ // 2 A RRs
+ rrset_a_empty.addRdata(in::A("192.0.2.2"));
+ EXPECT_EQ(60, rrset_a_empty.getLength());
+}
+
TEST_F(RRsetTest, toWireBuffer) {
rrset_a.toWire(buffer);
"20100322084538 20100220084538 1 example.com. FAKEFAKEFAKEFAKE\n",
rrset_aaaa->toText());
}
+
+TEST_F(RRsetRRSIGTest, getLength) {
+ // A RR
+ // test.example.com = 1 + 4 + 1 + 7 + 1 + 3 + 1 = 18 octets
+ // TYPE field = 2 octets
+ // CLASS field = 2 octets
+ // TTL field = 2 octets
+ // RDLENGTH field = 2 octets
+ // A RDATA = 4 octets
+ // Total = 18 + 2 + 2 + 2 + 2 + 4 = 30 octets
+
+ // 2 A RRs
+ EXPECT_EQ(60, rrset_a->getLength());
+
+ // RRSIG
+ // test.example.com = 1 + 4 + 1 + 7 + 1 + 3 + 1 = 18 octets
+ // TYPE field = 2 octets
+ // CLASS field = 2 octets
+ // TTL field = 2 octets
+ // RDLENGTH field = 2 octets
+ // RRSIG RDATA = 40 octets
+ // Total = 18 + 2 + 2 + 2 + 2 + 40 = 66 octets
+ RRsetPtr my_rrsig(new RRset(test_name, RRClass::IN(),
+ RRType::RRSIG(), RRTTL(3600)));
+ my_rrsig->addRdata(generic::RRSIG("A 4 3 3600 "
+ "20000101000000 20000201000000 "
+ "12345 example.com. FAKEFAKEFAKE"));
+ EXPECT_EQ(66, my_rrsig->getLength());
+
+ // RRset with attached RRSIG
+ rrset_a->addRRsig(my_rrsig);
+
+ EXPECT_EQ(60 + 66, rrset_a->getLength());
+}
}