]> git.ipfire.org Git - thirdparty/kea.git/commitdiff
[5425] Added basic support (alloc engine todo)
authorFrancis Dupont <fdupont@isc.org>
Sun, 19 Nov 2017 23:27:46 +0000 (00:27 +0100)
committerFrancis Dupont <fdupont@isc.org>
Sun, 19 Nov 2017 23:27:46 +0000 (00:27 +0100)
12 files changed:
doc/examples/kea4/advanced.json
doc/examples/kea6/advanced.json
doc/guide/dhcp4-srv.xml
doc/guide/dhcp6-srv.xml
src/lib/dhcpsrv/parsers/dhcp_parsers.cc
src/lib/dhcpsrv/parsers/dhcp_parsers.h
src/lib/dhcpsrv/pool.cc
src/lib/dhcpsrv/pool.h
src/lib/dhcpsrv/subnet.cc
src/lib/dhcpsrv/tests/cfg_subnets4_unittest.cc
src/lib/dhcpsrv/tests/cfg_subnets6_unittest.cc
src/lib/dhcpsrv/tests/pool_unittest.cc

index 327047bcd24b2cbf5a8768fe82144a7a8c5996e7..34b062e269bf3e0ed82c8e53539ffdf875c38619 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.
+            "pools": [
+                {
+                   "pool": "192.0.8.100 - 192.0.8.200",
+                   "known-clients": "never"
+                },
+                {
+                   "pool": "192.0.9.100 - 192.0.9.200",
+                   "known-clients": "only"
+                }
+            ],
+            "subnet": "192.0.8.0/23",
+            "reservations": [
+                {  "hw-address": "00:00:00:11:22:33" },
+                {  "hw-address": "00:00:00:44:55:66" },
+                {  "hw-address": "00:00:00:77:88:99" },
+                {  "hw-address": "00:00:00:aa:bb:cc" }
+            ]
         }
     ]
 },
index a8e67ee973fff17fbcfdc964b5a9e93488c2082c..7a6a50a152000f77797c8039bea9607c27ca92ff 100644 (file)
         // and another is when there is a shared subnet scenario.
         "relay": {
             "ip-address": "3000::1"
-        }
+        },
+    },
+    {
+        // This subnet is divided in two pools for unknown and
+        // known (i.e. which have a reservation) clients.
+        "pools": [
+            {
+               "pool": "2001:db8:8::/64",
+               "known-clients": "never"
+            },
+            {
+               "pool": "2001:db8:9::/64",
+               "known-clients": "only"
+           }
+        ],
+        "subnet": "2001:db8:8::/46",
+        "reservations": [
+            {  "hw-address": "00:00:00:11:22:33" },
+            {  "hw-address": "00:00:00:44:55:66" },
+            {  "hw-address": "00:00:00:77:88:99" },
+            {  "hw-address": "00:00:00:aa:bb:cc" }
+        ]
     }
     ]
 },
index bdd58cf0158938d1862a8acbf2e2bf6982c711f3..34f2fd9e81fe8131be60a466d135f58607572032 100644 (file)
@@ -2090,6 +2090,15 @@ It is merely echoed by the server
       at the pool level, see <xref linkend="classification-pools"/>.
       </para>
 
+      <para>
+      In a similar way a pool can be constrained to serve only known clients,
+      i.e. clients which have a reservation, using
+      <command>"known-clients": "only"</command>, or only unknown clients
+      with <command>"known-clients": "never"</command>. One can assign
+      addresses to registered clients without giving a different address per
+      reservations, for instance when there is not enough available addresses.
+      </para>
+
       <para>
       The process of doing classification is conducted in three steps. The first step
       is to assess an incoming packet and assign it to zero or more classes.  The
index a577843c372016edaff3cef98d2b077833cb332f..1ac0cf5aacd55d987a02586cd12c398318026b86 100644 (file)
@@ -1950,6 +1950,15 @@ should include options from the isc option space:
       linkend="classification-pools"/>.
       </para>
 
