BIND 10 trac2475, updated. d2551c3b2bddcc80c496a59e85e390687776c24d [2475] Split dhcp files into dhcp and dhcpsrv directories

BIND 10 source code commits bind10-changes at lists.isc.org
Fri Nov 16 11:21:06 UTC 2012


The branch, trac2475 has been updated
       via  d2551c3b2bddcc80c496a59e85e390687776c24d (commit)
      from  718e97a589b6d3cbdfed7b768f7fbfaba232b709 (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 d2551c3b2bddcc80c496a59e85e390687776c24d
Author: Stephen Morris <stephen at isc.org>
Date:   Fri Nov 16 11:19:19 2012 +0000

    [2475] Split dhcp files into dhcp and dhcpsrv directories

-----------------------------------------------------------------------

Summary of changes:
 configure.ac                                       |    2 +
 src/bin/dhcp6/Makefile.am                          |    2 +-
 src/bin/dhcp6/config_parser.cc                     |   33 +++++++------
 src/bin/dhcp6/dhcp6_srv.cc                         |   25 +++++-----
 src/bin/dhcp6/dhcp6_srv.h                          |    7 +--
 src/bin/dhcp6/tests/Makefile.am                    |    2 +-
 src/bin/dhcp6/tests/config_parser_unittest.cc      |   23 ++++-----
 src/bin/dhcp6/tests/ctrl_dhcp6_srv_unittest.cc     |   12 +++--
 src/bin/dhcp6/tests/dhcp6_srv_unittest.cc          |   18 +++----
 src/bin/dhcp6/tests/dhcp6_unittests.cc             |    4 +-
 src/lib/Makefile.am                                |    2 +-
 src/lib/dhcp/Makefile.am                           |   39 ++-------------
 src/lib/dhcp/tests/Makefile.am                     |   39 ++-------------
 src/lib/{dhcp => dhcpsrv}/Makefile.am              |   37 ++-------------
 src/lib/{dhcp => dhcpsrv}/addr_utilities.cc        |    5 +-
 src/lib/{dhcp => dhcpsrv}/addr_utilities.h         |    0
 src/lib/{dhcp => dhcpsrv}/alloc_engine.cc          |    6 +--
 src/lib/{dhcp => dhcpsrv}/alloc_engine.h           |    9 ++--
 src/lib/{dhcp => dhcpsrv}/cfgmgr.cc                |    2 +-
 src/lib/{dhcp => dhcpsrv}/cfgmgr.h                 |   18 +++----
 src/lib/{dhcp => dhcpsrv}/database_backends.dox    |    0
 src/lib/{dhcp => dhcpsrv}/dhcpdb_create.mysql      |    0
 src/lib/{dhcp => dhcpsrv}/lease_mgr.cc             |    2 +-
 src/lib/{dhcp => dhcpsrv}/lease_mgr.h              |    2 +-
 src/lib/{dhcp => dhcpsrv}/lease_mgr_factory.cc     |    6 +--
 src/lib/{dhcp => dhcpsrv}/lease_mgr_factory.h      |    5 +-
 src/lib/{dhcp => dhcpsrv}/memfile_lease_mgr.cc     |    4 +-
 src/lib/{dhcp => dhcpsrv}/memfile_lease_mgr.h      |    8 ++--
 src/lib/{dhcp => dhcpsrv}/mysql_lease_mgr.cc       |    2 +-
 src/lib/{dhcp => dhcpsrv}/mysql_lease_mgr.h        |    6 ++-
 src/lib/{dhcp => dhcpsrv}/pool.cc                  |    4 +-
 src/lib/{dhcp => dhcpsrv}/pool.h                   |    4 +-
 src/lib/{dhcp => dhcpsrv}/subnet.cc                |    5 +-
 src/lib/{dhcp => dhcpsrv}/subnet.h                 |    9 ++--
 src/lib/{dhcp => dhcpsrv}/tests/Makefile.am        |   50 +++++---------------
 .../tests/addr_utilities_unittest.cc               |    2 +-
 .../tests/alloc_engine_unittest.cc                 |   14 ++++--
 src/lib/{dhcp => dhcpsrv}/tests/cfgmgr_unittest.cc |    6 ++-
 .../tests/lease_mgr_factory_unittest.cc            |    7 +--
 .../{dhcp => dhcpsrv}/tests/lease_mgr_unittest.cc  |    7 +--
 .../tests/memfile_lease_mgr_unittest.cc            |   11 +++--
 .../tests/mysql_lease_mgr_unittest.cc              |    9 ++--
 src/lib/{dhcp => dhcpsrv}/tests/pool_unittest.cc   |    6 ++-
 src/lib/{dhcp => dhcpsrv}/tests/run_unittests.cc   |    3 +-
 src/lib/{dhcp => dhcpsrv}/tests/schema_copy.h      |    0
 src/lib/{dhcp => dhcpsrv}/tests/subnet_unittest.cc |    7 +--
 .../{dhcp => dhcpsrv}/tests/triplet_unittest.cc    |    6 ++-
 src/lib/{dhcp => dhcpsrv}/triplet.h                |    0
 48 files changed, 197 insertions(+), 273 deletions(-)
 copy src/lib/{dhcp => dhcpsrv}/Makefile.am (52%)
 rename src/lib/{dhcp => dhcpsrv}/addr_utilities.cc (99%)
 rename src/lib/{dhcp => dhcpsrv}/addr_utilities.h (100%)
 rename src/lib/{dhcp => dhcpsrv}/alloc_engine.cc (99%)
 rename src/lib/{dhcp => dhcpsrv}/alloc_engine.h (99%)
 rename src/lib/{dhcp => dhcpsrv}/cfgmgr.cc (99%)
 rename src/lib/{dhcp => dhcpsrv}/cfgmgr.h (99%)
 rename src/lib/{dhcp => dhcpsrv}/database_backends.dox (100%)
 rename src/lib/{dhcp => dhcpsrv}/dhcpdb_create.mysql (100%)
 rename src/lib/{dhcp => dhcpsrv}/lease_mgr.cc (99%)
 rename src/lib/{dhcp => dhcpsrv}/lease_mgr.h (99%)
 rename src/lib/{dhcp => dhcpsrv}/lease_mgr_factory.cc (96%)
 rename src/lib/{dhcp => dhcpsrv}/lease_mgr_factory.h (99%)
 rename src/lib/{dhcp => dhcpsrv}/memfile_lease_mgr.cc (99%)
 rename src/lib/{dhcp => dhcpsrv}/memfile_lease_mgr.h (99%)
 rename src/lib/{dhcp => dhcpsrv}/mysql_lease_mgr.cc (99%)
 rename src/lib/{dhcp => dhcpsrv}/mysql_lease_mgr.h (99%)
 rename src/lib/{dhcp => dhcpsrv}/pool.cc (98%)
 rename src/lib/{dhcp => dhcpsrv}/pool.h (99%)
 rename src/lib/{dhcp => dhcpsrv}/subnet.cc (99%)
 rename src/lib/{dhcp => dhcpsrv}/subnet.h (99%)
 copy src/lib/{dhcp => dhcpsrv}/tests/Makefile.am (56%)
 rename src/lib/{dhcp => dhcpsrv}/tests/addr_utilities_unittest.cc (99%)
 rename src/lib/{dhcp => dhcpsrv}/tests/alloc_engine_unittest.cc (98%)
 rename src/lib/{dhcp => dhcpsrv}/tests/cfgmgr_unittest.cc (99%)
 rename src/lib/{dhcp => dhcpsrv}/tests/lease_mgr_factory_unittest.cc (97%)
 rename src/lib/{dhcp => dhcpsrv}/tests/lease_mgr_unittest.cc (99%)
 rename src/lib/{dhcp => dhcpsrv}/tests/memfile_lease_mgr_unittest.cc (98%)
 rename src/lib/{dhcp => dhcpsrv}/tests/mysql_lease_mgr_unittest.cc (99%)
 rename src/lib/{dhcp => dhcpsrv}/tests/pool_unittest.cc (99%)
 copy src/lib/{dhcp => dhcpsrv}/tests/run_unittests.cc (99%)
 rename src/lib/{dhcp => dhcpsrv}/tests/schema_copy.h (100%)
 rename src/lib/{dhcp => dhcpsrv}/tests/subnet_unittest.cc (99%)
 rename src/lib/{dhcp => dhcpsrv}/tests/triplet_unittest.cc (98%)
 rename src/lib/{dhcp => dhcpsrv}/triplet.h (100%)

-----------------------------------------------------------------------
diff --git a/configure.ac b/configure.ac
index 95f95c6..b0ca18a 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1264,6 +1264,8 @@ AC_CONFIG_FILES([Makefile
                  src/lib/dns/benchmarks/Makefile
                  src/lib/dhcp/Makefile
                  src/lib/dhcp/tests/Makefile
+                 src/lib/dhcpsrv/Makefile
+                 src/lib/dhcpsrv/tests/Makefile
                  src/lib/exceptions/Makefile
                  src/lib/exceptions/tests/Makefile
                  src/lib/datasrc/Makefile
diff --git a/src/bin/dhcp6/Makefile.am b/src/bin/dhcp6/Makefile.am
index 55fe619..1d9766f 100644
--- a/src/bin/dhcp6/Makefile.am
+++ b/src/bin/dhcp6/Makefile.am
@@ -64,7 +64,7 @@ b10_dhcp6_LDADD += $(top_builddir)/src/lib/util/libb10-util.la
 b10_dhcp6_LDADD += $(top_builddir)/src/lib/asiolink/libb10-asiolink.la
 b10_dhcp6_LDADD += $(top_builddir)/src/lib/log/libb10-log.la
 b10_dhcp6_LDADD += $(top_builddir)/src/lib/dhcp/libb10-dhcp++.la
-b10_dhcp6_LDADD += $(top_builddir)/src/lib/dhcp/libb10-dhcpsrv.la
+b10_dhcp6_LDADD += $(top_builddir)/src/lib/dhcpsrv/libb10-dhcpsrv.la
 b10_dhcp6_LDADD += $(top_builddir)/src/lib/config/libb10-cfgclient.la
 b10_dhcp6_LDADD += $(top_builddir)/src/lib/cc/libb10-cc.la
 
diff --git a/src/bin/dhcp6/config_parser.cc b/src/bin/dhcp6/config_parser.cc
index da393ac..d6f3afe 100644
--- a/src/bin/dhcp6/config_parser.cc
+++ b/src/bin/dhcp6/config_parser.cc
@@ -12,27 +12,30 @@
 // OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
 // PERFORMANCE OF THIS SOFTWARE.
 
-#include <stdint.h>
-#include <iostream>
-#include <vector>
-#include <map>
-#include <boost/foreach.hpp>
-#include <boost/shared_ptr.hpp>
-#include <boost/scoped_ptr.hpp>
-#include <boost/lexical_cast.hpp>
-#include <boost/algorithm/string.hpp>
-#include <util/encode/hex.h>
 #include <asiolink/io_address.h>
 #include <cc/data.h>
 #include <config/ccsession.h>
-#include <log/logger_support.h>
 #include <dhcp/libdhcp++.h>
-#include <dhcp/triplet.h>
-#include <dhcp/pool.h>
-#include <dhcp/subnet.h>
-#include <dhcp/cfgmgr.h>
 #include <dhcp6/config_parser.h>
 #include <dhcp6/dhcp6_log.h>
+#include <dhcpsrv/cfgmgr.h>
+#include <dhcpsrv/pool.h>
+#include <dhcpsrv/subnet.h>
+#include <dhcpsrv/triplet.h>
+#include <log/logger_support.h>
+#include <util/encode/hex.h>
+
+#include <boost/algorithm/string.hpp>
+#include <boost/foreach.hpp>
+#include <boost/lexical_cast.hpp>
+#include <boost/scoped_ptr.hpp>
+#include <boost/shared_ptr.hpp>
+
+#include <iostream>
+#include <map>
+#include <vector>
+
+#include <stdint.h>
 
 using namespace std;
 using namespace isc::data;
diff --git a/src/bin/dhcp6/dhcp6_srv.cc b/src/bin/dhcp6/dhcp6_srv.cc
index 82a4777..2a5798d 100644
--- a/src/bin/dhcp6/dhcp6_srv.cc
+++ b/src/bin/dhcp6/dhcp6_srv.cc
@@ -14,33 +14,32 @@
 
 #include <config.h>
 
-#include <stdlib.h>
-#include <time.h>
-
 #include <asiolink/io_address.h>
-#include <dhcp6/dhcp6_log.h>
-#include <dhcp6/dhcp6_srv.h>
 #include <dhcp/dhcp6.h>
+#include <dhcp/duid.h>
 #include <dhcp/iface_mgr.h>
 #include <dhcp/libdhcp++.h>
 #include <dhcp/option6_addrlst.h>
-#include <dhcp/option6_iaaddr.h>
 #include <dhcp/option6_ia.h>
+#include <dhcp/option6_iaaddr.h>
+#include <dhcp/option6_iaaddr.h>
 #include <dhcp/option6_int_array.h>
 #include <dhcp/pkt6.h>
-#include <dhcp/subnet.h>
-#include <dhcp/cfgmgr.h>
+#include <dhcp6/dhcp6_log.h>
+#include <dhcp6/dhcp6_srv.h>
+#include <dhcpsrv/cfgmgr.h>
+#include <dhcpsrv/lease_mgr.h>
+#include <dhcpsrv/lease_mgr_factory.h>
+#include <dhcpsrv/subnet.h>
 #include <exceptions/exceptions.h>
 #include <util/io_utilities.h>
 #include <util/range_utilities.h>
-#include <dhcp/duid.h>
-#include <dhcp/lease_mgr.h>
-#include <dhcp/lease_mgr_factory.h>
-#include <dhcp/cfgmgr.h>
-#include <dhcp/option6_iaaddr.h>
 
 #include <boost/foreach.hpp>
 
+#include <stdlib.h>
+#include <time.h>
+
 using namespace isc;
 using namespace isc::asiolink;
 using namespace isc::dhcp;
diff --git a/src/bin/dhcp6/dhcp6_srv.h b/src/bin/dhcp6/dhcp6_srv.h
index f4f0f0c..a3be4f1 100644
--- a/src/bin/dhcp6/dhcp6_srv.h
+++ b/src/bin/dhcp6/dhcp6_srv.h
@@ -17,15 +17,16 @@
 
 #include <iostream>
 
-#include <boost/noncopyable.hpp>
-#include <dhcp/alloc_engine.h>
 #include <dhcp/dhcp6.h>
 #include <dhcp/duid.h>
 #include <dhcp/option.h>
 #include <dhcp/option6_ia.h>
 #include <dhcp/option_definition.h>
 #include <dhcp/pkt6.h>
-#include <dhcp/subnet.h>
+#include <dhcpsrv/alloc_engine.h>
+#include <dhcpsrv/subnet.h>
+
+#include <boost/noncopyable.hpp>
 
 namespace isc {
 
diff --git a/src/bin/dhcp6/tests/Makefile.am b/src/bin/dhcp6/tests/Makefile.am
index 78caa2f..b01b877 100644
--- a/src/bin/dhcp6/tests/Makefile.am
+++ b/src/bin/dhcp6/tests/Makefile.am
@@ -65,7 +65,7 @@ dhcp6_unittests_LDADD = $(GTEST_LDADD)
 dhcp6_unittests_LDADD += $(top_builddir)/src/lib/asiolink/libb10-asiolink.la
 dhcp6_unittests_LDADD += $(top_builddir)/src/lib/util/libb10-util.la
 dhcp6_unittests_LDADD += $(top_builddir)/src/lib/dhcp/libb10-dhcp++.la
-dhcp6_unittests_LDADD += $(top_builddir)/src/lib/dhcp/libb10-dhcpsrv.la
+dhcp6_unittests_LDADD += $(top_builddir)/src/lib/dhcpsrv/libb10-dhcpsrv.la
 dhcp6_unittests_LDADD += $(top_builddir)/src/lib/log/libb10-log.la
 dhcp6_unittests_LDADD += $(top_builddir)/src/lib/exceptions/libb10-exceptions.la
 dhcp6_unittests_LDADD += $(top_builddir)/src/lib/config/libb10-cfgclient.la
diff --git a/src/bin/dhcp6/tests/config_parser_unittest.cc b/src/bin/dhcp6/tests/config_parser_unittest.cc
index 95c7897..a5a1f99 100644
--- a/src/bin/dhcp6/tests/config_parser_unittest.cc
+++ b/src/bin/dhcp6/tests/config_parser_unittest.cc
@@ -13,23 +13,24 @@
 // PERFORMANCE OF THIS SOFTWARE.
 
 #include <config.h>
-#include <iostream>
-#include <fstream>
-#include <sstream>
+
+#include <config/ccsession.h>
+#include <dhcp/libdhcp++.h>
+#include <dhcp/option6_ia.h>
+#include <dhcp6/config_parser.h>
+#include <dhcp6/dhcp6_srv.h>
+#include <dhcpsrv/cfgmgr.h>
+#include <dhcpsrv/subnet.h>
 
 #include <boost/foreach.hpp>
 
+#include <fstream>
+#include <iostream>
+#include <sstream>
+
 #include <arpa/inet.h>
 #include <gtest/gtest.h>
 
-#include <dhcp6/dhcp6_srv.h>
-#include <dhcp6/config_parser.h>
-#include <config/ccsession.h>
-#include <dhcp/libdhcp++.h>
-#include <dhcp/subnet.h>
-#include <dhcp/cfgmgr.h>
-#include <dhcp/option6_ia.h>
-
 using namespace std;
 using namespace isc;
 using namespace isc::dhcp;
diff --git a/src/bin/dhcp6/tests/ctrl_dhcp6_srv_unittest.cc b/src/bin/dhcp6/tests/ctrl_dhcp6_srv_unittest.cc
index 1e88f83..ea359fc 100644
--- a/src/bin/dhcp6/tests/ctrl_dhcp6_srv_unittest.cc
+++ b/src/bin/dhcp6/tests/ctrl_dhcp6_srv_unittest.cc
@@ -13,16 +13,18 @@
 // PERFORMANCE OF THIS SOFTWARE.
 
 #include <config.h>
+
+#include <dhcp/dhcp6.h>
+#include <dhcp6/ctrl_dhcp6_srv.h>
+#include <config/ccsession.h>
+
+#include <gtest/gtest.h>
+
 #include <iostream>
 #include <fstream>
 #include <sstream>
 
 #include <arpa/inet.h>
-#include <gtest/gtest.h>
-
-#include <dhcp/dhcp6.h>
-#include <dhcp6/ctrl_dhcp6_srv.h>
-#include <config/ccsession.h>
 
 using namespace std;
 using namespace isc;
diff --git a/src/bin/dhcp6/tests/dhcp6_srv_unittest.cc b/src/bin/dhcp6/tests/dhcp6_srv_unittest.cc
index afb05d1..7036fb6 100644
--- a/src/bin/dhcp6/tests/dhcp6_srv_unittest.cc
+++ b/src/bin/dhcp6/tests/dhcp6_srv_unittest.cc
@@ -14,20 +14,11 @@
 
 #include <config.h>
 
-#include <fstream>
-#include <iostream>
-#include <sstream>
-
-#include <gtest/gtest.h>
-
 #include <asiolink/io_address.h>
 #include <boost/scoped_ptr.hpp>
 #include <config/ccsession.h>
-#include <dhcp/cfgmgr.h>
 #include <dhcp/dhcp6.h>
 #include <dhcp/duid.h>
-#include <dhcp/lease_mgr.h>
-#include <dhcp/lease_mgr_factory.h>
 #include <dhcp/option.h>
 #include <dhcp/option6_addrlst.h>
 #include <dhcp/option6_ia.h>
@@ -35,9 +26,18 @@
 #include <dhcp/option6_int_array.h>
 #include <dhcp6/config_parser.h>
 #include <dhcp6/dhcp6_srv.h>
+#include <dhcpsrv/cfgmgr.h>
+#include <dhcpsrv/lease_mgr.h>
+#include <dhcpsrv/lease_mgr_factory.h>
 #include <util/buffer.h>
 #include <util/range_utilities.h>
 
+#include <gtest/gtest.h>
+
+#include <fstream>
+#include <iostream>
+#include <sstream>
+
 using namespace isc;
 using namespace isc::asiolink;
 using namespace isc::config;
diff --git a/src/bin/dhcp6/tests/dhcp6_unittests.cc b/src/bin/dhcp6/tests/dhcp6_unittests.cc
index 360fb71..d9695e9 100644
--- a/src/bin/dhcp6/tests/dhcp6_unittests.cc
+++ b/src/bin/dhcp6/tests/dhcp6_unittests.cc
@@ -12,10 +12,10 @@
 // OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
 // PERFORMANCE OF THIS SOFTWARE.
 
-#include <stdio.h>
-#include <gtest/gtest.h>
 #include <log/logger_support.h>
 
+#include <gtest/gtest.h>
+
 int
 main(int argc, char* argv[]) {
 
diff --git a/src/lib/Makefile.am b/src/lib/Makefile.am
index 9ebd541..f636c0d 100644
--- a/src/lib/Makefile.am
+++ b/src/lib/Makefile.am
@@ -1,3 +1,3 @@
 SUBDIRS = exceptions util log cryptolink dns cc config acl xfr bench \
           asiolink asiodns nsas cache resolve testutils datasrc \
-          server_common python dhcp statistics
+          server_common python dhcp dhcpsrv statistics
diff --git a/src/lib/dhcp/Makefile.am b/src/lib/dhcp/Makefile.am
index 017a13e..1c74446 100644
--- a/src/lib/dhcp/Makefile.am
+++ b/src/lib/dhcp/Makefile.am
@@ -2,10 +2,6 @@ SUBDIRS = . tests
 
 AM_CPPFLAGS = -I$(top_builddir)/src/lib -I$(top_srcdir)/src/lib
 AM_CPPFLAGS += $(BOOST_INCLUDES)
-if HAVE_MYSQL
-AM_CPPFLAGS += $(MYSQL_CPPFLAGS)
-endif
-
 AM_CXXFLAGS = $(B10_CXXFLAGS)
 
 # Some versions of GCC warn about some versions of Boost regarding
@@ -16,13 +12,14 @@ AM_CXXFLAGS += $(WARNING_NO_MISSING_FIELD_INITIALIZERS_CFLAG)
 
 CLEANFILES = *.gcno *.gcda
 
-lib_LTLIBRARIES = libb10-dhcp++.la libb10-dhcpsrv.la
+lib_LTLIBRARIES = libb10-dhcp++.la
 libb10_dhcp___la_SOURCES  =
-libb10_dhcp___la_SOURCES += libdhcp++.cc libdhcp++.h
+libb10_dhcp___la_SOURCES += duid.cc duid.h
 libb10_dhcp___la_SOURCES += iface_mgr.cc iface_mgr.h
 libb10_dhcp___la_SOURCES += iface_mgr_bsd.cc
 libb10_dhcp___la_SOURCES += iface_mgr_linux.cc
 libb10_dhcp___la_SOURCES += iface_mgr_sun.cc
+libb10_dhcp___la_SOURCES += libdhcp++.cc libdhcp++.h
 libb10_dhcp___la_SOURCES += option.cc option.h
 libb10_dhcp___la_SOURCES += option_data_types.h
 libb10_dhcp___la_SOURCES += option_definition.cc option_definition.h
@@ -42,38 +39,10 @@ libb10_dhcp___la_LIBADD   = $(top_builddir)/src/lib/asiolink/libb10-asiolink.la
 libb10_dhcp___la_LIBADD  += $(top_builddir)/src/lib/util/libb10-util.la
 libb10_dhcp___la_LDFLAGS  = -no-undefined -version-info 2:0:0
 
-libb10_dhcpsrv_la_SOURCES  =
-libb10_dhcpsrv_la_SOURCES += addr_utilities.cc addr_utilities.h
-libb10_dhcpsrv_la_SOURCES += alloc_engine.cc alloc_engine.h
-libb10_dhcpsrv_la_SOURCES += cfgmgr.cc cfgmgr.h
-libb10_dhcpsrv_la_SOURCES += duid.cc duid.h
-libb10_dhcpsrv_la_SOURCES += lease_mgr.cc lease_mgr.h
-libb10_dhcpsrv_la_SOURCES += lease_mgr_factory.cc lease_mgr_factory.h
-libb10_dhcpsrv_la_SOURCES += memfile_lease_mgr.cc memfile_lease_mgr.h
-if HAVE_MYSQL
-libb10_dhcpsrv_la_SOURCES += mysql_lease_mgr.cc mysql_lease_mgr.h
-endif
-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_CXXFLAGS = $(AM_CXXFLAGS)
-libb10_dhcpsrv_la_CPPFLAGS = $(AM_CPPFLAGS) $(LOG4CPLUS_INCLUDES)
-libb10_dhcpsrv_la_LIBADD   = $(top_builddir)/src/lib/asiolink/libb10-asiolink.la
-libb10_dhcpsrv_la_LIBADD  += $(top_builddir)/src/lib/util/libb10-util.la
-libb10_dhcpsrv_la_LDFLAGS  = -no-undefined -version-info 2:0:0
-if HAVE_MYSQL
-libb10_dhcpsrv_la_LDFLAGS += $(MYSQL_LIBS)
-endif
-
-EXTRA_DIST  = README database_backends.dox
+EXTRA_DIST  = README
 
 if USE_CLANGPP
 # Disable unused parameter warning caused by some of the
 # Boost headers when compiling with clang.
 libb10_dhcp___la_CXXFLAGS += -Wno-unused-parameter
 endif
-
-# Distribute MySQL schema creation script
-EXTRA_DIST += dhcpdb_create.mysql
-dist_pkgdata_DATA = dhcpdb_create.mysql
diff --git a/src/lib/dhcp/addr_utilities.cc b/src/lib/dhcp/addr_utilities.cc
deleted file mode 100644
index 6ac3f14..0000000
--- a/src/lib/dhcp/addr_utilities.cc
+++ /dev/null
@@ -1,188 +0,0 @@
-// 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.h>
-#include <exceptions/exceptions.h>
-#include <dhcp/addr_utilities.h>
-
-using namespace isc;
-using namespace isc::asiolink;
-
-namespace {
-
-/// @brief mask used for first/last address calculation in a IPv4 prefix
-///
-/// Using a static mask is faster than calculating it dynamically every time.
-const uint32_t bitMask4[] = { 0xffffffff, 0x7fffffff, 0x3fffffff, 0x1fffffff,
-                              0x0fffffff, 0x07ffffff, 0x03ffffff, 0x01ffffff,
-                              0x00ffffff, 0x007fffff, 0x003fffff, 0x001fffff,
-                              0x000fffff, 0x0007ffff, 0x0003ffff, 0x0001ffff,
-                              0x0000ffff, 0x00007fff, 0x00003fff, 0x00001fff,
-                              0x00000fff, 0x000007ff, 0x000003ff, 0x000001ff,
-                              0x000000ff, 0x0000007f, 0x0000003f, 0x0000001f,
-                              0x0000000f, 0x00000007, 0x00000003, 0x00000001,
-                              0x00000000 };
-
-/// @brief mask used for first/last address calculation in a IPv6 prefix
-const uint8_t bitMask6[]= { 0, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0xff };
-
-/// @brief calculates the first IPv6 address in a IPv6 prefix
-///
-/// Note: This is a private function. Do not use it directly.
-/// Please use firstAddrInPrefix() instead.
-///
-/// @param prefix IPv6 prefix
-/// @param len prefix length
-isc::asiolink::IOAddress firstAddrInPrefix6(const isc::asiolink::IOAddress& prefix,
-                                            uint8_t len) {
-    if (len > 128) {
-        isc_throw(isc::BadValue,
-                  "Too large netmask. 0..128 is allowed in IPv6");
-    }
-
-    // First we copy the whole address as 16 bytes.
-    uint8_t packed[V6ADDRESS_LEN];
-    memcpy(packed, prefix.getAddress().to_v6().to_bytes().data(), 16);
-
-    // If the length is divisible by 8, it is simple. We just zero out the host
-    // part. Otherwise we need to handle the byte that has to be partially
-    // zeroed.
-    if (len % 8 != 0) {
-
-        // Get the appropriate mask. It has relevant bits (those that should
-        // stay) set and irrelevant (those that should be wiped) cleared.
-        uint8_t mask = bitMask6[len % 8];
-
-        // Let's leave only whatever the mask says should not be cleared.
-        packed[len / 8] = packed[len / 8] & mask;
-
-        // Since we have just dealt with this byte, let's move the prefix length
-        // to the beginning of the next byte (len is expressed in bits).
-        len = (len / 8 + 1) * 8;
-    }
-
-    // Clear out the remaining bits.
-    for (int i = len / 8; i < sizeof(packed); ++i) {
-        packed[i] = 0x0;
-    }
-
-    // Finally, let's wrap this into nice and easy IOAddress object.
-    return (isc::asiolink::IOAddress::from_bytes(AF_INET6, packed));
-}
-
-/// @brief calculates the first IPv4 address in a IPv4 prefix
-///
-/// Note: This is a private function. Do not use it directly.
-/// Please use firstAddrInPrefix() instead.
-///
-/// @param prefix IPv4 prefix
-/// @param len netmask length (0-32)
-isc::asiolink::IOAddress firstAddrInPrefix4(const isc::asiolink::IOAddress& prefix,
-                                            uint8_t len) {
-    if (len > 32) {
-        isc_throw(isc::BadValue, "Too large netmask. 0..32 is allowed in IPv4");
-    }
-
-    uint32_t addr = prefix;
-    return (IOAddress(addr & (~bitMask4[len])));
-}
-
-/// @brief calculates the last IPv4 address in a IPv4 prefix
-///
-/// Note: This is a private function. Do not use it directly.
-/// Please use firstAddrInPrefix() instead.
-///
-/// @param prefix IPv4 prefix that we calculate first address for
-/// @param len netmask length (0-32)
-isc::asiolink::IOAddress lastAddrInPrefix4(const isc::asiolink::IOAddress& prefix,
-                                           uint8_t len) {
-    if (len > 32) {
-        isc_throw(isc::BadValue, "Too large netmask. 0..32 is allowed in IPv4");
-    }
-
-    uint32_t addr = prefix;
-    return (IOAddress(addr | bitMask4[len]));
-}
-
-/// @brief calculates the last IPv6 address in a IPv6 prefix
-///
-/// Note: This is a private function. Do not use it directly.
-/// Please use lastAddrInPrefix() instead.
-///
-/// @param prefix IPv6 prefix that we calculate first address for
-/// @param len netmask length (0-128)
-isc::asiolink::IOAddress lastAddrInPrefix6(const isc::asiolink::IOAddress& prefix,
-                                           uint8_t len) {
-    if (len > 128) {
-        isc_throw(isc::BadValue,
-                  "Too large netmask. 0..128 is allowed in IPv6");
-    }
-
-    // First we copy the whole address as 16 bytes.
-    uint8_t packed[V6ADDRESS_LEN];
-    memcpy(packed, prefix.getAddress().to_v6().to_bytes().data(), 16);
-
-    // if the length is divisible by 8, it is simple. We just fill the host part
-    // with ones. Otherwise we need to handle the byte that has to be partially
-    // zeroed.
-    if (len % 8 != 0) {
-        // Get the appropriate mask. It has relevant bits (those that should
-        // stay) set and irrelevant (those that should be set to 1) cleared.
-        uint8_t mask = bitMask6[len % 8];
-
-        // Let's set those irrelevant bits with 1. It would be perhaps
-        // easier to not use negation here and invert bitMask6 content. However,
-        // with this approach, we can use the same mask in first and last
-        // address calculations.
-        packed[len / 8] = packed[len / 8] | ~mask;
-
-        // Since we have just dealt with this byte, let's move the prefix length
-        // to the beginning of the next byte (len is expressed in bits).
-        len = (len / 8 + 1) * 8;
-    }
-
-    // Finally set remaining bits to 1.
-    for (int i = len / 8; i < sizeof(packed); ++i) {
-        packed[i] = 0xff;
-    }
-
-    // Finally, let's wrap this into nice and easy IOAddress object.
-    return (isc::asiolink::IOAddress::from_bytes(AF_INET6, packed));
-}
-
-}; // end of anonymous namespace
-
-namespace isc {
-namespace dhcp {
-
-isc::asiolink::IOAddress firstAddrInPrefix(const isc::asiolink::IOAddress& prefix,
-                                            uint8_t len) {
-    if (prefix.getFamily() == AF_INET) {
-        return firstAddrInPrefix4(prefix, len);
-    } else {
-        return firstAddrInPrefix6(prefix, len);
-    }
-}
-
-isc::asiolink::IOAddress lastAddrInPrefix(const isc::asiolink::IOAddress& prefix,
-                                           uint8_t len) {
-    if (prefix.getFamily() == AF_INET) {
-        return lastAddrInPrefix4(prefix, len);
-    } else {
-        return lastAddrInPrefix6(prefix, len);
-    }
-}
-
-};
-};
diff --git a/src/lib/dhcp/addr_utilities.h b/src/lib/dhcp/addr_utilities.h
deleted file mode 100644
index a1d856c..0000000
--- a/src/lib/dhcp/addr_utilities.h
+++ /dev/null
@@ -1,58 +0,0 @@
-// 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 ADDR_UTILITIES_H
-#define ADDR_UTILITIES_H
-
-#include <asiolink/io_address.h>
-
-namespace isc {
-namespace dhcp {
-
-/// This code is based on similar code from the Dibbler project. I, Tomasz Mrugalski,
-/// as a sole creator of that code hereby release it under BSD license for the benefit
-/// of the BIND10 project.
-
-/// @brief returns a first address in a given prefix
-///
-/// Example: For 2001:db8:1::deaf:beef and length /120 the function will return
-/// 2001:db8:1::dead:be00. See also @ref lastAddrInPrefix.
-///
-/// @todo It currently works for v6 only and will throw if v4 address is passed.
-///
-/// @param prefix and address that belongs to a prefix
-/// @param len prefix length
-///
-/// @return first address from a prefix
-isc::asiolink::IOAddress firstAddrInPrefix(const isc::asiolink::IOAddress& prefix,
-                                            uint8_t len);
-
-/// @brief returns a last address in a given prefix
-///
-/// Example: For 2001:db8:1::deaf:beef and length /112 the function will return
-/// 2001:db8:1::dead:ffff. See also @ref firstAddrInPrefix.
-///
-/// @todo It currently works for v6 only and will throw if v4 address is passed.
-///
-/// @param prefix and address that belongs to a prefix
-/// @param len prefix length
-///
-/// @return first address from a prefix
-isc::asiolink::IOAddress lastAddrInPrefix(const isc::asiolink::IOAddress& prefix,
-                                           uint8_t len);
-
-};
-};
-
-#endif // ADDR_UTILITIES_H
diff --git a/src/lib/dhcp/alloc_engine.cc b/src/lib/dhcp/alloc_engine.cc
deleted file mode 100644
index 53ef7f3..0000000
--- a/src/lib/dhcp/alloc_engine.cc
+++ /dev/null
@@ -1,276 +0,0 @@
-// 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 <alloc_engine.h>
-#include <lease_mgr_factory.h>
-#include <string.h>
-
-#include <cstring>
-
-using namespace isc::asiolink;
-
-namespace isc {
-namespace dhcp {
-
-AllocEngine::IterativeAllocator::IterativeAllocator()
-    :Allocator() {
-}
-
-isc::asiolink::IOAddress
-AllocEngine::IterativeAllocator::increaseAddress(const isc::asiolink::IOAddress& addr) {
-    uint8_t packed[V6ADDRESS_LEN];
-    int len;
-
-    // First we copy the whole address as 16 bytes.
-    if (addr.getFamily()==AF_INET) {
-        // IPv4
-        std::memcpy(packed, addr.getAddress().to_v4().to_bytes().data(), 4);
-        len = 4;
-    } else {
-        // IPv6
-        std::memcpy(packed, addr.getAddress().to_v6().to_bytes().data(), 16);
-        len = 16;
-    }
-
-    for (int i = len - 1; i >= 0; --i) {
-        ++packed[i];
-        if (packed[i] != 0) {
-            break;
-        }
-    }
-
-    return (IOAddress::from_bytes(addr.getFamily(), packed));
-}
-
-
-isc::asiolink::IOAddress
-AllocEngine::IterativeAllocator::pickAddress(const Subnet6Ptr& subnet,
-                                             const DuidPtr&,
-                                             const IOAddress&) {
-
-    // Let's get the last allocated address. It is usually set correctly,
-    // but there are times when it won't be (like after removing a pool or
-    // perhaps restaring the server).
-    IOAddress last = subnet->getLastAllocated();
-
-    const Pool6Collection& pools = subnet->getPools();
-
-    if (pools.size() == 0) {
-        isc_throw(AllocFailed, "No pools defined in selected subnet");
-    }
-
-    // first we need to find a pool the last address belongs to.
-    Pool6Collection::const_iterator it;
-    for (it = pools.begin(); it != pools.end(); ++it) {
-        if ((*it)->inRange(last)) {
-            break;
-        }
-    }
-
-    // last one was bogus for one of several reasons:
-    // - we just booted up and that's the first address we're allocating
-    // - a subnet was removed or other reconfiguration just completed
-    // - perhaps allocation algorithm was changed
-    if (it == pools.end()) {
-        // ok to access first element directly. We checked that pools is non-empty
-        IOAddress next = pools[0]->getFirstAddress();
-        subnet->setLastAllocated(next);
-        return (next);
-    }
-
-    // Ok, we have a pool that the last address belonged to, let's use it.
-
-    IOAddress next = increaseAddress(last); // basically addr++
-    if ((*it)->inRange(next)) {
-        // the next one is in the pool as well, so we haven't hit pool boundary yet
-        subnet->setLastAllocated(next);
-        return (next);
-    }
-
-    // We hit pool boundary, let's try to jump to the next pool and try again
-    ++it;
-    if (it == pools.end()) {
-        // Really out of luck today. That was the last pool. Let's rewind
-        // to the beginning.
-        next = pools[0]->getFirstAddress();
-        subnet->setLastAllocated(next);
-        return (next);
-    }
-
-    // there is a next pool, let's try first adddress from it
-    next = (*it)->getFirstAddress();
-    subnet->setLastAllocated(next);
-    return (next);
-}
-
-AllocEngine::HashedAllocator::HashedAllocator()
-    :Allocator() {
-    isc_throw(NotImplemented, "Hashed allocator is not implemented");
-}
-
-
-isc::asiolink::IOAddress
-AllocEngine::HashedAllocator::pickAddress(const Subnet6Ptr&,
-                                             const DuidPtr&,
-                                             const IOAddress&) {
-    isc_throw(NotImplemented, "Hashed allocator is not implemented");
-}
-
-AllocEngine::RandomAllocator::RandomAllocator()
-    :Allocator() {
-    isc_throw(NotImplemented, "Random allocator is not implemented");
-}
-
-
-isc::asiolink::IOAddress
-AllocEngine::RandomAllocator::pickAddress(const Subnet6Ptr&,
-                                             const DuidPtr&,
-                                             const IOAddress&) {
-    isc_throw(NotImplemented, "Random allocator is not implemented");
-}
-
-
-AllocEngine::AllocEngine(AllocType engine_type, unsigned int attempts)
-    :attempts_(attempts) {
-    switch (engine_type) {
-    case ALLOC_ITERATIVE:
-        allocator_ = boost::shared_ptr<Allocator>(new IterativeAllocator());
-        break;
-    case ALLOC_HASHED:
-        allocator_ = boost::shared_ptr<Allocator>(new HashedAllocator());
-        break;
-    case ALLOC_RANDOM:
-        allocator_ = boost::shared_ptr<Allocator>(new RandomAllocator());
-        break;
-
-    default:
-        isc_throw(BadValue, "Invalid/unsupported allocation algorithm");
-    }
-}
-
-Lease6Ptr
-AllocEngine::allocateAddress6(const Subnet6Ptr& subnet,
-                              const DuidPtr& duid,
-                              uint32_t iaid,
-                              const IOAddress& hint,
-                              bool fake_allocation /* = false */ ) {
-
-    // That check is not necessary. We create allocator in AllocEngine
-    // constructor
-    if (!allocator_) {
-        isc_throw(InvalidOperation, "No allocator selected");
-    }
-
-    // check if there's existing lease for that subnet/duid/iaid combination.
-    Lease6Ptr existing = LeaseMgrFactory::instance().getLease6(*duid, iaid, subnet->getID());
-    if (existing) {
-        // we have a lease already. This is a returning client, probably after
-        // his reboot.
-        return (existing);
-    }
-
-    // check if the hint is in pool and is available
-    if (subnet->inPool(hint)) {
-        existing = LeaseMgrFactory::instance().getLease6(hint);
-        if (!existing) {
-            /// @todo: check if the hint is reserved once we have host support
-            /// implemented
-
-            // the hint is valid and not currently used, let's create a lease for it
-            Lease6Ptr lease = createLease(subnet, duid, iaid, hint, fake_allocation);
-
-            // It can happen that the lease allocation failed (we could have lost
-            // the race condition. That means that the hint is lo longer usable and
-            // we need to continue the regular allocation path.
-            if (lease) {
-                return (lease);
-            }
-        }
-    }
-
-    unsigned int i = attempts_;
-    do {
-        IOAddress candidate = allocator_->pickAddress(subnet, duid, hint);
-
-        /// @todo: check if the address is reserved once we have host support
-        /// implemented
-
-        Lease6Ptr existing = LeaseMgrFactory::instance().getLease6(candidate);
-        // there's no existing lease for selected candidate, so it is
-        // free. Let's allocate it.
-        if (!existing) {
-            Lease6Ptr lease = createLease(subnet, duid, iaid, candidate,
-                                          fake_allocation);
-            if (lease) {
-                return (lease);
-            }
-
-            // Although the address was free just microseconds ago, it may have
-            // been taken just now. If the lease insertion fails, we continue
-            // allocation attempts.
-        }
-
-        // continue trying allocation until we run out of attempts
-        // (or attempts are set to 0, which means infinite)
-        --i;
-    } while ( i || !attempts_);
-
-    isc_throw(AllocFailed, "Failed to allocate address after " << attempts_
-              << " tries");
-}
-
-Lease6Ptr AllocEngine::createLease(const Subnet6Ptr& subnet,
-                                   const DuidPtr& duid,
-                                   uint32_t iaid,
-                                   const IOAddress& addr,
-                                   bool fake_allocation /*= false */ ) {
-
-    Lease6Ptr lease(new Lease6(Lease6::LEASE_IA_NA, addr, duid, iaid,
-                               subnet->getPreferred(), subnet->getValid(),
-                               subnet->getT1(), subnet->getT2(), subnet->getID()));
-
-    if (!fake_allocation) {
-        // That is a real (REQUEST) allocation
-        bool status = LeaseMgrFactory::instance().addLease(lease);
-
-        if (status) {
-
-            return (lease);
-        } else {
-            // One of many failures with LeaseMgr (e.g. lost connection to the
-            // database, database failed etc.). One notable case for that
-            // is that we are working in multi-process mode and we lost a race
-            // (some other process got that address first)
-            return (Lease6Ptr());
-        }
-    } else {
-        // That is only fake (SOLICIT without rapid-commit) allocation
-
-        // It is for advertise only. We should not insert the lease into LeaseMgr,
-        // but rather check that we could have inserted it.
-        Lease6Ptr existing = LeaseMgrFactory::instance().getLease6(addr);
-        if (!existing) {
-            return (lease);
-        } else {
-            return (Lease6Ptr());
-        }
-    }
-}
-
-AllocEngine::~AllocEngine() {
-    // no need to delete allocator. smart_ptr will do the trick for us
-}
-
-}; // end of isc::dhcp namespace
-}; // end of isc namespace
diff --git a/src/lib/dhcp/alloc_engine.h b/src/lib/dhcp/alloc_engine.h
deleted file mode 100644
index 496703a..0000000
--- a/src/lib/dhcp/alloc_engine.h
+++ /dev/null
@@ -1,228 +0,0 @@
-// 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 ALLOC_ENGINE_H
-#define ALLOC_ENGINE_H
-
-#include <boost/shared_ptr.hpp>
-#include <boost/noncopyable.hpp>
-#include <dhcp/duid.h>
-#include <dhcp/subnet.h>
-#include <asiolink/io_address.h>
-#include <dhcp/lease_mgr.h>
-
-namespace isc {
-namespace dhcp {
-
-/// An exception that is thrown when allocation module fails (e.g. due to
-/// lack of available addresses)
-class AllocFailed : public isc::Exception {
-public:
-
-    /// @brief constructor
-    ///
-    /// @param file name of the file, where exception occurred
-    /// @param line line of the file, where exception occurred
-    /// @param what text description of the issue that caused exception
-    AllocFailed(const char* file, size_t line, const char* what)
-        : isc::Exception(file, line, what) {}
-};
-
-/// @brief DHCPv4 and DHCPv6 allocation engine
-///
-/// This class represents DHCP allocation engine. It is responsible
-/// for picking subnets, choosing and allocating a lease, extending,
-/// renewing, releasing and possibly expiring leases.
-///
-/// @todo: Does not handle out of leases well
-/// @todo: Does not handle out of allocation attempts well
-class AllocEngine : public boost::noncopyable {
-protected:
-
-    /// @brief base class for all address/prefix allocation algorithms
-    ///
-    /// This is an abstract class that should not be used directly, but rather
-    /// specialized implementations should be used instead.
-    class Allocator {
-    public:
-
-        /// @brief picks one address out of available pools in a given subnet
-        ///
-        /// This method returns one address from the available pools in the
-        /// specified subnet. It should not check if the address is used or
-        /// reserved - AllocEngine will check that and will call pickAddress
-        /// again if necessary. The number of times this method is called will
-        /// increase as the number of available leases will decrease.
-        virtual isc::asiolink::IOAddress
-        pickAddress(const Subnet6Ptr& subnet, const DuidPtr& duid,
-                    const isc::asiolink::IOAddress& hint) = 0;
-
-        /// @brief virtual destructor
-        virtual ~Allocator() {
-        }
-    protected:
-    };
-
-    /// @brief Address/prefix allocator that iterates over all addresses
-    ///
-    /// This class implements iterative algorithm that returns all addresses in
-    /// a pool iteratively, one after another. Once the last address is reached,
-    /// it starts allocating from the beginning of the first pool (i.e. it loops
-    /// over).
-    class IterativeAllocator : public Allocator {
-    public:
-
-        /// @brief default constructor
-        ///
-        /// Does not do anything
-        IterativeAllocator();
-
-        /// @brief returns the next address from pools in a subnet
-        ///
-        /// @param subnet next address will be returned from pool of that subnet
-        /// @param duid Client's DUID (ignored)
-        /// @param hint client's hint (ignored)
-        /// @return the next address
-        virtual isc::asiolink::IOAddress
-            pickAddress(const Subnet6Ptr& subnet,
-                        const DuidPtr& duid,
-                        const isc::asiolink::IOAddress& hint);
-    private:
-
-        /// @brief returns an address by one
-        /// @param addr address to be increased
-        /// @return address increased by one
-        isc::asiolink::IOAddress increaseAddress(const isc::asiolink::IOAddress& addr);
-
-    };
-
-    /// @brief Address/prefix allocator that gets an address based on a hash
-    ///
-    /// @todo: This is a skeleton class for now and is missing implementation.
-    class HashedAllocator : public Allocator {
-    public:
-
-        /// @brief default constructor (does nothing)
-        HashedAllocator();
-
-        /// @brief returns an address based on hash calculated from client's DUID.
-        ///
-        /// @todo: Implement this method
-        ///
-        /// @param subnet an address will be picked from pool of that subnet
-        /// @param duid Client's DUID
-        /// @param hint a hint (last address that was picked)
-        /// @return selected address
-        virtual isc::asiolink::IOAddress pickAddress(const Subnet6Ptr& subnet,
-                                                     const DuidPtr& duid,
-                                                     const isc::asiolink::IOAddress& hint);
-    };
-
-    /// @brief Random allocator that picks address randomly
-    ///
-    /// @todo: This is a skeleton class for now and is missing implementation.
-    class RandomAllocator : public Allocator {
-    public:
-
-        /// @brief default constructor (does nothing)
-        RandomAllocator();
-
-        /// @brief returns an random address from pool of specified subnet
-        ///
-        /// @todo: Implement this method
-        ///
-        /// @param subnet an address will be picked from pool of that subnet
-        /// @param duid Client's DUID (ignored)
-        /// @param hint the last address that was picked (ignored)
-        /// @return a random address from the pool
-        virtual isc::asiolink::IOAddress
-        pickAddress(const Subnet6Ptr& subnet, const DuidPtr& duid,
-                    const isc::asiolink::IOAddress& hint);
-    };
-
-    public:
-
-    /// @brief specifies allocation type
-    typedef enum {
-        ALLOC_ITERATIVE, // iterative - one address after another
-        ALLOC_HASHED,    // hashed - client's DUID/client-id is hashed
-        ALLOC_RANDOM     // random - an address is randomly selected
-    } AllocType;
-
-
-    /// @brief Default constructor.
-    ///
-    /// Instantiates necessary services, required to run DHCPv6 server.
-    /// In particular, creates IfaceMgr that will be responsible for
-    /// network interaction. Will instantiate lease manager, and load
-    /// old or create new DUID.
-    ///
-    /// @param engine_type selects allocation algorithm
-    /// @param attempts number of attempts for each lease allocation before
-    ///        we give up (0 means unlimited)
-    AllocEngine(AllocType engine_type, unsigned int attempts);
-
-    /// @brief Allocates an IPv6 lease
-    ///
-    /// This method uses currently selected allocator to pick an address from
-    /// specified subnet, creates a lease for that address and then inserts
-    /// it into LeaseMgr (if this allocation is not fake).
-    ///
-    /// @param subnet subnet the allocation should come from
-    /// @param duid Client'd DUID
-    /// @param iaid iaid field from the IA_NA container that client sent
-    /// @param hint a hint that the client provided
-    /// @param fake_allocation is this real i.e. REQUEST (false) or just picking
-    ///        an address for SOLICIT that is not really allocated (true)
-    /// @return Allocated IPv6 lease (or NULL if allocation failed)
-    Lease6Ptr
-    allocateAddress6(const Subnet6Ptr& subnet,
-                     const DuidPtr& duid,
-                     uint32_t iaid,
-                     const isc::asiolink::IOAddress& hint,
-                     bool fake_allocation);
-
-    /// @brief Destructor. Used during DHCPv6 service shutdown.
-    virtual ~AllocEngine();
-private:
-
-    /// @brief creates a lease and inserts it in LeaseMgr if necessary
-    ///
-    /// Creates a lease based on specified parameters and tries to insert it
-    /// into the database. That may fail in some cases, i.e. when there is another
-    /// allocation process and we lost a race to a specific lease.
-    ///
-    /// @param subnet subnet the lease is allocated from
-    /// @param duid client's DUID
-    /// @param iaid IAID from the IA_NA container the client sent to us
-    /// @param addr an address that was selected and is confirmed to be available
-    /// @param fake_allocation is this real i.e. REQUEST (false) or just picking
-    ///        an address for SOLICIT that is not really allocated (true)
-    /// @return allocated lease (or NULL in the unlikely case of the lease just
-    ///        becomed unavailable)
-    Lease6Ptr createLease(const Subnet6Ptr& subnet, const DuidPtr& duid,
-                          uint32_t iaid, const isc::asiolink::IOAddress& addr,
-                          bool fake_allocation = false);
-
-    /// @brief a pointer to currently used allocator
-    boost::shared_ptr<Allocator> allocator_;
-
-    /// @brief number of attempts before we give up lease allocation (0=unlimited)
-    unsigned int attempts_;
-};
-
-}; // namespace isc::dhcp
-}; // namespace isc
-
-#endif // ALLOC_ENGINE_H
diff --git a/src/lib/dhcp/cfgmgr.cc b/src/lib/dhcp/cfgmgr.cc
deleted file mode 100644
index 0e7c8f4..0000000
--- a/src/lib/dhcp/cfgmgr.cc
+++ /dev/null
@@ -1,111 +0,0 @@
-// 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/cfgmgr.h>
-
-using namespace isc::asiolink;
-using namespace isc::util;
-
-namespace isc {
-namespace dhcp {
-
-
-
-
-CfgMgr&
-CfgMgr::instance() {
-    static CfgMgr cfg_mgr;
-    return (cfg_mgr);
-}
-
-Subnet6Ptr
-CfgMgr::getSubnet6(const isc::asiolink::IOAddress& hint) {
-
-    // If there's only one subnet configured, let's just use it
-    // The idea is to keep small deployments easy. In a small network - one
-    // router that also runs DHCPv6 server. Users specifies a single pool and
-    // expects it to just work. Without this, the server would complain that it
-    // doesn't have IP address on its interfaces that matches that
-    // configuration. Such requirement makes sense in IPv4, but not in IPv6.
-    // The server does not need to have a global address (using just link-local
-    // is ok for DHCPv6 server) from the pool it serves.
-    if ((subnets6_.size() == 1) && hint.getAddress().to_v6().is_link_local()) {
-        return (subnets6_[0]);
-    }
-
-    // If there is more than one, we need to choose the proper one
-    for (Subnet6Collection::iterator subnet = subnets6_.begin();
-         subnet != subnets6_.end(); ++subnet) {
-        if ((*subnet)->inRange(hint)) {
-            return (*subnet);
-        }
-    }
-
-    // sorry, we don't support that subnet
-    return (Subnet6Ptr());
-}
-
-Subnet6Ptr CfgMgr::getSubnet6(OptionPtr /*interfaceId*/) {
-    /// @todo: Implement get subnet6 by interface-id (for relayed traffic)
-    isc_throw(NotImplemented, "Relayed DHCPv6 traffic is not supported yet.");
-}
-
-void CfgMgr::addSubnet6(const Subnet6Ptr& subnet) {
-    /// @todo: Check that this new subnet does not cross boundaries of any
-    /// other already defined subnet.
-    subnets6_.push_back(subnet);
-}
-
-Subnet4Ptr
-CfgMgr::getSubnet4(const isc::asiolink::IOAddress& hint) {
-
-    // If there's only one subnet configured, let's just use it
-    // The idea is to keep small deployments easy. In a small network - one
-    // router that also runs DHCPv6 server. Users specifies a single pool and
-    // expects it to just work. Without this, the server would complain that it
-    // doesn't have IP address on its interfaces that matches that
-    // configuration. Such requirement makes sense in IPv4, but not in IPv6.
-    // The server does not need to have a global address (using just link-local
-    // is ok for DHCPv6 server) from the pool it serves.
-    if (subnets4_.size() == 1) {
-        return (subnets4_[0]);
-    }
-
-    // If there is more than one, we need to choose the proper one
-    for (Subnet4Collection::iterator subnet = subnets4_.begin();
-         subnet != subnets4_.end(); ++subnet) {
-        if ((*subnet)->inRange(hint)) {
-            return (*subnet);
-        }
-    }
-
-    // sorry, we don't support that subnet
-    return (Subnet4Ptr());
-}
-
-void CfgMgr::addSubnet4(const Subnet4Ptr& subnet) {
-    /// @todo: Check that this new subnet does not cross boundaries of any
-    /// other already defined subnet.
-    subnets4_.push_back(subnet);
-}
-
-CfgMgr::CfgMgr() {
-}
-
-CfgMgr::~CfgMgr() {
-}
-
-}; // end of isc::dhcp namespace
-}; // end of isc namespace
diff --git a/src/lib/dhcp/cfgmgr.h b/src/lib/dhcp/cfgmgr.h
deleted file mode 100644
index ea8125f..0000000
--- a/src/lib/dhcp/cfgmgr.h
+++ /dev/null
@@ -1,165 +0,0 @@
-// 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 CFGMGR_H
-#define CFGMGR_H
-
-#include <string>
-#include <map>
-#include <vector>
-#include <boost/shared_ptr.hpp>
-#include <boost/noncopyable.hpp>
-#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 {
-
-
-/// @brief Configuration Manager
-///
-/// This singleton class holds the whole configuration for DHCPv4 and DHCPv6
-/// servers. It currently holds information about zero or more subnets6.
-/// Each subnet may contain zero or more pools. Pool4 and Pool6 is the most
-/// basic "chunk" of configuration. It contains a range of assigneable
-/// addresses.
-///
-/// Below is a sketch of configuration inheritance (not implemented yet).
-/// Let's investigate the following configuration:
-///
-/// preferred-lifetime 500;
-/// valid-lifetime 1000;
-/// subnet6 2001:db8:1::/48 {
-///     pool6 2001::db8:1::1 - 2001::db8:1::ff;
-/// };
-/// subnet6 2001:db8:2::/48 {
-///     valid-lifetime 2000;
-///     pool6 2001::db8:2::1 - 2001::db8:2::ff;
-/// };
-/// Parameters defined in a global scope are applicable to everything until
-/// they are overwritten in a smaller scope, in this case subnet6.
-/// In the example above, the first subnet6 has preferred lifetime of 500s
-/// and a valid lifetime of 1000s. The second subnet has preferred lifetime
-/// of 500s, but valid lifetime of 2000s.
-///
-/// Parameter inheritance is likely to be implemented in configuration handling
-/// routines, so there is no storage capability in a global scope for
-/// subnet-specific parameters.
-///
-/// @todo: Implement Subnet4 support (ticket #2237)
-/// @todo: Implement option definition support
-/// @todo: Implement parameter inheritance
-class CfgMgr : public boost::noncopyable {
-public:
-
-    /// @brief returns a single instance of Configuration Manager
-    ///
-    /// CfgMgr is a singleton and this method is the only way of
-    /// accessing it.
-    static CfgMgr& instance();
-
-    /// @brief get IPv6 subnet by address
-    ///
-    /// Finds a matching subnet, based on an address. This can be used
-    /// in two cases: when trying to find an appropriate lease based on
-    /// a) relay link address (that must be the address that is on link)
-    /// b) our global address on the interface the message was received on
-    ///    (for directly connected clients)
-    ///
-    /// @param hint an address that belongs to a searched subnet
-    Subnet6Ptr getSubnet6(const isc::asiolink::IOAddress& hint);
-
-    /// @brief get IPv6 subnet by interface-id
-    ///
-    /// Another possibility to find a subnet is based on interface-id.
-    ///
-    /// @param interface_id content of interface-id option returned by a relay
-    /// @todo This method is not currently supported.
-    Subnet6Ptr getSubnet6(OptionPtr interface_id);
-
-    /// @brief adds an IPv6 subnet
-    void addSubnet6(const Subnet6Ptr& subnet);
-
-    /// @todo: Add subnet6 removal routines. Currently it is not possible
-    /// to remove subnets. The only case where subnet6 removal would be
-    /// needed is a dynamic server reconfiguration - a use case that is not
-    /// planned to be supported any time soon.
-
-    /// @brief removes all subnets
-    ///
-    /// This method removes all existing subnets. It is used during
-    /// reconfiguration - old configuration is wiped and new definitions
-    /// are used to recreate subnets.
-    ///
-    /// @todo Implement more intelligent approach. Note that comparison
-    /// between old and new configuration is tricky. For example: is
-    /// 2000::/64 and 2000::/48 the same subnet or is it something
-    /// completely new?
-    void deleteSubnets6() {
-        subnets6_.clear();
-    }
-
-    /// @brief get IPv4 subnet by address
-    ///
-    /// Finds a matching subnet, based on an address. This can be used
-    /// in two cases: when trying to find an appropriate lease based on
-    /// a) relay link address (that must be the address that is on link)
-    /// b) our global address on the interface the message was received on
-    ///    (for directly connected clients)
-    ///
-    /// @param hint an address that belongs to a searched subnet
-    Subnet4Ptr getSubnet4(const isc::asiolink::IOAddress& hint);
-
-    /// @brief adds a subnet4
-    void addSubnet4(const Subnet4Ptr& subnet);
-
-    /// @brief removes all IPv4 subnets
-    void removeSubnets4();
-protected:
-
-    /// @brief Protected constructor.
-    ///
-    /// This constructor is protected for 2 reasons. First, it forbids any
-    /// instantiations of this class (CfgMgr is a singleton). Second, it
-    /// allows derived class to instantiate it. That is useful for testing
-    /// purposes.
-    CfgMgr();
-
-    /// @brief virtual desctructor
-    virtual ~CfgMgr();
-
-    /// @brief a container for IPv6 subnets.
-    ///
-    /// That is a simple vector of pointers. It does not make much sense to
-    /// optimize access time (e.g. using a map), because typical search
-    /// pattern will use calling inRange() method on each subnet until
-    /// a match is found.
-    Subnet6Collection subnets6_;
-
-    /// @brief a container for IPv4 subnets.
-    ///
-    /// That is a simple vector of pointers. It does not make much sense to
-    /// optimize access time (e.g. using a map), because typical search
-    /// pattern will use calling inRange() method on each subnet until
-    /// a match is found.
-    Subnet4Collection subnets4_;
-};
-
-} // namespace isc::dhcp
-} // namespace isc
-
-#endif // CFGMGR_H
diff --git a/src/lib/dhcp/database_backends.dox b/src/lib/dhcp/database_backends.dox
deleted file mode 100644
index 8eeb5c5..0000000
--- a/src/lib/dhcp/database_backends.dox
+++ /dev/null
@@ -1,64 +0,0 @@
-/**
-  @page dhcp-database-backends DHCP Database Back-Ends
-
-  All DHCP lease data is stored in some form of database, the interface
-  to this being through the Lease Manager.
-
-  All backend classes such as isc::dhcp::MySqlLeaseMgr are derived from
-  the abstract isc::dhcp::LeaseMgr class.  This provides methods to
-  create, retrieve, modify and delete leases in the database.
-
-  @section dhcpdb-instantiation Instantiation of Lease Managers
-
-  A lease manager is instantiated through the LeaseMgrFactory class.  This
-  has three methods:
-
-  - isc::dhcp::LeaseMgrFactory::create - Creates a singleton Lease
-    Manager of the appropriate type.
-  - isc::dhcp::LeaseMgrFactory::instance - Returns a reference to the
-    the instance of the Lease Manager.
-  - isc::dhcp::LeaseMgrFactory::destroy - Destroys the singleton lease manager.
-
-  The selection of the Lease Manager (and thus the backend database) is
-  controlled by the connection string passed to
-  isc::dhcp::LeaseMgrFactory::create.  This is a set of "keyword=value" pairs
-  (no embedded spaces), each pair separated by a space from the others, e.g.
-
-  \code
-  type=mysql user=keatest password=keatest name=keatest host=localhost
-  \endcode
-
-  The following keywords are used for all backends:
-
-  - <b>type</b> - specifies the type of database backend.  The following values
-  for the type keyword are supported:
-     - <b>mysql</b> - Use MySQL as the database
-
-  The following sections list the database-specific keywords:
-
-  @subsection dhcpdb-keywords-mysql MySQL connection string keywords
-
-  - <b>host</b> - host on which the selected database is running.  If not
-  supplied, "localhost" is assumed.
-  - <b>name</b> - name of the MySQL database to access.  There is no default -
-  this must always be supplied.
-  - <b>password</b> - password for the selected user ID (see below).  If not
-  specified, no password is used.
-  - <b>user</b> - database user ID under which the database is accessed.  If not
-    specified, no user ID is used - the database is assumed to be open.
-
-
-  @section dhcp-backend-unittest Running Unit Tests
-
-  With the use of databases requiring separate authorisation, there are
-  certain database-specific pre-requisites for successfully running the unit
-  tests.  These are listed in the following sections.
-
-  @subsection dhcp-mysql-unittest MySQL
-
-  A database called <i>keatest</i> needs to be set up using the MySQL
-  <b>CREATE DATABASE</b> command.  A database user, also called <i>keatest</i>
-  (with a password <i>keatest</i>) must be given full privileges in that
-  database.  The unit tests create the schema in the database before each test
-  and delete it afterwards.
-  */
diff --git a/src/lib/dhcp/dhcpdb_create.mysql b/src/lib/dhcp/dhcpdb_create.mysql
deleted file mode 100644
index 7a292ec..0000000
--- a/src/lib/dhcp/dhcpdb_create.mysql
+++ /dev/null
@@ -1,115 +0,0 @@
-# Copyright (C) 2012  Internet Systems Consortium.
-#
-# Permission to use, copy, modify, and 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 INTERNET SYSTEMS CONSORTIUM
-# DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
-# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
-# INTERNET SYSTEMS CONSORTIUM 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.
-
-# This is the BIND 10 DHCP schema specification for MySQL.
-#
-# The schema is reasonably portable (with the exception of the engine
-# specification, which is MySQL-specific).  Minor changes might be needed for
-# other databases.
-
-# To create the schema, either type the command:
-#
-# mysql -u <user> -p <password> <database> < dhcpdb_create.mysql
-#
-# ... at the command prompt, or log in to the MySQL database and at the "mysql>"
-# prompt, issue the command:
-#
-# source dhcpdb_create.mysql
-
-
-# Holds the IPv4 leases.
-CREATE TABLE lease4 (
-    address INT UNSIGNED PRIMARY KEY NOT NULL,  # IPv4 address
-    hwaddr VARBINARY(20),                       # Hardware address
-    client_id VARBINARY(128),                   # Client ID
-    lease_time INT UNSIGNED,                    # Length of the lease (seconds)
-    expire TIMESTAMP,                           # Expiration time of the lease
-    subnet_id INT UNSIGNED                      # Subnet identification
-    ) ENGINE = INNODB;
-
-# Holds the IPv6 leases.
-# N.B. The use of a VARCHAR for the address is temporary for development:
-# it will eventually be replaced by BINARY(16).
-CREATE TABLE lease6 (
-    address VARCHAR(40) PRIMARY KEY NOT NULL,   # IPv6 address
-    duid VARBINARY(128),                        # DUID
-    valid_lifetime INT UNSIGNED,                # Length of the lease (seconds)
-    expire TIMESTAMP,                           # Expiration time of the lease
-    subnet_id INT UNSIGNED,                     # Subnet identification
-    pref_lifetime INT UNSIGNED,                 # Preferred lifetime
-    lease_type TINYINT,                         # Lease type (see lease6_types
-                                                #    table for possible values)
-    iaid INT UNSIGNED,                          # See Section 10 of RFC 3315
-    prefix_len TINYINT UNSIGNED                 # For IA_PD only
-    ) ENGINE = INNODB;
-
-# ... and a definition of lease6 types.  This table is a convenience for
-# users of the database - if they want to view the lease table and use the
-# type names, they can join this table with the lease6 table
-CREATE TABLE lease6_types (
-    lease_type TINYINT PRIMARY KEY NOT NULL,    # Lease type code.
-    name VARCHAR(5)                             # Name of the lease type
-    );
-START TRANSACTION;
-INSERT INTO lease6_types VALUES (0, "IA_NA");   # Non-temporary v6 addresses
-INSERT INTO lease6_types VALUES (1, "IA_TA");   # Temporary v6 addresses
-INSERT INTO lease6_types VALUES (2, "IA_PD");   # Prefix delegations
-COMMIT;
-
-# Finally, the version of the schema.  We start at 0.1 during development.
-# This table is only modified during schema upgrades.  For historical reasons
-# (related to the names of the columns in the BIND 10 DNS database file), the
-# first column is called "version" and not "major".
-CREATE TABLE schema_version (
-    version INT PRIMARY KEY NOT NULL,       # Major version number
-    minor INT                               # Minor version number
-    );
-START TRANSACTION;
-INSERT INTO schema_version VALUES (0, 1);
-COMMIT;
-
-# Notes:
-#
-# Indexes
-# =======
-# It is likely that additional indexes will be needed.  However, the
-# increase in lookup performance from these will come at the expense
-# of a decrease in performance during insert operations due to the need
-# to update the indexes.  For this reason, the need for additional indexes
-# will be determined by experiment during performance tests.
-#
-# The most likely additional indexes will cover the following columns:
-#
-# expire
-# To speed up the deletion of expired leases from the database.
-#
-# hwaddr and client_id
-# For lease stability: if a client requests a new lease, try to find an
-# existing or recently expired lease for it so that it can keep using the
-# same IP address.
-#
-# Field Sizes
-# ===========
-# If any of the VARxxx field sizes are altered, the lengths in the MySQL
-# backend source file (mysql_lease_mgr.cc) must be correspondingly changed.
-#
-# Portability
-# ===========
-# The "ENGINE = INNODB" on some tables is not portablea to another database
-# and will need to be removed.
-#
-# Some columns contain binary data so are stored as VARBINARY instead of
-# VARCHAR.  This may be non-portable between databases: in this case, the
-# definition should be changed to VARCHAR.
diff --git a/src/lib/dhcp/lease_mgr.cc b/src/lib/dhcp/lease_mgr.cc
deleted file mode 100644
index c7dba6c..0000000
--- a/src/lib/dhcp/lease_mgr.cc
+++ /dev/null
@@ -1,98 +0,0 @@
-// Copyright (C) 2012 Internet Systems Consortium, Inc. ("ISC")
-//
-// Permission to use, copy, modify, and/or distribute this software for any
-// purpose with or without fee is hereby granted, provided that the above
-// copyright notice and this permission notice appear in all copies.
-//
-// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
-// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
-// AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
-// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
-// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
-// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
-// PERFORMANCE OF THIS SOFTWARE.
-
-#include <dhcp/lease_mgr.h>
-#include <exceptions/exceptions.h>
-
-#include <boost/foreach.hpp>
-#include <boost/algorithm/string.hpp>
-
-#include <algorithm>
-#include <iostream>
-#include <iterator>
-#include <map>
-#include <sstream>
-#include <string>
-
-#include <time.h>
-
-using namespace std;
-
-using namespace isc::dhcp;
-
-Lease6::Lease6(LeaseType type, const isc::asiolink::IOAddress& addr, DuidPtr duid,
-               uint32_t iaid, uint32_t preferred, uint32_t valid, uint32_t t1,
-               uint32_t t2, SubnetID subnet_id, uint8_t prefixlen)
-    :type_(type), addr_(addr), prefixlen_(prefixlen), iaid_(iaid), duid_(duid),
-     preferred_lft_(preferred), valid_lft_(valid), t1_(t1), t2_(t2),
-     subnet_id_(subnet_id), fixed_(false), fqdn_fwd_(false),
-     fqdn_rev_(false) {
-    if (!duid) {
-        isc_throw(InvalidOperation, "DUID must be specified for a lease");
-    }
-
-    cltt_ = time(NULL);
-}
-
-std::string LeaseMgr::getParameter(const std::string& name) const {
-    ParameterMap::const_iterator param = parameters_.find(name);
-    if (param == parameters_.end()) {
-        isc_throw(BadValue, "Parameter not found");
-    }
-    return (param->second);
-}
-
-std::string
-Lease6::toText() {
-    ostringstream stream;
-
-    stream << "Type:          " << static_cast<int>(type_) << " (";
-    switch (type_) {
-        case Lease6::LEASE_IA_NA:
-            stream << "IA_NA)\n";
-            break;
-        case Lease6::LEASE_IA_TA:
-            stream << "IA_TA)\n";
-            break;
-        case Lease6::LEASE_IA_PD:
-            stream << "IA_PD)\n";
-            break;
-        default:
-            stream << "unknown)\n";
-    }
-    stream << "Address:       " << addr_.toText() << "\n"
-           << "Prefix length: " << static_cast<int>(prefixlen_) << "\n"
-           << "IAID:          " << iaid_ << "\n"
-           << "Pref life:     " << preferred_lft_ << "\n"
-           << "Valid life:    " << valid_lft_ << "\n"
-           << "Cltt:          " << cltt_ << "\n"
-           << "Subnet ID:     " << subnet_id_ << "\n";
-
-    return (stream.str());
-}
-
-bool
-Lease6::operator==(const Lease6& other) const {
-    return (
-        type_ == other.type_ &&
-        addr_ == other.addr_ &&
-        prefixlen_ == other.prefixlen_ &&
-        iaid_ == other.iaid_ &&
-        *duid_ == *other.duid_ &&
-        preferred_lft_ == other.preferred_lft_ &&
-        valid_lft_ == other.valid_lft_ &&
-        cltt_ == other.cltt_ &&
-        subnet_id_ == other.subnet_id_
-        );
-}
diff --git a/src/lib/dhcp/lease_mgr.h b/src/lib/dhcp/lease_mgr.h
deleted file mode 100644
index 7819aad..0000000
--- a/src/lib/dhcp/lease_mgr.h
+++ /dev/null
@@ -1,577 +0,0 @@
-// 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 LEASE_MGR_H
-#define LEASE_MGR_H
-
-#include <asiolink/io_address.h>
-#include <dhcp/duid.h>
-#include <dhcp/option.h>
-#include <dhcp/subnet.h>
-#include <exceptions/exceptions.h>
-
-#include <boost/noncopyable.hpp>
-#include <boost/shared_ptr.hpp>
-
-#include <fstream>
-#include <map>
-#include <string>
-#include <utility>
-#include <vector>
-
-/// @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.
-
-#include <iostream>
-
-namespace isc {
-namespace dhcp {
-
-/// @brief Exception thrown if name of database is not specified
-class NoDatabaseName : public Exception {
-public:
-    NoDatabaseName(const char* file, size_t line, const char* what) :
-        isc::Exception(file, line, what) {}
-};
-
-/// @brief Exception thrown on failure to open database
-class DbOpenError : public Exception {
-public:
-    DbOpenError(const char* file, size_t line, const char* what) :
-        isc::Exception(file, line, what) {}
-};
-
-/// @brief Exception thrown on failure to execute a database function
-class DbOperationError : public Exception {
-public:
-    DbOperationError(const char* file, size_t line, const char* what) :
-        isc::Exception(file, line, what) {}
-};
-
-/// @brief Attempt to update lease that was not there
-class NoSuchLease : public Exception {
-public:
-    NoSuchLease(const char* file, size_t line, const char* what) :
-        isc::Exception(file, line, what) {}
-};
-
-/// @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 Constructor
-    ///
-    /// Initialize fields that don't have a default constructor.
-    /// @todo Remove this
-    Lease4() : addr_(0) {}
-};
-
-/// @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;
-
-    Lease6(LeaseType type, const isc::asiolink::IOAddress& addr, DuidPtr duid,
-           uint32_t iaid, uint32_t preferred, uint32_t valid, uint32_t t1,
-           uint32_t t2, SubnetID subnet_id, uint8_t prefixlen_ = 0);
-
-    /// @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 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.
-    /// This value will also be useful for failover to calculate the next expected
-    /// client transmission time.
-    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 Constructor
-    ///
-    /// Initialize fields that don't have a default constructor.
-    Lease6() : addr_("::") {}
-
-    /// @brief Convert Lease6 to Printable Form
-    ///
-    /// @return String form of the lease
-    std::string toText();
-
-    /// @brief Compare two leases for equality
-    ///
-    /// @param other lease6 object with which to compare
-    bool operator==(const Lease6& other) const;
-
-    /// @brief Compare two leases for inequality
-    ///
-    /// @param other lease6 object with which to compare
-    bool operator!=(const Lease6& other) const {
-        return (!operator==(other));
-    }
-
-};
-
-/// @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<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.
-///
-/// As all methods are virtual, this class throws no exceptions.  However,
-/// methods in concrete implementations of this class may throw exceptions:
-/// see the documentation of those classes for details.
-class LeaseMgr {
-public:
-    /// Client Hardware address
-    typedef std::vector<uint8_t> HWAddr;
-
-    /// Database configuration parameter map
-    typedef std::map<std::string, std::string> ParameterMap;
-
-    /// @brief Constructor
-    ///
-    /// @param parameters A data structure relating keywords and values
-    ///        concerned with the database.
-    LeaseMgr(const ParameterMap& parameters) : parameters_(parameters)
-    {}
-
-    /// @brief Destructor
-    virtual ~LeaseMgr()
-    {}
-
-    /// @brief Adds an IPv4 lease.
-    ///
-    /// @param lease lease to be added
-    ///
-    /// @result true if the lease was added, false if not (because a lease
-    ///         with the same address was already there).
-    virtual bool addLease(const Lease4Ptr& lease) = 0;
-
-    /// @brief Adds an IPv6 lease.
-    ///
-    /// @param lease lease to be added
-    ///
-    /// @result true if the lease was added, false if not (because a lease
-    ///         with the same address was already there).
-    virtual bool addLease(const Lease6Ptr& lease) = 0;
-
-    /// @brief Returns 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(const 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
-    ///
-    /// @return smart pointer to the lease (or NULL if a lease is not found)
-    virtual Lease4Ptr getLease4(const 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(const 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(const Lease4Ptr& lease4) = 0;
-
-    /// @brief Updates IPv6 lease.
-    ///
-    /// @param lease6 The lease to be updated.
-    virtual void updateLease6(const 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(const isc::asiolink::IOAddress& addr) = 0;
-
-    /// @brief Deletes a lease.
-    ///
-    /// @param addr IPv6 address of the lease to be deleted.
-    ///
-    /// @return true if deletion was successful, false if no such lease exists
-    virtual bool deleteLease6(const isc::asiolink::IOAddress& addr) = 0;
-
-    /// @brief Return backend type
-    ///
-    /// Returns the type of the backend (e.g. "mysql", "memfile" etc.)
-    ///
-    /// @return Type of the backend.
-    virtual std::string getType() const = 0;
-
-    /// @brief Returns backend name.
-    ///
-    /// If the backend is a database, this is the name of the database or the
-    /// file.  Otherwise it is just the same as the type.
-    ///
-    /// @return Name of the backend.
-    virtual std::string getName() const = 0;
-
-    /// @brief Returns description of the backend.
-    ///
-    /// This description may be multiline text that describes the backend.
-    ///
-    /// @return Description of the backend.
-    virtual std::string getDescription() const = 0;
-
-    /// @brief Returns backend version.
-    ///
-    /// @return Version number as a pair of unsigned integers.  "first" is the
-    ///         major version number, "second" the minor number.
-    ///
-    /// @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::pair<uint32_t, uint32_t> getVersion() const = 0;
-
-    /// @brief Commit Transactions
-    ///
-    /// Commits all pending database operations.  On databases that don't
-    /// support transactions, this is a no-op.
-    virtual void commit() = 0;
-
-    /// @brief Rollback Transactions
-    ///
-    /// Rolls back all pending database operations.  On databases that don't
-    /// support transactions, this is a no-op.
-    virtual void rollback() = 0;
-
-    /// @todo: Add host management here
-    /// As host reservation is outside of scope for 2012, support for hosts
-    /// is currently postponed.
-
-    /// @brief returns value of the parameter
-    virtual std::string getParameter(const std::string& name) const;
-
-private:
-    /// @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.
-    ParameterMap parameters_;
-};
-
-}; // end of isc::dhcp namespace
-}; // end of isc namespace
-
-#endif // LEASE_MGR_H
diff --git a/src/lib/dhcp/lease_mgr_factory.cc b/src/lib/dhcp/lease_mgr_factory.cc
deleted file mode 100644
index 7e75633..0000000
--- a/src/lib/dhcp/lease_mgr_factory.cc
+++ /dev/null
@@ -1,117 +0,0 @@
-// 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 "config.h"
-
-#include <dhcp/lease_mgr_factory.h>
-#include <dhcp/memfile_lease_mgr.h>
-#ifdef HAVE_MYSQL
-#include <dhcp/mysql_lease_mgr.h>
-#endif
-
-#include <boost/algorithm/string.hpp>
-#include <boost/foreach.hpp>
-#include <boost/scoped_ptr.hpp>
-
-#include <algorithm>
-#include <iostream>
-#include <iterator>
-#include <map>
-#include <sstream>
-#include <utility>
-
-using namespace std;
-
-namespace isc {
-namespace dhcp {
-
-boost::scoped_ptr<LeaseMgr>&
-LeaseMgrFactory::getLeaseMgrPtr() {
-    static boost::scoped_ptr<LeaseMgr> leaseMgrPtr;
-    return (leaseMgrPtr);
-}
-
-LeaseMgr::ParameterMap
-LeaseMgrFactory::parse(const std::string& dbconfig) {
-    LeaseMgr::ParameterMap mapped_tokens;
-
-    if (!dbconfig.empty()) {
-        vector<string> tokens;
-
-        // We need to pass a string to is_any_of, not just char*. Otherwise
-        // there are cryptic warnings on Debian6 running g++ 4.4 in
-        // /usr/include/c++/4.4/bits/stl_algo.h:2178 "array subscript is above
-        // array bounds"
-        boost::split(tokens, dbconfig, boost::is_any_of( string("\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);
-                mapped_tokens.insert(make_pair(name, value));
-            } else {
-                isc_throw(InvalidParameter, "Cannot parse " << token
-                          << ", expected format is name=value");
-            }
-        }
-    }
-
-    return (mapped_tokens);
-}
-
-void
-LeaseMgrFactory::create(const std::string& dbconfig) {
-    const std::string type = "type";
-
-    // Is "type" present?
-    LeaseMgr::ParameterMap parameters = parse(dbconfig);
-    if (parameters.find(type) == parameters.end()) {
-        isc_throw(InvalidParameter, "Database configuration parameters do not "
-                  "contain the 'type' keyword");
-    }
-
-    // Yes, check what it is.
-#ifdef HAVE_MYSQL
-    if (parameters[type] == string("mysql")) {
-        getLeaseMgrPtr().reset(new MySqlLeaseMgr(parameters));
-        return;
-    }
-#endif
-    if (parameters[type] == string("memfile")) {
-        getLeaseMgrPtr().reset(new Memfile_LeaseMgr(parameters));
-        return;
-    }
-
-    // Get here on no match
-    isc_throw(InvalidType, "Database configuration parameter 'type' does "
-              "not specify a supported database backend");
-}
-
-void
-LeaseMgrFactory::destroy() {
-    getLeaseMgrPtr().reset();
-}
-
-LeaseMgr&
-LeaseMgrFactory::instance() {
-    LeaseMgr* lmptr = getLeaseMgrPtr().get();
-    if (lmptr == NULL) {
-        isc_throw(NoLeaseManager, "no current lease manager is available");
-    }
-    return (*lmptr);
-}
-
-
-}; // namespace dhcp
-}; // namespace isc
diff --git a/src/lib/dhcp/lease_mgr_factory.h b/src/lib/dhcp/lease_mgr_factory.h
deleted file mode 100644
index c691e12..0000000
--- a/src/lib/dhcp/lease_mgr_factory.h
+++ /dev/null
@@ -1,123 +0,0 @@
-// 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 LEASE_MGR_FACTORY_H
-#define LEASE_MGR_FACTORY_H
-
-#include <string>
-#include <dhcp/lease_mgr.h>
-#include <exceptions/exceptions.h>
-
-namespace isc {
-namespace dhcp {
-
-/// @brief Invalid type exception
-///
-/// Thrown when the factory doesn't recognise the type of the backend.
-class InvalidType : public Exception {
-public:
-    InvalidType(const char* file, size_t line, const char* what) :
-        isc::Exception(file, line, what) {}
-};
-
-/// @brief No lease manager exception
-///
-/// Thrown if an attempt is made to get a reference to the current lease
-/// manager and none is currently available.
-class NoLeaseManager : public Exception {
-public:
-    NoLeaseManager(const char* file, size_t line, const char* what) :
-        isc::Exception(file, line, what) {}
-};
-
-/// @brief Lease Manager Factory
-///
-/// This class comprises nothing but static methods used to create a lease
-/// manager.  It analyzes the database information passed to the creation
-/// function and instantiates an appropriate lease manager based on the type
-/// requested.
-///
-/// Strictly speaking these functions could be stand-alone functions.  However,
-/// it is convenient to encapsulate them in a class for naming purposes.
-///
-/// @todo: Will need to develop some form of registration mechanism for
-///        user-supplied backends (so that there is no need to modify the code).
-class LeaseMgrFactory {
-public:
-    /// @brief Create an instance of a lease manager.
-    ///
-    /// Each database backend has its own lease manager type.  This static
-    /// method sets the "current" lease manager to be a manager of the
-    /// appropriate type.  The actual lease manager is returned by the
-    /// "instance" method.
-    ///
-    /// @note When called, the current lease manager is <b>always</b> destroyed
-    ///       and a new one created - even if the parameters are the same.
-    ///
-    /// dbconfig is a generic way of passing parameters. Parameters are passed
-    /// in the "name=value" format, separated by spaces.  The data MUST include
-    /// a keyword/value pair of the form "type=dbtype" giving the database
-    /// type, e.q. "mysql" or "sqlite3".
-    ///
-    /// @param dbconfig Database configuration parameters.  These are in
-    ///        the form of "keyword=value" pairs, separated by spaces. These
-    ///        are back-end specific, although must include the "type" keyword
-    ///        which gives the backend in use.
-    ///
-    /// @throw isc::InvalidParameter dbconfig string does not contain the "type"
-    ///        keyword.
-    /// @throw isc::dhcp::InvalidType The "type" keyword in dbconfig does not
-    ///        identify a supported backend.
-    static void create(const std::string& dbconfig);
-
-    /// @brief Destroy lease manager
-    ///
-    /// Destroys the current lease manager object.  This should have the effect
-    /// of closing the database connection.  The method is a no-op if no
-    /// lease manager is available.
-    static void destroy();
-
-    /// @brief Return Current Lease Manager
-    ///
-    /// Returns an instance of the "current" lease manager.  An exception
-    /// will be thrown if none is available.
-    ///
-    /// @throw isc::dhcp::NoLeaseManager No lease manager is available: use
-    ///        create() to create one before calling this method.
-    static LeaseMgr& instance();
-
-    /// @brief Parse Database Parameters
-    ///
-    /// Parses the string of "keyword=value" pairs and separates them
-    /// out into the map.
-    ///
-    /// @param dbconfig Database configuration string
-    ///
-    /// @return std::map<std::string, std::string> Map of keyword/value pairs.
-    static LeaseMgr::ParameterMap parse(const std::string& dbconfig);
-
-private:
-    /// @brief Hold pointer to lease manager
-    ///
-    /// Holds a pointer to the singleton lease manager.  The singleton
-    /// is encapsulated in this method to avoid a "static initialization
-    /// fiasco" if defined in an external static variable.
-    static boost::scoped_ptr<LeaseMgr>& getLeaseMgrPtr();
-
-};
-
-}; // end of isc::dhcp namespace
-}; // end of isc namespace
-
-#endif // LEASE_MGR_FACTORY_H
diff --git a/src/lib/dhcp/memfile_lease_mgr.cc b/src/lib/dhcp/memfile_lease_mgr.cc
deleted file mode 100644
index 1424b39..0000000
--- a/src/lib/dhcp/memfile_lease_mgr.cc
+++ /dev/null
@@ -1,132 +0,0 @@
-// 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 <iostream>
-
-#include <dhcp/memfile_lease_mgr.h>
-
-using namespace isc::dhcp;
-
-Memfile_LeaseMgr::Memfile_LeaseMgr(const ParameterMap& parameters)
-    : LeaseMgr(parameters) {
-    std::cout << "Warning: Using memfile database backend. It is usable for" << std::endl;
-    std::cout << "Warning: limited testing only. File support not implemented yet." << std::endl;
-    std::cout << "Warning: Leases will be lost after restart." << std::endl;
-}
-
-Memfile_LeaseMgr::~Memfile_LeaseMgr() {
-}
-
-bool Memfile_LeaseMgr::addLease(const Lease4Ptr&) {
-    return (false);
-}
-
-bool Memfile_LeaseMgr::addLease(const Lease6Ptr& lease) {
-    if (getLease6(lease->addr_)) {
-        // there is a lease with specified address already
-        return (false);
-    }
-    storage6_.insert(lease);
-    return (true);
-}
-
-Lease4Ptr Memfile_LeaseMgr::getLease4(const isc::asiolink::IOAddress&) const {
-    return (Lease4Ptr());
-}
-
-Lease4Collection Memfile_LeaseMgr::getLease4(const HWAddr& ) const {
-    return (Lease4Collection());
-}
-
-Lease4Ptr Memfile_LeaseMgr::getLease4(const 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(const isc::asiolink::IOAddress& addr) const {
-    Lease6Storage::iterator l = storage6_.find(addr);
-    if (l == storage6_.end()) {
-        return (Lease6Ptr());
-    } else {
-        return (*l);
-    }
-}
-
-Lease6Collection Memfile_LeaseMgr::getLease6(const DUID& , uint32_t ) const {
-    return (Lease6Collection());
-}
-
-Lease6Ptr Memfile_LeaseMgr::getLease6(const DUID& duid, uint32_t iaid,
-                                      SubnetID subnet_id) const {
-    /// @todo: Slow, naive implementation. Write it using additional indexes
-    for (Lease6Storage::iterator l = storage6_.begin(); l != storage6_.end(); ++l) {
-        if ( (*((*l)->duid_) == duid) &&
-             ( (*l)->iaid_ == iaid) &&
-             ( (*l)->subnet_id_ == subnet_id)) {
-            return (*l);
-        }
-    }
-    return (Lease6Ptr());
-}
-
-void Memfile_LeaseMgr::updateLease4(const Lease4Ptr& ) {
-}
-
-void Memfile_LeaseMgr::updateLease6(const Lease6Ptr& ) {
-
-}
-
-bool Memfile_LeaseMgr::deleteLease4(const isc::asiolink::IOAddress&) {
-    return (false);
-}
-
-bool Memfile_LeaseMgr::deleteLease6(const isc::asiolink::IOAddress& addr) {
-    Lease6Storage::iterator l = storage6_.find(addr);
-    if (l == storage6_.end()) {
-        // no such lease
-        return (false);
-    } else {
-        storage6_.erase(l);
-        return (true);
-    }
-}
-
-std::string Memfile_LeaseMgr::getDescription() const {
-    return (std::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."));
-}
-
-void
-Memfile_LeaseMgr::commit() {
-}
-
-void
-Memfile_LeaseMgr::rollback() {
-}
diff --git a/src/lib/dhcp/memfile_lease_mgr.h b/src/lib/dhcp/memfile_lease_mgr.h
deleted file mode 100644
index 9120c5c..0000000
--- a/src/lib/dhcp/memfile_lease_mgr.h
+++ /dev/null
@@ -1,258 +0,0 @@
-// 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 MEMFILE_LEASE_MGR_H
-#define MEMFILE_LEASE_MGR_H
-
-#include <boost/multi_index_container.hpp>
-#include <boost/multi_index/indexed_by.hpp>
-#include <boost/multi_index/ordered_index.hpp>
-#include <boost/multi_index/member.hpp>
-
-#include <dhcp/lease_mgr.h>
-
-namespace isc {
-namespace dhcp {
-
-// This is a concrete implementation of a Lease database.
-//
-// It is for testing purposes only. It is NOT a production code.
-//
-// 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 parameters A data structure relating keywords and values
-    ///        concerned with the database.
-    Memfile_LeaseMgr(const ParameterMap& parameters);
-
-    /// @brief Destructor (closes file)
-    virtual ~Memfile_LeaseMgr();
-
-    /// @brief Adds an IPv4 lease.
-    ///
-    /// @todo Not implemented yet
-    /// @param lease lease to be added
-    virtual bool addLease(const Lease4Ptr& lease);
-
-    /// @brief Adds an IPv6 lease.
-    ///
-    /// @param lease lease to be added
-    virtual bool addLease(const Lease6Ptr& lease);
-
-    /// @brief Returns existing IPv4 lease for specified IPv4 address.
-    ///
-    /// @todo Not implemented yet
-    /// @param addr address of the searched lease
-    ///
-    /// @return a collection of leases
-    virtual Lease4Ptr getLease4(const isc::asiolink::IOAddress& addr) const;
-
-    /// @brief Returns existing IPv4 lease for specific address and subnet
-    ///
-    /// @todo Not implemented yet
-    /// @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(const isc::asiolink::IOAddress& addr,
-                                SubnetID subnet_id) const;
-
-    /// @brief Returns existing IPv4 leases for specified hardware address.
-    ///
-    /// @todo Not implemented yet
-    ///
-    /// 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
-    ///
-    /// @todo Not implemented yet
-    ///
-    /// 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
-    ///
-    /// @todo Not implemented yet
-    ///
-    /// @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.
-    ///
-    /// @todo Not implemented yet
-    ///
-    /// @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)
-    virtual Lease6Ptr getLease6(const isc::asiolink::IOAddress& addr) const;
-
-    /// @brief Returns existing IPv6 lease for a given DUID+IA combination
-    ///
-    /// @todo Not implemented yet
-    ///
-    /// @param duid client DUID
-    /// @param iaid IA identifier
-    ///
-    /// @return collection of IPv6 leases
-    virtual Lease6Collection getLease6(const DUID& duid, uint32_t iaid) const;
-
-    /// @brief Returns existing IPv6 lease for a given DUID+IA combination
-    ///
-    /// @todo Not implemented yet
-    ///
-    /// @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)
-    virtual Lease6Ptr getLease6(const DUID& duid, uint32_t iaid, SubnetID subnet_id) const;
-
-    /// @brief Updates IPv4 lease.
-    ///
-    /// @todo Not implemented yet
-    ///
-    /// @param lease4 The lease to be updated.
-    ///
-    /// If no such lease is present, an exception will be thrown.
-    virtual void updateLease4(const Lease4Ptr& lease4);
-
-    /// @brief Updates IPv4 lease.
-    ///
-    /// @todo Not implemented yet
-    ///
-    /// @param lease6 The lease to be updated.
-    ///
-    /// If no such lease is present, an exception will be thrown.
-    virtual void updateLease6(const 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
-    virtual bool deleteLease4(const isc::asiolink::IOAddress& 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
-    virtual bool deleteLease6(const isc::asiolink::IOAddress& addr);
-
-    /// @brief Return backend type
-    ///
-    /// Returns the type of the backend.
-    ///
-    /// @return Type of the backend.
-    virtual std::string getType() const {
-        return (std::string("memfile"));
-    }
-
-    /// @brief Returns backend name.
-    ///
-    /// As there is no variation, in this case we return the type of the
-    /// backend.
-    ///
-    /// @return Name of the backend.
-    virtual std::string getName() const {
-        return ("memfile");
-    }
-
-    /// @brief Returns description of the backend.
-    ///
-    /// This description may be multiline text that describes the backend.
-    ///
-    /// @return Description of the backend.
-    virtual std::string getDescription() const;
-
-    /// @brief Returns backend version.
-    ///
-    /// @return Version number as a pair of unsigned integers.  "first" is the
-    ///         major version number, "second" the minor number.
-    virtual std::pair<uint32_t, uint32_t> getVersion() const {
-        return (std::make_pair(1, 0));
-    }
-
-    /// @brief Commit Transactions
-    ///
-    /// Commits all pending database operations.  On databases that don't
-    /// support transactions, this is a no-op.
-    virtual void commit();
-
-    /// @brief Rollback Transactions
-    ///
-    /// Rolls back all pending database operations.  On databases that don't
-    /// support transactions, this is a no-op.
-    virtual void rollback();
-
-protected:
-
-    typedef boost::multi_index_container< // this is a multi-index container...
-    Lease6Ptr, // it will hold shared_ptr to leases6
-        boost::multi_index::indexed_by< // and will be sorted by
-            // IPv6 address that are unique. That particular key is a member
-            // of the Lease6 structure, is of type IOAddress and can be accessed
-            // by doing &Lease6::addr_
-            boost::multi_index::ordered_unique< 
-                boost::multi_index::member<Lease6, isc::asiolink::IOAddress, &Lease6::addr_> 
-            >
-        >
-    > Lease6Storage; // Let the whole contraption be called Lease6Storage.
-
-    Lease6Storage storage6_;
-};
-
-}; // end of isc::dhcp namespace
-}; // end of isc namespace
-
-#endif // MEMFILE_LEASE_MGR
-
diff --git a/src/lib/dhcp/mysql_lease_mgr.cc b/src/lib/dhcp/mysql_lease_mgr.cc
deleted file mode 100644
index 78013d7..0000000
--- a/src/lib/dhcp/mysql_lease_mgr.cc
+++ /dev/null
@@ -1,1140 +0,0 @@
-// 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 <config.h>
-
-#include <dhcp/mysql_lease_mgr.h>
-#include <asiolink/io_address.h>
-
-#include <mysql/mysqld_error.h>
-
-#include <iostream>
-#include <iomanip>
-#include <string>
-#include <time.h>
-
-using namespace isc;
-using namespace isc::dhcp;
-using namespace std;
-
-namespace {
-///@{
-/// @brief Maximum Size of Database Fields
-///
-/// The following constants define buffer sizes for variable length database
-/// fields.  The values should be greater than or equal to the length set in
-/// the schema definition.
-///
-/// The exception is the length of any VARCHAR fields: these should be set
-/// greater than or equal to the length of the field plus 2: this allows for
-/// the insertion of a trailing null regardless of whether the data returned
-/// contains a trailing null (the documentation is not clear on this point).
-
-const size_t ADDRESS6_TEXT_MAX_LEN = 42;    // Max size of a IPv6 text buffer
-const size_t DUID_MAX_LEN = 128;            // Max size of a DUID
-///@}
-
-/// @brief MySQL Selection Statements
-///
-/// Each statement is associated with the index, used by the various methods
-/// to access the prepared statement.
-struct TaggedStatement {
-    MySqlLeaseMgr::StatementIndex index;
-    const char*                   text;
-};
-
-TaggedStatement tagged_statements[] = {
-    {MySqlLeaseMgr::DELETE_LEASE6,
-                    "DELETE FROM lease6 WHERE address = ?"},
-    {MySqlLeaseMgr::GET_LEASE6_ADDR,
-                    "SELECT address, duid, valid_lifetime, "
-                        "expire, subnet_id, pref_lifetime, "
-                        "lease_type, iaid, prefix_len "
-                            "FROM lease6 "
-                            "WHERE address = ?"},
-    {MySqlLeaseMgr::GET_LEASE6_DUID_IAID,
-                    "SELECT address, duid, valid_lifetime, "
-                        "expire, subnet_id, pref_lifetime, "
-                        "lease_type, iaid, prefix_len "
-                            "FROM lease6 "
-                            "WHERE duid = ? AND iaid = ?"},
-    {MySqlLeaseMgr::GET_LEASE6_DUID_IAID_SUBID,
-                    "SELECT address, duid, valid_lifetime, "
-                        "expire, subnet_id, pref_lifetime, "
-                        "lease_type, iaid, prefix_len "
-                            "FROM lease6 "
-                            "WHERE duid = ? AND iaid = ? AND subnet_id = ?"},
-    {MySqlLeaseMgr::GET_VERSION,
-                    "SELECT version, minor FROM schema_version"},
-    {MySqlLeaseMgr::INSERT_LEASE6,
-                    "INSERT INTO lease6(address, duid, valid_lifetime, "
-                        "expire, subnet_id, pref_lifetime, "
-                        "lease_type, iaid, prefix_len) "
-                            "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)"},
-    {MySqlLeaseMgr::UPDATE_LEASE6,
-                    "UPDATE lease6 SET address = ?, duid = ?, "
-                        "valid_lifetime = ?, expire = ?, subnet_id = ?, "
-                        "pref_lifetime = ?, lease_type = ?, iaid = ?, "
-                        "prefix_len = ? "
-                            "WHERE address = ?"},
-    // End of list sentinel
-    {MySqlLeaseMgr::NUM_STATEMENTS, NULL}
-};
-
-};  // Anonymous namespace
-
-namespace isc {
-namespace dhcp {
-
-
-
-/// @brief Exchange MySQL and Lease6 Data
-///
-/// On any MySQL operation, arrays of MYSQL_BIND structures must be built to
-/// describe the parameters in the prepared statements.  Where information is
-/// inserted or retrieved - INSERT, UPDATE, SELECT - a large amount of that
-/// structure is identical - it defines data values in the Lease6 structure.
-/// This class handles the creation of that array.
-///
-/// Owing to the MySQL API, the process requires some intermediate variables
-/// to hold things like length etc.  This object holds the intermediate
-/// variables as well.
-///
-/// @note There are no unit tests for this class.  It is tested indirectly
-/// in all MySqlLeaseMgr::xxx6() calls where it is used.
-
-class MySqlLease6Exchange {
-public:
-    /// @brief Constructor
-    ///
-    /// Apart from the initialization of false_ and true_, the initialization
-    /// of addr6_length_, duid_length_, addr6_buffer_ and duid_buffer_ are
-    /// to satisfy cppcheck: none are really needed, as all variables are
-    /// initialized/set in the methods.
-    MySqlLease6Exchange() : addr6_length_(0), duid_length_(0),
-                            false_(0), true_(1) {
-        memset(addr6_buffer_, 0, sizeof(addr6_buffer_));
-        memset(duid_buffer_, 0, sizeof(duid_buffer_));
-    }
-
-    /// @brief Create MYSQL_BIND objects for Lease6 Pointer
-    ///
-    /// Fills in the MYSQL_BIND objects for the Lease6 passed to it.
-    ///
-    /// @param lease Lease object to be added to the database.
-    ///
-    /// @return Vector of MySQL BIND objects representing the data to be added.
-    std::vector<MYSQL_BIND> createBindForSend(const Lease6Ptr& lease) {
-        // Store lease object to ensure it remains valid.
-        lease_ = lease;
-
-        // Ensure bind_ array clear for constructing the MYSQL_BIND structures
-        // for this lease.
-        memset(bind_, 0, sizeof(bind_));
-
-        // address: varchar(40)
-        addr6_ = lease_->addr_.toText();
-        addr6_length_ = addr6_.size();
-
-        // In the following statement, the string is being read.  However, the
-        // MySQL C interface does not use "const", so the "buffer" element
-        // is declared as "char*" instead of "const char*".  To resolve this,
-        // the "const" is discarded.  (Note that the address of addr6_.c_str()
-        // is guaranteed to be valid until the next non-const operation on
-        // addr6_.)
-        //
-        // Note that the const_cast could be avoided by copying the string to
-        // a writeable buffer and storing the address of that in the "buffer"
-        // element.  However, this introduces a copy operation (with additional
-        // overhead) purely to get round the strictures introduced by design of
-        // the MySQL interface (which uses the area pointed to by "buffer" as
-        // input when specifying query parameters and as output when retrieving
-        // data).  For that reason, "const_cast" has been used.
-        bind_[0].buffer_type = MYSQL_TYPE_STRING;
-        bind_[0].buffer = const_cast<char*>(addr6_.c_str());
-        bind_[0].buffer_length = addr6_length_;
-        bind_[0].length = &addr6_length_;
-
-        // duid: varchar(128)
-        duid_ = lease_->duid_->getDuid();
-        duid_length_ = duid_.size();
-
-        bind_[1].buffer_type = MYSQL_TYPE_BLOB;
-        bind_[1].buffer = reinterpret_cast<char*>(&(duid_[0]));
-        bind_[1].buffer_length = duid_length_;
-        bind_[1].length = &duid_length_;
-
-        // valid lifetime: unsigned int
-        bind_[2].buffer_type = MYSQL_TYPE_LONG;
-        bind_[2].buffer = reinterpret_cast<char*>(&lease->valid_lft_);
-        bind_[2].is_unsigned = true_;
-
-        // expire: timestamp
-        // The lease structure holds the client last transmission time (cltt_)
-        // For convenience for external tools, this is converted to lease
-        /// expiry time (expire).  The relationship is given by:
-        //
-        // expire = cltt_ + valid_lft_
-        //
-        // @TODO Handle overflows
-        MySqlLeaseMgr::convertToDatabaseTime(lease_->cltt_, lease_->valid_lft_,
-                                             expire_);
-        bind_[3].buffer_type = MYSQL_TYPE_TIMESTAMP;
-        bind_[3].buffer = reinterpret_cast<char*>(&expire_);
-        bind_[3].buffer_length = sizeof(expire_);
-
-        // subnet_id: unsigned int
-        // Can use lease_->subnet_id_ directly as it is of type uint32_t.
-        bind_[4].buffer_type = MYSQL_TYPE_LONG;
-        bind_[4].buffer = reinterpret_cast<char*>(&lease_->subnet_id_);
-        bind_[4].is_unsigned = true_;
-
-        // pref_lifetime: unsigned int
-        // Can use lease_->preferred_lft_ directly as it is of type uint32_t.
-        bind_[5].buffer_type = MYSQL_TYPE_LONG;
-        bind_[5].buffer = reinterpret_cast<char*>(&lease_->preferred_lft_);
-        bind_[5].is_unsigned = true_;
-
-        // lease_type: tinyint
-        // Must convert to uint8_t as lease_->type_ is a LeaseType variable
-        lease_type_ = lease_->type_;
-        bind_[6].buffer_type = MYSQL_TYPE_TINY;
-        bind_[6].buffer = reinterpret_cast<char*>(&lease_type_);
-        bind_[6].is_unsigned = true_;
-
-        // iaid: unsigned int
-        // Can use lease_->iaid_ directly as it is of type uint32_t.
-        bind_[7].buffer_type = MYSQL_TYPE_LONG;
-        bind_[7].buffer = reinterpret_cast<char*>(&lease_->iaid_);
-        bind_[7].is_unsigned = true_;
-
-        // prefix_len: unsigned tinyint
-        // Can use lease_->prefixlen_ directly as it is uint32_t.
-        bind_[8].buffer_type = MYSQL_TYPE_TINY;
-        bind_[8].buffer = reinterpret_cast<char*>(&lease_->prefixlen_);
-        bind_[8].is_unsigned = true_;
-
-        // Add the data to the vector.  Note the end element is one after the
-        // end of the array.
-        return (std::vector<MYSQL_BIND>(&bind_[0], &bind_[9]));
-    }
-
-    /// @brief Create BIND array to receive data
-    ///
-    /// Creates a MYSQL_BIND array to receive Lease6 data from the database.
-    /// After data is successfully received, getLeaseData() is used to copy
-    /// it to a Lease6 object.
-    ///
-    /// @return Vector of MySQL BIND objects.
-    std::vector<MYSQL_BIND> createBindForReceive() {
-
-        // Ensure both the array of MYSQL_BIND structures and the error array
-        // are clear.
-        memset(bind_, 0, sizeof(bind_));
-        memset(error_, 0, sizeof(error_));
-
-        // address:  varchar
-        // A Lease6_ address has a maximum of 39 characters.  The array is
-        // a few bites longer than this to guarantee that we can always null
-        // terminate it.
-        addr6_length_ = sizeof(addr6_buffer_) - 1;
-        bind_[0].buffer_type = MYSQL_TYPE_STRING;
-        bind_[0].buffer = addr6_buffer_;
-        bind_[0].buffer_length = addr6_length_;
-        bind_[0].length = &addr6_length_;
-        bind_[0].error = &error_[0];
-
-        // client_id: varbinary(128)
-        duid_length_ = sizeof(duid_buffer_);
-        bind_[1].buffer_type = MYSQL_TYPE_BLOB;
-        bind_[1].buffer = reinterpret_cast<char*>(duid_buffer_);
-        bind_[1].buffer_length = duid_length_;
-        bind_[1].length = &duid_length_;
-        bind_[1].error = &error_[1];
-
-        // lease_time: unsigned int
-        bind_[2].buffer_type = MYSQL_TYPE_LONG;
-        bind_[2].buffer = reinterpret_cast<char*>(&valid_lifetime_);
-        bind_[2].is_unsigned = true_;
-        bind_[2].error = &error_[2];
-
-        // expire: timestamp
-        bind_[3].buffer_type = MYSQL_TYPE_TIMESTAMP;
-        bind_[3].buffer = reinterpret_cast<char*>(&expire_);
-        bind_[3].buffer_length = sizeof(expire_);
-        bind_[3].error = &error_[3];
-
-        // subnet_id: unsigned int
-        bind_[4].buffer_type = MYSQL_TYPE_LONG;
-        bind_[4].buffer = reinterpret_cast<char*>(&subnet_id_);
-        bind_[4].is_unsigned = true_;
-        bind_[4].error = &error_[4];
-
-        // pref_lifetime: unsigned int
-        bind_[5].buffer_type = MYSQL_TYPE_LONG;
-        bind_[5].buffer = reinterpret_cast<char*>(&pref_lifetime_);
-        bind_[5].is_unsigned = true_;
-        bind_[5].error = &error_[5];
-
-        // lease_type: tinyint
-        bind_[6].buffer_type = MYSQL_TYPE_TINY;
-        bind_[6].buffer = reinterpret_cast<char*>(&lease_type_);
-        bind_[6].is_unsigned = true_;
-        bind_[6].error = &error_[6];
-
-        // iaid: unsigned int
-        bind_[7].buffer_type = MYSQL_TYPE_LONG;
-        bind_[7].buffer = reinterpret_cast<char*>(&iaid_);
-        bind_[7].is_unsigned = true_;
-        bind_[7].error = &error_[7];
-
-        // prefix_len: unsigned tinyint
-        bind_[8].buffer_type = MYSQL_TYPE_TINY;
-        bind_[8].buffer = reinterpret_cast<char*>(&prefixlen_);
-        bind_[8].is_unsigned = true_;
-        bind_[8].error = &error_[8];
-
-        // Add the data to the vector.  Note the end element is one after the
-        // end of the array.
-        return(std::vector<MYSQL_BIND>(&bind_[0], &bind_[9]));
-    }
-
-    /// @brief Copy Received Data into Lease6 Object
-    ///
-    /// Called after the MYSQL_BIND array created by createBindForReceive()
-    /// has been used, this copies data from the internal member vairables
-    /// into a Lease6 object.
-    ///
-    /// @return Lease6Ptr Pointer to a Lease6 object holding the relevant
-    ///         data.
-    ///
-    /// @throw isc::BadValue Unable to convert Lease Type value in database
-    Lease6Ptr getLeaseData() {
-
-        // Create the object to be returned.
-        Lease6Ptr result(new Lease6());
-
-        // Put the data in the lease object
-
-        // The address buffer is declared larger than the buffer size passed
-        // to the access function so that we can always append a null byte.
-        addr6_buffer_[addr6_length_] = '\0';
-        std::string address = addr6_buffer_;
-
-        // Set the other data, converting time as needed.
-        result->addr_ = isc::asiolink::IOAddress(address);
-        result->duid_.reset(new DUID(duid_buffer_, duid_length_));
-        MySqlLeaseMgr::convertFromDatabaseTime(expire_, valid_lifetime_,
-                                               result->cltt_);
-        result->valid_lft_ = valid_lifetime_;
-        result->subnet_id_ = subnet_id_;
-        result->preferred_lft_ = pref_lifetime_;
-
-        // We can't convert from a numeric value to an enum, hence:
-        switch (lease_type_) {
-            case Lease6::LEASE_IA_NA:
-                result->type_ = Lease6::LEASE_IA_NA;
-                break;
-
-            case Lease6::LEASE_IA_TA:
-                result->type_ = Lease6::LEASE_IA_TA;
-                break;
-
-            case Lease6::LEASE_IA_PD:
-                result->type_ = Lease6::LEASE_IA_PD;
-                break;
-
-            default:
-                isc_throw(BadValue, "invalid lease type returned (" <<
-                          lease_type_ << ") for lease with address " <<
-                          result->addr_.toText() << ". Only 0, 1, or 2 "
-                          "are allowed.");
-        }
-        result->iaid_ = iaid_;
-        result->prefixlen_ = prefixlen_;
-
-        return (result);
-    }
-
-private:
-    // Note: All array lengths are equal to the corresponding variable in the
-    // schema.
-    std::string     addr6_;             ///< String form of address
-    char            addr6_buffer_[ADDRESS6_TEXT_MAX_LEN];  ///< Character 
-                                        ///< array form of V6 address
-    unsigned long   addr6_length_;      ///< Length of the address
-    MYSQL_BIND      bind_[9];           ///< Static array for speed of access
-    std::vector<uint8_t> duid_;         ///< Client identification
-    uint8_t         duid_buffer_[DUID_MAX_LEN]; ///< Buffer form of DUID
-    unsigned long   duid_length_;       ///< Length of the DUID
-    my_bool         error_[9];          ///< For error reporting
-    MYSQL_TIME      expire_;            ///< Lease expiry time
-    const my_bool   false_;             ///< "false" for MySql
-    uint32_t        iaid_;              ///< Identity association ID
-    Lease6Ptr       lease_;             ///< Pointer to lease object
-    uint32_t        valid_lifetime_;    ///< Lease time
-    uint8_t         lease_type_;        ///< Lease type
-    uint8_t         prefixlen_;         ///< Prefix length
-    uint32_t        pref_lifetime_;     ///< Preferred lifetime
-    uint32_t        subnet_id_;         ///< Subnet identification
-    const my_bool   true_;              ///< "true_" for MySql
-};
-
-
-/// @brief Fetch and Release MySQL Results
-///
-/// When a MySQL statement is exected, to fetch the results the function
-/// mysql_stmt_fetch() must be called.  As well as getting data, this
-/// allocated internal state.  Subsequent calls to mysql_stmt_fetch
-/// can be made, but when all the data is retrieved, mysql_stmt_free_result
-/// must be called to free up the resources allocated.
-///
-/// Created prior to the first fetch, this class's destructor calls
-/// mysql_stmt_free_result, so eliminating the need for an explicit release
-/// in the method using mysql_stmt_free_result.  In this way, it guarantees
-/// that the resources are released even if the MySqlLeaseMgr method concerned
-/// exits via an exception.
-class MySqlFreeResult {
-public:
-
-    /// @brief Constructor
-    ///
-    /// Store the pointer to the statement for which data is being fetched.
-    ///
-    /// Note that according to the MySQL documentation, mysql_stmt_free_result
-    /// only releases resources if a cursor has been allocated for the
-    /// statement.  This implies that it is a no-op if none have been.  Either
-    /// way, any error from mysql_stmt_free_result is ignored. (Generating
-    /// an exception is not much help, as it will only confuse things if the
-    /// method calling mysql_stmt_fetch is exiting via an exception.)
-    MySqlFreeResult(MYSQL_STMT* statement) : statement_(statement)
-    {}
-
-    /// @brief Destructor
-    ///
-    /// Frees up fetch context if a fetch has been successfully executed.
-    ~MySqlFreeResult() {
-        (void) mysql_stmt_free_result(statement_);
-    }
-
-private:
-    MYSQL_STMT*     statement_;     ///< Statement for which results are freed
-};
-
-
-// MySqlLeaseMgr Methods
-
-MySqlLeaseMgr::MySqlLeaseMgr(const LeaseMgr::ParameterMap& parameters) 
-    : LeaseMgr(parameters), mysql_(NULL) {
-
-    // Allocate context for MySQL - it is destroyed in the destructor.
-    mysql_ = mysql_init(NULL);
-    if (mysql_ == NULL) {
-        isc_throw(DbOpenError, "unable to initialize MySQL");
-    }
-
-    // Open the database
-    openDatabase();
-
-    // Enable autocommit.  For maximum speed, the global parameter
-    // innodb_flush_log_at_trx_commit should be set to 2.
-    my_bool result = mysql_autocommit(mysql_, 1);
-    if (result != 0) {
-        isc_throw(DbOperationError, mysql_error(mysql_));
-    }
-
-    // Prepare all statements likely to be used.
-    prepareStatements();
-
-    // Create the exchange object for use in exchanging data between the
-    // program and the database.
-    exchange6_.reset(new MySqlLease6Exchange());
-}
-
-
-MySqlLeaseMgr::~MySqlLeaseMgr() {
-    // Free up the prepared statements, ignoring errors. (What would we do
-    // about them - we're destroying this object and are not really concerned
-    // with errors on a database connection that it about to go away.)
-    for (int i = 0; i < statements_.size(); ++i) {
-        if (statements_[i] != NULL) {
-            (void) mysql_stmt_close(statements_[i]);
-            statements_[i] = NULL;
-        }
-    }
-
-    // Close the database
-    mysql_close(mysql_);
-    mysql_ = NULL;
-}
-
-
-// Time conversion methods.
-//
-// Note that the MySQL TIMESTAMP data type (used for "expire") converts data
-// from the current timezone to UTC for storage, and from UTC to the current
-// timezone for retrieval.
-//
-// This causes no problems providing that:
-// a) cltt is given in local time
-// b) We let the system take care of timezone conversion when converting
-//    from a time read from the database into a local time.
-
-void
-MySqlLeaseMgr::convertToDatabaseTime(time_t cltt, uint32_t valid_lifetime,
-                                    MYSQL_TIME& expire) {
-
-    // Calculate expiry time and convert to various date/time fields.
-    // @TODO: handle overflows
-    time_t expire_time = cltt + valid_lifetime;
-
-    // Convert to broken-out time
-    struct tm expire_tm;
-    (void) localtime_r(&expire_time, &expire_tm);
-
-    // Place in output expire structure.
-    expire.year = expire_tm.tm_year + 1900;
-    expire.month = expire_tm.tm_mon + 1;     // Note different base
-    expire.day = expire_tm.tm_mday;
-    expire.hour = expire_tm.tm_hour;
-    expire.minute = expire_tm.tm_min;
-    expire.second = expire_tm.tm_sec;
-    expire.second_part = 0;                    // No fractional seconds
-    expire.neg = static_cast<my_bool>(0);      // Not negative
-}
-
-void
-MySqlLeaseMgr::convertFromDatabaseTime(const MYSQL_TIME& expire,
-                                       uint32_t valid_lifetime, time_t& cltt) {
-
-    // Copy across fields from MYSQL_TIME structure.
-    struct tm expire_tm;
-    memset(&expire_tm, 0, sizeof(expire_tm));
-
-    expire_tm.tm_year = expire.year - 1900;
-    expire_tm.tm_mon = expire.month - 1;
-    expire_tm.tm_mday = expire.day;
-    expire_tm.tm_hour = expire.hour;
-    expire_tm.tm_min = expire.minute;
-    expire_tm.tm_sec = expire.second;
-    expire_tm.tm_isdst = -1;    // Let the system work out about DST 
-
-    // Convert to local time
-    cltt = mktime(&expire_tm) - valid_lifetime;
-}
-
-
-void
-MySqlLeaseMgr::openDatabase() {
-
-    // Set up the values of the parameters
-    const char* host = "localhost";
-    string shost;
-    try {
-        shost = getParameter("host");
-        host = shost.c_str();
-    } catch (...) {
-        // No host.  Fine, we'll use "localhost"
-    }
-
-    const char* user = NULL;
-    string suser;
-    try {
-        suser = getParameter("user");
-        user = suser.c_str();
-    } catch (...) {
-        // No user.  Fine, we'll use NULL
-        ;
-    }
-
-    const char* password = NULL;
-    string spassword;
-    try {
-        spassword = getParameter("password");
-        password = spassword.c_str();
-    } catch (...) {
-        // No password.  Fine, we'll use NULL
-        ;
-    }
-
-    const char* name = NULL;
-    string sname;
-    try {
-        sname = getParameter("name");
-        name = sname.c_str();
-    } catch (...) {
-        // No database name.  Throw a "NoName" exception
-        isc_throw(NoDatabaseName, "must specified a name for the database");
-    }
-
-    // Set options for the connection:
-    // - automatic reconnection
-    my_bool auto_reconnect = 1;
-    int result = mysql_options(mysql_, MYSQL_OPT_RECONNECT, &auto_reconnect);
-    if (result != 0) {
-        isc_throw(DbOpenError, "unable to set auto-reconnect option: " <<
-                  mysql_error(mysql_));
-    }
-
-    // Open the database.
-    //
-    // The option CLIENT_FOUND_ROWS is specified so that in an UPDATE,
-    // the affected rows are the number of rows found that match the
-    // WHERE clause of the SQL statement, not the rows changed.  The reason
-    // here is that MySQL apparently does not update a row if data has not
-    // changed and so the "affected rows" (retrievable from MySQL) is zero.
-    // This makes it hard to distinguish whether the UPDATE changed no rows
-    // because no row matching the WHERE clause was found, or because a
-    // row was found by no data was altered.
-    MYSQL* status = mysql_real_connect(mysql_, host, user, password, name,
-                                       0, NULL, CLIENT_FOUND_ROWS);
-    if (status != mysql_) {
-        isc_throw(DbOpenError, mysql_error(mysql_));
-    }
-}
-
-
-void
-MySqlLeaseMgr::prepareStatement(StatementIndex index, const char* text) {
-    // Validate that there is space for the statement in the statements array
-    // and that nothing has been placed there before.
-    if ((index >= statements_.size()) || (statements_[index] != NULL)) {
-        isc_throw(InvalidParameter, "invalid prepared statement index (" <<
-                  static_cast<int>(index) << ") or indexed prepared " <<
-                  "statement is not null");
-    }
-
-    // All OK, so prepare the statement
-    text_statements_[index] = std::string(text);
-
-    statements_[index] = mysql_stmt_init(mysql_);
-    if (statements_[index] == NULL) {
-        isc_throw(DbOperationError, "unable to allocate MySQL prepared "
-                  "statement structure" << mysql_error(mysql_));
-    }
-
-    int status = mysql_stmt_prepare(statements_[index], text, strlen(text));
-    if (status != 0) {
-        isc_throw(DbOperationError, "unable to prepare MySQL statement <" <<
-                  text << ">, reason: " << mysql_error(mysql_));
-    }
-}
-
-
-void
-MySqlLeaseMgr::prepareStatements() {
-    // Allocate space for all statements
-    statements_.clear();
-    statements_.resize(NUM_STATEMENTS, NULL);
-    
-    text_statements_.clear();
-    text_statements_.resize(NUM_STATEMENTS, std::string(""));
-
-    // Created the MySQL prepared statements for each DML statement.
-    for (int i = 0; tagged_statements[i].text != NULL; ++i) {
-        prepareStatement(tagged_statements[i].index,
-                         tagged_statements[i].text);
-    }
-}
-
-
-bool
-MySqlLeaseMgr::addLease(const Lease4Ptr& /* lease */) {
-    isc_throw(NotImplemented, "MySqlLeaseMgr::addLease(const Lease4Ptr&) "
-              "not implemented yet");
-    return (false);
-}
-
-
-bool
-MySqlLeaseMgr::addLease(const Lease6Ptr& lease) {
-    const StatementIndex stindex = INSERT_LEASE6;
-
-    // Create the MYSQL_BIND array for the lease
-    std::vector<MYSQL_BIND> bind = exchange6_->createBindForSend(lease);
-
-    // Bind the parameters to the statement
-    int status = mysql_stmt_bind_param(statements_[stindex], &bind[0]);
-    checkError(status, stindex, "unable to bind parameters");
-
-    // Execute the statement
-    status = mysql_stmt_execute(statements_[stindex]);
-    if (status != 0) {
-
-        // Failure: check for the special case of duplicate entry.  If this is
-        // the case, we return false to indicate that the row was not added.
-        // Otherwise we throw an exception.
-        if (mysql_errno(mysql_) == ER_DUP_ENTRY) {
-            return (false);
-        }
-        checkError(status, stindex, "unable to execute");
-    }
-
-    // Insert succeeded
-    return (true);
-}
-
-
-Lease4Ptr
-MySqlLeaseMgr::getLease4(const isc::asiolink::IOAddress& /* addr */,
-                         SubnetID /* subnet_id */) const {
-    isc_throw(NotImplemented, "MySqlLeaseMgr::getLease4(const IOAddress&, SubnetID) "
-              "not implemented yet");
-    return (Lease4Ptr());
-}
-
-
-Lease4Ptr
-MySqlLeaseMgr::getLease4(const isc::asiolink::IOAddress& /* addr */) const {
-    isc_throw(NotImplemented, "MySqlLeaseMgr::getLease4(const IOAddress&) "
-              "not implemented yet");
-    return (Lease4Ptr());
-}
-
-
-Lease4Collection
-MySqlLeaseMgr::getLease4(const HWAddr& /* hwaddr */) const {
-    isc_throw(NotImplemented, "MySqlLeaseMgr::getLease4(const HWAddr&) "
-              "not implemented yet");
-    return (Lease4Collection());
-}
-
-
-Lease4Ptr
-MySqlLeaseMgr::getLease4(const HWAddr& /* hwaddr */,
-                         SubnetID /* subnet_id */) const {
-    isc_throw(NotImplemented, "MySqlLeaseMgr::getLease4(const HWAddr&, SubnetID) "
-              "not implemented yet");
-    return (Lease4Ptr());
-}
-
-
-Lease4Collection
-MySqlLeaseMgr::getLease4(const ClientId& /* clientid */) const {
-    isc_throw(NotImplemented, "MySqlLeaseMgr::getLease4(const ClientID&) "
-              "not implemented yet");
-    return (Lease4Collection());
-}
-
-
-Lease4Ptr
-MySqlLeaseMgr::getLease4(const ClientId& /* clientid */,
-                         SubnetID /* subnet_id */) const {
-    isc_throw(NotImplemented, "MySqlLeaseMgr::getLease4(const ClientID&, SubnetID) "
-              "not implemented yet");
-    return (Lease4Ptr());
-}
-
-
-// A convenience function used in the various getLease6() methods.  It binds
-// the selection parameters to the prepared statement, and binds the variables
-// that will receive the data.  These are stored in the MySqlLease6Exchange
-// object associated with the lease manager and converted to a Lease6 object
-// when retrieved.
-void
-MySqlLeaseMgr::bind6AndExecute(StatementIndex stindex, MYSQL_BIND* inbind) const {
-
-    // Bind the input parameters to the statement
-    int status = mysql_stmt_bind_param(statements_[stindex], inbind);
-    checkError(status, stindex, "unable to bind WHERE clause parameter");
-
-    // Set up the SELECT clause
-    std::vector<MYSQL_BIND> outbind = exchange6_->createBindForReceive();
-
-    // Bind the output parameters to the statement
-    status = mysql_stmt_bind_result(statements_[stindex], &outbind[0]);
-    checkError(status, stindex, "unable to bind SELECT caluse parameters");
-
-    // Execute the statement
-    status = mysql_stmt_execute(statements_[stindex]);
-    checkError(status, stindex, "unable to execute");
-}
-
-
-Lease6Ptr
-MySqlLeaseMgr::getLease6(const isc::asiolink::IOAddress& addr) const {
-    const StatementIndex stindex = GET_LEASE6_ADDR;
-
-    // Set up the WHERE clause value
-    MYSQL_BIND inbind[1];
-    memset(inbind, 0, sizeof(inbind));
-
-    std::string addr6 = addr.toText();
-    unsigned long addr6_length = addr6.size();
-
-    // See the earlier description of the use of "const_cast" when accessing
-    // the address for an explanation of the reason.
-    inbind[0].buffer_type = MYSQL_TYPE_STRING;
-    inbind[0].buffer = const_cast<char*>(addr6.c_str());
-    inbind[0].buffer_length = addr6_length;
-    inbind[0].length = &addr6_length;
-
-    // Bind the input parameters to the statement and bind the output
-    // to fields in the exchange object, then execute the prepared statement.
-    bind6AndExecute(stindex, inbind);
-
-    // Fetch the data and set up the "release" object to release associated
-    // resources when this method exits.
-    MySqlFreeResult fetch_release(statements_[stindex]);
-    int status = mysql_stmt_fetch(statements_[stindex]);
-
-    Lease6Ptr result;
-    if (status == 0) {
-        try {
-            result = exchange6_->getLeaseData();
-        } catch (const isc::BadValue& ex) {
-            // Lease type is returned, to rethrow the exception with a bit
-            // more data.
-            isc_throw(BadValue, ex.what() << ". Statement is <" <<
-                      text_statements_[stindex] << ">");
-        }
-
-        // As the address is the primary key in the table, we can't return
-        // two rows, so we don't bother checking whether multiple rows have
-        // been returned.
-
-    } else if (status == 1) {
-        checkError(status, stindex, "unable to fetch results");
-
-    } else {
-        // @TODO Handle truncation
-        // We are ignoring truncation for now, so the only other result is
-        // no data was found.  In that case, we return a null Lease6 structure.
-        // This has already been set, so no action is needed.
-    }
-
-    return (result);
-}
-
-
-Lease6Collection
-MySqlLeaseMgr::getLease6(const DUID& duid, uint32_t iaid) const {
-    const StatementIndex stindex = GET_LEASE6_DUID_IAID;
-
-    // Set up the WHERE clause value
-    MYSQL_BIND inbind[2];
-    memset(inbind, 0, sizeof(inbind));
-
-    // In the following statement, the DUID is being read.  However, the
-    // MySQL C interface does not use "const", so the "buffer" element
-    // is declared as "char*" instead of "const char*".  To resolve this,
-    // the "const" is discarded before the uint8_t* is cast to char*.
-    //
-    // Note that the const_cast could be avoided by copying the DUID to
-    // a writeable buffer and storing the address of that in the "buffer"
-    // element.  However, this introduces a copy operation (with additional
-    // overhead) purely to get round the strictures introduced by design of
-    // the MySQL interface (which uses the area pointed to by "buffer" as
-    // input when specifying query parameters and as output when retrieving
-    // data).  For that reason, "const_cast" has been used.
-    const vector<uint8_t>& duid_vector = duid.getDuid();
-    unsigned long duid_length = duid_vector.size();
-    inbind[0].buffer_type = MYSQL_TYPE_BLOB;
-    inbind[0].buffer = reinterpret_cast<char*>(
-            const_cast<uint8_t*>(&duid_vector[0]));
-    inbind[0].buffer_length = duid_length;
-    inbind[0].length = &duid_length;
-
-    // IAID
-    inbind[1].buffer_type = MYSQL_TYPE_LONG;
-    inbind[1].buffer = reinterpret_cast<char*>(&iaid);
-    inbind[1].is_unsigned = static_cast<my_bool>(1);
-
-    // Bind the input parameters to the statement and bind the output
-    // to fields in the exchange object, then execute the prepared statement.
-    bind6AndExecute(stindex, inbind);
-
-    // Ensure that all the lease information is retrieved in one go to avoid
-    // overhead of going back and forth between client and server.
-    int status = mysql_stmt_store_result(statements_[stindex]);
-    checkError(status, stindex, "unable to set up for storing all results");
-
-    // Fetch the data.  There could be multiple rows, so we need to iterate
-    // until all data has been retrieved.
-    Lease6Collection result;
-
-    // Set up the fetch "release" object to release resources associated
-    // with the call to mysql_stmt_fetch when this method exits, then
-    // retrieve the data.
-    MySqlFreeResult fetch_release(statements_[stindex]);
-    while ((status = mysql_stmt_fetch(statements_[stindex])) == 0) {
-        try {
-            Lease6Ptr lease = exchange6_->getLeaseData();
-            result.push_back(lease);
-
-        } catch (const isc::BadValue& ex) {
-            // Rethrow the exception with a bit more data.
-            isc_throw(BadValue, ex.what() << ". Statement is <" <<
-                      text_statements_[stindex] << ">");
-        }
-    }
-
-    // How did the fetch end?
-    if (status == 1) {
-        // Error - unable to fecth results
-        checkError(status, stindex, "unable to fetch results");
-    } else if (status == MYSQL_DATA_TRUNCATED) {
-        // @TODO Handle truncation
-        ;
-    }
-
-    return (result);
-}
-
-
-Lease6Ptr
-MySqlLeaseMgr::getLease6(const DUID& duid, uint32_t iaid,
-                         SubnetID subnet_id) const {
-    const StatementIndex stindex = GET_LEASE6_DUID_IAID_SUBID;
-
-    // Set up the WHERE clause value
-    MYSQL_BIND inbind[3];
-    memset(inbind, 0, sizeof(inbind));
-
-    // See the earlier description of the use of "const_cast" when accessing
-    // the DUID for an explanation of the reason.
-    const vector<uint8_t>& duid_vector = duid.getDuid();
-    unsigned long duid_length = duid_vector.size();
-    inbind[0].buffer_type = MYSQL_TYPE_BLOB;
-    inbind[0].buffer = reinterpret_cast<char*>(
-            const_cast<uint8_t*>(&duid_vector[0]));
-    inbind[0].buffer_length = duid_length;
-    inbind[0].length = &duid_length;
-
-    // IAID
-    inbind[1].buffer_type = MYSQL_TYPE_LONG;
-    inbind[1].buffer = reinterpret_cast<char*>(&iaid);
-    inbind[1].is_unsigned = static_cast<my_bool>(1);
-
-    // Subnet ID
-    inbind[2].buffer_type = MYSQL_TYPE_LONG;
-    inbind[2].buffer = reinterpret_cast<char*>(&subnet_id);
-    inbind[2].is_unsigned = static_cast<my_bool>(1);
-
-    // Bind the input parameters to the statement and bind the output
-    // to fields in the exchange object, then execute the prepared statement.
-    bind6AndExecute(stindex, inbind);
-
-    // Fetch the data and set up the "release" object to release associated
-    // resources when this method exits then retrieve the data.
-    Lease6Ptr result;
-    MySqlFreeResult fetch_release(statements_[stindex]);
-    int status = mysql_stmt_fetch(statements_[stindex]);
-    if (status == 0) {
-        try {
-            result = exchange6_->getLeaseData();
-
-            // TODO: check for more than one row returned.  At present, just
-            // ignore the excess and take the first.
-
-        } catch (const isc::BadValue& ex) {
-            // Lease type is returned, to rethrow the exception with a bit
-            // more data.
-            isc_throw(BadValue, ex.what() << ". Statement is <" <<
-                      text_statements_[stindex] << ">");
-        }
-
-        // As the address is the primary key in the table, we can't return
-        // two rows, so we don't bother checking whether multiple rows have
-        // been returned.
-
-    } else if (status == 1) {
-        checkError(status, stindex, "unable to fetch results");
-
-    } else {
-        // @TODO Handle truncation
-        // We are ignoring truncation for now, so the only other result is
-        // no data was found.  In that case, we return a null Lease6 structure.
-        // This has already been set, so the action is a no-op.
-    }
-
-    return (result);
-}
-
-
-void
-MySqlLeaseMgr::updateLease4(const Lease4Ptr& /* lease4 */) {
-    isc_throw(NotImplemented, "MySqlLeaseMgr::updateLease4(const Lease4Ptr&) "
-              "not implemented yet");
-}
-
-
-void
-MySqlLeaseMgr::updateLease6(const Lease6Ptr& lease) {
-    const StatementIndex stindex = UPDATE_LEASE6;
-
-    // Create the MYSQL_BIND array for the data being updated
-    std::vector<MYSQL_BIND> bind = exchange6_->createBindForSend(lease);
-
-    // Set up the WHERE clause value
-    MYSQL_BIND where;
-    memset(&where, 0, sizeof(where));
-
-    std::string addr6 = lease->addr_.toText();
-    unsigned long addr6_length = addr6.size();
-
-    // See the earlier description of the use of "const_cast" when accessing
-    // the address for an explanation of the reason.
-    where.buffer_type = MYSQL_TYPE_STRING;
-    where.buffer = const_cast<char*>(addr6.c_str());
-    where.buffer_length = addr6_length;
-    where.length = &addr6_length;
-    bind.push_back(where);
-
-    // Bind the parameters to the statement
-    int status = mysql_stmt_bind_param(statements_[stindex], &bind[0]);
-    checkError(status, stindex, "unable to bind parameters");
-
-    // Execute
-    status = mysql_stmt_execute(statements_[stindex]);
-    checkError(status, stindex, "unable to execute");
-
-    // See how many rows were affected.  The statement should only delete a
-    // single row.
-    int affected_rows = mysql_stmt_affected_rows(statements_[stindex]);
-    if (affected_rows == 0) {
-        isc_throw(NoSuchLease, "unable to update lease for address " <<
-                  addr6 << " as it does not exist");
-    } else if (affected_rows > 1) {
-        // Should not happen - primary key constraint should only have selected
-        // one row.
-        isc_throw(DbOperationError, "apparently updated more than one lease "
-                  "that had the address " << addr6);
-    }
-}
-
-
-bool
-MySqlLeaseMgr::deleteLease4(const isc::asiolink::IOAddress& /* addr */) {
-    isc_throw(NotImplemented, "MySqlLeaseMgr::deleteLease4(const IOAddress&) "
-              "not implemented yet");
-    return (false);
-}
-
-
-bool
-MySqlLeaseMgr::deleteLease6(const isc::asiolink::IOAddress& addr) {
-    const StatementIndex stindex = DELETE_LEASE6;
-
-    // Set up the WHERE clause value
-    MYSQL_BIND inbind[1];
-    memset(inbind, 0, sizeof(inbind));
-
-    std::string addr6 = addr.toText();
-    unsigned long addr6_length = addr6.size();
-
-    // See the earlier description of the use of "const_cast" when accessing
-    // the address for an explanation of the reason.
-    inbind[0].buffer_type = MYSQL_TYPE_STRING;
-    inbind[0].buffer = const_cast<char*>(addr6.c_str());
-    inbind[0].buffer_length = addr6_length;
-    inbind[0].length = &addr6_length;
-
-    // Bind the input parameters to the statement
-    int status = mysql_stmt_bind_param(statements_[stindex], inbind);
-    checkError(status, stindex, "unable to bind WHERE clause parameter");
-
-    // Execute
-    status = mysql_stmt_execute(statements_[stindex]);
-    checkError(status, stindex, "unable to execute");
-
-    // See how many rows were affected.  Note that the statement may delete
-    // multiple rows.
-    return (mysql_stmt_affected_rows(statements_[stindex]) > 0);
-}
-
-
-std::string
-MySqlLeaseMgr::getName() const {
-    std::string name = "";
-    try {
-        name = getParameter("name");
-    } catch (...) {
-        ;
-    }
-    return (name);
-}
-
-
-std::string
-MySqlLeaseMgr::getDescription() const {
-    return (std::string("MySQL Database"));
-}
-
-
-std::pair<uint32_t, uint32_t>
-MySqlLeaseMgr::getVersion() const {
-    const StatementIndex stindex = GET_VERSION;
-
-    uint32_t    major;      // Major version number
-    uint32_t    minor;      // Minor version number
-
-    // Execute the prepared statement
-    int status = mysql_stmt_execute(statements_[stindex]);
-    if (status != 0) {
-        isc_throw(DbOperationError, "unable to execute <"
-                  << text_statements_[stindex] << "> - reason: " <<
-                  mysql_error(mysql_));
-    }
-
-    // Bind the output of the statement to the appropriate variables.
-    MYSQL_BIND bind[2];
-    memset(bind, 0, sizeof(bind));
-
-    bind[0].buffer_type = MYSQL_TYPE_LONG;
-    bind[0].is_unsigned = 1;
-    bind[0].buffer = &major;
-    bind[0].buffer_length = sizeof(major);
-
-    bind[1].buffer_type = MYSQL_TYPE_LONG;
-    bind[1].is_unsigned = 1;
-    bind[1].buffer = &minor;
-    bind[1].buffer_length = sizeof(minor);
-
-    status = mysql_stmt_bind_result(statements_[stindex], bind);
-    if (status != 0) {
-        isc_throw(DbOperationError, "unable to bind result set: " <<
-                  mysql_error(mysql_));
-    }
-
-    // Fetch the data and set up the "release" object to release associated
-    // resources when this method exits then retrieve the data.
-    MySqlFreeResult fetch_release(statements_[stindex]);
-    status = mysql_stmt_fetch(statements_[stindex]);
-    if (status != 0) {
-        isc_throw(DbOperationError, "unable to obtain result set: " <<
-                  mysql_error(mysql_));
-    }
-
-    return (std::make_pair(major, minor));
-}
-
-
-void
-MySqlLeaseMgr::commit() {
-    if (mysql_commit(mysql_) != 0) {
-        isc_throw(DbOperationError, "commit failed: " << mysql_error(mysql_));
-    }
-}
-
-
-void
-MySqlLeaseMgr::rollback() {
-    if (mysql_rollback(mysql_) != 0) {
-        isc_throw(DbOperationError, "rollback failed: " << mysql_error(mysql_));
-    }
-}
-
-}; // end of isc::dhcp namespace
-}; // end of isc namespace
diff --git a/src/lib/dhcp/mysql_lease_mgr.h b/src/lib/dhcp/mysql_lease_mgr.h
deleted file mode 100644
index bdd99cc..0000000
--- a/src/lib/dhcp/mysql_lease_mgr.h
+++ /dev/null
@@ -1,447 +0,0 @@
-// 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 MYSQL_LEASE_MGR_H
-#define MYSQL_LEASE_MGR_H
-
-#include <time.h>
-#include <boost/scoped_ptr.hpp>
-#include <mysql.h>
-#include <dhcp/lease_mgr.h>
-
-namespace isc {
-namespace dhcp {
-
-// Define the current database schema values
-
-const uint32_t CURRENT_VERSION_VERSION = 0;
-const uint32_t CURRENT_VERSION_MINOR = 1;
-
-
-// Forward declaration of the Lease6 exchange object.  This class is defined
-// in the .cc file.
-class MySqlLease6Exchange;
-
-
-/// @brief MySQL Lease Manager
-///
-/// This is a concrete API for the backend for the MySQL database.
-class MySqlLeaseMgr : public LeaseMgr {
-public:
-    /// @brief Constructor
-    ///
-    /// Uses the following keywords in the parameters passed to it to
-    /// connect to the database:
-    /// - name - Name of the database to which to connect (mandatory)
-    /// - host - Host to which to connect (optional, defaults to "localhost")
-    /// - user - Username under which to connect (optional)
-    /// - password - Password for "user" on the database (optional)
-    ///
-    /// If the database is successfully opened, the version number in the
-    /// schema_version table will be checked against hard-coded value in
-    /// the implementation file.
-    ///
-    /// Finally, all the SQL commands are pre-compiled.
-    ///
-    /// @param parameters A data structure relating keywords and values
-    ///        concerned with the database.
-    ///
-    /// @throw isc::dhcp::NoDatabaseName Mandatory database name not given
-    /// @throw isc::dhcp::DbOpenError Error opening the database
-    /// @throw isc::dhcp::DbOperationError An operation on the open database has
-    ///        failed.
-    MySqlLeaseMgr(const ParameterMap& parameters);
-
-    /// @brief Destructor (closes database)
-    virtual ~MySqlLeaseMgr();
-
-    /// @brief Adds an IPv4 lease.
-    ///
-    /// @param lease lease to be added
-    ///
-    /// @result true if the lease was added, false if not (because a lease
-    ///         with the same address was already there).
-    ///
-    /// @throw isc::dhcp::DbOperationError An operation on the open database has
-    ///        failed.
-    virtual bool addLease(const Lease4Ptr& lease);
-
-    /// @brief Adds an IPv6 lease.
-    ///
-    /// @param lease lease to be added
-    ///
-    /// @result true if the lease was added, false if not (because a lease
-    ///         with the same address was already there).
-    ///
-    /// @throw isc::dhcp::DbOperationError An operation on the open database has
-    ///        failed.
-    virtual bool addLease(const Lease6Ptr& lease);
-
-    /// @brief Return 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 sought 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(const isc::asiolink::IOAddress& addr,
-                                SubnetID subnet_id) const;
-
-    /// @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 DUID) 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
-    ///
-    /// @return smart pointer to the lease (or NULL if a lease is not found)
-    virtual Lease4Ptr getLease4(const isc::asiolink::IOAddress& addr) 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
-    ///
-    /// 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;
-
-    /// @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.
-    ///
-    /// 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)
-    ///
-    /// @throw isc::BadValue record retrieved from database had an invalid
-    ///        lease type field.
-    /// @throw isc::dhcp::DbOperationError An operation on the open database has
-    ///        failed.
-    virtual Lease6Ptr getLease6(const isc::asiolink::IOAddress& addr) const;
-
-    /// @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;
-
-    /// @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;
-
-    /// @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(const Lease4Ptr& lease4);
-
-    /// @brief Updates IPv6 lease.
-    ///
-    /// @param lease6 The lease to be updated.
-    ///
-    /// @throw isc::dhcp::NoSuchLease Attempt to update a lease that did not
-    ///        exist.
-    /// @throw isc::dhcp::DbOperationError An operation on the open database has
-    ///        failed.
-    virtual void updateLease6(const Lease6Ptr& lease6);
-
-    /// @brief Deletes an IPv4 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(const isc::asiolink::IOAddress& addr);
-
-    /// @brief Deletes an IPv6 lease.
-    ///
-    /// @param addr IPv6 address of the lease to be deleted.
-    ///
-    /// @return true if deletion was successful, false if no such lease exists
-    ///
-    /// @throw isc::dhcp::DbOperationError An operation on the open database has
-    ///        failed.
-    virtual bool deleteLease6(const isc::asiolink::IOAddress& addr);
-
-    /// @brief Return backend type
-    ///
-    /// Returns the type of the backend (e.g. "mysql", "memfile" etc.)
-    ///
-    /// @return Type of the backend.
-    virtual std::string getType() const {
-        return (std::string("mysql"));
-    }
-
-    /// @brief Returns backend name.
-    ///
-    /// Each backend have specific name, e.g. "mysql" or "sqlite".
-    ///
-    /// @return Name of the backend.
-    virtual std::string getName() const;
-
-    /// @brief Returns description of the backend.
-    ///
-    /// This description may be multiline text that describes the backend.
-    ///
-    /// @return Description of the backend.
-    virtual std::string getDescription() const;
-
-    /// @brief Returns backend version.
-    ///
-    /// @return Version number as a pair of unsigned integers.  "first" is the
-    ///         major version number, "second" the minor number.
-    ///
-    /// @throw isc::dhcp::DbOperationError An operation on the open database has
-    ///        failed.
-    virtual std::pair<uint32_t, uint32_t> getVersion() const;
-
-    /// @brief Commit Transactions
-    ///
-    /// Commits all pending database operations.  On databases that don't
-    /// support transactions, this is a no-op.
-    ///
-    /// @throw DbOperationError Iif the commit failed.
-    virtual void commit();
-
-    /// @brief Rollback Transactions
-    ///
-    /// Rolls back all pending database operations.  On databases that don't
-    /// support transactions, this is a no-op.
-    ///
-    /// @throw DbOperationError If the rollback failed.
-    virtual void rollback();
-
-    ///@{
-    /// The following methods are used to convert between times and time
-    /// intervals stored in the Lease object, and the times stored in the
-    /// database.  The reason for the difference is because in the DHCP server,
-    /// the cltt (Client Time Since Last Transmission) is the natural data; in
-    /// the lease file - which may be read by the user - it is the expiry time
-    /// of the lease.
-
-    /// @brief Convert Lease Time to Database Times
-    ///
-    /// Within the DHCP servers, times are stored as client last transmit time
-    /// and valid lifetime.  In the database, the information is stored as
-    /// valid lifetime and "expire" (time of expiry of the lease).  They are
-    /// related by the equation:
-    ///
-    /// - expire = client last transmit time + valid lifetime
-    ///
-    /// This method converts from the times in the lease object into times
-    /// able to be added to the database.
-    ///
-    /// @param cltt Client last transmit time
-    /// @param valid_lifetime Valid lifetime
-    /// @param expire Reference to MYSQL_TIME object where the expiry time of
-    ///        the lease will be put.
-    static
-    void convertToDatabaseTime(time_t cltt, uint32_t valid_lifetime,
-                               MYSQL_TIME& expire);
-
-    /// @brief Convert Database Time to Lease Times
-    ///
-    /// Within the database, time is stored as "expire" (time of expiry of the
-    /// lease) and valid lifetime.  In the DHCP server, the information is
-    /// stored client last transmit time and valid lifetime.  These are related
-    /// by the equation:
-    ///
-    /// - client last transmit time = expire - valid_lifetime
-    ///
-    /// This method converts from the times in the database into times
-    /// able to be inserted into the lease object.
-    ///
-    /// @param expire Reference to MYSQL_TIME object from where the expiry
-    ///        time of the lease is taken.
-    /// @param valid_lifetime lifetime of the lease.
-    /// @param cltt Reference to location where client last transmit time
-    ///        is put.
-    static
-    void convertFromDatabaseTime(const MYSQL_TIME& expire, 
-                                 uint32_t valid_lifetime, time_t& cltt);
-    ///@}
-
-    /// @brief Statement Tags
-    ///
-    /// The contents of the enum are indexes into the list of SQL statements
-    enum StatementIndex {
-        DELETE_LEASE6,              // Delete from lease6 by address
-        GET_LEASE6_ADDR,            // Get lease6 by address
-        GET_LEASE6_DUID_IAID,       // Get lease6 by DUID and IAID
-        GET_LEASE6_DUID_IAID_SUBID, // Get lease6 by DUID, IAID and Subnet ID
-        GET_VERSION,                // Obtain version number
-        INSERT_LEASE6,              // Add entry to lease6 table
-        UPDATE_LEASE6,              // Update a Lease6 entry
-        NUM_STATEMENTS              // Number of statements
-    };
-
-private:
-    /// @brief Prepare Single Statement
-    ///
-    /// Creates a prepared statement from the text given and adds it to the
-    /// statements_ vector at the given index.
-    ///
-    /// @param index Index into the statements_ vector into which the text
-    ///        should be placed.  The vector must be big enough for the index
-    ///        to be valid, else an exception will be thrown.
-    /// @param text Text of the SQL statement to be prepared.
-    ///
-    /// @throw isc::dhcp::DbOperationError An operation on the open database has
-    ///        failed.
-    /// @throw isc::InvalidParameter 'index' is not valid for the vector.
-    void prepareStatement(StatementIndex index, const char* text);
-
-    /// @brief Prepare statements
-    ///
-    /// Creates the prepared statements for all of the SQL statements used
-    /// by the MySQL backend.
-    ///
-    /// @throw isc::dhcp::DbOperationError An operation on the open database has
-    ///        failed.
-    /// @throw isc::InvalidParameter 'index' is not valid for the vector.  This
-    ///        represents an internal error within the code.
-    void prepareStatements();
-
-    /// @brief Open Database
-    ///
-    /// Opens the database using the information supplied in the parameters
-    /// passed to the constructor.
-    ///
-    /// @throw NoDatabaseName Mandatory database name not given
-    /// @throw DbOpenError Error opening the database
-    void openDatabase();
-
-    /// @brief Binds Parameters and Executes
-    ///
-    /// This method abstracts a lot of common processing from the getXxxx()
-    /// methods.  It binds the parameters passed to it to the appropriate
-    /// prepared statement, and binds the variables in the exchange6 object to
-    /// the output parameters of the statement.  It then executes the prepared
-    /// statement.
-    ///
-    /// The data can be retrieved using mysql_stmt_fetch and the getLeaseData()
-    /// method on the exchange6 object.
-    ///
-    /// @param stindex Index of prepared statement to be executed
-    /// @param inbind Array of MYSQL_BIND objects representing the parameters.
-    ///        (Note that the number is determined by the number of parameters
-    ///        in the statement.)
-    ///
-    /// @throw isc::dhcp::DbOperationError An operation on the open database has
-    ///        failed.
-    void bind6AndExecute(StatementIndex stindex, MYSQL_BIND* inbind) const;
-
-    /// @brief Check Error and Throw Exception
-    ///
-    /// Virtually all MySQL functions return a status which, if non-zero,
-    /// indicates an error.  This inline function conceals a lot of error
-    /// checking/exception-throwing code.
-    ///
-    /// @param status Status code: non-zero implies an error
-    /// @param index Index of statement that caused the error
-    /// @param what High-level description of the error
-    ///
-    /// @throw isc::dhcp::DbOperationError An operation on the open database has
-    ///        failed.
-    inline void checkError(int status, StatementIndex index,
-                           const char* what) const {
-        if (status != 0) {
-            isc_throw(DbOperationError, what << " for <" <<
-                      text_statements_[index] << ">, reason: " <<
-                      mysql_error(mysql_) << " (error code " <<
-                      mysql_errno(mysql_) << ")");
-        }
-    }
-
-    // Members
-
-    /// Used for transfer of data to/from the database. This is a pointed-to
-    /// object as its contents may change in "const" calls, while the rest
-    /// of this object does not.  (At alternative would be to declare it as
-    /// "mutable".)
-    boost::scoped_ptr<MySqlLease6Exchange> exchange6_;
-    MYSQL*              mysql_;                 ///< MySQL context object
-    std::vector<std::string> text_statements_;  ///< Raw text of statements
-    std::vector<MYSQL_STMT*> statements_;       ///< Prepared statements
-};
-
-}; // end of isc::dhcp namespace
-}; // end of isc namespace
-
-#endif // MYSQL_LEASE_MGR_H
diff --git a/src/lib/dhcp/pool.cc b/src/lib/dhcp/pool.cc
deleted file mode 100644
index 1cf47a3..0000000
--- a/src/lib/dhcp/pool.cc
+++ /dev/null
@@ -1,118 +0,0 @@
-// 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_));
-}
-
-Pool4::Pool4(const isc::asiolink::IOAddress& first,
-             const isc::asiolink::IOAddress& last)
-    :Pool(first, last) {
-    // check if specified address boundaries are sane
-    if (first.getFamily() != AF_INET || last.getFamily() != AF_INET) {
-        isc_throw(BadValue, "Invalid Pool4 address boundaries: not IPv4");
-    }
-
-    if (last < first) {
-        isc_throw(BadValue, "Upper boundary is smaller than lower boundary.");
-    }
-}
-
-Pool4::Pool4(const isc::asiolink::IOAddress& prefix,
-             uint8_t prefix_len)
-    :Pool(prefix, IOAddress("0.0.0.0")) {
-
-    // check if the prefix is sane
-    if (prefix.getFamily() != AF_INET) {
-        isc_throw(BadValue, "Invalid Pool4 address boundaries: not IPv4");
-    }
-
-    // check if the prefix length is sane
-    if (prefix_len == 0 || prefix_len > 32) {
-        isc_throw(BadValue, "Invalid prefix length");
-    }
-
-    // Let's now calculate the last address in defined pool
-    last_ = lastAddrInPrefix(prefix, prefix_len);
-}
-
-
-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
deleted file mode 100644
index dd68fdd..0000000
--- a/src/lib/dhcp/pool.h
+++ /dev/null
@@ -1,184 +0,0 @@
-// Copyright (C) 2012 Internet Systems Consortium, Inc. ("ISC")
-//
-// Permission to use, copy, modify, and/or distribute this software for any
-// purpose with or without fee is hereby granted, provided that the above
-// copyright notice and this permission notice appear in all copies.
-//
-// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
-// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
-// AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
-// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
-// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
-// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
-// PERFORMANCE OF THIS SOFTWARE.
-
-#ifndef POOL_H
-#define POOL_H
-
-#include <vector>
-#include <asiolink/io_address.h>
-#include <boost/shared_ptr.hpp>
-
-namespace isc {
-namespace dhcp {
-
-/// @brief base class for Pool4 and Pool6
-///
-/// Stores information about pool of IPv4 or IPv6 addresses.
-/// That is a basic component of a configuration.
-class Pool {
-
-public:
-
-    /// @brief returns Pool-id
-    ///
-    /// @return pool-id value
-    /// Pool-id is an unique value that can be used to identify a pool.
-    uint32_t getId() const {
-        return (id_);
-    }
-
-    /// @brief Returns the first address in a pool.
-    ///
-    /// @return first address in a pool
-    const isc::asiolink::IOAddress& getFirstAddress() const {
-        return (first_);
-    }
-
-    /// @brief Returns the last address in a pool.
-    /// @return last address in a pool
-    const isc::asiolink::IOAddress& getLastAddress() const {
-        return (last_);
-    }
-
-    /// @brief Checks if a given address is in the range.
-    ///
-    /// @return true, if the address is in pool
-    bool inRange(const isc::asiolink::IOAddress& addr) const;
-
-protected:
-
-    /// @brief protected constructor
-    ///
-    /// This constructor is protected to prevent anyone from instantiating
-    /// Pool class directly. Instances of Pool4 and Pool6 should be created
-    /// instead.
-    Pool(const isc::asiolink::IOAddress& first,
-         const isc::asiolink::IOAddress& last);
-
-    /// @brief returns the next unique Pool-ID
-    ///
-    /// @return the next unique Pool-ID
-    static uint32_t getNextID() {
-        static uint32_t id = 0;
-        return (id++);
-    }
-
-    /// @brief pool-id
-    ///
-    /// This ID is used to identify this specific pool.
-    uint32_t id_;
-
-    /// @brief The first address in a pool
-    isc::asiolink::IOAddress first_;
-
-    /// @brief The last address in a pool
-    isc::asiolink::IOAddress last_;
-
-    /// @brief Comments field
-    ///
-    /// @todo: This field is currently not used.
-    std::string comments_;
-};
-
-/// @brief Pool information for IPv4 addresses
-///
-/// It holds information about pool4, i.e. a range of IPv4 address space that
-/// is configured for DHCP allocation.
-class Pool4 : public Pool {
-public:
-    /// @brief the constructor for Pool4 "min-max" style definition
-    ///
-    /// @param first the first address in a pool
-    /// @param last the last address in a pool
-    Pool4(const isc::asiolink::IOAddress& first,
-          const isc::asiolink::IOAddress& last);
-
-    /// @brief the constructor for Pool4 "prefix/len" style definition
-    ///
-    /// @param prefix specifies prefix of the pool
-    /// @param prefix_len specifies length of the prefix of the pool
-    Pool4(const isc::asiolink::IOAddress& prefix,
-          uint8_t prefix_len);
-};
-
-/// @brief a pointer an IPv4 Pool
-typedef boost::shared_ptr<Pool4> Pool4Ptr;
-
-/// @brief a container for IPv4 Pools
-typedef std::vector<Pool4Ptr> Pool4Collection;
-
-/// @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 type type of the pool (IA, TA or PD)
-    /// @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 type type of the pool (IA, TA or PD)
-    /// @param prefix specifies prefix of the pool
-    /// @param prefix_len specifies length of the prefix of the pool
-    Pool6(Pool6Type type, const isc::asiolink::IOAddress& prefix,
-          uint8_t prefix_len);
-
-    /// @brief returns pool type
-    ///
-    /// @return pool type
-    Pool6Type getType() const {
-        return (type_);
-    }
-
-private:
-    /// @brief defines a pool type
-    Pool6Type type_;
-
-    /// @brief prefix length
-    /// used by TYPE_PD only (zeroed for other types)
-    uint8_t prefix_len_;
-};
-
-/// @brief a pointer an IPv6 Pool
-typedef boost::shared_ptr<Pool6> Pool6Ptr;
-
-/// @brief a container for IPv6 Pools
-typedef std::vector<Pool6Ptr> Pool6Collection;
-
-} // end of isc::dhcp namespace
-} // end of isc namespace
-
-
-#endif // POOL_H
diff --git a/src/lib/dhcp/subnet.cc b/src/lib/dhcp/subnet.cc
deleted file mode 100644
index 28f2391..0000000
--- a/src/lib/dhcp/subnet.cc
+++ /dev/null
@@ -1,203 +0,0 @@
-// Copyright (C) 2012 Internet Systems Consortium, Inc. ("ISC")
-//
-// Permission to use, copy, modify, and/or distribute this software for any
-// purpose with or without fee is hereby granted, provided that the above
-// copyright notice and this permission notice appear in all copies.
-//
-// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
-// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
-// AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
-// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
-// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
-// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
-// PERFORMANCE OF THIS SOFTWARE.
-
-#include <dhcp/addr_utilities.h>
-#include <asiolink/io_address.h>
-#include <dhcp/subnet.h>
-#include <sstream>
-
-using namespace isc::asiolink;
-
-namespace isc {
-namespace dhcp {
-
-Subnet::Subnet(const isc::asiolink::IOAddress& prefix, uint8_t len,
-               const Triplet<uint32_t>& t1,
-               const Triplet<uint32_t>& t2,
-               const Triplet<uint32_t>& valid_lifetime)
-    :id_(getNextID()), prefix_(prefix), prefix_len_(len), t1_(t1),
-     t2_(t2), valid_(valid_lifetime),
-     last_allocated_(lastAddrInPrefix(prefix, len)) {
-    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));
-}
-
-void
-Subnet::addOption(OptionPtr& option, bool persistent /* = false */) {
-    validateOption(option);
-    options_.push_back(OptionDescriptor(option, persistent));
-}
-
-void
-Subnet::delOptions() {
-    options_.clear();
-}
-
-std::string Subnet::toText() const {
-    std::stringstream tmp;
-    tmp << prefix_.toText() << "/" << static_cast<unsigned int>(prefix_len_);
-    return (tmp.str());
-}
-
-Subnet4::Subnet4(const isc::asiolink::IOAddress& prefix, uint8_t length,
-                 const Triplet<uint32_t>& t1,
-                 const Triplet<uint32_t>& t2,
-                 const Triplet<uint32_t>& valid_lifetime)
-    :Subnet(prefix, length, t1, t2, valid_lifetime) {
-    if (prefix.getFamily() != AF_INET) {
-        isc_throw(BadValue, "Non IPv4 prefix " << prefix.toText()
-                  << " specified in subnet4");
-    }
-}
-
-void Subnet4::addPool4(const Pool4Ptr& pool) {
-    IOAddress first_addr = pool->getFirstAddress();
-    IOAddress last_addr = pool->getLastAddress();
-
-    if (!inRange(first_addr) || !inRange(last_addr)) {
-        isc_throw(BadValue, "Pool4 (" << first_addr.toText() << "-" << last_addr.toText()
-                  << " does not belong in this (" << prefix_ << "/" << prefix_len_
-                  << ") subnet4");
-    }
-
-    /// @todo: Check that pools do not overlap
-
-    pools_.push_back(pool);
-}
-
-Pool4Ptr Subnet4::getPool4(const isc::asiolink::IOAddress& hint /* = IOAddress("::")*/ ) {
-    Pool4Ptr candidate;
-    for (Pool4Collection::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);
-}
-
-void
-Subnet4::validateOption(const OptionPtr& option) const {
-    if (!option) {
-        isc_throw(isc::BadValue, "option configured for subnet must not be NULL");
-    } else if (option->getUniverse() != Option::V4) {
-        isc_throw(isc::BadValue, "expected V4 option to be added to the subnet");
-    }
-}
-
-bool Subnet4::inPool(const isc::asiolink::IOAddress& addr) const {
-
-    // Let's start with checking if it even belongs to that subnet.
-    if (!inRange(addr)) {
-        return (false);
-    }
-
-    for (Pool4Collection::const_iterator pool = pools_.begin(); pool != pools_.end(); ++pool) {
-        if ((*pool)->inRange(addr)) {
-            return (true);
-        }
-    }
-    // there's no pool that address belongs to
-    return (false);
-}
-
-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);
-}
-
-void
-Subnet6::validateOption(const OptionPtr& option) const {
-    if (!option) {
-        isc_throw(isc::BadValue, "option configured for subnet must not be NULL");
-    } else if (option->getUniverse() != Option::V6) {
-        isc_throw(isc::BadValue, "expected V6 option to be added to the subnet");
-    }
-}
-
-bool Subnet6::inPool(const isc::asiolink::IOAddress& addr) const {
-
-    // Let's start with checking if it even belongs to that subnet.
-    if (!inRange(addr)) {
-        return (false);
-    }
-
-    for (Pool6Collection::const_iterator pool = pools_.begin(); pool != pools_.end(); ++pool) {
-        if ((*pool)->inRange(addr)) {
-            return (true);
-        }
-    }
-    // there's no pool that address belongs to
-    return (false);
-}
-
-} // end of isc::dhcp namespace
-} // end of isc namespace
diff --git a/src/lib/dhcp/subnet.h b/src/lib/dhcp/subnet.h
deleted file mode 100644
index fcedda6..0000000
--- a/src/lib/dhcp/subnet.h
+++ /dev/null
@@ -1,517 +0,0 @@
-// 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 <asiolink/io_address.h>
-#include <dhcp/pool.h>
-#include <dhcp/triplet.h>
-#include <dhcp/option.h>
-#include <boost/shared_ptr.hpp>
-#include <boost/multi_index_container.hpp>
-#include <boost/multi_index/hashed_index.hpp>
-#include <boost/multi_index/sequenced_index.hpp>
-#include <boost/multi_index/mem_fun.hpp>
-#include <boost/multi_index/member.hpp>
-
-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). It also holds the set
-/// of DHCP option instances configured for the subnet. These options are
-/// included in DHCP messages being sent to clients which are connected
-/// to the particular subnet.
-///
-/// @todo: Implement support for options here
-
-
-/// @brief Unique indentifier for a subnet (both v4 and v6)
-typedef uint32_t SubnetID;
-
-class Subnet {
-public:
-
-    /// @brief Option descriptor.
-    ///
-    /// Option descriptor holds information about option configured for
-    /// a particular subnet. This information comprises the actual option
-    /// instance and information whether this option is sent to DHCP client
-    /// only on request (persistent = false) or always (persistent = true).
-    struct OptionDescriptor {
-        /// Option instance.
-        OptionPtr option;
-        /// Persistent flag, if true option is always sent to the client,
-        /// if false option is sent to the client on request.
-        bool persistent;
-
-        /// @brief Constructor.
-        ///
-        /// @param opt option
-        /// @param persist if true option is always sent.
-        OptionDescriptor(OptionPtr& opt, bool persist)
-            : option(opt), persistent(persist) {};
-
-        /// @brief Constructor
-        ///
-        /// @param persist if true option is always sent.
-        OptionDescriptor(bool persist)
-            : option(OptionPtr()), persistent(persist) {};
-    };
-
-    /// @brief Extractor class to extract key with another key.
-    ///
-    /// This class solves the problem of accessing index key values
-    /// that are stored in objects nested in other objects.
-    /// Each OptionDescriptor structure contains the OptionPtr object.
-    /// The value retured by one of its accessors (getType) is used
-    /// as an indexing value in the multi_index_container defined below.
-    /// There is no easy way to mark that value returned by Option::getType
-    /// should be an index of this multi_index_container. There are standard
-    /// key extractors such as 'member' or 'mem_fun' but they are not
-    /// sufficient here. The former can be used to mark that member of
-    /// the structure that is held in the container should be used as an
-    /// indexing value. The latter can be used if the indexing value is
-    /// a product of the class being held in the container. In this complex
-    /// scenario when the indexing value is a product of the function that
-    /// is wrapped by the structure, this new extractor template has to be
-    /// defined. The template class provides a 'chain' of two extractors
-    /// to access the value returned by nested object and to use it as
-    /// indexing value.
-    /// For some more examples of complex keys see:
-    /// http://www.cs.brown.edu/~jwicks/boost/libs/multi_index/doc/index.html
-    ///
-    /// @tparam KeyExtractor1 extractor used to access data in
-    /// OptionDescriptor::option
-    /// @tparam KeyExtractor2 extractor used to access
-    /// OptionDescriptor::option member.
-    template<typename KeyExtractor1, typename KeyExtractor2>
-    class KeyFromKey {
-    public:
-        typedef typename KeyExtractor1::result_type result_type;
-
-        /// @brief Constructor.
-        KeyFromKey()
-            : key1_(KeyExtractor1()), key2_(KeyExtractor2()) { };
-
-        /// @brief Extract key with another key.
-        ///
-        /// @param arg the key value.
-        ///
-        /// @tparam key value type.
-        template<typename T>
-        result_type operator() (T& arg) const {
-            return (key1_(key2_(arg)));
-        }
-    private:
-        KeyExtractor1 key1_; ///< key 1.
-        KeyExtractor2 key2_; ///< key 2.
-    };
-
-    /// @brief Multi index container for DHCP option descriptors.
-    ///
-    /// This container comprises three indexes to access option
-    /// descriptors:
-    /// - sequenced index: used to access elements in the order they
-    /// have been added to the container,
-    /// - option type index: used to search option descriptors containing
-    /// options with specific option code (aka option type).
-    /// - persistency flag index: used to search option descriptors with
-    /// 'persistent' flag set to true.
-    ///
-    /// This container is the equivalent of three separate STL containers:
-    /// - std::list of all options,
-    /// - std::multimap of options with option code used as a multimap key,
-    /// - std::multimap of option descriptors with option persistency flag
-    /// used as a multimap key.
-    /// The major advantage of this container over 3 separate STL containers
-    /// is automatic synchronization of all indexes when elements are added,
-    /// removed or modified in the container. With separate containers,
-    /// the synchronization would have to be guaranteed by the Subnet class
-    /// code. This would increase code complexity and presumably it would
-    /// be much harder to add new search criteria (indexes).
-    ///
-    /// @todo we may want to search for options using option spaces when
-    /// they are implemented.
-    ///
-    /// @see http://www.boost.org/doc/libs/1_51_0/libs/multi_index/doc/index.html
-    typedef boost::multi_index_container<
-        // Container comprises elements of OptionDescriptor type.
-        OptionDescriptor,
-        // Here we start enumerating various indexes.
-        boost::multi_index::indexed_by<
-            // Sequenced index allows accessing elements in the same way
-            // as elements in std::list.
-            // Sequenced is an index #0.
-            boost::multi_index::sequenced<>,
-            // Start definition of index #1.
-            boost::multi_index::hashed_non_unique<
-                // KeyFromKey is the index key extractor that allows accessing
-                // option type being held by the OptionPtr through
-                // OptionDescriptor structure.
-                KeyFromKey<
-                    // Use option type as the index key. The type is held
-                    // in OptionPtr object so we have to call Option::getType
-                    // to retrieve this key for each element.
-                    boost::multi_index::mem_fun<
-                        Option,
-                        uint16_t,
-                        &Option::getType
-                    >,
-                    // Indicate that OptionPtr is a member of
-                    // OptionDescriptor structure.
-                    boost::multi_index::member<
-                        OptionDescriptor,
-                        OptionPtr,
-                        &OptionDescriptor::option
-                    >
-                 >
-            >,
-            // Start definition of index #2.
-            // Use 'persistent' struct member as a key.
-            boost::multi_index::hashed_non_unique<
-                boost::multi_index::member<
-                    OptionDescriptor,
-                    bool,
-                    &OptionDescriptor::persistent
-                >
-            >
-        >
-    > OptionContainer;
-
-    /// Type of the index #1 - option type.
-    typedef OptionContainer::nth_index<1>::type OptionContainerTypeIndex;
-    /// Pair of iterators to represent the range of options having the
-    /// same option type value. The first element in this pair represents
-    /// the begining of the range, the second element represents the end.
-    typedef std::pair<OptionContainerTypeIndex::const_iterator,
-                      OptionContainerTypeIndex::const_iterator> OptionContainerTypeRange;
-    /// Type of the index #2 - option persistency flag.
-    typedef OptionContainer::nth_index<2>::type OptionContainerPersistIndex;
-
-    /// @brief checks if specified address is in range
-    bool inRange(const isc::asiolink::IOAddress& addr) const;
-
-    /// @brief Add new option instance to the collection.
-    ///
-    /// @param option option instance.
-    /// @param persistent if true, send an option regardless if client
-    /// requested it or not.
-    ///
-    /// @throw isc::BadValue if invalid option provided.
-    void addOption(OptionPtr& option, bool persistent = false);
-
-    /// @brief Delete all options configured for the subnet.
-    void delOptions();
-
-    /// @brief checks if the specified address is in pools
-    ///
-    /// Note the difference between inSubnet() and inPool(). For a given
-    /// subnet (e.g. 2001::/64) there may be one or more pools defined
-    /// that may or may not cover entire subnet, e.g. pool 2001::1-2001::10).
-    /// inPool() returning true implies inSubnet(), but the reverse implication
-    /// is not always true. For the given example, 2001::1234:abcd would return
-    /// true for inSubnet(), but false for inPool() check.
-    ///
-    /// @param addr this address will be checked if it belongs to any pools in
-    ///        that subnet
-    /// @return true if the address is in any of the pools
-    virtual bool inPool(const isc::asiolink::IOAddress& addr) const = 0;
-
-    /// @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_);
-    }
-
-    /// @brief Return a collection of options.
-    ///
-    /// @return reference to collection of options configured for a subnet.
-    /// The returned reference is valid as long as the Subnet object which
-    /// returned it still exists.
-    const OptionContainer& getOptions() const {
-        return (options_);
-    }
-
-    /// @brief returns the last address that was tried from this pool
-    ///
-    /// This method returns the last address that was attempted to be allocated
-    /// from this subnet. This is used as helper information for the next
-    /// iteration of the allocation algorithm.
-    ///
-    /// @todo: Define map<SubnetID, IOAddress> somewhere in the
-    ///        AllocEngine::IterativeAllocator and keep the data there
-    ///
-    /// @return address that was last tried from this pool
-    isc::asiolink::IOAddress getLastAllocated() const {
-        return (last_allocated_);
-    }
-
-    /// @brief sets the last address that was tried from this pool
-    ///
-    /// This method sets the last address that was attempted to be allocated
-    /// from this subnet. This is used as helper information for the next
-    /// iteration of the allocation algorithm.
-    ///
-    /// @todo: Define map<SubnetID, IOAddress> somewhere in the
-    ///        AllocEngine::IterativeAllocator and keep the data there
-    void setLastAllocated(const isc::asiolink::IOAddress& addr) {
-        last_allocated_ = addr;
-    }
-
-    /// @brief returns unique ID for that subnet
-    /// @return unique ID for that subnet
-    SubnetID getID() const { return (id_); }
-
-    /// @brief returns subnet parameters (prefix and prefix length)
-    ///
-    /// @return (prefix, prefix length) pair
-    std::pair<isc::asiolink::IOAddress, uint8_t> get() const {
-        return (std::make_pair(prefix_, prefix_len_));
-    }
-
-    /// @brief returns textual representation of the subnet (e.g. "2001:db8::/64")
-    ///
-    /// @return textual representation
-    virtual std::string toText() const;
-
-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 virtual destructor
-    ///
-    /// A virtual destructor is needed because other classes
-    /// derive from this class.
-    virtual ~Subnet() { };
-
-    /// @brief returns the next unique Subnet-ID
-    ///
-    /// @return the next unique Subnet-ID
-    static SubnetID getNextID() {
-        static SubnetID id = 0;
-        return (id++);
-    }
-
-    /// @brief Check if option is valid and can be added to a subnet.
-    ///
-    /// @param option option to be validated.
-    virtual void validateOption(const OptionPtr& option) const = 0;
-
-    /// @brief subnet-id
-    ///
-    /// Subnet-id is a unique value that can be used to find or identify
-    /// a Subnet4 or Subnet6.
-    SubnetID 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 collection of DHCP options configured for a subnet.
-    OptionContainer options_;
-
-    /// @brief last allocated address
-    ///
-    /// This is the last allocated address that was previously allocated from
-    /// this particular subnet. Some allocation algorithms (e.g. iterative) use
-    /// that value, others do not. It should be noted that although the value
-    /// is usually correct, there are cases when it is invalid, e.g. after
-    /// removing a pool, restarting or changing allocation algorithms. For
-    /// that purpose it should be only considered a help that should not be
-    /// fully trusted.
-    isc::asiolink::IOAddress last_allocated_;
-};
-
-/// @brief A configuration holder for IPv4 subnet.
-///
-/// This class represents an IPv4 subnet.
-class Subnet4 : public Subnet {
-public:
-
-    /// @brief Constructor with all parameters
-    ///
-    /// @param prefix Subnet4 prefix
-    /// @param length prefix length
-    /// @param t1 renewal timer (in seconds)
-    /// @param t2 rebind timer (in seconds)
-    /// @param valid_lifetime preferred lifetime of leases (in seconds)
-    Subnet4(const isc::asiolink::IOAddress& prefix, uint8_t length,
-            const Triplet<uint32_t>& t1,
-            const Triplet<uint32_t>& t2,
-            const Triplet<uint32_t>& valid_lifetime);
-
-    /// @brief Returns a pool that specified address belongs to
-    ///
-    /// @param hint address that the returned pool should cover (optional)
-    /// @return Pointer to found pool4 (or NULL)
-    Pool4Ptr getPool4(const isc::asiolink::IOAddress& hint =
-                      isc::asiolink::IOAddress("0.0.0.0"));
-
-    /// @brief Adds a new pool.
-    /// @param pool pool to be added
-    void addPool4(const Pool4Ptr& 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 Pool4Collection& getPools() const {
-        return pools_;
-    }
-
-    /// @brief checks if the specified address is in pools
-    ///
-    /// See the description in \ref Subnet::inPool().
-    ///
-    /// @param addr this address will be checked if it belongs to any pools in that subnet
-    /// @return true if the address is in any of the pools
-    bool inPool(const isc::asiolink::IOAddress& addr) const;
-
-protected:
-
-    /// @brief Check if option is valid and can be added to a subnet.
-    ///
-    /// @param option option to be validated.
-    ///
-    /// @throw isc::BadValue if provided option is invalid.
-    virtual void validateOption(const OptionPtr& option) const;
-
-    /// @brief collection of pools in that list
-    Pool4Collection pools_;
-};
-
-/// @brief A pointer to a Subnet4 object
-typedef boost::shared_ptr<Subnet4> Subnet4Ptr;
-
-/// @brief A collection of Subnet6 objects
-typedef std::vector<Subnet4Ptr> Subnet4Collection;
-
-
-/// @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_;
-    }
-
-    /// @brief checks if the specified address is in pools
-    ///
-    /// See the description in \ref Subnet::inPool().
-    ///
-    /// @param addr this address will be checked if it belongs to any pools in that subnet
-    /// @return true if the address is in any of the pools
-    bool inPool(const isc::asiolink::IOAddress& addr) const;
-
-protected:
-
-    /// @brief Check if option is valid and can be added to a subnet.
-    ///
-    /// @param option option to be validated.
-    ///
-    /// @throw isc::BadValue if provided option is invalid.
-    virtual void validateOption(const OptionPtr& option) const;
-
-    /// @brief collection of pools in that list
-    Pool6Collection pools_;
-
-    /// @brief a triplet with preferred lifetime (in seconds)
-    Triplet<uint32_t> preferred_;
-};
-
-/// @brief A pointer to a Subnet6 object
-typedef boost::shared_ptr<Subnet6> Subnet6Ptr;
-
-/// @brief A collection of Subnet6 objects
-typedef std::vector<Subnet6Ptr> Subnet6Collection;
-
-} // end of isc::dhcp namespace
-} // end of isc namespace
-
-#endif // SUBNET_T
diff --git a/src/lib/dhcp/tests/Makefile.am b/src/lib/dhcp/tests/Makefile.am
index f038fa0..945f822 100644
--- a/src/lib/dhcp/tests/Makefile.am
+++ b/src/lib/dhcp/tests/Makefile.am
@@ -24,7 +24,8 @@ TESTS_ENVIRONMENT = \
 
 TESTS =
 if HAVE_GTEST
-TESTS += libdhcp++_unittests libdhcpsrv_unittests
+TESTS += libdhcp++_unittests
+
 libdhcp___unittests_SOURCES  = run_unittests.cc
 libdhcp___unittests_SOURCES += iface_mgr_unittest.cc
 libdhcp___unittests_SOURCES += libdhcp++_unittest.cc
@@ -38,48 +39,18 @@ libdhcp___unittests_SOURCES += option_definition_unittest.cc
 libdhcp___unittests_SOURCES += option_unittest.cc
 libdhcp___unittests_SOURCES += pkt4_unittest.cc
 libdhcp___unittests_SOURCES += pkt6_unittest.cc
-libdhcp___unittests_SOURCES += schema_copy.h
+libdhcp___unittests_SOURCES += duid_unittest.cc
 
 libdhcp___unittests_CPPFLAGS = $(AM_CPPFLAGS) $(GTEST_INCLUDES) $(LOG4CPLUS_INCLUDES)
-libdhcp___unittests_LDFLAGS  = $(AM_LDFLAGS)  $(GTEST_LDFLAGS)
-libdhcp___unittests_CXXFLAGS = $(AM_CXXFLAGS)
-
-libdhcpsrv_unittests_SOURCES  = run_unittests.cc
-libdhcpsrv_unittests_SOURCES += addr_utilities_unittest.cc
-libdhcpsrv_unittests_SOURCES += alloc_engine_unittest.cc
-libdhcpsrv_unittests_SOURCES += cfgmgr_unittest.cc
-libdhcpsrv_unittests_SOURCES += duid_unittest.cc
-libdhcpsrv_unittests_SOURCES += lease_mgr_factory_unittest.cc
-libdhcpsrv_unittests_SOURCES += lease_mgr_unittest.cc
-libdhcpsrv_unittests_SOURCES += memfile_lease_mgr_unittest.cc
-if HAVE_MYSQL
-libdhcpsrv_unittests_SOURCES += mysql_lease_mgr_unittest.cc
-endif
-libdhcpsrv_unittests_SOURCES += pool_unittest.cc
-libdhcpsrv_unittests_SOURCES += subnet_unittest.cc
-libdhcpsrv_unittests_SOURCES += triplet_unittest.cc
-
-libdhcpsrv_unittests_CPPFLAGS = $(AM_CPPFLAGS) $(GTEST_INCLUDES) $(LOG4CPLUS_INCLUDES)
-libdhcpsrv_unittests_LDFLAGS  = $(AM_LDFLAGS)  $(GTEST_LDFLAGS)
-libdhcpsrv_unittests_CXXFLAGS = $(AM_CXXFLAGS)
-libdhcpsrv_unittests_LDADD  = $(GTEST_LDADD)
-libdhcpsrv_unittests_LDADD += $(top_builddir)/src/lib/exceptions/libb10-exceptions.la
-libdhcpsrv_unittests_LDADD += $(top_builddir)/src/lib/asiolink/libb10-asiolink.la
-libdhcpsrv_unittests_LDADD += $(top_builddir)/src/lib/dhcp/libb10-dhcpsrv.la
-libdhcpsrv_unittests_LDADD += $(top_builddir)/src/lib/dhcp/libb10-dhcp++.la
-libdhcpsrv_unittests_LDADD += $(top_builddir)/src/lib/log/libb10-log.la
-if HAVE_MYSQL
-libdhcpsrv_unittests_CPPFLAGS += $(MYSQL_CPPFLAGS)
-libdhcpsrv_unittests_LDFLAGS  += $(MYSQL_LIBS)
-endif
 
+libdhcp___unittests_LDFLAGS  = $(AM_LDFLAGS)  $(GTEST_LDFLAGS)
 
+libdhcp___unittests_CXXFLAGS = $(AM_CXXFLAGS)
 if USE_CLANGPP
 # This is to workaround unused variables tcout and tcerr in
 # log4cplus's streams.h and unused parameters from some of the
 # Boost headers.
 libdhcp___unittests_CXXFLAGS += -Wno-unused-variable -Wno-unused-parameter
-libdhcpsrv_unittests_CXXFLAGS += -Wno-unused-variable -Wno-unused-parameter
 endif
 
 libdhcp___unittests_LDADD  = $(top_builddir)/src/lib/dhcp/libb10-dhcp++.la
diff --git a/src/lib/dhcp/tests/addr_utilities_unittest.cc b/src/lib/dhcp/tests/addr_utilities_unittest.cc
deleted file mode 100644
index 2ea4e2a..0000000
--- a/src/lib/dhcp/tests/addr_utilities_unittest.cc
+++ /dev/null
@@ -1,154 +0,0 @@
-
-// Copyright (C) 2010  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 <stdint.h>
-#include <stdlib.h>
-
-#include <gtest/gtest.h>
-#include <vector>
-
-#include <dhcp/addr_utilities.h>
-
-using namespace std;
-using namespace isc::dhcp;
-using namespace isc::asiolink;
-
-// This test verifies that lastAddrInPrefix is able to handle IPv4 operations.
-TEST(AddrUtilitiesTest, lastAddrInPrefix4) {
-    IOAddress addr1("192.0.2.1");
-
-    // Prefixes rounded to addresses are easy...
-    EXPECT_EQ("192.255.255.255", lastAddrInPrefix(addr1, 8).toText());
-    EXPECT_EQ("192.0.255.255",   lastAddrInPrefix(addr1, 16).toText());
-    EXPECT_EQ("192.0.2.255",     lastAddrInPrefix(addr1, 24).toText());
-
-    // these are trickier
-    EXPECT_EQ("192.0.2.127", lastAddrInPrefix(addr1, 25).toText());
-    EXPECT_EQ("192.0.2.63",  lastAddrInPrefix(addr1, 26).toText());
-    EXPECT_EQ("192.0.2.31",  lastAddrInPrefix(addr1, 27).toText());
-    EXPECT_EQ("192.0.2.15",  lastAddrInPrefix(addr1, 28).toText());
-    EXPECT_EQ("192.0.2.7",   lastAddrInPrefix(addr1, 29).toText());
-    EXPECT_EQ("192.0.2.3",   lastAddrInPrefix(addr1, 30).toText());
-
-    // that doesn't make much sense as /31 subnet consists of network address
-    // and a broadcast address, with 0 usable addresses.
-    EXPECT_EQ("192.0.2.1",   lastAddrInPrefix(addr1, 31).toText());
-    EXPECT_EQ("192.0.2.1",   lastAddrInPrefix(addr1, 32).toText());
-
-    // Let's check extreme cases
-    IOAddress anyAddr("0.0.0.0");
-    EXPECT_EQ("127.255.255.255", lastAddrInPrefix(anyAddr, 1).toText());
-    EXPECT_EQ("255.255.255.255", lastAddrInPrefix(anyAddr, 0).toText());
-    EXPECT_EQ("0.0.0.0", lastAddrInPrefix(anyAddr, 32).toText());
-}
-
-// This test checks if firstAddrInPrefix is able to handle IPv4 operations.
-TEST(AddrUtilitiesTest, firstAddrInPrefix4) {
-    IOAddress addr1("192.223.2.255");
-
-    // Prefixes rounded to addresses are easy...
-    EXPECT_EQ("192.0.0.0",   firstAddrInPrefix(addr1, 8).toText());
-    EXPECT_EQ("192.223.0.0", firstAddrInPrefix(addr1, 16).toText());
-    EXPECT_EQ("192.223.2.0", firstAddrInPrefix(addr1, 24).toText());
-
-    // these are trickier
-    EXPECT_EQ("192.223.2.128", firstAddrInPrefix(addr1, 25).toText());
-    EXPECT_EQ("192.223.2.192", firstAddrInPrefix(addr1, 26).toText());
-    EXPECT_EQ("192.223.2.224", firstAddrInPrefix(addr1, 27).toText());
-    EXPECT_EQ("192.223.2.240", firstAddrInPrefix(addr1, 28).toText());
-    EXPECT_EQ("192.223.2.248", firstAddrInPrefix(addr1, 29).toText());
-    EXPECT_EQ("192.223.2.252", firstAddrInPrefix(addr1, 30).toText());
-
-    // that doesn't make much sense as /31 subnet consists of network address
-    // and a broadcast address, with 0 usable addresses.
-    EXPECT_EQ("192.223.2.254", firstAddrInPrefix(addr1, 31).toText());
-    EXPECT_EQ("192.223.2.255", firstAddrInPrefix(addr1, 32).toText());
-
-    // Let's check extreme cases.
-    IOAddress bcast("255.255.255.255");
-    EXPECT_EQ("128.0.0.0", firstAddrInPrefix(bcast, 1).toText());
-    EXPECT_EQ("0.0.0.0", firstAddrInPrefix(bcast, 0).toText());
-    EXPECT_EQ("255.255.255.255", firstAddrInPrefix(bcast, 32).toText());
-
-}
-
-/// This test checks if lastAddrInPrefix properly supports IPv6 operations
-TEST(AddrUtilitiesTest, lastAddrInPrefix6) {
-    IOAddress addr1("2001:db8:1:1234:5678:abcd:1234:beef");
-
-    // Prefixes rounded to nibbles are easy...
-    EXPECT_EQ("2001:db8:1:1234:5678:abcd:1234:ffff",
-              lastAddrInPrefix(addr1, 112).toText());
-    EXPECT_EQ("2001:db8:1:1234:5678:abcd:123f:ffff",
-              lastAddrInPrefix(addr1, 108).toText());
-    EXPECT_EQ("2001:db8:1:1234:5678:abcd:12ff:ffff",
-              lastAddrInPrefix(addr1, 104).toText());
-    EXPECT_EQ("2001:db8:1:1234:ffff:ffff:ffff:ffff",
-              lastAddrInPrefix(addr1, 64).toText());
-
-    IOAddress addr2("2001::");
-
-    // These are tricker, though, as they are done in 1 bit increments
-
-    // the last address in 2001::/127 pool should be 2001::1
-    EXPECT_EQ("2001::1", lastAddrInPrefix(addr2, 127).toText());
-
-    EXPECT_EQ("2001::3", lastAddrInPrefix(addr2, 126).toText());
-    EXPECT_EQ("2001::7", lastAddrInPrefix(addr2, 125).toText());
-    EXPECT_EQ("2001::f", lastAddrInPrefix(addr2, 124).toText());
-    EXPECT_EQ("2001::1f", lastAddrInPrefix(addr2, 123).toText());
-    EXPECT_EQ("2001::3f", lastAddrInPrefix(addr2, 122).toText());
-    EXPECT_EQ("2001::7f", lastAddrInPrefix(addr2, 121).toText());
-    EXPECT_EQ("2001::ff", lastAddrInPrefix(addr2, 120).toText());
-
-    // Let's check extreme cases
-    IOAddress anyAddr("::");
-    EXPECT_EQ("7fff:ffff:ffff:ffff:ffff:ffff:ffff:ffff",
-              lastAddrInPrefix(anyAddr, 1).toText());
-    EXPECT_EQ("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff",
-              lastAddrInPrefix(anyAddr, 0).toText());
-    EXPECT_EQ("::", lastAddrInPrefix(anyAddr, 128).toText());
-}
-
-/// This test checks if firstAddrInPrefix properly supports IPv6 operations
-TEST(AddrUtilitiesTest, firstAddrInPrefix6) {
-    IOAddress addr1("2001:db8:1:1234:5678:1234:abcd:beef");
-
-    // Prefixes rounded to nibbles are easy...
-    EXPECT_EQ("2001:db8:1:1234:5678:1234::",
-              firstAddrInPrefix(addr1, 96).toText());
-    EXPECT_EQ("2001:db8:1:1234:5678:1230::",
-              firstAddrInPrefix(addr1, 92).toText());
-    EXPECT_EQ("2001:db8:1:1234:5678:1200::",
-              firstAddrInPrefix(addr1, 88).toText());
-    EXPECT_EQ("2001:db8:1:1234::",
-              firstAddrInPrefix(addr1, 64).toText());
-
-    IOAddress addr2("2001::ffff");
-
-    // These are tricker, though, as they are done in 1 bit increments
-
-    // the first address in 2001::/127 pool should be 2001::1
-    EXPECT_EQ("2001::fffe", firstAddrInPrefix(addr2, 127).toText());
-
-    EXPECT_EQ("2001::fffc", firstAddrInPrefix(addr2, 126).toText());
-    EXPECT_EQ("2001::fff8", firstAddrInPrefix(addr2, 125).toText());
-    EXPECT_EQ("2001::fff0", firstAddrInPrefix(addr2, 124).toText());
-    EXPECT_EQ("2001::ffe0", firstAddrInPrefix(addr2, 123).toText());
-    EXPECT_EQ("2001::ffc0", firstAddrInPrefix(addr2, 122).toText());
-    EXPECT_EQ("2001::ff80", firstAddrInPrefix(addr2, 121).toText());
-    EXPECT_EQ("2001::ff00", firstAddrInPrefix(addr2, 120).toText());
-}
diff --git a/src/lib/dhcp/tests/alloc_engine_unittest.cc b/src/lib/dhcp/tests/alloc_engine_unittest.cc
deleted file mode 100644
index 456ad53..0000000
--- a/src/lib/dhcp/tests/alloc_engine_unittest.cc
+++ /dev/null
@@ -1,337 +0,0 @@
-// 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 <config.h>
-#include <asiolink/io_address.h>
-#include <dhcp/lease_mgr.h>
-#include <dhcp/lease_mgr_factory.h>
-#include <dhcp/duid.h>
-#include <dhcp/alloc_engine.h>
-#include <dhcp/cfgmgr.h>
-#include <dhcp/memfile_lease_mgr.h>
-#include <boost/shared_ptr.hpp>
-#include <boost/scoped_ptr.hpp>
-#include <iostream>
-#include <sstream>
-#include <map>
-#include <gtest/gtest.h>
-
-using namespace std;
-using namespace isc;
-using namespace isc::asiolink;
-using namespace isc::dhcp;
-
-namespace {
-
-class NakedAllocEngine : public AllocEngine {
-public:
-    NakedAllocEngine(AllocEngine::AllocType engine_type, unsigned int attempts)
-        :AllocEngine(engine_type, attempts) {
-    }
-    using AllocEngine::Allocator;
-    using AllocEngine::IterativeAllocator;
-};
-
-// empty class for now, but may be extended once Addr6 becomes bigger
-class AllocEngineTest : public ::testing::Test {
-public:
-    AllocEngineTest() {
-        duid_ = boost::shared_ptr<DUID>(new DUID(vector<uint8_t>(8, 0x42)));
-        iaid_ = 42;
-
-        // instantiate cfg_mgr
-        CfgMgr& cfg_mgr = CfgMgr::instance();
-
-        subnet_ = Subnet6Ptr(new Subnet6(IOAddress("2001:db8:1::"), 56, 1, 2, 3, 4));
-        pool_ = Pool6Ptr(new Pool6(Pool6::TYPE_IA, IOAddress("2001:db8:1::10"),
-                                   IOAddress("2001:db8:1::20")));
-        subnet_->addPool6(pool_);
-        cfg_mgr.addSubnet6(subnet_);
-
-        factory_.create("type=memfile");
-    }
-
-    void checkLease6(const Lease6Ptr& lease) {
-        // that is belongs to the right subnet
-        EXPECT_EQ(lease->subnet_id_, subnet_->getID());
-        EXPECT_TRUE(subnet_->inRange(lease->addr_));
-        EXPECT_TRUE(subnet_->inPool(lease->addr_));
-
-        // that it have proper parameters
-        EXPECT_EQ(iaid_, lease->iaid_);
-        EXPECT_EQ(subnet_->getValid(), lease->valid_lft_);
-        EXPECT_EQ(subnet_->getPreferred(), lease->preferred_lft_);
-        EXPECT_EQ(subnet_->getT1(), lease->t1_);
-        EXPECT_EQ(subnet_->getT2(), lease->t2_);
-        EXPECT_EQ(0, lease->prefixlen_); // this is IA_NA, not IA_PD
-        EXPECT_TRUE(false == lease->fqdn_fwd_);
-        EXPECT_TRUE(false == lease->fqdn_rev_);
-        EXPECT_TRUE(*lease->duid_ == *duid_);
-        // @todo: check cltt
-     }
-
-    ~AllocEngineTest() {
-        factory_.destroy();
-    }
-
-    DuidPtr duid_;
-    uint32_t iaid_;
-    Subnet6Ptr subnet_;
-    Pool6Ptr pool_;
-    LeaseMgrFactory factory_;
-};
-
-// This test checks if the Allocation Engine can be instantiated and that it
-// parses parameters string properly.
-TEST_F(AllocEngineTest, constructor) {
-    boost::scoped_ptr<AllocEngine> x;
-
-    // Hashed and random allocators are not supported yet
-    ASSERT_THROW(x.reset(new AllocEngine(AllocEngine::ALLOC_HASHED, 5)), NotImplemented);
-    ASSERT_THROW(x.reset(new AllocEngine(AllocEngine::ALLOC_RANDOM, 5)), NotImplemented);
-
-    ASSERT_NO_THROW(x.reset(new AllocEngine(AllocEngine::ALLOC_ITERATIVE, 100)));
-}
-
-/// @todo: This method is taken from mysql_lease_mgr_utilities.cc from ticket
-/// #2342. Get rid of one instance once the code is merged
-void
-detailCompareLease6(const Lease6Ptr& first, const Lease6Ptr& second) {
-    EXPECT_EQ(first->type_, second->type_);
-
-    // Compare address strings - odd things happen when they are different
-    // as the EXPECT_EQ appears to call the operator uint32_t() function,
-    // which causes an exception to be thrown for IPv6 addresses.
-    EXPECT_EQ(first->addr_.toText(), second->addr_.toText());
-    EXPECT_EQ(first->prefixlen_, second->prefixlen_);
-    EXPECT_EQ(first->iaid_, second->iaid_);
-    EXPECT_TRUE(*first->duid_ == *second->duid_);
-    EXPECT_EQ(first->preferred_lft_, second->preferred_lft_);
-    EXPECT_EQ(first->valid_lft_, second->valid_lft_);
-    EXPECT_EQ(first->cltt_, second->cltt_);
-    EXPECT_EQ(first->subnet_id_, second->subnet_id_);
-}
-
-
-// This test checks if the simple allocation can succeed
-TEST_F(AllocEngineTest, simpleAlloc) {
-    boost::scoped_ptr<AllocEngine> engine;
-    ASSERT_NO_THROW(engine.reset(new AllocEngine(AllocEngine::ALLOC_ITERATIVE, 100)));
-    ASSERT_TRUE(engine);
-
-    Lease6Ptr lease = engine->allocateAddress6(subnet_, duid_, iaid_, IOAddress("::"),
-                                               false);
-
-    // check that we got a lease
-    ASSERT_TRUE(lease);
-
-    // do all checks on the lease
-    checkLease6(lease);
-
-    // Check that the lease is indeed in LeaseMgr
-    Lease6Ptr from_mgr = LeaseMgrFactory::instance().getLease6(lease->addr_);
-    ASSERT_TRUE(from_mgr);
-
-    // Now check that the lease in LeaseMgr has the same parameters
-    detailCompareLease6(lease, from_mgr);
-}
-
-// This test checks if the fake allocation (for SOLICIT) can succeed
-TEST_F(AllocEngineTest, fakeAlloc) {
-    boost::scoped_ptr<AllocEngine> engine;
-    ASSERT_NO_THROW(engine.reset(new AllocEngine(AllocEngine::ALLOC_ITERATIVE, 100)));
-    ASSERT_TRUE(engine);
-
-    Lease6Ptr lease = engine->allocateAddress6(subnet_, duid_, iaid_, IOAddress("::"),
-                                               true);
-
-    // check that we got a lease
-    ASSERT_TRUE(lease);
-
-    // do all checks on the lease
-    checkLease6(lease);
-
-    // Check that the lease is NOT in LeaseMgr
-    Lease6Ptr from_mgr = LeaseMgrFactory::instance().getLease6(lease->addr_);
-    ASSERT_FALSE(from_mgr);
-}
-
-// This test checks if the allocation with a hint that is valid (in range,
-// in pool and free) can succeed
-TEST_F(AllocEngineTest, allocWithValidHint) {
-    boost::scoped_ptr<AllocEngine> engine;
-    ASSERT_NO_THROW(engine.reset(new AllocEngine(AllocEngine::ALLOC_ITERATIVE, 100)));
-    ASSERT_TRUE(engine);
-
-    Lease6Ptr lease = engine->allocateAddress6(subnet_, duid_, iaid_,
-                                               IOAddress("2001:db8:1::15"),
-                                               false);
-
-    // check that we got a lease
-    ASSERT_TRUE(lease);
-
-    // we should get what we asked for
-    EXPECT_EQ(lease->addr_.toText(), "2001:db8:1::15");
-
-    // do all checks on the lease
-    checkLease6(lease);
-
-    // Check that the lease is indeed in LeaseMgr
-    Lease6Ptr from_mgr = LeaseMgrFactory::instance().getLease6(lease->addr_);
-    ASSERT_TRUE(from_mgr);
-
-    // Now check that the lease in LeaseMgr has the same parameters
-    detailCompareLease6(lease, from_mgr);
-}
-
-// This test checks if the allocation with a hint that is in range,
-// in pool, but is currently used) can succeed
-TEST_F(AllocEngineTest, allocWithUsedHint) {
-    boost::scoped_ptr<AllocEngine> engine;
-    ASSERT_NO_THROW(engine.reset(new AllocEngine(AllocEngine::ALLOC_ITERATIVE, 100)));
-    ASSERT_TRUE(engine);
-
-    // let's create a lease and put it in the LeaseMgr
-    DuidPtr duid2 = boost::shared_ptr<DUID>(new DUID(vector<uint8_t>(8, 0xff)));
-    Lease6Ptr used(new Lease6(Lease6::LEASE_IA_NA, IOAddress("2001:db8:1::1f"),
-                              duid2, 1, 2, 3, 4, 5, subnet_->getID()));
-    ASSERT_TRUE(LeaseMgrFactory::instance().addLease(used));
-
-    // another client comes in and request an address that is in pool, but
-    // unfortunately it is used already. The same address must not be allocated
-    // twice.
-    Lease6Ptr lease = engine->allocateAddress6(subnet_, duid_, iaid_,
-                                               IOAddress("2001:db8:1::1f"),
-                                               false);
-    // check that we got a lease
-    ASSERT_TRUE(lease);
-
-    // allocated address must be different
-    EXPECT_TRUE(used->addr_.toText() != lease->addr_.toText());
-
-    // we should NOT get what we asked for, because it is used already
-    EXPECT_TRUE(lease->addr_.toText() != "2001:db8:1::1f");
-
-    // do all checks on the lease
-    checkLease6(lease);
-
-    // Check that the lease is indeed in LeaseMgr
-    Lease6Ptr from_mgr = LeaseMgrFactory::instance().getLease6(lease->addr_);
-    ASSERT_TRUE(from_mgr);
-
-    // Now check that the lease in LeaseMgr has the same parameters
-    detailCompareLease6(lease, from_mgr);
-}
-
-// This test checks if the allocation with a hint that is out the blue
-// can succeed. The invalid hint should be ignored completely.
-TEST_F(AllocEngineTest, allocBogusHint) {
-    boost::scoped_ptr<AllocEngine> engine;
-    ASSERT_NO_THROW(engine.reset(new AllocEngine(AllocEngine::ALLOC_ITERATIVE, 100)));
-    ASSERT_TRUE(engine);
-
-    // Client would like to get a 3000::abc lease, which does not belong to any
-    // supported lease. Allocation engine should ignore it and carry on
-    // with the normal allocation
-    Lease6Ptr lease = engine->allocateAddress6(subnet_, duid_, iaid_,
-                                               IOAddress("3000::abc"),
-                                               false);
-    // check that we got a lease
-    ASSERT_TRUE(lease);
-
-    // we should NOT get what we asked for, because it is used already
-    EXPECT_TRUE(lease->addr_.toText() != "3000::abc");
-
-    // do all checks on the lease
-    checkLease6(lease);
-
-    // Check that the lease is indeed in LeaseMgr
-    Lease6Ptr from_mgr = LeaseMgrFactory::instance().getLease6(lease->addr_);
-    ASSERT_TRUE(from_mgr);
-
-    // Now check that the lease in LeaseMgr has the same parameters
-    detailCompareLease6(lease, from_mgr);
-}
-
-// This test verifies that the allocator picks addresses that belong to the
-// pool
-TEST_F(AllocEngineTest, IterativeAllocator) {
-    boost::scoped_ptr<NakedAllocEngine::Allocator>
-        alloc(new NakedAllocEngine::IterativeAllocator());
-
-    for (int i = 0; i < 1000; ++i) {
-        IOAddress candidate = alloc->pickAddress(subnet_, duid_, IOAddress("::"));
-        EXPECT_TRUE(subnet_->inPool(candidate));
-    }
-}
-
-
-// This test verifies that the iterative allocator really walks over all addresses
-// in all pools in specified subnet. It also must not pick the same address twice
-// unless it runs out of pool space and must start over.
-TEST_F(AllocEngineTest, IterativeAllocator_manyPools) {
-    NakedAllocEngine::IterativeAllocator* alloc = new NakedAllocEngine::IterativeAllocator();
-
-    // let's start from 2, as there is 2001:db8:1::10 - 2001:db8:1::20 pool already.
-    for (int i = 2; i < 10; ++i) {
-        stringstream min, max;
-
-        min << "2001:db8:1::" << hex << i*16 + 1;
-        max << "2001:db8:1::" << hex << i*16 + 9;
-
-        Pool6Ptr pool(new Pool6(Pool6::TYPE_IA, IOAddress(min.str()),
-                                IOAddress(max.str())));
-        // cout << "Adding pool: " << min.str() << "-" << max.str() << endl;
-        subnet_->addPool6(pool);
-    }
-
-    int total = 17 + 8*9; // first pool (::10 - ::20) has 17 addresses in it,
-                          // there are 8 extra pools with 9 addresses in each.
-
-    // Let's keep picked addresses here and check their uniqueness.
-    std::map<IOAddress, int> generated_addrs;
-    int cnt = 0;
-    while (++cnt) {
-        IOAddress candidate = alloc->pickAddress(subnet_, duid_, IOAddress("::"));
-        EXPECT_TRUE(subnet_->inPool(candidate));
-
-        // One way to easily verify that the iterative allocator really works is
-        // to uncomment the following line and observe its output that it
-        // covers all defined subnets.
-        // cout << candidate.toText() << endl;
-
-        if (generated_addrs.find(candidate) == generated_addrs.end()) {
-            // we haven't had this
-            generated_addrs[candidate] = 0;
-        } else {
-            // we have seen this address before. That should mean that we
-            // iterated over all addresses.
-            if (generated_addrs.size() == total) {
-                // we have exactly the number of address in all pools
-                break;
-            }
-            ADD_FAILURE() << "Too many or not enough unique addresses generated.";
-            break;
-        }
-
-        if ( cnt>total ) {
-            ADD_FAILURE() << "Too many unique addresses generated.";
-            break;
-        }
-    }
-
-    delete alloc;
-}
-
-}; // end of anonymous namespace
diff --git a/src/lib/dhcp/tests/cfgmgr_unittest.cc b/src/lib/dhcp/tests/cfgmgr_unittest.cc
deleted file mode 100644
index 5cc6345..0000000
--- a/src/lib/dhcp/tests/cfgmgr_unittest.cc
+++ /dev/null
@@ -1,111 +0,0 @@
-// 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 <config.h>
-#include <iostream>
-#include <sstream>
-#include <arpa/inet.h>
-#include <gtest/gtest.h>
-#include <dhcp/cfgmgr.h>
-#include <exceptions/exceptions.h>
-
-using namespace std;
-using namespace isc::asiolink;
-using namespace isc::dhcp;
-using namespace isc::util;
-using namespace isc;
-
-// don't import the entire boost namespace.  It will unexpectedly hide uint8_t
-// for some systems.
-using boost::scoped_ptr;
-
-namespace {
-
-class CfgMgrTest : public ::testing::Test {
-public:
-    CfgMgrTest() {
-    }
-
-    ~CfgMgrTest() {
-        CfgMgr::instance().deleteSubnets6();
-    }
-};
-
-
-// This test verifies if the configuration manager is able to hold and return
-// valid leases
-TEST_F(CfgMgrTest, subnet4) {
-    CfgMgr& cfg_mgr = CfgMgr::instance();
-
-    Subnet4Ptr subnet1(new Subnet4(IOAddress("192.0.2.0"), 26, 1, 2, 3));
-    Subnet4Ptr subnet2(new Subnet4(IOAddress("192.0.2.64"), 26, 1, 2, 3));
-    Subnet4Ptr subnet3(new Subnet4(IOAddress("192.0.2.128"), 26, 1, 2, 3));
-
-    // there shouldn't be any subnet configured at this stage
-    EXPECT_EQ( Subnet4Ptr(), cfg_mgr.getSubnet4(IOAddress("192.0.2.0")));
-
-    cfg_mgr.addSubnet4(subnet1);
-
-    // Now we have only one subnet, any request will be served from it
-    EXPECT_EQ(subnet1, cfg_mgr.getSubnet4(IOAddress("192.0.2.63")));
-
-    // Now we add more subnets and check that both old and new subnets
-    // are accessible.
-    cfg_mgr.addSubnet4(subnet2);
-    cfg_mgr.addSubnet4(subnet3);
-
-    EXPECT_EQ(subnet3, cfg_mgr.getSubnet4(IOAddress("192.0.2.191")));
-    EXPECT_EQ(subnet1, cfg_mgr.getSubnet4(IOAddress("192.0.2.15")));
-    EXPECT_EQ(subnet2, cfg_mgr.getSubnet4(IOAddress("192.0.2.85")));
-
-    // Try to find an address that does not belong to any subnet
-    EXPECT_EQ(Subnet4Ptr(), cfg_mgr.getSubnet4(IOAddress("192.0.2.192")));
-}
-
-// This test verifies if the configuration manager is able to hold and return
-// valid leases
-
-TEST_F(CfgMgrTest, subnet6) {
-    CfgMgr& cfg_mgr = CfgMgr::instance();
-
-    Subnet6Ptr subnet1(new Subnet6(IOAddress("2000::"), 48, 1, 2, 3, 4));
-    Subnet6Ptr subnet2(new Subnet6(IOAddress("3000::"), 48, 1, 2, 3, 4));
-    Subnet6Ptr subnet3(new Subnet6(IOAddress("4000::"), 48, 1, 2, 3, 4));
-
-    // there shouldn't be any subnet configured at this stage
-    EXPECT_EQ( Subnet6Ptr(), cfg_mgr.getSubnet6(IOAddress("2000::1")));
-
-    cfg_mgr.addSubnet6(subnet1);
-
-    // Now we have only one subnet, any request will be served from it
-    EXPECT_EQ(subnet1, cfg_mgr.getSubnet6(IOAddress("2000::1")));
-
-    // If we have only a single subnet and the request came from a local
-    // address, let's use that subnet
-    EXPECT_EQ(subnet1, cfg_mgr.getSubnet6(IOAddress("fe80::dead:beef")));
-
-    cfg_mgr.addSubnet6(subnet2);
-    cfg_mgr.addSubnet6(subnet3);
-
-    EXPECT_EQ(subnet3, cfg_mgr.getSubnet6(IOAddress("4000::123")));
-    EXPECT_EQ(subnet2, cfg_mgr.getSubnet6(IOAddress("3000::dead:beef")));
-    EXPECT_EQ(Subnet6Ptr(), cfg_mgr.getSubnet6(IOAddress("5000::1")));
-
-    cfg_mgr.deleteSubnets6();
-    EXPECT_EQ(Subnet6Ptr(), cfg_mgr.getSubnet6(IOAddress("200::123")));
-    EXPECT_EQ(Subnet6Ptr(), cfg_mgr.getSubnet6(IOAddress("3000::123")));
-    EXPECT_EQ(Subnet6Ptr(), cfg_mgr.getSubnet6(IOAddress("4000::123")));
-}
-
-} // end of anonymous namespace
diff --git a/src/lib/dhcp/tests/lease_mgr_factory_unittest.cc b/src/lib/dhcp/tests/lease_mgr_factory_unittest.cc
deleted file mode 100644
index 37063b2..0000000
--- a/src/lib/dhcp/tests/lease_mgr_factory_unittest.cc
+++ /dev/null
@@ -1,50 +0,0 @@
-// 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_factory.h>
-
-using namespace std;
-using namespace isc::dhcp;
-
-// This set of tests only check the parsing functions of LeaseMgrFactory.
-// Tests of the LeaseMgr create/instance/destroy are implicitly carried out
-// in the tests for the different concrete lease managers (e.g. MySqlLeaseMgr).
-
-namespace {
-// empty class for now, but may be extended once Addr6 becomes bigger
-class LeaseMgrFactoryTest : public ::testing::Test {
-public:
-    LeaseMgrFactoryTest() {
-    }
-};
-
-// This test checks if the LeaseMgr can be instantiated and that it
-// parses parameters string properly.
-TEST_F(LeaseMgrFactoryTest, parse) {
-
-    std::map<std::string, std::string> parameters = LeaseMgrFactory::parse(
-        "param1=value1 param2=value2 param3=value3");
-
-    EXPECT_EQ("value1", parameters["param1"]);
-    EXPECT_EQ("value2", parameters["param2"]);
-    EXPECT_TRUE(parameters.find("type") == parameters.end());
-}
-
-}; // end of anonymous namespace
diff --git a/src/lib/dhcp/tests/lease_mgr_unittest.cc b/src/lib/dhcp/tests/lease_mgr_unittest.cc
deleted file mode 100644
index 7ad2036..0000000
--- a/src/lib/dhcp/tests/lease_mgr_unittest.cc
+++ /dev/null
@@ -1,294 +0,0 @@
-// 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 and is used for abstract LeaseMgr class testing.
-class ConcreteLeaseMgr : 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 parameters A data structure relating keywords and values
-    ///        concerned with the database.
-    ConcreteLeaseMgr(const LeaseMgr::ParameterMap& parameters)
-        : LeaseMgr(parameters)
-    {}
-
-    /// @brief Destructor
-    virtual ~ConcreteLeaseMgr()
-    {}
-
-    /// @brief Adds an IPv4 lease.
-    ///
-    /// @param lease lease to be added
-    virtual bool addLease(const Lease4Ptr&) {
-        return (false);
-    }
-
-    /// @brief Adds an IPv6 lease.
-    ///
-    /// @param lease lease to be added
-    virtual bool addLease(const Lease6Ptr&) {
-        return (false);
-    }
-
-    /// @brief Returns existing IPv4 lease for specified IPv4 address.
-    ///
-    /// @param addr address of the searched lease
-    ///
-    /// @return smart pointer to the lease (or NULL if a lease is not found)
-    virtual Lease4Ptr getLease4(const isc::asiolink::IOAddress&) const {
-        return (Lease4Ptr());
-    }
-
-    /// @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(const isc::asiolink::IOAddress&,
-                                SubnetID) const {
-        return (Lease4Ptr());
-    }
-
-    /// @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&) const {
-        return (Lease4Collection());
-    }
-
-    /// @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&, SubnetID) const {
-        return (Lease4Ptr());
-    }
-
-    /// @brief Returns existing IPv4 lease for specified client-id
-    ///
-    /// @param clientid client identifier
-    ///
-    /// @return lease collection
-    virtual Lease4Collection getLease4(const ClientId&) const {
-        return (Lease4Collection());
-    }
-
-    /// @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&, SubnetID) const {
-        return (Lease4Ptr());
-    }
-
-    /// @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)
-    virtual Lease6Ptr getLease6(const isc::asiolink::IOAddress&) const {
-        return (Lease6Ptr());
-    }
-
-    /// @brief Returns existing IPv6 lease for a given DUID+IA combination
-    ///
-    /// @param duid client DUID
-    /// @param iaid IA identifier
-    ///
-    /// @return collection of IPv6 leases
-    virtual Lease6Collection getLease6(const DUID&, uint32_t) const {
-        return (Lease6Collection());
-    }
-
-    /// @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)
-    virtual Lease6Ptr getLease6(const DUID&, uint32_t, SubnetID) const {
-        return (Lease6Ptr());
-    }
-
-    /// @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(const Lease4Ptr&) {}
-
-    /// @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(const Lease6Ptr&) {}
-
-    /// @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(const isc::asiolink::IOAddress&) {
-        return (false);
-    }
-
-    /// @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(const isc::asiolink::IOAddress&) {
-        return (false);
-    }
-
-    /// @brief Returns backend type.
-    ///
-    /// Returns the type of the backend (e.g. "mysql", "memfile" etc.)
-    ///
-    /// @return Type of the backend.
-    virtual std::string getType() const {
-        return (std::string("concrete"));
-    }
-
-    /// @brief Returns backend name.
-    ///
-    /// If the backend is a database, this is the name of the database or the
-    /// file.  Otherwise it is just the same as the type.
-    ///
-    /// @return Name of the backend.
-    virtual std::string getName() const {
-        return (std::string("concrete"));
-    }
-
-    /// @brief Returns description of the backend.
-    ///
-    /// This description may be multiline text that describes the backend.
-    ///
-    /// @return Description of the backend.
-    virtual std::string getDescription() const {
-        return (std::string("This is a dummy concrete backend implementation."));
-    }
-
-    /// @brief Returns backend version.
-    virtual std::pair<uint32_t, uint32_t> getVersion() const {
-        return (make_pair(uint32_t(0), uint32_t(0)));
-    }
-
-    /// @brief Commit transactions
-    virtual void commit() {
-    }
-
-    /// @brief Rollback transactions
-    virtual void rollback() {
-    }
-};
-
-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, getParameter) {
-
-    LeaseMgr::ParameterMap pmap;
-    pmap[std::string("param1")] = std::string("value1");
-    pmap[std::string("param2")] = std::string("value2");
-    ConcreteLeaseMgr leasemgr(pmap);
-
-    EXPECT_EQ("value1", leasemgr.getParameter("param1"));
-    EXPECT_EQ("value2", leasemgr.getParameter("param2"));
-    EXPECT_THROW(leasemgr.getParameter("param3"), BadValue);
-}
-
-// There's no point in calling any other methods in LeaseMgr, as they
-// are purely virtual, so we would only call ConcreteLeaseMgr methods.
-// Those methods are just stubs that do not return anything.
-
-// Lease6 is also defined in lease_mgr.h, so is tested in this file as well.
-// This test checks if the Lease6 structure can be instantiated correctly
-TEST(Lease6, Lease6Constructor) {
-
-    IOAddress addr("2001:db8:1::456");
-
-    uint8_t llt[] = {0, 1, 2, 3, 4, 5, 6, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf};
-    DuidPtr duid(new DUID(llt, sizeof(llt)));
-
-    uint32_t iaid = 7; // just a number
-
-    SubnetID subnet_id = 8; // just another number
-
-    Lease6Ptr x(new Lease6(Lease6::LEASE_IA_NA, addr,
-                           duid, iaid, 100, 200, 50, 80,
-                           subnet_id));
-
-    EXPECT_TRUE(x->addr_ == addr);
-    EXPECT_TRUE(*x->duid_ == *duid);
-    EXPECT_TRUE(x->iaid_ == iaid);
-    EXPECT_TRUE(x->subnet_id_ == subnet_id);
-    EXPECT_TRUE(x->type_ == Lease6::LEASE_IA_NA);
-    EXPECT_TRUE(x->preferred_lft_ == 100);
-    EXPECT_TRUE(x->valid_lft_ == 200);
-    EXPECT_TRUE(x->t1_ == 50);
-    EXPECT_TRUE(x->t2_ == 80);
-
-    // Lease6 must be instantiated with a DUID, not with NULL pointer
-    EXPECT_THROW(new Lease6(Lease6::LEASE_IA_NA, addr,
-                            DuidPtr(), iaid, 100, 200, 50, 80,
-                            subnet_id), InvalidOperation);
-}
-}; // end of anonymous namespace
diff --git a/src/lib/dhcp/tests/memfile_lease_mgr_unittest.cc b/src/lib/dhcp/tests/memfile_lease_mgr_unittest.cc
deleted file mode 100644
index 79706e1..0000000
--- a/src/lib/dhcp/tests/memfile_lease_mgr_unittest.cc
+++ /dev/null
@@ -1,133 +0,0 @@
-// 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 <config.h>
-#include <iostream>
-#include <sstream>
-#include <gtest/gtest.h>
-#include <asiolink/io_address.h>
-
-#include <dhcp/lease_mgr.h>
-#include <dhcp/duid.h>
-#include <dhcp/memfile_lease_mgr.h>
-
-using namespace std;
-using namespace isc;
-using namespace isc::asiolink;
-using namespace isc::dhcp;
-
-namespace {
-// empty class for now, but may be extended once Addr6 becomes bigger
-class MemfileLeaseMgrTest : public ::testing::Test {
-public:
-    MemfileLeaseMgrTest() {
-    }
-};
-
-// This test checks if the LeaseMgr can be instantiated and that it
-// parses parameters string properly.
-TEST_F(MemfileLeaseMgrTest, constructor) {
-
-    const LeaseMgr::ParameterMap pmap;  // Empty parameter map
-    boost::scoped_ptr<Memfile_LeaseMgr> lease_mgr;
-
-    ASSERT_NO_THROW(lease_mgr.reset(new Memfile_LeaseMgr(pmap)));
-}
-
-// Checks if the getType() and getName() methods both return "memfile".
-TEST_F(MemfileLeaseMgrTest, getTypeAndName) {
-    const LeaseMgr::ParameterMap pmap;  // Empty parameter map
-    boost::scoped_ptr<Memfile_LeaseMgr> lease_mgr(new Memfile_LeaseMgr(pmap));
-
-    EXPECT_EQ(std::string("memfile"), lease_mgr->getType());
-    EXPECT_EQ(std::string("memfile"), lease_mgr->getName());
-}
-
-// Checks that adding/getting/deleting a Lease6 object works.
-TEST_F(MemfileLeaseMgrTest, addGetDelete6) {
-    const LeaseMgr::ParameterMap pmap;  // Empty parameter map
-    boost::scoped_ptr<Memfile_LeaseMgr> lease_mgr(new Memfile_LeaseMgr(pmap));
-
-    IOAddress addr("2001:db8:1::456");
-
-    uint8_t llt[] = {0, 1, 2, 3, 4, 5, 6, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf};
-    DuidPtr duid(new DUID(llt, sizeof(llt)));
-
-    uint32_t iaid = 7; // just a number
-
-    SubnetID subnet_id = 8; // just another number
-
-    Lease6Ptr lease(new Lease6(Lease6::LEASE_IA_NA, addr,
-                               duid, iaid, 100, 200, 50, 80,
-                               subnet_id));
-
-    EXPECT_TRUE(lease_mgr->addLease(lease));
-
-    // should not be allowed to add a second lease with the same address
-    EXPECT_FALSE(lease_mgr->addLease(lease));
-
-    Lease6Ptr x = lease_mgr->getLease6(IOAddress("2001:db8:1::234"));
-    EXPECT_EQ(Lease6Ptr(), x);
-
-    x = lease_mgr->getLease6(IOAddress("2001:db8:1::456"));
-    ASSERT_TRUE(x);
-
-    EXPECT_EQ(x->addr_.toText(), addr.toText());
-    EXPECT_TRUE(*x->duid_ == *duid);
-    EXPECT_EQ(x->iaid_, iaid);
-    EXPECT_EQ(x->subnet_id_, subnet_id);
-
-    // These are not important from lease management perspective, but
-    // let's check them anyway.
-    EXPECT_EQ(x->type_, Lease6::LEASE_IA_NA);
-    EXPECT_EQ(x->preferred_lft_, 100);
-    EXPECT_EQ(x->valid_lft_, 200);
-    EXPECT_EQ(x->t1_, 50);
-    EXPECT_EQ(x->t2_, 80);
-
-    // Test getLease6(duid, iaid, subnet_id) - positive case
-    Lease6Ptr y = lease_mgr->getLease6(*duid, iaid, subnet_id);
-    ASSERT_TRUE(y);
-    EXPECT_TRUE(*y->duid_ == *duid);
-    EXPECT_EQ(y->iaid_, iaid);
-    EXPECT_EQ(y->addr_.toText(), addr.toText());
-
-    // Test getLease6(duid, iaid, subnet_id) - wrong iaid
-    uint32_t invalid_iaid = 9; // no such iaid
-    y = lease_mgr->getLease6(*duid, invalid_iaid, subnet_id);
-    EXPECT_FALSE(y);
-
-    uint32_t invalid_subnet_id = 999;
-    y = lease_mgr->getLease6(*duid, iaid, invalid_subnet_id);
-    EXPECT_FALSE(y);
-
-    // truncated duid
-    DuidPtr invalid_duid(new DUID(llt, sizeof(llt) - 1));
-    y = lease_mgr->getLease6(*invalid_duid, iaid, subnet_id);
-    EXPECT_FALSE(y);
-
-    // should return false - there's no such address
-    EXPECT_FALSE(lease_mgr->deleteLease6(IOAddress("2001:db8:1::789")));
-
-    // this one should succeed
-    EXPECT_TRUE(lease_mgr->deleteLease6(IOAddress("2001:db8:1::456")));
-
-    // after the lease is deleted, it should really be gone
-    x = lease_mgr->getLease6(IOAddress("2001:db8:1::456"));
-    EXPECT_EQ(Lease6Ptr(), x);
-}
-
-// TODO: Write more memfile tests
-
-}; // end of anonymous namespace
diff --git a/src/lib/dhcp/tests/mysql_lease_mgr_unittest.cc b/src/lib/dhcp/tests/mysql_lease_mgr_unittest.cc
deleted file mode 100644
index d99ae23..0000000
--- a/src/lib/dhcp/tests/mysql_lease_mgr_unittest.cc
+++ /dev/null
@@ -1,752 +0,0 @@
-// 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 <utility>
-#include <string>
-#include <gtest/gtest.h>
-
-#include <asiolink/io_address.h>
-#include <dhcp/lease_mgr_factory.h>
-#include <dhcp/mysql_lease_mgr.h>
-
-using namespace isc;
-using namespace isc::asiolink;
-using namespace isc::dhcp;
-using namespace std;
-
-namespace {
-
-// Creation of the schema
-#include "schema_copy.h"
-
-// IPv6 addresseses
-const char* ADDRESS_0 = "2001:db8::0";
-const char* ADDRESS_1 = "2001:db8::1";
-const char* ADDRESS_2 = "2001:db8::2";
-const char* ADDRESS_3 = "2001:db8::3";
-const char* ADDRESS_4 = "2001:db8::4";
-const char* ADDRESS_5 = "2001:db8::5";
-const char* ADDRESS_6 = "2001:db8::6";
-const char* ADDRESS_7 = "2001:db8::7";
-
-// Connection strings.  Assume:
-// Database: keatest
-// Username: keatest
-// Password: keatest
-const char* VALID_TYPE = "type=mysql";
-const char* INVALID_TYPE = "type=unknown";
-const char* VALID_NAME = "name=keatest";
-const char* INVALID_NAME = "name=invalidname";
-const char* VALID_HOST = "host=localhost";
-const char* INVALID_HOST = "host=invalidhost";
-const char* VALID_USER = "user=keatest";
-const char* INVALID_USER = "user=invaliduser";
-const char* VALID_PASSWORD = "password=keatest";
-const char* INVALID_PASSWORD = "password=invalid";
-
-// Given a combination of strings above, produce a connection string.
-string connectionString(const char* type, const char* name, const char* host,
-                        const char* user, const char* password) {
-    const string space = " ";
-    string result = "";
-
-    if (type != NULL) {
-        result += string(type);
-    }
-
-    if (name != NULL) {
-        if (! result.empty()) {
-            result += space;
-        }
-        result += string(name);
-    }
-
-    if (host != NULL) {
-        if (! result.empty()) {
-            result += space;
-        }
-        result += string(host);
-    }
-
-    if (user != NULL) {
-        if (! result.empty()) {
-            result += space;
-        }
-        result += string(user);
-    }
-
-    if (password != NULL) {
-        if (! result.empty()) {
-            result += space;
-        }
-        result += string(password);
-    }
-
-    return (result);
-}
-
-// Return valid connection string
-string
-validConnectionString() {
-    return (connectionString(VALID_TYPE, VALID_NAME, VALID_HOST,
-                             VALID_USER, VALID_PASSWORD));
-}
-
-// @brief Clear everything from the database
-//
-// There is no error checking in this code: if something fails, one of the
-// tests will fall over.
-void destroySchema() {
-    // Initialise
-    MYSQL handle;
-    (void) mysql_init(&handle);
-
-    // Open database
-    (void) mysql_real_connect(&handle, "localhost", "keatest",
-                              "keatest", "keatest", 0, NULL, 0);
-
-    // Get rid of everything in it.
-    for (int i = 0; destroy_statement[i] != NULL; ++i) {
-        (void) mysql_query(&handle, destroy_statement[i]);
-    }
-
-    // ... and close
-    (void) mysql_close(&handle);
-}
-
-// @brief Create the Schema
-//
-// Creates all the tables in what is assumed to be an empty database.
-//
-// There is no error checking in this code: if it fails, one of the tests
-// will fall over.
-void createSchema() {
-    // Initialise
-    MYSQL handle;
-    (void) mysql_init(&handle);
-
-    // Open database
-    (void) mysql_real_connect(&handle, "localhost", "keatest",
-                              "keatest", "keatest", 0, NULL, 0);
-
-    // Get rid of everything in it.
-    for (int i = 0; create_statement[i] != NULL; ++i) {
-        (void) mysql_query(&handle, create_statement[i]);
-    }
-
-    // ... and close
-    (void) mysql_close(&handle);
-}
-
-// Note: Doxygen "///" not used - even though Doxygen is used to
-// document class and methods - to avoid the comments appearing
-// in the programming manual.
-
-// @brief Test Fixture Class
-//
-// Opens the database prior to each test and closes it afterwards.
-// All pending transactions are deleted prior to closure.
-
-class MySqlLeaseMgrTest : public ::testing::Test {
-public:
-    // @brief Constructor
-    //
-    // Deletes everything from the database and opens it.
-    MySqlLeaseMgrTest() :
-        L0_ADDRESS(ADDRESS_0), L0_IOADDRESS(L0_ADDRESS), 
-        L1_ADDRESS(ADDRESS_1), L1_IOADDRESS(L1_ADDRESS), 
-        L2_ADDRESS(ADDRESS_2), L2_IOADDRESS(L2_ADDRESS), 
-        L3_ADDRESS(ADDRESS_3), L3_IOADDRESS(L3_ADDRESS), 
-        L4_ADDRESS(ADDRESS_4), L4_IOADDRESS(L4_ADDRESS), 
-        L5_ADDRESS(ADDRESS_5), L5_IOADDRESS(L5_ADDRESS), 
-        L6_ADDRESS(ADDRESS_6), L6_IOADDRESS(L6_ADDRESS), 
-        L7_ADDRESS(ADDRESS_7), L7_IOADDRESS(L7_ADDRESS) {
-
-        destroySchema();
-        createSchema();
-        try {
-            LeaseMgrFactory::create(validConnectionString());
-        } catch (...) {
-            std::cerr << "*** ERROR: unable to open database. The test\n"
-                         "*** environment is broken and must be fixed before\n"
-                         "*** the MySQL tests will run correctly.\n"
-                         "*** The reason for the problem is described in the\n"
-                         "*** accompanying exception output.\n";
-            throw;
-        }
-        lmptr_ = &(LeaseMgrFactory::instance());
-    }
-
-    // @brief Destructor
-    //
-    // Rolls back all pending transactions.  The deletion of the
-    // lmptr_ member variable will close the database.  Then
-    // reopen it and delete everything created by the test.
-    virtual ~MySqlLeaseMgrTest() {
-        lmptr_->rollback();
-        LeaseMgrFactory::destroy();
-        destroySchema();
-    }
-
-    // @brief Reopen the database
-    //
-    // Closes the database and re-open it.  Anything committed should be
-    // visible.
-    void reopen() {
-        LeaseMgrFactory::destroy();
-        LeaseMgrFactory::create(validConnectionString());
-        lmptr_ = &(LeaseMgrFactory::instance());
-    }
-
-    // @brief Initialize Lease6 Fields
-    //
-    // Returns a pointer to a Lease6 structure.  Different values are put
-    // in the lease according to the address passed.
-    //
-    // This is just a convenience function for the test methods.
-    //
-    // @param address Address to use for the initialization
-    //
-    // @return Lease6Ptr.  This will not point to anything if the initialization
-    //         failed (e.g. unknown address).
-    Lease6Ptr initializeLease6(std::string address) {
-        Lease6Ptr lease(new Lease6());
-
-        // Set the address of the lease
-        lease->addr_ = IOAddress(address);
-
-        // Initialize unused fields.
-        lease->t1_ = 0;                             // Not saved
-        lease->t2_ = 0;                             // Not saved
-        lease->fixed_ = false;                      // Unused
-        lease->hostname_ = std::string("");         // Unused
-        lease->fqdn_fwd_ = false;                   // Unused
-        lease->fqdn_rev_ = false;                   // Unused
-        lease->comments_ = std::string("");         // Unused
-
-        // Set the other parameters.  For historical reasons, L0_ADDRESS is not used.
-        if (address == L0_ADDRESS) {
-            lease->type_ = Lease6::LEASE_IA_TA;
-            lease->prefixlen_ = 4;
-            lease->iaid_ = 142;
-            lease->duid_ = boost::shared_ptr<DUID>(new DUID(vector<uint8_t>(8, 0x77)));
-            lease->preferred_lft_ = 900;   // Preferred lifetime
-            lease->valid_lft_ = 8677;      // Actual lifetime
-            lease->cltt_ = 168256;         // Current time of day
-            lease->subnet_id_ = 23;        // Arbitrary number
-
-        } else if (address == L1_ADDRESS) {
-            lease->type_ = Lease6::LEASE_IA_TA;
-            lease->prefixlen_ = 0;
-            lease->iaid_ = 42;
-            lease->duid_ = boost::shared_ptr<DUID>(new DUID(vector<uint8_t>(8, 0x42)));
-            lease->preferred_lft_ = 3600;  // Preferred lifetime
-            lease->valid_lft_ = 3677;      // Actual lifetime
-            lease->cltt_ = 123456;         // Current time of day
-            lease->subnet_id_ = 73;        // Arbitrary number
-
-        } else if (address == L2_ADDRESS) {
-            lease->type_ = Lease6::LEASE_IA_PD;
-            lease->prefixlen_ = 7;
-            lease->iaid_ = 89;
-            lease->duid_ = boost::shared_ptr<DUID>(new DUID(vector<uint8_t>(8, 0x3a)));
-            lease->preferred_lft_ = 1800;  // Preferred lifetime
-            lease->valid_lft_ = 5412;      // Actual lifetime
-            lease->cltt_ = 234567;         // Current time of day
-            lease->subnet_id_ = 73;        // Same as for L1_ADDRESS
-
-        } else if (address == L3_ADDRESS) {
-            lease->type_ = Lease6::LEASE_IA_NA;
-            lease->prefixlen_ = 28;
-            lease->iaid_ = 0xfffffffe;
-            vector<uint8_t> duid;
-            for (uint8_t i = 31; i < 126; ++i) {
-                duid.push_back(i);
-            }
-            lease->duid_ = boost::shared_ptr<DUID>(new DUID(duid));
-
-            // The times used in the next tests are deliberately restricted - we
-            // should be able to cope with valid lifetimes up to 0xffffffff.
-            //  However, this will lead to overflows.
-            // @TODO: test overflow conditions when code has been fixed
-            lease->preferred_lft_ = 7200;  // Preferred lifetime
-            lease->valid_lft_ = 7000;      // Actual lifetime
-            lease->cltt_ = 234567;         // Current time of day
-            lease->subnet_id_ = 37;        // Different from L1 and L2
-
-        } else if (address == L4_ADDRESS) {
-            // Same DUID and IAID as L1_ADDRESS
-            lease->type_ = Lease6::LEASE_IA_PD;
-            lease->prefixlen_ = 15;
-            lease->iaid_ = 42;
-            lease->duid_ = boost::shared_ptr<DUID>(new DUID(vector<uint8_t>(8, 0x42)));
-            lease->preferred_lft_ = 4800;  // Preferred lifetime
-            lease->valid_lft_ = 7736;      // Actual lifetime
-            lease->cltt_ = 222456;         // Current time of day
-            lease->subnet_id_ = 75;        // Arbitrary number
-
-        } else if (address == L5_ADDRESS) {
-            // Same DUID and IAID as L1_ADDRESS
-            lease->type_ = Lease6::LEASE_IA_PD;
-            lease->prefixlen_ = 24;
-            lease->iaid_ = 42;
-            lease->duid_ = boost::shared_ptr<DUID>(new DUID(vector<uint8_t>(8, 0x42)));
-            lease->preferred_lft_ = 5400;  // Preferred lifetime
-            lease->valid_lft_ = 7832;      // Actual lifetime
-            lease->cltt_ = 227476;         // Current time of day
-            lease->subnet_id_ = 175;       // Arbitrary number
-
-        } else if (address == L6_ADDRESS) {
-            // Same DUID as L1_ADDRESS
-            lease->type_ = Lease6::LEASE_IA_PD;
-            lease->prefixlen_ = 24;
-            lease->iaid_ = 93;
-            lease->duid_ = boost::shared_ptr<DUID>(new DUID(vector<uint8_t>(8, 0x42)));
-            lease->preferred_lft_ = 5400;  // Preferred lifetime
-            lease->valid_lft_ = 1832;      // Actual lifetime
-            lease->cltt_ = 627476;         // Current time of day
-            lease->subnet_id_ = 112;       // Arbitrary number
-
-        } else if (address == L7_ADDRESS) {
-            // Same IAID as L1_ADDRESS
-            lease->type_ = Lease6::LEASE_IA_PD;
-            lease->prefixlen_ = 24;
-            lease->iaid_ = 42;
-            lease->duid_ = boost::shared_ptr<DUID>(new DUID(vector<uint8_t>(8, 0xe5)));
-            lease->preferred_lft_ = 5600;  // Preferred lifetime
-            lease->valid_lft_ = 7975;      // Actual lifetime
-            lease->cltt_ = 213876;         // Current time of day
-            lease->subnet_id_ = 19;        // Arbitrary number
-
-        } else {
-            // Unknown address, return an empty pointer.
-            lease.reset();
-
-        }
-
-        return (lease);
-    }
-
-    // @brief Creates Leases for the test
-    //
-    // Creates all leases for the test and checks that they are different.
-    //
-    // @return vector<Lease6Ptr> Vector of pointers to leases
-    vector<Lease6Ptr> createLeases6() {
-
-        // Create leases
-        vector<Lease6Ptr> leases;
-        leases.push_back(initializeLease6(L0_ADDRESS));
-        leases.push_back(initializeLease6(L1_ADDRESS));
-        leases.push_back(initializeLease6(L2_ADDRESS));
-        leases.push_back(initializeLease6(L3_ADDRESS));
-        leases.push_back(initializeLease6(L4_ADDRESS));
-        leases.push_back(initializeLease6(L5_ADDRESS));
-        leases.push_back(initializeLease6(L6_ADDRESS));
-        leases.push_back(initializeLease6(L7_ADDRESS));
-
-        EXPECT_EQ(8, leases.size());
-
-        // Check they were created
-        for (int i = 0; i < leases.size(); ++i) {
-            EXPECT_TRUE(leases[i]);
-        }
-
-        // Check they are different
-        for (int i = 0; i < (leases.size() - 1); ++i) {
-            for (int j = (i + 1); j < leases.size(); ++j) {
-                EXPECT_TRUE(leases[i] != leases[j]);
-            }
-        }
-
-        return (leases);
-    }
-
-
-    // Member variables
-
-    LeaseMgr*   lmptr_;         // Pointer to the lease manager
-
-    string L0_ADDRESS;          // String form of address 1
-    IOAddress L0_IOADDRESS;     // IOAddress form of L1_ADDRESS
-
-    string L1_ADDRESS;          // String form of address 1
-    IOAddress L1_IOADDRESS;     // IOAddress form of L1_ADDRESS
-
-    string L2_ADDRESS;          // String form of address 2
-    IOAddress L2_IOADDRESS;     // IOAddress form of L2_ADDRESS
-
-    string L3_ADDRESS;          // String form of address 3
-    IOAddress L3_IOADDRESS;     // IOAddress form of L3_ADDRESS
-
-    string L4_ADDRESS;          // String form of address 4
-    IOAddress L4_IOADDRESS;     // IOAddress form of L4_ADDRESS
-
-    string L5_ADDRESS;          // String form of address 5
-    IOAddress L5_IOADDRESS;     // IOAddress form of L5_ADDRESS
-
-    string L6_ADDRESS;          // String form of address 6
-    IOAddress L6_IOADDRESS;     // IOAddress form of L6_ADDRESS
-
-    string L7_ADDRESS;          // String form of address 7
-    IOAddress L7_IOADDRESS;     // IOAddress form of L7_ADDRESS
-};
-
-
-// @brief Check that Database Can Be Opened
-//
-// This test checks if the MySqlLeaseMgr can be instantiated.  This happens
-// only if the database can be opened.  Note that this is not part of the
-// MySqlLeaseMgr test fixure set.  This test checks that the database can be
-// opened: the fixtures assume that and check basic operations.
-
-TEST(MySqlOpenTest, OpenDatabase) {
-
-    // Schema needs to be created for the test to work.
-    destroySchema();
-    createSchema();
-
-    // Check that lease manager open the database opens correctly and tidy up.
-    //  If it fails, print the error message.
-    try {
-        LeaseMgrFactory::create(validConnectionString());
-        EXPECT_NO_THROW((void) LeaseMgrFactory::instance());
-        LeaseMgrFactory::destroy();
-    } catch (const isc::Exception& ex) {
-        FAIL() << "*** ERROR: unable to open database, reason:\n"
-               << "    " << ex.what() << "\n"
-               << "*** The test environment is broken and must be fixed\n"
-               << "*** before the MySQL tests will run correctly.\n";
-    }
-
-    // Check that attempting to get an instance of the lease manager when
-    // none is set throws an exception.
-    EXPECT_THROW(LeaseMgrFactory::instance(), NoLeaseManager);
-
-    // Check that wrong specification of backend throws an exception.
-    // (This is really a check on LeaseMgrFactory, but is convenient to
-    // perform here.)
-    EXPECT_THROW(LeaseMgrFactory::create(connectionString(
-        NULL, VALID_NAME, VALID_HOST, INVALID_USER, VALID_PASSWORD)),
-        InvalidParameter);
-    EXPECT_THROW(LeaseMgrFactory::create(connectionString(
-        INVALID_TYPE, VALID_NAME, VALID_HOST, VALID_USER, VALID_PASSWORD)),
-        InvalidType);
-
-    // Check that invalid login data causes an exception.
-    EXPECT_THROW(LeaseMgrFactory::create(connectionString(
-        VALID_TYPE, INVALID_NAME, VALID_HOST, VALID_USER, VALID_PASSWORD)),
-        DbOpenError);
-    EXPECT_THROW(LeaseMgrFactory::create(connectionString(
-        VALID_TYPE, VALID_NAME, INVALID_HOST, VALID_USER, VALID_PASSWORD)),
-        DbOpenError);
-    EXPECT_THROW(LeaseMgrFactory::create(connectionString(
-        VALID_TYPE, VALID_NAME, VALID_HOST, INVALID_USER, VALID_PASSWORD)),
-        DbOpenError);
-    EXPECT_THROW(LeaseMgrFactory::create(connectionString(
-        VALID_TYPE, VALID_NAME, VALID_HOST, VALID_USER, INVALID_PASSWORD)),
-        DbOpenError);
-
-    // Check for missing parameters
-    EXPECT_THROW(LeaseMgrFactory::create(connectionString(
-        VALID_TYPE, NULL, VALID_HOST, INVALID_USER, VALID_PASSWORD)),
-        NoDatabaseName);
-
-    // Tidy up after the test
-    destroySchema();
-}
-
-// @brief Check the getType() method
-//
-// getType() returns a string giving the type of the backend, which should
-// always be "mysql".
-TEST_F(MySqlLeaseMgrTest, getType) {
-    EXPECT_EQ(std::string("mysql"), lmptr_->getType());
-}
-
-// @brief Check conversion functions
-//
-// The server works using cltt and valid_filetime.  In the database, the
-// information is stored as expire_time and valid-lifetime, which are
-// related by
-//
-// expire_time = cltt + valid_lifetime
-//
-// This test checks that the conversion is correct.  It does not check that the
-// data is entered into the database correctly, only that the MYSQL_TIME
-// structure used for the entry is correctly set up.
-TEST_F(MySqlLeaseMgrTest, checkTimeConversion) {
-    const time_t cltt = time(NULL);
-    const uint32_t valid_lft = 86400;       // 1 day
-    struct tm tm_expire;
-    MYSQL_TIME mysql_expire;
-
-    // Work out what the broken-down time will be for one day
-    // after the current time.
-    time_t expire_time = cltt + valid_lft;
-    (void) localtime_r(&expire_time, &tm_expire);
-
-    // Convert to the database time
-    MySqlLeaseMgr::convertToDatabaseTime(cltt, valid_lft, mysql_expire);
-
-    // Are the times the same?
-    EXPECT_EQ(tm_expire.tm_year + 1900, mysql_expire.year);
-    EXPECT_EQ(tm_expire.tm_mon + 1,  mysql_expire.month);
-    EXPECT_EQ(tm_expire.tm_mday, mysql_expire.day);
-    EXPECT_EQ(tm_expire.tm_hour, mysql_expire.hour);
-    EXPECT_EQ(tm_expire.tm_min, mysql_expire.minute);
-    EXPECT_EQ(tm_expire.tm_sec, mysql_expire.second);
-    EXPECT_EQ(0, mysql_expire.second_part);
-    EXPECT_EQ(0, mysql_expire.neg);
-
-    // Convert back
-    time_t converted_cltt = 0;
-    MySqlLeaseMgr::convertFromDatabaseTime(mysql_expire, valid_lft, converted_cltt);
-    EXPECT_EQ(cltt, converted_cltt);
-}
-
-
-// @brief Check getName() returns correct database name
-TEST_F(MySqlLeaseMgrTest, getName) {
-    EXPECT_EQ(std::string("keatest"), lmptr_->getName());
-
-    // @TODO: check for the negative
-}
-
-// @brief Check that getVersion() returns the expected version
-TEST_F(MySqlLeaseMgrTest, checkVersion) {
-    // Check version
-    pair<uint32_t, uint32_t> version;
-    ASSERT_NO_THROW(version = lmptr_->getVersion());
-    EXPECT_EQ(CURRENT_VERSION_VERSION, version.first);
-    EXPECT_EQ(CURRENT_VERSION_MINOR, version.second);
-}
-
-// @brief Compare two Lease6 structures for equality
-void
-detailCompareLease6(const Lease6Ptr& first, const Lease6Ptr& second) {
-    EXPECT_EQ(first->type_, second->type_);
-
-    // Compare address strings.  Comparison of address objects is not used, as
-    // odd things happen when they are different: the EXPECT_EQ macro appears to
-    // call the operator uint32_t() function, which causes an exception to be
-    // thrown for IPv6 addresses.
-    EXPECT_EQ(first->addr_.toText(), second->addr_.toText());
-    EXPECT_EQ(first->prefixlen_, second->prefixlen_);
-    EXPECT_EQ(first->iaid_, second->iaid_);
-    EXPECT_TRUE(*first->duid_ == *second->duid_);
-    EXPECT_EQ(first->preferred_lft_, second->preferred_lft_);
-    EXPECT_EQ(first->valid_lft_, second->valid_lft_);
-    EXPECT_EQ(first->cltt_, second->cltt_);
-    EXPECT_EQ(first->subnet_id_, second->subnet_id_);
-}
-
-
-// @brief Check individual Lease6 methods
-//
-// Checks that the add/update/delete works.  All are done within one
-// test so that "rollback" can be used to remove trace of the tests
-// from the database.
-//
-// Tests where a collection of leases can be returned are in the test
-// Lease6Collection.
-TEST_F(MySqlLeaseMgrTest, basicLease6) {
-    // Get the leases to be used for the test.
-    vector<Lease6Ptr> leases = createLeases6();
-
-    // Start the tests.  Add three leases to the database, read them back and
-    // check they are what we think they are.
-    EXPECT_TRUE(lmptr_->addLease(leases[1]));
-    EXPECT_TRUE(lmptr_->addLease(leases[2]));
-    EXPECT_TRUE(lmptr_->addLease(leases[3]));
-    lmptr_->commit();
-
-    // Reopen the database to ensure that they actually got stored.
-    reopen();
-
-    Lease6Ptr l_returned = lmptr_->getLease6(L1_IOADDRESS);
-    EXPECT_TRUE(l_returned);
-    detailCompareLease6(leases[1], l_returned);
-
-    l_returned = lmptr_->getLease6(L2_IOADDRESS);
-    EXPECT_TRUE(l_returned);
-    detailCompareLease6(leases[2], l_returned);
-
-    l_returned = lmptr_->getLease6(L3_IOADDRESS);
-    EXPECT_TRUE(l_returned);
-    detailCompareLease6(leases[3], l_returned);
-
-    // Check that we can't add a second lease with the same address
-    EXPECT_FALSE(lmptr_->addLease(leases[1]));
-
-    // Delete a lease, check that it's gone, and that we can't delete it
-    // a second time.
-    EXPECT_TRUE(lmptr_->deleteLease6(L1_IOADDRESS));
-    l_returned = lmptr_->getLease6(L1_IOADDRESS);
-    EXPECT_FALSE(l_returned);
-    EXPECT_FALSE(lmptr_->deleteLease6(L1_IOADDRESS));
-
-    // Check that the second address is still there.
-    l_returned = lmptr_->getLease6(L2_IOADDRESS);
-    EXPECT_TRUE(l_returned);
-    detailCompareLease6(leases[2], l_returned);
-}
-
-// @brief Check GetLease6 methods - Access by DUID/IAID
-//
-// Adds leases to the database and checks that they can be accessed via
-// a combination of DIUID and IAID.
-TEST_F(MySqlLeaseMgrTest, getLease6Extended1) {
-    // Get the leases to be used for the test.
-    vector<Lease6Ptr> leases = createLeases6();
-    EXPECT_LE(6, leases.size());    // Expect to access leases 0 through 5
-
-    // Add them to the database
-    for (int i = 0; i < leases.size(); ++i) {
-        EXPECT_TRUE(lmptr_->addLease(leases[i]));
-    }
-
-    // Get the leases matching the DUID and IAID of lease[1].
-    Lease6Collection returned = lmptr_->getLease6(*leases[1]->duid_,
-                                                  leases[1]->iaid_);
-
-    // Should be three leases, matching leases[1], [4] and [5].
-    ASSERT_EQ(3, returned.size());
-
-    // Easiest way to check is to look at the addresses.
-    vector<string> addresses;
-    for (Lease6Collection::const_iterator i = returned.begin();
-         i != returned.end(); ++i) {
-        addresses.push_back((*i)->addr_.toText());
-    }
-    sort(addresses.begin(), addresses.end());
-    EXPECT_EQ(L1_ADDRESS, addresses[0]);
-    EXPECT_EQ(L4_ADDRESS, addresses[1]);
-    EXPECT_EQ(L5_ADDRESS, addresses[2]);
-
-    // Check that nothing is returned when either the IAID or DUID match
-    // nothing.
-    returned = lmptr_->getLease6(*leases[1]->duid_, leases[1]->iaid_ + 1);
-    EXPECT_EQ(0, returned.size());
-
-    // Alter the leases[1] DUID to match nothing in the database.
-    vector<uint8_t> duid_vector = leases[1]->duid_->getDuid();
-    ++duid_vector[0];
-    DUID new_duid(duid_vector);
-    returned = lmptr_->getLease6(new_duid, leases[1]->iaid_);
-    EXPECT_EQ(0, returned.size());
-}
-
-
-
-// @brief Check GetLease6 methods - Access by DUID/IAID/SubnetID
-//
-// Adds leases to the database and checks that they can be accessed via
-// a combination of DIUID and IAID.
-TEST_F(MySqlLeaseMgrTest, getLease6Extended2) {
-    // Get the leases to be used for the test.
-    vector<Lease6Ptr> leases = createLeases6();
-    EXPECT_LE(6, leases.size());    // Expect to access leases 0 through 5
-
-    // Add them to the database
-    for (int i = 0; i < leases.size(); ++i) {
-        EXPECT_TRUE(lmptr_->addLease(leases[i]));
-    }
-
-    // Get the leases matching the DUID and IAID of lease[1].
-    Lease6Ptr returned = lmptr_->getLease6(*leases[1]->duid_,
-                                           leases[1]->iaid_,
-                                           leases[1]->subnet_id_);
-    ASSERT_TRUE(returned);
-    EXPECT_TRUE(*returned == *leases[1]);
-
-    // Modify each of the three parameters (DUID, IAID, Subnet ID) and
-    // check that nothing is returned.
-    returned = lmptr_->getLease6(*leases[1]->duid_, leases[1]->iaid_ + 1,
-                                 leases[1]->subnet_id_);
-    EXPECT_FALSE(returned);
-
-    returned = lmptr_->getLease6(*leases[1]->duid_, leases[1]->iaid_,
-                                 leases[1]->subnet_id_ + 1);
-    EXPECT_FALSE(returned);
-
-    // Alter the leases[1] DUID to match nothing in the database.
-    vector<uint8_t> duid_vector = leases[1]->duid_->getDuid();
-    ++duid_vector[0];
-    DUID new_duid(duid_vector);
-    returned = lmptr_->getLease6(new_duid, leases[1]->iaid_,
-                                 leases[1]->subnet_id_);
-    EXPECT_FALSE(returned);
-}
-
-
-
-// @brief Lease6 Update Tests
-//
-// Checks that we are able to update a lease in the database.
-TEST_F(MySqlLeaseMgrTest, updateLease6) {
-    // Get the leases to be used for the test.
-    vector<Lease6Ptr> leases = createLeases6();
-    EXPECT_LE(3, leases.size());    // Expect to access leases 0 through 5
-
-    // Add a lease to the database and check that the lease is there.
-    EXPECT_TRUE(lmptr_->addLease(leases[1]));
-    lmptr_->commit();
-
-    reopen();
-    Lease6Ptr l_returned = lmptr_->getLease6(L1_IOADDRESS);
-    EXPECT_TRUE(l_returned);
-    detailCompareLease6(leases[1], l_returned);
-
-    // Modify some fields in lease 1 (not the address) and update it.
-    ++leases[1]->iaid_;
-    leases[1]->type_ = Lease6::LEASE_IA_PD;
-    leases[1]->valid_lft_ *= 2;
-    lmptr_->updateLease6(leases[1]);
-    lmptr_->commit();
-    reopen();
-
-    // ... and check what is returned is what is expected.
-    l_returned.reset();
-    l_returned = lmptr_->getLease6(L1_IOADDRESS);
-    EXPECT_TRUE(l_returned);
-    detailCompareLease6(leases[1], l_returned);
-
-    // Alter the lease again and check.
-    ++leases[1]->iaid_;
-    leases[1]->type_ = Lease6::LEASE_IA_TA;
-    leases[1]->cltt_ += 6;
-    leases[1]->prefixlen_ = 93;
-    lmptr_->updateLease6(leases[1]);
-
-    l_returned.reset();
-    l_returned = lmptr_->getLease6(L1_IOADDRESS);
-    EXPECT_TRUE(l_returned);
-    detailCompareLease6(leases[1], l_returned);
-
-    // Check we can do an update without changing data.
-    lmptr_->updateLease6(leases[1]);
-    l_returned.reset();
-    l_returned = lmptr_->getLease6(L1_IOADDRESS);
-    EXPECT_TRUE(l_returned);
-    detailCompareLease6(leases[1], l_returned);
-
-    // Try updating a lease not in the database.
-    EXPECT_THROW(lmptr_->updateLease6(leases[2]), isc::dhcp::NoSuchLease);
-}
-
-}; // Of anonymous namespace
diff --git a/src/lib/dhcp/tests/pool_unittest.cc b/src/lib/dhcp/tests/pool_unittest.cc
deleted file mode 100644
index e596278..0000000
--- a/src/lib/dhcp/tests/pool_unittest.cc
+++ /dev/null
@@ -1,181 +0,0 @@
-// 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 <config.h>
-#include <iostream>
-#include <vector>
-#include <sstream>
-#include <gtest/gtest.h>
-#include <dhcp/pool.h>
-#include <asiolink/io_address.h>
-
-using boost::scoped_ptr;
-using namespace isc;
-using namespace isc::dhcp;
-using namespace isc::asiolink;
-
-namespace {
-
-TEST(Pool4Test, constructor_first_last) {
-
-    // let's construct 192.0.2.1-192.0.2.255 pool
-    Pool4 pool1(IOAddress("192.0.2.1"), IOAddress("192.0.2.255"));
-
-    EXPECT_EQ(IOAddress("192.0.2.1"), pool1.getFirstAddress());
-    EXPECT_EQ(IOAddress("192.0.2.255"), pool1.getLastAddress());
-
-    // This is Pool4, IPv6 addresses do not belong here
-    EXPECT_THROW(Pool6(Pool6::TYPE_IA, IOAddress("2001:db8::1"),
-                       IOAddress("192.168.0.5")), BadValue);
-    EXPECT_THROW(Pool6(Pool6::TYPE_IA, IOAddress("192.168.0.2"),
-                       IOAddress("2001:db8::1")), BadValue);
-
-    // Should throw. Range should be 192.0.2.1-192.0.2.2, not
-    // the other way around.
-    EXPECT_THROW(Pool6(Pool6::TYPE_IA, IOAddress("192.0.2.2"),
-                       IOAddress("192.0.2.1")), BadValue);
-}
-
-TEST(Pool4Test, constructor_prefix_len) {
-
-    // let's construct 2001:db8:1::/96 pool
-    Pool4 pool1(IOAddress("192.0.2.0"), 25);
-
-    EXPECT_EQ("192.0.2.0", pool1.getFirstAddress().toText());
-    EXPECT_EQ("192.0.2.127", pool1.getLastAddress().toText());
-
-    // No such thing as /33 prefix
-    EXPECT_THROW(Pool4(IOAddress("192.0.2.1"), 33), BadValue);
-
-    // /0 prefix does not make sense
-    EXPECT_THROW(Pool4(IOAddress("192.0.2.0"), 0), BadValue);
-
-    // This is Pool6, IPv4 addresses do not belong here
-    EXPECT_THROW(Pool4(IOAddress("2001:db8::1"), 20), BadValue);
-}
-
-TEST(Pool4Test, in_range) {
-   Pool4 pool1(IOAddress("192.0.2.10"), IOAddress("192.0.2.20"));
-
-   EXPECT_FALSE(pool1.inRange(IOAddress("192.0.2.0")));
-   EXPECT_TRUE(pool1.inRange(IOAddress("192.0.2.10")));
-   EXPECT_TRUE(pool1.inRange(IOAddress("192.0.2.17")));
-   EXPECT_TRUE(pool1.inRange(IOAddress("192.0.2.20")));
-   EXPECT_FALSE(pool1.inRange(IOAddress("192.0.2.21")));
-   EXPECT_FALSE(pool1.inRange(IOAddress("192.0.2.255")));
-   EXPECT_FALSE(pool1.inRange(IOAddress("255.255.255.255")));
-   EXPECT_FALSE(pool1.inRange(IOAddress("0.0.0.0")));
-}
-
-// This test creates 100 pools and verifies that their IDs are unique.
-TEST(Pool4Test, unique_id) {
-
-    const int num_pools = 100;
-    std::vector<Pool4Ptr> pools;
-
-    for (int i = 0; i < num_pools; ++i) {
-        pools.push_back(Pool4Ptr(new Pool4(IOAddress("192.0.2.0"),
-                                           IOAddress("192.0.2.255"))));
-    }
-
-    for (int i = 0; i < num_pools; ++i) {
-        for (int j = i + 1; j < num_pools; ++j) {
-            if (pools[i]->getId() == pools[j]->getId()) {
-                FAIL() << "Pool-ids must be unique";
-            }
-        }
-    }
-
-}
-
-
-TEST(Pool6Test, constructor_first_last) {
-
-    // let's construct 2001:db8:1:: - 2001:db8:1::ffff:ffff:ffff:ffff pool
-    Pool6 pool1(Pool6::TYPE_IA, IOAddress("2001:db8:1::"),
-                IOAddress("2001:db8:1::ffff:ffff:ffff:ffff"));
-
-    EXPECT_EQ(Pool6::TYPE_IA, pool1.getType());
-    EXPECT_EQ(IOAddress("2001:db8:1::"), pool1.getFirstAddress());
-    EXPECT_EQ(IOAddress("2001:db8:1::ffff:ffff:ffff:ffff"),
-              pool1.getLastAddress());
-
-    // This is Pool6, IPv4 addresses do not belong here
-    EXPECT_THROW(Pool6(Pool6::TYPE_IA, IOAddress("2001:db8::1"),
-                       IOAddress("192.168.0.5")), BadValue);
-    EXPECT_THROW(Pool6(Pool6::TYPE_IA, IOAddress("192.168.0.2"),
-                       IOAddress("2001:db8::1")), BadValue);
-
-    // Should throw. Range should be 2001:db8::1 - 2001:db8::2, not
-    // the other way around.
-    EXPECT_THROW(Pool6(Pool6::TYPE_IA, IOAddress("2001:db8::2"),
-                       IOAddress("2001:db8::1")), BadValue);
-}
-
-TEST(Pool6Test, constructor_prefix_len) {
-
-    // let's construct 2001:db8:1::/96 pool
-    Pool6 pool1(Pool6::TYPE_IA, IOAddress("2001:db8:1::"), 96);
-
-    EXPECT_EQ(Pool6::TYPE_IA, pool1.getType());
-    EXPECT_EQ("2001:db8:1::", pool1.getFirstAddress().toText());
-    EXPECT_EQ("2001:db8:1::ffff:ffff", pool1.getLastAddress().toText());
-
-    // No such thing as /130 prefix
-    EXPECT_THROW(Pool6(Pool6::TYPE_IA, IOAddress("2001:db8::"), 130),
-                 BadValue);
-
-    // /0 prefix does not make sense
-    EXPECT_THROW(Pool6(Pool6::TYPE_IA, IOAddress("2001:db8::"), 0),
-                 BadValue);
-
-    // This is Pool6, IPv4 addresses do not belong here
-    EXPECT_THROW(Pool6(Pool6::TYPE_IA, IOAddress("192.168.0.2"), 96),
-                 BadValue);
-}
-
-TEST(Pool6Test, in_range) {
-   Pool6 pool1(Pool6::TYPE_IA, IOAddress("2001:db8:1::1"),
-               IOAddress("2001:db8:1::f"));
-
-   EXPECT_FALSE(pool1.inRange(IOAddress("2001:db8:1::")));
-   EXPECT_TRUE(pool1.inRange(IOAddress("2001:db8:1::1")));
-   EXPECT_TRUE(pool1.inRange(IOAddress("2001:db8:1::7")));
-   EXPECT_TRUE(pool1.inRange(IOAddress("2001:db8:1::f")));
-   EXPECT_FALSE(pool1.inRange(IOAddress("2001:db8:1::10")));
-   EXPECT_FALSE(pool1.inRange(IOAddress("::")));
-}
-
-// This test creates 100 pools and verifies that their IDs are unique.
-TEST(Pool6Test, unique_id) {
-
-    const int num_pools = 100;
-    std::vector<Pool6Ptr> pools;
-
-    for (int i = 0; i < num_pools; ++i) {
-        pools.push_back(Pool6Ptr(new Pool6(Pool6::TYPE_IA, IOAddress("2001:db8:1::"),
-                                           IOAddress("2001:db8:1::ffff:ffff:ffff:ffff"))));
-    }
-
-    for (int i = 0; i < num_pools; ++i) {
-        for (int j = i + 1; j < num_pools; ++j) {
-            if (pools[i]->getId() == pools[j]->getId()) {
-                FAIL() << "Pool-ids must be unique";
-            }
-        }
-    }
-
-}
-
-}; // end of anonymous namespace
diff --git a/src/lib/dhcp/tests/schema_copy.h b/src/lib/dhcp/tests/schema_copy.h
deleted file mode 100644
index 1dd796d..0000000
--- a/src/lib/dhcp/tests/schema_copy.h
+++ /dev/null
@@ -1,85 +0,0 @@
-// 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 SCHEMA_COPY_H
-#define SCHEMA_COPY_H
-
-namespace {
-
-// What follows is a set of statements that creates a copy of the schema
-// in the test database.  It is used by the MySQL unit test prior to each
-// test.
-//
-// Each SQL statement is a single string.  The statements are not terminated
-// by semicolons, and the strings must end with a comma.  The final line
-// statement must be NULL (not in quotes)
-
-// THIS MUST BE KEPT UP TO DATE AND UPDATED IF THE SCHEMA CHANGES
-
-// Deletion of existing tables.
-
-const char* destroy_statement[] = {
-    "DROP TABLE lease4",
-    "DROP TABLE lease6",
-    "DROP TABLE lease6_types",
-    "DROP TABLE schema_version",
-    NULL
-};
-
-// Creation of the new tables.
-
-const char* create_statement[] = {
-    "CREATE TABLE lease4 ("
-        "address INT UNSIGNED PRIMARY KEY NOT NULL,"
-        "hwaddr VARBINARY(20),"
-        "client_id VARBINARY(128),"
-        "lease_time INT UNSIGNED,"
-        "expire TIMESTAMP,"
-        "subnet_id INT UNSIGNED"
-        ") ENGINE = INNODB",
-
-    "CREATE TABLE lease6 ("
-        "address VARCHAR(40) PRIMARY KEY NOT NULL,"
-        "duid VARBINARY(128),"
-        "valid_lifetime INT UNSIGNED,"
-        "expire TIMESTAMP,"
-        "subnet_id INT UNSIGNED,"
-        "pref_lifetime INT UNSIGNED,"
-        "lease_type TINYINT,"
-        "iaid INT UNSIGNED,"
-        "prefix_len TINYINT UNSIGNED"
-        ") ENGINE = INNODB",
-
-    "CREATE TABLE lease6_types ("
-        "lease_type TINYINT PRIMARY KEY NOT NULL,"
-        "name VARCHAR(5)"
-        ")",
-
-    "INSERT INTO lease6_types VALUES (0, \"IA_NA\")",
-    "INSERT INTO lease6_types VALUES (1, \"IA_TA\")",
-    "INSERT INTO lease6_types VALUES (2, \"IA_PD\")",
-
-    "CREATE TABLE schema_version ("
-        "version INT PRIMARY KEY NOT NULL,"
-        "minor INT"
-        ")",
-
-    "INSERT INTO schema_version VALUES (0, 1)",
-
-    NULL
-};
-
-};  // Anonymous namespace
-
-#endif // SCHEMA_COPY_H
diff --git a/src/lib/dhcp/tests/subnet_unittest.cc b/src/lib/dhcp/tests/subnet_unittest.cc
deleted file mode 100644
index 0d9c546..0000000
--- a/src/lib/dhcp/tests/subnet_unittest.cc
+++ /dev/null
@@ -1,447 +0,0 @@
-// 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 <config.h>
-#include <dhcp/subnet.h>
-#include <dhcp/option.h>
-#include <exceptions/exceptions.h>
-#include <boost/scoped_ptr.hpp>
-#include <gtest/gtest.h>
-#include <asiolink/io_address.h>
-
-// don't import the entire boost namespace.  It will unexpectedly hide uint8_t
-// for some systems.
-using boost::scoped_ptr;
-using namespace isc;
-using namespace isc::dhcp;
-using namespace isc::asiolink;
-
-namespace {
-
-TEST(Subnet4Test, constructor) {
-    EXPECT_NO_THROW(Subnet4 subnet1(IOAddress("192.0.2.2"), 16,
-                                    1, 2, 3));
-
-    EXPECT_THROW(Subnet4 subnet2(IOAddress("192.0.2.0"), 33, 1, 2, 3),
-                BadValue); // invalid prefix length
-    EXPECT_THROW(Subnet4 subnet3(IOAddress("2001:db8::1"), 24, 1, 2, 3),
-                BadValue); // IPv6 addresses are not allowed in Subnet4
-}
-
-TEST(Subnet4Test, in_range) {
-    Subnet4 subnet(IOAddress("192.0.2.1"), 24, 1000, 2000, 3000);
-
-    EXPECT_EQ(1000, subnet.getT1());
-    EXPECT_EQ(2000, subnet.getT2());
-    EXPECT_EQ(3000, subnet.getValid());
-
-    EXPECT_FALSE(subnet.inRange(IOAddress("192.0.0.0")));
-    EXPECT_TRUE(subnet.inRange(IOAddress("192.0.2.0")));
-    EXPECT_TRUE(subnet.inRange(IOAddress("192.0.2.1")));
-    EXPECT_TRUE(subnet.inRange(IOAddress("192.0.2.255")));
-    EXPECT_FALSE(subnet.inRange(IOAddress("192.0.3.0")));
-    EXPECT_FALSE(subnet.inRange(IOAddress("0.0.0.0")));
-    EXPECT_FALSE(subnet.inRange(IOAddress("255.255.255.255")));
-}
-
-TEST(Subnet4Test, Pool4InSubnet4) {
-
-    Subnet4Ptr subnet(new Subnet4(IOAddress("192.1.2.0"), 24, 1, 2, 3));
-
-    Pool4Ptr pool1(new Pool4(IOAddress("192.1.2.0"), 25));
-    Pool4Ptr pool2(new Pool4(IOAddress("192.1.2.128"), 26));
-    Pool4Ptr pool3(new Pool4(IOAddress("192.1.2.192"), 30));
-
-    subnet->addPool4(pool1);
-
-    // If there's only one pool, get that pool
-    Pool4Ptr mypool = subnet->getPool4();
-    EXPECT_EQ(mypool, pool1);
-
-
-    subnet->addPool4(pool2);
-    subnet->addPool4(pool3);
-
-    // If there are more than one pool and we didn't provide hint, we
-    // should get the first pool
-    mypool = subnet->getPool4();
-
-    EXPECT_EQ(mypool, pool1);
-
-    // If we provide a hint, we should get a pool that this hint belongs to
-    mypool = subnet->getPool4(IOAddress("192.1.2.195"));
-
-    EXPECT_EQ(mypool, pool3);
-
-}
-
-TEST(Subnet4Test, Subnet4_Pool4_checks) {
-
-    Subnet4Ptr subnet(new Subnet4(IOAddress("192.0.2.0"), 8, 1, 2, 3));
-
-    // this one is in subnet
-    Pool4Ptr pool1(new Pool4(IOAddress("192.255.0.0"), 16));
-    subnet->addPool4(pool1);
-
-    // this one is larger than the subnet!
-    Pool4Ptr pool2(new Pool4(IOAddress("193.0.0.0"), 24));
-
-    EXPECT_THROW(subnet->addPool4(pool2), BadValue);
-
-    // this one is totally out of blue
-    Pool4Ptr pool3(new Pool4(IOAddress("1.2.3.4"), 16));
-    EXPECT_THROW(subnet->addPool4(pool3), BadValue);
-}
-
-TEST(Subnet4Test, addInvalidOption) {
-    // Create the V4 subnet.
-    Subnet4Ptr subnet(new Subnet4(IOAddress("192.0.2.0"), 8, 1, 2, 3));
-
-    // Some dummy option code.
-    uint16_t code = 100;
-    // Create option with invalid universe (V6 instead of V4).
-    // Attempt to add this option should result in exception.
-    OptionPtr option1(new Option(Option::V6, code, OptionBuffer(10, 0xFF)));
-    EXPECT_THROW(subnet->addOption(option1), isc::BadValue);
-
-    // Create NULL pointer option. Attempt to add NULL option
-    // should result in exception.
-    OptionPtr option2;
-    ASSERT_FALSE(option2);
-    EXPECT_THROW(subnet->addOption(option2), isc::BadValue);
-}
-
-// This test verifies that inRange() and inPool() methods work properly.
-TEST(Subnet4Test, inRangeinPool) {
-    Subnet4Ptr subnet(new Subnet4(IOAddress("192.0.0.0"), 8, 1, 2, 3));
-
-    // this one is in subnet
-    Pool4Ptr pool1(new Pool4(IOAddress("192.2.0.0"), 16));
-    subnet->addPool4(pool1);
-
-    // 192.1.1.1 belongs to the subnet...
-    EXPECT_TRUE(subnet->inRange(IOAddress("192.1.1.1")));
-
-    // ... but it does not belong to any pool within
-    EXPECT_FALSE(subnet->inPool(IOAddress("192.1.1.1")));
-
-    // the last address that is in range, but out of pool
-    EXPECT_TRUE(subnet->inRange(IOAddress("192.1.255.255")));
-    EXPECT_FALSE(subnet->inPool(IOAddress("192.1.255.255")));
-
-    // the first address that is in range, in pool
-    EXPECT_TRUE(subnet->inRange(IOAddress("192.2.0.0")));
-    EXPECT_TRUE (subnet->inPool(IOAddress("192.2.0.0")));
-
-    // let's try something in the middle as well
-    EXPECT_TRUE(subnet->inRange(IOAddress("192.2.3.4")));
-    EXPECT_TRUE (subnet->inPool(IOAddress("192.2.3.4")));
-
-    // the last address that is in range, in pool
-    EXPECT_TRUE(subnet->inRange(IOAddress("192.2.255.255")));
-    EXPECT_TRUE (subnet->inPool(IOAddress("192.2.255.255")));
-
-    // the first address that is in range, but out of pool
-    EXPECT_TRUE(subnet->inRange(IOAddress("192.3.0.0")));
-    EXPECT_FALSE(subnet->inPool(IOAddress("192.3.0.0")));
-}
-
-// This test checks if the toText() method returns text representation
-TEST(Subnet4Test, toText) {
-    Subnet4Ptr subnet(new Subnet4(IOAddress("192.0.2.0"), 24, 1, 2, 3));
-    EXPECT_EQ("192.0.2.0/24", subnet->toText());
-}
-
-// This test checks if the get() method returns proper parameters
-TEST(Subnet4Test, get) {
-    Subnet4Ptr subnet(new Subnet4(IOAddress("192.0.2.0"), 28, 1, 2, 3));
-    EXPECT_EQ("192.0.2.0", subnet->get().first.toText());
-    EXPECT_EQ(28, subnet->get().second);
-}
-
-// Tests for Subnet6
-
-TEST(Subnet6Test, constructor) {
-
-    EXPECT_NO_THROW(Subnet6 subnet1(IOAddress("2001:db8:1::"), 64,
-                                    1, 2, 3, 4));
-
-    EXPECT_THROW(Subnet6 subnet2(IOAddress("2001:db8:1::"), 129, 1, 2, 3, 4),
-                BadValue); // invalid prefix length
-    EXPECT_THROW(Subnet6 subnet3(IOAddress("192.168.0.0"), 32, 1, 2, 3, 4),
-                BadValue); // IPv4 addresses are not allowed in Subnet6
-}
-
-TEST(Subnet6Test, in_range) {
-    Subnet6 subnet(IOAddress("2001:db8:1::"), 64, 1000, 2000, 3000, 4000);
-
-    EXPECT_EQ(1000, subnet.getT1());
-    EXPECT_EQ(2000, subnet.getT2());
-    EXPECT_EQ(3000, subnet.getPreferred());
-    EXPECT_EQ(4000, subnet.getValid());
-
-    EXPECT_FALSE(subnet.inRange(IOAddress("2001:db8:0:ffff:ffff:ffff:ffff:ffff")));
-    EXPECT_TRUE(subnet.inRange(IOAddress("2001:db8:1::0")));
-    EXPECT_TRUE(subnet.inRange(IOAddress("2001:db8:1::1")));
-    EXPECT_TRUE(subnet.inRange(IOAddress("2001:db8:1::ffff:ffff:ffff:ffff")));
-    EXPECT_FALSE(subnet.inRange(IOAddress("2001:db8:1:1::")));
-    EXPECT_FALSE(subnet.inRange(IOAddress("::")));
-}
-
-TEST(Subnet6Test, Pool6InSubnet6) {
-
-    Subnet6Ptr subnet(new Subnet6(IOAddress("2001:db8:1::"), 56, 1, 2, 3, 4));
-
-    Pool6Ptr pool1(new Pool6(Pool6::TYPE_IA, IOAddress("2001:db8:1:1::"), 64));
-    Pool6Ptr pool2(new Pool6(Pool6::TYPE_IA, IOAddress("2001:db8:1:2::"), 64));
-    Pool6Ptr pool3(new Pool6(Pool6::TYPE_IA, IOAddress("2001:db8:1:3::"), 64));
-
-    subnet->addPool6(pool1);
-
-    // If there's only one pool, get that pool
-    Pool6Ptr mypool = subnet->getPool6();
-    EXPECT_EQ(mypool, pool1);
-
-
-    subnet->addPool6(pool2);
-    subnet->addPool6(pool3);
-
-    // If there are more than one pool and we didn't provide hint, we
-    // should get the first pool
-    mypool = subnet->getPool6();
-
-    EXPECT_EQ(mypool, pool1);
-
-    // If we provide a hint, we should get a pool that this hint belongs to
-    mypool = subnet->getPool6(IOAddress("2001:db8:1:3::dead:beef"));
-
-    EXPECT_EQ(mypool, pool3);
-}
-
-TEST(Subnet6Test, Subnet6_Pool6_checks) {
-
-    Subnet6Ptr subnet(new Subnet6(IOAddress("2001:db8:1::"), 56, 1, 2, 3, 4));
-
-    // this one is in subnet
-    Pool6Ptr pool1(new Pool6(Pool6::TYPE_IA, IOAddress("2001:db8:1:1::"), 64));
-    subnet->addPool6(pool1);
-
-    // this one is larger than the subnet!
-    Pool6Ptr pool2(new Pool6(Pool6::TYPE_IA, IOAddress("2001:db8::"), 48));
-
-    EXPECT_THROW(subnet->addPool6(pool2), BadValue);
-
-
-    // this one is totally out of blue
-    Pool6Ptr pool3(new Pool6(Pool6::TYPE_IA, IOAddress("3000::"), 16));
-    EXPECT_THROW(subnet->addPool6(pool3), BadValue);
-
-
-    Pool6Ptr pool4(new Pool6(Pool6::TYPE_IA, IOAddress("4001:db8:1::"), 80));
-    EXPECT_THROW(subnet->addPool6(pool4), BadValue);
-}
-
-TEST(Subnet6Test, addOptions) {
-    // Create as subnet to add options to it.
-    Subnet6Ptr subnet(new Subnet6(IOAddress("2001:db8:1::"), 56, 1, 2, 3, 4));
-
-    // Differentiate options by their codes (100-109)
-    for (uint16_t code = 100; code < 110; ++code) {
-        OptionPtr option(new Option(Option::V6, code, OptionBuffer(10, 0xFF)));
-        ASSERT_NO_THROW(subnet->addOption(option));
-    }
-
-    // Get options from the Subnet and check if all 10 are there.
-    Subnet::OptionContainer options = subnet->getOptions();
-    ASSERT_EQ(10, options.size());
-
-    // Validate codes of added options.
-    uint16_t expected_code = 100;
-    for (Subnet::OptionContainer::const_iterator option_desc = options.begin();
-         option_desc != options.end(); ++option_desc) {
-        ASSERT_TRUE(option_desc->option);
-        EXPECT_EQ(expected_code, option_desc->option->getType());
-        ++expected_code;
-    }
-
-    subnet->delOptions();
-
-    options = subnet->getOptions();
-    EXPECT_EQ(0, options.size());
-}
-
-TEST(Subnet6Test, addNonUniqueOptions) {
-    // Create as subnet to add options to it.
-    Subnet6Ptr subnet(new Subnet6(IOAddress("2001:db8:1::"), 56, 1, 2, 3, 4));
-
-    // Create a set of options with non-unique codes.
-    for (int i = 0;  i < 2; ++i) {
-        // In the inner loop we create options with unique codes (100-109).
-        for (uint16_t code = 100; code < 110; ++code) {
-            OptionPtr option(new Option(Option::V6, code, OptionBuffer(10, 0xFF)));
-            ASSERT_NO_THROW(subnet->addOption(option));
-        }
-    }
-
-    // Sanity check that all options are there.
-    Subnet::OptionContainer options = subnet->getOptions();
-    ASSERT_EQ(20, options.size());
-
-    // Use container index #1 to get the options by their codes.
-    Subnet::OptionContainerTypeIndex& idx = options.get<1>();
-    // Look for the codes 100-109.
-    for (uint16_t code = 100; code < 110; ++ code) {
-        // For each code we should get two instances of options.
-        std::pair<Subnet::OptionContainerTypeIndex::const_iterator,
-                  Subnet::OptionContainerTypeIndex::const_iterator> range =
-            idx.equal_range(code);
-        // Distance between iterators indicates how many options
-        // have been retured for the particular code.
-        ASSERT_EQ(2, distance(range.first, range.second));
-        // Check that returned options actually have the expected option code.
-        for (Subnet::OptionContainerTypeIndex::const_iterator option_desc = range.first;
-             option_desc != range.second; ++option_desc) {
-            ASSERT_TRUE(option_desc->option);
-            EXPECT_EQ(code, option_desc->option->getType());
-        }
-    }
-
-    // Let's try to find some non-exiting option.
-    const uint16_t non_existing_code = 150;
-    std::pair<Subnet::OptionContainerTypeIndex::const_iterator,
-              Subnet::OptionContainerTypeIndex::const_iterator> range =
-        idx.equal_range(non_existing_code);
-    // Empty set is expected.
-    EXPECT_EQ(0, distance(range.first, range.second));
-
-    subnet->delOptions();
-
-    options = subnet->getOptions();
-    EXPECT_EQ(0, options.size());
-}
-
-TEST(Subnet6Test, addInvalidOption) {
-    // Create as subnet to add options to it.
-    Subnet6Ptr subnet(new Subnet6(IOAddress("2001:db8:1::"), 56, 1, 2, 3, 4));
-
-    // Some dummy option code.
-    uint16_t code = 100;
-    // Create option with invalid universe (V4 instead of V6).
-    // Attempt to add this option should result in exception.
-    OptionPtr option1(new Option(Option::V4, code, OptionBuffer(10, 0xFF)));
-    EXPECT_THROW(subnet->addOption(option1), isc::BadValue);
-
-    // Create NULL pointer option. Attempt to add NULL option
-    // should result in exception.
-    OptionPtr option2;
-    ASSERT_FALSE(option2);
-    EXPECT_THROW(subnet->addOption(option2), isc::BadValue);
-}
-
-TEST(Subnet6Test, addPersistentOption) {
-    // Create as subnet to add options to it.
-    Subnet6Ptr subnet(new Subnet6(IOAddress("2001:db8:1::"), 56, 1, 2, 3, 4));
-
-    // Add 10 options to the subnet with option codes 100 - 109.
-    for (uint16_t code = 100; code < 110; ++code) {
-        OptionPtr option(new Option(Option::V6, code, OptionBuffer(10, 0xFF)));
-        // We create 10 options and want some of them to be flagged
-        // persistent and some non-persistent. Persistent options are
-        // those that server sends to clients regardless if they ask
-        // for them or not. We pick 3 out of 10 options and mark them
-        // non-persistent and 7 other options persistent.
-        // Code values: 102, 105 and 108 are divisable by 3
-        // and options with these codes will be flagged non-persistent.
-        // Options with other codes will be flagged persistent.
-        bool persistent = (code % 3) ? true : false;
-        ASSERT_NO_THROW(subnet->addOption(option, persistent));
-    }
-
-    // Get added options from the subnet.
-    Subnet::OptionContainer options = subnet->getOptions();
-
-    // options.get<2> returns reference to container index #2. This
-    // index is used to access options by the 'persistent' flag.
-    Subnet::OptionContainerPersistIndex& idx = options.get<2>();
-
-    // Get all persistent options.
-    std::pair<Subnet::OptionContainerPersistIndex::const_iterator,
-              Subnet::OptionContainerPersistIndex::const_iterator> range_persistent =
-        idx.equal_range(true);
-    // 3 out of 10 options have been flagged persistent.
-    ASSERT_EQ(7, distance(range_persistent.first, range_persistent.second));
-
-    // Get all non-persistent options.
-    std::pair<Subnet::OptionContainerPersistIndex::const_iterator,
-              Subnet::OptionContainerPersistIndex::const_iterator> range_non_persistent =
-        idx.equal_range(false);
-    // 7 out of 10 options have been flagged persistent.
-    ASSERT_EQ(3, distance(range_non_persistent.first, range_non_persistent.second));
-
-    subnet->delOptions();
-
-    options = subnet->getOptions();
-    EXPECT_EQ(0, options.size());
-}
-
-// This test verifies that inRange() and inPool() methods work properly.
-TEST(Subnet6Test, inRangeinPool) {
-    Subnet6Ptr subnet(new Subnet6(IOAddress("2001:db8::"), 32, 1, 2, 3, 4));
-
-    // this one is in subnet
-    Pool6Ptr pool1(new Pool6(Pool6::TYPE_IA, IOAddress("2001:db8::10"),
-                             IOAddress("2001:db8::20")));
-    subnet->addPool6(pool1);
-
-    // 192.1.1.1 belongs to the subnet...
-    EXPECT_TRUE(subnet->inRange(IOAddress("2001:db8::1")));
-    // ... but it does not belong to any pool within
-    EXPECT_FALSE(subnet->inPool(IOAddress("2001:db8::1")));
-
-    // the last address that is in range, but out of pool
-    EXPECT_TRUE(subnet->inRange(IOAddress("2001:db8::f")));
-    EXPECT_FALSE(subnet->inPool(IOAddress("2001:db8::f")));
-
-    // the first address that is in range, in pool
-    EXPECT_TRUE(subnet->inRange(IOAddress("2001:db8::10")));
-    EXPECT_TRUE (subnet->inPool(IOAddress("2001:db8::10")));
-
-    // let's try something in the middle as well
-    EXPECT_TRUE(subnet->inRange(IOAddress("2001:db8::18")));
-    EXPECT_TRUE (subnet->inPool(IOAddress("2001:db8::18")));
-
-    // the last address that is in range, in pool
-    EXPECT_TRUE(subnet->inRange(IOAddress("2001:db8::20")));
-    EXPECT_TRUE (subnet->inPool(IOAddress("2001:db8::20")));
-
-    // the first address that is in range, but out of pool
-    EXPECT_TRUE(subnet->inRange(IOAddress("2001:db8::21")));
-    EXPECT_FALSE(subnet->inPool(IOAddress("2001:db8::21")));
-}
-
-// This test checks if the toText() method returns text representation
-TEST(Subnet6Test, toText) {
-    Subnet6 subnet(IOAddress("2001:db8::"), 32, 1, 2, 3, 4);
-    EXPECT_EQ("2001:db8::/32", subnet.toText());
-}
-
-// This test checks if the get() method returns proper parameters
-TEST(Subnet6Test, get) {
-    Subnet6 subnet(IOAddress("2001:db8::"), 32, 1, 2, 3, 4);
-    EXPECT_EQ("2001:db8::", subnet.get().first.toText());
-    EXPECT_EQ(32, subnet.get().second);
-}
-
-};
diff --git a/src/lib/dhcp/tests/triplet_unittest.cc b/src/lib/dhcp/tests/triplet_unittest.cc
deleted file mode 100644
index 727eb8a..0000000
--- a/src/lib/dhcp/tests/triplet_unittest.cc
+++ /dev/null
@@ -1,104 +0,0 @@
-// 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 <config.h>
-#include <stdint.h>
-#include <gtest/gtest.h>
-#include <dhcp/triplet.h>
-#include <exceptions/exceptions.h>
-
-using namespace isc::dhcp;
-using namespace isc;
-
-namespace {
-
-// constructor validation
-TEST(TripletTest, constructor) {
-
-    const uint32_t min = 10;
-    const uint32_t value = 20;
-    const uint32_t max = 30;
-
-    Triplet<uint32_t> x(min, value, max);
-
-    EXPECT_EQ(min, x.getMin());
-    EXPECT_EQ(value, x.get());
-    EXPECT_EQ(max, x.getMax());
-
-    // requested values below min should return allowed min value
-    EXPECT_EQ(min, x.get(min - 5));
-
-    EXPECT_EQ(min, x.get(min));
-
-    // requesting a value from within the range (min < x < max) should
-    // return the requested value
-    EXPECT_EQ(17, x.get(17));
-
-    EXPECT_EQ(max, x.get(max));
-
-    EXPECT_EQ(max, x.get(max + 5));
-
-    // this will be boring. It is expected to return 42 no matter what
-    Triplet<uint32_t> y(42);
-
-    EXPECT_EQ(42, y.getMin()); // min, default and max are equal to 42
-    EXPECT_EQ(42, y.get());    // it returns ...
-    EXPECT_EQ(42, y.getMax()); // the exact value...
-
-    // requested values below or above are ignore
-    EXPECT_EQ(42, y.get(5));   // all...
-    EXPECT_EQ(42, y.get(42));  // the...
-    EXPECT_EQ(42, y.get(80));  // time!
-}
-
-// Triplets must be easy to use.
-// Simple to/from int conversions must be done on the fly.
-TEST(TripletTest, operator) {
-
-    uint32_t x = 47;
-
-    Triplet<uint32_t> foo(1,2,3);
-    Triplet<uint32_t> bar(4,5,6);
-
-    foo = bar;
-
-    EXPECT_EQ(4, foo.getMin());
-    EXPECT_EQ(5, foo.get());
-    EXPECT_EQ(6, foo.getMax());
-
-    // assignment operator: uint32_t => triplet
-    Triplet<uint32_t> y(0);
-    y = x;
-
-    EXPECT_EQ(x, y.get());
-
-    // let's try the other way around: triplet => uint32_t
-    uint32_t z = 0;
-    z = y;
-
-    EXPECT_EQ(x, z);
-}
-
-// check if specified values are sane
-TEST(TripletTest, sanity_check) {
-
-    // min is larger than default
-    EXPECT_THROW(Triplet<uint32_t>(6,5,5), BadValue);
-
-    // max is smaller than default
-    EXPECT_THROW(Triplet<uint32_t>(5,5,4), BadValue);
-
-}
-
-}; // end of anonymous namespace
diff --git a/src/lib/dhcp/triplet.h b/src/lib/dhcp/triplet.h
deleted file mode 100644
index d9388fe..0000000
--- a/src/lib/dhcp/triplet.h
+++ /dev/null
@@ -1,115 +0,0 @@
-// 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 TRIPLET_H
-#define TRIPLET_H
-
-#include <exceptions/exceptions.h>
-
-namespace isc {
-namespace dhcp {
-
-/// @brief this template specifies a parameter value
-///
-/// This template class is used to store configuration parameters, like lifetime or T1.
-/// It defines 3 parameters: min, default, and max value. There are 2 constructors:
-/// - simple (just one value that sets all parameters)
-/// - extended (that sets default value and two thresholds)
-/// It will be used with integer types. It provides necessary operators, so
-/// it can be assigned to a plain integer or integer assigned to a Triplet.
-/// See TripletTest.operator test for details on an easy Triplet usage.
-template <class T>
-class Triplet {
-public:
-
-    /// @brief base type to Triple conversion
-    ///
-    /// Typically: uint32_t to Triplet assignment. It is very convenient
-    /// to be able to simply write Triplet<uint32_t> x = 7;
-    Triplet<T> operator=(T other) {
-        min_ = other;
-        default_ = other;
-        max_ = other;
-        return *this;
-    }
-
-    /// @brief triplet to base type conversion
-    ///
-    /// Typically: Triplet to uint32_t assignment. It is very convenient
-    /// to be able to simply write uint32_t z = x; (where x is a Triplet)
-    operator T() const {
-        return (default_);
-    }
-
-    /// @brief sets a fixed value
-    ///
-    /// This constructor assigns a fixed (i.e. no range, just a single value)
-    /// value.
-    Triplet(T value)
-        :min_(value), default_(value), max_(value) {
-    }
-
-    /// @brief sets the default value and thresholds
-    ///
-    /// @throw BadValue if min <= def <= max rule is violated
-    Triplet(T min, T def, T max)
-        :min_(min), default_(def), max_(max) {
-        if ( (min_ > def) || (def > max_) ) {
-            isc_throw(BadValue, "Invalid triplet values.");
-        }
-    }
-
-    /// @brief returns a minimum allowed value
-    T getMin() const { return min_;}
-
-    /// @brief returns the default value
-    T get() const { return default_;}
-
-    /// @brief returns value with a hint
-    ///
-    /// DHCP protocol treats any values sent by a client as hints.
-    /// This is a method that implements that. We can assign any value
-    /// from configured range that client asks.
-    T get(T hint) const {
-        if (hint <= min_) {
-            return (min_);
-        }
-
-        if (hint >= max_) {
-            return (max_);
-        }
-
-        return (hint);
-    }
-
-    /// @brief returns a maximum allowed value
-    T getMax() const { return max_; }
-
-protected:
-
-    /// @brief the minimum value
-    T min_;
-
-    /// @brief the default value
-    T default_;
-
-    /// @brief the maximum value
-    T max_;
-};
-
-
-} // namespace isc::dhcp
-} // namespace isc
-
-#endif // ifdef TRIPLET_H
diff --git a/src/lib/dhcpsrv/Makefile.am b/src/lib/dhcpsrv/Makefile.am
new file mode 100644
index 0000000..e205aee
--- /dev/null
+++ b/src/lib/dhcpsrv/Makefile.am
@@ -0,0 +1,52 @@
+SUBDIRS = . tests
+
+AM_CPPFLAGS = -I$(top_builddir)/src/lib -I$(top_srcdir)/src/lib
+AM_CPPFLAGS += $(BOOST_INCLUDES)
+if HAVE_MYSQL
+AM_CPPFLAGS += $(MYSQL_CPPFLAGS)
+endif
+
+AM_CXXFLAGS = $(B10_CXXFLAGS)
+
+# Some versions of GCC warn about some versions of Boost regarding
+# missing initializer for members in its posix_time.
+# https://svn.boost.org/trac/boost/ticket/3477
+# But older GCC compilers don't have the flag.
+AM_CXXFLAGS += $(WARNING_NO_MISSING_FIELD_INITIALIZERS_CFLAG)
+
+CLEANFILES = *.gcno *.gcda
+
+lib_LTLIBRARIES = libb10-dhcpsrv.la
+libb10_dhcpsrv_la_SOURCES  =
+libb10_dhcpsrv_la_SOURCES += addr_utilities.cc addr_utilities.h
+libb10_dhcpsrv_la_SOURCES += alloc_engine.cc alloc_engine.h
+libb10_dhcpsrv_la_SOURCES += cfgmgr.cc cfgmgr.h
+libb10_dhcpsrv_la_SOURCES += lease_mgr.cc lease_mgr.h
+libb10_dhcpsrv_la_SOURCES += lease_mgr_factory.cc lease_mgr_factory.h
+libb10_dhcpsrv_la_SOURCES += memfile_lease_mgr.cc memfile_lease_mgr.h
+if HAVE_MYSQL
+libb10_dhcpsrv_la_SOURCES += mysql_lease_mgr.cc mysql_lease_mgr.h
+endif
+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_CXXFLAGS = $(AM_CXXFLAGS)
+libb10_dhcpsrv_la_CPPFLAGS = $(AM_CPPFLAGS) $(LOG4CPLUS_INCLUDES)
+libb10_dhcpsrv_la_LIBADD   = $(top_builddir)/src/lib/asiolink/libb10-asiolink.la
+libb10_dhcpsrv_la_LIBADD  += $(top_builddir)/src/lib/dhcp/libb10-dhcp++.la
+libb10_dhcpsrv_la_LIBADD  += $(top_builddir)/src/lib/util/libb10-util.la
+libb10_dhcpsrv_la_LDFLAGS  = -no-undefined -version-info 2:0:0
+if HAVE_MYSQL
+libb10_dhcpsrv_la_LDFLAGS += $(MYSQL_LIBS)
+endif
+
+if USE_CLANGPP
+# Disable unused parameter warning caused by some of the
+# Boost headers when compiling with clang.
+libb10_dhcpsrv_la_CXXFLAGS += -Wno-unused-parameter
+endif
+
+# Distribute MySQL schema creation script and backend documentation
+EXTRA_DIST = dhcpdb_create.mysql database_backends.dox
+dist_pkgdata_DATA = dhcpdb_create.mysql
diff --git a/src/lib/dhcpsrv/addr_utilities.cc b/src/lib/dhcpsrv/addr_utilities.cc
new file mode 100644
index 0000000..a519016
--- /dev/null
+++ b/src/lib/dhcpsrv/addr_utilities.cc
@@ -0,0 +1,189 @@
+// 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 <dhcpsrv/addr_utilities.h>
+#include <exceptions/exceptions.h>
+
+#include <string.h>
+
+using namespace isc;
+using namespace isc::asiolink;
+
+namespace {
+
+/// @brief mask used for first/last address calculation in a IPv4 prefix
+///
+/// Using a static mask is faster than calculating it dynamically every time.
+const uint32_t bitMask4[] = { 0xffffffff, 0x7fffffff, 0x3fffffff, 0x1fffffff,
+                              0x0fffffff, 0x07ffffff, 0x03ffffff, 0x01ffffff,
+                              0x00ffffff, 0x007fffff, 0x003fffff, 0x001fffff,
+                              0x000fffff, 0x0007ffff, 0x0003ffff, 0x0001ffff,
+                              0x0000ffff, 0x00007fff, 0x00003fff, 0x00001fff,
+                              0x00000fff, 0x000007ff, 0x000003ff, 0x000001ff,
+                              0x000000ff, 0x0000007f, 0x0000003f, 0x0000001f,
+                              0x0000000f, 0x00000007, 0x00000003, 0x00000001,
+                              0x00000000 };
+
+/// @brief mask used for first/last address calculation in a IPv6 prefix
+const uint8_t bitMask6[]= { 0, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0xff };
+
+/// @brief calculates the first IPv6 address in a IPv6 prefix
+///
+/// Note: This is a private function. Do not use it directly.
+/// Please use firstAddrInPrefix() instead.
+///
+/// @param prefix IPv6 prefix
+/// @param len prefix length
+isc::asiolink::IOAddress firstAddrInPrefix6(const isc::asiolink::IOAddress& prefix,
+                                            uint8_t len) {
+    if (len > 128) {
+        isc_throw(isc::BadValue,
+                  "Too large netmask. 0..128 is allowed in IPv6");
+    }
+
+    // First we copy the whole address as 16 bytes.
+    uint8_t packed[V6ADDRESS_LEN];
+    memcpy(packed, prefix.getAddress().to_v6().to_bytes().data(), 16);
+
+    // If the length is divisible by 8, it is simple. We just zero out the host
+    // part. Otherwise we need to handle the byte that has to be partially
+    // zeroed.
+    if (len % 8 != 0) {
+
+        // Get the appropriate mask. It has relevant bits (those that should
+        // stay) set and irrelevant (those that should be wiped) cleared.
+        uint8_t mask = bitMask6[len % 8];
+
+        // Let's leave only whatever the mask says should not be cleared.
+        packed[len / 8] = packed[len / 8] & mask;
+
+        // Since we have just dealt with this byte, let's move the prefix length
+        // to the beginning of the next byte (len is expressed in bits).
+        len = (len / 8 + 1) * 8;
+    }
+
+    // Clear out the remaining bits.
+    for (int i = len / 8; i < sizeof(packed); ++i) {
+        packed[i] = 0x0;
+    }
+
+    // Finally, let's wrap this into nice and easy IOAddress object.
+    return (isc::asiolink::IOAddress::from_bytes(AF_INET6, packed));
+}
+
+/// @brief calculates the first IPv4 address in a IPv4 prefix
+///
+/// Note: This is a private function. Do not use it directly.
+/// Please use firstAddrInPrefix() instead.
+///
+/// @param prefix IPv4 prefix
+/// @param len netmask length (0-32)
+isc::asiolink::IOAddress firstAddrInPrefix4(const isc::asiolink::IOAddress& prefix,
+                                            uint8_t len) {
+    if (len > 32) {
+        isc_throw(isc::BadValue, "Too large netmask. 0..32 is allowed in IPv4");
+    }
+
+    uint32_t addr = prefix;
+    return (IOAddress(addr & (~bitMask4[len])));
+}
+
+/// @brief calculates the last IPv4 address in a IPv4 prefix
+///
+/// Note: This is a private function. Do not use it directly.
+/// Please use firstAddrInPrefix() instead.
+///
+/// @param prefix IPv4 prefix that we calculate first address for
+/// @param len netmask length (0-32)
+isc::asiolink::IOAddress lastAddrInPrefix4(const isc::asiolink::IOAddress& prefix,
+                                           uint8_t len) {
+    if (len > 32) {
+        isc_throw(isc::BadValue, "Too large netmask. 0..32 is allowed in IPv4");
+    }
+
+    uint32_t addr = prefix;
+    return (IOAddress(addr | bitMask4[len]));
+}
+
+/// @brief calculates the last IPv6 address in a IPv6 prefix
+///
+/// Note: This is a private function. Do not use it directly.
+/// Please use lastAddrInPrefix() instead.
+///
+/// @param prefix IPv6 prefix that we calculate first address for
+/// @param len netmask length (0-128)
+isc::asiolink::IOAddress lastAddrInPrefix6(const isc::asiolink::IOAddress& prefix,
+                                           uint8_t len) {
+    if (len > 128) {
+        isc_throw(isc::BadValue,
+                  "Too large netmask. 0..128 is allowed in IPv6");
+    }
+
+    // First we copy the whole address as 16 bytes.
+    uint8_t packed[V6ADDRESS_LEN];
+    memcpy(packed, prefix.getAddress().to_v6().to_bytes().data(), 16);
+
+    // if the length is divisible by 8, it is simple. We just fill the host part
+    // with ones. Otherwise we need to handle the byte that has to be partially
+    // zeroed.
+    if (len % 8 != 0) {
+        // Get the appropriate mask. It has relevant bits (those that should
+        // stay) set and irrelevant (those that should be set to 1) cleared.
+        uint8_t mask = bitMask6[len % 8];
+
+        // Let's set those irrelevant bits with 1. It would be perhaps
+        // easier to not use negation here and invert bitMask6 content. However,
+        // with this approach, we can use the same mask in first and last
+        // address calculations.
+        packed[len / 8] = packed[len / 8] | ~mask;
+
+        // Since we have just dealt with this byte, let's move the prefix length
+        // to the beginning of the next byte (len is expressed in bits).
+        len = (len / 8 + 1) * 8;
+    }
+
+    // Finally set remaining bits to 1.
+    for (int i = len / 8; i < sizeof(packed); ++i) {
+        packed[i] = 0xff;
+    }
+
+    // Finally, let's wrap this into nice and easy IOAddress object.
+    return (isc::asiolink::IOAddress::from_bytes(AF_INET6, packed));
+}
+
+}; // end of anonymous namespace
+
+namespace isc {
+namespace dhcp {
+
+isc::asiolink::IOAddress firstAddrInPrefix(const isc::asiolink::IOAddress& prefix,
+                                            uint8_t len) {
+    if (prefix.getFamily() == AF_INET) {
+        return firstAddrInPrefix4(prefix, len);
+    } else {
+        return firstAddrInPrefix6(prefix, len);
+    }
+}
+
+isc::asiolink::IOAddress lastAddrInPrefix(const isc::asiolink::IOAddress& prefix,
+                                           uint8_t len) {
+    if (prefix.getFamily() == AF_INET) {
+        return lastAddrInPrefix4(prefix, len);
+    } else {
+        return lastAddrInPrefix6(prefix, len);
+    }
+}
+
+};
+};
diff --git a/src/lib/dhcpsrv/addr_utilities.h b/src/lib/dhcpsrv/addr_utilities.h
new file mode 100644
index 0000000..a1d856c
--- /dev/null
+++ b/src/lib/dhcpsrv/addr_utilities.h
@@ -0,0 +1,58 @@
+// 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 ADDR_UTILITIES_H
+#define ADDR_UTILITIES_H
+
+#include <asiolink/io_address.h>
+
+namespace isc {
+namespace dhcp {
+
+/// This code is based on similar code from the Dibbler project. I, Tomasz Mrugalski,
+/// as a sole creator of that code hereby release it under BSD license for the benefit
+/// of the BIND10 project.
+
+/// @brief returns a first address in a given prefix
+///
+/// Example: For 2001:db8:1::deaf:beef and length /120 the function will return
+/// 2001:db8:1::dead:be00. See also @ref lastAddrInPrefix.
+///
+/// @todo It currently works for v6 only and will throw if v4 address is passed.
+///
+/// @param prefix and address that belongs to a prefix
+/// @param len prefix length
+///
+/// @return first address from a prefix
+isc::asiolink::IOAddress firstAddrInPrefix(const isc::asiolink::IOAddress& prefix,
+                                            uint8_t len);
+
+/// @brief returns a last address in a given prefix
+///
+/// Example: For 2001:db8:1::deaf:beef and length /112 the function will return
+/// 2001:db8:1::dead:ffff. See also @ref firstAddrInPrefix.
+///
+/// @todo It currently works for v6 only and will throw if v4 address is passed.
+///
+/// @param prefix and address that belongs to a prefix
+/// @param len prefix length
+///
+/// @return first address from a prefix
+isc::asiolink::IOAddress lastAddrInPrefix(const isc::asiolink::IOAddress& prefix,
+                                           uint8_t len);
+
+};
+};
+
+#endif // ADDR_UTILITIES_H
diff --git a/src/lib/dhcpsrv/alloc_engine.cc b/src/lib/dhcpsrv/alloc_engine.cc
new file mode 100644
index 0000000..7fb3471
--- /dev/null
+++ b/src/lib/dhcpsrv/alloc_engine.cc
@@ -0,0 +1,276 @@
+// 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 <dhcpsrv/alloc_engine.h>
+#include <dhcpsrv/lease_mgr_factory.h>
+
+#include <cstring>
+#include <string.h>
+
+using namespace isc::asiolink;
+
+namespace isc {
+namespace dhcp {
+
+AllocEngine::IterativeAllocator::IterativeAllocator()
+    :Allocator() {
+}
+
+isc::asiolink::IOAddress
+AllocEngine::IterativeAllocator::increaseAddress(const isc::asiolink::IOAddress& addr) {
+    uint8_t packed[V6ADDRESS_LEN];
+    int len;
+
+    // First we copy the whole address as 16 bytes.
+    if (addr.getFamily()==AF_INET) {
+        // IPv4
+        std::memcpy(packed, addr.getAddress().to_v4().to_bytes().data(), 4);
+        len = 4;
+    } else {
+        // IPv6
+        std::memcpy(packed, addr.getAddress().to_v6().to_bytes().data(), 16);
+        len = 16;
+    }
+
+    for (int i = len - 1; i >= 0; --i) {
+        ++packed[i];
+        if (packed[i] != 0) {
+            break;
+        }
+    }
+
+    return (IOAddress::from_bytes(addr.getFamily(), packed));
+}
+
+
+isc::asiolink::IOAddress
+AllocEngine::IterativeAllocator::pickAddress(const Subnet6Ptr& subnet,
+                                             const DuidPtr&,
+                                             const IOAddress&) {
+
+    // Let's get the last allocated address. It is usually set correctly,
+    // but there are times when it won't be (like after removing a pool or
+    // perhaps restaring the server).
+    IOAddress last = subnet->getLastAllocated();
+
+    const Pool6Collection& pools = subnet->getPools();
+
+    if (pools.size() == 0) {
+        isc_throw(AllocFailed, "No pools defined in selected subnet");
+    }
+
+    // first we need to find a pool the last address belongs to.
+    Pool6Collection::const_iterator it;
+    for (it = pools.begin(); it != pools.end(); ++it) {
+        if ((*it)->inRange(last)) {
+            break;
+        }
+    }
+
+    // last one was bogus for one of several reasons:
+    // - we just booted up and that's the first address we're allocating
+    // - a subnet was removed or other reconfiguration just completed
+    // - perhaps allocation algorithm was changed
+    if (it == pools.end()) {
+        // ok to access first element directly. We checked that pools is non-empty
+        IOAddress next = pools[0]->getFirstAddress();
+        subnet->setLastAllocated(next);
+        return (next);
+    }
+
+    // Ok, we have a pool that the last address belonged to, let's use it.
+
+    IOAddress next = increaseAddress(last); // basically addr++
+    if ((*it)->inRange(next)) {
+        // the next one is in the pool as well, so we haven't hit pool boundary yet
+        subnet->setLastAllocated(next);
+        return (next);
+    }
+
+    // We hit pool boundary, let's try to jump to the next pool and try again
+    ++it;
+    if (it == pools.end()) {
+        // Really out of luck today. That was the last pool. Let's rewind
+        // to the beginning.
+        next = pools[0]->getFirstAddress();
+        subnet->setLastAllocated(next);
+        return (next);
+    }
+
+    // there is a next pool, let's try first adddress from it
+    next = (*it)->getFirstAddress();
+    subnet->setLastAllocated(next);
+    return (next);
+}
+
+AllocEngine::HashedAllocator::HashedAllocator()
+    :Allocator() {
+    isc_throw(NotImplemented, "Hashed allocator is not implemented");
+}
+
+
+isc::asiolink::IOAddress
+AllocEngine::HashedAllocator::pickAddress(const Subnet6Ptr&,
+                                             const DuidPtr&,
+                                             const IOAddress&) {
+    isc_throw(NotImplemented, "Hashed allocator is not implemented");
+}
+
+AllocEngine::RandomAllocator::RandomAllocator()
+    :Allocator() {
+    isc_throw(NotImplemented, "Random allocator is not implemented");
+}
+
+
+isc::asiolink::IOAddress
+AllocEngine::RandomAllocator::pickAddress(const Subnet6Ptr&,
+                                             const DuidPtr&,
+                                             const IOAddress&) {
+    isc_throw(NotImplemented, "Random allocator is not implemented");
+}
+
+
+AllocEngine::AllocEngine(AllocType engine_type, unsigned int attempts)
+    :attempts_(attempts) {
+    switch (engine_type) {
+    case ALLOC_ITERATIVE:
+        allocator_ = boost::shared_ptr<Allocator>(new IterativeAllocator());
+        break;
+    case ALLOC_HASHED:
+        allocator_ = boost::shared_ptr<Allocator>(new HashedAllocator());
+        break;
+    case ALLOC_RANDOM:
+        allocator_ = boost::shared_ptr<Allocator>(new RandomAllocator());
+        break;
+
+    default:
+        isc_throw(BadValue, "Invalid/unsupported allocation algorithm");
+    }
+}
+
+Lease6Ptr
+AllocEngine::allocateAddress6(const Subnet6Ptr& subnet,
+                              const DuidPtr& duid,
+                              uint32_t iaid,
+                              const IOAddress& hint,
+                              bool fake_allocation /* = false */ ) {
+
+    // That check is not necessary. We create allocator in AllocEngine
+    // constructor
+    if (!allocator_) {
+        isc_throw(InvalidOperation, "No allocator selected");
+    }
+
+    // check if there's existing lease for that subnet/duid/iaid combination.
+    Lease6Ptr existing = LeaseMgrFactory::instance().getLease6(*duid, iaid, subnet->getID());
+    if (existing) {
+        // we have a lease already. This is a returning client, probably after
+        // his reboot.
+        return (existing);
+    }
+
+    // check if the hint is in pool and is available
+    if (subnet->inPool(hint)) {
+        existing = LeaseMgrFactory::instance().getLease6(hint);
+        if (!existing) {
+            /// @todo: check if the hint is reserved once we have host support
+            /// implemented
+
+            // the hint is valid and not currently used, let's create a lease for it
+            Lease6Ptr lease = createLease(subnet, duid, iaid, hint, fake_allocation);
+
+            // It can happen that the lease allocation failed (we could have lost
+            // the race condition. That means that the hint is lo longer usable and
+            // we need to continue the regular allocation path.
+            if (lease) {
+                return (lease);
+            }
+        }
+    }
+
+    unsigned int i = attempts_;
+    do {
+        IOAddress candidate = allocator_->pickAddress(subnet, duid, hint);
+
+        /// @todo: check if the address is reserved once we have host support
+        /// implemented
+
+        Lease6Ptr existing = LeaseMgrFactory::instance().getLease6(candidate);
+        // there's no existing lease for selected candidate, so it is
+        // free. Let's allocate it.
+        if (!existing) {
+            Lease6Ptr lease = createLease(subnet, duid, iaid, candidate,
+                                          fake_allocation);
+            if (lease) {
+                return (lease);
+            }
+
+            // Although the address was free just microseconds ago, it may have
+            // been taken just now. If the lease insertion fails, we continue
+            // allocation attempts.
+        }
+
+        // continue trying allocation until we run out of attempts
+        // (or attempts are set to 0, which means infinite)
+        --i;
+    } while ( i || !attempts_);
+
+    isc_throw(AllocFailed, "Failed to allocate address after " << attempts_
+              << " tries");
+}
+
+Lease6Ptr AllocEngine::createLease(const Subnet6Ptr& subnet,
+                                   const DuidPtr& duid,
+                                   uint32_t iaid,
+                                   const IOAddress& addr,
+                                   bool fake_allocation /*= false */ ) {
+
+    Lease6Ptr lease(new Lease6(Lease6::LEASE_IA_NA, addr, duid, iaid,
+                               subnet->getPreferred(), subnet->getValid(),
+                               subnet->getT1(), subnet->getT2(), subnet->getID()));
+
+    if (!fake_allocation) {
+        // That is a real (REQUEST) allocation
+        bool status = LeaseMgrFactory::instance().addLease(lease);
+
+        if (status) {
+
+            return (lease);
+        } else {
+            // One of many failures with LeaseMgr (e.g. lost connection to the
+            // database, database failed etc.). One notable case for that
+            // is that we are working in multi-process mode and we lost a race
+            // (some other process got that address first)
+            return (Lease6Ptr());
+        }
+    } else {
+        // That is only fake (SOLICIT without rapid-commit) allocation
+
+        // It is for advertise only. We should not insert the lease into LeaseMgr,
+        // but rather check that we could have inserted it.
+        Lease6Ptr existing = LeaseMgrFactory::instance().getLease6(addr);
+        if (!existing) {
+            return (lease);
+        } else {
+            return (Lease6Ptr());
+        }
+    }
+}
+
+AllocEngine::~AllocEngine() {
+    // no need to delete allocator. smart_ptr will do the trick for us
+}
+
+}; // end of isc::dhcp namespace
+}; // end of isc namespace
diff --git a/src/lib/dhcpsrv/alloc_engine.h b/src/lib/dhcpsrv/alloc_engine.h
new file mode 100644
index 0000000..940b1f4
--- /dev/null
+++ b/src/lib/dhcpsrv/alloc_engine.h
@@ -0,0 +1,229 @@
+// 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 ALLOC_ENGINE_H
+#define ALLOC_ENGINE_H
+
+#include <asiolink/io_address.h>
+#include <dhcp/duid.h>
+#include <dhcpsrv/subnet.h>
+#include <dhcpsrv/lease_mgr.h>
+
+#include <boost/shared_ptr.hpp>
+#include <boost/noncopyable.hpp>
+
+namespace isc {
+namespace dhcp {
+
+/// An exception that is thrown when allocation module fails (e.g. due to
+/// lack of available addresses)
+class AllocFailed : public isc::Exception {
+public:
+
+    /// @brief constructor
+    ///
+    /// @param file name of the file, where exception occurred
+    /// @param line line of the file, where exception occurred
+    /// @param what text description of the issue that caused exception
+    AllocFailed(const char* file, size_t line, const char* what)
+        : isc::Exception(file, line, what) {}
+};
+
+/// @brief DHCPv4 and DHCPv6 allocation engine
+///
+/// This class represents DHCP allocation engine. It is responsible
+/// for picking subnets, choosing and allocating a lease, extending,
+/// renewing, releasing and possibly expiring leases.
+///
+/// @todo: Does not handle out of leases well
+/// @todo: Does not handle out of allocation attempts well
+class AllocEngine : public boost::noncopyable {
+protected:
+
+    /// @brief base class for all address/prefix allocation algorithms
+    ///
+    /// This is an abstract class that should not be used directly, but rather
+    /// specialized implementations should be used instead.
+    class Allocator {
+    public:
+
+        /// @brief picks one address out of available pools in a given subnet
+        ///
+        /// This method returns one address from the available pools in the
+        /// specified subnet. It should not check if the address is used or
+        /// reserved - AllocEngine will check that and will call pickAddress
+        /// again if necessary. The number of times this method is called will
+        /// increase as the number of available leases will decrease.
+        virtual isc::asiolink::IOAddress
+        pickAddress(const Subnet6Ptr& subnet, const DuidPtr& duid,
+                    const isc::asiolink::IOAddress& hint) = 0;
+
+        /// @brief virtual destructor
+        virtual ~Allocator() {
+        }
+    protected:
+    };
+
+    /// @brief Address/prefix allocator that iterates over all addresses
+    ///
+    /// This class implements iterative algorithm that returns all addresses in
+    /// a pool iteratively, one after another. Once the last address is reached,
+    /// it starts allocating from the beginning of the first pool (i.e. it loops
+    /// over).
+    class IterativeAllocator : public Allocator {
+    public:
+
+        /// @brief default constructor
+        ///
+        /// Does not do anything
+        IterativeAllocator();
+
+        /// @brief returns the next address from pools in a subnet
+        ///
+        /// @param subnet next address will be returned from pool of that subnet
+        /// @param duid Client's DUID (ignored)
+        /// @param hint client's hint (ignored)
+        /// @return the next address
+        virtual isc::asiolink::IOAddress
+            pickAddress(const Subnet6Ptr& subnet,
+                        const DuidPtr& duid,
+                        const isc::asiolink::IOAddress& hint);
+    private:
+
+        /// @brief returns an address by one
+        /// @param addr address to be increased
+        /// @return address increased by one
+        isc::asiolink::IOAddress increaseAddress(const isc::asiolink::IOAddress& addr);
+
+    };
+
+    /// @brief Address/prefix allocator that gets an address based on a hash
+    ///
+    /// @todo: This is a skeleton class for now and is missing implementation.
+    class HashedAllocator : public Allocator {
+    public:
+
+        /// @brief default constructor (does nothing)
+        HashedAllocator();
+
+        /// @brief returns an address based on hash calculated from client's DUID.
+        ///
+        /// @todo: Implement this method
+        ///
+        /// @param subnet an address will be picked from pool of that subnet
+        /// @param duid Client's DUID
+        /// @param hint a hint (last address that was picked)
+        /// @return selected address
+        virtual isc::asiolink::IOAddress pickAddress(const Subnet6Ptr& subnet,
+                                                     const DuidPtr& duid,
+                                                     const isc::asiolink::IOAddress& hint);
+    };
+
+    /// @brief Random allocator that picks address randomly
+    ///
+    /// @todo: This is a skeleton class for now and is missing implementation.
+    class RandomAllocator : public Allocator {
+    public:
+
+        /// @brief default constructor (does nothing)
+        RandomAllocator();
+
+        /// @brief returns an random address from pool of specified subnet
+        ///
+        /// @todo: Implement this method
+        ///
+        /// @param subnet an address will be picked from pool of that subnet
+        /// @param duid Client's DUID (ignored)
+        /// @param hint the last address that was picked (ignored)
+        /// @return a random address from the pool
+        virtual isc::asiolink::IOAddress
+        pickAddress(const Subnet6Ptr& subnet, const DuidPtr& duid,
+                    const isc::asiolink::IOAddress& hint);
+    };
+
+    public:
+
+    /// @brief specifies allocation type
+    typedef enum {
+        ALLOC_ITERATIVE, // iterative - one address after another
+        ALLOC_HASHED,    // hashed - client's DUID/client-id is hashed
+        ALLOC_RANDOM     // random - an address is randomly selected
+    } AllocType;
+
+
+    /// @brief Default constructor.
+    ///
+    /// Instantiates necessary services, required to run DHCPv6 server.
+    /// In particular, creates IfaceMgr that will be responsible for
+    /// network interaction. Will instantiate lease manager, and load
+    /// old or create new DUID.
+    ///
+    /// @param engine_type selects allocation algorithm
+    /// @param attempts number of attempts for each lease allocation before
+    ///        we give up (0 means unlimited)
+    AllocEngine(AllocType engine_type, unsigned int attempts);
+
+    /// @brief Allocates an IPv6 lease
+    ///
+    /// This method uses currently selected allocator to pick an address from
+    /// specified subnet, creates a lease for that address and then inserts
+    /// it into LeaseMgr (if this allocation is not fake).
+    ///
+    /// @param subnet subnet the allocation should come from
+    /// @param duid Client'd DUID
+    /// @param iaid iaid field from the IA_NA container that client sent
+    /// @param hint a hint that the client provided
+    /// @param fake_allocation is this real i.e. REQUEST (false) or just picking
+    ///        an address for SOLICIT that is not really allocated (true)
+    /// @return Allocated IPv6 lease (or NULL if allocation failed)
+    Lease6Ptr
+    allocateAddress6(const Subnet6Ptr& subnet,
+                     const DuidPtr& duid,
+                     uint32_t iaid,
+                     const isc::asiolink::IOAddress& hint,
+                     bool fake_allocation);
+
+    /// @brief Destructor. Used during DHCPv6 service shutdown.
+    virtual ~AllocEngine();
+private:
+
+    /// @brief creates a lease and inserts it in LeaseMgr if necessary
+    ///
+    /// Creates a lease based on specified parameters and tries to insert it
+    /// into the database. That may fail in some cases, i.e. when there is another
+    /// allocation process and we lost a race to a specific lease.
+    ///
+    /// @param subnet subnet the lease is allocated from
+    /// @param duid client's DUID
+    /// @param iaid IAID from the IA_NA container the client sent to us
+    /// @param addr an address that was selected and is confirmed to be available
+    /// @param fake_allocation is this real i.e. REQUEST (false) or just picking
+    ///        an address for SOLICIT that is not really allocated (true)
+    /// @return allocated lease (or NULL in the unlikely case of the lease just
+    ///        becomed unavailable)
+    Lease6Ptr createLease(const Subnet6Ptr& subnet, const DuidPtr& duid,
+                          uint32_t iaid, const isc::asiolink::IOAddress& addr,
+                          bool fake_allocation = false);
+
+    /// @brief a pointer to currently used allocator
+    boost::shared_ptr<Allocator> allocator_;
+
+    /// @brief number of attempts before we give up lease allocation (0=unlimited)
+    unsigned int attempts_;
+};
+
+}; // namespace isc::dhcp
+}; // namespace isc
+
+#endif // ALLOC_ENGINE_H
diff --git a/src/lib/dhcpsrv/cfgmgr.cc b/src/lib/dhcpsrv/cfgmgr.cc
new file mode 100644
index 0000000..3c46b13
--- /dev/null
+++ b/src/lib/dhcpsrv/cfgmgr.cc
@@ -0,0 +1,111 @@
+// 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 <dhcpsrv/cfgmgr.h>
+
+using namespace isc::asiolink;
+using namespace isc::util;
+
+namespace isc {
+namespace dhcp {
+
+
+
+
+CfgMgr&
+CfgMgr::instance() {
+    static CfgMgr cfg_mgr;
+    return (cfg_mgr);
+}
+
+Subnet6Ptr
+CfgMgr::getSubnet6(const isc::asiolink::IOAddress& hint) {
+
+    // If there's only one subnet configured, let's just use it
+    // The idea is to keep small deployments easy. In a small network - one
+    // router that also runs DHCPv6 server. Users specifies a single pool and
+    // expects it to just work. Without this, the server would complain that it
+    // doesn't have IP address on its interfaces that matches that
+    // configuration. Such requirement makes sense in IPv4, but not in IPv6.
+    // The server does not need to have a global address (using just link-local
+    // is ok for DHCPv6 server) from the pool it serves.
+    if ((subnets6_.size() == 1) && hint.getAddress().to_v6().is_link_local()) {
+        return (subnets6_[0]);
+    }
+
+    // If there is more than one, we need to choose the proper one
+    for (Subnet6Collection::iterator subnet = subnets6_.begin();
+         subnet != subnets6_.end(); ++subnet) {
+        if ((*subnet)->inRange(hint)) {
+            return (*subnet);
+        }
+    }
+
+    // sorry, we don't support that subnet
+    return (Subnet6Ptr());
+}
+
+Subnet6Ptr CfgMgr::getSubnet6(OptionPtr /*interfaceId*/) {
+    /// @todo: Implement get subnet6 by interface-id (for relayed traffic)
+    isc_throw(NotImplemented, "Relayed DHCPv6 traffic is not supported yet.");
+}
+
+void CfgMgr::addSubnet6(const Subnet6Ptr& subnet) {
+    /// @todo: Check that this new subnet does not cross boundaries of any
+    /// other already defined subnet.
+    subnets6_.push_back(subnet);
+}
+
+Subnet4Ptr
+CfgMgr::getSubnet4(const isc::asiolink::IOAddress& hint) {
+
+    // If there's only one subnet configured, let's just use it
+    // The idea is to keep small deployments easy. In a small network - one
+    // router that also runs DHCPv6 server. Users specifies a single pool and
+    // expects it to just work. Without this, the server would complain that it
+    // doesn't have IP address on its interfaces that matches that
+    // configuration. Such requirement makes sense in IPv4, but not in IPv6.
+    // The server does not need to have a global address (using just link-local
+    // is ok for DHCPv6 server) from the pool it serves.
+    if (subnets4_.size() == 1) {
+        return (subnets4_[0]);
+    }
+
+    // If there is more than one, we need to choose the proper one
+    for (Subnet4Collection::iterator subnet = subnets4_.begin();
+         subnet != subnets4_.end(); ++subnet) {
+        if ((*subnet)->inRange(hint)) {
+            return (*subnet);
+        }
+    }
+
+    // sorry, we don't support that subnet
+    return (Subnet4Ptr());
+}
+
+void CfgMgr::addSubnet4(const Subnet4Ptr& subnet) {
+    /// @todo: Check that this new subnet does not cross boundaries of any
+    /// other already defined subnet.
+    subnets4_.push_back(subnet);
+}
+
+CfgMgr::CfgMgr() {
+}
+
+CfgMgr::~CfgMgr() {
+}
+
+}; // end of isc::dhcp namespace
+}; // end of isc namespace
diff --git a/src/lib/dhcpsrv/cfgmgr.h b/src/lib/dhcpsrv/cfgmgr.h
new file mode 100644
index 0000000..5bff64a
--- /dev/null
+++ b/src/lib/dhcpsrv/cfgmgr.h
@@ -0,0 +1,167 @@
+// 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 CFGMGR_H
+#define CFGMGR_H
+
+#include <asiolink/io_address.h>
+#include <dhcp/option.h>
+#include <dhcpsrv/pool.h>
+#include <dhcpsrv/subnet.h>
+#include <util/buffer.h>
+
+#include <boost/shared_ptr.hpp>
+#include <boost/noncopyable.hpp>
+
+#include <map>
+#include <string>
+#include <vector>
+
+namespace isc {
+namespace dhcp {
+
+
+/// @brief Configuration Manager
+///
+/// This singleton class holds the whole configuration for DHCPv4 and DHCPv6
+/// servers. It currently holds information about zero or more subnets6.
+/// Each subnet may contain zero or more pools. Pool4 and Pool6 is the most
+/// basic "chunk" of configuration. It contains a range of assigneable
+/// addresses.
+///
+/// Below is a sketch of configuration inheritance (not implemented yet).
+/// Let's investigate the following configuration:
+///
+/// preferred-lifetime 500;
+/// valid-lifetime 1000;
+/// subnet6 2001:db8:1::/48 {
+///     pool6 2001::db8:1::1 - 2001::db8:1::ff;
+/// };
+/// subnet6 2001:db8:2::/48 {
+///     valid-lifetime 2000;
+///     pool6 2001::db8:2::1 - 2001::db8:2::ff;
+/// };
+/// Parameters defined in a global scope are applicable to everything until
+/// they are overwritten in a smaller scope, in this case subnet6.
+/// In the example above, the first subnet6 has preferred lifetime of 500s
+/// and a valid lifetime of 1000s. The second subnet has preferred lifetime
+/// of 500s, but valid lifetime of 2000s.
+///
+/// Parameter inheritance is likely to be implemented in configuration handling
+/// routines, so there is no storage capability in a global scope for
+/// subnet-specific parameters.
+///
+/// @todo: Implement Subnet4 support (ticket #2237)
+/// @todo: Implement option definition support
+/// @todo: Implement parameter inheritance
+class CfgMgr : public boost::noncopyable {
+public:
+
+    /// @brief returns a single instance of Configuration Manager
+    ///
+    /// CfgMgr is a singleton and this method is the only way of
+    /// accessing it.
+    static CfgMgr& instance();
+
+    /// @brief get IPv6 subnet by address
+    ///
+    /// Finds a matching subnet, based on an address. This can be used
+    /// in two cases: when trying to find an appropriate lease based on
+    /// a) relay link address (that must be the address that is on link)
+    /// b) our global address on the interface the message was received on
+    ///    (for directly connected clients)
+    ///
+    /// @param hint an address that belongs to a searched subnet
+    Subnet6Ptr getSubnet6(const isc::asiolink::IOAddress& hint);
+
+    /// @brief get IPv6 subnet by interface-id
+    ///
+    /// Another possibility to find a subnet is based on interface-id.
+    ///
+    /// @param interface_id content of interface-id option returned by a relay
+    /// @todo This method is not currently supported.
+    Subnet6Ptr getSubnet6(OptionPtr interface_id);
+
+    /// @brief adds an IPv6 subnet
+    void addSubnet6(const Subnet6Ptr& subnet);
+
+    /// @todo: Add subnet6 removal routines. Currently it is not possible
+    /// to remove subnets. The only case where subnet6 removal would be
+    /// needed is a dynamic server reconfiguration - a use case that is not
+    /// planned to be supported any time soon.
+
+    /// @brief removes all subnets
+    ///
+    /// This method removes all existing subnets. It is used during
+    /// reconfiguration - old configuration is wiped and new definitions
+    /// are used to recreate subnets.
+    ///
+    /// @todo Implement more intelligent approach. Note that comparison
+    /// between old and new configuration is tricky. For example: is
+    /// 2000::/64 and 2000::/48 the same subnet or is it something
+    /// completely new?
+    void deleteSubnets6() {
+        subnets6_.clear();
+    }
+
+    /// @brief get IPv4 subnet by address
+    ///
+    /// Finds a matching subnet, based on an address. This can be used
+    /// in two cases: when trying to find an appropriate lease based on
+    /// a) relay link address (that must be the address that is on link)
+    /// b) our global address on the interface the message was received on
+    ///    (for directly connected clients)
+    ///
+    /// @param hint an address that belongs to a searched subnet
+    Subnet4Ptr getSubnet4(const isc::asiolink::IOAddress& hint);
+
+    /// @brief adds a subnet4
+    void addSubnet4(const Subnet4Ptr& subnet);
+
+    /// @brief removes all IPv4 subnets
+    void removeSubnets4();
+protected:
+
+    /// @brief Protected constructor.
+    ///
+    /// This constructor is protected for 2 reasons. First, it forbids any
+    /// instantiations of this class (CfgMgr is a singleton). Second, it
+    /// allows derived class to instantiate it. That is useful for testing
+    /// purposes.
+    CfgMgr();
+
+    /// @brief virtual desctructor
+    virtual ~CfgMgr();
+
+    /// @brief a container for IPv6 subnets.
+    ///
+    /// That is a simple vector of pointers. It does not make much sense to
+    /// optimize access time (e.g. using a map), because typical search
+    /// pattern will use calling inRange() method on each subnet until
+    /// a match is found.
+    Subnet6Collection subnets6_;
+
+    /// @brief a container for IPv4 subnets.
+    ///
+    /// That is a simple vector of pointers. It does not make much sense to
+    /// optimize access time (e.g. using a map), because typical search
+    /// pattern will use calling inRange() method on each subnet until
+    /// a match is found.
+    Subnet4Collection subnets4_;
+};
+
+} // namespace isc::dhcp
+} // namespace isc
+
+#endif // CFGMGR_H
diff --git a/src/lib/dhcpsrv/database_backends.dox b/src/lib/dhcpsrv/database_backends.dox
new file mode 100644
index 0000000..8eeb5c5
--- /dev/null
+++ b/src/lib/dhcpsrv/database_backends.dox
@@ -0,0 +1,64 @@
+/**
+  @page dhcp-database-backends DHCP Database Back-Ends
+
+  All DHCP lease data is stored in some form of database, the interface
+  to this being through the Lease Manager.
+
+  All backend classes such as isc::dhcp::MySqlLeaseMgr are derived from
+  the abstract isc::dhcp::LeaseMgr class.  This provides methods to
+  create, retrieve, modify and delete leases in the database.
+
+  @section dhcpdb-instantiation Instantiation of Lease Managers
+
+  A lease manager is instantiated through the LeaseMgrFactory class.  This
+  has three methods:
+
+  - isc::dhcp::LeaseMgrFactory::create - Creates a singleton Lease
+    Manager of the appropriate type.
+  - isc::dhcp::LeaseMgrFactory::instance - Returns a reference to the
+    the instance of the Lease Manager.
+  - isc::dhcp::LeaseMgrFactory::destroy - Destroys the singleton lease manager.
+
+  The selection of the Lease Manager (and thus the backend database) is
+  controlled by the connection string passed to
+  isc::dhcp::LeaseMgrFactory::create.  This is a set of "keyword=value" pairs
+  (no embedded spaces), each pair separated by a space from the others, e.g.
+
+  \code
+  type=mysql user=keatest password=keatest name=keatest host=localhost
+  \endcode
+
+  The following keywords are used for all backends:
+
+  - <b>type</b> - specifies the type of database backend.  The following values
+  for the type keyword are supported:
+     - <b>mysql</b> - Use MySQL as the database
+
+  The following sections list the database-specific keywords:
+
+  @subsection dhcpdb-keywords-mysql MySQL connection string keywords
+
+  - <b>host</b> - host on which the selected database is running.  If not
+  supplied, "localhost" is assumed.
+  - <b>name</b> - name of the MySQL database to access.  There is no default -
+  this must always be supplied.
+  - <b>password</b> - password for the selected user ID (see below).  If not
+  specified, no password is used.
+  - <b>user</b> - database user ID under which the database is accessed.  If not
+    specified, no user ID is used - the database is assumed to be open.
+
+
+  @section dhcp-backend-unittest Running Unit Tests
+
+  With the use of databases requiring separate authorisation, there are
+  certain database-specific pre-requisites for successfully running the unit
+  tests.  These are listed in the following sections.
+
+  @subsection dhcp-mysql-unittest MySQL
+
+  A database called <i>keatest</i> needs to be set up using the MySQL
+  <b>CREATE DATABASE</b> command.  A database user, also called <i>keatest</i>
+  (with a password <i>keatest</i>) must be given full privileges in that
+  database.  The unit tests create the schema in the database before each test
+  and delete it afterwards.
+  */
diff --git a/src/lib/dhcpsrv/dhcpdb_create.mysql b/src/lib/dhcpsrv/dhcpdb_create.mysql
new file mode 100644
index 0000000..7a292ec
--- /dev/null
+++ b/src/lib/dhcpsrv/dhcpdb_create.mysql
@@ -0,0 +1,115 @@
+# Copyright (C) 2012  Internet Systems Consortium.
+#
+# Permission to use, copy, modify, and 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 INTERNET SYSTEMS CONSORTIUM
+# DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
+# INTERNET SYSTEMS CONSORTIUM 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.
+
+# This is the BIND 10 DHCP schema specification for MySQL.
+#
+# The schema is reasonably portable (with the exception of the engine
+# specification, which is MySQL-specific).  Minor changes might be needed for
+# other databases.
+
+# To create the schema, either type the command:
+#
+# mysql -u <user> -p <password> <database> < dhcpdb_create.mysql
+#
+# ... at the command prompt, or log in to the MySQL database and at the "mysql>"
+# prompt, issue the command:
+#
+# source dhcpdb_create.mysql
+
+
+# Holds the IPv4 leases.
+CREATE TABLE lease4 (
+    address INT UNSIGNED PRIMARY KEY NOT NULL,  # IPv4 address
+    hwaddr VARBINARY(20),                       # Hardware address
+    client_id VARBINARY(128),                   # Client ID
+    lease_time INT UNSIGNED,                    # Length of the lease (seconds)
+    expire TIMESTAMP,                           # Expiration time of the lease
+    subnet_id INT UNSIGNED                      # Subnet identification
+    ) ENGINE = INNODB;
+
+# Holds the IPv6 leases.
+# N.B. The use of a VARCHAR for the address is temporary for development:
+# it will eventually be replaced by BINARY(16).
+CREATE TABLE lease6 (
+    address VARCHAR(40) PRIMARY KEY NOT NULL,   # IPv6 address
+    duid VARBINARY(128),                        # DUID
+    valid_lifetime INT UNSIGNED,                # Length of the lease (seconds)
+    expire TIMESTAMP,                           # Expiration time of the lease
+    subnet_id INT UNSIGNED,                     # Subnet identification
+    pref_lifetime INT UNSIGNED,                 # Preferred lifetime
+    lease_type TINYINT,                         # Lease type (see lease6_types
+                                                #    table for possible values)
+    iaid INT UNSIGNED,                          # See Section 10 of RFC 3315
+    prefix_len TINYINT UNSIGNED                 # For IA_PD only
+    ) ENGINE = INNODB;
+
+# ... and a definition of lease6 types.  This table is a convenience for
+# users of the database - if they want to view the lease table and use the
+# type names, they can join this table with the lease6 table
+CREATE TABLE lease6_types (
+    lease_type TINYINT PRIMARY KEY NOT NULL,    # Lease type code.
+    name VARCHAR(5)                             # Name of the lease type
+    );
+START TRANSACTION;
+INSERT INTO lease6_types VALUES (0, "IA_NA");   # Non-temporary v6 addresses
+INSERT INTO lease6_types VALUES (1, "IA_TA");   # Temporary v6 addresses
+INSERT INTO lease6_types VALUES (2, "IA_PD");   # Prefix delegations
+COMMIT;
+
+# Finally, the version of the schema.  We start at 0.1 during development.
+# This table is only modified during schema upgrades.  For historical reasons
+# (related to the names of the columns in the BIND 10 DNS database file), the
+# first column is called "version" and not "major".
+CREATE TABLE schema_version (
+    version INT PRIMARY KEY NOT NULL,       # Major version number
+    minor INT                               # Minor version number
+    );
+START TRANSACTION;
+INSERT INTO schema_version VALUES (0, 1);
+COMMIT;
+
+# Notes:
+#
+# Indexes
+# =======
+# It is likely that additional indexes will be needed.  However, the
+# increase in lookup performance from these will come at the expense
+# of a decrease in performance during insert operations due to the need
+# to update the indexes.  For this reason, the need for additional indexes
+# will be determined by experiment during performance tests.
+#
+# The most likely additional indexes will cover the following columns:
+#
+# expire
+# To speed up the deletion of expired leases from the database.
+#
+# hwaddr and client_id
+# For lease stability: if a client requests a new lease, try to find an
+# existing or recently expired lease for it so that it can keep using the
+# same IP address.
+#
+# Field Sizes
+# ===========
+# If any of the VARxxx field sizes are altered, the lengths in the MySQL
+# backend source file (mysql_lease_mgr.cc) must be correspondingly changed.
+#
+# Portability
+# ===========
+# The "ENGINE = INNODB" on some tables is not portablea to another database
+# and will need to be removed.
+#
+# Some columns contain binary data so are stored as VARBINARY instead of
+# VARCHAR.  This may be non-portable between databases: in this case, the
+# definition should be changed to VARCHAR.
diff --git a/src/lib/dhcpsrv/lease_mgr.cc b/src/lib/dhcpsrv/lease_mgr.cc
new file mode 100644
index 0000000..5f4dc2f
--- /dev/null
+++ b/src/lib/dhcpsrv/lease_mgr.cc
@@ -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 <dhcpsrv/lease_mgr.h>
+#include <exceptions/exceptions.h>
+
+#include <boost/foreach.hpp>
+#include <boost/algorithm/string.hpp>
+
+#include <algorithm>
+#include <iostream>
+#include <iterator>
+#include <map>
+#include <sstream>
+#include <string>
+
+#include <time.h>
+
+using namespace std;
+
+using namespace isc::dhcp;
+
+Lease6::Lease6(LeaseType type, const isc::asiolink::IOAddress& addr, DuidPtr duid,
+               uint32_t iaid, uint32_t preferred, uint32_t valid, uint32_t t1,
+               uint32_t t2, SubnetID subnet_id, uint8_t prefixlen)
+    :type_(type), addr_(addr), prefixlen_(prefixlen), iaid_(iaid), duid_(duid),
+     preferred_lft_(preferred), valid_lft_(valid), t1_(t1), t2_(t2),
+     subnet_id_(subnet_id), fixed_(false), fqdn_fwd_(false),
+     fqdn_rev_(false) {
+    if (!duid) {
+        isc_throw(InvalidOperation, "DUID must be specified for a lease");
+    }
+
+    cltt_ = time(NULL);
+}
+
+std::string LeaseMgr::getParameter(const std::string& name) const {
+    ParameterMap::const_iterator param = parameters_.find(name);
+    if (param == parameters_.end()) {
+        isc_throw(BadValue, "Parameter not found");
+    }
+    return (param->second);
+}
+
+std::string
+Lease6::toText() {
+    ostringstream stream;
+
+    stream << "Type:          " << static_cast<int>(type_) << " (";
+    switch (type_) {
+        case Lease6::LEASE_IA_NA:
+            stream << "IA_NA)\n";
+            break;
+        case Lease6::LEASE_IA_TA:
+            stream << "IA_TA)\n";
+            break;
+        case Lease6::LEASE_IA_PD:
+            stream << "IA_PD)\n";
+            break;
+        default:
+            stream << "unknown)\n";
+    }
+    stream << "Address:       " << addr_.toText() << "\n"
+           << "Prefix length: " << static_cast<int>(prefixlen_) << "\n"
+           << "IAID:          " << iaid_ << "\n"
+           << "Pref life:     " << preferred_lft_ << "\n"
+           << "Valid life:    " << valid_lft_ << "\n"
+           << "Cltt:          " << cltt_ << "\n"
+           << "Subnet ID:     " << subnet_id_ << "\n";
+
+    return (stream.str());
+}
+
+bool
+Lease6::operator==(const Lease6& other) const {
+    return (
+        type_ == other.type_ &&
+        addr_ == other.addr_ &&
+        prefixlen_ == other.prefixlen_ &&
+        iaid_ == other.iaid_ &&
+        *duid_ == *other.duid_ &&
+        preferred_lft_ == other.preferred_lft_ &&
+        valid_lft_ == other.valid_lft_ &&
+        cltt_ == other.cltt_ &&
+        subnet_id_ == other.subnet_id_
+        );
+}
diff --git a/src/lib/dhcpsrv/lease_mgr.h b/src/lib/dhcpsrv/lease_mgr.h
new file mode 100644
index 0000000..0e1f8d8
--- /dev/null
+++ b/src/lib/dhcpsrv/lease_mgr.h
@@ -0,0 +1,577 @@
+// 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 LEASE_MGR_H
+#define LEASE_MGR_H
+
+#include <asiolink/io_address.h>
+#include <dhcp/duid.h>
+#include <dhcp/option.h>
+#include <dhcpsrv/subnet.h>
+#include <exceptions/exceptions.h>
+
+#include <boost/noncopyable.hpp>
+#include <boost/shared_ptr.hpp>
+
+#include <fstream>
+#include <map>
+#include <string>
+#include <utility>
+#include <vector>
+
+/// @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.
+
+#include <iostream>
+
+namespace isc {
+namespace dhcp {
+
+/// @brief Exception thrown if name of database is not specified
+class NoDatabaseName : public Exception {
+public:
+    NoDatabaseName(const char* file, size_t line, const char* what) :
+        isc::Exception(file, line, what) {}
+};
+
+/// @brief Exception thrown on failure to open database
+class DbOpenError : public Exception {
+public:
+    DbOpenError(const char* file, size_t line, const char* what) :
+        isc::Exception(file, line, what) {}
+};
+
+/// @brief Exception thrown on failure to execute a database function
+class DbOperationError : public Exception {
+public:
+    DbOperationError(const char* file, size_t line, const char* what) :
+        isc::Exception(file, line, what) {}
+};
+
+/// @brief Attempt to update lease that was not there
+class NoSuchLease : public Exception {
+public:
+    NoSuchLease(const char* file, size_t line, const char* what) :
+        isc::Exception(file, line, what) {}
+};
+
+/// @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 Constructor
+    ///
+    /// Initialize fields that don't have a default constructor.
+    /// @todo Remove this
+    Lease4() : addr_(0) {}
+};
+
+/// @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;
+
+    Lease6(LeaseType type, const isc::asiolink::IOAddress& addr, DuidPtr duid,
+           uint32_t iaid, uint32_t preferred, uint32_t valid, uint32_t t1,
+           uint32_t t2, SubnetID subnet_id, uint8_t prefixlen_ = 0);
+
+    /// @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 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.
+    /// This value will also be useful for failover to calculate the next expected
+    /// client transmission time.
+    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 Constructor
+    ///
+    /// Initialize fields that don't have a default constructor.
+    Lease6() : addr_("::") {}
+
+    /// @brief Convert Lease6 to Printable Form
+    ///
+    /// @return String form of the lease
+    std::string toText();
+
+    /// @brief Compare two leases for equality
+    ///
+    /// @param other lease6 object with which to compare
+    bool operator==(const Lease6& other) const;
+
+    /// @brief Compare two leases for inequality
+    ///
+    /// @param other lease6 object with which to compare
+    bool operator!=(const Lease6& other) const {
+        return (!operator==(other));
+    }
+
+};
+
+/// @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<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.
+///
+/// As all methods are virtual, this class throws no exceptions.  However,
+/// methods in concrete implementations of this class may throw exceptions:
+/// see the documentation of those classes for details.
+class LeaseMgr {
+public:
+    /// Client Hardware address
+    typedef std::vector<uint8_t> HWAddr;
+
+    /// Database configuration parameter map
+    typedef std::map<std::string, std::string> ParameterMap;
+
+    /// @brief Constructor
+    ///
+    /// @param parameters A data structure relating keywords and values
+    ///        concerned with the database.
+    LeaseMgr(const ParameterMap& parameters) : parameters_(parameters)
+    {}
+
+    /// @brief Destructor
+    virtual ~LeaseMgr()
+    {}
+
+    /// @brief Adds an IPv4 lease.
+    ///
+    /// @param lease lease to be added
+    ///
+    /// @result true if the lease was added, false if not (because a lease
+    ///         with the same address was already there).
+    virtual bool addLease(const Lease4Ptr& lease) = 0;
+
+    /// @brief Adds an IPv6 lease.
+    ///
+    /// @param lease lease to be added
+    ///
+    /// @result true if the lease was added, false if not (because a lease
+    ///         with the same address was already there).
+    virtual bool addLease(const Lease6Ptr& lease) = 0;
+
+    /// @brief Returns 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(const 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
+    ///
+    /// @return smart pointer to the lease (or NULL if a lease is not found)
+    virtual Lease4Ptr getLease4(const 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(const 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(const Lease4Ptr& lease4) = 0;
+
+    /// @brief Updates IPv6 lease.
+    ///
+    /// @param lease6 The lease to be updated.
+    virtual void updateLease6(const 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(const isc::asiolink::IOAddress& addr) = 0;
+
+    /// @brief Deletes a lease.
+    ///
+    /// @param addr IPv6 address of the lease to be deleted.
+    ///
+    /// @return true if deletion was successful, false if no such lease exists
+    virtual bool deleteLease6(const isc::asiolink::IOAddress& addr) = 0;
+
+    /// @brief Return backend type
+    ///
+    /// Returns the type of the backend (e.g. "mysql", "memfile" etc.)
+    ///
+    /// @return Type of the backend.
+    virtual std::string getType() const = 0;
+
+    /// @brief Returns backend name.
+    ///
+    /// If the backend is a database, this is the name of the database or the
+    /// file.  Otherwise it is just the same as the type.
+    ///
+    /// @return Name of the backend.
+    virtual std::string getName() const = 0;
+
+    /// @brief Returns description of the backend.
+    ///
+    /// This description may be multiline text that describes the backend.
+    ///
+    /// @return Description of the backend.
+    virtual std::string getDescription() const = 0;
+
+    /// @brief Returns backend version.
+    ///
+    /// @return Version number as a pair of unsigned integers.  "first" is the
+    ///         major version number, "second" the minor number.
+    ///
+    /// @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::pair<uint32_t, uint32_t> getVersion() const = 0;
+
+    /// @brief Commit Transactions
+    ///
+    /// Commits all pending database operations.  On databases that don't
+    /// support transactions, this is a no-op.
+    virtual void commit() = 0;
+
+    /// @brief Rollback Transactions
+    ///
+    /// Rolls back all pending database operations.  On databases that don't
+    /// support transactions, this is a no-op.
+    virtual void rollback() = 0;
+
+    /// @todo: Add host management here
+    /// As host reservation is outside of scope for 2012, support for hosts
+    /// is currently postponed.
+
+    /// @brief returns value of the parameter
+    virtual std::string getParameter(const std::string& name) const;
+
+private:
+    /// @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.
+    ParameterMap parameters_;
+};
+
+}; // end of isc::dhcp namespace
+}; // end of isc namespace
+
+#endif // LEASE_MGR_H
diff --git a/src/lib/dhcpsrv/lease_mgr_factory.cc b/src/lib/dhcpsrv/lease_mgr_factory.cc
new file mode 100644
index 0000000..47c53ed
--- /dev/null
+++ b/src/lib/dhcpsrv/lease_mgr_factory.cc
@@ -0,0 +1,117 @@
+// 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 "config.h"
+
+#include <dhcpsrv/lease_mgr_factory.h>
+#include <dhcpsrv/memfile_lease_mgr.h>
+#ifdef HAVE_MYSQL
+#include <dhcpsrv/mysql_lease_mgr.h>
+#endif
+
+#include <boost/algorithm/string.hpp>
+#include <boost/foreach.hpp>
+#include <boost/scoped_ptr.hpp>
+
+#include <algorithm>
+#include <iostream>
+#include <iterator>
+#include <map>
+#include <sstream>
+#include <utility>
+
+using namespace std;
+
+namespace isc {
+namespace dhcp {
+
+boost::scoped_ptr<LeaseMgr>&
+LeaseMgrFactory::getLeaseMgrPtr() {
+    static boost::scoped_ptr<LeaseMgr> leaseMgrPtr;
+    return (leaseMgrPtr);
+}
+
+LeaseMgr::ParameterMap
+LeaseMgrFactory::parse(const std::string& dbconfig) {
+    LeaseMgr::ParameterMap mapped_tokens;
+
+    if (!dbconfig.empty()) {
+        vector<string> tokens;
+
+        // We need to pass a string to is_any_of, not just char*. Otherwise
+        // there are cryptic warnings on Debian6 running g++ 4.4 in
+        // /usr/include/c++/4.4/bits/stl_algo.h:2178 "array subscript is above
+        // array bounds"
+        boost::split(tokens, dbconfig, boost::is_any_of( string("\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);
+                mapped_tokens.insert(make_pair(name, value));
+            } else {
+                isc_throw(InvalidParameter, "Cannot parse " << token
+                          << ", expected format is name=value");
+            }
+        }
+    }
+
+    return (mapped_tokens);
+}
+
+void
+LeaseMgrFactory::create(const std::string& dbconfig) {
+    const std::string type = "type";
+
+    // Is "type" present?
+    LeaseMgr::ParameterMap parameters = parse(dbconfig);
+    if (parameters.find(type) == parameters.end()) {
+        isc_throw(InvalidParameter, "Database configuration parameters do not "
+                  "contain the 'type' keyword");
+    }
+
+    // Yes, check what it is.
+#ifdef HAVE_MYSQL
+    if (parameters[type] == string("mysql")) {
+        getLeaseMgrPtr().reset(new MySqlLeaseMgr(parameters));
+        return;
+    }
+#endif
+    if (parameters[type] == string("memfile")) {
+        getLeaseMgrPtr().reset(new Memfile_LeaseMgr(parameters));
+        return;
+    }
+
+    // Get here on no match
+    isc_throw(InvalidType, "Database configuration parameter 'type' does "
+              "not specify a supported database backend");
+}
+
+void
+LeaseMgrFactory::destroy() {
+    getLeaseMgrPtr().reset();
+}
+
+LeaseMgr&
+LeaseMgrFactory::instance() {
+    LeaseMgr* lmptr = getLeaseMgrPtr().get();
+    if (lmptr == NULL) {
+        isc_throw(NoLeaseManager, "no current lease manager is available");
+    }
+    return (*lmptr);
+}
+
+
+}; // namespace dhcp
+}; // namespace isc
diff --git a/src/lib/dhcpsrv/lease_mgr_factory.h b/src/lib/dhcpsrv/lease_mgr_factory.h
new file mode 100644
index 0000000..338c941
--- /dev/null
+++ b/src/lib/dhcpsrv/lease_mgr_factory.h
@@ -0,0 +1,124 @@
+// 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 LEASE_MGR_FACTORY_H
+#define LEASE_MGR_FACTORY_H
+
+#include <dhcpsrv/lease_mgr.h>
+#include <exceptions/exceptions.h>
+
+#include <string>
+
+namespace isc {
+namespace dhcp {
+
+/// @brief Invalid type exception
+///
+/// Thrown when the factory doesn't recognise the type of the backend.
+class InvalidType : public Exception {
+public:
+    InvalidType(const char* file, size_t line, const char* what) :
+        isc::Exception(file, line, what) {}
+};
+
+/// @brief No lease manager exception
+///
+/// Thrown if an attempt is made to get a reference to the current lease
+/// manager and none is currently available.
+class NoLeaseManager : public Exception {
+public:
+    NoLeaseManager(const char* file, size_t line, const char* what) :
+        isc::Exception(file, line, what) {}
+};
+
+/// @brief Lease Manager Factory
+///
+/// This class comprises nothing but static methods used to create a lease
+/// manager.  It analyzes the database information passed to the creation
+/// function and instantiates an appropriate lease manager based on the type
+/// requested.
+///
+/// Strictly speaking these functions could be stand-alone functions.  However,
+/// it is convenient to encapsulate them in a class for naming purposes.
+///
+/// @todo: Will need to develop some form of registration mechanism for
+///        user-supplied backends (so that there is no need to modify the code).
+class LeaseMgrFactory {
+public:
+    /// @brief Create an instance of a lease manager.
+    ///
+    /// Each database backend has its own lease manager type.  This static
+    /// method sets the "current" lease manager to be a manager of the
+    /// appropriate type.  The actual lease manager is returned by the
+    /// "instance" method.
+    ///
+    /// @note When called, the current lease manager is <b>always</b> destroyed
+    ///       and a new one created - even if the parameters are the same.
+    ///
+    /// dbconfig is a generic way of passing parameters. Parameters are passed
+    /// in the "name=value" format, separated by spaces.  The data MUST include
+    /// a keyword/value pair of the form "type=dbtype" giving the database
+    /// type, e.q. "mysql" or "sqlite3".
+    ///
+    /// @param dbconfig Database configuration parameters.  These are in
+    ///        the form of "keyword=value" pairs, separated by spaces. These
+    ///        are back-end specific, although must include the "type" keyword
+    ///        which gives the backend in use.
+    ///
+    /// @throw isc::InvalidParameter dbconfig string does not contain the "type"
+    ///        keyword.
+    /// @throw isc::dhcp::InvalidType The "type" keyword in dbconfig does not
+    ///        identify a supported backend.
+    static void create(const std::string& dbconfig);
+
+    /// @brief Destroy lease manager
+    ///
+    /// Destroys the current lease manager object.  This should have the effect
+    /// of closing the database connection.  The method is a no-op if no
+    /// lease manager is available.
+    static void destroy();
+
+    /// @brief Return Current Lease Manager
+    ///
+    /// Returns an instance of the "current" lease manager.  An exception
+    /// will be thrown if none is available.
+    ///
+    /// @throw isc::dhcp::NoLeaseManager No lease manager is available: use
+    ///        create() to create one before calling this method.
+    static LeaseMgr& instance();
+
+    /// @brief Parse Database Parameters
+    ///
+    /// Parses the string of "keyword=value" pairs and separates them
+    /// out into the map.
+    ///
+    /// @param dbconfig Database configuration string
+    ///
+    /// @return std::map<std::string, std::string> Map of keyword/value pairs.
+    static LeaseMgr::ParameterMap parse(const std::string& dbconfig);
+
+private:
+    /// @brief Hold pointer to lease manager
+    ///
+    /// Holds a pointer to the singleton lease manager.  The singleton
+    /// is encapsulated in this method to avoid a "static initialization
+    /// fiasco" if defined in an external static variable.
+    static boost::scoped_ptr<LeaseMgr>& getLeaseMgrPtr();
+
+};
+
+}; // end of isc::dhcp namespace
+}; // end of isc namespace
+
+#endif // LEASE_MGR_FACTORY_H
diff --git a/src/lib/dhcpsrv/memfile_lease_mgr.cc b/src/lib/dhcpsrv/memfile_lease_mgr.cc
new file mode 100644
index 0000000..8a59b73
--- /dev/null
+++ b/src/lib/dhcpsrv/memfile_lease_mgr.cc
@@ -0,0 +1,132 @@
+// 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 <dhcpsrv/memfile_lease_mgr.h>
+
+#include <iostream>
+
+using namespace isc::dhcp;
+
+Memfile_LeaseMgr::Memfile_LeaseMgr(const ParameterMap& parameters)
+    : LeaseMgr(parameters) {
+    std::cout << "Warning: Using memfile database backend. It is usable for" << std::endl;
+    std::cout << "Warning: limited testing only. File support not implemented yet." << std::endl;
+    std::cout << "Warning: Leases will be lost after restart." << std::endl;
+}
+
+Memfile_LeaseMgr::~Memfile_LeaseMgr() {
+}
+
+bool Memfile_LeaseMgr::addLease(const Lease4Ptr&) {
+    return (false);
+}
+
+bool Memfile_LeaseMgr::addLease(const Lease6Ptr& lease) {
+    if (getLease6(lease->addr_)) {
+        // there is a lease with specified address already
+        return (false);
+    }
+    storage6_.insert(lease);
+    return (true);
+}
+
+Lease4Ptr Memfile_LeaseMgr::getLease4(const isc::asiolink::IOAddress&) const {
+    return (Lease4Ptr());
+}
+
+Lease4Collection Memfile_LeaseMgr::getLease4(const HWAddr& ) const {
+    return (Lease4Collection());
+}
+
+Lease4Ptr Memfile_LeaseMgr::getLease4(const 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(const isc::asiolink::IOAddress& addr) const {
+    Lease6Storage::iterator l = storage6_.find(addr);
+    if (l == storage6_.end()) {
+        return (Lease6Ptr());
+    } else {
+        return (*l);
+    }
+}
+
+Lease6Collection Memfile_LeaseMgr::getLease6(const DUID& , uint32_t ) const {
+    return (Lease6Collection());
+}
+
+Lease6Ptr Memfile_LeaseMgr::getLease6(const DUID& duid, uint32_t iaid,
+                                      SubnetID subnet_id) const {
+    /// @todo: Slow, naive implementation. Write it using additional indexes
+    for (Lease6Storage::iterator l = storage6_.begin(); l != storage6_.end(); ++l) {
+        if ( (*((*l)->duid_) == duid) &&
+             ( (*l)->iaid_ == iaid) &&
+             ( (*l)->subnet_id_ == subnet_id)) {
+            return (*l);
+        }
+    }
+    return (Lease6Ptr());
+}
+
+void Memfile_LeaseMgr::updateLease4(const Lease4Ptr& ) {
+}
+
+void Memfile_LeaseMgr::updateLease6(const Lease6Ptr& ) {
+
+}
+
+bool Memfile_LeaseMgr::deleteLease4(const isc::asiolink::IOAddress&) {
+    return (false);
+}
+
+bool Memfile_LeaseMgr::deleteLease6(const isc::asiolink::IOAddress& addr) {
+    Lease6Storage::iterator l = storage6_.find(addr);
+    if (l == storage6_.end()) {
+        // no such lease
+        return (false);
+    } else {
+        storage6_.erase(l);
+        return (true);
+    }
+}
+
+std::string Memfile_LeaseMgr::getDescription() const {
+    return (std::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."));
+}
+
+void
+Memfile_LeaseMgr::commit() {
+}
+
+void
+Memfile_LeaseMgr::rollback() {
+}
diff --git a/src/lib/dhcpsrv/memfile_lease_mgr.h b/src/lib/dhcpsrv/memfile_lease_mgr.h
new file mode 100644
index 0000000..d9b40e5
--- /dev/null
+++ b/src/lib/dhcpsrv/memfile_lease_mgr.h
@@ -0,0 +1,258 @@
+// 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 MEMFILE_LEASE_MGR_H
+#define MEMFILE_LEASE_MGR_H
+
+#include <dhcpsrv/lease_mgr.h>
+
+#include <boost/multi_index/indexed_by.hpp>
+#include <boost/multi_index/member.hpp>
+#include <boost/multi_index/ordered_index.hpp>
+#include <boost/multi_index_container.hpp>
+
+namespace isc {
+namespace dhcp {
+
+// This is a concrete implementation of a Lease database.
+//
+// It is for testing purposes only. It is NOT a production code.
+//
+// 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 parameters A data structure relating keywords and values
+    ///        concerned with the database.
+    Memfile_LeaseMgr(const ParameterMap& parameters);
+
+    /// @brief Destructor (closes file)
+    virtual ~Memfile_LeaseMgr();
+
+    /// @brief Adds an IPv4 lease.
+    ///
+    /// @todo Not implemented yet
+    /// @param lease lease to be added
+    virtual bool addLease(const Lease4Ptr& lease);
+
+    /// @brief Adds an IPv6 lease.
+    ///
+    /// @param lease lease to be added
+    virtual bool addLease(const Lease6Ptr& lease);
+
+    /// @brief Returns existing IPv4 lease for specified IPv4 address.
+    ///
+    /// @todo Not implemented yet
+    /// @param addr address of the searched lease
+    ///
+    /// @return a collection of leases
+    virtual Lease4Ptr getLease4(const isc::asiolink::IOAddress& addr) const;
+
+    /// @brief Returns existing IPv4 lease for specific address and subnet
+    ///
+    /// @todo Not implemented yet
+    /// @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(const isc::asiolink::IOAddress& addr,
+                                SubnetID subnet_id) const;
+
+    /// @brief Returns existing IPv4 leases for specified hardware address.
+    ///
+    /// @todo Not implemented yet
+    ///
+    /// 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
+    ///
+    /// @todo Not implemented yet
+    ///
+    /// 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
+    ///
+    /// @todo Not implemented yet
+    ///
+    /// @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.
+    ///
+    /// @todo Not implemented yet
+    ///
+    /// @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)
+    virtual Lease6Ptr getLease6(const isc::asiolink::IOAddress& addr) const;
+
+    /// @brief Returns existing IPv6 lease for a given DUID+IA combination
+    ///
+    /// @todo Not implemented yet
+    ///
+    /// @param duid client DUID
+    /// @param iaid IA identifier
+    ///
+    /// @return collection of IPv6 leases
+    virtual Lease6Collection getLease6(const DUID& duid, uint32_t iaid) const;
+
+    /// @brief Returns existing IPv6 lease for a given DUID+IA combination
+    ///
+    /// @todo Not implemented yet
+    ///
+    /// @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)
+    virtual Lease6Ptr getLease6(const DUID& duid, uint32_t iaid, SubnetID subnet_id) const;
+
+    /// @brief Updates IPv4 lease.
+    ///
+    /// @todo Not implemented yet
+    ///
+    /// @param lease4 The lease to be updated.
+    ///
+    /// If no such lease is present, an exception will be thrown.
+    virtual void updateLease4(const Lease4Ptr& lease4);
+
+    /// @brief Updates IPv4 lease.
+    ///
+    /// @todo Not implemented yet
+    ///
+    /// @param lease6 The lease to be updated.
+    ///
+    /// If no such lease is present, an exception will be thrown.
+    virtual void updateLease6(const 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
+    virtual bool deleteLease4(const isc::asiolink::IOAddress& 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
+    virtual bool deleteLease6(const isc::asiolink::IOAddress& addr);
+
+    /// @brief Return backend type
+    ///
+    /// Returns the type of the backend.
+    ///
+    /// @return Type of the backend.
+    virtual std::string getType() const {
+        return (std::string("memfile"));
+    }
+
+    /// @brief Returns backend name.
+    ///
+    /// As there is no variation, in this case we return the type of the
+    /// backend.
+    ///
+    /// @return Name of the backend.
+    virtual std::string getName() const {
+        return ("memfile");
+    }
+
+    /// @brief Returns description of the backend.
+    ///
+    /// This description may be multiline text that describes the backend.
+    ///
+    /// @return Description of the backend.
+    virtual std::string getDescription() const;
+
+    /// @brief Returns backend version.
+    ///
+    /// @return Version number as a pair of unsigned integers.  "first" is the
+    ///         major version number, "second" the minor number.
+    virtual std::pair<uint32_t, uint32_t> getVersion() const {
+        return (std::make_pair(1, 0));
+    }
+
+    /// @brief Commit Transactions
+    ///
+    /// Commits all pending database operations.  On databases that don't
+    /// support transactions, this is a no-op.
+    virtual void commit();
+
+    /// @brief Rollback Transactions
+    ///
+    /// Rolls back all pending database operations.  On databases that don't
+    /// support transactions, this is a no-op.
+    virtual void rollback();
+
+protected:
+
+    typedef boost::multi_index_container< // this is a multi-index container...
+    Lease6Ptr, // it will hold shared_ptr to leases6
+        boost::multi_index::indexed_by< // and will be sorted by
+            // IPv6 address that are unique. That particular key is a member
+            // of the Lease6 structure, is of type IOAddress and can be accessed
+            // by doing &Lease6::addr_
+            boost::multi_index::ordered_unique< 
+                boost::multi_index::member<Lease6, isc::asiolink::IOAddress, &Lease6::addr_> 
+            >
+        >
+    > Lease6Storage; // Let the whole contraption be called Lease6Storage.
+
+    Lease6Storage storage6_;
+};
+
+}; // end of isc::dhcp namespace
+}; // end of isc namespace
+
+#endif // MEMFILE_LEASE_MGR
+
diff --git a/src/lib/dhcpsrv/mysql_lease_mgr.cc b/src/lib/dhcpsrv/mysql_lease_mgr.cc
new file mode 100644
index 0000000..a3387ac
--- /dev/null
+++ b/src/lib/dhcpsrv/mysql_lease_mgr.cc
@@ -0,0 +1,1140 @@
+// 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 <config.h>
+
+#include <asiolink/io_address.h>
+#include <dhcpsrv/mysql_lease_mgr.h>
+
+#include <mysql/mysqld_error.h>
+
+#include <iostream>
+#include <iomanip>
+#include <string>
+#include <time.h>
+
+using namespace isc;
+using namespace isc::dhcp;
+using namespace std;
+
+namespace {
+///@{
+/// @brief Maximum Size of Database Fields
+///
+/// The following constants define buffer sizes for variable length database
+/// fields.  The values should be greater than or equal to the length set in
+/// the schema definition.
+///
+/// The exception is the length of any VARCHAR fields: these should be set
+/// greater than or equal to the length of the field plus 2: this allows for
+/// the insertion of a trailing null regardless of whether the data returned
+/// contains a trailing null (the documentation is not clear on this point).
+
+const size_t ADDRESS6_TEXT_MAX_LEN = 42;    // Max size of a IPv6 text buffer
+const size_t DUID_MAX_LEN = 128;            // Max size of a DUID
+///@}
+
+/// @brief MySQL Selection Statements
+///
+/// Each statement is associated with the index, used by the various methods
+/// to access the prepared statement.
+struct TaggedStatement {
+    MySqlLeaseMgr::StatementIndex index;
+    const char*                   text;
+};
+
+TaggedStatement tagged_statements[] = {
+    {MySqlLeaseMgr::DELETE_LEASE6,
+                    "DELETE FROM lease6 WHERE address = ?"},
+    {MySqlLeaseMgr::GET_LEASE6_ADDR,
+                    "SELECT address, duid, valid_lifetime, "
+                        "expire, subnet_id, pref_lifetime, "
+                        "lease_type, iaid, prefix_len "
+                            "FROM lease6 "
+                            "WHERE address = ?"},
+    {MySqlLeaseMgr::GET_LEASE6_DUID_IAID,
+                    "SELECT address, duid, valid_lifetime, "
+                        "expire, subnet_id, pref_lifetime, "
+                        "lease_type, iaid, prefix_len "
+                            "FROM lease6 "
+                            "WHERE duid = ? AND iaid = ?"},
+    {MySqlLeaseMgr::GET_LEASE6_DUID_IAID_SUBID,
+                    "SELECT address, duid, valid_lifetime, "
+                        "expire, subnet_id, pref_lifetime, "
+                        "lease_type, iaid, prefix_len "
+                            "FROM lease6 "
+                            "WHERE duid = ? AND iaid = ? AND subnet_id = ?"},
+    {MySqlLeaseMgr::GET_VERSION,
+                    "SELECT version, minor FROM schema_version"},
+    {MySqlLeaseMgr::INSERT_LEASE6,
+                    "INSERT INTO lease6(address, duid, valid_lifetime, "
+                        "expire, subnet_id, pref_lifetime, "
+                        "lease_type, iaid, prefix_len) "
+                            "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)"},
+    {MySqlLeaseMgr::UPDATE_LEASE6,
+                    "UPDATE lease6 SET address = ?, duid = ?, "
+                        "valid_lifetime = ?, expire = ?, subnet_id = ?, "
+                        "pref_lifetime = ?, lease_type = ?, iaid = ?, "
+                        "prefix_len = ? "
+                            "WHERE address = ?"},
+    // End of list sentinel
+    {MySqlLeaseMgr::NUM_STATEMENTS, NULL}
+};
+
+};  // Anonymous namespace
+
+namespace isc {
+namespace dhcp {
+
+
+
+/// @brief Exchange MySQL and Lease6 Data
+///
+/// On any MySQL operation, arrays of MYSQL_BIND structures must be built to
+/// describe the parameters in the prepared statements.  Where information is
+/// inserted or retrieved - INSERT, UPDATE, SELECT - a large amount of that
+/// structure is identical - it defines data values in the Lease6 structure.
+/// This class handles the creation of that array.
+///
+/// Owing to the MySQL API, the process requires some intermediate variables
+/// to hold things like length etc.  This object holds the intermediate
+/// variables as well.
+///
+/// @note There are no unit tests for this class.  It is tested indirectly
+/// in all MySqlLeaseMgr::xxx6() calls where it is used.
+
+class MySqlLease6Exchange {
+public:
+    /// @brief Constructor
+    ///
+    /// Apart from the initialization of false_ and true_, the initialization
+    /// of addr6_length_, duid_length_, addr6_buffer_ and duid_buffer_ are
+    /// to satisfy cppcheck: none are really needed, as all variables are
+    /// initialized/set in the methods.
+    MySqlLease6Exchange() : addr6_length_(0), duid_length_(0),
+                            false_(0), true_(1) {
+        memset(addr6_buffer_, 0, sizeof(addr6_buffer_));
+        memset(duid_buffer_, 0, sizeof(duid_buffer_));
+    }
+
+    /// @brief Create MYSQL_BIND objects for Lease6 Pointer
+    ///
+    /// Fills in the MYSQL_BIND objects for the Lease6 passed to it.
+    ///
+    /// @param lease Lease object to be added to the database.
+    ///
+    /// @return Vector of MySQL BIND objects representing the data to be added.
+    std::vector<MYSQL_BIND> createBindForSend(const Lease6Ptr& lease) {
+        // Store lease object to ensure it remains valid.
+        lease_ = lease;
+
+        // Ensure bind_ array clear for constructing the MYSQL_BIND structures
+        // for this lease.
+        memset(bind_, 0, sizeof(bind_));
+
+        // address: varchar(40)
+        addr6_ = lease_->addr_.toText();
+        addr6_length_ = addr6_.size();
+
+        // In the following statement, the string is being read.  However, the
+        // MySQL C interface does not use "const", so the "buffer" element
+        // is declared as "char*" instead of "const char*".  To resolve this,
+        // the "const" is discarded.  (Note that the address of addr6_.c_str()
+        // is guaranteed to be valid until the next non-const operation on
+        // addr6_.)
+        //
+        // Note that the const_cast could be avoided by copying the string to
+        // a writeable buffer and storing the address of that in the "buffer"
+        // element.  However, this introduces a copy operation (with additional
+        // overhead) purely to get round the strictures introduced by design of
+        // the MySQL interface (which uses the area pointed to by "buffer" as
+        // input when specifying query parameters and as output when retrieving
+        // data).  For that reason, "const_cast" has been used.
+        bind_[0].buffer_type = MYSQL_TYPE_STRING;
+        bind_[0].buffer = const_cast<char*>(addr6_.c_str());
+        bind_[0].buffer_length = addr6_length_;
+        bind_[0].length = &addr6_length_;
+
+        // duid: varchar(128)
+        duid_ = lease_->duid_->getDuid();
+        duid_length_ = duid_.size();
+
+        bind_[1].buffer_type = MYSQL_TYPE_BLOB;
+        bind_[1].buffer = reinterpret_cast<char*>(&(duid_[0]));
+        bind_[1].buffer_length = duid_length_;
+        bind_[1].length = &duid_length_;
+
+        // valid lifetime: unsigned int
+        bind_[2].buffer_type = MYSQL_TYPE_LONG;
+        bind_[2].buffer = reinterpret_cast<char*>(&lease->valid_lft_);
+        bind_[2].is_unsigned = true_;
+
+        // expire: timestamp
+        // The lease structure holds the client last transmission time (cltt_)
+        // For convenience for external tools, this is converted to lease
+        /// expiry time (expire).  The relationship is given by:
+        //
+        // expire = cltt_ + valid_lft_
+        //
+        // @TODO Handle overflows
+        MySqlLeaseMgr::convertToDatabaseTime(lease_->cltt_, lease_->valid_lft_,
+                                             expire_);
+        bind_[3].buffer_type = MYSQL_TYPE_TIMESTAMP;
+        bind_[3].buffer = reinterpret_cast<char*>(&expire_);
+        bind_[3].buffer_length = sizeof(expire_);
+
+        // subnet_id: unsigned int
+        // Can use lease_->subnet_id_ directly as it is of type uint32_t.
+        bind_[4].buffer_type = MYSQL_TYPE_LONG;
+        bind_[4].buffer = reinterpret_cast<char*>(&lease_->subnet_id_);
+        bind_[4].is_unsigned = true_;
+
+        // pref_lifetime: unsigned int
+        // Can use lease_->preferred_lft_ directly as it is of type uint32_t.
+        bind_[5].buffer_type = MYSQL_TYPE_LONG;
+        bind_[5].buffer = reinterpret_cast<char*>(&lease_->preferred_lft_);
+        bind_[5].is_unsigned = true_;
+
+        // lease_type: tinyint
+        // Must convert to uint8_t as lease_->type_ is a LeaseType variable
+        lease_type_ = lease_->type_;
+        bind_[6].buffer_type = MYSQL_TYPE_TINY;
+        bind_[6].buffer = reinterpret_cast<char*>(&lease_type_);
+        bind_[6].is_unsigned = true_;
+
+        // iaid: unsigned int
+        // Can use lease_->iaid_ directly as it is of type uint32_t.
+        bind_[7].buffer_type = MYSQL_TYPE_LONG;
+        bind_[7].buffer = reinterpret_cast<char*>(&lease_->iaid_);
+        bind_[7].is_unsigned = true_;
+
+        // prefix_len: unsigned tinyint
+        // Can use lease_->prefixlen_ directly as it is uint32_t.
+        bind_[8].buffer_type = MYSQL_TYPE_TINY;
+        bind_[8].buffer = reinterpret_cast<char*>(&lease_->prefixlen_);
+        bind_[8].is_unsigned = true_;
+
+        // Add the data to the vector.  Note the end element is one after the
+        // end of the array.
+        return (std::vector<MYSQL_BIND>(&bind_[0], &bind_[9]));
+    }
+
+    /// @brief Create BIND array to receive data
+    ///
+    /// Creates a MYSQL_BIND array to receive Lease6 data from the database.
+    /// After data is successfully received, getLeaseData() is used to copy
+    /// it to a Lease6 object.
+    ///
+    /// @return Vector of MySQL BIND objects.
+    std::vector<MYSQL_BIND> createBindForReceive() {
+
+        // Ensure both the array of MYSQL_BIND structures and the error array
+        // are clear.
+        memset(bind_, 0, sizeof(bind_));
+        memset(error_, 0, sizeof(error_));
+
+        // address:  varchar
+        // A Lease6_ address has a maximum of 39 characters.  The array is
+        // a few bites longer than this to guarantee that we can always null
+        // terminate it.
+        addr6_length_ = sizeof(addr6_buffer_) - 1;
+        bind_[0].buffer_type = MYSQL_TYPE_STRING;
+        bind_[0].buffer = addr6_buffer_;
+        bind_[0].buffer_length = addr6_length_;
+        bind_[0].length = &addr6_length_;
+        bind_[0].error = &error_[0];
+
+        // client_id: varbinary(128)
+        duid_length_ = sizeof(duid_buffer_);
+        bind_[1].buffer_type = MYSQL_TYPE_BLOB;
+        bind_[1].buffer = reinterpret_cast<char*>(duid_buffer_);
+        bind_[1].buffer_length = duid_length_;
+        bind_[1].length = &duid_length_;
+        bind_[1].error = &error_[1];
+
+        // lease_time: unsigned int
+        bind_[2].buffer_type = MYSQL_TYPE_LONG;
+        bind_[2].buffer = reinterpret_cast<char*>(&valid_lifetime_);
+        bind_[2].is_unsigned = true_;
+        bind_[2].error = &error_[2];
+
+        // expire: timestamp
+        bind_[3].buffer_type = MYSQL_TYPE_TIMESTAMP;
+        bind_[3].buffer = reinterpret_cast<char*>(&expire_);
+        bind_[3].buffer_length = sizeof(expire_);
+        bind_[3].error = &error_[3];
+
+        // subnet_id: unsigned int
+        bind_[4].buffer_type = MYSQL_TYPE_LONG;
+        bind_[4].buffer = reinterpret_cast<char*>(&subnet_id_);
+        bind_[4].is_unsigned = true_;
+        bind_[4].error = &error_[4];
+
+        // pref_lifetime: unsigned int
+        bind_[5].buffer_type = MYSQL_TYPE_LONG;
+        bind_[5].buffer = reinterpret_cast<char*>(&pref_lifetime_);
+        bind_[5].is_unsigned = true_;
+        bind_[5].error = &error_[5];
+
+        // lease_type: tinyint
+        bind_[6].buffer_type = MYSQL_TYPE_TINY;
+        bind_[6].buffer = reinterpret_cast<char*>(&lease_type_);
+        bind_[6].is_unsigned = true_;
+        bind_[6].error = &error_[6];
+
+        // iaid: unsigned int
+        bind_[7].buffer_type = MYSQL_TYPE_LONG;
+        bind_[7].buffer = reinterpret_cast<char*>(&iaid_);
+        bind_[7].is_unsigned = true_;
+        bind_[7].error = &error_[7];
+
+        // prefix_len: unsigned tinyint
+        bind_[8].buffer_type = MYSQL_TYPE_TINY;
+        bind_[8].buffer = reinterpret_cast<char*>(&prefixlen_);
+        bind_[8].is_unsigned = true_;
+        bind_[8].error = &error_[8];
+
+        // Add the data to the vector.  Note the end element is one after the
+        // end of the array.
+        return(std::vector<MYSQL_BIND>(&bind_[0], &bind_[9]));
+    }
+
+    /// @brief Copy Received Data into Lease6 Object
+    ///
+    /// Called after the MYSQL_BIND array created by createBindForReceive()
+    /// has been used, this copies data from the internal member vairables
+    /// into a Lease6 object.
+    ///
+    /// @return Lease6Ptr Pointer to a Lease6 object holding the relevant
+    ///         data.
+    ///
+    /// @throw isc::BadValue Unable to convert Lease Type value in database
+    Lease6Ptr getLeaseData() {
+
+        // Create the object to be returned.
+        Lease6Ptr result(new Lease6());
+
+        // Put the data in the lease object
+
+        // The address buffer is declared larger than the buffer size passed
+        // to the access function so that we can always append a null byte.
+        addr6_buffer_[addr6_length_] = '\0';
+        std::string address = addr6_buffer_;
+
+        // Set the other data, converting time as needed.
+        result->addr_ = isc::asiolink::IOAddress(address);
+        result->duid_.reset(new DUID(duid_buffer_, duid_length_));
+        MySqlLeaseMgr::convertFromDatabaseTime(expire_, valid_lifetime_,
+                                               result->cltt_);
+        result->valid_lft_ = valid_lifetime_;
+        result->subnet_id_ = subnet_id_;
+        result->preferred_lft_ = pref_lifetime_;
+
+        // We can't convert from a numeric value to an enum, hence:
+        switch (lease_type_) {
+            case Lease6::LEASE_IA_NA:
+                result->type_ = Lease6::LEASE_IA_NA;
+                break;
+
+            case Lease6::LEASE_IA_TA:
+                result->type_ = Lease6::LEASE_IA_TA;
+                break;
+
+            case Lease6::LEASE_IA_PD:
+                result->type_ = Lease6::LEASE_IA_PD;
+                break;
+
+            default:
+                isc_throw(BadValue, "invalid lease type returned (" <<
+                          lease_type_ << ") for lease with address " <<
+                          result->addr_.toText() << ". Only 0, 1, or 2 "
+                          "are allowed.");
+        }
+        result->iaid_ = iaid_;
+        result->prefixlen_ = prefixlen_;
+
+        return (result);
+    }
+
+private:
+    // Note: All array lengths are equal to the corresponding variable in the
+    // schema.
+    std::string     addr6_;             ///< String form of address
+    char            addr6_buffer_[ADDRESS6_TEXT_MAX_LEN];  ///< Character 
+                                        ///< array form of V6 address
+    unsigned long   addr6_length_;      ///< Length of the address
+    MYSQL_BIND      bind_[9];           ///< Static array for speed of access
+    std::vector<uint8_t> duid_;         ///< Client identification
+    uint8_t         duid_buffer_[DUID_MAX_LEN]; ///< Buffer form of DUID
+    unsigned long   duid_length_;       ///< Length of the DUID
+    my_bool         error_[9];          ///< For error reporting
+    MYSQL_TIME      expire_;            ///< Lease expiry time
+    const my_bool   false_;             ///< "false" for MySql
+    uint32_t        iaid_;              ///< Identity association ID
+    Lease6Ptr       lease_;             ///< Pointer to lease object
+    uint32_t        valid_lifetime_;    ///< Lease time
+    uint8_t         lease_type_;        ///< Lease type
+    uint8_t         prefixlen_;         ///< Prefix length
+    uint32_t        pref_lifetime_;     ///< Preferred lifetime
+    uint32_t        subnet_id_;         ///< Subnet identification
+    const my_bool   true_;              ///< "true_" for MySql
+};
+
+
+/// @brief Fetch and Release MySQL Results
+///
+/// When a MySQL statement is exected, to fetch the results the function
+/// mysql_stmt_fetch() must be called.  As well as getting data, this
+/// allocated internal state.  Subsequent calls to mysql_stmt_fetch
+/// can be made, but when all the data is retrieved, mysql_stmt_free_result
+/// must be called to free up the resources allocated.
+///
+/// Created prior to the first fetch, this class's destructor calls
+/// mysql_stmt_free_result, so eliminating the need for an explicit release
+/// in the method using mysql_stmt_free_result.  In this way, it guarantees
+/// that the resources are released even if the MySqlLeaseMgr method concerned
+/// exits via an exception.
+class MySqlFreeResult {
+public:
+
+    /// @brief Constructor
+    ///
+    /// Store the pointer to the statement for which data is being fetched.
+    ///
+    /// Note that according to the MySQL documentation, mysql_stmt_free_result
+    /// only releases resources if a cursor has been allocated for the
+    /// statement.  This implies that it is a no-op if none have been.  Either
+    /// way, any error from mysql_stmt_free_result is ignored. (Generating
+    /// an exception is not much help, as it will only confuse things if the
+    /// method calling mysql_stmt_fetch is exiting via an exception.)
+    MySqlFreeResult(MYSQL_STMT* statement) : statement_(statement)
+    {}
+
+    /// @brief Destructor
+    ///
+    /// Frees up fetch context if a fetch has been successfully executed.
+    ~MySqlFreeResult() {
+        (void) mysql_stmt_free_result(statement_);
+    }
+
+private:
+    MYSQL_STMT*     statement_;     ///< Statement for which results are freed
+};
+
+
+// MySqlLeaseMgr Methods
+
+MySqlLeaseMgr::MySqlLeaseMgr(const LeaseMgr::ParameterMap& parameters) 
+    : LeaseMgr(parameters), mysql_(NULL) {
+
+    // Allocate context for MySQL - it is destroyed in the destructor.
+    mysql_ = mysql_init(NULL);
+    if (mysql_ == NULL) {
+        isc_throw(DbOpenError, "unable to initialize MySQL");
+    }
+
+    // Open the database
+    openDatabase();
+
+    // Enable autocommit.  For maximum speed, the global parameter
+    // innodb_flush_log_at_trx_commit should be set to 2.
+    my_bool result = mysql_autocommit(mysql_, 1);
+    if (result != 0) {
+        isc_throw(DbOperationError, mysql_error(mysql_));
+    }
+
+    // Prepare all statements likely to be used.
+    prepareStatements();
+
+    // Create the exchange object for use in exchanging data between the
+    // program and the database.
+    exchange6_.reset(new MySqlLease6Exchange());
+}
+
+
+MySqlLeaseMgr::~MySqlLeaseMgr() {
+    // Free up the prepared statements, ignoring errors. (What would we do
+    // about them - we're destroying this object and are not really concerned
+    // with errors on a database connection that it about to go away.)
+    for (int i = 0; i < statements_.size(); ++i) {
+        if (statements_[i] != NULL) {
+            (void) mysql_stmt_close(statements_[i]);
+            statements_[i] = NULL;
+        }
+    }
+
+    // Close the database
+    mysql_close(mysql_);
+    mysql_ = NULL;
+}
+
+
+// Time conversion methods.
+//
+// Note that the MySQL TIMESTAMP data type (used for "expire") converts data
+// from the current timezone to UTC for storage, and from UTC to the current
+// timezone for retrieval.
+//
+// This causes no problems providing that:
+// a) cltt is given in local time
+// b) We let the system take care of timezone conversion when converting
+//    from a time read from the database into a local time.
+
+void
+MySqlLeaseMgr::convertToDatabaseTime(time_t cltt, uint32_t valid_lifetime,
+                                    MYSQL_TIME& expire) {
+
+    // Calculate expiry time and convert to various date/time fields.
+    // @TODO: handle overflows
+    time_t expire_time = cltt + valid_lifetime;
+
+    // Convert to broken-out time
+    struct tm expire_tm;
+    (void) localtime_r(&expire_time, &expire_tm);
+
+    // Place in output expire structure.
+    expire.year = expire_tm.tm_year + 1900;
+    expire.month = expire_tm.tm_mon + 1;     // Note different base
+    expire.day = expire_tm.tm_mday;
+    expire.hour = expire_tm.tm_hour;
+    expire.minute = expire_tm.tm_min;
+    expire.second = expire_tm.tm_sec;
+    expire.second_part = 0;                    // No fractional seconds
+    expire.neg = static_cast<my_bool>(0);      // Not negative
+}
+
+void
+MySqlLeaseMgr::convertFromDatabaseTime(const MYSQL_TIME& expire,
+                                       uint32_t valid_lifetime, time_t& cltt) {
+
+    // Copy across fields from MYSQL_TIME structure.
+    struct tm expire_tm;
+    memset(&expire_tm, 0, sizeof(expire_tm));
+
+    expire_tm.tm_year = expire.year - 1900;
+    expire_tm.tm_mon = expire.month - 1;
+    expire_tm.tm_mday = expire.day;
+    expire_tm.tm_hour = expire.hour;
+    expire_tm.tm_min = expire.minute;
+    expire_tm.tm_sec = expire.second;
+    expire_tm.tm_isdst = -1;    // Let the system work out about DST 
+
+    // Convert to local time
+    cltt = mktime(&expire_tm) - valid_lifetime;
+}
+
+
+void
+MySqlLeaseMgr::openDatabase() {
+
+    // Set up the values of the parameters
+    const char* host = "localhost";
+    string shost;
+    try {
+        shost = getParameter("host");
+        host = shost.c_str();
+    } catch (...) {
+        // No host.  Fine, we'll use "localhost"
+    }
+
+    const char* user = NULL;
+    string suser;
+    try {
+        suser = getParameter("user");
+        user = suser.c_str();
+    } catch (...) {
+        // No user.  Fine, we'll use NULL
+        ;
+    }
+
+    const char* password = NULL;
+    string spassword;
+    try {
+        spassword = getParameter("password");
+        password = spassword.c_str();
+    } catch (...) {
+        // No password.  Fine, we'll use NULL
+        ;
+    }
+
+    const char* name = NULL;
+    string sname;
+    try {
+        sname = getParameter("name");
+        name = sname.c_str();
+    } catch (...) {
+        // No database name.  Throw a "NoName" exception
+        isc_throw(NoDatabaseName, "must specified a name for the database");
+    }
+
+    // Set options for the connection:
+    // - automatic reconnection
+    my_bool auto_reconnect = 1;
+    int result = mysql_options(mysql_, MYSQL_OPT_RECONNECT, &auto_reconnect);
+    if (result != 0) {
+        isc_throw(DbOpenError, "unable to set auto-reconnect option: " <<
+                  mysql_error(mysql_));
+    }
+
+    // Open the database.
+    //
+    // The option CLIENT_FOUND_ROWS is specified so that in an UPDATE,
+    // the affected rows are the number of rows found that match the
+    // WHERE clause of the SQL statement, not the rows changed.  The reason
+    // here is that MySQL apparently does not update a row if data has not
+    // changed and so the "affected rows" (retrievable from MySQL) is zero.
+    // This makes it hard to distinguish whether the UPDATE changed no rows
+    // because no row matching the WHERE clause was found, or because a
+    // row was found by no data was altered.
+    MYSQL* status = mysql_real_connect(mysql_, host, user, password, name,
+                                       0, NULL, CLIENT_FOUND_ROWS);
+    if (status != mysql_) {
+        isc_throw(DbOpenError, mysql_error(mysql_));
+    }
+}
+
+
+void
+MySqlLeaseMgr::prepareStatement(StatementIndex index, const char* text) {
+    // Validate that there is space for the statement in the statements array
+    // and that nothing has been placed there before.
+    if ((index >= statements_.size()) || (statements_[index] != NULL)) {
+        isc_throw(InvalidParameter, "invalid prepared statement index (" <<
+                  static_cast<int>(index) << ") or indexed prepared " <<
+                  "statement is not null");
+    }
+
+    // All OK, so prepare the statement
+    text_statements_[index] = std::string(text);
+
+    statements_[index] = mysql_stmt_init(mysql_);
+    if (statements_[index] == NULL) {
+        isc_throw(DbOperationError, "unable to allocate MySQL prepared "
+                  "statement structure" << mysql_error(mysql_));
+    }
+
+    int status = mysql_stmt_prepare(statements_[index], text, strlen(text));
+    if (status != 0) {
+        isc_throw(DbOperationError, "unable to prepare MySQL statement <" <<
+                  text << ">, reason: " << mysql_error(mysql_));
+    }
+}
+
+
+void
+MySqlLeaseMgr::prepareStatements() {
+    // Allocate space for all statements
+    statements_.clear();
+    statements_.resize(NUM_STATEMENTS, NULL);
+    
+    text_statements_.clear();
+    text_statements_.resize(NUM_STATEMENTS, std::string(""));
+
+    // Created the MySQL prepared statements for each DML statement.
+    for (int i = 0; tagged_statements[i].text != NULL; ++i) {
+        prepareStatement(tagged_statements[i].index,
+                         tagged_statements[i].text);
+    }
+}
+
+
+bool
+MySqlLeaseMgr::addLease(const Lease4Ptr& /* lease */) {
+    isc_throw(NotImplemented, "MySqlLeaseMgr::addLease(const Lease4Ptr&) "
+              "not implemented yet");
+    return (false);
+}
+
+
+bool
+MySqlLeaseMgr::addLease(const Lease6Ptr& lease) {
+    const StatementIndex stindex = INSERT_LEASE6;
+
+    // Create the MYSQL_BIND array for the lease
+    std::vector<MYSQL_BIND> bind = exchange6_->createBindForSend(lease);
+
+    // Bind the parameters to the statement
+    int status = mysql_stmt_bind_param(statements_[stindex], &bind[0]);
+    checkError(status, stindex, "unable to bind parameters");
+
+    // Execute the statement
+    status = mysql_stmt_execute(statements_[stindex]);
+    if (status != 0) {
+
+        // Failure: check for the special case of duplicate entry.  If this is
+        // the case, we return false to indicate that the row was not added.
+        // Otherwise we throw an exception.
+        if (mysql_errno(mysql_) == ER_DUP_ENTRY) {
+            return (false);
+        }
+        checkError(status, stindex, "unable to execute");
+    }
+
+    // Insert succeeded
+    return (true);
+}
+
+
+Lease4Ptr
+MySqlLeaseMgr::getLease4(const isc::asiolink::IOAddress& /* addr */,
+                         SubnetID /* subnet_id */) const {
+    isc_throw(NotImplemented, "MySqlLeaseMgr::getLease4(const IOAddress&, SubnetID) "
+              "not implemented yet");
+    return (Lease4Ptr());
+}
+
+
+Lease4Ptr
+MySqlLeaseMgr::getLease4(const isc::asiolink::IOAddress& /* addr */) const {
+    isc_throw(NotImplemented, "MySqlLeaseMgr::getLease4(const IOAddress&) "
+              "not implemented yet");
+    return (Lease4Ptr());
+}
+
+
+Lease4Collection
+MySqlLeaseMgr::getLease4(const HWAddr& /* hwaddr */) const {
+    isc_throw(NotImplemented, "MySqlLeaseMgr::getLease4(const HWAddr&) "
+              "not implemented yet");
+    return (Lease4Collection());
+}
+
+
+Lease4Ptr
+MySqlLeaseMgr::getLease4(const HWAddr& /* hwaddr */,
+                         SubnetID /* subnet_id */) const {
+    isc_throw(NotImplemented, "MySqlLeaseMgr::getLease4(const HWAddr&, SubnetID) "
+              "not implemented yet");
+    return (Lease4Ptr());
+}
+
+
+Lease4Collection
+MySqlLeaseMgr::getLease4(const ClientId& /* clientid */) const {
+    isc_throw(NotImplemented, "MySqlLeaseMgr::getLease4(const ClientID&) "
+              "not implemented yet");
+    return (Lease4Collection());
+}
+
+
+Lease4Ptr
+MySqlLeaseMgr::getLease4(const ClientId& /* clientid */,
+                         SubnetID /* subnet_id */) const {
+    isc_throw(NotImplemented, "MySqlLeaseMgr::getLease4(const ClientID&, SubnetID) "
+              "not implemented yet");
+    return (Lease4Ptr());
+}
+
+
+// A convenience function used in the various getLease6() methods.  It binds
+// the selection parameters to the prepared statement, and binds the variables
+// that will receive the data.  These are stored in the MySqlLease6Exchange
+// object associated with the lease manager and converted to a Lease6 object
+// when retrieved.
+void
+MySqlLeaseMgr::bind6AndExecute(StatementIndex stindex, MYSQL_BIND* inbind) const {
+
+    // Bind the input parameters to the statement
+    int status = mysql_stmt_bind_param(statements_[stindex], inbind);
+    checkError(status, stindex, "unable to bind WHERE clause parameter");
+
+    // Set up the SELECT clause
+    std::vector<MYSQL_BIND> outbind = exchange6_->createBindForReceive();
+
+    // Bind the output parameters to the statement
+    status = mysql_stmt_bind_result(statements_[stindex], &outbind[0]);
+    checkError(status, stindex, "unable to bind SELECT caluse parameters");
+
+    // Execute the statement
+    status = mysql_stmt_execute(statements_[stindex]);
+    checkError(status, stindex, "unable to execute");
+}
+
+
+Lease6Ptr
+MySqlLeaseMgr::getLease6(const isc::asiolink::IOAddress& addr) const {
+    const StatementIndex stindex = GET_LEASE6_ADDR;
+
+    // Set up the WHERE clause value
+    MYSQL_BIND inbind[1];
+    memset(inbind, 0, sizeof(inbind));
+
+    std::string addr6 = addr.toText();
+    unsigned long addr6_length = addr6.size();
+
+    // See the earlier description of the use of "const_cast" when accessing
+    // the address for an explanation of the reason.
+    inbind[0].buffer_type = MYSQL_TYPE_STRING;
+    inbind[0].buffer = const_cast<char*>(addr6.c_str());
+    inbind[0].buffer_length = addr6_length;
+    inbind[0].length = &addr6_length;
+
+    // Bind the input parameters to the statement and bind the output
+    // to fields in the exchange object, then execute the prepared statement.
+    bind6AndExecute(stindex, inbind);
+
+    // Fetch the data and set up the "release" object to release associated
+    // resources when this method exits.
+    MySqlFreeResult fetch_release(statements_[stindex]);
+    int status = mysql_stmt_fetch(statements_[stindex]);
+
+    Lease6Ptr result;
+    if (status == 0) {
+        try {
+            result = exchange6_->getLeaseData();
+        } catch (const isc::BadValue& ex) {
+            // Lease type is returned, to rethrow the exception with a bit
+            // more data.
+            isc_throw(BadValue, ex.what() << ". Statement is <" <<
+                      text_statements_[stindex] << ">");
+        }
+
+        // As the address is the primary key in the table, we can't return
+        // two rows, so we don't bother checking whether multiple rows have
+        // been returned.
+
+    } else if (status == 1) {
+        checkError(status, stindex, "unable to fetch results");
+
+    } else {
+        // @TODO Handle truncation
+        // We are ignoring truncation for now, so the only other result is
+        // no data was found.  In that case, we return a null Lease6 structure.
+        // This has already been set, so no action is needed.
+    }
+
+    return (result);
+}
+
+
+Lease6Collection
+MySqlLeaseMgr::getLease6(const DUID& duid, uint32_t iaid) const {
+    const StatementIndex stindex = GET_LEASE6_DUID_IAID;
+
+    // Set up the WHERE clause value
+    MYSQL_BIND inbind[2];
+    memset(inbind, 0, sizeof(inbind));
+
+    // In the following statement, the DUID is being read.  However, the
+    // MySQL C interface does not use "const", so the "buffer" element
+    // is declared as "char*" instead of "const char*".  To resolve this,
+    // the "const" is discarded before the uint8_t* is cast to char*.
+    //
+    // Note that the const_cast could be avoided by copying the DUID to
+    // a writeable buffer and storing the address of that in the "buffer"
+    // element.  However, this introduces a copy operation (with additional
+    // overhead) purely to get round the strictures introduced by design of
+    // the MySQL interface (which uses the area pointed to by "buffer" as
+    // input when specifying query parameters and as output when retrieving
+    // data).  For that reason, "const_cast" has been used.
+    const vector<uint8_t>& duid_vector = duid.getDuid();
+    unsigned long duid_length = duid_vector.size();
+    inbind[0].buffer_type = MYSQL_TYPE_BLOB;
+    inbind[0].buffer = reinterpret_cast<char*>(
+            const_cast<uint8_t*>(&duid_vector[0]));
+    inbind[0].buffer_length = duid_length;
+    inbind[0].length = &duid_length;
+
+    // IAID
+    inbind[1].buffer_type = MYSQL_TYPE_LONG;
+    inbind[1].buffer = reinterpret_cast<char*>(&iaid);
+    inbind[1].is_unsigned = static_cast<my_bool>(1);
+
+    // Bind the input parameters to the statement and bind the output
+    // to fields in the exchange object, then execute the prepared statement.
+    bind6AndExecute(stindex, inbind);
+
+    // Ensure that all the lease information is retrieved in one go to avoid
+    // overhead of going back and forth between client and server.
+    int status = mysql_stmt_store_result(statements_[stindex]);
+    checkError(status, stindex, "unable to set up for storing all results");
+
+    // Fetch the data.  There could be multiple rows, so we need to iterate
+    // until all data has been retrieved.
+    Lease6Collection result;
+
+    // Set up the fetch "release" object to release resources associated
+    // with the call to mysql_stmt_fetch when this method exits, then
+    // retrieve the data.
+    MySqlFreeResult fetch_release(statements_[stindex]);
+    while ((status = mysql_stmt_fetch(statements_[stindex])) == 0) {
+        try {
+            Lease6Ptr lease = exchange6_->getLeaseData();
+            result.push_back(lease);
+
+        } catch (const isc::BadValue& ex) {
+            // Rethrow the exception with a bit more data.
+            isc_throw(BadValue, ex.what() << ". Statement is <" <<
+                      text_statements_[stindex] << ">");
+        }
+    }
+
+    // How did the fetch end?
+    if (status == 1) {
+        // Error - unable to fecth results
+        checkError(status, stindex, "unable to fetch results");
+    } else if (status == MYSQL_DATA_TRUNCATED) {
+        // @TODO Handle truncation
+        ;
+    }
+
+    return (result);
+}
+
+
+Lease6Ptr
+MySqlLeaseMgr::getLease6(const DUID& duid, uint32_t iaid,
+                         SubnetID subnet_id) const {
+    const StatementIndex stindex = GET_LEASE6_DUID_IAID_SUBID;
+
+    // Set up the WHERE clause value
+    MYSQL_BIND inbind[3];
+    memset(inbind, 0, sizeof(inbind));
+
+    // See the earlier description of the use of "const_cast" when accessing
+    // the DUID for an explanation of the reason.
+    const vector<uint8_t>& duid_vector = duid.getDuid();
+    unsigned long duid_length = duid_vector.size();
+    inbind[0].buffer_type = MYSQL_TYPE_BLOB;
+    inbind[0].buffer = reinterpret_cast<char*>(
+            const_cast<uint8_t*>(&duid_vector[0]));
+    inbind[0].buffer_length = duid_length;
+    inbind[0].length = &duid_length;
+
+    // IAID
+    inbind[1].buffer_type = MYSQL_TYPE_LONG;
+    inbind[1].buffer = reinterpret_cast<char*>(&iaid);
+    inbind[1].is_unsigned = static_cast<my_bool>(1);
+
+    // Subnet ID
+    inbind[2].buffer_type = MYSQL_TYPE_LONG;
+    inbind[2].buffer = reinterpret_cast<char*>(&subnet_id);
+    inbind[2].is_unsigned = static_cast<my_bool>(1);
+
+    // Bind the input parameters to the statement and bind the output
+    // to fields in the exchange object, then execute the prepared statement.
+    bind6AndExecute(stindex, inbind);
+
+    // Fetch the data and set up the "release" object to release associated
+    // resources when this method exits then retrieve the data.
+    Lease6Ptr result;
+    MySqlFreeResult fetch_release(statements_[stindex]);
+    int status = mysql_stmt_fetch(statements_[stindex]);
+    if (status == 0) {
+        try {
+            result = exchange6_->getLeaseData();
+
+            // TODO: check for more than one row returned.  At present, just
+            // ignore the excess and take the first.
+
+        } catch (const isc::BadValue& ex) {
+            // Lease type is returned, to rethrow the exception with a bit
+            // more data.
+            isc_throw(BadValue, ex.what() << ". Statement is <" <<
+                      text_statements_[stindex] << ">");
+        }
+
+        // As the address is the primary key in the table, we can't return
+        // two rows, so we don't bother checking whether multiple rows have
+        // been returned.
+
+    } else if (status == 1) {
+        checkError(status, stindex, "unable to fetch results");
+
+    } else {
+        // @TODO Handle truncation
+        // We are ignoring truncation for now, so the only other result is
+        // no data was found.  In that case, we return a null Lease6 structure.
+        // This has already been set, so the action is a no-op.
+    }
+
+    return (result);
+}
+
+
+void
+MySqlLeaseMgr::updateLease4(const Lease4Ptr& /* lease4 */) {
+    isc_throw(NotImplemented, "MySqlLeaseMgr::updateLease4(const Lease4Ptr&) "
+              "not implemented yet");
+}
+
+
+void
+MySqlLeaseMgr::updateLease6(const Lease6Ptr& lease) {
+    const StatementIndex stindex = UPDATE_LEASE6;
+
+    // Create the MYSQL_BIND array for the data being updated
+    std::vector<MYSQL_BIND> bind = exchange6_->createBindForSend(lease);
+
+    // Set up the WHERE clause value
+    MYSQL_BIND where;
+    memset(&where, 0, sizeof(where));
+
+    std::string addr6 = lease->addr_.toText();
+    unsigned long addr6_length = addr6.size();
+
+    // See the earlier description of the use of "const_cast" when accessing
+    // the address for an explanation of the reason.
+    where.buffer_type = MYSQL_TYPE_STRING;
+    where.buffer = const_cast<char*>(addr6.c_str());
+    where.buffer_length = addr6_length;
+    where.length = &addr6_length;
+    bind.push_back(where);
+
+    // Bind the parameters to the statement
+    int status = mysql_stmt_bind_param(statements_[stindex], &bind[0]);
+    checkError(status, stindex, "unable to bind parameters");
+
+    // Execute
+    status = mysql_stmt_execute(statements_[stindex]);
+    checkError(status, stindex, "unable to execute");
+
+    // See how many rows were affected.  The statement should only delete a
+    // single row.
+    int affected_rows = mysql_stmt_affected_rows(statements_[stindex]);
+    if (affected_rows == 0) {
+        isc_throw(NoSuchLease, "unable to update lease for address " <<
+                  addr6 << " as it does not exist");
+    } else if (affected_rows > 1) {
+        // Should not happen - primary key constraint should only have selected
+        // one row.
+        isc_throw(DbOperationError, "apparently updated more than one lease "
+                  "that had the address " << addr6);
+    }
+}
+
+
+bool
+MySqlLeaseMgr::deleteLease4(const isc::asiolink::IOAddress& /* addr */) {
+    isc_throw(NotImplemented, "MySqlLeaseMgr::deleteLease4(const IOAddress&) "
+              "not implemented yet");
+    return (false);
+}
+
+
+bool
+MySqlLeaseMgr::deleteLease6(const isc::asiolink::IOAddress& addr) {
+    const StatementIndex stindex = DELETE_LEASE6;
+
+    // Set up the WHERE clause value
+    MYSQL_BIND inbind[1];
+    memset(inbind, 0, sizeof(inbind));
+
+    std::string addr6 = addr.toText();
+    unsigned long addr6_length = addr6.size();
+
+    // See the earlier description of the use of "const_cast" when accessing
+    // the address for an explanation of the reason.
+    inbind[0].buffer_type = MYSQL_TYPE_STRING;
+    inbind[0].buffer = const_cast<char*>(addr6.c_str());
+    inbind[0].buffer_length = addr6_length;
+    inbind[0].length = &addr6_length;
+
+    // Bind the input parameters to the statement
+    int status = mysql_stmt_bind_param(statements_[stindex], inbind);
+    checkError(status, stindex, "unable to bind WHERE clause parameter");
+
+    // Execute
+    status = mysql_stmt_execute(statements_[stindex]);
+    checkError(status, stindex, "unable to execute");
+
+    // See how many rows were affected.  Note that the statement may delete
+    // multiple rows.
+    return (mysql_stmt_affected_rows(statements_[stindex]) > 0);
+}
+
+
+std::string
+MySqlLeaseMgr::getName() const {
+    std::string name = "";
+    try {
+        name = getParameter("name");
+    } catch (...) {
+        ;
+    }
+    return (name);
+}
+
+
+std::string
+MySqlLeaseMgr::getDescription() const {
+    return (std::string("MySQL Database"));
+}
+
+
+std::pair<uint32_t, uint32_t>
+MySqlLeaseMgr::getVersion() const {
+    const StatementIndex stindex = GET_VERSION;
+
+    uint32_t    major;      // Major version number
+    uint32_t    minor;      // Minor version number
+
+    // Execute the prepared statement
+    int status = mysql_stmt_execute(statements_[stindex]);
+    if (status != 0) {
+        isc_throw(DbOperationError, "unable to execute <"
+                  << text_statements_[stindex] << "> - reason: " <<
+                  mysql_error(mysql_));
+    }
+
+    // Bind the output of the statement to the appropriate variables.
+    MYSQL_BIND bind[2];
+    memset(bind, 0, sizeof(bind));
+
+    bind[0].buffer_type = MYSQL_TYPE_LONG;
+    bind[0].is_unsigned = 1;
+    bind[0].buffer = &major;
+    bind[0].buffer_length = sizeof(major);
+
+    bind[1].buffer_type = MYSQL_TYPE_LONG;
+    bind[1].is_unsigned = 1;
+    bind[1].buffer = &minor;
+    bind[1].buffer_length = sizeof(minor);
+
+    status = mysql_stmt_bind_result(statements_[stindex], bind);
+    if (status != 0) {
+        isc_throw(DbOperationError, "unable to bind result set: " <<
+                  mysql_error(mysql_));
+    }
+
+    // Fetch the data and set up the "release" object to release associated
+    // resources when this method exits then retrieve the data.
+    MySqlFreeResult fetch_release(statements_[stindex]);
+    status = mysql_stmt_fetch(statements_[stindex]);
+    if (status != 0) {
+        isc_throw(DbOperationError, "unable to obtain result set: " <<
+                  mysql_error(mysql_));
+    }
+
+    return (std::make_pair(major, minor));
+}
+
+
+void
+MySqlLeaseMgr::commit() {
+    if (mysql_commit(mysql_) != 0) {
+        isc_throw(DbOperationError, "commit failed: " << mysql_error(mysql_));
+    }
+}
+
+
+void
+MySqlLeaseMgr::rollback() {
+    if (mysql_rollback(mysql_) != 0) {
+        isc_throw(DbOperationError, "rollback failed: " << mysql_error(mysql_));
+    }
+}
+
+}; // end of isc::dhcp namespace
+}; // end of isc namespace
diff --git a/src/lib/dhcpsrv/mysql_lease_mgr.h b/src/lib/dhcpsrv/mysql_lease_mgr.h
new file mode 100644
index 0000000..642d3ed
--- /dev/null
+++ b/src/lib/dhcpsrv/mysql_lease_mgr.h
@@ -0,0 +1,449 @@
+// 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 MYSQL_LEASE_MGR_H
+#define MYSQL_LEASE_MGR_H
+
+#include <dhcpsrv/lease_mgr.h>
+
+#include <boost/scoped_ptr.hpp>
+#include <mysql.h>
+
+#include <time.h>
+
+namespace isc {
+namespace dhcp {
+
+// Define the current database schema values
+
+const uint32_t CURRENT_VERSION_VERSION = 0;
+const uint32_t CURRENT_VERSION_MINOR = 1;
+
+
+// Forward declaration of the Lease6 exchange object.  This class is defined
+// in the .cc file.
+class MySqlLease6Exchange;
+
+
+/// @brief MySQL Lease Manager
+///
+/// This is a concrete API for the backend for the MySQL database.
+class MySqlLeaseMgr : public LeaseMgr {
+public:
+    /// @brief Constructor
+    ///
+    /// Uses the following keywords in the parameters passed to it to
+    /// connect to the database:
+    /// - name - Name of the database to which to connect (mandatory)
+    /// - host - Host to which to connect (optional, defaults to "localhost")
+    /// - user - Username under which to connect (optional)
+    /// - password - Password for "user" on the database (optional)
+    ///
+    /// If the database is successfully opened, the version number in the
+    /// schema_version table will be checked against hard-coded value in
+    /// the implementation file.
+    ///
+    /// Finally, all the SQL commands are pre-compiled.
+    ///
+    /// @param parameters A data structure relating keywords and values
+    ///        concerned with the database.
+    ///
+    /// @throw isc::dhcp::NoDatabaseName Mandatory database name not given
+    /// @throw isc::dhcp::DbOpenError Error opening the database
+    /// @throw isc::dhcp::DbOperationError An operation on the open database has
+    ///        failed.
+    MySqlLeaseMgr(const ParameterMap& parameters);
+
+    /// @brief Destructor (closes database)
+    virtual ~MySqlLeaseMgr();
+
+    /// @brief Adds an IPv4 lease.
+    ///
+    /// @param lease lease to be added
+    ///
+    /// @result true if the lease was added, false if not (because a lease
+    ///         with the same address was already there).
+    ///
+    /// @throw isc::dhcp::DbOperationError An operation on the open database has
+    ///        failed.
+    virtual bool addLease(const Lease4Ptr& lease);
+
+    /// @brief Adds an IPv6 lease.
+    ///
+    /// @param lease lease to be added
+    ///
+    /// @result true if the lease was added, false if not (because a lease
+    ///         with the same address was already there).
+    ///
+    /// @throw isc::dhcp::DbOperationError An operation on the open database has
+    ///        failed.
+    virtual bool addLease(const Lease6Ptr& lease);
+
+    /// @brief Return 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 sought 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(const isc::asiolink::IOAddress& addr,
+                                SubnetID subnet_id) const;
+
+    /// @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 DUID) 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
+    ///
+    /// @return smart pointer to the lease (or NULL if a lease is not found)
+    virtual Lease4Ptr getLease4(const isc::asiolink::IOAddress& addr) 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
+    ///
+    /// 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;
+
+    /// @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.
+    ///
+    /// 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)
+    ///
+    /// @throw isc::BadValue record retrieved from database had an invalid
+    ///        lease type field.
+    /// @throw isc::dhcp::DbOperationError An operation on the open database has
+    ///        failed.
+    virtual Lease6Ptr getLease6(const isc::asiolink::IOAddress& addr) const;
+
+    /// @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;
+
+    /// @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;
+
+    /// @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(const Lease4Ptr& lease4);
+
+    /// @brief Updates IPv6 lease.
+    ///
+    /// @param lease6 The lease to be updated.
+    ///
+    /// @throw isc::dhcp::NoSuchLease Attempt to update a lease that did not
+    ///        exist.
+    /// @throw isc::dhcp::DbOperationError An operation on the open database has
+    ///        failed.
+    virtual void updateLease6(const Lease6Ptr& lease6);
+
+    /// @brief Deletes an IPv4 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(const isc::asiolink::IOAddress& addr);
+
+    /// @brief Deletes an IPv6 lease.
+    ///
+    /// @param addr IPv6 address of the lease to be deleted.
+    ///
+    /// @return true if deletion was successful, false if no such lease exists
+    ///
+    /// @throw isc::dhcp::DbOperationError An operation on the open database has
+    ///        failed.
+    virtual bool deleteLease6(const isc::asiolink::IOAddress& addr);
+
+    /// @brief Return backend type
+    ///
+    /// Returns the type of the backend (e.g. "mysql", "memfile" etc.)
+    ///
+    /// @return Type of the backend.
+    virtual std::string getType() const {
+        return (std::string("mysql"));
+    }
+
+    /// @brief Returns backend name.
+    ///
+    /// Each backend have specific name, e.g. "mysql" or "sqlite".
+    ///
+    /// @return Name of the backend.
+    virtual std::string getName() const;
+
+    /// @brief Returns description of the backend.
+    ///
+    /// This description may be multiline text that describes the backend.
+    ///
+    /// @return Description of the backend.
+    virtual std::string getDescription() const;
+
+    /// @brief Returns backend version.
+    ///
+    /// @return Version number as a pair of unsigned integers.  "first" is the
+    ///         major version number, "second" the minor number.
+    ///
+    /// @throw isc::dhcp::DbOperationError An operation on the open database has
+    ///        failed.
+    virtual std::pair<uint32_t, uint32_t> getVersion() const;
+
+    /// @brief Commit Transactions
+    ///
+    /// Commits all pending database operations.  On databases that don't
+    /// support transactions, this is a no-op.
+    ///
+    /// @throw DbOperationError Iif the commit failed.
+    virtual void commit();
+
+    /// @brief Rollback Transactions
+    ///
+    /// Rolls back all pending database operations.  On databases that don't
+    /// support transactions, this is a no-op.
+    ///
+    /// @throw DbOperationError If the rollback failed.
+    virtual void rollback();
+
+    ///@{
+    /// The following methods are used to convert between times and time
+    /// intervals stored in the Lease object, and the times stored in the
+    /// database.  The reason for the difference is because in the DHCP server,
+    /// the cltt (Client Time Since Last Transmission) is the natural data; in
+    /// the lease file - which may be read by the user - it is the expiry time
+    /// of the lease.
+
+    /// @brief Convert Lease Time to Database Times
+    ///
+    /// Within the DHCP servers, times are stored as client last transmit time
+    /// and valid lifetime.  In the database, the information is stored as
+    /// valid lifetime and "expire" (time of expiry of the lease).  They are
+    /// related by the equation:
+    ///
+    /// - expire = client last transmit time + valid lifetime
+    ///
+    /// This method converts from the times in the lease object into times
+    /// able to be added to the database.
+    ///
+    /// @param cltt Client last transmit time
+    /// @param valid_lifetime Valid lifetime
+    /// @param expire Reference to MYSQL_TIME object where the expiry time of
+    ///        the lease will be put.
+    static
+    void convertToDatabaseTime(time_t cltt, uint32_t valid_lifetime,
+                               MYSQL_TIME& expire);
+
+    /// @brief Convert Database Time to Lease Times
+    ///
+    /// Within the database, time is stored as "expire" (time of expiry of the
+    /// lease) and valid lifetime.  In the DHCP server, the information is
+    /// stored client last transmit time and valid lifetime.  These are related
+    /// by the equation:
+    ///
+    /// - client last transmit time = expire - valid_lifetime
+    ///
+    /// This method converts from the times in the database into times
+    /// able to be inserted into the lease object.
+    ///
+    /// @param expire Reference to MYSQL_TIME object from where the expiry
+    ///        time of the lease is taken.
+    /// @param valid_lifetime lifetime of the lease.
+    /// @param cltt Reference to location where client last transmit time
+    ///        is put.
+    static
+    void convertFromDatabaseTime(const MYSQL_TIME& expire, 
+                                 uint32_t valid_lifetime, time_t& cltt);
+    ///@}
+
+    /// @brief Statement Tags
+    ///
+    /// The contents of the enum are indexes into the list of SQL statements
+    enum StatementIndex {
+        DELETE_LEASE6,              // Delete from lease6 by address
+        GET_LEASE6_ADDR,            // Get lease6 by address
+        GET_LEASE6_DUID_IAID,       // Get lease6 by DUID and IAID
+        GET_LEASE6_DUID_IAID_SUBID, // Get lease6 by DUID, IAID and Subnet ID
+        GET_VERSION,                // Obtain version number
+        INSERT_LEASE6,              // Add entry to lease6 table
+        UPDATE_LEASE6,              // Update a Lease6 entry
+        NUM_STATEMENTS              // Number of statements
+    };
+
+private:
+    /// @brief Prepare Single Statement
+    ///
+    /// Creates a prepared statement from the text given and adds it to the
+    /// statements_ vector at the given index.
+    ///
+    /// @param index Index into the statements_ vector into which the text
+    ///        should be placed.  The vector must be big enough for the index
+    ///        to be valid, else an exception will be thrown.
+    /// @param text Text of the SQL statement to be prepared.
+    ///
+    /// @throw isc::dhcp::DbOperationError An operation on the open database has
+    ///        failed.
+    /// @throw isc::InvalidParameter 'index' is not valid for the vector.
+    void prepareStatement(StatementIndex index, const char* text);
+
+    /// @brief Prepare statements
+    ///
+    /// Creates the prepared statements for all of the SQL statements used
+    /// by the MySQL backend.
+    ///
+    /// @throw isc::dhcp::DbOperationError An operation on the open database has
+    ///        failed.
+    /// @throw isc::InvalidParameter 'index' is not valid for the vector.  This
+    ///        represents an internal error within the code.
+    void prepareStatements();
+
+    /// @brief Open Database
+    ///
+    /// Opens the database using the information supplied in the parameters
+    /// passed to the constructor.
+    ///
+    /// @throw NoDatabaseName Mandatory database name not given
+    /// @throw DbOpenError Error opening the database
+    void openDatabase();
+
+    /// @brief Binds Parameters and Executes
+    ///
+    /// This method abstracts a lot of common processing from the getXxxx()
+    /// methods.  It binds the parameters passed to it to the appropriate
+    /// prepared statement, and binds the variables in the exchange6 object to
+    /// the output parameters of the statement.  It then executes the prepared
+    /// statement.
+    ///
+    /// The data can be retrieved using mysql_stmt_fetch and the getLeaseData()
+    /// method on the exchange6 object.
+    ///
+    /// @param stindex Index of prepared statement to be executed
+    /// @param inbind Array of MYSQL_BIND objects representing the parameters.
+    ///        (Note that the number is determined by the number of parameters
+    ///        in the statement.)
+    ///
+    /// @throw isc::dhcp::DbOperationError An operation on the open database has
+    ///        failed.
+    void bind6AndExecute(StatementIndex stindex, MYSQL_BIND* inbind) const;
+
+    /// @brief Check Error and Throw Exception
+    ///
+    /// Virtually all MySQL functions return a status which, if non-zero,
+    /// indicates an error.  This inline function conceals a lot of error
+    /// checking/exception-throwing code.
+    ///
+    /// @param status Status code: non-zero implies an error
+    /// @param index Index of statement that caused the error
+    /// @param what High-level description of the error
+    ///
+    /// @throw isc::dhcp::DbOperationError An operation on the open database has
+    ///        failed.
+    inline void checkError(int status, StatementIndex index,
+                           const char* what) const {
+        if (status != 0) {
+            isc_throw(DbOperationError, what << " for <" <<
+                      text_statements_[index] << ">, reason: " <<
+                      mysql_error(mysql_) << " (error code " <<
+                      mysql_errno(mysql_) << ")");
+        }
+    }
+
+    // Members
+
+    /// Used for transfer of data to/from the database. This is a pointed-to
+    /// object as its contents may change in "const" calls, while the rest
+    /// of this object does not.  (At alternative would be to declare it as
+    /// "mutable".)
+    boost::scoped_ptr<MySqlLease6Exchange> exchange6_;
+    MYSQL*              mysql_;                 ///< MySQL context object
+    std::vector<std::string> text_statements_;  ///< Raw text of statements
+    std::vector<MYSQL_STMT*> statements_;       ///< Prepared statements
+};
+
+}; // end of isc::dhcp namespace
+}; // end of isc namespace
+
+#endif // MYSQL_LEASE_MGR_H
diff --git a/src/lib/dhcpsrv/pool.cc b/src/lib/dhcpsrv/pool.cc
new file mode 100644
index 0000000..9c91acb
--- /dev/null
+++ b/src/lib/dhcpsrv/pool.cc
@@ -0,0 +1,118 @@
+// 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 <dhcpsrv/addr_utilities.h>
+#include <dhcpsrv/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_));
+}
+
+Pool4::Pool4(const isc::asiolink::IOAddress& first,
+             const isc::asiolink::IOAddress& last)
+    :Pool(first, last) {
+    // check if specified address boundaries are sane
+    if (first.getFamily() != AF_INET || last.getFamily() != AF_INET) {
+        isc_throw(BadValue, "Invalid Pool4 address boundaries: not IPv4");
+    }
+
+    if (last < first) {
+        isc_throw(BadValue, "Upper boundary is smaller than lower boundary.");
+    }
+}
+
+Pool4::Pool4(const isc::asiolink::IOAddress& prefix,
+             uint8_t prefix_len)
+    :Pool(prefix, IOAddress("0.0.0.0")) {
+
+    // check if the prefix is sane
+    if (prefix.getFamily() != AF_INET) {
+        isc_throw(BadValue, "Invalid Pool4 address boundaries: not IPv4");
+    }
+
+    // check if the prefix length is sane
+    if (prefix_len == 0 || prefix_len > 32) {
+        isc_throw(BadValue, "Invalid prefix length");
+    }
+
+    // Let's now calculate the last address in defined pool
+    last_ = lastAddrInPrefix(prefix, prefix_len);
+}
+
+
+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/dhcpsrv/pool.h b/src/lib/dhcpsrv/pool.h
new file mode 100644
index 0000000..eb5e5e2
--- /dev/null
+++ b/src/lib/dhcpsrv/pool.h
@@ -0,0 +1,186 @@
+// 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 <asiolink/io_address.h>
+
+#include <boost/shared_ptr.hpp>
+
+#include <vector>
+
+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 IPv4 addresses
+///
+/// It holds information about pool4, i.e. a range of IPv4 address space that
+/// is configured for DHCP allocation.
+class Pool4 : public Pool {
+public:
+    /// @brief the constructor for Pool4 "min-max" style definition
+    ///
+    /// @param first the first address in a pool
+    /// @param last the last address in a pool
+    Pool4(const isc::asiolink::IOAddress& first,
+          const isc::asiolink::IOAddress& last);
+
+    /// @brief the constructor for Pool4 "prefix/len" style definition
+    ///
+    /// @param prefix specifies prefix of the pool
+    /// @param prefix_len specifies length of the prefix of the pool
+    Pool4(const isc::asiolink::IOAddress& prefix,
+          uint8_t prefix_len);
+};
+
+/// @brief a pointer an IPv4 Pool
+typedef boost::shared_ptr<Pool4> Pool4Ptr;
+
+/// @brief a container for IPv4 Pools
+typedef std::vector<Pool4Ptr> Pool4Collection;
+
+/// @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 type type of the pool (IA, TA or PD)
+    /// @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 type type of the pool (IA, TA or PD)
+    /// @param prefix specifies prefix of the pool
+    /// @param prefix_len specifies length of the prefix of the pool
+    Pool6(Pool6Type type, const isc::asiolink::IOAddress& prefix,
+          uint8_t prefix_len);
+
+    /// @brief returns pool type
+    ///
+    /// @return pool type
+    Pool6Type getType() const {
+        return (type_);
+    }
+
+private:
+    /// @brief defines a pool type
+    Pool6Type type_;
+
+    /// @brief prefix length
+    /// used by TYPE_PD only (zeroed for other types)
+    uint8_t prefix_len_;
+};
+
+/// @brief a pointer an IPv6 Pool
+typedef boost::shared_ptr<Pool6> Pool6Ptr;
+
+/// @brief a container for IPv6 Pools
+typedef std::vector<Pool6Ptr> Pool6Collection;
+
+} // end of isc::dhcp namespace
+} // end of isc namespace
+
+
+#endif // POOL_H
diff --git a/src/lib/dhcpsrv/subnet.cc b/src/lib/dhcpsrv/subnet.cc
new file mode 100644
index 0000000..78da250
--- /dev/null
+++ b/src/lib/dhcpsrv/subnet.cc
@@ -0,0 +1,204 @@
+// 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 <dhcpsrv/addr_utilities.h>
+#include <dhcpsrv/subnet.h>
+
+#include <sstream>
+
+using namespace isc::asiolink;
+
+namespace isc {
+namespace dhcp {
+
+Subnet::Subnet(const isc::asiolink::IOAddress& prefix, uint8_t len,
+               const Triplet<uint32_t>& t1,
+               const Triplet<uint32_t>& t2,
+               const Triplet<uint32_t>& valid_lifetime)
+    :id_(getNextID()), prefix_(prefix), prefix_len_(len), t1_(t1),
+     t2_(t2), valid_(valid_lifetime),
+     last_allocated_(lastAddrInPrefix(prefix, len)) {
+    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));
+}
+
+void
+Subnet::addOption(OptionPtr& option, bool persistent /* = false */) {
+    validateOption(option);
+    options_.push_back(OptionDescriptor(option, persistent));
+}
+
+void
+Subnet::delOptions() {
+    options_.clear();
+}
+
+std::string Subnet::toText() const {
+    std::stringstream tmp;
+    tmp << prefix_.toText() << "/" << static_cast<unsigned int>(prefix_len_);
+    return (tmp.str());
+}
+
+Subnet4::Subnet4(const isc::asiolink::IOAddress& prefix, uint8_t length,
+                 const Triplet<uint32_t>& t1,
+                 const Triplet<uint32_t>& t2,
+                 const Triplet<uint32_t>& valid_lifetime)
+    :Subnet(prefix, length, t1, t2, valid_lifetime) {
+    if (prefix.getFamily() != AF_INET) {
+        isc_throw(BadValue, "Non IPv4 prefix " << prefix.toText()
+                  << " specified in subnet4");
+    }
+}
+
+void Subnet4::addPool4(const Pool4Ptr& pool) {
+    IOAddress first_addr = pool->getFirstAddress();
+    IOAddress last_addr = pool->getLastAddress();
+
+    if (!inRange(first_addr) || !inRange(last_addr)) {
+        isc_throw(BadValue, "Pool4 (" << first_addr.toText() << "-" << last_addr.toText()
+                  << " does not belong in this (" << prefix_ << "/" << prefix_len_
+                  << ") subnet4");
+    }
+
+    /// @todo: Check that pools do not overlap
+
+    pools_.push_back(pool);
+}
+
+Pool4Ptr Subnet4::getPool4(const isc::asiolink::IOAddress& hint /* = IOAddress("::")*/ ) {
+    Pool4Ptr candidate;
+    for (Pool4Collection::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);
+}
+
+void
+Subnet4::validateOption(const OptionPtr& option) const {
+    if (!option) {
+        isc_throw(isc::BadValue, "option configured for subnet must not be NULL");
+    } else if (option->getUniverse() != Option::V4) {
+        isc_throw(isc::BadValue, "expected V4 option to be added to the subnet");
+    }
+}
+
+bool Subnet4::inPool(const isc::asiolink::IOAddress& addr) const {
+
+    // Let's start with checking if it even belongs to that subnet.
+    if (!inRange(addr)) {
+        return (false);
+    }
+
+    for (Pool4Collection::const_iterator pool = pools_.begin(); pool != pools_.end(); ++pool) {
+        if ((*pool)->inRange(addr)) {
+            return (true);
+        }
+    }
+    // there's no pool that address belongs to
+    return (false);
+}
+
+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);
+}
+
+void
+Subnet6::validateOption(const OptionPtr& option) const {
+    if (!option) {
+        isc_throw(isc::BadValue, "option configured for subnet must not be NULL");
+    } else if (option->getUniverse() != Option::V6) {
+        isc_throw(isc::BadValue, "expected V6 option to be added to the subnet");
+    }
+}
+
+bool Subnet6::inPool(const isc::asiolink::IOAddress& addr) const {
+
+    // Let's start with checking if it even belongs to that subnet.
+    if (!inRange(addr)) {
+        return (false);
+    }
+
+    for (Pool6Collection::const_iterator pool = pools_.begin(); pool != pools_.end(); ++pool) {
+        if ((*pool)->inRange(addr)) {
+            return (true);
+        }
+    }
+    // there's no pool that address belongs to
+    return (false);
+}
+
+} // end of isc::dhcp namespace
+} // end of isc namespace
diff --git a/src/lib/dhcpsrv/subnet.h b/src/lib/dhcpsrv/subnet.h
new file mode 100644
index 0000000..aa1ef1f
--- /dev/null
+++ b/src/lib/dhcpsrv/subnet.h
@@ -0,0 +1,518 @@
+// Copyright (C) 2012 Internet Systems Consortium, Inc. ("ISC")
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+// AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+// PERFORMANCE OF THIS SOFTWARE.
+
+#ifndef SUBNET_H
+#define SUBNET_H
+
+#include <boost/shared_ptr.hpp>
+#include <boost/multi_index_container.hpp>
+#include <boost/multi_index/hashed_index.hpp>
+#include <boost/multi_index/sequenced_index.hpp>
+#include <boost/multi_index/mem_fun.hpp>
+#include <boost/multi_index/member.hpp>
+
+#include <asiolink/io_address.h>
+#include <dhcp/option.h>
+#include <dhcpsrv/pool.h>
+#include <dhcpsrv/triplet.h>
+
+namespace isc {
+namespace dhcp {
+
+/// @brief a base class for Subnet4 and Subnet6
+///
+/// This class presents a common base for IPv4 and IPv6 subnets.
+/// In a physical sense, a subnet defines a single network link with all devices
+/// attached to it. In most cases all devices attached to a single link can
+/// share the same parameters. Therefore Subnet holds several values that are
+/// typically shared by all hosts: renew timer (T1), rebind timer (T2) and
+/// leased addresses lifetime (valid-lifetime). It also holds the set
+/// of DHCP option instances configured for the subnet. These options are
+/// included in DHCP messages being sent to clients which are connected
+/// to the particular subnet.
+///
+/// @todo: Implement support for options here
+
+
+/// @brief Unique indentifier for a subnet (both v4 and v6)
+typedef uint32_t SubnetID;
+
+class Subnet {
+public:
+
+    /// @brief Option descriptor.
+    ///
+    /// Option descriptor holds information about option configured for
+    /// a particular subnet. This information comprises the actual option
+    /// instance and information whether this option is sent to DHCP client
+    /// only on request (persistent = false) or always (persistent = true).
+    struct OptionDescriptor {
+        /// Option instance.
+        OptionPtr option;
+        /// Persistent flag, if true option is always sent to the client,
+        /// if false option is sent to the client on request.
+        bool persistent;
+
+        /// @brief Constructor.
+        ///
+        /// @param opt option
+        /// @param persist if true option is always sent.
+        OptionDescriptor(OptionPtr& opt, bool persist)
+            : option(opt), persistent(persist) {};
+
+        /// @brief Constructor
+        ///
+        /// @param persist if true option is always sent.
+        OptionDescriptor(bool persist)
+            : option(OptionPtr()), persistent(persist) {};
+    };
+
+    /// @brief Extractor class to extract key with another key.
+    ///
+    /// This class solves the problem of accessing index key values
+    /// that are stored in objects nested in other objects.
+    /// Each OptionDescriptor structure contains the OptionPtr object.
+    /// The value retured by one of its accessors (getType) is used
+    /// as an indexing value in the multi_index_container defined below.
+    /// There is no easy way to mark that value returned by Option::getType
+    /// should be an index of this multi_index_container. There are standard
+    /// key extractors such as 'member' or 'mem_fun' but they are not
+    /// sufficient here. The former can be used to mark that member of
+    /// the structure that is held in the container should be used as an
+    /// indexing value. The latter can be used if the indexing value is
+    /// a product of the class being held in the container. In this complex
+    /// scenario when the indexing value is a product of the function that
+    /// is wrapped by the structure, this new extractor template has to be
+    /// defined. The template class provides a 'chain' of two extractors
+    /// to access the value returned by nested object and to use it as
+    /// indexing value.
+    /// For some more examples of complex keys see:
+    /// http://www.cs.brown.edu/~jwicks/boost/libs/multi_index/doc/index.html
+    ///
+    /// @tparam KeyExtractor1 extractor used to access data in
+    /// OptionDescriptor::option
+    /// @tparam KeyExtractor2 extractor used to access
+    /// OptionDescriptor::option member.
+    template<typename KeyExtractor1, typename KeyExtractor2>
+    class KeyFromKey {
+    public:
+        typedef typename KeyExtractor1::result_type result_type;
+
+        /// @brief Constructor.
+        KeyFromKey()
+            : key1_(KeyExtractor1()), key2_(KeyExtractor2()) { };
+
+        /// @brief Extract key with another key.
+        ///
+        /// @param arg the key value.
+        ///
+        /// @tparam key value type.
+        template<typename T>
+        result_type operator() (T& arg) const {
+            return (key1_(key2_(arg)));
+        }
+    private:
+        KeyExtractor1 key1_; ///< key 1.
+        KeyExtractor2 key2_; ///< key 2.
+    };
+
+    /// @brief Multi index container for DHCP option descriptors.
+    ///
+    /// This container comprises three indexes to access option
+    /// descriptors:
+    /// - sequenced index: used to access elements in the order they
+    /// have been added to the container,
+    /// - option type index: used to search option descriptors containing
+    /// options with specific option code (aka option type).
+    /// - persistency flag index: used to search option descriptors with
+    /// 'persistent' flag set to true.
+    ///
+    /// This container is the equivalent of three separate STL containers:
+    /// - std::list of all options,
+    /// - std::multimap of options with option code used as a multimap key,
+    /// - std::multimap of option descriptors with option persistency flag
+    /// used as a multimap key.
+    /// The major advantage of this container over 3 separate STL containers
+    /// is automatic synchronization of all indexes when elements are added,
+    /// removed or modified in the container. With separate containers,
+    /// the synchronization would have to be guaranteed by the Subnet class
+    /// code. This would increase code complexity and presumably it would
+    /// be much harder to add new search criteria (indexes).
+    ///
+    /// @todo we may want to search for options using option spaces when
+    /// they are implemented.
+    ///
+    /// @see http://www.boost.org/doc/libs/1_51_0/libs/multi_index/doc/index.html
+    typedef boost::multi_index_container<
+        // Container comprises elements of OptionDescriptor type.
+        OptionDescriptor,
+        // Here we start enumerating various indexes.
+        boost::multi_index::indexed_by<
+            // Sequenced index allows accessing elements in the same way
+            // as elements in std::list.
+            // Sequenced is an index #0.
+            boost::multi_index::sequenced<>,
+            // Start definition of index #1.
+            boost::multi_index::hashed_non_unique<
+                // KeyFromKey is the index key extractor that allows accessing
+                // option type being held by the OptionPtr through
+                // OptionDescriptor structure.
+                KeyFromKey<
+                    // Use option type as the index key. The type is held
+                    // in OptionPtr object so we have to call Option::getType
+                    // to retrieve this key for each element.
+                    boost::multi_index::mem_fun<
+                        Option,
+                        uint16_t,
+                        &Option::getType
+                    >,
+                    // Indicate that OptionPtr is a member of
+                    // OptionDescriptor structure.
+                    boost::multi_index::member<
+                        OptionDescriptor,
+                        OptionPtr,
+                        &OptionDescriptor::option
+                    >
+                 >
+            >,
+            // Start definition of index #2.
+            // Use 'persistent' struct member as a key.
+            boost::multi_index::hashed_non_unique<
+                boost::multi_index::member<
+                    OptionDescriptor,
+                    bool,
+                    &OptionDescriptor::persistent
+                >
+            >
+        >
+    > OptionContainer;
+
+    /// Type of the index #1 - option type.
+    typedef OptionContainer::nth_index<1>::type OptionContainerTypeIndex;
+    /// Pair of iterators to represent the range of options having the
+    /// same option type value. The first element in this pair represents
+    /// the begining of the range, the second element represents the end.
+    typedef std::pair<OptionContainerTypeIndex::const_iterator,
+                      OptionContainerTypeIndex::const_iterator> OptionContainerTypeRange;
+    /// Type of the index #2 - option persistency flag.
+    typedef OptionContainer::nth_index<2>::type OptionContainerPersistIndex;
+
+    /// @brief checks if specified address is in range
+    bool inRange(const isc::asiolink::IOAddress& addr) const;
+
+    /// @brief Add new option instance to the collection.
+    ///
+    /// @param option option instance.
+    /// @param persistent if true, send an option regardless if client
+    /// requested it or not.
+    ///
+    /// @throw isc::BadValue if invalid option provided.
+    void addOption(OptionPtr& option, bool persistent = false);
+
+    /// @brief Delete all options configured for the subnet.
+    void delOptions();
+
+    /// @brief checks if the specified address is in pools
+    ///
+    /// Note the difference between inSubnet() and inPool(). For a given
+    /// subnet (e.g. 2001::/64) there may be one or more pools defined
+    /// that may or may not cover entire subnet, e.g. pool 2001::1-2001::10).
+    /// inPool() returning true implies inSubnet(), but the reverse implication
+    /// is not always true. For the given example, 2001::1234:abcd would return
+    /// true for inSubnet(), but false for inPool() check.
+    ///
+    /// @param addr this address will be checked if it belongs to any pools in
+    ///        that subnet
+    /// @return true if the address is in any of the pools
+    virtual bool inPool(const isc::asiolink::IOAddress& addr) const = 0;
+
+    /// @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_);
+    }
+
+    /// @brief Return a collection of options.
+    ///
+    /// @return reference to collection of options configured for a subnet.
+    /// The returned reference is valid as long as the Subnet object which
+    /// returned it still exists.
+    const OptionContainer& getOptions() const {
+        return (options_);
+    }
+
+    /// @brief returns the last address that was tried from this pool
+    ///
+    /// This method returns the last address that was attempted to be allocated
+    /// from this subnet. This is used as helper information for the next
+    /// iteration of the allocation algorithm.
+    ///
+    /// @todo: Define map<SubnetID, IOAddress> somewhere in the
+    ///        AllocEngine::IterativeAllocator and keep the data there
+    ///
+    /// @return address that was last tried from this pool
+    isc::asiolink::IOAddress getLastAllocated() const {
+        return (last_allocated_);
+    }
+
+    /// @brief sets the last address that was tried from this pool
+    ///
+    /// This method sets the last address that was attempted to be allocated
+    /// from this subnet. This is used as helper information for the next
+    /// iteration of the allocation algorithm.
+    ///
+    /// @todo: Define map<SubnetID, IOAddress> somewhere in the
+    ///        AllocEngine::IterativeAllocator and keep the data there
+    void setLastAllocated(const isc::asiolink::IOAddress& addr) {
+        last_allocated_ = addr;
+    }
+
+    /// @brief returns unique ID for that subnet
+    /// @return unique ID for that subnet
+    SubnetID getID() const { return (id_); }
+
+    /// @brief returns subnet parameters (prefix and prefix length)
+    ///
+    /// @return (prefix, prefix length) pair
+    std::pair<isc::asiolink::IOAddress, uint8_t> get() const {
+        return (std::make_pair(prefix_, prefix_len_));
+    }
+
+    /// @brief returns textual representation of the subnet (e.g. "2001:db8::/64")
+    ///
+    /// @return textual representation
+    virtual std::string toText() const;
+
+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 virtual destructor
+    ///
+    /// A virtual destructor is needed because other classes
+    /// derive from this class.
+    virtual ~Subnet() { };
+
+    /// @brief returns the next unique Subnet-ID
+    ///
+    /// @return the next unique Subnet-ID
+    static SubnetID getNextID() {
+        static SubnetID id = 0;
+        return (id++);
+    }
+
+    /// @brief Check if option is valid and can be added to a subnet.
+    ///
+    /// @param option option to be validated.
+    virtual void validateOption(const OptionPtr& option) const = 0;
+
+    /// @brief subnet-id
+    ///
+    /// Subnet-id is a unique value that can be used to find or identify
+    /// a Subnet4 or Subnet6.
+    SubnetID 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 collection of DHCP options configured for a subnet.
+    OptionContainer options_;
+
+    /// @brief last allocated address
+    ///
+    /// This is the last allocated address that was previously allocated from
+    /// this particular subnet. Some allocation algorithms (e.g. iterative) use
+    /// that value, others do not. It should be noted that although the value
+    /// is usually correct, there are cases when it is invalid, e.g. after
+    /// removing a pool, restarting or changing allocation algorithms. For
+    /// that purpose it should be only considered a help that should not be
+    /// fully trusted.
+    isc::asiolink::IOAddress last_allocated_;
+};
+
+/// @brief A configuration holder for IPv4 subnet.
+///
+/// This class represents an IPv4 subnet.
+class Subnet4 : public Subnet {
+public:
+
+    /// @brief Constructor with all parameters
+    ///
+    /// @param prefix Subnet4 prefix
+    /// @param length prefix length
+    /// @param t1 renewal timer (in seconds)
+    /// @param t2 rebind timer (in seconds)
+    /// @param valid_lifetime preferred lifetime of leases (in seconds)
+    Subnet4(const isc::asiolink::IOAddress& prefix, uint8_t length,
+            const Triplet<uint32_t>& t1,
+            const Triplet<uint32_t>& t2,
+            const Triplet<uint32_t>& valid_lifetime);
+
+    /// @brief Returns a pool that specified address belongs to
+    ///
+    /// @param hint address that the returned pool should cover (optional)
+    /// @return Pointer to found pool4 (or NULL)
+    Pool4Ptr getPool4(const isc::asiolink::IOAddress& hint =
+                      isc::asiolink::IOAddress("0.0.0.0"));
+
+    /// @brief Adds a new pool.
+    /// @param pool pool to be added
+    void addPool4(const Pool4Ptr& 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 Pool4Collection& getPools() const {
+        return pools_;
+    }
+
+    /// @brief checks if the specified address is in pools
+    ///
+    /// See the description in \ref Subnet::inPool().
+    ///
+    /// @param addr this address will be checked if it belongs to any pools in that subnet
+    /// @return true if the address is in any of the pools
+    bool inPool(const isc::asiolink::IOAddress& addr) const;
+
+protected:
+
+    /// @brief Check if option is valid and can be added to a subnet.
+    ///
+    /// @param option option to be validated.
+    ///
+    /// @throw isc::BadValue if provided option is invalid.
+    virtual void validateOption(const OptionPtr& option) const;
+
+    /// @brief collection of pools in that list
+    Pool4Collection pools_;
+};
+
+/// @brief A pointer to a Subnet4 object
+typedef boost::shared_ptr<Subnet4> Subnet4Ptr;
+
+/// @brief A collection of Subnet6 objects
+typedef std::vector<Subnet4Ptr> Subnet4Collection;
+
+
+/// @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_;
+    }
+
+    /// @brief checks if the specified address is in pools
+    ///
+    /// See the description in \ref Subnet::inPool().
+    ///
+    /// @param addr this address will be checked if it belongs to any pools in that subnet
+    /// @return true if the address is in any of the pools
+    bool inPool(const isc::asiolink::IOAddress& addr) const;
+
+protected:
+
+    /// @brief Check if option is valid and can be added to a subnet.
+    ///
+    /// @param option option to be validated.
+    ///
+    /// @throw isc::BadValue if provided option is invalid.
+    virtual void validateOption(const OptionPtr& option) const;
+
+    /// @brief collection of pools in that list
+    Pool6Collection pools_;
+
+    /// @brief a triplet with preferred lifetime (in seconds)
+    Triplet<uint32_t> preferred_;
+};
+
+/// @brief A pointer to a Subnet6 object
+typedef boost::shared_ptr<Subnet6> Subnet6Ptr;
+
+/// @brief A collection of Subnet6 objects
+typedef std::vector<Subnet6Ptr> Subnet6Collection;
+
+} // end of isc::dhcp namespace
+} // end of isc namespace
+
+#endif // SUBNET_T
diff --git a/src/lib/dhcpsrv/tests/Makefile.am b/src/lib/dhcpsrv/tests/Makefile.am
new file mode 100644
index 0000000..8de5fda
--- /dev/null
+++ b/src/lib/dhcpsrv/tests/Makefile.am
@@ -0,0 +1,70 @@
+SUBDIRS = .
+
+AM_CPPFLAGS = -I$(top_builddir)/src/lib -I$(top_srcdir)/src/lib
+AM_CPPFLAGS += $(BOOST_INCLUDES)
+AM_CPPFLAGS += -DTEST_DATA_BUILDDIR=\"$(abs_top_builddir)/src/lib/dhcp/tests\"
+AM_CPPFLAGS += -DINSTALL_PROG=\"$(abs_top_srcdir)/install-sh\"
+
+AM_CXXFLAGS = $(B10_CXXFLAGS)
+
+# Some versions of GCC warn about some versions of Boost regarding
+# missing initializer for members in its posix_time.
+# https://svn.boost.org/trac/boost/ticket/3477
+# But older GCC compilers don't have the flag.
+AM_CXXFLAGS += $(WARNING_NO_MISSING_FIELD_INITIALIZERS_CFLAG)
+
+if USE_STATIC_LINK
+AM_LDFLAGS = -static
+endif
+
+CLEANFILES = *.gcno *.gcda
+
+TESTS_ENVIRONMENT = \
+	$(LIBTOOL) --mode=execute $(VALGRIND_COMMAND)
+
+TESTS =
+if HAVE_GTEST
+TESTS += libdhcpsrv_unittests
+
+libdhcpsrv_unittests_SOURCES  = run_unittests.cc
+libdhcpsrv_unittests_SOURCES += addr_utilities_unittest.cc
+libdhcpsrv_unittests_SOURCES += alloc_engine_unittest.cc
+libdhcpsrv_unittests_SOURCES += cfgmgr_unittest.cc
+libdhcpsrv_unittests_SOURCES += lease_mgr_factory_unittest.cc
+libdhcpsrv_unittests_SOURCES += lease_mgr_unittest.cc
+libdhcpsrv_unittests_SOURCES += memfile_lease_mgr_unittest.cc
+if HAVE_MYSQL
+libdhcpsrv_unittests_SOURCES += mysql_lease_mgr_unittest.cc
+endif
+libdhcpsrv_unittests_SOURCES += pool_unittest.cc
+libdhcpsrv_unittests_SOURCES += schema_copy.h
+libdhcpsrv_unittests_SOURCES += subnet_unittest.cc
+libdhcpsrv_unittests_SOURCES += triplet_unittest.cc
+
+libdhcpsrv_unittests_CPPFLAGS = $(AM_CPPFLAGS) $(GTEST_INCLUDES) $(LOG4CPLUS_INCLUDES)
+if HAVE_MYSQL
+libdhcpsrv_unittests_CPPFLAGS += $(MYSQL_CPPFLAGS)
+endif
+
+libdhcpsrv_unittests_LDFLAGS  = $(AM_LDFLAGS)  $(GTEST_LDFLAGS)
+if HAVE_MYSQL
+libdhcpsrv_unittests_LDFLAGS  += $(MYSQL_LIBS)
+endif
+
+libdhcpsrv_unittests_CXXFLAGS = $(AM_CXXFLAGS)
+if USE_CLANGPP
+# This is to workaround unused variables tcout and tcerr in
+# log4cplus's streams.h and unused parameters from some of the
+# Boost headers.
+libdhcpsrv_unittests_CXXFLAGS += -Wno-unused-variable -Wno-unused-parameter
+endif
+
+libdhcpsrv_unittests_LDADD  = $(top_builddir)/src/lib/dhcpsrv/libb10-dhcpsrv.la
+libdhcpsrv_unittests_LDADD += $(top_builddir)/src/lib/dhcp/libb10-dhcp++.la
+libdhcpsrv_unittests_LDADD += $(top_builddir)/src/lib/asiolink/libb10-asiolink.la
+libdhcpsrv_unittests_LDADD += $(top_builddir)/src/lib/exceptions/libb10-exceptions.la
+libdhcpsrv_unittests_LDADD += $(top_builddir)/src/lib/log/libb10-log.la
+libdhcpsrv_unittests_LDADD += $(GTEST_LDADD)
+endif
+
+noinst_PROGRAMS = $(TESTS)
diff --git a/src/lib/dhcpsrv/tests/addr_utilities_unittest.cc b/src/lib/dhcpsrv/tests/addr_utilities_unittest.cc
new file mode 100644
index 0000000..9e08034
--- /dev/null
+++ b/src/lib/dhcpsrv/tests/addr_utilities_unittest.cc
@@ -0,0 +1,154 @@
+
+// Copyright (C) 2010  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 <stdint.h>
+#include <stdlib.h>
+
+#include <gtest/gtest.h>
+#include <vector>
+
+#include <dhcpsrv/addr_utilities.h>
+
+using namespace std;
+using namespace isc::dhcp;
+using namespace isc::asiolink;
+
+// This test verifies that lastAddrInPrefix is able to handle IPv4 operations.
+TEST(AddrUtilitiesTest, lastAddrInPrefix4) {
+    IOAddress addr1("192.0.2.1");
+
+    // Prefixes rounded to addresses are easy...
+    EXPECT_EQ("192.255.255.255", lastAddrInPrefix(addr1, 8).toText());
+    EXPECT_EQ("192.0.255.255",   lastAddrInPrefix(addr1, 16).toText());
+    EXPECT_EQ("192.0.2.255",     lastAddrInPrefix(addr1, 24).toText());
+
+    // these are trickier
+    EXPECT_EQ("192.0.2.127", lastAddrInPrefix(addr1, 25).toText());
+    EXPECT_EQ("192.0.2.63",  lastAddrInPrefix(addr1, 26).toText());
+    EXPECT_EQ("192.0.2.31",  lastAddrInPrefix(addr1, 27).toText());
+    EXPECT_EQ("192.0.2.15",  lastAddrInPrefix(addr1, 28).toText());
+    EXPECT_EQ("192.0.2.7",   lastAddrInPrefix(addr1, 29).toText());
+    EXPECT_EQ("192.0.2.3",   lastAddrInPrefix(addr1, 30).toText());
+
+    // that doesn't make much sense as /31 subnet consists of network address
+    // and a broadcast address, with 0 usable addresses.
+    EXPECT_EQ("192.0.2.1",   lastAddrInPrefix(addr1, 31).toText());
+    EXPECT_EQ("192.0.2.1",   lastAddrInPrefix(addr1, 32).toText());
+
+    // Let's check extreme cases
+    IOAddress anyAddr("0.0.0.0");
+    EXPECT_EQ("127.255.255.255", lastAddrInPrefix(anyAddr, 1).toText());
+    EXPECT_EQ("255.255.255.255", lastAddrInPrefix(anyAddr, 0).toText());
+    EXPECT_EQ("0.0.0.0", lastAddrInPrefix(anyAddr, 32).toText());
+}
+
+// This test checks if firstAddrInPrefix is able to handle IPv4 operations.
+TEST(AddrUtilitiesTest, firstAddrInPrefix4) {
+    IOAddress addr1("192.223.2.255");
+
+    // Prefixes rounded to addresses are easy...
+    EXPECT_EQ("192.0.0.0",   firstAddrInPrefix(addr1, 8).toText());
+    EXPECT_EQ("192.223.0.0", firstAddrInPrefix(addr1, 16).toText());
+    EXPECT_EQ("192.223.2.0", firstAddrInPrefix(addr1, 24).toText());
+
+    // these are trickier
+    EXPECT_EQ("192.223.2.128", firstAddrInPrefix(addr1, 25).toText());
+    EXPECT_EQ("192.223.2.192", firstAddrInPrefix(addr1, 26).toText());
+    EXPECT_EQ("192.223.2.224", firstAddrInPrefix(addr1, 27).toText());
+    EXPECT_EQ("192.223.2.240", firstAddrInPrefix(addr1, 28).toText());
+    EXPECT_EQ("192.223.2.248", firstAddrInPrefix(addr1, 29).toText());
+    EXPECT_EQ("192.223.2.252", firstAddrInPrefix(addr1, 30).toText());
+
+    // that doesn't make much sense as /31 subnet consists of network address
+    // and a broadcast address, with 0 usable addresses.
+    EXPECT_EQ("192.223.2.254", firstAddrInPrefix(addr1, 31).toText());
+    EXPECT_EQ("192.223.2.255", firstAddrInPrefix(addr1, 32).toText());
+
+    // Let's check extreme cases.
+    IOAddress bcast("255.255.255.255");
+    EXPECT_EQ("128.0.0.0", firstAddrInPrefix(bcast, 1).toText());
+    EXPECT_EQ("0.0.0.0", firstAddrInPrefix(bcast, 0).toText());
+    EXPECT_EQ("255.255.255.255", firstAddrInPrefix(bcast, 32).toText());
+
+}
+
+/// This test checks if lastAddrInPrefix properly supports IPv6 operations
+TEST(AddrUtilitiesTest, lastAddrInPrefix6) {
+    IOAddress addr1("2001:db8:1:1234:5678:abcd:1234:beef");
+
+    // Prefixes rounded to nibbles are easy...
+    EXPECT_EQ("2001:db8:1:1234:5678:abcd:1234:ffff",
+              lastAddrInPrefix(addr1, 112).toText());
+    EXPECT_EQ("2001:db8:1:1234:5678:abcd:123f:ffff",
+              lastAddrInPrefix(addr1, 108).toText());
+    EXPECT_EQ("2001:db8:1:1234:5678:abcd:12ff:ffff",
+              lastAddrInPrefix(addr1, 104).toText());
+    EXPECT_EQ("2001:db8:1:1234:ffff:ffff:ffff:ffff",
+              lastAddrInPrefix(addr1, 64).toText());
+
+    IOAddress addr2("2001::");
+
+    // These are tricker, though, as they are done in 1 bit increments
+
+    // the last address in 2001::/127 pool should be 2001::1
+    EXPECT_EQ("2001::1", lastAddrInPrefix(addr2, 127).toText());
+
+    EXPECT_EQ("2001::3", lastAddrInPrefix(addr2, 126).toText());
+    EXPECT_EQ("2001::7", lastAddrInPrefix(addr2, 125).toText());
+    EXPECT_EQ("2001::f", lastAddrInPrefix(addr2, 124).toText());
+    EXPECT_EQ("2001::1f", lastAddrInPrefix(addr2, 123).toText());
+    EXPECT_EQ("2001::3f", lastAddrInPrefix(addr2, 122).toText());
+    EXPECT_EQ("2001::7f", lastAddrInPrefix(addr2, 121).toText());
+    EXPECT_EQ("2001::ff", lastAddrInPrefix(addr2, 120).toText());
+
+    // Let's check extreme cases
+    IOAddress anyAddr("::");
+    EXPECT_EQ("7fff:ffff:ffff:ffff:ffff:ffff:ffff:ffff",
+              lastAddrInPrefix(anyAddr, 1).toText());
+    EXPECT_EQ("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff",
+              lastAddrInPrefix(anyAddr, 0).toText());
+    EXPECT_EQ("::", lastAddrInPrefix(anyAddr, 128).toText());
+}
+
+/// This test checks if firstAddrInPrefix properly supports IPv6 operations
+TEST(AddrUtilitiesTest, firstAddrInPrefix6) {
+    IOAddress addr1("2001:db8:1:1234:5678:1234:abcd:beef");
+
+    // Prefixes rounded to nibbles are easy...
+    EXPECT_EQ("2001:db8:1:1234:5678:1234::",
+              firstAddrInPrefix(addr1, 96).toText());
+    EXPECT_EQ("2001:db8:1:1234:5678:1230::",
+              firstAddrInPrefix(addr1, 92).toText());
+    EXPECT_EQ("2001:db8:1:1234:5678:1200::",
+              firstAddrInPrefix(addr1, 88).toText());
+    EXPECT_EQ("2001:db8:1:1234::",
+              firstAddrInPrefix(addr1, 64).toText());
+
+    IOAddress addr2("2001::ffff");
+
+    // These are tricker, though, as they are done in 1 bit increments
+
+    // the first address in 2001::/127 pool should be 2001::1
+    EXPECT_EQ("2001::fffe", firstAddrInPrefix(addr2, 127).toText());
+
+    EXPECT_EQ("2001::fffc", firstAddrInPrefix(addr2, 126).toText());
+    EXPECT_EQ("2001::fff8", firstAddrInPrefix(addr2, 125).toText());
+    EXPECT_EQ("2001::fff0", firstAddrInPrefix(addr2, 124).toText());
+    EXPECT_EQ("2001::ffe0", firstAddrInPrefix(addr2, 123).toText());
+    EXPECT_EQ("2001::ffc0", firstAddrInPrefix(addr2, 122).toText());
+    EXPECT_EQ("2001::ff80", firstAddrInPrefix(addr2, 121).toText());
+    EXPECT_EQ("2001::ff00", firstAddrInPrefix(addr2, 120).toText());
+}
diff --git a/src/lib/dhcpsrv/tests/alloc_engine_unittest.cc b/src/lib/dhcpsrv/tests/alloc_engine_unittest.cc
new file mode 100644
index 0000000..9fd8e6c
--- /dev/null
+++ b/src/lib/dhcpsrv/tests/alloc_engine_unittest.cc
@@ -0,0 +1,341 @@
+// 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 <config.h>
+
+#include <asiolink/io_address.h>
+#include <dhcp/duid.h>
+#include <dhcpsrv/alloc_engine.h>
+#include <dhcpsrv/cfgmgr.h>
+#include <dhcpsrv/lease_mgr.h>
+#include <dhcpsrv/lease_mgr_factory.h>
+#include <dhcpsrv/memfile_lease_mgr.h>
+
+#include <boost/shared_ptr.hpp>
+#include <boost/scoped_ptr.hpp>
+
+#include <iostream>
+#include <sstream>
+#include <map>
+
+#include <gtest/gtest.h>
+
+using namespace std;
+using namespace isc;
+using namespace isc::asiolink;
+using namespace isc::dhcp;
+
+namespace {
+
+class NakedAllocEngine : public AllocEngine {
+public:
+    NakedAllocEngine(AllocEngine::AllocType engine_type, unsigned int attempts)
+        :AllocEngine(engine_type, attempts) {
+    }
+    using AllocEngine::Allocator;
+    using AllocEngine::IterativeAllocator;
+};
+
+// empty class for now, but may be extended once Addr6 becomes bigger
+class AllocEngineTest : public ::testing::Test {
+public:
+    AllocEngineTest() {
+        duid_ = boost::shared_ptr<DUID>(new DUID(vector<uint8_t>(8, 0x42)));
+        iaid_ = 42;
+
+        // instantiate cfg_mgr
+        CfgMgr& cfg_mgr = CfgMgr::instance();
+
+        subnet_ = Subnet6Ptr(new Subnet6(IOAddress("2001:db8:1::"), 56, 1, 2, 3, 4));
+        pool_ = Pool6Ptr(new Pool6(Pool6::TYPE_IA, IOAddress("2001:db8:1::10"),
+                                   IOAddress("2001:db8:1::20")));
+        subnet_->addPool6(pool_);
+        cfg_mgr.addSubnet6(subnet_);
+
+        factory_.create("type=memfile");
+    }
+
+    void checkLease6(const Lease6Ptr& lease) {
+        // that is belongs to the right subnet
+        EXPECT_EQ(lease->subnet_id_, subnet_->getID());
+        EXPECT_TRUE(subnet_->inRange(lease->addr_));
+        EXPECT_TRUE(subnet_->inPool(lease->addr_));
+
+        // that it have proper parameters
+        EXPECT_EQ(iaid_, lease->iaid_);
+        EXPECT_EQ(subnet_->getValid(), lease->valid_lft_);
+        EXPECT_EQ(subnet_->getPreferred(), lease->preferred_lft_);
+        EXPECT_EQ(subnet_->getT1(), lease->t1_);
+        EXPECT_EQ(subnet_->getT2(), lease->t2_);
+        EXPECT_EQ(0, lease->prefixlen_); // this is IA_NA, not IA_PD
+        EXPECT_TRUE(false == lease->fqdn_fwd_);
+        EXPECT_TRUE(false == lease->fqdn_rev_);
+        EXPECT_TRUE(*lease->duid_ == *duid_);
+        // @todo: check cltt
+     }
+
+    ~AllocEngineTest() {
+        factory_.destroy();
+    }
+
+    DuidPtr duid_;
+    uint32_t iaid_;
+    Subnet6Ptr subnet_;
+    Pool6Ptr pool_;
+    LeaseMgrFactory factory_;
+};
+
+// This test checks if the Allocation Engine can be instantiated and that it
+// parses parameters string properly.
+TEST_F(AllocEngineTest, constructor) {
+    boost::scoped_ptr<AllocEngine> x;
+
+    // Hashed and random allocators are not supported yet
+    ASSERT_THROW(x.reset(new AllocEngine(AllocEngine::ALLOC_HASHED, 5)), NotImplemented);
+    ASSERT_THROW(x.reset(new AllocEngine(AllocEngine::ALLOC_RANDOM, 5)), NotImplemented);
+
+    ASSERT_NO_THROW(x.reset(new AllocEngine(AllocEngine::ALLOC_ITERATIVE, 100)));
+}
+
+/// @todo: This method is taken from mysql_lease_mgr_utilities.cc from ticket
+/// #2342. Get rid of one instance once the code is merged
+void
+detailCompareLease6(const Lease6Ptr& first, const Lease6Ptr& second) {
+    EXPECT_EQ(first->type_, second->type_);
+
+    // Compare address strings - odd things happen when they are different
+    // as the EXPECT_EQ appears to call the operator uint32_t() function,
+    // which causes an exception to be thrown for IPv6 addresses.
+    EXPECT_EQ(first->addr_.toText(), second->addr_.toText());
+    EXPECT_EQ(first->prefixlen_, second->prefixlen_);
+    EXPECT_EQ(first->iaid_, second->iaid_);
+    EXPECT_TRUE(*first->duid_ == *second->duid_);
+    EXPECT_EQ(first->preferred_lft_, second->preferred_lft_);
+    EXPECT_EQ(first->valid_lft_, second->valid_lft_);
+    EXPECT_EQ(first->cltt_, second->cltt_);
+    EXPECT_EQ(first->subnet_id_, second->subnet_id_);
+}
+
+
+// This test checks if the simple allocation can succeed
+TEST_F(AllocEngineTest, simpleAlloc) {
+    boost::scoped_ptr<AllocEngine> engine;
+    ASSERT_NO_THROW(engine.reset(new AllocEngine(AllocEngine::ALLOC_ITERATIVE, 100)));
+    ASSERT_TRUE(engine);
+
+    Lease6Ptr lease = engine->allocateAddress6(subnet_, duid_, iaid_, IOAddress("::"),
+                                               false);
+
+    // check that we got a lease
+    ASSERT_TRUE(lease);
+
+    // do all checks on the lease
+    checkLease6(lease);
+
+    // Check that the lease is indeed in LeaseMgr
+    Lease6Ptr from_mgr = LeaseMgrFactory::instance().getLease6(lease->addr_);
+    ASSERT_TRUE(from_mgr);
+
+    // Now check that the lease in LeaseMgr has the same parameters
+    detailCompareLease6(lease, from_mgr);
+}
+
+// This test checks if the fake allocation (for SOLICIT) can succeed
+TEST_F(AllocEngineTest, fakeAlloc) {
+    boost::scoped_ptr<AllocEngine> engine;
+    ASSERT_NO_THROW(engine.reset(new AllocEngine(AllocEngine::ALLOC_ITERATIVE, 100)));
+    ASSERT_TRUE(engine);
+
+    Lease6Ptr lease = engine->allocateAddress6(subnet_, duid_, iaid_, IOAddress("::"),
+                                               true);
+
+    // check that we got a lease
+    ASSERT_TRUE(lease);
+
+    // do all checks on the lease
+    checkLease6(lease);
+
+    // Check that the lease is NOT in LeaseMgr
+    Lease6Ptr from_mgr = LeaseMgrFactory::instance().getLease6(lease->addr_);
+    ASSERT_FALSE(from_mgr);
+}
+
+// This test checks if the allocation with a hint that is valid (in range,
+// in pool and free) can succeed
+TEST_F(AllocEngineTest, allocWithValidHint) {
+    boost::scoped_ptr<AllocEngine> engine;
+    ASSERT_NO_THROW(engine.reset(new AllocEngine(AllocEngine::ALLOC_ITERATIVE, 100)));
+    ASSERT_TRUE(engine);
+
+    Lease6Ptr lease = engine->allocateAddress6(subnet_, duid_, iaid_,
+                                               IOAddress("2001:db8:1::15"),
+                                               false);
+
+    // check that we got a lease
+    ASSERT_TRUE(lease);
+
+    // we should get what we asked for
+    EXPECT_EQ(lease->addr_.toText(), "2001:db8:1::15");
+
+    // do all checks on the lease
+    checkLease6(lease);
+
+    // Check that the lease is indeed in LeaseMgr
+    Lease6Ptr from_mgr = LeaseMgrFactory::instance().getLease6(lease->addr_);
+    ASSERT_TRUE(from_mgr);
+
+    // Now check that the lease in LeaseMgr has the same parameters
+    detailCompareLease6(lease, from_mgr);
+}
+
+// This test checks if the allocation with a hint that is in range,
+// in pool, but is currently used) can succeed
+TEST_F(AllocEngineTest, allocWithUsedHint) {
+    boost::scoped_ptr<AllocEngine> engine;
+    ASSERT_NO_THROW(engine.reset(new AllocEngine(AllocEngine::ALLOC_ITERATIVE, 100)));
+    ASSERT_TRUE(engine);
+
+    // let's create a lease and put it in the LeaseMgr
+    DuidPtr duid2 = boost::shared_ptr<DUID>(new DUID(vector<uint8_t>(8, 0xff)));
+    Lease6Ptr used(new Lease6(Lease6::LEASE_IA_NA, IOAddress("2001:db8:1::1f"),
+                              duid2, 1, 2, 3, 4, 5, subnet_->getID()));
+    ASSERT_TRUE(LeaseMgrFactory::instance().addLease(used));
+
+    // another client comes in and request an address that is in pool, but
+    // unfortunately it is used already. The same address must not be allocated
+    // twice.
+    Lease6Ptr lease = engine->allocateAddress6(subnet_, duid_, iaid_,
+                                               IOAddress("2001:db8:1::1f"),
+                                               false);
+    // check that we got a lease
+    ASSERT_TRUE(lease);
+
+    // allocated address must be different
+    EXPECT_TRUE(used->addr_.toText() != lease->addr_.toText());
+
+    // we should NOT get what we asked for, because it is used already
+    EXPECT_TRUE(lease->addr_.toText() != "2001:db8:1::1f");
+
+    // do all checks on the lease
+    checkLease6(lease);
+
+    // Check that the lease is indeed in LeaseMgr
+    Lease6Ptr from_mgr = LeaseMgrFactory::instance().getLease6(lease->addr_);
+    ASSERT_TRUE(from_mgr);
+
+    // Now check that the lease in LeaseMgr has the same parameters
+    detailCompareLease6(lease, from_mgr);
+}
+
+// This test checks if the allocation with a hint that is out the blue
+// can succeed. The invalid hint should be ignored completely.
+TEST_F(AllocEngineTest, allocBogusHint) {
+    boost::scoped_ptr<AllocEngine> engine;
+    ASSERT_NO_THROW(engine.reset(new AllocEngine(AllocEngine::ALLOC_ITERATIVE, 100)));
+    ASSERT_TRUE(engine);
+
+    // Client would like to get a 3000::abc lease, which does not belong to any
+    // supported lease. Allocation engine should ignore it and carry on
+    // with the normal allocation
+    Lease6Ptr lease = engine->allocateAddress6(subnet_, duid_, iaid_,
+                                               IOAddress("3000::abc"),
+                                               false);
+    // check that we got a lease
+    ASSERT_TRUE(lease);
+
+    // we should NOT get what we asked for, because it is used already
+    EXPECT_TRUE(lease->addr_.toText() != "3000::abc");
+
+    // do all checks on the lease
+    checkLease6(lease);
+
+    // Check that the lease is indeed in LeaseMgr
+    Lease6Ptr from_mgr = LeaseMgrFactory::instance().getLease6(lease->addr_);
+    ASSERT_TRUE(from_mgr);
+
+    // Now check that the lease in LeaseMgr has the same parameters
+    detailCompareLease6(lease, from_mgr);
+}
+
+// This test verifies that the allocator picks addresses that belong to the
+// pool
+TEST_F(AllocEngineTest, IterativeAllocator) {
+    boost::scoped_ptr<NakedAllocEngine::Allocator>
+        alloc(new NakedAllocEngine::IterativeAllocator());
+
+    for (int i = 0; i < 1000; ++i) {
+        IOAddress candidate = alloc->pickAddress(subnet_, duid_, IOAddress("::"));
+        EXPECT_TRUE(subnet_->inPool(candidate));
+    }
+}
+
+
+// This test verifies that the iterative allocator really walks over all addresses
+// in all pools in specified subnet. It also must not pick the same address twice
+// unless it runs out of pool space and must start over.
+TEST_F(AllocEngineTest, IterativeAllocator_manyPools) {
+    NakedAllocEngine::IterativeAllocator* alloc = new NakedAllocEngine::IterativeAllocator();
+
+    // let's start from 2, as there is 2001:db8:1::10 - 2001:db8:1::20 pool already.
+    for (int i = 2; i < 10; ++i) {
+        stringstream min, max;
+
+        min << "2001:db8:1::" << hex << i*16 + 1;
+        max << "2001:db8:1::" << hex << i*16 + 9;
+
+        Pool6Ptr pool(new Pool6(Pool6::TYPE_IA, IOAddress(min.str()),
+                                IOAddress(max.str())));
+        // cout << "Adding pool: " << min.str() << "-" << max.str() << endl;
+        subnet_->addPool6(pool);
+    }
+
+    int total = 17 + 8*9; // first pool (::10 - ::20) has 17 addresses in it,
+                          // there are 8 extra pools with 9 addresses in each.
+
+    // Let's keep picked addresses here and check their uniqueness.
+    std::map<IOAddress, int> generated_addrs;
+    int cnt = 0;
+    while (++cnt) {
+        IOAddress candidate = alloc->pickAddress(subnet_, duid_, IOAddress("::"));
+        EXPECT_TRUE(subnet_->inPool(candidate));
+
+        // One way to easily verify that the iterative allocator really works is
+        // to uncomment the following line and observe its output that it
+        // covers all defined subnets.
+        // cout << candidate.toText() << endl;
+
+        if (generated_addrs.find(candidate) == generated_addrs.end()) {
+            // we haven't had this
+            generated_addrs[candidate] = 0;
+        } else {
+            // we have seen this address before. That should mean that we
+            // iterated over all addresses.
+            if (generated_addrs.size() == total) {
+                // we have exactly the number of address in all pools
+                break;
+            }
+            ADD_FAILURE() << "Too many or not enough unique addresses generated.";
+            break;
+        }
+
+        if ( cnt>total ) {
+            ADD_FAILURE() << "Too many unique addresses generated.";
+            break;
+        }
+    }
+
+    delete alloc;
+}
+
+}; // end of anonymous namespace
diff --git a/src/lib/dhcpsrv/tests/cfgmgr_unittest.cc b/src/lib/dhcpsrv/tests/cfgmgr_unittest.cc
new file mode 100644
index 0000000..166c08d
--- /dev/null
+++ b/src/lib/dhcpsrv/tests/cfgmgr_unittest.cc
@@ -0,0 +1,113 @@
+// 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 <config.h>
+
+#include <dhcpsrv/cfgmgr.h>
+#include <exceptions/exceptions.h>
+
+#include <iostream>
+#include <sstream>
+#include <arpa/inet.h>
+#include <gtest/gtest.h>
+
+using namespace std;
+using namespace isc::asiolink;
+using namespace isc::dhcp;
+using namespace isc::util;
+using namespace isc;
+
+// don't import the entire boost namespace.  It will unexpectedly hide uint8_t
+// for some systems.
+using boost::scoped_ptr;
+
+namespace {
+
+class CfgMgrTest : public ::testing::Test {
+public:
+    CfgMgrTest() {
+    }
+
+    ~CfgMgrTest() {
+        CfgMgr::instance().deleteSubnets6();
+    }
+};
+
+
+// This test verifies if the configuration manager is able to hold and return
+// valid leases
+TEST_F(CfgMgrTest, subnet4) {
+    CfgMgr& cfg_mgr = CfgMgr::instance();
+
+    Subnet4Ptr subnet1(new Subnet4(IOAddress("192.0.2.0"), 26, 1, 2, 3));
+    Subnet4Ptr subnet2(new Subnet4(IOAddress("192.0.2.64"), 26, 1, 2, 3));
+    Subnet4Ptr subnet3(new Subnet4(IOAddress("192.0.2.128"), 26, 1, 2, 3));
+
+    // there shouldn't be any subnet configured at this stage
+    EXPECT_EQ( Subnet4Ptr(), cfg_mgr.getSubnet4(IOAddress("192.0.2.0")));
+
+    cfg_mgr.addSubnet4(subnet1);
+
+    // Now we have only one subnet, any request will be served from it
+    EXPECT_EQ(subnet1, cfg_mgr.getSubnet4(IOAddress("192.0.2.63")));
+
+    // Now we add more subnets and check that both old and new subnets
+    // are accessible.
+    cfg_mgr.addSubnet4(subnet2);
+    cfg_mgr.addSubnet4(subnet3);
+
+    EXPECT_EQ(subnet3, cfg_mgr.getSubnet4(IOAddress("192.0.2.191")));
+    EXPECT_EQ(subnet1, cfg_mgr.getSubnet4(IOAddress("192.0.2.15")));
+    EXPECT_EQ(subnet2, cfg_mgr.getSubnet4(IOAddress("192.0.2.85")));
+
+    // Try to find an address that does not belong to any subnet
+    EXPECT_EQ(Subnet4Ptr(), cfg_mgr.getSubnet4(IOAddress("192.0.2.192")));
+}
+
+// This test verifies if the configuration manager is able to hold and return
+// valid leases
+
+TEST_F(CfgMgrTest, subnet6) {
+    CfgMgr& cfg_mgr = CfgMgr::instance();
+
+    Subnet6Ptr subnet1(new Subnet6(IOAddress("2000::"), 48, 1, 2, 3, 4));
+    Subnet6Ptr subnet2(new Subnet6(IOAddress("3000::"), 48, 1, 2, 3, 4));
+    Subnet6Ptr subnet3(new Subnet6(IOAddress("4000::"), 48, 1, 2, 3, 4));
+
+    // there shouldn't be any subnet configured at this stage
+    EXPECT_EQ( Subnet6Ptr(), cfg_mgr.getSubnet6(IOAddress("2000::1")));
+
+    cfg_mgr.addSubnet6(subnet1);
+
+    // Now we have only one subnet, any request will be served from it
+    EXPECT_EQ(subnet1, cfg_mgr.getSubnet6(IOAddress("2000::1")));
+
+    // If we have only a single subnet and the request came from a local
+    // address, let's use that subnet
+    EXPECT_EQ(subnet1, cfg_mgr.getSubnet6(IOAddress("fe80::dead:beef")));
+
+    cfg_mgr.addSubnet6(subnet2);
+    cfg_mgr.addSubnet6(subnet3);
+
+    EXPECT_EQ(subnet3, cfg_mgr.getSubnet6(IOAddress("4000::123")));
+    EXPECT_EQ(subnet2, cfg_mgr.getSubnet6(IOAddress("3000::dead:beef")));
+    EXPECT_EQ(Subnet6Ptr(), cfg_mgr.getSubnet6(IOAddress("5000::1")));
+
+    cfg_mgr.deleteSubnets6();
+    EXPECT_EQ(Subnet6Ptr(), cfg_mgr.getSubnet6(IOAddress("200::123")));
+    EXPECT_EQ(Subnet6Ptr(), cfg_mgr.getSubnet6(IOAddress("3000::123")));
+    EXPECT_EQ(Subnet6Ptr(), cfg_mgr.getSubnet6(IOAddress("4000::123")));
+}
+
+} // end of anonymous namespace
diff --git a/src/lib/dhcpsrv/tests/lease_mgr_factory_unittest.cc b/src/lib/dhcpsrv/tests/lease_mgr_factory_unittest.cc
new file mode 100644
index 0000000..8c30306
--- /dev/null
+++ b/src/lib/dhcpsrv/tests/lease_mgr_factory_unittest.cc
@@ -0,0 +1,51 @@
+// 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 <asiolink/io_address.h>
+#include <dhcpsrv/lease_mgr_factory.h>
+
+#include <iostream>
+#include <sstream>
+#include <gtest/gtest.h>
+
+using namespace std;
+using namespace isc::dhcp;
+
+// This set of tests only check the parsing functions of LeaseMgrFactory.
+// Tests of the LeaseMgr create/instance/destroy are implicitly carried out
+// in the tests for the different concrete lease managers (e.g. MySqlLeaseMgr).
+
+namespace {
+// empty class for now, but may be extended once Addr6 becomes bigger
+class LeaseMgrFactoryTest : public ::testing::Test {
+public:
+    LeaseMgrFactoryTest() {
+    }
+};
+
+// This test checks if the LeaseMgr can be instantiated and that it
+// parses parameters string properly.
+TEST_F(LeaseMgrFactoryTest, parse) {
+
+    std::map<std::string, std::string> parameters = LeaseMgrFactory::parse(
+        "param1=value1 param2=value2 param3=value3");
+
+    EXPECT_EQ("value1", parameters["param1"]);
+    EXPECT_EQ("value2", parameters["param2"]);
+    EXPECT_TRUE(parameters.find("type") == parameters.end());
+}
+
+}; // end of anonymous namespace
diff --git a/src/lib/dhcpsrv/tests/lease_mgr_unittest.cc b/src/lib/dhcpsrv/tests/lease_mgr_unittest.cc
new file mode 100644
index 0000000..bf47867
--- /dev/null
+++ b/src/lib/dhcpsrv/tests/lease_mgr_unittest.cc
@@ -0,0 +1,295 @@
+// 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 <asiolink/io_address.h>
+#include <dhcpsrv/lease_mgr.h>
+
+#include <iostream>
+#include <sstream>
+#include <gtest/gtest.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 and is used for abstract LeaseMgr class testing.
+class ConcreteLeaseMgr : 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 parameters A data structure relating keywords and values
+    ///        concerned with the database.
+    ConcreteLeaseMgr(const LeaseMgr::ParameterMap& parameters)
+        : LeaseMgr(parameters)
+    {}
+
+    /// @brief Destructor
+    virtual ~ConcreteLeaseMgr()
+    {}
+
+    /// @brief Adds an IPv4 lease.
+    ///
+    /// @param lease lease to be added
+    virtual bool addLease(const Lease4Ptr&) {
+        return (false);
+    }
+
+    /// @brief Adds an IPv6 lease.
+    ///
+    /// @param lease lease to be added
+    virtual bool addLease(const Lease6Ptr&) {
+        return (false);
+    }
+
+    /// @brief Returns existing IPv4 lease for specified IPv4 address.
+    ///
+    /// @param addr address of the searched lease
+    ///
+    /// @return smart pointer to the lease (or NULL if a lease is not found)
+    virtual Lease4Ptr getLease4(const isc::asiolink::IOAddress&) const {
+        return (Lease4Ptr());
+    }
+
+    /// @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(const isc::asiolink::IOAddress&,
+                                SubnetID) const {
+        return (Lease4Ptr());
+    }
+
+    /// @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&) const {
+        return (Lease4Collection());
+    }
+
+    /// @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&, SubnetID) const {
+        return (Lease4Ptr());
+    }
+
+    /// @brief Returns existing IPv4 lease for specified client-id
+    ///
+    /// @param clientid client identifier
+    ///
+    /// @return lease collection
+    virtual Lease4Collection getLease4(const ClientId&) const {
+        return (Lease4Collection());
+    }
+
+    /// @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&, SubnetID) const {
+        return (Lease4Ptr());
+    }
+
+    /// @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)
+    virtual Lease6Ptr getLease6(const isc::asiolink::IOAddress&) const {
+        return (Lease6Ptr());
+    }
+
+    /// @brief Returns existing IPv6 lease for a given DUID+IA combination
+    ///
+    /// @param duid client DUID
+    /// @param iaid IA identifier
+    ///
+    /// @return collection of IPv6 leases
+    virtual Lease6Collection getLease6(const DUID&, uint32_t) const {
+        return (Lease6Collection());
+    }
+
+    /// @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)
+    virtual Lease6Ptr getLease6(const DUID&, uint32_t, SubnetID) const {
+        return (Lease6Ptr());
+    }
+
+    /// @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(const Lease4Ptr&) {}
+
+    /// @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(const Lease6Ptr&) {}
+
+    /// @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(const isc::asiolink::IOAddress&) {
+        return (false);
+    }
+
+    /// @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(const isc::asiolink::IOAddress&) {
+        return (false);
+    }
+
+    /// @brief Returns backend type.
+    ///
+    /// Returns the type of the backend (e.g. "mysql", "memfile" etc.)
+    ///
+    /// @return Type of the backend.
+    virtual std::string getType() const {
+        return (std::string("concrete"));
+    }
+
+    /// @brief Returns backend name.
+    ///
+    /// If the backend is a database, this is the name of the database or the
+    /// file.  Otherwise it is just the same as the type.
+    ///
+    /// @return Name of the backend.
+    virtual std::string getName() const {
+        return (std::string("concrete"));
+    }
+
+    /// @brief Returns description of the backend.
+    ///
+    /// This description may be multiline text that describes the backend.
+    ///
+    /// @return Description of the backend.
+    virtual std::string getDescription() const {
+        return (std::string("This is a dummy concrete backend implementation."));
+    }
+
+    /// @brief Returns backend version.
+    virtual std::pair<uint32_t, uint32_t> getVersion() const {
+        return (make_pair(uint32_t(0), uint32_t(0)));
+    }
+
+    /// @brief Commit transactions
+    virtual void commit() {
+    }
+
+    /// @brief Rollback transactions
+    virtual void rollback() {
+    }
+};
+
+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, getParameter) {
+
+    LeaseMgr::ParameterMap pmap;
+    pmap[std::string("param1")] = std::string("value1");
+    pmap[std::string("param2")] = std::string("value2");
+    ConcreteLeaseMgr leasemgr(pmap);
+
+    EXPECT_EQ("value1", leasemgr.getParameter("param1"));
+    EXPECT_EQ("value2", leasemgr.getParameter("param2"));
+    EXPECT_THROW(leasemgr.getParameter("param3"), BadValue);
+}
+
+// There's no point in calling any other methods in LeaseMgr, as they
+// are purely virtual, so we would only call ConcreteLeaseMgr methods.
+// Those methods are just stubs that do not return anything.
+
+// Lease6 is also defined in lease_mgr.h, so is tested in this file as well.
+// This test checks if the Lease6 structure can be instantiated correctly
+TEST(Lease6, Lease6Constructor) {
+
+    IOAddress addr("2001:db8:1::456");
+
+    uint8_t llt[] = {0, 1, 2, 3, 4, 5, 6, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf};
+    DuidPtr duid(new DUID(llt, sizeof(llt)));
+
+    uint32_t iaid = 7; // just a number
+
+    SubnetID subnet_id = 8; // just another number
+
+    Lease6Ptr x(new Lease6(Lease6::LEASE_IA_NA, addr,
+                           duid, iaid, 100, 200, 50, 80,
+                           subnet_id));
+
+    EXPECT_TRUE(x->addr_ == addr);
+    EXPECT_TRUE(*x->duid_ == *duid);
+    EXPECT_TRUE(x->iaid_ == iaid);
+    EXPECT_TRUE(x->subnet_id_ == subnet_id);
+    EXPECT_TRUE(x->type_ == Lease6::LEASE_IA_NA);
+    EXPECT_TRUE(x->preferred_lft_ == 100);
+    EXPECT_TRUE(x->valid_lft_ == 200);
+    EXPECT_TRUE(x->t1_ == 50);
+    EXPECT_TRUE(x->t2_ == 80);
+
+    // Lease6 must be instantiated with a DUID, not with NULL pointer
+    EXPECT_THROW(new Lease6(Lease6::LEASE_IA_NA, addr,
+                            DuidPtr(), iaid, 100, 200, 50, 80,
+                            subnet_id), InvalidOperation);
+}
+}; // end of anonymous namespace
diff --git a/src/lib/dhcpsrv/tests/memfile_lease_mgr_unittest.cc b/src/lib/dhcpsrv/tests/memfile_lease_mgr_unittest.cc
new file mode 100644
index 0000000..721289b
--- /dev/null
+++ b/src/lib/dhcpsrv/tests/memfile_lease_mgr_unittest.cc
@@ -0,0 +1,134 @@
+// 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 <config.h>
+
+#include <asiolink/io_address.h>
+#include <dhcp/duid.h>
+#include <dhcpsrv/lease_mgr.h>
+#include <dhcpsrv/memfile_lease_mgr.h>
+
+#include <iostream>
+#include <sstream>
+#include <gtest/gtest.h>
+
+using namespace std;
+using namespace isc;
+using namespace isc::asiolink;
+using namespace isc::dhcp;
+
+namespace {
+// empty class for now, but may be extended once Addr6 becomes bigger
+class MemfileLeaseMgrTest : public ::testing::Test {
+public:
+    MemfileLeaseMgrTest() {
+    }
+};
+
+// This test checks if the LeaseMgr can be instantiated and that it
+// parses parameters string properly.
+TEST_F(MemfileLeaseMgrTest, constructor) {
+
+    const LeaseMgr::ParameterMap pmap;  // Empty parameter map
+    boost::scoped_ptr<Memfile_LeaseMgr> lease_mgr;
+
+    ASSERT_NO_THROW(lease_mgr.reset(new Memfile_LeaseMgr(pmap)));
+}
+
+// Checks if the getType() and getName() methods both return "memfile".
+TEST_F(MemfileLeaseMgrTest, getTypeAndName) {
+    const LeaseMgr::ParameterMap pmap;  // Empty parameter map
+    boost::scoped_ptr<Memfile_LeaseMgr> lease_mgr(new Memfile_LeaseMgr(pmap));
+
+    EXPECT_EQ(std::string("memfile"), lease_mgr->getType());
+    EXPECT_EQ(std::string("memfile"), lease_mgr->getName());
+}
+
+// Checks that adding/getting/deleting a Lease6 object works.
+TEST_F(MemfileLeaseMgrTest, addGetDelete6) {
+    const LeaseMgr::ParameterMap pmap;  // Empty parameter map
+    boost::scoped_ptr<Memfile_LeaseMgr> lease_mgr(new Memfile_LeaseMgr(pmap));
+
+    IOAddress addr("2001:db8:1::456");
+
+    uint8_t llt[] = {0, 1, 2, 3, 4, 5, 6, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf};
+    DuidPtr duid(new DUID(llt, sizeof(llt)));
+
+    uint32_t iaid = 7; // just a number
+
+    SubnetID subnet_id = 8; // just another number
+
+    Lease6Ptr lease(new Lease6(Lease6::LEASE_IA_NA, addr,
+                               duid, iaid, 100, 200, 50, 80,
+                               subnet_id));
+
+    EXPECT_TRUE(lease_mgr->addLease(lease));
+
+    // should not be allowed to add a second lease with the same address
+    EXPECT_FALSE(lease_mgr->addLease(lease));
+
+    Lease6Ptr x = lease_mgr->getLease6(IOAddress("2001:db8:1::234"));
+    EXPECT_EQ(Lease6Ptr(), x);
+
+    x = lease_mgr->getLease6(IOAddress("2001:db8:1::456"));
+    ASSERT_TRUE(x);
+
+    EXPECT_EQ(x->addr_.toText(), addr.toText());
+    EXPECT_TRUE(*x->duid_ == *duid);
+    EXPECT_EQ(x->iaid_, iaid);
+    EXPECT_EQ(x->subnet_id_, subnet_id);
+
+    // These are not important from lease management perspective, but
+    // let's check them anyway.
+    EXPECT_EQ(x->type_, Lease6::LEASE_IA_NA);
+    EXPECT_EQ(x->preferred_lft_, 100);
+    EXPECT_EQ(x->valid_lft_, 200);
+    EXPECT_EQ(x->t1_, 50);
+    EXPECT_EQ(x->t2_, 80);
+
+    // Test getLease6(duid, iaid, subnet_id) - positive case
+    Lease6Ptr y = lease_mgr->getLease6(*duid, iaid, subnet_id);
+    ASSERT_TRUE(y);
+    EXPECT_TRUE(*y->duid_ == *duid);
+    EXPECT_EQ(y->iaid_, iaid);
+    EXPECT_EQ(y->addr_.toText(), addr.toText());
+
+    // Test getLease6(duid, iaid, subnet_id) - wrong iaid
+    uint32_t invalid_iaid = 9; // no such iaid
+    y = lease_mgr->getLease6(*duid, invalid_iaid, subnet_id);
+    EXPECT_FALSE(y);
+
+    uint32_t invalid_subnet_id = 999;
+    y = lease_mgr->getLease6(*duid, iaid, invalid_subnet_id);
+    EXPECT_FALSE(y);
+
+    // truncated duid
+    DuidPtr invalid_duid(new DUID(llt, sizeof(llt) - 1));
+    y = lease_mgr->getLease6(*invalid_duid, iaid, subnet_id);
+    EXPECT_FALSE(y);
+
+    // should return false - there's no such address
+    EXPECT_FALSE(lease_mgr->deleteLease6(IOAddress("2001:db8:1::789")));
+
+    // this one should succeed
+    EXPECT_TRUE(lease_mgr->deleteLease6(IOAddress("2001:db8:1::456")));
+
+    // after the lease is deleted, it should really be gone
+    x = lease_mgr->getLease6(IOAddress("2001:db8:1::456"));
+    EXPECT_EQ(Lease6Ptr(), x);
+}
+
+// TODO: Write more memfile tests
+
+}; // end of anonymous namespace
diff --git a/src/lib/dhcpsrv/tests/mysql_lease_mgr_unittest.cc b/src/lib/dhcpsrv/tests/mysql_lease_mgr_unittest.cc
new file mode 100644
index 0000000..5e57090
--- /dev/null
+++ b/src/lib/dhcpsrv/tests/mysql_lease_mgr_unittest.cc
@@ -0,0 +1,753 @@
+// 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 <asiolink/io_address.h>
+#include <dhcpsrv/lease_mgr_factory.h>
+#include <dhcpsrv/mysql_lease_mgr.h>
+
+#include <iostream>
+#include <sstream>
+#include <utility>
+#include <string>
+#include <gtest/gtest.h>
+
+using namespace isc;
+using namespace isc::asiolink;
+using namespace isc::dhcp;
+using namespace std;
+
+namespace {
+
+// Creation of the schema
+#include "schema_copy.h"
+
+// IPv6 addresseses
+const char* ADDRESS_0 = "2001:db8::0";
+const char* ADDRESS_1 = "2001:db8::1";
+const char* ADDRESS_2 = "2001:db8::2";
+const char* ADDRESS_3 = "2001:db8::3";
+const char* ADDRESS_4 = "2001:db8::4";
+const char* ADDRESS_5 = "2001:db8::5";
+const char* ADDRESS_6 = "2001:db8::6";
+const char* ADDRESS_7 = "2001:db8::7";
+
+// Connection strings.  Assume:
+// Database: keatest
+// Username: keatest
+// Password: keatest
+const char* VALID_TYPE = "type=mysql";
+const char* INVALID_TYPE = "type=unknown";
+const char* VALID_NAME = "name=keatest";
+const char* INVALID_NAME = "name=invalidname";
+const char* VALID_HOST = "host=localhost";
+const char* INVALID_HOST = "host=invalidhost";
+const char* VALID_USER = "user=keatest";
+const char* INVALID_USER = "user=invaliduser";
+const char* VALID_PASSWORD = "password=keatest";
+const char* INVALID_PASSWORD = "password=invalid";
+
+// Given a combination of strings above, produce a connection string.
+string connectionString(const char* type, const char* name, const char* host,
+                        const char* user, const char* password) {
+    const string space = " ";
+    string result = "";
+
+    if (type != NULL) {
+        result += string(type);
+    }
+
+    if (name != NULL) {
+        if (! result.empty()) {
+            result += space;
+        }
+        result += string(name);
+    }
+
+    if (host != NULL) {
+        if (! result.empty()) {
+            result += space;
+        }
+        result += string(host);
+    }
+
+    if (user != NULL) {
+        if (! result.empty()) {
+            result += space;
+        }
+        result += string(user);
+    }
+
+    if (password != NULL) {
+        if (! result.empty()) {
+            result += space;
+        }
+        result += string(password);
+    }
+
+    return (result);
+}
+
+// Return valid connection string
+string
+validConnectionString() {
+    return (connectionString(VALID_TYPE, VALID_NAME, VALID_HOST,
+                             VALID_USER, VALID_PASSWORD));
+}
+
+// @brief Clear everything from the database
+//
+// There is no error checking in this code: if something fails, one of the
+// tests will fall over.
+void destroySchema() {
+    // Initialise
+    MYSQL handle;
+    (void) mysql_init(&handle);
+
+    // Open database
+    (void) mysql_real_connect(&handle, "localhost", "keatest",
+                              "keatest", "keatest", 0, NULL, 0);
+
+    // Get rid of everything in it.
+    for (int i = 0; destroy_statement[i] != NULL; ++i) {
+        (void) mysql_query(&handle, destroy_statement[i]);
+    }
+
+    // ... and close
+    (void) mysql_close(&handle);
+}
+
+// @brief Create the Schema
+//
+// Creates all the tables in what is assumed to be an empty database.
+//
+// There is no error checking in this code: if it fails, one of the tests
+// will fall over.
+void createSchema() {
+    // Initialise
+    MYSQL handle;
+    (void) mysql_init(&handle);
+
+    // Open database
+    (void) mysql_real_connect(&handle, "localhost", "keatest",
+                              "keatest", "keatest", 0, NULL, 0);
+
+    // Get rid of everything in it.
+    for (int i = 0; create_statement[i] != NULL; ++i) {
+        (void) mysql_query(&handle, create_statement[i]);
+    }
+
+    // ... and close
+    (void) mysql_close(&handle);
+}
+
+// Note: Doxygen "///" not used - even though Doxygen is used to
+// document class and methods - to avoid the comments appearing
+// in the programming manual.
+
+// @brief Test Fixture Class
+//
+// Opens the database prior to each test and closes it afterwards.
+// All pending transactions are deleted prior to closure.
+
+class MySqlLeaseMgrTest : public ::testing::Test {
+public:
+    // @brief Constructor
+    //
+    // Deletes everything from the database and opens it.
+    MySqlLeaseMgrTest() :
+        L0_ADDRESS(ADDRESS_0), L0_IOADDRESS(L0_ADDRESS), 
+        L1_ADDRESS(ADDRESS_1), L1_IOADDRESS(L1_ADDRESS), 
+        L2_ADDRESS(ADDRESS_2), L2_IOADDRESS(L2_ADDRESS), 
+        L3_ADDRESS(ADDRESS_3), L3_IOADDRESS(L3_ADDRESS), 
+        L4_ADDRESS(ADDRESS_4), L4_IOADDRESS(L4_ADDRESS), 
+        L5_ADDRESS(ADDRESS_5), L5_IOADDRESS(L5_ADDRESS), 
+        L6_ADDRESS(ADDRESS_6), L6_IOADDRESS(L6_ADDRESS), 
+        L7_ADDRESS(ADDRESS_7), L7_IOADDRESS(L7_ADDRESS) {
+
+        destroySchema();
+        createSchema();
+        try {
+            LeaseMgrFactory::create(validConnectionString());
+        } catch (...) {
+            std::cerr << "*** ERROR: unable to open database. The test\n"
+                         "*** environment is broken and must be fixed before\n"
+                         "*** the MySQL tests will run correctly.\n"
+                         "*** The reason for the problem is described in the\n"
+                         "*** accompanying exception output.\n";
+            throw;
+        }
+        lmptr_ = &(LeaseMgrFactory::instance());
+    }
+
+    // @brief Destructor
+    //
+    // Rolls back all pending transactions.  The deletion of the
+    // lmptr_ member variable will close the database.  Then
+    // reopen it and delete everything created by the test.
+    virtual ~MySqlLeaseMgrTest() {
+        lmptr_->rollback();
+        LeaseMgrFactory::destroy();
+        destroySchema();
+    }
+
+    // @brief Reopen the database
+    //
+    // Closes the database and re-open it.  Anything committed should be
+    // visible.
+    void reopen() {
+        LeaseMgrFactory::destroy();
+        LeaseMgrFactory::create(validConnectionString());
+        lmptr_ = &(LeaseMgrFactory::instance());
+    }
+
+    // @brief Initialize Lease6 Fields
+    //
+    // Returns a pointer to a Lease6 structure.  Different values are put
+    // in the lease according to the address passed.
+    //
+    // This is just a convenience function for the test methods.
+    //
+    // @param address Address to use for the initialization
+    //
+    // @return Lease6Ptr.  This will not point to anything if the initialization
+    //         failed (e.g. unknown address).
+    Lease6Ptr initializeLease6(std::string address) {
+        Lease6Ptr lease(new Lease6());
+
+        // Set the address of the lease
+        lease->addr_ = IOAddress(address);
+
+        // Initialize unused fields.
+        lease->t1_ = 0;                             // Not saved
+        lease->t2_ = 0;                             // Not saved
+        lease->fixed_ = false;                      // Unused
+        lease->hostname_ = std::string("");         // Unused
+        lease->fqdn_fwd_ = false;                   // Unused
+        lease->fqdn_rev_ = false;                   // Unused
+        lease->comments_ = std::string("");         // Unused
+
+        // Set the other parameters.  For historical reasons, L0_ADDRESS is not used.
+        if (address == L0_ADDRESS) {
+            lease->type_ = Lease6::LEASE_IA_TA;
+            lease->prefixlen_ = 4;
+            lease->iaid_ = 142;
+            lease->duid_ = boost::shared_ptr<DUID>(new DUID(vector<uint8_t>(8, 0x77)));
+            lease->preferred_lft_ = 900;   // Preferred lifetime
+            lease->valid_lft_ = 8677;      // Actual lifetime
+            lease->cltt_ = 168256;         // Current time of day
+            lease->subnet_id_ = 23;        // Arbitrary number
+
+        } else if (address == L1_ADDRESS) {
+            lease->type_ = Lease6::LEASE_IA_TA;
+            lease->prefixlen_ = 0;
+            lease->iaid_ = 42;
+            lease->duid_ = boost::shared_ptr<DUID>(new DUID(vector<uint8_t>(8, 0x42)));
+            lease->preferred_lft_ = 3600;  // Preferred lifetime
+            lease->valid_lft_ = 3677;      // Actual lifetime
+            lease->cltt_ = 123456;         // Current time of day
+            lease->subnet_id_ = 73;        // Arbitrary number
+
+        } else if (address == L2_ADDRESS) {
+            lease->type_ = Lease6::LEASE_IA_PD;
+            lease->prefixlen_ = 7;
+            lease->iaid_ = 89;
+            lease->duid_ = boost::shared_ptr<DUID>(new DUID(vector<uint8_t>(8, 0x3a)));
+            lease->preferred_lft_ = 1800;  // Preferred lifetime
+            lease->valid_lft_ = 5412;      // Actual lifetime
+            lease->cltt_ = 234567;         // Current time of day
+            lease->subnet_id_ = 73;        // Same as for L1_ADDRESS
+
+        } else if (address == L3_ADDRESS) {
+            lease->type_ = Lease6::LEASE_IA_NA;
+            lease->prefixlen_ = 28;
+            lease->iaid_ = 0xfffffffe;
+            vector<uint8_t> duid;
+            for (uint8_t i = 31; i < 126; ++i) {
+                duid.push_back(i);
+            }
+            lease->duid_ = boost::shared_ptr<DUID>(new DUID(duid));
+
+            // The times used in the next tests are deliberately restricted - we
+            // should be able to cope with valid lifetimes up to 0xffffffff.
+            //  However, this will lead to overflows.
+            // @TODO: test overflow conditions when code has been fixed
+            lease->preferred_lft_ = 7200;  // Preferred lifetime
+            lease->valid_lft_ = 7000;      // Actual lifetime
+            lease->cltt_ = 234567;         // Current time of day
+            lease->subnet_id_ = 37;        // Different from L1 and L2
+
+        } else if (address == L4_ADDRESS) {
+            // Same DUID and IAID as L1_ADDRESS
+            lease->type_ = Lease6::LEASE_IA_PD;
+            lease->prefixlen_ = 15;
+            lease->iaid_ = 42;
+            lease->duid_ = boost::shared_ptr<DUID>(new DUID(vector<uint8_t>(8, 0x42)));
+            lease->preferred_lft_ = 4800;  // Preferred lifetime
+            lease->valid_lft_ = 7736;      // Actual lifetime
+            lease->cltt_ = 222456;         // Current time of day
+            lease->subnet_id_ = 75;        // Arbitrary number
+
+        } else if (address == L5_ADDRESS) {
+            // Same DUID and IAID as L1_ADDRESS
+            lease->type_ = Lease6::LEASE_IA_PD;
+            lease->prefixlen_ = 24;
+            lease->iaid_ = 42;
+            lease->duid_ = boost::shared_ptr<DUID>(new DUID(vector<uint8_t>(8, 0x42)));
+            lease->preferred_lft_ = 5400;  // Preferred lifetime
+            lease->valid_lft_ = 7832;      // Actual lifetime
+            lease->cltt_ = 227476;         // Current time of day
+            lease->subnet_id_ = 175;       // Arbitrary number
+
+        } else if (address == L6_ADDRESS) {
+            // Same DUID as L1_ADDRESS
+            lease->type_ = Lease6::LEASE_IA_PD;
+            lease->prefixlen_ = 24;
+            lease->iaid_ = 93;
+            lease->duid_ = boost::shared_ptr<DUID>(new DUID(vector<uint8_t>(8, 0x42)));
+            lease->preferred_lft_ = 5400;  // Preferred lifetime
+            lease->valid_lft_ = 1832;      // Actual lifetime
+            lease->cltt_ = 627476;         // Current time of day
+            lease->subnet_id_ = 112;       // Arbitrary number
+
+        } else if (address == L7_ADDRESS) {
+            // Same IAID as L1_ADDRESS
+            lease->type_ = Lease6::LEASE_IA_PD;
+            lease->prefixlen_ = 24;
+            lease->iaid_ = 42;
+            lease->duid_ = boost::shared_ptr<DUID>(new DUID(vector<uint8_t>(8, 0xe5)));
+            lease->preferred_lft_ = 5600;  // Preferred lifetime
+            lease->valid_lft_ = 7975;      // Actual lifetime
+            lease->cltt_ = 213876;         // Current time of day
+            lease->subnet_id_ = 19;        // Arbitrary number
+
+        } else {
+            // Unknown address, return an empty pointer.
+            lease.reset();
+
+        }
+
+        return (lease);
+    }
+
+    // @brief Creates Leases for the test
+    //
+    // Creates all leases for the test and checks that they are different.
+    //
+    // @return vector<Lease6Ptr> Vector of pointers to leases
+    vector<Lease6Ptr> createLeases6() {
+
+        // Create leases
+        vector<Lease6Ptr> leases;
+        leases.push_back(initializeLease6(L0_ADDRESS));
+        leases.push_back(initializeLease6(L1_ADDRESS));
+        leases.push_back(initializeLease6(L2_ADDRESS));
+        leases.push_back(initializeLease6(L3_ADDRESS));
+        leases.push_back(initializeLease6(L4_ADDRESS));
+        leases.push_back(initializeLease6(L5_ADDRESS));
+        leases.push_back(initializeLease6(L6_ADDRESS));
+        leases.push_back(initializeLease6(L7_ADDRESS));
+
+        EXPECT_EQ(8, leases.size());
+
+        // Check they were created
+        for (int i = 0; i < leases.size(); ++i) {
+            EXPECT_TRUE(leases[i]);
+        }
+
+        // Check they are different
+        for (int i = 0; i < (leases.size() - 1); ++i) {
+            for (int j = (i + 1); j < leases.size(); ++j) {
+                EXPECT_TRUE(leases[i] != leases[j]);
+            }
+        }
+
+        return (leases);
+    }
+
+
+    // Member variables
+
+    LeaseMgr*   lmptr_;         // Pointer to the lease manager
+
+    string L0_ADDRESS;          // String form of address 1
+    IOAddress L0_IOADDRESS;     // IOAddress form of L1_ADDRESS
+
+    string L1_ADDRESS;          // String form of address 1
+    IOAddress L1_IOADDRESS;     // IOAddress form of L1_ADDRESS
+
+    string L2_ADDRESS;          // String form of address 2
+    IOAddress L2_IOADDRESS;     // IOAddress form of L2_ADDRESS
+
+    string L3_ADDRESS;          // String form of address 3
+    IOAddress L3_IOADDRESS;     // IOAddress form of L3_ADDRESS
+
+    string L4_ADDRESS;          // String form of address 4
+    IOAddress L4_IOADDRESS;     // IOAddress form of L4_ADDRESS
+
+    string L5_ADDRESS;          // String form of address 5
+    IOAddress L5_IOADDRESS;     // IOAddress form of L5_ADDRESS
+
+    string L6_ADDRESS;          // String form of address 6
+    IOAddress L6_IOADDRESS;     // IOAddress form of L6_ADDRESS
+
+    string L7_ADDRESS;          // String form of address 7
+    IOAddress L7_IOADDRESS;     // IOAddress form of L7_ADDRESS
+};
+
+
+// @brief Check that Database Can Be Opened
+//
+// This test checks if the MySqlLeaseMgr can be instantiated.  This happens
+// only if the database can be opened.  Note that this is not part of the
+// MySqlLeaseMgr test fixure set.  This test checks that the database can be
+// opened: the fixtures assume that and check basic operations.
+
+TEST(MySqlOpenTest, OpenDatabase) {
+
+    // Schema needs to be created for the test to work.
+    destroySchema();
+    createSchema();
+
+    // Check that lease manager open the database opens correctly and tidy up.
+    //  If it fails, print the error message.
+    try {
+        LeaseMgrFactory::create(validConnectionString());
+        EXPECT_NO_THROW((void) LeaseMgrFactory::instance());
+        LeaseMgrFactory::destroy();
+    } catch (const isc::Exception& ex) {
+        FAIL() << "*** ERROR: unable to open database, reason:\n"
+               << "    " << ex.what() << "\n"
+               << "*** The test environment is broken and must be fixed\n"
+               << "*** before the MySQL tests will run correctly.\n";
+    }
+
+    // Check that attempting to get an instance of the lease manager when
+    // none is set throws an exception.
+    EXPECT_THROW(LeaseMgrFactory::instance(), NoLeaseManager);
+
+    // Check that wrong specification of backend throws an exception.
+    // (This is really a check on LeaseMgrFactory, but is convenient to
+    // perform here.)
+    EXPECT_THROW(LeaseMgrFactory::create(connectionString(
+        NULL, VALID_NAME, VALID_HOST, INVALID_USER, VALID_PASSWORD)),
+        InvalidParameter);
+    EXPECT_THROW(LeaseMgrFactory::create(connectionString(
+        INVALID_TYPE, VALID_NAME, VALID_HOST, VALID_USER, VALID_PASSWORD)),
+        InvalidType);
+
+    // Check that invalid login data causes an exception.
+    EXPECT_THROW(LeaseMgrFactory::create(connectionString(
+        VALID_TYPE, INVALID_NAME, VALID_HOST, VALID_USER, VALID_PASSWORD)),
+        DbOpenError);
+    EXPECT_THROW(LeaseMgrFactory::create(connectionString(
+        VALID_TYPE, VALID_NAME, INVALID_HOST, VALID_USER, VALID_PASSWORD)),
+        DbOpenError);
+    EXPECT_THROW(LeaseMgrFactory::create(connectionString(
+        VALID_TYPE, VALID_NAME, VALID_HOST, INVALID_USER, VALID_PASSWORD)),
+        DbOpenError);
+    EXPECT_THROW(LeaseMgrFactory::create(connectionString(
+        VALID_TYPE, VALID_NAME, VALID_HOST, VALID_USER, INVALID_PASSWORD)),
+        DbOpenError);
+
+    // Check for missing parameters
+    EXPECT_THROW(LeaseMgrFactory::create(connectionString(
+        VALID_TYPE, NULL, VALID_HOST, INVALID_USER, VALID_PASSWORD)),
+        NoDatabaseName);
+
+    // Tidy up after the test
+    destroySchema();
+}
+
+// @brief Check the getType() method
+//
+// getType() returns a string giving the type of the backend, which should
+// always be "mysql".
+TEST_F(MySqlLeaseMgrTest, getType) {
+    EXPECT_EQ(std::string("mysql"), lmptr_->getType());
+}
+
+// @brief Check conversion functions
+//
+// The server works using cltt and valid_filetime.  In the database, the
+// information is stored as expire_time and valid-lifetime, which are
+// related by
+//
+// expire_time = cltt + valid_lifetime
+//
+// This test checks that the conversion is correct.  It does not check that the
+// data is entered into the database correctly, only that the MYSQL_TIME
+// structure used for the entry is correctly set up.
+TEST_F(MySqlLeaseMgrTest, checkTimeConversion) {
+    const time_t cltt = time(NULL);
+    const uint32_t valid_lft = 86400;       // 1 day
+    struct tm tm_expire;
+    MYSQL_TIME mysql_expire;
+
+    // Work out what the broken-down time will be for one day
+    // after the current time.
+    time_t expire_time = cltt + valid_lft;
+    (void) localtime_r(&expire_time, &tm_expire);
+
+    // Convert to the database time
+    MySqlLeaseMgr::convertToDatabaseTime(cltt, valid_lft, mysql_expire);
+
+    // Are the times the same?
+    EXPECT_EQ(tm_expire.tm_year + 1900, mysql_expire.year);
+    EXPECT_EQ(tm_expire.tm_mon + 1,  mysql_expire.month);
+    EXPECT_EQ(tm_expire.tm_mday, mysql_expire.day);
+    EXPECT_EQ(tm_expire.tm_hour, mysql_expire.hour);
+    EXPECT_EQ(tm_expire.tm_min, mysql_expire.minute);
+    EXPECT_EQ(tm_expire.tm_sec, mysql_expire.second);
+    EXPECT_EQ(0, mysql_expire.second_part);
+    EXPECT_EQ(0, mysql_expire.neg);
+
+    // Convert back
+    time_t converted_cltt = 0;
+    MySqlLeaseMgr::convertFromDatabaseTime(mysql_expire, valid_lft, converted_cltt);
+    EXPECT_EQ(cltt, converted_cltt);
+}
+
+
+// @brief Check getName() returns correct database name
+TEST_F(MySqlLeaseMgrTest, getName) {
+    EXPECT_EQ(std::string("keatest"), lmptr_->getName());
+
+    // @TODO: check for the negative
+}
+
+// @brief Check that getVersion() returns the expected version
+TEST_F(MySqlLeaseMgrTest, checkVersion) {
+    // Check version
+    pair<uint32_t, uint32_t> version;
+    ASSERT_NO_THROW(version = lmptr_->getVersion());
+    EXPECT_EQ(CURRENT_VERSION_VERSION, version.first);
+    EXPECT_EQ(CURRENT_VERSION_MINOR, version.second);
+}
+
+// @brief Compare two Lease6 structures for equality
+void
+detailCompareLease6(const Lease6Ptr& first, const Lease6Ptr& second) {
+    EXPECT_EQ(first->type_, second->type_);
+
+    // Compare address strings.  Comparison of address objects is not used, as
+    // odd things happen when they are different: the EXPECT_EQ macro appears to
+    // call the operator uint32_t() function, which causes an exception to be
+    // thrown for IPv6 addresses.
+    EXPECT_EQ(first->addr_.toText(), second->addr_.toText());
+    EXPECT_EQ(first->prefixlen_, second->prefixlen_);
+    EXPECT_EQ(first->iaid_, second->iaid_);
+    EXPECT_TRUE(*first->duid_ == *second->duid_);
+    EXPECT_EQ(first->preferred_lft_, second->preferred_lft_);
+    EXPECT_EQ(first->valid_lft_, second->valid_lft_);
+    EXPECT_EQ(first->cltt_, second->cltt_);
+    EXPECT_EQ(first->subnet_id_, second->subnet_id_);
+}
+
+
+// @brief Check individual Lease6 methods
+//
+// Checks that the add/update/delete works.  All are done within one
+// test so that "rollback" can be used to remove trace of the tests
+// from the database.
+//
+// Tests where a collection of leases can be returned are in the test
+// Lease6Collection.
+TEST_F(MySqlLeaseMgrTest, basicLease6) {
+    // Get the leases to be used for the test.
+    vector<Lease6Ptr> leases = createLeases6();
+
+    // Start the tests.  Add three leases to the database, read them back and
+    // check they are what we think they are.
+    EXPECT_TRUE(lmptr_->addLease(leases[1]));
+    EXPECT_TRUE(lmptr_->addLease(leases[2]));
+    EXPECT_TRUE(lmptr_->addLease(leases[3]));
+    lmptr_->commit();
+
+    // Reopen the database to ensure that they actually got stored.
+    reopen();
+
+    Lease6Ptr l_returned = lmptr_->getLease6(L1_IOADDRESS);
+    EXPECT_TRUE(l_returned);
+    detailCompareLease6(leases[1], l_returned);
+
+    l_returned = lmptr_->getLease6(L2_IOADDRESS);
+    EXPECT_TRUE(l_returned);
+    detailCompareLease6(leases[2], l_returned);
+
+    l_returned = lmptr_->getLease6(L3_IOADDRESS);
+    EXPECT_TRUE(l_returned);
+    detailCompareLease6(leases[3], l_returned);
+
+    // Check that we can't add a second lease with the same address
+    EXPECT_FALSE(lmptr_->addLease(leases[1]));
+
+    // Delete a lease, check that it's gone, and that we can't delete it
+    // a second time.
+    EXPECT_TRUE(lmptr_->deleteLease6(L1_IOADDRESS));
+    l_returned = lmptr_->getLease6(L1_IOADDRESS);
+    EXPECT_FALSE(l_returned);
+    EXPECT_FALSE(lmptr_->deleteLease6(L1_IOADDRESS));
+
+    // Check that the second address is still there.
+    l_returned = lmptr_->getLease6(L2_IOADDRESS);
+    EXPECT_TRUE(l_returned);
+    detailCompareLease6(leases[2], l_returned);
+}
+
+// @brief Check GetLease6 methods - Access by DUID/IAID
+//
+// Adds leases to the database and checks that they can be accessed via
+// a combination of DIUID and IAID.
+TEST_F(MySqlLeaseMgrTest, getLease6Extended1) {
+    // Get the leases to be used for the test.
+    vector<Lease6Ptr> leases = createLeases6();
+    EXPECT_LE(6, leases.size());    // Expect to access leases 0 through 5
+
+    // Add them to the database
+    for (int i = 0; i < leases.size(); ++i) {
+        EXPECT_TRUE(lmptr_->addLease(leases[i]));
+    }
+
+    // Get the leases matching the DUID and IAID of lease[1].
+    Lease6Collection returned = lmptr_->getLease6(*leases[1]->duid_,
+                                                  leases[1]->iaid_);
+
+    // Should be three leases, matching leases[1], [4] and [5].
+    ASSERT_EQ(3, returned.size());
+
+    // Easiest way to check is to look at the addresses.
+    vector<string> addresses;
+    for (Lease6Collection::const_iterator i = returned.begin();
+         i != returned.end(); ++i) {
+        addresses.push_back((*i)->addr_.toText());
+    }
+    sort(addresses.begin(), addresses.end());
+    EXPECT_EQ(L1_ADDRESS, addresses[0]);
+    EXPECT_EQ(L4_ADDRESS, addresses[1]);
+    EXPECT_EQ(L5_ADDRESS, addresses[2]);
+
+    // Check that nothing is returned when either the IAID or DUID match
+    // nothing.
+    returned = lmptr_->getLease6(*leases[1]->duid_, leases[1]->iaid_ + 1);
+    EXPECT_EQ(0, returned.size());
+
+    // Alter the leases[1] DUID to match nothing in the database.
+    vector<uint8_t> duid_vector = leases[1]->duid_->getDuid();
+    ++duid_vector[0];
+    DUID new_duid(duid_vector);
+    returned = lmptr_->getLease6(new_duid, leases[1]->iaid_);
+    EXPECT_EQ(0, returned.size());
+}
+
+
+
+// @brief Check GetLease6 methods - Access by DUID/IAID/SubnetID
+//
+// Adds leases to the database and checks that they can be accessed via
+// a combination of DIUID and IAID.
+TEST_F(MySqlLeaseMgrTest, getLease6Extended2) {
+    // Get the leases to be used for the test.
+    vector<Lease6Ptr> leases = createLeases6();
+    EXPECT_LE(6, leases.size());    // Expect to access leases 0 through 5
+
+    // Add them to the database
+    for (int i = 0; i < leases.size(); ++i) {
+        EXPECT_TRUE(lmptr_->addLease(leases[i]));
+    }
+
+    // Get the leases matching the DUID and IAID of lease[1].
+    Lease6Ptr returned = lmptr_->getLease6(*leases[1]->duid_,
+                                           leases[1]->iaid_,
+                                           leases[1]->subnet_id_);
+    ASSERT_TRUE(returned);
+    EXPECT_TRUE(*returned == *leases[1]);
+
+    // Modify each of the three parameters (DUID, IAID, Subnet ID) and
+    // check that nothing is returned.
+    returned = lmptr_->getLease6(*leases[1]->duid_, leases[1]->iaid_ + 1,
+                                 leases[1]->subnet_id_);
+    EXPECT_FALSE(returned);
+
+    returned = lmptr_->getLease6(*leases[1]->duid_, leases[1]->iaid_,
+                                 leases[1]->subnet_id_ + 1);
+    EXPECT_FALSE(returned);
+
+    // Alter the leases[1] DUID to match nothing in the database.
+    vector<uint8_t> duid_vector = leases[1]->duid_->getDuid();
+    ++duid_vector[0];
+    DUID new_duid(duid_vector);
+    returned = lmptr_->getLease6(new_duid, leases[1]->iaid_,
+                                 leases[1]->subnet_id_);
+    EXPECT_FALSE(returned);
+}
+
+
+
+// @brief Lease6 Update Tests
+//
+// Checks that we are able to update a lease in the database.
+TEST_F(MySqlLeaseMgrTest, updateLease6) {
+    // Get the leases to be used for the test.
+    vector<Lease6Ptr> leases = createLeases6();
+    EXPECT_LE(3, leases.size());    // Expect to access leases 0 through 5
+
+    // Add a lease to the database and check that the lease is there.
+    EXPECT_TRUE(lmptr_->addLease(leases[1]));
+    lmptr_->commit();
+
+    reopen();
+    Lease6Ptr l_returned = lmptr_->getLease6(L1_IOADDRESS);
+    EXPECT_TRUE(l_returned);
+    detailCompareLease6(leases[1], l_returned);
+
+    // Modify some fields in lease 1 (not the address) and update it.
+    ++leases[1]->iaid_;
+    leases[1]->type_ = Lease6::LEASE_IA_PD;
+    leases[1]->valid_lft_ *= 2;
+    lmptr_->updateLease6(leases[1]);
+    lmptr_->commit();
+    reopen();
+
+    // ... and check what is returned is what is expected.
+    l_returned.reset();
+    l_returned = lmptr_->getLease6(L1_IOADDRESS);
+    EXPECT_TRUE(l_returned);
+    detailCompareLease6(leases[1], l_returned);
+
+    // Alter the lease again and check.
+    ++leases[1]->iaid_;
+    leases[1]->type_ = Lease6::LEASE_IA_TA;
+    leases[1]->cltt_ += 6;
+    leases[1]->prefixlen_ = 93;
+    lmptr_->updateLease6(leases[1]);
+
+    l_returned.reset();
+    l_returned = lmptr_->getLease6(L1_IOADDRESS);
+    EXPECT_TRUE(l_returned);
+    detailCompareLease6(leases[1], l_returned);
+
+    // Check we can do an update without changing data.
+    lmptr_->updateLease6(leases[1]);
+    l_returned.reset();
+    l_returned = lmptr_->getLease6(L1_IOADDRESS);
+    EXPECT_TRUE(l_returned);
+    detailCompareLease6(leases[1], l_returned);
+
+    // Try updating a lease not in the database.
+    EXPECT_THROW(lmptr_->updateLease6(leases[2]), isc::dhcp::NoSuchLease);
+}
+
+}; // Of anonymous namespace
diff --git a/src/lib/dhcpsrv/tests/pool_unittest.cc b/src/lib/dhcpsrv/tests/pool_unittest.cc
new file mode 100644
index 0000000..8a9f825
--- /dev/null
+++ b/src/lib/dhcpsrv/tests/pool_unittest.cc
@@ -0,0 +1,183 @@
+// 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 <config.h>
+
+#include <asiolink/io_address.h>
+#include <dhcpsrv/pool.h>
+
+#include <iostream>
+#include <vector>
+#include <sstream>
+#include <gtest/gtest.h>
+
+using boost::scoped_ptr;
+using namespace isc;
+using namespace isc::dhcp;
+using namespace isc::asiolink;
+
+namespace {
+
+TEST(Pool4Test, constructor_first_last) {
+
+    // let's construct 192.0.2.1-192.0.2.255 pool
+    Pool4 pool1(IOAddress("192.0.2.1"), IOAddress("192.0.2.255"));
+
+    EXPECT_EQ(IOAddress("192.0.2.1"), pool1.getFirstAddress());
+    EXPECT_EQ(IOAddress("192.0.2.255"), pool1.getLastAddress());
+
+    // This is Pool4, IPv6 addresses do not belong here
+    EXPECT_THROW(Pool6(Pool6::TYPE_IA, IOAddress("2001:db8::1"),
+                       IOAddress("192.168.0.5")), BadValue);
+    EXPECT_THROW(Pool6(Pool6::TYPE_IA, IOAddress("192.168.0.2"),
+                       IOAddress("2001:db8::1")), BadValue);
+
+    // Should throw. Range should be 192.0.2.1-192.0.2.2, not
+    // the other way around.
+    EXPECT_THROW(Pool6(Pool6::TYPE_IA, IOAddress("192.0.2.2"),
+                       IOAddress("192.0.2.1")), BadValue);
+}
+
+TEST(Pool4Test, constructor_prefix_len) {
+
+    // let's construct 2001:db8:1::/96 pool
+    Pool4 pool1(IOAddress("192.0.2.0"), 25);
+
+    EXPECT_EQ("192.0.2.0", pool1.getFirstAddress().toText());
+    EXPECT_EQ("192.0.2.127", pool1.getLastAddress().toText());
+
+    // No such thing as /33 prefix
+    EXPECT_THROW(Pool4(IOAddress("192.0.2.1"), 33), BadValue);
+
+    // /0 prefix does not make sense
+    EXPECT_THROW(Pool4(IOAddress("192.0.2.0"), 0), BadValue);
+
+    // This is Pool6, IPv4 addresses do not belong here
+    EXPECT_THROW(Pool4(IOAddress("2001:db8::1"), 20), BadValue);
+}
+
+TEST(Pool4Test, in_range) {
+   Pool4 pool1(IOAddress("192.0.2.10"), IOAddress("192.0.2.20"));
+
+   EXPECT_FALSE(pool1.inRange(IOAddress("192.0.2.0")));
+   EXPECT_TRUE(pool1.inRange(IOAddress("192.0.2.10")));
+   EXPECT_TRUE(pool1.inRange(IOAddress("192.0.2.17")));
+   EXPECT_TRUE(pool1.inRange(IOAddress("192.0.2.20")));
+   EXPECT_FALSE(pool1.inRange(IOAddress("192.0.2.21")));
+   EXPECT_FALSE(pool1.inRange(IOAddress("192.0.2.255")));
+   EXPECT_FALSE(pool1.inRange(IOAddress("255.255.255.255")));
+   EXPECT_FALSE(pool1.inRange(IOAddress("0.0.0.0")));
+}
+
+// This test creates 100 pools and verifies that their IDs are unique.
+TEST(Pool4Test, unique_id) {
+
+    const int num_pools = 100;
+    std::vector<Pool4Ptr> pools;
+
+    for (int i = 0; i < num_pools; ++i) {
+        pools.push_back(Pool4Ptr(new Pool4(IOAddress("192.0.2.0"),
+                                           IOAddress("192.0.2.255"))));
+    }
+
+    for (int i = 0; i < num_pools; ++i) {
+        for (int j = i + 1; j < num_pools; ++j) {
+            if (pools[i]->getId() == pools[j]->getId()) {
+                FAIL() << "Pool-ids must be unique";
+            }
+        }
+    }
+
+}
+
+
+TEST(Pool6Test, constructor_first_last) {
+
+    // let's construct 2001:db8:1:: - 2001:db8:1::ffff:ffff:ffff:ffff pool
+    Pool6 pool1(Pool6::TYPE_IA, IOAddress("2001:db8:1::"),
+                IOAddress("2001:db8:1::ffff:ffff:ffff:ffff"));
+
+    EXPECT_EQ(Pool6::TYPE_IA, pool1.getType());
+    EXPECT_EQ(IOAddress("2001:db8:1::"), pool1.getFirstAddress());
+    EXPECT_EQ(IOAddress("2001:db8:1::ffff:ffff:ffff:ffff"),
+              pool1.getLastAddress());
+
+    // This is Pool6, IPv4 addresses do not belong here
+    EXPECT_THROW(Pool6(Pool6::TYPE_IA, IOAddress("2001:db8::1"),
+                       IOAddress("192.168.0.5")), BadValue);
+    EXPECT_THROW(Pool6(Pool6::TYPE_IA, IOAddress("192.168.0.2"),
+                       IOAddress("2001:db8::1")), BadValue);
+
+    // Should throw. Range should be 2001:db8::1 - 2001:db8::2, not
+    // the other way around.
+    EXPECT_THROW(Pool6(Pool6::TYPE_IA, IOAddress("2001:db8::2"),
+                       IOAddress("2001:db8::1")), BadValue);
+}
+
+TEST(Pool6Test, constructor_prefix_len) {
+
+    // let's construct 2001:db8:1::/96 pool
+    Pool6 pool1(Pool6::TYPE_IA, IOAddress("2001:db8:1::"), 96);
+
+    EXPECT_EQ(Pool6::TYPE_IA, pool1.getType());
+    EXPECT_EQ("2001:db8:1::", pool1.getFirstAddress().toText());
+    EXPECT_EQ("2001:db8:1::ffff:ffff", pool1.getLastAddress().toText());
+
+    // No such thing as /130 prefix
+    EXPECT_THROW(Pool6(Pool6::TYPE_IA, IOAddress("2001:db8::"), 130),
+                 BadValue);
+
+    // /0 prefix does not make sense
+    EXPECT_THROW(Pool6(Pool6::TYPE_IA, IOAddress("2001:db8::"), 0),
+                 BadValue);
+
+    // This is Pool6, IPv4 addresses do not belong here
+    EXPECT_THROW(Pool6(Pool6::TYPE_IA, IOAddress("192.168.0.2"), 96),
+                 BadValue);
+}
+
+TEST(Pool6Test, in_range) {
+   Pool6 pool1(Pool6::TYPE_IA, IOAddress("2001:db8:1::1"),
+               IOAddress("2001:db8:1::f"));
+
+   EXPECT_FALSE(pool1.inRange(IOAddress("2001:db8:1::")));
+   EXPECT_TRUE(pool1.inRange(IOAddress("2001:db8:1::1")));
+   EXPECT_TRUE(pool1.inRange(IOAddress("2001:db8:1::7")));
+   EXPECT_TRUE(pool1.inRange(IOAddress("2001:db8:1::f")));
+   EXPECT_FALSE(pool1.inRange(IOAddress("2001:db8:1::10")));
+   EXPECT_FALSE(pool1.inRange(IOAddress("::")));
+}
+
+// This test creates 100 pools and verifies that their IDs are unique.
+TEST(Pool6Test, unique_id) {
+
+    const int num_pools = 100;
+    std::vector<Pool6Ptr> pools;
+
+    for (int i = 0; i < num_pools; ++i) {
+        pools.push_back(Pool6Ptr(new Pool6(Pool6::TYPE_IA, IOAddress("2001:db8:1::"),
+                                           IOAddress("2001:db8:1::ffff:ffff:ffff:ffff"))));
+    }
+
+    for (int i = 0; i < num_pools; ++i) {
+        for (int j = i + 1; j < num_pools; ++j) {
+            if (pools[i]->getId() == pools[j]->getId()) {
+                FAIL() << "Pool-ids must be unique";
+            }
+        }
+    }
+
+}
+
+}; // end of anonymous namespace
diff --git a/src/lib/dhcpsrv/tests/run_unittests.cc b/src/lib/dhcpsrv/tests/run_unittests.cc
new file mode 100644
index 0000000..bd32c4d
--- /dev/null
+++ b/src/lib/dhcpsrv/tests/run_unittests.cc
@@ -0,0 +1,27 @@
+// 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 <log/logger_support.h>
+
+#include <gtest/gtest.h>
+
+int
+main(int argc, char* argv[]) {
+    ::testing::InitGoogleTest(&argc, argv);
+    isc::log::initLogger();
+
+    int result = RUN_ALL_TESTS();
+
+    return (result);
+}
diff --git a/src/lib/dhcpsrv/tests/schema_copy.h b/src/lib/dhcpsrv/tests/schema_copy.h
new file mode 100644
index 0000000..1dd796d
--- /dev/null
+++ b/src/lib/dhcpsrv/tests/schema_copy.h
@@ -0,0 +1,85 @@
+// 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 SCHEMA_COPY_H
+#define SCHEMA_COPY_H
+
+namespace {
+
+// What follows is a set of statements that creates a copy of the schema
+// in the test database.  It is used by the MySQL unit test prior to each
+// test.
+//
+// Each SQL statement is a single string.  The statements are not terminated
+// by semicolons, and the strings must end with a comma.  The final line
+// statement must be NULL (not in quotes)
+
+// THIS MUST BE KEPT UP TO DATE AND UPDATED IF THE SCHEMA CHANGES
+
+// Deletion of existing tables.
+
+const char* destroy_statement[] = {
+    "DROP TABLE lease4",
+    "DROP TABLE lease6",
+    "DROP TABLE lease6_types",
+    "DROP TABLE schema_version",
+    NULL
+};
+
+// Creation of the new tables.
+
+const char* create_statement[] = {
+    "CREATE TABLE lease4 ("
+        "address INT UNSIGNED PRIMARY KEY NOT NULL,"
+        "hwaddr VARBINARY(20),"
+        "client_id VARBINARY(128),"
+        "lease_time INT UNSIGNED,"
+        "expire TIMESTAMP,"
+        "subnet_id INT UNSIGNED"
+        ") ENGINE = INNODB",
+
+    "CREATE TABLE lease6 ("
+        "address VARCHAR(40) PRIMARY KEY NOT NULL,"
+        "duid VARBINARY(128),"
+        "valid_lifetime INT UNSIGNED,"
+        "expire TIMESTAMP,"
+        "subnet_id INT UNSIGNED,"
+        "pref_lifetime INT UNSIGNED,"
+        "lease_type TINYINT,"
+        "iaid INT UNSIGNED,"
+        "prefix_len TINYINT UNSIGNED"
+        ") ENGINE = INNODB",
+
+    "CREATE TABLE lease6_types ("
+        "lease_type TINYINT PRIMARY KEY NOT NULL,"
+        "name VARCHAR(5)"
+        ")",
+
+    "INSERT INTO lease6_types VALUES (0, \"IA_NA\")",
+    "INSERT INTO lease6_types VALUES (1, \"IA_TA\")",
+    "INSERT INTO lease6_types VALUES (2, \"IA_PD\")",
+
+    "CREATE TABLE schema_version ("
+        "version INT PRIMARY KEY NOT NULL,"
+        "minor INT"
+        ")",
+
+    "INSERT INTO schema_version VALUES (0, 1)",
+
+    NULL
+};
+
+};  // Anonymous namespace
+
+#endif // SCHEMA_COPY_H
diff --git a/src/lib/dhcpsrv/tests/subnet_unittest.cc b/src/lib/dhcpsrv/tests/subnet_unittest.cc
new file mode 100644
index 0000000..9ebef9c
--- /dev/null
+++ b/src/lib/dhcpsrv/tests/subnet_unittest.cc
@@ -0,0 +1,448 @@
+// 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 <config.h>
+
+#include <asiolink/io_address.h>
+#include <dhcp/option.h>
+#include <dhcpsrv/subnet.h>
+#include <exceptions/exceptions.h>
+
+#include <boost/scoped_ptr.hpp>
+#include <gtest/gtest.h>
+
+// don't import the entire boost namespace.  It will unexpectedly hide uint8_t
+// for some systems.
+using boost::scoped_ptr;
+using namespace isc;
+using namespace isc::dhcp;
+using namespace isc::asiolink;
+
+namespace {
+
+TEST(Subnet4Test, constructor) {
+    EXPECT_NO_THROW(Subnet4 subnet1(IOAddress("192.0.2.2"), 16,
+                                    1, 2, 3));
+
+    EXPECT_THROW(Subnet4 subnet2(IOAddress("192.0.2.0"), 33, 1, 2, 3),
+                BadValue); // invalid prefix length
+    EXPECT_THROW(Subnet4 subnet3(IOAddress("2001:db8::1"), 24, 1, 2, 3),
+                BadValue); // IPv6 addresses are not allowed in Subnet4
+}
+
+TEST(Subnet4Test, in_range) {
+    Subnet4 subnet(IOAddress("192.0.2.1"), 24, 1000, 2000, 3000);
+
+    EXPECT_EQ(1000, subnet.getT1());
+    EXPECT_EQ(2000, subnet.getT2());
+    EXPECT_EQ(3000, subnet.getValid());
+
+    EXPECT_FALSE(subnet.inRange(IOAddress("192.0.0.0")));
+    EXPECT_TRUE(subnet.inRange(IOAddress("192.0.2.0")));
+    EXPECT_TRUE(subnet.inRange(IOAddress("192.0.2.1")));
+    EXPECT_TRUE(subnet.inRange(IOAddress("192.0.2.255")));
+    EXPECT_FALSE(subnet.inRange(IOAddress("192.0.3.0")));
+    EXPECT_FALSE(subnet.inRange(IOAddress("0.0.0.0")));
+    EXPECT_FALSE(subnet.inRange(IOAddress("255.255.255.255")));
+}
+
+TEST(Subnet4Test, Pool4InSubnet4) {
+
+    Subnet4Ptr subnet(new Subnet4(IOAddress("192.1.2.0"), 24, 1, 2, 3));
+
+    Pool4Ptr pool1(new Pool4(IOAddress("192.1.2.0"), 25));
+    Pool4Ptr pool2(new Pool4(IOAddress("192.1.2.128"), 26));
+    Pool4Ptr pool3(new Pool4(IOAddress("192.1.2.192"), 30));
+
+    subnet->addPool4(pool1);
+
+    // If there's only one pool, get that pool
+    Pool4Ptr mypool = subnet->getPool4();
+    EXPECT_EQ(mypool, pool1);
+
+
+    subnet->addPool4(pool2);
+    subnet->addPool4(pool3);
+
+    // If there are more than one pool and we didn't provide hint, we
+    // should get the first pool
+    mypool = subnet->getPool4();
+
+    EXPECT_EQ(mypool, pool1);
+
+    // If we provide a hint, we should get a pool that this hint belongs to
+    mypool = subnet->getPool4(IOAddress("192.1.2.195"));
+
+    EXPECT_EQ(mypool, pool3);
+
+}
+
+TEST(Subnet4Test, Subnet4_Pool4_checks) {
+
+    Subnet4Ptr subnet(new Subnet4(IOAddress("192.0.2.0"), 8, 1, 2, 3));
+
+    // this one is in subnet
+    Pool4Ptr pool1(new Pool4(IOAddress("192.255.0.0"), 16));
+    subnet->addPool4(pool1);
+
+    // this one is larger than the subnet!
+    Pool4Ptr pool2(new Pool4(IOAddress("193.0.0.0"), 24));
+
+    EXPECT_THROW(subnet->addPool4(pool2), BadValue);
+
+    // this one is totally out of blue
+    Pool4Ptr pool3(new Pool4(IOAddress("1.2.3.4"), 16));
+    EXPECT_THROW(subnet->addPool4(pool3), BadValue);
+}
+
+TEST(Subnet4Test, addInvalidOption) {
+    // Create the V4 subnet.
+    Subnet4Ptr subnet(new Subnet4(IOAddress("192.0.2.0"), 8, 1, 2, 3));
+
+    // Some dummy option code.
+    uint16_t code = 100;
+    // Create option with invalid universe (V6 instead of V4).
+    // Attempt to add this option should result in exception.
+    OptionPtr option1(new Option(Option::V6, code, OptionBuffer(10, 0xFF)));
+    EXPECT_THROW(subnet->addOption(option1), isc::BadValue);
+
+    // Create NULL pointer option. Attempt to add NULL option
+    // should result in exception.
+    OptionPtr option2;
+    ASSERT_FALSE(option2);
+    EXPECT_THROW(subnet->addOption(option2), isc::BadValue);
+}
+
+// This test verifies that inRange() and inPool() methods work properly.
+TEST(Subnet4Test, inRangeinPool) {
+    Subnet4Ptr subnet(new Subnet4(IOAddress("192.0.0.0"), 8, 1, 2, 3));
+
+    // this one is in subnet
+    Pool4Ptr pool1(new Pool4(IOAddress("192.2.0.0"), 16));
+    subnet->addPool4(pool1);
+
+    // 192.1.1.1 belongs to the subnet...
+    EXPECT_TRUE(subnet->inRange(IOAddress("192.1.1.1")));
+
+    // ... but it does not belong to any pool within
+    EXPECT_FALSE(subnet->inPool(IOAddress("192.1.1.1")));
+
+    // the last address that is in range, but out of pool
+    EXPECT_TRUE(subnet->inRange(IOAddress("192.1.255.255")));
+    EXPECT_FALSE(subnet->inPool(IOAddress("192.1.255.255")));
+
+    // the first address that is in range, in pool
+    EXPECT_TRUE(subnet->inRange(IOAddress("192.2.0.0")));
+    EXPECT_TRUE (subnet->inPool(IOAddress("192.2.0.0")));
+
+    // let's try something in the middle as well
+    EXPECT_TRUE(subnet->inRange(IOAddress("192.2.3.4")));
+    EXPECT_TRUE (subnet->inPool(IOAddress("192.2.3.4")));
+
+    // the last address that is in range, in pool
+    EXPECT_TRUE(subnet->inRange(IOAddress("192.2.255.255")));
+    EXPECT_TRUE (subnet->inPool(IOAddress("192.2.255.255")));
+
+    // the first address that is in range, but out of pool
+    EXPECT_TRUE(subnet->inRange(IOAddress("192.3.0.0")));
+    EXPECT_FALSE(subnet->inPool(IOAddress("192.3.0.0")));
+}
+
+// This test checks if the toText() method returns text representation
+TEST(Subnet4Test, toText) {
+    Subnet4Ptr subnet(new Subnet4(IOAddress("192.0.2.0"), 24, 1, 2, 3));
+    EXPECT_EQ("192.0.2.0/24", subnet->toText());
+}
+
+// This test checks if the get() method returns proper parameters
+TEST(Subnet4Test, get) {
+    Subnet4Ptr subnet(new Subnet4(IOAddress("192.0.2.0"), 28, 1, 2, 3));
+    EXPECT_EQ("192.0.2.0", subnet->get().first.toText());
+    EXPECT_EQ(28, subnet->get().second);
+}
+
+// Tests for Subnet6
+
+TEST(Subnet6Test, constructor) {
+
+    EXPECT_NO_THROW(Subnet6 subnet1(IOAddress("2001:db8:1::"), 64,
+                                    1, 2, 3, 4));
+
+    EXPECT_THROW(Subnet6 subnet2(IOAddress("2001:db8:1::"), 129, 1, 2, 3, 4),
+                BadValue); // invalid prefix length
+    EXPECT_THROW(Subnet6 subnet3(IOAddress("192.168.0.0"), 32, 1, 2, 3, 4),
+                BadValue); // IPv4 addresses are not allowed in Subnet6
+}
+
+TEST(Subnet6Test, in_range) {
+    Subnet6 subnet(IOAddress("2001:db8:1::"), 64, 1000, 2000, 3000, 4000);
+
+    EXPECT_EQ(1000, subnet.getT1());
+    EXPECT_EQ(2000, subnet.getT2());
+    EXPECT_EQ(3000, subnet.getPreferred());
+    EXPECT_EQ(4000, subnet.getValid());
+
+    EXPECT_FALSE(subnet.inRange(IOAddress("2001:db8:0:ffff:ffff:ffff:ffff:ffff")));
+    EXPECT_TRUE(subnet.inRange(IOAddress("2001:db8:1::0")));
+    EXPECT_TRUE(subnet.inRange(IOAddress("2001:db8:1::1")));
+    EXPECT_TRUE(subnet.inRange(IOAddress("2001:db8:1::ffff:ffff:ffff:ffff")));
+    EXPECT_FALSE(subnet.inRange(IOAddress("2001:db8:1:1::")));
+    EXPECT_FALSE(subnet.inRange(IOAddress("::")));
+}
+
+TEST(Subnet6Test, Pool6InSubnet6) {
+
+    Subnet6Ptr subnet(new Subnet6(IOAddress("2001:db8:1::"), 56, 1, 2, 3, 4));
+
+    Pool6Ptr pool1(new Pool6(Pool6::TYPE_IA, IOAddress("2001:db8:1:1::"), 64));
+    Pool6Ptr pool2(new Pool6(Pool6::TYPE_IA, IOAddress("2001:db8:1:2::"), 64));
+    Pool6Ptr pool3(new Pool6(Pool6::TYPE_IA, IOAddress("2001:db8:1:3::"), 64));
+
+    subnet->addPool6(pool1);
+
+    // If there's only one pool, get that pool
+    Pool6Ptr mypool = subnet->getPool6();
+    EXPECT_EQ(mypool, pool1);
+
+
+    subnet->addPool6(pool2);
+    subnet->addPool6(pool3);
+
+    // If there are more than one pool and we didn't provide hint, we
+    // should get the first pool
+    mypool = subnet->getPool6();
+
+    EXPECT_EQ(mypool, pool1);
+
+    // If we provide a hint, we should get a pool that this hint belongs to
+    mypool = subnet->getPool6(IOAddress("2001:db8:1:3::dead:beef"));
+
+    EXPECT_EQ(mypool, pool3);
+}
+
+TEST(Subnet6Test, Subnet6_Pool6_checks) {
+
+    Subnet6Ptr subnet(new Subnet6(IOAddress("2001:db8:1::"), 56, 1, 2, 3, 4));
+
+    // this one is in subnet
+    Pool6Ptr pool1(new Pool6(Pool6::TYPE_IA, IOAddress("2001:db8:1:1::"), 64));
+    subnet->addPool6(pool1);
+
+    // this one is larger than the subnet!
+    Pool6Ptr pool2(new Pool6(Pool6::TYPE_IA, IOAddress("2001:db8::"), 48));
+
+    EXPECT_THROW(subnet->addPool6(pool2), BadValue);
+
+
+    // this one is totally out of blue
+    Pool6Ptr pool3(new Pool6(Pool6::TYPE_IA, IOAddress("3000::"), 16));
+    EXPECT_THROW(subnet->addPool6(pool3), BadValue);
+
+
+    Pool6Ptr pool4(new Pool6(Pool6::TYPE_IA, IOAddress("4001:db8:1::"), 80));
+    EXPECT_THROW(subnet->addPool6(pool4), BadValue);
+}
+
+TEST(Subnet6Test, addOptions) {
+    // Create as subnet to add options to it.
+    Subnet6Ptr subnet(new Subnet6(IOAddress("2001:db8:1::"), 56, 1, 2, 3, 4));
+
+    // Differentiate options by their codes (100-109)
+    for (uint16_t code = 100; code < 110; ++code) {
+        OptionPtr option(new Option(Option::V6, code, OptionBuffer(10, 0xFF)));
+        ASSERT_NO_THROW(subnet->addOption(option));
+    }
+
+    // Get options from the Subnet and check if all 10 are there.
+    Subnet::OptionContainer options = subnet->getOptions();
+    ASSERT_EQ(10, options.size());
+
+    // Validate codes of added options.
+    uint16_t expected_code = 100;
+    for (Subnet::OptionContainer::const_iterator option_desc = options.begin();
+         option_desc != options.end(); ++option_desc) {
+        ASSERT_TRUE(option_desc->option);
+        EXPECT_EQ(expected_code, option_desc->option->getType());
+        ++expected_code;
+    }
+
+    subnet->delOptions();
+
+    options = subnet->getOptions();
+    EXPECT_EQ(0, options.size());
+}
+
+TEST(Subnet6Test, addNonUniqueOptions) {
+    // Create as subnet to add options to it.
+    Subnet6Ptr subnet(new Subnet6(IOAddress("2001:db8:1::"), 56, 1, 2, 3, 4));
+
+    // Create a set of options with non-unique codes.
+    for (int i = 0;  i < 2; ++i) {
+        // In the inner loop we create options with unique codes (100-109).
+        for (uint16_t code = 100; code < 110; ++code) {
+            OptionPtr option(new Option(Option::V6, code, OptionBuffer(10, 0xFF)));
+            ASSERT_NO_THROW(subnet->addOption(option));
+        }
+    }
+
+    // Sanity check that all options are there.
+    Subnet::OptionContainer options = subnet->getOptions();
+    ASSERT_EQ(20, options.size());
+
+    // Use container index #1 to get the options by their codes.
+    Subnet::OptionContainerTypeIndex& idx = options.get<1>();
+    // Look for the codes 100-109.
+    for (uint16_t code = 100; code < 110; ++ code) {
+        // For each code we should get two instances of options.
+        std::pair<Subnet::OptionContainerTypeIndex::const_iterator,
+                  Subnet::OptionContainerTypeIndex::const_iterator> range =
+            idx.equal_range(code);
+        // Distance between iterators indicates how many options
+        // have been retured for the particular code.
+        ASSERT_EQ(2, distance(range.first, range.second));
+        // Check that returned options actually have the expected option code.
+        for (Subnet::OptionContainerTypeIndex::const_iterator option_desc = range.first;
+             option_desc != range.second; ++option_desc) {
+            ASSERT_TRUE(option_desc->option);
+            EXPECT_EQ(code, option_desc->option->getType());
+        }
+    }
+
+    // Let's try to find some non-exiting option.
+    const uint16_t non_existing_code = 150;
+    std::pair<Subnet::OptionContainerTypeIndex::const_iterator,
+              Subnet::OptionContainerTypeIndex::const_iterator> range =
+        idx.equal_range(non_existing_code);
+    // Empty set is expected.
+    EXPECT_EQ(0, distance(range.first, range.second));
+
+    subnet->delOptions();
+
+    options = subnet->getOptions();
+    EXPECT_EQ(0, options.size());
+}
+
+TEST(Subnet6Test, addInvalidOption) {
+    // Create as subnet to add options to it.
+    Subnet6Ptr subnet(new Subnet6(IOAddress("2001:db8:1::"), 56, 1, 2, 3, 4));
+
+    // Some dummy option code.
+    uint16_t code = 100;
+    // Create option with invalid universe (V4 instead of V6).
+    // Attempt to add this option should result in exception.
+    OptionPtr option1(new Option(Option::V4, code, OptionBuffer(10, 0xFF)));
+    EXPECT_THROW(subnet->addOption(option1), isc::BadValue);
+
+    // Create NULL pointer option. Attempt to add NULL option
+    // should result in exception.
+    OptionPtr option2;
+    ASSERT_FALSE(option2);
+    EXPECT_THROW(subnet->addOption(option2), isc::BadValue);
+}
+
+TEST(Subnet6Test, addPersistentOption) {
+    // Create as subnet to add options to it.
+    Subnet6Ptr subnet(new Subnet6(IOAddress("2001:db8:1::"), 56, 1, 2, 3, 4));
+
+    // Add 10 options to the subnet with option codes 100 - 109.
+    for (uint16_t code = 100; code < 110; ++code) {
+        OptionPtr option(new Option(Option::V6, code, OptionBuffer(10, 0xFF)));
+        // We create 10 options and want some of them to be flagged
+        // persistent and some non-persistent. Persistent options are
+        // those that server sends to clients regardless if they ask
+        // for them or not. We pick 3 out of 10 options and mark them
+        // non-persistent and 7 other options persistent.
+        // Code values: 102, 105 and 108 are divisable by 3
+        // and options with these codes will be flagged non-persistent.
+        // Options with other codes will be flagged persistent.
+        bool persistent = (code % 3) ? true : false;
+        ASSERT_NO_THROW(subnet->addOption(option, persistent));
+    }
+
+    // Get added options from the subnet.
+    Subnet::OptionContainer options = subnet->getOptions();
+
+    // options.get<2> returns reference to container index #2. This
+    // index is used to access options by the 'persistent' flag.
+    Subnet::OptionContainerPersistIndex& idx = options.get<2>();
+
+    // Get all persistent options.
+    std::pair<Subnet::OptionContainerPersistIndex::const_iterator,
+              Subnet::OptionContainerPersistIndex::const_iterator> range_persistent =
+        idx.equal_range(true);
+    // 3 out of 10 options have been flagged persistent.
+    ASSERT_EQ(7, distance(range_persistent.first, range_persistent.second));
+
+    // Get all non-persistent options.
+    std::pair<Subnet::OptionContainerPersistIndex::const_iterator,
+              Subnet::OptionContainerPersistIndex::const_iterator> range_non_persistent =
+        idx.equal_range(false);
+    // 7 out of 10 options have been flagged persistent.
+    ASSERT_EQ(3, distance(range_non_persistent.first, range_non_persistent.second));
+
+    subnet->delOptions();
+
+    options = subnet->getOptions();
+    EXPECT_EQ(0, options.size());
+}
+
+// This test verifies that inRange() and inPool() methods work properly.
+TEST(Subnet6Test, inRangeinPool) {
+    Subnet6Ptr subnet(new Subnet6(IOAddress("2001:db8::"), 32, 1, 2, 3, 4));
+
+    // this one is in subnet
+    Pool6Ptr pool1(new Pool6(Pool6::TYPE_IA, IOAddress("2001:db8::10"),
+                             IOAddress("2001:db8::20")));
+    subnet->addPool6(pool1);
+
+    // 192.1.1.1 belongs to the subnet...
+    EXPECT_TRUE(subnet->inRange(IOAddress("2001:db8::1")));
+    // ... but it does not belong to any pool within
+    EXPECT_FALSE(subnet->inPool(IOAddress("2001:db8::1")));
+
+    // the last address that is in range, but out of pool
+    EXPECT_TRUE(subnet->inRange(IOAddress("2001:db8::f")));
+    EXPECT_FALSE(subnet->inPool(IOAddress("2001:db8::f")));
+
+    // the first address that is in range, in pool
+    EXPECT_TRUE(subnet->inRange(IOAddress("2001:db8::10")));
+    EXPECT_TRUE (subnet->inPool(IOAddress("2001:db8::10")));
+
+    // let's try something in the middle as well
+    EXPECT_TRUE(subnet->inRange(IOAddress("2001:db8::18")));
+    EXPECT_TRUE (subnet->inPool(IOAddress("2001:db8::18")));
+
+    // the last address that is in range, in pool
+    EXPECT_TRUE(subnet->inRange(IOAddress("2001:db8::20")));
+    EXPECT_TRUE (subnet->inPool(IOAddress("2001:db8::20")));
+
+    // the first address that is in range, but out of pool
+    EXPECT_TRUE(subnet->inRange(IOAddress("2001:db8::21")));
+    EXPECT_FALSE(subnet->inPool(IOAddress("2001:db8::21")));
+}
+
+// This test checks if the toText() method returns text representation
+TEST(Subnet6Test, toText) {
+    Subnet6 subnet(IOAddress("2001:db8::"), 32, 1, 2, 3, 4);
+    EXPECT_EQ("2001:db8::/32", subnet.toText());
+}
+
+// This test checks if the get() method returns proper parameters
+TEST(Subnet6Test, get) {
+    Subnet6 subnet(IOAddress("2001:db8::"), 32, 1, 2, 3, 4);
+    EXPECT_EQ("2001:db8::", subnet.get().first.toText());
+    EXPECT_EQ(32, subnet.get().second);
+}
+
+};
diff --git a/src/lib/dhcpsrv/tests/triplet_unittest.cc b/src/lib/dhcpsrv/tests/triplet_unittest.cc
new file mode 100644
index 0000000..8edf4fa
--- /dev/null
+++ b/src/lib/dhcpsrv/tests/triplet_unittest.cc
@@ -0,0 +1,106 @@
+// 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 <config.h>
+
+#include <dhcpsrv/triplet.h>
+#include <exceptions/exceptions.h>
+
+#include <stdint.h>
+#include <gtest/gtest.h>
+
+using namespace isc::dhcp;
+using namespace isc;
+
+namespace {
+
+// constructor validation
+TEST(TripletTest, constructor) {
+
+    const uint32_t min = 10;
+    const uint32_t value = 20;
+    const uint32_t max = 30;
+
+    Triplet<uint32_t> x(min, value, max);
+
+    EXPECT_EQ(min, x.getMin());
+    EXPECT_EQ(value, x.get());
+    EXPECT_EQ(max, x.getMax());
+
+    // requested values below min should return allowed min value
+    EXPECT_EQ(min, x.get(min - 5));
+
+    EXPECT_EQ(min, x.get(min));
+
+    // requesting a value from within the range (min < x < max) should
+    // return the requested value
+    EXPECT_EQ(17, x.get(17));
+
+    EXPECT_EQ(max, x.get(max));
+
+    EXPECT_EQ(max, x.get(max + 5));
+
+    // this will be boring. It is expected to return 42 no matter what
+    Triplet<uint32_t> y(42);
+
+    EXPECT_EQ(42, y.getMin()); // min, default and max are equal to 42
+    EXPECT_EQ(42, y.get());    // it returns ...
+    EXPECT_EQ(42, y.getMax()); // the exact value...
+
+    // requested values below or above are ignore
+    EXPECT_EQ(42, y.get(5));   // all...
+    EXPECT_EQ(42, y.get(42));  // the...
+    EXPECT_EQ(42, y.get(80));  // time!
+}
+
+// Triplets must be easy to use.
+// Simple to/from int conversions must be done on the fly.
+TEST(TripletTest, operator) {
+
+    uint32_t x = 47;
+
+    Triplet<uint32_t> foo(1,2,3);
+    Triplet<uint32_t> bar(4,5,6);
+
+    foo = bar;
+
+    EXPECT_EQ(4, foo.getMin());
+    EXPECT_EQ(5, foo.get());
+    EXPECT_EQ(6, foo.getMax());
+
+    // assignment operator: uint32_t => triplet
+    Triplet<uint32_t> y(0);
+    y = x;
+
+    EXPECT_EQ(x, y.get());
+
+    // let's try the other way around: triplet => uint32_t
+    uint32_t z = 0;
+    z = y;
+
+    EXPECT_EQ(x, z);
+}
+
+// check if specified values are sane
+TEST(TripletTest, sanity_check) {
+
+    // min is larger than default
+    EXPECT_THROW(Triplet<uint32_t>(6,5,5), BadValue);
+
+    // max is smaller than default
+    EXPECT_THROW(Triplet<uint32_t>(5,5,4), BadValue);
+
+}
+
+}; // end of anonymous namespace
diff --git a/src/lib/dhcpsrv/triplet.h b/src/lib/dhcpsrv/triplet.h
new file mode 100644
index 0000000..d9388fe
--- /dev/null
+++ b/src/lib/dhcpsrv/triplet.h
@@ -0,0 +1,115 @@
+// 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 TRIPLET_H
+#define TRIPLET_H
+
+#include <exceptions/exceptions.h>
+
+namespace isc {
+namespace dhcp {
+
+/// @brief this template specifies a parameter value
+///
+/// This template class is used to store configuration parameters, like lifetime or T1.
+/// It defines 3 parameters: min, default, and max value. There are 2 constructors:
+/// - simple (just one value that sets all parameters)
+/// - extended (that sets default value and two thresholds)
+/// It will be used with integer types. It provides necessary operators, so
+/// it can be assigned to a plain integer or integer assigned to a Triplet.
+/// See TripletTest.operator test for details on an easy Triplet usage.
+template <class T>
+class Triplet {
+public:
+
+    /// @brief base type to Triple conversion
+    ///
+    /// Typically: uint32_t to Triplet assignment. It is very convenient
+    /// to be able to simply write Triplet<uint32_t> x = 7;
+    Triplet<T> operator=(T other) {
+        min_ = other;
+        default_ = other;
+        max_ = other;
+        return *this;
+    }
+
+    /// @brief triplet to base type conversion
+    ///
+    /// Typically: Triplet to uint32_t assignment. It is very convenient
+    /// to be able to simply write uint32_t z = x; (where x is a Triplet)
+    operator T() const {
+        return (default_);
+    }
+
+    /// @brief sets a fixed value
+    ///
+    /// This constructor assigns a fixed (i.e. no range, just a single value)
+    /// value.
+    Triplet(T value)
+        :min_(value), default_(value), max_(value) {
+    }
+
+    /// @brief sets the default value and thresholds
+    ///
+    /// @throw BadValue if min <= def <= max rule is violated
+    Triplet(T min, T def, T max)
+        :min_(min), default_(def), max_(max) {
+        if ( (min_ > def) || (def > max_) ) {
+            isc_throw(BadValue, "Invalid triplet values.");
+        }
+    }
+
+    /// @brief returns a minimum allowed value
+    T getMin() const { return min_;}
+
+    /// @brief returns the default value
+    T get() const { return default_;}
+
+    /// @brief returns value with a hint
+    ///
+    /// DHCP protocol treats any values sent by a client as hints.
+    /// This is a method that implements that. We can assign any value
+    /// from configured range that client asks.
+    T get(T hint) const {
+        if (hint <= min_) {
+            return (min_);
+        }
+
+        if (hint >= max_) {
+            return (max_);
+        }
+
+        return (hint);
+    }
+
+    /// @brief returns a maximum allowed value
+    T getMax() const { return max_; }
+
+protected:
+
+    /// @brief the minimum value
+    T min_;
+
+    /// @brief the default value
+    T default_;
+
+    /// @brief the maximum value
+    T max_;
+};
+
+
+} // namespace isc::dhcp
+} // namespace isc
+
+#endif // ifdef TRIPLET_H



More information about the bind10-changes mailing list