]> git.ipfire.org Git - thirdparty/kea.git/commitdiff
[897-add-infinite-valid-lifetime] Checkpoint (todo: only mysql has the 2038 issue)
authorFrancis Dupont <fdupont@isc.org>
Tue, 10 Sep 2019 22:49:16 +0000 (00:49 +0200)
committerFrancis Dupont <fdupont@isc.org>
Tue, 10 Sep 2019 22:49:16 +0000 (00:49 +0200)
22 files changed:
src/bin/dhcp4/dhcp4_srv.cc
src/bin/dhcp6/dhcp6_srv.cc
src/lib/dhcpsrv/cql_lease_mgr.cc
src/lib/dhcpsrv/cql_lease_mgr.h
src/lib/dhcpsrv/csv_lease_file4.cc
src/lib/dhcpsrv/csv_lease_file6.cc
src/lib/dhcpsrv/lease.cc
src/lib/dhcpsrv/lease.h
src/lib/dhcpsrv/lease_mgr.h
src/lib/dhcpsrv/memfile_lease_mgr.h
src/lib/dhcpsrv/memfile_lease_storage.h
src/lib/dhcpsrv/mysql_lease_mgr.cc
src/lib/dhcpsrv/mysql_lease_mgr.h
src/lib/dhcpsrv/ncr_generator.cc
src/lib/dhcpsrv/pgsql_lease_mgr.cc
src/lib/dhcpsrv/pgsql_lease_mgr.h
src/lib/dhcpsrv/tests/cql_lease_mgr_unittest.cc
src/lib/dhcpsrv/tests/generic_lease_mgr_unittest.cc
src/lib/dhcpsrv/tests/generic_lease_mgr_unittest.h
src/lib/dhcpsrv/tests/lease_unittest.cc
src/lib/dhcpsrv/tests/mysql_lease_mgr_unittest.cc
src/lib/dhcpsrv/tests/pgsql_lease_mgr_unittest.cc

index f658489a568cbc9ccc27ee31cbb912c1d76b9f59..0557ba4061b8191200939085aba78ec06b6fa673 100644 (file)
@@ -2178,11 +2178,16 @@ Dhcpv4Srv::assignLease(Dhcpv4Exchange& ex) {
             LOG_INFO(lease4_logger, DHCP4_LEASE_ADVERT)
                 .arg(query->getLabel())
                 .arg(lease->addr_.toText());
-        } else {
+        } else if (lease->valid_lft_ != Lease::INFINITY_LFT) {
             LOG_INFO(lease4_logger, DHCP4_LEASE_ALLOC)
                 .arg(query->getLabel())
                 .arg(lease->addr_.toText())
                 .arg(lease->valid_lft_);
+        } else {
+            LOG_INFO(lease4_logger, DHCP4_LEASE_ALLOC)
+                .arg(query->getLabel())
+                .arg(lease->addr_.toText())
+                .arg("infinity");
         }
 
         // We're logging this here, because this is the place where we know
index 453f65d7e2c73acd94e55dbcb13d8309970e5857..470e34e45641012bcdffd97abfa3d834bac9476d 100644 (file)
@@ -1897,12 +1897,18 @@ Dhcpv6Srv::assignIA_NA(const Pkt6Ptr& query, const Pkt6Ptr& answer,
                 .arg(query->getLabel())
                 .arg(lease->addr_.toText())
                 .arg(ia->getIAID());
-        } else {
+        } else if (lease->valid_lft_ != Lease::INFINITY_LFT) {
             LOG_INFO(lease6_logger, DHCP6_LEASE_ALLOC)
                 .arg(query->getLabel())
                 .arg(lease->addr_.toText())
                 .arg(ia->getIAID())
                 .arg(lease->valid_lft_);
+        } else {
+            LOG_INFO(lease6_logger, DHCP6_LEASE_ALLOC)
+                .arg(query->getLabel())
+                .arg(lease->addr_.toText())
+                .arg(ia->getIAID())
+                .arg("infinity");
         }
         LOG_DEBUG(lease6_logger, DBG_DHCP6_DETAIL_DATA, DHCP6_LEASE_DATA)
             .arg(query->getLabel())
@@ -2019,13 +2025,20 @@ Dhcpv6Srv::assignIA_PD(const Pkt6Ptr& query, const Pkt6Ptr& /*answer*/,
                     .arg((*l)->addr_.toText())
                     .arg(static_cast<int>((*l)->prefixlen_))
                     .arg(ia->getIAID());
-            } else {
+            } else if ((*l)->valid_lft_ != Lease::INFINITY_LFT) {
                 LOG_INFO(lease6_logger, DHCP6_PD_LEASE_ALLOC)
                     .arg(query->getLabel())
                     .arg((*l)->addr_.toText())
                     .arg(static_cast<int>((*l)->prefixlen_))
                     .arg(ia->getIAID())
                     .arg((*l)->valid_lft_);
+            } else {
+                LOG_INFO(lease6_logger, DHCP6_PD_LEASE_ALLOC)
+                    .arg(query->getLabel())
+                    .arg((*l)->addr_.toText())
+                    .arg(static_cast<int>((*l)->prefixlen_))
+                    .arg(ia->getIAID())
+                    .arg("infinity");
             }
 
             boost::shared_ptr<Option6IAPrefix>
index 3bea54355bcf1742e3fc851f7965344fd6e16e3b..9cddf8f25d0843c0db8241b1a722ec0780925a1c 100644 (file)
@@ -302,6 +302,7 @@ StatementMap CqlLease4Exchange::tagged_statements_{
       "FROM lease4 "
       "WHERE state = ? "
       "AND expire < ? "
+      "AND valid_lifetime < 4294967295 "
       "LIMIT ? "
       "ALLOW FILTERING "}},
 
