From: Francis Dupont Date: Wed, 22 Jun 2016 21:56:58 +0000 (+0200) Subject: [4500] copied renew tests to use rebind without server-id X-Git-Tag: trac4273_base~2^2~3 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=e97d758ee3ff8b27dad65a8a7674e4a98004c1dc;p=thirdparty%2Fkea.git [4500] copied renew tests to use rebind without server-id --- diff --git a/src/bin/dhcp6/tests/hooks_unittest.cc b/src/bin/dhcp6/tests/hooks_unittest.cc index aec9c260f0..d476b6078c 100644 --- a/src/bin/dhcp6/tests/hooks_unittest.cc +++ b/src/bin/dhcp6/tests/hooks_unittest.cc @@ -56,6 +56,8 @@ TEST_F(Dhcpv6SrvTest, Hooks) { int hook_index_buffer6_send = -1; int hook_index_lease6_renew = -1; int hook_index_lease6_release = -1; + int hook_index_lease6_rebind = -1; + int hook_index_lease6_decline = -1; int hook_index_pkt6_received = -1; int hook_index_select_subnet = -1; int hook_index_pkt6_send = -1; @@ -69,6 +71,10 @@ TEST_F(Dhcpv6SrvTest, Hooks) { .getIndex("lease6_renew")); EXPECT_NO_THROW(hook_index_lease6_release = ServerHooks::getServerHooks() .getIndex("lease6_release")); + EXPECT_NO_THROW(hook_index_lease6_rebind = ServerHooks::getServerHooks() + .getIndex("lease6_rebind")); + EXPECT_NO_THROW(hook_index_lease6_decline = ServerHooks::getServerHooks() + .getIndex("lease6_decline")); EXPECT_NO_THROW(hook_index_pkt6_received = ServerHooks::getServerHooks() .getIndex("pkt6_receive")); EXPECT_NO_THROW(hook_index_select_subnet = ServerHooks::getServerHooks() @@ -83,6 +89,8 @@ TEST_F(Dhcpv6SrvTest, Hooks) { EXPECT_TRUE(hook_index_buffer6_send > 0); EXPECT_TRUE(hook_index_lease6_renew > 0); EXPECT_TRUE(hook_index_lease6_release > 0); + EXPECT_TRUE(hook_index_lease6_rebind > 0); + EXPECT_TRUE(hook_index_lease6_decline > 0); } /// @brief a class dedicated to Hooks testing in DHCPv6 server @@ -382,22 +390,6 @@ public: return (0); } - /// Test callback that stores received callout name and pkt6 value - /// @param callout_handle handle passed by the hooks framework - /// @return always 0 - static int - lease6_rebind_callout(CalloutHandle& callout_handle) { - callback_name_ = string("lease6_rebind"); - - callout_handle.getArgument("query6", callback_qry_pkt6_); - callout_handle.getArgument("lease6", callback_lease6_); - callout_handle.getArgument("ia_na", callback_ia_na_); - - callback_argument_names_ = callout_handle.getArgumentNames(); - return (0); - } - - /// The following values are used by the callout to override /// renewed lease parameters static const uint32_t override_iaid_; @@ -446,6 +438,72 @@ public: return (0); } + /// Test callback that stores received callout name and pkt6 value + /// @param callout_handle handle passed by the hooks framework + /// @return always 0 + static int + lease6_rebind_callout(CalloutHandle& callout_handle) { + callback_name_ = string("lease6_rebind"); + + callout_handle.getArgument("query6", callback_qry_pkt6_); + callout_handle.getArgument("lease6", callback_lease6_); + callout_handle.getArgument("ia_na", callback_ia_na_); + + callback_argument_names_ = callout_handle.getArgumentNames(); + return (0); + } + + /// Test callback that overrides received lease. It updates + /// T1, T2, preferred and valid lifetimes + /// @param callout_handle handle passed by the hooks framework + /// @return always 0 + static int + lease6_rebind_update_callout(CalloutHandle& callout_handle) { + callback_name_ = string("lease6_rebind"); + + callout_handle.getArgument("query6", callback_qry_pkt6_); + callout_handle.getArgument("lease6", callback_lease6_); + callout_handle.getArgument("ia_na", callback_ia_na_); + + // Let's override some values in the lease + callback_lease6_->iaid_ = override_iaid_; + callback_lease6_->t1_ = override_t1_; + callback_lease6_->t2_ = override_t2_; + callback_lease6_->preferred_lft_ = override_preferred_; + callback_lease6_->valid_lft_ = override_valid_; + + // Override the values to be sent to the client as well + callback_ia_na_->setIAID(override_iaid_); + callback_ia_na_->setT1(override_t1_); + callback_ia_na_->setT2(override_t2_); + + callback_argument_names_ = callout_handle.getArgumentNames(); + return (0); + } + + /// Lease6_rebind callout that sets status to SKIP + /// + /// @param callout_handle handle passed by the hooks framework + /// @return always 0 + static int + lease6_rebind_skip_callout(CalloutHandle& callout_handle) { + callout_handle.setStatus(CalloutHandle::NEXT_STEP_SKIP); + + return (lease6_rebind_callout(callout_handle)); + } + + /// Lease6_rebind callout that sets status to DROP + /// + /// @param callout_handle handle passed by the hooks framework + /// @return always 0 + static int + lease6_rebind_drop_callout(CalloutHandle& callout_handle) { + callout_handle.setStatus(CalloutHandle::NEXT_STEP_DROP); + + return (lease6_rebind_callout(callout_handle)); + } + + /// Test callback that stores received callout name passed parameters /// @param callout_handle handle passed by the hooks framework /// @return always 0 @@ -538,7 +596,7 @@ public: /// Pointer to lease6 static Lease6Ptr callback_lease6_; - /// Pointer to IA_NA option being renewed + /// Pointer to IA_NA option being renewed or rebound static boost::shared_ptr callback_ia_na_; /// Pointer to a subnet received by callout @@ -1544,6 +1602,260 @@ TEST_F(HooksDhcpv6SrvTest, skipLease6Release) { ASSERT_TRUE(l); } +// This test verifies that incoming (positive) REBIND can be handled properly, +// and the lease6_rebind callouts are triggered. +TEST_F(HooksDhcpv6SrvTest, basicLease6Rebind) { + NakedDhcpv6Srv srv(0); + + // Install pkt6_receive_callout + EXPECT_NO_THROW(HooksManager::preCalloutsLibraryHandle().registerCallout( + "lease6_rebind", lease6_rebind_callout)); + + const IOAddress addr("2001:db8:1:1::cafe:babe"); + const uint32_t iaid = 234; + + // Generate client-id also duid_ + OptionPtr clientid = generateClientId(); + + // Check that the address we are about to use is indeed in pool + ASSERT_TRUE(subnet_->inPool(Lease::TYPE_NA, addr)); + + // Note that preferred, valid, T1 and T2 timers and CLTT are set to invalid + // value on purpose. They should be updated during REBIND. + Lease6Ptr lease(new Lease6(Lease::TYPE_NA, addr, duid_, iaid, + 501, 502, 503, 504, subnet_->getID(), + HWAddrPtr(), 0)); + lease->cltt_ = 1234; + ASSERT_TRUE(LeaseMgrFactory::instance().addLease(lease)); + + // Check that the lease is really in the database + Lease6Ptr l = LeaseMgrFactory::instance().getLease6(Lease::TYPE_NA, + addr); + ASSERT_TRUE(l); + + // Check that T1, T2, preferred, valid and cltt really set and not using + // previous (500, 501, etc.) values + EXPECT_NE(l->t1_, subnet_->getT1()); + EXPECT_NE(l->t2_, subnet_->getT2()); + EXPECT_NE(l->preferred_lft_, subnet_->getPreferred()); + EXPECT_NE(l->valid_lft_, subnet_->getValid()); + EXPECT_NE(l->cltt_, time(NULL)); + + // Let's create a REBIND + Pkt6Ptr req = Pkt6Ptr(new Pkt6(DHCPV6_REBIND, 1234)); + req->setRemoteAddr(IOAddress("fe80::abcd")); + req->setIface("eth0"); + boost::shared_ptr ia = generateIA(D6O_IA_NA, iaid, 1500, 3000); + + OptionPtr rebound_addr_opt(new Option6IAAddr(D6O_IAADDR, addr, 300, 500)); + ia->addOption(rebound_addr_opt); + req->addOption(ia); + req->addOption(clientid); + + // Pass it to the server and hope for a REPLY + Pkt6Ptr reply = srv.processRebind(req); + ASSERT_TRUE(reply); + + // Check that the callback called is indeed the one we installed + EXPECT_EQ("lease6_rebind", callback_name_); + + // Check that appropriate parameters are passed to the callouts + EXPECT_TRUE(callback_qry_pkt6_); + EXPECT_TRUE(callback_lease6_); + EXPECT_TRUE(callback_ia_na_); + + // Check if all expected parameters were really received + vector expected_argument_names; + expected_argument_names.push_back("query6"); + expected_argument_names.push_back("lease6"); + expected_argument_names.push_back("ia_na"); + + sort(callback_argument_names_.begin(), callback_argument_names_.end()); + sort(expected_argument_names.begin(), expected_argument_names.end()); + + EXPECT_TRUE(callback_argument_names_ == expected_argument_names); + + // Check if we get response at all + checkResponse(reply, DHCPV6_REPLY, 1234); + + OptionPtr tmp = reply->getOption(D6O_IA_NA); + ASSERT_TRUE(tmp); + + // Check that IA_NA was returned and that there's an address included + boost::shared_ptr addr_opt = checkIA_NA(reply, 234, subnet_->getT1(), + subnet_->getT2()); + + ASSERT_TRUE(addr_opt); + // Check that the lease is really in the database + l = checkLease(duid_, reply->getOption(D6O_IA_NA), addr_opt); + ASSERT_TRUE(l); + + // Check that the lease has been returned + ASSERT_TRUE(callback_lease6_); + + // Check that the returned lease6 in callout is the same as the one in the + // database + EXPECT_TRUE(*callback_lease6_ == *l); +} + +// This test verifies that incoming (positive) REBIND can be handled properly, +// and the lease6_rebind callouts are able to change the lease being updated. +TEST_F(HooksDhcpv6SrvTest, leaseUpdateLease6Rebind) { + NakedDhcpv6Srv srv(0); + + // Install pkt6_receive_callout + EXPECT_NO_THROW(HooksManager::preCalloutsLibraryHandle().registerCallout( + "lease6_rebind", lease6_rebind_update_callout)); + + const IOAddress addr("2001:db8:1:1::cafe:babe"); + const uint32_t iaid = 234; + + // Generate client-id also duid_ + OptionPtr clientid = generateClientId(); + + // Check that the address we are about to use is indeed in pool + ASSERT_TRUE(subnet_->inPool(Lease::TYPE_NA, addr)); + + // Note that preferred, valid, T1 and T2 timers and CLTT are set to invalid + // value on purpose. They should be updated during REBIND. + Lease6Ptr lease(new Lease6(Lease::TYPE_NA, addr, duid_, iaid, + 501, 502, 503, 504, subnet_->getID(), + HWAddrPtr(), 0)); + lease->cltt_ = 1234; + ASSERT_TRUE(LeaseMgrFactory::instance().addLease(lease)); + + // Check that the lease is really in the database + Lease6Ptr l = LeaseMgrFactory::instance().getLease6(Lease::TYPE_NA, + addr); + ASSERT_TRUE(l); + + // Check that T1, T2, preferred, valid and cltt really set and not using + // previous (500, 501, etc.) values + EXPECT_NE(l->t1_, subnet_->getT1()); + EXPECT_NE(l->t2_, subnet_->getT2()); + EXPECT_NE(l->preferred_lft_, subnet_->getPreferred()); + EXPECT_NE(l->valid_lft_, subnet_->getValid()); + EXPECT_NE(l->cltt_, time(NULL)); + + // Let's create a REBIND + Pkt6Ptr req = Pkt6Ptr(new Pkt6(DHCPV6_REBIND, 1234)); + req->setRemoteAddr(IOAddress("fe80::abcd")); + req->setIface("eth0"); + boost::shared_ptr ia = generateIA(D6O_IA_NA, iaid, 1500, 3000); + + OptionPtr rebound_addr_opt(new Option6IAAddr(D6O_IAADDR, addr, 300, 500)); + ia->addOption(rebound_addr_opt); + req->addOption(ia); + req->addOption(clientid); + + // Pass it to the server and hope for a REPLY + Pkt6Ptr reply = srv.processRebind(req); + ASSERT_TRUE(reply); + + // Check if we get response at all + checkResponse(reply, DHCPV6_REPLY, 1234); + + OptionPtr tmp = reply->getOption(D6O_IA_NA); + ASSERT_TRUE(tmp); + + // Check that IA_NA was returned and that there's an address included + boost::shared_ptr addr_opt = checkIA_NA(reply, 1000, 1001, 1002); + + ASSERT_TRUE(addr_opt); + // Check that the lease is really in the database + l = checkLease(duid_, reply->getOption(D6O_IA_NA), addr_opt); + ASSERT_TRUE(l); + + // Check that we chose the distinct override values + ASSERT_NE(override_t1_, subnet_->getT1()); + ASSERT_NE(override_t2_, subnet_->getT2()); + ASSERT_NE(override_preferred_, subnet_->getPreferred()); + EXPECT_NE(override_valid_, subnet_->getValid()); + + // Check that T1, T2, preferred, valid were overridden the the callout + EXPECT_EQ(override_t1_, l->t1_); + EXPECT_EQ(override_t2_, l->t2_); + EXPECT_EQ(override_preferred_, l->preferred_lft_); + EXPECT_EQ(override_valid_, l->valid_lft_); + + // Checking for CLTT is a bit tricky if we want to avoid off by 1 errors + int32_t cltt = static_cast(l->cltt_); + int32_t expected = static_cast(time(NULL)); + // Equality or difference by 1 between cltt and expected is ok. + EXPECT_GE(1, abs(cltt - expected)); + + EXPECT_TRUE(LeaseMgrFactory::instance().deleteLease(addr_opt->getAddress())); +} + +// This test verifies that incoming (positive) REBIND can be handled properly, +// and the lease6_rebind callouts are able to set the skip flag that will +// reject the rebinding +TEST_F(HooksDhcpv6SrvTest, skipLease6Rebind) { + NakedDhcpv6Srv srv(0); + + // Install pkt6_receive_callout + EXPECT_NO_THROW(HooksManager::preCalloutsLibraryHandle().registerCallout( + "lease6_rebind", lease6_rebind_skip_callout)); + + const IOAddress addr("2001:db8:1:1::cafe:babe"); + const uint32_t iaid = 234; + + // Generate client-id also duid_ + OptionPtr clientid = generateClientId(); + + // Check that the address we are about to use is indeed in pool + ASSERT_TRUE(subnet_->inPool(Lease::TYPE_NA, addr)); + + // Note that preferred, valid, T1 and T2 timers and CLTT are set to invalid + // value on purpose. They should be updated during REBIND. + Lease6Ptr lease(new Lease6(Lease::TYPE_NA, addr, duid_, iaid, + 501, 502, 503, 504, subnet_->getID(), + HWAddrPtr(), 0)); + lease->cltt_ = 1234; + ASSERT_TRUE(LeaseMgrFactory::instance().addLease(lease)); + + // Check that the lease is really in the database + Lease6Ptr l = LeaseMgrFactory::instance().getLease6(Lease::TYPE_NA, + addr); + ASSERT_TRUE(l); + + // Check that T1, T2, preferred, valid and cltt really set and not using + // previous (500, 501, etc.) values + EXPECT_NE(l->t1_, subnet_->getT1()); + EXPECT_NE(l->t2_, subnet_->getT2()); + EXPECT_NE(l->preferred_lft_, subnet_->getPreferred()); + EXPECT_NE(l->valid_lft_, subnet_->getValid()); + EXPECT_NE(l->cltt_, time(NULL)); + + // Let's create a REBIND + Pkt6Ptr req = Pkt6Ptr(new Pkt6(DHCPV6_REBIND, 1234)); + req->setRemoteAddr(IOAddress("fe80::abcd")); + req->setIface("eth0"); + boost::shared_ptr ia = generateIA(D6O_IA_NA, iaid, 1500, 3000); + + OptionPtr rebound_addr_opt(new Option6IAAddr(D6O_IAADDR, addr, 300, 500)); + ia->addOption(rebound_addr_opt); + req->addOption(ia); + req->addOption(clientid); + + // Pass it to the server and hope for a REPLY + Pkt6Ptr reply = srv.processRebind(req); + ASSERT_TRUE(reply); + + // Check that our callback was called + EXPECT_EQ("lease6_rebind", callback_name_); + + l = LeaseMgrFactory::instance().getLease6(Lease::TYPE_NA, addr); + + // Check that the old values are still there and they were not + // updated by the rebinding + EXPECT_NE(l->t1_, subnet_->getT1()); + EXPECT_NE(l->t2_, subnet_->getT2()); + EXPECT_NE(l->preferred_lft_, subnet_->getPreferred()); + EXPECT_NE(l->valid_lft_, subnet_->getValid()); + EXPECT_NE(l->cltt_, time(NULL)); +} + // This test checks that the basic decline hook (lease6_decline) is // triggered properly. TEST_F(HooksDhcpv6SrvTest, basicLease6Decline) {