#include <dhcp/hwaddr.h>
#include <asiolink/io_address.h>
#include <dhcpsrv/lease.h>
+#include <dhcpsrv/cfgmgr.h>
+#include <dhcpsrv/cfg_consistency.h>
#include <lease_parser.h>
#include <config.h>
// These are mandatory parameters.
IOAddress addr = getAddress(lease_info, "ip-address");
- SubnetID subnet_id = getUint32(lease_info, "subnet-id");
-
if (!addr.isV4()) {
isc_throw(BadValue, "Non-IPv4 address specified: " << addr);
}
HWAddr hwaddr = HWAddr::fromText(hwaddr_txt);
HWAddrPtr hwaddr_ptr = HWAddrPtr(new HWAddr(hwaddr));
- Subnet4Ptr subnet = cfg->getCfgSubnets4()->getSubnet(subnet_id);
- if (!subnet) {
- isc_throw(BadValue, "Invalid subnet-id: No IPv4 subnet with subnet-id="
- << subnet_id << " currently configured.");
+ // Now sort out the subnet-id. If specified, it must have correct value.
+ // If not specified, Kea will try to sort it out.
+ SubnetID subnet_id = 0;
+ if (lease_info->contains("subnet-id")) {
+ subnet_id = getUint32(lease_info, "subnet-id");
+ }
+ Subnet4Ptr subnet;
+ if (subnet_id) {
+ // If subnet-id is specified, it has to match.
+ subnet = cfg->getCfgSubnets4()->getSubnet(subnet_id);
+ if (!subnet) {
+ isc_throw(BadValue, "Invalid subnet-id: No IPv4 subnet with subnet-id="
+ << subnet_id << " currently configured.");
+ }
+ } else {
+ // Subnet-id was not specified. Let's try to figure it out on our own.
+ subnet = cfg->getCfgSubnets4()->selectSubnet(addr);
+ if (!subnet) {
+ isc_throw(BadValue, "subnet-id not specified and failed to find a"
+ << " subnet for address " << addr);
+ }
+ subnet_id = subnet->getID();
}
if (!subnet->inRange(addr)) {
// These are mandatory parameters.
IOAddress addr = getAddress(lease_info, "ip-address");
- SubnetID subnet_id = getUint32(lease_info, "subnet-id");
-
if (addr.isV4()) {
isc_throw(BadValue, "Non-IPv6 address specified: " << addr);
}
DUID duid = DUID::fromText(duid_txt);
DuidPtr duid_ptr = DuidPtr(new DUID(duid));
- // Check if the subnet-id specified is sane.
- Subnet6Ptr subnet = cfg->getCfgSubnets6()->getSubnet(subnet_id);
- if (!subnet) {
- isc_throw(BadValue, "Invalid subnet-id: No IPv6 subnet with subnet-id="
- << subnet_id << " currently configured.");
- }
-
Lease::Type type = Lease::TYPE_NA;
uint8_t prefix_len = 128;
if (lease_info->contains("type")) {
}
}
+ // Now sort out the subnet-id. If specified, it must have correct value.
+ // If not specified, Kea will try to sort it out.
+ SubnetID subnet_id = 0;
+ if (lease_info->contains("subnet-id")) {
+ subnet_id = getUint32(lease_info, "subnet-id");
+ }
+
+ // Check if the subnet-id specified is sane.
+ Subnet6Ptr subnet;
+ if (subnet_id) {
+ // If subnet-id is specified, it has to match.
+ subnet = cfg->getCfgSubnets6()->getSubnet(subnet_id);
+ if (!subnet) {
+ isc_throw(BadValue, "Invalid subnet-id: No IPv6 subnet with subnet-id="
+ << subnet_id << " currently configured.");
+ }
+ } else {
+ if (type != Lease::TYPE_NA) {
+ isc_throw(BadValue, "Subnet-id is 0 or not specified. This is allowed for"
+ " address leases only, not prefix leases.");
+ }
+ subnet = cfg->getCfgSubnets6()->selectSubnet(addr);
+ if (!subnet) {
+ isc_throw(BadValue, "subnet-id not specified and failed to find a "
+ "subnet for address " << addr);
+ }
+ subnet_id = subnet->getID();
+ }
+
// Check if the address specified really belongs to the subnet.
if ((type == Lease::TYPE_NA) && !subnet->inRange(addr)) {
isc_throw(BadValue, "The address " << addr.toText() << " does not belong "
string exp_rsp = "missing parameter 'ip-address' (<string>:3:19)";
testCommand(txt, CONTROL_RESULT_ERROR, exp_rsp);
- // Just ip is not enough (subnet-id and hwaddr missing).
+ // Just ip is not enough (subnet-id and hwaddr missing, although
+ // subnet-id can now be figured out by Kea code)
txt =
"{\n"
" \"command\": \"lease4-add\",\n"
" \"ip-address\": \"192.0.2.123\"\n"
" }\n"
"}";
- exp_rsp = "missing parameter 'subnet-id' (<string>:3:19)";
+ exp_rsp = "missing parameter 'hw-address' (<string>:3:19)";
testCommand(txt, CONTROL_RESULT_ERROR, exp_rsp);
// Better, but still no luck. (hwaddr missing).
" \"hw-address\": \"1a:1b:1c:1d:1e:1f\"\n"
" }\n"
"}";
- string exp_rsp = "Lease added.";
+ string exp_rsp = "Lease for address 192.0.2.202, subnet-id 44 added.";
testCommand(txt, CONTROL_RESULT_SUCCESS, exp_rsp);
// Now check that the lease is really there.
}
+// Check that subnet-id is optional. If not specified, Kea should select
+// it on its own.
+TEST_F(LeaseCmdsTest, Lease4AddSubnetIdMissing) {
+
+ // Initialize lease manager (false = v4, false = don't add leases)
+ initLeaseMgr(false, false);
+
+ // Check that the lease manager pointer is there.
+ ASSERT_TRUE(lmptr_);
+
+ // Now send the command without subnet-id. Kea should select
+ // the subnet id on its own.
+ string txt =
+ "{\n"
+ " \"command\": \"lease4-add\",\n"
+ " \"arguments\": {"
+ " \"ip-address\": \"192.0.2.202\",\n"
+ " \"hw-address\": \"1a:1b:1c:1d:1e:1f\"\n"
+ " }\n"
+ "}";
+ string exp_rsp = "Lease for address 192.0.2.202, subnet-id 44 added.";
+ testCommand(txt, CONTROL_RESULT_SUCCESS, exp_rsp);
+
+ // Now check that the lease is really there.
+ Lease4Ptr l = lmptr_->getLease4(IOAddress("192.0.2.202"));
+ ASSERT_TRUE(l);
+ EXPECT_EQ(44, l->subnet_id_);
+
+}
+
+// Check that subnet-id is optional. If not specified, Kea should select
+// it on its own, but if there's no subnet for address being added, it
+// should fail.
+TEST_F(LeaseCmdsTest, Lease4AddSubnetIdMissingBadAddr) {
+
+ // Initialize lease manager (false = v4, false = don't add leases)
+ initLeaseMgr(false, false);
+
+ // Check that the lease manager pointer is there.
+ ASSERT_TRUE(lmptr_);
+
+ // Now send the command without subnet-id. Kea should select
+ // the subnet id on its own.
+ string txt =
+ "{\n"
+ " \"command\": \"lease4-add\",\n"
+ " \"arguments\": {"
+ " \"ip-address\": \"192.0.55.1\",\n"
+ " \"hw-address\": \"1a:1b:1c:1d:1e:1f\"\n"
+ " }\n"
+ "}";
+ string exp_rsp = "subnet-id not specified and failed to find a subnet for "
+ "address 192.0.55.1";
+ testCommand(txt, CONTROL_RESULT_ERROR, exp_rsp);
+
+ // Now check that the lease was not added.
+ Lease4Ptr l = lmptr_->getLease4(IOAddress("192.0.55.1"));
+ ASSERT_FALSE(l);
+}
+
// Check that a well formed lease4 with tons of parameters can be added.
TEST_F(LeaseCmdsTest, Lease4AddFull) {
" \"user-context\": { \"foobar\": true }\n"
" }\n"
"}";
- string exp_rsp = "Lease added.";
+ string exp_rsp = "Lease for address 192.0.2.202, subnet-id 44 added.";
testCommand(txt, CONTROL_RESULT_SUCCESS, exp_rsp);
// Now check that the lease is really there.
" \"comment\": \"a comment\"\n"
" }\n"
"}";
- string exp_rsp = "Lease added.";
- testCommand(txt, CONTROL_RESULT_SUCCESS, exp_rsp);
+ string exp_rsp = "Lease for address 192.0.2.202, subnet-id 44 added.";
+ testCommand(txt, CONTROL_RESULT_SUCCESS, exp_rsp);
- // Now check that the lease is really there.
- Lease4Ptr l = lmptr_->getLease4(IOAddress("192.0.2.202"));
- ASSERT_TRUE(l);
+ // Now check that the lease is really there.
+ Lease4Ptr l = lmptr_->getLease4(IOAddress("192.0.2.202"));
+ ASSERT_TRUE(l);
- // Make sure the lease have proper value set.
- ASSERT_TRUE(l->hwaddr_);
- EXPECT_EQ("1a:1b:1c:1d:1e:1f", l->hwaddr_->toText(false));
- ASSERT_TRUE(l->getContext());
- EXPECT_EQ("{ \"comment\": \"a comment\" }", l->getContext()->str());
+ // Make sure the lease have proper value set.
+ ASSERT_TRUE(l->hwaddr_);
+ EXPECT_EQ("1a:1b:1c:1d:1e:1f", l->hwaddr_->toText(false));
+ ASSERT_TRUE(l->getContext());
+ EXPECT_EQ("{ \"comment\": \"a comment\" }", l->getContext()->str());
}
// Check that lease6-add with missing parameters will fail.
string exp_rsp = "missing parameter 'ip-address' (<string>:3:19)";
testCommand(txt, CONTROL_RESULT_ERROR, exp_rsp);
- // Just ip is not enough (subnet-id and duid missing).
+ // Just ip is not enough (subnet-id and duid missing, but subnet-id
+ // can now be figured out by kea)
txt =
"{\n"
" \"command\": \"lease6-add\",\n"
" \"ip-address\": \"2001:db8:1::3\"\n"
" }\n"
"}";
- exp_rsp = "missing parameter 'subnet-id' (<string>:3:19)";
+ exp_rsp = "missing parameter 'duid' (<string>:3:19)";
testCommand(txt, CONTROL_RESULT_ERROR, exp_rsp);
// Just subnet-id and ip is not enough (duid missing).
" \"iaid\": 1234\n"
" }\n"
"}";
- string exp_rsp = "Lease added.";
+ string exp_rsp = "Lease for address 2001:db8:1::3, subnet-id 66 added.";
testCommand(txt, CONTROL_RESULT_SUCCESS, exp_rsp);
// Now check that the lease is really there.
EXPECT_FALSE(l->getContext());
}
+// Check that subnet-id is optional. If not specified, Kea should select
+// it on its own.
+TEST_F(LeaseCmdsTest, Lease6AddSubnetIdMissing) {
+
+ // Initialize lease manager (true = v6, false = don't add leases)
+ initLeaseMgr(true, false);
+
+ // Check that the lease manager pointer is there.
+ ASSERT_TRUE(lmptr_);
+
+ // Now send the command (without subnet-id)
+ string txt =
+ "{\n"
+ " \"command\": \"lease6-add\",\n"
+ " \"arguments\": {"
+ " \"ip-address\": \"2001:db8:1::3\",\n"
+ " \"duid\": \"1a:1b:1c:1d:1e:1f\",\n"
+ " \"iaid\": 1234\n"
+ " }\n"
+ "}";
+ string exp_rsp = "Lease for address 2001:db8:1::3, subnet-id 66 added.";
+ testCommand(txt, CONTROL_RESULT_SUCCESS, exp_rsp);
+
+ // Now check that the lease is really there and has correct subnet-id.
+ Lease6Ptr l = lmptr_->getLease6(Lease::TYPE_NA, IOAddress("2001:db8:1::3"));
+ ASSERT_TRUE(l);
+ EXPECT_EQ(66, l->subnet_id_);
+}
+
+// Check that subnet-id is optional. If not specified, Kea should select
+// it on its own, but if there's no subnet for address being added, it
+// should fail.
+TEST_F(LeaseCmdsTest, Lease6AddSubnetIdMissingBadAddr) {
+
+ // Initialize lease manager (true = v6, false = don't add leases)
+ initLeaseMgr(true, false);
+
+ // Check that the lease manager pointer is there.
+ ASSERT_TRUE(lmptr_);
+
+ // Now send the command (without subnet-id)
+ string txt =
+ "{\n"
+ " \"command\": \"lease6-add\",\n"
+ " \"arguments\": {"
+ " \"ip-address\": \"2001:ffff::1\",\n"
+ " \"duid\": \"1a:1b:1c:1d:1e:1f\",\n"
+ " \"iaid\": 1234\n"
+ " }\n"
+ "}";
+ string exp_rsp = "subnet-id not specified and failed to find a subnet for "
+ "address 2001:ffff::1";
+ testCommand(txt, CONTROL_RESULT_ERROR, exp_rsp);
+
+ // Now check that the lease is really there and has correct subnet-id.
+ Lease6Ptr l = lmptr_->getLease6(Lease::TYPE_NA, IOAddress("2001:ffff::1"));
+ ASSERT_FALSE(l);
+}
+
// Check that a simple, well formed prefix lease can be added.
TEST_F(LeaseCmdsTest, Lease6AddPrefix) {
" \"iaid\": 1234\n"
" }\n"
"}";
- string exp_rsp = "Lease added.";
+ string exp_rsp = "Lease for prefix 2001:db8:abcd::/48, subnet-id 66 added.";
testCommand(txt, CONTROL_RESULT_SUCCESS, exp_rsp);
// Now check that the lease is really there.
" \"user-context\": { \"foobar\": true }\n"
" }\n"
"}";
- string exp_rsp = "Lease added.";
+ string exp_rsp = "Lease for address 2001:db8:1::3, subnet-id 66 added.";
testCommand(txt, CONTROL_RESULT_SUCCESS, exp_rsp);
// Now check that the lease is really there.
" \"comment\": \"a comment\"\n"
" }\n"
"}";
- string exp_rsp = "Lease added.";
+ string exp_rsp = "Lease for address 2001:db8:1::3, subnet-id 66 added.";
testCommand(txt, CONTROL_RESULT_SUCCESS, exp_rsp);
// Now check that the lease is really there.
string exp_rsp = "missing parameter 'ip-address' (<string>:3:19)";
testCommand(txt, CONTROL_RESULT_ERROR, exp_rsp);
- // Just ip is not enough (subnet-id and hwaddr missing).
+ // Just ip is not enough (subnet-id and hwaddr missing, although
+ // Kea can now figure out subnet-id on its own).
txt =
"{\n"
" \"command\": \"lease4-update\",\n"
" \"ip-address\": \"192.0.2.123\"\n"
" }\n"
"}";
- exp_rsp = "missing parameter 'subnet-id' (<string>:3:19)";
+ exp_rsp = "missing parameter 'hw-address' (<string>:3:19)";
testCommand(txt, CONTROL_RESULT_ERROR, exp_rsp);
// Better, but still no luck. (hwaddr missing).
EXPECT_FALSE(l->getContext());
}
+// Check that a lease4 can be updated. We're changing hw-address
+// and a hostname. The subnet-id is not specified.
+TEST_F(LeaseCmdsTest, Lease4UpdateNoSubnetId) {
+
+ // 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\": {"
+ " \"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_);
+ EXPECT_FALSE(l->getContext());
+}
+
// Check that a lease4 is created if it doesn't exist during the update.
// To trigger this behavior 'force-create' boolean parameter must be
// included in the command.
EXPECT_FALSE(l->getContext());
}
+// Check that a lease4 is created if it doesn't exist during the update.
+// To trigger this behavior 'force-create' boolean parameter must be
+// included in the command. The subnet-id is not specified, Kea will
+// figure it out.
+TEST_F(LeaseCmdsTest, Lease4UpdateForceCreateNoSubnetId) {
+ // Initialize lease manager (false = v4, false = don't add any lease)
+ initLeaseMgr(false, false);
+
+ // Check that the lease manager pointer is there.
+ ASSERT_TRUE(lmptr_);
+
+ // Now send the command.
+ string txt =
+ "{\n"
+ " \"command\": \"lease4-update\",\n"
+ " \"arguments\": {"
+ " \"ip-address\": \"192.0.2.1\",\n"
+ " \"hw-address\": \"1a:1b:1c:1d:1e:1f\",\n"
+ " \"hostname\": \"newhostname.example.org\","
+ " \"force-create\": true"
+ " }\n"
+ "}";
+ string exp_rsp = "IPv4 lease added.";
+ 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 the subnet-id is figured out correctly.
+ EXPECT_EQ(44, l->subnet_id_);
+
+ // Make sure it contains expected values..
+ ASSERT_TRUE(l->hwaddr_);
+ EXPECT_EQ("1a:1b:1c:1d:1e:1f", l->hwaddr_->toText(false));
+ EXPECT_EQ("newhostname.example.org", l->hostname_);
+ EXPECT_FALSE(l->getContext());
+}
+
// Check that lease4-update correctly handles case when the 'force-create'
// parameter is explicitly set to false.
TEST_F(LeaseCmdsTest, Lease4UpdateDoNotForceCreate) {
string exp_rsp = "missing parameter 'ip-address' (<string>:3:19)";
testCommand(txt, CONTROL_RESULT_ERROR, exp_rsp);
- // Just ip is not enough (subnet-id and hwaddr missing).
+ // Just ip is not enough (subnet-id and duid missing, although
+ // kea should be able to figure out the subnet-id on its own.
txt =
"{\n"
" \"command\": \"lease6-update\",\n"
" \"ip-address\": \"2001:db8:1::1\"\n"
" }\n"
"}";
- exp_rsp = "missing parameter 'subnet-id' (<string>:3:19)";
+ exp_rsp = "missing parameter 'duid' (<string>:3:19)";
testCommand(txt, CONTROL_RESULT_ERROR, exp_rsp);
// Better, but still no luck. (duid missing).
EXPECT_FALSE(l->getContext());
}
+// Check that a lease6 can be updated. We're changing hw-address
+// and a hostname. The subnet-id is not specified.
+TEST_F(LeaseCmdsTest, Lease6UpdateNoSubnetId) {
+
+ // 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\": {"
+ " \"ip-address\": \"2001:db8:1::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::1"));
+ ASSERT_TRUE(l);
+
+ // Make sure the subnet-id is correct.
+ EXPECT_EQ(66, l->subnet_id_);
+
+ // 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_);
+ EXPECT_FALSE(l->getContext());
+}
+
+
// Check that a lease6 can be updated. We're adding a comment and an user
// context.
TEST_F(LeaseCmdsTest, Lease6UpdateComment) {
EXPECT_FALSE(l->getContext());
}
+// Check that a lease6 is created if it doesn't exist during the update.
+// To trigger this behavior 'force-create' boolean parameter must be
+// included in the command. The subnet-id is not specified, Kea will
+// figure it out.
+TEST_F(LeaseCmdsTest, Lease6UpdateForceCreateNoSubnetId) {
+
+ // Initialize lease manager (true = v6, true = add a lease)
+ initLeaseMgr(true, false);
+
+ // Check that the lease manager pointer is there.
+ ASSERT_TRUE(lmptr_);
+
+ // Now send the command.
+ string txt =
+ "{\n"
+ " \"command\": \"lease6-update\",\n"
+ " \"arguments\": {"
+ " \"ip-address\": \"2001:db8:1::1\",\n"
+ " \"iaid\": 7654321,\n"
+ " \"duid\": \"88:88:88:88:88:88:88:88\",\n"
+ " \"hostname\": \"newhostname.example.org\","
+ " \"force-create\": true"
+ " }\n"
+ "}";
+ string exp_rsp = "IPv6 lease added.";
+ 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::1"));
+ ASSERT_TRUE(l);
+
+ // Make sure the subnet-id is figured out correctly.
+ EXPECT_EQ(66, l->subnet_id_);
+
+ // Make sure the lease is correct.
+ 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_);
+ EXPECT_FALSE(l->getContext());
+}
+
// Check that lease6-update correctly handles case when the 'force-create'
// parameter is explicitly set to false.
TEST_F(LeaseCmdsTest, Lease6UpdateDoNotForceCreate) {