Commit 0ed7f6f0 authored by Marcin Siodelski's avatar Marcin Siodelski
Browse files

[3562] Added negative test scenarios for ipv6 host reservations.

parent 7d63012c
......@@ -15,6 +15,7 @@
#include <dhcpsrv/host.h>
#include <util/strutil.h>
#include <exceptions/exceptions.h>
#include <sstream>
namespace isc {
namespace dhcp {
......@@ -42,6 +43,17 @@ IPv6Resrv::set(const asiolink::IOAddress& prefix, const uint8_t prefix_len) {
prefix_len_ = prefix_len;
}
std::string
IPv6Resrv::toText() const {
std::ostringstream s;
s << prefix_;
// For PD, append prefix length.
if (getType() == TYPE_PD) {
s << "/" << static_cast<int>(prefix_len_);
}
return (s.str());
}
bool
IPv6Resrv::operator==(const IPv6Resrv& other) const {
return (prefix_ == other.prefix_ &&
......@@ -158,6 +170,12 @@ Host::setIPv4Reservation(const asiolink::IOAddress& address) {
void
Host::addReservation(const IPv6Resrv& reservation) {
// Check if it is not duplicating existing reservation.
if (hasReservation(reservation)) {
isc_throw(isc::InvalidOperation, "failed on attempt to add a duplicated"
" host reservation for " << reservation.toText());
}
// Add it.
ipv6_reservations_.insert(IPv6ResrvTuple(reservation.getType(),
reservation));
}
......@@ -167,6 +185,22 @@ Host::getIPv6Reservations(const IPv6Resrv::Type& type) const {
return (ipv6_reservations_.equal_range(type));
}
bool
Host::hasReservation(const IPv6Resrv& reservation) const {
IPv6ResrvRange reservations = getIPv6Reservations(reservation.getType());
if (std::distance(reservations.first, reservations.second) > 0) {
for (IPv6ResrvIterator it = reservations.first;
it != reservations.second; ++it) {
if (it->second == reservation) {
return (true);
}
}
}
// No matching reservations found.
return (false);
}
void
Host::addClientClassInternal(ClientClasses& classes,
const std::string& class_name) {
......
......@@ -91,6 +91,9 @@ public:
/// multicast address or the prefix length is greater than 128.
void set(const asiolink::IOAddress& prefix, const uint8_t prefix_len);
/// @brief Returns information about the reservation in the textual format.
std::string toText() const;
/// @brief Equality operator.
///
/// @param other Reservation to compare to.
......@@ -340,6 +343,14 @@ public:
/// the specified type.
IPv6ResrvRange getIPv6Reservations(const IPv6Resrv::Type& type) const;
/// @brief Checks if specified IPv6 reservation exists for the host.
///
/// @param reservation A reservation to be checked for the host.
///
/// @return true if the reservation already exists for the host, false
/// otherwise.
bool hasReservation(const IPv6Resrv& reservation) const;
/// @brief Sets new hostname.
///
/// @param hostname New hostname.
......
......@@ -271,5 +271,78 @@ TEST_F(HostReservationParserTest, dhcp6IPv4Address) {
EXPECT_THROW(parser.build(config_element), DhcpConfigError);
}
// This test verifies that the configuration parser throws an exception
// when empty address has been specified.
TEST_F(HostReservationParserTest, dhcp6NullAddress) {
std::string config = "{ \"duid\": \"01:02:03:04:05:06:07:08:09:0A\","
"\"ip-addresses\": [ \"\" ],"
"\"prefixes\": [ ] }";
ElementPtr config_element = Element::fromJSON(config);
HostReservationParser6 parser(SubnetID(12));
EXPECT_THROW(parser.build(config_element), DhcpConfigError);
}
// This test verifies that the configuration parser throws an exception
// when invalid prefix length is specified.
TEST_F(HostReservationParserTest, dhcp6InvalidPrefixLength) {
std::string config = "{ \"duid\": \"01:02:03:04:05:06:07:08:09:0A\","
"\"prefixes\": [ \"2001:db8:1::/abc\" ] }";
ElementPtr config_element = Element::fromJSON(config);
HostReservationParser6 parser(SubnetID(12));
EXPECT_THROW(parser.build(config_element), DhcpConfigError);
}
// This test verifies that the configuration parser throws an exception
// when empty prefix is specified.
TEST_F(HostReservationParserTest, dhcp6NullPrefix) {
std::string config = "{ \"duid\": \"01:02:03:04:05:06:07:08:09:0A\","
"\"prefixes\": [ \"/64\" ] }";
ElementPtr config_element = Element::fromJSON(config);
HostReservationParser6 parser(SubnetID(12));
EXPECT_THROW(parser.build(config_element), DhcpConfigError);
}
// This test verifies that the configuration parser throws an exception
// when only slash is specified for the prefix..
TEST_F(HostReservationParserTest, dhcp6NullPrefix2) {
std::string config = "{ \"duid\": \"01:02:03:04:05:06:07:08:09:0A\","
"\"prefixes\": [ \"/\" ] }";
ElementPtr config_element = Element::fromJSON(config);
HostReservationParser6 parser(SubnetID(12));
EXPECT_THROW(parser.build(config_element), DhcpConfigError);
}
// This test verifies that the configuration parser throws an exception
// when the same address is reserved twice.
TEST_F(HostReservationParserTest, dhcp6DuplicatedAddress) {
std::string config = "{ \"duid\": \"01:02:03:04:05:06:07:08:09:0A\","
"\"ip-addresses\": [ \"2001:db8:1::1\", \"2001:db8:1::1\" ] }";
ElementPtr config_element = Element::fromJSON(config);
HostReservationParser6 parser(SubnetID(12));
EXPECT_THROW(parser.build(config_element), DhcpConfigError);
}
// This test verifies that the configuration parser throws an exception
// when the same prefix is reserved twice.
TEST_F(HostReservationParserTest, dhcp6DuplicatedPrefix) {
std::string config = "{ \"duid\": \"01:02:03:04:05:06:07:08:09:0A\","
"\"prefixes\": [ \"2001:db8:0101::/64\", \"2001:db8:0101::/64\" ] }";
ElementPtr config_element = Element::fromJSON(config);
HostReservationParser6 parser(SubnetID(12));
EXPECT_THROW(parser.build(config_element), DhcpConfigError);
}
} // end of anonymous namespace
......@@ -42,6 +42,15 @@ TEST(IPv6ResrvTest, constructorPrefix) {
EXPECT_EQ(IPv6Resrv::TYPE_PD, resrv.getType());
}
// This test verifies that the toText() function prints correctly.
TEST(IPv6ResrvTest, toText) {
IPv6Resrv resrv_prefix(IOAddress("2001:db8:1::"), 64);
EXPECT_EQ("2001:db8:1::/64", resrv_prefix.toText());
IPv6Resrv resrv_address(IOAddress("2001:db8:111::23"));
EXPECT_EQ("2001:db8:111::23", resrv_address.toText());
}
// This test verifies that invalid prefix is rejected.
TEST(IPv6ResrvTest, constructorInvalidPrefix) {
// IPv4 address is invalid for IPv6 reservation.
......@@ -339,6 +348,14 @@ TEST(HostTest, addReservations) {
host->addReservation(IPv6Resrv(IOAddress("2001:db8:1::1")));
);
// Check that reservations exist.
EXPECT_TRUE(host->hasReservation(IPv6Resrv(IOAddress("2001:db8:1::cafe"))));
EXPECT_TRUE(host->hasReservation(IPv6Resrv(IOAddress("2001:db8:1:1::"),
64)));
EXPECT_TRUE(host->hasReservation(IPv6Resrv(IOAddress("2001:db8:1:2::"),
64)));
EXPECT_TRUE(host->hasReservation(IPv6Resrv(IOAddress("2001:db8:1::1"))));
// Get only NA reservations.
IPv6ResrvRange addresses = host->getIPv6Reservations(IPv6Resrv::TYPE_NA);
ASSERT_EQ(2, std::distance(addresses.first, addresses.second));
......
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