Browse Source

[2325] Remaining tests for RENEW implemented.

Tomek Mrugalski 12 years ago
parent
commit
936137b0b1
1 changed files with 90 additions and 24 deletions
  1. 90 24
      src/bin/dhcp6/tests/dhcp6_srv_unittest.cc

+ 90 - 24
src/bin/dhcp6/tests/dhcp6_srv_unittest.cc

@@ -141,6 +141,31 @@ public:
         return (addr);
     }
 
+    // Checks that server rejected IA_NA, i.e. that it has no addresses and
+    // that expected status code really appears there.
+    // Status code indicates type of error encountered (in theory it can also
+    // indicate success, but servers typically don't send success status
+    // as this is the default result and it saves bandwidth)
+    void checkRejectedIA_NA(const boost::shared_ptr<Option6IA>& ia,
+                            uint16_t expected_status_code) {
+        // Make sure there is no address assigned.
+        EXPECT_FALSE(ia->getOption(D6O_IAADDR));
+
+        // T1, T2 should be zeroed
+        EXPECT_EQ(0, ia->getT1());
+        EXPECT_EQ(0, ia->getT2());
+
+        OptionPtr status = ia->getOption(D6O_STATUS_CODE);
+        EXPECT_TRUE(status);
+
+        if (status) {
+            // We don't have dedicated class for status code, so let's just interpret
+            // first 2 bytes as status. Remainder of the status code option content is
+            // just a text explanation what went wrong.
+            EXPECT_EQ(static_cast<uint16_t>(expected_status_code), status->getUint16());
+        }
+    }
+
     // Check that generated IAADDR option contains expected address.
     void checkIAAddr(const boost::shared_ptr<Option6IAAddr>& addr,
                      const IOAddress& expected_addr,
@@ -845,22 +870,29 @@ TEST_F(Dhcpv6SrvTest, RenewBasic) {
     // 1 >= difference between cltt and expected
     EXPECT_GE(1, abs(cltt - expected));
 
-    LeaseMgrFactory::instance().deleteLease6(addr_opt->getAddress());
+    EXPECT_TRUE(LeaseMgrFactory::instance().deleteLease6(addr_opt->getAddress()));
 }
 
-// This test verifies that incoming (negative) RENEW can be handled properly.
-// Client tries to RENEW an address that was never assigned to him.
+// This test verifies that incoming (invalid) RENEW can be handled properly.
+//
+// This test checks 3 scenarios:
+// 1. there is no such lease at all
+// 2. there is such a lease, but it is assigned to a different IAID
+// 3. there is such a lease, but it belongs to a different client
+//
 // expected:
 // - returned REPLY message has copy of client-id
 // - returned REPLY message has server-id
 // - returned REPLY message has IA that includes STATUS-CODE
 // - No lease in LeaseMgr
-TEST_F(Dhcpv6SrvTest, RenewNoLease) {
+TEST_F(Dhcpv6SrvTest, RenewReject) {
     boost::scoped_ptr<NakedDhcpv6Srv> srv;
     ASSERT_NO_THROW( srv.reset(new NakedDhcpv6Srv(0)) );
 
     IOAddress addr("2001:db8:1:1::dead");
-    const uint32_t iaid = 234;
+    const uint32_t transid = 1234;
+    const uint32_t valid_iaid = 234;
+    const uint32_t bogus_iaid = 456;
 
     // generate client-id also duid_
     OptionPtr clientid = generateClientId();
@@ -870,9 +902,9 @@ TEST_F(Dhcpv6SrvTest, RenewNoLease) {
     ASSERT_FALSE(l);
 
     // Let's create a RENEW
-    Pkt6Ptr req = Pkt6Ptr(new Pkt6(DHCPV6_RENEW, 1234));
+    Pkt6Ptr req = Pkt6Ptr(new Pkt6(DHCPV6_RENEW, transid));
     req->setRemoteAddr(IOAddress("fe80::abcd"));
-    boost::shared_ptr<Option6IA> ia = generateIA(iaid, 1500, 3000);
+    boost::shared_ptr<Option6IA> ia = generateIA(bogus_iaid, 1500, 3000);
 
     ASSERT_TRUE(subnet_->inPool(addr));
     OptionPtr renewed_addr_opt(new Option6IAAddr(D6O_IAADDR, addr, 300, 500));
@@ -883,36 +915,70 @@ TEST_F(Dhcpv6SrvTest, RenewNoLease) {
     // server-id is mandatory in RENEW
     req->addOption(srv->getServerID());
 
+    // Case 1: No lease known to server
+
     // Pass it to the server and hope for a REPLY
     Pkt6Ptr reply = srv->processRenew(req);
 
-    // check if we get response at all
-    checkResponse(reply, DHCPV6_REPLY, 1234);
-
+    // Check if we get response at all
+    checkResponse(reply, DHCPV6_REPLY, transid);
     OptionPtr tmp = reply->getOption(D6O_IA_NA);
     ASSERT_TRUE(tmp);
+    // Check that IA_NA was returned and that there's an address included
+    ia = boost::dynamic_pointer_cast<Option6IA>(tmp);
+    ASSERT_TRUE(ia);
+    checkRejectedIA_NA(ia, STATUS_NoAddrsAvail);
 
-    // check that IA_NA was returned and that there's an address included
+    // Check that there is no lease added
+    l = LeaseMgrFactory::instance().getLease6(addr);
+    ASSERT_FALSE(l);
+
+    // CASE 2: Lease is known and belongs to this client, but to a different IAID
+
+    // Note that preferred, valid, T1 and T2 timers and CLTT are set to invalid
+    // value on purpose. They should be updated during RENEW.
+    Lease6Ptr lease(new Lease6(Lease6::LEASE_IA_NA, addr, duid_, valid_iaid,
+                               501, 502, 503, 504, subnet_->getID(), 0));
+    lease->cltt_ = 123; // Let's use it as an indicator that the lease
+                        // was NOT updated.
+    ASSERT_TRUE(LeaseMgrFactory::instance().addLease(lease));
+
+    // Pass it to the server and hope for a REPLY
+    reply = srv->processRenew(req);
+    checkResponse(reply, DHCPV6_REPLY, transid);
+    tmp = reply->getOption(D6O_IA_NA);
+    ASSERT_TRUE(tmp);
+    // Check that IA_NA was returned and that there's an address included
     ia = boost::dynamic_pointer_cast<Option6IA>(tmp);
     ASSERT_TRUE(ia);
+    checkRejectedIA_NA(ia, STATUS_NoAddrsAvail);
 
-    // Make sure there is no address assigned.
-    EXPECT_FALSE(ia->getOption(D6O_IAADDR));
+    // There is a iaid mis-match, so server should respond that there is
+    // no such address to renew.
 
-    // T1, T2 should be zeroed
-    EXPECT_EQ(0, ia->getT1());
-    EXPECT_EQ(0, ia->getT2());
+    // CASE 3: Lease belongs to a client with different client-id
+    req->delOption(D6O_CLIENTID);
+    ia = boost::dynamic_pointer_cast<Option6IA>(req->getOption(D6O_IA_NA));
+    ia->setIAID(valid_iaid); // Now iaid in renew matches that in leasemgr
+    req->addOption(generateClientId(13)); // generate different DUID
+                                          // (with length 13)
+
+    reply = srv->processRenew(req);
+    checkResponse(reply, DHCPV6_REPLY, transid);
+    tmp = reply->getOption(D6O_IA_NA);
+    ASSERT_TRUE(tmp);
+    // Check that IA_NA was returned and that there's an address included
+    ia = boost::dynamic_pointer_cast<Option6IA>(tmp);
+    ASSERT_TRUE(ia);
+    checkRejectedIA_NA(ia, STATUS_NoAddrsAvail);
 
-    OptionPtr status = ia->getOption(D6O_STATUS_CODE);
-    ASSERT_TRUE(status);
 
-    // We don't have dedicated class for status code, so let's just interpret
-    // first 2 bytes as status. Remainder of the status code option is just
-    // a text explanation what went wrong.
-    EXPECT_EQ(static_cast<uint16_t>(STATUS_NoAddrsAvail), status->getUint16());
+    lease = LeaseMgrFactory::instance().getLease6(addr);
+    ASSERT_TRUE(lease);
+    // Verify that the lease was not updated.
+    EXPECT_EQ(123, lease->cltt_);
 
-    l = LeaseMgrFactory::instance().getLease6(addr);
-    ASSERT_FALSE(l);
+    EXPECT_TRUE(LeaseMgrFactory::instance().deleteLease6(addr));
 }
 
 // This test verifies if the status code option is generated properly.