BIND 10 master, updated. 37af28303d1cd61f675faea969cd1159df65bf9d [master] Merge branch 'trac3083'

BIND 10 source code commits bind10-changes at lists.isc.org
Tue Aug 27 15:57:54 UTC 2013


The branch, master has been updated
       via  37af28303d1cd61f675faea969cd1159df65bf9d (commit)
       via  8c203f0a835b8b5a4f6e40603ed2c7ff6ed86706 (commit)
       via  21b9e729efc4ba70e36c69cb223f61d0fb0f81a9 (commit)
       via  9fab3d3a0124810b18c32b181b90da2737cae477 (commit)
       via  18dc9853c008b26940ea70167daec3a26b382a79 (commit)
       via  231fed6c34f32ce87f15be0f79bcc258f900a783 (commit)
       via  bf6d6bcddd460b7fa2c77314bccb4e14ab856609 (commit)
       via  3bc0e24e4d1692c73124fe9727141cc2552e5aa3 (commit)
      from  0607a3acafcb7561b95577a56474d83b9c2da2c8 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
commit 37af28303d1cd61f675faea969cd1159df65bf9d
Merge: 0607a3a 8c203f0
Author: Marcin Siodelski <marcin at isc.org>
Date:   Tue Aug 27 17:43:40 2013 +0200

    [master] Merge branch 'trac3083'

-----------------------------------------------------------------------

Summary of changes:
 src/bin/dhcp4/dhcp4_srv.cc                     |    8 +-
 src/lib/dhcpsrv/alloc_engine.cc                |   73 +++++++++---
 src/lib/dhcpsrv/alloc_engine.h                 |  132 +++++++++++++++------
 src/lib/dhcpsrv/lease_mgr.cc                   |   46 ++++++++
 src/lib/dhcpsrv/lease_mgr.h                    |   12 +-
 src/lib/dhcpsrv/memfile_lease_mgr.cc           |   27 +++--
 src/lib/dhcpsrv/memfile_lease_mgr.h            |   35 ++++--
 src/lib/dhcpsrv/tests/alloc_engine_unittest.cc |  151 ++++++++++++++++++------
 src/lib/dhcpsrv/tests/lease_mgr_unittest.cc    |   71 ++++++++++-
 src/lib/dhcpsrv/tests/test_utils.cc            |    6 +
 10 files changed, 455 insertions(+), 106 deletions(-)

