mirror of
https://gitlab.isc.org/isc-projects/kea
synced 2025-09-02 06:55:16 +00:00
[3982] Changes after review
- Lease6::decline() implemented - DUID::generateEmpty() implemented - Unit-tests for Decline (not include address, not include IA_NA) implemented - several comments updated - logging corrected and reworded
This commit is contained in:
@@ -222,21 +222,22 @@ received in Decline message. It's expected that the option will contain an
|
|||||||
address that is being declined. Specific information will be printed in a
|
address that is being declined. Specific information will be printed in a
|
||||||
separate message.
|
separate message.
|
||||||
|
|
||||||
% DHCP6_DECLINE_FAIL_DUID_MISMATCH Client %1 tried to decline address %2, but it belongs to client with DUID %3
|
% DHCP6_DECLINE_FAIL_DUID_MISMATCH Client %1 sent DECLINE for address %2, but it belongs to client with DUID %3
|
||||||
This informational message is printed when a client attempts to decline
|
This informational message is printed when a client attempts to decline
|
||||||
a lease, but that lease belongs to a different client.
|
a lease, but that lease belongs to a different client. The decline request
|
||||||
|
will be rejected.
|
||||||
|
|
||||||
% DHCP6_DECLINE_FAIL_IAID_MISMATCH Client %1 tried to decline address %2, but used a wrong IAID (%3), instead of expected %4
|
% DHCP6_DECLINE_FAIL_IAID_MISMATCH Client %1 sent DECLINE for address %2, but used a wrong IAID (%3), instead of expected %4
|
||||||
This informational message is printed when a client attempts to decline
|
This informational message is printed when a client attempts to decline
|
||||||
a lease. The server has a lease for this address, it belongs to this client,
|
a lease. The server has a lease for this address, it belongs to this client,
|
||||||
but the recorded IAID does not match what client has sent. This means
|
but the recorded IAID does not match what client has sent. This means
|
||||||
the server will reject this Decline.
|
the server will reject this Decline.
|
||||||
|
|
||||||
% DHCP6_DECLINE_FAIL_LEASE_WITHOUT_DUID Client %1 attempted to decline address %2, but the associated lease has no DUID
|
% DHCP6_DECLINE_FAIL_LEASE_WITHOUT_DUID Client %1 sent DECLINE for address %2, but the associated lease has no DUID
|
||||||
This error condition likely indicates database corruption, as every IPv6
|
This error condition likely indicates database corruption, as every IPv6
|
||||||
lease is supposed to have a DUID, even if it is an empty one.
|
lease is supposed to have a DUID, even if it is an empty one.
|
||||||
|
|
||||||
% DHCP6_DECLINE_FAIL_NO_LEASE Client %1 attempted to decline address %2, but there's no lease for it
|
% DHCP6_DECLINE_FAIL_NO_LEASE Client %1 sent DECLINE for address %2, but there's no lease for it
|
||||||
This informational message is printed when a client tried to decline an address,
|
This informational message is printed when a client tried to decline an address,
|
||||||
but the server has no lease for said address. This means that the server's
|
but the server has no lease for said address. This means that the server's
|
||||||
and client's perception of the leases are different. The likely causes
|
and client's perception of the leases are different. The likely causes
|
||||||
@@ -246,7 +247,7 @@ moved to a different location and didn't notice) or possibly an attack
|
|||||||
inform the client that his decline request was rejected and client should
|
inform the client that his decline request was rejected and client should
|
||||||
be able to recover from that.
|
be able to recover from that.
|
||||||
|
|
||||||
% DHCP6_DECLINE_LEASE Address %1 was declined by client %2. The lease will be recovered in %3 seconds.
|
% DHCP6_DECLINE_LEASE Client %1 sent DECLINE for address %2 and the server marked it as declined. The lease will be recovered in %3 seconds.
|
||||||
This informational message indicates that the client leased an address, but
|
This informational message indicates that the client leased an address, but
|
||||||
discovered that it is being used by some other devicea and reported this to the
|
discovered that it is being used by some other devicea and reported this to the
|
||||||
server by sending a Decline message. The server marked the lease as
|
server by sending a Decline message. The server marked the lease as
|
||||||
|
@@ -2675,7 +2675,7 @@ Dhcpv6Srv::declineIA(const Pkt6Ptr& decline, const DuidPtr& duid,
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
Option6IAAddrPtr decline_addr = boost::dynamic_pointer_cast<Option6IAAddr>
|
Option6IAAddrPtr decline_addr = boost::dynamic_pointer_cast<Option6IAAddr>
|
||||||
(ia->getOption(D6O_IAADDR));
|
(opt->second);
|
||||||
if (!decline_addr) {
|
if (!decline_addr) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -2739,9 +2739,9 @@ Dhcpv6Srv::declineIA(const Pkt6Ptr& decline, const DuidPtr& duid,
|
|||||||
LOG_INFO(lease6_logger, DHCP6_DECLINE_FAIL_IAID_MISMATCH)
|
LOG_INFO(lease6_logger, DHCP6_DECLINE_FAIL_IAID_MISMATCH)
|
||||||
.arg(decline->getLabel())
|
.arg(decline->getLabel())
|
||||||
.arg(lease->addr_.toText())
|
.arg(lease->addr_.toText())
|
||||||
.arg(lease->iaid_)
|
.arg(ia->getIAID())
|
||||||
.arg(ia->getIAID());
|
.arg(lease->iaid_);
|
||||||
ia_rsp->addOption(createStatusCode(*decline, *ia_rsp, STATUS_NoBinding,
|
setStatusCode(ia_rsp, createStatusCode(*decline, *ia_rsp, STATUS_NoBinding,
|
||||||
"This is your address, but you used wrong IAID"));
|
"This is your address, but you used wrong IAID"));
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
@@ -2753,9 +2753,8 @@ Dhcpv6Srv::declineIA(const Pkt6Ptr& decline, const DuidPtr& duid,
|
|||||||
|
|
||||||
if (total_addrs == 0) {
|
if (total_addrs == 0) {
|
||||||
setStatusCode(ia_rsp, createStatusCode(*decline, *ia_rsp, STATUS_NoBinding,
|
setStatusCode(ia_rsp, createStatusCode(*decline, *ia_rsp, STATUS_NoBinding,
|
||||||
"No addresses sent in IA_NA."));
|
"No addresses sent in IA_NA"));
|
||||||
general_status = STATUS_NoBinding;
|
general_status = STATUS_NoBinding;
|
||||||
return (ia_rsp);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return (ia_rsp);
|
return (ia_rsp);
|
||||||
@@ -2779,32 +2778,24 @@ Dhcpv6Srv::declineLease(const Pkt6Ptr& decline, const Lease6Ptr lease,
|
|||||||
// the entries. This method does all necessary checks.
|
// the entries. This method does all necessary checks.
|
||||||
createRemovalNameChangeRequest(decline, lease);
|
createRemovalNameChangeRequest(decline, lease);
|
||||||
|
|
||||||
// Bump up the statistics.
|
// Bump up the subnet-specific statistic.
|
||||||
std::stringstream name;
|
StatsMgr::instance().addValue(
|
||||||
name << "subnet[" << lease->subnet_id_ << "].declined-addresses";
|
StatsMgr::generateName("subnet", lease->subnet_id_, "declined-addresses"),
|
||||||
isc::stats::StatsMgr::instance().addValue(name.str(), static_cast<int64_t>(1));
|
static_cast<int64_t>(1));
|
||||||
|
|
||||||
|
// Global declined addresses counter.
|
||||||
|
StatsMgr::instance().addValue("declined-addresses", static_cast<int64_t>(1));
|
||||||
|
|
||||||
// @todo: Call hooks.
|
// @todo: Call hooks.
|
||||||
|
|
||||||
// We need to disassociate the lease from the client. Once we move a lease
|
// We need to disassociate the lease from the client. Once we move a lease
|
||||||
// to declined state, it is no longer associated with the client in any
|
// to declined state, it is no longer associated with the client in any
|
||||||
// way.
|
// way.
|
||||||
vector<uint8_t> empty_duid(1,0);
|
lease->decline(CfgMgr::instance().getCurrentCfg()->getDeclinePeriod());
|
||||||
lease->hwaddr_.reset(new HWAddr());
|
|
||||||
lease->duid_.reset(new DUID(empty_duid));
|
|
||||||
lease->t1_ = 0;
|
|
||||||
lease->t2_ = 0;
|
|
||||||
lease->valid_lft_ = CfgMgr::instance().getCurrentCfg()->getDeclinePeriod();
|
|
||||||
lease->cltt_ = time(NULL);
|
|
||||||
lease->hostname_ = string("");
|
|
||||||
lease->fqdn_fwd_ = false;
|
|
||||||
lease->fqdn_rev_ = false;
|
|
||||||
|
|
||||||
lease->state_ = Lease::STATE_DECLINED;
|
|
||||||
LeaseMgrFactory::instance().updateLease6(lease);
|
LeaseMgrFactory::instance().updateLease6(lease);
|
||||||
|
|
||||||
LOG_INFO(dhcp6_logger, DHCP6_DECLINE_LEASE).arg(lease->addr_.toText())
|
LOG_INFO(dhcp6_logger, DHCP6_DECLINE_LEASE).arg(decline->getLabel())
|
||||||
.arg(decline->getLabel()).arg(lease->valid_lft_);
|
.arg(lease->addr_.toText()).arg(lease->valid_lft_);
|
||||||
|
|
||||||
ia_rsp->addOption(createStatusCode(*decline, *ia_rsp, STATUS_Success,
|
ia_rsp->addOption(createStatusCode(*decline, *ia_rsp, STATUS_Success,
|
||||||
"Lease declined. Hopefully the next one will be better."));
|
"Lease declined. Hopefully the next one will be better."));
|
||||||
|
@@ -263,7 +263,15 @@ protected:
|
|||||||
/// @return Reply message to be sent to the client.
|
/// @return Reply message to be sent to the client.
|
||||||
Pkt6Ptr processRelease(const Pkt6Ptr& release);
|
Pkt6Ptr processRelease(const Pkt6Ptr& release);
|
||||||
|
|
||||||
/// @brief Stub function that will handle incoming Decline.
|
/// @brief Process incoming Decline message.
|
||||||
|
///
|
||||||
|
/// This method processes Decline message. It conducts standard sanity
|
||||||
|
/// checks, creates empty reply and copies the necessary options from
|
||||||
|
/// the client's message. Finally, it calls @ref declineLeases, where
|
||||||
|
/// the actual address processing takes place.
|
||||||
|
///
|
||||||
|
/// @throw RFCViolation if Decline message is invalid (lacking mandatory
|
||||||
|
/// options)
|
||||||
///
|
///
|
||||||
/// @param decline message received from client
|
/// @param decline message received from client
|
||||||
Pkt6Ptr processDecline(const Pkt6Ptr& decline);
|
Pkt6Ptr processDecline(const Pkt6Ptr& decline);
|
||||||
@@ -705,10 +713,10 @@ protected:
|
|||||||
declineLeases(const Pkt6Ptr& decline, Pkt6Ptr& reply,
|
declineLeases(const Pkt6Ptr& decline, Pkt6Ptr& reply,
|
||||||
AllocEngine::ClientContext6& ctx);
|
AllocEngine::ClientContext6& ctx);
|
||||||
|
|
||||||
/// @brief Declines leases in a single IA_NA container
|
/// @brief Declines leases in a single IA_NA option
|
||||||
///
|
///
|
||||||
/// This method iterates over all addresses in this IA_NA, and verifies
|
/// This method iterates over all addresses in this IA_NA, verifies
|
||||||
/// whether it belongs to the client and calls @ref declineLease. If there's
|
/// whether they belong to the client and calls @ref declineLease. If there's
|
||||||
/// an error, general_status (a status put in the top level scope), will be
|
/// an error, general_status (a status put in the top level scope), will be
|
||||||
/// updated.
|
/// updated.
|
||||||
///
|
///
|
||||||
@@ -716,6 +724,7 @@ protected:
|
|||||||
/// @param duid client's duid (used to verify if the client owns the lease)
|
/// @param duid client's duid (used to verify if the client owns the lease)
|
||||||
/// @param general_status [out] status in top-level message (may be updated)
|
/// @param general_status [out] status in top-level message (may be updated)
|
||||||
/// @param ia specific IA_NA option to process.
|
/// @param ia specific IA_NA option to process.
|
||||||
|
/// @return IA_NA option with response (to be included in Reply message)
|
||||||
OptionPtr
|
OptionPtr
|
||||||
declineIA(const Pkt6Ptr& decline, const DuidPtr& duid, int& general_status,
|
declineIA(const Pkt6Ptr& decline, const DuidPtr& duid, int& general_status,
|
||||||
boost::shared_ptr<Option6IA> ia);
|
boost::shared_ptr<Option6IA> ia);
|
||||||
@@ -724,7 +733,8 @@ protected:
|
|||||||
///
|
///
|
||||||
/// This method performs the actual decline and all necessary operations:
|
/// This method performs the actual decline and all necessary operations:
|
||||||
/// - cleans up DNS, if necessary
|
/// - cleans up DNS, if necessary
|
||||||
/// - updates subnet[X].declined-addresses
|
/// - updates subnet[X].declined-addresses (per subnet stat)
|
||||||
|
/// - updates declined-addresses (global stat)
|
||||||
/// - deassociates client information from the lease
|
/// - deassociates client information from the lease
|
||||||
/// - moves the lease to DECLINED state
|
/// - moves the lease to DECLINED state
|
||||||
/// - sets lease expiration time to decline-probation-period
|
/// - sets lease expiration time to decline-probation-period
|
||||||
|
@@ -56,17 +56,19 @@ const char* DECLINE_CONFIGS[] = {
|
|||||||
class DeclineTest : public Dhcpv6MessageTest {
|
class DeclineTest : public Dhcpv6MessageTest {
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
/// @brief Specifies expected outcome
|
||||||
enum ExpectedResult {
|
enum ExpectedResult {
|
||||||
SHOULD_PASS, // pass = accept decline, move lease to declined state.
|
SHOULD_PASS, // pass = accept decline, move lease to declined state.
|
||||||
SHOULD_FAIL // fail = reject the decline
|
SHOULD_FAIL // fail = reject the decline
|
||||||
};
|
};
|
||||||
|
|
||||||
/// @brief Performs 4-way exchange to obtain new lease.
|
/// @brief Specifies what address should the client include in its Decline
|
||||||
///
|
enum AddressInclusion {
|
||||||
/// This is used as a preparatory step for Decline operation.
|
VALID_ADDR, // Client will include its own, valid address
|
||||||
///
|
BOGUS_ADDR, // Client will include an address it doesn't own
|
||||||
/// @param client Client to be used to obtain a lease.
|
NO_ADDR, // Client will send empty IA_NA (without address)
|
||||||
void acquireLease(Dhcp6Client& client);
|
NO_IA // Client will not send IA_NA at all
|
||||||
|
};
|
||||||
|
|
||||||
/// @brief Tests if the acquired lease is or is not declined.
|
/// @brief Tests if the acquired lease is or is not declined.
|
||||||
///
|
///
|
||||||
@@ -74,9 +76,8 @@ public:
|
|||||||
/// @param iaid1 IAID used during lease acquisition
|
/// @param iaid1 IAID used during lease acquisition
|
||||||
/// @param duid2 DUID used during Decline exchange
|
/// @param duid2 DUID used during Decline exchange
|
||||||
/// @param iaid2 IAID used during Decline exchange
|
/// @param iaid2 IAID used during Decline exchange
|
||||||
/// @param declient_correct_address specify if the valid address should
|
/// @param addr_type specify what sort of address the client should
|
||||||
/// be used (true = use the address client actually received,
|
/// include (its own, a bogus one or no address at all)
|
||||||
/// false = use a different address)
|
|
||||||
/// @param expected_result SHOULD_PASS if the lease is expected to
|
/// @param expected_result SHOULD_PASS if the lease is expected to
|
||||||
/// be successfully declined, or SHOULD_FAIL if the lease is expected
|
/// be successfully declined, or SHOULD_FAIL if the lease is expected
|
||||||
/// to not be declined.
|
/// to not be declined.
|
||||||
@@ -84,7 +85,7 @@ public:
|
|||||||
const uint32_t iaid1,
|
const uint32_t iaid1,
|
||||||
const std::string& duid2,
|
const std::string& duid2,
|
||||||
const uint32_t iaid2,
|
const uint32_t iaid2,
|
||||||
bool decline_correct_address,
|
AddressInclusion addr_type,
|
||||||
ExpectedResult expected_result);
|
ExpectedResult expected_result);
|
||||||
|
|
||||||
/// @brief Constructor.
|
/// @brief Constructor.
|
||||||
@@ -104,8 +105,11 @@ DeclineTest::acquireAndDecline(const std::string& duid1,
|
|||||||
const uint32_t iaid1,
|
const uint32_t iaid1,
|
||||||
const std::string& duid2,
|
const std::string& duid2,
|
||||||
const uint32_t iaid2,
|
const uint32_t iaid2,
|
||||||
bool decline_correct_address,
|
AddressInclusion addr_type,
|
||||||
ExpectedResult expected_result) {
|
ExpectedResult expected_result) {
|
||||||
|
// Set this global statistic explicitly to zero.
|
||||||
|
StatsMgr::instance().setValue("declined-addresses", static_cast<int64_t>(0));
|
||||||
|
|
||||||
Dhcp6Client client;
|
Dhcp6Client client;
|
||||||
client.setDUID(duid1);
|
client.setDUID(duid1);
|
||||||
client.useNA(iaid1);
|
client.useNA(iaid1);
|
||||||
@@ -117,11 +121,13 @@ DeclineTest::acquireAndDecline(const std::string& duid1,
|
|||||||
const Subnet6Collection* subnets =
|
const Subnet6Collection* subnets =
|
||||||
CfgMgr::instance().getCurrentCfg()->getCfgSubnets6()->getAll();
|
CfgMgr::instance().getCurrentCfg()->getCfgSubnets6()->getAll();
|
||||||
ASSERT_EQ(1, subnets->size());
|
ASSERT_EQ(1, subnets->size());
|
||||||
std::stringstream name;
|
|
||||||
name << "subnet[" << subnets->at(0)->getID() << "].declined-addresses";
|
// Let's generate the subnet specific statistic
|
||||||
|
std::string name = StatsMgr::generateName("subnet", subnets->at(0)->getID(),
|
||||||
|
"declined-addresses");
|
||||||
|
|
||||||
// Set this statistic explicitly to zero.
|
// Set this statistic explicitly to zero.
|
||||||
isc::stats::StatsMgr::instance().setValue(name.str(), static_cast<int64_t>(0));
|
StatsMgr::instance().setValue(name, static_cast<int64_t>(0));
|
||||||
|
|
||||||
// Perform 4-way exchange.
|
// Perform 4-way exchange.
|
||||||
ASSERT_NO_THROW(client.doSARR());
|
ASSERT_NO_THROW(client.doSARR());
|
||||||
@@ -134,17 +140,34 @@ DeclineTest::acquireAndDecline(const std::string& duid1,
|
|||||||
// Remember the acquired address.
|
// Remember the acquired address.
|
||||||
IOAddress acquired_address = leases_client_na[0].addr_;
|
IOAddress acquired_address = leases_client_na[0].addr_;
|
||||||
|
|
||||||
// Check the declined-addresses statistic before the Decline operation.
|
// Check the declined-addresses (subnet) before the Decline operation.
|
||||||
ObservationPtr declined_cnt = StatsMgr::instance().getObservation(name.str());
|
ObservationPtr declined_cnt = StatsMgr::instance().getObservation(name);
|
||||||
ASSERT_TRUE(declined_cnt);
|
ASSERT_TRUE(declined_cnt);
|
||||||
uint64_t before = declined_cnt->getInteger().first;
|
uint64_t before = declined_cnt->getInteger().first;
|
||||||
|
|
||||||
// Let's tamper with the address if necessary.
|
// Check the global declined-addresses statistic before the Decline.
|
||||||
if (!decline_correct_address) {
|
ObservationPtr declined_global = StatsMgr::instance()
|
||||||
|
.getObservation("declined-addresses");
|
||||||
|
ASSERT_TRUE(declined_global);
|
||||||
|
uint64_t before_global = declined_cnt->getInteger().first;
|
||||||
|
|
||||||
|
// Let's tamper with the address if necessary.
|
||||||
|
switch (addr_type) {
|
||||||
|
case VALID_ADDR:
|
||||||
|
// Nothing to do, client will do its job correctly by default
|
||||||
|
break;
|
||||||
|
case BOGUS_ADDR:
|
||||||
// Simple increase by one.
|
// Simple increase by one.
|
||||||
client.config_.leases_[0].addr_ =
|
client.config_.leases_[0].addr_ =
|
||||||
IOAddress::increase(client.config_.leases_[0].addr_);
|
IOAddress::increase(client.config_.leases_[0].addr_);
|
||||||
|
break;
|
||||||
|
case NO_ADDR:
|
||||||
|
// Tell the client to not include an address in its IA_NA
|
||||||
|
client.includeAddress(false);
|
||||||
|
break;
|
||||||
|
case NO_IA:
|
||||||
|
// Tell the client to not include IA_NA at all
|
||||||
|
client.useNA(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Use the second duid
|
// Use the second duid
|
||||||
@@ -161,10 +184,14 @@ DeclineTest::acquireAndDecline(const std::string& duid1,
|
|||||||
acquired_address);
|
acquired_address);
|
||||||
ASSERT_TRUE(lease);
|
ASSERT_TRUE(lease);
|
||||||
|
|
||||||
declined_cnt = StatsMgr::instance().getObservation(name.str());
|
declined_cnt = StatsMgr::instance().getObservation(name);
|
||||||
ASSERT_TRUE(declined_cnt);
|
ASSERT_TRUE(declined_cnt);
|
||||||
uint64_t after = declined_cnt->getInteger().first;
|
uint64_t after = declined_cnt->getInteger().first;
|
||||||
|
|
||||||
|
declined_global = StatsMgr::instance().getObservation("declined-addresses");
|
||||||
|
ASSERT_TRUE(declined_global);
|
||||||
|
uint64_t after_global = declined_global->getInteger().first;
|
||||||
|
|
||||||
// We check if the decline process was successful by checking if the
|
// We check if the decline process was successful by checking if the
|
||||||
// lease is in the database and what is its state.
|
// lease is in the database and what is its state.
|
||||||
if (expected_result == SHOULD_PASS) {
|
if (expected_result == SHOULD_PASS) {
|
||||||
@@ -173,6 +200,7 @@ DeclineTest::acquireAndDecline(const std::string& duid1,
|
|||||||
// The decline succeded, so the declined-addresses statistic should
|
// The decline succeded, so the declined-addresses statistic should
|
||||||
// be increased by one
|
// be increased by one
|
||||||
EXPECT_EQ(after, before + 1);
|
EXPECT_EQ(after, before + 1);
|
||||||
|
EXPECT_EQ(after_global, before_global + 1);
|
||||||
} else {
|
} else {
|
||||||
// the decline was supposed, to be rejected.
|
// the decline was supposed, to be rejected.
|
||||||
EXPECT_EQ(Lease::STATE_DEFAULT, lease->state_);
|
EXPECT_EQ(Lease::STATE_DEFAULT, lease->state_);
|
||||||
@@ -180,6 +208,7 @@ DeclineTest::acquireAndDecline(const std::string& duid1,
|
|||||||
// The decline failed, so the declined-addresses should be the same
|
// The decline failed, so the declined-addresses should be the same
|
||||||
// as before
|
// as before
|
||||||
EXPECT_EQ(before, after);
|
EXPECT_EQ(before, after);
|
||||||
|
EXPECT_EQ(before_global, after_global);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -187,37 +216,59 @@ DeclineTest::acquireAndDecline(const std::string& duid1,
|
|||||||
TEST_F(DeclineTest, basic) {
|
TEST_F(DeclineTest, basic) {
|
||||||
acquireAndDecline("01:02:03:04:05:06", 1234,
|
acquireAndDecline("01:02:03:04:05:06", 1234,
|
||||||
"01:02:03:04:05:06", 1234,
|
"01:02:03:04:05:06", 1234,
|
||||||
true, SHOULD_PASS);
|
VALID_ADDR, SHOULD_PASS);
|
||||||
}
|
}
|
||||||
|
|
||||||
// This test verifies the decline is rejected in the following case:
|
// This test verifies the decline is rejected in the following case:
|
||||||
// - Client acquires new lease using duid, iaid
|
// - Client acquires new lease using duid, iaid
|
||||||
// - Client sends the DHCPDECLINE with duid, iaid, but uses wrong address.
|
// - Client sends the DECLINE with duid, iaid, but uses wrong address.
|
||||||
// - The server rejects Decline due to address mismatch
|
// - The server rejects Decline due to address mismatch
|
||||||
TEST_F(DeclineTest, addressMismatch) {
|
TEST_F(DeclineTest, addressMismatch) {
|
||||||
acquireAndDecline("01:02:03:04:05:06", 1234,
|
acquireAndDecline("01:02:03:04:05:06", 1234,
|
||||||
"01:02:03:04:05:06", 1234,
|
"01:02:03:04:05:06", 1234,
|
||||||
false, SHOULD_FAIL);
|
BOGUS_ADDR, SHOULD_FAIL);
|
||||||
}
|
}
|
||||||
|
|
||||||
// This test verifies the decline is rejected in the following case:
|
// This test verifies the decline is rejected in the following case:
|
||||||
// - Client acquires new lease using duid, iaid1
|
// - Client acquires new lease using duid, iaid1
|
||||||
// - Client sends the DHCPDECLINE with duid, iaid2
|
// - Client sends the DECLINE with duid, iaid2
|
||||||
// - The server rejects Decline due to IAID mismatch
|
// - The server rejects Decline due to IAID mismatch
|
||||||
TEST_F(DeclineTest, iaidMismatch) {
|
TEST_F(DeclineTest, iaidMismatch) {
|
||||||
acquireAndDecline("01:02:03:04:05:06", 1234,
|
acquireAndDecline("01:02:03:04:05:06", 1234,
|
||||||
"01:02:03:04:05:06", 1235,
|
"01:02:03:04:05:06", 1235,
|
||||||
true, SHOULD_FAIL);
|
VALID_ADDR, SHOULD_FAIL);
|
||||||
}
|
}
|
||||||
|
|
||||||
// This test verifies the decline correctness in the following case:
|
// This test verifies the decline correctness in the following case:
|
||||||
// - Client acquires new lease using duid1, iaid
|
// - Client acquires new lease using duid1, iaid
|
||||||
// - Client sends the DHCPDECLINE using duid2, iaid
|
// - Client sends the DECLINE using duid2, iaid
|
||||||
// - The server rejects the Decline due to DUID mismatch
|
// - The server rejects the Decline due to DUID mismatch
|
||||||
TEST_F(DeclineTest, duidMismatch) {
|
TEST_F(DeclineTest, duidMismatch) {
|
||||||
acquireAndDecline("01:02:03:04:05:06", 1234,
|
acquireAndDecline("01:02:03:04:05:06", 1234,
|
||||||
"01:02:03:04:05:07", 1234,
|
"01:02:03:04:05:07", 1234,
|
||||||
true, SHOULD_FAIL);
|
VALID_ADDR, SHOULD_FAIL);
|
||||||
|
}
|
||||||
|
|
||||||
|
// This test verifies the decline correctness in the following case:
|
||||||
|
// - Client acquires new lease using duid1, iaid
|
||||||
|
// - Client sends the DECLINE using valid duid/iaid, but does not
|
||||||
|
// include the address in it
|
||||||
|
// - The server rejects the Decline due to missing address
|
||||||
|
TEST_F(DeclineTest, noAddrsSent) {
|
||||||
|
acquireAndDecline("01:02:03:04:05:06", 1234,
|
||||||
|
"01:02:03:04:05:06", 1234,
|
||||||
|
NO_ADDR, SHOULD_FAIL);
|
||||||
|
}
|
||||||
|
|
||||||
|
// This test verifies the decline correctness in the following case:
|
||||||
|
// - Client acquires new lease using duid1, iaid
|
||||||
|
// - Client sends the DECLINE using valid duid, but does not
|
||||||
|
// include IA_NA at all
|
||||||
|
// - The server rejects the Decline due to missing IA_NA
|
||||||
|
TEST_F(DeclineTest, noIAs) {
|
||||||
|
acquireAndDecline("01:02:03:04:05:06", 1234,
|
||||||
|
"01:02:03:04:05:06", 1234,
|
||||||
|
NO_IA, SHOULD_FAIL);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // end of anonymous namespace
|
} // end of anonymous namespace
|
||||||
|
@@ -96,7 +96,8 @@ Dhcp6Client::Dhcp6Client() :
|
|||||||
prefix_hint_(),
|
prefix_hint_(),
|
||||||
fqdn_(),
|
fqdn_(),
|
||||||
na_iaid_(1234),
|
na_iaid_(1234),
|
||||||
pd_iaid_(5678) {
|
pd_iaid_(5678),
|
||||||
|
include_address_(true) {
|
||||||
}
|
}
|
||||||
|
|
||||||
Dhcp6Client::Dhcp6Client(boost::shared_ptr<NakedDhcpv6Srv>& srv) :
|
Dhcp6Client::Dhcp6Client(boost::shared_ptr<NakedDhcpv6Srv>& srv) :
|
||||||
@@ -117,7 +118,8 @@ Dhcp6Client::Dhcp6Client(boost::shared_ptr<NakedDhcpv6Srv>& srv) :
|
|||||||
prefix_hint_(),
|
prefix_hint_(),
|
||||||
fqdn_(),
|
fqdn_(),
|
||||||
na_iaid_(1234),
|
na_iaid_(1234),
|
||||||
pd_iaid_(5678) {
|
pd_iaid_(5678),
|
||||||
|
include_address_(true) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -554,6 +556,11 @@ void
|
|||||||
Dhcp6Client::generateIAFromLeases(const Pkt6Ptr& query) {
|
Dhcp6Client::generateIAFromLeases(const Pkt6Ptr& query) {
|
||||||
/// @todo: add support for IAPREFIX here.
|
/// @todo: add support for IAPREFIX here.
|
||||||
|
|
||||||
|
if (!use_na_) {
|
||||||
|
// If we're told to not use IA_NA at all, there's nothing to be done here
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
for (std::vector<Lease6>::const_iterator lease = config_.leases_.begin();
|
for (std::vector<Lease6>::const_iterator lease = config_.leases_.begin();
|
||||||
lease != config_.leases_.end(); ++lease) {
|
lease != config_.leases_.end(); ++lease) {
|
||||||
if (lease->type_ != Lease::TYPE_NA) {
|
if (lease->type_ != Lease::TYPE_NA) {
|
||||||
@@ -562,8 +569,10 @@ Dhcp6Client::generateIAFromLeases(const Pkt6Ptr& query) {
|
|||||||
|
|
||||||
Option6IAPtr ia(new Option6IA(D6O_IA_NA, lease->iaid_));
|
Option6IAPtr ia(new Option6IA(D6O_IA_NA, lease->iaid_));
|
||||||
|
|
||||||
ia->addOption(Option6IAAddrPtr(new Option6IAAddr(D6O_IAADDR,
|
if (include_address_) {
|
||||||
|
ia->addOption(OptionPtr(new Option6IAAddr(D6O_IAADDR,
|
||||||
lease->addr_, lease->preferred_lft_, lease->valid_lft_)));
|
lease->addr_, lease->preferred_lft_, lease->valid_lft_)));
|
||||||
|
}
|
||||||
query->addOption(ia);
|
query->addOption(ia);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -500,6 +500,14 @@ public:
|
|||||||
use_client_id_ = send;
|
use_client_id_ = send;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// @brief Controls whether the client should send an addres in IA_NA
|
||||||
|
///
|
||||||
|
/// @todo: For now, this flag is only used in Decline
|
||||||
|
/// @param send should the address be included?
|
||||||
|
void includeAddress(const bool send) {
|
||||||
|
include_address_ = send;
|
||||||
|
}
|
||||||
|
|
||||||
/// @brief Specifies if the Rapid Commit option should be included in
|
/// @brief Specifies if the Rapid Commit option should be included in
|
||||||
/// the Solicit message.
|
/// the Solicit message.
|
||||||
///
|
///
|
||||||
@@ -751,6 +759,12 @@ private:
|
|||||||
uint32_t na_iaid_;
|
uint32_t na_iaid_;
|
||||||
/// @brief IAID used by the client when requesting prefix delegation.
|
/// @brief IAID used by the client when requesting prefix delegation.
|
||||||
uint32_t pd_iaid_;
|
uint32_t pd_iaid_;
|
||||||
|
|
||||||
|
/// @brief Determines if the client will include address in the messages
|
||||||
|
/// it sends.
|
||||||
|
///
|
||||||
|
/// @todo this flag is currently supported in Decline only.
|
||||||
|
bool include_address_;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // end of namespace isc::dhcp::test
|
} // end of namespace isc::dhcp::test
|
||||||
|
@@ -123,6 +123,18 @@ DUID::fromText(const std::string& text) {
|
|||||||
return DUID(binary);
|
return DUID(binary);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DuidPtr
|
||||||
|
DUID::generateEmpty() {
|
||||||
|
|
||||||
|
// Technically this is a one byte DUID with value of 0. However, we do have
|
||||||
|
// a number of safety checks against invalid duids (too long or empty) and
|
||||||
|
// we should keep them. Therefore "empty" means a single byte with value of 0.
|
||||||
|
std::vector<uint8_t> empty_duid(1,0);
|
||||||
|
|
||||||
|
DuidPtr duid(new DUID(empty_duid));
|
||||||
|
return (duid);
|
||||||
|
}
|
||||||
|
|
||||||
std::string DUID::toText() const {
|
std::string DUID::toText() const {
|
||||||
std::stringstream tmp;
|
std::stringstream tmp;
|
||||||
tmp << std::hex;
|
tmp << std::hex;
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
// Copyright (C) 2012-2014 Internet Systems Consortium, Inc. ("ISC")
|
// Copyright (C) 2012-2015 Internet Systems Consortium, Inc. ("ISC")
|
||||||
//
|
//
|
||||||
// Permission to use, copy, modify, and/or distribute this software for any
|
// Permission to use, copy, modify, and/or distribute this software for any
|
||||||
// purpose with or without fee is hereby granted, provided that the above
|
// purpose with or without fee is hereby granted, provided that the above
|
||||||
@@ -25,6 +25,10 @@
|
|||||||
namespace isc {
|
namespace isc {
|
||||||
namespace dhcp {
|
namespace dhcp {
|
||||||
|
|
||||||
|
/// @brief Shared pointer to a DUID
|
||||||
|
class DUID;
|
||||||
|
typedef boost::shared_ptr<DUID> DuidPtr;
|
||||||
|
|
||||||
/// @brief Holds DUID (DHCPv6 Unique Identifier)
|
/// @brief Holds DUID (DHCPv6 Unique Identifier)
|
||||||
///
|
///
|
||||||
/// This class holds DUID, that is used in client-id, server-id and
|
/// This class holds DUID, that is used in client-id, server-id and
|
||||||
@@ -66,6 +70,18 @@ class DUID {
|
|||||||
/// @return A reference to a vector holding a DUID.
|
/// @return A reference to a vector holding a DUID.
|
||||||
const std::vector<uint8_t>& getDuid() const;
|
const std::vector<uint8_t>& getDuid() const;
|
||||||
|
|
||||||
|
|
||||||
|
/// @brief Returns an instance of empty DUID
|
||||||
|
///
|
||||||
|
/// In general, empty DUID is not allowed. The only case where it is really
|
||||||
|
/// valid is to designate declined IPv6 Leases. We have a broad assumption
|
||||||
|
/// that the Lease->duid_ must always be set. However, declined lease
|
||||||
|
/// doesn't have any DUID associated with it. Hence we need a way to
|
||||||
|
/// indicate that fact.
|
||||||
|
///
|
||||||
|
/// @return a smart pointer to an empty DUID
|
||||||
|
static DuidPtr generateEmpty();
|
||||||
|
|
||||||
/// @brief Returns the DUID type
|
/// @brief Returns the DUID type
|
||||||
DUIDType getType() const;
|
DUIDType getType() const;
|
||||||
|
|
||||||
@@ -111,9 +127,6 @@ class DUID {
|
|||||||
std::vector<uint8_t> duid_;
|
std::vector<uint8_t> duid_;
|
||||||
};
|
};
|
||||||
|
|
||||||
/// @brief Shared pointer to a DUID
|
|
||||||
typedef boost::shared_ptr<DUID> DuidPtr;
|
|
||||||
|
|
||||||
/// @brief Forward declaration to the @c ClientId class.
|
/// @brief Forward declaration to the @c ClientId class.
|
||||||
class ClientId;
|
class ClientId;
|
||||||
/// @brief Shared pointer to a Client ID.
|
/// @brief Shared pointer to a Client ID.
|
||||||
|
@@ -165,6 +165,19 @@ TEST(DuidTest, toText) {
|
|||||||
EXPECT_EQ("00:01:02:03:04:ff:fe", duid.toText());
|
EXPECT_EQ("00:01:02:03:04:ff:fe", duid.toText());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This test verifies that empty DUID returns proper value
|
||||||
|
TEST(DuidTest, empty) {
|
||||||
|
DuidPtr empty;
|
||||||
|
EXPECT_NO_THROW(empty = DUID::generateEmpty());
|
||||||
|
|
||||||
|
// This method must return something
|
||||||
|
ASSERT_TRUE(empty);
|
||||||
|
|
||||||
|
// Ok, technically empty is not really empty, it's just a single
|
||||||
|
// byte with value of 0.
|
||||||
|
EXPECT_EQ("00", empty->toText());
|
||||||
|
}
|
||||||
|
|
||||||
// This test checks if the comparison operators are sane.
|
// This test checks if the comparison operators are sane.
|
||||||
TEST(DuidTest, operators) {
|
TEST(DuidTest, operators) {
|
||||||
uint8_t data1[] = {0, 1, 2, 3, 4, 5, 6};
|
uint8_t data1[] = {0, 1, 2, 3, 4, 5, 6};
|
||||||
|
@@ -261,6 +261,21 @@ Lease6::getDuidVector() const {
|
|||||||
return (duid_->getDuid());
|
return (duid_->getDuid());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Lease6::decline(uint32_t probation_period) {
|
||||||
|
hwaddr_.reset();
|
||||||
|
duid_ = DUID::generateEmpty();
|
||||||
|
t1_ = 0;
|
||||||
|
t2_ = 0;
|
||||||
|
preferred_lft_ = 0;
|
||||||
|
valid_lft_ = probation_period;
|
||||||
|
cltt_ = time(NULL);
|
||||||
|
hostname_ = string("");
|
||||||
|
fqdn_fwd_ = false;
|
||||||
|
fqdn_rev_ = false;
|
||||||
|
state_ = Lease::STATE_DECLINED;
|
||||||
|
}
|
||||||
|
|
||||||
std::string
|
std::string
|
||||||
Lease6::toText() const {
|
Lease6::toText() const {
|
||||||
ostringstream stream;
|
ostringstream stream;
|
||||||
|
@@ -495,6 +495,13 @@ struct Lease6 : public Lease {
|
|||||||
/// @return A reference to a vector holding a DUID.
|
/// @return A reference to a vector holding a DUID.
|
||||||
const std::vector<uint8_t>& getDuidVector() const;
|
const std::vector<uint8_t>& getDuidVector() const;
|
||||||
|
|
||||||
|
/// @brief Sets IPv6 lease to declined state.
|
||||||
|
///
|
||||||
|
/// See @ref Lease::decline for detailed description.
|
||||||
|
///
|
||||||
|
/// @param probation_period valid lifetime will be set to this value
|
||||||
|
void decline(uint32_t probation_period);
|
||||||
|
|
||||||
/// @brief Compare two leases for equality
|
/// @brief Compare two leases for equality
|
||||||
///
|
///
|
||||||
/// @param other lease6 object with which to compare
|
/// @param other lease6 object with which to compare
|
||||||
|
@@ -741,6 +741,42 @@ TEST(Lease6Test, getDuidVector) {
|
|||||||
EXPECT_TRUE(returned_vec == duid_vec);
|
EXPECT_TRUE(returned_vec == duid_vec);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This test verifies if the IPv6 lease can be declined properly.
|
||||||
|
TEST(Lease6Test, decline) {
|
||||||
|
|
||||||
|
uint8_t llt[] = {0, 1, 2, 3, 4, 5, 6, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf};
|
||||||
|
DuidPtr duid(new DUID(llt, sizeof(llt)));
|
||||||
|
|
||||||
|
HWAddrPtr hwaddr(new HWAddr(HWADDR, sizeof(HWADDR), HTYPE_ETHER));
|
||||||
|
|
||||||
|
// Let's create a lease for 2001:db8::1, DUID, iaid=1234,
|
||||||
|
// t1=1000, t2=2000, pref=3000, valid=4000, subnet-id = 1
|
||||||
|
Lease6 lease(Lease::TYPE_NA, IOAddress("2001:db8::1"), duid,
|
||||||
|
1234, 3000, 4000, 1000, 2000, 1, hwaddr);
|
||||||
|
lease.cltt_ = 12345678;
|
||||||
|
lease.hostname_ = "foo.example.org";
|
||||||
|
lease.fqdn_fwd_ = true;
|
||||||
|
lease.fqdn_rev_ = true;
|
||||||
|
|
||||||
|
time_t now = time(NULL);
|
||||||
|
|
||||||
|
// Move the lease to declined state and set probation-period to 123 seconds
|
||||||
|
lease.decline(123);
|
||||||
|
|
||||||
|
ASSERT_FALSE(lease.hwaddr_);
|
||||||
|
EXPECT_EQ(0, lease.t1_);
|
||||||
|
EXPECT_EQ(0, lease.t2_);
|
||||||
|
EXPECT_EQ(0, lease.preferred_lft_);
|
||||||
|
|
||||||
|
EXPECT_TRUE(now <= lease.cltt_);
|
||||||
|
EXPECT_TRUE(lease.cltt_ <= now + 1);
|
||||||
|
EXPECT_EQ("", lease.hostname_);
|
||||||
|
EXPECT_FALSE(lease.fqdn_fwd_);
|
||||||
|
EXPECT_FALSE(lease.fqdn_rev_);
|
||||||
|
EXPECT_EQ(Lease::STATE_DECLINED, lease.state_);
|
||||||
|
EXPECT_EQ(123, lease.valid_lft_);
|
||||||
|
}
|
||||||
|
|
||||||
// Verify the behavior of the function which checks FQDN data for equality.
|
// Verify the behavior of the function which checks FQDN data for equality.
|
||||||
TEST(Lease6Test, hasIdenticalFqdn) {
|
TEST(Lease6Test, hasIdenticalFqdn) {
|
||||||
Lease6 lease = createLease6("myhost.example.com.", true, true);
|
Lease6 lease = createLease6("myhost.example.com.", true, true);
|
||||||
|
Reference in New Issue
Block a user