Commit bd60252e authored by Thomas Markwalder's avatar Thomas Markwalder

[master] Merge branch 'trac3268'

Added osx_version check of 10.9.3 to configure.ac
Fixed Conflicts:
	src/bin/d2/tests/nc_test_utils.cc
	src/lib/dns/tests/labelsequence_unittest.cc
parents 075a6e58 0387d65f
......@@ -245,11 +245,13 @@ case "$host" in
# it should be avoided to rely on 'osx_version' unless there's no
# viable alternative.
osx_version=`/usr/bin/sw_vers -productVersion`
if [ test $osx_version = "10.9" \
-o $osx_version = "10.9.1" \
-o $osx_version = "10.9.2" ]; then
bind10_undefined_pthread_behavior=yes
fi
-o $osx_version = "10.9.1" \
-o $osx_version = "10.9.2" \
-o $osx_version = "10.9.3" ]; then
bind10_undefined_pthread_behavior=yes
fi
# libtool doesn't work perfectly with Darwin: libtool embeds the
# final install path in dynamic libraries and our loadable python
......
......@@ -5263,9 +5263,11 @@ Dhcp6/renew-timer 1000 integer (default)
configuration will be available. It will look similar to this:
<screen>
&gt; <userinput>config show DhcpDdns</userinput>
DhcpDdns/interface "eth0" string (default)
DhcpDdns/ip_address "127.0.0.1" string (default)
DhcpDdns/port 53001 integer (default)
DhcpDdns/dns_server_timeout 100 integer (default)
DhcpDdns/ncr_protocol "UDP" string (default)
DhcpDdns/ncr_format "JSON" string (default)
DhcpDdns/tsig_keys [] list (default)
DhcpDdns/forward_ddns/ddns_domains [] list (default)
DhcpDdns/reverse_ddns/ddns_domains [] list (default)
......@@ -5282,7 +5284,7 @@ DhcpDdns/reverse_ddns/ddns_domains [] list (default)
<itemizedlist>
<listitem>
<simpara>
<command>General Server Parameters</command> &mdash;
<command>Global Server Parameters</command> &mdash;
values which control connectivity and global server behavior
</simpara>
</listitem>
......@@ -5306,20 +5308,43 @@ DhcpDdns/reverse_ddns/ddns_domains [] list (default)
</listitem>
</itemizedlist>
<section id="d2-server-parameter-config">
<title>General Server Parameters</title>
<title>Global Server Parameters</title>
<orderedlist>
<listitem><para>
ip_address - IP address on which D2 listens for requests. The default is
the local loopback interface at address 127.0.0.1. You may specify
either an IPv4 or IPv6 address.
</para></listitem>
<listitem><para>
port - Port on which D2 listens for requests. The default value
is 53001.
</para></listitem>
<listitem><para>
ncr_format - Socket protocol to use when sending requests to D2.
Currently only UDP is supported. TCP may be available in an upcoming
release.
</para></listitem>
<listitem><para>
ncr_protocol - Packet format to use when sending requests to D2.
Currently only JSON format is supported. Other formats may be available
in future releases.
</para></listitem>
<listitem><para>
dns_server_timeout - The maximum amount of time in milliseconds, that
D2 will wait for a response from a DNS server to a single DNS update
message.
</para></listitem>
</orderedlist>
<para>
The DHCP-DDNS server must listen for requests on a known address and
port. By default, it will listen at 127.0.0.1 on port 53001. This is
governed by the parameters, "ip-address" and "port". Either value
may be changed using config set/commit. For example to change the
server to listen at 192.168.1.10 port 900:
D2 must listen for change requests on a known address and port. By
default it listens at 127.0.0.1 on port 53001. The following example
illustrates how to change D2's global parameters so it will listen
at 192.168.1.10 port 900:
<screen>
&gt; <userinput>config set DhcpDdns/ip_address "192.168.1.10"</userinput>
&gt; <userinput>config set DhcpDdns/port 900</userinput>
&gt; <userinput>config commit</userinput>
</screen>
The server may be configured to listen over IPv4 or IPv6, therefore
ip-address may an IPv4 or IPv6 address.
</para>
<warning>
<simpara>
......@@ -5332,7 +5357,6 @@ DhcpDdns/reverse_ddns/ddns_domains [] list (default)
authentication to guard against such attacks.
</simpara>
</warning>
<note>
<simpara>
If the ip_address and port are changed, it will be necessary to change the
......
......@@ -30,12 +30,14 @@ typedef std::vector<uint8_t> ByteAddress;
// *********************** D2CfgContext *************************
D2CfgContext::D2CfgContext()
: forward_mgr_(new DdnsDomainListMgr("forward_mgr")),
: d2_params_(new D2Params()),
forward_mgr_(new DdnsDomainListMgr("forward_mgr")),
reverse_mgr_(new DdnsDomainListMgr("reverse_mgr")),
keys_(new TSIGKeyInfoMap()) {
}
D2CfgContext::D2CfgContext(const D2CfgContext& rhs) : DCfgContextBase(rhs) {
d2_params_ = rhs.d2_params_;
if (rhs.forward_mgr_) {
forward_mgr_.reset(new DdnsDomainListMgr(rhs.forward_mgr_->getName()));
forward_mgr_->setDomains(rhs.forward_mgr_->getDomains());
......@@ -61,9 +63,6 @@ const char* D2CfgMgr::IPV6_REV_ZONE_SUFFIX = "ip6.arpa.";
D2CfgMgr::D2CfgMgr() : DCfgMgrBase(DCfgContextBasePtr(new D2CfgContext())) {
// TSIG keys need to parse before the Domains, so we can catch Domains
// that specify undefined keys. Create the necessary parsing order now.
addToParseOrder("interface");
addToParseOrder("ip_address");
addToParseOrder("port");
addToParseOrder("tsig_keys");
addToParseOrder("forward_ddns");
addToParseOrder("reverse_ddns");
......@@ -72,6 +71,11 @@ D2CfgMgr::D2CfgMgr() : DCfgMgrBase(DCfgContextBasePtr(new D2CfgContext())) {
D2CfgMgr::~D2CfgMgr() {
}
DCfgContextBasePtr
D2CfgMgr::createNewContext() {
return (DCfgContextBasePtr(new D2CfgContext()));
}
bool
D2CfgMgr::forwardUpdatesEnabled() {
// Forward updates are not enabled if no forward servers are defined.
......@@ -187,6 +191,47 @@ D2CfgMgr::reverseV6Address(const isc::asiolink::IOAddress& ioaddr) {
return(stream.str());
}
const D2ParamsPtr&
D2CfgMgr::getD2Params() {
return (getD2CfgContext()->getD2Params());
}
void
D2CfgMgr::buildParams(isc::data::ConstElementPtr params_config) {
// Base class build creates parses and invokes build on each parser.
// This populate the context scalar stores with all of the parameters.
DCfgMgrBase::buildParams(params_config);
// Fetch the parameters from the context to create the D2Params.
D2CfgContextPtr context = getD2CfgContext();
isc::dhcp::StringStoragePtr strings = context->getStringStorage();
asiolink::IOAddress ip_address(strings->
getOptionalParam("ip_address",
D2Params::DFT_IP_ADDRESS));
isc::dhcp::Uint32StoragePtr ints = context->getUint32Storage();
uint32_t port = ints->getOptionalParam("port", D2Params::DFT_PORT);
uint32_t dns_server_timeout
= ints->getOptionalParam("dns_server_timeout",
D2Params::DFT_DNS_SERVER_TIMEOUT);
dhcp_ddns::NameChangeProtocol ncr_protocol
= dhcp_ddns::stringToNcrProtocol(strings->
getOptionalParam("ncr_protocol",
D2Params::
DFT_NCR_PROTOCOL));
dhcp_ddns::NameChangeFormat ncr_format
= dhcp_ddns::stringToNcrFormat(strings->
getOptionalParam("ncr_format",
D2Params::
DFT_NCR_FORMAT));
// Attempt to create the new client config.
D2ParamsPtr params(new D2Params(ip_address, port, dns_server_timeout,
ncr_protocol, ncr_format));
context->getD2Params() = params;
}
isc::dhcp::ParserPtr
D2CfgMgr::createConfigParser(const std::string& config_id) {
......@@ -194,31 +239,34 @@ D2CfgMgr::createConfigParser(const std::string& config_id) {
D2CfgContextPtr context = getD2CfgContext();
// Create parser instance based on element_id.
isc::dhcp::DhcpConfigParser* parser = NULL;
if ((config_id == "interface") ||
(config_id == "ip_address")) {
parser = new isc::dhcp::StringParser(config_id,
context->getStringStorage());
} else if (config_id == "port") {
parser = new isc::dhcp::Uint32Parser(config_id,
context->getUint32Storage());
isc::dhcp::ParserPtr parser;
if ((config_id.compare("port") == 0) ||
(config_id.compare("dns_server_timeout") == 0)) {
parser.reset(new isc::dhcp::Uint32Parser(config_id,
context->getUint32Storage()));
} else if ((config_id.compare("ip_address") == 0) ||
(config_id.compare("ncr_protocol") == 0) ||
(config_id.compare("ncr_format") == 0)) {
parser.reset(new isc::dhcp::StringParser(config_id,
context->getStringStorage()));
} else if (config_id == "forward_ddns") {
parser = new DdnsDomainListMgrParser("forward_mgr",
context->getForwardMgr(),
context->getKeys());
parser.reset(new DdnsDomainListMgrParser("forward_mgr",
context->getForwardMgr(),
context->getKeys()));
} else if (config_id == "reverse_ddns") {
parser = new DdnsDomainListMgrParser("reverse_mgr",
context->getReverseMgr(),
context->getKeys());
parser.reset(new DdnsDomainListMgrParser("reverse_mgr",
context->getReverseMgr(),
context->getKeys()));
} else if (config_id == "tsig_keys") {
parser = new TSIGKeyInfoListParser("tsig_key_list", context->getKeys());
parser.reset(new TSIGKeyInfoListParser("tsig_key_list",
context->getKeys()));
} else {
isc_throw(NotImplemented,
"parser error: D2CfgMgr parameter not supported: "
<< config_id);
}
return (isc::dhcp::ParserPtr(parser));
return (parser);
}
}; // end of isc::dhcp namespace
......
......@@ -53,6 +53,11 @@ public:
return (DCfgContextBasePtr(new D2CfgContext(*this)));
}
/// @brief Fetches a reference to the D2Params
D2ParamsPtr& getD2Params() {
return (d2_params_);
}
/// @brief Fetches the forward DNS domain list manager.
///
/// @return returns a pointer to the forward manager.
......@@ -82,6 +87,9 @@ private:
/// @brief Private assignment operator to avoid potential for slicing.
D2CfgContext& operator=(const D2CfgContext& rhs);
/// @brief Global level parameter storage
D2ParamsPtr d2_params_;
/// @brief Forward domain list manager.
DdnsDomainListMgrPtr forward_mgr_;
......@@ -226,17 +234,33 @@ public:
/// @throw D2CfgError if not given an IPv6 address.
static std::string reverseV6Address(const isc::asiolink::IOAddress& ioaddr);
/// @brief Convenience method fetches the D2Params from context
/// @return reference to const D2ParamsPtr
const D2ParamsPtr& getD2Params();
protected:
/// @brief Performs the parsing of the given "params" element.
///
/// Iterates over the set of parameters, creating a parser based on the
/// parameter's id and then invoking its build method passing in the
/// parameter's configuration value.
///
/// @param params_config set of scalar configuration elements to parse
virtual void buildParams(isc::data::ConstElementPtr params_config);
/// @brief Given an element_id returns an instance of the appropriate
/// parser.
///
/// It is responsible for top-level or outermost DHCP-DDNS configuration
/// elements (see dhcp-ddns.spec):
/// 1. interface
/// 2. ip_address
/// 3. port
/// 4. forward_ddns
/// 5. reverse_ddns
/// -# ip_address
/// -# port
/// -# dns_server_timeout
/// -# ncr_protocol
/// -# ncr_format
/// -# tsig_keys
/// -# forward_ddns
/// -# reverse_ddns
///
/// @param element_id is the string name of the element as it will appear
/// in the configuration set.
......@@ -245,6 +269,17 @@ protected:
/// @throw throws DCfgMgrBaseError if an error occurs.
virtual isc::dhcp::ParserPtr
createConfigParser(const std::string& element_id);
/// @brief Creates an new, blank D2CfgContext context
///
/// This method is used at the beginning of configuration process to
/// create a fresh, empty copy of a D2CfgContext. This new context will
/// be populated during the configuration process and will replace the
/// existing context provided the configuration process completes without
/// error.
///
/// @return Returns a DCfgContextBasePtr to the new context instance.
virtual DCfgContextBasePtr createNewContext();
};
/// @brief Defines a shared pointer to D2CfgMgr.
......
......@@ -27,6 +27,102 @@
namespace isc {
namespace d2 {
// *********************** D2Params *************************
const char *D2Params::DFT_IP_ADDRESS = "127.0.0.1";
const size_t D2Params::DFT_PORT = 53001;
const size_t D2Params::DFT_DNS_SERVER_TIMEOUT = 100;
const char *D2Params::DFT_NCR_PROTOCOL = "UDP";
const char *D2Params::DFT_NCR_FORMAT = "JSON";
D2Params::D2Params(const isc::asiolink::IOAddress& ip_address,
const size_t port,
const size_t dns_server_timeout,
const dhcp_ddns::NameChangeProtocol& ncr_protocol,
const dhcp_ddns::NameChangeFormat& ncr_format)
: ip_address_(ip_address),
port_(port),
dns_server_timeout_(dns_server_timeout),
ncr_protocol_(ncr_protocol),
ncr_format_(ncr_format) {
validateContents();
}
D2Params::D2Params()
: ip_address_(isc::asiolink::IOAddress(DFT_IP_ADDRESS)),
port_(DFT_PORT),
dns_server_timeout_(DFT_DNS_SERVER_TIMEOUT),
ncr_protocol_(dhcp_ddns::NCR_UDP),
ncr_format_(dhcp_ddns::FMT_JSON) {
validateContents();
}
D2Params::~D2Params(){};
void
D2Params::validateContents() {
if ((ip_address_.toText() == "0.0.0.0") || (ip_address_.toText() == "::")) {
isc_throw(D2CfgError,
"D2Params: IP address cannot be \"" << ip_address_ << "\"");
}
if (port_ == 0) {
isc_throw(D2CfgError, "D2Params: port cannot be 0");
}
if (dns_server_timeout_ < 1) {
isc_throw(D2CfgError,
"D2Params: DNS server timeout must be larger than 0");
}
if (ncr_format_ != dhcp_ddns::FMT_JSON) {
isc_throw(D2CfgError, "D2Params: NCR Format:"
<< dhcp_ddns::ncrFormatToString(ncr_format_)
<< " is not yet supported");
}
if (ncr_protocol_ != dhcp_ddns::NCR_UDP) {
isc_throw(D2CfgError, "D2Params: NCR Protocol:"
<< dhcp_ddns::ncrProtocolToString(ncr_protocol_)
<< " is not yet supported");
}
}
bool
D2Params::operator == (const D2Params& other) const {
return ((ip_address_ == other.ip_address_) &&
(port_ == other.port_) &&
(dns_server_timeout_ == other.dns_server_timeout_) &&
(ncr_protocol_ == other.ncr_protocol_) &&
(ncr_format_ == other.ncr_format_));
}
bool
D2Params::operator != (const D2Params& other) const {
return (!(*this == other));
}
std::string
D2Params::toText() const {
std::ostringstream stream;
stream << ", ip_address: " << ip_address_.toText()
<< ", port: " << port_
<< ", dns_server_timeout_: " << dns_server_timeout_
<< ", ncr_protocol: "
<< dhcp_ddns::ncrProtocolToString(ncr_protocol_)
<< ", ncr_format: " << ncr_format_
<< dhcp_ddns::ncrFormatToString(ncr_format_);
return (stream.str());
}
std::ostream&
operator<<(std::ostream& os, const D2Params& config) {
os << config.toText();
return (os);
}
// *********************** TSIGKeyInfo *************************
TSIGKeyInfo::TSIGKeyInfo(const std::string& name, const std::string& algorithm,
......
......@@ -143,6 +143,125 @@ public:
isc::Exception(file, line, what) { };
};
/// @brief Acts as a storage vault for D2 global scalar parameters
class D2Params {
public:
/// @brief Default configuration constants.
//@{
/// @todo For now these are hard-coded as configuration layer cannot
/// readily provide them (see Trac #3358).
static const char *DFT_IP_ADDRESS;
static const size_t DFT_PORT;
static const size_t DFT_DNS_SERVER_TIMEOUT;
static const char *DFT_NCR_PROTOCOL;
static const char *DFT_NCR_FORMAT;
//@}
/// @brief Constructor
///
/// @param ip_address IP address at which D2 should listen for NCRs
/// @param port port on which D2 should listen NCRs
/// @param dns_server_timeout maximum amount of time in milliseconds to
/// wait for a response to a single DNS update request.
/// @param ncr_protocol socket protocol D2 should use to receive NCRS
/// @param ncr_format packet format of the inbound NCRs
///
/// @throw D2CfgError if:
/// -# ip_address is 0.0.0.0 or ::
/// -# port is 0
/// -# dns_server_timeout is < 1
/// -# ncr_protocol is invalid, currently only NCR_UDP is supported
/// -# ncr_format is invalid, currently only FMT_JSON is supported
D2Params(const isc::asiolink::IOAddress& ip_address,
const size_t port,
const size_t dns_server_timeout,
const dhcp_ddns::NameChangeProtocol& ncr_protocol,
const dhcp_ddns::NameChangeFormat& ncr_format);
/// @brief Default constructor
/// The default constructor creates an instance that has updates disabled.
D2Params();
/// @brief Destructor
virtual ~D2Params();
/// @brief Return the IP address D2 listens on.
const isc::asiolink::IOAddress& getIpAddress() const {
return(ip_address_);
}
/// @brief Return the TCP/UPD port D2 listens on.
size_t getPort() const {
return(port_);
}
/// @brief Return the DNS server timeout value.
size_t getDnsServerTimeout() const {
return(dns_server_timeout_);
}
/// @brief Return the socket protocol in use.
const dhcp_ddns::NameChangeProtocol& getNcrProtocol() const {
return(ncr_protocol_);
}
/// @brief Return the expected format of inbound requests (NCRs).
const dhcp_ddns::NameChangeFormat& getNcrFormat() const {
return(ncr_format_);
}
/// @brief Compares two D2Paramss for equality
bool operator == (const D2Params& other) const;
/// @brief Compares two D2Paramss for inequality
bool operator != (const D2Params& other) const;
/// @brief Generates a string representation of the class contents.
std::string toText() const;
protected:
/// @brief Validates member values.
///
/// Method is used by the constructor to validate member contents.
/// Currently checks:
/// -# ip_address is not 0.0.0.0 or ::
/// -# port is not 0
/// -# dns_server_timeout is 0
/// -# ncr_protocol is UDP
/// -# ncr_format is JSON
///
/// @throw D2CfgError if contents are invalid
virtual void validateContents();
private:
/// @brief IP address D2 listens on.
isc::asiolink::IOAddress ip_address_;
/// @brief IP port D2 listens on.
size_t port_;
/// @brief Timeout for a single DNS packet exchange in milliseconds.
size_t dns_server_timeout_;
/// @brief The socket protocol to use.
/// Currently only UDP is supported.
dhcp_ddns::NameChangeProtocol ncr_protocol_;
/// @brief Format of the inbound requests (NCRs).
/// Currently only JSON format is supported.
dhcp_ddns::NameChangeFormat ncr_format_;
};
/// @brief Dumps the contents of a D2Params as text to an output stream
///
/// @param os output stream to which text should be sent
/// @param config D2Param instnace to dump
std::ostream&
operator<<(std::ostream& os, const D2Params& config);
/// @brief Defines a pointer for D2Params instances.
typedef boost::shared_ptr<D2Params> D2ParamsPtr;
/// @brief Represents a TSIG Key.
///
/// Currently, this is simple storage class containing the basic attributes of
......
// Copyright (C) 2013 Internet Systems Consortium, Inc. ("ISC")
// Copyright (C) 2013-2014 Internet Systems Consortium, Inc. ("ISC")
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
......@@ -207,7 +207,7 @@ D2Process::configure(isc::data::ConstElementPtr config_set) {
if (rcode) {
// Non-zero means we got an invalid configuration, take no further
// action. In integrated mode, this will send a failed response back
// action. In integrated mode, this will send a failed response back
// to BIND10.
reconf_queue_flag_ = false;
return (answer);
......@@ -248,7 +248,7 @@ D2Process::checkQueueStatus() {
queue_mgr_->stopListening();
} catch (const isc::Exception& ex) {
// It is very unlikey that we would experience an error
// here, but theoretically possible.
// here, but theoretically possible.
LOG_ERROR(dctl_logger, DHCP_DDNS_QUEUE_MGR_STOP_ERROR)
.arg(ex.what());
}
......@@ -325,37 +325,42 @@ D2Process::reconfigureQueueMgr() {
queue_mgr_->removeListener();
// Get the configuration parameters that affect Queue Manager.
// @todo Need to add parameters for listener TYPE, FORMAT, address reuse
std::string ip_address;
uint32_t port;
getCfgMgr()->getContext()->getParam("ip_address", ip_address);
const D2ParamsPtr& d2_params = getD2CfgMgr()->getD2Params();
// Warn the user if the server address is not the loopback.
/// @todo Remove this once we provide a secure mechanism.
std::string ip_address = d2_params->getIpAddress().toText();
if (ip_address != "127.0.0.1" && ip_address != "::1") {
LOG_WARN(dctl_logger, DHCP_DDNS_NOT_ON_LOOPBACK).arg(ip_address);
}
getCfgMgr()->getContext()->getParam("port", port);
isc::asiolink::IOAddress addr(ip_address);
// Instantiate the listener.
queue_mgr_->initUDPListener(addr, port, dhcp_ddns::FMT_JSON, true);
if (d2_params->getNcrProtocol() == dhcp_ddns::NCR_UDP) {
queue_mgr_->initUDPListener(d2_params->getIpAddress(),
d2_params->getPort(),
d2_params->getNcrFormat(), true);
} else {
/// @todo Add TCP/IP once it's supported
// We should never get this far but if we do deal with it.
isc_throw(DProcessBaseError, "Unsupported NCR listener protocol:"
<< dhcp_ddns::ncrProtocolToString(d2_params->
getNcrProtocol()));
}
// Now start it. This assumes that starting is a synchronous,
// blocking call that executes quickly. @todo Should that change then
// we will have to expand the state model to accommodate this.
queue_mgr_->startListening();
} catch (const isc::Exception& ex) {
// Queue manager failed to initialize and therefore not listening.
// This is most likely due to an unavailable IP address or port,
// Queue manager failed to initialize and therefore not listening.
// This is most likely due to an unavailable IP address or port,
// which is a configuration issue.
LOG_ERROR(dctl_logger, DHCP_DDNS_QUEUE_MGR_START_ERROR).arg(ex.what());
}
}
isc::data::ConstElementPtr
D2Process::command(const std::string& command,
D2Process::command(const std::string& command,
isc::data::ConstElementPtr args) {
// @todo This is the initial implementation. If and when D2 is extended
// to support its own commands, this implementation must change. Otherwise
......
......@@ -195,10 +195,12 @@ D2UpdateMgr::makeTransaction(dhcp_ddns::NameChangeRequestPtr& next_ncr) {
NameChangeTransactionPtr trans;
if (next_ncr->getChangeType() == dhcp_ddns::CHG_ADD) {
trans.reset(new NameAddTransaction(io_service_, next_ncr,
forward_domain, reverse_domain));
forward_domain, reverse_domain,
cfg_mgr_));
} else {
trans.reset(new NameRemoveTransaction(io_service_, next_ncr,
forward_domain, reverse_domain));
forward_domain, reverse_domain,
cfg_mgr_));
}
// Add the new transaction to the list.
......
......@@ -97,15 +97,28 @@ DCfgContextBase::~DCfgContextBase() {
// *********************** DCfgMgrBase *************************
DCfgMgrBase::DCfgMgrBase(DCfgContextBasePtr context)
: parse_order_(), context_(context) {
if (!context_) {
isc_throw(DCfgMgrBaseError, "DCfgMgrBase ctor: context cannot be NULL");
}
: parse_order_() {
setContext(context);
}
DCfgMgrBase::~DCfgMgrBase() {
}
void
DCfgMgrBase::resetContext() {
DCfgContextBasePtr context = createNewContext();
setContext(context);
}
void
DCfgMgrBase::setContext(DCfgContextBasePtr& context) {
if (!context) {
isc_throw(DCfgMgrBaseError, "DCfgMgrBase: context cannot be NULL");
}
context_ = context;
}
isc::data::ConstElementPtr
DCfgMgrBase::parseConfig(isc::data::ConstElementPtr config_set) {
LOG_DEBUG(dctl_logger, DBGLVL_COMMAND,
......@@ -122,7 +135,8 @@ DCfgMgrBase::parseConfig(isc::data::ConstElementPtr config_set) {
// inconsistency if the parsing operation fails after the context has been
// modified. We need to preserve the original context here
// so as we can rollback changes when an error occurs.
DCfgContextBasePtr original_context = context_->clone();
DCfgContextBasePtr original_context = context_;
resetContext();
// Answer will hold the result returned to the caller.
ConstElementPtr answer;
......@@ -131,15 +145,42 @@ DCfgMgrBase::parseConfig(isc::data::ConstElementPtr config_set) {
std::string element_id;
try {
// Grab a map of element_ids and their data values from the new
// configuration set.
const std::map<std::string, ConstElementPtr>& values_map =
config_set->mapValue();