+      <para>
+      In a similar way a pool can be constrained to serve only known clients,
+      i.e. clients which have a reservation, using
+      <command>"known-clients": "only"</command>, or only unknown clients
+      with <command>"known-clients": "never"</command>. One can assign
+      prefixes to registered clients without giving a different prefix per
+      reservations, forinstance when there is not enough available prefixes.
+      </para>
+
       <para>
       The process of doing classification is conducted in three steps. The first step
       is to assess an incoming packet and assign it to zero or more classes.  The
index 4499cbe4aa5fdecc34574ba39982d98bd0843ff9..a384dbf135b49fb47a91f55ccaa3daf89bef0d12 100644 (file)
@@ -387,6 +387,19 @@ PoolParser::parse(PoolStoragePtr pools,
             pool->allowClientClass(cclass);
         }
     }
+
+    // Known-clients.
+    ConstElementPtr known_clients = pool_structure->get("known-clients");
+    if (known_clients) {
+        string kc = known_clients->stringValue();
+        if (kc == "only") {
+            pool->setKnownClients(Pool::SERVE_KNOWN);
+        } else if (kc == "never") {
+            pool->setKnownClients(Pool::SERVE_UNKNOWN);
+        } else
+            isc_throw(DhcpConfigError, "invalid known-clients value: " << kc
+                      << " (" << known_clients->getPosition() << ")");
+    }
 }
 
 //****************************** Pool4Parser *************************
@@ -861,6 +874,11 @@ PdPoolParser::parse(PoolStoragePtr pools, ConstElementPtr pd_pool_) {
         client_class_ = client_class;
     }
 
+    ConstElementPtr known_clients = pd_pool_->get("known-clients");
+    if (known_clients) {
+        known_clients_ = known_clients;
+    }
+
     // Check the pool parameters. It will throw an exception if any
     // of the required parameters are invalid.
     try {
@@ -884,7 +902,6 @@ PdPoolParser::parse(PoolStoragePtr pools, ConstElementPtr pd_pool_) {
         pool_->setContext(user_context_);
     }
 
-
     if (client_class_) {
         string cclass = client_class_->stringValue();
         if (!cclass.empty()) {
@@ -892,6 +909,18 @@ PdPoolParser::parse(PoolStoragePtr pools, ConstElementPtr pd_pool_) {
         }
     }
         
+    if (known_clients_) {
+        string kc = known_clients_->stringValue();
+        if (kc == "only") {
+            pool_->setKnownClients(Pool::SERVE_KNOWN);
+        } else if (kc == "never") {
+            pool_->setKnownClients(Pool::SERVE_UNKNOWN);
+        } else
+            isc_throw(isc::dhcp::DhcpConfigError,
+                      "invalid known-clients value: " << kc
+                      << " (" << known_clients_->getPosition() << ")");
+    }
+
     // Add the local pool to the external storage ptr.
     pools->push_back(pool_);
 }
index e195cd4bad33a934fef07c21fe8efa36df84007b..adabdb77325f4b1a8bacb7660bcdecc260fec7bc 100644 (file)
@@ -655,6 +655,7 @@ private:
 
     isc::data::ConstElementPtr client_class_;
 
+    isc::data::ConstElementPtr known_clients_;
 };
 
 /// @brief Parser for a list of prefix delegation pools.
index 3e41426eacd2cfe100b16846c8b3322105f1546a..da3258f2b9c7f87fc4790f12304aee5d481546c0 100644 (file)
@@ -19,6 +19,7 @@ Pool::Pool(Lease::Type type, const isc::asiolink::IOAddress& first,
            const isc::asiolink::IOAddress& last)
     :id_(getNextID()), first_(first), last_(last), type_(type),
      capacity_(0), cfg_option_(new CfgOption()), white_list_(),
+     known_clients_(SERVE_BOTH),
      last_allocated_(first), last_allocated_valid_(false) {
 }
 
@@ -121,6 +122,13 @@ Pool::toElement() const {
         map->set("client-class", Element::create(*cclasses.cbegin()));
     }
 
+    // Set known-clients
+    KnownClients kc = getKnownClients();
+    if (kc != SERVE_BOTH) {
+        map->set("known-clients",
+                 Element::create(kc == SERVE_KNOWN ? "only" : "never"));
+    }
+
     return (map);
 }
 
