--- /dev/null
+// Copyright (C) 2020 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/cfg_globals.h>
+
+using namespace isc::data;
+
+namespace isc {
+namespace dhcp {
+
+const std::map<std::string, int>
+CfgGlobals::nameToIndex = {
+ // Common parameters.
+ { "valid-lifetime", VALID_LIFETIME },
+ { "min-valid-lifetime", MIN_VALID_LIFETIME },
+ { "max-valid-lifetime", MAX_VALID_LIFETIME },
+ { "renew-timer", RENEW_TIMER },
+ { "rebind-timer", REBIND_TIMER },
+ { "decline-probation-period", DECLINE_PROBATION_PERIOD },
+ { "shared-networks", SHARED_NETWORKS },
+ { "interfaces-config", INTERFACES_CONFIG },
+ { "lease-database", LEASE_DATABASE },
+ { "hosts-database", HOSTS_DATABASE },
+ { "hosts-databases", HOSTS_DATABASES },
+ { "host-reservation-identifiers", HOST_RESERVATION_IDENTIFIERS },
+ { "client-classes", CLIENT_CLASSES },
+ { "option-def", OPTION_DEF },
+ { "option-data", OPTION_DATA },
+ { "hooks-libraries", HOOKS_LIBRARIES },
+ { "expired-leases-processing", EXPIRED_LEASES_PROCESSING },
+ { "dhcp4o6-port", DHCP4O6_PORT },
+ { "control-socket", CONTROL_SOCKET },
+ { "dhcp-queue-control", DHCP_QUEUE_CONTROL },
+ { "dhcp-ddns", DHCP_DDNS },
+ { "user-context", USER_CONTEXT },
+ { "comment", COMMENT },
+ { "sanity-checks", SANITY_CHECKS },
+ { "reservations", RESERVATIONS },
+ { "config-control", CONFIG_CONTROL },
+ { "server-tag", SERVER_TAG },
+ { "reservation-mode", RESERVATION_MODE },
+ { "reservations-global", RESERVATIONS_GLOBAL },
+ { "reservations-in-subnet", RESERVATIONS_IN_SUBNET },
+ { "reservations-out-of-pool", RESERVATIONS_OUT_OF_POOL },
+ { "calculate-tee-times", CALCULATE_TEE_TIMES },
+ { "t1-percent", T1_PERCENT },
+ { "t2-percent", T2_PERCENT },
+ { "loggers", LOGGERS },
+ { "hostname-char-set", HOSTNAME_CHAR_SET },
+ { "hostname-char-replacement", HOSTNAME_CHAR_REPLACEMENT },
+ { "ddns-send-updates", DDNS_SEND_UPDATES },
+ { "ddns-override-no-update", DDNS_OVERRIDE_NO_UPDATE },
+ { "ddns-override-client-update", DDNS_OVERRIDE_CLIENT_UPDATE },
+ { "ddns-replace-client-name", DDNS_REPLACE_CLIENT_NAME },
+ { "ddns-generated-prefix", DDNS_GENERATED_PREFIX },
+ { "ddns-qualifying-suffix", DDNS_QUALIFYING_SUFFIX },
+ { "store-extended-info", STORE_EXTENDED_INFO },
+ { "statistic-default-sample-count", STATISTIC_DEFAULT_SAMPLE_COUNT },
+ { "statistic-default-sample-age", STATISTIC_DEFAULT_SAMPLE_AGE },
+ { "multi-threading", MULTI_THREADING },
+ { "cache-threshold", CACHE_THRESHOLD },
+ { "cache-max-age", CACHE_MAX_AGE },
+ { "ip-reservations-unique", IP_RESERVATIONS_UNIQUE },
+ { "ddns-update-on-renew", DDNS_UPDATE_ON_RENEW },
+ { "ddns-use-conflict-resolution", DDNS_USE_CONFLICT_RESOLUTION },
+
+ // DHCPv4 specific parameters.
+ { "subnet4", SUBNET4 },
+ { "echo-client-id", ECHO_CLIENT_ID },
+ { "match-client-id", MATCH_CLIENT_ID },
+ { "authoritative", AUTHORITATIVE },
+ { "next-server", NEXT_SERVER },
+ { "server-hostname", SERVER_HOSTNAME },
+ { "boot-file-name", BOOT_FILE_NAME },
+
+ // DHCPv6 specific parameters.
+ { "data-directory", DATA_DIRECTORY },
+ { "preferred-lifetime", PREFERRED_LIFETIME },
+ { "min-preferred-lifetime", MIN_PREFERRED_LIFETIME },
+ { "max-preferred-lifetime", MAX_PREFERRED_LIFETIME },
+ { "subnet6", SUBNET6 },
+ { "mac-sources", MAC_SOURCES },
+ { "relay-supplied-options", RELAY_SUPPLIED_OPTIONS },
+ { "server-id", SERVER_ID }
+};
+
+// Load time sanity check.
+namespace {
+struct CfgGlobalsChecks {
+ CfgGlobalsChecks() {
+ // Check the size for missing entries.
+ if (CfgGlobals::nameToIndex.size() != CfgGlobals::SIZE) {
+ isc_throw(Unexpected, "CfgGlobals::nameToIndex has "
+ << CfgGlobals::nameToIndex.size()
+ << " elements (expected " << CfgGlobals::SIZE << ")");
+ }
+
+ // Build the name vector.
+ std::vector<std::string> names;
+ names.resize(CfgGlobals::SIZE);
+ for (auto it = CfgGlobals::nameToIndex.cbegin();
+ it != CfgGlobals::nameToIndex.cend(); ++it) {
+ int idx = it->second;
+ if ((idx < 0) || (idx > CfgGlobals::MAX_INDEX)) {
+ isc_throw(Unexpected, "invalid index " << idx
+ << " for name " << it->first);
+ }
+ if (!names[idx].empty()) {
+ isc_throw(Unexpected, "duplicated names for " << idx
+ << " got " << names[idx]);
+ }
+ names[idx] = it->first;
+ }
+
+ // No name should be empty.
+ for (int idx = 0; idx <= CfgGlobals::MAX_INDEX; ++idx) {
+ if (names[idx].empty()) {
+ isc_throw(Unexpected, "missing name for " << idx);
+ }
+ }
+ }
+};
+
+CfgGlobalsChecks check;
+} // end of anonymous namespace
+
+CfgGlobals::CfgGlobals() : values_(SIZE) {
+}
+
+ConstElementPtr
+CfgGlobals::get(const std::string& name) const {
+ auto const& it = nameToIndex.find(name);
+ if (it == nameToIndex.cend()) {
+ isc_throw(NotFound, "invalid global parameter name '" << name << "'");
+ }
+ return (get(it->second));
+}
+
+ConstElementPtr
+CfgGlobals::get(int index) const {
+ if ((index < 0) || (index > MAX_INDEX)) {
+ isc_throw(OutOfRange, "invalid global parameter index " << index);
+ }
+ return (values_[index]);
+}
+
+void
+CfgGlobals::set(const std::string& name, ConstElementPtr value) {
+ auto const& it = nameToIndex.find(name);
+ if (it == nameToIndex.cend()) {
+ isc_throw(NotFound, "invalid global parameter name '" << name << "'");
+ }
+ set(it->second, value);
+}
+
+void
+CfgGlobals::set(int index, ConstElementPtr value) {
+ if ((index < 0) || (index > MAX_INDEX)) {
+ isc_throw(OutOfRange, "invalid global parameter index " << index);
+ }
+ values_[index] = value;
+}
+
+void
+CfgGlobals::clear() {
+ for (int idx = 0; idx <= MAX_INDEX; ++idx) {
+ if (values_[idx]) {
+ values_[idx] = ConstElementPtr();
+ }
+ }
+}
+
+ElementPtr
+CfgGlobals::toElement() const {
+ ElementPtr result = Element::createMap();
+ for (auto it = nameToIndex.cbegin(); it != nameToIndex.cend(); ++it) {
+ int idx = it->second;
+ ConstElementPtr value = values_[idx];
+ if (value) {
+ result->set(it->first, value);
+ }
+ }
+ return (result);
+}
+
+} // namespace isc::dhcp
+} // namespace isc
--- /dev/null
+// Copyright (C) 2020 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/.
+
+#ifndef CFG_GLOBALS_H
+#define CFG_GLOBALS_H
+
+#include <cc/cfg_to_element.h>
+#include <cc/data.h>
+#include <boost/shared_ptr.hpp>
+#include <map>
+#include <string>
+#include <vector>
+
+namespace isc {
+namespace dhcp {
+
+/// @brief Class to store configured global parameters.
+///
+/// This class provides a direct access to a global parameter value
+/// using a vector as soon as the parameter name is known at compile
+/// time so in constant time vs in logarithm time using a map.
+class CfgGlobals : public isc::data::CfgToElement {
+public:
+
+ /// Class members.
+
+ /// @brief Enumeration of global parameters.
+ ///
+ /// The C++ compiler is required to start with 0 and to increment by 1
+ /// so gives an index.
+ ///
+ /// Names taken from @c SimpleParser4::GLOBAL4_PARAMETERS and
+ /// @c SimpleParser6::GLOBAL6_PARAMETERS, first part with common
+ /// parameters followed by DHCPv4 and DHCPv6 specific parameters.
+ /// Keep the order, enum element names is uppercase with - replaced by _.
+ enum Index : int {
+ // Common parameters.
+ VALID_LIFETIME,
+ MIN_VALID_LIFETIME,
+ MAX_VALID_LIFETIME,
+ RENEW_TIMER,
+ REBIND_TIMER,
+ DECLINE_PROBATION_PERIOD,
+ SHARED_NETWORKS,
+ INTERFACES_CONFIG,
+ LEASE_DATABASE,
+ HOSTS_DATABASE,
+ HOSTS_DATABASES,
+ HOST_RESERVATION_IDENTIFIERS,
+ CLIENT_CLASSES,
+ OPTION_DEF,
+ OPTION_DATA,
+ HOOKS_LIBRARIES,
+ EXPIRED_LEASES_PROCESSING,
+ DHCP4O6_PORT,
+ CONTROL_SOCKET,
+ DHCP_QUEUE_CONTROL,
+ DHCP_DDNS,
+ USER_CONTEXT,
+ COMMENT,
+ SANITY_CHECKS,
+ RESERVATIONS,
+ CONFIG_CONTROL,
+ SERVER_TAG,
+ RESERVATION_MODE,
+ RESERVATIONS_GLOBAL,
+ RESERVATIONS_IN_SUBNET,
+ RESERVATIONS_OUT_OF_POOL,
+ CALCULATE_TEE_TIMES,
+ T1_PERCENT,
+ T2_PERCENT,
+ LOGGERS,
+ HOSTNAME_CHAR_SET,
+ HOSTNAME_CHAR_REPLACEMENT,
+ DDNS_SEND_UPDATES,
+ DDNS_OVERRIDE_NO_UPDATE,
+ DDNS_OVERRIDE_CLIENT_UPDATE,
+ DDNS_REPLACE_CLIENT_NAME,
+ DDNS_GENERATED_PREFIX,
+ DDNS_QUALIFYING_SUFFIX,
+ STORE_EXTENDED_INFO,
+ STATISTIC_DEFAULT_SAMPLE_COUNT,
+ STATISTIC_DEFAULT_SAMPLE_AGE,
+ MULTI_THREADING,
+ CACHE_THRESHOLD,
+ CACHE_MAX_AGE,
+ IP_RESERVATIONS_UNIQUE,
+ DDNS_UPDATE_ON_RENEW,
+ DDNS_USE_CONFLICT_RESOLUTION,
+
+ // DHCPv4 specific parameters.
+ SUBNET4,
+ ECHO_CLIENT_ID,
+ MATCH_CLIENT_ID,
+ AUTHORITATIVE,
+ NEXT_SERVER,
+ SERVER_HOSTNAME,
+ BOOT_FILE_NAME,
+
+ // DHCPv6 specific parameters.
+ DATA_DIRECTORY,
+ PREFERRED_LIFETIME,
+ MIN_PREFERRED_LIFETIME,
+ MAX_PREFERRED_LIFETIME,
+ SUBNET6,
+ MAC_SOURCES,
+ RELAY_SUPPLIED_OPTIONS,
+ SERVER_ID
+ };
+
+ /// @brief Last index.
+ ///
+ /// @note: please update when a new element is appended to the Index enum.
+ static const int MAX_INDEX = SERVER_ID;
+
+ /// @brief Size of configured global objects.
+ static const size_t SIZE = MAX_INDEX + 1;
+
+ /// @brief Name to index map.
+ static const std::map<std::string, int> nameToIndex;
+
+ /// Instance members.
+
+ /// Constructor.
+ ///
+ /// Create a vector of null values.
+ CfgGlobals();
+
+ /// @brief Get a configured parameter value by name.
+ ///
+ /// @param name Name of the global parameter.
+ /// @return The value of the global parameter with the given name.
+ /// @throw NotFound if no global parameter has the given name.
+ isc::data::ConstElementPtr get(const std::string& name) const;
+
+ /// @brief Get a configured parameter value by index.
+ ///
+ /// @param index Index of the global parameter.
+ /// @return The value of the global parameter with the index.
+ /// @throw OutOfRange if the index is out of bounds.
+ isc::data::ConstElementPtr get(int index) const;
+
+ /// @brief Set a configured parameter value by name.
+ ///
+ /// @param name Name of the global parameter.
+ /// @param value Value of the configured parameter to set.
+ /// @throw NotFound if no global parameter has the given name.
+ void set(const std::string& name, isc::data::ConstElementPtr value);
+
+ /// @brief Set a configured parameter value by index.
+ ///
+ /// @param index Index of the global parameter.
+ /// @param value Value of the configured parameter to set.
+ /// @throw OutOfRange if the index is out of bounds.
+ void set(int index, isc::data::ConstElementPtr value);
+
+ /// @brief Clear configured parameter values.
+ void clear();
+
+ /// @brief Unparse configured globals.
+ ///
+ /// @return a pointer to unparsed globals.
+ isc::data::ElementPtr toElement() const;
+
+protected:
+ /// @brief Vectors of values.
+ std::vector<isc::data::ConstElementPtr> values_;
+};
+
+/// @brief Shared pointer to a CfgGlobals instance.
+typedef boost::shared_ptr<CfgGlobals> CfgGlobalsPtr;
+
+} // namespace isc::dhcp
+} // namespace isc
+
+#endif // CFG_GLOBALS_H