]> git.ipfire.org Git - thirdparty/kea.git/commitdiff
[295-min-max-lease-time-configuration-options] checkpoint
authorFrancis Dupont <fdupont@isc.org>
Wed, 15 May 2019 23:16:20 +0000 (01:16 +0200)
committerFrancis Dupont <fdupont@isc.org>
Sat, 22 Jun 2019 14:05:23 +0000 (10:05 -0400)
src/lib/dhcpsrv/alloc_engine.cc
src/lib/dhcpsrv/network.cc
src/lib/dhcpsrv/parsers/base_network_parser.cc
src/lib/dhcpsrv/parsers/base_network_parser.h
src/lib/dhcpsrv/parsers/dhcp_parsers.cc
src/lib/dhcpsrv/parsers/shared_network_parser.cc
src/lib/dhcpsrv/parsers/simple_parser4.cc
src/lib/dhcpsrv/parsers/simple_parser6.cc

index 5cfff72812b7ca5c70787cf058e5363ffb6153d2..4b373fefb9bd4dc86f4d5326a8d99a2a1aebb5ba 100644 (file)
@@ -9,6 +9,7 @@
 #include <dhcp/dhcp6.h>
 #include <dhcp/pkt4.h>
 #include <dhcp/pkt6.h>
+#include <dhcp/option_int.h>
 #include <dhcp_ddns/ncr_msg.h>
 #include <dhcpsrv/alloc_engine.h>
 #include <dhcpsrv/alloc_engine_log.h>
@@ -3437,6 +3438,17 @@ AllocEngine::createLease4(const ClientContext4& ctx, const IOAddress& addr,
         isc_throw(BadValue, "Can't create a lease without a subnet");
     }
 
+    // Use the dhcp-lease-time content or the default for lease length.
+    uint32_t valid_lft = ctx.subnet_->getValid();
+    OptionPtr opt = ctx.query_->getOption(DHO_DHCP_LEASE_TIME);
+    OptionUint32Ptr opt_lft;
+    if (opt) {
+        opt_lft = boost::dynamic_pointer_cast<OptionInt<uint32_t> >(opt);
+    }
+    if (opt_lft) {
+        valid_lft = ctx.subnet_->getValid().get(opt_lft->getValue());
+    }
+
     time_t now = time(NULL);
 
     // @todo: remove this kludge?
@@ -3447,8 +3459,7 @@ AllocEngine::createLease4(const ClientContext4& ctx, const IOAddress& addr,
     const uint8_t* local_copy0 = local_copy.empty() ? 0 : &local_copy[0];
 
     Lease4Ptr lease(new Lease4(addr, ctx.hwaddr_, local_copy0, local_copy.size(),
-                               ctx.subnet_->getValid(),
-                               now, ctx.subnet_->getID()));
+                               valid_lft, now, ctx.subnet_->getID()));
 
     // Set FQDN specific lease parameters.
     lease->fqdn_fwd_ = ctx.fwd_dns_update_;
