Commit 302a01c6 authored by Tomek Mrugalski's avatar Tomek Mrugalski 🛰
Browse files

[3145] Unit-tests for IA_PD, several clean-ups

parent 066f45d1
6XX. [func] tomek
libdhcp: Added support for IA_PD and IAPREFIX options.
(Trac #3145, git ABCD)
670. [func] marcin
libdhcpsrv: Added support to MySQL lease database backend to
store FQDN data for the lease.
......
......@@ -30,10 +30,24 @@ namespace dhcp {
Option6IA::Option6IA(uint16_t type, uint32_t iaid)
:Option(Option::V6, type), iaid_(iaid), t1_(0), t2_(0) {
// IA_TA has different layout than IA_NA and IA_PD. We can't sue this class
if (type == D6O_IA_TA) {
isc_throw(BadValue, "Can't use Option6IA for IA_TA as it has "
"a different layout");
}
}
Option6IA::Option6IA(uint16_t type, OptionBufferConstIter begin, OptionBufferConstIter end)
Option6IA::Option6IA(uint16_t type, OptionBufferConstIter begin,
OptionBufferConstIter end)
:Option(Option::V6, type) {
// IA_TA has different layout than IA_NA and IA_PD. We can't use this class
if (type == D6O_IA_TA) {
isc_throw(BadValue, "Can't use Option6IA for IA_TA as it has "
"a different layout");
}
unpack(begin, end);
}
......
......@@ -214,7 +214,7 @@ RECORD_DECL(IA_NA_RECORDS, OPT_UINT32_TYPE, OPT_UINT32_TYPE, OPT_UINT32_TYPE);
RECORD_DECL(IA_PD_RECORDS, OPT_UINT32_TYPE, OPT_UINT32_TYPE, OPT_UINT32_TYPE);
// ia-prefix
RECORD_DECL(IA_PREFIX_RECORDS, OPT_UINT32_TYPE, OPT_UINT32_TYPE,
OPT_UINT8_TYPE, OPT_BINARY_TYPE);
OPT_UINT8_TYPE, OPT_IPV6_ADDRESS_TYPE, OPT_BINARY_TYPE);
// lq-query
RECORD_DECL(LQ_QUERY_RECORDS, OPT_UINT8_TYPE, OPT_IPV6_ADDRESS_TYPE);
// lq-relay-data
......
......@@ -18,6 +18,7 @@
#include <dhcp/option.h>
#include <dhcp/option6_ia.h>
#include <dhcp/option6_iaaddr.h>
#include <dhcp/option6_iaprefix.h>
#include <util/buffer.h>
#include <boost/scoped_ptr.hpp>
......@@ -43,71 +44,96 @@ public:
buf_[i] = 255 - i;
}
}
OptionBuffer buf_;
OutputBuffer outBuf_;
};
TEST_F(Option6IATest, basic) {
buf_[0] = 0xa1; // iaid
buf_[1] = 0xa2;
buf_[2] = 0xa3;
buf_[3] = 0xa4;
/// @brief performs basic checks on IA option
///
/// Check that an option can be built based on incoming buffer and that
/// the option contains expected values.
/// @param type specifies option type (IA_NA or IA_PD)
void checkIA(uint16_t type) {
buf_[0] = 0xa1; // iaid
buf_[1] = 0xa2;
buf_[2] = 0xa3;
buf_[3] = 0xa4;
buf_[4] = 0x81; // T1
buf_[5] = 0x02;
buf_[6] = 0x03;
buf_[7] = 0x04;
buf_[8] = 0x84; // T2
buf_[9] = 0x03;
buf_[10] = 0x02;
buf_[11] = 0x01;
// Create an option
// unpack() is called from constructor
scoped_ptr<Option6IA> opt(new Option6IA(type,
buf_.begin(),
buf_.begin() + 12));
buf_[4] = 0x81; // T1
buf_[5] = 0x02;
buf_[6] = 0x03;
buf_[7] = 0x04;
EXPECT_EQ(Option::V6, opt->getUniverse());
EXPECT_EQ(type, opt->getType());
EXPECT_EQ(0xa1a2a3a4, opt->getIAID());
EXPECT_EQ(0x81020304, opt->getT1());
EXPECT_EQ(0x84030201, opt->getT2());
buf_[8] = 0x84; // T2
buf_[9] = 0x03;
buf_[10] = 0x02;
buf_[11] = 0x01;
// Pack this option again in the same buffer, but in
// different place
// Create an option
// unpack() is called from constructor
scoped_ptr<Option6IA> opt(new Option6IA(D6O_IA_NA,
buf_.begin(),
buf_.begin() + 12));
// Test for pack()
opt->pack(outBuf_);
EXPECT_EQ(Option::V6, opt->getUniverse());
EXPECT_EQ(D6O_IA_NA, opt->getType());
EXPECT_EQ(0xa1a2a3a4, opt->getIAID());
EXPECT_EQ(0x81020304, opt->getT1());
EXPECT_EQ(0x84030201, opt->getT2());
// 12 bytes header + 4 bytes content
EXPECT_EQ(12, opt->len() - opt->getHeaderLen());
EXPECT_EQ(type, opt->getType());
// Pack this option again in the same buffer, but in
// different place
EXPECT_EQ(16, outBuf_.getLength()); // lenght(IA_NA) = 16
// Test for pack()
opt->pack(outBuf_);
// Check if pack worked properly:
InputBuffer out(outBuf_.getData(), outBuf_.getLength());
// 12 bytes header + 4 bytes content
EXPECT_EQ(12, opt->len() - opt->getHeaderLen());
EXPECT_EQ(D6O_IA_NA, opt->getType());
// - if option type is correct
EXPECT_EQ(type, out.readUint16());
EXPECT_EQ(16, outBuf_.getLength()); // lenght(IA_NA) = 16
// - if option length is correct
EXPECT_EQ(12, out.readUint16());
// Check if pack worked properly:
InputBuffer out(outBuf_.getData(), outBuf_.getLength());
// - if iaid is correct
EXPECT_EQ(0xa1a2a3a4, out.readUint32() );
// - if option type is correct
EXPECT_EQ(D6O_IA_NA, out.readUint16());
// - if T1 is correct
EXPECT_EQ(0x81020304, out.readUint32() );
// - if option length is correct
EXPECT_EQ(12, out.readUint16());
// - if T1 is correct
EXPECT_EQ(0x84030201, out.readUint32() );
// - if iaid is correct
EXPECT_EQ(0xa1a2a3a4, out.readUint32() );
EXPECT_NO_THROW(opt.reset());
}
// - if T1 is correct
EXPECT_EQ(0x81020304, out.readUint32() );
OptionBuffer buf_;
OutputBuffer outBuf_;
};
// - if T1 is correct
EXPECT_EQ(0x84030201, out.readUint32() );
TEST_F(Option6IATest, basic) {
checkIA(D6O_IA_NA);
}
EXPECT_NO_THROW(opt.reset());
TEST_F(Option6IATest, pdBasic) {
checkIA(D6O_IA_PD);
}
// Check that this class cannot be used for IA_TA (IA_TA has no T1, T2 fields
// and people tend to think that if it's good for IA_NA and IA_PD, it can
// be used for IA_TA as well and that is not true)
TEST_F(Option6IATest, taForbidden) {
EXPECT_THROW(Option6IA(D6O_IA_TA, buf_.begin(), buf_.begin() + 50),
BadValue);
EXPECT_THROW(Option6IA(D6O_IA_TA, 123), BadValue);
}
// Check that getters/setters are working as expected.
TEST_F(Option6IATest, simple) {
scoped_ptr<Option6IA> ia(new Option6IA(D6O_IA_NA, 1234));
......@@ -131,12 +157,8 @@ TEST_F(Option6IATest, simple) {
EXPECT_NO_THROW(ia.reset());
}
// test if option can build suboptions
TEST_F(Option6IATest, suboptions_pack) {
buf_[0] = 0xff;
buf_[1] = 0xfe;
buf_[2] = 0xfc;
// test if the option can build suboptions
TEST_F(Option6IATest, suboptionsPack) {
scoped_ptr<Option6IA> ia(new Option6IA(D6O_IA_NA, 0x13579ace));
ia->setT1(0x2345);
......@@ -154,6 +176,7 @@ TEST_F(Option6IATest, suboptions_pack) {
ASSERT_EQ(4, sub1->len());
ASSERT_EQ(48, ia->len());
// This contains expected on-wire format
uint8_t expected[] = {
D6O_IA_NA/256, D6O_IA_NA%256, // type
0, 44, // length
......@@ -175,18 +198,68 @@ TEST_F(Option6IATest, suboptions_pack) {
};
ia->pack(outBuf_);
ASSERT_EQ(48, outBuf_.getLength());
ASSERT_EQ(48, outBuf_.getLength());
EXPECT_EQ(0, memcmp(outBuf_.getData(), expected, 48));
EXPECT_NO_THROW(ia.reset());
}
// test if IA_PD option can build IAPREFIX suboptions
TEST_F(Option6IATest, pdSuboptionsPack) {
// Let's build IA_PD
scoped_ptr<Option6IA> ia(new Option6IA(D6O_IA_PD, 0x13579ace));
ia->setT1(0x2345);
ia->setT2(0x3456);
// Put some dummy option in it
OptionPtr sub1(new Option(Option::V6, 0xcafe));
// Put a valid IAPREFIX option in it
boost::shared_ptr<Option6IAPrefix> addr1(
new Option6IAPrefix(D6O_IAPREFIX, IOAddress("2001:db8:1234:5678::abcd"),
91, 0x5000, 0x7000));
ia->addOption(sub1);
ia->addOption(addr1);
ASSERT_EQ(29, addr1->len());
ASSERT_EQ(4, sub1->len());
ASSERT_EQ(49, ia->len());
uint8_t expected[] = {
D6O_IA_PD/256, D6O_IA_PD%256, // type
0, 45, // length
0x13, 0x57, 0x9a, 0xce, // iaid
0, 0, 0x23, 0x45, // T1
0, 0, 0x34, 0x56, // T2
// iaprefix suboption
D6O_IAPREFIX/256, D6O_IAPREFIX%256, // type
0, 25, // len
0, 0, 0x50, 0, // preferred-lifetime
0, 0, 0x70, 0, // valid-lifetime
91, // prefix length
0x20, 0x01, 0xd, 0xb8, 0x12,0x34, 0x56, 0x78,
0, 0, 0, 0, 0, 0, 0xab, 0xcd, // IP address
// suboption
0xca, 0xfe, // type
0, 0 // len
};
ia->pack(outBuf_);
ASSERT_EQ(49, outBuf_.getLength());
EXPECT_EQ(0, memcmp(outBuf_.getData(), expected, 49));
EXPECT_NO_THROW(ia.reset());
}
// test if option can parse suboptions
TEST_F(Option6IATest, suboptions_unpack) {
// sizeof (expected) = 48 bytes
uint8_t expected[] = {
const uint8_t expected[] = {
D6O_IA_NA / 256, D6O_IA_NA % 256, // type
0, 28, // length
0x13, 0x57, 0x9a, 0xce, // iaid
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment