client_id.reset(new ClientId(opt_clientid->getData()));
}
- // Check if the client attempted to decline a lease it doesn't own.
- if (!lease->belongsToClient(decline->getHWAddr(), client_id)) {
+ // Check if the client attempted to decline an expired lease or a lease
+ // it doesn't own. Declining expired leases is typically a client
+ // misbehavior and may lead to pool exhaustion in case of a storm of
+ // such declines. Only decline the lease if the lease has been recently
+ // allocated to the client.
+ if (lease->expired() || lease->state_ != Lease::STATE_DEFAULT ||
+ !lease->belongsToClient(decline->getHWAddr(), client_id)) {
// Get printable hardware addresses
string client_hw = decline->getHWAddr() ?
EXPECT_EQ(Lease::STATE_DEFAULT, lease->state_);
}
+// Test that the released lease cannot be declined.
+TEST_F(DeclineTest, declineAfterRelease) {
+ Dhcp4Client client(Dhcp4Client::SELECTING);
+ // Configure DHCP server.
+ configure(DECLINE_CONFIGS[0], *client.getServer(), true, true, true, false, LEASE_AFFINITY_ENABLED);
+ // Perform 4-way exchange to obtain a new lease.
+ acquireLease(client);
+
+ // Remember the acquired address.
+ IOAddress leased_address = client.config_.lease_.addr_;
+
+ // Release the acquired lease.
+ client.doRelease();
+
+ // Try to decline the released address.
+ client.config_.lease_.addr_ = leased_address;
+ ASSERT_NO_THROW(client.doDecline());
+
+ // The address should not be declined. It should still be in the
+ // released state.
+ Lease4Ptr lease = LeaseMgrFactory::instance().getLease4(leased_address);
+ ASSERT_TRUE(lease);
+ EXPECT_EQ(Lease::STATE_RELEASED, lease->state_);
+}
+
+// Test that the expired lease cannot be declined.
+TEST_F(DeclineTest, declineAfterExpire) {
+ Dhcp4Client client(Dhcp4Client::SELECTING);
+ // Configure DHCP server.
+ configure(DECLINE_CONFIGS[0], *client.getServer());
+ // Perform 4-way exchange to obtain a new lease.
+ acquireLease(client);
+
+ // Age the lease (expire it).
+ auto lease = LeaseMgrFactory::instance().getLease4(client.config_.lease_.addr_);
+ ASSERT_TRUE(lease);
+ lease->cltt_ -= 7200;
+ LeaseMgrFactory::instance().updateLease4(lease);
+
+ // Try to decline the expired lease.
+ ASSERT_NO_THROW(client.doDecline());
+
+ // The address should not be declined. It should still be in the
+ // default state.
+ lease = LeaseMgrFactory::instance().getLease4(lease->addr_);
+ ASSERT_TRUE(lease);
+ EXPECT_EQ(Lease::STATE_DEFAULT, lease->state_);
+}
+
+// Test that expired-reclaimed lease cannot be declined.
+TEST_F(DeclineTest, declineAfterReclamation) {
+ Dhcp4Client client(Dhcp4Client::SELECTING);
+ // Configure DHCP server.
+ configure(DECLINE_CONFIGS[0], *client.getServer());
+ // Perform 4-way exchange to obtain a new lease.
+ acquireLease(client);
+
+ // Reclaim the lease.
+ auto lease = LeaseMgrFactory::instance().getLease4(client.config_.lease_.addr_);
+ ASSERT_TRUE(lease);
+ lease->state_ = Lease::STATE_EXPIRED_RECLAIMED;
+ LeaseMgrFactory::instance().updateLease4(lease);
+
+ // Try to decline the reclaimed lease.
+ ASSERT_NO_THROW(client.doDecline());
+
+ // The address should not be declined. It should still be in the
+ // reclaimed state.
+ lease = LeaseMgrFactory::instance().getLease4(lease->addr_);
+ ASSERT_TRUE(lease);
+ EXPECT_EQ(Lease::STATE_EXPIRED_RECLAIMED, lease->state_);
+}
+
} // end of anonymous namespace
Lease6Ptr lease = LeaseMgrFactory::instance().getLease6(Lease::TYPE_NA,
decline_addr->getAddress());
- if (!lease) {
+ if (!lease || lease->expired() || lease->state_ != Lease::STATE_DEFAULT) {
// Client trying to decline a lease that we don't know about.
LOG_INFO(lease6_logger, DHCP6_DECLINE_FAIL_NO_LEASE)
.arg(decline->getLabel()).arg(decline_addr->getAddress().toText());
NO_IA, SHOULD_FAIL);
}
+// Test that the released lease cannot be declined.
+TEST_F(DeclineTest, declineAfterRelease) {
+ Dhcp6Client client;
+ uint32_t iaid = 1;
+ client.requestAddress(iaid);
+
+ // Configure DHCP server.
+ configure(DECLINE_CONFIGS[0], *client.getServer());
+ // Perform 4-way exchange to obtain a new lease.
+ client.doSARR();
+ auto leases = client.getLeasesByType(Lease::TYPE_NA);
+ ASSERT_EQ(1, leases.size());
+ EXPECT_EQ(STATUS_Success, client.getStatusCode(iaid));
+
+ // Release the acquired lease.
+ auto lease = LeaseMgrFactory::instance().getLease6(Lease::TYPE_NA, leases[0].addr_);
+ lease->state_ = Lease::STATE_RELEASED;
+ LeaseMgrFactory::instance().updateLease6(lease);
+
+ // Try to decline the released address.
+ ASSERT_NO_THROW(client.doDecline());
+
+ // The address should not be declined. It should still be in the
+ // released state.
+ lease = LeaseMgrFactory::instance().getLease6(Lease::TYPE_NA, lease->addr_);
+ ASSERT_TRUE(lease);
+ EXPECT_EQ(Lease::STATE_RELEASED, lease->state_);
+}
+
+// Test that the released lease cannot be declined.
+TEST_F(DeclineTest, declineAfterExpire) {
+ Dhcp6Client client;
+ uint32_t iaid = 1;
+ client.requestAddress(iaid);
+
+ // Configure DHCP server.
+ configure(DECLINE_CONFIGS[0], *client.getServer());
+ // Perform 4-way exchange to obtain a new lease.
+ client.doSARR();
+ auto leases = client.getLeasesByType(Lease::TYPE_NA);
+ ASSERT_EQ(1, leases.size());
+ EXPECT_EQ(STATUS_Success, client.getStatusCode(iaid));
+
+ // Release the acquired lease.
+ auto lease = LeaseMgrFactory::instance().getLease6(Lease::TYPE_NA, leases[0].addr_);
+ lease->cltt_ -= 7200;
+ LeaseMgrFactory::instance().updateLease6(lease);
+
+ // Try to decline the expired lease.
+ ASSERT_NO_THROW(client.doDecline());
+
+ // The address should not be declined. It should still be in the
+ // default state.
+ lease = LeaseMgrFactory::instance().getLease6(Lease::TYPE_NA, lease->addr_);
+ ASSERT_TRUE(lease);
+ EXPECT_EQ(Lease::STATE_DEFAULT, lease->state_);
+}
+
+// Test that expired-reclaimed lease cannot be declined.
+TEST_F(DeclineTest, declineAfterReclamation) {
+ Dhcp6Client client;
+ uint32_t iaid = 1;
+ client.requestAddress(iaid);
+
+ // Configure DHCP server.
+ configure(DECLINE_CONFIGS[0], *client.getServer());
+ // Perform 4-way exchange to obtain a new lease.
+ client.doSARR();
+ auto leases = client.getLeasesByType(Lease::TYPE_NA);
+ ASSERT_EQ(1, leases.size());
+ EXPECT_EQ(STATUS_Success, client.getStatusCode(iaid));
+
+ // Release the acquired lease.
+ auto lease = LeaseMgrFactory::instance().getLease6(Lease::TYPE_NA, leases[0].addr_);
+ lease->state_ = Lease::STATE_EXPIRED_RECLAIMED;
+ LeaseMgrFactory::instance().updateLease6(lease);
+
+ // Try to decline the reclaimed lease.
+ ASSERT_NO_THROW(client.doDecline());
+
+ // The address should not be declined. It should still be in the
+ // reclaimed state.
+ lease = LeaseMgrFactory::instance().getLease6(Lease::TYPE_NA, lease->addr_);
+ ASSERT_TRUE(lease);
+ EXPECT_EQ(Lease::STATE_EXPIRED_RECLAIMED, lease->state_);
+}
+
+
} // end of anonymous namespace