Commit 4f43c309 authored by Marcin Siodelski's avatar Marcin Siodelski

[master] Merge branch 'trac3269'

parents acdbb45c 080ee7ee
...@@ -1442,7 +1442,7 @@ Dhcp6/dhcp-ddns/qualifying-suffix "example.com" string ...@@ -1442,7 +1442,7 @@ Dhcp6/dhcp-ddns/qualifying-suffix "example.com" string
<itemizedlist> <itemizedlist>
<listitem> <listitem>
<simpara><ulink url="http://tools.ietf.org/html/rfc3315">RFC 3315</ulink>: Supported messages are SOLICIT, <simpara><ulink url="http://tools.ietf.org/html/rfc3315">RFC 3315</ulink>: Supported messages are SOLICIT,
ADVERTISE, REQUEST, RELEASE, RENEW, REBIND and REPLY.</simpara> ADVERTISE, REQUEST, RELEASE, RENEW, REBIND, CONFIRM and REPLY.</simpara>
</listitem> </listitem>
<listitem> <listitem>
<simpara><ulink url="http://tools.ietf.org/html/rfc3633">RFC 3633</ulink>: Supported options are IA_PD and <simpara><ulink url="http://tools.ietf.org/html/rfc3633">RFC 3633</ulink>: Supported options are IA_PD and
...@@ -1510,9 +1510,9 @@ Dhcp6/renew-timer 1000 integer (default) ...@@ -1510,9 +1510,9 @@ Dhcp6/renew-timer 1000 integer (default)
</listitem> </listitem>
<listitem> <listitem>
<simpara> <simpara>
Confirmation (CONFIRM), duplication report (DECLINE), Duplication report (DECLINE), stateless configuration
stateless configuration (INFORMATION-REQUEST) and client (INFORMATION-REQUEST) and client reconfiguration (RECONFIGURE) are
reconfiguration (RECONFIGURE) are not yet supported. not yet supported.
</simpara> </simpara>
</listitem> </listitem>
<listitem> <listitem>
......
...@@ -2314,9 +2314,81 @@ Dhcpv6Srv::processRebind(const Pkt6Ptr& rebind) { ...@@ -2314,9 +2314,81 @@ Dhcpv6Srv::processRebind(const Pkt6Ptr& rebind) {
Pkt6Ptr Pkt6Ptr
Dhcpv6Srv::processConfirm(const Pkt6Ptr& confirm) { Dhcpv6Srv::processConfirm(const Pkt6Ptr& confirm) {
/// @todo: Implement this // Get IA_NAs from the Confirm. If there are none, the message is
// invalid and must be discarded. There is nothing more to do.
OptionCollection ias = confirm->getOptions(D6O_IA_NA);
if (ias.empty()) {
return (Pkt6Ptr());
}
// The server sends Reply message in response to Confirm.
Pkt6Ptr reply(new Pkt6(DHCPV6_REPLY, confirm->getTransid())); Pkt6Ptr reply(new Pkt6(DHCPV6_REPLY, confirm->getTransid()));
return reply; // Make sure that the necessary options are included.
copyDefaultOptions(confirm, reply);
appendDefaultOptions(confirm, reply);
// Indicates if at least one address has been verified. If no addresses
// are verified it means that the client has sent no IA_NA options
// or no IAAddr options and that client's message has to be discarded.
bool verified = false;
// Check if subnet can be selected for the message. If no subnet
// has been selected, the client is not on link.
SubnetPtr subnet = selectSubnet(confirm);
// Regardless if the subnet has been selected or not, we will iterate
// over the IA_NA options to check if they hold any addresses. If there
// are no, the Confirm is discarded.
// Check addresses in IA_NA options and make sure they are appropriate.
for (OptionCollection::const_iterator ia = ias.begin();
ia != ias.end(); ++ia) {
const OptionCollection& opts = ia->second->getOptions();
for (OptionCollection::const_iterator opt = opts.begin();
opt != opts.end(); ++opt) {
// Ignore options other than IAAddr.
if (opt->second->getType() == D6O_IAADDR) {
// Check that the address is in range in the subnet selected.
Option6IAAddrPtr iaaddr = boost::dynamic_pointer_cast<
Option6IAAddr>(opt->second);
// If there is subnet selected and the address has been included
// in IA_NA, mark it verified and verify that it belongs to the
// subnet.
if (iaaddr) {
// If at least one address is not in range, then return
// the NotOnLink status code.
if (subnet && !subnet->inRange(iaaddr->getAddress())) {
std::ostringstream status_msg;
status_msg << "Address " << iaaddr->getAddress()
<< " is not on link.";
reply->addOption(createStatusCode(STATUS_NotOnLink,
status_msg.str()));
return (reply);
}
verified = true;
} else {
isc_throw(Unexpected, "failed to cast the IA Address option"
" to the Option6IAAddrPtr. This is programming"
" error and should be reported");
}
}
}
}
// It seems that the client hasn't included any addresses in which case
// the Confirm must be discarded.
if (!verified) {
return (Pkt6Ptr());
}
// If there is a subnet, there were addresses in IA_NA options and the
// addresses where consistent with the subnet then the client is on link.
if (subnet) {
// All addresses in range, so return success.
reply->addOption(createStatusCode(STATUS_Success,
"All addresses are on-link"));
} else {
reply->addOption(createStatusCode(STATUS_NotOnLink,
"No subnet selected"));
}
return (reply);
} }
Pkt6Ptr Pkt6Ptr
......
...@@ -221,9 +221,29 @@ protected: ...@@ -221,9 +221,29 @@ protected:
/// @param rebind message received from client /// @param rebind message received from client
Pkt6Ptr processRebind(const Pkt6Ptr& rebind); Pkt6Ptr processRebind(const Pkt6Ptr& rebind);
/// @brief Stub function that will handle incoming CONFIRM messages. /// @brief Processes incoming Confirm message and returns Reply.
/// ///
/// @param confirm message received from client /// This function processes Confirm message from the client according
/// to section 18.2.2. of RFC3315. It discards the Confirm message if
/// the message sent by the client contains no addresses, i.e. it has
/// no IA_NA options or all IA_NA options contain no IAAddr options.
///
/// If the Confirm message contains addresses this function will perform
/// the following checks:
/// - check if there is appropriate subnet configured for the client
/// (e.g. subnet from which addresses are assigned for requests
/// received on the particular interface).
/// - check if all addresses sent in the Confirm message belong to the
/// selected subnet.
///
/// If any of the checks above fails, the Reply message with the status
/// code NotOnLink is returned. Otherwise, the Reply message with the
/// status code Success is returned.
///
/// @param confirm Confirm message sent by a client.
///
/// @return Reply message from the server al NULL pointer if Confirm
/// message should be discarded by the server.
Pkt6Ptr processConfirm(const Pkt6Ptr& confirm); Pkt6Ptr processConfirm(const Pkt6Ptr& confirm);
/// @brief Stub function that will handle incoming RELEASE messages. /// @brief Stub function that will handle incoming RELEASE messages.
......
...@@ -88,6 +88,8 @@ dhcp6_unittests_SOURCES += rebind_unittest.cc ...@@ -88,6 +88,8 @@ dhcp6_unittests_SOURCES += rebind_unittest.cc
dhcp6_unittests_SOURCES += sarr_unittest.cc dhcp6_unittests_SOURCES += sarr_unittest.cc
dhcp6_unittests_SOURCES += ../json_config_parser.cc ../json_config_parser.h dhcp6_unittests_SOURCES += ../json_config_parser.cc ../json_config_parser.h
dhcp6_unittests_SOURCES += config_parser_unittest.cc dhcp6_unittests_SOURCES += config_parser_unittest.cc
dhcp6_unittests_SOURCES += confirm_unittest.cc
dhcp6_unittests_SOURCES += dhcp6_message_test.cc dhcp6_message_test.h
if CONFIG_BACKEND_BUNDY if CONFIG_BACKEND_BUNDY
# For Bundy backend, we only need to run the usual tests. There are no # For Bundy backend, we only need to run the usual tests. There are no
......
// Copyright (C) 2014 Internet Systems Consortium, Inc. ("ISC")
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
// AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE.
#include <config.h>
#include <asiolink/io_address.h>
#include <cc/data.h>
#include <dhcp/tests/iface_mgr_test_config.h>
#include <dhcp6/json_config_parser.h>
#include <dhcp6/tests/dhcp6_message_test.h>
using namespace isc;
using namespace isc::asiolink;
using namespace isc::data;
using namespace isc::dhcp;
using namespace isc::dhcp::test;
using namespace isc::test;
namespace {
/// @brief Set of JSON configurations used throughout the Confirm tests.
///
/// - Configuration 0:
/// - only addresses (no prefixes)
/// - 2 subnets with 2001:db8:1::/64 and 2001:db8:2::/64
/// - 1 subnet for eth0 and 1 subnet for eth1
///
/// - Configuration 1:
/// - similar to Configuration 0
/// - pools configured: 3000:1::/64 and 3000:2::/64
/// - this specific configuration is used by tests using relays
///
const char* CONFIRM_CONFIGS[] = {
// Configuration 0
"{ \"interfaces\": [ \"all\" ],"
"\"preferred-lifetime\": 3000,"
"\"rebind-timer\": 2000, "
"\"renew-timer\": 1000, "
"\"subnet6\": [ { "
" \"pool\": [ \"2001:db8:1::/64\" ],"
" \"subnet\": \"2001:db8:1::/48\", "
" \"interface-id\": \"\","
" \"interface\": \"eth0\""
" },"
" {"
" \"pool\": [ \"2001:db8:2::/64\" ],"
" \"subnet\": \"2001:db8:2::/48\", "
" \"interface-id\": \"\","
" \"interface\": \"eth1\""
" } ],"
"\"valid-lifetime\": 4000 }",
// Configuration 1
"{ \"interfaces\": [ \"all\" ],"
"\"preferred-lifetime\": 3000,"
"\"rebind-timer\": 2000, "
"\"renew-timer\": 1000, "
"\"subnet6\": [ { "
" \"pool\": [ \"3000:1::/64\" ],"
" \"subnet\": \"3000:1::/48\", "
" \"interface-id\": \"\","
" \"interface\": \"eth0\""
" },"
" {"
" \"pool\": [ \"3000:2::/64\" ],"
" \"subnet\": \"3000:2::/48\", "
" \"interface-id\": \"\","
" \"interface\": \"eth1\""
" } ],"
"\"valid-lifetime\": 4000 }"
};
/// @brief Test fixture class for testing Confirm..
class ConfirmTest : public isc::dhcp::test::Dhcpv6MessageTest {
public:
/// @brief Constructor.
///
/// Sets up fake interfaces.
ConfirmTest()
: Dhcpv6MessageTest() {
}
};
// Test that directly connected client's Confirm message is processed and Reply
// message is sent back. In this test case, the client sends Confirm for two
// addresses that belong to the same IAID and are sent within the same IA_NA
// option (RFC3315, section 18.2.2).
TEST_F(ConfirmTest, directClientSameIAID) {
Dhcp6Client client;
// Configure client to request IA_NA.
client.useNA();
// Make 4-way exchange to get the lease.
ASSERT_NO_FATAL_FAILURE(requestLease(CONFIRM_CONFIGS[0], 2, client));
// Keep the client's lease for future reference.
Lease6 lease_client1 = client.getLease(0);
// Clone the lease and modify its address so as it is still in the range
// of the subnet to which the first lease belongs. When the client sends
// the Confirm it should include both addresses and the server should
// send Success because both of these addresses are on-link, regardless
// what the server has in the lease database.
Lease6 lease_client2 = lease_client1;
lease_client2.addr_ = bumpAddress(lease_client2.addr_);
client.createLease(lease_client2);
ASSERT_EQ(2, client.getLeaseNum());
// Send Confirm message to the server.
ASSERT_NO_THROW(client.doConfirm());
// Client should have received a status code option and this option should
// indicate the success.
ASSERT_TRUE(client.receivedStatusCode());
ASSERT_EQ(STATUS_Success, client.getStatusCode());
ASSERT_EQ(2, client.getLeaseNum());
lease_client2 = client.getLease(1);
lease_client2.addr_ = bumpSubnet(lease_client2.addr_);
client.createLease(lease_client2);
// Send confirm to the server. This time, one of the leases contains the
// address which doesn't belong to the configured subnet and the server
// should respond with STATUS_NotOnLink.
ASSERT_NO_THROW(client.doConfirm());
ASSERT_TRUE(client.receivedStatusCode());
ASSERT_EQ(STATUS_NotOnLink, client.getStatusCode());
// Make sure that the server id has been included.
EXPECT_TRUE(client.getContext().response_->getOption(D6O_SERVERID));
}
// Test that directly connected client's Confirm message is processed and Reply
// message is sent back. In this test case, the client sends Confirm for two
// addresses that belong to different IAIDs and are sent within the different
// IA_NA options (RFC3315, section 18.2.2).
TEST_F(ConfirmTest, directClientDifferentIAID) {
Dhcp6Client client;
// Configure client to request IA_NA.
client.useNA();
// Make 4-way exchange to get the lease.
ASSERT_NO_FATAL_FAILURE(requestLease(CONFIRM_CONFIGS[0], 2, client));
// Keep the client's lease for future reference.
Lease6 lease_client1 = client.getLease(0);
// Clone the lease and modify its address so as it is still in the range
// of the subnet to which the first lease belongs. When the client sends
// the Confirm it should include both addresses and the server should
// send Success because both of these addresses are on-link, regardless
// what the server has in the lease database.
Lease6 lease_client2 = lease_client1;
++lease_client2.iaid_;
lease_client2.addr_ = bumpAddress(lease_client2.addr_);
client.createLease(lease_client2);
ASSERT_EQ(2, client.getLeaseNum());
// Send Confirm message to the server.
ASSERT_NO_THROW(client.doConfirm());
// Client should have received a status code option and this option should
// indicate the success.
ASSERT_TRUE(client.receivedStatusCode());
ASSERT_EQ(STATUS_Success, client.getStatusCode());
// Make sure that the server id and client id have been included.
EXPECT_TRUE(client.getContext().response_->getOption(D6O_SERVERID));
EXPECT_TRUE(client.getContext().response_->getOption(D6O_CLIENTID));
ASSERT_EQ(2, client.getLeaseNum());
lease_client2 = client.getLease(1);
lease_client2.addr_ = bumpSubnet(lease_client2.addr_);
client.createLease(lease_client2);
// Send confirm to the server. This time, one of the leases contains the
// address which doesn't belong to the configured subnet and the server
// should respond with STATUS_NotOnLink.
ASSERT_NO_THROW(client.doConfirm());
ASSERT_TRUE(client.receivedStatusCode());
ASSERT_EQ(STATUS_NotOnLink, client.getStatusCode());
// Make sure that the server id have been included.
EXPECT_TRUE(client.getContext().response_->getOption(D6O_SERVERID));
EXPECT_TRUE(client.getContext().response_->getOption(D6O_CLIENTID));
}
// Test that relayed client's Confirm message is processed and Reply message
// is sent back (RFC3315, section 18.2.2).
TEST_F(ConfirmTest, relayedClient) {
Dhcp6Client client;
// Client to send relayed message.
client.useRelay();
// Configure client to request IA_NA.
client.useNA();
// Make 4-way exchange to get the lease.
ASSERT_NO_FATAL_FAILURE(requestLease(CONFIRM_CONFIGS[1], 2, client));
// Keep the client's lease for future reference.
Lease6 lease_client1 = client.getLease(0);
// Clone the lease and modify its address so as it is still in the range
// of the subnet to which the first lease belongs. When the client sends
// the Confirm it should include both addresses and the server should
// send Success because both of these addresses are on-link, regardless
// what the server has in the lease database.
Lease6 lease_client2 = lease_client1;
lease_client2.addr_ = bumpAddress(lease_client2.addr_);
++lease_client2.iaid_;
client.createLease(lease_client2);
// Send Confirm message to the server.
ASSERT_NO_THROW(client.doConfirm());
// Client should have received a status code option and this option should
// indicate the success.
ASSERT_TRUE(client.receivedStatusCode());
ASSERT_EQ(STATUS_Success, client.getStatusCode());
lease_client2 = client.getLease(1);
lease_client2.addr_ = bumpSubnet(lease_client2.addr_);
client.createLease(lease_client2);
// Send confirm to the server. This time, one of the leases contains the
// address which doesn't belong to the configured subnet and the server
// should respond with STATUS_NotOnLink.
ASSERT_NO_THROW(client.doConfirm());
ASSERT_TRUE(client.receivedStatusCode());
ASSERT_EQ(STATUS_NotOnLink, client.getStatusCode());
// Make sure that the server id and client id have been included.
EXPECT_TRUE(client.getContext().response_->getOption(D6O_SERVERID));
EXPECT_TRUE(client.getContext().response_->getOption(D6O_CLIENTID));
}
// Test that the Confirm message without any addresses is discarded
// (RFC3315, section 18.2.2).
TEST_F(ConfirmTest, relayedClientNoAddress) {
Dhcp6Client client;
// Configure the server.
configure(CONFIRM_CONFIGS[1], *client.getServer());
// Make sure we ended-up having expected number of subnets configured.
const Subnet6Collection* subnets = CfgMgr::instance().getSubnets6();
ASSERT_EQ(2, subnets->size());
// Client to send relayed message.
client.useRelay();
// Send Confirm message to the server. This message will contain no
// addresses because client has no leases.
ASSERT_NO_THROW(client.doConfirm());
EXPECT_FALSE(client.getContext().response_);
}
// This test checks that the server processes Confirm message correctly if
// the subnet can't be selected for the client (RFC3315, section 18.2.2).
TEST_F(ConfirmTest, relayedClientNoSubnet) {
Dhcp6Client client;
// Client to send relayed message.
client.useRelay();
// Configure client to request IA_NA.
client.useNA();
// Make 4-way exchange to get the lease.
ASSERT_NO_FATAL_FAILURE(requestLease(CONFIRM_CONFIGS[1], 2, client));
// Now that the client has a lease, let's remove any subnets to check
// how the server would respond to the Confirm.
ASSERT_NO_THROW(CfgMgr::instance().deleteSubnets6());
// Send Confirm message to the server.
ASSERT_NO_THROW(client.doConfirm());
// Client should have received a status code option and this option should
// indicate that the client is NotOnLink becuase subnet could not be
// selected.
ASSERT_TRUE(client.receivedStatusCode());
ASSERT_EQ(STATUS_NotOnLink, client.getStatusCode());
// Let's test another case that the client sends no addresses in the Confirm
// message. The subnet can't be selected for that client as in the previous
// case but this time the server must discard the client's message because
// it contains no addresses (is invalid).
// Set lifetimes to 0 so as the Confirm will ignore the specific address
// and send an empty IA_NA.
client.config_.leases_[0].lease_.preferred_lft_ = 0;
client.config_.leases_[0].lease_.valid_lft_ = 0;
ASSERT_NO_THROW(client.doConfirm());
EXPECT_FALSE(client.getContext().response_);
// Do similar test but this time remove the lease so as no IA_NA option
// is sent.
client.config_.clear();
ASSERT_NO_THROW(client.doConfirm());
EXPECT_FALSE(client.getContext().response_);
}
// This test checks that the relayed Confirm messsage is processed by the server
// when sent to unicast address RFC3315, section 18.2.8).
TEST_F(ConfirmTest, relayedUnicast) {
Dhcp6Client client;
// Client to send relayed message.
client.useRelay();
// Configure client to request IA_NA.
client.useNA();
// Make 4-way exchange to get the lease.
ASSERT_NO_FATAL_FAILURE(requestLease(CONFIRM_CONFIGS[1], 2, client));
// Make sure we have got the lease.
ASSERT_GT(client.getLeaseNum(), 0);
client.setDestAddress(IOAddress("2001:db8:1::1"));
// Send Confirm message to the server.
ASSERT_NO_THROW(client.doConfirm());
// Client should have received a response.
ASSERT_TRUE(client.getContext().response_);
// Client should have received a status code option and this option should
// indicate the success.
ASSERT_TRUE(client.receivedStatusCode());
ASSERT_EQ(STATUS_Success, client.getStatusCode());
// Make sure that the server id and client id have been included.
EXPECT_TRUE(client.getContext().response_->getOption(D6O_SERVERID));
EXPECT_TRUE(client.getContext().response_->getOption(D6O_CLIENTID));
}
// This test checks that the Confirm message is discarded by the server if it
// has been sent to unicast address (RFC3315, section 15).
TEST_F(ConfirmTest, unicast) {
Dhcp6Client client;
// Configure client to request IA_NA.
client.useNA();
// Make 4-way exchange to get the lease.
ASSERT_NO_FATAL_FAILURE(requestLease(CONFIRM_CONFIGS[0], 2, client));
// Make sure the client has got the lease.
ASSERT_GT(client.getLeaseNum(), 0);
// Send Confirm message to the server to the unicast address.
client.setDestAddress(IOAddress("2001:db8:1::1"));
ASSERT_NO_THROW(client.doConfirm());
// Mak sure that the server discarded client's Confirm message.
EXPECT_FALSE(client.getContext().response_);
}
} // end of anonymous namespace
...@@ -58,8 +58,11 @@ Dhcp6Client::Dhcp6Client(boost::shared_ptr<NakedDhcpv6Srv>& srv) : ...@@ -58,8 +58,11 @@ Dhcp6Client::Dhcp6Client(boost::shared_ptr<NakedDhcpv6Srv>& srv) :
void void
Dhcp6Client::applyRcvdConfiguration(const Pkt6Ptr& reply) { Dhcp6Client::applyRcvdConfiguration(const Pkt6Ptr& reply) {
typedef OptionCollection Opts; typedef OptionCollection Opts;
// Get all options in the reply message and pick IA_NA and IA_PD. // Get all options in the reply message and pick IA_NA, IA_PD and
// Status code.
Opts opts = reply->options_; Opts opts = reply->options_;
// Set the global status code to default: success and not received.
config_.resetGlobalStatusCode();
for (Opts::const_iterator opt = opts.begin(); opt != opts.end(); ++opt) { for (Opts::const_iterator opt = opts.begin(); opt != opts.end(); ++opt) {
Option6IAPtr ia = boost::dynamic_pointer_cast<Option6IA>(opt->second); Option6IAPtr ia = boost::dynamic_pointer_cast<Option6IA>(opt->second);
if (!ia) { if (!ia) {
...@@ -137,6 +140,16 @@ Dhcp6Client::applyRcvdConfiguration(const Pkt6Ptr& reply) { ...@@ -137,6 +140,16 @@ Dhcp6Client::applyRcvdConfiguration(const Pkt6Ptr& reply) {
applyLease(lease_info); applyLease(lease_info);
} }
} }
// Get the global status code.
OptionCustomPtr status_code = boost::dynamic_pointer_cast<
OptionCustom>(reply->getOption(D6O_STATUS_CODE));
// If status code has been sent, we override the default status code:
// Success and record that we have received the status code.
if (status_code) {
config_.received_status_code_ = true;
config_.status_code_ = status_code->readInteger<uint16_t>(0);
}
} }
void void
...@@ -150,7 +163,8 @@ Dhcp6Client::applyLease(const LeaseInfo& lease_info) { ...@@ -150,7 +163,8 @@ Dhcp6Client::applyLease(const LeaseInfo& lease_info) {
// lease assignment so we keep what we have. // lease assignment so we keep what we have.
if ((existing_lease.iaid_ == lease_info.lease_.iaid_) if ((existing_lease.iaid_ == lease_info.lease_.iaid_)
&& (existing_lease.type_ == lease_info.lease_.type_) && (existing_lease.type_ == lease_info.lease_.type_)
&& (lease_info.lease_.addr_ != asiolink::IOAddress("::"))) { && (lease_info.lease_.addr_ != asiolink::IOAddress("::"))
&& (existing_lease.addr_ == lease_info.lease_.addr_)) {
config_.leases_[i] = lease_info; config_.leases_[i] = lease_info;
return; return;
...@@ -164,7 +178,6 @@ Dhcp6Client::applyLease(const LeaseInfo& lease_info) { ...@@ -164,7 +178,6 @@ Dhcp6Client::applyLease(const LeaseInfo& lease_info) {
config_.leases_.push_back(lease_info); config_.leases_.push_back(lease_info);
} }
void void
Dhcp6Client::copyIAs(const Pkt6Ptr& source, const Pkt6Ptr& dest) { Dhcp6Client::copyIAs(const Pkt6Ptr& source, const Pkt6Ptr& dest) {
typedef OptionCollection Opts; typedef OptionCollection Opts;
...@@ -184,31 +197,42 @@ void ...@@ -184,31 +197,42 @@ void
Dhcp6Client::copyIAsFromLeases(const Pkt6Ptr& dest) const { Dhcp6Client::copyIAsFromLeases(const Pkt6Ptr& dest) const {
// Go over leases and create IA_NA and IA_PD options from them. // Go over leases and create IA_NA and IA_PD options from them.
// Create one IA per lease. // Create one IA per lease.
for (std::vector<LeaseInfo>::const_iterator info = config_.leases_.begin(); std::set<uint32_t> iaids = getIAIDs();
info != config_.leases_.end(); ++info) { for (std::set<uint32_t>::const_iterator iaid = iaids.begin();
Lease6 lease = info->lease_; iaid != iaids.end(); ++iaid) {
if (lease.type_ == Lease::TYPE_NA) { std::vector<Lease6> leases = getLeasesByIAID(*iaid);
Option6IAPtr opt(new Option6IA(D6O_IA_NA, lease.iaid_)); Option6IAPtr opt(new Option6IA(leases[0].type_ == Lease::TYPE_NA ?
opt->setT1(lease.t1_); D6O_IA_NA : D6O_IA_PD, *iaid));
opt->setT2(lease.t1_); opt->setT1(leases[0].t1_);
opt->addOption(Option6IAAddrPtr(new opt->setT2(leases[0].t2_);
Option6IAAddr(D6O_IAADDR, for (std::vector<Lease6>::const_iterator lease = leases.begin();
lease.addr_, lease != leases.end(); ++lease) {
lease.preferred_lft_, if ((lease->preferred_lft_ != 0) && (lease->valid_lft_ != 0)) {
lease.valid_lft_))); if (lease->type_ == Lease::TYPE_NA) {
dest->addOption(opt); opt->addOption(Option6IAAddrPtr(new Option6IAAddr(
} else if (lease.type_ == Lease::TYPE_PD) { D6O_IAADDR,
Option6IAPtr opt(new Option6IA(D6O_IA_PD, lease.iaid_)); lease->addr_,
opt->setT1(lease.t1_); lease->preferred_lft_,
opt->setT2(lease.t1_); lease->valid_lft_)));
opt->addOption(Option6IAPrefixPtr(new Option6IAPrefix(D6O_IAPREFIX, } else if (lease->type_ == Lease::TYPE_PD) {
lease.addr_, opt->addOption(Option6IAAddrPtr(new Option6IAPrefix(
lease.prefixlen_, D6O_IAPREFIX,
lease.preferred_lft_, lease->addr_,
lease.valid_lft_))); lease->prefixlen_,
dest->addOption(opt); lease->preferred_lft_,
lease->valid_lft_)));
}
} }
} }
dest->addOption(opt);
}
}
void
Dhcp6Client::createLease(const Lease6& lease) {
LeaseInfo info;
info.lease_ = lease;
applyLease(info);
} }
Pkt6Ptr