Browse Source

[2238] Pool, Subnet and Triplet moved to separate files.

Tomek Mrugalski 12 years ago
parent
commit
3690baaf06
8 changed files with 607 additions and 476 deletions
  1. 3 0
      src/lib/dhcp/Makefile.am
  2. 0 126
      src/lib/dhcp/cfgmgr.cc
  3. 2 350
      src/lib/dhcp/cfgmgr.h
  4. 87 0
      src/lib/dhcp/pool.cc
  5. 155 0
      src/lib/dhcp/pool.h
  6. 91 0
      src/lib/dhcp/subnet.cc
  7. 161 0
      src/lib/dhcp/subnet.h
  8. 108 0
      src/lib/dhcp/triplet.h

+ 3 - 0
src/lib/dhcp/Makefile.am

@@ -30,6 +30,9 @@ libb10_dhcp___la_SOURCES += pkt6.cc pkt6.h
 libb10_dhcp___la_SOURCES += pkt4.cc pkt4.h
 
 libb10_dhcpsrv_la_SOURCES  = cfgmgr.cc cfgmgr.h
+libb10_dhcpsrv_la_SOURCES += pool.cc pool.h
+libb10_dhcpsrv_la_SOURCES += subnet.cc subnet.h
+libb10_dhcpsrv_la_SOURCES += triplet.h
 libb10_dhcpsrv_la_SOURCES += addr_utilities.cc addr_utilities.h
 libb10_dhcpsrv_la_CXXFLAGS = $(AM_CXXFLAGS)
 libb10_dhcpsrv_la_CPPFLAGS = $(AM_CPPFLAGS) $(LOG4CPLUS_INCLUDES)

+ 0 - 126
src/lib/dhcp/cfgmgr.cc

@@ -12,7 +12,6 @@
 // OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
 // PERFORMANCE OF THIS SOFTWARE.
 
-#include <dhcp/addr_utilities.h>
 #include <asiolink/io_address.h>
 #include <dhcp/cfgmgr.h>
 
@@ -22,132 +21,7 @@ using namespace isc::util;
 namespace isc {
 namespace dhcp {
 
-Pool::Pool(const isc::asiolink::IOAddress& first,
-           const isc::asiolink::IOAddress& last)
-    :id_(getNextID()), first_(first), last_(last) {
-}
-
-bool Pool::inRange(const isc::asiolink::IOAddress& addr) const {
-    return (first_.smallerEqual(addr) && addr.smallerEqual(last_));
-}
-
-Pool6::Pool6(Pool6Type type, const isc::asiolink::IOAddress& first,
-             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) {
-        isc_throw(BadValue, "Invalid Pool6 address boundaries: not IPv6");
-    }
 
-    if (last < first) {
-        isc_throw(BadValue, "Upper boundary is smaller than lower boundary.");
-        // This check is a bit strict. If we decide that it is too strict,
-        // we need to comment it and uncomment lines below.
-        // On one hand, letting the user specify 2001::f - 2001::1 is nice, but
-        // on the other hand, 2001::1 may be a typo and the user really meant
-        // 2001::1:0 (or 1 followed by some hex digit), so a at least a warning
-        // would be useful.
-
-        // first_  = last;
-        // last_ = first;
-    }
-
-
-    // TYPE_PD is not supported by this constructor. first-last style
-    // parameters are for IA and TA only. There is another dedicated
-    // constructor for that (it uses prefix/length)
-    if ((type != TYPE_IA) && (type != TYPE_TA)) {
-        isc_throw(BadValue, "Invalid Pool6 type specified");
-    }
-}
-
-Pool6::Pool6(Pool6Type type, const isc::asiolink::IOAddress& prefix,
-             uint8_t prefix_len)
-    :Pool(prefix, IOAddress("::")),
-     type_(type), prefix_len_(prefix_len) {
-
-    // check if the prefix is sane
-    if (prefix.getFamily() != AF_INET6) {
-        isc_throw(BadValue, "Invalid Pool6 address boundaries: not IPv6");
-    }
-
-    // check if the prefix length is sane
-    if (prefix_len == 0 || prefix_len > 128) {
-        isc_throw(BadValue, "Invalid prefix length");
-    }
-
-    /// @todo: We should probably implement checks against weird addresses
-    /// here, like ::, starting with fe80, starting with ff etc. .
-
-    // Let's now calculate the last address in defined pool
-    last_ = lastAddrInPrefix(prefix, prefix_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);
-    }
-}
-
-bool Subnet::inRange(const isc::asiolink::IOAddress& addr) const {
-    IOAddress first = firstAddrInPrefix(prefix_, prefix_len_);
-    IOAddress last = lastAddrInPrefix(prefix_, prefix_len_);
-
-    return ((first <= addr) && (addr <= last));
-}
-
-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, "Non IPv6 prefix " << prefix.toText()
-                  << " specified in subnet6");
-    }
-}
-
-void Subnet6::addPool6(const Pool6Ptr& pool) {
-    IOAddress first_addr = pool->getFirstAddress();
-    IOAddress last_addr = pool->getLastAddress();
-
-    if (!inRange(first_addr) || !inRange(last_addr)) {
-        isc_throw(BadValue, "Pool6 (" << first_addr.toText() << "-" << last_addr.toText()
-                  << " does not belong in this (" << prefix_ << "/" << prefix_len_
-                  << ") subnet6");
-    }
-
-    /// @todo: Check that pools do not overlap
-
-    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) {
-
-        // if we won't find anything better, then let's just use the first pool
-        if (!candidate) {
-            candidate = *pool;
-        }
-
-        // if the client provided a pool and there's a pool that hint is valid in,
-        // then let's use that pool
-        if ((*pool)->inRange(hint)) {
-            return (*pool);
-        }
-    }
-    return (candidate);
-}
 
 
 CfgMgr&

