From cf00a00b681d4620574e88a1c2e00eae069fc659 Mon Sep 17 00:00:00 2001 From: Marcin Siodelski Date: Mon, 23 Oct 2017 12:10:21 +0200 Subject: [PATCH] [5395] Support retrieving leases and deleting leases by client identifier. --- src/hooks/dhcp/lease_cmds/lease_cmds.cc | 58 ++++++++--- .../lease_cmds/tests/lease_cmds_unittest.cc | 95 ++++++++++++++++++- 2 files changed, 139 insertions(+), 14 deletions(-) diff --git a/src/hooks/dhcp/lease_cmds/lease_cmds.cc b/src/hooks/dhcp/lease_cmds/lease_cmds.cc index 745b74b15a..a5d3f25fb7 100644 --- a/src/hooks/dhcp/lease_cmds/lease_cmds.cc +++ b/src/hooks/dhcp/lease_cmds/lease_cmds.cc @@ -39,24 +39,17 @@ namespace lease_cmds { /// @brief Wrapper class around reservation command handlers. class LeaseCmdsImpl : private CmdsImpl { public: - /// @brief Parameters specified for reservation-get and reservation-del - /// - /// As both call types (get and delete) need specify which reservation to - /// act on, they have the same set of parameters. In particular, those - /// two call types support the following sets of parameters: - /// - address - /// - subnet-id, identifier-type, identifier-value (v4) - /// - subnet-id, lease-type, iaid, identifier-type, identifier-value (v6) - /// - /// This class stores those parameters and is used to pass them around. + + /// @brief Parameters specified for lease commands. class Parameters { public: /// @brief specifies type of query (by IP addr, by hwaddr, by DUID) typedef enum { - TYPE_ADDR, ///< query by IP address (either v4 or v6) - TYPE_HWADDR, ///< query by hardware address (v4 only) - TYPE_DUID ///< query by DUID (v6 only) + TYPE_ADDR, ///< query by IP address (either v4 or v6) + TYPE_HWADDR, ///< query by hardware address (v4 only) + TYPE_DUID, ///< query by DUID (v6 only) + TYPE_CLIENT_ID ///< query by client identifier (v4 only). } Type; /// @brief Specifies subnet-id (always used) @@ -71,6 +64,9 @@ public: /// @brief Specifies identifier value (used when query_type is TYPE_DUID) isc::dhcp::DuidPtr duid; + /// @brief Specifies identifier value (used when query_type is TYPE_CLIENT_ID) + isc::dhcp::ClientIdPtr client_id; + /// @brief Attempts to covert text to one of specified types /// /// Supported values are: "address", hw-address and duid. @@ -85,6 +81,8 @@ public: return (Parameters::TYPE_HWADDR); } else if (txt == "duid") { return (Parameters::TYPE_DUID); + } else if (txt == "client-id") { + return (Parameters::TYPE_CLIENT_ID); } else { isc_throw(BadValue, "Incorrect identifier type: " << txt << ", the only supported values are: " @@ -345,6 +343,10 @@ LeaseCmdsImpl::getParameters(bool v6, const ConstElementPtr& params) { x.hwaddr = HWAddrPtr(new HWAddr(hw)); break; } + case Parameters::TYPE_CLIENT_ID: { + x.client_id = ClientId::fromText(ident->stringValue()); + break; + } case Parameters::TYPE_DUID: { DUID duid = DUID::fromText(ident->stringValue()); x.duid = DuidPtr(new DUID(duid)); @@ -411,6 +413,19 @@ LeaseCmdsImpl::leaseGetHandler(CalloutHandle& handle) { } break; + case Parameters::TYPE_CLIENT_ID: + if (v4) { + if (!p.client_id) { + isc_throw(InvalidParameter, "Program error: Query by client-id " + "requires client-id to be specified"); + } + + lease4 = LeaseMgrFactory::instance().getLease4(*p.client_id, p.subnet_id); + } else { + isc_throw(isc::InvalidParameter, "Query by client-id is not allowed in v6."); + } + break; + default: { isc_throw(InvalidOperation, "Unknown query type: " << static_cast(p.query_type)); break; @@ -473,6 +488,23 @@ LeaseCmdsImpl::lease4DelHandler(CalloutHandle& handle) { addr = lease4->addr_; break; + case Parameters::TYPE_CLIENT_ID: + if (!p.client_id) { + isc_throw(InvalidParameter, "Program error: Query by client-id " + "requires client-id to be specified"); + } + + // Let's see if there's such a lease at all. + lease4 = LeaseMgrFactory::instance().getLease4(*p.client_id, p.subnet_id); + if (!lease4) { + setErrorResponse(handle, "IPv4 lease not found.", CONTROL_RESULT_EMPTY); + return (0); + } + + // Found it, can use it as is. + addr = lease4->addr_; + break; + case Parameters::TYPE_DUID: isc_throw(InvalidParameter, "Delete by duid is not allowed in v4."); break; diff --git a/src/hooks/dhcp/lease_cmds/tests/lease_cmds_unittest.cc b/src/hooks/dhcp/lease_cmds/tests/lease_cmds_unittest.cc index 97aee68c51..1d0584b86e 100644 --- a/src/hooks/dhcp/lease_cmds/tests/lease_cmds_unittest.cc +++ b/src/hooks/dhcp/lease_cmds/tests/lease_cmds_unittest.cc @@ -1047,7 +1047,7 @@ TEST_F(LeaseCmdsTest, Lease4GetByAddr) { ASSERT_TRUE(lease); // Let's check if the response makes any sense. - checkLease4(lease, "192.0.2.1", 44, "08:08:08:08:08:08", false); + checkLease4(lease, "192.0.2.1", 44, "08:08:08:08:08:08", true); } // Checks that lease4-get can handle a situation when the query is @@ -1122,6 +1122,53 @@ TEST_F(LeaseCmdsTest, Lease6GetByAddr6NotFound) { testCommand(cmd, CONTROL_RESULT_EMPTY, exp_rsp); } +// Checks that lease4-get can handle a situation when the query is +// well formed, but the lease is not there. +TEST_F(LeaseCmdsTest, Lease4GetByClientIdNotFound) { + + // Initialize lease manager (false = v4, false = don't add a lease) + initLeaseMgr(false, false); + + // No such lease. + string cmd = + "{\n" + " \"command\": \"lease4-get\",\n" + " \"arguments\": {" + " \"identifier-type\": \"client-id\"," + " \"identifier\": \"01:02:03:04\"," + " \"subnet-id\": 44" + " }\n" + "}"; + string exp_rsp = "Lease not found."; + ConstElementPtr rsp = testCommand(cmd, CONTROL_RESULT_EMPTY, exp_rsp); +} + +// Check that lease4-get can find a lease by client identifier. +TEST_F(LeaseCmdsTest, Lease4GetByClientId) { + // Initialize lease manager (false = v4, true = add a lease) + initLeaseMgr(false, true); + + string cmd = + "{\n" + " \"command\": \"lease4-get\",\n" + " \"arguments\": {" + " \"identifier-type\": \"client-id\"," + " \"identifier\": \"42:42:42:42:42:42:42:42\"," + " \"subnet-id\": 44" + " }\n" + "}"; + string exp_rsp = "IPv4 lease found."; + ConstElementPtr rsp = testCommand(cmd, CONTROL_RESULT_SUCCESS, exp_rsp); + + // Now check that the lease parameters were indeed returned. + ASSERT_TRUE(rsp); + ConstElementPtr lease = rsp->get("arguments"); + ASSERT_TRUE(lease); + + // Let's check if the response makes any sense. + checkLease4(lease, "192.0.2.1", 44, "08:08:08:08:08:08", false); +} + // Checks that lease6-get(subnet-id, addr) can handle a situation when // the query is correctly formed, but the lease is not there. TEST_F(LeaseCmdsTest, Lease6GetByDuidNotFound) { @@ -1794,6 +1841,52 @@ TEST_F(LeaseCmdsTest, Lease4DelByHWAddr) { EXPECT_FALSE(lmptr_->getLease4(IOAddress("192.0.2.1"))); } +// Checks that lease4-del can handle a situation when the query is +// well formed, but the lease is not there. +TEST_F(LeaseCmdsTest, Lease4DelByClientIdNotFound) { + + // Initialize lease manager (false = v4, true = add a lease) + initLeaseMgr(false, true); + + // No such lease. + string cmd = + "{\n" + " \"command\": \"lease4-del\",\n" + " \"arguments\": {" + " \"identifier-type\": \"client-id\"," + " \"identifier\": \"01:02:03:04\"," + " \"subnet-id\": 44" + " }\n" + "}"; + string exp_rsp = "IPv4 lease not found."; + ConstElementPtr rsp = testCommand(cmd, CONTROL_RESULT_EMPTY, exp_rsp); + + // Make sure the lease is still there. + EXPECT_TRUE(lmptr_->getLease4(IOAddress("192.0.2.1"))); +} + +// Checks that lease4-del can find and delete a lease by client identifier. +TEST_F(LeaseCmdsTest, Lease4DelByClientId) { + // Initialize lease manager (false = v4, true = add a lease) + initLeaseMgr(false, true); + + // Invalid + string cmd = + "{\n" + " \"command\": \"lease4-del\",\n" + " \"arguments\": {" + " \"identifier-type\": \"client-id\"," + " \"identifier\": \"42:42:42:42:42:42:42:42\"," + " \"subnet-id\": 44" + " }\n" + "}"; + string exp_rsp = "IPv4 lease deleted."; + ConstElementPtr rsp = testCommand(cmd, CONTROL_RESULT_SUCCESS, exp_rsp); + + // Make sure the lease is really gone. + EXPECT_FALSE(lmptr_->getLease4(IOAddress("192.0.2.1"))); +} + // Checks that lease6-del(addr) can handle a situation when // the query is correctly formed, but the lease is not there. TEST_F(LeaseCmdsTest, Lease6DelByAddr6NotFound) { -- 2.47.2