-----------------------------------------------------------------------
diff --git a/src/bin/dhcp4/dhcp4_srv.cc b/src/bin/dhcp4/dhcp4_srv.cc
index d47b820..bf4f76b 100644
--- a/src/bin/dhcp4/dhcp4_srv.cc
+++ b/src/bin/dhcp4/dhcp4_srv.cc
@@ -715,9 +715,13 @@ Dhcpv4Srv::assignLease(const Pkt4Ptr& question, Pkt4Ptr& answer) {
     // will try to honour the hint, but it is just a hint - some other address
     // may be used instead. If fake_allocation is set to false, the lease will
     // be inserted into the LeaseMgr as well.
+    // @todo pass the actual FQDN data.
+    Lease4Ptr old_lease;
     Lease4Ptr lease = alloc_engine_->allocateAddress4(subnet, client_id, hwaddr,
-                                                      hint, fake_allocation,
-                                                      callout_handle);
+                                                      hint, false, false, "",
+                                                      fake_allocation,
+                                                      callout_handle,
+                                                      old_lease);
 
     if (lease) {
         // We have a lease! Let's set it in the packet and send it back to
diff --git a/src/lib/dhcpsrv/alloc_engine.cc b/src/lib/dhcpsrv/alloc_engine.cc
index 8c86cfc..2bef8f8 100644
--- a/src/lib/dhcpsrv/alloc_engine.cc
+++ b/src/lib/dhcpsrv/alloc_engine.cc
@@ -93,7 +93,7 @@ AllocEngine::IterativeAllocator::pickAddress(const SubnetPtr& subnet,
 
     // Let's get the last allocated address. It is usually set correctly,
     // but there are times when it won't be (like after removing a pool or
-    // perhaps restaring the server).
+    // perhaps restarting the server).
     IOAddress last = subnet->getLastAllocated();
 
     const PoolCollection& pools = subnet->getPools();
@@ -140,7 +140,7 @@ AllocEngine::IterativeAllocator::pickAddress(const SubnetPtr& subnet,
         return (next);
     }
 
-    // there is a next pool, let's try first adddress from it
+    // there is a next pool, let's try first address from it
     next = (*it)->getFirstAddress();
     subnet->setLastAllocated(next);
     return (next);
@@ -330,8 +330,17 @@ AllocEngine::allocateAddress4(const SubnetPtr& subnet,
                               const ClientIdPtr& clientid,
                               const HWAddrPtr& hwaddr,
                               const IOAddress& hint,
+                              const bool fwd_dns_update,
+                              const bool rev_dns_update,
+                              const std::string& hostname,
                               bool fake_allocation,
-                              const isc::hooks::CalloutHandlePtr& callout_handle) {
+                              const isc::hooks::CalloutHandlePtr& callout_handle,
+                              Lease4Ptr& old_lease) {
+
+    // The NULL pointer indicates that the old lease didn't exist. It may
+    // be later set to non NULL value if existing lease is found in the
+    // database.
+    old_lease.reset();
 
     try {
         // Allocator is always created in AllocEngine constructor and there is
@@ -351,10 +360,13 @@ AllocEngine::allocateAddress4(const SubnetPtr& subnet,
         // Check if there's existing lease for that subnet/clientid/hwaddr combination.
         Lease4Ptr existing = LeaseMgrFactory::instance().getLease4(*hwaddr, subnet->getID());
         if (existing) {
+            // Save the old lease, before renewal.
+            old_lease.reset(new Lease4(*existing));
             // We have a lease already. This is a returning client, probably after
             // its reboot.
-            existing = renewLease4(subnet, clientid, hwaddr, existing, callout_handle,
-                                   fake_allocation);
+            existing = renewLease4(subnet, clientid, hwaddr,
+                                   fwd_dns_update, rev_dns_update, hostname,
+                                   existing, callout_handle, fake_allocation);
             if (existing) {
                 return (existing);
             }
@@ -366,9 +378,13 @@ AllocEngine::allocateAddress4(const SubnetPtr& subnet,
         if (clientid) {
             existing = LeaseMgrFactory::instance().getLease4(*clientid, subnet->getID());
             if (existing) {
+                // Save the old lease before renewal.
+                old_lease.reset(new Lease4(*existing));
                 // we have a lease already. This is a returning client, probably after
                 // its reboot.
-                existing = renewLease4(subnet, clientid, hwaddr, existing, callout_handle,
+                existing = renewLease4(subnet, clientid, hwaddr,
+                                       fwd_dns_update, rev_dns_update,
+                                       hostname, existing, callout_handle,
                                        fake_allocation);
                 // @todo: produce a warning. We haven't found him using MAC address, but
                 // we found him using client-id
@@ -387,7 +403,9 @@ AllocEngine::allocateAddress4(const SubnetPtr& subnet,
 
                 // The hint is valid and not currently used, let's create a lease for it
                 Lease4Ptr lease = createLease4(subnet, clientid, hwaddr, hint,
-                                               callout_handle, fake_allocation);
+                                               fwd_dns_update, rev_dns_update,
+                                               hostname, callout_handle,
+                                               fake_allocation);
 
                 // It can happen that the lease allocation failed (we could have lost
                 // the race condition. That means that the hint is lo longer usable and
@@ -397,8 +415,12 @@ AllocEngine::allocateAddress4(const SubnetPtr& subnet,
                 }
             } else {
                 if (existing->expired()) {
+                    // Save the old lease, before reusing it.
+                    old_lease.reset(new Lease4(*existing));
                     return (reuseExpiredLease(existing, subnet, clientid, hwaddr,
-                                              callout_handle, fake_allocation));
+                                              fwd_dns_update, rev_dns_update,
+                                              hostname, callout_handle,
+                                              fake_allocation));
                 }
 
             }
@@ -431,7 +453,9 @@ AllocEngine::allocateAddress4(const SubnetPtr& subnet,
             if (!existing) {
                 // there's no existing lease for selected candidate, so it is
                 // free. Let's allocate it.
-                Lease4Ptr lease = createLease4(subnet, clientid, hwaddr, candidate,
+                Lease4Ptr lease = createLease4(subnet, clientid, hwaddr,
+                                               candidate, fwd_dns_update,
+                                               rev_dns_update, hostname,
                                                callout_handle, fake_allocation);
                 if (lease) {
                     return (lease);
@@ -442,8 +466,12 @@ AllocEngine::allocateAddress4(const SubnetPtr& subnet,
                 // allocation attempts.
             } else {
                 if (existing->expired()) {
+                    // Save old lease before reusing it.
+                    old_lease.reset(new Lease4(*existing));
                     return (reuseExpiredLease(existing, subnet, clientid, hwaddr,
-                                              callout_handle, fake_allocation));
+                                              fwd_dns_update, rev_dns_update,
+                                              hostname, callout_handle,
+                                              fake_allocation));
                 }
             }
 
@@ -466,6 +494,9 @@ AllocEngine::allocateAddress4(const SubnetPtr& subnet,
 Lease4Ptr AllocEngine::renewLease4(const SubnetPtr& subnet,
                                    const ClientIdPtr& clientid,
                                    const HWAddrPtr& hwaddr,
+                                   const bool fwd_dns_update,
+                                   const bool rev_dns_update,
+                                   const std::string& hostname,
                                    const Lease4Ptr& lease,
                                    const isc::hooks::CalloutHandlePtr& callout_handle,
                                    bool fake_allocation /* = false */) {
@@ -487,6 +518,9 @@ Lease4Ptr AllocEngine::renewLease4(const SubnetPtr& subnet,
     lease->t1_ = subnet->getT1();
     lease->t2_ = subnet->getT2();
     lease->valid_lft_ = subnet->getValid();
+    lease->fqdn_fwd_ = fwd_dns_update;
+    lease->fqdn_rev_ = rev_dns_update;
+    lease->hostname_ = hostname;
 
     bool skip = false;
     // Execute all callouts registered for packet6_send
@@ -615,6 +649,9 @@ Lease4Ptr AllocEngine::reuseExpiredLease(Lease4Ptr& expired,
                                          const SubnetPtr& subnet,
                                          const ClientIdPtr& clientid,
                                          const HWAddrPtr& hwaddr,
+                                         const bool fwd_dns_update,
+                                         const bool rev_dns_update,
+                                         const std::string& hostname,
                                          const isc::hooks::CalloutHandlePtr& callout_handle,
                                          bool fake_allocation /*= false */ ) {
 
@@ -631,9 +668,9 @@ Lease4Ptr AllocEngine::reuseExpiredLease(Lease4Ptr& expired,
     expired->cltt_ = time(NULL);
     expired->subnet_id_ = subnet->getID();
     expired->fixed_ = false;
-    expired->hostname_ = std::string("");
-    expired->fqdn_fwd_ = false;
-    expired->fqdn_rev_ = false;
+    expired->hostname_ = hostname;
+    expired->fqdn_fwd_ = fwd_dns_update;
+    expired->fqdn_rev_ = rev_dns_update;
 
     /// @todo: log here that the lease was reused (there's ticket #2524 for
     /// logging in libdhcpsrv)
@@ -771,6 +808,9 @@ Lease4Ptr AllocEngine::createLease4(const SubnetPtr& subnet,
                                     const DuidPtr& clientid,
                                     const HWAddrPtr& hwaddr,
                                     const IOAddress& addr,
+                                    const bool fwd_dns_update,
+                                    const bool rev_dns_update,
+                                    const std::string& hostname,
                                     const isc::hooks::CalloutHandlePtr& callout_handle,
                                     bool fake_allocation /*= false */ ) {
     if (!hwaddr) {
@@ -789,6 +829,11 @@ Lease4Ptr AllocEngine::createLease4(const SubnetPtr& subnet,
                                subnet->getT1(), subnet->getT2(), now,
                                subnet->getID()));
 
+    // Set FQDN specific lease parameters.
+    lease->fqdn_fwd_ = fwd_dns_update;
+    lease->fqdn_rev_ = rev_dns_update;
+    lease->hostname_ = hostname;
+
     // Let's execute all callouts registered for lease4_select
     if (callout_handle &&
         HooksManager::getHooksManager().calloutsPresent(hook_index_lease4_select_)) {
@@ -827,8 +872,6 @@ Lease4Ptr AllocEngine::createLease4(const SubnetPtr& subnet,
         callout_handle->getArgument("lease4", lease);
     }
 
-
-
     if (!fake_allocation) {
         // That is a real (REQUEST) allocation
         bool status = LeaseMgrFactory::instance().addLease(lease);
diff --git a/src/lib/dhcpsrv/alloc_engine.h b/src/lib/dhcpsrv/alloc_engine.h
index 6c662bf..ad18b83 100644
--- a/src/lib/dhcpsrv/alloc_engine.h
+++ b/src/lib/dhcpsrv/alloc_engine.h
@@ -182,28 +182,63 @@ protected:
     ///        we give up (0 means unlimited)
     AllocEngine(AllocType engine_type, unsigned int attempts);
 
-    /// @brief Allocates an IPv4 lease
+    /// @brief Returns IPv4 lease.
     ///
-    /// This method uses currently selected allocator to pick an address from
-    /// specified subnet, creates a lease for that address and then inserts
-    /// it into LeaseMgr (if this allocation is not fake).
+    /// This method finds the appropriate lease for the client using the
+    /// following algorithm:
+    /// - If lease exists for the combination of the HW address, client id and
+    /// subnet, try to renew a lease and return it.
+    /// - If lease exists for the combination of the client id and subnet, try
+    /// to renew the lease and return it.
+    /// - If client supplied an address hint and this address is available,
+    /// allocate the new lease with this address.
+    /// - If client supplied an address hint and the lease for this address
+    /// exists in the database, return this lease if it is expired.
+    /// - Pick new address from the pool and try to allocate it for the client,
+    /// if expired lease exists for the picked address, try to reuse this lease.
+    ///
+    /// When a server should do DNS updates, it is required that allocation
+    /// returns the information how the lease was obtained by the allocation
+    /// engine. In particular, the DHCP server should be able to check whether
+    /// existing lease was returned, or new lease was allocated. When existing
+    /// lease was returned, server should check whether the FQDN has changed
+    /// between the allocation of the old and new lease. If so, server should
+    /// perform appropriate DNS update. If not, server may choose to not
+    /// perform the update. The information about the old lease is returned via
+    /// @c old_lease parameter. If NULL value is returned, it is an indication
+    /// that new lease was allocated for the client. If non-NULL value is
+    /// returned, it is an indication that allocation engine reused/renewed an
+    /// existing lease.
     ///
     /// @param subnet subnet the allocation should come from
     /// @param clientid Client identifier
-    /// @param hwaddr client's hardware address info
-    /// @param hint a hint that the client provided
-    /// @param fake_allocation is this real i.e. REQUEST (false) or just picking
+    /// @param hwaddr Client's hardware address info
+    /// @param hint A hint that the client provided
+    /// @param fwd_dns_update Indicates whether forward DNS update will be
+    ///        performed for the client (true) or not (false).
+    /// @param rev_dns_update Indicates whether reverse DNS update will be
+    ///        performed for the client (true) or not (false).
+    /// @param hostname A string carrying hostname to be used for DNS updates.
+    /// @param fake_allocation Is this real i.e. REQUEST (false) or just picking
     ///        an address for DISCOVER that is not really allocated (true)
-    /// @param callout_handle a callout handle (used in hooks). A lease callouts
+    /// @param callout_handle A callout handle (used in hooks). A lease callouts
     ///        will be executed if this parameter is passed.
+    /// @param [out] old_lease Holds the pointer to a previous instance of a
+    ///        lease. The NULL pointer indicates that lease didn't exist prior
+    ///        to calling this function (e.g. new lease has been allocated).
+    ///
     /// @return Allocated IPv4 lease (or NULL if allocation failed)
     Lease4Ptr
     allocateAddress4(const SubnetPtr& subnet,
                      const ClientIdPtr& clientid,
                      const HWAddrPtr& hwaddr,
                      const isc::asiolink::IOAddress& hint,
+                     const bool fwd_dns_update,
+                     const bool rev_dns_update,
+                     const std::string& hostname,
                      bool fake_allocation,
-                     const isc::hooks::CalloutHandlePtr& callout_handle);
+                     const isc::hooks::CalloutHandlePtr& callout_handle,
+                     Lease4Ptr& old_lease);
 
     /// @brief Renews a IPv4 lease
     ///
@@ -214,18 +249,26 @@ protected:
     /// to get a new lease. It thinks that it gets a new lease, but in fact
     /// we are only renewing the still valid lease for that client.
     ///
-    /// @param subnet subnet the client is attached to
-    /// @param clientid client identifier
-    /// @param hwaddr client's hardware address
-    /// @param lease lease to be renewed
+    /// @param subnet A subnet the client is attached to
+    /// @param clientid Client identifier
+    /// @param hwaddr Client's hardware address
+    /// @param fwd_dns_update Indicates whether forward DNS update will be
+    ///        performed for the client (true) or not (false).
+    /// @param rev_dns_update Indicates whether reverse DNS update will be
+    ///        performed for the client (true) or not (false).
+    /// @param hostname A string carrying hostname to be used for DNS updates.
+    /// @param lease A lease to be renewed
     /// @param callout_handle a callout handle (used in hooks). A lease callouts
     ///        will be executed if this parameter is passed.
-    /// @param fake_allocation is this real i.e. REQUEST (false) or just picking
+    /// @param fake_allocation Is this real i.e. REQUEST (false) or just picking
     ///        an address for DISCOVER that is not really allocated (true)
     Lease4Ptr
     renewLease4(const SubnetPtr& subnet,
                 const ClientIdPtr& clientid,
                 const HWAddrPtr& hwaddr,
+                const bool fwd_dns_update,
+                const bool rev_dns_update,
+                const std::string& hostname,
                 const Lease4Ptr& lease,
                 const isc::hooks::CalloutHandlePtr& callout_handle,
                 bool fake_allocation /* = false */);
@@ -241,9 +284,11 @@ protected:
     /// @param iaid iaid field from the IA_NA container that client sent
     /// @param hint a hint that the client provided
     /// @param fwd_dns_update A boolean value which indicates that server takes
-    /// responisibility for the forward DNS Update for this lease (if true).
+    ///        responsibility for the forward DNS Update for this lease
+    ///        (if true).
     /// @param rev_dns_update A boolean value which indicates that server takes
-    /// responibility for the reverse DNS Update for this lease (if true).
+    ///        responsibility for the reverse DNS Update for this lease
+    ///        (if true).
     /// @param hostname A fully qualified domain-name of the client.
     /// @param fake_allocation is this real i.e. REQUEST (false) or just picking
     ///        an address for SOLICIT that is not really allocated (true)
@@ -272,20 +317,28 @@ private:
     /// into the database. That may fail in some cases, e.g. when there is another
     /// allocation process and we lost a race to a specific lease.
     ///
-    /// @param subnet subnet the lease is allocated from
-    /// @param clientid client identifier
-    /// @param hwaddr client's hardware address
-    /// @param addr an address that was selected and is confirmed to be available
+    /// @param subnet Subnet the lease is allocated from
+    /// @param clientid Client identifier
+    /// @param hwaddr Client's hardware address
+    /// @param addr An address that was selected and is confirmed to be available
+    /// @param fwd_dns_update Indicates whether forward DNS update will be
+    ///        performed for the client (true) or not (false).
+    /// @param rev_dns_update Indicates whether reverse DNS update will be
+    ///        performed for the client (true) or not (false).
+    /// @param hostname A string carrying hostname to be used for DNS updates.
     /// @param callout_handle a callout handle (used in hooks). A lease callouts
     ///        will be executed if this parameter is passed (and there are callouts
     ///        registered)
-    /// @param fake_allocation is this real i.e. REQUEST (false) or just picking
+    /// @param fake_allocation Is this real i.e. REQUEST (false) or just picking
     ///        an address for DISCOVER that is not really allocated (true)
     /// @return allocated lease (or NULL in the unlikely case of the lease just
     ///        becomed unavailable)
     Lease4Ptr createLease4(const SubnetPtr& subnet, const DuidPtr& clientid,
                            const HWAddrPtr& hwaddr,
                            const isc::asiolink::IOAddress& addr,
+                           const bool fwd_dns_update,
+                           const bool rev_dns_update,
+                           const std::string& hostname,
                            const isc::hooks::CalloutHandlePtr& callout_handle,
                            bool fake_allocation = false);
 
@@ -301,9 +354,11 @@ private:
     /// @param addr an address that was selected and is confirmed to be
     /// available
     /// @param fwd_dns_update A boolean value which indicates that server takes
-    /// responisibility for the forward DNS Update for this lease (if true).
+    ///        responsibility for the forward DNS Update for this lease
+    ///        (if true).
     /// @param rev_dns_update A boolean value which indicates that server takes
-    /// responibility for the reverse DNS Update for this lease (if true).
+    ///        responsibility for the reverse DNS Update for this lease
+    ///        (if true).
     /// @param hostname A fully qualified domain-name of the client.
     /// @param callout_handle a callout handle (used in hooks). A lease callouts
     ///        will be executed if this parameter is passed (and there are callouts
@@ -311,7 +366,7 @@ private:
     /// @param fake_allocation is this real i.e. REQUEST (false) or just picking
     ///        an address for SOLICIT that is not really allocated (true)
     /// @return allocated lease (or NULL in the unlikely case of the lease just
-    ///        becomed unavailable)
+    ///         became unavailable)
     Lease6Ptr createLease6(const Subnet6Ptr& subnet, const DuidPtr& duid,
                            uint32_t iaid, const isc::asiolink::IOAddress& addr,
                            const bool fwd_dns_update, const bool rev_dns_update,
@@ -325,19 +380,28 @@ private:
     /// is updated if this is real (i.e. REQUEST, fake_allocation = false), not
     /// dummy allocation request (i.e. DISCOVER, fake_allocation = true).
     ///
-    /// @param expired old, expired lease
-    /// @param subnet subnet the lease is allocated from
-    /// @param clientid client identifier
-    /// @param hwaddr client's hardware address
-    /// @param callout_handle a callout handle (used in hooks). A lease callouts
+    /// @param expired Old, expired lease
+    /// @param subnet Subnet the lease is allocated from
+    /// @param clientid Client identifier
+    /// @param hwaddr Client's hardware address
+    /// @param fwd_dns_update Indicates whether forward DNS update will be
+    ///        performed for the client (true) or not (false).
+    /// @param rev_dns_update Indicates whether reverse DNS update will be
+    ///        performed for the client (true) or not (false).
+    /// @param hostname A string carrying hostname to be used for DNS updates.
+    /// @param callout_handle A callout handle (used in hooks). A lease callouts
     ///        will be executed if this parameter is passed.
-    /// @param fake_allocation is this real i.e. REQUEST (false) or just picking
+    /// @param fake_allocation Is this real i.e. REQUEST (false) or just picking
     ///        an address for DISCOVER that is not really allocated (true)
     /// @return refreshed lease
     /// @throw BadValue if trying to recycle lease that is still valid
-    Lease4Ptr reuseExpiredLease(Lease4Ptr& expired, const SubnetPtr& subnet,
+    Lease4Ptr reuseExpiredLease(Lease4Ptr& expired,
+                                const SubnetPtr& subnet,
                                 const ClientIdPtr& clientid,
                                 const HWAddrPtr& hwaddr,
+                                const bool fwd_dns_update,
+                                const bool rev_dns_update,
+                                const std::string& hostname,
                                 const isc::hooks::CalloutHandlePtr& callout_handle,
                                 bool fake_allocation = false);
 
@@ -352,9 +416,11 @@ private:
     /// @param duid client's DUID
     /// @param iaid IAID from the IA_NA container the client sent to us
     /// @param fwd_dns_update A boolean value which indicates that server takes
-    /// responisibility for the forward DNS Update for this lease (if true).
+    ///        responsibility for the forward DNS Update for this lease
+    ///        (if true).
     /// @param rev_dns_update A boolean value which indicates that server takes
-    /// responibility for the reverse DNS Update for this lease (if true).
+    ///        responsibility for the reverse DNS Update for this lease
+    ///        (if true).
     /// @param hostname A fully qualified domain-name of the client.
     /// @param callout_handle a callout handle (used in hooks). A lease callouts
     ///        will be executed if this parameter is passed.
diff --git a/src/lib/dhcpsrv/lease_mgr.cc b/src/lib/dhcpsrv/lease_mgr.cc
index 2310dd4..c4810fd 100644
--- a/src/lib/dhcpsrv/lease_mgr.cc
+++ b/src/lib/dhcpsrv/lease_mgr.cc
@@ -38,6 +38,52 @@ Lease::Lease(const isc::asiolink::IOAddress& addr, uint32_t t1, uint32_t t2,
      subnet_id_(subnet_id), fixed_(false), fqdn_fwd_(false), fqdn_rev_(false) {
 }
 
+Lease4::Lease4(const Lease4& other)
+    : Lease(other.addr_, other.t1_, other.t2_, other.valid_lft_,
+            other.subnet_id_, other.cltt_), ext_(other.ext_),
+      hwaddr_(other.hwaddr_) {
+
+    fixed_ = other.fixed_;
+    fqdn_fwd_ = other.fqdn_fwd_;
+    fqdn_rev_ = other.fqdn_rev_;
+    hostname_ = other.hostname_;
+    comments_ = other.comments_;
+
+    if (other.client_id_) {
+        client_id_.reset(new ClientId(other.client_id_->getClientId()));
+
+    } else {
+        client_id_.reset();
+
+    }
+}
+
+Lease4&
+Lease4::operator=(const Lease4& other) {
+    if (this != &other) {
+        addr_ = other.addr_;
+        t1_ = other.t1_;
+        t2_ = other.t2_;
+        valid_lft_ = other.valid_lft_;
+        cltt_ = other.cltt_;
+        subnet_id_ = other.subnet_id_;
+        fixed_ = other.fixed_;
+        hostname_ = other.hostname_;
+        fqdn_fwd_ = other.fqdn_fwd_;
+        fqdn_rev_ = other.fqdn_rev_;
+        comments_ = other.comments_;
+        ext_ = other.ext_;
+        hwaddr_ = other.hwaddr_;
+
+        if (other.client_id_) {
+            client_id_.reset(new ClientId(other.client_id_->getClientId()));
+        } else {
+            client_id_.reset();
+        }
+    }
+    return (*this);
+}
+
 Lease6::Lease6(LeaseType type, const isc::asiolink::IOAddress& addr,
                DuidPtr duid, uint32_t iaid, uint32_t preferred, uint32_t valid,
                uint32_t t1, uint32_t t2, SubnetID subnet_id, uint8_t prefixlen)
diff --git a/src/lib/dhcpsrv/lease_mgr.h b/src/lib/dhcpsrv/lease_mgr.h
index 02e517e..3e0e092 100644
--- a/src/lib/dhcpsrv/lease_mgr.h
+++ b/src/lib/dhcpsrv/lease_mgr.h
@@ -1,4 +1,4 @@
-// Copyright (C) 2012 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2012-2013 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
@@ -259,6 +259,16 @@ struct Lease4 : public Lease {
     Lease4() : Lease(0, 0, 0, 0, 0, 0) {
     }
 
+    /// @brief Copy constructor
+    ///
+    /// @param other the @c Lease4 object to be copied.
+    Lease4(const Lease4& other);
+
+    /// @brief Assignment operator.
+    ///
+    /// @param other the @c Lease4 object to be assigned.
+    Lease4& operator=(const Lease4& other);
+
     /// @brief Compare two leases for equality
     ///
     /// @param other lease6 object with which to compare
diff --git a/src/lib/dhcpsrv/memfile_lease_mgr.cc b/src/lib/dhcpsrv/memfile_lease_mgr.cc
index 713d625..804eef8 100644
--- a/src/lib/dhcpsrv/memfile_lease_mgr.cc
+++ b/src/lib/dhcpsrv/memfile_lease_mgr.cc
@@ -62,7 +62,7 @@ Lease4Ptr Memfile_LeaseMgr::getLease4(const isc::asiolink::IOAddress& addr) cons
     if (l == storage4_.end()) {
         return (Lease4Ptr());
     } else {
-        return (*l);
+        return (Lease4Ptr(new Lease4(**l)));
     }
 }
 
@@ -94,7 +94,7 @@ Lease4Ptr Memfile_LeaseMgr::getLease4(const HWAddr& hwaddr,
     }
 
     // Lease was found. Return it to the caller.
-    return (*lease);
+    return (Lease4Ptr(new Lease4(**lease)));
 }
 
 Lease4Collection Memfile_LeaseMgr::getLease4(const ClientId& clientid) const {
@@ -123,11 +123,11 @@ Lease4Ptr Memfile_LeaseMgr::getLease4(const ClientId& client_id,
         return Lease4Ptr();
     }
     // Lease was found. Return it to the caller.
-    return (*lease);
+    return (Lease4Ptr(new Lease4(**lease)));
 }
 
-Lease6Ptr Memfile_LeaseMgr::getLease6(
-        const isc::asiolink::IOAddress& addr) const {
+Lease6Ptr
+Memfile_LeaseMgr::getLease6(const isc::asiolink::IOAddress& addr) const {
     LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL,
               DHCPSRV_MEMFILE_GET_ADDR6).arg(addr.toText());
 
@@ -135,7 +135,7 @@ Lease6Ptr Memfile_LeaseMgr::getLease6(
     if (l == storage6_.end()) {
         return (Lease6Ptr());
     } else {
-        return (*l);
+        return (Lease6Ptr(new Lease6(**l)));
     }
 }
 
@@ -167,20 +167,31 @@ Lease6Ptr Memfile_LeaseMgr::getLease6(const DUID& duid, uint32_t iaid,
         return (Lease6Ptr());
     }
     // Lease was found, return it to the caller.
-    return (*lease);
+    return (Lease6Ptr(new Lease6(**lease)));
 }
 
 void Memfile_LeaseMgr::updateLease4(const Lease4Ptr& lease) {
     LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL,
               DHCPSRV_MEMFILE_UPDATE_ADDR4).arg(lease->addr_.toText());
 
+    Lease4Storage::iterator lease_it = storage4_.find(lease->addr_);
+    if (lease_it == storage4_.end()) {
+        isc_throw(NoSuchLease, "failed to update the lease with address "
+                  << lease->addr_.toText() << " - no such lease");
+    }
+    **lease_it = *lease;
 }
 
 void Memfile_LeaseMgr::updateLease6(const Lease6Ptr& lease) {
     LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL,
               DHCPSRV_MEMFILE_UPDATE_ADDR6).arg(lease->addr_.toText());
 
-
+    Lease6Storage::iterator lease_it = storage6_.find(lease->addr_);
+    if (lease_it == storage6_.end()) {
+        isc_throw(NoSuchLease, "failed to update the lease with address "
+                  << lease->addr_.toText() << " - no such lease");
+    }
+    **lease_it = *lease;
 }
 
 bool Memfile_LeaseMgr::deleteLease(const isc::asiolink::IOAddress& addr) {
diff --git a/src/lib/dhcpsrv/memfile_lease_mgr.h b/src/lib/dhcpsrv/memfile_lease_mgr.h
index 4ac7536..2f75a98 100644
--- a/src/lib/dhcpsrv/memfile_lease_mgr.h
+++ b/src/lib/dhcpsrv/memfile_lease_mgr.h
@@ -65,8 +65,10 @@ public:
 
     /// @brief Returns existing IPv4 lease for specified IPv4 address.
     ///
-    /// @todo Not implemented yet
-    /// @param addr address of the searched lease
+    /// This function returns a copy of the lease. The modification in the
+    /// return lease does not affect the instance held in the lease storage.
+    ///
+    /// @param addr An address of the searched lease.
     ///
     /// @return a collection of leases
     virtual Lease4Ptr getLease4(const isc::asiolink::IOAddress& addr) const;
@@ -85,10 +87,11 @@ public:
     /// @return lease collection
     virtual Lease4Collection getLease4(const isc::dhcp::HWAddr& hwaddr) const;
 
-    /// @brief Returns existing IPv4 leases for specified hardware address
+    /// @brief Returns existing IPv4 lease for specified hardware address
     ///        and a subnet
     ///
-    /// @todo Not implemented yet
+    /// This function returns a copy of the lease. The modification in the
+    /// return lease does not affect the instance held in the lease storage.
     ///
     /// There can be at most one lease for a given HW address in a single
     /// pool, so this method with either return a single lease or NULL.
@@ -109,11 +112,12 @@ public:
 
     /// @brief Returns existing IPv4 lease for specified client-id
     ///
+    /// This function returns a copy of the lease. The modification in the
+    /// return lease does not affect the instance held in the lease storage.
+    ///
     /// There can be at most one lease for a given HW address in a single
     /// pool, so this method with either return a single lease or NULL.
     ///
-    /// @todo Not implemented yet
-    ///
     /// @param clientid client identifier
     /// @param subnet_id identifier of the subnet that lease must belong to
     ///
@@ -123,7 +127,10 @@ public:
 
     /// @brief Returns existing IPv6 lease for a given IPv6 address.
     ///
-    /// @param addr address of the searched lease
+    /// This function returns a copy of the lease. The modification in the
+    /// return lease does not affect the instance held in the lease storage.
+    ///
+    /// @param addr An address of the searched lease.
     ///
     /// @return smart pointer to the lease (or NULL if a lease is not found)
     virtual Lease6Ptr getLease6(const isc::asiolink::IOAddress& addr) const;
@@ -140,27 +147,31 @@ public:
 
     /// @brief Returns existing IPv6 lease for a given DUID+IA combination
     ///
-    /// @todo Not implemented yet
+    /// This function returns a copy of the lease. The modification in the
+    /// return lease does not affect the instance held in the lease storage.
     ///
     /// @param duid client DUID
     /// @param iaid IA identifier
     /// @param subnet_id identifier of the subnet the lease must belong to
     ///
     /// @return smart pointer to the lease (or NULL if a lease is not found)
-    virtual Lease6Ptr getLease6(const DUID& duid, uint32_t iaid, SubnetID subnet_id) const;
+    virtual Lease6Ptr getLease6(const DUID& duid, uint32_t iaid,
+                                SubnetID subnet_id) const;
 
     /// @brief Updates IPv4 lease.
     ///
-    /// @todo Not implemented yet
+    /// @warning This function does not validate the pointer to the lease.
+    /// It is caller's responsibility to pass the valid pointer.
     ///
     /// @param lease4 The lease to be updated.
     ///
     /// If no such lease is present, an exception will be thrown.
     virtual void updateLease4(const Lease4Ptr& lease4);
 
-    /// @brief Updates IPv4 lease.
+    /// @brief Updates IPv6 lease.
     ///
-    /// @todo Not implemented yet
+    /// @warning This function does not validate the pointer to the lease.
+    /// It is caller's responsibility to pass the valid pointer.
     ///
     /// @param lease6 The lease to be updated.
     ///
diff --git a/src/lib/dhcpsrv/tests/alloc_engine_unittest.cc b/src/lib/dhcpsrv/tests/alloc_engine_unittest.cc
index 2da09c7..083c20f 100644
--- a/src/lib/dhcpsrv/tests/alloc_engine_unittest.cc
+++ b/src/lib/dhcpsrv/tests/alloc_engine_unittest.cc
@@ -164,8 +164,6 @@ public:
         EXPECT_EQ(subnet_->getValid(), lease->valid_lft_);
         EXPECT_EQ(subnet_->getT1(), lease->t1_);
         EXPECT_EQ(subnet_->getT2(), lease->t2_);
-        EXPECT_TRUE(false == lease->fqdn_fwd_);
-        EXPECT_TRUE(false == lease->fqdn_rev_);
         if (lease->client_id_ && !clientid_) {
             ADD_FAILURE() << "Lease4 has a client-id, while it should have none.";
         } else
@@ -188,6 +186,7 @@ public:
     Subnet4Ptr subnet_;       ///< Subnet4 (used in tests)
     Pool4Ptr pool_;           ///< Pool belonging to subnet_
     LeaseMgrFactory factory_; ///< Pointer to LeaseMgr factory
+    Lease4Ptr old_lease_;     ///< Holds previous instance of the lease.
 };
 
 // This test checks if the Allocation Engine can be instantiated and that it
@@ -612,8 +611,13 @@ TEST_F(AllocEngine4Test, simpleAlloc4) {
     ASSERT_TRUE(engine);
 
     Lease4Ptr lease = engine->allocateAddress4(subnet_, clientid_, hwaddr_,
-                                               IOAddress("0.0.0.0"), false,
-                                               CalloutHandlePtr());
+                                               IOAddress("0.0.0.0"),
+                                               false, true,
+                                               "somehost.example.com.",
+                                               false, CalloutHandlePtr(),
+                                               old_lease_);
+    // The new lease has been allocated, so the old lease should not exist.
+    EXPECT_FALSE(old_lease_);
 
     // Check that we got a lease
     ASSERT_TRUE(lease);
@@ -636,8 +640,13 @@ TEST_F(AllocEngine4Test, fakeAlloc4) {
     ASSERT_TRUE(engine);
 
     Lease4Ptr lease = engine->allocateAddress4(subnet_, clientid_, hwaddr_,
-                                               IOAddress("0.0.0.0"), true,
-                                               CalloutHandlePtr());
+                                               IOAddress("0.0.0.0"),
+                                               false, true, "host.example.com.",
+                                               true, CalloutHandlePtr(),
+                                               old_lease_);
+
+    // The new lease has been allocated, so the old lease should not exist.
+    EXPECT_FALSE(old_lease_);
 
     // Check that we got a lease
     ASSERT_TRUE(lease);
@@ -660,11 +669,15 @@ TEST_F(AllocEngine4Test, allocWithValidHint4) {
 
     Lease4Ptr lease = engine->allocateAddress4(subnet_, clientid_, hwaddr_,
                                                IOAddress("192.0.2.105"),
-                                               false, CalloutHandlePtr());
-
+                                               true, true, "host.example.com.",
+                                               false, CalloutHandlePtr(),
+                                               old_lease_);
     // Check that we got a lease
     ASSERT_TRUE(lease);
 
+    // We have allocated the new lease, so the old lease should not exist.
+    EXPECT_FALSE(old_lease_);
+
     // We should get what we asked for
     EXPECT_EQ(lease->addr_.toText(), "192.0.2.105");
 
@@ -700,7 +713,13 @@ TEST_F(AllocEngine4Test, allocWithUsedHint4) {
     // twice.
     Lease4Ptr lease = engine->allocateAddress4(subnet_, clientid_, hwaddr_,
                                                IOAddress("192.0.2.106"),
-                                               false, CalloutHandlePtr());
+                                               false, false, "",
+                                               false, CalloutHandlePtr(),
+                                               old_lease_);
+
+    // New lease has been allocated, so the old lease should not exist.
+    EXPECT_FALSE(old_lease_);
+
     // Check that we got a lease
     ASSERT_TRUE(lease);
 
@@ -734,10 +753,15 @@ TEST_F(AllocEngine4Test, allocBogusHint4) {
     // with the normal allocation
     Lease4Ptr lease = engine->allocateAddress4(subnet_, clientid_, hwaddr_,
                                                IOAddress("10.1.1.1"),
-                                               false, CalloutHandlePtr());
+                                               false, false, "",
+                                               false, CalloutHandlePtr(),
+                                               old_lease_);
     // Check that we got a lease
     ASSERT_TRUE(lease);
 
+    // We have allocated a new lease, so the old lease should not exist.
+    EXPECT_FALSE(old_lease_);
+
     // We should NOT get what we asked for, because it is used already
     EXPECT_TRUE(lease->addr_.toText() != "10.1.1.1");
 
@@ -761,21 +785,32 @@ TEST_F(AllocEngine4Test, allocateAddress4Nulls) {
 
     // Allocations without subnet are not allowed
     Lease4Ptr lease = engine->allocateAddress4(SubnetPtr(), clientid_, hwaddr_,
-                                               IOAddress("0.0.0.0"), false,
-                                               CalloutHandlePtr());
+                                               IOAddress("0.0.0.0"),
+                                               false, false, "",
+                                               false, CalloutHandlePtr(),
+                                               old_lease_);
     EXPECT_FALSE(lease);
 
     // Allocations without HW address are not allowed
     lease = engine->allocateAddress4(subnet_, clientid_, HWAddrPtr(),
-                                     IOAddress("0.0.0.0"), false, CalloutHandlePtr());
+                                     IOAddress("0.0.0.0"),
+                                     false, false, "",
+                                     false, CalloutHandlePtr(),
+                                     old_lease_);
     EXPECT_FALSE(lease);
+    EXPECT_FALSE(old_lease_);
 
     // Allocations without client-id are allowed
     clientid_ = ClientIdPtr();
     lease = engine->allocateAddress4(subnet_, ClientIdPtr(), hwaddr_,
-                                     IOAddress("0.0.0.0"), false, CalloutHandlePtr());
+                                     IOAddress("0.0.0.0"),
+                                     true, true, "myhost.example.com.",
+                                     false, CalloutHandlePtr(),
+                                     old_lease_);
     // Check that we got a lease
     ASSERT_TRUE(lease);
+    // New lease has been allocated, so the old lease should not exist.
+    EXPECT_FALSE(old_lease_);
 
     // Do all checks on the lease
     checkLease4(lease);
@@ -876,12 +911,18 @@ TEST_F(AllocEngine4Test, smallPool4) {
     subnet_->addPool(pool_);
     cfg_mgr.addSubnet4(subnet_);
 
-    Lease4Ptr lease = engine->allocateAddress4(subnet_, clientid_, hwaddr_, IOAddress("0.0.0.0"),
-                                               false, CalloutHandlePtr());
+    Lease4Ptr lease = engine->allocateAddress4(subnet_, clientid_, hwaddr_,
+                                               IOAddress("0.0.0.0"),
+                                               true, true, "host.example.com.",
+                                               false, CalloutHandlePtr(),
+                                               old_lease_);
 
     // Check that we got that single lease
     ASSERT_TRUE(lease);
 
+    // We have allocated new lease, so the old lease should not exist.
+    EXPECT_FALSE(old_lease_);
+
     EXPECT_EQ("192.0.2.17", lease->addr_.toText());
 
     // Do all checks on the lease
@@ -916,8 +957,9 @@ TEST_F(AllocEngine4Test, outOfAddresses4) {
     uint8_t hwaddr2[] = { 0, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe};
     uint8_t clientid2[] = { 8, 7, 6, 5, 4, 3, 2, 1 };
     time_t now = time(NULL);
-    Lease4Ptr lease(new Lease4(addr, hwaddr2, sizeof(hwaddr2), clientid2, sizeof(clientid2),
-                               501, 502, 503, now, subnet_->getID()));
+    Lease4Ptr lease(new Lease4(addr, hwaddr2, sizeof(hwaddr2), clientid2,
+                               sizeof(clientid2), 501, 502, 503, now,
+                               subnet_->getID()));
     lease->cltt_ = time(NULL) - 10; // Allocated 10 seconds ago
     ASSERT_TRUE(LeaseMgrFactory::instance().addLease(lease));
 
@@ -925,9 +967,12 @@ TEST_F(AllocEngine4Test, outOfAddresses4) {
     // else, so the allocation should fail
 
     Lease4Ptr lease2 = engine->allocateAddress4(subnet_, clientid_, hwaddr_,
-                                                IOAddress("0.0.0.0"), false,
-                                                CalloutHandlePtr());
+                                                IOAddress("0.0.0.0"),
+                                                false, false, "",
+                                                false, CalloutHandlePtr(),
+                                                old_lease_);
     EXPECT_FALSE(lease2);
+    EXPECT_FALSE(old_lease_);
 }
 
 // This test checks if an expired lease can be reused in DISCOVER (fake allocation)
@@ -950,29 +995,51 @@ TEST_F(AllocEngine4Test, discoverReuseExpiredLease4) {
     uint8_t hwaddr2[] = { 0, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe};
     uint8_t clientid2[] = { 8, 7, 6, 5, 4, 3, 2, 1 };
     time_t now = time(NULL) - 500; // Allocated 500 seconds ago
-    Lease4Ptr lease(new Lease4(addr, clientid2, sizeof(clientid2), hwaddr2, sizeof(hwaddr2),
+    Lease4Ptr lease(new Lease4(addr, clientid2, sizeof(clientid2),
+                               hwaddr2, sizeof(hwaddr2),
                                495, 100, 200, now, subnet_->getID()));
+    // Copy the lease, so as it can be compared with the old lease returned
+    // by the allocation engine.
+    Lease4 original_lease(*lease);
+
     // Lease was assigned 500 seconds ago, but its valid lifetime is 495, so it
     // is expired already
     ASSERT_TRUE(lease->expired());
     ASSERT_TRUE(LeaseMgrFactory::instance().addLease(lease));
 
     // CASE 1: Asking for any address
-    lease = engine->allocateAddress4(subnet_, clientid_, hwaddr_, IOAddress("0.0.0.0"),
-                                     true, CalloutHandlePtr());
+    lease = engine->allocateAddress4(subnet_, clientid_, hwaddr_,
+                                     IOAddress("0.0.0.0"),
+                                     false, false, "",
+                                     true, CalloutHandlePtr(),
+                                     old_lease_);
     // Check that we got that single lease
     ASSERT_TRUE(lease);
     EXPECT_EQ(addr.toText(), lease->addr_.toText());
 
+    // We are reusing expired lease, the old (expired) instance should be
+    // returned. The returned instance should be the same as the original
+    // lease.
+    ASSERT_TRUE(old_lease_);
+    EXPECT_TRUE(original_lease == *old_lease_);
+
     // Do all checks on the lease (if subnet-id, preferred/valid times are ok etc.)
     checkLease4(lease);
 
     // CASE 2: Asking specifically for this address
-    lease = engine->allocateAddress4(subnet_, clientid_, hwaddr_, IOAddress(addr.toText()),
-                                     true, CalloutHandlePtr());
+    lease = engine->allocateAddress4(subnet_, clientid_, hwaddr_,
+                                     IOAddress(addr.toText()),
+                                     false, false, "",
+                                     true, CalloutHandlePtr(),
+                                     old_lease_);
     // Check that we got that single lease
     ASSERT_TRUE(lease);
     EXPECT_EQ(addr.toText(), lease->addr_.toText());
+
+    // We are updating expired lease. The copy of the old lease should be
+    // returned and it should be equal to the original lease.
+    ASSERT_TRUE(old_lease_);
+    EXPECT_TRUE(*old_lease_ == original_lease);
 }
 
 // This test checks if an expired lease can be reused in REQUEST (actual allocation)
@@ -987,8 +1054,13 @@ TEST_F(AllocEngine4Test, requestReuseExpiredLease4) {
     uint8_t hwaddr2[] = { 0, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe};
     uint8_t clientid2[] = { 8, 7, 6, 5, 4, 3, 2, 1 };
     time_t now = time(NULL) - 500; // Allocated 500 seconds ago
-    Lease4Ptr lease(new Lease4(addr, clientid2, sizeof(clientid2), hwaddr2, sizeof(hwaddr2),
-                               495, 100, 200, now, subnet_->getID()));
+    Lease4Ptr lease(new Lease4(addr, clientid2, sizeof(clientid2), hwaddr2,
+                               sizeof(hwaddr2), 495, 100, 200, now,
+                               subnet_->getID()));
+    // Make a copy of the lease, so as we can comapre that with the old lease
+    // instance returned by the allocation engine.
+    Lease4 original_lease(*lease);
+
     // Lease was assigned 500 seconds ago, but its valid lifetime is 495, so it
     // is expired already
     ASSERT_TRUE(lease->expired());
@@ -996,8 +1068,10 @@ TEST_F(AllocEngine4Test, requestReuseExpiredLease4) {
 
     // A client comes along, asking specifically for this address
     lease = engine->allocateAddress4(subnet_, clientid_, hwaddr_,
-                                     IOAddress(addr.toText()), false,
-                                     CalloutHandlePtr());
+                                     IOAddress(addr.toText()),
+                                     false, true, "host.example.com.",
+                                     false, CalloutHandlePtr(),
+                                     old_lease_);
 
     // Check that he got that single lease
     ASSERT_TRUE(lease);
@@ -1009,6 +1083,11 @@ TEST_F(AllocEngine4Test, requestReuseExpiredLease4) {
 
     // Now check that the lease in LeaseMgr has the same parameters
     detailCompareLease(lease, from_mgr);
+
+    // The allocation engine should return a copy of the old lease. This
+    // lease should be equal to the original lease.
+    ASSERT_TRUE(old_lease_);
+    EXPECT_TRUE(*old_lease_ == original_lease);
 }
 
 /// @todo write renewLease6
@@ -1039,7 +1118,8 @@ TEST_F(AllocEngine4Test, renewLease4) {
     // Lease was assigned 45 seconds ago and is valid for 100 seconds. Let's
     // renew it.
     ASSERT_FALSE(lease->expired());
-    lease = engine->renewLease4(subnet_, clientid_, hwaddr_, lease,
+    lease = engine->renewLease4(subnet_, clientid_, hwaddr_, true,
+                                true, "host.example.com.", lease, 
                                 callout_handle, false);
     // Check that he got that single lease
     ASSERT_TRUE(lease);
@@ -1406,7 +1486,9 @@ TEST_F(HookAllocEngine4Test, lease4_select) {
 
     Lease4Ptr lease = engine->allocateAddress4(subnet_, clientid_, hwaddr_,
                                                IOAddress("0.0.0.0"),
-                                               false, callout_handle);
+                                               false, false, "",
+                                               false, callout_handle,
+                                               old_lease_);
     // Check that we got a lease
     ASSERT_TRUE(lease);
 
@@ -1468,8 +1550,11 @@ TEST_F(HookAllocEngine4Test, change_lease4_select) {
     CalloutHandlePtr callout_handle = HooksManager::createCalloutHandle();
 
     // Call allocateAddress4. Callouts should be triggered here.
-    Lease4Ptr lease = engine->allocateAddress4(subnet_, clientid_, hwaddr_, IOAddress("0.0.0.0"),
-                                               false, callout_handle);
+    Lease4Ptr lease = engine->allocateAddress4(subnet_, clientid_, hwaddr_,
+                                               IOAddress("0.0.0.0"),
+                                               false, false, "",
+                                               false, callout_handle,
+                                               old_lease_);
     // Check that we got a lease
     ASSERT_TRUE(lease);
 
diff --git a/src/lib/dhcpsrv/tests/lease_mgr_unittest.cc b/src/lib/dhcpsrv/tests/lease_mgr_unittest.cc
index d5535ae..883874a 100644
--- a/src/lib/dhcpsrv/tests/lease_mgr_unittest.cc
+++ b/src/lib/dhcpsrv/tests/lease_mgr_unittest.cc
@@ -245,7 +245,7 @@ TEST(LeaseMgr, getParameter) {
 ///
 /// Lease4 is also defined in lease_mgr.h, so is tested in this file as well.
 // This test checks if the Lease4 structure can be instantiated correctly
-TEST(Lease4, Lease4Constructor) {
+TEST(Lease4, constructor) {
 
     // Random values for the tests
     const uint8_t HWADDR[] = {0x08, 0x00, 0x2b, 0x02, 0x3f, 0x4e};
@@ -292,12 +292,79 @@ TEST(Lease4, Lease4Constructor) {
     }
 }
 
+// This test verfies that copy constructor copies Lease4 fields correctly.
+TEST(Lease4, copyConstructor) {
+
+    // Random values for the tests
+    const uint8_t HWADDR[] = {0x08, 0x00, 0x2b, 0x02, 0x3f, 0x4e};
+    std::vector<uint8_t> hwaddr(HWADDR, HWADDR + sizeof(HWADDR));
+
+    const uint8_t CLIENTID[] = {0x17, 0x34, 0xe2, 0xff, 0x09, 0x92, 0x54};
+    std::vector<uint8_t> clientid_vec(CLIENTID, CLIENTID + sizeof(CLIENTID));
+    ClientId clientid(clientid_vec);
+
+    // ...and a time
+    const time_t current_time = time(NULL);
+
+    // Other random constants.
+    const uint32_t SUBNET_ID = 42;
+    const uint32_t VALID_LIFETIME = 500;
+
+    // Create the lease
+    Lease4 lease(0xffffffff, HWADDR, sizeof(HWADDR),
+                 CLIENTID, sizeof(CLIENTID), VALID_LIFETIME, 0, 0, current_time,
+                 SUBNET_ID);
+
+    // Use copy constructor to copy the lease.
+    Lease4 copied_lease(lease);
+
+    // Both leases should be now equal. When doing this check we assume that
+    // the equality operator works correctly.
+    EXPECT_TRUE(lease == copied_lease);
+    // Client IDs are equal, but they should be in two distinct pointers.
+    EXPECT_FALSE(lease.client_id_ == copied_lease.client_id_);
+}
+
+// This test verfies that the assignment operator copies all Lease4 fields
+// correctly.
+TEST(Lease4, operatorAssign) {
+
+    // Random values for the tests
+    const uint8_t HWADDR[] = {0x08, 0x00, 0x2b, 0x02, 0x3f, 0x4e};
+    std::vector<uint8_t> hwaddr(HWADDR, HWADDR + sizeof(HWADDR));
+
+    const uint8_t CLIENTID[] = {0x17, 0x34, 0xe2, 0xff, 0x09, 0x92, 0x54};
+    std::vector<uint8_t> clientid_vec(CLIENTID, CLIENTID + sizeof(CLIENTID));
+    ClientId clientid(clientid_vec);
+
+    // ...and a time
+    const time_t current_time = time(NULL);
+
+    // Other random constants.
+    const uint32_t SUBNET_ID = 42;
+    const uint32_t VALID_LIFETIME = 500;
+
+    // Create the lease
+    Lease4 lease(0xffffffff, HWADDR, sizeof(HWADDR),
+                 CLIENTID, sizeof(CLIENTID), VALID_LIFETIME, 0, 0, current_time,
+                 SUBNET_ID);
+
+    // Use assignment operator to assign the lease.
+    Lease4 copied_lease = lease;
+
+    // Both leases should be now equal. When doing this check we assume that
+    // the equality operator works correctly.
+    EXPECT_TRUE(lease == copied_lease);
+    // Client IDs are equal, but they should be in two distinct pointers.
+    EXPECT_FALSE(lease.client_id_ == copied_lease.client_id_);
+}
+
 /// @brief Lease4 Equality Test
 ///
 /// Checks that the operator==() correctly compares two leases for equality.
 /// As operator!=() is also defined for this class, every check on operator==()
 /// is followed by the reverse check on operator!=().
-TEST(Lease4, OperatorEquals) {
+TEST(Lease4, operatorEquals) {
 
     // Random values for the tests
     const uint32_t ADDRESS = 0x01020304;
diff --git a/src/lib/dhcpsrv/tests/test_utils.cc b/src/lib/dhcpsrv/tests/test_utils.cc
index ea62225..d8794fb 100644
--- a/src/lib/dhcpsrv/tests/test_utils.cc
+++ b/src/lib/dhcpsrv/tests/test_utils.cc
@@ -47,6 +47,9 @@ detailCompareLease(const Lease4Ptr& first, const Lease4Ptr& second) {
     EXPECT_EQ(first->valid_lft_, second->valid_lft_);
     EXPECT_EQ(first->cltt_, second->cltt_);
     EXPECT_EQ(first->subnet_id_, second->subnet_id_);
+    EXPECT_EQ(first->fqdn_fwd_, second->fqdn_fwd_);
+    EXPECT_EQ(first->fqdn_rev_, second->fqdn_rev_);
+    EXPECT_EQ(first->hostname_, second->hostname_);
 }
 
 void
@@ -67,6 +70,9 @@ detailCompareLease(const Lease6Ptr& first, const Lease6Ptr& second) {
     EXPECT_EQ(first->valid_lft_, second->valid_lft_);
     EXPECT_EQ(first->cltt_, second->cltt_);
     EXPECT_EQ(first->subnet_id_, second->subnet_id_);
+    EXPECT_EQ(first->fqdn_fwd_, second->fqdn_fwd_);
+    EXPECT_EQ(first->fqdn_rev_, second->fqdn_rev_);
+    EXPECT_EQ(first->hostname_, second->hostname_);
 }
 
 };



More information about the bind10-changes mailing list