-// Copyright (C) 2014-2017 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2014-2018 Internet Systems Consortium, Inc. ("ISC")
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
/// @param timeout_ms Amount of time after which the method returns.
void runTimersWithTimeout(const IOServicePtr& io_service, const long timeout_ms) {
IntervalTimer timer(*io_service);
- timer.setup([this, &io_service]() {
+ timer.setup([&io_service]() {
io_service->stop();
}, timeout_ms, IntervalTimer::ONE_SHOT);
io_service->run();
// the server has no more addresses to assign.
Dhcp4Client client3(client1.getServer(), Dhcp4Client::SELECTING);
client3.setIfaceName("eth1");
- testAssigned([this, &client3]() {
+ testAssigned([&client3]() {
ASSERT_NO_THROW(client3.doDiscover());
Pkt4Ptr resp3 = client3.getContext().response_;
ASSERT_FALSE(resp3);
// Asking for an address that is not in address pool should result in getting
// an address from one of the subnets, but generally hard to tell from which one.
- testAssigned([this, &client] {
+ testAssigned([&client] {
ASSERT_NO_THROW(client.doDiscover(boost::shared_ptr<IOAddress>(new IOAddress("10.0.0.23"))));
});
// Release the lease that the client has got, because we'll need this address
// further in the test.
- testAssigned([this, &client1] {
+ testAssigned([&client1] {
ASSERT_NO_THROW(client1.doRelease());
});
configure(NETWORKS_CONFIG[10], *client.getServer());
// Perform 4-way exchange.
- testAssigned([this, &client] {
+ testAssigned([&client] {
ASSERT_NO_THROW(client.doDORA());
});
Pkt4Ptr resp = client.getContext().response_;
configure(NETWORKS_CONFIG[8], *client1.getServer());
// Perform 4-way exchange.
- testAssigned([this, &client1] {
+ testAssigned([&client1] {
ASSERT_NO_THROW(client1.doDORA());
});
Pkt4Ptr resp1 = client1.getContext().response_;
client2.setIfaceName("eth0");
// Perform 4-way exchange.
- testAssigned([this, &client2] {
+ testAssigned([&client2] {
ASSERT_NO_THROW(client2.doDORA());
});
Pkt4Ptr resp2 = client2.getContext().response_;
configure(NETWORKS_CONFIG[9], *client1.getServer());
// Perform 4-way exchange.
- testAssigned([this, &client1] {
+ testAssigned([&client1] {
ASSERT_NO_THROW(client1.doDORA());
});
Pkt4Ptr resp1 = client1.getContext().response_;
client2.useRelay(true, IOAddress("192.1.2.3"));
// Perform 4-way exchange.
- testAssigned([this, &client2] {
+ testAssigned([&client2] {
ASSERT_NO_THROW(client2.doDORA());
});
Pkt4Ptr resp2 = client2.getContext().response_;
configure(NETWORKS_CONFIG[11], *client.getServer());
// Perform 4-way exchange.
- testAssigned([this, &client] {
+ testAssigned([&client] {
ASSERT_NO_THROW(client.doDORA());
});
Pkt4Ptr resp1 = client.getContext().response_;
client.setState(Dhcp4Client::RENEWING);
// Try to renew the lease with modified MAC address.
- testAssigned([this, &client] {
+ testAssigned([&client] {
ASSERT_NO_THROW(client.doRequest());
});
Pkt4Ptr resp2 = client.getContext().response_;
configure(NETWORKS_CONFIG[13], *client1.getServer());
// Simply send DHCPDISCOVER to avoid allocating a lease.
- testAssigned([this, &client1] {
+ testAssigned([&client1] {
ASSERT_NO_THROW(client1.doDiscover());
});
Pkt4Ptr resp1 = client1.getContext().response_;
// Configure DHCP server.
ASSERT_NO_THROW(configure(NETWORKS_CONFIG[15], *client1.getServer()));
- testAssigned([this, &client1] {
+ testAssigned([&client1] {
ASSERT_NO_THROW(client1.doDORA());
});
Dhcp4Client client2(client1.getServer(), Dhcp4Client::SELECTING);
client2.setIfaceName("eth0");
- testAssigned([this, &client2] {
+ testAssigned([&client2] {
ASSERT_NO_THROW(client2.doDORA());
});
// Release the lease that the client has got, because we'll need this address
// further in the test.
- testAssigned([this, &client1] {
+ testAssigned([&client1] {
ASSERT_NO_THROW(client1.doRelease());
});
// Release the lease that the client has got, because we'll need this address
// further in the test.
- testAssigned([this, &client1] {
+ testAssigned([&client1] {
ASSERT_NO_THROW(client1.doRelease());
});
}
void
-Dhcpv6Srv::processPacket(Pkt6Ptr& query, Pkt6Ptr& rsp, bool allow_packet_park) {
+Dhcpv6Srv::processPacket(Pkt6Ptr& query, Pkt6Ptr& rsp) {
bool skip_unpack = false;
// The packet has just been received so contains the uninterpreted wire
callout_handle->getArgument("query6", query);
}
- AllocEngine::ClientContext6Ptr ctx;
-
try {
- NameChangeRequestPtr ncr;
-
switch (query->getType()) {
case DHCPV6_SOLICIT:
- rsp = processSolicit(query);
- break;
-
- case DHCPV6_REQUEST:
- rsp = processRequest(query, ctx);
- break;
-
- case DHCPV6_RENEW:
- rsp = processRenew(query, ctx);
- break;
-
case DHCPV6_REBIND:
- rsp = processRebind(query, ctx);
- break;
-
case DHCPV6_CONFIRM:
- rsp = processConfirm(query);
+ sanityCheck(query, MANDATORY, FORBIDDEN);
break;
+ case DHCPV6_REQUEST:
+ case DHCPV6_RENEW:
case DHCPV6_RELEASE:
- rsp = processRelease(query, ctx);
- break;
-
case DHCPV6_DECLINE:
- rsp = processDecline(query, ctx);
+ sanityCheck(query, MANDATORY, MANDATORY);
break;
case DHCPV6_INFORMATION_REQUEST:
- rsp = processInfRequest(query);
- break;
-
case DHCPV6_DHCPV4_QUERY:
- processDhcp4Query(query);
+ sanityCheck(query, OPTIONAL, OPTIONAL);
break;
default:
// Increase the statistic of dropped packets.
StatsMgr::instance().addValue("pkt6-receive-drop", static_cast<int64_t>(1));
+ return;
+ }
+
+ if (query->getType() == DHCPV6_DHCPV4_QUERY) {
+ processDhcp4Query(query);
+ return;
+ }
+
+ // Let's create a simplified client context here.
+ AllocEngine::ClientContext6 ctx;
+ bool drop = false;
+ initContext(query, ctx, drop);
+
+ // Stop here if initContext decided to drop the packet.
+ if (drop) {
+ return;
+ }
+
+ // Park point here.
+
+ try {
+ switch (query->getType()) {
+ case DHCPV6_SOLICIT:
+ rsp = processSolicit(query, ctx);
+ break;
+
+ case DHCPV6_REQUEST:
+ rsp = processRequest(query, ctx);
+ break;
+
+ case DHCPV6_RENEW:
+ rsp = processRenew(query, ctx);
+ break;
+
+ case DHCPV6_REBIND:
+ rsp = processRebind(query, ctx);
+ break;
+
+ case DHCPV6_CONFIRM:
+ rsp = processConfirm(query, ctx);
+ break;
+
+ case DHCPV6_RELEASE:
+ rsp = processRelease(query, ctx);
+ break;
+
+ case DHCPV6_DECLINE:
+ rsp = processDecline(query, ctx);
+ break;
+
+ case DHCPV6_INFORMATION_REQUEST:
+ rsp = processInfRequest(query, ctx);
+ break;
+
+ default:
+ return;
+ }
+
} catch (const std::exception& e) {
// Catch-all exception (at least for ones based on the isc Exception
bool packet_park = false;
- if (ctx && HooksManager::calloutsPresent(Hooks.hook_index_leases6_committed_)) {
+ if (ctx.committed_ &&
+ HooksManager::calloutsPresent(Hooks.hook_index_leases6_committed_)) {
CalloutHandlePtr callout_handle = getCalloutHandle(query);
// Delete all previous arguments
callout_handle->setArgument("query6", query);
Lease6CollectionPtr new_leases(new Lease6Collection());
- if (ctx->new_lease_) {
- new_leases->push_back(ctx->new_lease_);
+ if (!ctx.new_leases_.empty()) {
+ new_leases->assign(ctx.new_leases_.cbegin(),
+ ctx.new_leases_.cend());
}
callout_handle->setArgument("leases6", new_leases);
+ // Two points: check only address? avoid duplicates in deleted_leases?
Lease6CollectionPtr deleted_leases(new Lease6Collection());
- if (ctx->old_lease_) {
- if ((!ctx->new_lease_) || (ctx->new_lease_->addr_ != ctx->old_lease_->addr_)) {
- deleted_leases->push_back(ctx->old_lease_);
+ for (auto const iac : ctx.ias_) {
+ if (!iac.old_leases_.empty()) {
+ for (auto old_lease : iac.old_leases_) {
+ if (ctx.new_leases_.empty()) {
+ deleted_leases->push_back(old_lease);
+ continue;
+ }
+ bool in_new = false;
+ for (auto const new_lease : ctx.new_leases_) {
+ if ((new_lease->addr_ == old_lease->addr_) &&
+ (new_lease->prefixlen_ == old_lease->prefixlen_)) {
+ in_new = true;
+ break;
+ }
+ }
+ if (in_new) {
+ continue;
+ }
+ deleted_leases->push_back(old_lease);
+ }
}
}
callout_handle->setArgument("deleted_leases6", deleted_leases);
.arg(query->getLabel());
rsp.reset();
- } else if ((callout_handle->getStatus() == CalloutHandle::NEXT_STEP_PARK)
- && allow_packet_park) {
+ } else if (callout_handle->getStatus() == CalloutHandle::NEXT_STEP_PARK) {
packet_park = true;
}
}
Pkt6Ptr
-Dhcpv6Srv::processSolicit(const Pkt6Ptr& solicit) {
-
- sanityCheck(solicit, MANDATORY, FORBIDDEN);
-
- // Let's create a simplified client context here.
- AllocEngine::ClientContext6 ctx;
- bool drop = false;
- initContext(solicit, ctx, drop);
-
- // Stop here if initContext decided to drop the packet.
- if (drop) {
- return (Pkt6Ptr());
- }
+Dhcpv6Srv::processSolicit(const Pkt6Ptr& solicit,
+ AllocEngine::ClientContext6& ctx) {
Pkt6Ptr response(new Pkt6(DHCPV6_ADVERTISE, solicit->getTransid()));
Pkt6Ptr
Dhcpv6Srv::processRequest(const Pkt6Ptr& request,
- AllocEngine::ClientContext6Ptr& context) {
-
- sanityCheck(request, MANDATORY, MANDATORY);
-
- // Let's create a simplified client context here.
- context.reset(new AllocEngine::ClientContext6());
- AllocEngine::ClientContext6& ctx = *context;
- bool drop = false;
- initContext(request, ctx, drop);
-
- // Stop here if initContext decided to drop the packet.
- if (drop) {
- context.reset();
- return (Pkt6Ptr());
- }
+ AllocEngine::ClientContext6& ctx) {
Pkt6Ptr reply(new Pkt6(DHCPV6_REPLY, request->getTransid()));
generateFqdn(reply);
createNameChangeRequests(reply, ctx);
+ ctx.committed_ = true;
+
return (reply);
}
Pkt6Ptr
Dhcpv6Srv::processRenew(const Pkt6Ptr& renew,
- AllocEngine::ClientContext6Ptr& context) {
-
- sanityCheck(renew, MANDATORY, MANDATORY);
-
- // Let's create a simplified client context here.
- context.reset(new AllocEngine::ClientContext6());
- AllocEngine::ClientContext6& ctx = *context;
- bool drop = false;
- initContext(renew, ctx, drop);
-
- // Stop here if initContext decided to drop the packet.
- if (drop) {
- context.reset();
- return (Pkt6Ptr());
- }
+ AllocEngine::ClientContext6& ctx) {
Pkt6Ptr reply(new Pkt6(DHCPV6_REPLY, renew->getTransid()));
generateFqdn(reply);
createNameChangeRequests(reply, ctx);
+ ctx.committed_ = true;
+
return (reply);
}
Pkt6Ptr
Dhcpv6Srv::processRebind(const Pkt6Ptr& rebind,
- AllocEngine::ClientContext6Ptr& context) {
-
- sanityCheck(rebind, MANDATORY, FORBIDDEN);
-
- // Let's create a simplified client context here.
- context.reset(new AllocEngine::ClientContext6());
- AllocEngine::ClientContext6& ctx = *context;
- bool drop = false;
- initContext(rebind, ctx, drop);
-
- // Stop here if initContext decided to drop the packet.
- if (drop) {
- context.reset();
- return (Pkt6Ptr());
- }
+ AllocEngine::ClientContext6& ctx) {
Pkt6Ptr reply(new Pkt6(DHCPV6_REPLY, rebind->getTransid()));
generateFqdn(reply);
createNameChangeRequests(reply, ctx);
+ ctx.committed_ = true;
+
return (reply);
}
Pkt6Ptr
-Dhcpv6Srv::processConfirm(const Pkt6Ptr& confirm) {
-
- sanityCheck(confirm, MANDATORY, FORBIDDEN);
-
- // Let's create a simplified client context here.
- AllocEngine::ClientContext6 ctx;
- bool drop = false;
- initContext(confirm, ctx, drop);
-
- // Stop here if initContext decided to drop the packet.
- if (drop) {
- return (Pkt6Ptr());
- }
+Dhcpv6Srv::processConfirm(const Pkt6Ptr& confirm,
+ AllocEngine::ClientContext6& ctx) {
setReservedClientClasses(confirm, ctx);
requiredClassify(confirm, ctx);
Pkt6Ptr
Dhcpv6Srv::processRelease(const Pkt6Ptr& release,
- AllocEngine::ClientContext6Ptr& context) {
-
- sanityCheck(release, MANDATORY, MANDATORY);
-
- // Let's create a simplified client context here.
- context.reset(new AllocEngine::ClientContext6());
- AllocEngine::ClientContext6& ctx = *context;
- bool drop = false;
- initContext(release, ctx, drop);
-
- // Stop here if initContext decided to drop the packet.
- if (drop) {
- context.reset();
- return (Pkt6Ptr());
- }
+ AllocEngine::ClientContext6& ctx) {
setReservedClientClasses(release, ctx);
requiredClassify(release, ctx);
+ // Create an empty Reply message.
Pkt6Ptr reply(new Pkt6(DHCPV6_REPLY, release->getTransid()));
+ // Copy client options (client-id, also relay information if present)
copyClientOptions(release, reply);
+
+ // Get the configured option list
CfgOptionList co_list;
// buildCfgOptionList(release, ctx, co_list);
appendDefaultOptions(release, reply, co_list);
/// @todo If client sent a release and we should remove outstanding
/// DNS records.
+ ctx.committed_ = true;
+
return (reply);
}
Pkt6Ptr
Dhcpv6Srv::processDecline(const Pkt6Ptr& decline,
- AllocEngine::ClientContext6Ptr& context) {
-
- // Do sanity check.
- sanityCheck(decline, MANDATORY, MANDATORY);
-
- // Let's create a simplified client context here.
- context.reset(new AllocEngine::ClientContext6());
- AllocEngine::ClientContext6& ctx = *context;
- bool drop = false;
- initContext(decline, ctx, drop);
-
- // Stop here if initContext decided to drop the packet.
- if (drop) {
- context.reset();
- return (Pkt6Ptr());
- }
+ AllocEngine::ClientContext6& ctx) {
setReservedClientClasses(decline, ctx);
requiredClassify(decline, ctx);
appendDefaultOptions(decline, reply, co_list);
if (declineLeases(decline, reply, ctx)) {
+ ctx.committed_ = true;
return (reply);
} else {
// declineLeases returns false only if the hooks set the next step
// status to DROP. We'll just doing as requested.
- context.reset();
return (Pkt6Ptr());
}
}
}
// Ok, all is good. Decline this lease.
- if (!declineLease(decline, lease, ia_rsp, ctx)) {
+ if (!declineLease(decline, lease, ia_rsp)) {
// declineLease returns false only when hook callouts set the next
// step status to drop. We just propagate the bad news here.
return (OptionPtr());
bool
Dhcpv6Srv::declineLease(const Pkt6Ptr& decline, const Lease6Ptr lease,
- boost::shared_ptr<Option6IA> ia_rsp,
- AllocEngine::ClientContext6& ctx) {
+ boost::shared_ptr<Option6IA> ia_rsp) {
// We do not want to decrease the assigned-nas at this time. While
// technically a declined address is no longer allocated, the primary usage
// of the assigned-addresses statistic is to monitor pool utilization. Most
lease->decline(CfgMgr::instance().getCurrentCfg()->getDeclinePeriod());
LeaseMgrFactory::instance().updateLease6(lease);
- ctx.new_lease_ = lease;
-
LOG_INFO(lease6_logger, DHCP6_DECLINE_LEASE).arg(decline->getLabel())
.arg(lease->addr_.toText()).arg(lease->valid_lft_);
}
Pkt6Ptr
-Dhcpv6Srv::processInfRequest(const Pkt6Ptr& inf_request) {
-
- sanityCheck(inf_request, OPTIONAL, OPTIONAL);
-
- // Let's create a simplified client context here.
- AllocEngine::ClientContext6 ctx;
- bool drop = false;
- initContext(inf_request, ctx, drop);
-
- // Stop here if initContext decided to drop the packet.
- if (drop) {
- return (Pkt6Ptr());
- }
+Dhcpv6Srv::processInfRequest(const Pkt6Ptr& inf_request,
+ AllocEngine::ClientContext6& ctx) {
setReservedClientClasses(inf_request, ctx);
requiredClassify(inf_request, ctx);
void
Dhcpv6Srv::processDhcp4Query(const Pkt6Ptr& dhcp4_query) {
- sanityCheck(dhcp4_query, OPTIONAL, OPTIONAL);
-
// flags are in transid
// uint32_t flags = dhcp4_query->getTransid();
// do nothing with DHCPV4_QUERY_FLAGS_UNICAST
// Get the DHCPv4 message option
OptionPtr dhcp4_msg = dhcp4_query->getOption(D6O_DHCPV4_MSG);
if (dhcp4_msg) {
- // Forward the whole message to the DHCPv4 server via IPC
- Dhcp6to4Ipc::instance().send(dhcp4_query);
+ try {
+ // Forward the whole message to the DHCPv4 server via IPC
+ Dhcp6to4Ipc::instance().send(dhcp4_query);
+ } catch (const std::exception&) {
+ // Assume the error was already logged
+ return;
+ }
}
// This method does not return anything as we always sent back
///
/// @param query A pointer to the packet to be processed.
/// @param rsp A pointer to the response
- /// @param allow_packet_park Indicates if parking a packet is allowed.
- void processPacket(Pkt6Ptr& query, Pkt6Ptr& rsp,
- bool allow_packet_park = true);
+ void processPacket(Pkt6Ptr& query, Pkt6Ptr& rsp);
/// @brief Instructs the server to shut down.
void shutdown();
/// immediately.
///
/// @param solicit Solicit message received from client
+ /// @param ctx Reference to client context
///
/// @return Advertise, Reply message or NULL.
- Pkt6Ptr processSolicit(const Pkt6Ptr& solicit);
+ Pkt6Ptr processSolicit(const Pkt6Ptr& solicit,
+ AllocEngine::ClientContext6& ctx);
/// @brief Processes incoming Request and returns Reply response.
///
/// leases.
///
/// @param request a message received from client
- /// @param [out] context pointer to the client context where allocated
- /// and deleted leases are stored.
+ /// @param ctx Reference to client context
///
/// @return REPLY message or NULL
Pkt6Ptr processRequest(const Pkt6Ptr& request,
- AllocEngine::ClientContext6Ptr& context);
+ AllocEngine::ClientContext6& ctx);
/// @brief Processes incoming Renew message.
///
/// @param renew message received from the client
- /// @param [out] context pointer to the client context where allocated
- /// and deleted leases are stored.
+ /// @param ctx Reference to client context
+ ///
/// @return Reply message to be sent to the client.
Pkt6Ptr processRenew(const Pkt6Ptr& renew,
- AllocEngine::ClientContext6Ptr& context);
+ AllocEngine::ClientContext6& ctx);
/// @brief Processes incoming Rebind message.
///
/// now.
///
/// @param rebind message received from the client.
- /// @param [out] context pointer to the client context where allocated
- /// and deleted leases are stored.
+ /// @param ctx Reference to client context
+ ///
/// @return Reply message to be sent to the client.
Pkt6Ptr processRebind(const Pkt6Ptr& rebind,
- AllocEngine::ClientContext6Ptr& context);
+ AllocEngine::ClientContext6& ctx);
/// @brief Processes incoming Confirm message and returns Reply.
///
/// status code Success is returned.
///
/// @param confirm Confirm message sent by a client.
+ /// @param ctx Reference to client context
///
/// @return Reply message from the server or NULL pointer if Confirm
/// message should be discarded by the server.
- Pkt6Ptr processConfirm(const Pkt6Ptr& confirm);
+ Pkt6Ptr processConfirm(const Pkt6Ptr& confirm,
+ AllocEngine::ClientContext6& ctx);
/// @brief Process incoming Release message.
///
/// @param release message received from client
- /// @param [out] context pointer to the client context where released
- /// leases are stored.
+ /// @param ctx Reference to client context
+ ///
/// @return Reply message to be sent to the client.
Pkt6Ptr processRelease(const Pkt6Ptr& release,
- AllocEngine::ClientContext6Ptr& context);
+ AllocEngine::ClientContext6& ctx);
/// @brief Process incoming Decline message.
///
/// 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 [out] context pointer to the client context where declined
- /// leases are stored.
+ /// @param ctx Reference to client context
+ ///
+ /// @return Reply message to be sent to the client.
Pkt6Ptr processDecline(const Pkt6Ptr& decline,
- AllocEngine::ClientContext6Ptr& context);
+ AllocEngine::ClientContext6& ctx);
/// @brief Processes incoming Information-request message.
///
/// @param inf_request message received from client
+ /// @param ctx Reference to client context
+ ///
/// @return Reply message to be sent to the client.
- Pkt6Ptr processInfRequest(const Pkt6Ptr& inf_request);
+ Pkt6Ptr processInfRequest(const Pkt6Ptr& inf_request,
+ AllocEngine::ClientContext6& ctx);
/// @brief Processes incoming DHCPv4-query message.
///
/// to the client once we get back DHCP4-REPLY from the DHCPv4 server.
///
/// @param dhcp4_query message received from client
+ /// Does not throw
void processDhcp4Query(const Pkt6Ptr& dhcp4_query);
/// @brief Selects a subnet for a given client's packet.
#include <dhcpsrv/cfgmgr.h>
#include <dhcp6/dhcp6to4_ipc.h>
#include <dhcp6/dhcp6_log.h>
+#include <dhcp6/ctrl_dhcp6_srv.h>
#include <dhcp6/dhcp6_srv.h>
#include <exceptions/exceptions.h>
#include <hooks/callout_handle.h>
}
// Can't call the pkt6_send callout because we don't have the query
-
- ControlledDhcpv4Srv::getInstance()->
- processPacketBufferSend(getCalloutHandle(pkt), pkt);
+ CalloutHandlePtr callout_handle = getCalloutHandle(pkt);
+ ControlledDhcpv6Srv::getInstance()->
+ processPacketBufferSend(callout_handle, pkt);
}
}; // namespace dhcp
EXPECT_TRUE(query3->inClass("router"));
// Process queries
- Pkt6Ptr response1 = srv.processSolicit(query1);
- Pkt6Ptr response2 = srv.processSolicit(query2);
- Pkt6Ptr response3 = srv.processSolicit(query3);
+ AllocEngine::ClientContext6 ctx1;
+ bool drop = false;
+ srv.initContext(query1, ctx1, drop);
+ ASSERT_FALSE(drop);
+ Pkt6Ptr response1 = srv.processSolicit(query1, ctx1);
+ AllocEngine::ClientContext6 ctx2;
+ srv.initContext(query2, ctx2, drop);
+ ASSERT_FALSE(drop);
+ Pkt6Ptr response2 = srv.processSolicit(query2, ctx2);
+ AllocEngine::ClientContext6 ctx3;
+ srv.initContext(query3, ctx3, drop);
+ ASSERT_FALSE(drop);
+ Pkt6Ptr response3 = srv.processSolicit(query3, ctx3);
// Classification processing should add an ip-forwarding option
OptionPtr opt1 = response1->getOption(2345);
EXPECT_FALSE(query3->inClass("router"));
// Process queries
- Pkt6Ptr response1 = srv.processSolicit(query1);
- Pkt6Ptr response2 = srv.processSolicit(query2);
- Pkt6Ptr response3 = srv.processSolicit(query3);
+ AllocEngine::ClientContext6 ctx1;
+ bool drop = false;
+ srv.initContext(query1, ctx1, drop);
+ ASSERT_FALSE(drop);
+ Pkt6Ptr response1 = srv.processSolicit(query1, ctx1);
+ AllocEngine::ClientContext6 ctx2;
+ srv.initContext(query2, ctx2, drop);
+ ASSERT_FALSE(drop);
+ Pkt6Ptr response2 = srv.processSolicit(query2, ctx2);
+ AllocEngine::ClientContext6 ctx3;
+ srv.initContext(query3, ctx3, drop);
+ ASSERT_FALSE(drop);
+ Pkt6Ptr response3 = srv.processSolicit(query3, ctx3);
// Classification processing should do nothing
OptionPtr opt1 = response1->getOption(2345);
EXPECT_FALSE(query3->inClass("router"));
// Process queries
- Pkt6Ptr response1 = srv.processSolicit(query1);
- Pkt6Ptr response2 = srv.processSolicit(query2);
- Pkt6Ptr response3 = srv.processSolicit(query3);
+ AllocEngine::ClientContext6 ctx1;
+ bool drop = false;
+ srv.initContext(query1, ctx1, drop);
+ ASSERT_FALSE(drop);
+ Pkt6Ptr response1 = srv.processSolicit(query1, ctx1);
+ AllocEngine::ClientContext6 ctx2;
+ srv.initContext(query2, ctx2, drop);
+ ASSERT_FALSE(drop);
+ Pkt6Ptr response2 = srv.processSolicit(query2, ctx2);
+ AllocEngine::ClientContext6 ctx3;
+ srv.initContext(query3, ctx3, drop);
+ ASSERT_FALSE(drop);
+ Pkt6Ptr response3 = srv.processSolicit(query3, ctx3);
// Classification processing should add an ip-forwarding option
OptionPtr opt1 = response1->getOption(2345);
EXPECT_TRUE(query->inClass("router"));
// Process the query
- Pkt6Ptr response = srv.processSolicit(query);
+ AllocEngine::ClientContext6 ctx;
+ bool drop = false;
+ srv.initContext(query, ctx, drop);
+ ASSERT_FALSE(drop);
+ Pkt6Ptr response = srv.processSolicit(query, ctx);
// Processing should add an ip-forwarding option
OptionPtr opt = response->getOption(2345);
query->addOption(hostname);
// Process the query
- Pkt6Ptr response = srv.processSolicit(query);
+ AllocEngine::ClientContext6 ctx;
+ bool drop = false;
+ srv.initContext(query, ctx, drop);
+ ASSERT_FALSE(drop);
+ Pkt6Ptr response = srv.processSolicit(query, ctx);
// Processing should add an ip-forwarding option
OptionPtr opt = response->getOption(2345);
EXPECT_TRUE(query->inClass("router"));
// Process the query
- Pkt6Ptr response = srv.processSolicit(query);
+ AllocEngine::ClientContext6 ctx;
+ bool drop = false;
+ srv.initContext(query, ctx, drop);
+ ASSERT_FALSE(drop);
+ Pkt6Ptr response = srv.processSolicit(query, ctx);
// Processing should add an ip-forwarding option
OptionPtr opt = response->getOption(2345);
query->addOption(hostname);
// Process the query
- Pkt6Ptr response = srv.processSolicit(query);
+ AllocEngine::ClientContext6 ctx;
+ bool drop = false;
+ srv.initContext(query, ctx, drop);
+ ASSERT_FALSE(drop);
+ Pkt6Ptr response = srv.processSolicit(query, ctx);
// Processing should add an ip-forwarding option
OptionPtr opt = response->getOption(2345);
// This discover does not belong to foo class, so it will not
// be serviced
srv.classifyPacket(query1);
- Pkt6Ptr response1 = srv.processSolicit(query1);
+ AllocEngine::ClientContext6 ctx1;
+ bool drop = false;
+ srv.initContext(query1, ctx1, drop);
+ ASSERT_FALSE(drop);
+ Pkt6Ptr response1 = srv.processSolicit(query1, ctx1);
ASSERT_TRUE(response1);
OptionPtr ia_na1 = response1->getOption(D6O_IA_NA);
ASSERT_TRUE(ia_na1);
query2->addClass("bar");
// Still not supported, because it belongs to wrong class.
srv.classifyPacket(query2);
- Pkt6Ptr response2 = srv.processSolicit(query2);
+ AllocEngine::ClientContext6 ctx2;
+ srv.initContext(query2, ctx2, drop);
+ ASSERT_FALSE(drop);
+ Pkt6Ptr response2 = srv.processSolicit(query2, ctx2);
ASSERT_TRUE(response2);
OptionPtr ia_na2 = response2->getOption(D6O_IA_NA);
ASSERT_TRUE(ia_na2);
query3->addClass("foo");
// This time it should work
srv.classifyPacket(query3);
- Pkt6Ptr response3 = srv.processSolicit(query3);
+ AllocEngine::ClientContext6 ctx3;
+ srv.initContext(query3, ctx3, drop);
+ ASSERT_FALSE(drop);
+ Pkt6Ptr response3 = srv.processSolicit(query3, ctx3);
ASSERT_TRUE(response3);
OptionPtr ia_na3 = response3->getOption(D6O_IA_NA);
ASSERT_TRUE(ia_na3);
EXPECT_TRUE(query3->inClass("barz"));
// Process queries
- Pkt6Ptr response1 = srv.processSolicit(query1);
- Pkt6Ptr response2 = srv.processSolicit(query2);
- Pkt6Ptr response3 = srv.processSolicit(query3);
+ AllocEngine::ClientContext6 ctx1;
+ bool drop = false;
+ srv.initContext(query1, ctx1, drop);
+ ASSERT_FALSE(drop);
+ Pkt6Ptr response1 = srv.processSolicit(query1, ctx1);
+ AllocEngine::ClientContext6 ctx2;
+ srv.initContext(query2, ctx2, drop);
+ ASSERT_FALSE(drop);
+ Pkt6Ptr response2 = srv.processSolicit(query2, ctx2);
+ AllocEngine::ClientContext6 ctx3;
+ srv.initContext(query3, ctx3, drop);
+ ASSERT_FALSE(drop);
+ Pkt6Ptr response3 = srv.processSolicit(query3, ctx3);
// Classification processing should add an ip-forwarding option
OptionPtr opt1 = response1->getOption(2345);
-// Copyright (C) 2014-2017 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2014-2018 Internet Systems Consortium, Inc. ("ISC")
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// A message with no client-id should fail
Pkt6Ptr confirm = Pkt6Ptr(new Pkt6(DHCPV6_CONFIRM, 1234));
- EXPECT_THROW(srv.processConfirm(confirm), RFCViolation);
+ EXPECT_THROW(srv.sanityCheck(confirm, Dhcpv6Srv::MANDATORY,
+ Dhcpv6Srv::FORBIDDEN), RFCViolation);
// A message with a single client-id should succeed
OptionPtr clientid = generateClientId();
confirm->addOption(clientid);
- EXPECT_NO_THROW(srv.processConfirm(confirm));
+ EXPECT_NO_THROW(srv.sanityCheck(confirm, Dhcpv6Srv::MANDATORY,
+ Dhcpv6Srv::FORBIDDEN));
// A message with server-id present should fail
confirm->addOption(srv.getServerID());
- EXPECT_THROW(srv.processConfirm(confirm), RFCViolation);
+ EXPECT_THROW(srv.sanityCheck(confirm, Dhcpv6Srv::MANDATORY,
+ Dhcpv6Srv::FORBIDDEN), RFCViolation);
}
// Test that directly connected client's Confirm message is processed and Reply
sol->addOption(clientid);
// Pass it to the server and get an advertise
- Pkt6Ptr reply = srv.processSolicit(sol);
+ AllocEngine::ClientContext6 ctx;
+ bool drop = false;
+ srv.initContext(sol, ctx, drop);
+ ASSERT_FALSE(drop);
+ Pkt6Ptr reply = srv.processSolicit(sol, ctx);
// check that we get the right NAK
checkNakResponse(reply, DHCPV6_ADVERTISE, 1234, STATUS_NoAddrsAvail,
sol->addOption(clientid);
// Pass it to the server and get an advertise
- Pkt6Ptr adv = srv_.processSolicit(sol);
+ AllocEngine::ClientContext6 ctx;
+ bool drop = false;
+ srv_.initContext(sol, ctx, drop);
+ ASSERT_FALSE(drop);
+ Pkt6Ptr adv = srv_.processSolicit(sol, ctx);
// check if we get response at all
ASSERT_TRUE(adv);
sol->addOption(option_oro);
// Need to process SOLICIT again after requesting new option.
- adv = srv_.processSolicit(sol);
+ AllocEngine::ClientContext6 ctx2;
+ srv_.initContext(sol, ctx2, drop);
+ ASSERT_FALSE(drop);
+ adv = srv_.processSolicit(sol, ctx2);
ASSERT_TRUE(adv);
OptionPtr tmp = adv->getOption(D6O_NAME_SERVERS);
sol->addOption(clientid);
// Pass it to the server and get an advertise
- Pkt6Ptr reply = srv.processSolicit(sol);
+ AllocEngine::ClientContext6 ctx;
+ bool drop = false;
+ srv.initContext(sol, ctx, drop);
+ ASSERT_FALSE(drop);
+ Pkt6Ptr reply = srv.processSolicit(sol, ctx);
// check if we get response at all
checkResponse(reply, DHCPV6_ADVERTISE, 1234);
sol->addOption(clientid);
// Pass it to the server and get an advertise
- Pkt6Ptr reply = srv.processSolicit(sol);
+ AllocEngine::ClientContext6 ctx;
+ bool drop = false;
+ srv.initContext(sol, ctx, drop);
+ ASSERT_FALSE(drop);
+ Pkt6Ptr reply = srv.processSolicit(sol, ctx);
// check if we get response at all
checkResponse(reply, DHCPV6_ADVERTISE, 1234);
sol->addOption(clientid);
// Pass it to the server and get an advertise
- Pkt6Ptr reply = srv.processSolicit(sol);
+ AllocEngine::ClientContext6 ctx;
+ bool drop = false;
+ srv.initContext(sol, ctx, drop);
+ ASSERT_FALSE(drop);
+ Pkt6Ptr reply = srv.processSolicit(sol, ctx);
// check if we get response at all
checkResponse(reply, DHCPV6_ADVERTISE, 1234);
sol->addOption(clientid);
// Pass it to the server and get an advertise
- Pkt6Ptr reply = srv.processSolicit(sol);
+ AllocEngine::ClientContext6 ctx;
+ bool drop = false;
+ srv.initContext(sol, ctx, drop);
+ ASSERT_FALSE(drop);
+ Pkt6Ptr reply = srv.processSolicit(sol, ctx);
// check if we get response at all
checkResponse(reply, DHCPV6_ADVERTISE, 1234);
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);
+ AllocEngine::ClientContext6 ctx1;
+ bool drop = false;
+ srv.initContext(sol1, ctx1, drop);
+ ASSERT_FALSE(drop);
+ Pkt6Ptr reply1 = srv.processSolicit(sol1, ctx1);
+ AllocEngine::ClientContext6 ctx2;
+ srv.initContext(sol2, ctx2, drop);
+ ASSERT_FALSE(drop);
+ Pkt6Ptr reply2 = srv.processSolicit(sol2, ctx2);
+ AllocEngine::ClientContext6 ctx3;
+ srv.initContext(sol3, ctx3, drop);
+ ASSERT_FALSE(drop);
+ Pkt6Ptr reply3 = srv.processSolicit(sol3, ctx3);
// check if we get response at all
checkResponse(reply1, DHCPV6_ADVERTISE, 1234);
sol->addOption(oro);
// Let the server process it and generate a response.
- Pkt6Ptr response = srv_.processSolicit(sol);
+ AllocEngine::ClientContext6 ctx;
+ bool drop = false;
+ srv_.initContext(sol, ctx, drop);
+ ASSERT_FALSE(drop);
+ Pkt6Ptr response = srv_.processSolicit(sol, ctx);
// The server should add a subscriber-id option
ASSERT_TRUE(response->getOption(D6O_SUBSCRIBER_ID));
// Let the server process it again. This time the name-servers
// option should be present.
- response = srv_.processSolicit(sol);
+ AllocEngine::ClientContext6 ctx2;
+ srv_.initContext(sol, ctx2, drop);
+ ASSERT_FALSE(drop);
+ response = srv_.processSolicit(sol, ctx2);
// Processing should add a subscriber-id option
ASSERT_TRUE(response->getOption(D6O_SUBSCRIBER_ID));
sol->addOption(clientid);
// Pass it to the server and get an advertise
- Pkt6Ptr adv = srv_.processSolicit(sol);
+ AllocEngine::ClientContext6 ctx;
+ bool drop = false;
+ srv_.initContext(sol, ctx, drop);
+ ASSERT_FALSE(drop);
+ Pkt6Ptr adv = srv_.processSolicit(sol, ctx);
// check if we get response at all
ASSERT_TRUE(adv);
sol->addOption(vendor);
// Need to process SOLICIT again after requesting new option.
- adv = srv_.processSolicit(sol);
+ AllocEngine::ClientContext6 ctx2;
+ srv_.initContext(sol, ctx2, drop);
+ ASSERT_FALSE(drop);
+ adv = srv_.processSolicit(sol, ctx2);
ASSERT_TRUE(adv);
// Check if there is vendor option response
sol->addOption(vendor);
// Pass it to the server and get an advertise
- Pkt6Ptr adv = srv_.processSolicit(sol);
+ AllocEngine::ClientContext6 ctx;
+ bool drop = false;
+ srv_.initContext(sol, ctx, drop);
+ ASSERT_FALSE(drop);
+ Pkt6Ptr adv = srv_.processSolicit(sol, ctx);
// check if we get response at all
ASSERT_TRUE(adv);
/// @param request a message received from client
/// @return REPLY message or NULL
Pkt6Ptr processRequest(const Pkt6Ptr& request) {
- AllocEngine::ClientContext6Ptr context(new AllocEngine::ClientContext6());
- return (processRequest(request, context));
+ AllocEngine::ClientContext6 ctx;
+ return (processRequest(request, ctx));
}
/// @brief Processes incoming Renew message.
/// @param renew a message received from client
/// @return REPLY message or NULL
Pkt6Ptr processRenew(const Pkt6Ptr& renew) {
- AllocEngine::ClientContext6Ptr context(new AllocEngine::ClientContext6());
- return (processRenew(renew, context));
+ AllocEngine::ClientContext6 ctx;
+ return (processRenew(renew, ctx));
}
/// @brief Processes incoming Rebind message.
/// @param rebind a message received from client
/// @return REPLY message or NULL
Pkt6Ptr processRebind(const Pkt6Ptr& rebind) {
- AllocEngine::ClientContext6Ptr context(new AllocEngine::ClientContext6());
- return (processRebind(rebind, context));
+ AllocEngine::ClientContext6 ctx;
+ return (processRebind(rebind, ctx));
}
/// @brief Processes incoming Release message.
/// @param release a message received from client
/// @return REPLY message or NULL
Pkt6Ptr processRelease(const Pkt6Ptr& release) {
- AllocEngine::ClientContext6Ptr context(new AllocEngine::ClientContext6());
- return (processRelease(release, context));
+ AllocEngine::ClientContext6 ctx;
+ return (processRelease(release, ctx));
}
/// @brief Processes incoming Decline message.
/// @param decline a message received from client
/// @return REPLY message or NULL
Pkt6Ptr processDecline(const Pkt6Ptr& decline) {
- AllocEngine::ClientContext6Ptr context(new AllocEngine::ClientContext6());
- return (processDecline(decline, context));
+ AllocEngine::ClientContext6 ctx;
+ return (processDecline(decline, ctx));
}
using Dhcpv6Srv::processSolicit;
-// Copyright (C) 2013-2017 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2013-2018 Internet Systems Consortium, Inc. ("ISC")
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// For different client's message types we have to invoke different
// functions to generate response.
Pkt6Ptr reply;
+ AllocEngine::ClientContext6 ctx;
+ bool drop = false;
+ srv_->initContext(req, ctx, drop);
+ ASSERT_FALSE(drop);
if (msg_type == DHCPV6_SOLICIT) {
- ASSERT_NO_THROW(reply = srv_->processSolicit(req));
+ ASSERT_NO_THROW(reply = srv_->processSolicit(req, ctx));
} else if (msg_type == DHCPV6_REQUEST) {
- ASSERT_NO_THROW(reply = srv_->processRequest(req));
+ ASSERT_NO_THROW(reply = srv_->processRequest(req, ctx));
} else if (msg_type == DHCPV6_RENEW) {
- ASSERT_NO_THROW(reply = srv_->processRenew(req));
+ ASSERT_NO_THROW(reply = srv_->processRenew(req, ctx));
} else if (msg_type == DHCPV6_RELEASE) {
// For Release no lease will be acquired so we have to leave
// function here.
- ASSERT_NO_THROW(reply = srv_->processRelease(req));
+ ASSERT_NO_THROW(reply = srv_->processRelease(req, ctx));
return;
} else {
// We are not interested in testing other message types.
// The following fields are used in testing pkt6_receive_callout.
// See fields description in the class for details
-IOServicePtr HooksDhcpv4SrvTest::io_service_;
+IOServicePtr HooksDhcpv6SrvTest::io_service_;
string HooksDhcpv6SrvTest::callback_name_;
Pkt6Ptr HooksDhcpv6SrvTest::callback_qry_pkt6_;
Pkt6Ptr HooksDhcpv6SrvTest::callback_resp_pkt6_;
sol->addOption(clientid);
// Pass it to the server and get an advertise
- Pkt6Ptr adv = srv_->processSolicit(sol);
+ AllocEngine::ClientContext6 ctx;
+ bool drop = false;
+ srv_->initContext(sol, ctx, drop);
+ ASSERT_FALSE(drop);
+ Pkt6Ptr adv = srv_->processSolicit(sol, ctx);
// Check if we get response at all
ASSERT_TRUE(adv);
sol->addOption(clientid);
// Pass it to the server and get an advertise
- Pkt6Ptr adv = srv_->processSolicit(sol);
+ AllocEngine::ClientContext6 ctx;
+ bool drop = false;
+ srv_->initContext(sol, ctx, drop);
+ ASSERT_FALSE(drop);
+ Pkt6Ptr adv = srv_->processSolicit(sol, ctx);
// Check if we get response at all
ASSERT_TRUE(adv);
ASSERT_EQ(0, srv_->fake_sent_.size());
}
+// This test verifies that the leases6_committed hook point is not triggered
+// for the SOLICIT.
+TEST_F(HooksDhcpv6SrvTest, leases6CommittedSolicit) {
+ IfaceMgrTestConfig test_config(true);
+
+ // Install leases6_committed callout
+ ASSERT_NO_THROW(HooksManager::preCalloutsLibraryHandle().registerCallout(
+ "leases6_committed", leases6_committed_callout));
+
+
+ Dhcp6Client client;
+ client.setInterface("eth1");
+ ASSERT_NO_THROW(client.doSolicit());
+
+ // Make sure that we received a response
+ ASSERT_TRUE(client.getContext().response_);
+
+ // Make sure that the callout wasn't called.
+ EXPECT_TRUE(callback_name_.empty());
+}
+
+// This test verifies that the leases6_committed hook point is not triggered
+// for the INFREQUEST.
+TEST_F(HooksDhcpv6SrvTest, leases6CommittedInfRequest) {
+ IfaceMgrTestConfig test_config(true);
+
+ ASSERT_NO_THROW(HooksManager::preCalloutsLibraryHandle().registerCallout(
+ "leases6_committed", leases6_committed_callout));
+
+
+ Dhcp6Client client;
+ client.useRelay();
+ ASSERT_NO_THROW(client.doInfRequest());
+
+ // Make sure that we received a response
+ ASSERT_TRUE(client.getContext().response_);
+
+ // Make sure that the callout wasn't called.
+ EXPECT_TRUE(callback_name_.empty());
+}
+
// This test verifies that incoming (positive) RENEW can be handled properly,
// and the lease6_renew callouts are triggered.
TEST_F(HooksDhcpv6SrvTest, basicLease6Renew) {
EXPECT_NE(l->cltt_, time(NULL));
}
+// This test verifies that the callout installed on the leases6_committed hook
+// point is executed as a result of REQUEST message sent to allocate new
+// lease or renew an existing lease.
+TEST_F(HooksDhcpv6SrvTest, leases6CommittedRequest) {
+ IfaceMgrTestConfig test_config(true);
+
+ ASSERT_NO_THROW(HooksManager::preCalloutsLibraryHandle().registerCallout(
+ "leases6_committed", leases6_committed_callout));
+
+
+ Dhcp6Client client;
+ client.setInterface("eth1");
+ client.requestAddress(0xabca, IOAddress("2001:db8:1::28"));
+ ASSERT_NO_THROW(client.doSARR());
+
+ // Make sure that we received a response
+ ASSERT_TRUE(client.getContext().response_);
+
+ // Check that the callback called is indeed the one we installed
+ EXPECT_EQ("leases6_committed", callback_name_);
+
+ // Check if all expected parameters were really received
+ vector<string> expected_argument_names;
+ expected_argument_names.push_back("query6");
+ expected_argument_names.push_back("deleted_leases6");
+ expected_argument_names.push_back("leases6");
+
+ sort(expected_argument_names.begin(), expected_argument_names.end());
+ EXPECT_TRUE(callback_argument_names_ == expected_argument_names);
+
+ // Newly allocated lease should be returned.
+ ASSERT_TRUE(callback_lease6_);
+ EXPECT_EQ("2001:db8:1::28", callback_lease6_->addr_.toText());
+
+ // Deleted lease must not be present, because it is a new allocation.
+ EXPECT_FALSE(callback_deleted_lease6_);
+
+ // Pkt passed to a callout must be configured to copy retrieved options.
+ EXPECT_TRUE(callback_qry_options_copy_);
+
+ resetCalloutBuffers();
+
+ // Renew the lease and make sure that the callout has been executed.
+ ASSERT_NO_THROW(client.doRenew());
+
+ // Make sure that we received a response
+ ASSERT_TRUE(client.getContext().response_);
+
+ // Check that the callback called is indeed the one we installed
+ EXPECT_EQ("leases6_committed", callback_name_);
+
+ // Renewed lease should be returned.
+ ASSERT_TRUE(callback_lease6_);
+ EXPECT_EQ("2001:db8:1::28", callback_lease6_->addr_.toText());
+
+ // Deleted lease must not be present, because it is a new allocation.
+ EXPECT_FALSE(callback_deleted_lease6_);
+
+ // Pkt passed to a callout must be configured to copy retrieved options.
+ EXPECT_TRUE(callback_qry_options_copy_);
+
+ resetCalloutBuffers();
+
+ // Let's try to renew again but force the client to request a different
+ // address.
+ client.requestAddress(0xabca, IOAddress("2001:db8:1::29"));
+
+ ASSERT_NO_THROW(client.doRequest());
+
+ // Make sure that we received a response
+ ASSERT_TRUE(client.getContext().response_);
+
+ // Check that the callback called is indeed the one we installed
+ EXPECT_EQ("leases6_committed", callback_name_);
+
+ // New lease should be returned.
+ ASSERT_TRUE(callback_lease6_);
+ EXPECT_EQ("2001:db8:1::29", callback_lease6_->addr_.toText());
+
+ // The old lease should have been deleted.
+ ASSERT_TRUE(callback_deleted_lease6_);
+ EXPECT_EQ("2001:db8:1::28", callback_deleted_lease6_->addr_.toText());
+
+ // Pkt passed to a callout must be configured to copy retrieved options.
+ EXPECT_TRUE(callback_qry_options_copy_);
+
+ resetCalloutBuffers();
+
+ // Now request an address that can't be allocated. The client should receive
+ // an error.
+
+ client.requestAddress(0xabca, IOAddress("4000::2"));
+ //// client.ciaddr_ = IOAddress("10.0.0.1");
+
+ ASSERT_NO_THROW(client.doRequest());
+
+ // Make sure that we received a response
+ ASSERT_TRUE(client.getContext().response_);
+
+ // Check that the callback called is indeed the one we installed
+ EXPECT_EQ("leases6_committed", callback_name_);
+
+ EXPECT_FALSE(callback_lease6_);
+ EXPECT_FALSE(callback_deleted_lease6_);
+}
+
+// This test verifies that it is possible to park a packet as a result of
+// the leases6_committed callouts.
+TEST_F(HooksDhcpv6SrvTest, leases6CommittedParkRequests) {
+ IfaceMgrTestConfig test_config(true);
+
+ // This callout uses provided IO service object to post a function
+ // that unparks the packet. The packet is parked and can be unparked
+ // by simply calling IOService::poll.
+ ASSERT_NO_THROW(HooksManager::preCalloutsLibraryHandle().registerCallout(
+ "leases6_committed", leases6_committed_park_callout));
+
+ // Create first client and perform DORA.
+ Dhcp6Client client1;
+ client1.setInterface("eth1");
+ client1.requestAddress(0xabca, IOAddress("2001:db8:1::28"));
+ ASSERT_NO_THROW(client1.doSARR());
+
+ // We should be offered an address but the REPLY should not arrive
+ // at this point, because the packet is parked.
+ ASSERT_FALSE(client1.getContext().response_);
+
+ // Check that the callback called is indeed the one we installed
+ EXPECT_EQ("leases6_committed", callback_name_);
+
+ // Check if all expected parameters were really received
+ vector<string> expected_argument_names;
+ expected_argument_names.push_back("query6");
+ expected_argument_names.push_back("deleted_leases6");
+ expected_argument_names.push_back("leases6");
+
+ sort(expected_argument_names.begin(), expected_argument_names.end());
+ EXPECT_TRUE(callback_argument_names_ == expected_argument_names);
+
+ // Newly allocated lease should be passed to the callout.
+ ASSERT_TRUE(callback_lease6_);
+ EXPECT_EQ("2001:db8:1::28", callback_lease6_->addr_.toText());
+
+ // Deleted lease must not be present, because it is a new allocation.
+ EXPECT_FALSE(callback_deleted_lease6_);
+
+ // Pkt passed to a callout must be configured to copy retrieved options.
+ EXPECT_TRUE(callback_qry_options_copy_);
+
+ // Reset all indicators because we'll be now creating a second client.
+ resetCalloutBuffers();
+
+ // Create the second client to test that it may communicate with the
+ // server while the previous packet is parked.
+ Dhcp6Client client2;
+ client2.setInterface("eth1");
+ client2.requestAddress(0xabca, IOAddress("2001:db8:1::29"));
+ ASSERT_NO_THROW(client2.doSARR());
+
+ // The DHCPOFFER should have been returned but not DHCPACK, as this
+ // packet got parked too.
+ ASSERT_FALSE(client2.getContext().response_);
+
+ // Check that the callback called is indeed the one we installed.
+ EXPECT_EQ("leases6_committed", callback_name_);
+
+ // There should be now two actions scheduled on our IO service
+ // by the invoked callouts. They unpark both DHCPACK messages.
+ ASSERT_NO_THROW(io_service_->poll());
+
+ // Receive and check the first response.
+ ASSERT_NO_THROW(client1.receiveResponse());
+ ASSERT_TRUE(client1.getContext().response_);
+ Pkt6Ptr rsp = client1.getContext().response_;
+ EXPECT_EQ(DHCPV6_REPLY, rsp->getType());
+ //// EXPECT_EQ("2001:db8:1::28", rsp->getYiaddr().toText());
+
+ // Receive and check the second response.
+ ASSERT_NO_THROW(client2.receiveResponse());
+ ASSERT_TRUE(client2.getContext().response_);
+ rsp = client2.getContext().response_;
+ EXPECT_EQ(DHCPV6_REPLY, rsp->getType());
+ //// EXPECT_EQ("2001:db8:1::29", rsp->getYiaddr().toText());
+}
+
// 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.
ASSERT_TRUE(l);
}
+/// leases4CommittedRelease
+
// This test verifies that incoming (positive) REBIND can be handled properly,
// and the lease6_rebind callouts are triggered.
TEST_F(HooksDhcpv6SrvTest, basicLease6Rebind) {
EXPECT_NE(l->cltt_, time(NULL));
}
+/// leases4CommittedRebind
+
// This test checks that the basic decline hook (lease6_decline) is
// triggered properly.
TEST_F(HooksDhcpv6SrvTest, basicLease6Decline) {
EXPECT_EQ(Lease::STATE_DEFAULT, from_mgr->state_);
}
+/// leases4CommittedDecline
+
// Checks if callout installed on host6_identifier can generate an
// identifier and whether that identifier is actually used.
TEST_F(HooksDhcpv6SrvTest, host6Identifier) {
sol->addOption(clientid);
// Pass it to the server and get an advertise
- Pkt6Ptr adv = srv_->processSolicit(sol);
+ AllocEngine::ClientContext6 ctx;
+ bool drop = false;
+ srv_->initContext(sol, ctx, drop);
+ ASSERT_FALSE(drop);
+ Pkt6Ptr adv = srv_->processSolicit(sol, ctx);
// Check if we get response at all
ASSERT_TRUE(adv);
sol->addOption(clientid);
// Pass it to the server and get an advertise
- Pkt6Ptr adv = srv_->processSolicit(sol);
+ AllocEngine::ClientContext6 ctx;
+ bool drop = false;
+ srv_->initContext(sol, ctx, drop);
+ ASSERT_FALSE(drop);
+ Pkt6Ptr adv = srv_->processSolicit(sol, ctx);
// Check if we get response at all
ASSERT_TRUE(adv);
}
+// Checks if callouts installed on the dhcp6_srv_configured ared indeed called
+// and all the necessary parameters are passed.
+TEST_F(LoadUnloadDhcpv6SrvTest, Dhcpv6SrvConfigured) {
+ boost::shared_ptr<ControlledDhcpv6Srv> srv(new ControlledDhcpv6Srv(0));
+
+ // Ensure no marker files to start with.
+ ASSERT_FALSE(checkMarkerFileExists(LOAD_MARKER_FILE));
+ ASSERT_FALSE(checkMarkerFileExists(UNLOAD_MARKER_FILE));
+ ASSERT_FALSE(checkMarkerFileExists(SRV_CONFIG_MARKER_FILE));
+
+ // Minimal valid configuration for the server. It includes the
+ // section which loads the callout library #3, which implements
+ // dhcp6_srv_configured callout.
+ std::string config_str =
+ "{"
+ " \"interfaces-config\": {"
+ " \"interfaces\": [ ]"
+ " },"
+ " \"preferred-lifetime\": 3000,"
+ " \"rebind-timer\": 2000,"
+ " \"renew-timer\": 1000,"
+ " \"subnet6\": [ ],"
+ " \"valid-lifetime\": 4000,"
+ " \"lease-database\": {"
+ " \"type\": \"memfile\","
+ " \"persist\": false"
+ " },"
+ " \"hooks-libraries\": ["
+ " {"
+ " \"library\": \"" + std::string(CALLOUT_LIBRARY_3) + "\""
+ " }"
+ " ]"
+ "}";
+
+ ConstElementPtr config = Element::fromJSON(config_str);
+
+ // Configure the server.
+ ConstElementPtr answer;
+ ASSERT_NO_THROW(answer = srv->processConfig(config));
+
+ // Make sure there were no errors.
+ int status_code;
+ isc::config::parseAnswer(status_code, answer);
+ ASSERT_EQ(0, status_code);
+
+ // The hook library should have been loaded.
+ EXPECT_TRUE(checkMarkerFile(LOAD_MARKER_FILE, "3"));
+ EXPECT_FALSE(checkMarkerFileExists(UNLOAD_MARKER_FILE));
+ // The dhcp6_srv_configured should have been invoked and the provided
+ // parameters should be recorded.
+ EXPECT_TRUE(checkMarkerFile(SRV_CONFIG_MARKER_FILE,
+ "3io_contextjson_confignetwork_stateserver_config"));
+
+ // Destroy the server, instance which should unload the libraries.
+ srv.reset();
+
+ // The server was destroyed, so the unload() function should now
+ // include the library number in its marker file.
+ EXPECT_TRUE(checkMarkerFile(LOAD_MARKER_FILE, "3"));
+ EXPECT_TRUE(checkMarkerFile(UNLOAD_MARKER_FILE, "3"));
+ EXPECT_TRUE(checkMarkerFile(SRV_CONFIG_MARKER_FILE,
+ "3io_contextjson_confignetwork_stateserver_config"));
+}
+
} // end of anonymous namespace
/// @param timeout_ms Amount of time after which the method returns.
void runTimersWithTimeout(const IOServicePtr& io_service, const long timeout_ms) {
IntervalTimer timer(*io_service);
- timer.setup([this, &io_service]() {
+ timer.setup([&io_service]() {
io_service->stop();
}, timeout_ms, IntervalTimer::ONE_SHOT);
io_service->run();
IOAddress requested_address = exp_addr1.empty() ? IOAddress::IPV6_ZERO_ADDRESS() :
IOAddress(exp_addr1);
ASSERT_NO_THROW(client1.requestAddress(0xabca0, requested_address));
- testAssigned([this, &client1] {
+ testAssigned([&client1] {
ASSERT_NO_THROW(client1.doSolicit());
});
// first subnet is already full (it's a really small subnet) and the second
// subnet does not allow rapid-commit.
ASSERT_NO_THROW(client2.requestAddress(0xabca0));
- testAssigned([this, &client2] {
+ testAssigned([&client2] {
ASSERT_NO_THROW(client2.doSolicit());
});
// Client #1 requests an address in first subnet within a shared network.
ASSERT_NO_THROW(client1.requestAddress(0xabca0, IOAddress("2001:db8:1::20")));
- testAssigned([this, &client1] {
+ testAssigned([&client1] {
ASSERT_NO_THROW(client1.doSARR());
});
ASSERT_TRUE(hasLeaseForAddress(client1, IOAddress("2001:db8:1::20")));
Dhcp6Client client2(client1.getServer());
client2.setInterface("eth1");
ASSERT_NO_THROW(client2.requestAddress(0xabca0));
- testAssigned([this, &client2] {
+ testAssigned([&client2] {
ASSERT_NO_THROW(client2.doSARR());
});
ASSERT_TRUE(hasLeaseForAddress(client2, IOAddress("2001:db8:2::20")));
Dhcp6Client client3(client1.getServer());
client3.setInterface("eth1");
ASSERT_NO_THROW(client3.requestAddress(0xabca0));
- testAssigned([this, &client3] {
+ testAssigned([&client3] {
ASSERT_NO_THROW(client3.doSolicit(true));
});
EXPECT_EQ(0, client3.getLeaseNum());
// Client #3 should be assigned an address if subnet 3 is selected for it.
client3.setInterface("eth0");
- testAssigned([this, &client3] {
+ testAssigned([&client3] {
ASSERT_NO_THROW(client3.doSolicit(true));
});
EXPECT_EQ(1, client3.getLeaseNum());
// Client #1 should be able to renew its lease.
- testAssigned([this, &client1] {
+ testAssigned([&client1] {
ASSERT_NO_THROW(client1.doRenew());
});
EXPECT_EQ(1, client1.getLeaseNum());
EXPECT_TRUE(hasLeaseForAddress(client1, IOAddress("2001:db8:1::20")));
// Client #2 should be able to renew its lease too.
- testAssigned([this, &client2] {
+ testAssigned([&client2] {
ASSERT_NO_THROW(client2.doRenew());
});
EXPECT_EQ(1, client2.getLeaseNum());
// Client #1 should be assigned an address from shared network.
ASSERT_NO_THROW(client1.requestAddress(0xabca0));
- testAssigned([this, &client1] {
+ testAssigned([&client1] {
ASSERT_NO_THROW(client1.doSARR());
});
ASSERT_TRUE(hasLeaseForAddress(client1, IOAddress("2001:db8:1::20")));
Dhcp6Client client2(client1.getServer());
client2.useRelay(true, IOAddress("3001::2"));
ASSERT_NO_THROW(client2.requestAddress(0xabca0));
- testAssigned([this, &client2] {
+ testAssigned([&client2] {
ASSERT_NO_THROW(client2.doSARR());
});
ASSERT_TRUE(hasLeaseForAddress(client2, IOAddress("2001:db8:2::20")));
// Provide a hint to an existing address within first subnet. This address
// should be offered out of this subnet.
ASSERT_NO_THROW(client.requestAddress(0xabca, IOAddress("2001:db8:1::20")));
- testAssigned([this, &client] {
+ testAssigned([&client] {
ASSERT_NO_THROW(client.doSolicit(true));
});
ASSERT_TRUE(hasLeaseForAddress(client, IOAddress("2001:db8:1::20"),
// the same shared network when we ask for it.
client.clearRequestedIAs();
ASSERT_NO_THROW(client.requestAddress(0xabca, IOAddress("2001:db8:2::20")));
- testAssigned([this, &client] {
+ testAssigned([&client] {
ASSERT_NO_THROW(client.doSolicit(true));
});
ASSERT_TRUE(hasLeaseForAddress(client, IOAddress("2001:db8:2::20"),
// an address from one of the subnets, but generally hard to tell from which one.
client.clearRequestedIAs();
ASSERT_NO_THROW(client.requestAddress(0xabca, IOAddress("3002::123")));
- testAssigned([this, &client] {
+ testAssigned([&client] {
ASSERT_NO_THROW(client.doSolicit(true));
});
std::vector<Lease6> leases = client.getLeasesByType(Lease::TYPE_NA);
// Client #1 requests an address in the restricted subnet but can't be assigned
// this address because the client doesn't belong to a certain class.
ASSERT_NO_THROW(client1.requestAddress(0xabca, IOAddress("2001:db8:1::20")));
- testAssigned([this, &client1] {
+ testAssigned([&client1] {
ASSERT_NO_THROW(client1.doSARR());
});
ASSERT_TRUE(hasLeaseForAddress(client1, IOAddress("2001:db8:2::20")));
// Release the lease that the client has got, because we'll need this address
// further in the test.
- testAssigned([this, &client1] {
+ testAssigned([&client1] {
ASSERT_NO_THROW(client1.doRelease());
});
client1.addExtraOption(option1234);
// This time, the allocation of the address provided as hint should be successful.
- testAssigned([this, &client1] {
+ testAssigned([&client1] {
ASSERT_NO_THROW(client1.doSARR());
});
ASSERT_TRUE(hasLeaseForAddress(client1, IOAddress("2001:db8:1::20")));
Dhcp6Client client2(client1.getServer());
client2.setInterface("eth1");
ASSERT_NO_THROW(client2.requestAddress(0xabca0));
- testAssigned([this, &client2] {
+ testAssigned([&client2] {
ASSERT_NO_THROW(client2.doSARR());
});
ASSERT_TRUE(hasLeaseForAddress(client2, IOAddress("2001:db8:2::20")));
// subnet to which client2 now belongs.
ASSERT_NO_FATAL_FAILURE(configure(NETWORKS_CONFIG[3], *client1.getServer()));
- testAssigned([this, &client2] {
+ testAssigned([&client2] {
ASSERT_NO_THROW(client2.doRenew());
});
EXPECT_EQ(0, client2.getLeaseNum());
// get renewed.
OptionPtr option1234_bis(new OptionUint16(Option::V6, 1234, 0x0002));
client2.addExtraOption(option1234_bis);
- testAssigned([this, &client2] {
+ testAssigned([&client2] {
ASSERT_NO_THROW(client2.doRenew());
});
EXPECT_EQ(1, client2.getLeaseNum());
// Client #1 should get his reserved address from the second subnet.
ASSERT_NO_THROW(client1.requestAddress(0xabca, IOAddress("2001:db8:1::20")));
- testAssigned([this, &client1] {
+ testAssigned([&client1] {
ASSERT_NO_THROW(client1.doSARR());
});
ASSERT_TRUE(hasLeaseForAddress(client1, IOAddress("2001:db8:2::28")));
// Client #2 should get its reserved address from the first subnet.
ASSERT_NO_THROW(client2.requestAddress(0xabca, IOAddress("2001:db8:1::30")));
- testAssigned([this, &client2] {
+ testAssigned([&client2] {
ASSERT_NO_THROW(client2.doSARR());
});
ASSERT_TRUE(hasLeaseForAddress(client2, IOAddress("2001:db8:1::28")));
// because its lease is now reserved for some other client. The client won't be
// assigned a lease for which it has a reservation because another client holds
// this lease.
- testAssigned([this, &client1] {
+ testAssigned([&client1] {
ASSERT_NO_THROW(client1.doRenew());
});
ASSERT_TRUE(client1.hasLeaseWithZeroLifetimeForAddress(IOAddress("2001:db8:2::28")));
}
// Client #2 is now renewing its lease and should get its newly reserved address.
- testAssigned([this, &client2] {
+ testAssigned([&client2] {
ASSERT_NO_THROW(client2.doRenew());
});
ASSERT_TRUE(client2.hasLeaseWithZeroLifetimeForAddress(IOAddress("2001:db8:1::28")));
ASSERT_TRUE(hasLeaseForAddress(client2, IOAddress("2001:db8:2::28")));
// Same for client #1.
- testAssigned([this, &client1] {
+ testAssigned([&client1] {
ASSERT_NO_THROW(client1.doRenew());
});
ASSERT_TRUE(hasLeaseForAddress(client1, IOAddress("2001:db8:1::28")));
// Assigned address should be allocated from the second subnet, because the
// client doesn't belong to the "a-devices" class.
ASSERT_NO_THROW(client.requestAddress(0xabca));
- testAssigned([this, &client] {
+ testAssigned([&client] {
ASSERT_NO_THROW(client.doSARR());
});
ASSERT_TRUE(hasLeaseForAddress(client, IOAddress("2001:db8:2::16")));
client.addExtraOption(option1234);
// The client should now be assigned the reserved address from the first subnet.
- testAssigned([this, &client] {
+ testAssigned([&client] {
ASSERT_NO_THROW(client.doRenew());
});
ASSERT_TRUE(client.hasLeaseWithZeroLifetimeForAddress(IOAddress("2001:db8:2::16")));
// Client requests an address from the second subnet which should be successful.
ASSERT_NO_THROW(client.requestAddress(0xabca, IOAddress("2001:db8:2::20")));
- testAssigned([this, &client] {
+ testAssigned([&client] {
ASSERT_NO_THROW(client.doSARR());
});
ASSERT_TRUE(hasLeaseForAddress(client, IOAddress("2001:db8:2::20")));
// The client should not be able to renew the existing lease because it is now
// prohibited by the classification. Instead, the client should get a lease from the
// unrestricted subnet.
- testAssigned([this, &client] {
+ testAssigned([&client] {
ASSERT_NO_THROW(client.doRenew());
});
ASSERT_TRUE(client.hasLeaseWithZeroLifetimeForAddress(IOAddress("2001:db8:2::20")));
// Perform 4-way exchange and make sure we have been assigned address from the
// subnet we wanted.
- testAssigned([this, &client1] {
+ testAssigned([&client1] {
ASSERT_NO_THROW(client1.doSARR());
});
ASSERT_TRUE(hasLeaseForAddress(client1, IOAddress("2001:db8:1::20")));
// Perform 4-way exchange and make sure we have been assigned address from the
// subnet we wanted.
- testAssigned([this, &client2] {
+ testAssigned([&client2] {
ASSERT_NO_THROW(client2.doSARR());
});
ASSERT_TRUE(hasLeaseForAddress(client2, IOAddress("2001:db8:2::20")));
// Perform 4-way exchange and make sure we have been assigned address from the
// subnet we wanted.
- testAssigned([this, &client3] {
+ testAssigned([&client3] {
ASSERT_NO_THROW(client3.doSARR());
});
ASSERT_TRUE(hasLeaseForAddress(client3, IOAddress("3000::1")));
// Send solicit without a hint. The client should be offerred an address from the
// shared network. Depending on the subnet from which the address has been allocated
// a specific value of the Name Servers option should be returned.
- testAssigned([this, &client] {
+ testAssigned([&client] {
ASSERT_NO_THROW(client.doSolicit(true));
});
client.clearRequestedIAs();
client.requestAddress(0xabca, IOAddress("2001:db8:2::20"));
- testAssigned([this, &client] {
+ testAssigned([&client] {
ASSERT_NO_THROW(client.doSolicit(true));
});
ASSERT_TRUE(client.hasOptionWithAddress(D6O_NAME_SERVERS, "5555::33"));
// This time, let's do the 4-way exchange.
- testAssigned([this, &client] {
+ testAssigned([&client] {
ASSERT_NO_THROW(client.doSARR());
});
ASSERT_TRUE(client.hasOptionWithAddress(D6O_NAME_SERVERS, "5555::33"));
// And renew the lease.
- testAssigned([this, &client] {
+ testAssigned([&client] {
ASSERT_NO_THROW(client.doRenew());
});
ASSERT_TRUE(client.hasLeaseForAddress(IOAddress("2001:db8:2::20")));
// Client #1 should be assigned an address from one of the two subnets
// belonging to the first shared network.
- testAssigned([this, &client1] {
+ testAssigned([&client1] {
ASSERT_NO_THROW(client1.doSARR());
});
if (!hasLeaseForAddress(client1, IOAddress("2001:db8:1::20")) &&
// Client #2 should be assigned an address from one of the two subnets
// belonging to the second shared network.
- testAssigned([this, &client2] {
+ testAssigned([&client2] {
ASSERT_NO_THROW(client2.doSARR());
});
if (!hasLeaseForAddress(client2, IOAddress("2001:db8:3::20")) &&
// Client #1 should be assigned an address from one of the two subnets
// belonging to the first shared network.
- testAssigned([this, &client1] {
+ testAssigned([&client1] {
ASSERT_NO_THROW(client1.doSARR());
});
if (!hasLeaseForAddress(client1, IOAddress("2001:db8:1::20")) &&
// Client #2 should be assigned an address from one of the two subnets
// belonging to the second shared network
- testAssigned([this, &client2] {
+ testAssigned([&client2] {
ASSERT_NO_THROW(client2.doSARR());
});
if (!hasLeaseForAddress(client2, IOAddress("2001:db8:3::20")) &&
ASSERT_NO_FATAL_FAILURE(configure(NETWORKS_CONFIG[10], *client.getServer()));
// Perform 4-way exchange.
- testAssigned([this, &client] {
+ testAssigned([&client] {
ASSERT_NO_THROW(client.doSARR());
});
ASSERT_NO_FATAL_FAILURE(configure(NETWORKS_CONFIG[11], *client1.getServer()));
// The client 1 should be offerred an address from the second subnet.
- testAssigned([this, &client1] {
+ testAssigned([&client1] {
ASSERT_NO_THROW(client1.doSolicit(true));
});
ASSERT_TRUE(hasLeaseForAddress(client1, IOAddress("2001:db8:2::20"),
client2.addExtraOption(option1234);
// Client 2 should be offerred an address from the first subnet.
- testAssigned([this, &client2] {
+ testAssigned([&client2] {
ASSERT_NO_THROW(client2.doSolicit(true));
});
ASSERT_TRUE(hasLeaseForAddress(client2, IOAddress("2001:db8:1::20"),
ASSERT_NO_FATAL_FAILURE(configure(NETWORKS_CONFIG[0], *client.getServer()));
// 4-way exchange.
- testAssigned([this, &client] {
+ testAssigned([&client] {
ASSERT_NO_THROW(client.doSARR());
});
// The two addresses should come from different subnets.
ASSERT_TRUE(hasLeaseForPrefixPool(client, IOAddress("5000::"), 96, 96));
// Try to renew.
- testAssigned([this, &client] {
+ testAssigned([&client] {
ASSERT_NO_THROW(client.doRenew());
});
ASSERT_TRUE(hasLeaseForAddress(client, IOAddress("2001:db8:1::20")));
ASSERT_NO_FATAL_FAILURE(configure(NETWORKS_CONFIG[4], *client.getServer()));
// 4-way exchange.
- testAssigned([this, &client] {
+ testAssigned([&client] {
ASSERT_NO_THROW(client.doSARR());
});
ASSERT_EQ(4, client.getLeaseNum());
ASSERT_NE("1234::", leases_2222[0].addr_.toText());
// Try to renew and check this again.
- testAssigned([this, &client] {
+ testAssigned([&client] {
ASSERT_NO_THROW(client.doRenew());
});
ASSERT_EQ(4, client.getLeaseNum());
ASSERT_NO_FATAL_FAILURE(configure(NETWORKS_CONFIG[13], *client.getServer()));
// 4-way exchange.
- testAssigned([this, &client] {
+ testAssigned([&client] {
ASSERT_NO_THROW(client.doSARR());
});
ASSERT_EQ(2, client.getLeaseNum());
// Client #1 should be assigned an address from shared network.
ASSERT_NO_THROW(client1.requestAddress(0xabca0));
- testAssigned([this, &client1] {
+ testAssigned([&client1] {
ASSERT_NO_THROW(client1.doSARR());
});
ASSERT_TRUE(hasLeaseForAddress(client1, IOAddress("2001:db8:1::20")));
client2.useRelay(true, IOAddress("3001::2"));
client2.useInterfaceId("vlan1000");
ASSERT_NO_THROW(client2.requestAddress(0xabca0));
- testAssigned([this, &client2] {
+ testAssigned([&client2] {
ASSERT_NO_THROW(client2.doSARR());
});
ASSERT_TRUE(hasLeaseForAddress(client2, IOAddress("2001:db8:2::20")));
// Client #1 should be assigned an address from shared network.
ASSERT_NO_THROW(client1.requestAddress(0xabca0));
- testAssigned([this, &client1] {
+ testAssigned([&client1] {
ASSERT_NO_THROW(client1.doSARR());
});
ASSERT_TRUE(hasLeaseForAddress(client1, IOAddress("2001:db8:1::20")));
client2.useRelay(true, IOAddress("3001::2"));
client2.useInterfaceId("vlan1000");
ASSERT_NO_THROW(client2.requestAddress(0xabca0));
- testAssigned([this, &client2] {
+ testAssigned([&client2] {
ASSERT_NO_THROW(client2.doSARR());
});
ASSERT_TRUE(hasLeaseForAddress(client2, IOAddress("2001:db8:2::20")));
// Client #1 requests an address in the restricted pool but can't be assigned
// this address because the client doesn't belong to a certain class.
ASSERT_NO_THROW(client1.requestAddress(0xabca, IOAddress("2001:db8:1::20")));
- testAssigned([this, &client1] {
+ testAssigned([&client1] {
ASSERT_NO_THROW(client1.doSARR());
});
ASSERT_TRUE(hasLeaseForAddress(client1, IOAddress("2001:db8:1::50")));
// Release the lease that the client has got, because we'll need this address
// further in the test.
- testAssigned([this, &client1] {
+ testAssigned([&client1] {
ASSERT_NO_THROW(client1.doRelease());
});
client1.addExtraOption(option1234);
// This time, the allocation of the address provided as hint should be successful.
- testAssigned([this, &client1] {
+ testAssigned([&client1] {
ASSERT_NO_THROW(client1.doSARR());
});
ASSERT_TRUE(hasLeaseForAddress(client1, IOAddress("2001:db8:1::20")));
Dhcp6Client client2(client1.getServer());
client2.setInterface("eth1");
ASSERT_NO_THROW(client2.requestAddress(0xabca0));
- testAssigned([this, &client2] {
+ testAssigned([&client2] {
ASSERT_NO_THROW(client2.doSARR());
});
ASSERT_TRUE(hasLeaseForAddress(client2, IOAddress("2001:db8:1::50")));
// pool to which client2 now belongs.
ASSERT_NO_FATAL_FAILURE(configure(NETWORKS_CONFIG[20], *client1.getServer()));
- testAssigned([this, &client2] {
+ testAssigned([&client2] {
ASSERT_NO_THROW(client2.doRenew());
});
EXPECT_EQ(0, client2.getLeasesWithNonZeroLifetime().size());
// get renewed.
OptionPtr option1234_bis(new OptionUint16(Option::V6, 1234, 0x0002));
client2.addExtraOption(option1234_bis);
- testAssigned([this, &client2] {
+ testAssigned([&client2] {
ASSERT_NO_THROW(client2.doRenew());
});
EXPECT_EQ(1, client2.getLeaseNum());
// Client #1 requests an address in the restricted pool but can't be assigned
// this address because the client doesn't belong to a certain class.
ASSERT_NO_THROW(client1.requestAddress(0xabca, IOAddress("2001:db8:1::20")));
- testAssigned([this, &client1] {
+ testAssigned([&client1] {
ASSERT_NO_THROW(client1.doSARR());
});
ASSERT_TRUE(hasLeaseForAddress(client1, IOAddress("2001:db8:1::50")));
// Release the lease that the client has got, because we'll need this address
// further in the test.
- testAssigned([this, &client1] {
+ testAssigned([&client1] {
ASSERT_NO_THROW(client1.doRelease());
});
client1.addExtraOption(option1234);
// This time, the allocation of the address provided as hint should be successful.
- testAssigned([this, &client1] {
+ testAssigned([&client1] {
ASSERT_NO_THROW(client1.doSARR());
});
ASSERT_TRUE(hasLeaseForAddress(client1, IOAddress("2001:db8:1::20")));
Dhcp6Client client2(client1.getServer());
client2.setInterface("eth1");
ASSERT_NO_THROW(client2.requestAddress(0xabca0));
- testAssigned([this, &client2] {
+ testAssigned([&client2] {
ASSERT_NO_THROW(client2.doSARR());
});
ASSERT_TRUE(hasLeaseForAddress(client2, IOAddress("2001:db8:1::50")));
// pool to which client2 now belongs.
ASSERT_NO_FATAL_FAILURE(configure(NETWORKS_CONFIG[22], *client1.getServer()));
- testAssigned([this, &client2] {
+ testAssigned([&client2] {
ASSERT_NO_THROW(client2.doRenew());
});
EXPECT_EQ(0, client2.getLeasesWithNonZeroLifetime().size());
// get renewed.
OptionPtr option1234_bis(new OptionUint16(Option::V6, 1234, 0x0002));
client2.addExtraOption(option1234_bis);
- testAssigned([this, &client2] {
+ testAssigned([&client2] {
ASSERT_NO_THROW(client2.doRenew());
});
EXPECT_EQ(1, client2.getLeaseNum());
AllocEngine::ClientContext6::ClientContext6()
: query_(), fake_allocation_(false), subnet_(), host_subnet_(), duid_(),
hwaddr_(), host_identifiers_(), hosts_(), fwd_dns_update_(false),
- rev_dns_update_(false), hostname_(), callout_handle_(),
- ias_() {
+ rev_dns_update_(false), committed_(false), hostname_(),
+ callout_handle_(), ias_() {
}
AllocEngine::ClientContext6::ClientContext6(const Subnet6Ptr& subnet,
const CalloutHandlePtr& callout_handle)
: query_(query), fake_allocation_(fake_allocation), subnet_(subnet),
duid_(duid), hwaddr_(), host_identifiers_(), hosts_(),
- fwd_dns_update_(fwd_dns), rev_dns_update_(rev_dns),
+ fwd_dns_update_(fwd_dns), rev_dns_update_(rev_dns), committed_(false),
hostname_(hostname), callout_handle_(callout_handle),
- allocated_resources_(), ias_() {
+ allocated_resources_(), new_leases_(), ias_() {
// Initialize host identifiers.
if (duid) {
// IAs.
BOOST_FOREACH(Lease6Ptr lease, leases) {
ctx.addAllocatedResource(lease->addr_, lease->prefixlen_);
+ ctx.new_leases_.push_back(lease);
}
return (leases);
}
// IAs.
BOOST_FOREACH(Lease6Ptr lease, leases) {
ctx.addAllocatedResource(lease->addr_, lease->prefixlen_);
+ ctx.new_leases_.push_back(lease);
}
}
/// (if true).
bool rev_dns_update_;
+ /// @brief A boolean value which indicates that server must
+ /// invoke the leases committed callout (if true).
+ bool committed_;
+
/// @brief Hostname.
///
/// The server retrieves the hostname from the Client FQDN option,
/// @brief Holds addresses and prefixes allocated for all IAs.
ResourceContainer allocated_resources_;
+ /// @brief A collection of newly allocated leases.
+ Lease6Collection new_leases_;
+
//@}
/// @brief Parameters pertaining to individual IAs.
// a context.
TEST(ClientContext6Test, addAllocatedResource) {
AllocEngine::ClientContext6 ctx;
+ ASSERT_FALSE(ctx.committed_);
ctx.addAllocatedResource(IOAddress("2001:db8:1::1"));
ctx.addAllocatedResource(IOAddress("3000:1::"), 64);