mirror of
https://gitlab.isc.org/isc-projects/kea
synced 2025-08-31 14:05:33 +00:00
[#2536] Implementing DNRv4v6 Option with TDD
This commit is contained in:
@@ -6,15 +6,10 @@
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include <asiolink/io_address.h>
|
||||
#include <dhcp/dhcp4.h>
|
||||
#include <dhcp/dhcp6.h>
|
||||
#include <dhcp/opaque_data_tuple.h>
|
||||
#include <dhcp/option4_dnr.h>
|
||||
#include <dhcp/option6_dnr.h>
|
||||
#include <dhcp/option_data_types.h>
|
||||
#include <dns/labelsequence.h>
|
||||
#include <util/strutil.h>
|
||||
|
||||
#include <set>
|
||||
|
||||
using namespace isc::asiolink;
|
||||
@@ -34,7 +29,7 @@ Option4Dnr::clone() const {
|
||||
}
|
||||
|
||||
void
|
||||
Option4Dnr::pack(util::OutputBuffer& buf, bool check) const {
|
||||
Option4Dnr::pack(OutputBuffer& buf, bool check) const {
|
||||
packHeader(buf, check);
|
||||
for (const DnrInstance& dnr_instance : dnr_instances_) {
|
||||
buf.writeUint16(dnr_instance.getDnrInstanceDataLength());
|
||||
@@ -62,7 +57,7 @@ Option4Dnr::unpack(OptionBufferConstIter begin, OptionBufferConstIter end) {
|
||||
}
|
||||
|
||||
// Unpack DnrInstanceDataLength.
|
||||
dnr_instance.unpackDnrInstanceDataLength(begin);
|
||||
dnr_instance.unpackDnrInstanceDataLength(begin, end);
|
||||
|
||||
const OptionBufferConstIter dnr_instance_end = begin +
|
||||
dnr_instance.getDnrInstanceDataLength();
|
||||
@@ -413,9 +408,15 @@ DnrInstance::addIpAddress(const IOAddress& ip_address) {
|
||||
}
|
||||
|
||||
void
|
||||
DnrInstance::unpackDnrInstanceDataLength(OptionBufferConstIter& begin) {
|
||||
DnrInstance::unpackDnrInstanceDataLength(OptionBufferConstIter& begin, OptionBufferConstIter end) {
|
||||
dnr_instance_data_length_ = readUint16(&*begin, getDnrInstanceDataLengthSize());
|
||||
begin += getDnrInstanceDataLengthSize();
|
||||
if (std::distance(begin, end) < dnr_instance_data_length_) {
|
||||
isc_throw(OutOfRange, getLogPrefix()
|
||||
<< " malformed: DNR instance data truncated to size "
|
||||
<< std::distance(begin, end) << " but it was supposed to be "
|
||||
<< dnr_instance_data_length_);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
@@ -438,8 +439,9 @@ DnrInstance::unpackAddresses(OptionBufferConstIter& begin, const OptionBufferCon
|
||||
// If additional data is supplied (i.e. not ADN only mode),
|
||||
// the option includes at least one valid IP address.
|
||||
if (addr_length_ == 0) {
|
||||
isc_throw(OutOfRange, getLogPrefix() << " malformed: Addr Len=" << addr_length_
|
||||
<< " is not greater than 0");
|
||||
isc_throw(OutOfRange, getLogPrefix()
|
||||
<< " malformed: Addr Len=" << addr_length_
|
||||
<< " but it must contain at least one valid IP address");
|
||||
}
|
||||
|
||||
begin += getAddrLengthSize();
|
||||
|
@@ -9,12 +9,30 @@
|
||||
|
||||
#include <asiolink/io_address.h>
|
||||
#include <dhcp/dhcp4.h>
|
||||
#include <dhcp/dhcp6.h>
|
||||
#include <dhcp/option.h>
|
||||
#include <dhcp/option_data_types.h>
|
||||
#include <dns/name.h>
|
||||
|
||||
namespace isc {
|
||||
namespace dhcp {
|
||||
|
||||
/// @brief Exception thrown when invalid domain name is specified.
|
||||
class InvalidOptionDnrDomainName : public Exception {
|
||||
public:
|
||||
InvalidOptionDnrDomainName(const char* file, size_t line, const char* what)
|
||||
: isc::Exception(file, line, what) {
|
||||
}
|
||||
};
|
||||
|
||||
/// @brief Exception thrown when Service parameters have wrong format.
|
||||
class InvalidOptionDnrSvcParams : public Exception {
|
||||
public:
|
||||
InvalidOptionDnrSvcParams(const char* file, size_t line, const char* what)
|
||||
: isc::Exception(file, line, what) {
|
||||
}
|
||||
};
|
||||
|
||||
/// @brief Represents DNR Instance which is used both in DHCPv4
|
||||
/// and DHCPv6 Encrypted DNS %Option.
|
||||
///
|
||||
@@ -208,24 +226,37 @@ public:
|
||||
|
||||
/// @brief Unpacks DNR Instance Data Length from wire data buffer and stores
|
||||
/// it in @c dnr_instance_data_length_.
|
||||
///
|
||||
/// It may throw in case of malformed data detected during parsing.
|
||||
///
|
||||
/// @param begin beginning of the buffer from which the field will be read
|
||||
void unpackDnrInstanceDataLength(OptionBufferConstIter& begin);
|
||||
/// @param end end of the buffer from which the field will be read
|
||||
void unpackDnrInstanceDataLength(OptionBufferConstIter& begin, OptionBufferConstIter end);
|
||||
|
||||
/// @brief Unpacks Service Priority from wire data buffer and stores it in @c service_priority_.
|
||||
/// @param begin beginning of the buffer from which the field will be read
|
||||
void unpackServicePriority(OptionBufferConstIter& begin);
|
||||
|
||||
/// @brief Unpacks the ADN from given wire data buffer and stores it in @c adn_ field.
|
||||
///
|
||||
/// It may throw in case of malformed data detected during parsing.
|
||||
///
|
||||
/// @param begin beginning of the buffer from which the ADN will be read
|
||||
/// @param end end of the buffer from which the ADN will be read
|
||||
void unpackAdn(OptionBufferConstIter& begin, OptionBufferConstIter end);
|
||||
|
||||
/// @brief Unpacks IP address(es) from wire data and stores it/them in @c ip_addresses_.
|
||||
///
|
||||
/// It may throw in case of malformed data detected during parsing.
|
||||
///
|
||||
/// @param begin beginning of the buffer from which the field will be read
|
||||
/// @param end end of the buffer from which the field will be read
|
||||
virtual void unpackAddresses(OptionBufferConstIter& begin, OptionBufferConstIter end);
|
||||
|
||||
/// @brief Unpacks Service Parameters from wire data buffer and stores it in @c svc_params_.
|
||||
///
|
||||
/// It may throw in case of malformed data detected during parsing.
|
||||
///
|
||||
/// @param begin beginning of the buffer from which the field will be read
|
||||
/// @param end end of the buffer from which the field will be read
|
||||
void unpackSvcParams(OptionBufferConstIter& begin, OptionBufferConstIter end);
|
||||
|
@@ -6,8 +6,6 @@
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include <dhcp/dhcp6.h>
|
||||
#include <dhcp/opaque_data_tuple.h>
|
||||
#include <dhcp/option6_dnr.h>
|
||||
|
||||
using namespace isc::asiolink;
|
||||
@@ -111,8 +109,9 @@ Option6Dnr::unpackAddresses(OptionBufferConstIter& begin, OptionBufferConstIter
|
||||
// If additional data is supplied (i.e. not ADN only mode),
|
||||
// the option includes at least one valid IP address.
|
||||
if (addr_length_ == 0) {
|
||||
isc_throw(OutOfRange, getLogPrefix() << " malformed: Addr Len=" << addr_length_
|
||||
<< " is not greater than 0");
|
||||
isc_throw(OutOfRange, getLogPrefix()
|
||||
<< " malformed: Addr Len=" << addr_length_
|
||||
<< " but it must contain at least one valid IP address");
|
||||
}
|
||||
|
||||
// Check if IPv6 Address(es) field is not truncated.
|
||||
|
@@ -7,28 +7,11 @@
|
||||
#ifndef OPTION6_DNR_H
|
||||
#define OPTION6_DNR_H
|
||||
|
||||
#include <dhcp/option.h>
|
||||
#include <dhcp/option4_dnr.h>
|
||||
|
||||
namespace isc {
|
||||
namespace dhcp {
|
||||
|
||||
/// @brief Exception thrown when invalid domain name is specified.
|
||||
class InvalidOptionDnrDomainName : public Exception {
|
||||
public:
|
||||
InvalidOptionDnrDomainName(const char* file, size_t line, const char* what)
|
||||
: isc::Exception(file, line, what) {
|
||||
}
|
||||
};
|
||||
|
||||
/// @brief Exception thrown when Service parameters have wrong format.
|
||||
class InvalidOptionDnrSvcParams : public Exception {
|
||||
public:
|
||||
InvalidOptionDnrSvcParams(const char* file, size_t line, const char* what)
|
||||
: isc::Exception(file, line, what) {
|
||||
}
|
||||
};
|
||||
|
||||
/// @brief Represents DHCPv6 Encrypted DNS %Option (code 144).
|
||||
///
|
||||
/// This option has been defined in the @c draft-ietf-add-dnr (to be replaced
|
||||
|
@@ -6,13 +6,9 @@
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include <asiolink/io_address.h>
|
||||
#include <dhcp/dhcp4.h>
|
||||
#include <dhcp/opaque_data_tuple.h>
|
||||
#include <dhcp/option4_dnr.h>
|
||||
|
||||
#include <boost/scoped_ptr.hpp>
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
using namespace isc;
|
||||
@@ -22,6 +18,7 @@ using boost::scoped_ptr;
|
||||
|
||||
namespace {
|
||||
|
||||
// This test verifies constructor of the empty Option4Dnr class.
|
||||
TEST(Option4DnrTest, emptyCtor) {
|
||||
// Create option instance. Check that constructor doesn't throw.
|
||||
scoped_ptr<Option4Dnr> option;
|
||||
@@ -33,7 +30,9 @@ TEST(Option4DnrTest, emptyCtor) {
|
||||
EXPECT_EQ(DHO_V4_DNR, option->getType());
|
||||
}
|
||||
|
||||
TEST(Option4DnrTest, oneDnrOnlyModeInstance) {
|
||||
// This test verifies constructor of the empty Option4Dnr class together
|
||||
// with adding ADN-only-mode DNR instance to option's DNR instances.
|
||||
TEST(Option4DnrTest, oneAdnOnlyModeInstance) {
|
||||
// Create option instance. Check that constructor doesn't throw.
|
||||
scoped_ptr<Option4Dnr> option;
|
||||
EXPECT_NO_THROW(option.reset(new Option4Dnr()));
|
||||
@@ -70,7 +69,9 @@ TEST(Option4DnrTest, oneDnrOnlyModeInstance) {
|
||||
option->toText());
|
||||
}
|
||||
|
||||
TEST(Option4DnrTest, multipleDnrOnlyModeInstances) {
|
||||
// This test verifies constructor of the empty Option4Dnr class together
|
||||
// with adding multiple ADN-only-mode DNR instances to option's DNR instances.
|
||||
TEST(Option4DnrTest, multipleAdnOnlyModeInstances) {
|
||||
// Create option instance. Check that constructor doesn't throw.
|
||||
scoped_ptr<Option4Dnr> option;
|
||||
EXPECT_NO_THROW(option.reset(new Option4Dnr()));
|
||||
@@ -129,6 +130,10 @@ TEST(Option4DnrTest, multipleDnrOnlyModeInstances) {
|
||||
option->toText());
|
||||
}
|
||||
|
||||
// This test verifies constructor of the empty Option4Dnr class together
|
||||
// with adding to option's DNR instances:
|
||||
// 1. ADN-only-mode DNR instance
|
||||
// 2. All fields included (IP addresses and service params also) DNR instance.
|
||||
TEST(Option4DnrTest, mixedDnrInstances) {
|
||||
// Create option instance. Check that constructor doesn't throw.
|
||||
scoped_ptr<Option4Dnr> option;
|
||||
@@ -186,7 +191,10 @@ TEST(Option4DnrTest, mixedDnrInstances) {
|
||||
option->toText());
|
||||
}
|
||||
|
||||
TEST(Option4DnrTest, packOneDnrOnlyModeInstance) {
|
||||
// This test verifies option packing into wire data.
|
||||
// Provided data to pack contains 1 DNR instance:
|
||||
// 1. ADN only mode
|
||||
TEST(Option4DnrTest, packOneAdnOnlyModeInstance) {
|
||||
// Create option instance. Check that constructor doesn't throw.
|
||||
scoped_ptr<Option4Dnr> option;
|
||||
EXPECT_NO_THROW(option.reset(new Option4Dnr()));
|
||||
@@ -222,7 +230,12 @@ TEST(Option4DnrTest, packOneDnrOnlyModeInstance) {
|
||||
EXPECT_EQ(0, memcmp(ref_data, buf.getData(), buf.getLength()));
|
||||
}
|
||||
|
||||
TEST(Option4DnrTest, packMultipleDnrOnlyModeInstances) {
|
||||
// This test verifies option packing into wire data.
|
||||
// Provided data to pack contains 3 DNR instances:
|
||||
// 1. ADN only mode
|
||||
// 2. ADN only mode
|
||||
// 3. ADN only mode
|
||||
TEST(Option4DnrTest, packMultipleAdnOnlyModeInstances) {
|
||||
// Create option instance. Check that constructor doesn't throw.
|
||||
scoped_ptr<Option4Dnr> option;
|
||||
EXPECT_NO_THROW(option.reset(new Option4Dnr()));
|
||||
@@ -278,6 +291,10 @@ TEST(Option4DnrTest, packMultipleDnrOnlyModeInstances) {
|
||||
EXPECT_EQ(0, memcmp(ref_data, buf.getData(), buf.getLength()));
|
||||
}
|
||||
|
||||
// This test verifies option packing into wire data.
|
||||
// Provided data to pack contains 2 DNR instances:
|
||||
// 1. ADN only mode
|
||||
// 2. All fields included (IP addresses and service params also).
|
||||
TEST(Option4DnrTest, packMixedDnrInstances) {
|
||||
// Create option instance. Check that constructor doesn't throw.
|
||||
scoped_ptr<Option4Dnr> option;
|
||||
@@ -334,6 +351,7 @@ TEST(Option4DnrTest, packMixedDnrInstances) {
|
||||
EXPECT_EQ(0, memcmp(ref_data, buf.getData(), buf.getLength()));
|
||||
}
|
||||
|
||||
// This test verifies option constructor from wire data.
|
||||
TEST(Option4DnrTest, onWireDataCtor) {
|
||||
// Prepare data to decode - ADN only mode 1 DNR instance.
|
||||
const uint8_t buf_data[] = {
|
||||
@@ -351,6 +369,10 @@ TEST(Option4DnrTest, onWireDataCtor) {
|
||||
ASSERT_TRUE(option);
|
||||
}
|
||||
|
||||
// This test verifies option constructor from wire data in terms
|
||||
// of proper data unpacking.
|
||||
// Provided wire data contains 1 DNR instance:
|
||||
// 1. ADN only mode
|
||||
TEST(Option4DnrTest, unpackOneAdnOnly) {
|
||||
// Prepare data to decode - ADN only mode 1 DNR instance.
|
||||
const uint8_t buf_data[] = {
|
||||
@@ -396,6 +418,10 @@ TEST(Option4DnrTest, unpackOneAdnOnly) {
|
||||
option->toText());
|
||||
}
|
||||
|
||||
// This test verifies option constructor from wire data in terms
|
||||
// of proper data unpacking.
|
||||
// Provided wire data contains 1 DNR instance:
|
||||
// 1. All fields included (IP addresses and service params also).
|
||||
TEST(Option4DnrTest, unpackOneDnrInstance) {
|
||||
// Prepare data to decode - 1 DNR instance.
|
||||
const uint8_t buf_data[] = {
|
||||
@@ -438,6 +464,11 @@ TEST(Option4DnrTest, unpackOneDnrInstance) {
|
||||
EXPECT_EQ(66, option->len());
|
||||
}
|
||||
|
||||
// This test verifies option constructor from wire data in terms
|
||||
// of proper data unpacking.
|
||||
// Provided wire data contains 2 DNR instances:
|
||||
// 1. ADN only mode
|
||||
// 2. All fields included (IP addresses and service params also).
|
||||
TEST(Option4DnrTest, unpackMixedDnrInstances) {
|
||||
// Prepare data to decode - 2 DNR instances.
|
||||
const uint8_t buf_data[] = {
|
||||
@@ -495,4 +526,257 @@ TEST(Option4DnrTest, unpackMixedDnrInstances) {
|
||||
EXPECT_EQ(92, option->len());
|
||||
}
|
||||
|
||||
// Test checks that exception is thrown when trying to unpack malformed wire data
|
||||
// - mandatory fields are truncated - Service Priority and ADN Len truncated.
|
||||
TEST(Option4DnrTest, unpackTruncatedDnrInstanceDataLen) {
|
||||
// Prepare malformed data to decode.
|
||||
const uint8_t buf_data[] = {
|
||||
0x00, 24, // DNR Instance Data Len
|
||||
0x00, 0x01, // Service priority is 1 dec
|
||||
21, // ADN Length is 21 dec
|
||||
0x07, 0x6D, 0x79, 0x68, 0x6F, 0x73, 0x74, '1', // FQDN: myhost1.
|
||||
0x07, 0x65, 0x78, 0x61, 0x6D, 0x70, 0x6C, 0x65, // example.
|
||||
0x03, 0x63, 0x6F, 0x6D, 0x00, // com.
|
||||
0x00, 62 // DNR Instance Data Len truncated
|
||||
};
|
||||
OptionBuffer buf(buf_data, buf_data + sizeof(buf_data));
|
||||
|
||||
// Create option instance. Check that constructor throws an exception while doing unpack.
|
||||
scoped_ptr<Option4Dnr> option;
|
||||
EXPECT_THROW(option.reset(new Option4Dnr(buf.begin(), buf.end())), OutOfRange);
|
||||
ASSERT_FALSE(option);
|
||||
}
|
||||
|
||||
// Test checks that exception is thrown when trying to unpack malformed wire data
|
||||
// - DNR instance data truncated when compared to DNR Instance Data Len field.
|
||||
TEST(Option4DnrTest, unpackTruncatedDnrInstanceData) {
|
||||
// Prepare malformed data to decode.
|
||||
const uint8_t buf_data[] = {
|
||||
0x00, 24, // DNR Instance Data Len
|
||||
0x00, 0x01, // Service priority is 1 dec
|
||||
21, // ADN Length is 21 dec
|
||||
0x07, 0x6D, 0x79, 0x68, 0x6F, 0x73, 0x74, '1', // FQDN: myhost1.
|
||||
0x07, 0x65, 0x78, 0x61, 0x6D, 0x70, 0x6C, 0x65, // example.
|
||||
0x03, 0x63, 0x6F, 0x6D, 0x00, // com.
|
||||
0x00, 62, // DNR Instance Data Len
|
||||
0x00, 0x02, // Service priority is 2 dec
|
||||
21 // ADN Length is 21 dec
|
||||
// the rest of DNR instance data is truncated
|
||||
};
|
||||
OptionBuffer buf(buf_data, buf_data + sizeof(buf_data));
|
||||
|
||||
// Create option instance. Check that constructor throws an exception while doing unpack.
|
||||
scoped_ptr<Option4Dnr> option;
|
||||
EXPECT_THROW(option.reset(new Option4Dnr(buf.begin(), buf.end())), OutOfRange);
|
||||
ASSERT_FALSE(option);
|
||||
}
|
||||
|
||||
// Test checks that exception is thrown when trying to unpack malformed wire data
|
||||
// - ADN field data truncated.
|
||||
TEST(Option4DnrTest, unpackTruncatedAdn) {
|
||||
// Prepare malformed data to decode.
|
||||
const uint8_t buf_data[] = {
|
||||
0x00, 24, // DNR Instance Data Len
|
||||
0x00, 0x01, // Service priority is 1 dec
|
||||
21, // ADN Length is 21 dec
|
||||
0x07, 0x6D, 0x79, 0x68, 0x6F, 0x73, 0x74, '1', // FQDN: myhost1.
|
||||
0x07, 0x65, 0x78, 0x61, 0x6D, 0x70, 0x6C, 0x65, // example.
|
||||
0x03, 0x63, 0x6F, 0x6D, 0x00, // com.
|
||||
0x00, 3, // DNR Instance Data Len
|
||||
0x00, 0x02, // Service priority is 2 dec
|
||||
21 // ADN Length is 21 dec
|
||||
// ADN data is missing.
|
||||
};
|
||||
OptionBuffer buf(buf_data, buf_data + sizeof(buf_data));
|
||||
|
||||
// Create option instance. Check that constructor throws an exception while doing unpack.
|
||||
scoped_ptr<Option4Dnr> option;
|
||||
EXPECT_THROW(option.reset(new Option4Dnr(buf.begin(), buf.end())), OpaqueDataTupleError);
|
||||
ASSERT_FALSE(option);
|
||||
}
|
||||
|
||||
// Test checks that exception is thrown when trying to unpack malformed wire data
|
||||
// - ADN FQDN contains only whitespace - non valid FQDN.
|
||||
TEST(Option4DnrTest, unpackInvalidFqdnAdn) {
|
||||
// Prepare malformed data to decode.
|
||||
const uint8_t buf_data[] = {
|
||||
0x00, 24, // DNR Instance Data Len
|
||||
0x00, 0x01, // Service priority is 1 dec
|
||||
21, // ADN Length is 21 dec
|
||||
0x07, 0x6D, 0x79, 0x68, 0x6F, 0x73, 0x74, '1', // FQDN: myhost1.
|
||||
0x07, 0x65, 0x78, 0x61, 0x6D, 0x70, 0x6C, 0x65, // example.
|
||||
0x03, 0x63, 0x6F, 0x6D, 0x00, // com.
|
||||
0x00, 4, // DNR Instance Data Len
|
||||
0x00, 0x02, // Service priority is 2 dec
|
||||
1, // ADN Length is 1 dec
|
||||
' ' // ADN contains only whitespace
|
||||
};
|
||||
OptionBuffer buf(buf_data, buf_data + sizeof(buf_data));
|
||||
|
||||
// Create option instance. Check that constructor throws an exception while doing unpack.
|
||||
scoped_ptr<Option4Dnr> option;
|
||||
EXPECT_THROW(option.reset(new Option4Dnr(buf.begin(), buf.end())), InvalidOptionDnrDomainName);
|
||||
ASSERT_FALSE(option);
|
||||
}
|
||||
|
||||
// Test checks that exception is thrown when trying to unpack malformed wire data
|
||||
// - ADN Length is 0 and no ADN FQDN at all.
|
||||
TEST(Option4DnrTest, unpackNoFqdnAdn) {
|
||||
// Prepare malformed data to decode.
|
||||
const uint8_t buf_data[] = {
|
||||
0x00, 24, // DNR Instance Data Len
|
||||
0x00, 0x01, // Service priority is 1 dec
|
||||
21, // ADN Length is 21 dec
|
||||
0x07, 0x6D, 0x79, 0x68, 0x6F, 0x73, 0x74, '1', // FQDN: myhost1.
|
||||
0x07, 0x65, 0x78, 0x61, 0x6D, 0x70, 0x6C, 0x65, // example.
|
||||
0x03, 0x63, 0x6F, 0x6D, 0x00, // com.
|
||||
0x00, 3, // DNR Instance Data Len
|
||||
0x00, 0x02, // Service priority is 2 dec
|
||||
0 // ADN Length is 0 dec
|
||||
};
|
||||
OptionBuffer buf(buf_data, buf_data + sizeof(buf_data));
|
||||
|
||||
// Create option instance. Check that constructor throws an exception while doing unpack.
|
||||
scoped_ptr<Option4Dnr> option;
|
||||
EXPECT_THROW(option.reset(new Option4Dnr(buf.begin(), buf.end())), InvalidOptionDnrDomainName);
|
||||
ASSERT_FALSE(option);
|
||||
}
|
||||
|
||||
// Test checks that exception is thrown when trying to unpack malformed wire data
|
||||
// - IPv4 address(es) field data truncated.
|
||||
TEST(Option4DnrTest, unpackTruncatedIpAddress) {
|
||||
// Prepare malformed data to decode.
|
||||
const uint8_t buf_data[] = {
|
||||
0x00, 24, // DNR Instance Data Len
|
||||
0x00, 0x01, // Service priority is 1 dec
|
||||
21, // ADN Length is 21 dec
|
||||
0x07, 0x6D, 0x79, 0x68, 0x6F, 0x73, 0x74, '1', // FQDN: myhost1.
|
||||
0x07, 0x65, 0x78, 0x61, 0x6D, 0x70, 0x6C, 0x65, // example.
|
||||
0x03, 0x63, 0x6F, 0x6D, 0x00, // com.
|
||||
0x00, 25, // DNR Instance Data Len
|
||||
0x00, 0x02, // Service priority is 2 dec
|
||||
21, // ADN Length is 21 dec
|
||||
0x07, 0x6D, 0x79, 0x68, 0x6F, 0x73, 0x74, '2', // FQDN: myhost2.
|
||||
0x07, 0x65, 0x78, 0x61, 0x6D, 0x70, 0x6C, 0x65, // example.
|
||||
0x03, 0x63, 0x6F, 0x6D, 0x00, // com.
|
||||
8 // Addr Len
|
||||
// the rest of DNR instance data is truncated.
|
||||
};
|
||||
OptionBuffer buf(buf_data, buf_data + sizeof(buf_data));
|
||||
|
||||
// Create option instance. Check that constructor throws an exception while doing unpack.
|
||||
scoped_ptr<Option4Dnr> option;
|
||||
EXPECT_THROW(option.reset(new Option4Dnr(buf.begin(), buf.end())), OpaqueDataTupleError);
|
||||
ASSERT_FALSE(option);
|
||||
}
|
||||
|
||||
// Test checks that exception is thrown when trying to unpack malformed wire data
|
||||
// - Addr length is 0 and no IPv4 addresses at all.
|
||||
TEST(Option4DnrTest, unpackNoIpAddress) {
|
||||
// Prepare malformed data to decode.
|
||||
const uint8_t buf_data[] = {
|
||||
0x00, 24, // DNR Instance Data Len
|
||||
0x00, 0x01, // Service priority is 1 dec
|
||||
21, // ADN Length is 21 dec
|
||||
0x07, 0x6D, 0x79, 0x68, 0x6F, 0x73, 0x74, '1', // FQDN: myhost1.
|
||||
0x07, 0x65, 0x78, 0x61, 0x6D, 0x70, 0x6C, 0x65, // example.
|
||||
0x03, 0x63, 0x6F, 0x6D, 0x00, // com.
|
||||
0x00, 25, // DNR Instance Data Len
|
||||
0x00, 0x02, // Service priority is 2 dec
|
||||
21, // ADN Length is 21 dec
|
||||
0x07, 0x6D, 0x79, 0x68, 0x6F, 0x73, 0x74, '2', // FQDN: myhost2.
|
||||
0x07, 0x65, 0x78, 0x61, 0x6D, 0x70, 0x6C, 0x65, // example.
|
||||
0x03, 0x63, 0x6F, 0x6D, 0x00, // com.
|
||||
0 // Addr Len = 0
|
||||
};
|
||||
OptionBuffer buf(buf_data, buf_data + sizeof(buf_data));
|
||||
|
||||
// Create option instance. Check that constructor throws an exception while doing unpack.
|
||||
scoped_ptr<Option4Dnr> option;
|
||||
EXPECT_THROW(option.reset(new Option4Dnr(buf.begin(), buf.end())), OutOfRange);
|
||||
ASSERT_FALSE(option);
|
||||
}
|
||||
|
||||
// Test checks that exception is thrown when trying to unpack malformed wire data
|
||||
// - Addr length is not a multiple of 4.
|
||||
TEST(Option4DnrTest, unpackIpAddressNon4Modulo) {
|
||||
// Prepare malformed data to decode.
|
||||
const uint8_t buf_data[] = {
|
||||
0x00, 24, // DNR Instance Data Len
|
||||
0x00, 0x01, // Service priority is 1 dec
|
||||
21, // ADN Length is 21 dec
|
||||
0x07, 0x6D, 0x79, 0x68, 0x6F, 0x73, 0x74, '1', // FQDN: myhost1.
|
||||
0x07, 0x65, 0x78, 0x61, 0x6D, 0x70, 0x6C, 0x65, // example.
|
||||
0x03, 0x63, 0x6F, 0x6D, 0x00, // com.
|
||||
0x00, 32, // DNR Instance Data Len
|
||||
0x00, 0x02, // Service priority is 2 dec
|
||||
21, // ADN Length is 21 dec
|
||||
0x07, 0x6D, 0x79, 0x68, 0x6F, 0x73, 0x74, '2', // FQDN: myhost2.
|
||||
0x07, 0x65, 0x78, 0x61, 0x6D, 0x70, 0x6C, 0x65, // example.
|
||||
0x03, 0x63, 0x6F, 0x6D, 0x00, // com.
|
||||
7, // Addr Len
|
||||
192, 168, 0, 1, // IP address 1
|
||||
192, 168, 0 // IP address 2 truncated
|
||||
};
|
||||
OptionBuffer buf(buf_data, buf_data + sizeof(buf_data));
|
||||
|
||||
// Create option instance. Check that constructor throws an exception while doing unpack.
|
||||
scoped_ptr<Option4Dnr> option;
|
||||
EXPECT_THROW(option.reset(new Option4Dnr(buf.begin(), buf.end())), OutOfRange);
|
||||
ASSERT_FALSE(option);
|
||||
}
|
||||
|
||||
// Test checks that exception is thrown when trying to unpack malformed wire data
|
||||
// - SvcParams Key contains char that is not allowed.
|
||||
TEST(Option4DnrTest, unpackvcParamsInvalidCharKey) {
|
||||
// Prepare malformed data to decode.
|
||||
const uint8_t buf_data[] = {
|
||||
0x00, 24, // DNR Instance Data Len
|
||||
0x00, 0x01, // Service priority is 1 dec
|
||||
21, // ADN Length is 21 dec
|
||||
0x07, 0x6D, 0x79, 0x68, 0x6F, 0x73, 0x74, '1', // FQDN: myhost1.
|
||||
0x07, 0x65, 0x78, 0x61, 0x6D, 0x70, 0x6C, 0x65, // example.
|
||||
0x03, 0x63, 0x6F, 0x6D, 0x00, // com.
|
||||
0x00, 39, // DNR Instance Data Len
|
||||
0x00, 0x02, // Service priority is 2 dec
|
||||
21, // ADN Length is 21 dec
|
||||
0x07, 0x6D, 0x79, 0x68, 0x6F, 0x73, 0x74, '2', // FQDN: myhost2.
|
||||
0x07, 0x65, 0x78, 0x61, 0x6D, 0x70, 0x6C, 0x65, // example.
|
||||
0x03, 0x63, 0x6F, 0x6D, 0x00, // com.
|
||||
8, // Addr Len
|
||||
192, 168, 0, 1, // IP address 1
|
||||
192, 168, 0, 2, // IP address 2 truncated
|
||||
'k', 'e', 'y', '+', '2', '3' // Svc Params key has forbidden char +
|
||||
};
|
||||
OptionBuffer buf(buf_data, buf_data + sizeof(buf_data));
|
||||
|
||||
// Create option instance. Check that constructor throws an exception while doing unpack.
|
||||
scoped_ptr<Option4Dnr> option;
|
||||
EXPECT_THROW(option.reset(new Option4Dnr(buf.begin(), buf.end())), InvalidOptionDnrSvcParams);
|
||||
ASSERT_FALSE(option);
|
||||
}
|
||||
|
||||
// This test verifies that string representation of the option returned by
|
||||
// toText method is correctly formatted.
|
||||
TEST(Option4DnrTest, toText) {
|
||||
// Create option instance. Check that constructor doesn't throw.
|
||||
scoped_ptr<Option4Dnr> option;
|
||||
EXPECT_NO_THROW(option.reset(new Option4Dnr()));
|
||||
ASSERT_TRUE(option);
|
||||
|
||||
// Prepare example DNR instance to add.
|
||||
DnrInstance dnr_1 = DnrInstance(Option::V4, 1, "myhost1.example.com.");
|
||||
|
||||
// Add DNR instance.
|
||||
option->addDnrInstance(dnr_1);
|
||||
|
||||
// Let's check if toText() works ok.
|
||||
// toText() len does not count in headers len.
|
||||
const int indent = 4;
|
||||
std::string expected = " type=162(V4_DNR), len=26, " // the indentation of 4 spaces
|
||||
"DNR Instance 1(Instance len=24, service_priority=1, "
|
||||
"adn_length=21, adn='myhost1.example.com.')";
|
||||
EXPECT_EQ(expected, option->toText(indent));
|
||||
}
|
||||
|
||||
} // namespace
|
@@ -6,9 +6,6 @@
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include <asiolink/io_address.h>
|
||||
#include <dhcp/dhcp6.h>
|
||||
#include <dhcp/opaque_data_tuple.h>
|
||||
#include <dhcp/option6_dnr.h>
|
||||
|
||||
#include <boost/scoped_ptr.hpp>
|
||||
|
Reference in New Issue
Block a user