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
- :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``.
.. 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:
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
///
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)) {
HWAddr hwaddr = HWAddr::fromText(hw_address->stringValue());
- 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);
+
+ if (v4) {
+ Lease4Collection leases =
+ LeaseMgrFactory::instance().getLease4(hwaddr);
+ 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 =
- @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)
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": {
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
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);
/// @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
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) {
/// @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();
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)
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() {
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() {
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() {
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() {
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() {
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 {
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 =
// 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() {
// 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() {
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();
}
"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",
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);
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);
}
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"),
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";
"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",
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;
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
"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, "
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
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 {
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
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
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
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";
"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",
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;
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
"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",
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
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 {
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
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
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
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";
"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",
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;
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
<< "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";
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
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()) {
}
}
+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);
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
///
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.
// 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.
/// @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;
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.
return (Lease6Ptr());
}
+Lease6Collection
+ConcreteLeaseMgr::getLease6(const HWAddr&) const {
+ return (Lease6Collection());
+}
+
Lease6Collection
ConcreteLeaseMgr::getLeases6(Lease::Type /* not used yet */,
const DUID&, uint32_t) const {
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
// 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;
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;
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;
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;
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;
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;
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;
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;
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());
}
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.
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
/// @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();
--- /dev/null
+{
+ "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"
+ ]
+}