BIND 10 trac1396, updated. 000f7efd1c2d316c3ee02902713cedc355efefba [1396] Add RRset::getLength()

BIND 10 source code commits bind10-changes at lists.isc.org
Tue Jan 28 03:55:03 UTC 2014


The branch, trac1396 has been updated
       via  000f7efd1c2d316c3ee02902713cedc355efefba (commit)
       via  7f9bc84501ca5a850e4975db715eae07234e7c25 (commit)
      from  4b77db4d8be806ebfb82ef5403fae266c56b1c89 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
commit 000f7efd1c2d316c3ee02902713cedc355efefba
Author: Mukund Sivaraman <muks at isc.org>
Date:   Tue Jan 28 08:53:13 2014 +0530

    [1396] Add RRset::getLength()

commit 7f9bc84501ca5a850e4975db715eae07234e7c25
Author: Mukund Sivaraman <muks at isc.org>
Date:   Tue Jan 28 08:21:48 2014 +0530

    [1396] Rename method to getLength()
    
    At first I thought getLength() may already be in use by RR type-specific
    classes, but it's not in use. getLength() is more consistent with naming
    of other classes' wire data length methods.

-----------------------------------------------------------------------

Summary of changes:
 src/lib/dns/rdata.cc                |    2 +-
 src/lib/dns/rdata.h                 |    6 ++--
 src/lib/dns/rrset.cc                |   59 +++++++++++++++++++++++++++++++++++
 src/lib/dns/rrset.h                 |   28 +++++++++++++++++
 src/lib/dns/tests/rdata_unittest.cc |    6 ++--
 src/lib/dns/tests/rrset_unittest.cc |   58 ++++++++++++++++++++++++++++++++++
 6 files changed, 152 insertions(+), 7 deletions(-)

-----------------------------------------------------------------------
diff --git a/src/lib/dns/rdata.cc b/src/lib/dns/rdata.cc
index 09f289b..ff95fee 100644
--- a/src/lib/dns/rdata.cc
+++ b/src/lib/dns/rdata.cc
@@ -47,7 +47,7 @@ namespace dns {
 namespace rdata {
 
 uint16_t
-Rdata::getWireLength() const {
+Rdata::getLength() const {
     OutputBuffer obuffer(0);
 
     toWire(obuffer);
diff --git a/src/lib/dns/rdata.h b/src/lib/dns/rdata.h
index 352554e..79ca641 100644
--- a/src/lib/dns/rdata.h
+++ b/src/lib/dns/rdata.h
@@ -227,15 +227,15 @@ public:
     /// IMPLEMENTATION NOTE: Currently this base class implementation is
     /// non-optimal as it renders the wire data to a buffer and returns
     /// the buffer's length. What would perform better is to add
-    /// implementations of \c getWireLength() method to every RDATA
+    /// implementations of \c getLength() method to every RDATA
     /// type. This is why this method is virtual. Once all Rdata types
-    /// have \c getWireLength() implementations, this base class
+    /// have \c getLength() implementations, this base class
     /// implementation must be removed and the method should become a
     /// pure interface.
     ///
     /// \return The length of the wire format representation of the
     /// RDATA.
-    virtual uint16_t getWireLength() const;
+    virtual uint16_t getLength() const;
 };
 
 namespace generic {
diff --git a/src/lib/dns/rrset.cc b/src/lib/dns/rrset.cc
index 8dfe884..7fbd0d1 100644
--- a/src/lib/dns/rrset.cc
+++ b/src/lib/dns/rrset.cc
@@ -289,6 +289,50 @@ BasicRRset::toText() const {
     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));
@@ -322,6 +366,21 @@ RRset::getRRsigDataCount() const {
     }
 }
 
+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);
diff --git a/src/lib/dns/rrset.h b/src/lib/dns/rrset.h
index eb8fa6e..537c999 100644
--- a/src/lib/dns/rrset.h
+++ b/src/lib/dns/rrset.h
@@ -206,6 +206,20 @@ public:
     /// \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
@@ -642,6 +656,13 @@ public:
     /// \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.
@@ -813,6 +834,13 @@ public:
 
     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.
     ///
diff --git a/src/lib/dns/tests/rdata_unittest.cc b/src/lib/dns/tests/rdata_unittest.cc
index 3772e9b..1678f0b 100644
--- a/src/lib/dns/tests/rdata_unittest.cc
+++ b/src/lib/dns/tests/rdata_unittest.cc
@@ -211,12 +211,12 @@ TEST_F(RdataTest, createRdataWithLexer) {
                    "file does not end with newline");
 }
 
-TEST_F(RdataTest, getWireLength) {
+TEST_F(RdataTest, getLength) {
     const in::AAAA aaaa_rdata("2001:db8::1");
-    EXPECT_EQ(16, aaaa_rdata.getWireLength());
+    EXPECT_EQ(16, aaaa_rdata.getLength());
 
     const generic::TXT txt_rdata("Hello World");
-    EXPECT_EQ(12, txt_rdata.getWireLength());
+    EXPECT_EQ(12, txt_rdata.getLength());
 }
 
 }
diff --git a/src/lib/dns/tests/rrset_unittest.cc b/src/lib/dns/tests/rrset_unittest.cc
index da3eb52..72049b2 100644
--- a/src/lib/dns/tests/rrset_unittest.cc
+++ b/src/lib/dns/tests/rrset_unittest.cc
@@ -204,6 +204,30 @@ TEST_F(RRsetTest, toText) {
               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);
 
@@ -365,4 +389,38 @@ TEST_F(RRsetRRSIGTest, toText) {
               "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());
+}
 }



More information about the bind10-changes mailing list