+ 2 - 350
src/lib/dhcp/cfgmgr.h

@@ -23,360 +23,12 @@
 #include <asiolink/io_address.h>
 #include <util/buffer.h>
 #include <dhcp/option.h>
+#include <dhcp/pool.h>
+#include <dhcp/subnet.h>
 
 namespace isc {
 namespace dhcp {
 
-class Pool6;
-
-class Subnet6;
-
-/// @brief this template specifies a parameter value
-///
-/// 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 base type to Triple conversion
-    ///
-    /// Typically: uint32_t to Triplet assignment. It is very convenient
-    /// to be able to simply write Triplet<uint32_t> x = 7;
-    Triplet<T> operator=(T other) {
-        min_ = other;
-        default_ = other;
-        max_ = other;
-        return *this;
-    }
-
-    /// @brief triplet to base type conversion
-    ///
-    /// Typically: Triplet to uint32_t assignment. It is very convenient
-    /// to be able to simply write uint32_t z = x; (where x is a Triplet)
-    operator T() const {
-        return (default_);
-    }
-
-    /// @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) {
-    }
-
-    /// @brief sets the default value and thresholds
-    ///
-    /// @throw BadValue if min <= def <= max rule is violated
-    Triplet(T min, T def, T max)
-        :min_(min), default_(def), max_(max) {
-        if ( (min_ > def) || (def > max_) ) {
-            isc_throw(BadValue, "Invalid triplet values.");
-        }
-    }
-
-    /// @brief returns a minimum allowed value
-    T getMin() const { return min_;}
-
-    /// @brief returns the default value
-    T get() const { return default_;}
-
-    /// @brief returns value with a hint
-    ///
-    /// DHCP protocol treats any values sent by a client as hints.
-    /// This is a method that implements that. We can assign any value
-    /// from configured range that client asks.
-    T get(T hint) const {
-        if (hint <= min_) {
-            return (min_);
-        }
-
-        if (hint >= max_) {
-            return (max_);
-        }
-
-        return (hint);
-    }
-
-    /// @brief returns a maximum allowed value
-    T getMax() const { return max_; }
-
-protected:
-
-    /// @brief the minimum value
-    T min_;
-
-    /// @brief the default value
-    T default_;
-
-    /// @brief the maximum 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:
-
-    /// @brief returns Pool-id
-    ///
-    /// @return pool-id value
-    /// Pool-id is an unique value that can be used to identify a pool.
-    uint32_t getId() const {
-        return (id_);
-    }
-
-    /// @brief Returns the first address in a pool.
-    ///
-    /// @return first address in a pool
-    const isc::asiolink::IOAddress& getFirstAddress() const {
-        return (first_);
-    }
-
-    /// @brief Returns the last address in a pool.
-    /// @return last address in a pool
-    const isc::asiolink::IOAddress& getLastAddress() const {
-        return (last_);
-    }
-
-    /// @brief Checks if a given address is in the range.
-    ///
-    /// @return true, if the address is in pool
-    bool inRange(const isc::asiolink::IOAddress& addr) const;
-
-protected:
-
-    /// @brief protected constructor
-    ///
-    /// This constructor is protected to prevent anyone from instantiating
-    /// Pool class directly. Instances of Pool4 and Pool6 should be created
-    /// instead.
-    Pool(const isc::asiolink::IOAddress& first,
-         const isc::asiolink::IOAddress& last);
-
-    /// @brief returns the next unique Pool-ID
-    ///
-    /// @return the next unique Pool-ID
-    static uint32_t getNextID() {
-        static uint32_t id = 0;
-        return (id++);
-    }
-
-    /// @brief pool-id
-    ///
-    /// This ID is used to identify this specific pool.
-    uint32_t id_;
-
-    /// @brief The first address in a pool
-    isc::asiolink::IOAddress first_;
-
-    /// @brief The last address in a pool
-    isc::asiolink::IOAddress last_;
-
-    /// @brief Comments field
-    ///
-    /// @todo: This field is currently not used.
-    std::string comments_;
-};
-
-/// @brief Pool information for IPv6 addresses and prefixes
-///
-/// It holds information about pool6, i.e. a range of IPv6 address space that
-/// is configured for DHCP allocation.
-class Pool6 : public Pool {
-public:
-
-    /// @brief specifies Pool type
-    ///
-    /// Currently there are 3 pool types defined in DHCPv6:
-    /// - Non-temporary addresses (conveyed in IA_NA)
-    /// - Temporary addresses (conveyed in IA_TA)
-    /// - Delegated Prefixes (conveyed in IA_PD)
-    /// There is a new one being worked on (IA_PA, see draft-ietf-dhc-host-gen-id), but
-    /// support for it is not planned for now.
-    typedef enum {
-        TYPE_IA,
-        TYPE_TA,
-        TYPE_PD
-    }  Pool6Type;
-
-    /// @brief the constructor for Pool6 "min-max" style definition
-    ///
-    /// @param first the first address in a pool
-    /// @param last the last address in a pool
-    Pool6(Pool6Type type, const isc::asiolink::IOAddress& first,
-          const isc::asiolink::IOAddress& last);
-
-    /// @brief the constructor for Pool6 "prefix/len" style definition
-    ///
-    /// @param prefix specifies prefix of the pool
-    /// @param prefix_len specifies length of the prefix of the pool
-    Pool6(Pool6Type type, const isc::asiolink::IOAddress& prefix,
-          uint8_t prefix_len);
-
-    /// @brief returns pool type
-    ///
-    /// @return pool type
-    Pool6Type getType() const {
-        return (type_);
-    }
-
-private:
-    /// @brief defines a pool type
-    Pool6Type type_;
-
-    /// @brief prefix length
-    /// used by TYPE_PD only (zeroed for other types)
-    uint8_t prefix_len_;
-};
-
-/// @brief a pointer an IPv6 Pool
-typedef boost::shared_ptr<Pool6> Pool6Ptr;
-
-/// @brief a container for IPv6 Pools
-typedef std::vector<Pool6Ptr> Pool6Collection;
-
-/// @brief a base class for Subnet4 and Subnet6
-///
-/// This class presents a common base for IPv4 and IPv6 subnets.
-/// In a physical sense, a subnet defines a single network link with all devices
-/// attached to it. In most cases all devices attached to a single link can
-/// share the same parameters. Therefore Subnet holds several values that are
-/// typically shared by all hosts: renew timer (T1), rebind timer (T2) and
-/// leased addresses lifetime (valid-lifetime).
-///
-/// @todo: Implement support for options here
-class Subnet {
-public:
-    /// @brief checks if specified address is in range
-    bool inRange(const isc::asiolink::IOAddress& addr) const;
-
-    /// @brief return valid-lifetime for addresses in that prefix
-    Triplet<uint32_t> getValid() const {
-        return (valid_);
-    }
-
-    /// @brief returns T1 (renew timer), expressed in seconds
-    Triplet<uint32_t> getT1() const {
-        return (t1_);
-    }
-
-    /// @brief returns T2 (rebind timer), expressed in seconds
-    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,
-           const Triplet<uint32_t>& t1,
-           const Triplet<uint32_t>& t2,
-           const Triplet<uint32_t>& valid_lifetime);
-
-    /// @brief returns the next unique Subnet-ID
-    ///
-    /// @return the next unique Subnet-ID
-    static uint32_t getNextID() {
-        static uint32_t id = 0;
-        return (id++);
-    }
-
-    /// @brief subnet-id
-    ///
-    /// Subnet-id is a unique value that can be used to find or identify
-    /// a Subnet4 or Subnet6.
-    uint32_t id_;
-
-    /// @brief a prefix of the subnet
-    isc::asiolink::IOAddress prefix_;
-
-    /// @brief a prefix length of the subnet
-    uint8_t prefix_len_;
-
-    /// @brief a tripet (min/default/max) holding allowed renew timer values
-    Triplet<uint32_t> t1_;
-
-    /// @brief a tripet (min/default/max) holding allowed rebind timer values
-    Triplet<uint32_t> t2_;
-
-    /// @brief a tripet (min/default/max) holding allowed valid lifetime values
-    Triplet<uint32_t> valid_;
-};
-
-/// @brief A configuration holder for IPv6 subnet.
-///
-/// This class represents an IPv6 subnet.
-class Subnet6 : public Subnet {
-public:
-
-    /// @brief Constructor with all parameters
-    ///
-    /// @param prefix Subnet6 prefix
-    /// @param length prefix length
-    /// @param t1 renewal timer (in seconds)
-    /// @param t2 rebind timer (in seconds)
-    /// @param preferred_lifetime preferred lifetime of leases (in seconds)
-    /// @param valid_lifetime preferred lifetime of leases (in seconds)
-    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);
-
-    /// @brief Returns preverred lifetime (in seconds)
-    ///
-    /// @return a triplet with preferred lifetime
-    Triplet<uint32_t> getPreferred() const {
-        return (preferred_);
-    }
-
-    /// @brief Returns a pool that specified address belongs to
-    ///
-    /// @param hint address that the returned pool should cover (optional)
-    /// @return Pointer to found pool6 (or NULL)
-    Pool6Ptr getPool6(const isc::asiolink::IOAddress& hint =
-                      isc::asiolink::IOAddress("::"));
-
-    /// @brief Adds a new pool.
-    /// @param pool pool to be added
-    void addPool6(const Pool6Ptr& pool);
-
-    /// @brief returns all pools
-    ///
-    /// The reference is only valid as long as the object that
-    /// returned it.
-    ///
-    /// @return a collection of all pools
-    const Pool6Collection& getPools() const {
-        return pools_;
-    }
-
-protected:
-    /// @brief collection of pools in that list
-    Pool6Collection pools_;
-
-    /// @brief a triplet with preferred lifetime (in seconds)
-    Triplet<uint32_t> preferred_;
-};
-
-/// @brief A pointer to a Subnet6 object
-typedef boost::shared_ptr<Subnet6> Subnet6Ptr;
-
-/// @brief A collection of Subnet6 objects
-typedef std::vector<Subnet6Ptr> Subnet6Collection;
 
 /// @brief Configuration Manager
 ///