@@ -3852,7 +3863,17 @@ AllocEngine::updateLease4Information(const Lease4Ptr& lease,
     lease->hwaddr_ = ctx.hwaddr_;
     lease->client_id_ = ctx.subnet_->getMatchClientId() ? ctx.clientid_ : ClientIdPtr();
     lease->cltt_ = time(NULL);
-    lease->valid_lft_ = ctx.subnet_->getValid();
+    // Use the dhcp-lease-time content or the default for lease length.
+    OptionPtr opt = ctx.query_->getOption(DHO_DHCP_LEASE_TIME);
+    OptionUint32Ptr opt_lft;
+    if (opt) {
+        opt_lft = boost::dynamic_pointer_cast<OptionInt<uint32_t> >(opt);
+    }
+    if (opt_lft) {
+        lease->valid_lft_ = ctx.subnet_->getValid().get(opt_lft->getValue());
+    } else {
+        lease->valid_lft_ = ctx.subnet_->getValid();
+    }
     lease->fqdn_fwd_ = ctx.fwd_dns_update_;
     lease->fqdn_rev_ = ctx.rev_dns_update_;
     lease->hostname_ = ctx.hostname_;
index 8b106aa303764b7bec723f6edc6f745f2f73bb39..a757ca2c384994f8971910ab7ac509c176584137 100644 (file)
@@ -171,8 +171,22 @@ Network::toElement() const {
 
     // Set valid-lifetime
     if (!valid_.unspecified()) {
-        map->set("valid-lifetime",
-                 Element::create(static_cast<long long>(valid_.get())));
+        if ((valid_.get() == valid_.getMin()) &&
+            (valid_.get() == valid_.getMax())) {
+            map->set("valid-lifetime",
+                     Element::create(static_cast<long long>(valid_.get())));
+        } else {
+            map->set("default-valid-lifetime",
+                     Element::create(static_cast<long long>(valid_.get())));
+            if (valid_.get() != valid_.getMin()) {
+                map->set("min-valid-lifetime",
+                         Element::create(static_cast<long long>(valid_.getMin())));
+            }
+            if (valid_.get() != valid_.getMax()) {
+                map->set("max-valid-lifetime",
+                         Element::create(static_cast<long long>(valid_.getMax())));
+            }
+        }
     }
 
     // Set reservation mode
@@ -291,8 +305,22 @@ Network6::toElement() const {
 
     // Set preferred-lifetime
     if (!preferred_.unspecified()) {
-        map->set("preferred-lifetime",
-                 Element::create(static_cast<long long>(preferred_.get())));
+        if ((preferred_.get() == preferred_.getMin()) &&
+            (preferred_.get() == preferred_.getMax())) {
+            map->set("preferred-lifetime",
+                     Element::create(static_cast<long long>(preferred_.get())));
+        } else {
+            map->set("default-preferred-lifetime",
+                     Element::create(static_cast<long long>(preferred_.get())));
+            if (preferred_.get() != preferred_.getMin()) {
+                map->set("min-preferred-lifetime",
+                         Element::create(static_cast<long long>(preferred_.getMin())));
+            }
+            if (preferred_.get() != preferred_.getMax()) {
+                map->set("max-preferred-lifetime",
+                         Element::create(static_cast<long long>(preferred_.getMax())));
+            }
+        }
     }
 
     // Set interface-id
index 257d672477c06bd092f3ad62c69f3db29306b300..eb162ecf09195dd10501c2e2efbf82ebfd2123be 100644 (file)
@@ -15,23 +15,88 @@ using namespace isc::util;
 namespace isc {
 namespace dhcp {
 
+const Triplet<uint32_t>
+BaseNetworkParser::parseLifetime(const ConstElementPtr& scope,
+                                 const std::string& name) {
+    uint32_t value;
+    bool has_value = false;
+    uint32_t min_value;
+    bool has_min = false;
+    uint32_t max_value;
+    bool has_max = false;
+    if (scope->contains(name)) {
+        value = getInteger(scope, name);
+        has_value = true;
+    }
+    if (scope->contains("default-" + name)) {
+        if (has_value) {
+            isc_throw(DhcpConfigError, "have both " << name << " and default-"
+                      << name << " in " << scope->getPosition());
+        }
+        value = getInteger(scope, "default-" + name);
+        has_value = true;
+    }
+    if (scope->contains("min-" + name)) {
+        min_value = getInteger(scope, "min-" + name);
+        has_min = true;
+    }
+    if (scope->contains("max-" + name)) {
+        max_value = getInteger(scope, "max-" + name);
+        has_max = true;
+    }
+    if (!has_value && !has_min && !has_max) {
+        return (Triplet<uint32_t>());
+    }
+    if (has_value) {
+        if (!has_min && !has_max) {
+            // default only.
+            min_value = value;
+            max_value = value;
+        } else if (!has_min) {
+            // default and max.
+            min_value = value;
+        } else if (!has_max) {
+            // default and min.
+            max_value = value;
+        }
+    } else if (has_min) {
+        // min only.
+        if (!has_max) {
+            value = min_value;
+            max_value = min_value;
+        } else {
+            // min and max.
+            isc_throw(DhcpConfigError, "have min-" << name << " and max-"
+                      << name << " but no default-" << name << " nor "
+                      << name << " in " << scope->getPosition());
+        }
+    } else {
+        // max only.
+        min_value = max_value;
+        value = max_value;
+    }
+    // Check that value is between min and max.
+    if ((value < min_value) || (value > max_value)) {
+        isc_throw(DhcpConfigError, "the value of default-" << name << " ("
+                  << value << ") is not between min-" << name << " ("
+                  << min_value << ") and max-" << name << " ("
+                  << max_value << ")");
+    }
+    return (Triplet<uint32_t>(min_value, value, max_value));
+}
+
 void
 BaseNetworkParser::parseCommonTimers(const ConstElementPtr& network_data,
                                      NetworkPtr& network) {
-    Triplet<uint32_t> t1;
     if (network_data->contains("renew-timer")) {
         network->setT1(getInteger(network_data, "renew-timer"));
     }
 
-    Triplet<uint32_t> t2;
     if (network_data->contains("rebind-timer")) {
         network->setT2(getInteger(network_data, "rebind-timer"));
     }
 
-    Triplet<uint32_t> valid;
-    if (network_data->contains("valid-lifetime")) {
-        network->setValid(getInteger(network_data, "valid-lifetime"));
-    }
+    network->setValid(parseLifetime(network_data, "valid-lifetime"));
 }
 
 void
index 57dbf39b86b6aa31ce27619bf382d685b0d265de..1800524e6f6541409b6e93486ec37af527dd3733 100644 (file)
@@ -19,6 +19,17 @@ namespace dhcp {
 class BaseNetworkParser : public data::SimpleParser {
 protected:
 
+    /// @brief Parses DHCP lifetime.
+    ///
+    /// Used here for valid-lifetime but reused for preferred-lifetime.
+    ///
+    /// @param scope Data element holding e.g.  shared network configuration
+    /// to be parsed.
+    /// @param name Base name of the lifetime parameter.
+    /// @return A triplet with the parsed lifetime value.
+    const Triplet<uint32_t> parseLifetime(const data::ConstElementPtr& scope,
+                                          const std::string& name);
+
     /// @brief Parses common DHCP timers.
     ///
     /// The parsed parameters are:
index aa36e2e954f282a69cf792462dc4ad30895968cf..1a4b24a36d64872b87c43daa4729770b22c4829b 100644 (file)
@@ -1165,10 +1165,7 @@ Subnet6ConfigParser::initSubnet(data::ConstElementPtr params,
     }
 
     // Parse preferred lifetime as it is not parsed by the common function.
-    Triplet<uint32_t> pref;
-    if (params->contains("preferred-lifetime")) {
-        pref = getInteger(params, "preferred-lifetime");
-    }
+    Triplet<uint32_t> pref = parseLifetime(params, "preferred-lifetime");
 
     // Create a new subnet.
     Subnet6* subnet6 = new Subnet6(addr, len, Triplet<uint32_t>(),
index 6572b0555984863539d14a3ad14ecb8322b9e687..93fea77dbc2a53df8de46232543c287140bd2b0c 100644 (file)
@@ -200,11 +200,8 @@ SharedNetwork6Parser::parse(const data::ConstElementPtr& shared_network_data) {
         parseCommonTimers(shared_network_data, network);
 
         // preferred-lifetime
-        Triplet<uint32_t> preferred;
-        if (shared_network_data->contains("preferred-lifetime")) {
-            shared_network->setPreferred(getInteger(shared_network_data,
-                                                    "preferred-lifetime"));
-        }
+        shared_network->setPreferred(parseLifetime(shared_network_data,
+                                                   "preferred-lifetime"));
 
         // Get interface-id option content. For now we support string
         // representation only
index 274f0cb5b447fc45f740967a10eeb5ab81fc10f2..e92e7ce7ca6088afb149a3101c1e5890ee9d5dda 100644 (file)
@@ -37,6 +37,9 @@ namespace dhcp {
 /// Order follows global_param rule in bison grammar.
 const SimpleKeywords SimpleParser4::GLOBAL4_PARAMETERS = {
     { "valid-lifetime",               Element::integer },
+    { "default-valid-lifetime",       Element::integer },
+    { "min-valid-lifetime",           Element::integer },
+    { "max-valid-lifetime",           Element::integer },
     { "renew-timer",                  Element::integer },
     { "rebind-timer",                 Element::integer },
     { "decline-probation-period",     Element::integer },
@@ -183,6 +186,9 @@ const ParamsList SimpleParser4::INHERIT_TO_SUBNET4 = {
     "reservation-mode",
     "server-hostname",
     "valid-lifetime",
+    "default-valid-lifetime",
+    "min-valid-lifetime",
+    "max-valid-lifetime",
     "calculate-tee-times",
     "t1-percent",
     "t2-percent"
index 4d907db92b6c1dc0a37841b83500ebdeced33a11..a425545ced4414e544f04580f8cf7095293cbee7 100644 (file)
@@ -37,7 +37,13 @@ namespace dhcp {
 const SimpleKeywords SimpleParser6::GLOBAL6_PARAMETERS = {
     { "data-directory",               Element::string },
     { "preferred-lifetime",           Element::integer },
+    { "default-preferred-lifetime",   Element::integer },
+    { "min-preferred-lifetime",       Element::integer },
+    { "max-preferred-lifetime",       Element::integer },
     { "valid-lifetime",               Element::integer },
+    { "default-valid-lifetime",       Element::integer },
+    { "min-valid-lifetime",           Element::integer },
+    { "max-valid-lifetime",           Element::integer },
     { "renew-timer",                  Element::integer },
     { "rebind-timer",                 Element::integer },
     { "decline-probation-period",     Element::integer },
@@ -156,12 +162,18 @@ const ParamsList SimpleParser6::INHERIT_TO_SUBNET6 = {
     "interface",
     "interface-id",
     "preferred-lifetime",
+    "default-preferred-lifetime",
+    "min-preferred-lifetime",
+    "max-preferred-lifetime",
     "rapid-commit",
     "rebind-timer",
     "relay",
     "renew-timer",
     "reservation-mode",
     "valid-lifetime",
+    "default-valid-lifetime",
+    "min-valid-lifetime",
+    "max-valid-lifetime",
     "calculate-tee-times",
     "t1-percent",
     "t2-percent"