index 5254ea5ca5b6ef5d534d47a9796f4238464e8582..d74022ac331712cd46d5984fd42512dcaebf0d41 100644 (file)
@@ -28,6 +28,13 @@ namespace dhcp {
 class Pool {
 
 public:
+    /// @brief Value of known clients
+    typedef enum {
+        SERVE_BOTH = 0,   ///< the pool serves both known and unknown clients
+        SERVE_KNOWN = 1,  ///< the pool serves only known clients
+        SERVE_UNKNOWN = 2 ///< the pool never serves known clients
+    } KnownClients;
+
     /// @note:
     /// PoolType enum was removed. Please use Lease::Type instead
 
@@ -133,6 +140,16 @@ public:
         return (white_list_);
     }
 
+    /// @brief Returns the value of known clients
+    KnownClients getKnownClients() const {
+        return (known_clients_);
+    }
+
+    /// @brief Sets the value of known clients
+    void setKnownClients(KnownClients known_clients) {
+        known_clients_ = known_clients;
+    }
+
     /// @brief returns the last address that was tried from this pool
     ///
     /// @return address/prefix that was last tried from this pool
@@ -222,6 +239,9 @@ protected:
     /// @ref Network::white_list_
     ClientClasses white_list_;
 
+    /// @brief Value of known clients
+    KnownClients known_clients_;
+
     /// @brief Pointer to the user context (may be NULL)
     data::ConstElementPtr user_context_;
 
index a07a9c47c0bd60f94c6b8d497ba27bf37430d354..8585264aa9f2060e05a33403a4d74498cbb3d107 100644 (file)
@@ -742,6 +742,13 @@ Subnet6::toElement() const {
         } else if (!cclasses.empty()) {
             pool_map->set("client-class", Element::create(*cclasses.cbegin()));
         }
+        // Set known-clients
+        Pool::KnownClients kc = (*pool)->getKnownClients();
+        if (kc != Pool::SERVE_BOTH) {
+            pool_map->set("known-clients",
+                          Element::create(kc == Pool::SERVE_KNOWN ?
+                                          "only" : "never"));
+        }
         // Push on the pool list
         pool_list->add(pool_map);
     }
@@ -804,6 +811,13 @@ Subnet6::toElement() const {
         } else if (!cclasses.empty()) {
             pool_map->set("client-class", Element::create(*cclasses.cbegin()));
         }
+        // Set known-clients
+        Pool::KnownClients kc = pdpool->getKnownClients();
+        if (kc != Pool::SERVE_BOTH) {
+            pool_map->set("known-clients",
+                          Element::create(kc == Pool::SERVE_KNOWN ?
+                                          "only" : "never"));
+        }
         // Push on the pool list
         pdpool_list->add(pool_map);
     }
