Commit 3690baaf authored by Tomek Mrugalski's avatar Tomek Mrugalski 🛰
Browse files

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

parent 704ca46a
......@@ -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)
......
......@@ -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&
......
......@@ -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
///
......
// 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
// 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.