+ 87 - 0
src/lib/dhcp/pool.cc

@@ -0,0 +1,87 @@
+// Copyright (C) 2012 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/addr_utilities.h>
+#include <dhcp/pool.h>
+
+using namespace isc::asiolink;
+
+namespace isc {
+namespace dhcp {
+
+Pool::Pool(const isc::asiolink::IOAddress& first,
+           const isc::asiolink::IOAddress& last)
+    :id_(getNextID()), first_(first), last_(last) {
+}
+
+bool Pool::inRange(const isc::asiolink::IOAddress& addr) const {
+    return (first_.smallerEqual(addr) && addr.smallerEqual(last_));
+}
+
+Pool6::Pool6(Pool6Type type, const isc::asiolink::IOAddress& first,
+             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) {
+        isc_throw(BadValue, "Invalid Pool6 address boundaries: not IPv6");
+    }
+
+    if (last < first) {
+        isc_throw(BadValue, "Upper boundary is smaller than lower boundary.");
+        // This check is a bit strict. If we decide that it is too strict,
+        // we need to comment it and uncomment lines below.
+        // On one hand, letting the user specify 2001::f - 2001::1 is nice, but
+        // on the other hand, 2001::1 may be a typo and the user really meant
+        // 2001::1:0 (or 1 followed by some hex digit), so a at least a warning
+        // would be useful.
+
+        // first_  = last;
+        // last_ = first;
+    }
+
+
+    // TYPE_PD is not supported by this constructor. first-last style
+    // parameters are for IA and TA only. There is another dedicated
+    // constructor for that (it uses prefix/length)
+    if ((type != TYPE_IA) && (type != TYPE_TA)) {
+        isc_throw(BadValue, "Invalid Pool6 type specified");
+    }
+}
+
+Pool6::Pool6(Pool6Type type, const isc::asiolink::IOAddress& prefix,
+             uint8_t prefix_len)
+    :Pool(prefix, IOAddress("::")),
+     type_(type), prefix_len_(prefix_len) {
+
+    // check if the prefix is sane
+    if (prefix.getFamily() != AF_INET6) {
+        isc_throw(BadValue, "Invalid Pool6 address boundaries: not IPv6");
+    }
+
+    // check if the prefix length is sane
+    if (prefix_len == 0 || prefix_len > 128) {
+        isc_throw(BadValue, "Invalid prefix length");
+    }
+
+    /// @todo: We should probably implement checks against weird addresses
+    /// here, like ::, starting with fe80, starting with ff etc. .
+
+    // Let's now calculate the last address in defined pool
+    last_ = lastAddrInPrefix(prefix, prefix_len);
+}
+
+}; // end of isc::dhcp namespace
+}; // end of isc namespace

