summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThomas Markwalder <tmark@isc.org>2013-10-11 20:10:06 +0200
committerThomas Markwalder <tmark@isc.org>2013-10-11 20:10:06 +0200
commitf0edd52c244689cd370853d520bc6e97d23a3bb2 (patch)
tree8712fa5450977c297b865f6e800f678d76fcab7b
parent[master] Added ChangeLog entry for #3180. (diff)
downloadkea-f0edd52c244689cd370853d520bc6e97d23a3bb2.tar.xz
kea-f0edd52c244689cd370853d520bc6e97d23a3bb2.zip
[3186] Initial classes in DHCP user check hook library
Adds new source tree branch, bind10/src/hooks, for maintaining custom hooks libraries. Adds bare bones implementation of UserRegistry for use in custom DHCP hooks library.
-rw-r--r--configure.ac4
-rw-r--r--src/Makefile.am2
-rw-r--r--src/hooks/Makefile.am1
-rw-r--r--src/hooks/dhcp/Makefile.am1
-rw-r--r--src/hooks/dhcp/user_chk/Makefile.am59
-rw-r--r--src/hooks/dhcp/user_chk/load_unload.cc32
-rw-r--r--src/hooks/dhcp/user_chk/tests/Makefile.am62
-rw-r--r--src/hooks/dhcp/user_chk/tests/run_unittests.cc27
-rw-r--r--src/hooks/dhcp/user_chk/tests/user_registry_unittests.cc133
-rw-r--r--src/hooks/dhcp/user_chk/tests/user_unittests.cc72
-rw-r--r--src/hooks/dhcp/user_chk/tests/userid_unittests.cc165
-rw-r--r--src/hooks/dhcp/user_chk/user.cc226
-rw-r--r--src/hooks/dhcp/user_chk/user.h109
-rw-r--r--src/hooks/dhcp/user_chk/user_data_source.cc49
-rw-r--r--src/hooks/dhcp/user_chk/user_data_source.h42
-rw-r--r--src/hooks/dhcp/user_chk/user_registry.cc89
-rw-r--r--src/hooks/dhcp/user_chk/user_registry.h62
-rw-r--r--src/hooks/dhcp/user_chk/version.cc24
18 files changed, 1159 insertions, 0 deletions
diff --git a/configure.ac b/configure.ac
index 7786ab552b..e464d2c5da 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1288,6 +1288,10 @@ AC_CONFIG_FILES([Makefile
src/bin/usermgr/Makefile
src/bin/usermgr/tests/Makefile
src/bin/tests/Makefile
+ src/hooks/Makefile
+ src/hooks/dhcp/Makefile
+ src/hooks/dhcp/user_chk/Makefile
+ src/hooks/dhcp/user_chk/tests/Makefile
src/lib/Makefile
src/lib/asiolink/Makefile
src/lib/asiolink/tests/Makefile
diff --git a/src/Makefile.am b/src/Makefile.am
index 395553c6fa..04e464c5be 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -1,4 +1,6 @@
SUBDIRS = lib bin
+# hooks lib could be a configurable switch
+SUBDIRS += hooks
EXTRA_DIST = \
cppcheck-suppress.lst \
diff --git a/src/hooks/Makefile.am b/src/hooks/Makefile.am
new file mode 100644
index 0000000000..815beed70b
--- /dev/null
+++ b/src/hooks/Makefile.am
@@ -0,0 +1 @@
+SUBDIRS = dhcp
diff --git a/src/hooks/dhcp/Makefile.am b/src/hooks/dhcp/Makefile.am
new file mode 100644
index 0000000000..6785617c01
--- /dev/null
+++ b/src/hooks/dhcp/Makefile.am
@@ -0,0 +1 @@
+SUBDIRS = user_chk
diff --git a/src/hooks/dhcp/user_chk/Makefile.am b/src/hooks/dhcp/user_chk/Makefile.am
new file mode 100644
index 0000000000..898067ab29
--- /dev/null
+++ b/src/hooks/dhcp/user_chk/Makefile.am
@@ -0,0 +1,59 @@
+SUBDIRS = . tests
+
+AM_CPPFLAGS = -I$(top_builddir)/src/lib -I$(top_srcdir)/src/lib
+AM_CPPFLAGS += $(BOOST_INCLUDES)
+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)
+
+# Define rule to build logging source files from message file
+# hooks_messages.h hooks_messages.cc: s-messages
+
+# s-messages: hooks_messages.mes
+# $(top_builddir)/src/lib/log/compiler/message $(top_srcdir)/src/lib/hooks/hooks_messages.mes
+# touch $@
+
+# Tell automake that the message files are built as part of the build process
+# (so that they are built before the main library is built).
+# BUILT_SOURCES = hooks_messages.h hooks_messages.cc
+BUILT_SOURCES =
+
+# Ensure that the message file is included in the distribution
+EXTRA_DIST =
+
+# Get rid of generated message files on a clean
+# CLEANFILES = *.gcno *.gcda hooks_messages.h hooks_messages.cc s-messages
+CLEANFILES = *.gcno *.gcda
+
+lib_LTLIBRARIES = libdhcp_user_chk.la
+libdhcp_user_chk_la_SOURCES =
+libdhcp_user_chk_la_SOURCES += load_unload.cc
+libdhcp_user_chk_la_SOURCES += user.cc user.h
+libdhcp_user_chk_la_SOURCES += user_data_source.cc user_data_source.h
+libdhcp_user_chk_la_SOURCES += user_registry.cc user_registry.h
+libdhcp_user_chk_la_SOURCES += version.cc
+
+#nodist_libdhcp_user_chk_la_SOURCES = hooks_messages.cc hooks_messages.h
+nodist_libdhcp_user_chk_la_SOURCES =
+
+libdhcp_user_chk_la_CXXFLAGS = $(AM_CXXFLAGS)
+libdhcp_user_chk_la_CPPFLAGS = $(AM_CPPFLAGS) $(LOG4CPLUS_INCLUDES)
+libdhcp_user_chk_la_LDFLAGS = $(AM_LDFLAGS)
+libdhcp_user_chk_la_LDFLAGS += -avoid-version -export-dynamic -module
+libdhcp_user_chk_la_LIBADD =
+libdhcp_user_chk_la_LIBADD += $(top_builddir)/src/lib/hooks/libb10-hooks.la
+libdhcp_user_chk_la_LIBADD += $(top_builddir)/src/lib/log/libb10-log.la
+libdhcp_user_chk_la_LIBADD += $(top_builddir)/src/lib/exceptions/libb10-exceptions.la
+libdhcp_user_chk_la_LIBADD += $(top_builddir)/src/lib/util/libb10-util.la
+libdhcp_user_chk_la_LIBADD += $(top_builddir)/src/lib/util/threads/libb10-threads.la
+
+
+if USE_CLANGPP
+# Disable unused parameter warning caused by some of the
+# Boost headers when compiling with clang.
+libdhcp_user_chk_la_CXXFLAGS += -Wno-unused-parameter
+endif
diff --git a/src/hooks/dhcp/user_chk/load_unload.cc b/src/hooks/dhcp/user_chk/load_unload.cc
new file mode 100644
index 0000000000..2d10fa4865
--- /dev/null
+++ b/src/hooks/dhcp/user_chk/load_unload.cc
@@ -0,0 +1,32 @@
+// Copyright (C) 2013 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.
+// load_unload.cc
+
+#include <hooks/hooks.h>
+
+using namespace isc::hooks;
+
+extern "C" {
+
+int load(LibraryHandle&) {
+ // @todo instantiate registry here
+ return (0);
+}
+
+int unload() {
+ // @todo destruct registry here
+ return (0);
+}
+
+}
diff --git a/src/hooks/dhcp/user_chk/tests/Makefile.am b/src/hooks/dhcp/user_chk/tests/Makefile.am
new file mode 100644
index 0000000000..51e0ebf36e
--- /dev/null
+++ b/src/hooks/dhcp/user_chk/tests/Makefile.am
@@ -0,0 +1,62 @@
+SUBDIRS = .
+
+AM_CPPFLAGS = -I$(top_builddir)/src/lib -I$(top_srcdir)/src/lib
+AM_CPPFLAGS += -I$(top_builddir)/src/hooks/dhcp/user_chk
+AM_CPPFLAGS += $(BOOST_INCLUDES) $(BOTAN_INCLUDES)
+AM_CPPFLAGS += -DTEST_DATA_BUILDDIR=\"$(abs_top_builddir)/src/hooks/dhcp/user_chk/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)
+
+USER_CHK_LIB = $(top_builddir)/src/hooks/dhcp/user_chk/libdhcp_user_chk.la
+
+if USE_STATIC_LINK
+AM_LDFLAGS = -static
+endif
+
+CLEANFILES = *.gcno *.gcda
+
+TESTS_ENVIRONMENT = \
+ $(LIBTOOL) --mode=execute $(VALGRIND_COMMAND)
+
+TESTS =
+if HAVE_GTEST
+TESTS += libdhcp_user_chk_unittests
+
+libdhcp_user_chk_unittests_SOURCES =
+libdhcp_user_chk_unittests_SOURCES += ../user.cc ../user.h
+libdhcp_user_chk_unittests_SOURCES += ../user_data_source.cc ../user_data_source.h
+libdhcp_user_chk_unittests_SOURCES += ../user_registry.cc ../user_registry.h
+libdhcp_user_chk_unittests_SOURCES += run_unittests.cc
+libdhcp_user_chk_unittests_SOURCES += userid_unittests.cc
+libdhcp_user_chk_unittests_SOURCES += user_unittests.cc
+libdhcp_user_chk_unittests_SOURCES += user_registry_unittests.cc
+
+libdhcp_user_chk_unittests_CPPFLAGS = $(AM_CPPFLAGS) $(GTEST_INCLUDES) $(LOG4CPLUS_INCLUDES)
+
+libdhcp_user_chk_unittests_LDFLAGS = $(AM_LDFLAGS) $(GTEST_LDFLAGS)
+
+libdhcp_user_chk_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_user_chk_unittests_CXXFLAGS += -Wno-unused-parameter
+endif
+
+libdhcp_user_chk_unittests_LDADD = $(top_builddir)/src/lib/log/libb10-log.la
+libdhcp_user_chk_unittests_LDADD += $(top_builddir)/src/lib/util/libb10-util.la
+libdhcp_user_chk_unittests_LDADD += $(top_builddir)/src/lib/dhcp/libb10-dhcp++.la
+libdhcp_user_chk_unittests_LDADD += $(top_builddir)/src/lib/exceptions/libb10-exceptions.la
+#libdhcp_user_chk_unittests_LDADD += $(top_builddir)/src/hooks/dhcp/user_chk/libdhcp_user_chk.la
+libdhcp_user_chk_unittests_LDADD += ${BOTAN_LIBS} ${BOTAN_RPATH}
+libdhcp_user_chk_unittests_LDADD += $(GTEST_LDADD)
+endif
+
+noinst_PROGRAMS = $(TESTS)
diff --git a/src/hooks/dhcp/user_chk/tests/run_unittests.cc b/src/hooks/dhcp/user_chk/tests/run_unittests.cc
new file mode 100644
index 0000000000..185f888273
--- /dev/null
+++ b/src/hooks/dhcp/user_chk/tests/run_unittests.cc
@@ -0,0 +1,27 @@
+// Copyright (C) 2013 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/hooks/dhcp/user_chk/tests/user_registry_unittests.cc b/src/hooks/dhcp/user_chk/tests/user_registry_unittests.cc
new file mode 100644
index 0000000000..d6d5114e51
--- /dev/null
+++ b/src/hooks/dhcp/user_chk/tests/user_registry_unittests.cc
@@ -0,0 +1,133 @@
+// Copyright (C) 2013 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/hwaddr.h>
+#include <exceptions/exceptions.h>
+#include <user_registry.h>
+
+#include <boost/function.hpp>
+#include <boost/bind.hpp>
+#include <boost/shared_ptr.hpp>
+#include <gtest/gtest.h>
+
+using namespace std;
+
+namespace {
+
+TEST(UserRegistry, constructor) {
+ UserRegistryPtr reg;
+ ASSERT_NO_THROW(reg.reset(new UserRegistry()));
+}
+
+TEST(UserRegistry, userBasics) {
+ UserRegistryPtr reg;
+ ASSERT_NO_THROW(reg.reset(new UserRegistry()));
+
+ UserIdPtr id, id2;
+ // Make user ids.
+ ASSERT_NO_THROW(id.reset(new UserId(UserId::HW_ADDRESS, "01010101")));
+ ASSERT_NO_THROW(id2.reset(new UserId(UserId::HW_ADDRESS, "02020202")));
+
+ UserPtr user, user2;
+ // Verify that a blank user cannot be added.
+ ASSERT_THROW(reg->addUser(user), isc::BadValue);
+
+ // Make new users.
+ ASSERT_NO_THROW(user.reset(new User(*id)));
+ ASSERT_NO_THROW(user2.reset(new User(*id)));
+
+ // Add first user.
+ ASSERT_NO_THROW(reg->addUser(user));
+
+ // Verify user added can be found.
+ UserPtr found_user;
+ ASSERT_NO_THROW(found_user = reg->findUser(*id));
+ EXPECT_TRUE(found_user);
+ EXPECT_EQ(*id, found_user->getUserId());
+
+ // Verify user not added cannot be found.
+ ASSERT_NO_THROW(found_user = reg->findUser(*id2));
+ EXPECT_FALSE(found_user);
+
+ // Verfiy user can no longer be found.
+ ASSERT_NO_THROW(reg->removeUser(*id));
+ ASSERT_NO_THROW(found_user = reg->findUser(*id));
+ EXPECT_FALSE(found_user);
+}
+
+TEST(UserRegistry, findByHWAddr) {
+ UserRegistryPtr reg;
+ ASSERT_NO_THROW(reg.reset(new UserRegistry()));
+
+ // Make a user.
+ UserPtr user;
+ ASSERT_NO_THROW(user.reset(new User(UserId::HW_ADDRESS, "01010101")));
+
+ // Verify user can be added.
+ ASSERT_NO_THROW(reg->addUser(user));
+
+ // Make a HWAddr instance using the same id value.
+ isc::dhcp::HWAddr hwaddr(user->getUserId().getId(),
+ isc::dhcp::HTYPE_ETHER);
+
+ // Verify user can be found by HWAddr.
+ UserPtr found_user;
+ ASSERT_NO_THROW(found_user = reg->findUser(hwaddr));
+ EXPECT_TRUE(found_user);
+ EXPECT_EQ(user->getUserId(), found_user->getUserId());
+}
+
+TEST(UserRegistry, findByDUID) {
+ UserRegistryPtr reg;
+ ASSERT_NO_THROW(reg.reset(new UserRegistry()));
+
+ // Make a user.
+ UserPtr user;
+ ASSERT_NO_THROW(user.reset(new User(UserId::DUID, "01010101")));
+
+ // Verify user can be added.
+ ASSERT_NO_THROW(reg->addUser(user));
+
+ // Make a HWAddr instance using the same id value.
+ isc::dhcp::DUID duid(user->getUserId().getId());
+
+ // Verify user can be found by HWAddr.
+ UserPtr found_user;
+ ASSERT_NO_THROW(found_user = reg->findUser(duid));
+ EXPECT_TRUE(found_user);
+ EXPECT_EQ(user->getUserId(), found_user->getUserId());
+}
+
+TEST(UserRegistry, findByClientId) {
+ UserRegistryPtr reg;
+ ASSERT_NO_THROW(reg.reset(new UserRegistry()));
+
+ // Make a user.
+ UserPtr user;
+ ASSERT_NO_THROW(user.reset(new User(UserId::CLIENT_ID, "01010101")));
+
+ // Verify user can be added.
+ ASSERT_NO_THROW(reg->addUser(user));
+
+ // Make a HWAddr instance using the same id value.
+ isc::dhcp::ClientId client_id(user->getUserId().getId());
+
+ // Verify user can be found by HWAddr.
+ UserPtr found_user;
+ ASSERT_NO_THROW(found_user = reg->findUser(client_id));
+ EXPECT_TRUE(found_user);
+ EXPECT_EQ(user->getUserId(), found_user->getUserId());
+}
+
+} // end of anonymous namespace
diff --git a/src/hooks/dhcp/user_chk/tests/user_unittests.cc b/src/hooks/dhcp/user_chk/tests/user_unittests.cc
new file mode 100644
index 0000000000..03cc072b2f
--- /dev/null
+++ b/src/hooks/dhcp/user_chk/tests/user_unittests.cc
@@ -0,0 +1,72 @@
+// Copyright (C) 2013 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 <exceptions/exceptions.h>
+#include <user.h>
+
+#include <boost/function.hpp>
+#include <boost/bind.hpp>
+#include <boost/shared_ptr.hpp>
+#include <gtest/gtest.h>
+
+using namespace std;
+
+namespace {
+
+TEST(UserTest, construction) {
+ std::string test_address("01FF02AC030B0709");
+
+ UserIdPtr id;
+ ASSERT_NO_THROW(id.reset(new UserId(UserId::HW_ADDRESS, test_address)));
+
+ UserPtr user;
+ // Verify construction from a UserId.
+ ASSERT_NO_THROW(user.reset(new User(*id)));
+
+ // Verify construction from a type and an address vector.
+ ASSERT_NO_THROW(user.reset(new User(UserId::HW_ADDRESS, id->getId())));
+ ASSERT_NO_THROW(user.reset(new User(UserId::DUID, id->getId())));
+ ASSERT_NO_THROW(user.reset(new User(UserId::CLIENT_ID, id->getId())));
+
+ // Verify construction from a type and an address string.
+ ASSERT_NO_THROW(user.reset(new User(UserId::HW_ADDRESS, test_address)));
+ ASSERT_NO_THROW(user.reset(new User(UserId::DUID, test_address)));
+ ASSERT_NO_THROW(user.reset(new User(UserId::CLIENT_ID, test_address)));
+}
+
+TEST(UserTest, properties) {
+ UserPtr user;
+ ASSERT_NO_THROW(user.reset(new User(UserId::DUID, "01020304050607")));
+
+ std::string value = "";
+ EXPECT_NO_THROW(user->setProperty("one","1"));
+ EXPECT_NO_THROW(value = user->getProperty("one"));
+ EXPECT_EQ(value, "1");
+
+ EXPECT_NO_THROW(user->setProperty("one","1.0"));
+ EXPECT_NO_THROW(value = user->getProperty("one"));
+ EXPECT_EQ(value, "1.0");
+
+ EXPECT_NO_THROW(user->delProperty("one"));
+ EXPECT_NO_THROW(value = user->getProperty("one"));
+ EXPECT_TRUE(value.empty());
+
+ EXPECT_THROW(user->setProperty("", "blah"), isc::BadValue);
+
+ EXPECT_NO_THROW(user->setProperty("one", ""));
+ EXPECT_NO_THROW(value = user->getProperty("one"));
+ EXPECT_TRUE(value.empty());
+}
+
+} // end of anonymous namespace
diff --git a/src/hooks/dhcp/user_chk/tests/userid_unittests.cc b/src/hooks/dhcp/user_chk/tests/userid_unittests.cc
new file mode 100644
index 0000000000..43c78891f0
--- /dev/null
+++ b/src/hooks/dhcp/user_chk/tests/userid_unittests.cc
@@ -0,0 +1,165 @@
+// Copyright (C) 2013 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 <exceptions/exceptions.h>
+#include <user.h>
+
+#include <boost/function.hpp>
+#include <boost/bind.hpp>
+#include <boost/shared_ptr.hpp>
+#include <gtest/gtest.h>
+
+using namespace std;
+
+namespace {
+
+TEST(UserIdTest, invalidConstructors) {
+ // Verify that constructor does not allow empty id vector.
+ std::vector<uint8_t> empty_bytes;
+ ASSERT_THROW(UserId(UserId::HW_ADDRESS, empty_bytes), isc::BadValue);
+ ASSERT_THROW(UserId(UserId::DUID, empty_bytes), isc::BadValue);
+ ASSERT_THROW(UserId(UserId::CLIENT_ID, empty_bytes), isc::BadValue);
+
+ // Verify that constructor does not allow empty id string.
+ ASSERT_THROW(UserId(UserId::HW_ADDRESS, ""), isc::BadValue);
+ ASSERT_THROW(UserId(UserId::DUID, ""), isc::BadValue);
+ ASSERT_THROW(UserId(UserId::CLIENT_ID, ""), isc::BadValue);
+}
+
+TEST(UserIdTest, hwAddress_type) {
+
+ EXPECT_EQ(std::string(UserId::HW_ADDRESS_STR),
+ UserId::lookupTypeStr(UserId::HW_ADDRESS));
+
+ EXPECT_EQ(UserId::HW_ADDRESS,
+ UserId::lookupType(UserId::HW_ADDRESS_STR));
+
+ uint8_t tmp[] = { 0x01, 0xFF, 0x02, 0xAC, 0x03, 0x0B, 0x07, 0x08 };
+ std::vector<uint8_t> bytes(tmp, tmp + (sizeof(tmp)/sizeof(uint8_t)));
+
+ UserIdPtr id;
+ ASSERT_NO_THROW(id.reset(new UserId(UserId::HW_ADDRESS, bytes)));
+ EXPECT_EQ(id->getType(), UserId::HW_ADDRESS);
+ EXPECT_EQ(bytes, id->getId());
+
+ // Verify a == b;
+ UserIdPtr id2;
+ ASSERT_NO_THROW(id2.reset(new UserId(UserId::HW_ADDRESS, id->toText())));
+ EXPECT_TRUE(*id == *id2);
+ EXPECT_FALSE(*id != *id2);
+ EXPECT_FALSE(*id < *id2);
+
+ // Verify a < b;
+ ASSERT_NO_THROW(id2.reset(new UserId(UserId::HW_ADDRESS,
+ "01FF02AC030B0709")));
+ EXPECT_FALSE(*id == *id2);
+ EXPECT_TRUE(*id != *id2);
+ EXPECT_TRUE(*id < *id2);
+
+ // Verify a > b;
+ ASSERT_NO_THROW(id2.reset(new UserId(UserId::HW_ADDRESS,
+ "01FF02AC030B0707")));
+ EXPECT_FALSE(*id == *id2);
+ EXPECT_TRUE(*id != *id2);
+ EXPECT_FALSE(*id < *id2);
+}
+
+TEST(UserIdTest, duid_type) {
+ EXPECT_EQ(std::string(UserId::DUID_STR),
+ UserId::lookupTypeStr(UserId::DUID));
+
+ EXPECT_EQ(UserId::DUID,
+ UserId::lookupType(UserId::DUID_STR));
+
+ uint8_t tmp[] = { 0x01, 0xFF, 0x02, 0xAC, 0x03, 0x0B, 0x07, 0x08 };
+ std::vector<uint8_t> bytes(tmp, tmp + (sizeof(tmp)/sizeof(uint8_t)));
+
+ UserIdPtr id;
+ ASSERT_NO_THROW(id.reset(new UserId(UserId::DUID, bytes)));
+ EXPECT_EQ(id->getType(), UserId::DUID);
+ EXPECT_EQ(bytes, id->getId());
+
+ // Verify a == b;
+ UserIdPtr id2;
+ ASSERT_NO_THROW(id2.reset(new UserId(UserId::DUID, id->toText())));
+ EXPECT_TRUE(*id == *id2);
+ EXPECT_FALSE(*id != *id2);
+ EXPECT_FALSE(*id < *id2);
+
+ // Verify a < b;
+ ASSERT_NO_THROW(id2.reset(new UserId(UserId::DUID, "01FF02AC030B0709")));
+ EXPECT_FALSE(*id == *id2);
+ EXPECT_TRUE(*id != *id2);
+ EXPECT_TRUE(*id < *id2);
+
+ // Verify a > b;
+ ASSERT_NO_THROW(id2.reset(new UserId(UserId::DUID, "01FF02AC030B0707")));
+ EXPECT_FALSE(*id == *id2);
+ EXPECT_TRUE(*id != *id2);
+ EXPECT_FALSE(*id < *id2);
+}
+
+TEST(UserIdTest, client_id_type) {
+ EXPECT_EQ(std::string(UserId::CLIENT_ID_STR),
+ UserId::lookupTypeStr(UserId::CLIENT_ID));
+
+ EXPECT_EQ(UserId::CLIENT_ID,
+ UserId::lookupType(UserId::CLIENT_ID_STR));
+
+ uint8_t tmp[] = { 0x01, 0xFF, 0x02, 0xAC, 0x03, 0x0B, 0x07, 0x08 };
+ std::vector<uint8_t> bytes(tmp, tmp + (sizeof(tmp)/sizeof(uint8_t)));
+
+ UserIdPtr id;
+ ASSERT_NO_THROW(id.reset(new UserId(UserId::CLIENT_ID, bytes)));
+ EXPECT_EQ(id->getType(), UserId::CLIENT_ID);
+ EXPECT_EQ(bytes, id->getId());
+
+ // Verify a == b;
+ UserIdPtr id2;
+ ASSERT_NO_THROW(id2.reset(new UserId(UserId::CLIENT_ID, id->toText())));
+ EXPECT_TRUE(*id == *id2);
+ EXPECT_FALSE(*id != *id2);
+ EXPECT_FALSE(*id < *id2);
+
+ // Verify a < b;
+ ASSERT_NO_THROW(id2.reset(new UserId(UserId::CLIENT_ID,
+ "01FF02AC030B0709")));
+ EXPECT_FALSE(*id == *id2);
+ EXPECT_TRUE(*id != *id2);
+ EXPECT_TRUE(*id < *id2);
+
+ // Verify a > b;
+ ASSERT_NO_THROW(id2.reset(new UserId(UserId::CLIENT_ID,
+ "01FF02AC030B0707")));
+ EXPECT_FALSE(*id == *id2);
+ EXPECT_TRUE(*id != *id2);
+ EXPECT_FALSE(*id < *id2);
+}
+
+TEST(UserIdTest, type_compare) {
+ UserIdPtr hw, duid, client;
+ ASSERT_NO_THROW(hw.reset(new UserId(UserId::HW_ADDRESS,
+ "01FF02AC030B0709")));
+ ASSERT_NO_THROW(duid.reset(new UserId(UserId::DUID,
+ "01FF02AC030B0709")));
+ ASSERT_NO_THROW(client.reset(new UserId(UserId::CLIENT_ID,
+ "01FF02AC030B0709")));
+
+ // Verify that UserIdType influences logical comparators.
+ EXPECT_NE(*hw, *duid);
+ EXPECT_NE(*hw , *client);
+ EXPECT_NE(*duid, *client);
+}
+
+} // end of anonymous namespace
diff --git a/src/hooks/dhcp/user_chk/user.cc b/src/hooks/dhcp/user_chk/user.cc
new file mode 100644
index 0000000000..3955cf6288
--- /dev/null
+++ b/src/hooks/dhcp/user_chk/user.cc
@@ -0,0 +1,226 @@
+// Copyright (C) 2013 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/hwaddr.h>
+#include <dhcp/duid.h>
+#include <exceptions/exceptions.h>
+
+#include <user.h>
+
+#include <iomanip>
+#include <sstream>
+
+//********************************* UserId ******************************
+const char* UserId::HW_ADDRESS_STR = "HW_ADDR";
+const char* UserId::DUID_STR = "DUID";
+const char* UserId::CLIENT_ID_STR = "CLIENT_ID";
+
+UserId::UserId(UserIdType id_type, const std::vector<uint8_t>& id)
+ : id_type_(id_type), id_(id) {
+ if (id.size() == 0) {
+ isc_throw(isc::BadValue, "UserId id may not be blank");
+ }
+}
+
+UserId::UserId(UserIdType id_type, const std::string & id_str) :
+ id_type_(id_type) {
+
+ if (id_str.empty()) {
+ isc_throw(isc::BadValue, "UserId id string may not be blank");
+ }
+
+ // logic to convert id_str etc...
+ // input str is expected to be 2-digits per bytes, no delims
+ std::vector<uint8_t> addr_bytes;
+ decodeHex(id_str, addr_bytes);
+
+ // Attempt to instantiate the appropriate id class to leverage validation.
+ switch (id_type) {
+ case HW_ADDRESS: {
+ isc::dhcp::HWAddr hwaddr(addr_bytes, isc::dhcp::HTYPE_ETHER);
+ break;
+ }
+ case CLIENT_ID: {
+ isc::dhcp::ClientId client_id(addr_bytes);
+ break;
+ }
+ case DUID: {
+ isc::dhcp::DUID duid(addr_bytes);
+ break;
+ }
+ default:
+ isc_throw (isc::BadValue, "Invalid id_type: " << id_type);
+ break;
+ }
+
+ // It's a valid id.
+ id_ = addr_bytes;
+}
+
+UserId::~UserId() {
+}
+
+const std::vector<uint8_t>&
+UserId::getId() const {
+ return (id_);
+}
+
+UserId::UserIdType
+UserId::getType() const {
+ return (id_type_);
+}
+
+std::string
+UserId::toText(char delim_char) const {
+ std::stringstream tmp;
+ tmp << std::hex;
+ bool delim = false;
+ for (std::vector<uint8_t>::const_iterator it = id_.begin();
+ it != id_.end(); ++it) {
+ if (delim_char && delim) {
+ tmp << delim_char;
+ }
+
+ tmp << std::setw(2) << std::setfill('0')
+ << static_cast<unsigned int>(*it);
+ delim = true;
+ }
+
+ return (tmp.str());
+}
+
+bool
+UserId::operator ==(const UserId & other) const {
+ return ((this->id_type_ == other.id_type_) && (this->id_ == other.id_));
+}
+
+bool
+UserId::operator !=(const UserId & other) const {
+ return (!(*this == other));
+}
+
+bool
+UserId::operator <(const UserId & other) const {
+ return ((this->id_type_ == other.id_type_) && (this->id_ < other.id_));
+}
+
+void
+UserId::decodeHex(const std::string& input, std::vector<uint8_t>& bytes)
+const {
+ int len = input.size();
+ if ((len % 2) != 0) {
+ isc_throw (isc::BadValue,
+ "input string must be event number of digits: "
+ << input);
+ }
+
+ for (int i = 0; i < len / 2; i++) {
+ unsigned int tmp;
+ if (sscanf (&input[i*2], "%02x", &tmp) != 1) {
+ isc_throw (isc::BadValue,
+ "input string contains invalid characters: "
+ << input);
+ }
+
+ bytes.push_back(static_cast<uint8_t>(tmp));
+ }
+}
+
+std::string
+UserId::lookupTypeStr(UserIdType type) {
+ const char* tmp = NULL;
+ switch (type) {
+ case HW_ADDRESS:
+ tmp = HW_ADDRESS_STR;
+ break;
+ case DUID:
+ tmp = DUID_STR;
+ break;
+ case CLIENT_ID:
+ tmp = CLIENT_ID_STR;
+ break;
+ default:
+ isc_throw(isc::BadValue, "Invalid UserIdType:" << type);
+ break;
+ }
+
+ return (std::string(tmp));
+}
+
+UserId::UserIdType
+UserId::lookupType(const std::string& type_str) {
+ if (type_str == HW_ADDRESS_STR) {
+ return (HW_ADDRESS);
+ } else if (type_str == DUID_STR) {
+ return (DUID);
+ } else if (type_str == CLIENT_ID_STR) {
+ return (CLIENT_ID);
+ }
+
+ isc_throw(isc::BadValue, "Invalid UserIdType string:" << type_str);
+}
+
+std::ostream&
+operator<<(std::ostream& os, const UserId& user_id) {
+ std::string tmp = UserId::lookupTypeStr(user_id.getType());
+ os << tmp << "=" << user_id.toText();
+ return (os);
+}
+
+//********************************* User ******************************
+
+User::User(const UserId& user_id) : user_id_(user_id) {
+}
+
+User::User(UserId::UserIdType id_type, const std::vector<uint8_t>& id)
+ : user_id_(id_type, id) {
+}
+
+User::User(UserId::UserIdType id_type, const std::string& id_str)
+ : user_id_(id_type, id_str) {
+}
+
+User::~User() {
+}
+
+void User::setProperty(const std::string& name, const std::string& value) {
+ if (name.empty()) {
+ isc_throw (isc::BadValue, "User property name cannot be blank");
+ }
+
+ properties_[name]=value;
+}
+
+std::string
+User::getProperty(const std::string& name) const {
+ PropertyMap::const_iterator it = properties_.find(name);
+ if (it != properties_.end()) {
+ return ((*it).second);
+ }
+
+ return ("");
+}
+
+void
+User::delProperty(const std::string & name) {
+ PropertyMap::iterator it = properties_.find(name);
+ if (it != properties_.end()) {
+ properties_.erase(it);
+ }
+}
+
+const UserId&
+User::getUserId() const {
+ return (user_id_);
+}
diff --git a/src/hooks/dhcp/user_chk/user.h b/src/hooks/dhcp/user_chk/user.h
new file mode 100644
index 0000000000..beada576b1
--- /dev/null
+++ b/src/hooks/dhcp/user_chk/user.h
@@ -0,0 +1,109 @@
+// Copyright (C) 2013 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 _USER_H
+#define _USER_H
+
+#include <boost/shared_ptr.hpp>
+
+#include <vector>
+#include <map>
+
+class UserId {
+public:
+ enum UserIdType {
+ HW_ADDRESS,
+ DUID,
+ CLIENT_ID
+ };
+
+ static const char* HW_ADDRESS_STR;
+ static const char* DUID_STR;
+ static const char* CLIENT_ID_STR;
+
+ UserId(UserIdType id_type, const std::vector<uint8_t>& id);
+
+ UserId(UserIdType id_type, const std::string& id_str);
+
+ ~UserId();
+
+ /// @brief Returns a const reference to the actual id value
+ const std::vector<uint8_t>& getId() const;
+
+ /// @brief Returns the UserIdType
+ UserIdType getType() const;
+
+ /// @brief Returns textual representation of a id (e.g. 00:01:02:03:ff)
+ std::string toText(char delim_char=0x0) const;
+
+ /// @brief Compares two UserIds for equality
+ bool operator ==(const UserId & other) const;
+
+ /// @brief Compares two UserIds for inequality
+ bool operator !=(const UserId & other) const;
+
+ /// @brief Performs less than comparision of two UserIds
+ bool operator <(const UserId & other) const;
+
+ static std::string lookupTypeStr(UserIdType type);
+
+ static UserIdType lookupType(const std::string& type_str);
+
+private:
+ void decodeHex(const std::string& input, std::vector<uint8_t>& bytes) const;
+
+ /// @brief The type of id value
+ UserIdType id_type_;
+
+ /// @brief The id value
+ std::vector<uint8_t> id_;
+
+};
+
+std::ostream&
+operator<<(std::ostream& os, const UserId& user_id);
+
+typedef boost::shared_ptr<UserId> UserIdPtr;
+
+typedef std::map<std::string, std::string> PropertyMap;
+
+class User {
+public:
+
+ User(const UserId & user_id);
+
+ User(UserId::UserIdType id_type, const std::vector<uint8_t>& id);
+
+ User(UserId::UserIdType id_type, const std::string& id_str);
+
+ ~User();
+
+ void setProperty(const std::string& name, const std::string& value);
+
+ std::string getProperty(const std::string& name) const;
+
+ void delProperty(const std::string& name);
+
+ const UserId& getUserId() const;
+
+private:
+
+ UserId user_id_;
+
+ PropertyMap properties_;
+};
+
+typedef boost::shared_ptr<User> UserPtr;
+
+#endif
diff --git a/src/hooks/dhcp/user_chk/user_data_source.cc b/src/hooks/dhcp/user_chk/user_data_source.cc
new file mode 100644
index 0000000000..9a80b2f6b5
--- /dev/null
+++ b/src/hooks/dhcp/user_chk/user_data_source.cc
@@ -0,0 +1,49 @@
+// Copyright (C) 2013 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 <user_data_source.h>
+
+UserDataSource::UserDataSource() {
+}
+
+UserDataSource::~UserDataSource() {
+ if (open_flag_) {
+ close();
+ }
+}
+
+void
+UserDataSource::open() {
+ open_flag_ = false;
+}
+
+UserPtr
+UserDataSource::readNextUser() {
+ return (UserPtr());
+}
+
+void
+UserDataSource::close() {
+ open_flag_ = false;
+}
+
+bool
+UserDataSource::isOpen() const {
+ return open_flag_;
+}
+
+void
+UserDataSource::setOpenFlag(bool value) {
+ open_flag_ = value;
+}
diff --git a/src/hooks/dhcp/user_chk/user_data_source.h b/src/hooks/dhcp/user_chk/user_data_source.h
new file mode 100644
index 0000000000..33a64ed297
--- /dev/null
+++ b/src/hooks/dhcp/user_chk/user_data_source.h
@@ -0,0 +1,42 @@
+// Copyright (C) 2013 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 _USER_DATA_SOURCE_H
+#define _USER_DATA_SOURCE_H
+
+#include <user.h>
+
+class UserDataSource {
+
+public:
+ UserDataSource();
+
+ ~UserDataSource();
+
+ void open();
+
+ UserPtr readNextUser();
+
+ void close();
+
+ bool isOpen() const;
+
+ void setOpenFlag(bool value);
+
+private:
+ bool open_flag_;
+};
+
+typedef boost::shared_ptr<UserDataSource> UserDataSourcePtr;
+
+#endif
diff --git a/src/hooks/dhcp/user_chk/user_registry.cc b/src/hooks/dhcp/user_chk/user_registry.cc
new file mode 100644
index 0000000000..e816ddbc3c
--- /dev/null
+++ b/src/hooks/dhcp/user_chk/user_registry.cc
@@ -0,0 +1,89 @@
+// Copyright (C) 2013 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 <user_registry.h>
+#include <user.h>
+
+UserRegistry::UserRegistry() {
+}
+
+UserRegistry::~UserRegistry(){
+}
+
+void
+UserRegistry::addUser(UserPtr& user) {
+ if (!user) {
+ isc_throw (isc::BadValue, "UserRegistry cannot add blank user");
+ }
+
+ if (findUser(user->getUserId())) {
+ isc_throw (isc::BadValue, "Duplicate User!");
+ }
+
+ users_[user->getUserId()] = user;
+}
+
+const UserPtr&
+UserRegistry::findUser(const UserId& id) const {
+ static UserPtr empty;
+ UserMap::const_iterator it = users_.find(id);
+ if (it != users_.end()) {
+ return ((*it).second);
+ }
+
+ return empty;
+}
+
+void
+UserRegistry::removeUser(const UserId& id) {
+ static UserPtr empty;
+ UserMap::iterator it = users_.find(id);
+ if (it != users_.end()) {
+ users_.erase(it);
+ }
+}
+
+const UserPtr&
+UserRegistry::findUser(const isc::dhcp::HWAddr& hwaddr) const {
+ UserId id(UserId::HW_ADDRESS, hwaddr.hwaddr_);
+ return (findUser(id));
+}
+
+const UserPtr&
+UserRegistry::findUser(const isc::dhcp::ClientId& client_id) const {
+ UserId id(UserId::CLIENT_ID, client_id.getClientId());
+ return (findUser(id));
+}
+
+const UserPtr&
+UserRegistry::findUser(const isc::dhcp::DUID& duid) const {
+ UserId id(UserId::DUID, duid.getDuid());
+ return (findUser(id));
+}
+
+void UserRegistry::refresh() {
+}
+
+void UserRegistry::clearall() {
+ users_.clear();
+}
+
+void UserRegistry::setSource(UserDataSourcePtr& source) {
+ source_ = source;
+}
+
+const UserDataSourcePtr& UserRegistry::getSource() {
+ return (source_);
+}
+
diff --git a/src/hooks/dhcp/user_chk/user_registry.h b/src/hooks/dhcp/user_chk/user_registry.h
new file mode 100644
index 0000000000..1e089d06af
--- /dev/null
+++ b/src/hooks/dhcp/user_chk/user_registry.h
@@ -0,0 +1,62 @@
+// Copyright (C) 2013 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 _USER_REGISTRY_H
+#define _USER_REGISTRY_H
+
+#include <dhcp/hwaddr.h>
+#include <dhcp/duid.h>
+#include <user.h>
+#include <user_data_source.h>
+
+#include <string>
+
+using namespace std;
+
+typedef std::map<UserId,UserPtr> UserMap;
+
+class UserRegistry {
+public:
+ UserRegistry();
+
+ ~UserRegistry();
+
+ void addUser(UserPtr& user);
+
+ const UserPtr& findUser(const UserId& id) const;
+
+ void removeUser(const UserId& id);
+
+ const UserPtr& findUser(const isc::dhcp::HWAddr& hwaddr) const;
+
+ const UserPtr& findUser(const isc::dhcp::ClientId& client_id) const;
+
+ const UserPtr& findUser(const isc::dhcp::DUID& duid) const;
+
+ void refresh();
+
+ void clearall();
+
+ const UserDataSourcePtr& getSource();
+
+ void setSource(UserDataSourcePtr& source);
+
+private:
+ UserMap users_;
+
+ UserDataSourcePtr source_;
+};
+
+typedef boost::shared_ptr<UserRegistry> UserRegistryPtr;
+
+#endif
diff --git a/src/hooks/dhcp/user_chk/version.cc b/src/hooks/dhcp/user_chk/version.cc
new file mode 100644
index 0000000000..e82bba1930
--- /dev/null
+++ b/src/hooks/dhcp/user_chk/version.cc
@@ -0,0 +1,24 @@
+// Copyright (C) 2013 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.
+// version.cc
+
+#include <hooks/hooks.h>
+
+extern "C" {
+
+int version() {
+ return (BIND10_HOOKS_VERSION);
+}
+
+}