]> git.ipfire.org Git - thirdparty/kea.git/commitdiff
[5549a] Addressed comments
authorFrancis Dupont <fdupont@isc.org>
Wed, 13 Jun 2018 12:56:39 +0000 (14:56 +0200)
committerFrancis Dupont <fdupont@isc.org>
Wed, 13 Jun 2018 12:56:39 +0000 (14:56 +0200)
13 files changed:
doc/examples/kea4/advanced.json
doc/examples/kea4/classify2.json
doc/examples/kea6/advanced.json
doc/examples/kea6/classify2.json
doc/guide/dhcp4-srv.xml
doc/guide/dhcp6-srv.xml
src/bin/dhcp4/dhcp4_srv.cc
src/bin/dhcp4/dhcp4_srv.h
src/bin/dhcp4/tests/dhcp4_srv_unittest.cc
src/bin/dhcp6/dhcp6_srv.cc
src/bin/dhcp6/dhcp6_srv.h
src/bin/dhcp6/tests/classify_unittests.cc
src/lib/dhcpsrv/parsers/client_class_def_parser.cc

index 6065a68d3e304101b612d90c515c0e7d6018edf5..608a154d2f5ba6d3e7ef34f9c2d83ca14e65b9a9 100644 (file)
             "relay": {
                 "ip-address": "192.168.1.1"
             }
-        },
-        {
-            // This subnet is divided in two pools for unknown and
-            // known (i.e. which have a reservation) clients.
-            // The built-in KNOWN and UNKNOWN classes are set or not
-            // at host reservation lookup (KNOWN if this returns something,
-            // UNKNOWN if this finds nothing) and client classes depending
-            // on it are evaluated.
-            // This happens after subnet selection and before address
-            // allocation from pools.
-            "pools": [
-                {
-                   "pool": "192.0.8.100 - 192.0.8.200",
-                   "client-class": "UNKNOWN"
-                },
-                {
-                   "pool": "192.0.9.100 - 192.0.9.200",
-                   "client-class": "KNOWN"
-                }
-            ],
-            "subnet": "192.0.8.0/23",
-            "reservations": [
-                {  "hw-address": "00:00:00:11:22:33", "hostname": "h1" },
-                {  "hw-address": "00:00:00:44:55:66", "hostname": "h4" },
-                {  "hw-address": "00:00:00:77:88:99", "hostname": "h7" },
-                {  "hw-address": "00:00:00:aa:bb:cc", "hostname": "ha" }
-            ]
         }
     ]
 },
index fca82e2ab8049598daa57afc50b5c9266e52606d..f7cba5cc09335cd45ba45f2dc9a2cb34c7cfb985 100644 (file)
            } ],
            "subnet": "192.0.4.0/23",
            "interface": "ethY"
-     }
+        },
+// This subnet is divided in two pools for unknown and known
+// (i.e. which have a reservation) clients. The built-in KNOWN and
+// UNKNOWN classes are set or not at host reservation lookup (KNOWN if
+// this returns something, UNKNOWN if this finds nothing) and client
+//classes depending on it are evaluated.
+// This happens after subnet selection and before address allocation
+//from pools.
+        {
+           "pools": [
+                {
+                   "pool": "192.0.8.100 - 192.0.8.200",
+                   "client-class": "UNKNOWN"
+                },
+                {
+                   "pool": "192.0.9.100 - 192.0.9.200",
+                   "client-class": "KNOWN"
+                }
+            ],
+            "subnet": "192.0.8.0/23",
+            "reservations": [
+                {  "hw-address": "00:00:00:11:22:33", "hostname": "h1" },
+                {  "hw-address": "00:00:00:44:55:66", "hostname": "h4" },
+                {  "hw-address": "00:00:00:77:88:99", "hostname": "h7" },
+                {  "hw-address": "00:00:00:aa:bb:cc", "hostname": "ha" }
+            ]
+        }
   ]
 },
 
