summaryrefslogtreecommitdiffstats
path: root/src/lib/dhcpsrv/parsers/base_network_parser.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/dhcpsrv/parsers/base_network_parser.cc')
-rw-r--r--src/lib/dhcpsrv/parsers/base_network_parser.cc271
1 files changed, 271 insertions, 0 deletions
diff --git a/src/lib/dhcpsrv/parsers/base_network_parser.cc b/src/lib/dhcpsrv/parsers/base_network_parser.cc
new file mode 100644
index 0000000..9af4919
--- /dev/null
+++ b/src/lib/dhcpsrv/parsers/base_network_parser.cc
@@ -0,0 +1,271 @@
+// Copyright (C) 2019-2022 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 <util/triplet.h>
+#include <dhcpsrv/parsers/base_network_parser.h>
+#include <util/optional.h>
+#include <util/strutil.h>
+
+using namespace isc::data;
+using namespace isc::util;
+
+namespace isc {
+namespace dhcp {
+
+void
+BaseNetworkParser::moveReservationMode(ElementPtr config) {
+ if (!config->contains("reservation-mode")) {
+ return;
+ }
+ if (config->contains("reservations-global") ||
+ config->contains("reservations-in-subnet") ||
+ config->contains("reservations-out-of-pool")) {
+ isc_throw(DhcpConfigError, "invalid use of both 'reservation-mode'"
+ " and one of 'reservations-global', 'reservations-in-subnet'"
+ " or 'reservations-out-of-pool' parameters");
+ }
+ std::string hr_mode = getString(config, "reservation-mode");
+ if ((hr_mode == "disabled") || (hr_mode == "off")) {
+ config->set("reservations-global", Element::create(false));
+ config->set("reservations-in-subnet", Element::create(false));
+ } else if (hr_mode == "out-of-pool") {
+ config->set("reservations-global", Element::create(false));
+ config->set("reservations-in-subnet", Element::create(true));
+ config->set("reservations-out-of-pool", Element::create(true));
+ } else if (hr_mode == "global") {
+ config->set("reservations-global", Element::create(true));
+ config->set("reservations-in-subnet", Element::create(false));
+ } else if (hr_mode == "all") {
+ config->set("reservations-global", Element::create(false));
+ config->set("reservations-in-subnet", Element::create(true));
+ config->set("reservations-out-of-pool", Element::create(false));
+ } else {
+ isc_throw(DhcpConfigError, "invalid reservation-mode parameter: '"
+ << hr_mode << "' ("
+ << getPosition("reservation-mode", config) << ")");
+ }
+ config->remove("reservation-mode");
+}
+
+void
+BaseNetworkParser::moveReservationMode(CfgGlobalsPtr config) {
+ if (!config->get(CfgGlobals::RESERVATION_MODE)) {
+ return;
+ }
+ if (config->get(CfgGlobals::RESERVATIONS_GLOBAL) ||
+ config->get(CfgGlobals::RESERVATIONS_IN_SUBNET) ||
+ config->get(CfgGlobals::RESERVATIONS_OUT_OF_POOL)) {
+ isc_throw(DhcpConfigError, "invalid use of both 'reservation-mode'"
+ " and one of 'reservations-global', 'reservations-in-subnet'"
+ " or 'reservations-out-of-pool' parameters");
+ }
+ std::string hr_mode = config->get(CfgGlobals::RESERVATION_MODE)->stringValue();
+ if ((hr_mode == "disabled") || (hr_mode == "off")) {
+ config->set(CfgGlobals::RESERVATIONS_GLOBAL, Element::create(false));
+ config->set(CfgGlobals::RESERVATIONS_IN_SUBNET, Element::create(false));
+ } else if (hr_mode == "out-of-pool") {
+ config->set(CfgGlobals::RESERVATIONS_GLOBAL, Element::create(false));
+ config->set(CfgGlobals::RESERVATIONS_IN_SUBNET, Element::create(true));
+ config->set(CfgGlobals::RESERVATIONS_OUT_OF_POOL, Element::create(true));
+ } else if (hr_mode == "global") {
+ config->set(CfgGlobals::RESERVATIONS_GLOBAL, Element::create(true));
+ config->set(CfgGlobals::RESERVATIONS_IN_SUBNET, Element::create(false));
+ } else if (hr_mode == "all") {
+ config->set(CfgGlobals::RESERVATIONS_GLOBAL, Element::create(false));
+ config->set(CfgGlobals::RESERVATIONS_IN_SUBNET, Element::create(true));
+ config->set("reservations-out-of-pool", Element::create(false));
+ } else {
+ isc_throw(DhcpConfigError, "invalid reservation-mode parameter: '"
+ << hr_mode << "' ("
+ << config->get(CfgGlobals::RESERVATION_MODE)->getPosition()
+ << ")");
+ }
+ config->set(CfgGlobals::RESERVATION_MODE, ConstElementPtr());
+}
+
+void
+BaseNetworkParser::parseCommon(const ConstElementPtr& network_data,
+ NetworkPtr& network) {
+ bool has_renew = network_data->contains("renew-timer");
+ bool has_rebind = network_data->contains("rebind-timer");
+ int64_t renew = -1;
+ int64_t rebind = -1;
+
+ if (has_renew) {
+ renew = getInteger(network_data, "renew-timer");
+ if (renew < 0) {
+ isc_throw(DhcpConfigError, "the value of renew-timer ("
+ << renew << ") must be a positive number");
+ }
+ network->setT1(renew);
+ }
+
+ if (has_rebind) {
+ rebind = getInteger(network_data, "rebind-timer");
+ if (rebind < 0) {
+ isc_throw(DhcpConfigError, "the value of rebind-timer ("
+ << rebind << ") must be a positive number");
+ }
+ network->setT2(rebind);
+ }
+
+ if (has_renew && has_rebind && (renew > rebind)) {
+ isc_throw(DhcpConfigError, "the value of renew-timer (" << renew
+ << ") is greater than the value of rebind-timer ("
+ << rebind << ")");
+ }
+
+ network->setValid(parseIntTriplet(network_data, "valid-lifetime"));
+
+ if (network_data->contains("store-extended-info")) {
+ network->setStoreExtendedInfo(getBoolean(network_data,
+ "store-extended-info"));
+ }
+
+ if (network_data->contains("reservations-global")) {
+ network->setReservationsGlobal(getBoolean(network_data,
+ "reservations-global"));
+ }
+
+ if (network_data->contains("reservations-in-subnet")) {
+ network->setReservationsInSubnet(getBoolean(network_data,
+ "reservations-in-subnet"));
+ }
+
+ if (network_data->contains("reservations-out-of-pool")) {
+ network->setReservationsOutOfPool(getBoolean(network_data,
+ "reservations-out-of-pool"));
+ }
+}
+
+void
+BaseNetworkParser::parseTeePercents(const ConstElementPtr& network_data,
+ NetworkPtr& network) {
+ bool calculate_tee_times = network->getCalculateTeeTimes();
+ if (network_data->contains("calculate-tee-times")) {
+ calculate_tee_times = getBoolean(network_data, "calculate-tee-times");
+ network->setCalculateTeeTimes(calculate_tee_times);
+ }
+
+ Optional<double> t2_percent;
+ if (network_data->contains("t2-percent")) {
+ t2_percent = getDouble(network_data, "t2-percent");
+ }
+
+ Optional<double> t1_percent;
+ if (network_data->contains("t1-percent")) {
+ t1_percent = getDouble(network_data, "t1-percent");
+ }
+ 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);
+}
+
+void
+BaseNetworkParser::parseCacheParams(const ConstElementPtr& network_data,
+ NetworkPtr& network) {
+ if (network_data->contains("cache-threshold")) {
+ double cache_threshold = getDouble(network_data, "cache-threshold");
+ if ((cache_threshold <= 0.0) || (cache_threshold >= 1.0)) {
+ isc_throw(DhcpConfigError, "cache-threshold: " << cache_threshold
+ << " is invalid, it must be greater than 0.0 and less than 1.0");
+ }
+ network->setCacheThreshold(cache_threshold);
+ }
+
+ if (network_data->contains("cache-max-age")) {
+ network->setCacheMaxAge(getInteger(network_data, "cache-max-age"));
+ }
+}
+
+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>
+ (network_data, "ddns-replace-client-name",
+ "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"));
+ }
+
+ 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 sanitizer values here so we can detect problems and
+ // cause a configuration. We don't 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");
+ }
+ }
+
+ if (network_data->contains("ddns-update-on-renew")) {
+ network->setDdnsUpdateOnRenew(getBoolean(network_data, "ddns-update-on-renew"));
+ }
+
+ if (network_data->contains("ddns-use-conflict-resolution")) {
+ network->setDdnsUseConflictResolution(getBoolean(network_data, "ddns-use-conflict-resolution"));
+ }
+}
+
+} // end of namespace isc::dhcp
+} // end of namespace isc