+ 155 - 0
src/lib/dhcp/pool.h

@@ -0,0 +1,155 @@
+// Copyright (C) 2012 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 POOL_H
+#define POOL_H
+
+#include <vector>
+#include <asiolink/io_address.h>
+#include <boost/shared_ptr.hpp>
+
+namespace isc {
+namespace dhcp {
+
+/// @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:
+
+    /// @brief returns Pool-id
+    ///
+    /// @return pool-id value
+    /// Pool-id is an unique value that can be used to identify a pool.
+    uint32_t getId() const {
+        return (id_);
+    }
+
+    /// @brief Returns the first address in a pool.
+    ///
+    /// @return first address in a pool
+    const isc::asiolink::IOAddress& getFirstAddress() const {
+        return (first_);
+    }
+
+    /// @brief Returns the last address in a pool.
+    /// @return last address in a pool
+    const isc::asiolink::IOAddress& getLastAddress() const {
+        return (last_);
+    }
+
+    /// @brief Checks if a given address is in the range.
+    ///
+    /// @return true, if the address is in pool
+    bool inRange(const isc::asiolink::IOAddress& addr) const;
+
+protected:
+
+    /// @brief protected constructor
+    ///
+    /// This constructor is protected to prevent anyone from instantiating
+    /// Pool class directly. Instances of Pool4 and Pool6 should be created
+    /// instead.
+    Pool(const isc::asiolink::IOAddress& first,
+         const isc::asiolink::IOAddress& last);
+
+    /// @brief returns the next unique Pool-ID
+    ///
+    /// @return the next unique Pool-ID
+    static uint32_t getNextID() {
+        static uint32_t id = 0;
+        return (id++);
+    }
+
+    /// @brief pool-id
+    ///
+    /// This ID is used to identify this specific pool.
+    uint32_t id_;
+
+    /// @brief The first address in a pool
+    isc::asiolink::IOAddress first_;
+
+    /// @brief The last address in a pool
+    isc::asiolink::IOAddress last_;
+
+    /// @brief Comments field
+    ///
+    /// @todo: This field is currently not used.
+    std::string comments_;
+};
+
+/// @brief Pool information for IPv6 addresses and prefixes
+///
+/// It holds information about pool6, i.e. a range of IPv6 address space that
+/// is configured for DHCP allocation.
+class Pool6 : public Pool {
+public:
+
+    /// @brief specifies Pool type
+    ///
+    /// Currently there are 3 pool types defined in DHCPv6:
+    /// - Non-temporary addresses (conveyed in IA_NA)
+    /// - Temporary addresses (conveyed in IA_TA)
+    /// - Delegated Prefixes (conveyed in IA_PD)
+    /// There is a new one being worked on (IA_PA, see draft-ietf-dhc-host-gen-id), but
+    /// support for it is not planned for now.
+    typedef enum {
+        TYPE_IA,
+        TYPE_TA,
+        TYPE_PD
+    }  Pool6Type;
+
+    /// @brief the constructor for Pool6 "min-max" style definition
+    ///
+    /// @param first the first address in a pool
+    /// @param last the last address in a pool
+    Pool6(Pool6Type type, const isc::asiolink::IOAddress& first,
+          const isc::asiolink::IOAddress& last);
+
+    /// @brief the constructor for Pool6 "prefix/len" style definition
+    ///
+    /// @param prefix specifies prefix of the pool
+    /// @param prefix_len specifies length of the prefix of the pool
+    Pool6(Pool6Type type, const isc::asiolink::IOAddress& prefix,
+          uint8_t prefix_len);
+
+    /// @brief returns pool type
+    ///
+    /// @return pool type
+    Pool6Type getType() const {
+        return (type_);
+    }
+
+private:
+    /// @brief defines a pool type
+    Pool6Type type_;
+
+    /// @brief prefix length
+    /// used by TYPE_PD only (zeroed for other types)
+    uint8_t prefix_len_;
+};
+
+/// @brief a pointer an IPv6 Pool
+typedef boost::shared_ptr<Pool6> Pool6Ptr;
+
+/// @brief a container for IPv6 Pools
+typedef std::vector<Pool6Ptr> Pool6Collection;
+
+} // end of isc::dhcp namespace
+} // end of isc namespace
+
+
+#endif // POOL_H

