]> git.ipfire.org Git - thirdparty/kea.git/commitdiff
[github24] Prefix Exclude option is returned to the clients.
authorMarcin Siodelski <marcin@isc.org>
Thu, 29 Sep 2016 10:56:03 +0000 (12:56 +0200)
committerMarcin Siodelski <marcin@isc.org>
Thu, 29 Sep 2016 10:56:03 +0000 (12:56 +0200)
Currently it is only returned for dynamically allocated prefixes
from certain pools. It won't work for host reservations.

src/bin/dhcp6/dhcp6_srv.cc
src/bin/dhcp6/dhcp6_srv.h
src/bin/dhcp6/tests/renew_unittest.cc
src/bin/dhcp6/tests/sarr_unittest.cc
src/lib/dhcpsrv/alloc_engine.cc
src/lib/dhcpsrv/alloc_engine.h

index 58893bb15a23db9a547e60809716997448c46f95..05b6e8bdf2b342351e998dd1dd4b325d2d142b8d 100644 (file)
@@ -20,6 +20,7 @@
 #include <dhcp/option6_iaaddr.h>
 #include <dhcp/option6_iaprefix.h>
 #include <dhcp/option6_status_code.h>
+#include <dhcp/option6_pdexclude.h>
 #include <dhcp/option_custom.h>
 #include <dhcp/option_vendor.h>
 #include <dhcp/option_vendor_class.h>
@@ -68,6 +69,7 @@
 #include <boost/tokenizer.hpp>
 #include <boost/algorithm/string/erase.hpp>
 
+#include <algorithm>
 #include <stdlib.h>
 #include <time.h>
 #include <iomanip>
