123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377 |
- // Copyright (C) 2010 Internet Systems Consortium, Inc. ("ISC")
- //
- // Permission to use, copy, modify, and/or distribute this software for any
- // purpose with or without fee is hereby granted, provided that the above
- // copyright notice and this permission notice appear in all copies.
- //
- // THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
- // REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
- // AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
- // INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
- // LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
- // OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
- // PERFORMANCE OF THIS SOFTWARE.
- #include <vector>
- #include <exceptions/exceptions.h>
- #include <util/buffer.h>
- #include <dns/messagerenderer.h>
- #include <dns/name.h>
- #include <dns/rdata.h>
- #include <dns/rdataclass.h>
- #include <dns/rdatafields.h>
- #include <dns/tests/unittest_util.h>
- #include <gtest/gtest.h>
- using isc::UnitTestUtil;
- using namespace std;
- using namespace isc::dns;
- using namespace isc::dns::rdata;
- using isc::util::OutputBuffer;
- using isc::util::InputBuffer;
- namespace {
- class RdataFieldsTest : public ::testing::Test {
- protected:
- RdataFieldsTest() : obuffer(0), ns_name("example.com"),
- other_name("www.example.com")
- {}
- void constructCommonTests(const RdataFields& fields,
- const uint8_t* const expected_data,
- const size_t expected_data_len);
- void constructCommonTestsNS(const RdataFields& fields);
- void constructCommonTestsTXT(const RdataFields& fields);
- void constructCommonTestsRRSIG(const RdataFields& fields);
- void constructCommonTestsOPT(const RdataFields& fields);
- OutputBuffer obuffer;
- MessageRenderer renderer;
- const Name ns_name;
- const Name other_name;
- vector<unsigned char> expected_wire;
- vector<unsigned char> fields_wire;
- };
- const uint8_t in_a_data[] = { 192, 0, 2, 1 };
- // binary representation of example.com.
- const uint8_t ns_data[] = { 0x07, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65,
- 0x03, 0x63, 0x6f, 0x6d, 0x00 };
- //
- // IN/A RDATA: fixed length, single data field
- //
- void
- RdataFieldsTest::constructCommonTests(const RdataFields& fields,
- const uint8_t* const expected_data,
- const size_t expected_data_len)
- {
- EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData, expected_data,
- expected_data_len, fields.getData(),
- fields.getDataLength());
- EXPECT_EQ(sizeof(RdataFields::FieldSpec), fields.getFieldSpecDataSize());
- EXPECT_EQ(1, fields.getFieldCount());
- EXPECT_EQ(RdataFields::DATA, fields.getFieldSpec(0).type);
- EXPECT_EQ(4, fields.getFieldSpec(0).len);
- fields.toWire(obuffer);
- EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData, expected_data,
- expected_data_len, obuffer.getData(),
- obuffer.getLength());
- fields.toWire(renderer);
- EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData, expected_data,
- expected_data_len, renderer.getData(),
- renderer.getLength());
- }
- TEST_F(RdataFieldsTest, constructFromRdata) {
- const RdataFields fields(in::A("192.0.2.1"));
- constructCommonTests(fields, in_a_data, sizeof(in_a_data));
- }
- TEST_F(RdataFieldsTest, constructFromParams) {
- const RdataFields::FieldSpec spec(RdataFields::DATA, 4);
- const RdataFields fields(&spec, sizeof(spec), in_a_data,
- sizeof(in_a_data));
- constructCommonTests(fields, in_a_data, sizeof(in_a_data));
- }
- //
- // NS RDATA: containing a compressible name.
- //
- void
- RdataFieldsTest::constructCommonTestsNS(const RdataFields& fields) {
- EXPECT_EQ(sizeof(RdataFields::FieldSpec), fields.getFieldSpecDataSize());
- EXPECT_EQ(1, fields.getFieldCount());
- EXPECT_EQ(RdataFields::COMPRESSIBLE_NAME, fields.getFieldSpec(0).type);
- EXPECT_EQ(ns_name.getLength(), fields.getFieldSpec(0).len);
- expected_wire.clear();
- UnitTestUtil::readWireData("rdatafields1.wire", expected_wire);
- other_name.toWire(obuffer);
- fields.toWire(obuffer);
- EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData, &expected_wire[0],
- expected_wire.size(), obuffer.getData(),
- obuffer.getLength());
- expected_wire.clear();
- UnitTestUtil::readWireData("rdatafields2.wire", expected_wire);
- other_name.toWire(renderer);
- fields.toWire(renderer);
- EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData, &expected_wire[0],
- expected_wire.size(), renderer.getData(),
- renderer.getLength());
- }
- TEST_F(RdataFieldsTest, constructFromRdataNS) {
- const RdataFields fields_ns((generic::NS(ns_name)));
- constructCommonTestsNS(fields_ns);
- }
- TEST_F(RdataFieldsTest, constructFromParamsNS) {
- const RdataFields::FieldSpec spec(RdataFields::COMPRESSIBLE_NAME,
- sizeof(ns_data));
- const RdataFields fields_ns(&spec, sizeof(spec), ns_data, sizeof(ns_data));
- constructCommonTestsNS(fields_ns);
- }
- //
- // TXT RDATA: multiple fields, lengths vary
- //
- void
- RdataFieldsTest::constructCommonTestsTXT(const RdataFields& fields) {
- // Since all fields are plain data, they are handled as a single data
- // field.
- EXPECT_EQ(sizeof(RdataFields::FieldSpec), fields.getFieldSpecDataSize());
- EXPECT_EQ(1, fields.getFieldCount());
- EXPECT_EQ(RdataFields::DATA, fields.getFieldSpec(0).type);
- EXPECT_EQ(expected_wire.size(), fields.getFieldSpec(0).len);
- fields.toWire(obuffer);
- EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData, &expected_wire[0],
- expected_wire.size(), obuffer.getData(),
- obuffer.getLength());
- fields.toWire(renderer);
- EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData, &expected_wire[0],
- expected_wire.size(), renderer.getData(),
- renderer.getLength());
- }
- TEST_F(RdataFieldsTest, constructFromRdataTXT) {
- UnitTestUtil::readWireData("rdatafields3.wire", expected_wire);
- InputBuffer ibuffer(&expected_wire[0], expected_wire.size());
- const uint16_t rdlen = ibuffer.readUint16();
- const RdataFields fields(generic::TXT(ibuffer, rdlen));
- // drop the RDLEN part
- expected_wire.erase(expected_wire.begin(), expected_wire.begin() + 2);
- constructCommonTestsTXT(fields);
- }
- TEST_F(RdataFieldsTest, constructFromParamsTXT) {
- UnitTestUtil::readWireData("rdatafields3.wire", expected_wire);
- expected_wire.erase(expected_wire.begin(), expected_wire.begin() + 2);
- const RdataFields::FieldSpec spec(RdataFields::DATA, expected_wire.size());
- const RdataFields fields(&spec, sizeof(spec), &expected_wire[0],
- expected_wire.size());
- constructCommonTestsTXT(fields);
- }
- //
- // RRSIG: multiple fields, with an incompressible name
- //
- void
- RdataFieldsTest::constructCommonTestsRRSIG(const RdataFields& fields) {
- // In terms of RdataFields RRSIG RDATA consists of 3 fields:
- // - 18-byte data field (from the "type covered" field to "key tag" field)
- // - an incompressible name field (for the signer's name field).
- // this is a variable length field. In this test it's a 13-byte field.
- // - a variable-length data field for the signature. In this tests
- // it's a 15-byte field.
- EXPECT_EQ(3 * sizeof(RdataFields::FieldSpec),
- fields.getFieldSpecDataSize());
- EXPECT_EQ(3, fields.getFieldCount());
- EXPECT_EQ(RdataFields::DATA, fields.getFieldSpec(0).type);
- EXPECT_EQ(18, fields.getFieldSpec(0).len);
- EXPECT_EQ(RdataFields::INCOMPRESSIBLE_NAME, fields.getFieldSpec(1).type);
- EXPECT_EQ(13, fields.getFieldSpec(1).len);
- EXPECT_EQ(RdataFields::DATA, fields.getFieldSpec(2).type);
- EXPECT_EQ(15, fields.getFieldSpec(2).len);
- expected_wire.clear();
- UnitTestUtil::readWireData("rdatafields5.wire", expected_wire);
- Name("com").toWire(obuffer);
- obuffer.writeUint16(fields.getDataLength());
- fields.toWire(obuffer);
- other_name.toWire(obuffer);
- EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData, &expected_wire[0],
- expected_wire.size(), obuffer.getData(),
- obuffer.getLength());
- expected_wire.clear();
- UnitTestUtil::readWireData("rdatafields6.wire", expected_wire);
- Name("com").toWire(renderer);
- renderer.writeUint16(fields.getDataLength());
- fields.toWire(renderer); // the signer field won't be compressed
- other_name.toWire(renderer); // but will be used as a compression target
- EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData, &expected_wire[0],
- expected_wire.size(), renderer.getData(),
- renderer.getLength());
- }
- TEST_F(RdataFieldsTest, constructFromRdataRRSIG) {
- UnitTestUtil::readWireData("rdatafields4.wire", expected_wire);
- InputBuffer ibuffer(&expected_wire[0], expected_wire.size());
- const uint16_t rdlen = ibuffer.readUint16();
- const RdataFields fields(generic::RRSIG(ibuffer, rdlen));
- // drop the RDLEN part
- expected_wire.erase(expected_wire.begin(), expected_wire.begin() + 2);
- constructCommonTestsRRSIG(fields);
- }
- TEST_F(RdataFieldsTest, constructFromParamsRRSIG) {
- UnitTestUtil::readWireData("rdatafields4.wire", fields_wire);
- fields_wire.erase(fields_wire.begin(), fields_wire.begin() + 2);
- const RdataFields::FieldSpec specs[] = {
- RdataFields::FieldSpec(RdataFields::DATA, 18),
- RdataFields::FieldSpec(RdataFields::INCOMPRESSIBLE_NAME, 13),
- RdataFields::FieldSpec(RdataFields::DATA, 15)
- };
- const RdataFields fields(specs, sizeof(specs), &fields_wire[0],
- fields_wire.size());
- constructCommonTestsRRSIG(fields);
- }
- TEST_F(RdataFieldsTest, convertRdatatoParams) {
- // Confirm we can restore the original data from the serialized data.
- // We use RRSIG as a relatively complicated field structure.
- UnitTestUtil::readWireData("rdatafields4.wire", expected_wire);
- InputBuffer ibuffer(&expected_wire[0], expected_wire.size());
- const uint16_t rdlen = ibuffer.readUint16();
- const RdataFields fields(generic::RRSIG(ibuffer, rdlen));
- expected_wire.erase(expected_wire.begin(), expected_wire.begin() + 2);
- // Copy the data in separate storage
- vector<uint8_t> spec_store(fields.getFieldSpecDataSize());
- void* cp_spec = &spec_store[0];
- memcpy(cp_spec, fields.getFieldSpecData(), spec_store.size());
- vector<uint8_t> data_store(fields.getDataLength());
- memcpy(&data_store[0], fields.getData(), fields.getDataLength());
- // Restore the data in the form of RdataFields
- const RdataFields fields_byparams(cp_spec, fields.getFieldSpecDataSize(),
- &data_store[0], fields.getDataLength());
- // Check it's valid
- constructCommonTestsRRSIG(fields_byparams);
- }
- //
- // OPT: an empty RDATA
- //
- void
- RdataFieldsTest::constructCommonTestsOPT(const RdataFields& fields) {
- EXPECT_EQ(0, fields.getFieldSpecDataSize());
- EXPECT_EQ(0, fields.getFieldCount());
- EXPECT_EQ(0, fields.getDataLength());
- EXPECT_EQ((const uint8_t*) NULL, fields.getData());
- fields.toWire(obuffer);
- EXPECT_EQ(0, obuffer.getLength());
- fields.toWire(renderer);
- EXPECT_EQ(0, renderer.getLength());
- }
- TEST_F(RdataFieldsTest, constructFromRdataOPT) {
- InputBuffer ibuffer(NULL, 0);
- const RdataFields fields(generic::OPT(ibuffer, 0));
- constructCommonTestsOPT(fields);
- }
- TEST_F(RdataFieldsTest, constructFromParamsOPT) {
- const RdataFields fields(NULL, 0, NULL, 0);
- constructCommonTestsOPT(fields);
- }
- // Invalid input to the "from parameter" constructor: sum of the field lengths
- // is not equal to the data length.
- TEST_F(RdataFieldsTest, invalidFieldLength) {
- UnitTestUtil::readWireData("rdatafields4.wire", fields_wire);
- fields_wire.erase(fields_wire.begin(), fields_wire.begin() + 2);
- const RdataFields::FieldSpec specs[] = {
- RdataFields::FieldSpec(RdataFields::DATA, 18),
- RdataFields::FieldSpec(RdataFields::INCOMPRESSIBLE_NAME, 13),
- RdataFields::FieldSpec(RdataFields::DATA, 14)
- };
- // sum of field len < data len
- EXPECT_THROW(RdataFields(specs, 3, &fields_wire[0], fields_wire.size()),
- isc::InvalidParameter);
- // sum of field len > data len
- EXPECT_THROW(RdataFields(specs, 3, &fields_wire[0],
- fields_wire.size() - 2),
- isc::InvalidParameter);
- }
- // Invalid input to the "from parameter" constructor: NULL vs length mismatch
- TEST_F(RdataFieldsTest, mismatchFieldLengthAndData) {
- const unsigned char dummy_data = 0;
- const RdataFields::FieldSpec dummy_spec(RdataFields::DATA, 1);
- EXPECT_THROW(RdataFields(NULL, 1, &dummy_data, 1), isc::InvalidParameter);
- EXPECT_THROW(RdataFields(&dummy_spec, 0, NULL, 0), isc::InvalidParameter);
- EXPECT_THROW(RdataFields(&dummy_spec, 1, NULL, 1), isc::InvalidParameter);
- EXPECT_THROW(RdataFields(NULL, 0, &dummy_data, 0), isc::InvalidParameter);
- }
- // Bogus input to getFieldSpec()
- TEST_F(RdataFieldsTest, getFieldSpecWithBadFieldId) {
- const RdataFields fields_in_a(in::A("192.0.2.1"));
- EXPECT_THROW(fields_in_a.getFieldSpec(1), isc::OutOfRange);
- }
- // Tests for unexpected methods in RdataFieldComposerTest. Confirm
- // a call to these methods triggers an exception. Expected methods are
- // tested via other tests above.
- class DummyRdata : public Rdata {
- public:
- enum Mode { CLEAR, SKIP, TRIM };
- explicit DummyRdata(Mode mode) : mode_(mode) {}
- DummyRdata(const DummyRdata& source) : Rdata(), mode_(source.mode_) {}
- virtual ~DummyRdata() {}
- virtual void toWire(AbstractMessageRenderer& renderer) const {
- // call the unexpected method corresponding to the test mode.
- // method parameters don't matter.
- switch (mode_) {
- case CLEAR:
- renderer.clear();
- break;
- case SKIP:
- renderer.skip(2);
- break;
- case TRIM:
- renderer.trim(2);
- break;
- }
- }
-
- // These are defined only to make the compiler happy. We don't use them
- // for the test.
- virtual string toText() const { return (""); }
- virtual void toWire(OutputBuffer&) const {}
- virtual int compare(const Rdata&) const { return (0); }
- private:
- const int mode_;
- };
- TEST(RdataFieldComposerTest, unusedMethods) {
- EXPECT_THROW(RdataFields(DummyRdata(DummyRdata::CLEAR)), isc::Unexpected);
- }
- }
|