]> git.ipfire.org Git - thirdparty/kea.git/commitdiff
[295-min-max-lease-time-configuration-options] checkpoint
authorFrancis Dupont <fdupont@isc.org>
Thu, 16 May 2019 12:15:54 +0000 (14:15 +0200)
committerFrancis Dupont <fdupont@isc.org>
Sat, 22 Jun 2019 14:05:23 +0000 (10:05 -0400)
src/bin/dhcp6/dhcp6_srv.cc
src/lib/dhcpsrv/alloc_engine.cc
src/lib/dhcpsrv/alloc_engine.h
src/lib/dhcpsrv/tests/alloc_engine6_unittest.cc
src/lib/dhcpsrv/tests/alloc_engine_expiration_unittest.cc

index 37ad8b9ffa62dd2cd2b4849108499277d4a488df..814e7a5cad9f0050300be7c4603f46b2d3a3f368 100644 (file)
@@ -1065,11 +1065,12 @@ Dhcpv6Srv::buildCfgOptionList(const Pkt6Ptr& question,
     // Secondly, pool specific options. Pools are defined within a subnet, so
     // if there is no subnet, there is nothing to do.
     if (ctx.subnet_) {
-        BOOST_FOREACH(const AllocEngine::ResourceType& resource,
-                      ctx.allocated_resources_) {
-            PoolPtr pool = ctx.subnet_->getPool(resource.second == 128 ?
-                                                Lease::TYPE_NA : Lease::TYPE_PD,
-                                                resource.first, false);
+        for (auto resource : ctx.allocated_resources_) {
+            PoolPtr pool =
+                ctx.subnet_->getPool(resource.getPrefixLength() == 128 ?
+                                     Lease::TYPE_NA : Lease::TYPE_PD,
+                                     resource.getAddress(),
+                                     false);
             if (pool && !pool->getCfgOption()->empty()) {
                 co_list.push_back(pool->getCfgOption());
             }
@@ -1807,7 +1808,11 @@ Dhcpv6Srv::assignIA_NA(const Pkt6Ptr& query, const Pkt6Ptr& answer,
     // Set per-IA context values.
     ctx.createIAContext();
     ctx.currentIA().iaid_ = ia->getIAID();
-    ctx.currentIA().addHint(hint);
+    if (hint_opt) {
+        ctx.currentIA().addHint(hint_opt);
+    } else {
+        ctx.currentIA().addHint(hint);
+    }
     ctx.currentIA().type_ = Lease::TYPE_NA;
 
     // Use allocation engine to pick a lease for this client. Allocation engine
@@ -1913,7 +1918,11 @@ Dhcpv6Srv::assignIA_PD(const Pkt6Ptr& query, const Pkt6Ptr& /*answer*/,
     // Set per-IA context values.
     ctx.createIAContext();
     ctx.currentIA().iaid_ = ia->getIAID();
-    ctx.currentIA().addHint(hint);
+    if (hint_opt) {
+        ctx.currentIA().addHint(hint_opt);
+    } else {
+        ctx.currentIA().addHint(hint);
+    }
     ctx.currentIA().type_ = Lease::TYPE_PD;
 
     // Use allocation engine to pick a lease for this client. Allocation engine
@@ -2056,7 +2065,7 @@ Dhcpv6Srv::extendIA_NA(const Pkt6Ptr& query, const Pkt6Ptr& answer,
             // There's no way to protect against this.
             continue;
         }
-        ctx.currentIA().addHint(iaaddr->getAddress());
+        ctx.currentIA().addHint(iaaddr);
     }
 
     Lease6Collection leases = alloc_engine_->renewLeases6(ctx);
@@ -2095,7 +2104,7 @@ Dhcpv6Srv::extendIA_NA(const Pkt6Ptr& query, const Pkt6Ptr& answer,
             .arg(ia->getIAID());
 
         // Now remove this prefix from the hints list.
-        AllocEngine::ResourceType hint_type((*l)->addr_, (*l)->prefixlen_);
+        AllocEngine::Resource hint_type((*l)->addr_, (*l)->prefixlen_);
         hints.erase(std::remove(hints.begin(), hints.end(), hint_type),
                     hints.end());
     }
@@ -2114,7 +2123,7 @@ Dhcpv6Srv::extendIA_NA(const Pkt6Ptr& query, const Pkt6Ptr& answer,
         }
 
         // Now remove this address from the hints list.
-        AllocEngine::ResourceType hint_type((*l)->addr_, 128);
+        AllocEngine::Resource hint_type((*l)->addr_, 128);
         hints.erase(std::remove(hints.begin(), hints.end(), hint_type), hints.end());
 
         // If the new FQDN settings have changed for the lease, we need to
@@ -2138,7 +2147,7 @@ Dhcpv6Srv::extendIA_NA(const Pkt6Ptr& query, const Pkt6Ptr& answer,
     for (AllocEngine::HintContainer::const_iterator hint = hints.begin();
          hint != hints.end(); ++hint) {
         Option6IAAddrPtr iaaddr(new Option6IAAddr(D6O_IAADDR,
-                                                  hint->first, 0, 0));
+                                                  hint->getAddress(), 0, 0));
         ia_rsp->addOption(iaaddr);
     }
 
@@ -2231,7 +2240,7 @@ Dhcpv6Srv::extendIA_PD(const Pkt6Ptr& query,
         }
 
         // Put the client's prefix into the hints list.
-        ctx.currentIA().addHint(prf->getAddress(), prf->getLength());
+        ctx.currentIA().addHint(prf);
     }
 
     // Call Allocation Engine and attempt to renew leases. Number of things
@@ -2291,7 +2300,7 @@ Dhcpv6Srv::extendIA_PD(const Pkt6Ptr& query,
             .arg(ia->getIAID());
 
         // Now remove this prefix from the hints list.
-        AllocEngine::ResourceType hint_type((*l)->addr_, (*l)->prefixlen_);
+        AllocEngine::Resource hint_type((*l)->addr_, (*l)->prefixlen_);
         hints.erase(std::remove(hints.begin(), hints.end(), hint_type),
                     hints.end());
     }
@@ -2310,7 +2319,7 @@ Dhcpv6Srv::extendIA_PD(const Pkt6Ptr& query,
         }
 
         // Now remove this prefix from the hints list.
-        AllocEngine::ResourceType hint_type((*l)->addr_, (*l)->prefixlen_);
+        AllocEngine::Resource hint_type((*l)->addr_, (*l)->prefixlen_);
         hints.erase(std::remove(hints.begin(), hints.end(), hint_type), hints.end());
     }
 
@@ -2322,9 +2331,11 @@ Dhcpv6Srv::extendIA_PD(const Pkt6Ptr& query,
         // Send the prefix with the zero lifetimes only if the prefix
         // contains non-zero value. A zero value indicates that the hint was
         // for the prefix length.
-        if (!prefix->first.isV6Zero()) {
-            OptionPtr prefix_opt(new Option6IAPrefix(D6O_IAPREFIX, prefix->first,
-                                                     prefix->second, 0, 0));
+        if (!prefix->getAddress().isV6Zero()) {
+            OptionPtr prefix_opt(new Option6IAPrefix(D6O_IAPREFIX,
+                                                     prefix->getAddress(),
+                                                     prefix->getPrefixLength(),
+                                                     0, 0));
             ia_rsp->addOption(prefix_opt);
         }
     }
@@ -3502,13 +3513,12 @@ Dhcpv6Srv::requiredClassify(const Pkt6Ptr& pkt, AllocEngine::ClientContext6& ctx
         }
 
         // And finish by pools
-        BOOST_FOREACH(const AllocEngine::ResourceType& resource,
-                      ctx.allocated_resources_) {
-            PoolPtr pool = ctx.subnet_->getPool(resource.second == 128 ?
-                                                    Lease::TYPE_NA :
-                                                    Lease::TYPE_PD,
-                                                resource.first,
-                                                false);
+        for (auto resource : ctx.allocated_resources_) {
+            PoolPtr pool =
+                ctx.subnet_->getPool(resource.getPrefixLength() == 128 ?
+                                     Lease::TYPE_NA : Lease::TYPE_PD,
+                                     resource.getAddress(),
+                                     false);
             if (pool) {
                 const ClientClasses& to_add = pool->getRequiredClasses();
                 for (ClientClasses::const_iterator cclass = to_add.cbegin();
index 4b373fefb9bd4dc86f4d5326a8d99a2a1aebb5ba..eda417398e3d91857d6320dcf0fdfa4d4ee42517 100644 (file)
@@ -373,6 +373,16 @@ AllocEngine::AllocatorPtr AllocEngine::getAllocator(Lease::Type type) {
     return (alloc->second);
 }
 
+AllocEngine::Resource::Resource(const Option6IAAddrPtr& iaaddr)
+    : address_(iaaddr->getAddress()), prefix_len_(128),
+      preferred_(iaaddr->getPreferred()), valid_(iaaddr->getValid()) {
+}
+
+AllocEngine::Resource::Resource(const Option6IAPrefixPtr& iaprefix)
+    : address_(iaprefix->getAddress()), prefix_len_(iaprefix->getLength()),
+      preferred_(iaprefix->getPreferred()), valid_(iaprefix->getValid()) {
+}
+
 } // end of namespace isc::dhcp
 } // end of namespace isc
 
@@ -461,23 +471,37 @@ AllocEngine::ClientContext6::IAContext::IAContext()
 void
 AllocEngine::ClientContext6::
 IAContext::addHint(const asiolink::IOAddress& prefix,
-                   const uint8_t prefix_len) {
-    hints_.push_back(std::make_pair(prefix, prefix_len));
+                   const uint8_t prefix_len,
+                   const uint32_t preferred,
+                   const uint32_t valid) {
+    hints_.push_back(Resource(prefix, prefix_len, preferred, valid));
+}
+
+void
+AllocEngine::ClientContext6::
+IAContext::addHint(const Option6IAAddrPtr& iaaddr) {
+    hints_.push_back(Resource(iaaddr));
+}
+
+void
+AllocEngine::ClientContext6::
+IAContext::addHint(const Option6IAPrefixPtr& iaprefix) {
+    hints_.push_back(Resource(iaprefix));
 }
 
 void
 AllocEngine::ClientContext6::
 addAllocatedResource(const asiolink::IOAddress& prefix,
                      const uint8_t prefix_len) {
-    static_cast<void>(allocated_resources_.insert(std::make_pair(prefix,
-                                                                 prefix_len)));
+    static_cast<void>(allocated_resources_.insert(Resource(prefix,
+                                                           prefix_len)));
 }
 
 bool
 AllocEngine::ClientContext6::
 isAllocated(const asiolink::IOAddress& prefix, const uint8_t prefix_len) const {
     return (static_cast<bool>
-            (allocated_resources_.count(std::make_pair(prefix, prefix_len))));
+            (allocated_resources_.count(Resource(prefix, prefix_len))));
 }
 
 ConstHostPtr
@@ -816,7 +840,7 @@ AllocEngine::allocateUnreservedLeases6(ClientContext6& ctx) {
     IOAddress hint = IOAddress::IPV6_ZERO_ADDRESS();
     if (!ctx.currentIA().hints_.empty()) {
         /// @todo: We support only one hint for now
-        hint = ctx.currentIA().hints_[0].first;
+        hint = ctx.currentIA().hints_[0].getAddress();
     }
 
     Subnet6Ptr original_subnet = ctx.subnet_;
index f3fb6760f64d24196fe890a271ddc5c1d5cbdbc7..f228a9d3fb63aa5f5505a71718f0935c9afa59a6 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright (C) 2012-2018 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2012-2019 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
@@ -14,6 +14,8 @@
 #include <dhcp/pkt4.h>
 #include <dhcp/pkt6.h>
 #include <dhcp/option6_ia.h>
+#include <dhcp/option6_iaaddr.h>
+#include <dhcp/option6_iaprefix.h>
 #include <dhcpsrv/host.h>
 #include <dhcpsrv/subnet.h>
 #include <dhcpsrv/lease_mgr.h>
@@ -272,18 +274,125 @@ private:
 
 public:
 
-    /// @brief Defines a single hint (an address + prefix-length).
+    /// @brief Defines a single hint
     ///
     /// This is an entry that represents what the client had requested,
     /// either an address or a prefix. Prefix length is 128 for regular
-    /// addresses.
-    typedef std::pair<isc::asiolink::IOAddress, uint8_t> ResourceType;
+    /// addresses. Optionally it provides wanted preferred and valid
+    /// lifetimes.
+    ///
+    /// @note Seems to be used only for DHCPv6.
+    class Resource {
+    public:
+
+        /// @brief Default constructor.
+        ///
+        /// @param address the address or prefix
+        /// @param prefix_len the prefix length (128 for addresses)
+        /// @param preferred the optional preferred lifetime
+        /// @param valid the optional valid lifetime
+        Resource(const isc::asiolink::IOAddress& address,
+                 const uint8_t prefix_len,
+                 const uint32_t preferred = 0,
+                 const uint32_t valid = 0)
+            : address_(address), prefix_len_(prefix_len),
+              preferred_(preferred), valid_(valid) {
+        }
+
+        /// @brief Constructor from an IAADDR DHCPv6 option.
+        ///
+        /// @param iaaddr The pointer to the IAADDR option
+        Resource(const Option6IAAddrPtr& iaaddr);
+
+        /// @brief Constructor from an IAPREFIX DHCPv6 option.
+        ///
+        /// @param iaprefix The pointer to the IAPREFIX option
+        Resource(const Option6IAPrefixPtr& iaprefix);
+
+        /// @brief Returns the address.
+        ///
+        /// @return the address or prefix
+        isc::asiolink::IOAddress getAddress() const {
+            return (address_);
+        }
+
+        /// @brief Returns the prefix length.
+        ///
+        /// @return the prefix length
+        uint8_t getPrefixLength() const {
+            return (prefix_len_);
+        }
+
+        /// @brief Returns the optional preferred lifetime.
+        ///
+        /// @return the preferred lifetime (0 if not set)
+        uint32_t getPreferred() const {
+            return (preferred_);
+        }
+
+        /// @brief Returns the optional valid lifetime.
+        ///
+        /// @return the valid lifetime (0 if not set)
+        uint32_t getValid() const {
+            return (valid_);
+        }
+
+        /// @brief Compares two @c AllocEngine::Resource objects for equality.
+        ///
+        /// @param other object to be compared with this object
+        /// @return true if objects are equal, false otherwise.
+        bool equals(const Resource& other) const {
+            return (address_ == other.address_ &&
+                    prefix_len_ == other.prefix_len_);
+        }
+
+        /// @brief Equality operator.
+        ///
+        /// @param other object to be compared with this object
+        /// @return true if objects are equal, false otherwise.
+        bool operator==(const Resource& other) const {
+            return (equals(other));
+        }
+
+    protected:
+
+        /// @brief The address or prefix.
+        isc::asiolink::IOAddress address_;
+
+        /// @brief The prefix length (128 for an address).
+        uint8_t prefix_len_;
+
+        /// @brief The preferred lifetime (0 when not set).
+        uint32_t preferred_;
+
+        /// @brief The valid lifetime (0 when not set).
+        uint32_t valid_;
+    };
+
+    /// @brief Resource compare class.
+    ///
+    /// Needed for using sets of Resource objets.
+    struct ResourceCompare {
+        /// @brief Compare operator
+        ///
+        /// @note Only the address/prefix part of resources is used.
+        /// @param lhr Left hand resource objet
+        /// @param rhr Right hand resource objet
+        /// @return true if lhr is less than rhr, false otherwise
+        bool operator() (const Resource& lhr, const Resource& rhr) const {
+            if (lhr.getAddress() == rhr.getAddress()) {
+                return (lhr.getPrefixLength() < rhr.getPrefixLength());
+            } else {
+                return (lhr.getAddress() < rhr.getAddress());
+            }
+        }
+    };
 
     /// @brief Container for client's hints.
-    typedef std::vector<ResourceType> HintContainer;
+    typedef std::vector<Resource> HintContainer;
 
     /// @brief Container holding allocated prefixes or addresses.
-    typedef std::set<ResourceType> ResourceContainer;
+    typedef std::set<Resource, ResourceCompare> ResourceContainer;
 
     /// @brief A tuple holding host identifier type and value.
     typedef std::pair<Host::IdentifierType, std::vector<uint8_t> > IdentifierPair;
@@ -428,8 +537,22 @@ public:
             ///
             /// @param prefix Prefix or address.
             /// @param prefix_len Prefix length. Default is 128 for addresses.
+            /// @param preferred Wanted preferred lifetime. Default 0.
+            /// @param valid Wanted valid lifetime. Default 0.
             void addHint(const asiolink::IOAddress& prefix,
-                         const uint8_t prefix_len = 128);
+                         const uint8_t prefix_len = 128,
+                         const uint32_t preferred = 0,
+                         const uint32_t valid = 0);
+
+            /// @brief Convenience method adding new hint from IAADDR option.
+            ///
+            /// @param iaaddr Pointer to IAADDR.
+            void addHint(const Option6IAAddrPtr& iaaddr);
+
+            /// @brief Convenience method adding new hint from IAPREFIX option.
+            ///
+            /// @param iaprefix Pointer to IAPREFIX.
+            void addHint(const Option6IAPrefixPtr& iaprefix);
         };
 
         /// @brief Container holding IA specific contexts.
index 39ef215470d532c6d2d9bd5c413630c606a5a929..eb68eaca0285b5704fcda2d971cae591e3f87f91 100644 (file)
@@ -28,8 +28,8 @@ TEST(ClientContext6Test, addHint) {
    ctx.currentIA().addHint(IOAddress("3000:1::"), 64);
 
    ASSERT_EQ(2, ctx.currentIA().hints_.size());
-   EXPECT_EQ("2001:db8:1::1", ctx.currentIA().hints_[0].first.toText());
-   EXPECT_EQ("3000:1::", ctx.currentIA().hints_[1].first.toText());
+   EXPECT_EQ("2001:db8:1::1", ctx.currentIA().hints_[0].getAddress().toText());
+   EXPECT_EQ("3000:1::", ctx.currentIA().hints_[1].getAddress().toText());
 }
 
 // Test convenience method adding allocated prefixes and addresses to
@@ -1031,7 +1031,7 @@ TEST_F(AllocEngine6Test, renewExtendLeaseLifetime) {
 
     // This is what the client will send in his renew message.
     AllocEngine::HintContainer hints;
-    hints.push_back(make_pair(IOAddress("2001:db8:1::15"), 128));
+    hints.push_back(AllocEngine::Resource(IOAddress("2001:db8:1::15"), 128));
 
     // Client should receive a lease.
     Lease6Collection renewed = renewTest(engine, pool_, hints, true);
@@ -1064,7 +1064,7 @@ TEST_F(AllocEngine6Test, renewExtendLeaseLifetimeForReservation) {
 
     // This is what the client will send in his renew message.
     AllocEngine::HintContainer hints;
-    hints.push_back(make_pair(IOAddress("2001:db8:1::15"), 128));
+    hints.push_back(AllocEngine::Resource(IOAddress("2001:db8:1::15"), 128));
 
     // Client should receive a lease.
     Lease6Collection renewed = renewTest(engine, pool_, hints, true);
@@ -1667,7 +1667,7 @@ TEST_F(AllocEngine6Test, addressRenewal) {
 
     // This is what the client will send in his renew message.
     AllocEngine::HintContainer hints;
-    hints.push_back(make_pair(leases[0]->addr_, 128));
+    hints.push_back(AllocEngine::Resource(leases[0]->addr_, 128));
 
     Lease6Collection renewed = renewTest(engine, pool_, hints, true);
     ASSERT_EQ(1, renewed.size());
@@ -1707,7 +1707,7 @@ TEST_F(AllocEngine6Test, reservedAddressRenewal) {
 
     // This is what the client will send in his renew message.
     AllocEngine::HintContainer hints;
-    hints.push_back(make_pair(leases[0]->addr_, 128));
+    hints.push_back(AllocEngine::Resource(leases[0]->addr_, 128));
 
     Lease6Collection renewed = renewTest(engine, pool_, hints, true);
     ASSERT_EQ(1, renewed.size());
@@ -1846,7 +1846,7 @@ TEST_F(AllocEngine6Test, reservedAddressRenewChange) {
 
     // This is what the client will send in his renew message.
     AllocEngine::HintContainer hints;
-    hints.push_back(make_pair(leases[0]->addr_, 128));
+    hints.push_back(AllocEngine::Resource(leases[0]->addr_, 128));
 
     // Create reservation for the client. This is in-pool reservation,
     // as the pool is 2001:db8:1::10 - 2001:db8:1::20.
@@ -1870,7 +1870,7 @@ TEST_F(AllocEngine6Test, reservedAddressRenewReserved) {
 
     // This is what the client will send in his renew message.
     AllocEngine::HintContainer hints;
-    hints.push_back(make_pair(leases[0]->addr_, 128));
+    hints.push_back(AllocEngine::Resource(leases[0]->addr_, 128));
 
     // Create reservation for this address, but for another client.
     // This is in-pool reservation, as the pool is 2001:db8:1::10 - 2001:db8:1::20.
@@ -2453,7 +2453,7 @@ TEST_F(SharedNetworkAlloc6Test, solicitSharedNetworkOutOfAddresses) {
     // Now, try requesting this address by providing a hint. The engine
     // should try to honor the hint even though we start from the subnet2.
     ctx.subnet_ = subnet2_;
-    ctx.currentIA().hints_.push_back(make_pair(IOAddress("2001:db8:1::1"), 128));
+    ctx.currentIA().addHint(IOAddress("2001:db8:1::1"));
     ASSERT_NO_THROW(lease2 = expectOneLease(engine_.allocateLeases6(ctx)));
     ASSERT_TRUE(lease2);
     ASSERT_TRUE(subnet1_->inRange(lease2->addr_));
@@ -2830,7 +2830,7 @@ TEST_F(AllocEngine6Test, globalHostDynamicAddress) {
 
     // This is what the client will send in his renew message.
     AllocEngine::HintContainer hints;
-    hints.push_back(make_pair(IOAddress("2001:db8:1::10"), 128));
+    hints.push_back(AllocEngine::Resource(IOAddress("2001:db8:1::10"), 128));
 
     // Set test fixture hostname_ to the expected value. This gets checked in
     // renewTest.
@@ -2893,7 +2893,7 @@ TEST_F(AllocEngine6Test, globalHostReservedAddress) {
 
     // This is what the client will send in his renew message.
     AllocEngine::HintContainer hints;
-    hints.push_back(make_pair(IOAddress("3001::1"), 128));
+    hints.push_back(AllocEngine::Resource(IOAddress("3001::1"), 128));
 
     // Set test fixture hostname_ to the expected value. This gets checked in
     // renewTest.
@@ -2957,7 +2957,7 @@ TEST_F(AllocEngine6Test, globalHostReservedPrefix) {
 
     // This is what the client will send in his renew message.
     AllocEngine::HintContainer hints;
-    hints.push_back(make_pair(IOAddress("3001::"), 64));
+    hints.push_back(AllocEngine::Resource(IOAddress("3001::"), 64));
 
     // Set test fixture hostname_ to the expected value. This gets checked via
     // renewTest.
index ab44236f12b9964632890ebad9440ccfe8da169a..1519163b236c26279871c805f23190bc653d928d 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright (C) 2015-2018 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2015-2019 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
@@ -1422,7 +1422,7 @@ ExpirationAllocEngine6Test::testReclaimReusedLeases(const uint16_t msg_type,
                                         msg_type == DHCPV6_SOLICIT,
                                         Pkt6Ptr(new Pkt6(msg_type, 0x1234)));
         ctx.currentIA().iaid_ = 1;
-        ctx.currentIA().hints_.push_back(std::make_pair(leases_[i]->addr_, 128));
+        ctx.currentIA().addHint(leases_[i]->addr_);
 
         // Depending on the message type, we will call a different function.
         if (msg_type == DHCPV6_RENEW) {