]> git.ipfire.org Git - thirdparty/kea.git/commitdiff
[5549a] Ported unit tests
authorFrancis Dupont <fdupont@isc.org>
Sat, 19 May 2018 12:39:50 +0000 (14:39 +0200)
committerFrancis Dupont <fdupont@isc.org>
Sat, 19 May 2018 12:39:50 +0000 (14:39 +0200)
src/bin/dhcp4/dhcp4_srv.cc
src/bin/dhcp4/tests/dhcp4_srv_unittest.cc
src/bin/dhcp6/tests/classify_unittests.cc

index 149265a550b86b331ffa576169aeb84f71100769..cd2aba14bed96256c387f2c5304aa87272efc43d 100644 (file)
@@ -168,7 +168,7 @@ Dhcpv4Exchange::Dhcpv4Exchange(const AllocEnginePtr& alloc_engine,
         }
 
         // Perform second pass of classification.
-       Dhcpv4Srv::evaluateClasses(query, true);
+        Dhcpv4Srv::evaluateClasses(query, true);
     }
 
     const ClientClasses& classes = query_->getClasses();
index 324bd0f74c0e640c3c822ed8de9d0d5ee49d1e6d..7a31d989ce04c86cd14bd2cd820b2d18b5c8631d 100644 (file)
@@ -2466,6 +2466,62 @@ TEST_F(Dhcpv4SrvTest, clientPoolClassify) {
     EXPECT_FALSE(offer->getYiaddr().isV4Zero());
 }
 
