Commit 52b0c820 authored by Francis Dupont's avatar Francis Dupont
Browse files

[540-recommend-moving-hostname-char-set-and-hostname-char-replacement-out-of-d...

[540-recommend-moving-hostname-char-set-and-hostname-char-replacement-out-of-dhcp-ddns] Checkpoint before regen
parent 703ba503
......@@ -1447,6 +1447,7 @@ ControlCharacterFill [^"\\]|\\{JSONEscapeSequence}
\"hostname-char-set\" {
switch(driver.ctx_) {
case isc::dhcp::Parser4Context::DHCP4:
case isc::dhcp::Parser4Context::DHCP_DDNS:
return isc::dhcp::Dhcp4Parser::make_HOSTNAME_CHAR_SET(driver.loc_);
default:
......@@ -1456,6 +1457,7 @@ ControlCharacterFill [^"\\]|\\{JSONEscapeSequence}
\"hostname-char-replacement\" {
switch(driver.ctx_) {
case isc::dhcp::Parser4Context::DHCP4:
case isc::dhcp::Parser4Context::DHCP_DDNS:
return isc::dhcp::Dhcp4Parser::make_HOSTNAME_CHAR_REPLACEMENT(driver.loc_);
default:
......
......@@ -477,6 +477,8 @@ global_param: valid_lifetime
| t1_percent
| t2_percent
| loggers
| hostname_char_set
| hostname_char_replacement
| unknown_map_entry
;
......
......@@ -4627,8 +4627,8 @@ TEST_F(Dhcp6ParserTest, d2ClientConfig) {
EXPECT_EQ(D2ClientConfig::RCM_WHEN_PRESENT, d2_client_config->getReplaceClientNameMode());
EXPECT_EQ("test.prefix", d2_client_config->getGeneratedPrefix());
EXPECT_EQ("test.suffix.", d2_client_config->getQualifyingSuffix());
EXPECT_EQ("[^A-Za-z0-9_-]", d2_client_config->getHostnameCharSet());
EXPECT_EQ("x", d2_client_config->getHostnameCharReplacement());
EXPECT_EQ("[^A-Za-z0-9_-]", d2_client_config->getHostnameCharSet().get());
EXPECT_EQ("x", d2_client_config->getHostnameCharReplacement().get());
}
// This test checks the ability of the server to handle a configuration
......
// Copyright (C) 2013-2018 Internet Systems Consortium, Inc. ("ISC")
// Copyright (C) 2013-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
......@@ -17,6 +17,7 @@
using namespace std;
using namespace isc::asiolink;
using namespace isc::data;
using namespace isc::util;
namespace isc {
namespace dhcp {
......@@ -94,8 +95,8 @@ D2ClientConfig::D2ClientConfig(const bool enable_updates,
const ReplaceClientNameMode replace_client_name_mode,
const std::string& generated_prefix,
const std::string& qualifying_suffix,
const std::string& hostname_char_set,
const std::string& hostname_char_replacement)
Optional<std::string> hostname_char_set,
Optional<std::string> hostname_char_replacement)
: enable_updates_(enable_updates),
server_ip_(server_ip),
server_port_(server_port),
......@@ -111,7 +112,8 @@ D2ClientConfig::D2ClientConfig(const bool enable_updates,
qualifying_suffix_(qualifying_suffix),
hostname_char_set_(hostname_char_set),
hostname_char_replacement_(hostname_char_replacement),
hostname_sanitizer_(0) {
hostname_sanitizer_(0),
fetch_globals_fn_(0) {
validateContents();
}
......@@ -129,9 +131,10 @@ D2ClientConfig::D2ClientConfig()
replace_client_name_mode_(stringToReplaceClientNameMode(DFT_REPLACE_CLIENT_NAME_MODE)),
generated_prefix_(DFT_GENERATED_PREFIX),
qualifying_suffix_(""),
hostname_char_set_(DFT_HOSTNAME_CHAR_SET),
hostname_char_replacement_(DFT_HOSTNAME_CHAR_SET),
hostname_sanitizer_(0) {
hostname_char_set_(DFT_HOSTNAME_CHAR_SET, true),
hostname_char_replacement_(DFT_HOSTNAME_CHAR_SET, true),
hostname_sanitizer_(0),
fetch_globals_fn_(0) {
validateContents();
}
......@@ -170,10 +173,10 @@ D2ClientConfig::validateContents() {
<< server_ip_.toText() << "/" << server_port_);
}
if (!hostname_char_set_.empty()) {
if (!getHostnameCharSet().unspecified() && !getHostnameCharSet().empty()) {
try {
hostname_sanitizer_.reset(new isc::util::str::StringSanitizer(hostname_char_set_,
hostname_char_replacement_));
hostname_sanitizer_.reset(new isc::util::str::StringSanitizer(getHostnameCharSet(),
getHostnameCharReplacement()));
} catch (const std::exception& ex) {
isc_throw(D2ClientError, "D2ClientConfig: hostname-char-set"
" is not a valid regular expression");
......@@ -229,8 +232,8 @@ D2ClientConfig::toText() const {
<< replaceClientNameModeToString(replace_client_name_mode_)
<< ", generated-prefix: [" << generated_prefix_ << "]"
<< ", qualifying-suffix: [" << qualifying_suffix_ << "]"
<< ", hostname-char-set: [" << hostname_char_set_ << "]"
<< ", hostname-char-replacement: [" << hostname_char_replacement_ << "]";
<< ", hostname-char-set: [" << getHostnameCharSet() << "]"
<< ", hostname-char-replacement: [" << getHostnameCharReplacement() << "]";
}
return (stream.str());
......@@ -269,9 +272,13 @@ D2ClientConfig::toElement() const {
// Set generated-prefix
result->set("generated-prefix", Element::create(generated_prefix_));
// Set hostname-char-set
result->set("hostname-char-set", Element::create(hostname_char_set_));
if (!hostname_char_set_.unspecified()) {
result->set("hostname-char-set", Element::create(hostname_char_set_));
}
// Set hostname-char-replacement
result->set("hostname-char-replacement", Element::create(hostname_char_replacement_));
if (!hostname_char_replacement_.unspecified()) {
result->set("hostname-char-replacement", Element::create(hostname_char_replacement_));
}
return (result);
}
......
// Copyright (C) 2013-2018 Internet Systems Consortium, Inc. ("ISC")
// Copyright (C) 2013-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
......@@ -18,6 +18,7 @@
#include <dhcp_ddns/ncr_io.h>
#include <exceptions/exceptions.h>
#include <util/strutil.h>
#include <util/optional.h>
#include <boost/shared_ptr.hpp>
......@@ -28,7 +29,6 @@
namespace isc {
namespace dhcp {
/// An exception that is thrown if an error occurs while configuring
/// the D2 DHCP DDNS client.
class D2ClientError : public isc::Exception {
......@@ -43,6 +43,10 @@ public:
: isc::Exception(file, line, what) {}
};
/// @brief Callback function for @c D2ClientConfig that retrieves globally
/// configured parameters.
typedef std::function<data::ConstElementPtr()> FetchNetworkGlobalsFn;
/// @brief Acts as a storage vault for D2 client configuration
///
......@@ -97,7 +101,7 @@ public:
/// @param generated_prefix Prefix to use when generating domain-names.
/// @param qualifying_suffix Suffix to use to qualify partial domain-names.
/// @param hostname_char_set regular expression string which describes invalid
/// characters to be scrubbed from client host names
/// characters to be scrubbed from client host names
/// @param hostname_char_replacement string of zero or more characters to
/// replace invalid chars when sanitizing client host names
///
......@@ -118,8 +122,8 @@ public:
const ReplaceClientNameMode replace_client_name_mode,
const std::string& generated_prefix,
const std::string& qualifying_suffix,
const std::string& hostname_char_set,
const std::string& hostname_char_replacement);
util::Optional<std::string> hostname_char_set,
util::Optional<std::string> hostname_char_replacement);
/// @brief Default constructor
......@@ -195,13 +199,35 @@ public:
}
/// @brief Return the char set regexp used to sanitize client hostnames.
const std::string& getHostnameCharSet() const {
return(hostname_char_set_);
}
util::Optional<std::string> getHostnameCharSet() const {
if (hostname_char_set_.unspecified() && fetch_globals_fn_) {
data::ConstElementPtr globals = fetch_globals_fn_();
if (globals && (globals->getType() == data::Element::map)) {
data::ConstElementPtr global_param =
globals->get("hostname-char-set");
if (global_param) {
return (global_param->stringValue());
}
}
}
return (hostname_char_set_);
}
/// @brief Return the invalid char replacement used to sanitize client hostnames.
const std::string& getHostnameCharReplacement() const {
return(hostname_char_replacement_);
util::Optional<std::string> getHostnameCharReplacement() const {
if (hostname_char_replacement_.unspecified() && fetch_globals_fn_) {
data::ConstElementPtr globals = fetch_globals_fn_();
if (globals && (globals->getType() == data::Element::map)) {
data::ConstElementPtr global_param =
globals->get("hostname-char-replacement");
if (global_param) {
return (global_param->stringValue());
}
}
}
return (hostname_char_replacement_);
}
/// @brief Return pointer to compiled regular expression string sanitizer
......@@ -210,6 +236,22 @@ public:
return(hostname_sanitizer_);
}
/// @brief Sets the optional callback function used to fetch globally
/// configured parameters.
///
/// @param fetch_globals_fn Pointer to the function.
void setFetchGlobalsFn(FetchNetworkGlobalsFn fetch_globals_fn) {
fetch_globals_fn_ = fetch_globals_fn;
}
/// @brief Checks if the D2 client config is associated with a function
/// used to fetch globally configured parameters.
///
/// @return true if it is associated, false otherwise.
bool hasFetchGlobalsFn() const {
return (static_cast<bool>(fetch_globals_fn_));
}
/// @brief Compares two D2ClientConfigs for equality
bool operator == (const D2ClientConfig& other) const;
......@@ -306,14 +348,18 @@ private:
/// @brief Regular expression describing invalid characters for client hostnames.
/// If empty, host name scrubbing is not done.
std::string hostname_char_set_;
util::Optional<std::string> hostname_char_set_;
/// @brief A string to replace invalid characters when scrubbing hostnames.
/// Meaningful only if hostname_char_set_ is not empty.
std::string hostname_char_replacement_;
util::Optional<std::string> hostname_char_replacement_;
/// @brief Pointer to compiled regular expression string sanitizer
util::str::StringSanitizerPtr hostname_sanitizer_;
/// @brief Pointer to the optional callback used to fetch globally
/// configured parameters inherited to the @c D2ClientConfig object.
FetchNetworkGlobalsFn fetch_globals_fn_;
};
std::ostream&
......
......@@ -653,7 +653,7 @@ SubnetConfigParser::createSubnet(ConstElementPtr params) {
// In order to take advantage of the dynamic inheritance of global
// parameters to a subnet we need to set a callback function for each
// subnet to allow for fetching global parameters.
subnet_->setFetchGlobalsFn([]() -> ConstElementPtr {
subnet_->setFetchGlobalsFn([]() -> ConstElementPtr {
return (CfgMgr::instance().getCurrentCfg()->getConfiguredGlobals());
});
......@@ -1384,11 +1384,16 @@ D2ClientConfigParser::parse(isc::data::ConstElementPtr client_config) {
std::string generated_prefix =
getString(client_config, "generated-prefix");
std::string hostname_char_set =
getString(client_config, "hostname-char-set");
Optional<std::string> hostname_char_set(D2ClientConfig::DFT_HOSTNAME_CHAR_SET, true);
if (client_config->contains("hostname-char-set")) {
hostname_char_set = getString(client_config, "hostname-char-set");
}
std::string hostname_char_replacement =
getString(client_config, "hostname-char-replacement");
Optional<std::string> hostname_char_replacement(D2ClientConfig::DFT_HOSTNAME_CHAR_REPLACEMENT, true);
if (client_config->contains("hostname-char-replacement")) {
hostname_char_replacement =
getString(client_config, "hostname-char-replacement");
}
// qualifying-suffix is the only parameter which has no default
std::string qualifying_suffix = "";
......@@ -1484,6 +1489,13 @@ D2ClientConfigParser::parse(isc::data::ConstElementPtr client_config) {
new_config->setContext(user_context);
}
// In order to take advantage of the dynamic inheritance of global
// parameters to a subnet we need to set a callback function for
// the d2 client config to allow for fetching global parameters.
new_config->setFetchGlobalsFn([]() -> ConstElementPtr {
return (CfgMgr::instance().getCurrentCfg()->getConfiguredGlobals());
});
return(new_config);
}
......@@ -1502,9 +1514,8 @@ const SimpleDefaults D2ClientConfigParser::D2_CLIENT_CONFIG_DEFAULTS = {
{ "override-no-update", Element::boolean, "false" },
{ "override-client-update", Element::boolean, "false" },
{ "replace-client-name", Element::string, "never" },
{ "generated-prefix", Element::string, "myhost" },
{ "hostname-char-set", Element::string, "" },
{ "hostname-char-replacement", Element::string, "" }
{ "generated-prefix", Element::string, "myhost" }
// hostname-char-set and hostname-char-replacement moved to global
// qualifying-suffix has no default
};
......
......@@ -72,7 +72,9 @@ const SimpleKeywords SimpleParser4::GLOBAL4_PARAMETERS = {
{ "calculate-tee-times", Element::boolean },
{ "t1-percent", Element::real },
{ "t2-percent", Element::real },
{ "loggers", Element::list }
{ "loggers", Element::list },
{ "hostname-char-set", Element::string },
{ "hostname-char-replacement", Element::string }
};
/// @brief This table defines default values for option definitions in DHCPv4.
......@@ -103,20 +105,20 @@ const SimpleDefaults SimpleParser4::OPTION4_DEFAULTS = {
/// in Dhcp4) are optional. If not defined, the following values will be
/// used.
const SimpleDefaults SimpleParser4::GLOBAL4_DEFAULTS = {
{ "valid-lifetime", Element::integer, "7200" },
{ "decline-probation-period", Element::integer, "86400" }, // 24h
{ "dhcp4o6-port", Element::integer, "0" },
{ "echo-client-id", Element::boolean, "true" },
{ "match-client-id", Element::boolean, "true" },
{ "authoritative", Element::boolean, "false" },
{ "next-server", Element::string, "0.0.0.0" },
{ "server-hostname", Element::string, "" },
{ "boot-file-name", Element::string, "" },
{ "server-tag", Element::string, "" },
{ "reservation-mode", Element::string, "all" },
{ "calculate-tee-times", Element::boolean, "false" },
{ "t1-percent", Element::real, ".50" },
{ "t2-percent", Element::real, ".875" }
{ "valid-lifetime", Element::integer, "7200" },
{ "decline-probation-period", Element::integer, "86400" }, // 24h
{ "dhcp4o6-port", Element::integer, "0" },
{ "echo-client-id", Element::boolean, "true" },
{ "match-client-id", Element::boolean, "true" },
{ "authoritative", Element::boolean, "false" },
{ "next-server", Element::string, "0.0.0.0" },
{ "server-hostname", Element::string, "" },
{ "boot-file-name", Element::string, "" },
{ "server-tag", Element::string, "" },
{ "reservation-mode", Element::string, "all" },
{ "calculate-tee-times", Element::boolean, "false" },
{ "t1-percent", Element::real, ".50" },
{ "t2-percent", Element::real, ".875" }
};
/// @brief This table defines default values for each IPv4 subnet.
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment