2
0
mirror of https://gitlab.isc.org/isc-projects/kea synced 2025-08-22 09:57:41 +00:00

[#3826] Implemented lease6-get-by-hw-address command.

This commit is contained in:
Razvan Becheriu 2025-07-24 18:32:50 +03:00
parent 8da73b894a
commit 4c40c4e025
35 changed files with 746 additions and 57 deletions

View File

@ -61,6 +61,7 @@ src/share/api/lease6-del.json
src/share/api/lease6-get.json
src/share/api/lease6-get-all.json
src/share/api/lease6-get-by-duid.json
src/share/api/lease6-get-by-hw-address.json
src/share/api/lease6-get-by-hostname.json
src/share/api/lease6-get-page.json
src/share/api/lease6-resend-ddns.json

View File

@ -71,6 +71,9 @@ This library provides the following commands:
- :isccmd:`lease4-get-by-hw-address` - returns all IPv4 leases with the specified
hardware address.
- :isccmd:`lease6-get-by-hw-address` - returns all IPv6 leases with the specified
hardware address.
- :isccmd:`lease4-get-by-client-id` - returns all IPv4 leases with the specified
``client-id``.
@ -751,6 +754,9 @@ leases were found.
.. isccmd:: lease4-get-by-hw-address
.. _command-lease4-get-by-hw-address:
.. isccmd:: lease6-get-by-hw-address
.. _command-lease6-get-by-hw-address:
.. isccmd:: lease4-get-by-client-id
.. _command-lease4-get-by-client-id:

View File

@ -194,7 +194,7 @@ public:
int
leaseGetPageHandler(hooks::CalloutHandle& handle);
/// @brief lease4-get-by-hw-address command handler
/// @brief lease4-get-by-hw-address, lease6-get-by-hw-address command handler
///
/// Provides the implementation for @ref isc::lease_cmds::LeaseCmds::leaseGetByHwAddressHandler
///
@ -1576,8 +1576,10 @@ LeaseCmdsImpl::leaseGetPageHandler(CalloutHandle& handle) {
int
LeaseCmdsImpl::leaseGetByHwAddressHandler(CalloutHandle& handle) {
bool v4 = true;
try {
extractCommand(handle);
v4 = (cmd_name_ == "lease4-get-by-hw-address");
// arguments must always be present
if (!cmd_args_ || (cmd_args_->getType() != Element::map)) {
@ -1597,16 +1599,28 @@ LeaseCmdsImpl::leaseGetByHwAddressHandler(CalloutHandle& handle) {
HWAddr hwaddr = HWAddr::fromText(hw_address->stringValue());
ElementPtr leases_json = Element::createList();
if (v4) {
Lease4Collection leases =
LeaseMgrFactory::instance().getLease4(hwaddr);
ElementPtr leases_json = Element::createList();
for (auto const& lease : leases) {
ElementPtr lease_json = lease->toElement();
leases_json->add(lease_json);
}
} else {
Lease6Collection leases =
LeaseMgrFactory::instance().getLease6(hwaddr);
for (auto const& lease : leases) {
ElementPtr lease_json = lease->toElement();
leases_json->add(lease_json);
}
}
std::ostringstream s;
s << leases_json->size() << " IPv4 lease(s) found.";
s << leases_json->size()
<< " IPv" << (v4 ? "4" : "6")
<< " lease(s) found.";
ElementPtr args = Element::createMap();
args->set("leases", leases_json);
ConstElementPtr response =

View File

@ -64,7 +64,7 @@ For details see documentation and code of the following handlers:
- @ref isc::lease_cmds::LeaseCmdsImpl::leaseGetHandler (lease4-get, lease6-get)
- @ref isc::lease_cmds::LeaseCmdsImpl::leaseGetAllHandler(lease4-get-all, lease6-get-all)
- @ref isc::lease_cmds::LeaseCmdsImpl::leaseGetPageHandler(lease4-get-page, lease6-get-page)
- @ref isc::lease_cmds::LeaseCmdsImpl::leaseGetByHwAddressHandler(lease4-get-by-hw-address)
- @ref isc::lease_cmds::LeaseCmdsImpl::leaseGetByHwAddressHandler(lease4-get-by-hw-address, lease6-get-by-hw-address)
- @ref isc::lease_cmds::LeaseCmdsImpl::leaseGetByClientIdHandler(lease4-get-by-client-id)
- @ref isc::lease_cmds::LeaseCmdsImpl::leaseGetByDuidHandler(lease6-get-by-duid)
- @ref isc::lease_cmds::LeaseCmdsImpl::leaseGetByHostnameHandler(lease4-get-by-hostname, lease6-get-by-hostname)

View File

@ -262,12 +262,12 @@ public:
int
leaseGetPageHandler(hooks::CalloutHandle& handle);
/// @brief lease4-get-by-hw-address command handler
/// @brief lease4-get-by-hw-address, lease6-get-by-hw-address command handler
///
/// This command attempts to retrieve all IPv4 leases with a particular
/// This command attempts to retrieve all IPv4 or IPv6 leases with a particular
/// hardware address.
///
/// Example command:
/// Example command for IPv4:
/// {
/// "command": "lease4-get-by-hw-address",
/// "arguments": {

View File

@ -147,6 +147,17 @@ int lease4_get_by_hw_address(CalloutHandle& handle) {
return (lease_cmds.leaseGetByHwAddressHandler(handle));
}
/// @brief This is a command callout for 'lease6-get-by-hw-address' command.
///
/// @param handle Callout handle used to retrieve a command and
/// provide a response.
/// @return 0 if this callout has been invoked successfully,
/// 1 if an error occurs, 3 if no leases are returned.
int lease6_get_by_hw_address(CalloutHandle& handle) {
LeaseCmds lease_cmds;
return (lease_cmds.leaseGetByHwAddressHandler(handle));
}
/// @brief This is a command callout for 'lease4-get-by-client-id' command.
///
/// @param handle Callout handle used to retrieve a command and
@ -332,6 +343,8 @@ int load(LibraryHandle& handle) {
handle.registerCommandCallout("lease6-get-page", lease6_get_page);
handle.registerCommandCallout("lease4-get-by-hw-address",
lease4_get_by_hw_address);
handle.registerCommandCallout("lease6-get-by-hw-address",
lease6_get_by_hw_address);
handle.registerCommandCallout("lease4-get-by-client-id",
lease4_get_by_client_id);
handle.registerCommandCallout("lease6-get-by-duid", lease6_get_by_duid);

View File

@ -64,7 +64,7 @@ public:
/// @param pool_id expected pool-id (if value is 0 the parameter pool-id should not be present)
void checkLease6(isc::data::ConstElementPtr l, std::string ip,
uint8_t prefixlen, uint32_t subnet_id, std::string duid,
bool hwaddr_required, uint32_t pool_id = 0) {
std::string hwaddr = std::string(), uint32_t pool_id = 0) {
ASSERT_TRUE(l);
// If the element is a list we need to retrieve the lease that
@ -96,8 +96,9 @@ public:
EXPECT_EQ(duid, l->get("duid")->stringValue());
// hwaddr may or may not appear
if (hwaddr_required) {
EXPECT_TRUE(l->get("hwaddr"));
if (!hwaddr.empty()) {
ASSERT_TRUE(l->get("hw-address"));
EXPECT_EQ(hwaddr, l->get("hw-address")->stringValue());
}
if (pool_id) {
@ -280,6 +281,18 @@ public:
/// @brief Verifies that the limit of 0 is rejected.
void testLease6GetPagedLimitIsZero();
/// @brief Check that lease6-get-by-hw-address can handle a situation when
/// the query is broken (required parameter is missing).
void testLease6GetByHwAddressParams();
/// @brief Check that lease6-get-by-hw-address works as expected (find no
/// lease).
void testLease6GetByHwAddressFind0();
/// @brief Check that lease6-get-by-hw-address works as expected (find two
/// leases).
void testLease6GetByHwAddressFind2();
/// @brief Check that lease6-get-by-duid can handle a situation when the
/// query is broken (required parameter is missing).
void testLease6GetByDuidParams();
@ -1519,7 +1532,7 @@ void Lease6CmdsTest::testLease6GetByAddr() {
ASSERT_TRUE(lease);
// Now check that the lease was indeed returned.
checkLease6(lease, "2001:db8:1::1", 0, 66, "42:42:42:42:42:42:42:42", false);
checkLease6(lease, "2001:db8:1::1", 0, 66, "42:42:42:42:42:42:42:42");
}
void Lease6CmdsTest::testLease6GetByAddrPrefix() {
// Initialize lease manager (true = v6, false = don't add leases)
@ -1554,7 +1567,7 @@ void Lease6CmdsTest::testLease6GetByAddrPrefix() {
ASSERT_TRUE(lease);
// Now check that the lease was indeed returned.
checkLease6(lease, "2001:db8:1234:ab::", 56, 66, "77:77:77:77:77:77:77:77", false);
checkLease6(lease, "2001:db8:1234:ab::", 56, 66, "77:77:77:77:77:77:77:77");
}
void Lease6CmdsTest::testLease6GetByDuid() {
@ -1584,7 +1597,7 @@ void Lease6CmdsTest::testLease6GetByDuid() {
ASSERT_TRUE(lease);
// Now check that the lease was indeed returned.
checkLease6(lease, "2001:db8:1::1", 0, 66, "42:42:42:42:42:42:42:42", false);
checkLease6(lease, "2001:db8:1::1", 0, 66, "42:42:42:42:42:42:42:42");
}
void Lease6CmdsTest::testLease6GetAll() {
@ -1611,10 +1624,10 @@ void Lease6CmdsTest::testLease6GetAll() {
ASSERT_EQ(Element::list, leases->getType());
// Let's check if the response contains desired leases.
checkLease6(leases, "2001:db8:1::1", 0, 66, "42:42:42:42:42:42:42:42", false);
checkLease6(leases, "2001:db8:1::2", 0, 66, "56:56:56:56:56:56:56:56", false, 5);
checkLease6(leases, "2001:db8:2::1", 0, 99, "42:42:42:42:42:42:42:42", false);
checkLease6(leases, "2001:db8:2::2", 0, 99, "56:56:56:56:56:56:56:56", false);
checkLease6(leases, "2001:db8:1::1", 0, 66, "42:42:42:42:42:42:42:42");
checkLease6(leases, "2001:db8:1::2", 0, 66, "56:56:56:56:56:56:56:56", "", 5);
checkLease6(leases, "2001:db8:2::1", 0, 99, "42:42:42:42:42:42:42:42");
checkLease6(leases, "2001:db8:2::2", 0, 99, "56:56:56:56:56:56:56:56");
}
void Lease6CmdsTest::testLease6GetAllNoLeases() {
@ -1671,8 +1684,8 @@ void Lease6CmdsTest::testLease6GetAllBySubnetId() {
ASSERT_EQ(Element::list, leases->getType());
// Let's check if the response contains desired leases.
checkLease6(leases, "2001:db8:1::1", 0, 66, "42:42:42:42:42:42:42:42", false);
checkLease6(leases, "2001:db8:1::2", 0, 66, "56:56:56:56:56:56:56:56", false, 5);
checkLease6(leases, "2001:db8:1::1", 0, 66, "42:42:42:42:42:42:42:42");
checkLease6(leases, "2001:db8:1::2", 0, 66, "56:56:56:56:56:56:56:56", "", 5);
}
void Lease6CmdsTest::testLease6GetAllBySubnetIdNoLeases() {
@ -1732,10 +1745,10 @@ void Lease6CmdsTest::testLease6GetAllByMultipleSubnetIds() {
ASSERT_EQ(Element::list, leases->getType());
// Let's check if the response contains desired leases.
checkLease6(leases, "2001:db8:1::1", 0, 66, "42:42:42:42:42:42:42:42", false);
checkLease6(leases, "2001:db8:1::2", 0, 66, "56:56:56:56:56:56:56:56", false, 5);
checkLease6(leases, "2001:db8:2::1", 0, 99, "42:42:42:42:42:42:42:42", false);
checkLease6(leases, "2001:db8:2::2", 0, 99, "56:56:56:56:56:56:56:56", false);
checkLease6(leases, "2001:db8:1::1", 0, 66, "42:42:42:42:42:42:42:42");
checkLease6(leases, "2001:db8:1::2", 0, 66, "56:56:56:56:56:56:56:56", "", 5);
checkLease6(leases, "2001:db8:2::1", 0, 99, "42:42:42:42:42:42:42:42");
checkLease6(leases, "2001:db8:2::2", 0, 99, "56:56:56:56:56:56:56:56");
}
void Lease6CmdsTest::testLease6GetBySubnetIdInvalidArguments() {
@ -1855,7 +1868,7 @@ void Lease6CmdsTest::testLease6GetPaged() {
pool_id = 5;
}
checkLease6(leases, last_address, 0, from_mgr->subnet_id_,
from_mgr->duid_->toText(), false, pool_id);
from_mgr->duid_->toText(), "", pool_id);
}
} else {
@ -1979,6 +1992,91 @@ void Lease6CmdsTest::testLease6GetPagedLimitIsZero() {
testCommand(cmd, CONTROL_RESULT_ERROR, exp_rsp);
}
void Lease6CmdsTest::testLease6GetByHwAddressParams() {
// No parameters whatsoever.
string cmd =
"{\n"
" \"command\": \"lease6-get-by-hw-address\",\n"
" \"arguments\": {"
" }\n"
"}";
string exp_rsp = "'hw-address' parameter not specified";
testCommand(cmd, CONTROL_RESULT_ERROR, exp_rsp);
// hw-address must be a string.
cmd =
"{\n"
" \"command\": \"lease6-get-by-hw-address\",\n"
" \"arguments\": {"
" \"hw-address\": 1234\n"
" }\n"
"}";
exp_rsp = "'hw-address' parameter must be a string";
testCommand(cmd, CONTROL_RESULT_ERROR, exp_rsp);
// Simply bad value.
cmd =
"{\n"
" \"command\": \"lease6-get-by-hw-address\",\n"
" \"arguments\": {"
" \"hw-address\": \"00::01:00:bc:0d:67\"\n"
" }\n"
"}";
exp_rsp = "two consecutive separators (':') specified in a decoded string";
exp_rsp += " '00::01:00:bc:0d:67'";
testCommand(cmd, CONTROL_RESULT_ERROR, exp_rsp);
}
void Lease6CmdsTest::testLease6GetByHwAddressFind0() {
// Initialize lease manager (true = v6, false = don't add leases)
initLeaseMgr(true, false);
// No such lease.
string cmd =
"{\n"
" \"command\": \"lease6-get-by-hw-address\",\n"
" \"arguments\": {"
" \"hw-address\": \"01:02:03:04:05:06\"\n"
" }\n"
"}";
string exp_rsp = "0 IPv6 lease(s) found.";
testCommand(cmd, CONTROL_RESULT_EMPTY, exp_rsp);
}
void Lease6CmdsTest::testLease6GetByHwAddressFind2() {
// Initialize lease manager (true = v6, true = add leases)
initLeaseMgr(true, true);
// Get the lease.
string cmd =
"{\n"
" \"command\": \"lease6-get-by-hw-address\",\n"
" \"arguments\": {"
" \"hw-address\": \"08:08:08:08:08:08\"\n"
" }\n"
"}";
string exp_rsp = "2 IPv6 lease(s) found.";
ConstElementPtr rsp = testCommand(cmd, CONTROL_RESULT_SUCCESS, exp_rsp);
// Now check that the lease parameters were indeed returned.
ASSERT_TRUE(rsp);
ConstElementPtr map = rsp->get("arguments");
ASSERT_TRUE(map);
ASSERT_EQ(Element::map, map->getType());
ConstElementPtr leases = map->get("leases");
ASSERT_TRUE(leases);
ASSERT_EQ(Element::list, leases->getType());
ASSERT_EQ(2, leases->size());
// Let's check if the response makes any sense.
ConstElementPtr lease = leases->get(0);
ASSERT_TRUE(lease);
checkLease6(lease, "2001:db8:1::1", 0, 66, "42:42:42:42:42:42:42:42", "08:08:08:08:08:08");
lease = leases->get(1);
ASSERT_TRUE(lease);
checkLease6(lease, "2001:db8:2::1", 0, 99, "42:42:42:42:42:42:42:42", "08:08:08:08:08:08");
}
void Lease6CmdsTest::testLease6GetByDuidParams() {
// No parameters whatsoever.
string cmd =
@ -2058,10 +2156,10 @@ void Lease6CmdsTest::testLease6GetByDuidFind2() {
// Let's check if the response makes any sense.
ConstElementPtr lease = leases->get(0);
ASSERT_TRUE(lease);
checkLease6(lease, "2001:db8:1::1", 0, 66, "42:42:42:42:42:42:42:42", false);
checkLease6(lease, "2001:db8:1::1", 0, 66, "42:42:42:42:42:42:42:42");
lease = leases->get(1);
ASSERT_TRUE(lease);
checkLease6(lease, "2001:db8:2::1", 0, 99, "42:42:42:42:42:42:42:42", false);
checkLease6(lease, "2001:db8:2::1", 0, 99, "42:42:42:42:42:42:42:42");
}
void Lease6CmdsTest::testLease6GetByHostnameParams() {
@ -2142,10 +2240,10 @@ void Lease6CmdsTest::testLease6GetByHostnameFind2() {
// Let's check if the response makes any sense.
ConstElementPtr lease = leases->get(0);
ASSERT_TRUE(lease);
checkLease6(lease, "2001:db8:1::1", 0, 66, "42:42:42:42:42:42:42:42", false);
checkLease6(lease, "2001:db8:1::1", 0, 66, "42:42:42:42:42:42:42:42");
lease = leases->get(2);
ASSERT_TRUE(lease);
checkLease6(lease, "2001:db8:2::1", 0, 99, "42:42:42:42:42:42:42:42", false);
checkLease6(lease, "2001:db8:2::1", 0, 99, "42:42:42:42:42:42:42:42");
}
void Lease6CmdsTest::testLease6UpdateMissingParams() {
@ -4789,6 +4887,34 @@ TEST_F(Lease6CmdsTest, lease6GetPagedLimitIsZeroMultiThreading) {
testLease6GetPagedLimitIsZero();
}
TEST_F(Lease6CmdsTest, lease6GetByHwAddressParams) {
testLease6GetByHwAddressParams();
}
TEST_F(Lease6CmdsTest, lease6GetByHwAddressParamsMultiThreading) {
MultiThreadingTest mt(true);
testLease6GetByHwAddressParams();
}
TEST_F(Lease6CmdsTest, lease6GetByHwAddressFind0) {
testLease6GetByHwAddressFind0();
}
TEST_F(Lease6CmdsTest, lease6GetByHwAddressFind0MultiThreading) {
MultiThreadingTest mt(true);
testLease6GetByHwAddressFind0();
}
TEST_F(Lease6CmdsTest, lease6GetByHwAddressFind2) {
testLease6GetByHwAddressFind2();
}
TEST_F(Lease6CmdsTest, lease6GetByHwAddressFind2MultiThreading) {
MultiThreadingTest mt(true);
testLease6GetByHwAddressFind2();
}
TEST_F(Lease6CmdsTest, lease6GetByDuidParams) {
testLease6GetByDuidParams();
}

View File

@ -46,7 +46,7 @@ TEST_F(LeaseCmdsTest, commands) {
"lease4-get", "lease6-get",
"lease4-get-all", "lease6-get-all",
"lease4-get-page", "lease6-get-page",
"lease4-get-by-hw-address",
"lease4-get-by-hw-address", "lease6-get-by-hw-address",
"lease4-get-by-client-id", "lease6-get-by-duid",
"lease4-get-by-hostname", "lease6-get-by-hostname",
"lease4-del", "lease6-del",

View File

@ -360,7 +360,8 @@ public:
isc::dhcp::Lease6Ptr createLease6(const std::string& ip_address,
const isc::dhcp::SubnetID& subnet_id,
const uint8_t duid_pattern,
bool declined = false, uint32_t pool_id = 0) {
bool declined = false, uint32_t pool_id = 0,
const uint8_t hw_address_pattern = 0) {
isc::dhcp::Lease6Ptr lease(new isc::dhcp::Lease6());
lease->addr_ = isc::asiolink::IOAddress(ip_address);
@ -382,6 +383,7 @@ public:
lease->fqdn_rev_ = true;
lease->hostname_ = "myhost.example.com.";
lease->pool_id_ = pool_id;
lease->hwaddr_.reset(new isc::dhcp::HWAddr(std::vector<uint8_t>(6, hw_address_pattern), isc::dhcp::HTYPE_ETHER));
return (lease);
}
@ -429,10 +431,10 @@ public:
if (insert_lease) {
if (v6) {
lmptr_->addLease(createLease6("2001:db8:1::1", 66, 0x42, declined));
lmptr_->addLease(createLease6("2001:db8:1::2", 66, 0x56, declined, 5));
lmptr_->addLease(createLease6("2001:db8:2::1", 99, 0x42, declined));
lmptr_->addLease(createLease6("2001:db8:2::2", 99, 0x56, declined));
lmptr_->addLease(createLease6("2001:db8:1::1", 66, 0x42, declined, 0, 0x08));
lmptr_->addLease(createLease6("2001:db8:1::2", 66, 0x56, declined, 5, 0x09));
lmptr_->addLease(createLease6("2001:db8:2::1", 99, 0x42, declined, 0, 0x08));
lmptr_->addLease(createLease6("2001:db8:2::2", 99, 0x56, declined, 0, 0x09));
if (declined) {
isc::stats::StatsMgr::instance().setValue(
isc::stats::StatsMgr::generateName("subnet", 66, "declined-addresses"),

View File

@ -33,7 +33,8 @@ extern const isc::log::MessageID MYSQL_LB_GET_EXPIRED4 = "MYSQL_LB_GET_EXPIRED4"
extern const isc::log::MessageID MYSQL_LB_GET_EXPIRED6 = "MYSQL_LB_GET_EXPIRED6";
extern const isc::log::MessageID MYSQL_LB_GET_HOSTNAME4 = "MYSQL_LB_GET_HOSTNAME4";
extern const isc::log::MessageID MYSQL_LB_GET_HOSTNAME6 = "MYSQL_LB_GET_HOSTNAME6";
extern const isc::log::MessageID MYSQL_LB_GET_HWADDR = "MYSQL_LB_GET_HWADDR";
extern const isc::log::MessageID MYSQL_LB_GET_HWADDR4 = "MYSQL_LB_GET_HWADDR4";
extern const isc::log::MessageID MYSQL_LB_GET_HWADDR6 = "MYSQL_LB_GET_HWADDR6";
extern const isc::log::MessageID MYSQL_LB_GET_IAID_DUID = "MYSQL_LB_GET_IAID_DUID";
extern const isc::log::MessageID MYSQL_LB_GET_IAID_SUBID_DUID = "MYSQL_LB_GET_IAID_SUBID_DUID";
extern const isc::log::MessageID MYSQL_LB_GET_PAGE4 = "MYSQL_LB_GET_PAGE4";
@ -93,7 +94,8 @@ const char* values[] = {
"MYSQL_LB_GET_EXPIRED6", "obtaining maximum %1 of expired IPv6 leases",
"MYSQL_LB_GET_HOSTNAME4", "obtaining IPv4 leases for hostname %1",
"MYSQL_LB_GET_HOSTNAME6", "obtaining IPv6 leases for hostname %1",
"MYSQL_LB_GET_HWADDR", "obtaining IPv4 leases for hardware address %1",
"MYSQL_LB_GET_HWADDR4", "obtaining IPv4 leases for hardware address %1",
"MYSQL_LB_GET_HWADDR6", "obtaining IPv6 leases for hardware address %1",
"MYSQL_LB_GET_IAID_DUID", "obtaining IPv6 leases for IAID %1, DUID %2, lease type %3",
"MYSQL_LB_GET_IAID_SUBID_DUID", "obtaining IPv6 leases for IAID %1, subnet ID %2, DUID %3, lease type %4",
"MYSQL_LB_GET_PAGE4", "obtaining at most %1 IPv4 leases starting from address %2",

View File

@ -34,7 +34,8 @@ extern const isc::log::MessageID MYSQL_LB_GET_EXPIRED4;
extern const isc::log::MessageID MYSQL_LB_GET_EXPIRED6;
extern const isc::log::MessageID MYSQL_LB_GET_HOSTNAME4;
extern const isc::log::MessageID MYSQL_LB_GET_HOSTNAME6;
extern const isc::log::MessageID MYSQL_LB_GET_HWADDR;
extern const isc::log::MessageID MYSQL_LB_GET_HWADDR4;
extern const isc::log::MessageID MYSQL_LB_GET_HWADDR6;
extern const isc::log::MessageID MYSQL_LB_GET_IAID_DUID;
extern const isc::log::MessageID MYSQL_LB_GET_IAID_SUBID_DUID;
extern const isc::log::MessageID MYSQL_LB_GET_PAGE4;

View File

@ -143,12 +143,18 @@ A debug message issued when the server is attempting to obtain a set
of IPv6 leases from the MySQL database for a client with the specified
hostname.
% MYSQL_LB_GET_HWADDR obtaining IPv4 leases for hardware address %1
% MYSQL_LB_GET_HWADDR4 obtaining IPv4 leases for hardware address %1
Logged at debug log level 50.
A debug message issued when the server is attempting to obtain a set
of IPv4 leases from the MySQL database for a client with the specified
hardware address.
% MYSQL_LB_GET_HWADDR6 obtaining IPv6 leases for hardware address %1
Logged at debug log level 50.
A debug message issued when the server is attempting to obtain a set
of IPv6 leases from the MySQL database for a client with the specified
hardware address.
% MYSQL_LB_GET_IAID_DUID obtaining IPv6 leases for IAID %1, DUID %2, lease type %3
Logged at debug log level 50.
A debug message issued when the server is attempting to obtain a set of IPv6

View File

@ -301,6 +301,15 @@ tagged_statements = { {
"state, user_context, pool_id "
"FROM lease6 "
"WHERE address = ? AND lease_type = ?"},
{MySqlLeaseMgr::GET_LEASE6_HWADDR,
"SELECT address, duid, valid_lifetime, "
"expire, subnet_id, pref_lifetime, "
"lease_type, iaid, prefix_len, "
"fqdn_fwd, fqdn_rev, hostname, "
"hwaddr, hwtype, hwaddr_source, "
"state, user_context, pool_id "
"FROM lease6 "
"WHERE hwaddr = ?"},
{MySqlLeaseMgr::GET_LEASE6_DUID_IAID,
"SELECT address, duid, valid_lifetime, "
"expire, subnet_id, pref_lifetime, "
@ -2564,7 +2573,7 @@ MySqlLeaseMgr::getLease4(const IOAddress& addr) const {
Lease4Collection
MySqlLeaseMgr::getLease4(const HWAddr& hwaddr) const {
LOG_DEBUG(mysql_lb_logger, MYSQL_LB_DBG_TRACE_DETAIL, MYSQL_LB_GET_HWADDR)
LOG_DEBUG(mysql_lb_logger, MYSQL_LB_DBG_TRACE_DETAIL, MYSQL_LB_GET_HWADDR4)
.arg(hwaddr.toText());
// Set up the WHERE clause value
@ -2874,6 +2883,47 @@ MySqlLeaseMgr::getLease6(Lease::Type lease_type,
return (result);
}
Lease6Collection
MySqlLeaseMgr::getLease6(const HWAddr& hwaddr) const {
LOG_DEBUG(mysql_lb_logger, MYSQL_LB_DBG_TRACE_DETAIL, MYSQL_LB_GET_HWADDR6)
.arg(hwaddr.toText());
// Set up the WHERE clause value
MYSQL_BIND inbind[1];
memset(inbind, 0, sizeof(inbind));
inbind[0].buffer_type = MYSQL_TYPE_BLOB;
unsigned long hwaddr_length = hwaddr.hwaddr_.size();
// If the data happens to be empty, we have to create a 1 byte dummy
// buffer and pass it to the binding.
uint8_t single_byte_data = 0;
// As "buffer" is "char*" - even though the data is being read - we need
// to cast away the "const"ness as well as reinterpreting the data as
// a "char*". (We could avoid the "const_cast" by copying the data to a
// local variable, but as the data is only being read, this introduces
// an unnecessary copy).
uint8_t* data = !hwaddr.hwaddr_.empty() ? const_cast<uint8_t*>(&hwaddr.hwaddr_[0])
: &single_byte_data;
inbind[0].buffer = reinterpret_cast<char*>(data);
inbind[0].buffer_length = hwaddr_length;
inbind[0].length = &hwaddr_length;
// Get the data
Lease6Collection result;
// Get a context
MySqlLeaseContextAlloc get_context(*this);
MySqlLeaseContextPtr ctx = get_context.ctx_;
getLeaseCollection(ctx, GET_LEASE6_HWADDR, inbind, result);
return (result);
}
Lease6Collection
MySqlLeaseMgr::getLeases6(Lease::Type lease_type, const DUID& duid,
uint32_t iaid) const {

View File

@ -338,6 +338,24 @@ public:
virtual Lease6Ptr getLease6(Lease::Type type,
const isc::asiolink::IOAddress& addr) const override;
/// @brief Returns existing IPv6 leases for specified hardware address.
///
/// Although in the usual case there will be only one lease, for mobile
/// clients or clients with multiple static/fixed/reserved leases there
/// can be more than one. Thus return type is a container, not a single
/// pointer.
///
/// @param hwaddr hardware address of the client
///
/// @return lease collection
///
/// @throw isc::dhcp::DataTruncation Data was truncated on retrieval to
/// fit into the space allocated for the result. This indicates a
/// programming error.
/// @throw isc::db::DbOperationError An operation on the open database has
/// failed.
virtual Lease6Collection getLease6(const isc::dhcp::HWAddr& hwaddr) const override;
/// @brief Returns existing IPv6 leases for a given DUID+IA combination
///
/// Although in the usual case there will be only one lease, for mobile
@ -756,6 +774,7 @@ public:
GET_LEASE4_REMOTEID_QET, // Get page of leases by remote ID and query end time.
GET_LEASE6, // Get all IPv6 leases
GET_LEASE6_ADDR, // Get lease6 by address and type
GET_LEASE6_HWADDR, // Get lease6 by HW address
GET_LEASE6_DUID_IAID, // Get lease6 by DUID and IAID
GET_LEASE6_DUID_IAID_SUBID, // Get lease6 by DUID, IAID and subnet ID
GET_LEASE6_PAGE, // Get page of leases beginning with an address

View File

@ -911,6 +911,42 @@ TEST_F(MySqlLeaseMgrTest, testLease6HWTypeAndSourceMultiThreading) {
testLease6HWTypeAndSource();
}
/// @brief Check GetLease6 methods - access by Hardware Address
TEST_F(MySqlLeaseMgrTest, getLease6HWAddr1) {
testGetLease6HWAddr1();
}
/// @brief Check GetLease6 methods - access by Hardware Address
TEST_F(MySqlLeaseMgrTest, getLease6HWAddr1MultiThreading) {
MultiThreadingTest mt(true);
testGetLease6HWAddr1();
}
/// @brief Check GetLease6 methods - access by Hardware Address
TEST_F(MySqlLeaseMgrTest, getLease6HWAddr2) {
testGetLease6HWAddr2();
}
/// @brief Check GetLease6 methods - access by Hardware Address
TEST_F(MySqlLeaseMgrTest, getLease6HWAddr2MultiThreading) {
MultiThreadingTest mt(true);
testGetLease6HWAddr2();
}
/// @brief Get lease6 by hardware address (2)
///
/// Check that the system can cope with getting a hardware address of
/// any size.
TEST_F(MySqlLeaseMgrTest, getLease6HWAddrSize) {
testGetLease4HWAddrSize();
}
/// @brief Get lease6 by hardware address (2)
TEST_F(MySqlLeaseMgrTest, getLease6HWAddrSizeMultiThreading) {
MultiThreadingTest mt(true);
testGetLease6HWAddrSize();
}
/// @brief Check that the expired DHCPv6 leases can be retrieved.
///
/// This test adds a number of leases to the lease database and marks

View File

@ -32,7 +32,8 @@ extern const isc::log::MessageID PGSQL_LB_GET_EXPIRED4 = "PGSQL_LB_GET_EXPIRED4"
extern const isc::log::MessageID PGSQL_LB_GET_EXPIRED6 = "PGSQL_LB_GET_EXPIRED6";
extern const isc::log::MessageID PGSQL_LB_GET_HOSTNAME4 = "PGSQL_LB_GET_HOSTNAME4";
extern const isc::log::MessageID PGSQL_LB_GET_HOSTNAME6 = "PGSQL_LB_GET_HOSTNAME6";
extern const isc::log::MessageID PGSQL_LB_GET_HWADDR = "PGSQL_LB_GET_HWADDR";
extern const isc::log::MessageID PGSQL_LB_GET_HWADDR4 = "PGSQL_LB_GET_HWADDR4";
extern const isc::log::MessageID PGSQL_LB_GET_HWADDR6 = "PGSQL_LB_GET_HWADDR6";
extern const isc::log::MessageID PGSQL_LB_GET_IAID_DUID = "PGSQL_LB_GET_IAID_DUID";
extern const isc::log::MessageID PGSQL_LB_GET_IAID_SUBID_DUID = "PGSQL_LB_GET_IAID_SUBID_DUID";
extern const isc::log::MessageID PGSQL_LB_GET_PAGE4 = "PGSQL_LB_GET_PAGE4";
@ -89,7 +90,8 @@ const char* values[] = {
"PGSQL_LB_GET_EXPIRED6", "obtaining maximum %1 of expired IPv6 leases",
"PGSQL_LB_GET_HOSTNAME4", "obtaining IPv4 leases for hostname %1",
"PGSQL_LB_GET_HOSTNAME6", "obtaining IPv6 leases for hostname %1",
"PGSQL_LB_GET_HWADDR", "obtaining IPv4 leases for hardware address %1",
"PGSQL_LB_GET_HWADDR4", "obtaining IPv4 leases for hardware address %1",
"PGSQL_LB_GET_HWADDR6", "obtaining IPv6 leases for hardware address %1",
"PGSQL_LB_GET_IAID_DUID", "obtaining IPv4 leases for IAID %1 and DUID %2, lease type %3",
"PGSQL_LB_GET_IAID_SUBID_DUID", "obtaining IPv4 leases for IAID %1, subnet ID %2, DUID %3, and lease type %4",
"PGSQL_LB_GET_PAGE4", "obtaining at most %1 IPv4 leases starting from address %2",

View File

@ -33,7 +33,8 @@ extern const isc::log::MessageID PGSQL_LB_GET_EXPIRED4;
extern const isc::log::MessageID PGSQL_LB_GET_EXPIRED6;
extern const isc::log::MessageID PGSQL_LB_GET_HOSTNAME4;
extern const isc::log::MessageID PGSQL_LB_GET_HOSTNAME6;
extern const isc::log::MessageID PGSQL_LB_GET_HWADDR;
extern const isc::log::MessageID PGSQL_LB_GET_HWADDR4;
extern const isc::log::MessageID PGSQL_LB_GET_HWADDR6;
extern const isc::log::MessageID PGSQL_LB_GET_IAID_DUID;
extern const isc::log::MessageID PGSQL_LB_GET_IAID_SUBID_DUID;
extern const isc::log::MessageID PGSQL_LB_GET_PAGE4;

View File

@ -137,12 +137,18 @@ A debug message issued when the server is attempting to obtain a set
of IPv6 leases from the PostgreSQL database for a client with the specified
hostname.
% PGSQL_LB_GET_HWADDR obtaining IPv4 leases for hardware address %1
% PGSQL_LB_GET_HWADDR4 obtaining IPv4 leases for hardware address %1
Logged at debug log level 50.
A debug message issued when the server is attempting to obtain a set
of IPv4 leases from the PostgreSQL database for a client with the specified
hardware address.
% PGSQL_LB_GET_HWADDR6 obtaining IPv6 leases for hardware address %1
Logged at debug log level 50.
A debug message issued when the server is attempting to obtain a set
of IPv6 leases from the PostgreSQL database for a client with the specified
hardware address.
% PGSQL_LB_GET_IAID_DUID obtaining IPv4 leases for IAID %1 and DUID %2, lease type %3
Logged at debug log level 50.
A debug message issued when the server is attempting to obtain a set of IPv6

View File

@ -324,6 +324,17 @@ PgSqlTaggedStatement tagged_statements[] = {
"FROM lease6 "
"WHERE address = cast($1 as inet) AND lease_type = $2" },
// GET_LEASE6_HWADDR
{ 1, { OID_BYTEA },
"get_lease6_hwaddr",
"SELECT host(address), duid, valid_lifetime, "
"extract(epoch from expire)::bigint, subnet_id, pref_lifetime, "
"lease_type, iaid, prefix_len, fqdn_fwd, fqdn_rev, hostname, "
"hwaddr, hwtype, hwaddr_source, "
"state, user_context, pool_id "
"FROM lease6 "
"WHERE hwaddr = $1" },
// GET_LEASE6_DUID_IAID
{ 3, { OID_BYTEA, OID_INT8, OID_INT2 },
"get_lease6_duid_iaid",
@ -1936,7 +1947,7 @@ PgSqlLeaseMgr::getLease4(const IOAddress& addr) const {
Lease4Collection
PgSqlLeaseMgr::getLease4(const HWAddr& hwaddr) const {
LOG_DEBUG(pgsql_lb_logger, PGSQL_LB_DBG_TRACE_DETAIL, PGSQL_LB_GET_HWADDR)
LOG_DEBUG(pgsql_lb_logger, PGSQL_LB_DBG_TRACE_DETAIL, PGSQL_LB_GET_HWADDR4)
.arg(hwaddr.toText());
// Set up the WHERE clause value
@ -2176,6 +2187,33 @@ PgSqlLeaseMgr::getLease6(Lease::Type lease_type,
return (result);
}
Lease6Collection
PgSqlLeaseMgr::getLease6(const HWAddr& hwaddr) const {
LOG_DEBUG(pgsql_lb_logger, PGSQL_LB_DBG_TRACE_DETAIL, PGSQL_LB_GET_HWADDR6)
.arg(hwaddr.toText());
// Set up the WHERE clause value
PsqlBindArray bind_array;
// HWADDR
if (!hwaddr.hwaddr_.empty()) {
bind_array.add(hwaddr.hwaddr_);
} else {
bind_array.add("");
}
// Get the data
Lease6Collection result;
// Get a context
PgSqlLeaseContextAlloc get_context(*this);
PgSqlLeaseContextPtr ctx = get_context.ctx_;
getLeaseCollection(ctx, GET_LEASE6_HWADDR, bind_array, result);
return (result);
}
Lease6Collection
PgSqlLeaseMgr::getLeases6(Lease::Type lease_type, const DUID& duid,
uint32_t iaid) const {

View File

@ -319,6 +319,21 @@ public:
virtual Lease6Ptr getLease6(Lease::Type type,
const isc::asiolink::IOAddress& addr) const override;
/// @brief Returns existing IPv6 leases for specified hardware address.
///
/// Although in the usual case there will be only one lease, for mobile
/// clients or clients with multiple static/fixed/reserved leases there
/// can be more than one. Thus return type is a container, not a single
/// pointer.
///
/// @param hwaddr hardware address of the client
///
/// @return lease collection
///
/// @throw isc::db::DbOperationError An operation on the open database has
/// failed.
virtual Lease6Collection getLease6(const isc::dhcp::HWAddr& hwaddr) const override;
/// @brief Returns existing IPv6 leases for a given DUID+IA combination
///
/// Although in the usual case there will be only one lease, for mobile
@ -731,6 +746,7 @@ public:
GET_LEASE4_REMOTEID_QET, // Get page of leases by remote ID and query end time.
GET_LEASE6, // Get all IPv6 leases
GET_LEASE6_ADDR, // Get lease6 by address and type
GET_LEASE6_HWADDR, // Get lease6 by HW address
GET_LEASE6_DUID_IAID, // Get lease6 by DUID and IAID
GET_LEASE6_DUID_IAID_SUBID, // Get lease6 by DUID, IAID and subnet ID
GET_LEASE6_PAGE, // Get page of leases beginning with an address

View File

@ -873,6 +873,42 @@ TEST_F(PgSqlLeaseMgrTest, testLease6HWTypeAndSourceMultiThreading) {
testLease6HWTypeAndSource();
}
/// @brief Check GetLease6 methods - access by Hardware Address
TEST_F(PgSqlLeaseMgrTest, getLease6HWAddr1) {
testGetLease6HWAddr1();
}
/// @brief Check GetLease6 methods - access by Hardware Address
TEST_F(PgSqlLeaseMgrTest, getLease6HWAddr1MultiThreading) {
MultiThreadingTest mt(true);
testGetLease6HWAddr1();
}
/// @brief Check GetLease6 methods - access by Hardware Address
TEST_F(PgSqlLeaseMgrTest, getLease6HWAddr2) {
testGetLease6HWAddr2();
}
/// @brief Check GetLease6 methods - access by Hardware Address
TEST_F(PgSqlLeaseMgrTest, getLease6HWAddr2MultiThreading) {
MultiThreadingTest mt(true);
testGetLease6HWAddr2();
}
/// @brief Get lease6 by hardware address (2)
///
/// Check that the system can cope with getting a hardware address of
/// any size.
TEST_F(PgSqlLeaseMgrTest, getLease6HWAddrSize) {
testGetLease6HWAddrSize();
}
/// @brief Get lease6 by hardware address (2)
TEST_F(PgSqlLeaseMgrTest, getLease6HWAddrSizeMultiThreading) {
MultiThreadingTest mt(true);
testGetLease6HWAddrSize();
}
/// @brief Check that the expired DHCPv6 leases can be retrieved.
///
/// This test adds a number of leases to the lease database and marks

View File

@ -111,7 +111,8 @@ extern const isc::log::MessageID DHCPSRV_MEMFILE_GET_EXPIRED4 = "DHCPSRV_MEMFILE
extern const isc::log::MessageID DHCPSRV_MEMFILE_GET_EXPIRED6 = "DHCPSRV_MEMFILE_GET_EXPIRED6";
extern const isc::log::MessageID DHCPSRV_MEMFILE_GET_HOSTNAME4 = "DHCPSRV_MEMFILE_GET_HOSTNAME4";
extern const isc::log::MessageID DHCPSRV_MEMFILE_GET_HOSTNAME6 = "DHCPSRV_MEMFILE_GET_HOSTNAME6";
extern const isc::log::MessageID DHCPSRV_MEMFILE_GET_HWADDR = "DHCPSRV_MEMFILE_GET_HWADDR";
extern const isc::log::MessageID DHCPSRV_MEMFILE_GET_HWADDR4 = "DHCPSRV_MEMFILE_GET_HWADDR4";
extern const isc::log::MessageID DHCPSRV_MEMFILE_GET_HWADDR6 = "DHCPSRV_MEMFILE_GET_HWADDR6";
extern const isc::log::MessageID DHCPSRV_MEMFILE_GET_IAID_DUID = "DHCPSRV_MEMFILE_GET_IAID_DUID";
extern const isc::log::MessageID DHCPSRV_MEMFILE_GET_IAID_SUBID_DUID = "DHCPSRV_MEMFILE_GET_IAID_SUBID_DUID";
extern const isc::log::MessageID DHCPSRV_MEMFILE_GET_PAGE4 = "DHCPSRV_MEMFILE_GET_PAGE4";
@ -289,7 +290,8 @@ const char* values[] = {
"DHCPSRV_MEMFILE_GET_EXPIRED6", "obtaining maximum %1 of expired IPv6 leases",
"DHCPSRV_MEMFILE_GET_HOSTNAME4", "obtaining IPv4 leases for hostname %1",
"DHCPSRV_MEMFILE_GET_HOSTNAME6", "obtaining IPv6 leases for hostname %1",
"DHCPSRV_MEMFILE_GET_HWADDR", "obtaining IPv4 leases for hardware address %1",
"DHCPSRV_MEMFILE_GET_HWADDR4", "obtaining IPv4 leases for hardware address %1",
"DHCPSRV_MEMFILE_GET_HWADDR6", "obtaining IPv6 leases for hardware address %1",
"DHCPSRV_MEMFILE_GET_IAID_DUID", "obtaining IPv6 leases for IAID %1 and DUID %2 and lease type %3",
"DHCPSRV_MEMFILE_GET_IAID_SUBID_DUID", "obtaining IPv6 leases for IAID %1, Subnet ID %2, DUID %3 and lease type %4",
"DHCPSRV_MEMFILE_GET_PAGE4", "obtaining at most %1 IPv4 leases starting from address %2",

View File

@ -112,7 +112,8 @@ extern const isc::log::MessageID DHCPSRV_MEMFILE_GET_EXPIRED4;
extern const isc::log::MessageID DHCPSRV_MEMFILE_GET_EXPIRED6;
extern const isc::log::MessageID DHCPSRV_MEMFILE_GET_HOSTNAME4;
extern const isc::log::MessageID DHCPSRV_MEMFILE_GET_HOSTNAME6;
extern const isc::log::MessageID DHCPSRV_MEMFILE_GET_HWADDR;
extern const isc::log::MessageID DHCPSRV_MEMFILE_GET_HWADDR4;
extern const isc::log::MessageID DHCPSRV_MEMFILE_GET_HWADDR6;
extern const isc::log::MessageID DHCPSRV_MEMFILE_GET_IAID_DUID;
extern const isc::log::MessageID DHCPSRV_MEMFILE_GET_IAID_SUBID_DUID;
extern const isc::log::MessageID DHCPSRV_MEMFILE_GET_PAGE4;

View File

@ -633,12 +633,18 @@ A debug message issued when the server is attempting to obtain a set of
IPv6 leases from the memory file database for a client with the specified
hostname.
% DHCPSRV_MEMFILE_GET_HWADDR obtaining IPv4 leases for hardware address %1
% DHCPSRV_MEMFILE_GET_HWADDR4 obtaining IPv4 leases for hardware address %1
Logged at debug log level 50.
A debug message issued when the server is attempting to obtain a set of
IPv4 leases from the memory file database for a client with the specified
hardware address.
% DHCPSRV_MEMFILE_GET_HWADDR6 obtaining IPv6 leases for hardware address %1
Logged at debug log level 50.
A debug message issued when the server is attempting to obtain a set of
IPv6 leases from the memory file database for a client with the specified
hardware address.
% DHCPSRV_MEMFILE_GET_IAID_DUID obtaining IPv6 leases for IAID %1 and DUID %2 and lease type %3
Logged at debug log level 50.
A debug message issued when the server is attempting to obtain a set of IPv6

View File

@ -553,8 +553,8 @@ Lease6::toText() const {
<< "Pref life: " << lifetimeToText(preferred_lft_) << "\n"
<< "Valid life: " << lifetimeToText(valid_lft_) << "\n"
<< "Cltt: " << cltt_ << "\n"
<< "DUID: " << (duid_?duid_->toText():"(none)") << "\n"
<< "Hardware addr: " << (hwaddr_?hwaddr_->toText(false):"(none)") << "\n"
<< "DUID: " << (duid_ ? duid_->toText() : "(none)") << "\n"
<< "Hardware addr: " << (hwaddr_ ? hwaddr_->toText(false) : "(none)") << "\n"
<< "Subnet ID: " << subnet_id_ << "\n"
<< "Pool ID: " << pool_id_ << "\n"
<< "State: " << statesToText(state_) << "\n";

View File

@ -409,6 +409,18 @@ public:
virtual Lease6Ptr getLease6(Lease::Type type,
const isc::asiolink::IOAddress& addr) const = 0;
/// @brief Returns existing IPv6 leases for specified hardware address.
///
/// Although in the usual case there will be only one lease, for mobile
/// clients or clients with multiple static/fixed/reserved leases there
/// can be more than one. Thus return type is a container, not a single
/// pointer.
///
/// @param hwaddr hardware address of the client
///
/// @return lease collection
virtual Lease6Collection getLease6(const isc::dhcp::HWAddr& hwaddr) const = 0;
/// @brief Returns existing IPv6 leases for a given DUID+IA combination
///
/// Although in the usual case there will be only one lease, for mobile

View File

@ -1209,7 +1209,7 @@ Memfile_LeaseMgr::getLease4Internal(const HWAddr& hwaddr,
Lease4Collection
Memfile_LeaseMgr::getLease4(const HWAddr& hwaddr) const {
LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL,
DHCPSRV_MEMFILE_GET_HWADDR).arg(hwaddr.toText());
DHCPSRV_MEMFILE_GET_HWADDR4).arg(hwaddr.toText());
Lease4Collection collection;
if (MultiThreadingMgr::instance().getMode()) {
@ -1456,6 +1456,38 @@ Memfile_LeaseMgr::getLease6Internal(Lease::Type type,
}
}
void
Memfile_LeaseMgr::getLease6Internal(const HWAddr& hwaddr,
Lease6Collection& collection) const {
// Using composite index by 'hw address' and 'subnet id'. It is
// ok to use it for searching by the 'hw address' only.
const Lease6StorageHWAddressSubnetIdIndex& idx =
storage6_.get<HWAddressSubnetIdIndexTag>();
std::pair<Lease6StorageHWAddressSubnetIdIndex::const_iterator,
Lease6StorageHWAddressSubnetIdIndex::const_iterator> l
= idx.equal_range(boost::make_tuple(hwaddr.hwaddr_));
BOOST_FOREACH(auto const& lease, l) {
collection.push_back(Lease6Ptr(new Lease6(*lease)));
}
}
Lease6Collection
Memfile_LeaseMgr::getLease6(const HWAddr& hwaddr) const {
LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL,
DHCPSRV_MEMFILE_GET_HWADDR6).arg(hwaddr.toText());
Lease6Collection collection;
if (MultiThreadingMgr::instance().getMode()) {
std::lock_guard<std::mutex> lock(*mutex_);
getLease6Internal(hwaddr, collection);
} else {
getLease6Internal(hwaddr, collection);
}
return (collection);
}
Lease6Ptr
Memfile_LeaseMgr::getAnyLease6Internal(const isc::asiolink::IOAddress& addr) const {
Lease6Storage::iterator l = storage6_.find(addr);

View File

@ -295,6 +295,18 @@ public:
virtual Lease6Ptr getLease6(Lease::Type type,
const isc::asiolink::IOAddress& addr) const override;
/// @brief Returns existing IPv6 leases for specified hardware address.
///
/// Although in the usual case there will be only one lease, for mobile
/// clients or clients with multiple static/fixed/reserved leases there
/// can be more than one. Thus return type is a container, not a single
/// pointer.
///
/// @param hwaddr hardware address of the client
///
/// @return lease collection
virtual Lease6Collection getLease6(const isc::dhcp::HWAddr& hwaddr) const override;
/// @brief Returns existing IPv6 lease for a given DUID + IA + lease type
/// combination
///
@ -666,6 +678,13 @@ private:
Lease6Ptr getLease6Internal(Lease::Type type,
const isc::asiolink::IOAddress& addr) const;
/// @brief Gets existing IPv6 leases for specified hardware address.
///
/// @param hwaddr hardware address of the client
/// @param collection lease collection
void getLease6Internal(const isc::dhcp::HWAddr& hwaddr,
Lease6Collection& collection) const;
/// @brief Returns existing IPv6 lease of any type for a given IPv6 address.
///
/// @param addr An address of the searched lease.

View File

@ -174,6 +174,27 @@ typedef boost::multi_index_container<
// than derived class: Lease6.
boost::multi_index::member<Lease, uint32_t, &Lease::pool_id_>
>
>,
// Specification of the eight index starts here.
boost::multi_index::ordered_non_unique<
boost::multi_index::tag<HWAddressSubnetIdIndexTag>,
// This is a composite index that combines two attributes of the
// Lease6 object: hardware address and subnet id.
boost::multi_index::composite_key<
Lease6,
// The hardware address is held in the hwaddr_ member of the
// Lease4 object, which is a HWAddr object. Boost does not
// provide a key extractor for getting a member of a member,
// so we need a simple method for that.
boost::multi_index::const_mem_fun<Lease, const std::vector<uint8_t>&,
&Lease::getHWAddrVector>,
// The subnet id is held in the subnet_id_ member of Lease6
// class. Note that the subnet_id_ is defined in the base
// class (Lease) so we have to point to this class rather
// than derived class: Lease6.
boost::multi_index::member<Lease, SubnetID, &Lease::subnet_id_>
>
>
>
> Lease6Storage; // Specify the type name of this container.
@ -343,6 +364,10 @@ typedef Lease6Storage::index<DuidIaidTypeIndexTag>::type Lease6StorageDuidIaidTy
/// @brief DHCPv6 lease storage index by expiration time.
typedef Lease6Storage::index<ExpirationIndexTag>::type Lease6StorageExpirationIndex;
/// @brief DHCPv6 lease storage index by HW address and subnet-id.
typedef Lease6Storage::index<HWAddressSubnetIdIndexTag>::type
Lease6StorageHWAddressSubnetIdIndex;
/// @brief DHCPv6 lease storage index by subnet-id.
typedef Lease6Storage::index<SubnetIdIndexTag>::type Lease6StorageSubnetIdIndex;

View File

@ -1549,6 +1549,35 @@ TEST_F(MemfileLeaseMgrTest, testLease6MacMultiThread) {
testLease6MAC();
}
/// @brief Checks lease6 retrieval through HWAddr
TEST_F(MemfileLeaseMgrTest, getLease6HWAddr1) {
startBackend(V6);
testGetLease6HWAddr1();
}
/// @brief Checks lease6 retrieval through HWAddr
TEST_F(MemfileLeaseMgrTest, getLease6HWAddr1MultiThread) {
startBackend(V6);
MultiThreadingMgr::instance().setMode(true);
testGetLease6HWAddr1();
}
/// @brief Check GetLease6 methods - access by Hardware Address
///
/// Adds leases to the database and checks that they can be accessed via
/// a combination of DUID and IAID.
TEST_F(MemfileLeaseMgrTest, getLease6HWAddr2) {
startBackend(V6);
testGetLease6HWAddr2();
}
/// @brief Check GetLease6 methods - access by Hardware Address
TEST_F(MemfileLeaseMgrTest, getLease6HWAddr2MultiThread) {
startBackend(V6);
MultiThreadingMgr::instance().setMode(true);
testGetLease6HWAddr2();
}
/// @brief Check that memfile reports version correctly.
TEST_F(MemfileLeaseMgrTest, versionCheck) {
// Check that V4 backend reports versions correctly.

View File

@ -87,6 +87,11 @@ ConcreteLeaseMgr::getLease6(Lease::Type /* not used yet */,
return (Lease6Ptr());
}
Lease6Collection
ConcreteLeaseMgr::getLease6(const HWAddr&) const {
return (Lease6Collection());
}
Lease6Collection
ConcreteLeaseMgr::getLeases6(Lease::Type /* not used yet */,
const DUID&, uint32_t) const {

View File

@ -148,6 +148,18 @@ public:
virtual Lease6Ptr getLease6(Lease::Type /* not used yet */,
const isc::asiolink::IOAddress&) const override;
/// @brief Returns existing IPv6 leases for specified hardware address.
///
/// Although in the usual case there will be only one lease, for mobile
/// clients or clients with multiple static/fixed/reserved leases there
/// can be more than one. Thus return type is a container, not a single
/// pointer.
///
/// @param hwaddr hardware address of the client
///
/// @return lease collection
virtual Lease6Collection getLease6(const HWAddr&) const override;
/// @brief Returns existing IPv6 lease for a given DUID+IA combination
///
/// @param duid ignored

View File

@ -229,6 +229,7 @@ GenericLeaseMgrTest::initializeLease6(std::string address) {
// Set other parameters. For historical reasons, address 0 is not used.
if (address == straddress6_[0]) {
lease->hwaddr_.reset(new HWAddr(vector<uint8_t>(6, 0x08), HTYPE_ETHER));
lease->type_ = leasetype6_[0];
lease->prefixlen_ = 128;
lease->iaid_ = 142;
@ -243,6 +244,7 @@ GenericLeaseMgrTest::initializeLease6(std::string address) {
lease->hostname_ = "myhost.example.com.";
} else if (address == straddress6_[1]) {
lease->hwaddr_.reset(new HWAddr(vector<uint8_t>(6, 0x19), HTYPE_ETHER));
lease->type_ = leasetype6_[1];
lease->prefixlen_ = 128;
lease->iaid_ = 42;
@ -258,6 +260,7 @@ GenericLeaseMgrTest::initializeLease6(std::string address) {
lease->pool_id_ = 7;
} else if (address == straddress6_[2]) {
lease->hwaddr_.reset(new HWAddr(vector<uint8_t>(6, 0x2a), HTYPE_ETHER));
lease->type_ = leasetype6_[2];
lease->prefixlen_ = 48;
lease->iaid_ = 89;
@ -272,6 +275,8 @@ GenericLeaseMgrTest::initializeLease6(std::string address) {
lease->hostname_ = "myhost.example.com.";
} else if (address == straddress6_[3]) {
// Hardware address same as lease 1.
lease->hwaddr_.reset(new HWAddr(vector<uint8_t>(6, 0x19), HTYPE_ETHER));
lease->type_ = leasetype6_[3];
lease->prefixlen_ = 128;
lease->iaid_ = 0xfffffffe;
@ -295,6 +300,7 @@ GenericLeaseMgrTest::initializeLease6(std::string address) {
lease->hostname_ = "myhost.example.com.";
} else if (address == straddress6_[4]) {
lease->hwaddr_.reset(new HWAddr(vector<uint8_t>(6, 0x4c), HTYPE_ETHER));
// Same DUID and IAID as straddress6_1
lease->type_ = leasetype6_[4];
lease->prefixlen_ = 128;
@ -310,6 +316,8 @@ GenericLeaseMgrTest::initializeLease6(std::string address) {
lease->hostname_ = "otherhost.example.com.";
} else if (address == straddress6_[5]) {
// Same as lease 1
lease->hwaddr_.reset(new HWAddr(vector<uint8_t>(6, 0x19), HTYPE_ETHER));
// Same DUID and IAID as straddress6_1
lease->type_ = leasetype6_[5];
lease->prefixlen_ = 56;
@ -327,6 +335,7 @@ GenericLeaseMgrTest::initializeLease6(std::string address) {
lease->setContext(Element::fromJSON("{ \"foo\": true }"));
} else if (address == straddress6_[6]) {
lease->hwaddr_.reset(new HWAddr(vector<uint8_t>(6, 0x6e), HTYPE_ETHER));
// Same DUID as straddress6_1
lease->type_ = leasetype6_[6];
lease->prefixlen_ = 128;
@ -343,6 +352,7 @@ GenericLeaseMgrTest::initializeLease6(std::string address) {
lease->hostname_ = "hostname.example.com.";
} else if (address == straddress6_[7]) {
lease->hwaddr_.reset(new HWAddr(vector<uint8_t>(), HTYPE_ETHER)); // Empty
// Same IAID as straddress6_1
lease->type_ = leasetype6_[7];
lease->prefixlen_ = 128;
@ -606,8 +616,9 @@ GenericLeaseMgrTest::testGetLease4HWAddr2() {
detailCompareLease(leases[7], *returned.begin());
// Try to get something with invalid hardware address
vector<uint8_t> invalid(6, 0);
returned = lmptr_->getLease4(invalid);
HWAddr hwaddr(vector<uint8_t>(6, 0x80), HTYPE_ETHER);
hwaddr.hwaddr_ = vector<uint8_t>(6, 0);
returned = lmptr_->getLease4(hwaddr);
EXPECT_EQ(0, returned.size());
}
@ -1008,6 +1019,77 @@ GenericLeaseMgrTest::testLease6HWTypeAndSource() {
EXPECT_FALSE(stored3->hwaddr_);
}
void
GenericLeaseMgrTest::testGetLease6HWAddr1() {
// Let's initialize two different leases 6 and just add the first ...
Lease6Ptr leaseA = initializeLease6(straddress6_[5]);
HWAddr hwaddrA(*leaseA->hwaddr_);
HWAddr hwaddrB(vector<uint8_t>(6, 0x80), HTYPE_ETHER);
EXPECT_TRUE(lmptr_->addLease(leaseA));
// we should not have a lease, with this HWAddr
Lease6Collection returned = lmptr_->getLease6(hwaddrB);
ASSERT_EQ(0, returned.size());
// But with this one
returned = lmptr_->getLease6(hwaddrA);
ASSERT_EQ(1, returned.size());
}
void
GenericLeaseMgrTest::testGetLease6HWAddr2() {
// Get the leases to be used for the test and add to the database
vector<Lease6Ptr> leases = createLeases6();
for (size_t i = 0; i < leases.size(); ++i) {
EXPECT_TRUE(lmptr_->addLease(leases[i]));
}
// Get the leases matching the hardware address of lease 1
HWAddr tmp(*leases[1]->hwaddr_);
Lease6Collection returned = lmptr_->getLease6(tmp);
// Should be three leases, matching leases[1], [3] and [5].
ASSERT_EQ(3, returned.size());
// Check the lease[5] (and only this one) has an user context.
size_t contexts = 0;
for (auto const& i : returned) {
if (i->getContext()) {
++contexts;
EXPECT_EQ("{ \"foo\": true }", i->getContext()->str());
}
}
EXPECT_EQ(1, contexts);
// Easiest way to check is to look at the addresses.
vector<string> addresses;
for (auto const& i : returned) {
addresses.push_back(i->addr_.toText());
}
sort(addresses.begin(), addresses.end());
EXPECT_EQ(straddress6_[1], addresses[0]);
EXPECT_EQ(straddress6_[3], addresses[1]);
EXPECT_EQ(straddress6_[5], addresses[2]);
// Repeat test with just one expected match
returned = lmptr_->getLease6(*leases[2]->hwaddr_);
ASSERT_EQ(1, returned.size());
detailCompareLease(leases[2], *returned.begin());
// Check that an empty vector is valid
EXPECT_TRUE(leases[7]->hwaddr_->hwaddr_.empty());
returned = lmptr_->getLease6(*leases[7]->hwaddr_);
ASSERT_EQ(1, returned.size());
detailCompareLease(leases[7], *returned.begin());
// Try to get something with invalid hardware address
HWAddr hwaddr(vector<uint8_t>(6, 0x80), HTYPE_ETHER);
hwaddr.hwaddr_ = vector<uint8_t>(6, 0);
returned = lmptr_->getLease6(hwaddr);
EXPECT_EQ(0, returned.size());
}
void
GenericLeaseMgrTest::testLease4InvalidHostname() {
// Get the leases to be used for the test.
@ -1077,6 +1159,29 @@ GenericLeaseMgrTest::testGetLease4HWAddrSize() {
EXPECT_THROW(lmptr_->addLease(leases[1]), isc::db::DbOperationError);
}
void
GenericLeaseMgrTest::testGetLease6HWAddrSize() {
// Create leases, although we need only one.
vector<Lease6Ptr> leases = createLeases6();
// Now add leases with increasing hardware address size.
for (uint8_t i = 0; i <= HWAddr::MAX_HWADDR_LEN; ++i) {
leases[1]->hwaddr_->hwaddr_.resize(i, i);
EXPECT_TRUE(lmptr_->addLease(leases[1]));
Lease6Collection returned =
lmptr_->getLease6(*leases[1]->hwaddr_);
ASSERT_EQ(1, returned.size());
detailCompareLease(leases[1], *returned.begin());
ASSERT_TRUE(lmptr_->deleteLease(leases[1]));
}
// Database should not let us add one that is too big
// (The 42 is a random value put in each byte of the address.)
leases[1]->hwaddr_->hwaddr_.resize(HWAddr::MAX_HWADDR_LEN + 100, 42);
EXPECT_THROW(lmptr_->addLease(leases[1]), isc::db::DbOperationError);
}
void
GenericLeaseMgrTest::testGetLease4HWAddrSubnetId() {
// Get the leases to be used for the test and add to the database

View File

@ -314,6 +314,21 @@ public:
/// @brief Checks that Lease6 stores hardware type and hardware source.
void testLease6HWTypeAndSource();
/// @brief Test lease retrieval using HW address.
void testGetLease6HWAddr1();
/// @brief Check GetLease4 methods - access by Hardware Address
///
/// Adds leases to the database and checks that they can be accessed using
/// HWAddr information.
void testGetLease6HWAddr2();
/// @brief Get lease4 by hardware address (2)
///
/// Check that the system can cope with getting a hardware address of
/// any size.
void testGetLease6HWAddrSize();
/// @brief Test that IPv6 lease can be added, retrieved and deleted.
void testAddGetDelete6();

View File

@ -0,0 +1,51 @@
{
"access": "read",
"avail": "3.1.1",
"brief": [
"This command retrieves all IPv6 leases with the specified hardware address."
],
"cmd-syntax": [
"{",
" \"command\": \"lease6-get-by-hw-address\",",
" \"arguments\": {",
" \"hw-address\": \"00:0c:01:02:03:04\"",
" }",
"}"
],
"description": "See <xref linkend=\"command-lease6-get-by-hw-address\"/>",
"hook": "lease_cmds",
"name": "lease6-get-by-hw-address",
"resp-comment": [
"Result 0 is returned when at least one lease is found, 1 when parameters are malformed or missing,",
"3 is returned if no leases are found."
],
"resp-syntax": [
" {",
" \"arguments\": {",
" \"leases\": [",
" {",
" \"cltt\": 1600439560,",
" \"duid\": \"00:01:00:01:26:f7:81:88:00:0c:01:02:03:04\",",
" \"fqdn-fwd\": false,",
" \"fqdn-rev\": false,",
" \"hostname\": \"foobar.example.org\",",
" \"hw-address\": \"00:0c:01:02:03:04\",",
" \"iaid\": 1,",
" \"ip-address\": \"2001:db8:1::\",",
" \"preferred-lft\": 3000,",
" \"state\": 0,",
" \"subnet-id\": 1,",
" \"type\": \"IA_NA\",",
" \"valid-lft\": 4000",
" }",
" ]",
" },",
" \"result\": 0,",
" \"text\": \"1 IPv6 lease(s) found.\"",
" }"
],
"support": [
"kea-dhcp6"
]
}