+// Checks if the KNOWN built-in class is indeed used for pool selection.
+TEST_F(Dhcpv4SrvTest, clientPoolClassifyKnown) {
+    IfaceMgrTestConfig test_config(true);
+    IfaceMgr::instance().openSockets4();
+
+    NakedDhcpv4Srv srv(0);
+
+    // This test configures 2 pools.
+    // The first one requires reservation, the second does the opposite.
+    string config = "{ \"interfaces-config\": {"
+        "    \"interfaces\": [ \"*\" ]"
+        "},"
+        "\"client-classes\": [ {"
+        "    \"name\": \"unknown\", "
+        "    \"test\": \"not member('KNOWN')\" "
+        "} ],"
+        "\"rebind-timer\": 2000, "
+        "\"renew-timer\": 1000, "
+        "\"subnet4\": [ "
+        "{   \"pools\": [ { "
+        "      \"pool\": \"192.0.2.1 - 192.0.2.100\", "
+        "      \"client-class\": \"KNOWN\" }, "
+        "    { \"pool\": \"192.0.3.1 - 192.0.3.100\", "
+        "      \"client-class\": \"unknown\" } ], "
+        "    \"subnet\": \"192.0.0.0/16\" } "
+        "],"
+        "\"valid-lifetime\": 4000 }";
+
+    ConstElementPtr json;
+    ASSERT_NO_THROW(json = parseDHCP4(config, true));
+
+    ConstElementPtr status;
+    EXPECT_NO_THROW(status = configureDhcp4Server(srv, json));
+
+    CfgMgr::instance().commit();
+
+    // check if returned status is OK
+    ASSERT_TRUE(status);
+    comment_ = config::parseAnswer(rcode_, status);
+    ASSERT_EQ(0, rcode_);
+
+    // Create a simple packet that we'll use for classification
+    Pkt4Ptr dis = Pkt4Ptr(new Pkt4(DHCPDISCOVER, 1234));
+    dis->setRemoteAddr(IOAddress("192.0.2.1"));
+    dis->setCiaddr(IOAddress("192.0.2.1"));
+    dis->setIface("eth0");
+    OptionPtr clientid = generateClientId();
+    dis->addOption(clientid);
+
+    // First pool requires reservation so the second will be used
+    Pkt4Ptr offer = srv.processDiscover(dis);
+    ASSERT_TRUE(offer);
+    EXPECT_EQ(DHCPOFFER, offer->getType());
+    EXPECT_EQ("192.0.3.1", offer->getYiaddr().toText());
+}
+
 // Verifies last resort option 43 is backward compatible
 TEST_F(Dhcpv4SrvTest, option43LastResort) {
     IfaceMgrTestConfig test_config(true);
index 5a5a6ffd177e594553f80d5bd38eca306cd389ae..771329f829e28500df870f94b39665166dfa5b1c 100644 (file)
@@ -1085,6 +1085,97 @@ TEST_F(ClassifyTest, clientClassifyPool) {
     EXPECT_TRUE(ia_na3->getOption(D6O_IAADDR));
 }
 
+// Checks if the KNOWN built-in class is indeed used for pool selection.
+TEST_F(ClassifyTest, clientClassifyPoolKnown) {
+    IfaceMgrTestConfig test_config(true);
+
+    NakedDhcpv6Srv srv(0);
+
+    // This test configures 2 pools.
+    // The first one requires reservation, the second does the opposite.
+    std::string config = "{ \"interfaces-config\": {"
+        "  \"interfaces\": [ \"*\" ]"
+        "},"
+        "\"client-classes\": [ {"
+        "    \"name\": \"unknown\", "
+        "    \"test\": \"not member('KNOWN')\" "
+        "} ],"
+        "\"preferred-lifetime\": 3000,"
+        "\"rebind-timer\": 2000, "
+        "\"renew-timer\": 1000, "
+        "\"subnet6\": [ "
+        " {  \"pools\": [ "
+        "    { "
+        "       \"pool\": \"2001:db8:1::/64\", "
+        "       \"client-class\": \"KNOWN\" "
+        "    }, "
+        "    { "
+        "       \"pool\": \"2001:db8:2::/64\", "
+        "       \"client-class\": \"unknown\" "
+        "    } "
+        "   ], "
+        "   \"subnet\": \"2001:db8:2::/40\", "
+        "   \"reservations\": [ "
+        "      { \"duid\": \"01:02:03:04\", \"hostname\": \"foo\" } ] "
+        " } "
+        "], "
+        "\"valid-lifetime\": 4000 }";
+
+    ASSERT_NO_THROW(configure(config));
+
+    OptionPtr clientid1 = generateClientId();
+    Pkt6Ptr query1 = Pkt6Ptr(new Pkt6(DHCPV6_SOLICIT, 1234));
+    query1->setRemoteAddr(IOAddress("2001:db8:1::3"));
+    query1->addOption(generateIA(D6O_IA_NA, 234, 1500, 3000));
+    query1->addOption(clientid1);
+    query1->setIface("eth1");
+
+    // First pool requires reservation so the second will be used
+    srv.classifyPacket(query1);
+    AllocEngine::ClientContext6 ctx1;
+    bool drop = false;
+    srv.initContext(query1, ctx1, drop);
+    ASSERT_FALSE(drop);
+    Pkt6Ptr response1 = srv.processSolicit(ctx1);
+    ASSERT_TRUE(response1);
+    OptionPtr ia_na1 = response1->getOption(D6O_IA_NA);
+    ASSERT_TRUE(ia_na1);
+    EXPECT_FALSE(ia_na1->getOption(D6O_STATUS_CODE));
+    OptionPtr iaaddr1 = ia_na1->getOption(D6O_IAADDR);
+    ASSERT_TRUE(iaaddr1);
+    boost::shared_ptr<Option6IAAddr> addr1 =
+        boost::dynamic_pointer_cast<Option6IAAddr>(iaaddr1);
+    ASSERT_TRUE(addr1);
+    EXPECT_EQ("2001:db8:2::", addr1->getAddress().toText());
+
+    // Try with DUID 01:02:03:04
+    uint8_t duid[] = { 0x01, 0x02, 0x03, 0x04 };
+    OptionBuffer buf(duid, duid + sizeof(duid));
+    OptionPtr clientid2(new Option(Option::V6, D6O_CLIENTID, buf));
+    Pkt6Ptr query2 = Pkt6Ptr(new Pkt6(DHCPV6_SOLICIT, 2345));
+    query2->setRemoteAddr(IOAddress("2001:db8:1::3"));
+    query2->addOption(generateIA(D6O_IA_NA, 234, 1500, 3000));
+    query2->addOption(clientid2);
+    query2->setIface("eth1");
+
+    // Now the first pool will be used
+    srv.classifyPacket(query2);
+    AllocEngine::ClientContext6 ctx2;
+    srv.initContext(query2, ctx2, drop);
+    ASSERT_FALSE(drop);
+    Pkt6Ptr response2 = srv.processSolicit(ctx2);
+    ASSERT_TRUE(response2);
+    OptionPtr ia_na2 = response2->getOption(D6O_IA_NA);
+    ASSERT_TRUE(ia_na2);
+    EXPECT_FALSE(ia_na2->getOption(D6O_STATUS_CODE));
+    OptionPtr iaaddr2 = ia_na2->getOption(D6O_IAADDR);
+    ASSERT_TRUE(iaaddr2);
+    boost::shared_ptr<Option6IAAddr> addr2 =
+        boost::dynamic_pointer_cast<Option6IAAddr>(iaaddr2);
+    ASSERT_TRUE(addr2);
+    EXPECT_EQ("2001:db8:1::", addr2->getAddress().toText());
+}
+
 // Tests whether a packet with custom vendor-class (not erouter or docsis)
 // is classified properly.
 TEST_F(ClassifyTest, vendorClientClassification2) {