]> git.ipfire.org Git - thirdparty/kea.git/commitdiff
[#2976] Added DORA+RENEW tests
authorFrancis Dupont <fdupont@isc.org>
Sun, 31 Mar 2024 20:55:45 +0000 (22:55 +0200)
committerRazvan Becheriu <razvan@isc.org>
Fri, 26 Apr 2024 15:25:06 +0000 (18:25 +0300)
src/bin/dhcp4/tests/dhcp4_srv_unittest.cc
src/bin/dhcp4/tests/dora_unittest.cc

index d385812690b61e54e317b21ddb94c0fe1d07edbd..0b16a9d5a4b4b19db83453a6f461c017aa783d2c 100644 (file)
@@ -5586,7 +5586,7 @@ TEST_F(StashAgentOptionTest, relayAgentInfoEntry) {
     EXPECT_FALSE(query_->inClass("STASH_AGENT_OPTIONS"));
 }
 
-// Verify the relay-agent-info entry must be a map or a string.
+// Verify that the relay-agent-info entry must be a map or a string.
 TEST_F(StashAgentOptionTest, badRelayAgentInfoEntry) {
     // Set the relay-agent-info entry to a boolean.
     relay_agent_info_ = Element::create(true);
@@ -5601,7 +5601,7 @@ TEST_F(StashAgentOptionTest, badRelayAgentInfoEntry) {
     EXPECT_FALSE(query_->inClass("STASH_AGENT_OPTIONS"));
 }
 
-// Verify the sub-options entry is required in new extended info format.
+// Verify that the sub-options entry is required in new extended info format.
 TEST_F(StashAgentOptionTest, subOptionsEntry) {
     // Remove the sub-options entry.
     relay_agent_info_ = Element::createMap();
@@ -5617,7 +5617,7 @@ TEST_F(StashAgentOptionTest, subOptionsEntry) {
     EXPECT_FALSE(query_->inClass("STASH_AGENT_OPTIONS"));
 }
 
-// Verify the sub-options entry must be a string.
+// Verify that the sub-options entry must be a string.
 TEST_F(StashAgentOptionTest, badSubOptionsEntry) {
     // Set the sub-options entry to a boolean.
     sub_options_ = Element::create(true);
@@ -5632,7 +5632,7 @@ TEST_F(StashAgentOptionTest, badSubOptionsEntry) {
     EXPECT_FALSE(query_->inClass("STASH_AGENT_OPTIONS"));
 }
 
-// Verify the sub-options entry must be not empty.
+// Verify that the sub-options entry must be not empty.
 TEST_F(StashAgentOptionTest, emptySubOptionsEntry) {
     // Set the sub-options entry to empty.
     sub_options_ = Element::create("");
@@ -5647,7 +5647,7 @@ TEST_F(StashAgentOptionTest, emptySubOptionsEntry) {
     EXPECT_FALSE(query_->inClass("STASH_AGENT_OPTIONS"));
 }
 
-// Verify the sub-options entry must be a valid hexstring.
+// Verify that the sub-options entry must be a valid hexstring.
 TEST_F(StashAgentOptionTest, hexString) {
     // Set the sub-options entry to invalid hexstring.
     sub_options_ = Element::create("foobar");
@@ -5660,7 +5660,7 @@ TEST_F(StashAgentOptionTest, hexString) {
     EXPECT_FALSE(query_->inClass("STASH_AGENT_OPTIONS"));
 }
 
-// Verify the sub-options entry must be a valid RAI content.
+// Verify that the sub-options entry must be a valid RAI content.
 TEST_F(StashAgentOptionTest, badRelayAgentInfo) {
     // Set the sub-options entry to truncated RAI content.
     string content = sub_options_->stringValue();
@@ -5690,6 +5690,42 @@ TEST_F(StashAgentOptionTest, badRelayAgentInfo) {
     EXPECT_FALSE(query_->inClass("STASH_AGENT_OPTIONS"));
 }
 
+// Verify that the client id when set must match.
+TEST_F(StashAgentOptionTest, badClientId) {
+    // Use another the client id.
+    query_->delOption(DHO_DHCP_CLIENT_IDENTIFIER);
+    query_->addOption(generateClientId(8));
+
+    CfgMgr::instance().commit();
+    EXPECT_NO_THROW(LeaseMgrFactory::instance().addLease(lease_));
+
+    EXPECT_NO_THROW(srv_.recoverStashedAgentOption(query_));
+    OptionPtr rai_query = query_->getOption(DHO_DHCP_AGENT_OPTIONS);
+    EXPECT_FALSE(rai_query);
+    EXPECT_FALSE(query_->inClass("STASH_AGENT_OPTIONS"));
+}
+
+// Verify that when the client id is not used the hardware address must match.
+TEST_F(StashAgentOptionTest, badHwareAddress) {
+    // No longer use the client id.
+    query_->delOption(DHO_DHCP_CLIENT_IDENTIFIER);
+    lease_.reset(new Lease4(addr_, hwaddr_, ClientIdPtr(), 100, time(0), 1));
+    lease_->setContext(user_context_);
+
+    // Change the hardware address.
+    auto hwaddr2 = generateHWAddr(8);
+    ASSERT_NE(hwaddr_, hwaddr2);
+    query_->setHWAddr(hwaddr2);
+
+    CfgMgr::instance().commit();
+    EXPECT_NO_THROW(LeaseMgrFactory::instance().addLease(lease_));
+
+    EXPECT_NO_THROW(srv_.recoverStashedAgentOption(query_));
+    OptionPtr rai_query = query_->getOption(DHO_DHCP_AGENT_OPTIONS);
+    EXPECT_FALSE(rai_query);
+    EXPECT_FALSE(query_->inClass("STASH_AGENT_OPTIONS"));
+}
+
 /// @todo: lease ownership
 
 /// @todo: Implement proper tests for MySQL lease/host database,
index 9520f14d2b26c7d255c8e08d78fed21bc7a7c75f..bc0122b8ab079634e3b45019eb0f4f1fac8c29c8 100644 (file)
@@ -167,6 +167,20 @@ namespace {
 /// - Configuration 20:
 ///   - No subnets.
 ///   - Global authoritative flag is true.
+///
+/// - Configuration 21:
+///   - Use for testing stash agent options (flag true).
+///   - 1 subnet with storing extended info enabled
+///
+/// - Configuration 22:
+///   - Use for testing stash agent options (flag true).
+///   - 1 subnet with storing extended info enabled
+///   - 1 reservation using the circuit-id
+///
+/// - Configuration 23:
+///   - Use for testing stash agent options (flag false).
+///   - 1 subnet with storing extended info enabled
+///   - 1 reservation using the circuit-id
 const char* DORA_CONFIGS[] = {
     // Configuration 0
     "{ \"interfaces-config\": {"
@@ -649,6 +663,54 @@ const char* DORA_CONFIGS[] = {
         "\"authoritative\": true,"
         "\"subnet4\": []"
     "}",
+
+    // Configuration 21
+    "{ \"interfaces-config\": {"
+        "      \"interfaces\": [ \"*\" ]"
+        "},"
+        "\"valid-lifetime\": 600,"
+        "\"stash-agent-options\": true,"
+        "\"subnet4\": [ {"
+        "    \"subnet\": \"10.0.0.0/24\", "
+        "    \"id\": 1, "
+        "    \"store-extended-info\": true,"
+        "    \"pools\": [ { \"pool\": \"10.0.0.10-10.0.0.100\" } ]"
+        "} ]"
+    "}",
+
+    // Configuration 22
+    "{ \"interfaces-config\": {"
+        "      \"interfaces\": [ \"*\" ]"
+        "},"
+        "\"valid-lifetime\": 600,"
+        "\"stash-agent-options\": true,"
+        "\"host-reservation-identifiers\": [ \"circuit-id\" ],"
+        "\"subnet4\": [ {"
+        "    \"subnet\": \"10.0.0.0/24\", "
+        "    \"id\": 1, "
+        "    \"store-extended-info\": true,"
+        "    \"reservations\": [ {"
+        "        \"circuit-id\": \"'charter950'\","
+        "        \"ip-address\": \"10.0.0.9\" } ]"
+        "} ]"
+    "}",
+
+    // Configuration 23
+    "{ \"interfaces-config\": {"
+        "      \"interfaces\": [ \"*\" ]"
+        "},"
+        "\"valid-lifetime\": 600,"
+        "\"stash-agent-options\": false,"
+        "\"host-reservation-identifiers\": [ \"circuit-id\" ],"
+        "\"subnet4\": [ {"
+        "    \"subnet\": \"10.0.0.0/24\", "
+        "    \"id\": 1, "
+        "    \"store-extended-info\": true,"
+        "    \"reservations\": [ {"
+        "        \"circuit-id\": \"'charter950'\","
+        "        \"ip-address\": \"10.0.0.9\" } ]"
+        "} ]"
+    "}",
 };
 
 /// @brief Test fixture class for testing 4-way (DORA) exchanges.
@@ -911,6 +973,22 @@ public:
     /// @brief Checks that features related to lease caching (such as lease reuse statistics) work.
     void leaseCaching();
 
+    /// @brief Checks that stash-agent-options enables direct renewall
+    /// of addresses from pool allocation for a relayed client.
+    ///
+    /// @note: no negative counterpart as the stash-agent-options is not
+    /// required for this scenario.
+    void stashAgentOptions();
+
+    /// @brief Checks that stash-agent-options enables direct renewall
+    /// of addresses from host reservation using the relay-agent-info option.
+    void stashAgentOptionsReservation();
+
+    /// @brief Checks that stash-agent-options is required for direct
+    /// renewall of addresses from host reservation using the
+    /// relay-agent-info option.
+    void noStashAgentOptionsReservation();
+
     /// @brief Checks the value of a statistic.
     ///
     /// @param name name of statistic to check
@@ -3085,6 +3163,145 @@ TEST_F(DORATest, leaseCachingMultiThreading) {
     leaseCaching();
 }
 
+void
+DORATest::stashAgentOptions() {
+    Dhcp4Client client(Dhcp4Client::SELECTING);
+    // Use relay agent to make sure that the desired subnet is
+    // selected for our client.
+    client.useRelay(true, IOAddress("10.0.0.20"), IOAddress("10.0.0.21"));
+    // Specify client identifier.
+    client.includeClientId("01:11:22:33:44:55:66");
+    // Set the circuit id.
+    client.setCircuitId("charter950");
+
+    // Configure DHCP server.
+    configure(DORA_CONFIGS[21], *client.getServer());
+    // Perform 4-way exchange and should obtain an address from pool.
+    ASSERT_NO_THROW_LOG(client.doDORA());
+    // Make sure that the server responded.
+    ASSERT_TRUE(client.getContext().response_);
+    Pkt4Ptr resp = client.getContext().response_;
+    // Make sure that the server has responded with DHCPACK.
+    ASSERT_EQ(DHCPACK, static_cast<int>(resp->getType()));
+    // Make sure that the client has got the lease for the first address
+    // of the pool.
+    ASSERT_EQ("10.0.0.10", client.config_.lease_.addr_.toText());
+
+    // Renew.
+    client.setState(Dhcp4Client::RENEWING);
+    // Set the unicast destination address to indicate that it is a renewal.
+    client.setDestAddress(IOAddress("10.0.0.1"));
+    // Disable relay.
+    client.useRelay(false);
+    ASSERT_NO_THROW_LOG(client.doRequest());
+    ASSERT_TRUE(client.getContext().response_);
+    resp = client.getContext().response_;
+    ASSERT_EQ(DHCPACK, static_cast<int>(resp->getType()));
+    ASSERT_EQ("10.0.0.10", client.config_.lease_.addr_.toText());
+}
+
+TEST_F(DORATest, stashAgentOptions) {
+    Dhcpv4SrvMTTestGuard guard(*this, false);
+    stashAgentOptions();
+}
+
+TEST_F(DORATest, stashAgentOptionsMultiThreading) {
+    Dhcpv4SrvMTTestGuard guard(*this, true);
+    stashAgentOptions();
+}
+
+void
+DORATest::stashAgentOptionsReservation() {
+    Dhcp4Client client(Dhcp4Client::SELECTING);
+    // Use relay agent to make sure that the desired subnet is
+    // selected for our client.
+    client.useRelay(true, IOAddress("10.0.0.20"), IOAddress("10.0.0.21"));
+    // Specify client identifier.
+    client.includeClientId("01:11:22:33:44:55:66");
+    // Set the circuit id.
+    client.setCircuitId("charter950");
+
+    // Configure DHCP server.
+    configure(DORA_CONFIGS[22], *client.getServer());
+    // Perform 4-way exchange and should obtain the reserved address.
+    ASSERT_NO_THROW_LOG(client.doDORA());
+    // Make sure that the server responded.
+    ASSERT_TRUE(client.getContext().response_);
+    Pkt4Ptr resp = client.getContext().response_;
+    // Make sure that the server has responded with DHCPACK.
+    ASSERT_EQ(DHCPACK, static_cast<int>(resp->getType()));
+    // Make sure that the client has got the lease for the reserved address.
+    ASSERT_EQ("10.0.0.9", client.config_.lease_.addr_.toText());
+
+    // Renew.
+    client.setState(Dhcp4Client::RENEWING);
+    // Set the unicast destination address to indicate that it is a renewal.
+    client.setDestAddress(IOAddress("10.0.0.1"));
+    // Disable relay.
+    client.useRelay(false);
+    ASSERT_NO_THROW_LOG(client.doRequest());
+    ASSERT_TRUE(client.getContext().response_);
+    resp = client.getContext().response_;
+    ASSERT_EQ(DHCPACK, static_cast<int>(resp->getType()));
+    ASSERT_EQ("10.0.0.9", client.config_.lease_.addr_.toText());
+}
+
+TEST_F(DORATest, stashAgentOptionsReservation) {
+    Dhcpv4SrvMTTestGuard guard(*this, false);
+    stashAgentOptionsReservation();
+}
+
+TEST_F(DORATest, stashAgentOptionsReservationMultiThreading) {
+    Dhcpv4SrvMTTestGuard guard(*this, true);
+    stashAgentOptionsReservation();
+}
+
+void
+DORATest::noStashAgentOptionsReservation() {
+    Dhcp4Client client(Dhcp4Client::SELECTING);
+    // Use relay agent to make sure that the desired subnet is
+    // selected for our client.
+    client.useRelay(true, IOAddress("10.0.0.20"), IOAddress("10.0.0.21"));
+    // Specify client identifier.
+    client.includeClientId("01:11:22:33:44:55:66");
+    // Set the circuit id.
+    client.setCircuitId("charter950");
+
+    // Configure DHCP server.
+    configure(DORA_CONFIGS[23], *client.getServer());
+    // Perform 4-way exchange and should obtain the reserved address.
+    ASSERT_NO_THROW_LOG(client.doDORA());
+    // Make sure that the server responded.
+    ASSERT_TRUE(client.getContext().response_);
+    Pkt4Ptr resp = client.getContext().response_;
+    // Make sure that the server has responded with DHCPACK.
+    ASSERT_EQ(DHCPACK, static_cast<int>(resp->getType()));
+    // Make sure that the client has got the lease for the reserved address.
+    ASSERT_EQ("10.0.0.9", client.config_.lease_.addr_.toText());
+
+    // Renew.
+    client.setState(Dhcp4Client::RENEWING);
+    // Set the unicast destination address to indicate that it is a renewal.
+    client.setDestAddress(IOAddress("10.0.0.1"));
+    // Disable relay.
+    client.useRelay(false);
+    ASSERT_NO_THROW_LOG(client.doRequest());
+    ASSERT_TRUE(client.getContext().response_);
+    resp = client.getContext().response_;
+    // The client is not recognized so a NAK is returned.
+    ASSERT_EQ(DHCPNAK, static_cast<int>(resp->getType()));
+}
+
+TEST_F(DORATest, noStashAgentOptionsReservation) {
+    Dhcpv4SrvMTTestGuard guard(*this, false);
+    noStashAgentOptionsReservation();
+}
+
+TEST_F(DORATest, noStashAgentOptionsReservationMultiThreading) {
+    Dhcpv4SrvMTTestGuard guard(*this, true);
+    noStashAgentOptionsReservation();
+}
+
 /// @brief Checks the value of a statistic.
 ///
 /// @param name name of statistic to check