@@ -448,8 +449,12 @@ CqlLease4Exchange::createBindForInsert(const Lease4Ptr &lease, AnyArray &data) {
         // For convenience for external tools, this is converted to lease
         // expiry time (expire). The relationship is given by:
         // expire = cltt_ + valid_lft_
-        CqlExchange::convertToDatabaseTime(lease_->cltt_, lease_->valid_lft_,
-                                           expire_);
+        // Avoid overflow
+        uint32_t valid_lft = lease_->valid_lft_;
+        if (valid_lft == Lease::INFINITY_LFT) {
+            valid_lft = Lease::FIVEHUNDREDDAYS;
+        }
+        CqlExchange::convertToDatabaseTime(lease_->cltt_, valid_lft, expire_);
 
         // subnet_id: int
         subnet_id_ = static_cast<cass_int32_t>(lease_->subnet_id_);
@@ -551,8 +556,12 @@ CqlLease4Exchange::createBindForUpdate(const Lease4Ptr &lease, AnyArray &data,
         // For convenience for external tools, this is converted to lease
         // expiry time (expire). The relationship is given by:
         // expire = cltt_ + valid_lft_
-        CqlExchange::convertToDatabaseTime(lease_->cltt_, lease_->valid_lft_,
-                                           expire_);
+        // Avoid overflow
+        uint32_t valid_lft = lease_->valid_lft_;
+        if (valid_lft == Lease::INFINITY_LFT) {
+            valid_lft = Lease::FIVEHUNDREDDAYS;
+        }
+        CqlExchange::convertToDatabaseTime(lease_->cltt_, valid_lft, expire_);
 
         // subnet_id: int
         subnet_id_ = static_cast<cass_int32_t>(lease_->subnet_id_);
@@ -696,7 +705,12 @@ CqlLease4Exchange::retrieve() {
         }
 
         time_t cltt = 0;
-        CqlExchange::convertFromDatabaseTime(expire_, valid_lifetime_, cltt);
+        // Recover from overflow
+        uint32_t valid_lft = valid_lifetime_;
+        if (valid_lft == Lease::INFINITY_LFT) {
+            valid_lft = Lease::FIVEHUNDREDDAYS;
+        }
+        CqlExchange::convertFromDatabaseTime(expire_, valid_lft, cltt);
 
         HWAddrPtr hwaddr(new HWAddr(hwaddr_, HTYPE_ETHER));
 
@@ -1004,6 +1018,7 @@ StatementMap CqlLease6Exchange::tagged_statements_ = {
       "FROM lease6 "
       "WHERE state = ? "
       "AND expire < ? "
+      "AND valid_lifetime < 4294967295 "
       "LIMIT ? "
       "ALLOW FILTERING "}},
 
@@ -1112,7 +1127,12 @@ CqlLease6Exchange::createBindForInsert(const Lease6Ptr &lease, AnyArray &data) {
         // For convenience for external tools, this is converted to lease
         // expiry time (expire). The relationship is given by:
         // expire = cltt_ + valid_lft_
-        CqlExchange::convertToDatabaseTime(lease_->cltt_, lease_->valid_lft_, expire_);
+        // Avoid overflow
+        uint32_t valid_lft = lease_->valid_lft_;
+        if (valid_lft == Lease::INFINITY_LFT) {
+            valid_lft = Lease::FIVEHUNDREDDAYS;
+        }
+        CqlExchange::convertToDatabaseTime(lease_->cltt_, valid_lft, expire_);
 
         // subnet_id: int
         subnet_id_ = static_cast<cass_int32_t>(lease_->subnet_id_);
@@ -1247,8 +1267,12 @@ CqlLease6Exchange::createBindForUpdate(const Lease6Ptr &lease, AnyArray &data,
         // For convenience for external tools, this is converted to lease
         // expiry time (expire). The relationship is given by:
         // expire = cltt_ + valid_lft_
-        CqlExchange::convertToDatabaseTime(lease_->cltt_, lease_->valid_lft_,
-                                           expire_);
+        // Avoid overflow
+        uint32_t valid_lft = lease_->valid_lft_;
+        if (valid_lft == Lease::INFINITY_LFT) {
+            valid_lft = Lease::FIVEHUNDREDDAYS;
+        }
+        CqlExchange::convertToDatabaseTime(lease_->cltt_, valid_lft, expire_);
 
         // subnet_id: int
         subnet_id_ = static_cast<cass_int32_t>(lease_->subnet_id_);
@@ -1505,7 +1529,12 @@ CqlLease6Exchange::retrieve() {
                        fqdn_fwd_, fqdn_rev_, hostname_, hwaddr, prefix_len_));
 
         time_t cltt = 0;
-        CqlExchange::convertFromDatabaseTime(expire_, valid_lifetime_, cltt);
+        // Recover from overflow
+        uint32_t valid_lft = valid_lifetime_;
+        if (valid_lft == Lease::INFINITY_LFT) {
+            valid_lft = Lease::FIVEHUNDREDDAYS;
+        }
+        CqlExchange::convertFromDatabaseTime(expire_, valid_lft, cltt);
         result->cltt_ = cltt;
 
         result->state_ = state_;
@@ -2311,7 +2340,6 @@ CqlLeaseMgr::getLeases6(const DUID& duid) const {
 
     // Set up the WHERE clause value
     AnyArray data;
-    
     CassBlob duid_data(duid.getDuid());
 
     data.add(&duid_data);
index ae042b3c46d2588658c3a7ab7829a0a0e74c3ed1..f5f1a8e6582cc8fdc4b1d9db85c28e7d268a3672 100644 (file)
@@ -320,7 +320,7 @@ public:
     ///
     /// @return Lease collection (may be empty if no IPv6 lease found).
     virtual Lease6Collection getLeases6(const DUID& duid) const override;
-    
+
     /// @brief Returns range of IPv6 leases using paging.
     ///
     /// This method implements paged browsing of the lease database. The first
index a696377c99e5eeba67e500a8420ec60f609ae986..fc3cf1886a11a84f69ae7a067636da828074fc74 100644 (file)
@@ -60,7 +60,7 @@ CSVLeaseFile4::append(const Lease4& lease) {
     }
 
     row.writeAt(getColumnIndex("valid_lifetime"), lease.valid_lft_);
-    row.writeAt(getColumnIndex("expire"), static_cast<uint64_t>(lease.cltt_ + lease.valid_lft_));
+    row.writeAt(getColumnIndex("expire"), static_cast<uint64_t>(lease.cltt_) + lease.valid_lft_);
     row.writeAt(getColumnIndex("subnet_id"), lease.subnet_id_);
     row.writeAt(getColumnIndex("fqdn_fwd"), lease.fqdn_fwd_);
     row.writeAt(getColumnIndex("fqdn_rev"), lease.fqdn_rev_);
index a1119a6177422cde20e2d06d041c9f2e69413a50..c73b7d9aa6e021ed921d0a7fef982f910e735c57 100644 (file)
@@ -46,7 +46,7 @@ CSVLeaseFile6::append(const Lease6& lease) {
     row.writeAt(getColumnIndex("address"), lease.addr_.toText());
     row.writeAt(getColumnIndex("duid"), lease.duid_->toText());
     row.writeAt(getColumnIndex("valid_lifetime"), lease.valid_lft_);
-    row.writeAt(getColumnIndex("expire"), static_cast<uint64_t>(lease.cltt_ + lease.valid_lft_));
+    row.writeAt(getColumnIndex("expire"), static_cast<uint64_t>(lease.cltt_) + lease.valid_lft_);
     row.writeAt(getColumnIndex("subnet_id"), lease.subnet_id_);
     row.writeAt(getColumnIndex("pref_lifetime"), lease.preferred_lft_);
     row.writeAt(getColumnIndex("lease_type"), lease.type_);
index 4b1f0bd6b5900c7e3e1d156aeb1bba3e8428f05f..789a78a9469e082916218a099b63457cdcc2635a 100644 (file)
@@ -93,7 +93,7 @@ Lease::basicStatesToText(const uint32_t state) {
 
 bool
 Lease::expired() const {
-    return (getExpirationTime() < time(NULL));
+    return ((valid_lft_ != INFINITY_LFT) && (getExpirationTime() < time(NULL)));
 }
 
 bool
@@ -527,9 +527,13 @@ Lease6::toText() const {
            << "Address:       " << addr_ << "\n"
            << "Prefix length: " << static_cast<int>(prefixlen_) << "\n"
            << "IAID:          " << iaid_ << "\n"
-           << "Pref life:     " << preferred_lft_ << "\n"
-           << "Valid life:    " << valid_lft_ << "\n"
-           << "Cltt:          " << cltt_ << "\n"
+           << "Pref life:     " << preferred_lft_ << "\n";
+    if (valid_lft_ != INFINITY_LFT) {
+        stream << "Valid life:    " << valid_lft_ << "\n";
+    } else {
+        stream << "Valid life:    " << "infinity" << "\n";
+    }
+    stream << "Cltt:          " << cltt_ << "\n"
            << "DUID:          " << (duid_?duid_->toText():"(none)") << "\n"
            << "Hardware addr: " << (hwaddr_?hwaddr_->toText(false):"(none)") << "\n"
            << "Subnet ID:     " << subnet_id_ << "\n"
@@ -546,9 +550,13 @@ std::string
 Lease4::toText() const {
     ostringstream stream;
 
-    stream << "Address:       " << addr_ << "\n"
-           << "Valid life:    " << valid_lft_ << "\n"
-           << "Cltt:          " << cltt_ << "\n"
+    stream << "Address:       " << addr_ << "\n";
+    if (valid_lft_ != INFINITY_LFT) {
+        stream << "Valid life:    " << valid_lft_ << "\n";
+    } else {
+        stream << "Valid life:    " << "infinity" << "\n";
+    }
+    stream << "Cltt:          " << cltt_ << "\n"
            << "Hardware addr: " << (hwaddr_ ? hwaddr_->toText(false) : "(none)") << "\n"
            << "Client id:     " << (client_id_ ? client_id_->toText() : "(none)") << "\n"
            << "Subnet ID:     " << subnet_id_ << "\n"
index 2f661daa5b42a87fd726c992c949db034ba01bda..ff77ce87dfc2e284a3db230138bcf03a590e09e7 100644 (file)
@@ -34,6 +34,12 @@ typedef boost::shared_ptr<Lease> LeasePtr;
 /// leases.
 struct Lease : public isc::data::UserContext, public isc::data::CfgToElement {
 
+    /// @brief Infinity (means static, i.e. never expire)
+    static const uint32_t INFINITY_LFT = 0xffffffff;
+
+    /// @brief Five hundred days (infinity overflows in 32 bits)
+    static const uint32_t FIVEHUNDREDDAYS = 500 * 24 * 60 * 60;
+
     /// @brief Type of lease or pool
     typedef enum {
         TYPE_NA = 0, ///< the lease contains non-temporary IPv6 address
index 233f3539c88be593cb6eaaf8c6ab7ceafa21db67..5026ee0b4eee994b9f778fd1a22d1f2c4f204593 100644 (file)
@@ -459,9 +459,9 @@ public:
 
     /// @brief Returns collection of leases for matching DUID
     ///
-    /// @return Lease collection 
+    /// @return Lease collection
     /// (may be empty if no IPv6 lease found for the DUID).
-    virtual Lease6Collection getLeases6(const DUID& duid) const = 0; 
+    virtual Lease6Collection getLeases6(const DUID& duid) const = 0;
 
     /// @brief Returns range of IPv6 leases using paging.
     ///
index 49dbf3e0bf8acb7837b24789f560ac198b6a3fb1..69ccd8c0b6d91e24be2b27c6574f0f2c640a0617 100644 (file)
@@ -316,10 +316,10 @@ public:
     /// @brief Returns IPv6 leases for the DUID.
     ///
     /// @todo: implement an optimised of the query using index.
-    /// @return Lease collection (may be empty if no IPv6 lease found) 
+    /// @return Lease collection (may be empty if no IPv6 lease found)
     /// for the DUID.
     virtual Lease6Collection getLeases6(const DUID& duid) const;
-    
+
     /// @brief Returns range of IPv6 leases using paging.
     ///
     /// This method implements paged browsing of the lease database. The first
index 3254eefe3a6ed3a6bb7133cca260883c4816b753..4863633b09bd7dd243e70f3b8eae004ddea3725c 100644 (file)
@@ -46,7 +46,7 @@ struct ClientIdHWAddressSubnetIdIndexTag { };
 struct SubnetIdIndexTag { };
 
 /// @brief Tag for index using DUID.
-struct DuidIndexTag { }; 
+struct DuidIndexTag { };
 /// @name Multi index containers holding DHCPv4 and DHCPv6 leases.
 ///
 //@{
index 8d741fa085aeda94d9cfc8df0265367543da9eb1..900654f6fe9afe35cce58aebd1509528bb7eabc1 100644 (file)
@@ -165,7 +165,8 @@ tagged_statements = { {
                         "fqdn_fwd, fqdn_rev, hostname, "
                         "state, user_context "
                             "FROM lease4 "
-                            "WHERE state != ? AND expire < ? "
+                            "WHERE state != ? AND expire < ?"
+                            " AND valid_lifetime != 4294967295 "
                             "ORDER BY expire ASC "
                             "LIMIT ?"},
     {MySqlLeaseMgr::GET_LEASE6,
@@ -241,7 +242,8 @@ tagged_statements = { {
                         "hwaddr, hwtype, hwaddr_source, "
                         "state, user_context "
                             "FROM lease6 "
-                            "WHERE state != ? AND expire < ? "
+                            "WHERE state != ? AND expire < ?"
+                            " AND valid_lifetime != 4294967295 "
                             "ORDER BY expire ASC "
                             "LIMIT ?"},
     {MySqlLeaseMgr::INSERT_LEASE4,
@@ -539,7 +541,12 @@ public:
             // expiry time (expire).  The relationship is given by:
             //
             // expire = cltt_ + valid_lft_
-            MySqlConnection::convertToDatabaseTime(lease_->cltt_, lease_->valid_lft_,
+            // Avoid overflow
+            uint32_t valid_lft = lease_->valid_lft_;
+            if (valid_lft == Lease::INFINITY_LFT) {
+                valid_lft = Lease::FIVEHUNDREDDAYS;
+            }
+            MySqlConnection::convertToDatabaseTime(lease_->cltt_, valid_lft,
                                                    expire_);
             bind_[4].buffer_type = MYSQL_TYPE_TIMESTAMP;
             bind_[4].buffer = reinterpret_cast<char*>(&expire_);
@@ -744,7 +751,12 @@ public:
         // Convert times received from the database to times for the lease
         // structure
         time_t cltt = 0;
-        MySqlConnection::convertFromDatabaseTime(expire_, valid_lifetime_, cltt);
+        // Recover from overflow
+        uint32_t valid_lft = valid_lifetime_;
+        if (valid_lft == Lease::INFINITY_LFT) {
+            valid_lft = Lease::FIVEHUNDREDDAYS;
+        }
+        MySqlConnection::convertFromDatabaseTime(expire_, valid_lft, cltt);
 
         if (client_id_null_ == MLM_TRUE) {
             // There's no client-id, so we pass client-id_length_ set to 0
@@ -971,7 +983,12 @@ public:
             /// expiry time (expire).  The relationship is given by:
             //
             // expire = cltt_ + valid_lft_
-            MySqlConnection::convertToDatabaseTime(lease_->cltt_, lease_->valid_lft_,
+            // Avoid overflow
+            uint32_t valid_lft = lease_->valid_lft_;
+            if (valid_lft == Lease::INFINITY_LFT) {
+                valid_lft = Lease::FIVEHUNDREDDAYS;
+            }
+            MySqlConnection::convertToDatabaseTime(lease_->cltt_, valid_lft,
                                                    expire_);
             bind_[3].buffer_type = MYSQL_TYPE_TIMESTAMP;
             bind_[3].buffer = reinterpret_cast<char*>(&expire_);
@@ -1384,7 +1401,12 @@ public:
                                     subnet_id_, fqdn_fwd_, fqdn_rev_,
                                     hostname, hwaddr, prefixlen_));
         time_t cltt = 0;
-        MySqlConnection::convertFromDatabaseTime(expire_, valid_lifetime_, cltt);
+        // Recover from overflow
+        uint32_t valid_lft = valid_lifetime_;
+        if (valid_lft == Lease::INFINITY_LFT) {
+            valid_lft = Lease::FIVEHUNDREDDAYS;
+        }
+        MySqlConnection::convertFromDatabaseTime(expire_, valid_lft, cltt);
         result->cltt_ = cltt;
 
         // Set state.
@@ -2312,7 +2334,7 @@ Lease6Collection
 MySqlLeaseMgr::getLeases6(const DUID& duid) const {
    LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL, DHCPSRV_MYSQL_GET_DUID)
              .arg(duid.toText());
-   
+
     // Set up the WHERE clause value
     MYSQL_BIND inbind[1];
     memset(inbind, 0, sizeof(inbind));
@@ -2325,9 +2347,8 @@ MySqlLeaseMgr::getLeases6(const DUID& duid) const {
             const_cast<uint8_t*>(&duid_vector[0]));
     inbind[0].buffer_length = duid_length;
     inbind[0].length = &duid_length;
-    
+
     Lease6Collection result;
-    
     getLeaseCollection(GET_LEASE6_DUID, inbind, result);
 
     return result;
index a11009c8749c89748e76d82732614e898a20b5f4..19919c191f1c9cf6bacdc36b2a41ccc8575fad20 100644 (file)
@@ -316,7 +316,7 @@ public:
     /// @return Lease collection (may be empty if no IPv6 lease found)
     /// for the DUID.
     virtual Lease6Collection getLeases6(const DUID& duid) const;
-    
+
     /// @brief Returns range of IPv6 leases using paging.
     ///
     /// This method implements paged browsing of the lease database. The first
index 7b0e9f29d2a52406621605b2f6ad7267ac76c55b..8dd5a7aca76e07d04347ab32021e5a6fe1f07eda 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright (C) 2015 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
@@ -44,7 +44,7 @@ void queueNCRCommon(const NameChangeType& chg_type, const LeasePtrType& lease,
                   DHCPSRV_QUEUE_NCR_SKIP)
             .arg(label)
             .arg(lease->addr_.toText());
-            
+
         return;
     }
 
@@ -55,11 +55,15 @@ void queueNCRCommon(const NameChangeType& chg_type, const LeasePtrType& lease,
         D2Dhcid dhcid = D2Dhcid(identifier, hostname_wire);
 
         // Create name change request.
+        uint32_t valid_lft = lease->valid_lft_;
+        if (valid_lft == Lease::INFINITY_LFT) {
+            valid_lft = Lease::FIVEHUNDREDDAYS;
+        }
         NameChangeRequestPtr ncr
             (new NameChangeRequest(chg_type, lease->fqdn_fwd_, lease->fqdn_rev_,
                                    lease->hostname_, lease->addr_.toText(),
-                                   dhcid, lease->cltt_ + lease->valid_lft_,
-                                   lease->valid_lft_));
+                                   dhcid, lease->cltt_ + valid_lft,
+                                   valid_lft));
 
         LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL_DATA, DHCPSRV_QUEUE_NCR)
             .arg(label)
index 26ff0c1c7be62ef5f618e04c902ab5e25512c7c7..c5d1ed9e26c869b5ea9283797a651a08112c5f11 100644 (file)
@@ -145,7 +145,7 @@ PgSqlTaggedStatement tagged_statements[] = {
         "fqdn_fwd, fqdn_rev, hostname, "
         "state, user_context "
       "FROM lease4 "
-      "WHERE state != $1 AND expire < $2 "
+      "WHERE state != $1 AND expire < $2 AND valid_lifetime != 4294967295 "
       "ORDER BY expire "
       "LIMIT $3"},
 
@@ -238,7 +238,7 @@ PgSqlTaggedStatement tagged_statements[] = {
         "hwaddr, hwtype, hwaddr_source, "
         "state, user_context "
       "FROM lease6 "
-      "WHERE state != $1 AND expire < $2 "
+      "WHERE state != $1 AND expire < $2 AND valid_lifetime != 4294967295 "
       "ORDER BY expire "
       "LIMIT $3"},
 
@@ -469,7 +469,12 @@ public:
             valid_lifetime_str_ = boost::lexical_cast<std::string>(lease->valid_lft_);
             bind_array.add(valid_lifetime_str_);
 
-            expire_str_ = convertToDatabaseTime(lease->cltt_, lease_->valid_lft_);
+            // Avoid overflow
+            uint32_t valid_lft = lease_->valid_lft_;
+            if (valid_lft == Lease::INFINITY_LFT) {
+                valid_lft = Lease::FIVEHUNDREDDAYS;
+            }
+            expire_str_ = convertToDatabaseTime(lease->cltt_, valid_lft);
             bind_array.add(expire_str_);
 
             subnet_id_str_ = boost::lexical_cast<std::string>(lease->subnet_id_);
@@ -524,7 +529,12 @@ public:
 
             getColumnValue(r, row , SUBNET_ID_COL, subnet_id_);
 
-            cltt_ = expire_ - valid_lifetime_;
+            // Recover from overflow
+            uint32_t valid_lft = valid_lifetime_;
+            if (valid_lft == Lease::INFINITY_LFT) {
+                valid_lft = Lease::FIVEHUNDREDDAYS;
+            }
+            cltt_ = expire_ - valid_lft;
 
             getColumnValue(r, row, FQDN_FWD_COL, fqdn_fwd_);
 
@@ -700,7 +710,12 @@ public:
             valid_lifetime_str_ = boost::lexical_cast<std::string>(lease->valid_lft_);
             bind_array.add(valid_lifetime_str_);
 
-            expire_str_ = convertToDatabaseTime(lease->cltt_, lease_->valid_lft_);
+            // Avoid overflow
+            uint32_t valid_lft = lease_->valid_lft_;
+            if (valid_lft == Lease::INFINITY_LFT) {
+                valid_lft = Lease::FIVEHUNDREDDAYS;
+            }
+            expire_str_ = convertToDatabaseTime(lease->cltt_, valid_lft);
             bind_array.add(expire_str_);
 
             subnet_id_str_ = boost::lexical_cast<std::string>(lease->subnet_id_);
@@ -806,7 +821,12 @@ public:
             expire_ = convertFromDatabaseTime(getRawColumnValue(r, row,
                                                                 EXPIRE_COL));
 
-            cltt_ = expire_ - valid_lifetime_;
+            // Recover from overflow
+            uint32_t valid_lft = valid_lifetime_;
+            if (valid_lft == Lease::INFINITY_LFT) {
+                valid_lft = Lease::FIVEHUNDREDDAYS;
+            }
+            cltt_ = expire_ - valid_lft;
 
             getColumnValue(r, row , SUBNET_ID_COL, subnet_id_);
 
index c779fafaa6eb80dd5349efdeca4db75f2e1afce0..29650c07963aa2657a7fd6ad437e0329014c77fc 100644 (file)
@@ -288,7 +288,7 @@ public:
     /// @return Lease collection (may be empty if no IPv6 lease found)
     /// for the DUID
     virtual Lease6Collection getLeases6(const DUID& duid) const;
-    
+
     /// @brief Returns range of IPv6 leases using paging.
     ///
     /// This method implements paged browsing of the lease database. The first
index 8c31f811d0ec8649b824fe4f90210d3d0acf9225..fa1b2267dc47e5aa35e2d94bb0e21809dafea18c 100644 (file)
@@ -508,6 +508,11 @@ TEST_F(CqlLeaseMgrTest, maxDate4) {
     testMaxDate4();
 }
 
+/// @brief checks that infinite lifetimes do not overflow.
+TEST_F(CqlLeaseMgrTest, infiniteLifeTime4) {
+    testInfiniteLifeTime4();
+}
+
 /// @brief Lease4 update tests
 ///
 /// Checks that we are able to update a lease in the database.
@@ -620,6 +625,12 @@ TEST_F(CqlLeaseMgrTest, getExpiredLeases4) {
     testCqlGetExpiredLeases4();
 }
 
+/// @brief Checks that the static (i.e. with infinite valid lifetime) DHCPv4
+/// leases will never expire.
+TEST_F(CqlLeaseMgrTest, staticLeases4) {
+    testStaticLeases4();
+}
+
 /// @brief Check that expired reclaimed DHCPv4 leases are removed.
 TEST_F(CqlLeaseMgrTest, deleteExpiredReclaimedLeases4) {
     testDeleteExpiredReclaimedLeases4();
@@ -648,6 +659,11 @@ TEST_F(CqlLeaseMgrTest, maxDate6) {
     testMaxDate6();
 }
 
+/// @brief checks that infinite lifetimes do not overflow.
+TEST_F(CqlLeaseMgrTest, infiniteLifeTime6) {
+    testInfiniteLifeTime6();
+}
+
 /// @brief Verify that too long hostname for Lease6 is not accepted.
 ///
 /// Checks that the it is not possible to create a lease when the hostname
@@ -764,6 +780,12 @@ TEST_F(CqlLeaseMgrTest, getExpiredLeases6) {
     testCqlGetExpiredLeases6();
 }
 
+/// @brief Checks that the static (i.e. with infinite valid lifetime) DHCPv6
+/// leases will never expire.
+TEST_F(CqlLeaseMgrTest, staticLeases6) {
+    testStaticLeases6();
+}
+
 /// @brief Check that expired reclaimed DHCPv6 leases are removed.
 TEST_F(CqlLeaseMgrTest, deleteExpiredReclaimedLeases6) {
     testDeleteExpiredReclaimedLeases6();
index eceec558d673477819ccf2d3a46500e800e39875..e40e9de2db019c615f71af44ad680c3cac0918f0 100644 (file)
@@ -127,7 +127,7 @@ GenericLeaseMgrTest::initializeLease4(std::string address) {
         // The times used in the next tests are deliberately restricted - we
         // should be able to cope with valid lifetimes up to 0xffffffff.
         //  However, this will lead to overflows.
-        // @TODO: test overflow conditions when code has been fixed
+        // @TODO: test overflow conditions as now the code was fixed.
         lease->valid_lft_ = 7000;
         lease->cltt_ = 234567;
         lease->subnet_id_ = 37;
@@ -254,7 +254,7 @@ GenericLeaseMgrTest::initializeLease6(std::string address) {
         // The times used in the next tests are deliberately restricted - we
         // should be able to cope with valid lifetimes up to 0xffffffff.
         //  However, this will lead to overflows.
-        // @TODO: test overflow conditions when code has been fixed
+        // @TODO: test overflow conditions as now the code was fixed.
         lease->preferred_lft_ = 7200;
         lease->valid_lft_ = 7000;
         lease->cltt_ = 234567;
@@ -712,6 +712,23 @@ GenericLeaseMgrTest::testMaxDate4() {
     detailCompareLease(leases[1], l_returned);
 }
 
+void
+GenericLeaseMgrTest::testInfiniteLifeTime4() {
+    // Get the leases to be used for the test.
+    vector<Lease4Ptr> leases = createLeases4();
+    Lease4Ptr lease = leases[1];
+
+    // Set valid_lft_ to infinite, cllt_ to now.
+    lease->valid_lft_ = Lease::INFINITY_LFT;
+    lease->cltt_ = time(NULL);
+
+    // Insert should not throw.
+    EXPECT_TRUE(lmptr_->addLease(leases[1]));
+    Lease4Ptr l_returned = lmptr_->getLease4(ioaddress4_[1]);
+    ASSERT_TRUE(l_returned);
+    detailCompareLease(leases[1], l_returned);
+}
+
 void
 GenericLeaseMgrTest::testBasicLease4() {
     // Get the leases to be used for the test.
@@ -883,6 +900,23 @@ GenericLeaseMgrTest::testMaxDate6() {
     detailCompareLease(leases[1], l_returned);
 }
 
+void
+GenericLeaseMgrTest::testInfiniteLifeTime6() {
+    // Get the leases to be used for the test.
+    vector<Lease6Ptr> leases = createLeases6();
+    Lease6Ptr lease = leases[1];
+
+    // Set valid_lft_ to infinite, cllt_ to now.
+    lease->valid_lft_ = Lease::INFINITY_LFT;
+    lease->cltt_ = time(NULL);
+
+    // Insert should not throw.
+    EXPECT_TRUE(lmptr_->addLease(leases[1]));
+    Lease6Ptr l_returned = lmptr_->getLease6(leasetype6_[1], ioaddress6_[1]);
+    ASSERT_TRUE(l_returned);
+    detailCompareLease(leases[1], l_returned);
+}
+
 // Checks whether a MAC address can be stored and retrieved together with
 // a lease.
 void
@@ -2167,6 +2201,48 @@ GenericLeaseMgrTest::testGetExpiredLeases6() {
     }
 }
 
+void
+GenericLeaseMgrTest::testStaticLeases4() {
+    // Get the leases to be used for the test.
+    vector<Lease4Ptr> leases = createLeases4();
+    Lease4Ptr lease = leases[1];
+
+    // Set valid_lft_ to infinite. Leave the small cltt even it won't happen
+    // in the real world to catch more possible issues.
+    lease->valid_lft_ = Lease::INFINITY_LFT;
+
+    // Add it to the database.
+    ASSERT_TRUE(lmptr_->addLease(leases[1]));
+
+    // Retrieve at most 10 expired leases.
+    Lease4Collection expired_leases;
+    ASSERT_NO_THROW(lmptr_->getExpiredLeases4(expired_leases, 10));
+
+    // No lease should be returned.
+    EXPECT_EQ(0, expired_leases.size());
+}
+
+void
+GenericLeaseMgrTest::testStaticLeases6() {
+    // Get the leases to be used for the test.
+    vector<Lease6Ptr> leases = createLeases6();
+    Lease6Ptr lease = leases[1];
+
+    // Set valid_lft_ to infinite. Leave the small cltt even it won't happen
+    // in the real world to catch more possible issues.
+    lease->valid_lft_ = Lease::INFINITY_LFT;
+
+    // Add it to the database.
+    ASSERT_TRUE(lmptr_->addLease(leases[1]));
+
+    // Retrieve at most 10 expired leases.
+    Lease6Collection expired_leases;
+    ASSERT_NO_THROW(lmptr_->getExpiredLeases6(expired_leases, 10));
+
+    // No lease should be returned.
+    EXPECT_EQ(0, expired_leases.size());
+}
+
 void
 GenericLeaseMgrTest::testDeleteExpiredReclaimedLeases4() {
     // Get the leases to be used for the test.
index a86632b440926d739ffda2b977fd4811c6183220..67c2eab75a41c1102f2ba4500933100a56fb70d0 100644 (file)
@@ -68,8 +68,7 @@ public:
     /// @param address Address to use for the initialization
     ///
     /// @return Lease6Ptr.  This will not point to anything if the
-    /// initialization
-    ///         failed (e.g. unknown address).
+    ///         initialization failed (e.g. unknown address).
     Lease6Ptr initializeLease6(std::string address);
 
     /// @brief Check Leases present and different
@@ -145,6 +144,9 @@ public:
     /// @brief checks that invalid dates are safely handled.
     void testMaxDate4();
 
+    /// @brief checks that infinite lifetimes do not overflow.
+    void testInfiniteLifeTime4();
+
     /// @brief Test lease retrieval using client id.
     void testGetLease4ClientId();
 
@@ -244,6 +246,9 @@ public:
     /// @brief Checks that invalid dates are safely handled.
     void testMaxDate6();
 
+    /// @brief checks that infinite lifetimes do not overflow.
+    void testInfiniteLifeTime6();
+
     /// @brief Checks that Lease6 can be stored with and without a hardware address.
     void testLease6MAC();
 
@@ -342,6 +347,14 @@ public:
     /// - reclaimed leases are not returned.
     void testGetExpiredLeases6();
 
+    /// @brief Checks that the static (i.e. with infinite valid lifetime)
+    /// DHCPv4 leases will never expire.
+    void testStaticLeases4();
+
+    /// @brief Checks that the static (i.e. with infinite valid lifetime)
+    /// DHCPv4 leases will never expire.
+    void testStaticLeases6();
+
     /// @brief Checks that declined IPv4 leases that have expired can be retrieved.
     ///
     /// This test checks that the following:
index 0763c0ce782d4f841529069cedcc381478184b38..0f5b2be287abaa65896e83d5aef106c36b54ab6b 100644 (file)
@@ -926,6 +926,11 @@ TEST(Lease6Test, Lease6Expired) {
     // Case 3: the lease is expired
     lease.cltt_ = time(NULL) - 102;
     EXPECT_TRUE(lease.expired());
+
+    // Case 4: the lease is static
+    lease.cltt_ = 1;
+    lease.valid_lft_ = Lease::INFINITY_LFT;
+    EXPECT_FALSE(lease.expired());
 }
 
 // Verify that the DUID can be returned as a vector object and if DUID is NULL
index 72a8ba8ef75c4934127775bcdb2ed612dc4b6e8b..35f3ca2a17cca3c3acd8bbcbfd918cbe051b65d0 100644 (file)
@@ -277,6 +277,11 @@ TEST_F(MySqlLeaseMgrTest, maxDate4) {
     testMaxDate4();
 }
 
+/// @brief checks that infinite lifetimes do not overflow.
+TEST_F(MySqlLeaseMgrTest, infiniteLifeTime4) {
+    testInfiniteLifeTime4();
+}
+
 /// @brief Lease4 update tests
 ///
 /// Checks that we are able to update a lease in the database.
@@ -404,6 +409,12 @@ TEST_F(MySqlLeaseMgrTest, getExpiredLeases4) {
     testGetExpiredLeases4();
 }
 
+/// @brief Checks that the static (i.e. with infinite valid lifetime) DHCPv4
+/// leases will never expire.
+TEST_F(MySqlLeaseMgrTest, staticLeases4) {
+    testStaticLeases4();
+}
+
 /// @brief Check that expired reclaimed DHCPv4 leases are removed.
 TEST_F(MySqlLeaseMgrTest, deleteExpiredReclaimedLeases4) {
     testDeleteExpiredReclaimedLeases4();
@@ -432,6 +443,11 @@ TEST_F(MySqlLeaseMgrTest, maxDate6) {
     testMaxDate6();
 }
 
+/// @brief checks that infinite lifetimes do not overflow.
+TEST_F(MySqlLeaseMgrTest, infiniteLifeTime6) {
+    testInfiniteLifeTime6();
+}
+
 /// @brief Verify that too long hostname for Lease6 is not accepted.
 ///
 /// Checks that the it is not possible to create a lease when the hostname
@@ -543,6 +559,12 @@ TEST_F(MySqlLeaseMgrTest, getExpiredLeases6) {
     testGetExpiredLeases6();
 }
 
+/// @brief Checks that the static (i.e. with infinite valid lifetime) DHCPv6
+/// leases will never expire.
+TEST_F(MySqlLeaseMgrTest, staticLeases6) {
+    testStaticLeases6();
+}
+
 /// @brief Check that expired reclaimed DHCPv6 leases are removed.
 TEST_F(MySqlLeaseMgrTest, deleteExpiredReclaimedLeases6) {
     testDeleteExpiredReclaimedLeases6();
index ec783594b879fa57b4cbbc16fb701d871cb59ec7..6e162715bd6a2edf9c76d69a6015f737f711948c 100644 (file)
@@ -267,6 +267,11 @@ TEST_F(PgSqlLeaseMgrTest, maxDate4) {
     testMaxDate4();
 }
 
+/// @brief checks that infinite lifetimes do not overflow.
+TEST_F(PgSqlLeaseMgrTest, infiniteLifeTime4) {
+    testInfiniteLifeTime4();
+}
+
 /// @brief Lease4 update tests
 ///
 /// Checks that we are able to update a lease in the database.
@@ -394,6 +399,12 @@ TEST_F(PgSqlLeaseMgrTest, getExpiredLeases4) {
     testGetExpiredLeases4();
 }
 
+/// @brief Checks that the static (i.e. with infinite valid lifetime) DHCPv4
+/// leases will never expire.
+TEST_F(PgSqlLeaseMgrTest, staticLeases4) {
+    testStaticLeases4();
+}
+
 /// @brief Check that expired reclaimed DHCPv4 leases are removed.
 TEST_F(PgSqlLeaseMgrTest, deleteExpiredReclaimedLeases4) {
     testDeleteExpiredReclaimedLeases4();
@@ -422,6 +433,11 @@ TEST_F(PgSqlLeaseMgrTest, maxDate6) {
     testMaxDate6();
 }
 
+/// @brief checks that infinite lifetimes do not overflow.
+TEST_F(PgSqlLeaseMgrTest, infiniteLifeTime6) {
+    testInfiniteLifeTime6();
+}
+
 /// @brief Verify that too long hostname for Lease6 is not accepted.
 ///
 /// Checks that the it is not possible to create a lease when the hostname
@@ -533,6 +549,12 @@ TEST_F(PgSqlLeaseMgrTest, getExpiredLeases6) {
     testGetExpiredLeases6();
 }
 
+/// @brief Checks that the static (i.e. with infinite valid lifetime) DHCPv6
+/// leases will never expire.
+TEST_F(PgSqlLeaseMgrTest, staticLeases6) {
+    testStaticLeases6();
+}
+
 /// @brief Check that expired reclaimed DHCPv6 leases are removed.
 TEST_F(PgSqlLeaseMgrTest, deleteExpiredReclaimedLeases6) {
     testDeleteExpiredReclaimedLeases6();