-// Copyright (C) 2012-2015 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2012-2016 Internet Systems Consortium, Inc. ("ISC")
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
Pool6::Pool6(Lease::Type type, const isc::asiolink::IOAddress& first,
const isc::asiolink::IOAddress& last)
- :Pool(type, first, last), prefix_len_(128) {
+ : Pool(type, first, last), prefix_len_(128),
+ excluded_prefix_(IOAddress::IPV6_ZERO_ADDRESS()),
+ excluded_prefix_len_(0) {
// check if specified address boundaries are sane
if (!first.isV6() || !last.isV6()) {
}
Pool6::Pool6(Lease::Type type, const isc::asiolink::IOAddress& prefix,
- uint8_t prefix_len, uint8_t delegated_len /* = 128 */)
- :Pool(type, prefix, IOAddress("::")), prefix_len_(delegated_len) {
+ const uint8_t prefix_len, const uint8_t delegated_len /* = 128 */)
+ : Pool(type, prefix, IOAddress::IPV6_ZERO_ADDRESS()),
+ prefix_len_(delegated_len),
+ excluded_prefix_(IOAddress::IPV6_ZERO_ADDRESS()),
+ excluded_prefix_len_(0) {
+
+ init(type, prefix, prefix_len, delegated_len,
+ IOAddress::IPV6_ZERO_ADDRESS(), 0);
+}
- // check if the prefix is sane
+Pool6::Pool6(const asiolink::IOAddress& prefix, const uint8_t prefix_len,
+ const uint8_t delegated_len,
+ const asiolink::IOAddress& excluded_prefix,
+ const uint8_t excluded_prefix_len)
+ : Pool(Lease::TYPE_PD, prefix, IOAddress::IPV6_ZERO_ADDRESS()),
+ prefix_len_(delegated_len),
+ excluded_prefix_(excluded_prefix),
+ excluded_prefix_len_(excluded_prefix_len) {
+
+ init(Lease::TYPE_PD, prefix, prefix_len, delegated_len, excluded_prefix,
+ excluded_prefix_len);
+
+ // The excluded prefix can only be specified using this constructor.
+ // Therefore, the initialization of the excluded prefix is takes place
+ // here, rather than in the init(...) function.
+ if (!excluded_prefix_.isV6()) {
+ isc_throw(BadValue, "excluded prefix must be an IPv6 prefix");
+ }
+
+ // An "unspecified" prefix should have both value and length equal to 0.
+ if ((excluded_prefix_.isV6Zero() && (excluded_prefix_len_ != 0)) ||
+ (!excluded_prefix_.isV6Zero() && (excluded_prefix_len_ == 0))) {
+ isc_throw(BadValue, "invalid excluded prefix "
+ << excluded_prefix_ << "/"
+ << static_cast<unsigned>(excluded_prefix_len_));
+ }
+
+ // If excluded prefix has been specified.
+ if (!excluded_prefix_.isV6Zero() && (excluded_prefix_len_ != 0)) {
+
+ // Excluded prefix length must not be greater than 128.
+ if (excluded_prefix_len_ > 128) {
+ isc_throw(BadValue, "excluded prefix length "
+ << static_cast<unsigned>(excluded_prefix_len_)
+ << " must not be greater than 128");
+ }
+
+ // Excluded prefix must be a sub-prefix of a delegated prefix. First
+ // check the prefix length as it is less involved.
+ if (excluded_prefix_len_ <= prefix_len_) {
+ isc_throw(BadValue, "excluded prefix length "
+ << static_cast<unsigned>(excluded_prefix_len_)
+ << " must be lower than the delegated prefix length "
+ << static_cast<unsigned>(prefix_len_));
+ }
+
+ /// @todo Check that the prefixes actually match. Theoretically, a
+ /// user could specify a prefix which sets insgnificant bits. We should
+ /// clear insignificant bits based on the prefix length but this
+ /// should be considered a part of the IOAddress class, perhaps and
+ /// requires a bit of work (mainly in terms of testing).
+ }
+}
+
+void
+Pool6::init(const Lease::Type& type,
+ const asiolink::IOAddress& prefix,
+ const uint8_t prefix_len,
+ const uint8_t delegated_len,
+ const asiolink::IOAddress& excluded_prefix,
+ const uint8_t excluded_prefix_len) {
+ // Check if the prefix is sane
if (!prefix.isV6()) {
isc_throw(BadValue, "Invalid Pool6 address boundaries: not IPv6");
}
- // check if the prefix length is sane
+ // Check if the prefix length is sane
if (prefix_len == 0 || prefix_len > 128) {
- isc_throw(BadValue, "Invalid prefix length: " << static_cast<unsigned>(prefix_len));
+ isc_throw(BadValue, "Invalid prefix length: "
+ << static_cast<unsigned>(prefix_len));
}
if (prefix_len > delegated_len) {
- isc_throw(BadValue, "Delegated length (" << static_cast<int>(delegated_len)
+ isc_throw(BadValue, "Delegated length ("
+ << static_cast<int>(delegated_len)
<< ") must be longer than or equal to prefix length ("
<< static_cast<int>(prefix_len) << ")");
}
std::string
Pool6::toText() const {
- std::stringstream tmp;
- tmp << "type=" << Lease::typeToText(type_) << ", " << first_
- << "-" << last_ << ", delegated_len="
- << static_cast<int>(prefix_len_);
- return (tmp.str());
+ std::ostringstream s;
+ s << "type=" << Lease::typeToText(type_) << ", " << first_
+ << "-" << last_ << ", delegated_len="
+ << static_cast<int>(prefix_len_);
+
+ if (excluded_prefix_len_ > 0) {
+ s << ", excluded_prefix=" << excluded_prefix_
+ << ", excluded_prefix_len="
+ << static_cast<unsigned>(excluded_prefix_len_);
+ }
+ return (s.str());
}
}; // end of isc::dhcp namespace
-// Copyright (C) 2012-2015 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2012-2016 Internet Systems Consortium, Inc. ("ISC")
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
/// @param type type of the pool (IA, TA or PD)
/// @param prefix specifies prefix of the pool
/// @param prefix_len specifies prefix length of the pool
- /// @param delegated_len specifies lenght of the delegated prefixes
+ /// @param delegated_len specifies length of the delegated prefixes
Pool6(Lease::Type type, const isc::asiolink::IOAddress& prefix,
uint8_t prefix_len, uint8_t delegated_len = 128);
+ /// @brief Constructor for DHCPv6 prefix pool with an excluded prefix.
+ ///
+ /// If @c excluded_prefix is equal to '::' and the @c excluded_prefix_len
+ /// is equal to 0, the excluded prefix is assumed to be unspecified for
+ /// the pool. In this case, the server will not send the Prefix Exclude
+ /// option to a client.
+ ///
+ /// @param prefix specified a prefix of the pool.
+ /// @param prefix_Leb specifies prefix length of the pool.
+ /// @param delegated_len specifies length of the delegated prefixes.
+ /// @param excluded_prefix specifies an excluded prefix as per RFC6603.
+ /// @param excluded_prefix_len specifies length of an excluded prefix.
+ Pool6(const asiolink::IOAddress& prefix, const uint8_t prefix_len,
+ const uint8_t delegated_len,
+ const asiolink::IOAddress& excluded_prefix,
+ const uint8_t excluded_prefix_len);
+
/// @brief returns pool type
///
/// @return pool type
return (prefix_len_);
}
+ /// @brief Returns an excluded prefix.
+ ///
+ /// An excluded prefix can be specified for a prefix pool as specified
+ /// in RFC6603.
+ ///
+ /// @return Reference to an IOAddress object representing an excluded
+ /// prefix pool. A value of '::' if the excluded prefix is not specified.
+ const isc::asiolink::IOAddress& getExcludedPrefix() const{
+ return (excluded_prefix_);
+ }
+
+ /// @brief Returns an excluded prefix length.
+ ///
+ /// An excluded prefix can be specified for a prefix pool as specified
+ /// in RFC6603.
+ ///
+ /// @return Excluded prefix length in the range of 2 to 128, if the
+ /// excluded prefix is specified. A value of 0 if the excluded prefix
+ /// is not specified.
+ uint8_t getExcludedPrefixLength() const{
+ return (excluded_prefix_len_);
+ }
+
/// @brief returns textual representation of the pool
///
/// @return textual representation
virtual std::string toText() const;
private:
+
+ /// @brief Generic method initializing a DHCPv6 pool.
+ ///
+ /// This method should be called by the constructors to initialize
+ /// DHCPv6 pools.
+ ///
+ /// @param Lease/pool type.
+ /// @param prefix An address or delegated prefix (depending on the
+ /// pool type specified as @c type).
+ /// @param prefix_len Prefix length. If a pool is an address pool,
+ /// this value should be set to 128.
+ /// @param delegated_len Length of the delegated prefixes. If a pool
+ /// is an address pool, this value should be set to 128.
+ /// @param excluded_prefix An excluded prefix as per RFC6603. This
+ /// value should only be specified for prefix pools. The value of
+ /// '::' means "unspecified".
+ /// @param excluded_prefix_len Length of the excluded prefix. This
+ /// is only specified for prefix pools. The value of 0 should be
+ /// used when @c excluded_prefix is not specified.
+ void init(const Lease::Type& type,
+ const asiolink::IOAddress& prefix,
+ const uint8_t prefix_len,
+ const uint8_t delegated_len,
+ const asiolink::IOAddress& excluded_prefix,
+ const uint8_t excluded_prefix_len);
+
/// @brief Defines prefix length (for TYPE_PD only)
uint8_t prefix_len_;
+
+ /// @brief The excluded prefix (RFC6603).
+ ///
+ /// This prefix can only be specified for DHCPv6 prefix pools.
+ /// An "unspecified" prefix has a value of '::'.
+ isc::asiolink::IOAddress excluded_prefix_;
+
+ /// @brief The excluded prefix length (RFC6603).
+ ///
+ /// This value can only be specified for DHCPv6 prefix pool.
+ /// An "unspecified" prefix has a length of 0.
+ uint8_t excluded_prefix_len_;
};
/// @brief a pointer an IPv6 Pool
-// Copyright (C) 2012-2015 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2012-2016 Internet Systems Consortium, Inc. ("ISC")
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
77, 77));
}
+// Checks that prefix pools with excluded prefixes are handlded properly.
+TEST(Pool6Test, PDExclude) {
+ Pool6Ptr pool;
+
+ // Create a pool with a good excluded prefix. The good excluded prefix
+ // is the one for which is a sub-prefix of the main prefix.
+ ASSERT_NO_THROW(pool.reset(new Pool6(IOAddress("2001:db8:1::"), 96, 112,
+ IOAddress("2001:db8:1:2::"), 120)));
+
+ // Verify pool properties.
+ EXPECT_EQ(Lease::TYPE_PD, pool->getType());
+ EXPECT_EQ(112, pool->getLength());
+ EXPECT_EQ("2001:db8:1::", pool->getFirstAddress().toText());
+ EXPECT_EQ("2001:db8:1::ffff:ffff", pool->getLastAddress().toText());
+ EXPECT_EQ("2001:db8:1:2::", pool->getExcludedPrefix().toText());
+ EXPECT_EQ(120, static_cast<unsigned>(pool->getExcludedPrefixLength()));
+
+ // Create another pool instance, but with the excluded prefix being
+ // "unspecified".
+ ASSERT_NO_THROW(pool.reset(new Pool6(IOAddress("2001:db8:1::"), 96, 112,
+ IOAddress::IPV6_ZERO_ADDRESS(), 0)));
+
+ EXPECT_EQ(Lease::TYPE_PD, pool->getType());
+ EXPECT_EQ(112, pool->getLength());
+ EXPECT_EQ("2001:db8:1::", pool->getFirstAddress().toText());
+ EXPECT_EQ("2001:db8:1::ffff:ffff", pool->getLastAddress().toText());
+ EXPECT_TRUE(pool->getExcludedPrefix().isV6Zero());
+ EXPECT_EQ(0, static_cast<unsigned>(pool->getExcludedPrefixLength()));
+
+ // Excluded prefix length must be greater than the main prefix length.
+ EXPECT_THROW(Pool6(IOAddress("2001:db8:1::"), 96, 112,
+ IOAddress("2001:db8:1::"), 112),
+ BadValue);
+
+ // Again, the excluded prefix length must be greater than main prefix
+ // length.
+ EXPECT_THROW(Pool6(IOAddress("2001:db8:1::"), 96, 112,
+ IOAddress("2001:db8:1::"), 104),
+ BadValue);
+
+ // The "unspecified" excluded prefix must have both values set to 0.
+ EXPECT_THROW(Pool6(IOAddress("2001:db8:1::"), 48, 64,
+ IOAddress("2001:db8:1::"), 0),
+ BadValue);
+
+ // Similar case as above, but the prefix value is 0 and the length
+ // is non zero.
+ EXPECT_THROW(Pool6(IOAddress("2001:db8:1::"), 48, 64,
+ IOAddress::IPV6_ZERO_ADDRESS(), 72),
+ BadValue);
+
+ // Excluded prefix must be an IPv6 prefix.
+ EXPECT_THROW(Pool6(IOAddress("10::"), 8, 16,
+ IOAddress("10.0.0.0"), 24),
+ BadValue);
+
+ // Excluded prefix length must not be greater than 128.
+ EXPECT_THROW(Pool6(IOAddress("2001:db8:1::"), 48, 64,
+ IOAddress("2001:db8:1::"), 129),
+ BadValue);
+}
+
// Checks that temporary address pools are handled properly
TEST(Pool6Test, TA) {
// Note: since we defined TA pool types during PD work, we can test it
}
// Simple check if toText returns reasonable values
-TEST(Poo6Test,toText) {
+TEST(Pool6Test,toText) {
Pool6 pool1(Lease::TYPE_NA, IOAddress("2001:db8::1"),
IOAddress("2001:db8::2"));
EXPECT_EQ("type=IA_NA, 2001:db8::1-2001:db8::2, delegated_len=128",
Pool6 pool2(Lease::TYPE_PD, IOAddress("2001:db8:1::"), 96, 112);
EXPECT_EQ("type=IA_PD, 2001:db8:1::-2001:db8:1::ffff:ffff, delegated_len=112",
pool2.toText());
+
+ Pool6 pool3(IOAddress("2001:db8:1::"), 96, 112,
+ IOAddress("2001:db8:1::1000"), 120);
+ EXPECT_EQ("type=IA_PD, 2001:db8:1::-2001:db8:1::ffff:ffff, delegated_len=112,"
+ " excluded_prefix=2001:db8:1::1000, excluded_prefix_len=120",
+ pool3.toText());
+
}
// Checks if the number of possible leases in range is reported correctly.