index 0e5e0c59ed3ac51311827f0a24384eb2fdd5891f..c97c7bee84050ffdd669b37dbc5c5730fe10b9f6 100644 (file)
@@ -813,6 +813,7 @@ TEST(CfgSubnets4Test, unparsePool) {
     Pool4Ptr pool1(new Pool4(IOAddress("192.0.2.1"), IOAddress("192.0.2.10")));
     Pool4Ptr pool2(new Pool4(IOAddress("192.0.2.64"), 26));
     pool2->allowClientClass("bar");
+    pool2->setKnownClients(Pool::SERVE_KNOWN);
 
     subnet->addPool(pool1);
     subnet->addPool(pool2);
@@ -843,7 +844,8 @@ TEST(CfgSubnets4Test, unparsePool) {
         "        },{\n"
         "            \"option-data\": [ ],\n"
         "            \"pool\": \"192.0.2.64/26\",\n"
-        "            \"client-class\": \"bar\"\n"
+        "            \"client-class\": \"bar\",\n"
+        "            \"known-clients\": \"only\"\n"
         "        }\n"
         "    ]\n"
         "} ]\n";
index df09f3301fc899a6f07df5de0a513b588435ad73..d12cada9569224c8266d3e7d1eeb0f58c46305e2 100644 (file)
@@ -504,6 +504,7 @@ TEST(CfgSubnets6Test, unparsePool) {
                              IOAddress("2001:db8:1::199")));
     Pool6Ptr pool2(new Pool6(Lease::TYPE_NA, IOAddress("2001:db8:1:1::"), 64));
     pool2->allowClientClass("bar");
+    pool2->setKnownClients(Pool::SERVE_UNKNOWN);
 
     subnet->addPool(pool1);
     subnet->addPool(pool2);
@@ -528,7 +529,8 @@ TEST(CfgSubnets6Test, unparsePool) {
         "        },{\n"
         "            \"pool\": \"2001:db8:1:1::/64\",\n"
         "            \"option-data\": [ ],\n"
-        "            \"client-class\": \"bar\"\n"
+        "            \"client-class\": \"bar\",\n"
+        "            \"known-clients\": \"never\"\n"
         "        }\n"
         "    ],\n"
         "    \"pd-pools\": [ ],\n"
@@ -550,6 +552,7 @@ TEST(CfgSubnets6Test, unparsePdPool) {
     Pool6Ptr pdpool2(new Pool6(IOAddress("2001:db8:3::"), 48, 56,
                                IOAddress("2001:db8:3::"), 64));
     pdpool2->allowClientClass("bar");
+    pdpool2->setKnownClients(Pool::SERVE_KNOWN);
 
     subnet->addPool(pdpool1);
     subnet->addPool(pdpool2);
@@ -581,7 +584,8 @@ TEST(CfgSubnets6Test, unparsePdPool) {
         "            \"excluded-prefix\": \"2001:db8:3::\",\n"
         "            \"excluded-prefix-len\": 64,\n"
         "            \"option-data\": [ ],\n"
-        "            \"client-class\": \"bar\"\n"
+        "            \"client-class\": \"bar\",\n"
+        "            \"known-clients\": \"only\"\n"
         "        }\n"
         "    ],\n"
         "    \"option-data\": [ ]\n"
index 5662f6a5ce158281bd24f4d000f63809dab82753..d720c2b023e21f0f79d44b7d59f5db2e09093a3a 100644 (file)
@@ -268,6 +268,20 @@ TEST(Pool4Test, clientClasses) {
     EXPECT_TRUE(pool->clientSupported(bar_class));
 }
 
+// This test checks that handling for known-clients is valid.
+TEST(Pool4Test, knownClients) {
+    // Create a pool.
+    Pool4Ptr pool(new Pool4(IOAddress("192.0.2.0"),
+                            IOAddress("192.0.2.255")));
+
+    // This pool serves everybody by default.
+    EXPECT_EQ(Pool::SERVE_BOTH, pool->getKnownClients());
+
+    // Set it to only known clients.
+    pool->setKnownClients(Pool::SERVE_KNOWN);
+    EXPECT_EQ(Pool::SERVE_KNOWN,pool->getKnownClients());
+}
+
 // This test checks that handling for last allocated address/prefix is valid.
 TEST(Pool4Test, lastAllocated) {
     // Create a pool.
@@ -638,7 +652,7 @@ TEST(Pool6Test, clientClass) {
 TEST(Pool6Test, clientClasses) {    
     // Create a pool.
     Pool6 pool(Lease::TYPE_NA, IOAddress("2001:db8::1"),
-                IOAddress("2001:db8::2"));
+               IOAddress("2001:db8::2"));
 
     // This client does not belong to any class.
     isc::dhcp::ClientClasses no_class;
@@ -672,6 +686,20 @@ TEST(Pool6Test, clientClasses) {
     EXPECT_TRUE(pool.clientSupported(bar_class));
 }
 
+// This test checks that handling for known-clients is valid.
+TEST(Pool6Test, knownClients) {
+    // Create a pool.
+    Pool6 pool(Lease::TYPE_NA, IOAddress("2001:db8::1"),
+               IOAddress("2001:db8::2"));
+
+    // This pool serves everybody by default.
+    EXPECT_EQ(Pool::SERVE_BOTH, pool.getKnownClients());
+
+    // Set it to only known clients.
+    pool.setKnownClients(Pool::SERVE_KNOWN);
+    EXPECT_EQ(Pool::SERVE_KNOWN,pool.getKnownClients());
+}
+
 // This test checks that handling for last allocated address/prefix is valid.
 TEST(Pool6Test, lastAllocated) {
     // Create a pool.