From: Tomek Mrugalski Date: Fri, 4 Aug 2017 17:37:10 +0000 (+0200) Subject: [5280] leaseX-update, leaseX-del implemented. X-Git-Tag: trac5124a_base~18 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=d1be21aa573beea83624dc42e6267b28d7ad4d8e;p=thirdparty%2Fkea.git [5280] leaseX-update, leaseX-del implemented. --- diff --git a/src/hooks/dhcp/lease_cmds/lease_cmds.cc b/src/hooks/dhcp/lease_cmds/lease_cmds.cc index d28feb37c9..d6742a39b1 100644 --- a/src/hooks/dhcp/lease_cmds/lease_cmds.cc +++ b/src/hooks/dhcp/lease_cmds/lease_cmds.cc @@ -240,15 +240,13 @@ private: static ConstElementPtr leaseGetHandler(const string& command, ConstElementPtr args); - /// @brief lease4-del, lease6-del command handler + /// @brief lease4-del command handler /// - /// This command attempts to delete a lease that match selected criteria. - /// The following types of parameters are supported: - /// - (subnet-id, address) for both v4 and v6 - /// - (subnet-id, identifier-type, identifier) for v4 - /// - (subnet-id, type, iana, identifier-type, identifier) for v6 + /// This command attempts to delete an IPv4 lease that match selected + /// criteria. Two types of parameters are supported: (subnet-id, address) or + /// (subnet-id, identifier-type, identifier). /// - /// Example command for command by (subnet-id, address): + /// Example command for deletion by (subnet-id, address): /// { /// "command": "lease4-del", /// "arguments": { @@ -257,7 +255,7 @@ private: /// } /// } /// - /// Example command for query by (subnet-id, identifier-type, identifier) + /// Example command for deletion by (subnet-id, identifier-type, identifier) /// { /// "command": "lease4-del", /// "arguments": { @@ -265,33 +263,58 @@ private: /// "identifier-type": "hw-address", /// "identifier": "00:01:02:03:04:05" /// } - /// } + /// }"; + /// @param command should be 'lease4-del' (but it's ignored) + /// @param args must contain host reservation definition. + /// @return result of the operation (host will be included as parameters, if found) + static ConstElementPtr + lease4DelHandler(const string& command, ConstElementPtr args); + + /// @brief lease6-del command handler /// - /// Example command for query by (subnet-id, type, iana, identifier-type, - /// identifier): + /// This command attempts to delete a lease that match selected criteria. + /// Two types of parameters are supported: (subnet-id, address) or + /// (subnet-id, type, iaid, identifier-type, identifier). + /// + /// Example command for deletion by (subnet-id, address): /// { /// "command": "lease6-del", /// "arguments": { - /// "subnet-id": 66, - /// "iaid": 42, - /// "type": "IA_NA", - /// "identifier-type": "duid", - /// "identifier": "77:77:77:77:77:77:77:77" + /// "subnet-id": 1, + /// "ip-address": "192.0.2.202" /// } /// } - /// @param command 'lease4-del' or 'lease6-del' - /// @param args must contain lease parameters - /// @return result of the operation + /// + /// Example command for deletion by (subnet-id, type, iaid, identifier-type, + /// identifier): + /// { + /// "command": "lease6-del", + /// "arguments": { + /// "subnet-id": 1, + /// "type": "IA_NA", + /// "iaid": 123456, + /// "identifier-type": "hw-address", + /// "identifier": "00:01:02:03:04:05" + /// } + /// }"; + /// @param command should be 'lease6-del' (but it's ignored) + /// @param args must contain host reservation definition. + /// @return result of the operation (host will be included as parameters, if found) static ConstElementPtr - leaseDelHandler(const string& command, ConstElementPtr args); + lease6DelHandler(const string& command, ConstElementPtr args); - /// @brief Not implemented yet. static ConstElementPtr - leaseUpdateHandler(const string& command, ConstElementPtr args); + lease4UpdateHandler(const string& command, ConstElementPtr args); /// @brief Not implemented yet. static ConstElementPtr - leaseWipeHandler(const string& command, ConstElementPtr args); + lease6UpdateHandler(const string& command, ConstElementPtr args); + + static ConstElementPtr + lease4WipeHandler(const string& command, ConstElementPtr args); + + static ConstElementPtr + lease6WipeHandler(const string& command, ConstElementPtr args); /// @brief Extracts parameters required for reservation-get and reservation-del /// @@ -326,19 +349,19 @@ void LeaseCmdsImpl::registerCommands() { boost::bind(&LeaseCmdsImpl::leaseGetHandler, _1, _2)); CommandMgr::instance().registerCommand("lease4-del", - boost::bind(&LeaseCmdsImpl::leaseDelHandler, _1, _2)); + boost::bind(&LeaseCmdsImpl::lease4DelHandler, _1, _2)); CommandMgr::instance().registerCommand("lease6-del", - boost::bind(&LeaseCmdsImpl::leaseDelHandler, _1, _2)); + boost::bind(&LeaseCmdsImpl::lease6DelHandler, _1, _2)); CommandMgr::instance().registerCommand("lease4-update", - boost::bind(&LeaseCmdsImpl::leaseUpdateHandler, _1, _2)); + boost::bind(&LeaseCmdsImpl::lease4UpdateHandler, _1, _2)); CommandMgr::instance().registerCommand("lease6-update", - boost::bind(&LeaseCmdsImpl::leaseUpdateHandler, _1, _2)); + boost::bind(&LeaseCmdsImpl::lease6UpdateHandler, _1, _2)); CommandMgr::instance().registerCommand("lease4-del-all", - boost::bind(&LeaseCmdsImpl::leaseWipeHandler, _1, _2)); + boost::bind(&LeaseCmdsImpl::lease4WipeHandler, _1, _2)); CommandMgr::instance().registerCommand("lease6-del-all", - boost::bind(&LeaseCmdsImpl::leaseWipeHandler, _1, _2)); + boost::bind(&LeaseCmdsImpl::lease6WipeHandler, _1, _2)); } void LeaseCmdsImpl::deregisterCommands() { @@ -579,17 +602,186 @@ LeaseCmdsImpl::leaseGetHandler(const std::string& name, ConstElementPtr params) } ConstElementPtr -LeaseCmdsImpl::leaseDelHandler(const std::string& cmd, ConstElementPtr args) { - return (createAnswer(CONTROL_RESULT_ERROR, "not implemented yet.")); +LeaseCmdsImpl::lease4DelHandler(const std::string& , ConstElementPtr params) { + Parameters p; + Lease4Ptr lease4; + IOAddress addr(IOAddress::IPV4_ZERO_ADDRESS()); + try { + p = getParameters(params); + + switch (p.query_type) { + case Parameters::TYPE_ADDR: { + + // If address was specified explicitly, let's use it as is. + addr = p.addr; + break; + } + case Parameters::TYPE_HWADDR: + if (!p.hwaddr) { + return (createAnswer(CONTROL_RESULT_ERROR, + "Program error: Query by hw-address " + "requires hwaddr to be specified")); + } + + // Let's see if there's such a lease at all. + lease4 = LeaseMgrFactory::instance().getLease4(*p.hwaddr, p.subnet_id); + if (!lease4) { + return (createAnswer(CONTROL_RESULT_EMPTY, "IPv4 lease not found.")); + } + + // Found it, can use it as is. + addr = lease4->addr_; + break; + + case Parameters::TYPE_DUID: + return (createAnswer(CONTROL_RESULT_ERROR, + "Delete by duid is not allowed in v4.")); + break; + + default: { + stringstream tmp; + tmp << "Unknown query type: " << static_cast(p.query_type); + return (createAnswer(CONTROL_RESULT_ERROR, tmp.str())); + } + } + + if (LeaseMgrFactory::instance().deleteLease(addr)) { + return (createAnswer(CONTROL_RESULT_SUCCESS, "IPv4 lease deleted.")); + } else { + return (createAnswer(CONTROL_RESULT_EMPTY, "IPv4 lease not found.")); + } + } catch (const std::exception& ex) { + return (createAnswer(CONTROL_RESULT_ERROR, ex.what())); + } +} + +ConstElementPtr +LeaseCmdsImpl::lease6DelHandler(const std::string& , ConstElementPtr params) { + Parameters p; + Lease6Ptr lease6; + IOAddress addr(IOAddress::IPV6_ZERO_ADDRESS()); + try { + p = getParameters(params); + + switch (p.query_type) { + case Parameters::TYPE_ADDR: { + + // If address was specified explicitly, let's use it as is. + addr = p.addr; + break; + } + case Parameters::TYPE_HWADDR: + return (createAnswer(CONTROL_RESULT_ERROR, + "Delete by hw-address is not allowed in v6.")); + + case Parameters::TYPE_DUID: + if (!p.duid) { + return (createAnswer(CONTROL_RESULT_ERROR, + "Program error: Query by duid " + "requires duid to be specified")); + } + + // Let's see if there's such a lease at all. + lease6 = LeaseMgrFactory::instance().getLease6(p.lease_type, *p.duid, + p.iaid, p.subnet_id); + if (!lease6) { + return (createAnswer(CONTROL_RESULT_EMPTY, "IPv6 lease not found.")); + } + + // Found it, can use it as is. + addr = lease6->addr_; + break; + + default: { + stringstream tmp; + tmp << "Unknown query type: " << static_cast(p.query_type); + return (createAnswer(CONTROL_RESULT_ERROR, tmp.str())); + } + } + + if (LeaseMgrFactory::instance().deleteLease(addr)) { + return (createAnswer(CONTROL_RESULT_SUCCESS, "IPv6 lease deleted.")); + } else { + return (createAnswer(CONTROL_RESULT_EMPTY, "IPv6 lease not found.")); + } + } catch (const std::exception& ex) { + return (createAnswer(CONTROL_RESULT_ERROR, ex.what())); + } +} + +ConstElementPtr +LeaseCmdsImpl::lease4UpdateHandler(const string& , ConstElementPtr params) { + try { + + // We need the lease to be specified. + if (!params) { + isc_throw(isc::BadValue, "no parameters specified for lease4-update command"); + } + + // Get the parameters specified by the user first. + ConstSrvConfigPtr config = CfgMgr::instance().getCurrentCfg(); + Lease4Ptr lease4; + Lease4Parser parser; + // The parser does sanity checks (if the address is in scope, if + // subnet-id is valid, etc) + lease4 = parser.parse(config, params); + + // Ok, now check if there is a lease to be updated. + Lease4Ptr existing = LeaseMgrFactory::instance().getLease4(lease4->addr_); + if (!existing) { + stringstream tmp; + tmp << "There is no lease for address " << lease4->addr_ << ", can't update."; + return (createAnswer(CONTROL_RESULT_EMPTY, tmp.str())); + } + + LeaseMgrFactory::instance().updateLease4(lease4); + return (createAnswer(CONTROL_RESULT_SUCCESS, "IPv4 lease updated.")); + + } catch (const std::exception& ex) { + return (createAnswer(CONTROL_RESULT_ERROR, ex.what())); + } +} + +ConstElementPtr +LeaseCmdsImpl::lease6UpdateHandler(const string& , ConstElementPtr params) { + try { + // We need the lease to be specified. + if (!params) { + isc_throw(isc::BadValue, "no parameters specified for lease6-update command"); + } + + // Get the parameters specified by the user first. + ConstSrvConfigPtr config = CfgMgr::instance().getCurrentCfg(); + Lease6Ptr lease6; + Lease6Parser parser; + // The parser does sanity checks (if the address is in scope, if + // subnet-id is valid, etc) + lease6 = parser.parse(config, params); + + // Ok, now check if there is a lease to be updated. + Lease6Ptr existing = LeaseMgrFactory::instance().getLease6(lease6->type_, + lease6->addr_); + if (!existing) { + stringstream tmp; + tmp << "There is no lease for address " << lease6->addr_ << ", can't update."; + return (createAnswer(CONTROL_RESULT_EMPTY, tmp.str())); + } + + LeaseMgrFactory::instance().updateLease6(lease6); + return (createAnswer(CONTROL_RESULT_SUCCESS, "IPv6 lease updated.")); + + } catch (const std::exception& ex) { + return (createAnswer(CONTROL_RESULT_ERROR, ex.what())); + } } ConstElementPtr -LeaseCmdsImpl::leaseUpdateHandler(const string& cmd, ConstElementPtr args) { +LeaseCmdsImpl::lease4WipeHandler(const string& cmd, ConstElementPtr args) { return (createAnswer(CONTROL_RESULT_ERROR, "not implemented yet.")); } ConstElementPtr -LeaseCmdsImpl::leaseWipeHandler(const string& cmd, ConstElementPtr args) { +LeaseCmdsImpl::lease6WipeHandler(const string& cmd, ConstElementPtr args) { return (createAnswer(CONTROL_RESULT_ERROR, "not implemented yet.")); } 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 64d35ce8ec..b91b2128c9 100644 --- a/src/hooks/dhcp/lease_cmds/tests/lease_cmds_unittest.cc +++ b/src/hooks/dhcp/lease_cmds/tests/lease_cmds_unittest.cc @@ -947,7 +947,7 @@ TEST_F(LeaseCmdsTest, Lease4GetMissingParams) { // valid, but the lease is not there. TEST_F(LeaseCmdsTest, Lease4GetByAddrNotFound) { - // Initialize lease manager (false = v4, true = add lease) + // Initialize lease manager (false = v4, true = add a lease) initLeaseMgr(false, true); // Invalid @@ -966,7 +966,7 @@ TEST_F(LeaseCmdsTest, Lease4GetByAddrNotFound) { // Checks that lease4-get can return a lease by address. TEST_F(LeaseCmdsTest, Lease4GetByAddr) { - // Initialize lease manager (false = v4, true = add lease) + // Initialize lease manager (false = v4, true = add a lease) initLeaseMgr(false, true); // Query for valid, existing lease. @@ -1014,7 +1014,7 @@ TEST_F(LeaseCmdsTest, Lease4GetByHWAddrNotFound) { // Checks that lease4-get can find a lease by hardware address. TEST_F(LeaseCmdsTest, Lease4GetByHWAddr) { - // Initialize lease manager (false = v4, true = add lease) + // Initialize lease manager (false = v4, true = add a lease) initLeaseMgr(false, true); // Invalid @@ -1043,7 +1043,7 @@ TEST_F(LeaseCmdsTest, Lease4GetByHWAddr) { // the query is correctly formed, but the lease is not there. TEST_F(LeaseCmdsTest, Lease6GetByAddr6NotFound) { - // Initialize lease manager (true = v6, true = add lease) + // Initialize lease manager (true = v6, true = add a lease) initLeaseMgr(true, true); // Now send the command. @@ -1065,7 +1065,7 @@ TEST_F(LeaseCmdsTest, Lease6GetByAddr6NotFound) { // 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) { - // Initialize lease manager (true = v6, true = add lease) + // Initialize lease manager (true = v6, true = add a lease) initLeaseMgr(true, true); // Now send the command. @@ -1179,4 +1179,581 @@ TEST_F(LeaseCmdsTest, Lease6GetByDUID) { checkLease6(lease, "2001:db8::1", 0, 66, "77:77:77:77:77:77:77:77", false); } +// Test checks if lease4-update handler refuses calls with missing parameters. +TEST_F(LeaseCmdsTest, Lease4UpdateMissingParams) { + // Initialize lease manager (false = v4, true = add a lease) + initLeaseMgr(false, true); + + // Check that the lease manager pointer is there. + ASSERT_TRUE(lmptr_); + + // Everything missing. What sort of crap is that? + string txt = + "{\n" + " \"command\": \"lease4-update\",\n" + " \"arguments\": {" + " }\n" + "}"; + string exp_rsp = "missing parameter 'ip-address' (:3:19)"; + testCommand(txt, CONTROL_RESULT_ERROR, exp_rsp); + + // Just ip is not enough (subnet-id and hwaddr missing). + txt = + "{\n" + " \"command\": \"lease4-update\",\n" + " \"arguments\": {" + " \"ip-address\": \"192.0.2.123\"\n" + " }\n" + "}"; + exp_rsp = "missing parameter 'subnet-id' (:3:19)"; + testCommand(txt, CONTROL_RESULT_ERROR, exp_rsp); + + // Better, but still no luck. (hwaddr missing). + txt = + "{\n" + " \"command\": \"lease4-update\",\n" + " \"arguments\": {" + " \"subnet-id\": 44,\n" + " \"ip-address\": \"192.0.2.202\"\n" + " }\n" + "}"; + exp_rsp = "missing parameter 'hw-address' (:3:19)"; + testCommand(txt, CONTROL_RESULT_ERROR, exp_rsp); + + // Close, but no cigars. (ip-address missing). + txt = + "{\n" + " \"command\": \"lease4-update\",\n" + " \"arguments\": {" + " \"subnet-id\": 44,\n" + " \"hw-address\": \"1a:1b:1c:1d:1e:1f\"\n" + " }\n" + "}"; + exp_rsp = "missing parameter 'ip-address' (:3:19)"; + testCommand(txt, CONTROL_RESULT_ERROR, exp_rsp); +} + +// Verify that lease4-update can be rejected if parameters are specified, but +// have incorrect values. +TEST_F(LeaseCmdsTest, Lease4UpdateBadParams) { + + // Initialize lease manager (false = v4, true = add a lease) + initLeaseMgr(false, true); + + // Check that the lease manager pointer is there. + ASSERT_TRUE(lmptr_); + + // All params are there, but there's no subnet-id 123 configured. + // (initLeaseMgr initialized subnet-id 44 for v4 and subnet-id 66 for v6). + string txt = + "{\n" + " \"command\": \"lease4-update\",\n" + " \"arguments\": {" + " \"subnet-id\": 123,\n" + " \"ip-address\": \"192.0.2.202\",\n" + " \"hw-address\": \"1a:1b:1c:1d:1e:1f\"\n" + " }\n" + "}"; + string exp_rsp = "Invalid subnet-id: No IPv4 subnet with subnet-id=123 currently configured."; + testCommand(txt, CONTROL_RESULT_ERROR, exp_rsp); + + // This time the new IP address does not belong to the subnet. + txt = + "{\n" + " \"command\": \"lease4-update\",\n" + " \"arguments\": {" + " \"subnet-id\": 44,\n" + " \"ip-address\": \"10.0.0.1\",\n" + " \"hw-address\": \"1a:1b:1c:1d:1e:1f\"\n" + " }\n" + "}"; + exp_rsp = "The address 10.0.0.1 does not belong to subnet 192.0.2.0/24, subnet-id=44"; + testCommand(txt, CONTROL_RESULT_ERROR, exp_rsp); + + // We don't use any of that bleeding edge nonsense in this museum. v4 only. + txt = + "{\n" + " \"command\": \"lease4-update\",\n" + " \"arguments\": {" + " \"subnet-id\": 44,\n" + " \"ip-address\": \"2001:db8::1\",\n" + " \"hw-address\": \"1a:1b:1c:1d:1e:1f\"\n" + " }\n" + "}"; + exp_rsp = "Non-IPv4 address specified: 2001:db8::1"; + testCommand(txt, CONTROL_RESULT_ERROR, exp_rsp); +} + +// Check that a lease4 can be updated. We're changing hw-address +// and a hostname. +TEST_F(LeaseCmdsTest, Lease4Update) { + + // Initialize lease manager (false = v4, true = add a lease) + initLeaseMgr(false, true); + + // Check that the lease manager pointer is there. + ASSERT_TRUE(lmptr_); + + // Now send the command. + string txt = + "{\n" + " \"command\": \"lease4-update\",\n" + " \"arguments\": {" + " \"subnet-id\": 44,\n" + " \"ip-address\": \"192.0.2.1\",\n" + " \"hw-address\": \"1a:1b:1c:1d:1e:1f\",\n" + " \"hostname\": \"newhostname.example.org\"" + " }\n" + "}"; + string exp_rsp = "IPv4 lease updated."; + testCommand(txt, CONTROL_RESULT_SUCCESS, exp_rsp); + + // Now check that the lease is still there. + Lease4Ptr l = lmptr_->getLease4(IOAddress("192.0.2.1")); + ASSERT_TRUE(l); + + // Make sure it's been updated. + ASSERT_TRUE(l->hwaddr_); + EXPECT_EQ("1a:1b:1c:1d:1e:1f", l->hwaddr_->toText(false)); + EXPECT_EQ("newhostname.example.org", l->hostname_); +} + +// Test checks if lease6-update handler refuses calls with missing parameters. +TEST_F(LeaseCmdsTest, Lease6UpdateMissingParams) { + // Initialize lease manager (true = v6, true = add a lease) + initLeaseMgr(true, true); + + // Check that the lease manager pointer is there. + ASSERT_TRUE(lmptr_); + + // Everything missing. What sort of crap is that? + string txt = + "{\n" + " \"command\": \"lease6-update\",\n" + " \"arguments\": {" + " }\n" + "}"; + string exp_rsp = "missing parameter 'ip-address' (:3:19)"; + testCommand(txt, CONTROL_RESULT_ERROR, exp_rsp); + + // Just ip is not enough (subnet-id and hwaddr missing). + txt = + "{\n" + " \"command\": \"lease6-update\",\n" + " \"arguments\": {" + " \"ip-address\": \"2001:db8::1\"\n" + " }\n" + "}"; + exp_rsp = "missing parameter 'subnet-id' (:3:19)"; + testCommand(txt, CONTROL_RESULT_ERROR, exp_rsp); + + // Better, but still no luck. (duid missing). + txt = + "{\n" + " \"command\": \"lease6-update\",\n" + " \"arguments\": {" + " \"subnet-id\": 44,\n" + " \"ip-address\": \"2001:db8::1\"\n" + " }\n" + "}"; + exp_rsp = "missing parameter 'duid' (:3:19)"; + testCommand(txt, CONTROL_RESULT_ERROR, exp_rsp); + + // ip-address and identifier-type missing. + txt = + "{\n" + " \"command\": \"lease6-update\",\n" + " \"arguments\": {" + " \"subnet-id\": 44,\n" + " \"duid\": \"1a:1b:1c:1d:1e:1f\"\n" + " }\n" + "}"; + exp_rsp = "missing parameter 'ip-address' (:3:19)"; + testCommand(txt, CONTROL_RESULT_ERROR, exp_rsp); +} + +// Verify that lease6-update can be rejected if parameters are specified, but +// have incorrect values. +TEST_F(LeaseCmdsTest, Lease6UpdateBadParams) { + + // Initialize lease manager (true = v6, true = add a lease) + initLeaseMgr(true, true); + + // Check that the lease manager pointer is there. + ASSERT_TRUE(lmptr_); + + // All params are there, but there's no subnet-id 123 configured. + // (initLeaseMgr initialized subnet-id 44 for v4 and subnet-id 66 for v6). + string txt = + "{\n" + " \"command\": \"lease6-update\",\n" + " \"arguments\": {" + " \"subnet-id\": 123,\n" + " \"ip-address\": \"2001:db8::1\",\n" + " \"duid\": \"88:88:88:88:88:88:88:88\"\n" + " }\n" + "}"; + string exp_rsp = "Invalid subnet-id: No IPv6 subnet with subnet-id=123 currently configured."; + testCommand(txt, CONTROL_RESULT_ERROR, exp_rsp); + + // This time the new IP address does not belong to the subnet. + txt = + "{\n" + " \"command\": \"lease6-update\",\n" + " \"arguments\": {" + " \"subnet-id\": 66,\n" + " \"ip-address\": \"3000::1\",\n" + " \"duid\": \"88:88:88:88:88:88:88:88\"\n" + " }\n" + "}"; + exp_rsp = "The address 3000::1 does not belong to subnet 2001:db8::/48, subnet-id=66"; + testCommand(txt, CONTROL_RESULT_ERROR, exp_rsp); + + // Nope, can't do v4 address in v6 lease. + txt = + "{\n" + " \"command\": \"lease6-update\",\n" + " \"arguments\": {" + " \"subnet-id\": 66,\n" + " \"ip-address\": \"192.0.2.1\",\n" + " \"duid\": \"88:88:88:88:88:88:88:88\"\n" + " }\n" + "}"; + exp_rsp = "Non-IPv6 address specified: 192.0.2.1"; + testCommand(txt, CONTROL_RESULT_ERROR, exp_rsp); +} + +// Check that a lease6 can be updated. We're changing hw-address +// and a hostname. +TEST_F(LeaseCmdsTest, Lease6Update) { + + // Initialize lease manager (true = v6, true = add a lease) + initLeaseMgr(true, true); + + // Check that the lease manager pointer is there. + ASSERT_TRUE(lmptr_); + + // Now send the command. + string txt = + "{\n" + " \"command\": \"lease6-update\",\n" + " \"arguments\": {" + " \"subnet-id\": 66,\n" + " \"ip-address\": \"2001:db8::1\",\n" + " \"iaid\": 7654321,\n" + " \"duid\": \"88:88:88:88:88:88:88:88\",\n" + " \"hostname\": \"newhostname.example.org\"" + " }\n" + "}"; + string exp_rsp = "IPv6 lease updated."; + testCommand(txt, CONTROL_RESULT_SUCCESS, exp_rsp); + + // Now check that the lease is really there. + Lease6Ptr l = lmptr_->getLease6(Lease::TYPE_NA, IOAddress("2001:db8::1")); + ASSERT_TRUE(l); + + // Make sure the lease has been updated. + ASSERT_TRUE(l->duid_); + EXPECT_EQ("88:88:88:88:88:88:88:88", l->duid_->toText()); + EXPECT_EQ("newhostname.example.org", l->hostname_); + EXPECT_EQ(7654321, l->iaid_); +} + +// Checks that lease6-del can handle a situation when the query is +// broken (some required parameters are missing). +TEST_F(LeaseCmdsTest, Lease4DelMissingParams) { + + // No parameters whatsoever. You want just a lease, any lease? + string cmd = + "{\n" + " \"command\": \"lease4-del\",\n" + " \"arguments\": {" + " }\n" + "}"; + string exp_rsp = "Mandatory 'subnet-id' parameter missing."; + testCommand(cmd, CONTROL_RESULT_ERROR, exp_rsp); + + // Just the subnet-id won't cut it, either. + cmd = + "{\n" + " \"command\": \"lease4-del\",\n" + " \"arguments\": {" + " \"subnet-id\": 123" + " }\n" + "}"; + exp_rsp = "No 'ip-address' provided and 'identifier-type' is either missing or not a string."; + testCommand(cmd, CONTROL_RESULT_ERROR, exp_rsp); + + // We can't identify your laptop by color. Sorry, buddy. + cmd = + "{\n" + " \"command\": \"lease4-del\",\n" + " \"arguments\": {" + " \"subnet-id\": 123,\n" + " \"identifier-type\": \"color\",\n" + " \"identifier\": \"blue\"\n" + " }\n" + "}"; + exp_rsp = "Incorrect identifier type: color, the only supported values are: " + "address, hw-address, duid"; + testCommand(cmd, CONTROL_RESULT_ERROR, exp_rsp); + + // Query by DUID is not supported in v4. Sorry. + cmd = + "{\n" + " \"command\": \"lease4-del\",\n" + " \"arguments\": {" + " \"subnet-id\": 123,\n" + " \"identifier-type\": \"duid\",\n" + " \"identifier\": \"01:01:01:01:01:01\"\n" + " }\n" + "}"; + exp_rsp = "Delete by duid is not allowed in v4."; + testCommand(cmd, CONTROL_RESULT_ERROR, exp_rsp); + + // Identifier value is missing. + cmd = + "{\n" + " \"command\": \"lease4-del\",\n" + " \"arguments\": {" + " \"subnet-id\": 123,\n" + " \"identifier-type\": \"hw-address\"\n" + " }\n" + "}"; + exp_rsp = "No 'ip-address' provided and 'identifier' is either missing or not a string."; + testCommand(cmd, CONTROL_RESULT_ERROR, exp_rsp); + + // Identifier-type is missing. + cmd = + "{\n" + " \"command\": \"lease4-del\",\n" + " \"arguments\": {" + " \"subnet-id\": 123,\n" + " \"identifier\": \"01:02:03:04:05\"\n" + " }\n" + "}"; + exp_rsp = "No 'ip-address' provided and 'identifier-type' is either missing or not a string."; + testCommand(cmd, CONTROL_RESULT_ERROR, exp_rsp); +} + +// Checks that lease4-del can handle a situation when the query is +// valid, but the lease is not there. +TEST_F(LeaseCmdsTest, Lease4DelByAddrNotFound) { + + // Initialize lease manager (false = v4, true = add a lease) + initLeaseMgr(false, true); + + // Invalid + string cmd = + "{\n" + " \"command\": \"lease4-del\",\n" + " \"arguments\": {" + " \"ip-address\": \"192.0.2.5\"," + " \"subnet-id\": 44" + " }\n" + "}"; + string exp_rsp = "IPv4 lease not found."; + ConstElementPtr rsp = testCommand(cmd, CONTROL_RESULT_EMPTY, exp_rsp); +} + +// Checks that lease4-del can return a lease by address. +TEST_F(LeaseCmdsTest, Lease4DelByAddr) { + + // Initialize lease manager (false = v4, true = add a lease) + initLeaseMgr(false, true); + + // Query for valid, existing lease. + string cmd = + "{\n" + " \"command\": \"lease4-del\",\n" + " \"arguments\": {" + " \"ip-address\": \"192.0.2.1\"," + " \"subnet-id\": 44" + " }\n" + "}"; + string exp_rsp = "IPv4 lease deleted."; + 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 lease4-del can handle a situation when the query is +// well formed, but the lease is not there. +TEST_F(LeaseCmdsTest, Lease4DelByHWAddrNotFound) { + + // 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\": \"hw-address\"," + " \"identifier\": \"01:02:03:04:05:06\"," + " \"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 a lease by hardware address. +TEST_F(LeaseCmdsTest, Lease4DelByHWAddr) { + + // Initialize lease manager (false = v4, true = add a lease) + initLeaseMgr(false, true); + + // Invalid + string cmd = + "{\n" + " \"command\": \"lease4-del\",\n" + " \"arguments\": {" + " \"identifier-type\": \"hw-address\"," + " \"identifier\": \"08:08:08:08:08:08\"," + " \"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) { + + // Initialize lease manager (true = v6, true = add a lease) + initLeaseMgr(true, true); + + // Now send the command. + string cmd = + "{\n" + " \"command\": \"lease6-del\",\n" + " \"arguments\": {" + " \"subnet-id\": 1,\n" + " \"ip-address\": \"2001:db8::2\"\n" + " }\n" + "}"; + string exp_rsp = "IPv6 lease not found."; + + // Note the status expected is empty. The query completed correctly, + // just didn't found the lease. + testCommand(cmd, CONTROL_RESULT_EMPTY, exp_rsp); +} + +// Checks that lease6-del(subnet-id, addr) can handle a situation when +// the query is correctly formed, but the lease is not there. +TEST_F(LeaseCmdsTest, Lease6DelByDuidNotFound) { + + // Initialize lease manager (true = v6, true = add a lease) + initLeaseMgr(true, true); + + // Now send the command. + string cmd = + "{\n" + " \"command\": \"lease6-del\",\n" + " \"arguments\": {" + " \"subnet-id\": 1,\n" + " \"identifier-type\": \"duid\"," + " \"identifier\": \"00:01:02:03:04:05:06:07\"\n" + " }\n" + "}"; + string exp_rsp = "IPv6 lease not found."; + + // Note the status expected is empty. The query completed correctly, + // just didn't found the lease. + testCommand(cmd, CONTROL_RESULT_EMPTY, exp_rsp); + + // Make sure the lease is still there. + EXPECT_TRUE(lmptr_->getLease6(Lease::TYPE_NA, IOAddress("2001:db8::1"))); +} + +// Checks that lease6-del(subnet-id, addr6) can handle a situation when +// the query is correctly formed and the lease is returned. +TEST_F(LeaseCmdsTest, Lease6DelByAddr) { + + initLeaseMgr(true, true); // (true = v6, true = create a lease) + + // Now send the command. + string cmd = + "{\n" + " \"command\": \"lease6-del\",\n" + " \"arguments\": {" + " \"subnet-id\": 66,\n" + " \"ip-address\": \"2001:db8::1\"" + " }\n" + "}"; + string exp_rsp = "IPv6 lease deleted."; + + // The status expected is success. The lease should be deleted. + testCommand(cmd, CONTROL_RESULT_SUCCESS, exp_rsp); + + // Make sure the lease is really gone. + EXPECT_FALSE(lmptr_->getLease6(Lease::TYPE_NA, IOAddress("2001:db8::1"))); +} + +// Checks that lease6-del(subnet-id, type, addr6) can handle a situation when +// the query is correctly formed and the lease is deleted. +TEST_F(LeaseCmdsTest, Lease6DelByAddrPrefix) { + + initLeaseMgr(true, false); // (true = v6, false = don't add any leases) + + // Let's start with regular address lease and make it a prefix lease. + Lease6Ptr l = createLease6(); + l->addr_ = IOAddress("2001:db8:1234:ab::"); + l->type_ = Lease::TYPE_PD; + l->prefixlen_ = 56; + lmptr_->addLease(l); + + // Now send the command. + string cmd = + "{\n" + " \"command\": \"lease6-del\",\n" + " \"arguments\": {" + " \"type\": \"IA_PD\"," + " \"ip-address\": \"2001:db8:1234:ab::\"" + " }\n" + "}"; + string exp_rsp = "IPv6 lease deleted."; + + // The status expected is success. The lease should be deleted. + testCommand(cmd, CONTROL_RESULT_SUCCESS, exp_rsp); + + // Make sure the lease is really gone. + EXPECT_FALSE(lmptr_->getLease6(Lease::TYPE_PD, IOAddress("2001:db8:1234:ab::"))); +} + +// Checks that lease6-del(subnet-id, iaid, identifier-type, identifier) can handle +// a situation when the query finds a lease. +TEST_F(LeaseCmdsTest, Lease6DelByDUID) { + + initLeaseMgr(true, true); // (true = v6, true = create a lease) + + // Now send the command. + string cmd = + "{\n" + " \"command\": \"lease6-del\",\n" + " \"arguments\": {" + " \"subnet-id\": 66,\n" + " \"iaid\": 42," + " \"identifier-type\": \"duid\"," + " \"identifier\": \"77:77:77:77:77:77:77:77\"\n" + " }\n" + "}"; + string exp_rsp = "IPv6 lease deleted."; + + // The status expected is success. The lease should be deleted. + testCommand(cmd, CONTROL_RESULT_SUCCESS, exp_rsp); + + // Make sure the lease is really gone. + EXPECT_FALSE(lmptr_->getLease6(Lease::TYPE_NA, IOAddress("2001:db8::1"))); +} + } // end of anonymous namespace