index 9705c6e1a76c2c61be22abfc09cc8c8c8ca381dd..2d324b1a9d502da02eabdfab09f49a3893427885 100644 (file)
         "relay": {
             "ip-address": "3000::1"
         }
-    },
-    {
-            // This subnet is divided in two pools for unknown and
-            // known (i.e. which have a reservation) clients.
-            // The built-in KNOWN and UNKNOWN classes are set or not
-            // at host reservation lookup (KNOWN if this returns something,
-            // UNKNOWN if this finds nothing) and client classes depending
-            // on it are evaluated.
-            // This happens after subnet selection and before address/prefix
-            // allocation from [pd]pools.
-        "pools": [
-            {
-               "pool": "2001:db8:8::/64",
-               "client-class": "UNKNOWN"
-            },
-            {
-               "pool": "2001:db8:9::/64",
-               "client-class": "KNOWN"
-           }
-        ],
-        "subnet": "2001:db8:8::/46",
-        "reservations": [
-            {  "hw-address": "00:00:00:11:22:33", "hostname": "h1" },
-            {  "hw-address": "00:00:00:44:55:66", "hostname": "h4" },
-            {  "hw-address": "00:00:00:77:88:99", "hostname": "h7" },
-            {  "hw-address": "00:00:00:aa:bb:cc", "hostname": "ha" }
-        ]
     }
     ]
 },
index f931ecbfd124db567a0629f0d2103d9488fa8e14..997dad3ad26f9bd7de3bc2e05fc64f6416a26534 100644 (file)
            } ],
          "subnet": "2001:db8:4::/64",
          "interface": "ethY"
+    },
+// This subnet is divided in two pools for unknown and known
+// (i.e. which have a reservation) clients. The built-in KNOWN and
+// UNKNOWN classes are set or not at host reservation lookup (KNOWN if
+// this returns something, UNKNOWN if this finds nothing) and client
+//classes depending on it are evaluated.
+// This happens after subnet selection and before address allocation
+//from pools.
+    {
+        "pools": [
+            {
+               "pool": "2001:db8:8::/64",
+               "client-class": "UNKNOWN"
+            },
+            {
+               "pool": "2001:db8:9::/64",
+               "client-class": "KNOWN"
+           }
+        ],
+        "subnet": "2001:db8:8::/46",
+        "reservations": [
+            {  "hw-address": "00:00:00:11:22:33", "hostname": "h1" },
+            {  "hw-address": "00:00:00:44:55:66", "hostname": "h4" },
+            {  "hw-address": "00:00:00:77:88:99", "hostname": "h7" },
+            {  "hw-address": "00:00:00:aa:bb:cc", "hostname": "ha" }
+        ]
     }
 
   ]
index 5b48a92a204b114e2091eadfee4e6c8feef1e577..441c3d227832bb2b12e8207aee0b1691af52ea98 100644 (file)
@@ -2241,7 +2241,7 @@ It is merely echoed by the server
       <para>
       In a similar way a pool can be constrained to serve only known
       clients, i.e. clients which have a reservation, using the
-      build-n "KNOWN" or "UNKNOWN" classes.  One can assign addresses
+      built-in "KNOWN" or "UNKNOWN" classes.  One can assign addresses
       to registered clients without giving a different address per
       reservations, for instance when there is not enough available
       addresses. The determination whether there is a reservation
index 9279e76e336d4c50d958a44457dd0e1c2b8dcec6..b192d08775acefae32188cddda572ee80c1fd1f6 100644 (file)
@@ -2239,7 +2239,7 @@ should include options from the isc option space:
       <para>
       In a similar way a pool can be constrained to serve only known
       clients, i.e. clients which have a reservation, using the
-      build-n "KNOWN" or "UNKNOWN" classes.  One can assign addresses
+      built-in "KNOWN" or "UNKNOWN" classes.  One can assign addresses
       to registered clients without giving a different address per
       reservations, for instance when there is not enough available
       addresses. The determination whether there is a reservation
