BIND 10 master, updated. ff7fa9a2025f682ee668f64197523ab7230b8a85 Merge branch 'trac2000'
BIND 10 source code commits
bind10-changes at lists.isc.org
Thu Feb 20 02:52:30 UTC 2014
The branch, master has been updated
via ff7fa9a2025f682ee668f64197523ab7230b8a85 (commit)
via c1c4ea8d1b7629dac379f192d30cc79535214236 (commit)
via 6b2038265d47dd365b439051caa7c23b8e19309c (commit)
via f9daba2bfb0b915cd17d4330d47c991c18652d8d (commit)
via 6e87315672b64f37f850add634946899e452af99 (commit)
via bb87247db5283a9c406255feb8449ccfefb74c49 (commit)
via 8f858639af900655ea87f54ed7193169ff559088 (commit)
via 916893ac37eeeb169c90c7cf374630a7cfba127b (commit)
via 0408d1e6472105cb9c762ac3ef7082d47dc6a720 (commit)
via a001951886e545f2f0a299fccbeb7fb9388deccf (commit)
via e2c4caa23971f3ebd70483ccc9c0b9ba8b7efa2e (commit)
via b6875c7848cf648d45d0448ba8aa3f30a281d3c4 (commit)
from 018edab669b4fa2dc12b7285d57e35f33e48a7f8 (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 ff7fa9a2025f682ee668f64197523ab7230b8a85
Merge: 018edab c1c4ea8
Author: Mukund Sivaraman <muks at isc.org>
Date: Thu Feb 20 08:10:19 2014 +0530
Merge branch 'trac2000'
-----------------------------------------------------------------------
Summary of changes:
src/lib/dns/rdata/generic/opt_41.cc | 182 ++++++++++++++++++++----
src/lib/dns/rdata/generic/opt_41.h | 57 +++++++-
src/lib/dns/tests/rdata_opt_unittest.cc | 143 +++++++++++++++++--
src/lib/dns/tests/testdata/Makefile.am | 4 +-
src/lib/dns/tests/testdata/rdata_opt_fromWire | 16 ---
src/lib/dns/tests/testdata/rdata_opt_fromWire1 | 15 ++
src/lib/dns/tests/testdata/rdata_opt_fromWire2 | 4 +
src/lib/dns/tests/testdata/rdata_opt_fromWire3 | 8 ++
src/lib/dns/tests/testdata/rdata_opt_fromWire4 | 9 ++
9 files changed, 381 insertions(+), 57 deletions(-)
delete mode 100644 src/lib/dns/tests/testdata/rdata_opt_fromWire
create mode 100644 src/lib/dns/tests/testdata/rdata_opt_fromWire1
create mode 100644 src/lib/dns/tests/testdata/rdata_opt_fromWire2
create mode 100644 src/lib/dns/tests/testdata/rdata_opt_fromWire3
create mode 100644 src/lib/dns/tests/testdata/rdata_opt_fromWire4
-----------------------------------------------------------------------
diff --git a/src/lib/dns/rdata/generic/opt_41.cc b/src/lib/dns/rdata/generic/opt_41.cc
index 136bdf9..6b292e9 100644
--- a/src/lib/dns/rdata/generic/opt_41.cc
+++ b/src/lib/dns/rdata/generic/opt_41.cc
@@ -14,25 +14,68 @@
#include <config.h>
-#include <string>
-
#include <util/buffer.h>
#include <dns/messagerenderer.h>
#include <dns/rdata.h>
#include <dns/rdataclass.h>
+#include <boost/foreach.hpp>
+
+#include <string>
+#include <string.h>
+
using namespace std;
using namespace isc::util;
// BEGIN_ISC_NAMESPACE
// BEGIN_RDATA_NAMESPACE
+/// \brief Constructor.
+OPT::PseudoRR::PseudoRR(uint16_t code,
+ boost::shared_ptr<std::vector<uint8_t> >& data) :
+ code_(code),
+ data_(data)
+{
+}
+
+uint16_t
+OPT::PseudoRR::getCode() const {
+ return (code_);
+}
+
+const uint8_t*
+OPT::PseudoRR::getData() const {
+ return (&(*data_)[0]);
+}
+
+uint16_t
+OPT::PseudoRR::getLength() const {
+ return (data_->size());
+}
+
+struct OPTImpl {
+ OPTImpl() :
+ rdlength_(0)
+ {}
+
+ uint16_t rdlength_;
+ std::vector<OPT::PseudoRR> pseudo_rrs_;
+};
+
+/// \brief Default constructor.
+OPT::OPT() :
+ impl_(new OPTImpl)
+{
+}
+
/// \brief Constructor from string.
///
/// This constructor cannot be used, and always throws an exception.
///
/// \throw InvalidRdataText OPT RR cannot be constructed from text.
-OPT::OPT(const std::string&) {
+OPT::OPT(const std::string&) :
+ impl_(NULL)
+{
isc_throw(InvalidRdataText, "OPT RR cannot be constructed from text");
}
@@ -42,50 +85,141 @@ OPT::OPT(const std::string&) {
///
/// \throw InvalidRdataText OPT RR cannot be constructed from text.
OPT::OPT(MasterLexer&, const Name*,
- MasterLoader::Options, MasterLoaderCallbacks&)
+ MasterLoader::Options, MasterLoaderCallbacks&) :
+ impl_(NULL)
{
isc_throw(InvalidRdataText, "OPT RR cannot be constructed from text");
}
-OPT::OPT(InputBuffer& buffer, size_t rdata_len) {
- // setPosition() will throw against a short buffer anyway, but it's safer
- // to check it explicitly here.
- if (buffer.getLength() - buffer.getPosition() < rdata_len) {
- isc_throw(InvalidRdataLength, "RDLEN of OPT is too large");
+OPT::OPT(InputBuffer& buffer, size_t rdata_len) :
+ impl_(NULL)
+{
+ std::auto_ptr<OPTImpl> impl_ptr(new OPTImpl);
+
+ while (true) {
+ if (rdata_len == 0) {
+ break;
+ }
+
+ if (rdata_len < 4) {
+ isc_throw(InvalidRdataLength,
+ "Pseudo OPT RR record too short: "
+ << rdata_len << " bytes");
+ }
+
+ const uint16_t option_code = buffer.readUint16();
+ const uint16_t option_length = buffer.readUint16();
+ rdata_len -= 4;
+
+ if (static_cast<uint16_t>(impl_ptr->rdlength_ + option_length) <
+ impl_ptr->rdlength_)
+ {
+ isc_throw(InvalidRdataText,
+ "Option length " << option_length
+ << " would overflow OPT RR RDLEN (currently "
+ << impl_ptr->rdlength_ << ").");
+ }
+
+ if (rdata_len < option_length) {
+ isc_throw(InvalidRdataLength, "Corrupt pseudo OPT RR record");
+ }
+
+ boost::shared_ptr<std::vector<uint8_t> >
+ option_data(new std::vector<uint8_t>(option_length));
+ buffer.readData(&(*option_data)[0], option_length);
+ impl_ptr->pseudo_rrs_.push_back(PseudoRR(option_code, option_data));
+ impl_ptr->rdlength_ += option_length;
+ rdata_len -= option_length;
+ }
+
+ impl_ = impl_ptr.release();
+}
+
+OPT::OPT(const OPT& other) :
+ Rdata(), impl_(new OPTImpl(*other.impl_))
+{
+}
+
+OPT&
+OPT::operator=(const OPT& source) {
+ if (this == &source) {
+ return (*this);
}
- // This simple implementation ignores any options
- buffer.setPosition(buffer.getPosition() + rdata_len);
+ OPTImpl* newimpl = new OPTImpl(*source.impl_);
+ delete impl_;
+ impl_ = newimpl;
+
+ return (*this);
}
-OPT::OPT(const OPT&) : Rdata() {
- // there's nothing to copy in this simple implementation.
+OPT::~OPT() {
+ delete impl_;
}
std::string
OPT::toText() const {
- // OPT records do not have a text format.
- return ("");
+ isc_throw(isc::InvalidOperation,
+ "OPT RRs do not have a presentation format");
}
void
-OPT::toWire(OutputBuffer&) const {
- // nothing to do, as this simple version doesn't support any options.
+OPT::toWire(OutputBuffer& buffer) const {
+ BOOST_FOREACH(const PseudoRR& pseudo_rr, impl_->pseudo_rrs_) {
+ buffer.writeUint16(pseudo_rr.getCode());
+ const uint16_t length = pseudo_rr.getLength();
+ buffer.writeUint16(length);
+ if (length > 0) {
+ buffer.writeData(pseudo_rr.getData(), length);
+ }
+ }
}
void
-OPT::toWire(AbstractMessageRenderer&) const {
- // nothing to do, as this simple version doesn't support any options.
+OPT::toWire(AbstractMessageRenderer& renderer) const {
+ BOOST_FOREACH(const PseudoRR& pseudo_rr, impl_->pseudo_rrs_) {
+ renderer.writeUint16(pseudo_rr.getCode());
+ const uint16_t length = pseudo_rr.getLength();
+ renderer.writeUint16(length);
+ if (length > 0) {
+ renderer.writeData(pseudo_rr.getData(), length);
+ }
+ }
}
int
-OPT::compare(const Rdata& other) const {
- //const OPT& other_opt = dynamic_cast<const OPT&>(other);
- // right now we don't need other_opt:
- static_cast<void>(dynamic_cast<const OPT&>(other));
-
+OPT::compare(const Rdata&) const {
+ isc_throw(isc::InvalidOperation,
+ "It is meaningless to compare a set of OPT pseudo RRs; "
+ "they have unspecified order");
return (0);
}
+void
+OPT::appendPseudoRR(uint16_t code, const uint8_t* data, uint16_t length) {
+ // See if it overflows 16-bit length field. We only worry about the
+ // pseudo-RR length here, not the whole message length (which should
+ // be checked and enforced elsewhere).
+ if (static_cast<uint16_t>(impl_->rdlength_ + length) <
+ impl_->rdlength_)
+ {
+ isc_throw(isc::InvalidParameter,
+ "Option length " << length
+ << " would overflow OPT RR RDLEN (currently "
+ << impl_->rdlength_ << ").");
+ }
+
+ boost::shared_ptr<std::vector<uint8_t> >
+ option_data(new std::vector<uint8_t>(length));
+ std::memcpy(&(*option_data)[0], data, length);
+ impl_->pseudo_rrs_.push_back(PseudoRR(code, option_data));
+ impl_->rdlength_ += length;
+}
+
+const std::vector<OPT::PseudoRR>&
+OPT::getPseudoRRs() const {
+ return (impl_->pseudo_rrs_);
+}
+
// END_RDATA_NAMESPACE
// END_ISC_NAMESPACE
diff --git a/src/lib/dns/rdata/generic/opt_41.h b/src/lib/dns/rdata/generic/opt_41.h
index 0cb7043..cc51977 100644
--- a/src/lib/dns/rdata/generic/opt_41.h
+++ b/src/lib/dns/rdata/generic/opt_41.h
@@ -18,6 +18,10 @@
#include <dns/rdata.h>
+#include <boost/shared_ptr.hpp>
+
+#include <vector>
+
// BEGIN_ISC_NAMESPACE
// BEGIN_COMMON_DECLARATIONS
@@ -25,15 +29,64 @@
// BEGIN_RDATA_NAMESPACE
+struct OPTImpl;
+
class OPT : public Rdata {
public:
// BEGIN_COMMON_MEMBERS
// END_COMMON_MEMBERS
// The default constructor makes sense for OPT as it can be empty.
- OPT() {}
+ OPT();
+ OPT& operator=(const OPT& source);
+ ~OPT();
+
+ /// \brief A class representing a pseudo RR (or option) within an
+ /// OPT RR (see RFC 6891).
+ class PseudoRR {
+ public:
+ /// \brief Constructor.
+ /// \param code The OPTION-CODE field of the pseudo RR.
+ /// \param data The OPTION-DATA field of the pseudo
+ /// RR. OPTION-LENGTH is set to the length of this vector.
+ PseudoRR(uint16_t code,
+ boost::shared_ptr<std::vector<uint8_t> >& data);
+
+ /// \brief Return the option code of this pseudo RR.
+ uint16_t getCode() const;
+
+ /// \brief Return the option data of this pseudo RR.
+ const uint8_t* getData() const;
+
+ /// \brief Return the length of the option data of this
+ /// pseudo RR.
+ uint16_t getLength() const;
+
+ private:
+ uint16_t code_;
+ boost::shared_ptr<std::vector<uint8_t> > data_;
+ };
+
+ /// \brief Append a pseudo RR (option) in this OPT RR.
+ ///
+ /// \param code The OPTION-CODE field of the pseudo RR.
+ /// \param data The OPTION-DATA field of the pseudo RR.
+ /// \param length The size of the \c data argument. OPTION-LENGTH is
+ /// set to this size.
+ /// \throw \c isc::InvalidParameter if this pseudo RR would cause
+ /// the OPT RDATA to overflow its RDLENGTH.
+ void appendPseudoRR(uint16_t code, const uint8_t* data, uint16_t length);
+
+ /// \brief Return a vector of the pseudo RRs (options) in this
+ /// OPT RR.
+ ///
+ /// Note: The returned reference is only valid during the lifetime
+ /// of this \c generic::OPT object. It should not be used
+ /// afterwards.
+ const std::vector<PseudoRR>& getPseudoRRs() const;
+
private:
- // RR-type specific members are here.
+ OPTImpl* impl_;
};
// END_RDATA_NAMESPACE
diff --git a/src/lib/dns/tests/rdata_opt_unittest.cc b/src/lib/dns/tests/rdata_opt_unittest.cc
index 20ccfe4..9d09a60 100644
--- a/src/lib/dns/tests/rdata_opt_unittest.cc
+++ b/src/lib/dns/tests/rdata_opt_unittest.cc
@@ -23,19 +23,28 @@
#include <dns/tests/unittest_util.h>
#include <dns/tests/rdata_unittest.h>
+#include <util/unittests/wiredata.h>
-using isc::UnitTestUtil;
using namespace std;
using namespace isc::dns;
using namespace isc::util;
using namespace isc::dns::rdata;
+using isc::UnitTestUtil;
+using isc::util::unittests::matchWireData;
namespace {
class Rdata_OPT_Test : public RdataTest {
// there's nothing to specialize
};
-const generic::OPT rdata_opt;
+const uint8_t rdata_opt_wiredata[] = {
+ // Option code
+ 0x00, 0x2a,
+ // Option length
+ 0x00, 0x03,
+ // Option data
+ 0x00, 0x01, 0x02
+};
TEST_F(Rdata_OPT_Test, createFromText) {
// OPT RR cannot be created from text.
@@ -46,14 +55,28 @@ TEST_F(Rdata_OPT_Test, createFromWire) {
// Valid cases: in the simple implementation with no supported options,
// we can only check these don't throw.
EXPECT_NO_THROW(rdataFactoryFromFile(RRType::OPT(), RRClass("CLASS4096"),
- "rdata_opt_fromWire"));
+ "rdata_opt_fromWire1"));
EXPECT_NO_THROW(rdataFactoryFromFile(RRType::OPT(), RRClass::CH(),
- "rdata_opt_fromWire", 2));
+ "rdata_opt_fromWire1", 2));
- // short buffer case.
+ // Short RDLEN. This throws InvalidRdataLength even if subsequent
+ // pseudo RRs cause RDLEN size to be exhausted.
EXPECT_THROW(rdataFactoryFromFile(RRType::OPT(), RRClass::IN(),
- "rdata_opt_fromWire", 11),
+ "rdata_opt_fromWire2"),
InvalidRdataLength);
+ EXPECT_THROW(rdataFactoryFromFile(RRType::OPT(), RRClass::IN(),
+ "rdata_opt_fromWire3"),
+ InvalidRdataLength);
+ // Option lengths can add up and overflow RDLEN. Unlikely when
+ // parsed from wire data, but we'll check for it anyway.
+ EXPECT_THROW(rdataFactoryFromFile(RRType::OPT(), RRClass::IN(),
+ "rdata_opt_fromWire4"),
+ InvalidRdataText);
+
+ // short buffer case.
+ EXPECT_THROW(rdataFactoryFromFile(RRType::OPT(), RRClass::IN(),
+ "rdata_opt_fromWire1", 11),
+ InvalidBufferPosition);
}
TEST_F(Rdata_OPT_Test, createFromLexer) {
@@ -64,26 +87,118 @@ TEST_F(Rdata_OPT_Test, createFromLexer) {
}
TEST_F(Rdata_OPT_Test, toWireBuffer) {
+ const generic::OPT rdata_opt =
+ dynamic_cast<const generic::OPT&>
+ (*rdataFactoryFromFile(RRType("OPT"), RRClass("IN"),
+ "rdata_opt_fromWire1", 2));
+
+ obuffer.clear();
rdata_opt.toWire(obuffer);
- EXPECT_EQ(0, obuffer.getLength());
+
+ matchWireData(rdata_opt_wiredata, sizeof(rdata_opt_wiredata),
+ obuffer.getData(), obuffer.getLength());
}
TEST_F(Rdata_OPT_Test, toWireRenderer) {
+ const generic::OPT rdata_opt =
+ dynamic_cast<const generic::OPT&>
+ (*rdataFactoryFromFile(RRType("OPT"), RRClass("IN"),
+ "rdata_opt_fromWire1", 2));
+
+ renderer.clear();
rdata_opt.toWire(renderer);
- EXPECT_EQ(0, obuffer.getLength());
+
+ matchWireData(rdata_opt_wiredata, sizeof(rdata_opt_wiredata),
+ renderer.getData(), renderer.getLength());
}
TEST_F(Rdata_OPT_Test, toText) {
- EXPECT_EQ("", rdata_opt.toText());
+ // empty OPT
+ const generic::OPT rdata_opt;
+
+ EXPECT_THROW(rdata_opt.toText(),
+ isc::InvalidOperation);
}
TEST_F(Rdata_OPT_Test, compare) {
- // This simple implementation always returns "true"
- EXPECT_EQ(0, rdata_opt.compare(
+ // empty OPT
+ const generic::OPT rdata_opt;
+
+ EXPECT_THROW(rdata_opt.compare(
*rdataFactoryFromFile(RRType::OPT(), RRClass::CH(),
- "rdata_opt_fromWire", 2)));
+ "rdata_opt_fromWire1", 2)),
+ isc::InvalidOperation);
+
+ // comparison attempt between incompatible RR types also results in
+ // isc::InvalidOperation.
+ EXPECT_THROW(rdata_opt.compare(*RdataTest::rdata_nomatch),
+ isc::InvalidOperation);
+}
+
+TEST_F(Rdata_OPT_Test, appendPseudoRR) {
+ generic::OPT rdata_opt;
+
+ // Append empty option data
+ rdata_opt.appendPseudoRR(0x0042, NULL, 0);
+
+ // Append simple option data
+ const uint8_t option_data[] = {'H', 'e', 'l', 'l', 'o'};
+ rdata_opt.appendPseudoRR(0x0043, option_data, sizeof(option_data));
+
+ // Duplicate option codes are okay.
+ rdata_opt.appendPseudoRR(0x0042, option_data, sizeof(option_data));
+
+ // When option length may overflow RDLEN, append should throw.
+ const std::vector<uint8_t> buffer((1 << 16) - 1);
+ EXPECT_THROW(rdata_opt.appendPseudoRR(0x0044, &buffer[0], buffer.size()),
+ isc::InvalidParameter);
+
+ const uint8_t rdata_opt_wiredata2[] = {
+ // OPTION #1
+ // ` Option code
+ 0x00, 0x42,
+ // ` Option length
+ 0x00, 0x00,
+
+ // OPTION #2
+ // ` Option code
+ 0x00, 0x43,
+ // ` Option length
+ 0x00, 0x05,
+ // ` Option data
+ 'H', 'e', 'l', 'l', 'o',
+
+ // OPTION #3
+ // ` Option code
+ 0x00, 0x42,
+ // ` Option length
+ 0x00, 0x05,
+ // ` Option data
+ 'H', 'e', 'l', 'l', 'o'
+ };
+
+ obuffer.clear();
+ rdata_opt.toWire(obuffer);
+
+ matchWireData(rdata_opt_wiredata2, sizeof(rdata_opt_wiredata2),
+ obuffer.getData(), obuffer.getLength());
+}
+
+TEST_F(Rdata_OPT_Test, getPseudoRRs) {
+ const generic::OPT rdf =
+ dynamic_cast<const generic::OPT&>
+ (*rdataFactoryFromFile(RRType("OPT"), RRClass("IN"),
+ "rdata_opt_fromWire1", 2));
+
+ const std::vector<generic::OPT::PseudoRR>& rrs = rdf.getPseudoRRs();
+ ASSERT_FALSE(rrs.empty());
+ EXPECT_EQ(1, rrs.size());
+ EXPECT_EQ(0x2a, rrs.at(0).getCode());
+ EXPECT_EQ(3, rrs.at(0).getLength());
- // comparison attempt between incompatible RR types should be rejected
- EXPECT_THROW(rdata_opt.compare(*RdataTest::rdata_nomatch), bad_cast);
+ const uint8_t expected_data[] = {0x00, 0x01, 0x02};
+ const uint8_t* actual_data = rrs.at(0).getData();
+ EXPECT_EQ(0, std::memcmp(expected_data, actual_data,
+ sizeof(expected_data)));
}
}
diff --git a/src/lib/dns/tests/testdata/Makefile.am b/src/lib/dns/tests/testdata/Makefile.am
index 3d10337..fadf30e 100644
--- a/src/lib/dns/tests/testdata/Makefile.am
+++ b/src/lib/dns/tests/testdata/Makefile.am
@@ -132,7 +132,9 @@ EXTRA_DIST += rdata_nsec3_fromWire10.spec rdata_nsec3_fromWire11.spec
EXTRA_DIST += rdata_nsec3_fromWire12.spec rdata_nsec3_fromWire13.spec
EXTRA_DIST += rdata_nsec3_fromWire14.spec rdata_nsec3_fromWire15.spec
EXTRA_DIST += rdata_nsec3_fromWire16.spec rdata_nsec3_fromWire17.spec
-EXTRA_DIST += rdata_opt_fromWire rdata_rrsig_fromWire1
+EXTRA_DIST += rdata_opt_fromWire1 rdata_opt_fromWire2
+EXTRA_DIST += rdata_opt_fromWire3 rdata_opt_fromWire4
+EXTRA_DIST += rdata_rrsig_fromWire1
EXTRA_DIST += rdata_rrsig_fromWire2.spec
EXTRA_DIST += rdata_rp_fromWire1.spec rdata_rp_fromWire2.spec
EXTRA_DIST += rdata_rp_fromWire3.spec rdata_rp_fromWire4.spec
diff --git a/src/lib/dns/tests/testdata/rdata_opt_fromWire b/src/lib/dns/tests/testdata/rdata_opt_fromWire
deleted file mode 100644
index 0ca5f6a..0000000
--- a/src/lib/dns/tests/testdata/rdata_opt_fromWire
+++ /dev/null
@@ -1,16 +0,0 @@
-#
-# various kinds of OPT RDATA stored in an input buffer
-#
-# empty RDATA (which is okay)
-#
-# 0 1 (bytes)
- 00 00
-#
-# an OPT RR containing an NSID Option
-# code=3 len=3 ID value (opaque)
-# 2 3 4 5 6 7 8 9 10
- 00 07 00 03 00 03 00 01 02
-#
-# short buffer (this can be tested only at the end of the buffer)
-# 1 2 3 4 5
- 00 04 c0 00 02
diff --git a/src/lib/dns/tests/testdata/rdata_opt_fromWire1 b/src/lib/dns/tests/testdata/rdata_opt_fromWire1
new file mode 100644
index 0000000..f2eb680
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_opt_fromWire1
@@ -0,0 +1,15 @@
+# Various kinds of OPT RDATA stored in an input buffer
+#
+# Empty RDATA (which is okay)
+#
+# 0 1 (bytes)
+ 00 00
+#
+# An OPT RR containing an NSID Option
+# code=3 len=3 ID value (opaque)
+# 2 3 4 5 6 7 8 9 10
+ 00 07 00 2a 00 03 00 01 02
+#
+# Short buffer (this can be tested only at the end of the buffer)
+# 1 2 3 4 5
+ 00 04 c0 00 02
diff --git a/src/lib/dns/tests/testdata/rdata_opt_fromWire2 b/src/lib/dns/tests/testdata/rdata_opt_fromWire2
new file mode 100644
index 0000000..2c5a11f
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_opt_fromWire2
@@ -0,0 +1,4 @@
+# Short RDATA length
+#
+# OPT RDATA, RDLEN=1
+0001
diff --git a/src/lib/dns/tests/testdata/rdata_opt_fromWire3 b/src/lib/dns/tests/testdata/rdata_opt_fromWire3
new file mode 100644
index 0000000..52db1d8
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_opt_fromWire3
@@ -0,0 +1,8 @@
+# Short RDATA length (in second pseudo RR)
+#
+# OPT RDATA, RDLEN=8
+0008
+# Pseudo RR 1 of size 7 (code=3, len=3)
+00 03 00 03 00 01 02
+# Pseudo RR 2 of size 7 exhausts RDLEN (code=4, len=3)
+00 04 00 03 00 01 02
diff --git a/src/lib/dns/tests/testdata/rdata_opt_fromWire4 b/src/lib/dns/tests/testdata/rdata_opt_fromWire4
new file mode 100644
index 0000000..a302127
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_opt_fromWire4
@@ -0,0 +1,9 @@
+# Sum of option lengths would overflow RDLEN
+#
+# OPT RDATA, RDLEN=14 (0x000e)
+000e
+# Pseudo RR 1 (code=3, len=3)
+00 03 00 03 00 01 02
+# Pseudo RR 2 (code=4, len=65535 overflows RDLEN)
+00 04 ff ff 00 01 02
+# Rest of option data is omitted...
More information about the bind10-changes
mailing list