+ 91 - 0
src/lib/dhcp/subnet.cc

@@ -0,0 +1,91 @@
+// Copyright (C) 2012 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 <dhcp/addr_utilities.h>
+#include <asiolink/io_address.h>
+#include <dhcp/subnet.h>
+#include <dhcp/pool.h>
+
+using namespace isc::asiolink;
+
+namespace isc {
+namespace dhcp {
+
+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);
+    }
+}
+
+bool Subnet::inRange(const isc::asiolink::IOAddress& addr) const {
+    IOAddress first = firstAddrInPrefix(prefix_, prefix_len_);
+    IOAddress last = lastAddrInPrefix(prefix_, prefix_len_);
+
+    return ((first <= addr) && (addr <= last));
+}
+
+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, "Non IPv6 prefix " << prefix.toText()
+                  << " specified in subnet6");
+    }
+}
+
+void Subnet6::addPool6(const Pool6Ptr& pool) {
+    IOAddress first_addr = pool->getFirstAddress();
+    IOAddress last_addr = pool->getLastAddress();
+
+    if (!inRange(first_addr) || !inRange(last_addr)) {
+        isc_throw(BadValue, "Pool6 (" << first_addr.toText() << "-" << last_addr.toText()
+                  << " does not belong in this (" << prefix_ << "/" << prefix_len_
+                  << ") subnet6");
+    }
+
+    /// @todo: Check that pools do not overlap
+
+    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) {
+
+        // if we won't find anything better, then let's just use the first pool
+        if (!candidate) {
+            candidate = *pool;
+        }
+
+        // if the client provided a pool and there's a pool that hint is valid in,
+        // then let's use that pool
+        if ((*pool)->inRange(hint)) {
+            return (*pool);
+        }
+    }
+    return (candidate);
+}
+
+} // end of isc::dhcp namespace
+} // end of isc namespace

