From: Tomek Mrugalski Date: Fri, 21 Sep 2012 17:01:14 +0000 (+0200) Subject: [2238] Pool, Subnet and Triplet moved to separate files. X-Git-Tag: trac2402_base~5^2~17^2~1 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=3690baaf0660af752b00a370fadcd60859c50ca4;p=thirdparty%2Fkea.git [2238] Pool, Subnet and Triplet moved to separate files. --- diff --git a/src/lib/dhcp/Makefile.am b/src/lib/dhcp/Makefile.am index a45884858b..4c22b3596c 100644 --- a/src/lib/dhcp/Makefile.am +++ b/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) diff --git a/src/lib/dhcp/cfgmgr.cc b/src/lib/dhcp/cfgmgr.cc index ff55a90ccf..15e3ad97d6 100644 --- a/src/lib/dhcp/cfgmgr.cc +++ b/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 #include #include @@ -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& t1, - const Triplet& t2, - const Triplet& 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& t1, - const Triplet& t2, - const Triplet& preferred_lifetime, - const Triplet& 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& diff --git a/src/lib/dhcp/cfgmgr.h b/src/lib/dhcp/cfgmgr.h index 48cb847fe2..5b73f2b966 100644 --- a/src/lib/dhcp/cfgmgr.h +++ b/src/lib/dhcp/cfgmgr.h @@ -23,360 +23,12 @@ #include #include #include +#include +#include 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 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 x = 7; - Triplet 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 Pool6Ptr; - -/// @brief a container for IPv6 Pools -typedef std::vector 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 getValid() const { - return (valid_); - } - - /// @brief returns T1 (renew timer), expressed in seconds - Triplet getT1() const { - return (t1_); - } - - /// @brief returns T2 (rebind timer), expressed in seconds - Triplet 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& t1, - const Triplet& t2, - const Triplet& 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 t1_; - - /// @brief a tripet (min/default/max) holding allowed rebind timer values - Triplet t2_; - - /// @brief a tripet (min/default/max) holding allowed valid lifetime values - Triplet 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& t1, - const Triplet& t2, - const Triplet& preferred_lifetime, - const Triplet& valid_lifetime); - - /// @brief Returns preverred lifetime (in seconds) - /// - /// @return a triplet with preferred lifetime - Triplet 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 preferred_; -}; - -/// @brief A pointer to a Subnet6 object -typedef boost::shared_ptr Subnet6Ptr; - -/// @brief A collection of Subnet6 objects -typedef std::vector Subnet6Collection; /// @brief Configuration Manager /// diff --git a/src/lib/dhcp/pool.cc b/src/lib/dhcp/pool.cc new file mode 100644 index 0000000000..da8a2e3389 --- /dev/null +++ b/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 +#include +#include + +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 diff --git a/src/lib/dhcp/pool.h b/src/lib/dhcp/pool.h new file mode 100644 index 0000000000..8f6fd8675f --- /dev/null +++ b/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 +#include +#include + +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 Pool6Ptr; + +/// @brief a container for IPv6 Pools +typedef std::vector Pool6Collection; + +} // end of isc::dhcp namespace +} // end of isc namespace + + +#endif // POOL_H diff --git a/src/lib/dhcp/subnet.cc b/src/lib/dhcp/subnet.cc new file mode 100644 index 0000000000..a999295690 --- /dev/null +++ b/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 +#include +#include +#include + +using namespace isc::asiolink; + +namespace isc { +namespace dhcp { + +Subnet::Subnet(const isc::asiolink::IOAddress& prefix, uint8_t len, + const Triplet& t1, + const Triplet& t2, + const Triplet& 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& t1, + const Triplet& t2, + const Triplet& preferred_lifetime, + const Triplet& 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 diff --git a/src/lib/dhcp/subnet.h b/src/lib/dhcp/subnet.h new file mode 100644 index 0000000000..aa59010ee6 --- /dev/null +++ b/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 +#include +#include +#include + +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 getValid() const { + return (valid_); + } + + /// @brief returns T1 (renew timer), expressed in seconds + Triplet getT1() const { + return (t1_); + } + + /// @brief returns T2 (rebind timer), expressed in seconds + Triplet 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& t1, + const Triplet& t2, + const Triplet& 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 t1_; + + /// @brief a tripet (min/default/max) holding allowed rebind timer values + Triplet t2_; + + /// @brief a tripet (min/default/max) holding allowed valid lifetime values + Triplet 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& t1, + const Triplet& t2, + const Triplet& preferred_lifetime, + const Triplet& valid_lifetime); + + /// @brief Returns preverred lifetime (in seconds) + /// + /// @return a triplet with preferred lifetime + Triplet 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 preferred_; +}; + +/// @brief A pointer to a Subnet6 object +typedef boost::shared_ptr Subnet6Ptr; + +/// @brief A collection of Subnet6 objects +typedef std::vector Subnet6Collection; + +} // end of isc::dhcp namespace +} // end of isc namespace + +#endif // SUBNET_T diff --git a/src/lib/dhcp/triplet.h b/src/lib/dhcp/triplet.h new file mode 100644 index 0000000000..549698babd --- /dev/null +++ b/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 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 x = 7; + Triplet 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