index 0c67f0d603555dc84195bcd02ef91d1a089311ea..6eb3458b157347d43469a6546d7da849aac9b650 100644 (file)
@@ -166,8 +166,14 @@ Dhcpv4Exchange::Dhcpv4Exchange(const AllocEnginePtr& alloc_engine,
     // Set KNOWN builtin class if something was found, UNKNOWN if not.
     if (!context_->hosts_.empty()) {
         query->addClass("KNOWN");
+        LOG_DEBUG(dhcp4_logger, DBG_DHCP4_BASIC, DHCP4_CLASS_ASSIGNED)
+            .arg(query->getLabel())
+            .arg("KNOWN");
     } else {
         query->addClass("UNKNOWN");
+        LOG_DEBUG(dhcp4_logger, DBG_DHCP4_BASIC, DHCP4_CLASS_ASSIGNED)
+            .arg(query->getLabel())
+            .arg("UNKNOWN");
     }
 
     // Perform second pass of classification.
index 1ea0e28b09442786584e62267a0af340650cc4e9..c095cdfef00cd90448c0a14d0fbf41415f1f751e 100644 (file)
@@ -856,6 +856,9 @@ public:
     ///
     /// @note Second part of the classification.
     ///
+    /// Evaluate expressions of client classes: if it returns true the class
+    /// is added to the incoming packet.
+    ///
     /// @param pkt packet to be classified.
     /// @param depend_on_known if false classes depending on the KNOWN or
     /// UNKNOWN classes are skipped, if true only these classes are evaluated.
index b41561471c8aa6c8e22d4667f74522880adbec90..03c12a32cfef29e32fd5f4a0ff1ce5ef2c07bbcb 100644 (file)
@@ -2466,7 +2466,7 @@ TEST_F(Dhcpv4SrvTest, clientPoolClassify) {
     EXPECT_FALSE(offer->getYiaddr().isV4Zero());
 }
 
-// Checks if the [UN]KNOWN built-in classes is indeed used for pool selection.
+// Checks if the KNOWN built-in classes is indeed used for pool selection.
 TEST_F(Dhcpv4SrvTest, clientPoolClassifyKnown) {
     IfaceMgrTestConfig test_config(true);
     IfaceMgr::instance().openSockets4();
@@ -2518,6 +2518,66 @@ TEST_F(Dhcpv4SrvTest, clientPoolClassifyKnown) {
     EXPECT_EQ("192.0.3.1", offer->getYiaddr().toText());
 }
 
+// Checks if the UNKNOWN built-in classes is indeed used for pool selection.
+TEST_F(Dhcpv4SrvTest, clientPoolClassifyUnknown) {
+    IfaceMgrTestConfig test_config(true);
+    IfaceMgr::instance().openSockets4();
+
+    NakedDhcpv4Srv srv(0);
+
+    // This test configures 2 pools.
+    // The first one requires no reservation, the second does the opposite.
+    string config = "{ \"interfaces-config\": {"
+        "    \"interfaces\": [ \"*\" ]"
+        "},"
+        "\"rebind-timer\": 2000, "
+        "\"renew-timer\": 1000, "
+        "\"subnet4\": [ "
+        "{   \"pools\": [ { "
+        "      \"pool\": \"192.0.2.1 - 192.0.2.100\", "
+        "      \"client-class\": \"UNKNOWN\" }, "
+        "    { \"pool\": \"192.0.3.1 - 192.0.3.100\", "
+        "      \"client-class\": \"KNOWN\" } ], "
+        "    \"subnet\": \"192.0.0.0/16\", "
+        "    \"reservations\": [ { "
+        "       \"hw-address\": \"00:00:00:11:22:33\", "
+        "       \"hostname\": \"foo.bar\" } ] } "
+        "],"
+        "\"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);
+
+    // Set harware address / identifier
+    const HWAddr& hw = HWAddr::fromText("00:00:00:11:22:33");
+    HWAddrPtr hw_addr(new HWAddr(hw));
+    dis->setHWAddr(hw_addr);
+
+    // First pool requires no 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 79f6f836e6feeb36e1f4545bff897483fd56dffc..30ad693fe71653f736b9eeb5bc72c8c33947ddf3 100644 (file)
@@ -383,8 +383,14 @@ Dhcpv6Srv::initContext(const Pkt6Ptr& pkt,
     // Set KNOWN builtin class if something was found, UNKNOWN if not.
     if (!ctx.hosts_.empty()) {
         pkt->addClass("KNOWN");
+        LOG_DEBUG(dhcp6_logger, DBG_DHCP6_BASIC, DHCP6_CLASS_ASSIGNED)
+          .arg(pkt->getLabel())
+          .arg("KNOWN");
     } else {
         pkt->addClass("UNKNOWN");
+        LOG_DEBUG(dhcp6_logger, DBG_DHCP6_BASIC, DHCP6_CLASS_ASSIGNED)
+          .arg(pkt->getLabel())
+          .arg("UNKNOWN");
     }
 
     // Perform second pass of classification.
index 9bd50cfbf06e18b0a9c3d3eb40096e50a0b2820f..7de5ab20af354d83d423d4e478a71f466f7a67b7 100644 (file)
@@ -678,6 +678,9 @@ protected:
     ///
     /// @note Second part of the classification.
     ///
+    /// Evaluate expressions of client classes: if it returns true the class
+    /// is added to the incoming packet.
+    ///
     /// @param pkt packet to be classified.
     /// @param depend_on_known if false classes depending on the KNOWN or
     /// UNKNOWN classes are skipped, if true only these classes are evaluated.
index b8b2254d970351495859839f856d3db22ba36174..9620874853349d116198018c320e05c1eebae131 100644 (file)
@@ -1031,7 +1031,7 @@ TEST_F(ClassifyTest, clientClassifyPool) {
         "       \"client-class\": \"xyzzy\" "
         "    } "
         "   ], "
-        "   \"subnet\": \"2001:db8:2::/40\" "
+        "   \"subnet\": \"2001:db8::/40\" "
         " } "
         "], "
         "\"valid-lifetime\": 4000 }";
@@ -1110,7 +1110,7 @@ TEST_F(ClassifyTest, clientClassifyPoolKnown) {
         "       \"client-class\": \"UNKNOWN\" "
         "    } "
         "   ], "
-        "   \"subnet\": \"2001:db8:2::/40\", "
+        "   \"subnet\": \"2001:db8::/40\", "
         "   \"reservations\": [ "
         "      { \"duid\": \"01:02:03:04\", \"hostname\": \"foo\" } ] "
         " } "
index 5a78efce9fbb402066bc17f2d69912ceccdc4e78..3ac010b3de4bbd17f8bc1d4e5d9cb94e772b93dd 100644 (file)
@@ -77,12 +77,6 @@ ClientClassDefParser::parse(ClientClassDictionaryPtr& class_dictionary,
                   << getPosition("name", class_def_cfg) << ")");
     }
 
-    // Let's try to parse the only-if-required flag
-    bool required = false;
-    if (class_def_cfg->contains("only-if-required")) {
-        required = getBoolean(class_def_cfg, "only-if-required");
-    }
-
     // Parse matching expression
     ExpressionPtr match_expr;
     ConstElementPtr test_cfg = class_def_cfg->get("test");
@@ -148,6 +142,12 @@ ClientClassDefParser::parse(ClientClassDictionaryPtr& class_dictionary,
     // Parse user context
     ConstElementPtr user_context = class_def_cfg->get("user-context");
 
+    // Let's try to parse the only-if-required flag
+    bool required = false;
+    if (class_def_cfg->contains("only-if-required")) {
+        required = getBoolean(class_def_cfg, "only-if-required");
+    }
+
     // Let's try to parse the next-server field
     IOAddress next_server("0.0.0.0");
     if (class_def_cfg->contains("next-server")) {