From: Francis Dupont Date: Wed, 15 May 2019 23:16:20 +0000 (+0200) Subject: [295-min-max-lease-time-configuration-options] checkpoint X-Git-Tag: Kea-1.6.0-beta2~253 X-Git-Url: http://git.ipfire.org/gitweb/gitweb.cgi?a=commitdiff_plain;h=da42fc316e78a0749e0b0f6534564c67140ec995;p=thirdparty%2Fkea.git [295-min-max-lease-time-configuration-options] checkpoint --- diff --git a/src/lib/dhcpsrv/alloc_engine.cc b/src/lib/dhcpsrv/alloc_engine.cc index 5cfff72812..4b373fefb9 100644 --- a/src/lib/dhcpsrv/alloc_engine.cc +++ b/src/lib/dhcpsrv/alloc_engine.cc @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -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 >(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 >(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_; diff --git a/src/lib/dhcpsrv/network.cc b/src/lib/dhcpsrv/network.cc index 8b106aa303..a757ca2c38 100644 --- a/src/lib/dhcpsrv/network.cc +++ b/src/lib/dhcpsrv/network.cc @@ -171,8 +171,22 @@ Network::toElement() const { // Set valid-lifetime if (!valid_.unspecified()) { - map->set("valid-lifetime", - Element::create(static_cast(valid_.get()))); + if ((valid_.get() == valid_.getMin()) && + (valid_.get() == valid_.getMax())) { + map->set("valid-lifetime", + Element::create(static_cast(valid_.get()))); + } else { + map->set("default-valid-lifetime", + Element::create(static_cast(valid_.get()))); + if (valid_.get() != valid_.getMin()) { + map->set("min-valid-lifetime", + Element::create(static_cast(valid_.getMin()))); + } + if (valid_.get() != valid_.getMax()) { + map->set("max-valid-lifetime", + Element::create(static_cast(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(preferred_.get()))); + if ((preferred_.get() == preferred_.getMin()) && + (preferred_.get() == preferred_.getMax())) { + map->set("preferred-lifetime", + Element::create(static_cast(preferred_.get()))); + } else { + map->set("default-preferred-lifetime", + Element::create(static_cast(preferred_.get()))); + if (preferred_.get() != preferred_.getMin()) { + map->set("min-preferred-lifetime", + Element::create(static_cast(preferred_.getMin()))); + } + if (preferred_.get() != preferred_.getMax()) { + map->set("max-preferred-lifetime", + Element::create(static_cast(preferred_.getMax()))); + } + } } // Set interface-id diff --git a/src/lib/dhcpsrv/parsers/base_network_parser.cc b/src/lib/dhcpsrv/parsers/base_network_parser.cc index 257d672477..eb162ecf09 100644 --- a/src/lib/dhcpsrv/parsers/base_network_parser.cc +++ b/src/lib/dhcpsrv/parsers/base_network_parser.cc @@ -15,23 +15,88 @@ using namespace isc::util; namespace isc { namespace dhcp { +const Triplet +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()); + } + 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(min_value, value, max_value)); +} + void BaseNetworkParser::parseCommonTimers(const ConstElementPtr& network_data, NetworkPtr& network) { - Triplet t1; if (network_data->contains("renew-timer")) { network->setT1(getInteger(network_data, "renew-timer")); } - Triplet t2; if (network_data->contains("rebind-timer")) { network->setT2(getInteger(network_data, "rebind-timer")); } - Triplet valid; - if (network_data->contains("valid-lifetime")) { - network->setValid(getInteger(network_data, "valid-lifetime")); - } + network->setValid(parseLifetime(network_data, "valid-lifetime")); } void diff --git a/src/lib/dhcpsrv/parsers/base_network_parser.h b/src/lib/dhcpsrv/parsers/base_network_parser.h index 57dbf39b86..1800524e6f 100644 --- a/src/lib/dhcpsrv/parsers/base_network_parser.h +++ b/src/lib/dhcpsrv/parsers/base_network_parser.h @@ -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 parseLifetime(const data::ConstElementPtr& scope, + const std::string& name); + /// @brief Parses common DHCP timers. /// /// The parsed parameters are: diff --git a/src/lib/dhcpsrv/parsers/dhcp_parsers.cc b/src/lib/dhcpsrv/parsers/dhcp_parsers.cc index aa36e2e954..1a4b24a36d 100644 --- a/src/lib/dhcpsrv/parsers/dhcp_parsers.cc +++ b/src/lib/dhcpsrv/parsers/dhcp_parsers.cc @@ -1165,10 +1165,7 @@ Subnet6ConfigParser::initSubnet(data::ConstElementPtr params, } // Parse preferred lifetime as it is not parsed by the common function. - Triplet pref; - if (params->contains("preferred-lifetime")) { - pref = getInteger(params, "preferred-lifetime"); - } + Triplet pref = parseLifetime(params, "preferred-lifetime"); // Create a new subnet. Subnet6* subnet6 = new Subnet6(addr, len, Triplet(), diff --git a/src/lib/dhcpsrv/parsers/shared_network_parser.cc b/src/lib/dhcpsrv/parsers/shared_network_parser.cc index 6572b05559..93fea77dbc 100644 --- a/src/lib/dhcpsrv/parsers/shared_network_parser.cc +++ b/src/lib/dhcpsrv/parsers/shared_network_parser.cc @@ -200,11 +200,8 @@ SharedNetwork6Parser::parse(const data::ConstElementPtr& shared_network_data) { parseCommonTimers(shared_network_data, network); // preferred-lifetime - Triplet 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 diff --git a/src/lib/dhcpsrv/parsers/simple_parser4.cc b/src/lib/dhcpsrv/parsers/simple_parser4.cc index 274f0cb5b4..e92e7ce7ca 100644 --- a/src/lib/dhcpsrv/parsers/simple_parser4.cc +++ b/src/lib/dhcpsrv/parsers/simple_parser4.cc @@ -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" diff --git a/src/lib/dhcpsrv/parsers/simple_parser6.cc b/src/lib/dhcpsrv/parsers/simple_parser6.cc index 4d907db92b..a425545ced 100644 --- a/src/lib/dhcpsrv/parsers/simple_parser6.cc +++ b/src/lib/dhcpsrv/parsers/simple_parser6.cc @@ -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"