break;
case NO_IA:
// Tell the client to not include IA_NA at all
- client.useNA(false);
+ client.config_.clear();
+ client.clearRequestedIAs();
}
// Use the second duid
link_local_("fe80::3a60:77ff:fed5:cdef"),
iface_name_("eth0"),
srv_(boost::shared_ptr<NakedDhcpv6Srv>(new NakedDhcpv6Srv(0))),
- use_na_(false),
- use_pd_(false),
use_relay_(false),
use_oro_(false),
use_client_id_(true),
use_rapid_commit_(false),
- address_hint_(),
- prefix_hint_(),
+ client_ias_(),
fqdn_(),
- na_iaid_(1234),
- pd_iaid_(5678),
include_address_(true) {
}
link_local_("fe80::3a60:77ff:fed5:cdef"),
iface_name_("eth0"),
srv_(srv),
- use_na_(false),
- use_pd_(false),
use_relay_(false),
use_oro_(false),
use_client_id_(true),
use_rapid_commit_(false),
- address_hint_(),
- prefix_hint_(),
+ client_ias_(),
fqdn_(),
- na_iaid_(1234),
- pd_iaid_(5678),
include_address_(true) {
}
void
Dhcp6Client::appendRequestedIAs(const Pkt6Ptr& query) const {
- if (use_na_) {
- conditionallyAppendRequestedIA(query, D6O_IA_NA, na_iaid_);
- }
-
- if (use_pd_) {
- conditionallyAppendRequestedIA(query, D6O_IA_PD, pd_iaid_);
- }
-}
-
-void
-Dhcp6Client::conditionallyAppendRequestedIA(const Pkt6Ptr& query,
- const uint8_t ia_type,
- const uint32_t iaid) const {
- // Get existing options of the specified type.
- OptionCollection options = query->getOptions(ia_type);
- std::pair<unsigned int, OptionPtr> option_pair;
-
- // Check if the option we want to add is already present.
- BOOST_FOREACH(option_pair, options) {
- Option6IAPtr ia = boost::dynamic_pointer_cast<Option6IA>(option_pair.second);
- // This shouldn't happen.
- if (!ia) {
- isc_throw(Unexpected, "Dhcp6Client: IA option has an invalid C++ type;"
- " this is a programming issue");
+ BOOST_FOREACH(const ClientIA& ia, client_ias_) {
+ OptionCollection options = query->getOptions(ia.type_ == Lease::TYPE_NA ?
+ D6O_IA_NA : D6O_IA_PD);
+ std::pair<unsigned int, OptionPtr> option_pair;
+ Option6IAPtr existing_ia;
+ BOOST_FOREACH(option_pair, options) {
+ Option6IAPtr ia_opt = boost::dynamic_pointer_cast<Option6IA>(option_pair.second);
+ // This shouldn't happen.
+ if (!ia_opt) {
+ isc_throw(Unexpected, "Dhcp6Client: IA option has an invalid C++ type;"
+ " this is a programming issue");
+ }
+ if (ia_opt->getIAID() == ia.iaid_) {
+ existing_ia = ia_opt;
+ }
}
- // There is an option of the specific type already. If it has our
- // IAID we return here, because we don't want to duplicate the IA.
- // If IAID is different, we check other existing IAs.
- if (ia->getIAID() == iaid) {
- return;
+ if (!existing_ia) {
+ existing_ia.reset(new Option6IA(ia.type_ == Lease::TYPE_NA ?
+ D6O_IA_NA : D6O_IA_PD, ia.iaid_));
+ query->addOption(existing_ia);
}
- }
- // If we're here, it means that there is no instance of our IA yet.
- Option6IAPtr requested_ia(new Option6IA(ia_type, iaid));
- // Add prefix hint if specified.
- if (prefix_hint_ && (ia_type == D6O_IA_PD)) {
- requested_ia->addOption(prefix_hint_);
+ bool option_exists = false;
+ if ((ia.type_ == Lease::TYPE_NA) && !ia.prefix_.isV6Zero()) {
+ Option6IAAddrPtr ia_addr(new Option6IAAddr(D6O_IAADDR, ia.prefix_,
+ 0, 0));
+ BOOST_FOREACH(option_pair, existing_ia->getOptions()) {
+ Option6IAAddrPtr existing_addr = boost::dynamic_pointer_cast<
+ Option6IAAddr>(option_pair.second);
+ if (existing_addr && (existing_addr->getAddress() == ia.prefix_)) {
+ option_exists = true;
+ }
+ }
- } else if (address_hint_ && (ia_type == D6O_IA_NA)) {
- requested_ia->addOption(address_hint_);
- }
+ if (!option_exists) {
+ existing_ia->addOption(ia_addr);
+ }
- query->addOption(requested_ia);
-}
+ } else if ((ia.type_ == Lease::TYPE_PD) && (!ia.prefix_.isV6Zero() ||
+ (ia.prefix_len_ > 0))) {
+ Option6IAPrefixPtr ia_prefix(new Option6IAPrefix(D6O_IAPREFIX, ia.prefix_,
+ ia.prefix_len_,
+ 0, 0));
+ BOOST_FOREACH(option_pair, existing_ia->getOptions()) {
+ Option6IAPrefixPtr existing_prefix = boost::dynamic_pointer_cast<
+ Option6IAPrefix>(option_pair.second);
+ if (existing_prefix && (existing_prefix->getAddress() == ia.prefix_) &&
+ existing_prefix->getLength()) {
+ option_exists = true;
+ }
+ }
+ if (!option_exists) {
+ existing_ia->addOption(ia_prefix);
+ }
+ }
+ }
+}
void
Dhcp6Client::copyIAs(const Pkt6Ptr& source, const Pkt6Ptr& dest) {
// IA_NA, IA_TA and IA_PD options are not allowed in INF-REQUEST,
// but hey! Let's test it.
- if (use_na_) {
- // Insert IA_NA option.
- context_.query_->addOption(Option6IAPtr(new Option6IA(D6O_IA_NA,
- na_iaid_)));
- }
-
- // IA-PD is also not allowed. So it may be useful in testing, too.
- if (use_pd_) {
- // Insert IA_PD option.
- Option6IAPtr ia(new Option6IA(D6O_IA_PD, pd_iaid_));
- if (prefix_hint_) {
- ia->addOption(prefix_hint_);
- }
- context_.query_->addOption(ia);
- }
+ appendRequestedIAs(context_.query_);
sendMsg(context_.query_);
context_.response_ = receiveOneMsg();
Dhcp6Client::generateIAFromLeases(const Pkt6Ptr& query) {
/// @todo: add support for IAPREFIX here.
- if (!use_na_) {
+/* if (!use_na_) {
// If we're told to not use IA_NA at all, there's nothing to be done here
return;
- }
+ } */
for (std::vector<Lease6>::const_iterator lease = config_.leases_.begin();
lease != config_.leases_.end(); ++lease) {
srv_->run();
}
+/*void
+Dhcp6Client::useNA(const bool use, const uint32_t iaid) {
+ use_na_ = use;
+ client_ias_.push_back(ClientIA(Lease::TYPE_NA, iaid,
+ asiolink::IOAddress::IPV6_ZERO_ADDRESS(),
+ 0));
+ na_iaid_ = iaid;
+} */
+
void
-Dhcp6Client::useHint(const uint32_t pref_lft, const uint32_t valid_lft,
- const std::string& address) {
- address_hint_.reset(new Option6IAAddr(D6O_IAADDR,
- asiolink::IOAddress(address),
- pref_lft, valid_lft));
+Dhcp6Client::useNA(const uint32_t iaid, const asiolink::IOAddress& address) {
+ client_ias_.push_back(ClientIA(Lease::TYPE_NA, iaid, address, 128));
}
+/*void
+Dhcp6Client::usePD(const bool use, const uint32_t iaid) {
+ use_pd_ = use;
+ client_ias_.push_back(ClientIA(Lease::TYPE_PD, iaid,
+ asiolink::IOAddress::IPV6_ZERO_ADDRESS(),
+ 0));
+ pd_iaid_ = iaid;
+}*/
+
void
-Dhcp6Client::useHint(const uint32_t pref_lft, const uint32_t valid_lft,
- const uint8_t len, const std::string& prefix) {
- prefix_hint_.reset(new Option6IAPrefix(D6O_IAPREFIX,
- asiolink::IOAddress(prefix),
- len, pref_lft, valid_lft));
+Dhcp6Client::usePD(const uint32_t iaid,const asiolink::IOAddress& prefix,
+ const uint8_t prefix_len) {
+ client_ias_.push_back(ClientIA(Lease::TYPE_PD, iaid, prefix, prefix_len));
}
void
#include <dhcp/duid.h>
#include <dhcp/option.h>
#include <dhcp/option6_client_fqdn.h>
+#include <dhcpsrv/lease.h>
#include <dhcp6/tests/dhcp6_test_utils.h>
#include <boost/noncopyable.hpp>
#include <boost/shared_ptr.hpp>
+#include <list>
#include <set>
#include <vector>
Pkt6Ptr response_;
};
+ /// @brief Structure holding information to be placed in client's IA.
+ struct ClientIA {
+ Lease::Type type_; ///< IA type
+ uint32_t iaid_; ///< IAID
+ asiolink::IOAddress prefix_; ///< prefix or address
+ uint8_t prefix_len_; ///< prefix length
+
+ /// @brief Constructor.
+ ///
+ /// @param type IA type.
+ /// @param iaid IAID.
+ /// @param prefix Address or prefix.
+ /// @param prefix_len Prefix length.
+ ClientIA(const Lease::Type& type, const uint32_t iaid,
+ const asiolink::IOAddress& prefix,
+ const uint8_t prefix_len)
+ : type_(type), iaid_(iaid), prefix_(prefix),
+ prefix_len_(prefix_len) {
+ }
+ };
+
/// @brief Creates a new client.
///
/// This constructor initializes the class members to default values:
link_local_ = link_local;
}
- /// @brief Set an address hint to be sent to a server.
- ///
- /// @param pref_lft Preferred lifetime.
- /// @param valid_lft Valid lifetime.
- /// @param address Address for which the client has a preference.
- void useHint(const uint32_t pref_lft, const uint32_t valid_lft,
- const std::string& address);
-
- /// @brief Sets a prefix hint to be sent to a server.
- ///
- /// @param pref_lft Preferred lifetime.
- /// @param valid_lft Valid lifetime.
- /// @param len Prefix length.
- /// @param prefix Prefix for which the client has a preference.
- void useHint(const uint32_t pref_lft, const uint32_t valid_lft,
- const uint8_t len, const std::string& prefix);
-
/// @brief Place IA_NA options to request address assignment.
///
/// This function configures the client to place IA_NA options in its
/// Solicit messages to request the IPv6 address assignment.
///
/// @param iaid IAID to be used in the IA_NA.
- void useNA(const uint32_t iaid) {
+/* void useNA(const uint32_t iaid) {
useNA(true, iaid);
- }
+ } */
- /// @brief Place IA_NA options to request address assignment.
+/* /// @brief Place IA_NA options to request address assignment.
///
/// This function configures the client to place IA_NA options in its
/// Solicit messages to request the IPv6 address assignment.
/// @param use Parameter which 'true' value indicates that client should
/// request address assignment.
/// @param iaid IAID to be used in the IA_NA.
- void useNA(const bool use = true, const uint32_t iaid = 1234) {
- use_na_ = use;
- na_iaid_ = iaid;
- }
+ void useNA(const bool use = true, const uint32_t iaid = 1234); */
/// @brief Place IA_PD options to request address assignment.
///
/// Solicit messages to request the IPv6 address assignment.
///
/// @param iaid IAID to be used in the IA_PD.
- void usePD(const uint32_t iaid) {
+/* void usePD(const uint32_t iaid) {
usePD(true, iaid);
- }
+ } */
/// @brief Place IA_PD options to request prefix assignment.
///
/// @param use Parameter which 'true' value indicates that client should
/// request prefix assignment.
/// @param iaid IAID to be used in the IA_NA.
- void usePD(const bool use = true, const uint32_t iaid = 5678) {
- use_pd_ = use;
- pd_iaid_ = iaid;
+// void usePD(const bool use = true, const uint32_t iaid = 5678);
+
+ void useNA(const uint32_t iaid = 1234, const asiolink::IOAddress& address =
+ asiolink::IOAddress::IPV6_ZERO_ADDRESS());
+
+ void usePD(const uint32_t iaid = 5678, const asiolink::IOAddress& prefix =
+ asiolink::IOAddress::IPV6_ZERO_ADDRESS(),
+ const uint8_t prefix_len = 0);
+
+ /// @brief Removes requested IAs.
+ void clearRequestedIAs() {
+ client_ias_.clear();
}
/// @brief Simulate sending messages through a relay.
use_client_id_ = send;
}
- /// @brief Controls whether the client should send an addres in IA_NA
- ///
- /// @todo: For now, this flag is only used in Decline
- /// @param send should the address be included?
- void includeAddress(const bool send) {
- include_address_ = send;
- }
-
/// @brief Specifies if the Rapid Commit option should be included in
/// the Solicit message.
///
void useFQDN(const uint8_t flags, const std::string& fqdn_name,
Option6ClientFqdn::DomainNameType fqdn_type);
+ void includeAddress(const bool send) {
+ include_address_ = send;
+ }
+
/// @brief Lease configuration obtained by the client.
Configuration config_;
/// added.
void appendRequestedIAs(const Pkt6Ptr& query) const;
- /// @brief Include IA of the specified type if it doesn't exist yet.
- ///
- /// This methods includes an IA option of the specific type, and
- /// having a given IAID to the query message, if this IA hasn't
- /// been added yet.
- ///
- /// @param query Pointer to the client's message to which IA should be
- /// added.
- /// @param ia_type One of the D6O_IA_NA or D6O_IA_PD
- /// @param iaid IAID of the IA.
- void conditionallyAppendRequestedIA(const Pkt6Ptr& query,
- const uint8_t ia_type,
- const uint32_t iaid) const;
-
/// @brief Copy IA options from one message to another.
///
/// This method copies IA_NA and IA_PD options from one message to another.
/// @brief Pointer to the server that the client is communicating with.
boost::shared_ptr<isc::dhcp::test::NakedDhcpv6Srv> srv_;
- bool use_na_; ///< Enable address assignment.
- bool use_pd_; ///< Enable prefix delegation.
bool use_relay_; ///< Enable relaying messages to the server.
bool use_oro_; ///< Conth
bool use_client_id_;
bool use_rapid_commit_;
- /// @brief Pointer to the option holding an address hint.
- Option6IAAddrPtr address_hint_;
-
- /// @brief Pointer to the option holding a prefix hint.
- Option6IAPrefixPtr prefix_hint_;
+ /// @brief List holding information to be sent in client's IAs.
+ std::list<ClientIA> client_ias_;
/// @brief List of options to be requested
///
/// @brief FQDN requested by the client.
Option6ClientFqdnPtr fqdn_;
- /// @bref IAID used by the client when requesting address assignment.
- uint32_t na_iaid_;
- /// @brief IAID used by the client when requesting prefix delegation.
- uint32_t pd_iaid_;
-
- /// @brief Determines if the client will include address in the messages
- /// it sends.
- ///
- /// @todo this flag is currently supported in Decline only.
bool include_address_;
};
// Configure client to request IA_NA and append IA_NA option
// to the client's message.
- client.useNA();
- ASSERT_NO_THROW(client.useHint(100, 200, 64, "2001:db8:1:1::dead:beef"));
+ client.useNA(1234, IOAddress("2001:db8:1:1::dead:beef"));
// Perform 4-way exchange.
ASSERT_NO_THROW(client.doSARR());
// Configure client to request IA_NA and aAppend IA_NA option
// to the client's message.
client.setDUID("01:02:03:04");
- client.useNA();
- ASSERT_NO_THROW(client.useHint(100, 200, 64, "2001:db8:1:1::dead:beef"));
+ client.useNA(1234, IOAddress("2001:db8:1:1::dead:beef"));
// Perform 4-way exchange.
ASSERT_NO_THROW(client.doSARR());
// Now redo the client, adding one to the DUID
client.clearConfig();
client.modifyDUID();
- client.useNA();
- ASSERT_NO_THROW(client.useHint(100, 200, 64, "2001:db8:1:1::dead:beef"));
// Perform 4-way exchange.
ASSERT_NO_THROW(client.doSARR());
// we get a dynamic address.
client.clearConfig();
client.modifyDUID();
- client.useNA();
- ASSERT_NO_THROW(client.useHint(100, 200, 64, "2001:db8:1:1::dead:beef"));
+ client.clearRequestedIAs();
+ client.useNA(1234);
// Perform 4-way exchange.
ASSERT_NO_THROW(client.doSARR());
// Configure client to request IA_NA and aAppend IA_NA option
// to the client's message.
client.setDUID("01:02:03:04");
- client.useNA();
- ASSERT_NO_THROW(client.useHint(100, 200, 64, "2001:db8:1:1::dead:beef"));
+ client.useNA(1234, IOAddress("2001:db8:1:1::dead:beef"));
// Perform 4-way exchange.
ASSERT_NO_THROW(client.doSARR());
Lease6 lease_client = client.getLease(0);
EXPECT_EQ("2001:db8:1:1::babe", lease_client.addr_.toText());
+ // Do not send the hint while renewing.
+ client.clearRequestedIAs();
+
// Send Renew message to the server.
ASSERT_NO_THROW(client.doRenew());
// Configure client to request IA_NA and aAppend IA_NA option
// to the client's message.
client.setDUID("01:02:03:04");
- client.useNA();
- ASSERT_NO_THROW(client.useHint(100, 200, 64, "2001:db8:1:1::dead:beef"));
+ client.useNA(1234, IOAddress("2001:db8:1:1::dead:beef"));
// Perform 4-way exchange.
ASSERT_NO_THROW(client.doSARR());
Lease6 lease_client = client.getLease(0);
EXPECT_EQ("2001:db8:1:1::babe", lease_client.addr_.toText());
+ // Do not send the hint while renewing.
+ client.clearRequestedIAs();
+
// Send Rebind message to the server.
ASSERT_NO_THROW(client.doRebind());
Lease6 lease_client = client.getLease(0);
// Modify the IAID of the lease record that client stores. By adding
// one to IAID we guarantee that the IAID will change.
+ client.clearRequestedIAs();
client.config_.leases_[0].iaid_ = 1235;
- client.useNA(true, 1235);
+ client.useNA(1235);
// Try to Rebind. The server should allocate new lease for this IAID.
ASSERT_NO_THROW(client.doRebind());
// Modify the IAID of the lease record that client stores. By adding
// one to IAID we guarantee that the IAID will change.
+ client.clearRequestedIAs();
client.config_.leases_[0].iaid_ = 1235;
- client.useNA(true, 1235);
+ client.useNA(1235);
// Try to Rebind. The server should allocate new lease for this IAID.
ASSERT_NO_THROW(client.doRebind());
// Modify the IAID of the lease record that client stores. By adding
// one to IAID we guarantee that the IAID will change.
+ client.clearRequestedIAs();
client.config_.leases_[0].iaid_ = 5679;
- client.usePD(true, 5679);
+ client.usePD(5679);
// Try to Rebind. The server should allocate new lease for this IAID.
ASSERT_NO_THROW(client.doRebind());
EXPECT_EQ(STATUS_Success, client.getStatusCode(na_iaid_));
// Specify the hint used for IA_PD.
- client.useHint(0, 0, 64, "::");
+ client.usePD(pd_iaid_, IOAddress::IPV6_ZERO_ADDRESS(), 64);
// Send Renew message to the server, including IA_NA and requesting IA_PD.
ASSERT_NO_THROW(client.doRenew());
// Reconfigure the server to use both NA and PD pools.
configure(RENEW_CONFIGS[2], *client.getServer());
- // Specify the hint used for IA_PD.
- client.useHint(0, 0, 64, "::");
-
// Send Renew message to the server, including IA_NA and requesting IA_PD.
ASSERT_NO_THROW(client.doRenew());
ASSERT_EQ(0, leases_client_na.size());
ASSERT_EQ(STATUS_NoAddrsAvail, client.getStatusCode(na_iaid_));
- client.useHint(0, 0, "2001:db8:1::100");
+ client.useNA(na_iaid_, IOAddress("2001:db8:1::100"));
// Send Renew message to the server, including IA_PD and requesting IA_NA.
// The server should return NoAddrsAvail status code in this case.
#include <stats/stats_mgr.h>
using namespace isc;
+using namespace isc::asiolink;
using namespace isc::dhcp;
using namespace isc::dhcp::test;
getCfgSubnets6()->getAll();
ASSERT_EQ(1, subnets->size());
// Append IAPREFIX option to the client's message.
- ASSERT_NO_THROW(client.useHint(100, 200, 64, "2001:db8:3:33::33"));
+ ASSERT_NO_THROW(client.usePD(5678, asiolink::IOAddress("2001:db8:3:33::33"),
+ 64));
// Perform 4-way exchange.
ASSERT_NO_THROW(client.doSARR());
// Server should have assigned a prefix.
client.modifyDUID();
// Use the hint with some least significant bytes set.
- ASSERT_NO_THROW(client.useHint(100, 200, 64, "2001:db8:3:33::34"));
+ client.clearRequestedIAs();
+ ASSERT_NO_THROW(client.usePD(5678, IOAddress("2001:db8:3:33::34"), 64));
ASSERT_NO_THROW(client.doSARR());
// Server should assign a lease.
ASSERT_EQ(1, client.getLeaseNum());
Pool6>(ctx.subnet_->getPool(ctx.currentIA().type_, hint, false));
if (pool) {
+
/// @todo: We support only one hint for now
Lease6Ptr lease = LeaseMgrFactory::instance().getLease6(ctx.currentIA().type_,
hint);