From: Marcin Siodelski Date: Tue, 28 Jul 2015 10:28:31 +0000 (+0200) Subject: [3947] Added missing unit tests for the NoBinding cases in Renew/Rebind. X-Git-Tag: trac3238_base~6^2~4 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=623693cd96134a950c536861f800ae59557d85d1;p=thirdparty%2Fkea.git [3947] Added missing unit tests for the NoBinding cases in Renew/Rebind. --- diff --git a/src/bin/dhcp6/tests/rebind_unittest.cc b/src/bin/dhcp6/tests/rebind_unittest.cc index 7c4c6ca2e2..d06f30c49e 100644 --- a/src/bin/dhcp6/tests/rebind_unittest.cc +++ b/src/bin/dhcp6/tests/rebind_unittest.cc @@ -32,7 +32,7 @@ namespace { /// /// - Configuration 0: /// - only addresses (no prefixes) -/// - 2 subnets with 2001:db8:1::/64 and 2001:db8:2::64 +/// - 2 subnets with 2001:db8:1::/64 and 2001:db8:2::/64 /// - 1 subnet for eth0 and 1 subnet for eth1 /// /// - Configuration 1: @@ -57,7 +57,7 @@ namespace { /// - this specific configuration is used by tests which don't use relays /// /// - Configuration 5: -/// - similar to Configuration 5 but with different subnets +/// - similar to Configuration 4 but with different subnets /// - 2 subnets: 2001:db8:3::/40 and 2001:db8:4::/40 /// - 2 prefix pools: 2001:db8:3::/72 and 2001:db8:4::/72 /// - delegated length /80 @@ -69,11 +69,22 @@ namespace { /// - 'new-leases-on-renew' enabled /// /// - Configuration 7: +/// - only prefixes (no addresses) +/// - 1 subnet with the 3000::/72 +/// - 'new-leases-on-rebew' enabled +/// +/// - Configuration 8: /// - addresses and prefixes /// - address pool: 2001:db8:1::/64 /// - prefix pool: 3000::/72 /// - 'new-leases-on-renew' enabled /// +/// - Configuration 9: +/// - addresses and prefixes +/// - address pool: 2001:db8:1::/64 +/// - prefix pool: 3000::/72 +/// - 'new-leases-on-renew' disabled +/// const char* REBIND_CONFIGS[] = { // Configuration 0 "{ \"interfaces-config\": {" @@ -246,6 +257,48 @@ const char* REBIND_CONFIGS[] = { "\"preferred-lifetime\": 3000," "\"rebind-timer\": 2000, " "\"renew-timer\": 1000, " + "\"new-leases-on-renew\": True," + "\"subnet6\": [ { " + " \"pd-pools\": [" + " { \"prefix\": \"3000::\", " + " \"prefix-len\": 72, " + " \"delegated-len\": 80" + " } ]," + " \"subnet\": \"2001:db8:1::/48\", " + " \"interface-id\": \"\"," + " \"interface\": \"eth0\"" + " } ]," + "\"valid-lifetime\": 4000 }", + +// Configuration 8 + "{ \"interfaces-config\": {" + " \"interfaces\": [ \"*\" ]" + "}," + "\"preferred-lifetime\": 3000," + "\"rebind-timer\": 2000, " + "\"renew-timer\": 1000, " + "\"new-leases-on-renew\": True," + "\"subnet6\": [ { " + " \"pools\": [ { \"pool\": \"2001:db8:1::/64\" } ]," + " \"pd-pools\": [" + " { \"prefix\": \"3000::\", " + " \"prefix-len\": 72, " + " \"delegated-len\": 80" + " } ]," + " \"subnet\": \"2001:db8:1::/48\", " + " \"interface-id\": \"\"," + " \"interface\": \"eth0\"" + " } ]," + "\"valid-lifetime\": 4000 }", + +// Configuration 9 + "{ \"interfaces-config\": {" + " \"interfaces\": [ \"*\" ]" + "}," + "\"preferred-lifetime\": 3000," + "\"rebind-timer\": 2000, " + "\"renew-timer\": 1000, " + "\"new-leases-on-renew\": False," "\"subnet6\": [ { " " \"pools\": [ { \"pool\": \"2001:db8:1::/64\" } ]," " \"pd-pools\": [" @@ -259,6 +312,7 @@ const char* REBIND_CONFIGS[] = { " } ]," "\"valid-lifetime\": 4000 }" + }; /// @brief Test fixture class for testing Rebind. @@ -810,7 +864,7 @@ TEST_F(RebindTest, requestPrefixInRebind) { ASSERT_EQ(STATUS_NoPrefixAvail, client.getStatusCode(5678)); // Reconfigure the server to use both NA and PD pools. - configure(REBIND_CONFIGS[7], *client.getServer()); + configure(REBIND_CONFIGS[8], *client.getServer()); // Send Rebind message to the server, including IA_NA and requesting IA_PD. ASSERT_NO_THROW(client.doRebind()); @@ -830,5 +884,157 @@ TEST_F(RebindTest, requestPrefixInRebind) { EXPECT_EQ(STATUS_Success, client.getStatusCode(5678)); } +// This test verifies that the client can request the prefix delegation +// while it is rebinding an address lease. +TEST_F(RebindTest, requestAddressInRebind) { + Dhcp6Client client; + + // Configure client to request IA_NA and IA_PD. + client.useNA(); + client.usePD(); + + // Configure the server with PD pools only. + ASSERT_NO_THROW(configure(REBIND_CONFIGS[7], *client.getServer())); + + // Perform 4-way exchange. + ASSERT_NO_THROW(client.doSARR()); + + // Simulate aging of leases. + client.fastFwdTime(1000); + + // Make sure that the client has acquired PD lease. + std::vector leases_client_pd = client.getLeasesByType(Lease::TYPE_PD); + ASSERT_EQ(1, leases_client_pd.size()); + EXPECT_EQ(STATUS_Success, client.getStatusCode(5678)); + + // The client should not acquire a NA lease. + std::vector leases_client_na = + client.getLeasesByType(Lease::TYPE_NA); + ASSERT_EQ(0, leases_client_na.size()); + ASSERT_EQ(STATUS_NoAddrsAvail, client.getStatusCode(1234)); + + // Send Rebind message to the server, including IA_PD and requesting IA_NA. + // The server should return NoAddrsAvail status code in this case. + ASSERT_NO_THROW(client.doRebind()); + leases_client_na = client.getLeasesByType(Lease::TYPE_NA); + ASSERT_EQ(0, leases_client_na.size()); + ASSERT_EQ(STATUS_NoAddrsAvail, client.getStatusCode(1234)); + + // Reconfigure the server to use both NA and PD pools. + configure(REBIND_CONFIGS[8], *client.getServer()); + + // Send Rebind message to the server, including IA_PD and requesting IA_NA. + ASSERT_NO_THROW(client.doRebind()); + + // Make sure that the client has renewed PD lease. + std::vector leases_client_pd_renewed = + client.getLeasesByType(Lease::TYPE_PD); + ASSERT_EQ(1, leases_client_pd_renewed.size()); + EXPECT_EQ(STATUS_Success, client.getStatusCode(5678)); + EXPECT_GE(leases_client_pd_renewed[0].cltt_ - leases_client_pd[0].cltt_, 1000); + + // The client should now also acquire a NA lease. + leases_client_na = client.getLeasesByType(Lease::TYPE_NA); + ASSERT_EQ(1, leases_client_na.size()); + EXPECT_EQ(STATUS_Success, client.getStatusCode(1234)); +} + +// This test verifies that when the client requests the prefix delegation +// while it is renewing an address lease its message is dropped. +TEST_F(RebindTest, requestPrefixInRebindNotAllowed) { + Dhcp6Client client; + + // Configure client to request IA_NA and IA_PD. + client.useNA(); + client.usePD(); + + // Configure the server with NA pools only. + ASSERT_NO_THROW(configure(REBIND_CONFIGS[0], *client.getServer())); + + // Perform 4-way exchange. + ASSERT_NO_THROW(client.doSARR()); + + // Simulate aging of leases. + client.fastFwdTime(1000); + + // Make sure that the client has acquired NA lease. + std::vector leases_client_na = client.getLeasesByType(Lease::TYPE_NA); + ASSERT_EQ(1, leases_client_na.size()); + + // The client should not acquire a PD lease. + std::vector leases_client_pd = client.getLeasesByType(Lease::TYPE_PD); + ASSERT_TRUE(leases_client_pd.empty()); + ASSERT_EQ(STATUS_NoPrefixAvail, client.getStatusCode(5678)); + + // Send Rebind message to the server, including IA_NA and requesting IA_PD. + ASSERT_NO_THROW(client.doRebind()); + EXPECT_FALSE(client.getContext().response_); + + // Reconfigure the server to use both NA and PD pools. + configure(REBIND_CONFIGS[9], *client.getServer()); + + // Send Rebind message to the server, including IA_NA and requesting IA_PD. + ASSERT_NO_THROW(client.doRebind()); + EXPECT_FALSE(client.getContext().response_); +} + +// This test verifies that when the client requests an address assignment +// while it is renewing a prefix lease it is returned NoBinding, when +// the server is not configured to allocate new leases during Renew. +TEST_F(RebindTest, requestAddressInRebindNotAllowed) { + Dhcp6Client client; + + // Configure client to request IA_NA and IA_PD. + client.useNA(); + client.usePD(); + + // Configure the server with PD pools only. + ASSERT_NO_THROW(configure(REBIND_CONFIGS[4], *client.getServer())); + + // Perform 4-way exchange. + ASSERT_NO_THROW(client.doSARR()); + + // Simulate aging of leases. + client.fastFwdTime(1000); + + // Make sure that the client has acquired PD lease. + std::vector leases_client_pd = client.getLeasesByType(Lease::TYPE_PD); + ASSERT_EQ(1, leases_client_pd.size()); + EXPECT_EQ(STATUS_Success, client.getStatusCode(5678)); + + // The client should not acquire a NA lease. + std::vector leases_client_na = + client.getLeasesByType(Lease::TYPE_NA); + ASSERT_EQ(0, leases_client_na.size()); + ASSERT_EQ(STATUS_NoAddrsAvail, client.getStatusCode(1234)); + + // Send Rebind message to the server, including IA_PD and requesting IA_NA. + // The server should return NoBinding status code in this case. + ASSERT_NO_THROW(client.doRebind()); + leases_client_na = client.getLeasesByType(Lease::TYPE_NA); + ASSERT_EQ(0, leases_client_na.size()); + ASSERT_EQ(STATUS_NoBinding, client.getStatusCode(1234)); + + // Reconfigure the server to use both NA and PD pools. + configure(REBIND_CONFIGS[9], *client.getServer()); + + // Send Rebind message to the server, including IA_PD and requesting IA_NA. + ASSERT_NO_THROW(client.doRebind()); + + // Make sure that the client has renewed PD lease. + std::vector leases_client_pd_renewed = + client.getLeasesByType(Lease::TYPE_PD); + ASSERT_EQ(1, leases_client_pd_renewed.size()); + EXPECT_EQ(STATUS_Success, client.getStatusCode(5678)); + EXPECT_GE(leases_client_pd_renewed[0].cltt_ - leases_client_pd[0].cltt_, 1000); + + // The server should not allocate an address to the client, as this has been + // explicitly disabled in the configuration. Instead, it should send + // NoBinding status code. + leases_client_na = client.getLeasesByType(Lease::TYPE_NA); + ASSERT_EQ(0, leases_client_na.size()); + EXPECT_EQ(STATUS_NoBinding, client.getStatusCode(1234)); +} + } // end of anonymous namespace diff --git a/src/bin/dhcp6/tests/renew_unittest.cc b/src/bin/dhcp6/tests/renew_unittest.cc index cef2b7ef2c..497a355472 100644 --- a/src/bin/dhcp6/tests/renew_unittest.cc +++ b/src/bin/dhcp6/tests/renew_unittest.cc @@ -44,6 +44,23 @@ namespace { /// - address pool: 2001:db8:1::/64 /// - prefix pool: 3000::/72 /// +/// - Configuration 3: +/// - only addresses (no prefixes) +/// - 1 subnet with 2001:db8:1::/64 pool +/// - 'new-leases-on-renew' disabled +/// +/// - Configuration 4: +/// - only prefixes (no addresses) +/// - prefix pool: 3000::/72 +/// - 'new-leases-on-renew' disabled +/// +/// - Configuration 5: +/// - addresses and prefixes +/// - 1 subnet with one address pool and one prefix pool +/// - address pool: 2001:db8:1::/64 +/// - prefix pool: 3000::/72 +/// - 'new-leases-on-renew' disabled +/// const char* RENEW_CONFIGS[] = { // Configuration 0 "{ \"interfaces-config\": {" @@ -97,6 +114,63 @@ const char* RENEW_CONFIGS[] = { " \"interface-id\": \"\"," " \"interface\": \"eth0\"" " } ]," + "\"valid-lifetime\": 4000 }", + +// Configuration 3 + "{ \"interfaces-config\": {" + " \"interfaces\": [ \"*\" ]" + "}," + "\"preferred-lifetime\": 3000," + "\"rebind-timer\": 2000, " + "\"renew-timer\": 1000, " + "\"new-leases-on-renew\": False," + "\"subnet6\": [ { " + " \"pools\": [ { \"pool\": \"2001:db8:1::/64\" } ]," + " \"subnet\": \"2001:db8:1::/48\", " + " \"interface-id\": \"\"," + " \"interface\": \"eth0\"" + " } ]," + "\"valid-lifetime\": 4000 }", + +// Configuration 4 + "{ \"interfaces-config\": {" + " \"interfaces\": [ \"*\" ]" + "}," + "\"preferred-lifetime\": 3000," + "\"rebind-timer\": 2000, " + "\"renew-timer\": 1000, " + "\"new-leases-on-renew\": False," + "\"subnet6\": [ { " + " \"pd-pools\": [" + " { \"prefix\": \"3000::\", " + " \"prefix-len\": 72, " + " \"delegated-len\": 80" + " } ]," + " \"subnet\": \"2001:db8:1::/48\", " + " \"interface-id\": \"\"," + " \"interface\": \"eth0\"" + " } ]," + "\"valid-lifetime\": 4000 }", + +// Configuration 5 + "{ \"interfaces-config\": {" + " \"interfaces\": [ \"*\" ]" + "}," + "\"preferred-lifetime\": 3000," + "\"rebind-timer\": 2000, " + "\"renew-timer\": 1000, " + "\"new-leases-on-renew\": False," + "\"subnet6\": [ { " + " \"pools\": [ { \"pool\": \"2001:db8:1::/64\" } ]," + " \"pd-pools\": [" + " { \"prefix\": \"3000::\", " + " \"prefix-len\": 72, " + " \"delegated-len\": 80" + " } ]," + " \"subnet\": \"2001:db8:1::/48\", " + " \"interface-id\": \"\"," + " \"interface\": \"eth0\"" + " } ]," "\"valid-lifetime\": 4000 }" }; @@ -353,5 +427,120 @@ TEST_F(RenewTest, requestAddressInRenewHint) { EXPECT_EQ(STATUS_Success, client.getStatusCode(1234)); } +// This test verifies that when the client requests the prefix delegation +// while it is renewing an address lease it is returned NoBinding, when +// the server is not configured to allocate new leases during Renew. +TEST_F(RenewTest, requestPrefixInRenewNotAllowed) { + Dhcp6Client client; + + // Configure client to request IA_NA and IA_PD. + client.useNA(); + client.usePD(); + + // Configure the server with NA pools only. + ASSERT_NO_THROW(configure(RENEW_CONFIGS[3], *client.getServer())); + + // Perform 4-way exchange. + ASSERT_NO_THROW(client.doSARR()); + + // Simulate aging of leases. + client.fastFwdTime(1000); + + // Make sure that the client has acquired NA lease. + std::vector leases_client_na = client.getLeasesByType(Lease::TYPE_NA); + ASSERT_EQ(1, leases_client_na.size()); + + // The client should not acquire a PD lease. + std::vector leases_client_pd = client.getLeasesByType(Lease::TYPE_PD); + ASSERT_TRUE(leases_client_pd.empty()); + ASSERT_EQ(STATUS_NoPrefixAvail, client.getStatusCode(5678)); + + // Send Renew message to the server, including IA_NA and requesting IA_PD. + ASSERT_NO_THROW(client.doRenew()); + leases_client_pd = client.getLeasesByType(Lease::TYPE_PD); + ASSERT_TRUE(leases_client_pd.empty()); + ASSERT_EQ(STATUS_NoBinding, client.getStatusCode(5678)); + + // Reconfigure the server to use both NA and PD pools. + configure(RENEW_CONFIGS[5], *client.getServer()); + + // Send Renew message to the server, including IA_NA and requesting IA_PD. + ASSERT_NO_THROW(client.doRenew()); + + // Make sure that the client has acquired NA lease. + std::vector leases_client_na_renewed = + client.getLeasesByType(Lease::TYPE_NA); + ASSERT_EQ(1, leases_client_na_renewed.size()); + EXPECT_EQ(STATUS_Success, client.getStatusCode(1234)); + + // The lease should have been renewed. + EXPECT_EQ(1000, leases_client_na_renewed[0].cltt_ - leases_client_na[0].cltt_); + + // The server should not delegate a prefix to the client, as this has been + // explicitly disabled in the configuration. Instead, it should send + // NoBinding status code. + leases_client_pd = client.getLeasesByType(Lease::TYPE_PD); + ASSERT_EQ(0, leases_client_pd.size()); + EXPECT_EQ(STATUS_NoBinding, client.getStatusCode(5678)); +} + +// This test verifies that when the client requests an address assignment +// while it is renewing a prefix lease it is returned NoBinding, when +// the server is not configured to allocate new leases during Renew. +TEST_F(RenewTest, requestAddressInRenewNotAllowed) { + Dhcp6Client client; + + // Configure client to request IA_NA and IA_PD. + client.useNA(); + client.usePD(); + + // Configure the server with PD pools only. + ASSERT_NO_THROW(configure(RENEW_CONFIGS[4], *client.getServer())); + + // Perform 4-way exchange. + ASSERT_NO_THROW(client.doSARR()); + + // Simulate aging of leases. + client.fastFwdTime(1000); + + // Make sure that the client has acquired PD lease. + std::vector leases_client_pd = client.getLeasesByType(Lease::TYPE_PD); + ASSERT_EQ(1, leases_client_pd.size()); + EXPECT_EQ(STATUS_Success, client.getStatusCode(5678)); + + // The client should not acquire a NA lease. + std::vector leases_client_na = + client.getLeasesByType(Lease::TYPE_NA); + ASSERT_EQ(0, leases_client_na.size()); + ASSERT_EQ(STATUS_NoAddrsAvail, client.getStatusCode(1234)); + + // Send Renew message to the server, including IA_PD and requesting IA_NA. + // The server should return NoBinding status code in this case. + ASSERT_NO_THROW(client.doRenew()); + leases_client_na = client.getLeasesByType(Lease::TYPE_NA); + ASSERT_EQ(0, leases_client_na.size()); + ASSERT_EQ(STATUS_NoBinding, client.getStatusCode(1234)); + + // Reconfigure the server to use both NA and PD pools. + configure(RENEW_CONFIGS[5], *client.getServer()); + + // Send Renew message to the server, including IA_PD and requesting IA_NA. + ASSERT_NO_THROW(client.doRenew()); + + // Make sure that the client has renewed PD lease. + std::vector leases_client_pd_renewed = + client.getLeasesByType(Lease::TYPE_PD); + ASSERT_EQ(1, leases_client_pd_renewed.size()); + EXPECT_EQ(STATUS_Success, client.getStatusCode(5678)); + EXPECT_GE(leases_client_pd_renewed[0].cltt_ - leases_client_pd[0].cltt_, 1000); + + // The server should not allocate an address to the client, as this has been + // explicitly disabled in the configuration. Instead, it should send + // NoBinding status code. + leases_client_na = client.getLeasesByType(Lease::TYPE_NA); + ASSERT_EQ(0, leases_client_na.size()); + EXPECT_EQ(STATUS_NoBinding, client.getStatusCode(1234)); +} + } // end of anonymous namespace diff --git a/src/lib/dhcpsrv/alloc_engine.cc b/src/lib/dhcpsrv/alloc_engine.cc index 1bbf0ca699..f3e0a742b7 100644 --- a/src/lib/dhcpsrv/alloc_engine.cc +++ b/src/lib/dhcpsrv/alloc_engine.cc @@ -1093,6 +1093,18 @@ AllocEngine::renewLeases6(ClientContext6& ctx) { Lease6Collection leases = LeaseMgrFactory::instance() .getLeases6(ctx.type_, *ctx.duid_, ctx.iaid_, ctx.subnet_->getID()); + // If this client has no leases and we do not allow allocation of + // new leases in renewals, return now to indicate NoBinding. + if (leases.empty() && !ctx.allow_new_leases_in_renewals_) { + LOG_DEBUG(alloc_engine_logger, ALLOC_ENGINE_DBG_TRACE, + ALLOC_ENGINE_V6_NO_BINDING) + .arg(ctx.query_->getLabel()) + .arg(Lease::typeToText(ctx.type_)) + .arg(ctx.iaid_) + .arg(ctx.subnet_->getID()); + return (Lease6Collection()); + } + if (!leases.empty()) { LOG_DEBUG(alloc_engine_logger, ALLOC_ENGINE_DBG_TRACE, ALLOC_ENGINE_V6_RENEW_REMOVE_RESERVED) diff --git a/src/lib/dhcpsrv/alloc_engine_messages.mes b/src/lib/dhcpsrv/alloc_engine_messages.mes index 8488c9f69a..60893718bc 100644 --- a/src/lib/dhcpsrv/alloc_engine_messages.mes +++ b/src/lib/dhcpsrv/alloc_engine_messages.mes @@ -246,6 +246,15 @@ reserved for it. This informational message signals that the specified client was assigned the prefix reserved for it. +% ALLOC_ENGINE_V6_NO_BINDING %1: client requesting renew/rebind has no binding for lease type %2, IAID %3 and subnet id %4 +This debug message is issued when the allocation engine determines that the renewing +client has no binding for the given lease type, IAID and subnet id. The server is +configured to not allocate new bindings during the Renew/Rebind. Hence the +server doesn't allocate new leases and returns NoBinding status code or +ignores the message. The first argument contains the client and the +transaction identification information. The remaining arguments hold +the lease type, IAID and subnet id respectively. + % ALLOC_ENGINE_V6_RENEW_HR allocating leases reserved for the client %1 as a result of Renew This debug message is issued when the allocation engine tries to allocate reserved leases for the client sending a Renew message.