+ 161 - 0
src/lib/dhcp/subnet.h

@@ -0,0 +1,161 @@
+// Copyright (C) 2012 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 SUBNET_H
+#define SUBNET_H
+
+#include <boost/shared_ptr.hpp>
+#include <asiolink/io_address.h>
+#include <dhcp/pool.h>
+#include <dhcp/triplet.h>
+
+namespace isc {
+namespace dhcp {
+
+/// @brief a base class for Subnet4 and Subnet6
+///
+/// This class presents a common base for IPv4 and IPv6 subnets.
+/// In a physical sense, a subnet defines a single network link with all devices
+/// attached to it. In most cases all devices attached to a single link can
+/// share the same parameters. Therefore Subnet holds several values that are
+/// typically shared by all hosts: renew timer (T1), rebind timer (T2) and
+/// leased addresses lifetime (valid-lifetime).
+///
+/// @todo: Implement support for options here
+class Subnet {
+public:
+    /// @brief checks if specified address is in range
+    bool inRange(const isc::asiolink::IOAddress& addr) const;
+
+    /// @brief return valid-lifetime for addresses in that prefix
+    Triplet<uint32_t> getValid() const {
+        return (valid_);
+    }
+
+    /// @brief returns T1 (renew timer), expressed in seconds
+    Triplet<uint32_t> getT1() const {
+        return (t1_);
+    }
+
+    /// @brief returns T2 (rebind timer), expressed in seconds
+    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,
+           const Triplet<uint32_t>& t1,
+           const Triplet<uint32_t>& t2,
+           const Triplet<uint32_t>& valid_lifetime);
+
+    /// @brief returns the next unique Subnet-ID
+    ///
+    /// @return the next unique Subnet-ID
+    static uint32_t getNextID() {
+        static uint32_t id = 0;
+        return (id++);
+    }
+
+    /// @brief subnet-id
+    ///
+    /// Subnet-id is a unique value that can be used to find or identify
+    /// a Subnet4 or Subnet6.
+    uint32_t id_;
+
+    /// @brief a prefix of the subnet
+    isc::asiolink::IOAddress prefix_;
+
+    /// @brief a prefix length of the subnet
+    uint8_t prefix_len_;
+
+    /// @brief a tripet (min/default/max) holding allowed renew timer values
+    Triplet<uint32_t> t1_;
+
+    /// @brief a tripet (min/default/max) holding allowed rebind timer values
+    Triplet<uint32_t> t2_;
+
+    /// @brief a tripet (min/default/max) holding allowed valid lifetime values
+    Triplet<uint32_t> valid_;
+};
+
+/// @brief A configuration holder for IPv6 subnet.
+///
+/// This class represents an IPv6 subnet.
+class Subnet6 : public Subnet {
+public:
+
+    /// @brief Constructor with all parameters
+    ///
+    /// @param prefix Subnet6 prefix
+    /// @param length prefix length
+    /// @param t1 renewal timer (in seconds)
+    /// @param t2 rebind timer (in seconds)
+    /// @param preferred_lifetime preferred lifetime of leases (in seconds)
+    /// @param valid_lifetime preferred lifetime of leases (in seconds)
+    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);
+
+    /// @brief Returns preverred lifetime (in seconds)
+    ///
+    /// @return a triplet with preferred lifetime
+    Triplet<uint32_t> getPreferred() const {
+        return (preferred_);
+    }
+
+    /// @brief Returns a pool that specified address belongs to
+    ///
+    /// @param hint address that the returned pool should cover (optional)
+    /// @return Pointer to found pool6 (or NULL)
+    Pool6Ptr getPool6(const isc::asiolink::IOAddress& hint =
+                      isc::asiolink::IOAddress("::"));
+
+    /// @brief Adds a new pool.
+    /// @param pool pool to be added
+    void addPool6(const Pool6Ptr& pool);
+
+    /// @brief returns all pools
+    ///
+    /// The reference is only valid as long as the object that
+    /// returned it.
+    ///
+    /// @return a collection of all pools
+    const Pool6Collection& getPools() const {
+        return pools_;
+    }
+
+protected:
+    /// @brief collection of pools in that list
+    Pool6Collection pools_;
+
+    /// @brief a triplet with preferred lifetime (in seconds)
+    Triplet<uint32_t> preferred_;
+};
+
+/// @brief A pointer to a Subnet6 object
+typedef boost::shared_ptr<Subnet6> Subnet6Ptr;
+
+/// @brief A collection of Subnet6 objects
+typedef std::vector<Subnet6Ptr> Subnet6Collection;
+
+} // end of isc::dhcp namespace
+} // end of isc namespace
+
+#endif // SUBNET_T

