2019-03-06 09:10:19 +01:00
|
|
|
// Copyright (C) 2019 Internet Systems Consortium, Inc. ("ISC")
|
|
|
|
//
|
|
|
|
// This Source Code Form is subject to the terms of the Mozilla Public
|
|
|
|
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
|
|
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
|
|
|
|
|
|
#include <config.h>
|
|
|
|
#include <dhcpsrv/triplet.h>
|
|
|
|
#include <dhcpsrv/parsers/base_network_parser.h>
|
|
|
|
#include <util/optional.h>
|
2019-09-27 15:52:28 -04:00
|
|
|
#include <util/strutil.h>
|
2019-03-06 09:10:19 +01:00
|
|
|
|
|
|
|
using namespace isc::data;
|
|
|
|
using namespace isc::util;
|
|
|
|
|
|
|
|
namespace isc {
|
|
|
|
namespace dhcp {
|
|
|
|
|
2019-05-16 01:16:20 +02:00
|
|
|
const Triplet<uint32_t>
|
|
|
|
BaseNetworkParser::parseLifetime(const ConstElementPtr& scope,
|
|
|
|
const std::string& name) {
|
2019-09-26 08:33:41 -04:00
|
|
|
uint32_t value = 0;
|
2019-05-16 01:16:20 +02:00
|
|
|
bool has_value = false;
|
2019-09-26 08:33:41 -04:00
|
|
|
uint32_t min_value = 0;
|
2019-05-16 01:16:20 +02:00
|
|
|
bool has_min = false;
|
2019-09-26 08:33:41 -04:00
|
|
|
uint32_t max_value = 0;
|
2019-05-16 01:16:20 +02:00
|
|
|
bool has_max = false;
|
|
|
|
if (scope->contains(name)) {
|
|
|
|
value = getInteger(scope, 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-"
|
2019-05-17 13:07:42 +02:00
|
|
|
<< name << " but no " << name << " (default) in "
|
|
|
|
<< scope->getPosition());
|
2019-05-16 01:16:20 +02:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
// max only.
|
|
|
|
min_value = max_value;
|
|
|
|
value = max_value;
|
|
|
|
}
|
2019-06-18 22:38:24 +02:00
|
|
|
// Check that min <= max.
|
|
|
|
if (min_value > max_value) {
|
2019-06-19 16:32:50 +02:00
|
|
|
if (has_min && has_max) {
|
|
|
|
isc_throw(DhcpConfigError, "the value of min-" << name << " ("
|
|
|
|
<< min_value << ") is not less than max-" << name << " ("
|
|
|
|
<< max_value << ")");
|
|
|
|
} else if (has_min) {
|
|
|
|
// Only min and default so min > default.
|
|
|
|
isc_throw(DhcpConfigError, "the value of min-" << name << " ("
|
|
|
|
<< min_value << ") is not less than (default) " << name
|
|
|
|
<< " (" << value << ")");
|
|
|
|
} else {
|
|
|
|
// Only default and max so default > max.
|
|
|
|
isc_throw(DhcpConfigError, "the value of (default) " << name
|
|
|
|
<< " (" << value << ") is not less than max-" << name
|
|
|
|
<< " (" << max_value << ")");
|
|
|
|
}
|
2019-06-18 22:38:24 +02:00
|
|
|
}
|
2019-05-16 01:16:20 +02:00
|
|
|
// Check that value is between min and max.
|
|
|
|
if ((value < min_value) || (value > max_value)) {
|
2019-05-17 13:07:42 +02:00
|
|
|
isc_throw(DhcpConfigError, "the value of (default) " << name << " ("
|
2019-05-16 01:16:20 +02:00
|
|
|
<< value << ") is not between min-" << name << " ("
|
|
|
|
<< min_value << ") and max-" << name << " ("
|
|
|
|
<< max_value << ")");
|
|
|
|
}
|
|
|
|
return (Triplet<uint32_t>(min_value, value, max_value));
|
|
|
|
}
|
|
|
|
|
2019-03-06 09:10:19 +01:00
|
|
|
void
|
2019-03-06 16:44:29 +01:00
|
|
|
BaseNetworkParser::parseCommonTimers(const ConstElementPtr& network_data,
|
2019-03-06 09:10:19 +01:00
|
|
|
NetworkPtr& network) {
|
2019-03-06 16:44:29 +01:00
|
|
|
if (network_data->contains("renew-timer")) {
|
|
|
|
network->setT1(getInteger(network_data, "renew-timer"));
|
2019-03-06 09:10:19 +01:00
|
|
|
}
|
|
|
|
|
2019-03-06 16:44:29 +01:00
|
|
|
if (network_data->contains("rebind-timer")) {
|
|
|
|
network->setT2(getInteger(network_data, "rebind-timer"));
|
2019-03-06 09:10:19 +01:00
|
|
|
}
|
|
|
|
|
2019-05-16 01:16:20 +02:00
|
|
|
network->setValid(parseLifetime(network_data, "valid-lifetime"));
|
2019-03-06 09:10:19 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2019-03-06 16:44:29 +01:00
|
|
|
BaseNetworkParser::parseTeePercents(const ConstElementPtr& network_data,
|
2019-03-06 09:10:19 +01:00
|
|
|
NetworkPtr& network) {
|
|
|
|
bool calculate_tee_times = network->getCalculateTeeTimes();
|
2019-03-06 16:44:29 +01:00
|
|
|
if (network_data->contains("calculate-tee-times")) {
|
2019-06-05 23:22:33 +02:00
|
|
|
calculate_tee_times = getBoolean(network_data, "calculate-tee-times");
|
2019-03-06 09:10:19 +01:00
|
|
|
network->setCalculateTeeTimes(calculate_tee_times);
|
|
|
|
}
|
|
|
|
|
|
|
|
Optional<double> t2_percent;
|
2019-03-06 16:44:29 +01:00
|
|
|
if (network_data->contains("t2-percent")) {
|
|
|
|
t2_percent = getDouble(network_data, "t2-percent");
|
2019-03-06 09:10:19 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
Optional<double> t1_percent;
|
2019-03-06 16:44:29 +01:00
|
|
|
if (network_data->contains("t1-percent")) {
|
|
|
|
t1_percent = getDouble(network_data, "t1-percent");
|
2019-03-06 09:10:19 +01:00
|
|
|
}
|
|
|
|
if (calculate_tee_times) {
|
|
|
|
if (!t2_percent.unspecified() && ((t2_percent.get() <= 0.0) ||
|
|
|
|
(t2_percent.get() >= 1.0))) {
|
|
|
|
isc_throw(DhcpConfigError, "t2-percent: " << t2_percent.get()
|
|
|
|
<< " is invalid, it must be greater than 0.0 and less than 1.0");
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!t1_percent.unspecified() && ((t1_percent.get() <= 0.0) ||
|
|
|
|
(t1_percent.get() >= 1.0))) {
|
|
|
|
isc_throw(DhcpConfigError, "t1-percent: " << t1_percent.get()
|
|
|
|
<< " is invalid it must be greater than 0.0 and less than 1.0");
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!t1_percent.unspecified() && !t2_percent.unspecified() &&
|
|
|
|
(t1_percent.get() >= t2_percent.get())) {
|
|
|
|
isc_throw(DhcpConfigError, "t1-percent: " << t1_percent.get()
|
|
|
|
<< " is invalid, it must be less than t2-percent: "
|
|
|
|
<< t2_percent.get());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
network->setT2Percent(t2_percent);
|
|
|
|
network->setT1Percent(t1_percent);
|
|
|
|
}
|
|
|
|
|
2019-04-12 11:27:49 +02:00
|
|
|
void
|
|
|
|
BaseNetworkParser::parseHostReservationMode(const data::ConstElementPtr& network_data,
|
|
|
|
NetworkPtr& network) {
|
|
|
|
if (network_data->contains("reservation-mode")) {
|
|
|
|
try {
|
|
|
|
std::string hr_mode = getString(network_data, "reservation-mode");
|
|
|
|
network->setHostReservationMode(Network::hrModeFromString(hr_mode));
|
|
|
|
} catch (const BadValue& ex) {
|
|
|
|
isc_throw(DhcpConfigError, "invalid reservation-mode parameter: "
|
|
|
|
<< ex.what() << " (" << getPosition("reservation-mode",
|
|
|
|
network_data) << ")");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-09-26 08:33:41 -04:00
|
|
|
void
|
|
|
|
BaseNetworkParser::parseDdnsParams(const data::ConstElementPtr& network_data,
|
|
|
|
NetworkPtr& network) {
|
|
|
|
|
|
|
|
if (network_data->contains("ddns-send-updates")) {
|
|
|
|
network->setDdnsSendUpdates(getBoolean(network_data, "ddns-send-updates"));
|
|
|
|
}
|
|
|
|
|
|
|
|
if (network_data->contains("ddns-override-no-update")) {
|
|
|
|
network->setDdnsOverrideNoUpdate(getBoolean(network_data, "ddns-override-no-update"));
|
|
|
|
}
|
|
|
|
|
|
|
|
if (network_data->contains("ddns-override-client-update")) {
|
|
|
|
network->setDdnsOverrideClientUpdate(getBoolean(network_data, "ddns-override-client-update"));
|
|
|
|
}
|
|
|
|
|
|
|
|
if (network_data->contains("ddns-replace-client-name")) {
|
|
|
|
network->setDdnsReplaceClientNameMode(getAndConvert<D2ClientConfig::ReplaceClientNameMode,
|
|
|
|
D2ClientConfig::stringToReplaceClientNameMode>
|
2019-09-27 15:52:28 -04:00
|
|
|
(network_data, "ddns-replace-client-name",
|
2019-09-26 08:33:41 -04:00
|
|
|
"ReplaceClientName mode"));
|
|
|
|
}
|
|
|
|
|
|
|
|
if (network_data->contains("ddns-generated-prefix")) {
|
|
|
|
network->setDdnsGeneratedPrefix(getString(network_data, "ddns-generated-prefix"));
|
|
|
|
}
|
|
|
|
|
|
|
|
if (network_data->contains("ddns-qualifying-suffix")) {
|
|
|
|
network->setDdnsQualifyingSuffix(getString(network_data, "ddns-qualifying-suffix"));
|
|
|
|
}
|
2019-09-27 15:52:28 -04:00
|
|
|
|
|
|
|
std::string hostname_char_set;
|
|
|
|
if (network_data->contains("hostname-char-set")) {
|
|
|
|
hostname_char_set = getString(network_data, "hostname-char-set");
|
|
|
|
network->setHostnameCharSet(hostname_char_set);
|
|
|
|
}
|
|
|
|
|
|
|
|
std::string hostname_char_replacement;
|
|
|
|
if (network_data->contains("hostname-char-replacement")) {
|
|
|
|
hostname_char_replacement = getString(network_data, "hostname-char-replacement");
|
|
|
|
network->setHostnameCharReplacement(hostname_char_replacement);
|
|
|
|
}
|
|
|
|
|
|
|
|
// We need to validate santizer values here so we can detect problems and
|
|
|
|
// cause a configuration. We dont' retain the compilation because it's not
|
|
|
|
// something we can inherit.
|
|
|
|
if (!hostname_char_set.empty()) {
|
|
|
|
try {
|
|
|
|
str::StringSanitizerPtr sanitizer(new str::StringSanitizer(hostname_char_set,
|
|
|
|
hostname_char_replacement));
|
|
|
|
} catch (const std::exception& ex) {
|
|
|
|
isc_throw(BadValue, "hostname-char-set '" << hostname_char_set
|
|
|
|
<< "' is not a valid regular expression");
|
|
|
|
}
|
|
|
|
}
|
2019-09-26 08:33:41 -04:00
|
|
|
}
|
|
|
|
|
2019-03-06 09:10:19 +01:00
|
|
|
} // end of namespace isc::dhcp
|
|
|
|
} // end of namespace isc
|