BIND 10 master, updated. 60b979b7088f9e282b173c8d71792e2c4b20b57c [master] Merge branch 'trac2326' (DHCPv6 release)
BIND 10 source code commits
bind10-changes at lists.isc.org
Thu Jan 3 13:55:03 UTC 2013
The branch, master has been updated
via 60b979b7088f9e282b173c8d71792e2c4b20b57c (commit)
via 0974318566abe08d0702ddd185156842c6642424 (commit)
via 31147f0f82fd1e1b8ead164153599269822517ea (commit)
via 8679b4053024172db8e3d55b7ed50a855efc77c0 (commit)
via c864447b8ec187264fac032be1561c77bb3103b6 (commit)
via 72beaf8964363734d4f5e7b4b11ae7b8b4b5557c (commit)
via 34cb2bf92262addf0fb401365c23773dee3f3e89 (commit)
via 6ce0831748423ab48611785f29ee999beeaf8322 (commit)
via 32b6b02bc06bbf0303639964f3544e9cba4b138d (commit)
via 318530edbf905ff288f527ef73bb88da4c57b548 (commit)
from bef01123fb5dfaee927bc58da465109240811a18 (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commit 60b979b7088f9e282b173c8d71792e2c4b20b57c
Merge: bef0112 0974318
Author: Tomek Mrugalski <tomasz at isc.org>
Date: Thu Jan 3 14:53:59 2013 +0100
[master] Merge branch 'trac2326' (DHCPv6 release)
Conflicts:
ChangeLog
src/bin/dhcp6/dhcp6_messages.mes
-----------------------------------------------------------------------
Summary of changes:
ChangeLog | 5 +
src/bin/dhcp6/dhcp6_messages.mes | 43 ++++
src/bin/dhcp6/dhcp6_srv.cc | 181 +++++++++++++-
src/bin/dhcp6/dhcp6_srv.h | 39 ++-
src/bin/dhcp6/tests/dhcp6_srv_unittest.cc | 373 ++++++++++++++++++++++-------
5 files changed, 554 insertions(+), 87 deletions(-)
-----------------------------------------------------------------------
diff --git a/ChangeLog b/ChangeLog
index 0be10ce..7a02a50 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,8 @@
+537. [func] tomek
+ b10-dhcp6: Support for RELEASE message has been added. Clients
+ are now able to release their non-temporary IPv6 addresses.
+ (Trac #2326, git 0974318566abe08d0702ddd185156842c6642424)
+
536. [build] jinmei
Detect a build issue on FreeBSD with g++ 4.2 and Boost installed via
FreeBSD ports at ./configure time. This seems to be a bug of
diff --git a/src/bin/dhcp6/dhcp6_messages.mes b/src/bin/dhcp6/dhcp6_messages.mes
index eb8923e..1913bb5 100644
--- a/src/bin/dhcp6/dhcp6_messages.mes
+++ b/src/bin/dhcp6/dhcp6_messages.mes
@@ -65,6 +65,13 @@ This informational message is printed every time DHCPv6 is started.
It indicates what database backend type is being to store lease and
other information.
+% DHCP6_LEASE_WITHOUT_DUID lease for address %1 does not have a DUID
+This error message indicates a database consistency failure. The lease
+database has an entry indicating that the given address is in use,
+but the lease does not contain any client identification. This is most
+likely due to a software error: please raise a bug report. As a temporary
+workaround, manually remove the lease entry from the database.
+
% DHCP6_LEASE_ADVERT lease %1 advertised (client duid=%2, iaid=%3)
This debug message indicates that the server successfully advertised
a lease. It is up to the client to choose one server out of the
@@ -86,6 +93,37 @@ This message indicates that the server failed to grant (in response to
received REQUEST) a lease for a given client. There may be many reasons for
such failure. Each specific failure is logged in a separate log entry.
+% DHCP6_RELEASE address %1 belonging to client duid=%2, iaid=%3 was released properly.
+This debug message indicates that an address was released properly. It
+is a normal operation during client shutdown.
+
+% DHCP6_RELEASE_FAIL failed to remove lease for address %1 for duid=%2, iaid=%3
+This error message indicates that the software failed to remove a
+lease from the lease database. It probably due to an error during a
+database operation: resolution will most likely require administrator
+intervention (e.g. check if DHCP process has sufficient privileges to
+update the database). It may also be triggered if a lease was manually
+removed from the database during RELEASE message processing.
+
+% DHCP6_RELEASE_FAIL_WRONG_DUID client (duid=%1) tried to release address %2, but it belongs to client (duid=%3)
+This warning message indicates that client tried to release an address
+that belongs to a different client. This should not happen in normal
+circumstances and may indicate a misconfiguration of the client. However,
+since the client releasing the address will stop using it anyway, there
+is a good chance that the situation will correct itself.
+
+% DHCP6_RELEASE_FAIL_WRONG_IAID client (duid=%1) tried to release address %2, but it used wrong IAID (expected %3, but got %4)
+This warning message indicates that client tried to release an address
+that does belong to it, but the address was expected to be in a different
+IA (identity association) container. This probably means that the client's
+support for multiple addresses is flawed.
+
+% DHCP6_RELEASE_MISSING_CLIENTID client (address=%1) sent RELEASE message without mandatory client-id
+This warning message indicates that client sent RELEASE message without
+mandatory client-id option. This is most likely caused by a buggy client
+(or a relay that malformed forwarded message). This request will not be
+processed and a response with error status code will be sent back.
+
% DHCP6_NOT_RUNNING IPv6 DHCP server is not running
A warning message is issued when an attempt is made to shut down the
IPv6 DHCP server but it is not running.
@@ -216,3 +254,8 @@ recently and does not recognize its well-behaving clients. This is more
probable if you see many such messages. Clients will recover from this,
but they will most likely get a different IP addresses and experience
a brief service interruption.
+
+% DHCP6_UNKNOWN_RELEASE received RELEASE from unknown client (duid=%1, iaid=%2)
+This warning message is printed when client attempts to release a lease,
+but no such lease is known by the server. See DHCP6_UNKNOWN_RENEW for
+possible reasons for such behavior.
diff --git a/src/bin/dhcp6/dhcp6_srv.cc b/src/bin/dhcp6/dhcp6_srv.cc
index a50be03..ad8fb8c 100644
--- a/src/bin/dhcp6/dhcp6_srv.cc
+++ b/src/bin/dhcp6/dhcp6_srv.cc
@@ -436,6 +436,8 @@ void Dhcpv6Srv::assignLeases(const Pkt6Ptr& question, Pkt6Ptr& answer) {
// We need to allocate addresses for all IA_NA options in the client's
// question (i.e. SOLICIT or REQUEST) message.
+ // @todo add support for IA_TA
+ // @todo add support for IA_PD
// We need to select a subnet the client is connected in.
Subnet6Ptr subnet = selectSubnet(question);
@@ -604,7 +606,7 @@ OptionPtr Dhcpv6Srv::renewIA_NA(const Subnet6Ptr& subnet, const DuidPtr& duid,
boost::shared_ptr<Option6IA> ia_rsp(new Option6IA(D6O_IA_NA, ia->getIAID()));
// Insert status code NoAddrsAvail.
- ia_rsp->addOption(createStatusCode(STATUS_NoAddrsAvail,
+ ia_rsp->addOption(createStatusCode(STATUS_NoBinding,
"Sorry, no known leases for this duid/iaid."));
LOG_DEBUG(dhcp6_logger, DBG_DHCP6_DETAIL, DHCP6_UNKNOWN_RENEW)
@@ -640,6 +642,8 @@ void Dhcpv6Srv::renewLeases(const Pkt6Ptr& renew, Pkt6Ptr& reply) {
// We need to renew addresses for all IA_NA options in the client's
// RENEW message.
+ // @todo add support for IA_TA
+ // @todo add support for IA_PD
// We need to select a subnet the client is connected in.
Subnet6Ptr subnet = selectSubnet(renew);
@@ -688,11 +692,176 @@ void Dhcpv6Srv::renewLeases(const Pkt6Ptr& renew, Pkt6Ptr& reply) {
break;
}
}
+}
+
+void Dhcpv6Srv::releaseLeases(const Pkt6Ptr& release, Pkt6Ptr& reply) {
+
+ // We need to release addresses for all IA_NA options in the client's
+ // RELEASE message.
+ // @todo Add support for IA_TA
+ // @todo Add support for IA_PD
+ // @todo Consider supporting more than one address in a single IA_NA.
+ // That was envisaged by RFC3315, but it never happened. The only
+ // software that supports that is Dibbler, but its author seriously doubts
+ // if anyone is really using it. Clients that want more than one address
+ // just include more instances of IA_NA options.
+
+ // Let's find client's DUID. Client is supposed to include its client-id
+ // option almost all the time (the only exception is an anonymous inf-request,
+ // but that is mostly a theoretical case). Our allocation engine needs DUID
+ // and will refuse to allocate anything to anonymous clients.
+ OptionPtr opt_duid = release->getOption(D6O_CLIENTID);
+ if (!opt_duid) {
+ // This should not happen. We have checked this before.
+ // see sanityCheck() called from processRelease()
+ LOG_WARN(dhcp6_logger, DHCP6_RELEASE_MISSING_CLIENTID)
+ .arg(release->getRemoteAddr().toText());
+
+ reply->addOption(createStatusCode(STATUS_UnspecFail,
+ "You did not include mandatory client-id"));
+ return;
+ }
+ DuidPtr duid(new DUID(opt_duid->getData()));
+
+ int general_status = STATUS_Success;
+ for (Option::OptionCollection::iterator opt = release->options_.begin();
+ opt != release->options_.end(); ++opt) {
+ switch (opt->second->getType()) {
+ case D6O_IA_NA: {
+ OptionPtr answer_opt = releaseIA_NA(duid, release, general_status,
+ boost::dynamic_pointer_cast<Option6IA>(opt->second));
+ if (answer_opt) {
+ reply->addOption(answer_opt);
+ }
+ break;
+ }
+ // @todo: add support for IA_PD
+ // @todo: add support for IA_TA
+ default:
+ // remaining options are stateless and thus ignored in this context
+ ;
+ }
+ }
+
+ // To be pedantic, we should also include status code in the top-level
+ // scope, not just in each IA_NA. See RFC3315, section 18.2.6.
+ // This behavior will likely go away in RFC3315bis.
+ reply->addOption(createStatusCode(general_status,
+ "Summary status for all processed IA_NAs"));
+}
+
+OptionPtr Dhcpv6Srv::releaseIA_NA(const DuidPtr& duid, Pkt6Ptr question,
+ int& general_status,
+ boost::shared_ptr<Option6IA> ia) {
+ // Release can be done in one of two ways:
+ // Approach 1: extract address from client's IA_NA and see if it belongs
+ // to this particular client.
+ // Approach 2: find a subnet for this client, get a lease for
+ // this subnet/duid/iaid and check if its content matches to what the
+ // client is asking us to release.
+ //
+ // This method implements approach 1.
+
+ // That's our response
+ boost::shared_ptr<Option6IA> ia_rsp(new Option6IA(D6O_IA_NA, ia->getIAID()));
+
+ boost::shared_ptr<Option6IAAddr> release_addr = boost::dynamic_pointer_cast<Option6IAAddr>
+ (ia->getOption(D6O_IAADDR));
+ if (!release_addr) {
+ ia_rsp->addOption(createStatusCode(STATUS_NoBinding,
+ "You did not include address in your RELEASE"));
+ general_status = STATUS_NoBinding;
+ return (ia_rsp);
+ }
+
+ Lease6Ptr lease = LeaseMgrFactory::instance().getLease6(release_addr->getAddress());
+
+ if (!lease) {
+ // client releasing a lease that we don't know about.
+
+ // Insert status code NoAddrsAvail.
+ ia_rsp->addOption(createStatusCode(STATUS_NoBinding,
+ "Sorry, no known leases for this duid/iaid, can't release."));
+ general_status = STATUS_NoBinding;
+
+ LOG_INFO(dhcp6_logger, DHCP6_UNKNOWN_RELEASE)
+ .arg(duid->toText())
+ .arg(ia->getIAID());
+
+ return (ia_rsp);
+ }
+
+ if (!lease->duid_) {
+ // Something is gravely wrong here. We do have a lease, but it does not
+ // have mandatory DUID information attached. Someone was messing with our
+ // database.
+
+ LOG_ERROR(dhcp6_logger, DHCP6_LEASE_WITHOUT_DUID)
+ .arg(release_addr->getAddress().toText());
+
+ general_status = STATUS_UnspecFail;
+ ia_rsp->addOption(createStatusCode(STATUS_UnspecFail,
+ "Database consistency check failed when trying to RELEASE"));
+ return (ia_rsp);
+ }
+
+ if (*duid != *(lease->duid_)) {
+ // Sorry, it's not your address. You can't release it.
+
+ LOG_INFO(dhcp6_logger, DHCP6_RELEASE_FAIL_WRONG_DUID)
+ .arg(duid->toText())
+ .arg(release_addr->getAddress().toText())
+ .arg(lease->duid_->toText());
+
+ general_status = STATUS_NoBinding;
+ ia_rsp->addOption(createStatusCode(STATUS_NoBinding,
+ "This address does not belong to you, you can't release it"));
+ return (ia_rsp);
+ }
+
+ if (ia->getIAID() != lease->iaid_) {
+ // This address belongs to this client, but to a different IA
+ LOG_WARN(dhcp6_logger, DHCP6_RELEASE_FAIL_WRONG_IAID)
+ .arg(duid->toText())
+ .arg(release_addr->getAddress().toText())
+ .arg(lease->iaid_)
+ .arg(ia->getIAID());
+ ia_rsp->addOption(createStatusCode(STATUS_NoBinding,
+ "This is your address, but you used wrong IAID"));
+ general_status = STATUS_NoBinding;
+ return (ia_rsp);
+ }
+
+ // It is not necessary to check if the address matches as we used
+ // getLease6(addr) method that is supposed to return a proper lease.
+ // Ok, we've passed all checks. Let's release this address.
+ if (!LeaseMgrFactory::instance().deleteLease(lease->addr_)) {
+ ia_rsp->addOption(createStatusCode(STATUS_UnspecFail,
+ "Server failed to release a lease"));
+
+ LOG_ERROR(dhcp6_logger, DHCP6_RELEASE_FAIL)
+ .arg(lease->addr_.toText())
+ .arg(duid->toText())
+ .arg(lease->iaid_);
+ general_status = STATUS_UnspecFail;
+
+ return (ia_rsp);
+ } else {
+ LOG_DEBUG(dhcp6_logger, DBG_DHCP6_DETAIL, DHCP6_RELEASE)
+ .arg(lease->addr_.toText())
+ .arg(duid->toText())
+ .arg(lease->iaid_);
+ ia_rsp->addOption(createStatusCode(STATUS_Success,
+ "Lease released. Thank you, please come again."));
+
+ return (ia_rsp);
+ }
}
+
Pkt6Ptr Dhcpv6Srv::processSolicit(const Pkt6Ptr& solicit) {
sanityCheck(solicit, MANDATORY, FORBIDDEN);
@@ -751,8 +920,16 @@ Pkt6Ptr Dhcpv6Srv::processConfirm(const Pkt6Ptr& confirm) {
}
Pkt6Ptr Dhcpv6Srv::processRelease(const Pkt6Ptr& release) {
- /// @todo: Implement this
+
+ sanityCheck(release, MANDATORY, MANDATORY);
+
Pkt6Ptr reply(new Pkt6(DHCPV6_REPLY, release->getTransid()));
+
+ copyDefaultOptions(release, reply);
+ appendDefaultOptions(release, reply);
+
+ releaseLeases(release, reply);
+
return reply;
}
diff --git a/src/bin/dhcp6/dhcp6_srv.h b/src/bin/dhcp6/dhcp6_srv.h
index b6b0306..0f3e641 100644
--- a/src/bin/dhcp6/dhcp6_srv.h
+++ b/src/bin/dhcp6/dhcp6_srv.h
@@ -212,17 +212,39 @@ protected:
/// @brief Renews specific IA_NA option
///
- /// Generates response to IA_NA. This typically includes finding a lease that
- /// corresponds to the received address. If no such lease is found, an IA_NA
- /// response is generated with an appropriate status code.
+ /// Generates response to IA_NA in Renew. This typically includes finding a
+ /// lease that corresponds to the received address. If no such lease is
+ /// found, an IA_NA response is generated with an appropriate status code.
///
/// @param subnet subnet the sender belongs to
/// @param duid client's duid
/// @param question client's message
/// @param ia IA_NA option that is being renewed
+ /// @return IA_NA option (server's response)
OptionPtr renewIA_NA(const Subnet6Ptr& subnet, const DuidPtr& duid,
Pkt6Ptr question, boost::shared_ptr<Option6IA> ia);
+ /// @brief Releases specific IA_NA option
+ ///
+ /// Generates response to IA_NA in Release message. This covers finding and
+ /// removal of a lease that corresponds to the received address. If no such
+ /// lease is found, an IA_NA response is generated with an appropriate
+ /// status code.
+ ///
+ /// As RFC 3315 requires that a single status code be sent for the whole message,
+ /// this method may update the passed general_status: it is set to SUCCESS when
+ /// message processing begins, but may be updated to some error code if the
+ /// release process fails.
+ ///
+ /// @param duid client's duid
+ /// @param question client's message
+ /// @param general_status a global status (it may be updated in case of errors)
+ /// @param ia IA_NA option that is being renewed
+ /// @return IA_NA option (server's response)
+ OptionPtr releaseIA_NA(const DuidPtr& duid, Pkt6Ptr question,
+ int& general_status,
+ boost::shared_ptr<Option6IA> ia);
+
/// @brief Copies required options from client message to server answer.
///
/// Copies options that must appear in any server response (ADVERTISE, REPLY)
@@ -271,6 +293,17 @@ protected:
/// @param reply server's response
void renewLeases(const Pkt6Ptr& renew, Pkt6Ptr& reply);
+ /// @brief Attempts to release received addresses
+ ///
+ /// It iterates through received IA_NA options and attempts to release
+ /// received addresses. If no such leases are found, or the lease fails
+ /// proper checks (e.g. belongs to someone else), a proper status
+ /// code is added to reply message. Released addresses are not added
+ /// to REPLY packet, just its IA_NA containers.
+ /// @param release client's message asking to release
+ /// @param reply server's response
+ void releaseLeases(const Pkt6Ptr& release, Pkt6Ptr& reply);
+
/// @brief Sets server-identifier.
///
/// This method attempts to set server-identifier DUID. It loads it
diff --git a/src/bin/dhcp6/tests/dhcp6_srv_unittest.cc b/src/bin/dhcp6/tests/dhcp6_srv_unittest.cc
index 4c02dde..db93f9e 100644
--- a/src/bin/dhcp6/tests/dhcp6_srv_unittest.cc
+++ b/src/bin/dhcp6/tests/dhcp6_srv_unittest.cc
@@ -59,6 +59,7 @@ public:
using Dhcpv6Srv::processSolicit;
using Dhcpv6Srv::processRequest;
using Dhcpv6Srv::processRenew;
+ using Dhcpv6Srv::processRelease;
using Dhcpv6Srv::createStatusCode;
using Dhcpv6Srv::selectSubnet;
using Dhcpv6Srv::sanityCheck;
@@ -143,11 +144,14 @@ public:
}
// Checks that server rejected IA_NA, i.e. that it has no addresses and
- // that expected status code really appears there.
+ // that expected status code really appears there. In some limited cases
+ // (reply to RELEASE) it may be used to verify positive case, where
+ // IA_NA response is expected to not include address.
+ //
// Status code indicates type of error encountered (in theory it can also
// indicate success, but servers typically don't send success status
// as this is the default result and it saves bandwidth)
- void checkRejectedIA_NA(const boost::shared_ptr<Option6IA>& ia,
+ void checkIA_NAStatusCode(const boost::shared_ptr<Option6IA>& ia,
uint16_t expected_status_code) {
// Make sure there is no address assigned.
EXPECT_FALSE(ia->getOption(D6O_IAADDR));
@@ -158,6 +162,12 @@ public:
boost::shared_ptr<OptionCustom> status =
boost::dynamic_pointer_cast<OptionCustom>(ia->getOption(D6O_STATUS_CODE));
+
+ // It is ok to not include status success as this is the default behavior
+ if (expected_status_code == STATUS_Success && !status) {
+ return;
+ }
+
EXPECT_TRUE(status);
if (status) {
@@ -169,6 +179,26 @@ public:
}
}
+
+ void checkMsgStatusCode(const Pkt6Ptr& msg, uint16_t expected_status) {
+ boost::shared_ptr<OptionCustom> status =
+ boost::dynamic_pointer_cast<OptionCustom>(msg->getOption(D6O_STATUS_CODE));
+
+ // It is ok to not include status success as this is the default behavior
+ if (expected_status == STATUS_Success && !status) {
+ return;
+ }
+
+ EXPECT_TRUE(status);
+ if (status) {
+ // We don't have dedicated class for status code, so let's just interpret
+ // first 2 bytes as status. Remainder of the status code option content is
+ // just a text explanation what went wrong.
+ EXPECT_EQ(static_cast<uint16_t>(expected_status),
+ status->readInteger<uint16_t>(0));
+ }
+ }
+
// Check that generated IAADDR option contains expected address.
void checkIAAddr(const boost::shared_ptr<Option6IAAddr>& addr,
const IOAddress& expected_addr,
@@ -353,10 +383,9 @@ TEST_F(Dhcpv6SrvTest, advertiseOptions) {
ElementPtr json = Element::fromJSON(config);
- boost::scoped_ptr<NakedDhcpv6Srv> srv;
- ASSERT_NO_THROW(srv.reset(new NakedDhcpv6Srv(0)));
+ NakedDhcpv6Srv srv(0);
- EXPECT_NO_THROW(x = configureDhcp6Server(*srv, json));
+ EXPECT_NO_THROW(x = configureDhcp6Server(srv, json));
ASSERT_TRUE(x);
comment_ = parseAnswer(rcode_, x);
@@ -369,7 +398,7 @@ TEST_F(Dhcpv6SrvTest, advertiseOptions) {
sol->addOption(clientid);
// Pass it to the server and get an advertise
- boost::shared_ptr<Pkt6> adv = srv->processSolicit(sol);
+ boost::shared_ptr<Pkt6> adv = srv.processSolicit(sol);
// check if we get response at all
ASSERT_TRUE(adv);
@@ -393,7 +422,7 @@ TEST_F(Dhcpv6SrvTest, advertiseOptions) {
sol->addOption(option_oro);
// Need to process SOLICIT again after requesting new option.
- adv = srv->processSolicit(sol);
+ adv = srv.processSolicit(sol);
ASSERT_TRUE(adv);
OptionPtr tmp = adv->getOption(D6O_NAME_SERVERS);
@@ -444,8 +473,7 @@ TEST_F(Dhcpv6SrvTest, advertiseOptions) {
// - server-id
// - IA that includes IAADDR
TEST_F(Dhcpv6SrvTest, SolicitBasic) {
- boost::scoped_ptr<NakedDhcpv6Srv> srv;
- ASSERT_NO_THROW( srv.reset(new NakedDhcpv6Srv(0)) );
+ NakedDhcpv6Srv srv(0);
Pkt6Ptr sol = Pkt6Ptr(new Pkt6(DHCPV6_SOLICIT, 1234));
sol->setRemoteAddr(IOAddress("fe80::abcd"));
@@ -454,7 +482,7 @@ TEST_F(Dhcpv6SrvTest, SolicitBasic) {
sol->addOption(clientid);
// Pass it to the server and get an advertise
- Pkt6Ptr reply = srv->processSolicit(sol);
+ Pkt6Ptr reply = srv.processSolicit(sol);
// check if we get response at all
checkResponse(reply, DHCPV6_ADVERTISE, 1234);
@@ -467,7 +495,7 @@ TEST_F(Dhcpv6SrvTest, SolicitBasic) {
checkIAAddr(addr, addr->getAddress(), subnet_->getPreferred(), subnet_->getValid());
// check DUIDs
- checkServerId(reply, srv->getServerID());
+ checkServerId(reply, srv.getServerID());
checkClientId(reply, clientid);
}
@@ -487,8 +515,7 @@ TEST_F(Dhcpv6SrvTest, SolicitBasic) {
// - server-id
// - IA that includes IAADDR
TEST_F(Dhcpv6SrvTest, SolicitHint) {
- boost::scoped_ptr<NakedDhcpv6Srv> srv;
- ASSERT_NO_THROW( srv.reset(new NakedDhcpv6Srv(0)) );
+ NakedDhcpv6Srv srv(0);
// Let's create a SOLICIT
Pkt6Ptr sol = Pkt6Ptr(new Pkt6(DHCPV6_SOLICIT, 1234));
@@ -505,7 +532,7 @@ TEST_F(Dhcpv6SrvTest, SolicitHint) {
sol->addOption(clientid);
// Pass it to the server and get an advertise
- Pkt6Ptr reply = srv->processSolicit(sol);
+ Pkt6Ptr reply = srv.processSolicit(sol);
// check if we get response at all
checkResponse(reply, DHCPV6_ADVERTISE, 1234);
@@ -521,7 +548,7 @@ TEST_F(Dhcpv6SrvTest, SolicitHint) {
checkIAAddr(addr, hint, subnet_->getPreferred(), subnet_->getValid());
// check DUIDs
- checkServerId(reply, srv->getServerID());
+ checkServerId(reply, srv.getServerID());
checkClientId(reply, clientid);
}
@@ -541,8 +568,7 @@ TEST_F(Dhcpv6SrvTest, SolicitHint) {
// - server-id
// - IA that includes IAADDR
TEST_F(Dhcpv6SrvTest, SolicitInvalidHint) {
- boost::scoped_ptr<NakedDhcpv6Srv> srv;
- ASSERT_NO_THROW( srv.reset(new NakedDhcpv6Srv(0)) );
+ NakedDhcpv6Srv srv(0);
// Let's create a SOLICIT
Pkt6Ptr sol = Pkt6Ptr(new Pkt6(DHCPV6_SOLICIT, 1234));
@@ -557,7 +583,7 @@ TEST_F(Dhcpv6SrvTest, SolicitInvalidHint) {
sol->addOption(clientid);
// Pass it to the server and get an advertise
- Pkt6Ptr reply = srv->processSolicit(sol);
+ Pkt6Ptr reply = srv.processSolicit(sol);
// check if we get response at all
checkResponse(reply, DHCPV6_ADVERTISE, 1234);
@@ -571,7 +597,7 @@ TEST_F(Dhcpv6SrvTest, SolicitInvalidHint) {
EXPECT_TRUE(subnet_->inPool(addr->getAddress()));
// check DUIDs
- checkServerId(reply, srv->getServerID());
+ checkServerId(reply, srv.getServerID());
checkClientId(reply, clientid);
}
@@ -586,8 +612,7 @@ TEST_F(Dhcpv6SrvTest, SolicitInvalidHint) {
// client. ADVERTISE is basically saying "if you send me a request, you will
// probably get an address like this" (there are no guarantees).
TEST_F(Dhcpv6SrvTest, ManySolicits) {
- boost::scoped_ptr<NakedDhcpv6Srv> srv;
- ASSERT_NO_THROW( srv.reset(new NakedDhcpv6Srv(0)) );
+ NakedDhcpv6Srv srv(0);
Pkt6Ptr sol1 = Pkt6Ptr(new Pkt6(DHCPV6_SOLICIT, 1234));
Pkt6Ptr sol2 = Pkt6Ptr(new Pkt6(DHCPV6_SOLICIT, 2345));
@@ -611,9 +636,9 @@ TEST_F(Dhcpv6SrvTest, ManySolicits) {
sol3->addOption(clientid3);
// Pass it to the server and get an advertise
- Pkt6Ptr reply1 = srv->processSolicit(sol1);
- Pkt6Ptr reply2 = srv->processSolicit(sol2);
- Pkt6Ptr reply3 = srv->processSolicit(sol3);
+ Pkt6Ptr reply1 = srv.processSolicit(sol1);
+ Pkt6Ptr reply2 = srv.processSolicit(sol2);
+ Pkt6Ptr reply3 = srv.processSolicit(sol3);
// check if we get response at all
checkResponse(reply1, DHCPV6_ADVERTISE, 1234);
@@ -634,9 +659,9 @@ TEST_F(Dhcpv6SrvTest, ManySolicits) {
checkIAAddr(addr3, addr3->getAddress(), subnet_->getPreferred(), subnet_->getValid());
// check DUIDs
- checkServerId(reply1, srv->getServerID());
- checkServerId(reply2, srv->getServerID());
- checkServerId(reply3, srv->getServerID());
+ checkServerId(reply1, srv.getServerID());
+ checkServerId(reply2, srv.getServerID());
+ checkServerId(reply3, srv.getServerID());
checkClientId(reply1, clientid1);
checkClientId(reply2, clientid2);
checkClientId(reply3, clientid3);
@@ -666,8 +691,7 @@ TEST_F(Dhcpv6SrvTest, ManySolicits) {
// - server-id
// - IA that includes IAADDR
TEST_F(Dhcpv6SrvTest, RequestBasic) {
- boost::scoped_ptr<NakedDhcpv6Srv> srv;
- ASSERT_NO_THROW( srv.reset(new NakedDhcpv6Srv(0)) );
+ NakedDhcpv6Srv srv(0);
// Let's create a REQUEST
Pkt6Ptr req = Pkt6Ptr(new Pkt6(DHCPV6_REQUEST, 1234));
@@ -684,10 +708,10 @@ TEST_F(Dhcpv6SrvTest, RequestBasic) {
req->addOption(clientid);
// server-id is mandatory in REQUEST
- req->addOption(srv->getServerID());
+ req->addOption(srv.getServerID());
// Pass it to the server and hope for a REPLY
- Pkt6Ptr reply = srv->processRequest(req);
+ Pkt6Ptr reply = srv.processRequest(req);
// check if we get response at all
checkResponse(reply, DHCPV6_REPLY, 1234);
@@ -703,7 +727,7 @@ TEST_F(Dhcpv6SrvTest, RequestBasic) {
checkIAAddr(addr, hint, subnet_->getPreferred(), subnet_->getValid());
// check DUIDs
- checkServerId(reply, srv->getServerID());
+ checkServerId(reply, srv.getServerID());
checkClientId(reply, clientid);
// check that the lease is really in the database
@@ -720,8 +744,7 @@ TEST_F(Dhcpv6SrvTest, RequestBasic) {
// client. ADVERTISE is basically saying "if you send me a request, you will
// probably get an address like this" (there are no guarantees).
TEST_F(Dhcpv6SrvTest, ManyRequests) {
- boost::scoped_ptr<NakedDhcpv6Srv> srv;
- ASSERT_NO_THROW( srv.reset(new NakedDhcpv6Srv(0)) );
+ NakedDhcpv6Srv srv(0);
Pkt6Ptr req1 = Pkt6Ptr(new Pkt6(DHCPV6_REQUEST, 1234));
Pkt6Ptr req2 = Pkt6Ptr(new Pkt6(DHCPV6_REQUEST, 2345));
@@ -745,14 +768,14 @@ TEST_F(Dhcpv6SrvTest, ManyRequests) {
req3->addOption(clientid3);
// server-id is mandatory in REQUEST
- req1->addOption(srv->getServerID());
- req2->addOption(srv->getServerID());
- req3->addOption(srv->getServerID());
+ req1->addOption(srv.getServerID());
+ req2->addOption(srv.getServerID());
+ req3->addOption(srv.getServerID());
// Pass it to the server and get an advertise
- Pkt6Ptr reply1 = srv->processRequest(req1);
- Pkt6Ptr reply2 = srv->processRequest(req2);
- Pkt6Ptr reply3 = srv->processRequest(req3);
+ Pkt6Ptr reply1 = srv.processRequest(req1);
+ Pkt6Ptr reply2 = srv.processRequest(req2);
+ Pkt6Ptr reply3 = srv.processRequest(req3);
// check if we get response at all
checkResponse(reply1, DHCPV6_REPLY, 1234);
@@ -773,9 +796,9 @@ TEST_F(Dhcpv6SrvTest, ManyRequests) {
checkIAAddr(addr3, addr3->getAddress(), subnet_->getPreferred(), subnet_->getValid());
// check DUIDs
- checkServerId(reply1, srv->getServerID());
- checkServerId(reply2, srv->getServerID());
- checkServerId(reply3, srv->getServerID());
+ checkServerId(reply1, srv.getServerID());
+ checkServerId(reply2, srv.getServerID());
+ checkServerId(reply3, srv.getServerID());
checkClientId(reply1, clientid1);
checkClientId(reply2, clientid2);
checkClientId(reply3, clientid3);
@@ -799,8 +822,7 @@ TEST_F(Dhcpv6SrvTest, ManyRequests) {
// - returned REPLY message has IA that includes IAADDR
// - lease is actually renewed in LeaseMgr
TEST_F(Dhcpv6SrvTest, RenewBasic) {
- boost::scoped_ptr<NakedDhcpv6Srv> srv;
- ASSERT_NO_THROW( srv.reset(new NakedDhcpv6Srv(0)) );
+ NakedDhcpv6Srv srv(0);
const IOAddress addr("2001:db8:1:1::cafe:babe");
const uint32_t iaid = 234;
@@ -841,10 +863,10 @@ TEST_F(Dhcpv6SrvTest, RenewBasic) {
req->addOption(clientid);
// Server-id is mandatory in RENEW
- req->addOption(srv->getServerID());
+ req->addOption(srv.getServerID());
// Pass it to the server and hope for a REPLY
- Pkt6Ptr reply = srv->processRenew(req);
+ Pkt6Ptr reply = srv.processRenew(req);
// Check if we get response at all
checkResponse(reply, DHCPV6_REPLY, 1234);
@@ -860,7 +882,7 @@ TEST_F(Dhcpv6SrvTest, RenewBasic) {
checkIAAddr(addr_opt, addr, subnet_->getPreferred(), subnet_->getValid());
// Check DUIDs
- checkServerId(reply, srv->getServerID());
+ checkServerId(reply, srv.getServerID());
checkClientId(reply, clientid);
// Check that the lease is really in the database
@@ -895,9 +917,7 @@ TEST_F(Dhcpv6SrvTest, RenewBasic) {
// - returned REPLY message has IA that includes STATUS-CODE
// - No lease in LeaseMgr
TEST_F(Dhcpv6SrvTest, RenewReject) {
-
- boost::scoped_ptr<NakedDhcpv6Srv> srv;
- ASSERT_NO_THROW( srv.reset(new NakedDhcpv6Srv(0)) );
+ NakedDhcpv6Srv srv(0);
const IOAddress addr("2001:db8:1:1::dead");
const uint32_t transid = 1234;
@@ -925,12 +945,12 @@ TEST_F(Dhcpv6SrvTest, RenewReject) {
req->addOption(clientid);
// Server-id is mandatory in RENEW
- req->addOption(srv->getServerID());
+ req->addOption(srv.getServerID());
// Case 1: No lease known to server
// Pass it to the server and hope for a REPLY
- Pkt6Ptr reply = srv->processRenew(req);
+ Pkt6Ptr reply = srv.processRenew(req);
// Check if we get response at all
checkResponse(reply, DHCPV6_REPLY, transid);
@@ -939,7 +959,7 @@ TEST_F(Dhcpv6SrvTest, RenewReject) {
// Check that IA_NA was returned and that there's an address included
ia = boost::dynamic_pointer_cast<Option6IA>(tmp);
ASSERT_TRUE(ia);
- checkRejectedIA_NA(ia, STATUS_NoAddrsAvail);
+ checkIA_NAStatusCode(ia, STATUS_NoBinding);
// Check that there is no lease added
l = LeaseMgrFactory::instance().getLease6(addr);
@@ -956,14 +976,14 @@ TEST_F(Dhcpv6SrvTest, RenewReject) {
ASSERT_TRUE(LeaseMgrFactory::instance().addLease(lease));
// Pass it to the server and hope for a REPLY
- reply = srv->processRenew(req);
+ reply = srv.processRenew(req);
checkResponse(reply, DHCPV6_REPLY, transid);
tmp = reply->getOption(D6O_IA_NA);
ASSERT_TRUE(tmp);
// Check that IA_NA was returned and that there's an address included
ia = boost::dynamic_pointer_cast<Option6IA>(tmp);
ASSERT_TRUE(ia);
- checkRejectedIA_NA(ia, STATUS_NoAddrsAvail);
+ checkIA_NAStatusCode(ia, STATUS_NoBinding);
// There is a iaid mis-match, so server should respond that there is
// no such address to renew.
@@ -975,14 +995,14 @@ TEST_F(Dhcpv6SrvTest, RenewReject) {
req->addOption(generateClientId(13)); // generate different DUID
// (with length 13)
- reply = srv->processRenew(req);
+ reply = srv.processRenew(req);
checkResponse(reply, DHCPV6_REPLY, transid);
tmp = reply->getOption(D6O_IA_NA);
ASSERT_TRUE(tmp);
// Check that IA_NA was returned and that there's an address included
ia = boost::dynamic_pointer_cast<Option6IA>(tmp);
ASSERT_TRUE(ia);
- checkRejectedIA_NA(ia, STATUS_NoAddrsAvail);
+ checkIA_NAStatusCode(ia, STATUS_NoBinding);
lease = LeaseMgrFactory::instance().getLease6(addr);
ASSERT_TRUE(lease);
@@ -992,10 +1012,198 @@ TEST_F(Dhcpv6SrvTest, RenewReject) {
EXPECT_TRUE(LeaseMgrFactory::instance().deleteLease(addr));
}
+// This test verifies that incoming (positive) RELEASE can be handled properly,
+// that a REPLY is generated, that the response has status code and that the
+// lease is indeed removed from the database.
+//
+// expected:
+// - returned REPLY message has copy of client-id
+// - returned REPLY message has server-id
+// - returned REPLY message has IA that does not include an IAADDR
+// - lease is actually removed from LeaseMgr
+TEST_F(Dhcpv6SrvTest, ReleaseBasic) {
+ NakedDhcpv6Srv srv(0);
+
+ const IOAddress addr("2001:db8:1:1::cafe:babe");
+ const uint32_t iaid = 234;
+
+ // Generate client-id also duid_
+ OptionPtr clientid = generateClientId();
+
+ // Check that the address we are about to use is indeed in pool
+ ASSERT_TRUE(subnet_->inPool(addr));
+
+ // Note that preferred, valid, T1 and T2 timers and CLTT are set to invalid
+ // value on purpose. They should be updated during RENEW.
+ Lease6Ptr lease(new Lease6(Lease6::LEASE_IA_NA, addr, duid_, iaid,
+ 501, 502, 503, 504, subnet_->getID(), 0));
+ lease->cltt_ = 1234;
+ ASSERT_TRUE(LeaseMgrFactory::instance().addLease(lease));
+
+ // Check that the lease is really in the database
+ Lease6Ptr l = LeaseMgrFactory::instance().getLease6(addr);
+ ASSERT_TRUE(l);
+
+ // Let's create a RELEASE
+ Pkt6Ptr req = Pkt6Ptr(new Pkt6(DHCPV6_RELEASE, 1234));
+ req->setRemoteAddr(IOAddress("fe80::abcd"));
+ boost::shared_ptr<Option6IA> ia = generateIA(iaid, 1500, 3000);
+
+ OptionPtr released_addr_opt(new Option6IAAddr(D6O_IAADDR, addr, 300, 500));
+ ia->addOption(released_addr_opt);
+ req->addOption(ia);
+ req->addOption(clientid);
+
+ // Server-id is mandatory in RELEASE
+ req->addOption(srv.getServerID());
+
+ // Pass it to the server and hope for a REPLY
+ Pkt6Ptr reply = srv.processRelease(req);
+
+ // Check if we get response at all
+ checkResponse(reply, DHCPV6_REPLY, 1234);
+
+ OptionPtr tmp = reply->getOption(D6O_IA_NA);
+ ASSERT_TRUE(tmp);
+
+ // Check that IA_NA was returned and that there's an address included
+ ia = boost::dynamic_pointer_cast<Option6IA>(tmp);
+ checkIA_NAStatusCode(ia, STATUS_Success);
+ checkMsgStatusCode(reply, STATUS_Success);
+
+ // There should be no address returned in RELEASE (see RFC3315, 18.2.6)
+ EXPECT_FALSE(tmp->getOption(D6O_IAADDR));
+
+ // Check DUIDs
+ checkServerId(reply, srv.getServerID());
+ checkClientId(reply, clientid);
+
+ // Check that the lease is really gone in the database
+ // get lease by address
+ l = LeaseMgrFactory::instance().getLease6(addr);
+ ASSERT_FALSE(l);
+
+ // get lease by subnetid/duid/iaid combination
+ l = LeaseMgrFactory::instance().getLease6(*duid_, iaid, subnet_->getID());
+ ASSERT_FALSE(l);
+}
+
+// This test verifies that incoming (invalid) RELEASE can be handled properly.
+//
+// This test checks 3 scenarios:
+// 1. there is no such lease at all
+// 2. there is such a lease, but it is assigned to a different IAID
+// 3. there is such a lease, but it belongs to a different client
+//
+// expected:
+// - returned REPLY message has copy of client-id
+// - returned REPLY message has server-id
+// - returned REPLY message has IA that includes STATUS-CODE
+// - No lease in LeaseMgr
+TEST_F(Dhcpv6SrvTest, ReleaseReject) {
+
+ NakedDhcpv6Srv srv(0);
+
+ const IOAddress addr("2001:db8:1:1::dead");
+ const uint32_t transid = 1234;
+ const uint32_t valid_iaid = 234;
+ const uint32_t bogus_iaid = 456;
+
+ // Quick sanity check that the address we're about to use is ok
+ ASSERT_TRUE(subnet_->inPool(addr));
+
+ // GenerateClientId() also sets duid_
+ OptionPtr clientid = generateClientId();
+
+ // Check that the lease is NOT in the database
+ Lease6Ptr l = LeaseMgrFactory::instance().getLease6(addr);
+ ASSERT_FALSE(l);
+
+ // Let's create a RELEASE
+ Pkt6Ptr req = Pkt6Ptr(new Pkt6(DHCPV6_RELEASE, transid));
+ req->setRemoteAddr(IOAddress("fe80::abcd"));
+ boost::shared_ptr<Option6IA> ia = generateIA(bogus_iaid, 1500, 3000);
+
+ OptionPtr released_addr_opt(new Option6IAAddr(D6O_IAADDR, addr, 300, 500));
+ ia->addOption(released_addr_opt);
+ req->addOption(ia);
+ req->addOption(clientid);
+
+ // Server-id is mandatory in RENEW
+ req->addOption(srv.getServerID());
+
+ // Case 1: No lease known to server
+ SCOPED_TRACE("CASE 1: No lease known to server");
+
+ // Pass it to the server and hope for a REPLY
+ Pkt6Ptr reply = srv.processRelease(req);
+
+ // Check if we get response at all
+ checkResponse(reply, DHCPV6_REPLY, transid);
+ OptionPtr tmp = reply->getOption(D6O_IA_NA);
+ ASSERT_TRUE(tmp);
+ // Check that IA_NA was returned and that there's an address included
+ ia = boost::dynamic_pointer_cast<Option6IA>(tmp);
+ ASSERT_TRUE(ia);
+ checkIA_NAStatusCode(ia, STATUS_NoBinding);
+ checkMsgStatusCode(reply, STATUS_NoBinding);
+
+ // Check that the lease is not there
+ l = LeaseMgrFactory::instance().getLease6(addr);
+ ASSERT_FALSE(l);
+
+ // CASE 2: Lease is known and belongs to this client, but to a different IAID
+ SCOPED_TRACE("CASE 2: Lease is known and belongs to this client, but to a different IAID");
+
+ Lease6Ptr lease(new Lease6(Lease6::LEASE_IA_NA, addr, duid_, valid_iaid,
+ 501, 502, 503, 504, subnet_->getID(), 0));
+ ASSERT_TRUE(LeaseMgrFactory::instance().addLease(lease));
+
+ // Pass it to the server and hope for a REPLY
+ reply = srv.processRelease(req);
+ checkResponse(reply, DHCPV6_REPLY, transid);
+ tmp = reply->getOption(D6O_IA_NA);
+ ASSERT_TRUE(tmp);
+ // Check that IA_NA was returned and that there's an address included
+ ia = boost::dynamic_pointer_cast<Option6IA>(tmp);
+ ASSERT_TRUE(ia);
+ checkIA_NAStatusCode(ia, STATUS_NoBinding);
+ checkMsgStatusCode(reply, STATUS_NoBinding);
+
+ // Check that the lease is still there
+ l = LeaseMgrFactory::instance().getLease6(addr);
+ ASSERT_TRUE(l);
+
+ // CASE 3: Lease belongs to a client with different client-id
+ SCOPED_TRACE("CASE 3: Lease belongs to a client with different client-id");
+
+ req->delOption(D6O_CLIENTID);
+ ia = boost::dynamic_pointer_cast<Option6IA>(req->getOption(D6O_IA_NA));
+ ia->setIAID(valid_iaid); // Now iaid in renew matches that in leasemgr
+ req->addOption(generateClientId(13)); // generate different DUID
+ // (with length 13)
+
+ reply = srv.processRelease(req);
+ checkResponse(reply, DHCPV6_REPLY, transid);
+ tmp = reply->getOption(D6O_IA_NA);
+ ASSERT_TRUE(tmp);
+ // Check that IA_NA was returned and that there's an address included
+ ia = boost::dynamic_pointer_cast<Option6IA>(tmp);
+ ASSERT_TRUE(ia);
+ checkIA_NAStatusCode(ia, STATUS_NoBinding);
+ checkMsgStatusCode(reply, STATUS_NoBinding);
+
+ // Check that the lease is still there
+ l = LeaseMgrFactory::instance().getLease6(addr);
+ ASSERT_TRUE(l);
+
+ // Finally, let's cleanup the database
+ EXPECT_TRUE(LeaseMgrFactory::instance().deleteLease(addr));
+}
+
// This test verifies if the status code option is generated properly.
TEST_F(Dhcpv6SrvTest, StatusCode) {
- boost::scoped_ptr<NakedDhcpv6Srv> srv;
- ASSERT_NO_THROW( srv.reset(new NakedDhcpv6Srv(0)) );
+ NakedDhcpv6Srv srv(0);
// a dummy content for client-id
uint8_t expected[] = {
@@ -1005,7 +1213,7 @@ TEST_F(Dhcpv6SrvTest, StatusCode) {
0x41, 0x42, 0x43, 0x44, 0x45 // string value ABCDE
};
// Create the option.
- OptionPtr status = srv->createStatusCode(3, "ABCDE");
+ OptionPtr status = srv.createStatusCode(3, "ABCDE");
// Allocate an output buffer. We will store the option
// in wire format here.
OutputBuffer buf(sizeof(expected));
@@ -1019,34 +1227,34 @@ TEST_F(Dhcpv6SrvTest, StatusCode) {
// This test verifies if the sanityCheck() really checks options presence.
TEST_F(Dhcpv6SrvTest, sanityCheck) {
- boost::scoped_ptr<NakedDhcpv6Srv> srv;
- ASSERT_NO_THROW( srv.reset(new NakedDhcpv6Srv(0)) );
+ NakedDhcpv6Srv srv(0);
Pkt6Ptr pkt = Pkt6Ptr(new Pkt6(DHCPV6_SOLICIT, 1234));
- // check that the packets originating from local addresses can be
+ // Set link-local sender address, so appropriate subnet can be
+ // selected for this packet.
pkt->setRemoteAddr(IOAddress("fe80::abcd"));
// client-id is optional for information-request, so
- EXPECT_NO_THROW(srv->sanityCheck(pkt, Dhcpv6Srv::OPTIONAL, Dhcpv6Srv::OPTIONAL));
+ EXPECT_NO_THROW(srv.sanityCheck(pkt, Dhcpv6Srv::OPTIONAL, Dhcpv6Srv::OPTIONAL));
// empty packet, no client-id, no server-id
- EXPECT_THROW(srv->sanityCheck(pkt, Dhcpv6Srv::MANDATORY, Dhcpv6Srv::FORBIDDEN),
+ EXPECT_THROW(srv.sanityCheck(pkt, Dhcpv6Srv::MANDATORY, Dhcpv6Srv::FORBIDDEN),
RFCViolation);
// This doesn't make much sense, but let's check it for completeness
- EXPECT_NO_THROW(srv->sanityCheck(pkt, Dhcpv6Srv::FORBIDDEN, Dhcpv6Srv::FORBIDDEN));
+ EXPECT_NO_THROW(srv.sanityCheck(pkt, Dhcpv6Srv::FORBIDDEN, Dhcpv6Srv::FORBIDDEN));
OptionPtr clientid = generateClientId();
pkt->addOption(clientid);
// client-id is mandatory, server-id is forbidden (as in SOLICIT or REBIND)
- EXPECT_NO_THROW(srv->sanityCheck(pkt, Dhcpv6Srv::MANDATORY, Dhcpv6Srv::FORBIDDEN));
+ EXPECT_NO_THROW(srv.sanityCheck(pkt, Dhcpv6Srv::MANDATORY, Dhcpv6Srv::FORBIDDEN));
- pkt->addOption(srv->getServerID());
+ pkt->addOption(srv.getServerID());
// both client-id and server-id are mandatory (as in REQUEST, RENEW, RELEASE, DECLINE)
- EXPECT_NO_THROW(srv->sanityCheck(pkt, Dhcpv6Srv::MANDATORY, Dhcpv6Srv::MANDATORY));
+ EXPECT_NO_THROW(srv.sanityCheck(pkt, Dhcpv6Srv::MANDATORY, Dhcpv6Srv::MANDATORY));
// sane section ends here, let's do some negative tests as well
@@ -1054,13 +1262,13 @@ TEST_F(Dhcpv6SrvTest, sanityCheck) {
pkt->addOption(clientid);
// with more than one client-id it should throw, no matter what
- EXPECT_THROW(srv->sanityCheck(pkt, Dhcpv6Srv::OPTIONAL, Dhcpv6Srv::OPTIONAL),
+ EXPECT_THROW(srv.sanityCheck(pkt, Dhcpv6Srv::OPTIONAL, Dhcpv6Srv::OPTIONAL),
RFCViolation);
- EXPECT_THROW(srv->sanityCheck(pkt, Dhcpv6Srv::MANDATORY, Dhcpv6Srv::OPTIONAL),
+ EXPECT_THROW(srv.sanityCheck(pkt, Dhcpv6Srv::MANDATORY, Dhcpv6Srv::OPTIONAL),
RFCViolation);
- EXPECT_THROW(srv->sanityCheck(pkt, Dhcpv6Srv::OPTIONAL, Dhcpv6Srv::MANDATORY),
+ EXPECT_THROW(srv.sanityCheck(pkt, Dhcpv6Srv::OPTIONAL, Dhcpv6Srv::MANDATORY),
RFCViolation);
- EXPECT_THROW(srv->sanityCheck(pkt, Dhcpv6Srv::MANDATORY, Dhcpv6Srv::MANDATORY),
+ EXPECT_THROW(srv.sanityCheck(pkt, Dhcpv6Srv::MANDATORY, Dhcpv6Srv::MANDATORY),
RFCViolation);
pkt->delOption(D6O_CLIENTID);
@@ -1069,20 +1277,21 @@ TEST_F(Dhcpv6SrvTest, sanityCheck) {
// again we have only one client-id
// let's try different type of insanity - several server-ids
- pkt->addOption(srv->getServerID());
- pkt->addOption(srv->getServerID());
+ pkt->addOption(srv.getServerID());
+ pkt->addOption(srv.getServerID());
// with more than one server-id it should throw, no matter what
- EXPECT_THROW(srv->sanityCheck(pkt, Dhcpv6Srv::OPTIONAL, Dhcpv6Srv::OPTIONAL),
+ EXPECT_THROW(srv.sanityCheck(pkt, Dhcpv6Srv::OPTIONAL, Dhcpv6Srv::OPTIONAL),
RFCViolation);
- EXPECT_THROW(srv->sanityCheck(pkt, Dhcpv6Srv::MANDATORY, Dhcpv6Srv::OPTIONAL),
+ EXPECT_THROW(srv.sanityCheck(pkt, Dhcpv6Srv::MANDATORY, Dhcpv6Srv::OPTIONAL),
RFCViolation);
- EXPECT_THROW(srv->sanityCheck(pkt, Dhcpv6Srv::OPTIONAL, Dhcpv6Srv::MANDATORY),
+ EXPECT_THROW(srv.sanityCheck(pkt, Dhcpv6Srv::OPTIONAL, Dhcpv6Srv::MANDATORY),
RFCViolation);
- EXPECT_THROW(srv->sanityCheck(pkt, Dhcpv6Srv::MANDATORY, Dhcpv6Srv::MANDATORY),
+ EXPECT_THROW(srv.sanityCheck(pkt, Dhcpv6Srv::MANDATORY, Dhcpv6Srv::MANDATORY),
RFCViolation);
-
-
}
+/// @todo: Add more negative tests for processX(), e.g. extend sanityCheck() test
+/// to call processX() methods.
+
} // end of anonymous namespace
More information about the bind10-changes
mailing list