2
0
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:
Tomek Mrugalski
2015-09-21 14:52:26 +02:00
parent 055c76bb0b
commit f96d8c9dd9
12 changed files with 247 additions and 75 deletions

View File

@@ -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

View File

@@ -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."));

View File

@@ -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

View File

@@ -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

View File

@@ -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);
} }
} }

View File

@@ -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

View File

@@ -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;

View File

@@ -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.

View File

@@ -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};

View File

@@ -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;

View File

@@ -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

View File

@@ -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);