Commit 785c2e52 authored by Tomek Mrugalski's avatar Tomek Mrugalski 🛰

[master] Merge branch 'trac5272' (lease_cmds hook added)

parents bd8f1b29 2bda0e20
......@@ -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
......
SUBDIRS = user_chk
SUBDIRS = user_chk lease_cmds
/lease_cmds_messages.cc
/lease_cmds_messages.h
/s-messages
/html
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/dhcpsrv/libkea-dhcpsrv.la
libdhcp_lease_cmds_la_LIBADD += $(top_builddir)/src/lib/config/libkea-cfgclient.la
libdhcp_lease_cmds_la_LIBADD += $(top_builddir)/src/lib/cc/libkea-cc.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
libdhcp_lease_cmds_la_LIBADD += $(LOG4CPLUS_LIBS)
libdhcp_lease_cmds_la_LIBADD += $(CRYPTO_LIBS)
libdhcp_lease_cmds_la_LIBADD += $(BOOST_LIBS)
This diff is collapsed.
// 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 <boost/shared_ptr.hpp>
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 destroyed.
///
/// For an actual implementation, see @ref LeaseCmdsImpl class in lease_cmds.cc file.
class LeaseCmds {
public:
/// @brief Initializes additional lease commands.
///
/// 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
///
/// Unregisters commands:
/// - lease4-add
/// - lease6-add
/// - lease4-get
/// - lease6-get
/// - lease4-del
/// - lease6-del
/// - lease4-update
/// - lease6-update
/// - lease4-del-all
/// - lease6-del-all
~LeaseCmds();
private:
/// Pointer to the actual implementation
boost::shared_ptr<LeaseCmdsImpl> impl_;
};
};
};
#endif
// 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 <lease_cmds_log.h>
namespace isc {
namespace lease_cmds {
isc::log::Logger lease_cmds_logger("lease_cmds_hooks");
}
}
// 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 <log/logger_support.h>
#include <log/macros.h>
#include <lease_cmds_messages.h>
namespace isc {
namespace lease_cmds {
extern isc::log::Logger lease_cmds_logger;
} // end of isc::lease_cmds
} // end of isc namespace
#endif
# 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 Lease6-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.
// 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 <cc/data.h>
#include <dhcp/hwaddr.h>
#include <asiolink/io_address.h>
#include <dhcpsrv/lease.h>
#include <lease_parser.h>
#include <config.h>
using namespace std;
using namespace isc::dhcp;
using namespace isc::data;
using namespace isc::asiolink;
namespace isc {
namespace lease_cmds {
Lease4Ptr
Lease4Parser::parse(ConstSrvConfigPtr& cfg,
const ConstElementPtr& lease_info) {
if (!lease_info) {
isc_throw(BadValue, "lease information missing");
}
// These are mandatory parameters.
IOAddress addr = getAddress(lease_info, "ip-address");
SubnetID subnet_id = getUint32(lease_info, "subnet-id");
if (!addr.isV4()) {
isc_throw(BadValue, "Non-IPv4 address specified: " << addr);
}
// Not a most straightforward conversion, but it works.
string hwaddr_txt = getString(lease_info, "hw-address");
HWAddr hwaddr = HWAddr::fromText(hwaddr_txt);
HWAddrPtr hwaddr_ptr = HWAddrPtr(new HWAddr(hwaddr));
Subnet4Ptr subnet = cfg->getCfgSubnets4()->getSubnet(subnet_id);
if (!subnet) {
isc_throw(BadValue, "Invalid subnet-id: No IPv4 subnet with subnet-id="
<< subnet_id << " currently configured.");
}
if (!subnet->inRange(addr)) {
isc_throw(BadValue, "The address " << addr.toText() << " does not belong "
"to subnet " << subnet->toText() << ", subnet-id=" << subnet_id);
}
// Client-id is optional.
ClientIdPtr client_id;
if (lease_info->contains("client-id")) {
string txt = getString(lease_info, "client-id");
client_id = ClientId::fromText(txt);
}
// These parameters are optional. If not specified, we'll derive them from
// the current subnet configuration, if possible.
uint32_t valid_lft = 0;
if (lease_info->contains("valid-lft")) {
valid_lft = getUint32(lease_info, "valid-lft");
} else {
valid_lft = subnet->getValid();
}
/// Let's calculate client last transmission time (cltt). If expiration
/// timestamp is specified explicitly, we will use that. Note there are no
/// checks whether this is in the past. There may be valid cases when user
/// wants to insert expired leases, e.g. when migrating from one DHCP server
/// to another and wants to migrate the database as is, without discarding
/// any leases.
time_t cltt;
if (lease_info->contains("expire")) {
int64_t tmp = getUint32(lease_info, "expire");
cltt = static_cast<time_t>(tmp - valid_lft);
} else {
cltt = time(NULL);
}
bool fqdn_fwd = false;
if (lease_info->contains("fqdn-fwd")) {
fqdn_fwd = getBoolean(lease_info, "fqdn-fwd");
}
bool fqdn_rev = false;
if (lease_info->contains("fqdn-rev")) {
fqdn_rev = getBoolean(lease_info, "fqdn-rev");
}
string hostname;
if (lease_info->contains("hostname")) {
hostname = getString(lease_info, "hostname");
}
if (hostname.empty() && (fqdn_fwd || fqdn_rev)) {
isc_throw(BadValue, "No hostname specified and either forward or reverse"
" fqdn was set to true.");
}
uint32_t state = 0;
if (lease_info->contains("state")) {
state = getUint8(lease_info, "state");
}
// Let's fabricate some data and we're ready to go.
uint32_t t1 = subnet->getT1();
uint32_t t2 = subnet->getT2();
Lease4Ptr l(new Lease4(addr, hwaddr_ptr, client_id, valid_lft, t1, t2,
cltt, subnet_id,
fqdn_fwd, fqdn_rev, hostname));
l->state_ = state;
return (l);
}
Lease6Ptr
Lease6Parser::parse(ConstSrvConfigPtr& cfg,
const ConstElementPtr& lease_info) {
if (!lease_info) {
isc_throw(BadValue, "lease information missing");
}
// These are mandatory parameters.
IOAddress addr = getAddress(lease_info, "ip-address");
SubnetID subnet_id = getUint32(lease_info, "subnet-id");
if (addr.isV4()) {
isc_throw(BadValue, "Non-IPv6 address specified: " << addr);
}
// Not a most straightforward conversion, but it works.
string duid_txt = getString(lease_info, "duid");
DUID duid = DUID::fromText(duid_txt);
DuidPtr duid_ptr = DuidPtr(new DUID(duid));
// Check if the subnet-id specified is sane.
Subnet6Ptr subnet = cfg->getCfgSubnets6()->getSubnet(subnet_id);
if (!subnet) {
isc_throw(BadValue, "Invalid subnet-id: No IPv6 subnet with subnet-id="
<< subnet_id << " currently configured.");
}
Lease::Type type = Lease::TYPE_NA;
uint8_t prefix_len = 128;
if (lease_info->contains("type")) {
string txt = getString(lease_info, "type");
if (txt == "IA_NA") {
type = Lease::TYPE_NA;
} else if (txt == "IA_TA") {
type = Lease::TYPE_TA;
} else if (txt == "IA_PD") {
type = Lease::TYPE_PD;
prefix_len = getUint8(lease_info, "prefix-len");
} else {
isc_throw(BadValue, "Incorrect lease type: " << txt << ", the only "
"supported values are: na, ta and pd");
}
}
// Check if the address specified really belongs to the subnet.
if ((type == Lease::TYPE_NA) && !subnet->inRange(addr)) {
isc_throw(BadValue, "The address " << addr.toText() << " does not belong "
"to subnet " << subnet->toText() << ", subnet-id=" << subnet_id);
}
uint32_t iaid = getUint32(lease_info, "iaid");
// Hw-address is optional in v6 leases.
HWAddrPtr hwaddr_ptr;
if (lease_info->contains("hw-address")) {
string hwaddr_txt = getString(lease_info, "hw-address");
HWAddr hwaddr = HWAddr::fromText(hwaddr_txt);
hwaddr_ptr = HWAddrPtr(new HWAddr(hwaddr));
}
// These parameters are optional. If not specified, we'll derive them
// from the current subnet configuration, if possible.
uint32_t valid_lft = 0;
if (lease_info->contains("valid-lft")) {
valid_lft = getUint32(lease_info, "valid-lft");
} else {
valid_lft = subnet->getValid();
}
// These parameters are optional. If not specified, we'll derive them
// from the current subnet configuration, if possible.
uint32_t pref_lft = 0;
if (lease_info->contains("preferred-lft")) {
pref_lft = getUint32(lease_info, "preferred-lft");
} else {
pref_lft = subnet->getValid();
}
/// Let's calculate client last transmission time (cltt). If expiration
/// timestamp is specified explicitly, we will use that. Note there are
/// no checks whether this is in the past. There may be valid cases when
/// user wants to insert expired leases, e.g. when migrating from one
/// DHCP server to another and wants to migrate the database as is, without
/// discarding any leases.
time_t cltt;
if (lease_info->contains("expire")) {
int64_t tmp = getUint32(lease_info, "expire");
cltt = static_cast<time_t>(tmp - valid_lft);
} else {
cltt = time(NULL);
}
bool fqdn_fwd = false;
if (lease_info->contains("fqdn-fwd")) {
fqdn_fwd = getBoolean(lease_info, "fqdn-fwd");
}
bool fqdn_rev = false;
if (lease_info->contains("fqdn-rev")) {
fqdn_rev = getBoolean(lease_info, "fqdn-rev");
}
string hostname;
if (lease_info->contains("hostname")) {
hostname = getString(lease_info, "hostname");
}
if (hostname.empty() && (fqdn_fwd || fqdn_rev)) {
isc_throw(BadValue, "No hostname specified and either forward or reverse"
" fqdn was set to true.");
}
uint32_t state = 0;
if (lease_info->contains("state")) {
state = getUint8(lease_info, "state");
}
// Let's fabricate some data and we're ready to go.
uint32_t t1 = subnet->getT1();
uint32_t t2 = subnet->getT2();
Lease6Ptr l(new Lease6(type, addr, duid_ptr, iaid, pref_lft, valid_lft, t1, t2,
subnet_id, fqdn_fwd, fqdn_rev, hostname,
hwaddr_ptr, prefix_len));
l->cltt_ = cltt;
l->state_ = state;
return (l);
}
};
};
// 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_PARSER_H
#define LEASE_PARSER_H
#include <cc/data.h>
#include <cc/simple_parser.h>
#include <dhcpsrv/lease.h>
#include <dhcpsrv/srv_config.h>
namespace isc {
namespace lease_cmds {
/// @brief Parser for Lease4 structure
///
/// It expects the data in the following format:
/// {
/// "ip-address": "192.0.2.1",
/// "hw-address": "00:01:02:03:04:05",
/// "client-id": "this-is-a-client",
/// "valid-lft": 3600,
/// "cltt": 12345678,
/// "expire": 1499282530,
/// "subnet-id": 1,
/// "fqdn-fwd": true,
/// "fqdn-rev": true,
/// "hostname": "myhost.example.org",
/// "state": 0
/// }
class Lease4Parser : public isc::data::SimpleParser {
public:
/// @brief Parses Element tree and tries to convert to Lease4
///
/// See @ref Lease6Parser class description for expected format.
///
/// @param cfg Currently running config (used for sanity checks and defaults)
/// @param lease_info structure to be parsed
/// @return A pointer to Lease4
/// @throw BadValue if any of the parameters is invalid
/// @throw DhcpConfigError if mandatory parameter is missing
virtual isc::dhcp::Lease4Ptr parse(isc::dhcp::ConstSrvConfigPtr& cfg,
const isc::data::ConstElementPtr& lease_info);
/// @brief virtual dtor (does nothing)
virtual ~Lease4Parser() {}
};
/// @brief Parser for Lease6 structure
///
/// {
/// "address": "2001:db8::1",
/// "duid": "00:01:02:03:04:05",
/// "type": "IA_NA",
/// "cltt": 12345678,
/// "preferred-lft": 3600,
/// "valid-lft": 3600,
/// "expire": 1499282530,
/// "subnet-id": 1,
/// "fqdn-fwd": true,
/// "fqdn-rev": true,
/// "hostname": "myhost.example.org",
/// "state": 0
/// }
/// It expects the input data to use the following format:
class Lease6Parser : public isc::data::SimpleParser {
public:
/// @brief Parses Element tree and tries to convert to Lease4
///
/// See @ref Lease6Parser class description for expected format.
///
/// @param cfg Currently running config (used for sanity checks and defaults)
/// @param lease_info structure to be parsed
/// @return A pointer to Lease4
/// @throw BadValue if any of the parameters is invalid
/// @throw DhcpConfigError if mandatory parameter is missing
virtual isc::dhcp::Lease6Ptr parse(isc::dhcp::ConstSrvConfigPtr& cfg,
const isc::data::ConstElementPtr& lease_info);
/// @brief virtual dtor (does nothing)
virtual ~Lease6Parser() {}
};
}; // end of isc::dhcp namespace
}; // end of isc namespace
#endif
// 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 <config.h>
#include <lease_cmds.h>
#include <lease_cmds_log.h>
#include <string>
#include <hooks/hooks.h>
#include <exceptions/exceptions.h>
using namespace isc::hooks;
using namespace isc::lease_cmds;
boost::shared_ptr<LeaseCmds> 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