Commit 066f45d1 authored by Tomek Mrugalski's avatar Tomek Mrugalski 🛰
Browse files

[3145] Option6 IAPREFIX + unit-tests implemented

parent 5420c8bb
......@@ -26,6 +26,7 @@ libb10_dhcp___la_SOURCES += option4_addrlst.cc option4_addrlst.h
libb10_dhcp___la_SOURCES += option4_client_fqdn.cc option4_client_fqdn.h
libb10_dhcp___la_SOURCES += option6_ia.cc option6_ia.h
libb10_dhcp___la_SOURCES += option6_iaaddr.cc option6_iaaddr.h
libb10_dhcp___la_SOURCES += option6_iaprefix.cc option6_iaprefix.h
libb10_dhcp___la_SOURCES += option6_addrlst.cc option6_addrlst.h
libb10_dhcp___la_SOURCES += option6_client_fqdn.cc option6_client_fqdn.h
libb10_dhcp___la_SOURCES += option_int.h
......
// Copyright (C) 2013 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 <asiolink/io_address.h>
#include <dhcp/dhcp6.h>
#include <dhcp/libdhcp++.h>
#include <dhcp/option6_iaprefix.h>
#include <exceptions/exceptions.h>
#include <util/io_utilities.h>
#include <sstream>
#include <stdint.h>
#include <arpa/inet.h>
using namespace std;
using namespace isc::asiolink;
using namespace isc::util;
namespace isc {
namespace dhcp {
Option6IAPrefix::Option6IAPrefix(uint16_t type, const isc::asiolink::IOAddress& prefix,
uint8_t prefix_len, uint32_t pref, uint32_t valid)
:Option6IAAddr(type, prefix, pref, valid), prefix_len_(prefix_len) {
}
Option6IAPrefix::Option6IAPrefix(uint32_t type, OptionBuffer::const_iterator begin,
OptionBuffer::const_iterator end)
:Option6IAAddr(type, begin, end) {
unpack(begin, end);
}
void Option6IAPrefix::pack(isc::util::OutputBuffer& buf) {
if (!addr_.isV6()) {
isc_throw(isc::BadValue, addr_.toText()
<< " is not an IPv6 address");
}
buf.writeUint16(type_);
// len() returns complete option length. len field contains
// length without 4-byte option header
buf.writeUint16(len() - getHeaderLen());
buf.writeUint32(preferred_);
buf.writeUint32(valid_);
buf.writeUint8(prefix_len_);
buf.writeData(&addr_.toBytes()[0], isc::asiolink::V6ADDRESS_LEN);
// store encapsulated options (the only defined so far is PD_EXCLUDE)
packOptions(buf);
}
void Option6IAPrefix::unpack(OptionBuffer::const_iterator begin,
OptionBuffer::const_iterator end) {
if ( distance(begin, end) < OPTION6_IAPREFIX_LEN) {
isc_throw(OutOfRange, "Option " << type_ << " truncated");
}
preferred_ = readUint32( &(*begin) );
begin += sizeof(uint32_t);
valid_ = readUint32( &(*begin) );
begin += sizeof(uint32_t);
prefix_len_ = *begin;
begin += sizeof(uint8_t);
// 16 bytes: IPv6 address
addr_ = IOAddress::fromBytes(AF_INET6, &(*begin));
begin += V6ADDRESS_LEN;
// unpack encapsulated options (the only defined so far is PD_EXCLUDE)
unpackOptions(OptionBuffer(begin, end));
}
std::string Option6IAPrefix::toText(int indent /* =0 */) {
stringstream tmp;
for (int i=0; i<indent; i++)
tmp << " ";
tmp << "type=" << type_ << "(IAPREFIX) prefix=" << addr_.toText() << "/"
<< prefix_len_ << ", preferred-lft=" << preferred_ << ", valid-lft="
<< valid_ << endl;
for (OptionCollection::const_iterator opt=options_.begin();
opt!=options_.end();
++opt) {
tmp << (*opt).second->toText(indent+2);
}
return tmp.str();
}
uint16_t Option6IAPrefix::len() {
uint16_t length = OPTION6_HDR_LEN + OPTION6_IAPREFIX_LEN;
// length of all suboptions
for (Option::OptionCollection::iterator it = options_.begin();
it != options_.end(); ++it) {
length += (*it).second->len();
}
return (length);
}
} // end of namespace isc::dhcp
} // end of namespace isc
// Copyright (C) 2013 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.
#ifndef OPTION6_IAPREFIX_H
#define OPTION6_IAPREFIX_H
#include <asiolink/io_address.h>
#include <dhcp/option6_iaaddr.h>
#include <dhcp/option.h>
namespace isc {
namespace dhcp {
/// @brief Class that represents IAPREFIX option in DHCPv6
///
/// It is based on a similar class that handles addresses.
/// The major differences are fields order and prefix has also
/// additional prefix length field.
///
/// It should be noted that to get a full prefix (2 values: base address, and
/// a prefix length) 2 methods are used: getAddress() and getLength(). Although
/// using getAddress() to obtain base address is somewhat counter-intuitive at
/// first, it becomes obvious when one realizes that an address is a special
/// case of a prefix with /128. It make everyone's like much easier, because
/// the base address doubles as a regular address in many cases, e.g. when
/// searching for a lease.
class Option6IAPrefix : public Option6IAAddr {
public:
/// length of the fixed part of the IAPREFIX option
static const size_t OPTION6_IAPREFIX_LEN = 25;
/// @brief Ctor, used for options constructed (during transmission).
///
/// @param type option type
/// @param addr reference to an address
/// @param prefix_length length (1-128)
/// @param preferred address preferred lifetime (in seconds)
/// @param valid address valid lifetime (in seconds)
Option6IAPrefix(uint16_t type, const isc::asiolink::IOAddress& addr,
uint8_t prefix_length, uint32_t preferred, uint32_t valid);
/// @brief ctor, used for received options.
///
/// @param type option type
/// @param begin iterator to first byte of option data
/// @param end iterator to end of option data (first byte after option end)
Option6IAPrefix(uint32_t type, OptionBuffer::const_iterator begin,
OptionBuffer::const_iterator end);
/// @brief Writes option in wire-format.
///
/// Writes option in wire-format to buf, returns pointer to first unused
/// byte after stored option.
///
/// @param buf pointer to a buffer
void pack(isc::util::OutputBuffer& buf);
/// @brief Parses received buffer.
///
/// @param begin iterator to first byte of option data
/// @param end iterator to end of option data (first byte after option end)
virtual void unpack(OptionBufferConstIter begin,
OptionBufferConstIter end);
/// Returns string representation of the option.
///
/// @param indent number of spaces before printing text
///
/// @return string with text representation.
virtual std::string
toText(int indent = 0);
/// sets address in this option.
///
/// @param addr address to be sent in this option
void setPrefix(const isc::asiolink::IOAddress& prefix,
uint8_t length) { addr_ = prefix; prefix_len_ = length; }
uint8_t getLength() const { return prefix_len_; }
/// returns data length (data length + DHCPv4/DHCPv6 option header)
virtual uint16_t len();
protected:
uint8_t prefix_len_;
};
} // isc::dhcp namespace
} // isc namespace
#endif // OPTION_IA_H
......@@ -36,6 +36,7 @@ libdhcp___unittests_SOURCES += option6_addrlst_unittest.cc
libdhcp___unittests_SOURCES += option6_client_fqdn_unittest.cc
libdhcp___unittests_SOURCES += option6_ia_unittest.cc
libdhcp___unittests_SOURCES += option6_iaaddr_unittest.cc
libdhcp___unittests_SOURCES += option6_iaprefix_unittest.cc
libdhcp___unittests_SOURCES += option_int_unittest.cc
libdhcp___unittests_SOURCES += option_int_array_unittest.cc
libdhcp___unittests_SOURCES += option_data_types_unittest.cc
......
// Copyright (C) 2011-2013 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 <config.h>
#include <dhcp/dhcp6.h>
#include <dhcp/option.h>
#include <dhcp/option6_iaprefix.h>
#include <util/buffer.h>
#include <boost/scoped_ptr.hpp>
#include <gtest/gtest.h>
#include <iostream>
#include <sstream>
#include <arpa/inet.h>
using namespace std;
using namespace isc;
using namespace isc::dhcp;
using namespace isc::util;
namespace {
class Option6IAPrefixTest : public ::testing::Test {
public:
Option6IAPrefixTest() : buf_(255), outBuf_(255) {
for (int i = 0; i < 255; i++) {
buf_[i] = 255 - i;
}
}
OptionBuffer buf_;
OutputBuffer outBuf_;
};
TEST_F(Option6IAPrefixTest, basic) {
for (int i = 0; i < 255; i++) {
buf_[i] = 0;
}
buf_[ 0] = 0x00;
buf_[ 1] = 0x00;
buf_[ 2] = 0x03;
buf_[ 3] = 0xe8; // preferred lifetime = 1000
buf_[ 4] = 0xb2;
buf_[ 5] = 0xd0;
buf_[ 6] = 0x5e;
buf_[ 7] = 0x00; // valid lifetime = 3,000,000,000
buf_[ 8] = 77; // Prefix length = 77
buf_[ 9] = 0x20;
buf_[10] = 0x01;
buf_[11] = 0x0d;
buf_[12] = 0xb8;
buf_[13] = 0x00;
buf_[14] = 0x01;
buf_[21] = 0xde;
buf_[22] = 0xad;
buf_[23] = 0xbe;
buf_[24] = 0xef; // 2001:db8:1::dead:beef
// Create an option (unpack content)
boost::scoped_ptr<Option6IAPrefix> opt(new Option6IAPrefix(D6O_IAPREFIX,
buf_.begin(),
buf_.begin() + 25));
// Pack this option
opt->pack(outBuf_);
EXPECT_EQ(29, outBuf_.getLength());
EXPECT_EQ(Option::V6, opt->getUniverse());
// 4 bytes header + 4 bytes content
EXPECT_EQ("2001:db8:1::dead:beef", opt->getAddress().toText());
EXPECT_EQ(1000, opt->getPreferred());
EXPECT_EQ(3000000000U, opt->getValid());
EXPECT_EQ(77, opt->getLength());
EXPECT_EQ(D6O_IAPREFIX, opt->getType());
EXPECT_EQ(Option::OPTION6_HDR_LEN + Option6IAPrefix::OPTION6_IAPREFIX_LEN,
opt->len());
// Check if pack worked properly:
const uint8_t* out = (const uint8_t*)outBuf_.getData();
// - if option type is correct
EXPECT_EQ(D6O_IAPREFIX, out[0]*256 + out[1]);
// - if option length is correct
EXPECT_EQ(25, out[2]*256 + out[3]);
// - if option content is correct
EXPECT_EQ(0, memcmp(out + 4, &buf_[0], 25));
EXPECT_NO_THROW(opt.reset());
}
}
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