namespace dhcp {
Pool::Pool(const isc::asiolink::IOAddress& first,
- const isc::asiolink::IOAddress& last,
- const Triplet<uint32_t>& t1,
- const Triplet<uint32_t>& t2,
- const Triplet<uint32_t>& valid_lifetime)
- :id_(getNextID()), first_(first), last_(last), t1_(t1), t2_(t2),
- valid_(valid_lifetime) {
+ const isc::asiolink::IOAddress& last)
+ :id_(getNextID()), first_(first), last_(last) {
}
bool Pool::inRange(const isc::asiolink::IOAddress& addr) {
}
Pool6::Pool6(Pool6Type type, const isc::asiolink::IOAddress& first,
- const isc::asiolink::IOAddress& last,
- const Triplet<uint32_t>& t1,
- const Triplet<uint32_t>& t2,
- const Triplet<uint32_t>& preferred_lifetime,
- const Triplet<uint32_t>& valid_lifetime)
- :Pool(first, last, t1, t2, valid_lifetime),
- type_(type), prefix_len_(0), preferred_(preferred_lifetime) {
+ const isc::asiolink::IOAddress& last)
+ :Pool(first, last), type_(type), prefix_len_(0) {
// check if specified address boundaries are sane
if (first.getFamily() != AF_INET6 || last.getFamily() != AF_INET6) {
}
Pool6::Pool6(Pool6Type type, const isc::asiolink::IOAddress& prefix,
- uint8_t prefix_len,
- const Triplet<uint32_t>& t1,
- const Triplet<uint32_t>& t2,
- const Triplet<uint32_t>& preferred_lifetime,
- const Triplet<uint32_t>& valid_lifetime)
- :Pool(prefix, IOAddress("::"), t1, t2, valid_lifetime),
- type_(type), prefix_len_(prefix_len), preferred_(preferred_lifetime) {
+ uint8_t prefix_len)
+ :Pool(prefix, IOAddress("::")),
+ type_(type), prefix_len_(prefix_len) {
// check if the prefix is sane
if (prefix.getFamily() != AF_INET6) {
last_ = lastAddrInPrefix(prefix, prefix_len);
}
-Subnet::Subnet(const isc::asiolink::IOAddress& prefix, uint8_t len)
- :id_(getNextID()), prefix_(prefix), prefix_len_(len) {
+Subnet::Subnet(const isc::asiolink::IOAddress& prefix, uint8_t len,
+ const Triplet<uint32_t>& t1,
+ const Triplet<uint32_t>& t2,
+ const Triplet<uint32_t>& valid_lifetime)
+ :id_(getNextID()), prefix_(prefix), prefix_len_(len), t1_(t1),
+ t2_(t2), valid_(valid_lifetime) {
if ( (prefix.getFamily() == AF_INET6 && len > 128) ||
(prefix.getFamily() == AF_INET && len > 32) ) {
isc_throw(BadValue, "Invalid prefix length specified for subnet: " << len);
return ( (first <= addr) && (addr <= last) );
}
-Subnet6::Subnet6(const isc::asiolink::IOAddress& prefix, uint8_t length)
- :Subnet(prefix, length) {
+Subnet6::Subnet6(const isc::asiolink::IOAddress& prefix, uint8_t length,
+ const Triplet<uint32_t>& t1,
+ const Triplet<uint32_t>& t2,
+ const Triplet<uint32_t>& preferred_lifetime,
+ const Triplet<uint32_t>& valid_lifetime)
+ :Subnet(prefix, length, t1, t2, valid_lifetime),
+ preferred_(preferred_lifetime){
if (prefix.getFamily() != AF_INET6) {
- isc_throw(BadValue, "Invalid prefix " << prefix.toText() << " specified in subnet6");
+ isc_throw(BadValue, "Invalid prefix " << prefix.toText()
+ << " specified in subnet6");
}
}
pools_.push_back(pool);
}
-
Pool6Ptr Subnet6::getPool6(const isc::asiolink::IOAddress& hint /* = IOAddress("::")*/ ) {
Pool6Ptr candidate;
for (Pool6Collection::iterator pool = pools_.begin(); pool != pools_.end(); ++pool) {
namespace dhcp {
class Pool6;
+
class Subnet6;
-/// @brief this class specifes parameter value
+/// @brief this template specifes a parameter value
///
-/// This class is used to store configuration parameters, like lifetime or T1.
-/// It defines 3 parameters: min/default/max values. There are 2 constructors:
+/// This template class is used to store configuration parameters, like lifetime or T1.
+/// It defines 3 parameters: min, default, and max value. There are 2 constructors:
/// - simple (just one value that sets all parameters)
/// - extended (that sets default value and two thresholds)
+/// It will be used with integer types. It provides necessary operators, so
+/// it can be assigned to a plain integer or integer assigned to a Triplet.
+/// See TripletTest.operator test for details on an easy Triplet usage.
template <class T>
class Triplet {
public:
}
/// @brief sets a fixed value
+ ///
+ /// This constructor assigns a fixed (i.e. no range, just a single value)
+ /// value.
Triplet(T value)
:min_(value), default_(value), max_(value) {
}
T max_;
};
+
+/// @brief base class for Pool4 and Pool6
+///
+/// Stores information about pool of IPv4 or IPv6 addresses.
+/// That is a basic component of a configuration.
class Pool {
public:
return (id_);
}
- Triplet<uint32_t> getValid() const {
- return (valid_);
- }
-
const isc::asiolink::IOAddress& getFirstAddress() const {
return (first_);
}
return (last_);
}
- Triplet<uint32_t> getT1() const {
- return (t1_);
- }
-
- Triplet<uint32_t> getT2() const {
- return (t2_);
- }
-
/// @brief checks if specified address is in range
bool inRange(const isc::asiolink::IOAddress& addr);
/// @brief protected constructor
Pool(const isc::asiolink::IOAddress& first,
- const isc::asiolink::IOAddress& last,
- const Triplet<uint32_t>& t1,
- const Triplet<uint32_t>& t2,
- const Triplet<uint32_t>& valid_lifetime);
+ const isc::asiolink::IOAddress& last);
static uint32_t getNextID() {
static uint32_t id = 0;
isc::asiolink::IOAddress last_;
- Triplet<uint32_t> t1_;
-
- Triplet<uint32_t> t2_;
-
- Triplet<uint32_t> valid_;
-
std::string comments_;
///uint128_t available_leases_;
} Pool6Type;
Pool6(Pool6Type type, const isc::asiolink::IOAddress& first,
- const isc::asiolink::IOAddress& last,
- const Triplet<uint32_t>& t1,
- const Triplet<uint32_t>& t2,
- const Triplet<uint32_t>& preferred_lifetime,
- const Triplet<uint32_t>& valid_lifetime);
+ const isc::asiolink::IOAddress& last);
Pool6(Pool6Type type, const isc::asiolink::IOAddress& addr,
- uint8_t prefix_len,
- const Triplet<uint32_t>& t1,
- const Triplet<uint32_t>& t2,
- const Triplet<uint32_t>& preferred_lifetime,
- const Triplet<uint32_t>& valid_lifetime);
+ uint8_t prefix_len);
Pool6Type getType() const {
return (type_);
}
- Triplet<uint32_t> getPreferred() const {
- return (preferred_);
- }
-
protected:
Pool6Type type_;
/// @brief prefix length
/// used by TYPE_PD only (zeroed for other types)
uint8_t prefix_len_;
-
- Triplet<uint32_t> preferred_;
};
typedef boost::shared_ptr<Pool> PoolPtr;
/// @brief checks if specified address is in range
bool inRange(const isc::asiolink::IOAddress& addr);
+ Triplet<uint32_t> getValid() const {
+ return (valid_);
+ }
+
+ Triplet<uint32_t> getT1() const {
+ return (t1_);
+ }
+
+ Triplet<uint32_t> getT2() const {
+ return (t2_);
+ }
+
protected:
/// @brief protected constructor
//
/// By making the constructor protected, we make sure that noone will
/// ever instantiate that class. Pool4 and Pool6 should be used instead.
- Subnet(const isc::asiolink::IOAddress& prefix, uint8_t len);
+ Subnet(const isc::asiolink::IOAddress& prefix, uint8_t len,
+ const Triplet<uint32_t>& t1,
+ const Triplet<uint32_t>& t2,
+ const Triplet<uint32_t>& valid_lifetime);
static uint32_t getNextID() {
static uint32_t id = 0;
uint8_t prefix_len_;
Pool6Collection pool_;
+
+ Triplet<uint32_t> t1_;
+
+ Triplet<uint32_t> t2_;
+
+ Triplet<uint32_t> valid_;
};
class Subnet6 : public Subnet {
public:
- Subnet6(const isc::asiolink::IOAddress& prefix, uint8_t length);
+ Subnet6(const isc::asiolink::IOAddress& prefix, uint8_t length,
+ const Triplet<uint32_t>& t1,
+ const Triplet<uint32_t>& t2,
+ const Triplet<uint32_t>& preferred_lifetime,
+ const Triplet<uint32_t>& valid_lifetime);
+
+ Triplet<uint32_t> getPreferred() const {
+ return (preferred_);
+ }
- Pool6Ptr getPool6(const isc::asiolink::IOAddress& hint = isc::asiolink::IOAddress("::"));
+ Pool6Ptr getPool6(const isc::asiolink::IOAddress& hint =
+ isc::asiolink::IOAddress("::"));
void addPool6(const Pool6Ptr& pool);
/// collection of pools in that list
Pool6Collection pools_;
+ Triplet<uint32_t> preferred_;
};
typedef boost::shared_ptr<Subnet6> Subnet6Ptr;
typedef std::vector<Subnet6Ptr> Subnet6Collection;
+
+/// @brief Configuration Manager
+///
+/// This singleton class holds the whole configuration for DHCPv4 and DHCPv6
+/// servers. It currently holds information about zero or more subnets6.
+/// Each subnet may contain zero or more pools. Pool4 and Pool6 is the most
+/// basic "chunk" of configuration. It contains a range of assigneable
+/// addresses.
+///
+/// The sketch of configuration inheritance (it is not implemented yet).
+/// Let's investigate the following configuration:
+///
+/// valid-lifetime 1000;
+/// subnet6 2001:db8:1::/48 {
+/// pool6 2001::db8:1::1 - 2001::db8:1::ff;
+/// };
+/// subnet6 2001:db8:2::/48 {
+/// valid-lifetime 2000;
+/// pool6 2001::db8:2::1 - 2001::db8:2::ff;
+/// };
+/// Parameters defined in a global scope are considered valid until
+/// they are overwritten in a smaller scope, in this case subnet6.
+/// In the example above, the first subnet6
+///
+/// @todo: Implement Subnet4 support (ticket #2237)
+/// @todo: Implement option definition support
+/// @todo: Implement inheritance.
class CfgMgr : public boost::noncopyable {
public:
static CfgMgr& instance();
// let's construct 2001:db8:1:: - 2001:db8:1::ffff:ffff:ffff:ffff pool
Pool6 pool1(Pool6::TYPE_IA, IOAddress("2001:db8:1::"),
- IOAddress("2001:db8:1::ffff:ffff:ffff:ffff"),
- 1000, 2000, 3000, 4000);
+ IOAddress("2001:db8:1::ffff:ffff:ffff:ffff"));
EXPECT_EQ(Pool6::TYPE_IA, pool1.getType());
EXPECT_EQ(IOAddress("2001:db8:1::"), pool1.getFirstAddress());
EXPECT_EQ(IOAddress("2001:db8:1::ffff:ffff:ffff:ffff"),
pool1.getLastAddress());
- EXPECT_EQ(1000, pool1.getT1());
- EXPECT_EQ(2000, pool1.getT2());
- EXPECT_EQ(3000, pool1.getPreferred());
- EXPECT_EQ(4000, pool1.getValid());
// This is Pool6, IPv4 addresses do not belong here
EXPECT_THROW(Pool6(Pool6::TYPE_IA, IOAddress("2001:db8::1"),
- IOAddress("192.168.0.5"),
- 1000, 2000, 3000, 4000), BadValue);
+ IOAddress("192.168.0.5")), BadValue);
EXPECT_THROW(Pool6(Pool6::TYPE_IA, IOAddress("192.168.0.2"),
- IOAddress("2001:db8::1"),
- 1000, 2000, 3000, 4000), BadValue);
-
+ IOAddress("2001:db8::1")), BadValue);
// Should throw. Range should be 2001:db8::1 - 2001:db8::2, not
// the other way around.
EXPECT_THROW(Pool6(Pool6::TYPE_IA, IOAddress("2001:db8::2"),
- IOAddress("2001:db8::1"),
- 1000, 2000, 3000, 4000), BadValue);
+ IOAddress("2001:db8::1")), BadValue);
}
TEST(Pool6Test, constructor_prefix_len) {
// let's construct 2001:db8:1::/96 pool
- Pool6 pool1(Pool6::TYPE_IA, IOAddress("2001:db8:1::"),
- 96, 1000, 2000, 3000, 4000);
+ Pool6 pool1(Pool6::TYPE_IA, IOAddress("2001:db8:1::"), 96);
EXPECT_EQ(Pool6::TYPE_IA, pool1.getType());
EXPECT_EQ("2001:db8:1::", pool1.getFirstAddress().toText());
EXPECT_EQ("2001:db8:1::ffff:ffff", pool1.getLastAddress().toText());
- EXPECT_EQ(1000, pool1.getT1());
- EXPECT_EQ(2000, pool1.getT2());
- EXPECT_EQ(3000, pool1.getPreferred());
- EXPECT_EQ(4000, pool1.getValid());
// This is Pool6, IPv4 addresses do not belong here
- EXPECT_THROW(Pool6(Pool6::TYPE_IA, IOAddress("192.168.0.2"),
- 96, 1000, 2000, 3000, 4000),
+ EXPECT_THROW(Pool6(Pool6::TYPE_IA, IOAddress("192.168.0.2"), 96),
BadValue);
}
TEST(Pool6Test, in_range) {
Pool6 pool1(Pool6::TYPE_IA, IOAddress("2001:db8:1::1"),
- IOAddress("2001:db8:1::f"),
- 1000, 2000, 3000, 4000);
+ IOAddress("2001:db8:1::f"));
EXPECT_FALSE(pool1.inRange(IOAddress("2001:db8:1::")));
EXPECT_TRUE(pool1.inRange(IOAddress("2001:db8:1::1")));
for (int i = 0; i < num_pools; ++i) {
pools.push_back(Pool6Ptr(new Pool6(Pool6::TYPE_IA, IOAddress("2001:db8:1::"),
- IOAddress("2001:db8:1::ffff:ffff:ffff:ffff"),
- 1000, 2000, 3000, 4000)));
+ IOAddress("2001:db8:1::ffff:ffff:ffff:ffff"))));
}
for (int i = 0; i < num_pools; ++i) {
TEST(Subnet6Test, constructor) {
- EXPECT_NO_THROW(Subnet6 subnet1(IOAddress("2001:db8:1::"), 64));
+ EXPECT_NO_THROW(Subnet6 subnet1(IOAddress("2001:db8:1::"), 64,
+ 1, 2, 3, 4));
- EXPECT_THROW(Subnet6 subnet2(IOAddress("2001:db8:1::"), 129),
+ EXPECT_THROW(Subnet6 subnet2(IOAddress("2001:db8:1::"), 129, 1, 2, 3, 4),
BadValue); // invalid prefix length
- EXPECT_THROW(Subnet6 subnet3(IOAddress("192.168.0.0"), 32),
+ EXPECT_THROW(Subnet6 subnet3(IOAddress("192.168.0.0"), 32, 1, 2, 3, 4),
BadValue); // IPv4 addresses are not allowed in Subnet6
}
TEST(Subnet6Test, in_range) {
- Subnet6 subnet(IOAddress("2001:db8:1::"), 64);
+ Subnet6 subnet(IOAddress("2001:db8:1::"), 64, 1000, 2000, 3000, 4000);
+
+ EXPECT_EQ(1000, subnet.getT1());
+ EXPECT_EQ(2000, subnet.getT2());
+ EXPECT_EQ(3000, subnet.getPreferred());
+ EXPECT_EQ(4000, subnet.getValid());
+
EXPECT_FALSE(subnet.inRange(IOAddress("2001:db8:0:ffff:ffff:ffff:ffff:ffff")));
EXPECT_TRUE(subnet.inRange(IOAddress("2001:db8:1::0")));
TEST(Subnet6Test, Pool6InSubnet6) {
- Subnet6Ptr subnet(new Subnet6(IOAddress("2001:db8:1::"), 56));
-
- Pool6Ptr pool1(new Pool6(Pool6::TYPE_IA, IOAddress("2001:db8:1:1::"),
- 64, 101, 102, 103, 104));
- Pool6Ptr pool2(new Pool6(Pool6::TYPE_IA, IOAddress("2001:db8:1:2::"),
- 64, 201, 202, 203, 204));
- Pool6Ptr pool3(new Pool6(Pool6::TYPE_IA, IOAddress("2001:db8:1:3::"),
- 64, 301, 302, 303, 304));
+ Subnet6Ptr subnet(new Subnet6(IOAddress("2001:db8:1::"), 56, 1, 2, 3, 4));
+ Pool6Ptr pool1(new Pool6(Pool6::TYPE_IA, IOAddress("2001:db8:1:1::"), 64));
+ Pool6Ptr pool2(new Pool6(Pool6::TYPE_IA, IOAddress("2001:db8:1:2::"), 64));
+ Pool6Ptr pool3(new Pool6(Pool6::TYPE_IA, IOAddress("2001:db8:1:3::"), 64));
subnet->addPool6(pool1);
TEST(Subnet6Test, Subnet6_Pool6_checks) {
- Subnet6Ptr subnet(new Subnet6(IOAddress("2001:db8:1::"), 56));
+ Subnet6Ptr subnet(new Subnet6(IOAddress("2001:db8:1::"), 56, 1, 2, 3, 4));
// this one is in subnet
- Pool6Ptr pool1(new Pool6(Pool6::TYPE_IA, IOAddress("2001:db8:1:1::"),
- 64, 101, 102, 103, 104));
+ Pool6Ptr pool1(new Pool6(Pool6::TYPE_IA, IOAddress("2001:db8:1:1::"), 64));
subnet->addPool6(pool1);
- Pool6Ptr pool2(new Pool6(Pool6::TYPE_IA, IOAddress("2001:db8::"),
- 48, 201, 202, 203, 204)); // this one is larger than the subnet!
+ // this one is larger than the subnet!
+ Pool6Ptr pool2(new Pool6(Pool6::TYPE_IA, IOAddress("2001:db8::"), 48));
+
EXPECT_THROW(subnet->addPool6(pool2), BadValue);
// this one is totally out of blue
- Pool6Ptr pool3(new Pool6(Pool6::TYPE_IA, IOAddress("3000::"),
- 16, 301, 302, 303, 304));
+ Pool6Ptr pool3(new Pool6(Pool6::TYPE_IA, IOAddress("3000::"), 16));
EXPECT_THROW(subnet->addPool6(pool3), BadValue);
}
ASSERT_TRUE(&cfg_mgr != 0);
- Subnet6Ptr subnet1(new Subnet6(IOAddress("2000::"), 48));
- Subnet6Ptr subnet2(new Subnet6(IOAddress("3000::"), 48));
- Subnet6Ptr subnet3(new Subnet6(IOAddress("4000::"), 48));
+ Subnet6Ptr subnet1(new Subnet6(IOAddress("2000::"), 48, 1, 2, 3, 4));
+ Subnet6Ptr subnet2(new Subnet6(IOAddress("3000::"), 48, 1, 2, 3, 4));
+ Subnet6Ptr subnet3(new Subnet6(IOAddress("4000::"), 48, 1, 2, 3, 4));
// there shouldn't be any subnet configured at this stage
EXPECT_EQ( Subnet6Ptr(), cfg_mgr.getSubnet6(IOAddress("2000::1")));