@@ -857,6 +859,7 @@ Dhcpv6Srv::buildCfgOptionList(const Pkt6Ptr& question,
 
 void
 Dhcpv6Srv::appendRequestedOptions(const Pkt6Ptr& question, Pkt6Ptr& answer,
+                                  AllocEngine::ClientContext6& ctx,
                                   const CfgOptionList& co_list) {
 
     // Client requests some options using ORO option. Try to
@@ -865,18 +868,39 @@ Dhcpv6Srv::appendRequestedOptions(const Pkt6Ptr& question, Pkt6Ptr& answer,
         boost::dynamic_pointer_cast<OptionIntArray<uint16_t> >
         (question->getOption(D6O_ORO));
 
-    // Option ORO not found? We're done here then.
-    if (!option_oro || co_list.empty()) {
+    // If there is no ORO option, there is nothing more to do.
+    if (!option_oro) {
         return;
+
     }
 
     // Get the list of options that client requested.
     const std::vector<uint16_t>& requested_opts = option_oro->getValues();
+
+    if (co_list.empty()) {
+        // If there are no options configured, we at least have to check if
+        // the client has requested PD exclude, which is configured as
+        // part of the pool configuration.
+        ctx.pd_exclude_requested_ = (std::find(requested_opts.begin(),
+                                               requested_opts.end(),
+                                               D6O_PD_EXCLUDE) !=
+                                     requested_opts.end());
+        return;
+    }
+
     BOOST_FOREACH(uint16_t opt, requested_opts) {
+        // Prefix Exclude option requires special handling, as it can
+        // be configured as part of the pool configuration.
+        if (opt == D6O_PD_EXCLUDE) {
+            ctx.pd_exclude_requested_ = true;
+            // Prefix Exclude can only be included in the IA Prefix option
+            // of IA_PD. Thus there is nothing more to do here.
+            continue;
+        }
         // Iterate on the configured option list
         for (CfgOptionList::const_iterator copts = co_list.begin();
              copts != co_list.end(); ++copts) {
-            OptionDescriptor desc = (*copts)->get("dhcp6", opt);
+            OptionDescriptor desc = (*copts)->get(DHCP6_OPTION_SPACE, opt);
             // Got it: add it and jump to the outer loop
             if (desc.option_) {
                 answer->addOption(desc.option_);
@@ -1531,6 +1555,19 @@ Dhcpv6Srv::assignIA_PD(const Pkt6Ptr& query, const Pkt6Ptr& answer,
                                          (*l)->prefixlen_, (*l)->preferred_lft_,
                                          (*l)->valid_lft_));
             ia_rsp->addOption(addr);
+
+            if (ctx.pd_exclude_requested_) {
+                // PD exclude option has been requested via ORO, thus we need to
+                // include it if the pool configuration specifies this option.
+                Pool6Ptr pool = ctx.currentIA().pool_;
+                if (pool && pool->getExcludedPrefixLength() > 0) {
+                    OptionPtr opt(new Option6PDExclude((*l)->addr_,
+                                                       (*l)->prefixlen_,
+                                                       pool->getExcludedPrefix(),
+                                                       pool->getExcludedPrefixLength()));
+                    addr->addOption(opt);
+                }
+            }
         }
 
         // It would be possible to insert status code=0(success) as well,
@@ -1801,10 +1838,26 @@ Dhcpv6Srv::extendIA_PD(const Pkt6Ptr& query,
 
     // For all the leases we have now, add the IAPPREFIX with non-zero lifetimes
     for (Lease6Collection::const_iterator l = leases.begin(); l != leases.end(); ++l) {
+
         Option6IAPrefixPtr prf(new Option6IAPrefix(D6O_IAPREFIX,
                                (*l)->addr_, (*l)->prefixlen_,
                                (*l)->preferred_lft_, (*l)->valid_lft_));
         ia_rsp->addOption(prf);
+
+        if (ctx.pd_exclude_requested_) {
+            // PD exclude option has been requested via ORO, thus we need to
+            // include it if the pool configuration specifies this option.
+            Pool6Ptr pool = ctx.currentIA().pool_;
+            if (pool && pool->getExcludedPrefixLength() > 0) {
+                OptionPtr opt(new Option6PDExclude((*l)->addr_,
+                                                   (*l)->prefixlen_,
+                                                   pool->getExcludedPrefix(),
+                                                   pool->getExcludedPrefixLength()));
+                prf->addOption(opt);
+            }
+        }
+
+
         LOG_INFO(lease6_logger, DHCP6_PD_LEASE_RENEW)
             .arg(query->getLabel())
             .arg((*l)->addr_.toText())
@@ -2295,7 +2348,7 @@ Dhcpv6Srv::processSolicit(const Pkt6Ptr& solicit) {
     CfgOptionList co_list;
     buildCfgOptionList(solicit, ctx, co_list);
     appendDefaultOptions(solicit, response, co_list);
-    appendRequestedOptions(solicit, response, co_list);
+    appendRequestedOptions(solicit, response, ctx, co_list);
     appendRequestedVendorOptions(solicit, response, ctx, co_list);
 
     processClientFqdn(solicit, response, ctx);
@@ -2325,7 +2378,7 @@ Dhcpv6Srv::processRequest(const Pkt6Ptr& request) {
     CfgOptionList co_list;
     buildCfgOptionList(request, ctx, co_list);
     appendDefaultOptions(request, reply, co_list);
-    appendRequestedOptions(request, reply, co_list);
+    appendRequestedOptions(request, reply, ctx, co_list);
     appendRequestedVendorOptions(request, reply, ctx, co_list);
 
     processClientFqdn(request, reply, ctx);
@@ -2351,7 +2404,7 @@ Dhcpv6Srv::processRenew(const Pkt6Ptr& renew) {
     CfgOptionList co_list;
     buildCfgOptionList(renew, ctx, co_list);
     appendDefaultOptions(renew, reply, co_list);
-    appendRequestedOptions(renew, reply, co_list);
+    appendRequestedOptions(renew, reply, ctx, co_list);
     appendRequestedVendorOptions(renew, reply, ctx, co_list);
 
     processClientFqdn(renew, reply, ctx);
@@ -2377,7 +2430,7 @@ Dhcpv6Srv::processRebind(const Pkt6Ptr& rebind) {
     CfgOptionList co_list;
     buildCfgOptionList(rebind, ctx, co_list);
     appendDefaultOptions(rebind, reply, co_list);
-    appendRequestedOptions(rebind, reply, co_list);
+    appendRequestedOptions(rebind, reply, ctx, co_list);
     appendRequestedVendorOptions(rebind, reply, ctx, co_list);
 
     processClientFqdn(rebind, reply, ctx);
@@ -2411,7 +2464,7 @@ Dhcpv6Srv::processConfirm(const Pkt6Ptr& confirm) {
     CfgOptionList co_list;
     buildCfgOptionList(confirm, ctx, co_list);
     appendDefaultOptions(confirm, reply, co_list);
-    appendRequestedOptions(confirm, reply, co_list);
+    appendRequestedOptions(confirm, reply, ctx, co_list);
     appendRequestedVendorOptions(confirm, reply, ctx, co_list);
     // 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
@@ -2813,7 +2866,7 @@ Dhcpv6Srv::processInfRequest(const Pkt6Ptr& inf_request) {
     appendDefaultOptions(inf_request, reply, co_list);
 
     // Try to assign options that were requested by the client.
-    appendRequestedOptions(inf_request, reply, co_list);
+    appendRequestedOptions(inf_request, reply, ctx, co_list);
 
     // Try to assigne vendor options that were requested by the client.
     appendRequestedVendorOptions(inf_request, reply, ctx, co_list);
index 7513f909bfd993ff446611102a55e62201b49929..9435823499f3c8ed6c399ea836f9dbc1eb3f7a8a 100644 (file)
@@ -475,8 +475,13 @@ protected:
     ///
     /// @param question client's message
     /// @param answer server's message (options will be added here)
+    /// @param [out] ctx client context. This method sets the
+    /// ctx.pd_exclude_requested_ field to 'true' if the Prefix Exclude
+    /// option has been requested.
+    ///
     /// @param co_list configured option list
     void appendRequestedOptions(const Pkt6Ptr& question, Pkt6Ptr& answer,
+                                AllocEngine::ClientContext6& ctx,
                                 const CfgOptionList& co_list);
 
     /// @brief Appends requested vendor options to server's answer.
index 3413d659cab3498517d9ea85798af13d805938d4..cac72e226e3a466b11eaf1f1b141c06ab7387b84 100644 (file)
@@ -10,6 +10,7 @@
 #include <dhcp/docsis3_option_defs.h>
 #include <dhcp/option_string.h>
 #include <dhcp/option_vendor.h>
+#include <dhcp/option6_pdexclude.h>
 #include <dhcp/tests/iface_mgr_test_config.h>
 #include <dhcp6/json_config_parser.h>
 #include <dhcp6/tests/dhcp6_message_test.h>
@@ -44,6 +45,13 @@ namespace {
 ///   - 1 subnet with 2001:db8:1::/64 pool
 ///   - DOCSIS vendor config file sub-option
 ///
+/// - Configuration 4:
+///   - addresses and prefixes
+///   - 1 subnet with one address pool and one prefix pool
+///   - address pool: 2001:db8:1::/64
+///   - prefix pool: 3000::/72
+///   - excluded prefix 3000::1000/120 in a prefix pool.
+///
 const char* RENEW_CONFIGS[] = {
 // Configuration 0
     "{ \"interfaces-config\": {"
@@ -117,8 +125,29 @@ const char* RENEW_CONFIGS[] = {
         "    \"interface-id\": \"\","
         "    \"interface\": \"eth0\""
         " } ],"
-        "\"valid-lifetime\": 4000 }"
+        "\"valid-lifetime\": 4000 }",
 
+// Configuration 4
+    "{ \"interfaces-config\": {"
+        "  \"interfaces\": [ \"*\" ]"
+        "},"
+        "\"preferred-lifetime\": 3000,"
+        "\"rebind-timer\": 2000, "
+        "\"renew-timer\": 1000, "
+        "\"subnet6\": [ { "
+        "    \"pools\": [ { \"pool\": \"2001:db8:1::/64\" } ],"
+        "    \"pd-pools\": ["
+        "        { \"prefix\": \"3000::\", "
+        "          \"prefix-len\": 72, "
+        "          \"delegated-len\": 80,"
+        "          \"excluded-prefix\": \"3000::1000\","
+        "          \"excluded-prefix-len\": 120"
+        "        } ],"
+        "    \"subnet\": \"2001:db8:1::/48\", "
+        "    \"interface-id\": \"\","
+        "    \"interface\": \"eth0\""
+        " } ],"
+        "\"valid-lifetime\": 4000 }"
 };
 
 /// @brief Test fixture class for testing Renew.
@@ -199,6 +228,91 @@ TEST_F(RenewTest, requestPrefixInRenew) {
     EXPECT_EQ(STATUS_Success, client.getStatusCode(pd_iaid_));
 }
 
+// Test that it is possible to renew a prefix lease with a Prefix Exclude
+// option being included during renew.
+TEST_F(RenewTest, renewWithExcludedPrefix) {
+    Dhcp6Client client;
+
+    // Configure client to request IA_NA and IA_PD.
+    client.requestAddress(na_iaid_);
+    client.requestPrefix(pd_iaid_);
+
+    // Request Prefix Exclude option.
+    client.requestOption(D6O_PD_EXCLUDE);
+
+    // Configure the server with NA pools only.
+    ASSERT_NO_THROW(configure(RENEW_CONFIGS[2], *client.getServer()));
+
+    // Perform 4-way exchange.
+    ASSERT_NO_THROW(client.doSARR());
+
+    // Simulate aging of leases.
+    client.fastFwdTime(1000);
+
+    // Make sure that the client has acquired NA lease.
+    std::vector<Lease6> leases_client_na = client.getLeasesByType(Lease::TYPE_NA);
+    ASSERT_EQ(1, leases_client_na.size());
+    EXPECT_EQ(STATUS_Success, client.getStatusCode(na_iaid_));
+
+    // The client should also acquire a PD lease.
+    std::vector<Lease6> leases_client_pd = client.getLeasesByType(Lease::TYPE_PD);
+    ASSERT_EQ(1, leases_client_pd.size());
+    ASSERT_EQ(STATUS_Success, client.getStatusCode(pd_iaid_));
+
+    // Send Renew message to the server, including IA_NA and IA_PD.
+    ASSERT_NO_THROW(client.doRenew());
+
+    std::vector<Lease6> leases_client_na_renewed =
+        client.getLeasesByType(Lease::TYPE_NA);
+    ASSERT_EQ(1, leases_client_na_renewed.size());
+    EXPECT_EQ(STATUS_Success, client.getStatusCode(na_iaid_));
+
+    std::vector<Lease6> leases_client_pd_renewed =
+        client.getLeasesByType(Lease::TYPE_PD);
+    ASSERT_EQ(1, leases_client_pd_renewed.size());
+    EXPECT_EQ(STATUS_Success, client.getStatusCode(pd_iaid_));
+
+    // Make sure that Prefix Exclude option hasn't been included.
+    OptionPtr option = client.getContext().response_->getOption(D6O_IA_PD);
+    ASSERT_TRUE(option);
+    option = option->getOption(D6O_IAPREFIX);
+    ASSERT_TRUE(option);
+    option = option->getOption(D6O_PD_EXCLUDE);
+    ASSERT_FALSE(option);
+
+    // Reconfigure the server to use the prefix pool with excluded prefix.
+    configure(RENEW_CONFIGS[4], *client.getServer());
+
+    // Send Renew message to the server, including IA_NA and IA_PD.
+    ASSERT_NO_THROW(client.doRenew());
+
+    // Make sure that the client has acquired NA lease.
+    leases_client_na_renewed = client.getLeasesByType(Lease::TYPE_NA);
+    ASSERT_EQ(1, leases_client_na_renewed.size());
+    EXPECT_EQ(STATUS_Success, client.getStatusCode(na_iaid_));
+
+    // Make sure that the client has acquired PD lease.
+    leases_client_pd_renewed = client.getLeasesByType(Lease::TYPE_PD);
+    ASSERT_EQ(1, leases_client_pd_renewed.size());
+    EXPECT_EQ(STATUS_Success, client.getStatusCode(pd_iaid_));
+
+    // The leases should have been renewed.
+    EXPECT_EQ(1000, leases_client_na_renewed[0].cltt_ - leases_client_na[0].cltt_);
+    EXPECT_EQ(1000, leases_client_pd_renewed[0].cltt_ - leases_client_pd[0].cltt_);
+
+    // This time, the Prefix Exclude option should be included.
+    option = client.getContext().response_->getOption(D6O_IA_PD);
+    ASSERT_TRUE(option);
+    option = option->getOption(D6O_IAPREFIX);
+    ASSERT_TRUE(option);
+    option = option->getOption(D6O_PD_EXCLUDE);
+    ASSERT_TRUE(option);
+    Option6PDExcludePtr pd_exclude = boost::dynamic_pointer_cast<Option6PDExclude>(option);
+    ASSERT_TRUE(pd_exclude);
+    EXPECT_EQ("3000::1000", pd_exclude->getExcludedPrefix().toText());
+    EXPECT_EQ(120, static_cast<unsigned>(pd_exclude->getExcludedPrefixLength()));
+}
+
 // This test verifies that the client can request a prefix delegation
 // with a hint, while it is renewing an address lease.
 TEST_F(RenewTest, requestPrefixInRenewUseHint) {
index 3a500dfebdfcc72373e8bf71b4f10536e9c740e9..1cc568b25e5849ebd6381a4c154c9aadb0b1ddb5 100644 (file)
@@ -7,6 +7,7 @@
 #include <config.h>
 #include <dhcp/tests/iface_mgr_test_config.h>
 #include <dhcp/option6_client_fqdn.h>
+#include <dhcp/option6_pdexclude.h>
 #include <dhcp6/tests/dhcp6_test_utils.h>
 #include <dhcp6/tests/dhcp6_client.h>
 #include <dhcpsrv/cfgmgr.h>
@@ -39,6 +40,11 @@ namespace {
 ///     one
 ///   - DNS updates enabled
 ///
+/// - Configuration 2:
+///   - one subnet 3000::/32 used on eth0 interface
+///   - prefixes of length 64, delegated from the pool: 2001:db8:3::/48
+///   - Excluded Prefix specified (RFC 6603).
+///
 const char* CONFIGS[] = {
     // Configuration 0
     "{ \"interfaces-config\": {"
@@ -82,7 +88,29 @@ const char* CONFIGS[] = {
         " \"dhcp-ddns\" : {"
         "     \"enable-updates\" : True, "
         "     \"qualifying-suffix\" : \"example.com\" }"
-    "}"
+    "}",
+
+    // Configuration 2
+    "{ \"interfaces-config\": {"
+        "  \"interfaces\": [ \"*\" ]"
+        "},"
+        "\"preferred-lifetime\": 3000,"
+        "\"rebind-timer\": 2000, "
+        "\"renew-timer\": 1000, "
+        "\"subnet6\": [ { "
+        "    \"pd-pools\": ["
+        "        { \"prefix\": \"2001:db8:3::\", "
+        "          \"prefix-len\": 48, "
+        "          \"delegated-len\": 64,"
+        "          \"excluded-prefix\": \"2001:db8:3::1000\","
+        "          \"excluded-prefix-len\": 120"
+        "        } ],"
+        "    \"subnet\": \"3000::/32\", "
+        "    \"interface-id\": \"\","
+        "    \"interface\": \"eth0\""
+        " } ],"
+        "\"valid-lifetime\": 4000 }",
+
 };
 
 /// @brief Test fixture class for testing 4-way exchange: Solicit-Advertise,
@@ -173,6 +201,46 @@ TEST_F(SARRTest, directClientPrefixHint) {
     ASSERT_TRUE(lease_server);
 }
 
+/// This test verifies that it is possible to specify an excluded prefix
+/// (RFC 6603) and send it back to the client requesting prefix delegation.
+TEST_F(SARRTest, directClientExcludedPrefix) {
+    Dhcp6Client client;
+    // Configure client to request IA_PD.
+    client.requestPrefix();
+    client.requestOption(D6O_PD_EXCLUDE);
+    configure(CONFIGS[2], *client.getServer());
+    // Make sure we ended-up having expected number of subnets configured.
+    const Subnet6Collection* subnets = CfgMgr::instance().getCurrentCfg()->
+        getCfgSubnets6()->getAll();
+    ASSERT_EQ(1, subnets->size());
+    // Perform 4-way exchange.
+    ASSERT_NO_THROW(client.doSARR());
+    // Server should have assigned a prefix.
+    ASSERT_EQ(1, client.getLeaseNum());
+    Lease6 lease_client = client.getLease(0);
+    EXPECT_EQ(64, lease_client.prefixlen_);
+    EXPECT_EQ(3000, lease_client.preferred_lft_);
+    EXPECT_EQ(4000, lease_client.valid_lft_);
+    Lease6Ptr lease_server = checkLease(lease_client);
+    // Check that the server recorded the lease.
+    ASSERT_TRUE(lease_server);
+
+    OptionPtr option = client.getContext().response_->getOption(D6O_IA_PD);
+    ASSERT_TRUE(option);
+    Option6IAPtr ia = boost::dynamic_pointer_cast<Option6IA>(option);
+    ASSERT_TRUE(ia);
+    option = ia->getOption(D6O_IAPREFIX);
+    ASSERT_TRUE(option);
+    Option6IAPrefixPtr pd_option = boost::dynamic_pointer_cast<Option6IAPrefix>(option);
+    ASSERT_TRUE(pd_option);
+    option = pd_option->getOption(D6O_PD_EXCLUDE);
+    ASSERT_TRUE(option);
+    Option6PDExcludePtr pd_exclude = boost::dynamic_pointer_cast<Option6PDExclude>(option);
+    ASSERT_TRUE(pd_exclude);
+    EXPECT_EQ("2001:db8:3::1000", pd_exclude->getExcludedPrefix().toText());
+    EXPECT_EQ(120, static_cast<unsigned>(pd_exclude->getExcludedPrefixLength()));
+}
+
 // Check that when the client includes the Rapid Commit option in its
 // Solicit, the server responds with Reply and commits the lease.
 TEST_F(SARRTest, rapidCommitEnable) {
index 1f8d9d4e3d3839bc236baed7791d92d3919b25d1..61543ab8cb07c24ae789e871f16b0f8a52f6f882 100644 (file)
@@ -350,7 +350,7 @@ AllocEngine::ClientContext6::ClientContext6(const Subnet6Ptr& subnet,
       duid_(duid), hwaddr_(), host_identifiers_(), host_(),
       fwd_dns_update_(fwd_dns), rev_dns_update_(rev_dns),
       hostname_(hostname), callout_handle_(callout_handle),
-      allocated_resources_(), ias_() {
+      allocated_resources_(), ias_(), pd_exclude_requested_(false) {
 
     // Initialize host identifiers.
     if (duid) {
@@ -360,7 +360,7 @@ AllocEngine::ClientContext6::ClientContext6(const Subnet6Ptr& subnet,
 
 AllocEngine::ClientContext6::IAContext::IAContext()
     : iaid_(0), type_(Lease::TYPE_NA), hints_(), old_leases_(),
-      changed_leases_(), ia_rsp_() {
+      changed_leases_(), ia_rsp_(), pool_() {
 }
 
 void
@@ -583,10 +583,10 @@ AllocEngine::allocateUnreservedLeases6(ClientContext6& ctx) {
 
     // check if the hint is in pool and is available
     // This is equivalent of subnet->inPool(hint), but returns the pool
-    Pool6Ptr pool = boost::dynamic_pointer_cast<
+    ctx.currentIA().pool_ = boost::dynamic_pointer_cast<
         Pool6>(ctx.subnet_->getPool(ctx.currentIA().type_, hint, false));
 
-    if (pool) {
+    if (ctx.currentIA().pool_) {
 
         /// @todo: We support only one hint for now
         Lease6Ptr lease =
@@ -608,7 +608,7 @@ AllocEngine::allocateUnreservedLeases6(ClientContext6& ctx) {
 
                 // The hint is valid and not currently used, let's create a
                 // lease for it
-                lease = createLease6(ctx, hint, pool->getLength());
+                lease = createLease6(ctx, hint, ctx.currentIA().pool_->getLength());
 
                 // It can happen that the lease allocation failed (we could
                 // have lost the race condition. That means that the hint is
@@ -647,7 +647,8 @@ AllocEngine::allocateUnreservedLeases6(ClientContext6& ctx) {
                     ctx.currentIA().old_leases_.push_back(old_lease);
 
                     /// We found a lease and it is expired, so we can reuse it
-                    lease = reuseExpiredLease(lease, ctx, pool->getLength());
+                    lease = reuseExpiredLease(lease, ctx,
+                                              ctx.currentIA().pool_->getLength());
 
                     /// @todo: We support only one lease per ia for now
                     leases.push_back(lease);
@@ -663,6 +664,8 @@ AllocEngine::allocateUnreservedLeases6(ClientContext6& ctx) {
         }
     }
 
+    ctx.currentIA().pool_.reset();
+
     // The hint was useless (it was not provided at all, was used by someone else,
     // was out of pool or reserved for someone else). Search the pool until first
     // of the following occurs:
@@ -689,10 +692,10 @@ AllocEngine::allocateUnreservedLeases6(ClientContext6& ctx) {
         // non-PD leases.
         uint8_t prefix_len = 128;
         if (ctx.currentIA().type_ == Lease::TYPE_PD) {
-            Pool6Ptr pool = boost::dynamic_pointer_cast<Pool6>(
+            ctx.currentIA().pool_ = boost::dynamic_pointer_cast<Pool6>(
                 ctx.subnet_->getPool(ctx.currentIA().type_, candidate, false));
             /// @todo: verify that the pool is non-null
-            prefix_len = pool->getLength();
+            prefix_len = ctx.currentIA().pool_->getLength();
         }
 
         Lease6Ptr existing = LeaseMgrFactory::instance().getLease6(ctx.currentIA().type_,
index 69ac652f04c8c0d1de4f3533479b3d7128ea95da..82708c4e5c230a22f5ae5116bf1760c2325c74a5 100644 (file)
@@ -381,6 +381,10 @@ public:
             /// response
             Option6IAPtr ia_rsp_;
 
+            /// @brief A pointer to a pool from which an address or prefix has
+            /// been assigned in this IA.
+            Pool6Ptr pool_;
+
             /// @brief Default constructor.
             ///
             /// Initializes @ref type_ to @c Lease::TYPE_NA and @ref iaid_ to 0.
@@ -397,6 +401,10 @@ public:
         /// @brief Container holding IA specific contexts.
         std::vector<IAContext> ias_;
 
+        /// @brief Indicates if PD exclude option has been requested by a
+        /// client.
+        bool pd_exclude_requested_;
+
         /// @brief Convenience method adding allocated prefix or address.
         ///
         /// @param prefix Prefix or address.