From: Tomek Mrugalski Date: Fri, 14 Jul 2017 08:32:50 +0000 (+0200) Subject: [5272] lease_cmds in progress X-Git-Tag: trac5124a_base~20^2~15 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=a2924fcc11ae8b7a7b2fb5071a65d02252485220;p=thirdparty%2Fkea.git [5272] lease_cmds in progress --- diff --git a/configure.ac b/configure.ac index 6989c00bb7..bba2cc942a 100644 --- a/configure.ac +++ b/configure.ac @@ -1630,6 +1630,8 @@ AC_CONFIG_FILES([Makefile src/bin/shell/tests/shell_unittest.py src/hooks/Makefile src/hooks/dhcp/Makefile + src/hooks/dhcp/lease_cmds/Makefile + src/hooks/dhcp/lease_cmds/tests/Makefile src/hooks/dhcp/user_chk/Makefile src/hooks/dhcp/user_chk/tests/Makefile src/hooks/dhcp/user_chk/tests/test_data_files_config.h diff --git a/src/hooks/dhcp/Makefile.am b/src/hooks/dhcp/Makefile.am index 6785617c01..ebf9cfe743 100644 --- a/src/hooks/dhcp/Makefile.am +++ b/src/hooks/dhcp/Makefile.am @@ -1 +1 @@ -SUBDIRS = user_chk +SUBDIRS = user_chk lease_cmds diff --git a/src/hooks/dhcp/lease_cmds/Makefile.am b/src/hooks/dhcp/lease_cmds/Makefile.am new file mode 100644 index 0000000000..3fd9e71b4f --- /dev/null +++ b/src/hooks/dhcp/lease_cmds/Makefile.am @@ -0,0 +1,62 @@ +SUBDIRS = . tests + +AM_CPPFLAGS = -I$(top_builddir)/src/lib -I$(top_srcdir)/src/lib +AM_CPPFLAGS += $(BOOST_INCLUDES) +AM_CXXFLAGS = $(KEA_CXXFLAGS) + +# Define rule to build logging source files from message file +lease_cmds_messages.h lease_cmds_messages.cc: s-messages +s-messages: lease_cmds_messages.mes + $(top_builddir)/src/lib/log/compiler/kea-msg-compiler $(top_srcdir)/src/hooks/dhcp/lease_cmds/lease_cmds_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 = lease_cmds_messages.h lease_cmds_messages.cc + +# Ensure that the message file is included in the distribution +EXTRA_DIST = lease_cmds_messages.mes + +# Get rid of generated message files on a clean +CLEANFILES = *.gcno *.gcda lease_cmds_messages.h lease_cmds_messages.cc s-messages + +# convenience archive + +noinst_LTLIBRARIES = liblease_cmds.la + +liblease_cmds_la_SOURCES = lease_cmds.cc lease_cmds.h +liblease_cmds_la_SOURCES += lease_parser.h lease_parser.cc +liblease_cmds_la_SOURCES += lease_cmds_log.cc lease_cmds_log.h +liblease_cmds_la_SOURCES += load_unload.cc +liblease_cmds_la_SOURCES += version.cc + +nodist_liblease_cmds_la_SOURCES = lease_cmds_messages.cc lease_cmds_messages.h + +liblease_cmds_la_CXXFLAGS = $(AM_CXXFLAGS) +liblease_cmds_la_CPPFLAGS = $(AM_CPPFLAGS) + +# install the shared object into $(libdir)/hooks +lib_hooksdir = $(libdir)/hooks +lib_hooks_LTLIBRARIES = libdhcp_lease_cmds.la + +libdhcp_lease_cmds_la_SOURCES = +libdhcp_lease_cmds_la_LDFLAGS = $(AM_LDFLAGS) +libdhcp_lease_cmds_la_LDFLAGS += -avoid-version -export-dynamic -module +libdhcp_lease_cmds_la_LIBADD = liblease_cmds.la +libdhcp_lease_cmds_la_LIBADD += $(top_builddir)/src/lib/cc/libkea-cc.la +libdhcp_lease_cmds_la_LIBADD += $(top_builddir)/src/lib/config/libkea-cfgclient.la +libdhcp_lease_cmds_la_LIBADD += $(top_builddir)/src/lib/dhcpsrv/libkea-dhcpsrv.la +libdhcp_lease_cmds_la_LIBADD += $(top_builddir)/src/lib/hooks/libkea-hooks.la +libdhcp_lease_cmds_la_LIBADD += $(top_builddir)/src/lib/asiolink/libkea-asiolink.la +libdhcp_lease_cmds_la_LIBADD += $(top_builddir)/src/lib/dhcp/libkea-dhcp++.la +libdhcp_lease_cmds_la_LIBADD += $(top_builddir)/src/lib/eval/libkea-eval.la +libdhcp_lease_cmds_la_LIBADD += $(top_builddir)/src/lib/dhcp_ddns/libkea-dhcp_ddns.la +libdhcp_lease_cmds_la_LIBADD += $(top_builddir)/src/lib/stats/libkea-stats.la +libdhcp_lease_cmds_la_LIBADD += $(top_builddir)/src/lib/dns/libkea-dns++.la +libdhcp_lease_cmds_la_LIBADD += $(top_builddir)/src/lib/cryptolink/libkea-cryptolink.la +libdhcp_lease_cmds_la_LIBADD += $(top_builddir)/src/lib/log/libkea-log.la +libdhcp_lease_cmds_la_LIBADD += $(top_builddir)/src/lib/util/threads/libkea-threads.la +libdhcp_lease_cmds_la_LIBADD += $(top_builddir)/src/lib/util/libkea-util.la +libdhcp_lease_cmds_la_LIBADD += $(top_builddir)/src/lib/exceptions/libkea-exceptions.la + +EXTRA_DIST += lease_cmds.dox diff --git a/src/hooks/dhcp/lease_cmds/lease_cmds.cc b/src/hooks/dhcp/lease_cmds/lease_cmds.cc new file mode 100644 index 0000000000..c3f507937d --- /dev/null +++ b/src/hooks/dhcp/lease_cmds/lease_cmds.cc @@ -0,0 +1,528 @@ +// Copyright (C) 2017 Internet Systems Consortium, Inc. ("ISC") +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace isc::dhcp; +using namespace isc::data; +using namespace isc::config; +using namespace isc::asiolink; +using namespace std; + +namespace isc { +namespace lease_cmds { + +/// @brief Wrapper class around reservation command handlers. +class LeaseCmdsImpl { +public: + LeaseCmdsImpl(); + + ~LeaseCmdsImpl(); + +/// @brief Parameters specified for reservation-get and reservation-del +/// +/// As both call types (get and delete) need specify which reservation to +/// act on, they have the same set of parameters. In particular, those +/// two call types support the following sets of parameters: +/// - subnet-id, address +/// - subnet-id, identifier type, identifier value +/// +/// This class stores those parameters and is used to pass them around. +class Parameters { +public: + + /// @brief specifies type of query (by IP addr, by hwaddr, by DUID) + typedef enum { + TYPE_ADDR, ///< query by IP address (either v4 or v6) + TYPE_HWADDR, ///< query by hardware address (v4 only) + TYPE_DUID ///< query by DUID (v6 only) + } Type; + + /// @brief Specifies subnet-id (always used) + SubnetID subnet_id; + + /// @brief Specifies IPv4 or IPv6 address (used when query_by_addr is true) + IOAddress addr; + + /// @brief Specifies identifier type (usually FLEX_ID, used when + /// query_by_addr is false) + HWAddrPtr hwaddr; + + /// @brief Specifies identifier value (used when query_by_addr is false) + isc::dhcp::DuidPtr duid; + + /// @brief specifies parameter types (true = query by address, false = + /// query by indetifier-type,identifier) + Type query_type; + + /// @brief Default contstructor. + Parameters() + :addr("::"), query_type(TYPE_ADDR) { + } +}; + +private: + + /// @brief Registers commands: + /// + /// Registers: + /// - lease4-add + /// - lease6-add + /// - lease4-get + /// - lease6-get + /// - lease4-del + /// - lease6-del + /// - lease4-update + /// - lease6-update + /// - lease4-del-all + /// - lease6-del-all + + /// @throw Unexpected if CommandMgr is not available (should not happen) + void registerCommands(); + + /// @brief Dergisters commands: + /// + /// Deregisters: + /// - lease4-add + /// - lease6-add + /// - lease4-get + /// - lease6-get + /// - lease4-del + /// - lease6-del + /// - lease4-update + /// - lease6-update + /// - lease4-del-all + /// - lease6-del-all + /// + /// @throw Unexpected if CommandMgr is not available (should not happen) + void deregisterCommands(); + + /// @brief reservation-add command handler + /// + /// This command attempts to add a lease. + /// + /// An example full command looks as follows. Note that the args + /// parameter is expected to contain the "arguments" portion of it. + /// This function covers v4 lease only. + /// + /// Example command + /// { + /// "command": "lease4-add", + /// "parameters": { + /// "address": "192.0.2.1", + /// "hwaddr": "00:01:02:03:04:05", + /// "client-id": "this-is-a-client", + /// "valid-lft": 3600, + /// "expire": 1499282530, + /// "subnet-id": 1, + /// "fdqn_fwd": true, + /// "fqdn_rev": true, + /// "hostname": "myhost.example.org", + /// "state": 0 + /// } + /// } + /// + /// @param command should be 'reservation-add' (but it's ignored) + /// @param args must contain host reservation definition. + /// @return result of the operation + static ConstElementPtr + leaseAddHandler(const string& command, ConstElementPtr args); + + /// @brief reservation-get command handler + /// + /// This command attempts to retrieve a host that match selected criteria. + /// Two types of parameters are supported: (subnet-id, address) or + /// (subnet-id, identifier-type, identifier). + /// + /// Example command for query by (subnet-id, address): + /// { + /// "command": "reservation-get", + /// "arguments": { + /// "subnet-id": 1, + /// "ip-address": "192.0.2.202" + /// } + /// } + /// + /// Example command for query by (subnet-id, identifier-type, identifier) + /// { + /// "command": "reservation-get", + /// "arguments": { + /// "subnet-id": 1, + /// "identifier-type": "hw-address", + /// "identifier": "00:01:02:03:04:05" + /// } + /// }"; + /// @param command should be 'reservation-get' (but it's ignored) + /// @param args must contain host reservation definition. + /// @return result of the operation (host will be included as parameters, if found) + static ConstElementPtr + leaseGetHandler(const string& command, ConstElementPtr args); + + /// @brief reservation-del command handler + /// + /// This command attempts to delete a host that match selected criteria. + /// Two types of parameters are supported: (subnet-id, address) or + /// (subnet-id, identifier-type, identifier). + /// + /// Note: for this operation to work, hosts-database must be specified + /// in your configuration file (or from code point of view, alternate_source_ + /// must be set in HostMgr). + /// + /// Example command for query by (subnet-id, address): + /// { + /// "command": "reservation-get", + /// "arguments": { + /// "subnet-id": 1, + /// "ip-address": "192.0.2.202" + /// } + /// } + /// + /// Example command for query by (subnet-id, identifier-type, identifier) + /// { + /// "command": "reservation-get", + /// "arguments": { + /// "subnet-id": 1, + /// "identifier-type": "hw-address", + /// "identifier": "00:01:02:03:04:05" + /// } + /// }"; + /// @param command should be 'reservation-add' (but it's ignored) + /// @param args must contain host reservation definition. + /// @return result of the operation (host will be included as parameters, if found) + static ConstElementPtr + leaseDelHandler(const string& command, ConstElementPtr args); + + static ConstElementPtr + leaseUpdateHandler(const string& command, ConstElementPtr args); + + static ConstElementPtr + leaseWipeHandler(const string& command, ConstElementPtr args); + + /// @brief Extracts parameters required for reservation-get and reservation-del + /// + /// See @ref Parameters class for detailed description of what is expected + /// in the args structure. + /// + /// @param args - arguments passed to command + /// @return parsed parameters + /// @throw BadValue if input arguments don't make sense. + static Parameters getParameters(const ConstElementPtr& args); + + /// @brief Covenience pointer used to access database storage + static HostDataSourcePtr db_storage_; + + /// @brief Protocol family (IPv4 or IPv6) + static uint16_t family_; +}; + +LeaseCmdsImpl::LeaseCmdsImpl() { + family_ = CfgMgr::instance().getFamily(); + + registerCommands(); +} + +LeaseCmdsImpl::~LeaseCmdsImpl() { + deregisterCommands(); +} + +void LeaseCmdsImpl::registerCommands() { + /// @todo: Use registration mechanism once #5321 discussion is done + CommandMgr::instance().registerCommand("lease4-add", + boost::bind(&LeaseCmdsImpl::leaseAddHandler, _1, _2)); + CommandMgr::instance().registerCommand("lease6-add", + boost::bind(&LeaseCmdsImpl::leaseAddHandler, _1, _2)); + + CommandMgr::instance().registerCommand("lease4-get", + boost::bind(&LeaseCmdsImpl::leaseGetHandler, _1, _2)); + CommandMgr::instance().registerCommand("lease6-get", + boost::bind(&LeaseCmdsImpl::leaseGetHandler, _1, _2)); + + CommandMgr::instance().registerCommand("lease4-del", + boost::bind(&LeaseCmdsImpl::leaseDelHandler, _1, _2)); + CommandMgr::instance().registerCommand("lease6-del", + boost::bind(&LeaseCmdsImpl::leaseDelHandler, _1, _2)); + + CommandMgr::instance().registerCommand("lease4-update", + boost::bind(&LeaseCmdsImpl::leaseUpdateHandler, _1, _2)); + CommandMgr::instance().registerCommand("lease6-update", + boost::bind(&LeaseCmdsImpl::leaseUpdateHandler, _1, _2)); + + CommandMgr::instance().registerCommand("lease4-del-all", + boost::bind(&LeaseCmdsImpl::leaseWipeHandler, _1, _2)); + CommandMgr::instance().registerCommand("lease6-del-all", + boost::bind(&LeaseCmdsImpl::leaseWipeHandler, _1, _2)); +} + +void LeaseCmdsImpl::deregisterCommands() { + /// @todo: Use deregistration mechanism once #5321 discussion is done + CommandMgr::instance().deregisterCommand("lease4-add"); + CommandMgr::instance().deregisterCommand("lease6-add"); + + CommandMgr::instance().deregisterCommand("lease4-get"); + CommandMgr::instance().deregisterCommand("lease6-get"); + + CommandMgr::instance().deregisterCommand("lease4-del"); + CommandMgr::instance().deregisterCommand("lease6-del"); + + CommandMgr::instance().deregisterCommand("lease4-update"); + CommandMgr::instance().deregisterCommand("lease6-update"); + + CommandMgr::instance().deregisterCommand("lease4-del-all"); + CommandMgr::instance().deregisterCommand("lease6-del-all"); +} + +ConstElementPtr +LeaseCmdsImpl::leaseAddHandler(const std::string& name, + ConstElementPtr params) { + bool v4 = (name == "lease4-add"); + + string txt = "(missing parameters)"; + if (params) { + txt = params->str(); + } + + try { + if (!params) { + isc_throw(isc::BadValue, "no parameters specified for the command"); + } + + ConstElementPtr lease_data = params->get("lease"); + if (!lease_data) { + isc_throw(isc::BadValue, "'lease' parameters must be specified"); + } + + Lease4Ptr lease4; + Lease6Ptr lease6; + if (v4) { + LeaseDataParser4 parser; + lease4 = parser.parse(lease_data); + + checkLeaseIntegrity(lease4); + + if (lease4) { + LeaseMgrFactory::instance().add(lease4); + } + + } else { + LeaseDataParser6 parser; + lease6 = parser.parse(lease_data); + + checkLeaseIntegrity(lease6); + + if (lease6) { + LeaseMgrFactory::instance().add(lease6); + } + } + + + } catch (const std::exception& ex) { + LOG_ERROR(lease_cmds_logger, LEASE_CMDS_RESERV_ADD_FAILED) + .arg(txt) + .arg(ex.what()); + return (createAnswer(CONTROL_RESULT_ERROR, ex.what())); + } + LOG_INFO(lease_cmds_logger, v4?LEASE_CMDS_ADD4 : LEASE_CMDS_ADD6).arg(txt); + return (createAnswer(CONTROL_RESULT_SUCCESS, "Lease added.")); +} + +LeaseCmdsImpl::Parameters +LeaseCmdsImpl::getParameters(const ConstElementPtr& params) { + Parameters x; + + if (!params || params->getType() != Element::map) { + isc_throw(BadValue, "Parameters missing or are not a map."); + } + + // We support 2 sets of parameters for lease-get/lease-del: + // lease-get(subnet-id, address) + // lease-get(subnet-id, interifier-type, identifier) + + ConstElementPtr tmp = params->get("subnet-id"); + if (!tmp) { + isc_throw(BadValue, "Mandatory 'subnet-id' parameter missing."); + } + if (tmp->getType() != Element::integer) { + isc_throw(BadValue, "'subnet-id' parameter is not integer."); + } + x.subnet_id = tmp->intValue(); + + tmp = params->get("ip-address"); + ConstLeasePtr host; + if (tmp) { + if (tmp->getType() != Element::string) { + isc_throw(BadValue, "'ip-address' is not a string."); + } + + x.addr = IOAddress(tmp->stringValue()); + x.query_by_addr = true; + return (x); + } + + // No address specified. Ok, so it must be identifier based query. + // "identifier-type": "duid", + // "identifier": "aa:bb:cc:dd:ee:..." + + ConstElementPtr type = params->get("identifier-type"); + ConstElementPtr ident = params->get("identifier"); + if (!type || type->getType() != Element::string) { + isc_throw(BadValue, "No 'ip-address' provided" + " and 'identifier-type' is either missing or not a string."); + } + if (!ident || ident->getType() != Element::string) { + isc_throw(BadValue, "No 'ip-address' provided" + " and 'identifier' is either missing or not a string."); + } + + // Got the parameters. Let's see if their values make sense. + + // Try to parse the identifier value first. + try { + x.ident = util::str::quotedStringToBinary(ident->stringValue()); + if (x.ident.empty()) { + util::str::decodeFormattedHexString(ident->stringValue(), + x.ident); + } + } catch (...) { + // The string doesn't match any known pattern, so we have to + // report an error at this point. + isc_throw(BadValue, "Unable to parse 'identifier' value."); + } + + if (x.ident.empty()) { + isc_throw(BadValue, "Unable to query for empty 'identifier'."); + } + + // Next, try to convert identifier-type + try { + x.type = Lease::getIdentifierType(type->stringValue()); + } catch (const std::exception& ex) { + isc_throw(BadValue, "Value of 'identifier-type' was not recognized."); + } + + x.query_by_addr = false; + return (x); +} + +ConstElementPtr +LeaseCmdsImpl::leaseGetHandler(const std::string& name, ConstElementPtr params) { + Parameters p; + Lease4Ptr lease4; + Lease6Ptr lease6; + bool v4 = (name == "lease4-get"); + try { + p = getParameters(params); + + switch (p.query_type) { + case TYPE_ADDR: { + // Query by address + if (v4) { + lease4 = LeaseMgr::instance().getLease4(p.subnet_id, p.addr); + } else { + lease6 = LeaseMgr::instance().getLease6(p.subnet_id, p.addr); + } + break; + } + case TYPE_HWADDR: + if (v4) { + lease4 = LeaseMgr::instance().getLease4(p.subnet_id, p.hwaddr); + } else { + return (createAnswer(CONTROL_RESULT_ERROR, + "Query by hw-address is not allowed in v6.")); + } + case TYPE_DUID: + if (v6) { + lease6 = LeaseMgr::instance().getLease6(p.subnet_id, p.duid); + } else { + return (createAnswer(CONTROL_RESULT_ERROR, + "Query by duid is not allowed in v4.")); + } + default: + return (createAnswer(CONTROL_RESULT_ERROR, + "Unknown query type: " << static_cast(p.query_type))); + } + } catch (const std::exception& ex) { + return (createAnswer(CONTROL_RESULT_ERROR, + "Failure during leaseX-get: " << ex.what())); + } + + ElementPtr lease_json; + if (v4 && lease4) { + lease_json = lease4->toElement4(); + } + if (!v4 && lease6) { + lease_json = lease6->toElement6(); + + } + if (lease) { + return (createAnswer(CONTROL_RESULT_SUCCESS, "Lease found.", lease_json)); + } else { + return (createAnswer(CONTROL_RESULT_SUCCESS, "Lease not found.")); + } +} + +ConstElementPtr +LeaseCmdsImpl::reservationDelHandler(const std::string& /*name*/, + ConstElementPtr params) { + Parameters p; + bool deleted; + try { + p = getParameters(params); + + if (p.query_by_addr) { + // try to delete by address + deleted = LeaseMgr::instance().del(p.subnet_id, p.addr); + } else { + // try to delete by identifier + if (family_ == AF_INET) { + deleted = LeaseMgr::instance().del4(p.subnet_id, p.type, + &p.ident[0], p.ident.size()); + } else { + deleted = LeaseMgr::instance().del6(p.subnet_id, p.type, + &p.ident[0], p.ident.size()); + } + } + } catch (const std::exception& ex) { + return (createAnswer(CONTROL_RESULT_ERROR, ex.what())); + } + + if (deleted) { + return (createAnswer(CONTROL_RESULT_SUCCESS, "Lease deleted.")); + } else { + return (createAnswer(CONTROL_RESULT_ERROR, + "Lease not deleted (not found).")); + } +} + +uint16_t LeaseCmdsImpl::family_ = AF_INET; +LeaseDataSourcePtr LeaseCmdsImpl::db_storage_; + +LeaseCmds::LeaseCmds() + :impl_(new LeaseCmdsImpl()) { +} + +LeaseCmds::~LeaseCmds() { + impl_.reset(); +} + +}; +}; diff --git a/src/hooks/dhcp/lease_cmds/lease_cmds.h b/src/hooks/dhcp/lease_cmds/lease_cmds.h new file mode 100644 index 0000000000..48161e541b --- /dev/null +++ b/src/hooks/dhcp/lease_cmds/lease_cmds.h @@ -0,0 +1,69 @@ +// Copyright (C) 2017 Internet Systems Consortium, Inc. ("ISC") +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#ifndef LEASE_CMDS_H +#define LEASE_CMDS_H + +#include + +namespace isc { +namespace lease_cmds { + +/// @brief Forward declaration of implementation class. +class LeaseCmdsImpl; + +/// @brief A wrapper class that provides convenient initialization to the library. +/// +/// This is a wrapper class that simply registers extra commands when +/// instantiated and deregisters them when the instance is destryed. +/// +/// For an actual implementation, see @ref LeaseCmdsImpl class in lease_cmds.cc file. +class LeaseCmds { +public: + + /// @brief Initalizes additional host commands. + /// + /// First, it ensures that either alternate host data source or CfgHosts + /// (configuration storage) are available. Then it checks that CommandMgr + /// is available. Then finally, it registers the following commands: + /// - lease4-add + /// - lease6-add + /// - lease4-get + /// - lease6-get + /// - lease4-del + /// - lease6-del + /// - lease4-update + /// - lease6-update + /// - lease4-del-all + /// - lease6-del-all + /// + /// @throw Unexpected If any of the above fails. + LeaseCmds(); + + /// @brief Destructor + /// + /// - lease4-add + /// - lease6-add + /// - lease4-get + /// - lease6-get + /// - lease4-del + /// - lease6-del + /// - lease4-update + /// - lease6-update + /// - lease4-del-all + /// - lease6-del-all + /// Unregisters commands: + ~LeaseCmds(); +private: + + /// Pointer to the actual implementation + boost::shared_ptr impl_; +}; + +}; +}; + +#endif diff --git a/src/hooks/dhcp/lease_cmds/lease_cmds_log.cc b/src/hooks/dhcp/lease_cmds/lease_cmds_log.cc new file mode 100644 index 0000000000..8215a6effa --- /dev/null +++ b/src/hooks/dhcp/lease_cmds/lease_cmds_log.cc @@ -0,0 +1,16 @@ +// Copyright (C) 2017 Internet Systems Consortium, Inc. ("ISC") +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#include + +namespace isc { +namespace lease_cmds { + +isc::log::Logger lease_cmds_logger("lease_cmds_hooks"); + +} +} + diff --git a/src/hooks/dhcp/lease_cmds/lease_cmds_log.h b/src/hooks/dhcp/lease_cmds/lease_cmds_log.h new file mode 100644 index 0000000000..56172b0feb --- /dev/null +++ b/src/hooks/dhcp/lease_cmds/lease_cmds_log.h @@ -0,0 +1,23 @@ +// Copyright (C) 2017 Internet Systems Consortium, Inc. ("ISC") +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#ifndef LEASE_CMD_LOG_H +#define LEASE_CMD_LOG_H + +#include +#include +#include + +namespace isc { +namespace lease_cmds { + +extern isc::log::Logger lease_cmds_logger; + +} // end of isc::lease_cmds +} // end of isc namespace + + +#endif diff --git a/src/hooks/dhcp/lease_cmds/lease_cmds_messages.mes b/src/hooks/dhcp/lease_cmds/lease_cmds_messages.mes new file mode 100644 index 0000000000..f222135f78 --- /dev/null +++ b/src/hooks/dhcp/lease_cmds/lease_cmds_messages.mes @@ -0,0 +1,51 @@ +# Copyright (C) 2017 Internet Systems Consortium, Inc. ("ISC") + +% LEASE_CMDS_INIT_FAILED loading Lease Commands hooks library failed: %1 +This error message indicates an error during loading the Lease Commands +hooks library. The details of the error are provided as argument of +the log message. + +% LEASE_CMDS_INIT_OK loading Lease Commands hooks library successful +This info message indicates that the Lease Commands hooks library has been +loaded successfully. Enjoy! + +% LEASE_CMDS_DEINIT_FAILED unloading Lease Commands hooks library failed: %1 +This error message indicates an error during unloading the Lease Commands +hooks library. The details of the error are provided as argument of +the log message. + +% LEASE_CMDS_DEINIT_OK unloading Lease Commands hooks library successful +This info message indicates that the Lease Commands hooks library has been +removed successfully. + +% LEASE_CMDS_ADD4_FAILED Lease4-add command failed (parameters: %1, reason: %2) +The lease4-add command has failed. Both the reason as well as the +parameters passed are logged. + +% LEASE_CMDS_ADD6_FAILED Lease4-add command failed (parameters: %1, reason: %2) +The lease6-add command has failed. Both the reason as well as the +parameters passed are logged. + +% LEASE_CMDS_ADD4 lease4-add command successful (parameters: %1) +The lease4-add command has been successful. Parameters of the host +added are logged. + +% LEASE_CMDS_ADD6 lease6-add command successful (parameters: %1) +The lease6-add command has been successful. Parameters of the host +added are logged. + +% LEASE_CMDS_DEL4_FAILED lease4-del command failed (parameters: %1, reason: %2) +The attempt to delete an IPv4 lease (lease4-del command) has failed. Both the +reason as well as the parameters passed are logged. + +% LEASE_CMDS_DEL6_FAILED lease6-del command failed (parameters: %1, reason: %2) +The attempt to delete an IPv6 lease (lease4-del command) has failed. Both the +reason as well as the parameters passed are logged. + +% LEASE_CMDS_DEL4 lease4-del command successful (parameters: %1) +The attempt to delete an IPv4 lease (lease4-del command) has been successful. +Parameters of the host removed are logged. + +% LEASE_CMDS_DEL6 lease4-del command successful (parameters: %1) +The attempt to delete an IPv4 lease (lease4-del command) has been successful. +Parameters of the host removed are logged. diff --git a/src/hooks/dhcp/lease_cmds/lease_parser.cc b/src/hooks/dhcp/lease_cmds/lease_parser.cc new file mode 100644 index 0000000000..d5130a17e4 --- /dev/null +++ b/src/hooks/dhcp/lease_cmds/lease_parser.cc @@ -0,0 +1,17 @@ +// Copyright (C) 2017 Internet Systems Consortium, Inc. ("ISC") +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + + +// V4: +// address,hwaddr,client_id,valid_lifetime,expire,subnet_id,fqdn_fwd,fqdn_rev,hostname,state + +// V6: +// address,duid,valid_lifetime,expire,subnet_id,pref_lifetime,lease_type,iaid,prefix_len,fqdn_fwd,fqdn_rev,hostname,hwaddr,state + +#include + + + diff --git a/src/hooks/dhcp/lease_cmds/lease_parser.h b/src/hooks/dhcp/lease_cmds/lease_parser.h new file mode 100644 index 0000000000..5d29c9254a --- /dev/null +++ b/src/hooks/dhcp/lease_cmds/lease_parser.h @@ -0,0 +1,37 @@ +// Copyright (C) 2014-2017 Internet Systems Consortium, Inc. ("ISC") +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#ifndef LEASE_PARSER_H +#define LEASE_PARSER_H + +#include +#include +#include + +namespace isc { +namespace lease_cmds { + +/// @brief Parser for a single Lease information. +class LeaseParser : public isc::data::SimpleParser { +}; + +class Lease4Parser : public LeaseParser { +public: + virtual isc::dhcp::Lease4Ptr parse(const isc::data::ConstElementPtr& lease_info); + virtual ~Lease4Parser() {} +}; + +class Lease6Parser : public LeaseParser { +public: + virtual isc::dhcp::Lease6Ptr parse(const isc::data::ConstElementPtr& lease_info); + virtual ~Lease6Parser() {} +}; + +}; // end of isc::dhcp namespace +}; // end of isc namespace + +#endif + diff --git a/src/hooks/dhcp/lease_cmds/load_unload.cc b/src/hooks/dhcp/lease_cmds/load_unload.cc new file mode 100644 index 0000000000..c1277cfc52 --- /dev/null +++ b/src/hooks/dhcp/lease_cmds/load_unload.cc @@ -0,0 +1,63 @@ +// Copyright (C) 2017 Internet Systems Consortium, Inc. ("ISC") +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +/// @file load_unload.cc Defines the load and unload hooks library functions. + +#include +#include +#include +#include +#include +#include + +using namespace isc::hooks; +using namespace isc::lease_cmds; + +boost::shared_ptr instance; + +extern "C" { + +/// @brief This function is called when the library is loaded. +/// +/// This function creates LeaseCmds object that registers +/// additional commands. +/// +/// @param handle library handle (ignored) +/// @return 0 when initialization is successful, 1 otherwise +int load(LibraryHandle& /*handle*/) { + + try { + instance.reset(new LeaseCmds()); + } catch (const isc::Unexpected& ex) { + LOG_ERROR(lease_cmds_logger, LEASE_CMDS_INIT_FAILED) + .arg(ex.what()); + return (1); + } + + LOG_INFO(lease_cmds_logger, LEASE_CMDS_INIT_OK); + return (0); +} + +/// @brief This function is called when the library is unloaded. +/// +/// This function creates LeaseCmds object that deregisters +/// additional commands. +/// +/// @return 0 if deregistration was successful, 1 otherwise +int unload() { + try { + instance.reset(); + } catch (const isc::Unexpected& ex) { + LOG_ERROR(lease_cmds_logger, LEASE_CMDS_DEINIT_FAILED) + .arg(ex.what()); + return (1); + } + + LOG_INFO(lease_cmds_logger, LEASE_CMDS_DEINIT_OK); + return (0); +} + +} diff --git a/src/hooks/dhcp/lease_cmds/tests/Makefile.am b/src/hooks/dhcp/lease_cmds/tests/Makefile.am new file mode 100644 index 0000000000..3a5f464080 --- /dev/null +++ b/src/hooks/dhcp/lease_cmds/tests/Makefile.am @@ -0,0 +1,64 @@ +SUBDIRS = . + +# The 'parallel-tests' is the default only on recent automake versions. +# However, since Kea 1.2.0 was released with files generated with automake version +# that doesn't use it, we can't use parallel without rebuilding 1.2.0 tarballs. +# We will flip this back to parallel-tests once 1.3.0 goes out with parallel +# enabled. +AUTOMAKE_OPTIONS = serial-tests + +AM_CPPFLAGS = -I$(top_builddir)/src/lib -I$(top_srcdir)/src/lib +AM_CPPFLAGS += -I$(top_builddir)/src/hooks/dhcp/lease_cmds -I$(top_srcdir)/src/hooks/dhcp/lease_cmds +AM_CPPFLAGS += $(BOOST_INCLUDES) +AM_CPPFLAGS += -DLIB_SO=\"$(abs_top_builddir)/src/hooks/dhcp/lease_cmds/.libs/libdhcp_lease_cmds.so\" +AM_CPPFLAGS += -DINSTALL_PROG=\"$(abs_top_srcdir)/install-sh\" + +AM_CXXFLAGS = $(KEA_CXXFLAGS) + +if USE_STATIC_LINK +AM_LDFLAGS = -static +endif + +# Unit test data files need to get installed. +EXTRA_DIST = + +CLEANFILES = *.gcno *.gcda + +# TESTS_ENVIRONMENT = $(LIBTOOL) --mode=execute $(VALGRIND_COMMAND) +LOG_COMPILER = $(LIBTOOL) +AM_LOG_FLAGS = --mode=execute + +TESTS = +if HAVE_GTEST +TESTS += lease_cmds_unittests + +lease_cmds_unittests_SOURCES = run_unittests.cc +lease_cmds_unittests_SOURCES += lease_cmds_unittest.cc + +lease_cmds_unittests_CPPFLAGS = $(AM_CPPFLAGS) $(GTEST_INCLUDES) $(LOG4CPLUS_INCLUDES) + +lease_cmds_unittests_LDFLAGS = $(AM_LDFLAGS) $(CRYPTO_LDFLAGS) $(GTEST_LDFLAGS) + +lease_cmds_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. +lease_cmds_unittests_CXXFLAGS += -Wno-unused-parameter +endif + +lease_cmds_unittests_LDADD = $(top_builddir)/src/lib/dhcpsrv/libkea-dhcpsrv.la +lease_cmds_unittests_LDADD += $(top_builddir)/src/lib/dhcp/libkea-dhcp++.la +lease_cmds_unittests_LDADD += $(top_builddir)/src/lib/asiolink/libkea-asiolink.la +lease_cmds_unittests_LDADD += $(top_builddir)/src/lib/cc/libkea-cc.la +lease_cmds_unittests_LDADD += $(top_builddir)/src/lib/config/libkea-cfgclient.la +lease_cmds_unittests_LDADD += $(top_builddir)/src/lib/hooks/libkea-hooks.la +lease_cmds_unittests_LDADD += $(top_builddir)/src/lib/log/libkea-log.la +lease_cmds_unittests_LDADD += $(top_builddir)/src/lib/util/libkea-util.la +lease_cmds_unittests_LDADD += $(top_builddir)/src/lib/exceptions/libkea-exceptions.la +lease_cmds_unittests_LDADD += $(LOG4CPLUS_LIBS) +lease_cmds_unittests_LDADD += $(CRYPTO_LIBS) +lease_cmds_unittests_LDADD += $(BOOST_LIBS) +lease_cmds_unittests_LDADD += $(GTEST_LDADD) +endif +noinst_PROGRAMS = $(TESTS)