#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>
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?
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_;
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_;
// 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
// 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
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
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:
}
// 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>(),
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
/// 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 },
"reservation-mode",
"server-hostname",
"valid-lifetime",
+ "default-valid-lifetime",
+ "min-valid-lifetime",
+ "max-valid-lifetime",
"calculate-tee-times",
"t1-percent",
"t2-percent"
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 },
"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"