+ 108 - 0
src/lib/dhcp/triplet.h

@@ -0,0 +1,108 @@
+// Copyright (C) 2012 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.
+
+namespace isc {
+namespace dhcp {
+
+/// @brief this template specifies a parameter value
+///
+/// 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 base type to Triple conversion
+    ///
+    /// Typically: uint32_t to Triplet assignment. It is very convenient
+    /// to be able to simply write Triplet<uint32_t> x = 7;
+    Triplet<T> operator=(T other) {
+        min_ = other;
+        default_ = other;
+        max_ = other;
+        return *this;
+    }
+
+    /// @brief triplet to base type conversion
+    ///
+    /// Typically: Triplet to uint32_t assignment. It is very convenient
+    /// to be able to simply write uint32_t z = x; (where x is a Triplet)
+    operator T() const {
+        return (default_);
+    }
+
+    /// @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) {
+    }
+
+    /// @brief sets the default value and thresholds
+    ///
+    /// @throw BadValue if min <= def <= max rule is violated
+    Triplet(T min, T def, T max)
+        :min_(min), default_(def), max_(max) {
+        if ( (min_ > def) || (def > max_) ) {
+            isc_throw(BadValue, "Invalid triplet values.");
+        }
+    }
+
+    /// @brief returns a minimum allowed value
+    T getMin() const { return min_;}
+
+    /// @brief returns the default value
+    T get() const { return default_;}
+
+    /// @brief returns value with a hint
+    ///
+    /// DHCP protocol treats any values sent by a client as hints.
+    /// This is a method that implements that. We can assign any value
+    /// from configured range that client asks.
+    T get(T hint) const {
+        if (hint <= min_) {
+            return (min_);
+        }
+
+        if (hint >= max_) {
+            return (max_);
+        }
+
+        return (hint);
+    }
+
+    /// @brief returns a maximum allowed value
+    T getMax() const { return max_; }
+
+protected:
+
+    /// @brief the minimum value
+    T min_;
+
+    /// @brief the default value
+    T default_;
+
+    /// @brief the maximum value
+    T max_;
+};
+
+
+} // namespace isc::dhcp
+} // namespace isc