BIND 10 master, updated. 4784ca566b009035404a5abf1759c2eedf5a7515 [master] Merge branch 'trac2140' (Abstract API for DHCP database)
BIND 10 source code commits
bind10-changes at lists.isc.org
Thu Oct 11 12:16:19 UTC 2012
The branch, master has been updated
via 4784ca566b009035404a5abf1759c2eedf5a7515 (commit)
via df196f7609757253c4f2f918cd91012bb3af1163 (commit)
via a1983f43686919fae5dfb05ad8e6da07e5534111 (commit)
via 56dd56426342f9fa3d63c436f35ba86208512ee0 (commit)
via 08d6f75709a7669481b92fc0b2e4176174bc0f48 (commit)
via 0b7e9646307a6e58d3e1df60c68cbac5dbcbfecb (commit)
via 01eb4277b933cb0537204d98b9200550ee3eb641 (commit)
via 5ff43d80fb8eaae5ac2621a5a754cf94204149de (commit)
via 2c7936f05e6e2055016cdf7f4c915a80f465cde5 (commit)
via a49d8187d7b89c1f40b520b4af324096eb69fa5d (commit)
from 5fadea676fc73e068977173bb62b58d04fedf52c (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commit 4784ca566b009035404a5abf1759c2eedf5a7515
Merge: 5fadea6 df196f7
Author: Tomek Mrugalski <tomasz at isc.org>
Date: Thu Oct 11 14:15:10 2012 +0200
[master] Merge branch 'trac2140' (Abstract API for DHCP database)
Conflicts:
ChangeLog
src/lib/dhcp/tests/Makefile.am
-----------------------------------------------------------------------
Summary of changes:
ChangeLog | 6 +
src/lib/dhcp/Makefile.am | 2 +
src/lib/dhcp/duid.cc | 90 ++++++
src/lib/dhcp/duid.h | 98 ++++++
src/lib/dhcp/lease_mgr.cc | 65 ++++
src/lib/dhcp/lease_mgr.h | 480 ++++++++++++++++++++++++++++++
src/lib/dhcp/tests/Makefile.am | 2 +
src/lib/dhcp/tests/duid_unittest.cc | 169 +++++++++++
src/lib/dhcp/tests/lease_mgr_unittest.cc | 296 ++++++++++++++++++
9 files changed, 1208 insertions(+)
create mode 100644 src/lib/dhcp/duid.cc
create mode 100644 src/lib/dhcp/duid.h
create mode 100644 src/lib/dhcp/lease_mgr.cc
create mode 100644 src/lib/dhcp/lease_mgr.h
create mode 100644 src/lib/dhcp/tests/duid_unittest.cc
create mode 100644 src/lib/dhcp/tests/lease_mgr_unittest.cc
-----------------------------------------------------------------------
diff --git a/ChangeLog b/ChangeLog
index 1ee100d..8a81718 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,9 @@
+490. [func] tomek
+ libdhcp++: An abstract API for lease database has been
+ implemented. It offers a common interface to all concrete
+ database backends.
+ (Trac #2140, git df196f7609757253c4f2f918cd91012bb3af1163)
+
489. [func] muks
The isc::dns::RRsetList class has been removed. It was now unused
inside the BIND 10 codebase, and the interface was considered
diff --git a/src/lib/dhcp/Makefile.am b/src/lib/dhcp/Makefile.am
index 4c22b35..6585a38 100644
--- a/src/lib/dhcp/Makefile.am
+++ b/src/lib/dhcp/Makefile.am
@@ -16,6 +16,7 @@ CLEANFILES = *.gcno *.gcda
lib_LTLIBRARIES = libb10-dhcp++.la libb10-dhcpsrv.la
libb10_dhcp___la_SOURCES =
libb10_dhcp___la_SOURCES += libdhcp++.cc libdhcp++.h
+libb10_dhcp___la_SOURCES += lease_mgr.cc lease_mgr.h
libb10_dhcp___la_SOURCES += iface_mgr.cc iface_mgr.h
libb10_dhcp___la_SOURCES += iface_mgr_linux.cc
libb10_dhcp___la_SOURCES += iface_mgr_bsd.cc
@@ -28,6 +29,7 @@ libb10_dhcp___la_SOURCES += option4_addrlst.cc option4_addrlst.h
libb10_dhcp___la_SOURCES += dhcp6.h dhcp4.h
libb10_dhcp___la_SOURCES += pkt6.cc pkt6.h
libb10_dhcp___la_SOURCES += pkt4.cc pkt4.h
+libb10_dhcp___la_SOURCES += duid.cc duid.h
libb10_dhcpsrv_la_SOURCES = cfgmgr.cc cfgmgr.h
libb10_dhcpsrv_la_SOURCES += pool.cc pool.h
diff --git a/src/lib/dhcp/duid.cc b/src/lib/dhcp/duid.cc
new file mode 100644
index 0000000..db7ba25
--- /dev/null
+++ b/src/lib/dhcp/duid.cc
@@ -0,0 +1,90 @@
+// 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 <vector>
+#include <exceptions/exceptions.h>
+#include <stdint.h>
+#include <util/io_utilities.h>
+#include <dhcp/duid.h>
+
+namespace isc {
+namespace dhcp {
+
+DUID::DUID(const std::vector<uint8_t>& duid) {
+ if (duid.size() > MAX_DUID_LEN) {
+ isc_throw(OutOfRange, "DUID too large");
+ } else {
+ duid_ = duid;
+ }
+}
+
+DUID::DUID(const uint8_t * data, size_t len) {
+ if (len > MAX_DUID_LEN) {
+ isc_throw(OutOfRange, "DUID too large");
+ }
+
+ duid_ = std::vector<uint8_t>(data, data + len);
+}
+
+const std::vector<uint8_t> DUID::getDuid() const {
+ return (duid_);
+}
+
+DUID::DUIDType DUID::getType() const {
+ if (duid_.size() < 2) {
+ return (DUID_UNKNOWN);
+ }
+ uint16_t type = (duid_[0] << 8) + duid_[1];
+ if (type < DUID_MAX) {
+ return (static_cast<DUID::DUIDType>(type));
+ } else {
+ return (DUID_UNKNOWN);
+ }
+}
+
+bool DUID::operator == (const DUID& other) const {
+ return (this->duid_ == other.duid_);
+}
+
+bool DUID::operator != (const DUID& other) const {
+ return (this->duid_ != other.duid_);
+}
+
+/// constructor based on vector<uint8_t>
+ClientId::ClientId(const std::vector<uint8_t>& clientid)
+ :DUID(clientid) {
+}
+
+/// constructor based on C-style data
+ClientId::ClientId(const uint8_t *clientid, size_t len)
+ :DUID(clientid, len) {
+}
+
+/// @brief returns a copy of client-id data
+const std::vector<uint8_t> ClientId::getClientId() const {
+ return (duid_);
+}
+
+// compares two client-ids
+bool ClientId::operator == (const ClientId& other) const {
+ return (this->duid_ == other.duid_);
+}
+
+// compares two client-ids
+bool ClientId::operator != (const ClientId& other) const {
+ return (this->duid_ != other.duid_);
+}
+
+}; // end of isc::dhcp namespace
+}; // end of isc namespace
diff --git a/src/lib/dhcp/duid.h b/src/lib/dhcp/duid.h
new file mode 100644
index 0000000..53257db
--- /dev/null
+++ b/src/lib/dhcp/duid.h
@@ -0,0 +1,98 @@
+// 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 <stdint.h>
+#include <unistd.h>
+#include <vector>
+#include <asiolink/io_address.h>
+
+
+namespace isc {
+namespace dhcp {
+
+/// @brief Holds DUID (DHCPv6 Unique Identifier)
+///
+/// This class holds DUID, that is used in client-id, server-id and
+/// several other options. It is used to identify DHCPv6 entity.
+class DUID {
+ public:
+ /// @brief maximum duid size
+ /// As defined in RFC3315, section 9.1
+ static const size_t MAX_DUID_LEN = 128;
+
+ /// @brief specifies DUID type
+ typedef enum {
+ DUID_UNKNOWN = 0, ///< invalid/unknown type
+ DUID_LLT = 1, ///< link-layer + time, see RFC3315, section 9.2
+ DUID_EN = 2, ///< enterprise-id, see RFC3315, section 9.3
+ DUID_LL = 3, ///< link-layer, see RFC3315, section 9.4
+ DUID_UUID = 4, ///< UUID, see RFC6355
+ DUID_MAX ///< not a real type, just maximum defined value + 1
+ } DUIDType;
+
+ /// @brief creates a DUID
+ DUID(const std::vector<uint8_t>& duid);
+
+ /// @brief creates a DUID
+ DUID(const uint8_t *duid, size_t len);
+
+ /// @brief returns a const reference to the actual DUID value
+ ///
+ /// Note: For safety reasons, this method returns a copy of data as
+ /// otherwise the reference would be only valid as long as the object that
+ /// returned it. In any case, this method should be used only sporadically.
+ /// If there are frequent uses, we must implement some other method
+ /// (e.g. storeSelf()) that will avoid data copying.
+ const std::vector<uint8_t> getDuid() const;
+
+ /// @brief returns DUID type
+ DUIDType getType() const;
+
+ // compares two DUIDs
+ bool operator == (const DUID& other) const;
+
+ // compares two DUIDs
+ bool operator != (const DUID& other) const;
+
+ protected:
+ /// the actual content of the DUID
+ std::vector<uint8_t> duid_;
+};
+
+/// @brief Holds Client identifier or client IPv4 address
+///
+/// This class is intended to be a generic IPv4 client identifier. It can hold
+/// a client-id
+class ClientId : DUID {
+ public:
+
+ /// constructor based on vector<uint8_t>
+ ClientId(const std::vector<uint8_t>& clientid);
+
+ /// constructor based on C-style data
+ ClientId(const uint8_t *clientid, size_t len);
+
+ /// @brief returns reference to the client-id data
+ ///
+ const std::vector<uint8_t> getClientId() const;
+
+ // compares two client-ids
+ bool operator == (const ClientId& other) const;
+
+ // compares two client-ids
+ bool operator != (const ClientId& other) const;
+};
+
+}; // end of isc::dhcp namespace
+}; // end of isc namespace
diff --git a/src/lib/dhcp/lease_mgr.cc b/src/lib/dhcp/lease_mgr.cc
new file mode 100644
index 0000000..927c328
--- /dev/null
+++ b/src/lib/dhcp/lease_mgr.cc
@@ -0,0 +1,65 @@
+// 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 <sstream>
+#include <iostream>
+#include <map>
+#include <iostream>
+#include <string>
+#include <sstream>
+#include <algorithm>
+#include <iterator>
+#include <exceptions/exceptions.h>
+#include <boost/foreach.hpp>
+#include <boost/algorithm/string.hpp>
+#include "lease_mgr.h"
+
+using namespace std;
+
+using namespace isc::dhcp;
+
+LeaseMgr::LeaseMgr(const std::string& dbconfig) {
+
+ if (dbconfig.length() == 0) {
+ return;
+ }
+
+ vector<string> tokens;
+
+ boost::split(tokens, dbconfig, boost::is_any_of("\t "));
+
+ BOOST_FOREACH(std::string token, tokens) {
+ size_t pos = token.find("=");
+ if (pos != string::npos) {
+ string name = token.substr(0, pos);
+ string value = token.substr(pos + 1, -1);
+ parameters_.insert(pair<string,string>(name, value));
+ } else {
+ isc_throw(InvalidParameter, "Cannot parse " << token
+ << ", expected format is name=value");
+ }
+
+ }
+}
+
+std::string LeaseMgr::getParameter(const std::string& name) const {
+ map<string, string>::const_iterator param = parameters_.find(name);
+ if (param == parameters_.end()) {
+ isc_throw(BadValue, "Parameter not found");
+ }
+ return (param->second);
+}
+
+LeaseMgr::~LeaseMgr() {
+}
diff --git a/src/lib/dhcp/lease_mgr.h b/src/lib/dhcp/lease_mgr.h
new file mode 100644
index 0000000..4b7a1af
--- /dev/null
+++ b/src/lib/dhcp/lease_mgr.h
@@ -0,0 +1,480 @@
+// 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 <string>
+#include <fstream>
+#include <vector>
+#include <map>
+#include <asiolink/io_address.h>
+#include <boost/shared_ptr.hpp>
+#include <dhcp/option.h>
+#include <dhcp/duid.h>
+
+/// @file dhcp/lease_mgr.h
+/// @brief An abstract API for lease database
+///
+/// This file contains declarations of Lease4, Lease6 and LeaseMgr classes.
+/// They are essential components of the interface to any database backend.
+/// Each concrete database backend (e.g. MySQL) will define a class derived
+/// from LeaseMgr class.
+///
+/// Failover considerations:
+/// There are no intermediate plans to implement DHCPv4 failover
+/// (draft-ietf-dhc-failover-12.txt). Currently (Oct. 2012) the DHCPv6 failover
+/// is being defined in DHC WG in IETF (draft-ietf-dhcpv6-failover-requirements,
+/// draft-ietf-dhcpv6-dailover-design), but the work is not advanced enough
+/// for implementation plans yet. v4 failover requires additional parameters
+/// to be kept with a lease. It is likely that v6 failover will require similar
+/// fields. Such implementation will require database schema extension.
+/// We have designed a way to expand/upgrade schemas during upgrades: a database
+/// schema is versioned and sanity checks about required version will be done
+/// upon start and/or upgrade. With this mechanism in place, we can add new
+/// fields to the database. In particular we can use that capability to
+/// introduce failover related fields.
+///
+/// However, there is another approach that can be reliably used to provide
+/// failover, even without the actual failover protocol implemented. As the
+/// first backend will use MySQL, we will be able to use Multi-Master capability
+/// offered by MySQL and use two separatate Kea instances connecting to the
+/// same database.
+///
+/// Nevertheless, we hope to have failover protocol eventually implemented in
+/// the Kea.
+
+namespace isc {
+namespace dhcp {
+
+/// @brief specifies unique subnet identifier
+/// @todo: Move this to subnet.h once ticket #2237 is merged
+typedef uint32_t SubnetID;
+
+/// @brief Structure that holds a lease for IPv4 address
+///
+/// For performance reasons it is a simple structure, not a class. If we chose
+/// make it a class, all fields would have to made private and getters/setters
+/// would be required. As this is a critical part of the code that will be used
+/// extensively, direct access is warranted.
+struct Lease4 {
+ /// IPv4 address
+ isc::asiolink::IOAddress addr_;
+
+ /// @brief Address extension
+ ///
+ /// It is envisaged that in some cases IPv4 address will be accompanied with some
+ /// additional data. One example of such use are Address + Port solutions (or
+ /// Port-restricted Addresses), where several clients may get the same address, but
+ /// different port ranges. This feature is not expected to be widely used.
+ /// Under normal circumstances, the value should be 0.
+ uint32_t ext_;
+
+ /// @brief hardware address
+ std::vector<uint8_t> hwaddr_;
+
+ /// @brief client identifier
+ boost::shared_ptr<ClientId> client_id_;
+
+ /// @brief renewal timer
+ ///
+ /// Specifies renewal time. Although technically it is a property of IA container,
+ /// not the address itself, since our data model does not define separate IA
+ /// entity, we are keeping it in the lease. In case of multiple addresses/prefixes
+ /// for the same IA, each must have consistent T1 and T2 values. Specified in
+ /// seconds since cltt.
+ uint32_t t1_;
+
+ /// @brief rebinding timer
+ ///
+ /// Specifies rebinding time. Although technically it is a property of IA container,
+ /// not the address itself, since our data model does not define separate IA
+ /// entity, we are keeping it in the lease. In case of multiple addresses/prefixes
+ /// for the same IA, each must have consistent T1 and T2 values. Specified in
+ /// seconds since cltt.
+ uint32_t t2_;
+
+ /// @brief valid lifetime
+ ///
+ /// Expressed as number of seconds since cltt
+ uint32_t valid_lft_;
+
+ /// @brief client last transmission time
+ ///
+ /// Specifies a timestamp, when last transmission from a client was received.
+ time_t cltt_;
+
+ /// @brief Subnet identifier
+ ///
+ /// Specifies subnet-id of the subnet that the lease belongs to
+ SubnetID subnet_id_;
+
+ /// @brief Is this a fixed lease?
+ ///
+ /// Fixed leases are kept after they are released/expired.
+ bool fixed_;
+
+ /// @brief client hostname
+ ///
+ /// This field may be empty
+ std::string hostname_;
+
+ /// @brief did we update AAAA record for this lease?
+ bool fqdn_fwd_;
+
+ /// @brief did we update PTR record for this lease?
+ bool fqdn_rev_;
+
+ /// @brief Lease comments.
+ ///
+ /// Currently not used. It may be used for keeping comments made by the
+ /// system administrator.
+ std::string comments_;
+
+ /// @todo: Add DHCPv4 failover related fields here
+};
+
+/// @brief Pointer to a Lease4 structure.
+typedef boost::shared_ptr<Lease4> Lease4Ptr;
+
+/// @brief A collection of IPv4 leases.
+typedef std::vector< boost::shared_ptr<Lease4Ptr> > Lease4Collection;
+
+/// @brief Structure that holds a lease for IPv6 address and/or prefix
+///
+/// For performance reasons it is a simple structure, not a class. Had we chose to
+/// make it a class, all fields would have to be made private and getters/setters
+/// would be required. As this is a critical part of the code that will be used
+/// extensively, direct access rather than through getters/setters is warranted.
+struct Lease6 {
+ typedef enum {
+ LEASE_IA_NA, /// the lease contains non-temporary IPv6 address
+ LEASE_IA_TA, /// the lease contains temporary IPv6 address
+ LEASE_IA_PD /// the lease contains IPv6 prefix (for prefix delegation)
+ } LeaseType;
+
+ /// @brief specifies lease type (normal addr, temporary addr, prefix)
+ LeaseType type_;
+
+ /// IPv6 address
+ isc::asiolink::IOAddress addr_;
+
+ /// IPv6 prefix length (used only for PD)
+ uint8_t prefixlen_;
+
+ /// @brief IAID
+ ///
+ /// Identity Association IDentifier. DHCPv6 stores all addresses and prefixes
+ /// in IA containers (IA_NA, IA_TA, IA_PD). Most containers may appear more
+ /// than once in a message. To differentiate between them, IAID field is present
+ uint32_t iaid_;
+
+ /// @brief hardware address
+ ///
+ /// This field is not really used and is optional at best. The concept of identifying
+ /// clients by their hardware address was replaced in DHCPv6 by DUID concept. Each
+ /// client has its own unique DUID (DHCP Unique IDentifier). Furthermore, client's
+ /// HW address is not always available, because client may be behind a relay (relay
+ /// stores only link-local address).
+ std::vector<uint8_t> hwaddr_;
+
+ /// @brief client identifier
+ boost::shared_ptr<DUID> duid_;
+
+ /// @brief preferred lifetime
+ ///
+ /// This parameter specifies preferred lifetime since the lease was assigned/renewed
+ /// (cltt), expressed in seconds.
+ uint32_t preferred_lft_;
+
+ /// @brief valid lifetime
+ ///
+ /// This parameter specified valid lifetime since the lease was assigned/renewed
+ /// (cltt), expressed in seconds.
+ uint32_t valid_lft_;
+
+ /// @brief T1 timer
+ ///
+ /// Specifies renewal time. Although technically it is a property of IA container,
+ /// not the address itself, since our data model does not define separate IA
+ /// entity, we are keeping it in the lease. In case of multiple addresses/prefixes
+ /// for the same IA, each must have consistent T1 and T2 values. Specified in
+ /// seconds since cltt.
+ uint32_t t1_;
+
+ /// @brief T2 timer
+ ///
+ /// Specifies rebinding time. Although technically it is a property of IA container,
+ /// not the address itself, since our data model does not define separate IA
+ /// entity, we are keeping it in the lease. In case of multiple addresses/prefixes
+ /// for the same IA, each must have consistent T1 and T2 values. Specified in
+ /// seconds since cltt.
+ uint32_t t2_;
+
+ /// @brief client last transmission time
+ ///
+ /// Specifies a timestamp, when last transmission from a client was received.
+ time_t cltt_;
+
+ /// @brief Subnet identifier
+ ///
+ /// Specifies subnet-id of the subnet that the lease belongs to
+ SubnetID subnet_id_;
+
+ /// @brief Is this a fixed lease?
+ ///
+ /// Fixed leases are kept after they are released/expired.
+ bool fixed_;
+
+ /// @brief client hostname
+ ///
+ /// This field may be empty
+ std::string hostname_;
+
+ /// @brief did we update AAAA record for this lease?
+ bool fqdn_fwd_;
+
+ /// @brief did we update PTR record for this lease?
+ bool fqdn_rev_;
+
+ /// @brief Lease comments
+ ///
+ /// This field is currently not used.
+ std::string comments_;
+
+ /// @todo: Add DHCPv6 failover related fields here
+};
+
+/// @brief Pointer to a Lease6 structure.
+typedef boost::shared_ptr<Lease6> Lease6Ptr;
+
+/// @brief Const pointer to a Lease6 structure.
+typedef boost::shared_ptr<const Lease6> ConstLease6Ptr;
+
+/// @brief A collection of IPv6 leases.
+typedef std::vector< boost::shared_ptr<Lease6Ptr> > Lease6Collection;
+
+/// @brief Abstract Lease Manager
+///
+/// This is an abstract API for lease database backends. It provides unified
+/// interface to all backends. As this is an abstract class, it should not
+/// be used directly, but rather specialized derived class should be used
+/// instead.
+class LeaseMgr {
+public:
+
+ /// Client Hardware address
+ typedef std::vector<uint8_t> HWAddr;
+
+ /// @brief The sole lease manager constructor
+ ///
+ /// dbconfig is a generic way of passing parameters. Parameters
+ /// are passed in the "name=value" format, separated by spaces.
+ /// Values may be enclosed in double quotes, if needed.
+ ///
+ /// @param dbconfig database configuration
+ LeaseMgr(const std::string& dbconfig);
+
+ /// @brief Destructor (closes file)
+ virtual ~LeaseMgr();
+
+ /// @brief Adds an IPv4 lease.
+ ///
+ /// @param lease lease to be added
+ virtual bool addLease(Lease4Ptr lease) = 0;
+
+ /// @brief Adds an IPv6 lease.
+ ///
+ /// @param lease lease to be added
+ virtual bool addLease(Lease6Ptr lease) = 0;
+
+ /// @brief Returns existing IPv4 lease for specified IPv4 address and subnet_id
+ ///
+ /// This method is used to get a lease for specific subnet_id. There can be
+ /// at most one lease for any given subnet, so this method returns a single
+ /// pointer.
+ ///
+ /// @param addr address of the searched lease
+ /// @param subnet_id ID of the subnet the lease must belong to
+ ///
+ /// @return smart pointer to the lease (or NULL if a lease is not found)
+ virtual Lease4Ptr getLease4(isc::asiolink::IOAddress addr,
+ SubnetID subnet_id) const = 0;
+
+ /// @brief Returns an IPv4 lease for specified IPv4 address
+ ///
+ /// This method return a lease that is associated with a given address.
+ /// For other query types (by hardware addr, by client-id) there can be
+ /// several leases in different subnets (e.g. for mobile clients that
+ /// got address in different subnets). However, for a single address
+ /// there can be only one lease, so this method returns a pointer to
+ /// a single lease, not a container of leases.
+ ///
+ /// @param addr address of the searched lease
+ /// @param subnet_id ID of the subnet the lease must belong to
+ ///
+ /// @return smart pointer to the lease (or NULL if a lease is not found)
+ virtual Lease4Ptr getLease4(isc::asiolink::IOAddress addr) const = 0;
+
+ /// @brief Returns existing IPv4 leases for specified hardware address.
+ ///
+ /// Although in the usual case there will be only one lease, for mobile
+ /// clients or clients with multiple static/fixed/reserved leases there
+ /// can be more than one. Thus return type is a container, not a single
+ /// pointer.
+ ///
+ /// @param hwaddr hardware address of the client
+ ///
+ /// @return lease collection
+ virtual Lease4Collection getLease4(const HWAddr& hwaddr) const = 0;
+
+ /// @brief Returns existing IPv4 leases for specified hardware address
+ /// and a subnet
+ ///
+ /// There can be at most one lease for a given HW address in a single
+ /// pool, so this method with either return a single lease or NULL.
+ ///
+ /// @param hwaddr hardware address of the client
+ /// @param subnet_id identifier of the subnet that lease must belong to
+ ///
+ /// @return a pointer to the lease (or NULL if a lease is not found)
+ virtual Lease4Ptr getLease4(const HWAddr& hwaddr,
+ SubnetID subnet_id) const = 0;
+
+ /// @brief Returns existing IPv4 lease for specified client-id
+ ///
+ /// Although in the usual case there will be only one lease, for mobile
+ /// clients or clients with multiple static/fixed/reserved leases there
+ /// can be more than one. Thus return type is a container, not a single
+ /// pointer.
+ ///
+ /// @param clientid client identifier
+ ///
+ /// @return lease collection
+ virtual Lease4Collection getLease4(const ClientId& clientid) const = 0;
+
+ /// @brief Returns existing IPv4 lease for specified client-id
+ ///
+ /// There can be at most one lease for a given HW address in a single
+ /// pool, so this method with either return a single lease or NULL.
+ ///
+ /// @param clientid client identifier
+ /// @param subnet_id identifier of the subnet that lease must belong to
+ ///
+ /// @return a pointer to the lease (or NULL if a lease is not found)
+ virtual Lease4Ptr getLease4(const ClientId& clientid,
+ SubnetID subnet_id) const = 0;
+
+ /// @brief Returns existing IPv6 lease for a given IPv6 address.
+ ///
+ /// For a given address, we assume that there will be only one lease.
+ /// The assumtion here is that there will not be site or link-local
+ /// addresses used, so there is no way of having address duplication.
+ ///
+ /// @param addr address of the searched lease
+ ///
+ /// @return smart pointer to the lease (or NULL if a lease is not found)
+ virtual Lease6Ptr getLease6(isc::asiolink::IOAddress addr) const = 0;
+
+ /// @brief Returns existing IPv6 leases for a given DUID+IA combination
+ ///
+ /// Although in the usual case there will be only one lease, for mobile
+ /// clients or clients with multiple static/fixed/reserved leases there
+ /// can be more than one. Thus return type is a container, not a single
+ /// pointer.
+ ///
+ /// @param duid client DUID
+ /// @param iaid IA identifier
+ ///
+ /// @return smart pointer to the lease (or NULL if a lease is not found)
+ virtual Lease6Collection getLease6(const DUID& duid,
+ uint32_t iaid) const = 0;
+
+ /// @brief Returns existing IPv6 lease for a given DUID+IA combination
+ ///
+ /// @param duid client DUID
+ /// @param iaid IA identifier
+ /// @param subnet_id subnet id of the subnet the lease belongs to
+ ///
+ /// @return smart pointer to the lease (or NULL if a lease is not found)
+ virtual Lease6Ptr getLease6(const DUID& duid, uint32_t iaid,
+ SubnetID subnet_id) const = 0;
+
+ /// @brief Updates IPv4 lease.
+ ///
+ /// @param lease4 The lease to be updated.
+ ///
+ /// If no such lease is present, an exception will be thrown.
+ virtual void updateLease4(Lease4Ptr lease4) = 0;
+
+ /// @brief Updates IPv4 lease.
+ ///
+ /// @param lease4 The lease to be updated.
+ ///
+ /// If no such lease is present, an exception will be thrown.
+ virtual void updateLease6(Lease6Ptr lease6) = 0;
+
+ /// @brief Deletes a lease.
+ ///
+ /// @param addr IPv4 address of the lease to be deleted.
+ ///
+ /// @return true if deletion was successful, false if no such lease exists
+ virtual bool deleteLease4(uint32_t addr) = 0;
+
+ /// @brief Deletes a lease.
+ ///
+ /// @param addr IPv4 address of the lease to be deleted.
+ ///
+ /// @return true if deletion was successful, false if no such lease exists
+ virtual bool deleteLease6(isc::asiolink::IOAddress addr) = 0;
+
+ /// @brief Returns backend name.
+ ///
+ /// Each backend have specific name, e.g. "mysql" or "sqlite".
+ virtual std::string getName() const = 0;
+
+ /// @brief Returns description of the backend.
+ ///
+ /// This description may be multiline text that describes the backend.
+ virtual std::string getDescription() const = 0;
+
+ /// @brief Returns backend version.
+ ///
+ /// @todo: We will need to implement 3 version functions eventually:
+ /// A. abstract API version
+ /// B. backend version
+ /// C. database version (stored in the database scheme)
+ ///
+ /// and then check that:
+ /// B>=A and B=C (it is ok to have newer backend, as it should be backward
+ /// compatible)
+ /// Also if B>C, some database upgrade procedure may be triggered
+ virtual std::string getVersion() const = 0;
+
+ /// @todo: Add host management here
+ /// As host reservation is outside of scope for 2012, support for hosts
+ /// is currently postponed.
+
+protected:
+ /// @brief returns value of the parameter
+ std::string getParameter(const std::string& name) const;
+
+ /// @brief list of parameters passed in dbconfig
+ ///
+ /// That will be mostly used for storing database name, username,
+ /// password and other parameters required for DB access. It is not
+ /// intended to keep any DHCP-related parameters.
+ std::map<std::string, std::string> parameters_;
+};
+
+}; // end of isc::dhcp namespace
+
+}; // end of isc namespace
diff --git a/src/lib/dhcp/tests/Makefile.am b/src/lib/dhcp/tests/Makefile.am
index 9fd3492..a15d957 100644
--- a/src/lib/dhcp/tests/Makefile.am
+++ b/src/lib/dhcp/tests/Makefile.am
@@ -28,6 +28,7 @@ TESTS += libdhcp++_unittests libdhcpsrv_unittests
libdhcp___unittests_SOURCES = run_unittests.cc
libdhcp___unittests_SOURCES += libdhcp++_unittest.cc
libdhcp___unittests_SOURCES += iface_mgr_unittest.cc
+libdhcp___unittests_SOURCES += lease_mgr_unittest.cc
libdhcp___unittests_SOURCES += option6_iaaddr_unittest.cc
libdhcp___unittests_SOURCES += option6_ia_unittest.cc
libdhcp___unittests_SOURCES += option6_addrlst_unittest.cc
@@ -35,6 +36,7 @@ libdhcp___unittests_SOURCES += option4_addrlst_unittest.cc
libdhcp___unittests_SOURCES += option_unittest.cc
libdhcp___unittests_SOURCES += pkt6_unittest.cc
libdhcp___unittests_SOURCES += pkt4_unittest.cc
+libdhcp___unittests_SOURCES += duid_unittest.cc
libdhcp___unittests_CPPFLAGS = $(AM_CPPFLAGS) $(GTEST_INCLUDES) $(LOG4CPLUS_INCLUDES)
libdhcp___unittests_LDFLAGS = $(AM_LDFLAGS) $(GTEST_LDFLAGS)
diff --git a/src/lib/dhcp/tests/duid_unittest.cc b/src/lib/dhcp/tests/duid_unittest.cc
new file mode 100644
index 0000000..93f304c
--- /dev/null
+++ b/src/lib/dhcp/tests/duid_unittest.cc
@@ -0,0 +1,169 @@
+// Copyright (C) 2011 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 <config.h>
+#include <iostream>
+#include <sstream>
+#include <arpa/inet.h>
+#include <gtest/gtest.h>
+#include <exceptions/exceptions.h>
+#include <boost/scoped_ptr.hpp>
+#include <asiolink/io_address.h>
+#include <dhcp/duid.h>
+
+using namespace std;
+using namespace isc;
+using namespace isc::dhcp;
+using namespace isc::asiolink;
+
+// don't import the entire boost namespace. It will unexpectedly hide uint8_t
+// for some systems.
+using boost::scoped_ptr;
+
+namespace {
+
+// This test verifies if the constructors are working as expected
+// and process passed parameters.
+TEST(DuidTest, constructor) {
+
+ uint8_t data1[] = {0, 1, 2, 3, 4, 5, 6};
+
+ vector<uint8_t> data2(data1, data1 + sizeof(data1));
+
+ scoped_ptr<DUID> duid1(new DUID(data1, sizeof(data1)));
+ scoped_ptr<DUID> duid2(new DUID(data2));
+
+ vector<uint8_t> vecdata = duid1->getDuid();
+ EXPECT_EQ(data2, vecdata);
+ EXPECT_EQ(DUID::DUID_LLT, duid1->getType());
+
+ vecdata = duid2->getDuid();
+ EXPECT_EQ(data2, vecdata);
+
+ EXPECT_EQ(DUID::DUID_LLT, duid2->getType());
+}
+
+// This test verifies if DUID size restrictions are implemented
+// properly.
+TEST(DuidTest, size) {
+ const int MAX_DUID_SIZE = 128;
+ uint8_t data[MAX_DUID_SIZE + 1];
+ vector<uint8_t> data2;
+ for (uint8_t i = 0; i < MAX_DUID_SIZE + 1; ++i) {
+ data[i] = i;
+ if (i < MAX_DUID_SIZE)
+ data2.push_back(i);
+ }
+ ASSERT_EQ(data2.size(), MAX_DUID_SIZE);
+
+ scoped_ptr<DUID> duidmaxsize1(new DUID(data, MAX_DUID_SIZE));
+ scoped_ptr<DUID> duidmaxsize2(new DUID(data2));
+
+ EXPECT_THROW(
+ scoped_ptr<DUID> toolarge1(new DUID(data, MAX_DUID_SIZE + 1)),
+ OutOfRange);
+
+ // that's one too much
+ data2.push_back(128);
+
+ EXPECT_THROW(
+ scoped_ptr<DUID> toolarge2(new DUID(data2)),
+ OutOfRange);
+}
+
+// This test verifies if the implementation supports all defined
+// DUID types.
+TEST(DuidTest, getType) {
+ uint8_t llt[] = {0, 1, 2, 3, 4, 5, 6};
+ uint8_t en[] = {0, 2, 2, 3, 4, 5, 6};
+ uint8_t ll[] = {0, 3, 2, 3, 4, 5, 6};
+ uint8_t uuid[] = {0, 4, 2, 3, 4, 5, 6};
+ uint8_t invalid[] = {0,55, 2, 3, 4, 5, 6};
+
+ scoped_ptr<DUID> duid_llt(new DUID(llt, sizeof(llt)));
+ scoped_ptr<DUID> duid_en(new DUID(en, sizeof(en)));
+ scoped_ptr<DUID> duid_ll(new DUID(ll, sizeof(ll)));
+ scoped_ptr<DUID> duid_uuid(new DUID(uuid, sizeof(uuid)));
+ scoped_ptr<DUID> duid_invalid(new DUID(invalid, sizeof(invalid)));
+
+ EXPECT_EQ(DUID::DUID_LLT, duid_llt->getType());
+ EXPECT_EQ(DUID::DUID_EN, duid_en->getType());
+ EXPECT_EQ(DUID::DUID_LL, duid_ll->getType());
+ EXPECT_EQ(DUID::DUID_UUID, duid_uuid->getType());
+ EXPECT_EQ(DUID::DUID_UNKNOWN, duid_invalid->getType());
+}
+
+// This test checks if the comparison operators are sane.
+TEST(DuidTest, operators) {
+ uint8_t data1[] = {0, 1, 2, 3, 4, 5, 6};
+ uint8_t data2[] = {0, 1, 2, 3, 4};
+ uint8_t data3[] = {0, 1, 2, 3, 4, 5, 7}; // last digit different
+ uint8_t data4[] = {0, 1, 2, 3, 4, 5, 6}; // the same as 1
+
+ scoped_ptr<DUID> duid1(new DUID(data1, sizeof(data1)));
+ scoped_ptr<DUID> duid2(new DUID(data2, sizeof(data2)));
+ scoped_ptr<DUID> duid3(new DUID(data3, sizeof(data3)));
+ scoped_ptr<DUID> duid4(new DUID(data4, sizeof(data4)));
+
+ EXPECT_TRUE(*duid1 == *duid4);
+ EXPECT_FALSE(*duid1 == *duid2);
+ EXPECT_FALSE(*duid1 == *duid3);
+
+ EXPECT_FALSE(*duid1 != *duid4);
+ EXPECT_TRUE(*duid1 != *duid2);
+ EXPECT_TRUE(*duid1 != *duid3);
+}
+
+// This test verifies if the ClientId constructors are working properly
+// and passed parameters are used
+TEST(ClientIdTest, constructor) {
+ IOAddress addr2("192.0.2.1");
+ IOAddress addr3("2001:db8:1::1");
+
+ uint8_t data1[] = {0, 1, 2, 3, 4, 5, 6};
+ vector<uint8_t> data2(data1, data1 + sizeof(data1));
+
+ // checks for C-style construtor (uint8_t * + len)
+ scoped_ptr<ClientId> id1(new ClientId(data1, sizeof(data1)));
+ vector<uint8_t> vecdata = id1->getClientId();
+ EXPECT_EQ(data2, vecdata);
+
+ // checks for vector-based constructor
+ scoped_ptr<ClientId> id2(new ClientId(data2));
+ vecdata = id2->getClientId();
+ EXPECT_EQ(data2, vecdata);
+}
+
+// This test checks if the comparison operators are sane.
+TEST(ClientIdTest, operators) {
+ uint8_t data1[] = {0, 1, 2, 3, 4, 5, 6};
+ uint8_t data2[] = {0, 1, 2, 3, 4};
+ uint8_t data3[] = {0, 1, 2, 3, 4, 5, 7}; // last digit different
+ uint8_t data4[] = {0, 1, 2, 3, 4, 5, 6}; // the same as 1
+
+ scoped_ptr<ClientId> id1(new ClientId(data1, sizeof(data1)));
+ scoped_ptr<ClientId> id2(new ClientId(data2, sizeof(data2)));
+ scoped_ptr<ClientId> id3(new ClientId(data3, sizeof(data3)));
+ scoped_ptr<ClientId> id4(new ClientId(data4, sizeof(data4)));
+
+ EXPECT_TRUE(*id1 == *id4);
+ EXPECT_FALSE(*id1 == *id2);
+ EXPECT_FALSE(*id1 == *id3);
+
+ EXPECT_FALSE(*id1 != *id4);
+ EXPECT_TRUE(*id1 != *id2);
+ EXPECT_TRUE(*id1 != *id3);
+}
+
+} // end of anonymous namespace
diff --git a/src/lib/dhcp/tests/lease_mgr_unittest.cc b/src/lib/dhcp/tests/lease_mgr_unittest.cc
new file mode 100644
index 0000000..97659a1
--- /dev/null
+++ b/src/lib/dhcp/tests/lease_mgr_unittest.cc
@@ -0,0 +1,296 @@
+// Copyright (C) 2011-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 <config.h>
+#include <iostream>
+#include <sstream>
+#include <gtest/gtest.h>
+
+#include <asiolink/io_address.h>
+#include <dhcp/lease_mgr.h>
+
+using namespace std;
+using namespace isc;
+using namespace isc::asiolink;
+using namespace isc::dhcp;
+
+// This is a concrete implementation of a Lease database.
+// It does not do anything useful now, and is used for abstract LeaseMgr
+// class testing. It may later evolve into more useful backend if the
+// need arises. We can reuse code from memfile benchmark. See code in
+// tests/tools/dhcp-ubench/memfile_bench.{cc|h}
+class Memfile_LeaseMgr : public LeaseMgr {
+public:
+
+ /// @brief The sole lease manager constructor
+ ///
+ /// dbconfig is a generic way of passing parameters. Parameters
+ /// are passed in the "name=value" format, separated by spaces.
+ /// Values may be enclosed in double quotes, if needed.
+ ///
+ /// @param dbconfig database configuration
+ Memfile_LeaseMgr(const std::string& dbconfig);
+
+ /// @brief Destructor (closes file)
+ virtual ~Memfile_LeaseMgr();
+
+ /// @brief Adds an IPv4 lease.
+ ///
+ /// @param lease lease to be added
+ virtual bool addLease(Lease4Ptr lease);
+
+ /// @brief Adds an IPv6 lease.
+ ///
+ /// @param lease lease to be added
+ virtual bool addLease(Lease6Ptr lease);
+
+ /// @brief Returns existing IPv4 lease for specified IPv4 address.
+ ///
+ /// @param addr address of the searched lease
+ ///
+ /// @return a collection of leases
+ virtual Lease4Ptr getLease4(isc::asiolink::IOAddress addr) const;
+
+ /// @brief Returns existing IPv4 lease for specific address and subnet
+ /// @param addr address of the searched lease
+ /// @param subnet_id ID of the subnet the lease must belong to
+ ///
+ /// @return smart pointer to the lease (or NULL if a lease is not found)
+ virtual Lease4Ptr getLease4(isc::asiolink::IOAddress addr,
+ SubnetID subnet_id) const;
+
+ /// @brief Returns existing IPv4 leases for specified hardware address.
+ ///
+ /// Although in the usual case there will be only one lease, for mobile
+ /// clients or clients with multiple static/fixed/reserved leases there
+ /// can be more than one. Thus return type is a container, not a single
+ /// pointer.
+ ///
+ /// @param hwaddr hardware address of the client
+ ///
+ /// @return lease collection
+ virtual Lease4Collection getLease4(const HWAddr& hwaddr) const;
+
+ /// @brief Returns existing IPv4 leases for specified hardware address
+ /// and a subnet
+ ///
+ /// There can be at most one lease for a given HW address in a single
+ /// pool, so this method with either return a single lease or NULL.
+ ///
+ /// @param hwaddr hardware address of the client
+ /// @param subnet_id identifier of the subnet that lease must belong to
+ ///
+ /// @return a pointer to the lease (or NULL if a lease is not found)
+ virtual Lease4Ptr getLease4(const HWAddr& hwaddr,
+ SubnetID subnet_id) const;
+
+ /// @brief Returns existing IPv4 lease for specified client-id
+ ///
+ /// @param clientid client identifier
+ virtual Lease4Collection getLease4(const ClientId& clientid) const;
+
+ /// @brief Returns existing IPv4 lease for specified client-id
+ ///
+ /// There can be at most one lease for a given HW address in a single
+ /// pool, so this method with either return a single lease or NULL.
+ ///
+ /// @param clientid client identifier
+ /// @param subnet_id identifier of the subnet that lease must belong to
+ ///
+ /// @return a pointer to the lease (or NULL if a lease is not found)
+ virtual Lease4Ptr getLease4(const ClientId& clientid,
+ SubnetID subnet_id) const;
+
+ /// @brief Returns existing IPv6 lease for a given IPv6 address.
+ ///
+ /// @param addr address of the searched lease
+ ///
+ /// @return smart pointer to the lease (or NULL if a lease is not found)
+ Lease6Ptr getLease6(isc::asiolink::IOAddress addr) const;
+
+ /// @brief Returns existing IPv6 lease for a given DUID+IA combination
+ ///
+ /// @param duid client DUID
+ /// @param iaid IA identifier
+ ///
+ /// @return collection of IPv6 leases
+ Lease6Collection getLease6(const DUID& duid, uint32_t iaid) const;
+
+ /// @brief Returns existing IPv6 lease for a given DUID+IA combination
+ ///
+ /// @param duid client DUID
+ /// @param iaid IA identifier
+ /// @param subnet_id identifier of the subnet the lease must belong to
+ ///
+ /// @return smart pointer to the lease (or NULL if a lease is not found)
+ Lease6Ptr getLease6(const DUID& duid, uint32_t iaid, SubnetID subnet_id) const;
+
+ /// @brief Updates IPv4 lease.
+ ///
+ /// @param lease4 The lease to be updated.
+ ///
+ /// If no such lease is present, an exception will be thrown.
+ void updateLease4(Lease4Ptr lease4);
+
+ /// @brief Updates IPv4 lease.
+ ///
+ /// @param lease4 The lease to be updated.
+ ///
+ /// If no such lease is present, an exception will be thrown.
+ void updateLease6(Lease6Ptr lease6);
+
+ /// @brief Deletes a lease.
+ ///
+ /// @param addr IPv4 address of the lease to be deleted.
+ ///
+ /// @return true if deletion was successful, false if no such lease exists
+ bool deleteLease4(uint32_t addr);
+
+ /// @brief Deletes a lease.
+ ///
+ /// @param addr IPv4 address of the lease to be deleted.
+ ///
+ /// @return true if deletion was successful, false if no such lease exists
+ bool deleteLease6(isc::asiolink::IOAddress addr);
+
+ /// @brief Returns backend name.
+ ///
+ /// Each backend have specific name, e.g. "mysql" or "sqlite".
+ std::string getName() const { return "memfile"; }
+
+ /// @brief Returns description of the backend.
+ ///
+ /// This description may be multiline text that describes the backend.
+ std::string getDescription() const;
+
+ /// @brief Returns backend version.
+ std::string getVersion() const { return "test-version"; }
+
+ using LeaseMgr::getParameter;
+
+protected:
+
+
+};
+
+Memfile_LeaseMgr::Memfile_LeaseMgr(const std::string& dbconfig)
+ : LeaseMgr(dbconfig) {
+}
+
+Memfile_LeaseMgr::~Memfile_LeaseMgr() {
+}
+
+bool Memfile_LeaseMgr::addLease(boost::shared_ptr<isc::dhcp::Lease4>) {
+ return (false);
+}
+
+bool Memfile_LeaseMgr::addLease(boost::shared_ptr<isc::dhcp::Lease6>) {
+ return (false);
+}
+
+Lease4Ptr Memfile_LeaseMgr::getLease4(isc::asiolink::IOAddress) const {
+ return (Lease4Ptr());
+}
+
+Lease4Collection Memfile_LeaseMgr::getLease4(const HWAddr& ) const {
+ return (Lease4Collection());
+}
+
+Lease4Ptr Memfile_LeaseMgr::getLease4(isc::asiolink::IOAddress ,
+ SubnetID) const {
+ return (Lease4Ptr());
+}
+
+Lease4Ptr Memfile_LeaseMgr::getLease4(const HWAddr&,
+ SubnetID) const {
+ return (Lease4Ptr());
+}
+
+
+Lease4Ptr Memfile_LeaseMgr::getLease4(const ClientId&,
+ SubnetID) const {
+ return (Lease4Ptr());
+}
+
+Lease4Collection Memfile_LeaseMgr::getLease4(const ClientId& ) const {
+ return (Lease4Collection());
+}
+
+Lease6Ptr Memfile_LeaseMgr::getLease6(isc::asiolink::IOAddress) const {
+ return (Lease6Ptr());
+}
+
+Lease6Collection Memfile_LeaseMgr::getLease6(const DUID& , uint32_t ) const {
+ return (Lease6Collection());
+}
+
+Lease6Ptr Memfile_LeaseMgr::getLease6(const DUID&, uint32_t,
+ SubnetID) const {
+ return (Lease6Ptr());
+}
+
+void Memfile_LeaseMgr::updateLease4(Lease4Ptr ) {
+}
+
+void Memfile_LeaseMgr::updateLease6(Lease6Ptr ) {
+
+}
+
+bool Memfile_LeaseMgr::deleteLease4(uint32_t ) {
+ return (false);
+}
+
+bool Memfile_LeaseMgr::deleteLease6(isc::asiolink::IOAddress ) {
+ return (false);
+}
+
+std::string Memfile_LeaseMgr::getDescription() const {
+ return (string("This is a dummy memfile backend implementation.\n"
+ "It does not offer any useful lease management and its only\n"
+ "purpose is to test abstract lease manager API."));
+}
+
+namespace {
+// empty class for now, but may be extended once Addr6 becomes bigger
+class LeaseMgrTest : public ::testing::Test {
+public:
+ LeaseMgrTest() {
+ }
+};
+
+// This test checks if the LeaseMgr can be instantiated and that it
+// parses parameters string properly.
+TEST_F(LeaseMgrTest, constructor) {
+
+ // should not throw any exceptions here
+ Memfile_LeaseMgr * leaseMgr = new Memfile_LeaseMgr("");
+ delete leaseMgr;
+
+ leaseMgr = new Memfile_LeaseMgr("param1=value1 param2=value2");
+
+ EXPECT_EQ("value1", leaseMgr->getParameter("param1"));
+ EXPECT_EQ("value2", leaseMgr->getParameter("param2"));
+ EXPECT_THROW(leaseMgr->getParameter("param3"), BadValue);
+
+ delete leaseMgr;
+}
+
+// There's no point in calling any other methods in LeaseMgr, as they
+// are purely virtual, so we would only call Memfile_LeaseMgr methods.
+// Those methods are just stubs that does not return anything.
+// It seems likely that we will need to extend the memfile code for
+// allocation engine tests, so we may implement tests that call
+// Memfile_LeaseMgr methods then.
+
+}; // end of anonymous namespace
More information about the bind10-changes
mailing list