Browse Source

[3035] Added functions to check that two leases belong to the same client.

Marcin Siodelski 11 years ago
parent
commit
782e4e8e61
3 changed files with 186 additions and 63 deletions
  1. 43 37
      src/lib/dhcpsrv/lease_mgr.cc
  2. 28 0
      src/lib/dhcpsrv/lease_mgr.h
  3. 115 26
      src/lib/dhcpsrv/tests/lease_mgr_unittest.cc

+ 43 - 37
src/lib/dhcpsrv/lease_mgr.cc

@@ -156,11 +156,10 @@ Lease4::toText() const {
     return (stream.str());
 }
 
-
 bool
-Lease4::operator==(const Lease4& other) const {
-    if ( (client_id_ && !other.client_id_) ||
-         (!client_id_ && other.client_id_) ) {
+Lease4::matches(const Lease4& other) const {
+    if ((client_id_ && !other.client_id_) ||
+        (!client_id_ && other.client_id_)) {
         // One lease has client-id, but the other doesn't
         return false;
     }
@@ -171,43 +170,50 @@ Lease4::operator==(const Lease4& other) const {
         return false;
     }
 
-    return (
-        addr_ == other.addr_ &&
-        ext_ == other.ext_ &&
-        hwaddr_ == other.hwaddr_ &&
-        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_
-    );
+    return (addr_ == other.addr_ &&
+            ext_ == other.ext_ &&
+            hwaddr_ == other.hwaddr_);
+
+}
+
+bool
+Lease4::operator==(const Lease4& other) const {
+    return (matches(other) &&
+            subnet_id_ == other.subnet_id_ &&
+            t1_ == other.t1_ &&
+            t2_ == other.t2_ &&
+            valid_lft_ == other.valid_lft_ &&
+            cltt_ == other.cltt_ &&
+            fixed_ == other.fixed_ &&
+            hostname_ == other.hostname_ &&
+            fqdn_fwd_ == other.fqdn_fwd_ &&
+            fqdn_rev_ == other.fqdn_rev_ &&
+            comments_ == other.comments_);
+}
+
+bool
+Lease6::matches(const Lease6& other) const {
+    return (addr_ == other.addr_ &&
+            type_ == other.type_ &&
+            prefixlen_ == other.prefixlen_ &&
+            iaid_ == other.iaid_ &&
+            *duid_ == *other.duid_);
 }
 
 bool
 Lease6::operator==(const Lease6& other) const {
-    return (
-        addr_ == other.addr_ &&
-        type_ == other.type_ &&
-        prefixlen_ == other.prefixlen_ &&
-        iaid_ == other.iaid_ &&
-        *duid_ == *other.duid_ &&
-        preferred_lft_ == other.preferred_lft_ &&
-        valid_lft_ == other.valid_lft_ &&
-        t1_ == other.t1_ &&
-        t2_ == other.t2_ &&
-        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_
-    );
+    return (matches(other) &&
+            preferred_lft_ == other.preferred_lft_ &&
+            valid_lft_ == other.valid_lft_ &&
+            t1_ == other.t1_ &&
+            t2_ == other.t2_ &&
+            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_);
 }
 
 } // namespace isc::dhcp

+ 28 - 0
src/lib/dhcpsrv/lease_mgr.h

@@ -264,6 +264,20 @@ struct Lease4 : public Lease {
     /// @param other the @c Lease4 object to be copied.
     Lease4(const Lease4& other);
 
+    /// @brief Check if two objects encapsulate the lease for the same
+    /// client.
+    ///
+    /// Checks if two @c Lease4 objects have the same address, client id,
+    /// HW address and ext_ value.  If these parameters match it is an
+    /// indication that both objects describe the lease for the same
+    /// client but apparently one is a result of renewal of the other. The
+    /// special case of the matching lease is the one that is equal to another.
+    ///
+    /// @param other A lease to compare with.
+    ///
+    /// @return true if the selected parameters of the two leases match.
+    bool matches(const Lease4& other) const;
+
     /// @brief Assignment operator.
     ///
     /// @param other the @c Lease4 object to be assigned.
@@ -352,6 +366,20 @@ struct Lease6 : public Lease {
         type_(LEASE_IA_NA) {
     }
 
+    /// @brief Checks if two lease objects encapsulate the lease for the same
+    /// client.
+    ///
+    /// This function compares address, type, prefix length, IAID and DUID
+    /// parameters between two @c Lease6 objects. If these parameters match
+    /// it is an indication that both objects describe the lease for the same
+    /// client but apparently one is a result of renewal of the other. The
+    /// special case of the matching lease is the one that is equal to another.
+    ///
+    /// @param other A lease to compare to.
+    ///
+    /// @return true if selected parameters of the two leases match.
+    bool matches(const Lease6& other) const;
+
     /// @brief Compare two leases for equality
     ///
     /// @param other lease6 object with which to compare

+ 115 - 26
src/lib/dhcpsrv/tests/lease_mgr_unittest.cc

@@ -221,6 +221,17 @@ public:
 
 namespace {
 
+/// Hardware address used by different tests.
+const uint8_t HWADDR[] = {0x08, 0x00, 0x2b, 0x02, 0x3f, 0x4e};
+/// Client id used by different tests.
+const uint8_t CLIENTID[] = {0x17, 0x34, 0xe2, 0xff, 0x09, 0x92, 0x54};
+/// Valid lifetime value used by different tests.
+const uint32_t VALID_LIFETIME = 500;
+/// Subnet ID used by different tests.
+const uint32_t SUBNET_ID = 42;
+/// IAID value used by different tests.
+const uint32_t IAID = 7;
+
 /// @brief getParameter test
 ///
 /// This test checks if the LeaseMgr can be instantiated and that it
@@ -248,20 +259,14 @@ TEST(LeaseMgr, getParameter) {
 TEST(Lease4, constructor) {
 
     // 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;
-
     // We want to check that various addresses work, so let's iterate over
     // these.
     const uint32_t ADDRESS[] = {
@@ -296,20 +301,14 @@ TEST(Lease4, constructor) {
 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,
@@ -330,20 +329,14 @@ TEST(Lease4, copyConstructor) {
 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,
@@ -359,6 +352,52 @@ TEST(Lease4, operatorAssign) {
     EXPECT_FALSE(lease.client_id_ == copied_lease.client_id_);
 }
 
+// This test verifies that the matches() returns true if two leases differ
+// by values other than address, HW address, Client ID and ext_.
+TEST(Lease4, matches) {
+    // Create two leases which share the same address, HW address, client id
+    // and ext_ value.
+    const time_t current_time = time(NULL);
+    Lease4 lease1(IOAddress("192.0.2.3"), HWADDR, sizeof(HWADDR), CLIENTID,
+                  sizeof(CLIENTID), VALID_LIFETIME, current_time, 0, 0,
+                  SUBNET_ID);
+    lease1.hostname_ = "lease1.example.com.";
+    lease1.fqdn_fwd_ = true;
+    lease1.fqdn_rev_ = true;
+    Lease4 lease2(IOAddress("192.0.2.3"), HWADDR, sizeof(HWADDR), CLIENTID,
+                  sizeof(CLIENTID), VALID_LIFETIME + 10, current_time - 10,
+                  100, 200, SUBNET_ID);
+    lease2.hostname_ = "lease2.example.com.";
+    lease2.fqdn_fwd_ = false;
+    lease2.fqdn_rev_ = true;
+
+    // Leases should match.
+    EXPECT_TRUE(lease1.matches(lease2));
+    EXPECT_TRUE(lease2.matches(lease1));
+
+    // Change address, leases should not match anymore.
+    lease1.addr_ = IOAddress("192.0.2.4");
+    EXPECT_FALSE(lease1.matches(lease2));
+    lease1.addr_ = lease2.addr_;
+
+    // Change HW address, leases should not match.
+    lease1.hwaddr_[1] += 1;
+    EXPECT_FALSE(lease1.matches(lease2));
+    lease1.hwaddr_ = lease2.hwaddr_;
+
+    // Chanage client id, leases should not match.
+    std::vector<uint8_t> client_id = lease1.client_id_->getClientId();
+    client_id[1] += 1;
+    lease1.client_id_.reset(new ClientId(client_id));
+    EXPECT_FALSE(lease1.matches(lease2));
+    lease1.client_id_ = lease2.client_id_;
+
+    // Change ext_, leases should not match.
+    lease1.ext_ += 1;
+    EXPECT_FALSE(lease1.matches(lease2));
+    lease1.ext_ = lease2.ext_;
+}
+
 /// @brief Lease4 Equality Test
 ///
 /// Checks that the operator==() correctly compares two leases for equality.
@@ -368,14 +407,11 @@ TEST(Lease4, operatorEquals) {
 
     // Random values for the tests
     const uint32_t ADDRESS = 0x01020304;
-    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);
     const time_t current_time = time(NULL);
-    const uint32_t SUBNET_ID = 42;
-    const uint32_t VALID_LIFETIME = 500;
 
     // Check when the leases are equal.
     Lease4 lease1(ADDRESS, HWADDR, sizeof(HWADDR),
@@ -507,18 +543,17 @@ TEST(Lease6, Lease6Constructor) {
     // Other values
     uint8_t llt[] = {0, 1, 2, 3, 4, 5, 6, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf};
     DuidPtr duid(new DUID(llt, sizeof(llt)));
-    uint32_t iaid = 7;      // Just a number
     SubnetID subnet_id = 8; // Just another number
 
     for (int i = 0; i < sizeof(ADDRESS) / sizeof(ADDRESS[0]); ++i) {
         IOAddress addr(ADDRESS[i]);
         Lease6Ptr lease(new Lease6(Lease6::LEASE_IA_NA, addr,
-                               duid, iaid, 100, 200, 50, 80,
+                               duid, IAID, 100, 200, 50, 80,
                                subnet_id));
 
         EXPECT_TRUE(lease->addr_ == addr);
         EXPECT_TRUE(*lease->duid_ == *duid);
-        EXPECT_TRUE(lease->iaid_ == iaid);
+        EXPECT_TRUE(lease->iaid_ == IAID);
         EXPECT_TRUE(lease->subnet_id_ == subnet_id);
         EXPECT_TRUE(lease->type_ == Lease6::LEASE_IA_NA);
         EXPECT_TRUE(lease->preferred_lft_ == 100);
@@ -531,16 +566,70 @@ TEST(Lease6, Lease6Constructor) {
     IOAddress addr(ADDRESS[0]);
     Lease6Ptr lease2;
     EXPECT_THROW(lease2.reset(new Lease6(Lease6::LEASE_IA_NA, addr,
-                                         DuidPtr(), iaid, 100, 200, 50, 80,
+                                         DuidPtr(), IAID, 100, 200, 50, 80,
                                          subnet_id)), InvalidOperation);
 }
 
+// This test verifies that the matches() function returns true if two leases
+// differ by values other than address, type, prefix length, IAID and DUID.
+TEST(Lease6, matches) {
+
+    // Create two matching leases.
+    uint8_t llt[] = {0, 1, 2, 3, 4, 5, 6, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf};
+    DuidPtr duid(new DUID(llt, sizeof(llt)));
+
+    Lease6 lease1(Lease6::LEASE_IA_NA, IOAddress("2001:db8:1::1"), duid,
+                                                 IAID, 100, 200, 50, 80,
+                                                 SUBNET_ID);
+    lease1.hostname_ = "lease1.example.com.";
+    lease1.fqdn_fwd_ = true;
+    lease1.fqdn_rev_ = true;
+    Lease6 lease2(Lease6::LEASE_IA_NA, IOAddress("2001:db8:1::1"), duid,
+                                                 IAID, 200, 300, 90, 70,
+                                                 SUBNET_ID);
+    lease2.hostname_ = "lease1.example.com.";
+    lease2.fqdn_fwd_ = false;
+    lease2.fqdn_rev_ = true;
+
+    EXPECT_TRUE(lease1.matches(lease2));
+
+    // Modify each value used to match both leases, and make sure that
+    // leases don't match.
+
+    // Modify address.
+    lease1.addr_ = IOAddress("2001:db8:1::2");
+    EXPECT_FALSE(lease1.matches(lease2));
+    lease1.addr_ = lease2.addr_;
+
+    // Modify lease type.
+    lease1.type_ = Lease6::LEASE_IA_TA;
+    EXPECT_FALSE(lease1.matches(lease2));
+    lease1.type_ = lease2.type_;
+
+    // Modify prefix length.
+    lease1.prefixlen_ += 1;
+    EXPECT_FALSE(lease1.matches(lease2));
+    lease1.prefixlen_ = lease2.prefixlen_;
+
+    // Modify IAID.
+    lease1.iaid_ += 1;
+    EXPECT_FALSE(lease1.matches(lease2));
+    lease1.iaid_ = lease2.iaid_;
+
+    // Modify DUID.
+    llt[1] += 1;
+    duid.reset(new DUID(llt, sizeof(llt)));
+    lease1.duid_ = duid;
+    EXPECT_FALSE(lease1.matches(lease2));
+    lease1.duid_ = lease2.duid_;
+}
+
 /// @brief Lease6 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(Lease6, OperatorEquals) {
+TEST(Lease6, operatorEquals) {
 
     // check a variety of addresses with different bits set.
     const IOAddress addr("2001:db8:1::456");