Browse Source

[5110] Entire D2 configuration is now handled through new parsing scheme

src/bin/d2/d2_cfg_mgr.h
src/bin/d2/d2_cfg_mgr.cc
    "forward-ddns" and "reverse-ddns" are now parsed using SimpleParsers

src/bin/d2/d2_config.h
src/bin/d2/d2_config.cc
    TSIGKeyInfoParser converted to flat style
    DnsServerInfoParser, DnsServerInfoListParser, DdnsDomainParser,
    DdnsDomainListParser, DdnsDomainListMgrParser
    - now all derive from SimpleParser

src/bin/d2/d2_lexer.ll
    Added sub-grammar/contexts for PARSER_TSIG_KEY, PARSER_DDNS_DOMAIN,
    PARSER_DNS_SERVER:

src/bin/d2/d2_parser.yy
    Added "false" tokens for sub-contexts:
        SUB_TSIG_KEY, SUB_TSIG_KEYS, SUB_DDNS_DOMAIN,SUB_DDNS_DOMAINS,
        SUB_DNS_SERVER, SUB_DNS_SERVERS

src/bin/d2/d2_simple_parser.h
src/bin/d2/d2_simple_parser.cc
    Added Defaults:
        TSIG_KEY_DEFAULTS, DDNS_DOMAIN_MGR_DEFAULTS, DDNS_DOMAIN_DEFAULTS,
        DNS_SERVER_DEFAULTS

    D2SimpleParser::setDdnsDomainDefaults()
    D2SimpleParser::setManagerDefaults() - new methods to handle setting
    scalar defaults and defaults of child elements

    D2SimpleParser::setAllDefaults() - now sets defaults for entire D2
    config

parser_context.h
parser_context.cc
    Added parser types:
        PARSER_SUB_DHCPDDNS,
        PARSER_TSIG_KEY,
        PARSER_TSIG_KEYS,
        PARSER_DDNS_DOMAIN,
        PARSER_DDNS_DOMAINS,
        PARSER_DNS_SERVER,
        PARSER_DNS_SERVERS

src/bin/d2/tests/d2_cfg_mgr_unittests.h
src/bin/d2/tests/d2_cfg_mgr_unittests.cc
    Moved all component SimpleParser tests to d2_simple_parser_unittest.cc/h
    Revamped D2CfgMgrTest

src/bin/d2/tests/d2_simple_parser_unittest.h
src/bin/d2/tests/d2_simple_parser_unittest.cc
    Moved component SimpleParser tests here.

src/bin/d2/tests/nc_test_utils.h
src/bin/d2/tests/nc_test_utils.cc
    Moved valid_d2_config global from lib/process/tests to here

src/bin/d2/tests/testdata/d2_cfg_tests.json
    Updated format and error messages

src/lib/process/testutils/d_test_stubs.h
src/lib/process/testutils/d_test_stubs.cc
    Removed valid_d2_config
Thomas Markwalder 8 years ago
parent
commit
7e1ef0b296

+ 15 - 20
src/bin/d2/d2_cfg_mgr.cc

@@ -268,6 +268,16 @@ D2CfgMgr::parseElement(const std::string& element_id,
         } else if (element_id == "tsig-keys") {
             TSIGKeyInfoListParser parser;
             getD2CfgContext()->setKeys(parser.parse(element));
+        } else if (element_id ==  "forward-ddns") {
+            DdnsDomainListMgrParser parser;
+            DdnsDomainListMgrPtr mgr = parser.parse(element, element_id,
+                                                    context->getKeys());
+            context->setForwardMgr(mgr);
+        } else if (element_id ==  "reverse-ddns") {
+            DdnsDomainListMgrParser parser;
+            DdnsDomainListMgrPtr mgr = parser.parse(element, element_id,
+                                                    context->getKeys());
+            context->setReverseMgr(mgr);
         } else {
             // not something we handle here
             return (false);
@@ -357,29 +367,14 @@ D2CfgMgr::buildParams(isc::data::ConstElementPtr params_config) {
     getD2CfgContext()->getD2Params() = params;
 }
 
-isc::dhcp::ParserPtr
+dhcp::ParserPtr
 D2CfgMgr::createConfigParser(const std::string& config_id,
                              const isc::data::Element::Position& pos) {
-    // Get D2 specific context.
-    D2CfgContextPtr context = getD2CfgContext();
-
-    // Create parser instance based on element_id.
-    isc::dhcp::ParserPtr parser;
-    if (config_id ==  "forward-ddns") {
-        parser.reset(new DdnsDomainListMgrParser("forward-ddns",
-                                                 context->getForwardMgr(),
-                                                 context->getKeys()));
-    } else if (config_id ==  "reverse-ddns") {
-        parser.reset(new DdnsDomainListMgrParser("reverse-ddns",
-                                                 context->getReverseMgr(),
-                                                 context->getKeys()));
-    } else {
-        isc_throw(NotImplemented,
-                  "parser error: D2CfgMgr parameter not supported : "
-                  " (" << config_id << pos << ")");
-    }
+    isc_throw(NotImplemented,
+              "parser error: D2CfgMgr parameter not supported : "
+               " (" << config_id << pos << ")");
 
-    return (parser);
+    return (dhcp::ParserPtr());
 }
 
 }; // end of isc::dhcp namespace

+ 14 - 2
src/bin/d2/d2_cfg_mgr.h

@@ -57,6 +57,12 @@ public:
         return (forward_mgr_);
     }
 
+    /// @brief Sets the forward domain list manager
+    /// @param pointer to the new forward manager
+    void setForwardMgr(DdnsDomainListMgrPtr forward_mgr) {
+        forward_mgr_ = forward_mgr;
+    }
+
     /// @brief Fetches the reverse DNS domain list manager.
     ///
     /// @return returns a pointer to the reverse manager.
@@ -64,6 +70,12 @@ public:
         return (reverse_mgr_);
     }
 
+    /// @brief Sets the reverse domain list manager
+    /// @param pointer to the new reverse manager
+    void setReverseMgr(DdnsDomainListMgrPtr reverse_mgr) {
+        reverse_mgr_ = reverse_mgr;
+    }
+
     /// @brief Fetches the map of TSIG keys.
     ///
     /// @return returns a pointer to the key map.
@@ -71,9 +83,9 @@ public:
         return (keys_);
     }
 
-    /// @brief Sets the may of TSIG keys
+    /// @brief Sets the mapy of TSIG keys
     ///
-    /// @param new of TSIG keys
+    /// @param pointer to the new TSIG key map
     void setKeys(const TSIGKeyInfoMapPtr& keys) {
         keys_ = keys;
     }

+ 108 - 410
src/bin/d2/d2_config.cc

@@ -13,7 +13,6 @@
 #include <asiolink/io_error.h>
 
 #include <boost/foreach.hpp>
-#include <boost/lexical_cast.hpp>
 #include <boost/scoped_ptr.hpp>
 #include <boost/algorithm/string/predicate.hpp>
 
@@ -27,11 +26,13 @@ namespace d2 {
 
 // *********************** D2Params  *************************
 
-const char *D2Params::DFT_IP_ADDRESS = "127.0.0.1";
-const char *D2Params::DFT_PORT = "53001";
-const char *D2Params::DFT_DNS_SERVER_TIMEOUT = "100";
-const char *D2Params::DFT_NCR_PROTOCOL = "UDP";
-const char *D2Params::DFT_NCR_FORMAT = "JSON";
+const char*     D2Params::DFT_IP_ADDRESS = "127.0.0.1";
+const uint32_t  D2Params::DFT_PORT = 53001;
+const char*     D2Params::DFT_PORT_STR = "53001";
+const uint32_t  D2Params::DFT_DNS_SERVER_TIMEOUT = 100;
+const char*     D2Params::DFT_DNS_SERVER_TIMEOUT_STR = "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,
@@ -48,8 +49,7 @@ D2Params::D2Params(const isc::asiolink::IOAddress& ip_address,
 
 D2Params::D2Params()
     : ip_address_(isc::asiolink::IOAddress(DFT_IP_ADDRESS)),
-     port_(boost::lexical_cast<size_t>(DFT_PORT)),
-     dns_server_timeout_(boost::lexical_cast<size_t>(DFT_DNS_SERVER_TIMEOUT)),
+     port_(DFT_PORT), dns_server_timeout_(DFT_DNS_SERVER_TIMEOUT),
      ncr_protocol_(dhcp_ddns::NCR_UDP),
      ncr_format_(dhcp_ddns::FMT_JSON) {
     validateContents();
@@ -190,6 +190,7 @@ TSIGKeyInfo::remakeKey() {
 
 // *********************** DnsServerInfo  *************************
 
+const char* DnsServerInfo::STANDARD_DNS_PORT_STR = "53";
 const char* DnsServerInfo::EMPTY_IP_STR = "0.0.0.0";
 
 DnsServerInfo::DnsServerInfo(const std::string& hostname,
@@ -337,105 +338,37 @@ DdnsDomainListMgr::matchDomain(const std::string& fqdn, DdnsDomainPtr& domain) {
 // *********************** TSIGKeyInfoParser  *************************
 
 TSIGKeyInfoPtr
-TSIGKeyInfoParser::parse(isc::data::ConstElementPtr key_config) {
-    std::string name;
-    std::string algorithm;
-    uint32_t digestbits = 0;
-    std::string secret;
-
-    isc::data::ConstElementPtr name_elem;
-    isc::data::ConstElementPtr algo_elem;
-    isc::data::ConstElementPtr bits_elem;
-    isc::data::ConstElementPtr secret_elem;
-
-    BOOST_FOREACH(isc::dhcp::ConfigPair param, key_config->mapValue()) {
-        std::string entry(param.first);
-        isc::data::ConstElementPtr value(param.second);
-        try {
-            if (entry == "name") {
-                name = value->stringValue();
-                if (name.empty()) {
-                    isc_throw(D2CfgError, "tsig-key: name cannot be blank"
-                              << " (" << value->getPosition() << ")");
-                }
-                name_elem = value;
-            } else if (entry == "algorithm") {
-                algorithm = value->stringValue();
-                // Algorithm must be valid.
-                try {
-                    TSIGKeyInfo::stringToAlgorithmName(algorithm);
-                } catch (const std::exception& ex) {
-                    isc_throw(D2CfgError, "tsig-key : " << ex.what()
-                        << " (" << value->getPosition() << ")");
-                }
-                algo_elem = value;
-            } else if (entry == "digest-bits") {
-                digestbits = value->intValue();
-                bits_elem = value;
-            } else if (entry == "secret") {
-                secret = value->stringValue();
-                // Secret cannot be blank.
-                // Cryptolink lib doesn't offer any way to validate these.
-                // As long as it isn't blank we'll accept it. If the content
-                // is bad, the call to TSIGKeyInfo::remakeKey() made in
-                // the TSIGKeyInfo ctor below will throw.
-                if (secret.empty()) {
-                    isc_throw(D2CfgError, "tsig-key: secret cannot be blank ("
-                              << value->getPosition() << ")");
-                }
-                secret_elem = value;
-            } else {
-                isc_throw(D2CfgError, "tsig-key: unsupported parameter '"
-                          << entry << " (" << value->getPosition() << ")");
-            }
-        } catch (const isc::data::TypeError&) {
-            isc_throw(D2CfgError,
-                      "tsig-key: invalid value type specified for parameter '"
-                      << entry << " (" << value->getPosition() << ")");
-        }
-    }
+TSIGKeyInfoParser::parse(data::ConstElementPtr key_config) {
+    std::string name = getString(key_config, "name");
+    std::string algorithm = getString(key_config, "algorithm");
+    uint32_t digestbits = getInteger(key_config, "digest-bits");
+    std::string secret = getString(key_config, "secret");
 
-    if (!name_elem) {
-        isc_throw(D2CfgError, "tsig-key: must specify name"
-                  << " (" << key_config->getPosition() << ")");
-    }
-
-    if (!algo_elem) {
-        isc_throw(D2CfgError,
-                  "tsig-key: must specify algorithm"
-                  << " (" << key_config->getPosition() << ")");
-    }
-
-    if (!secret_elem) {
-        isc_throw(D2CfgError,
-                  "tsig-key: must specify secret"
-                  << " (" << key_config->getPosition() << ")");
+    // Algorithm must be valid.
+    try {
+        TSIGKeyInfo::stringToAlgorithmName(algorithm);
+    } catch (const std::exception& ex) {
+        isc_throw(D2CfgError, "tsig-key : " << ex.what()
+                  << " (" << getPosition("algorithm", key_config) << ")");
     }
 
     // Non-zero digest-bits must be an integral number of octets, greater
-    // than 80 and at least half of the algorithm key length.
-    if (digestbits > 0) {
-        if ((digestbits % 8) != 0) {
-            isc_throw(D2CfgError,
-                      "tsig-key: digest bits must be a multiple of 8"
-                       << " (" << bits_elem->getPosition() << ")");
+    // than 80 and at least half of the algorithm key length. It defaults
+    // to zero and JSON parsing ensures it's a multiple of 8.
+    if ((digestbits > 0) &&
+        ((digestbits < 80) ||
+         (boost::iequals(algorithm, TSIGKeyInfo::HMAC_SHA224_STR)
+          && (digestbits < 112)) ||
+         (boost::iequals(algorithm, TSIGKeyInfo::HMAC_SHA256_STR)
+          && (digestbits < 128)) ||
+         (boost::iequals(algorithm, TSIGKeyInfo::HMAC_SHA384_STR)
+          && (digestbits < 192)) ||
+         (boost::iequals(algorithm, TSIGKeyInfo::HMAC_SHA512_STR)
+          && (digestbits < 256)))) {
+        isc_throw(D2CfgError, "tsig-key: digest-bits too small : "
+                  << " (" << getPosition("digest-bits", key_config) << ")");
         }
 
-        if ((digestbits < 80) ||
-            (boost::iequals(algorithm, TSIGKeyInfo::HMAC_SHA224_STR)
-             && (digestbits < 112)) ||
-            (boost::iequals(algorithm, TSIGKeyInfo::HMAC_SHA256_STR)
-             && (digestbits < 128)) ||
-            (boost::iequals(algorithm, TSIGKeyInfo::HMAC_SHA384_STR)
-             && (digestbits < 192)) ||
-            (boost::iequals(algorithm, TSIGKeyInfo::HMAC_SHA512_STR)
-                   && (digestbits < 256))) {
-                isc_throw(D2CfgError, "tsig-key: digest-bits too small : "
-                          << " (" << bits_elem->getPosition() << ")");
-        }
-    }
-
-
     // Everything should be valid, so create the key instance.
     // It is possible for the asiodns::dns::TSIGKey create to fail such as
     // with an invalid secret content.
@@ -453,9 +386,9 @@ TSIGKeyInfoParser::parse(isc::data::ConstElementPtr key_config) {
 // *********************** TSIGKeyInfoListParser  *************************
 
 TSIGKeyInfoMapPtr
-TSIGKeyInfoListParser::parse(isc::data::ConstElementPtr key_list) {
+TSIGKeyInfoListParser::parse(data::ConstElementPtr key_list) {
     TSIGKeyInfoMapPtr keys(new TSIGKeyInfoMap());
-    isc::data::ConstElementPtr key_config;
+    data::ConstElementPtr key_config;
     BOOST_FOREACH(key_config, key_list->listValue()) {
         TSIGKeyInfoParser key_parser;
         TSIGKeyInfoPtr key = key_parser.parse(key_config);
@@ -475,48 +408,11 @@ TSIGKeyInfoListParser::parse(isc::data::ConstElementPtr key_list) {
 
 // *********************** DnsServerInfoParser  *************************
 
-DnsServerInfoParser::DnsServerInfoParser(const std::string& entry_name,
-    DnsServerInfoStoragePtr servers)
-    : entry_name_(entry_name), servers_(servers), local_scalars_() {
-    if (!servers_) {
-        isc_throw(D2CfgError, "DnsServerInfoParser ctor:"
-                  " server storage cannot be null");
-    }
-}
-
-DnsServerInfoParser::~DnsServerInfoParser() {
-}
-
-void
-DnsServerInfoParser::build(isc::data::ConstElementPtr server_config) {
-    isc::dhcp::ConfigPair config_pair;
-    // For each element in the server configuration:
-    // 1. Create a parser for the element.
-    // 2. Invoke the parser's build method passing in the element's
-    // configuration.
-    // 3. Invoke the parser's commit method to store the element's parsed
-    // data to the parser's local storage.
-    BOOST_FOREACH (config_pair, server_config->mapValue()) {
-        isc::dhcp::ParserPtr parser(createConfigParser(config_pair.first,
-                                                       config_pair.second->
-                                                       getPosition()));
-        parser->build(config_pair.second);
-        parser->commit();
-    }
-
-    std::string hostname;
-    std::string ip_address;
-    uint32_t port = DnsServerInfo::STANDARD_DNS_PORT;
-    std::map<std::string, isc::data::Element::Position> pos;
-
-    // Fetch the server configuration's parsed scalar values from parser's
-    // local storage.  They're all optional, so no try-catch here.
-    pos["hostname"] = local_scalars_.getParam("hostname", hostname,
-                                              DCfgContextBase::OPTIONAL);
-    pos["ip-address"] = local_scalars_.getParam("ip-address", ip_address,
-                                                DCfgContextBase::OPTIONAL);
-    pos["port"] =  local_scalars_.getParam("port", port,
-                                           DCfgContextBase::OPTIONAL);
+DnsServerInfoPtr
+DnsServerInfoParser::parse(data::ConstElementPtr server_config) {
+    std::string hostname = getString(server_config, "hostname");
+    std::string ip_address = getString(server_config, "ip-address");
+    uint32_t port = getInteger(server_config, "port");
 
     // The configuration must specify one or the other.
     if (hostname.empty() == ip_address.empty()) {
@@ -525,13 +421,7 @@ DnsServerInfoParser::build(isc::data::ConstElementPtr server_config) {
                   << " (" << server_config->getPosition() << ")");
     }
 
-    // Port cannot be zero.
-    if (port == 0) {
-        isc_throw(D2CfgError, "Dns Server : port cannot be 0"
-                  << " (" << pos["port"] << ")");
-    }
-
-    DnsServerInfoPtr serverInfo;
+    DnsServerInfoPtr server_info;
     if (!hostname.empty()) {
         /// @todo when resolvable hostname is supported we create the entry
         /// as follows:
@@ -548,172 +438,52 @@ DnsServerInfoParser::build(isc::data::ConstElementPtr server_config) {
         /// processing.
         /// Until then we'll throw unsupported.
         isc_throw(D2CfgError, "Dns Server : hostname is not yet supported"
-                  << " (" << pos["hostname"] << ")");
+                  << " (" << getPosition("hostname", server_config) << ")");
     } else {
         try {
             // Create an IOAddress from the IP address string given and then
             // create the DnsServerInfo.
             isc::asiolink::IOAddress io_addr(ip_address);
-            serverInfo.reset(new DnsServerInfo(hostname, io_addr, port));
+            server_info.reset(new DnsServerInfo(hostname, io_addr, port));
         } catch (const isc::asiolink::IOError& ex) {
             isc_throw(D2CfgError, "Dns Server : invalid IP address : "
-                      << ip_address << " (" << pos["ip-address"] << ")");
+                      << ip_address
+                      << " (" << getPosition("ip-address", server_config) << ")");
         }
     }
 
-    // Add the new DnsServerInfo to the server storage.
-    servers_->push_back(serverInfo);
-}
-
-isc::dhcp::ParserPtr
-DnsServerInfoParser::createConfigParser(const std::string& config_id,
-                                        const isc::data::Element::
-                                        Position& pos) {
-    DhcpConfigParser* parser = NULL;
-    // Based on the configuration id of the element, create the appropriate
-    // parser. Scalars are set to use the parser's local scalar storage.
-    if ((config_id == "hostname")  ||
-        (config_id == "ip-address")) {
-        parser = new isc::dhcp::StringParser(config_id,
-                                             local_scalars_.getStringStorage());
-    } else if (config_id == "port") {
-        parser = new isc::dhcp::Uint32Parser(config_id,
-                                             local_scalars_.getUint32Storage());
-    } else {
-        isc_throw(NotImplemented,
-                  "parser error: DnsServerInfo parameter not supported: "
-                  << config_id << " (" << pos << ")");
-    }
-
-    // Return the new parser instance.
-    return (isc::dhcp::ParserPtr(parser));
-}
-
-void
-DnsServerInfoParser::commit() {
+    return(server_info);
 }
 
 // *********************** DnsServerInfoListParser  *************************
 
-DnsServerInfoListParser::DnsServerInfoListParser(const std::string& list_name,
-                                       DnsServerInfoStoragePtr servers)
-    :list_name_(list_name), servers_(servers), parsers_() {
-    if (!servers_) {
-        isc_throw(D2CfgError, "DdnsServerInfoListParser ctor:"
-                  " server storage cannot be null");
-    }
-}
-
-DnsServerInfoListParser::~DnsServerInfoListParser(){
-}
-
-void
-DnsServerInfoListParser::
-build(isc::data::ConstElementPtr server_list){
-    int i = 0;
-    isc::data::ConstElementPtr server_config;
-    // For each server element in the server list:
-    // 1. Create a parser for the server element.
-    // 2. Invoke the parser's build method passing in the server's
-    // configuration.
-    // 3. Add the parser to a local collection of parsers.
+DnsServerInfoStoragePtr
+DnsServerInfoListParser::parse(data::ConstElementPtr server_list) {
+    DnsServerInfoStoragePtr servers(new DnsServerInfoStorage());
+    data::ConstElementPtr server_config;
+    DnsServerInfoParser parser;
     BOOST_FOREACH(server_config, server_list->listValue()) {
-        // Create a name for the parser based on its position in the list.
-        std::string entry_name = boost::lexical_cast<std::string>(i++);
-        isc::dhcp::ParserPtr parser(new DnsServerInfoParser(entry_name,
-                                                            servers_));
-        parser->build(server_config);
-        parsers_.push_back(parser);
-    }
-
-    // Domains must have at least one server.
-    if (parsers_.size() == 0) {
-        isc_throw (D2CfgError, "Server List must contain at least one server"
-                   << " (" << server_list->getPosition() << ")");
+        DnsServerInfoPtr server = parser.parse(server_config);
+        servers->push_back(server);
     }
-}
 
-void
-DnsServerInfoListParser::commit() {
-    // Invoke commit on each server parser.
-    BOOST_FOREACH(isc::dhcp::ParserPtr parser, parsers_) {
-        parser->commit();
-    }
+    return (servers);
 }
 
 // *********************** DdnsDomainParser  *************************
 
-DdnsDomainParser::DdnsDomainParser(const std::string& entry_name,
-                                   DdnsDomainMapPtr domains,
-                                   TSIGKeyInfoMapPtr keys)
-    : entry_name_(entry_name), domains_(domains), keys_(keys),
-    local_servers_(new DnsServerInfoStorage()), local_scalars_() {
-    if (!domains_) {
-        isc_throw(D2CfgError,
-                  "DdnsDomainParser ctor, domain storage cannot be null");
-    }
-}
-
-
-DdnsDomainParser::~DdnsDomainParser() {
-}
-
-void
-DdnsDomainParser::build(isc::data::ConstElementPtr domain_config) {
-    // For each element in the domain configuration:
-    // 1. Create a parser for the element.
-    // 2. Invoke the parser's build method passing in the element's
-    // configuration.
-    // 3. Invoke the parser's commit method to store the element's parsed
-    // data to the parser's local storage.
-    isc::dhcp::ConfigPair config_pair;
-    BOOST_FOREACH(config_pair, domain_config->mapValue()) {
-        isc::dhcp::ParserPtr parser(createConfigParser(config_pair.first,
-                                                       config_pair.second->
-                                                       getPosition()));
-        parser->build(config_pair.second);
-        parser->commit();
-    }
-
-    // Now construct the domain.
-    std::string name;
-    std::string key_name;
-    std::map<std::string, isc::data::Element::Position> pos;
-
-
-    // Fetch the parsed scalar values from parser's local storage.
-    // Any required that are missing will throw.
-    try {
-        pos["name"] = local_scalars_.getParam("name", name);
-        pos["key-name"] = local_scalars_.getParam("key-name", key_name,
-                                                  DCfgContextBase::OPTIONAL);
-    } catch (const std::exception& ex) {
-        isc_throw(D2CfgError, "DdnsDomain incomplete : " << ex.what()
-                  << " (" << domain_config->getPosition() << ")");
-    }
-
-    // Blank domain names are not allowed.
-    if (name.empty()) {
-        isc_throw(D2CfgError, "DndsDomain : name cannot be blank ("
-                   << pos["name"] << ")");
-    }
-
-    // Currently, the premise is that domain storage is always empty
-    // prior to parsing so always adding domains never replacing them.
-    // Duplicates are not allowed and should be flagged as a configuration
-    // error.
-    if (domains_->find(name) != domains_->end()) {
-        isc_throw(D2CfgError, "Duplicate domain specified:" << name
-                  << " (" << pos["name"] << ")");
-    }
+DdnsDomainPtr DdnsDomainParser::parse(data::ConstElementPtr domain_config,
+                                      const TSIGKeyInfoMapPtr keys) {
+    std::string name = getString(domain_config, "name");
+    std::string key_name = getString(domain_config, "key-name");
 
     // Key name is optional. If it is not blank, then find the key in the
-    /// list of defined keys.
+    // list of defined keys.
     TSIGKeyInfoPtr tsig_key_info;
     if (!key_name.empty()) {
-        if (keys_) {
-            TSIGKeyInfoMap::iterator kit = keys_->find(key_name);
-            if (kit != keys_->end()) {
+        if (keys) {
+            TSIGKeyInfoMap::iterator kit = keys->find(key_name);
+            if (kit != keys->end()) {
                 tsig_key_info = kit->second;
             }
         }
@@ -721,147 +491,75 @@ DdnsDomainParser::build(isc::data::ConstElementPtr domain_config) {
         if (!tsig_key_info) {
             isc_throw(D2CfgError, "DdnsDomain : " << name
                       << " specifies an undefined key: " << key_name
-                      << " (" << pos["key-name"] << ")");
+                      << " (" << getPosition("key-name", domain_config) << ")");
         }
     }
 
-    // Instantiate the new domain and add it to domain storage.
-    DdnsDomainPtr domain(new DdnsDomain(name, local_servers_, tsig_key_info));
-
-    // Add the new domain to the domain storage.
-    (*domains_)[name] = domain;
-}
+    // Parse the list of DNS servers
+    data::ConstElementPtr servers_config;
+    try {
+        servers_config = domain_config->get("dns-servers");
+    } catch (const std::exception& ex) {
+        isc_throw(D2CfgError, "DdnsDomain : missing dns-server list"
+                      << " (" << servers_config->getPosition() << ")");
+    }
 
-isc::dhcp::ParserPtr
-DdnsDomainParser::createConfigParser(const std::string& config_id,
-                                     const isc::data::Element::Position& pos) {
-    DhcpConfigParser* parser = NULL;
-    // Based on the configuration id of the element, create the appropriate
-    // parser. Scalars are set to use the parser's local scalar storage.
-    if ((config_id == "name")  ||
-        (config_id == "key-name")) {
-        parser = new isc::dhcp::StringParser(config_id,
-                                             local_scalars_.getStringStorage());
-    } else if (config_id == "dns-servers") {
-       // Server list parser is given in our local server storage. It will pass
-       // this down to its server parsers and is where they will write their
-       // server instances upon commit.
-       parser = new DnsServerInfoListParser(config_id, local_servers_);
-    } else {
-       isc_throw(NotImplemented,
-                "parser error: DdnsDomain parameter not supported: "
-                << config_id << " (" << pos << ")");
+    DnsServerInfoListParser server_parser;
+    DnsServerInfoStoragePtr servers =  server_parser.parse(servers_config);
+    if (servers->size() == 0) {
+        isc_throw(D2CfgError, "DNS server list cannot be empty"
+                    << servers_config->getPosition());
     }
 
-    // Return the new domain parser instance.
-    return (isc::dhcp::ParserPtr(parser));
-}
+    // Instantiate the new domain and add it to domain storage.
+    DdnsDomainPtr domain(new DdnsDomain(name, servers, tsig_key_info));
 
-void
-DdnsDomainParser::commit() {
+    return(domain);
 }
 
 // *********************** DdnsDomainListParser  *************************
 
-DdnsDomainListParser::DdnsDomainListParser(const std::string& list_name,
-                                           DdnsDomainMapPtr domains,
-                                           TSIGKeyInfoMapPtr keys)
-    :list_name_(list_name), domains_(domains), keys_(keys), parsers_() {
-    if (!domains_) {
-        isc_throw(D2CfgError, "DdnsDomainListParser ctor:"
-                  " domain storage cannot be null");
-    }
-}
+DdnsDomainMapPtr DdnsDomainListParser::parse(data::ConstElementPtr domain_list,
+                                             const TSIGKeyInfoMapPtr keys) {
+    DdnsDomainMapPtr domains(new DdnsDomainMap());
+    DdnsDomainParser parser;
+    data::ConstElementPtr domain_config;
+    BOOST_FOREACH(domain_config, domain_list->listValue()) {
+        DdnsDomainPtr domain = parser.parse(domain_config, keys);
 
-DdnsDomainListParser::~DdnsDomainListParser(){
-}
+        // Duplicates are not allowed
+        if (domains->find(domain->getName()) != domains->end()) {
+            isc_throw(D2CfgError, "Duplicate domain specified:"
+                      << domain->getName()
+                      << " (" << getPosition("name", domain_config) << ")");
+        }
 
-void
-DdnsDomainListParser::
-build(isc::data::ConstElementPtr domain_list){
-    // For each domain element in the domain list:
-    // 1. Create a parser for the domain element.
-    // 2. Invoke the parser's build method passing in the domain's
-    // configuration.
-    // 3. Add the parser to the local collection of parsers.
-    int i = 0;
-    isc::data::ConstElementPtr domain_config;
-    BOOST_FOREACH(domain_config, domain_list->listValue()) {
-        std::string entry_name = boost::lexical_cast<std::string>(i++);
-        isc::dhcp::ParserPtr parser(new DdnsDomainParser(entry_name,
-                                                         domains_, keys_));
-        parser->build(domain_config);
-        parsers_.push_back(parser);
+        (*domains)[domain->getName()] = domain;
     }
-}
 
-void
-DdnsDomainListParser::commit() {
-    // Invoke commit on each server parser. This will cause each one to
-    // create it's server instance and commit it to storage.
-    BOOST_FOREACH(isc::dhcp::ParserPtr parser, parsers_) {
-        parser->commit();
-    }
+    return (domains);
 }
 
-
 // *********************** DdnsDomainListMgrParser  *************************
 
-DdnsDomainListMgrParser::DdnsDomainListMgrParser(const std::string& entry_name,
-                              DdnsDomainListMgrPtr mgr, TSIGKeyInfoMapPtr keys)
-    : entry_name_(entry_name), mgr_(mgr), keys_(keys),
-    local_domains_(new DdnsDomainMap()), local_scalars_() {
-}
+DdnsDomainListMgrPtr
+DdnsDomainListMgrParser::parse(data::ConstElementPtr mgr_config,
+                               const std::string& mgr_name,
+                               const TSIGKeyInfoMapPtr keys) {
+    DdnsDomainListMgrPtr mgr(new DdnsDomainListMgr(mgr_name));
 
+    // Parse the list of domains
+    data::ConstElementPtr domains_config = mgr_config->get("ddns-domains");
+    if (domains_config) {
+        DdnsDomainListParser domain_parser;
+        DdnsDomainMapPtr domains =  domain_parser.parse(domains_config, keys);
 
-DdnsDomainListMgrParser::~DdnsDomainListMgrParser() {
-}
-
-void
-DdnsDomainListMgrParser::build(isc::data::ConstElementPtr domain_config) {
-    // For each element in the domain manager configuration:
-    // 1. Create a parser for the element.
-    // 2. Invoke the parser's build method passing in the element's
-    // configuration.
-    // 3. Invoke the parser's commit method to store the element's parsed
-    // data to the parser's local storage.
-    isc::dhcp::ConfigPair config_pair;
-    BOOST_FOREACH(config_pair, domain_config->mapValue()) {
-        isc::dhcp::ParserPtr parser(createConfigParser(config_pair.first,
-                                                       config_pair.second->
-                                                       getPosition()));
-        parser->build(config_pair.second);
-        parser->commit();
-    }
-
-    // Add the new domain to the domain storage.
-    mgr_->setDomains(local_domains_);
-}
-
-isc::dhcp::ParserPtr
-DdnsDomainListMgrParser::createConfigParser(const std::string& config_id,
-                                            const isc::data::Element::
-                                            Position& pos) {
-    DhcpConfigParser* parser = NULL;
-    if (config_id == "ddns-domains") {
-       // Domain list parser is given our local domain storage. It will pass
-       // this down to its domain parsers and is where they will write their
-       // domain instances upon commit.
-       parser = new DdnsDomainListParser(config_id, local_domains_, keys_);
-    } else {
-       isc_throw(NotImplemented, "parser error: "
-                 "DdnsDomainListMgr parameter not supported: " << config_id
-                 << " (" << pos << ")");
+        // Add the new domain to the domain storage.
+        mgr->setDomains(domains);
     }
 
-    // Return the new domain parser instance.
-    return (isc::dhcp::ParserPtr(parser));
-}
-
-void
-DdnsDomainListMgrParser::commit() {
+    return(mgr);
 }
 
-
 }; // end of isc::dhcp namespace
 }; // end of isc namespace

+ 60 - 267
src/bin/d2/d2_config.h

@@ -140,11 +140,13 @@ public:
 
     /// @brief Default configuration constants.
     //@{
-    static const char *DFT_IP_ADDRESS;
-    static const char *DFT_PORT;
-    static const char *DFT_DNS_SERVER_TIMEOUT;
-    static const char *DFT_NCR_PROTOCOL;
-    static const char *DFT_NCR_FORMAT;
+    static const char*      DFT_IP_ADDRESS;
+    static const uint32_t   DFT_PORT;
+    static const char*      DFT_PORT_STR;
+    static const uint32_t   DFT_DNS_SERVER_TIMEOUT;
+    static const char*      DFT_DNS_SERVER_TIMEOUT_STR;
+    static const char*      DFT_NCR_PROTOCOL;
+    static const char*      DFT_NCR_FORMAT;
     //@}
 
     /// @brief Constructor
@@ -420,14 +422,13 @@ typedef boost::shared_ptr<TSIGKeyInfoMap> TSIGKeyInfoMapPtr;
 /// updates.
 class DnsServerInfo {
 public:
-
     /// @brief defines DNS standard port value
     static const uint32_t STANDARD_DNS_PORT = 53;
+    static const char* STANDARD_DNS_PORT_STR;
 
     /// @brief defines an "empty" string version of an ip address.
     static const char* EMPTY_IP_STR;
 
-
     /// @brief Constructor
     ///
     /// @param hostname is the resolvable name of the server. If not blank,
@@ -732,7 +733,7 @@ typedef boost::shared_ptr<DScalarContext> DScalarContextPtr;
 ///
 /// This class parses the configuration element "tsig-key" defined in
 /// src/bin/d2/dhcp-ddns.spec and creates an instance of a TSIGKeyInfo.
-class TSIGKeyInfoParser : public  isc::data::SimpleParser { 
+class TSIGKeyInfoParser : public  data::SimpleParser { 
 public:
     /// @brief Constructor
     TSIGKeyInfoParser(){};    
@@ -748,7 +749,7 @@ public:
     /// @param key_config is the "tsig-key" configuration to parse
     ///
     /// @return pointer to the new TSIGKeyInfo instance
-    TSIGKeyInfoPtr parse(isc::data::ConstElementPtr key_config);
+    TSIGKeyInfoPtr parse(data::ConstElementPtr key_config);
 
 private:
 };
@@ -758,7 +759,7 @@ private:
 /// This class parses a list of "tsig-key" configuration elements.
 /// (see src/bin/d2/dhcp-ddns.spec). The TSIGKeyInfo instances are added
 /// to the given storage upon commit.
-class TSIGKeyInfoListParser : public isc::data::SimpleParser {
+class TSIGKeyInfoListParser : public data::SimpleParser {
 public:
     /// @brief Constructor
     TSIGKeyInfoListParser(){};
@@ -778,81 +779,36 @@ public:
     /// @param key_list_config is the list of "tsig_key" elements to parse.
     ///
     /// @return a map containing the TSIGKeyInfo instances 
-    TSIGKeyInfoMapPtr parse(isc::data::ConstElementPtr key_list_config);
+    TSIGKeyInfoMapPtr parse(data::ConstElementPtr key_list_config);
 };
 
 /// @brief Parser for  DnsServerInfo
 ///
 /// This class parses the configuration element "dns-server" defined in
 /// src/bin/d2/dhcp-ddns.spec and creates an instance of a DnsServerInfo.
-class DnsServerInfoParser : public  isc::dhcp::DhcpConfigParser {
+class DnsServerInfoParser : public  data::SimpleParser {
 public:
     /// @brief Constructor
-    ///
-    /// @param entry_name is an arbitrary label assigned to this configuration
-    /// definition. Since servers are specified in a list this value is likely
-    /// be something akin to "server:0", set during parsing.
-    /// @param servers is a pointer to the storage area to which the parser
-    /// should commit the newly created DnsServerInfo instance.
-    DnsServerInfoParser(const std::string& entry_name,
-                        DnsServerInfoStoragePtr servers);
+    DnsServerInfoParser(){};
 
     /// @brief Destructor
-    virtual ~DnsServerInfoParser();
+    virtual ~DnsServerInfoParser(){};
 
     /// @brief Performs the actual parsing of the given  "dns-server" element.
     ///
     /// Parses a configuration for the elements needed to instantiate a
     /// DnsServerInfo, validates those entries, creates a DnsServerInfo instance
-    /// then attempts to add to a list of  servers.
+    /// and returns it.
     ///
     /// @param server_config is the "dns-server" configuration to parse
     ///
+    /// @return a pointer to the newly created server instance
+    ///
     /// @throw D2CfgError if:
     /// -# hostname is not blank, hostname is not yet supported
     /// -# ip_address is invalid
     /// -# port is 0
-    virtual void build(isc::data::ConstElementPtr server_config);
-
-    /// @brief Creates a parser for the given "dns-server" member element id.
-    ///
-    /// The server elements currently supported are(see dhcp-ddns.spec):
-    ///   1. hostname
-    ///   2. ip_address
-    ///   3. port
-    ///
-    /// @param config_id is the "item_name" for a specific member element of
-    /// the "dns-server" specification.
-    /// @param pos position within the configuration text (or file) of element
-    /// to be parsed.  This is passed for error messaging.
-    ///
-    /// @return returns a pointer to newly created parser.
-    ///
-    /// @throw D2CfgError if configuration contains an unknown parameter
-    virtual isc::dhcp::ParserPtr
-    createConfigParser(const std::string& config_id,
-                       const isc::data::Element::Position& =
-                       isc::data::Element::ZERO_POSITION());
-
-    /// @brief Commits the configured DnsServerInfo
-    /// Currently this method is a NOP, as the server instance is created and
-    /// then added to the list of servers in build().
-    virtual void commit();
-
-private:
-    /// @brief Arbitrary label assigned to this parser instance.
-    /// Since servers are specified in a list this value is likely be something
-    /// akin to "server:0", set during parsing.  Primarily here for diagnostics.
-    std::string entry_name_;
-
-    /// @brief Pointer to the storage area to which the parser should commit
-    /// the newly created DnsServerInfo instance. This is given to us as a
-    /// constructor argument by an upper level.
-    DnsServerInfoStoragePtr servers_;
-
-    /// @brief Local storage area for scalar parameter values. Use to hold
-    /// data until time to commit.
-    DScalarContext local_scalars_;
+    DnsServerInfoPtr parse(data::ConstElementPtr server_config);
 };
 
 /// @brief Parser for a list of DnsServerInfos
@@ -860,213 +816,94 @@ private:
 /// This class parses a list of "dns-server" configuration elements.
 /// (see src/bin/d2/dhcp-ddns.spec). The DnsServerInfo instances are added
 /// to the given storage upon commit.
-class DnsServerInfoListParser : public isc::dhcp::DhcpConfigParser {
+class DnsServerInfoListParser : public data::SimpleParser{
 public:
-
     /// @brief Constructor
-    ///
-    /// @param list_name is an arbitrary label assigned to this parser instance.
-    /// @param servers is a pointer to the storage area to which the parser
-    /// should commit the newly created DnsServerInfo instance.
-    DnsServerInfoListParser(const std::string& list_name,
-                            DnsServerInfoStoragePtr servers);
+    DnsServerInfoListParser(){};
 
     /// @brief Destructor
-    virtual ~DnsServerInfoListParser();
+    virtual ~DnsServerInfoListParser(){};
 
     /// @brief Performs the actual parsing of the given list "dns-server"
     /// elements.
-    /// It iterates over each server entry in the list:
-    ///   1. Instantiate a DnsServerInfoParser for the entry
-    ///   2. Pass the element configuration to the parser's build method
-    ///   3. Add the parser instance to local storage
     ///
-    /// The net effect is to parse all of the server entries in the list
-    /// prepping them for commit.
+    /// Creates an empty server list
+    /// It iterates over each server entry in the list:
+    ///   1. Creates a server instance by passing the entry to @c 
+    ///   DnsSeverInfoParser::parse()
+    ///   2. Adds the server to the server list
     ///
     /// @param server_list_config is the list of "dns-server" elements to parse.
-    virtual void build(isc::data::ConstElementPtr server_list_config);
-
-    /// @brief Commits the list of DnsServerInfos
-    ///
-    /// Iterates over the internal list of DdnsServerInfoParsers, invoking
-    /// commit on each one.
-    virtual void commit();
-
-private:
-    /// @brief Arbitrary label assigned to this parser instance.
-    std::string list_name_;
-
-    /// @brief Pointer to the storage area to which the parser should commit
-    /// the list of newly created DnsServerInfo instances. This is given to us
-    /// as a constructor argument by an upper level.
-    DnsServerInfoStoragePtr servers_;
-
-    /// @brief Local storage of DnsServerInfoParser instances
-    isc::dhcp::ParserCollection parsers_;
+    /// @return A pointer to the new, populated server list
+    DnsServerInfoStoragePtr parse(data::ConstElementPtr server_list_config);
 };
 
 /// @brief Parser for  DdnsDomain
 ///
 /// This class parses the configuration element "ddns-domain" defined in
 /// src/bin/d2/dhcp-ddns.spec and creates an instance of a DdnsDomain.
-class DdnsDomainParser : public isc::dhcp::DhcpConfigParser {
+class DdnsDomainParser : public data::SimpleParser {
 public:
     /// @brief Constructor
-    ///
-    /// @param entry_name is an arbitrary label assigned to this configuration
-    /// definition. Since domains are specified in a list this value is likely
-    /// be something akin to "forward-ddns:0", set during parsing.
-    /// @param domains is a pointer to the storage area to which the parser
-    /// @param keys is a pointer to a map of the defined TSIG keys.
-    /// should commit the newly created DdnsDomain instance.
-    DdnsDomainParser(const std::string& entry_name, DdnsDomainMapPtr domains,
-                     TSIGKeyInfoMapPtr keys);
+    DdnsDomainParser(){};
 
     /// @brief Destructor
-    virtual ~DdnsDomainParser();
+    virtual ~DdnsDomainParser(){};
 
     /// @brief Performs the actual parsing of the given  "ddns-domain" element.
     ///
     /// Parses a configuration for the elements needed to instantiate a
-    /// DdnsDomain, validates those entries, creates a DdnsDomain instance
-    /// then attempts to add it to a list of domains.
+    /// DdnsDomain, validates those entries, and creates a DdnsDomain instance.
     ///
     /// @param domain_config is the "ddns-domain" configuration to parse
-    virtual void build(isc::data::ConstElementPtr domain_config);
-
-    /// @brief Creates a parser for the given "ddns-domain" member element id.
-    ///
-    /// The domain elements currently supported are(see dhcp-ddns.spec):
-    ///   1. name
-    ///   2. key_name
-    ///   3. dns_servers
+    /// @param keys map of defined TSIG keys
     ///
-    /// @param config_id is the "item_name" for a specific member element of
-    /// the "ddns-domain" specification.
-    /// @param pos position within the configuration text (or file) of element
-    /// to be parsed.  This is passed for error messaging.
-    ///
-    /// @return returns a pointer to newly created parser.
-    ///
-    /// @throw D2CfgError if configuration contains an unknown parameter
-    virtual isc::dhcp::ParserPtr
-    createConfigParser(const std::string& config_id,
-                       const isc::data::Element::Position& pos =
-                       isc::data::Element::ZERO_POSITION());
-
-    /// @brief Commits the configured DdnsDomain
-    /// Currently this method is a NOP, as the domain instance is created and
-    /// then added to the list of domains in build().
-    virtual void commit();
-
-private:
-
-    /// @brief Arbitrary label assigned to this parser instance.
-    std::string entry_name_;
-
-    /// @brief Pointer to the storage area to which the parser should commit
-    /// the newly created DdnsDomain instance. This is given to us as a
-    /// constructor argument by an upper level.
-    DdnsDomainMapPtr domains_;
-
-    /// @brief Pointer to the map of defined TSIG keys.
-    /// This map is passed into us and contains all of the TSIG keys defined
-    /// for this configuration.  It is used to validate the key name entry of
-    /// DdnsDomains that specify one.
-    TSIGKeyInfoMapPtr keys_;
-
-    /// @brief Local storage for DnsServerInfo instances. This is passed into
-    /// DnsServerInfoListParser(s), which in turn passes it into each
-    /// DnsServerInfoParser.  When the DnsServerInfoParsers "commit" they add
-    /// their server instance to this storage.
-    DnsServerInfoStoragePtr local_servers_;
-
-    /// @brief Local storage area for scalar parameter values. Use to hold
-    /// data until time to commit.
-    DScalarContext local_scalars_;
+    /// @return a pointer to the new domain instance
+    DdnsDomainPtr parse(data::ConstElementPtr domain_config,
+                        const TSIGKeyInfoMapPtr keys);
 };
 
 /// @brief Parser for a list of DdnsDomains
 ///
 /// This class parses a list of "ddns-domain" configuration elements.
-/// (see src/bin/d2/dhcp-ddns.spec). The DdnsDomain instances are added
-/// to the given storage upon commit.
-class DdnsDomainListParser : public isc::dhcp::DhcpConfigParser {
+/// (see src/bin/d2/dhcp-ddns.spec) into a map of DdnsDomains.  
+class DdnsDomainListParser : public data::SimpleParser {
 public:
 
     /// @brief Constructor
-    ///
-    /// @param list_name is an arbitrary label assigned to this parser instance.
-    /// @param domains is a pointer to the storage area to which the parser
-    /// @param keys is a pointer to a map of the defined TSIG keys.
-    /// should commit the newly created DdnsDomain instance.
-    DdnsDomainListParser(const std::string& list_name,
-                         DdnsDomainMapPtr domains, TSIGKeyInfoMapPtr keys);
+    DdnsDomainListParser(){};
 
     /// @brief Destructor
-    virtual ~DdnsDomainListParser();
+    virtual ~DdnsDomainListParser(){};
 
     /// @brief Performs the actual parsing of the given list "ddns-domain"
     /// elements.
+    /// Creates a new DdnsDomain map
     /// It iterates over each domain entry in the list:
-    ///   1. Instantiate a DdnsDomainParser for the entry
-    ///   2. Pass the element configuration to the parser's build method
-    ///   3. Add the parser instance to local storage
-    ///
-    /// The net effect is to parse all of the domain entries in the list
-    /// prepping them for commit.
+    ///   1. Creates a DdnsDomain instance by passing the entry into @c 
+    ///   DdnsDomainParser::parser()
+    ///   2. Adds the DdnsDomain instance to the domain map
     ///
     /// @param domain_list_config is the list of "ddns-domain" elements to
     /// parse.
-    virtual void build(isc::data::ConstElementPtr domain_list_config);
-
-    /// @brief Commits the list of DdnsDomains
-    ///
-    /// Iterates over the internal list of DdnsDomainParsers, invoking
-    /// commit on each one.
-    virtual void commit();
-
-private:
-    /// @brief Arbitrary label assigned to this parser instance.
-    std::string list_name_;
-
-    /// @brief Pointer to the storage area to which the parser should commit
-    /// the list of newly created DdnsDomain instances. This is given to us
-    /// as a constructor argument by an upper level.
-    DdnsDomainMapPtr domains_;
-
-    /// @brief Pointer to the map of defined TSIG keys.
-    /// This map is passed into us and contains all of the TSIG keys defined
-    /// for this configuration.  It is used to validate the key name entry of
-    /// DdnsDomains that specify one.
-    TSIGKeyInfoMapPtr keys_;
-
-    /// @brief Local storage of DdnsDomainParser instances
-    isc::dhcp::ParserCollection parsers_;
+    /// @param keys map of defined TSIG keys
+    /// @return a pointer to the newly populated domain map
+    DdnsDomainMapPtr parse(data::ConstElementPtr domain_list_config,
+                           const TSIGKeyInfoMapPtr keys);
 };
 
 /// @brief Parser for DdnsDomainListMgr
 ///
 /// This class parses the configuration elements "forward-ddns" and
 /// "reverse-ddns" as defined in src/bin/d2/dhcp-ddns.spec.  It populates the
-/// given DdnsDomainListMgr with parsed information upon commit.  Note that
-/// unlike other parsers, this parser does NOT instantiate the final object
-/// during the commit phase, it populates it.  It must pre-exist.
-class DdnsDomainListMgrParser : public isc::dhcp::DhcpConfigParser {
+/// given DdnsDomainListMgr with parsed information.  
+class DdnsDomainListMgrParser : public data::SimpleParser {
 public:
     /// @brief Constructor
-    ///
-    /// @param entry_name is an arbitrary label assigned to this configuration
-    /// definition.
-    /// @param mgr is a pointer to the DdnsDomainListMgr to populate.
-    /// @param keys is a pointer to a map of the defined TSIG keys.
-    /// @throw throws D2CfgError if mgr pointer is empty.
-    DdnsDomainListMgrParser(const std::string& entry_name,
-                     DdnsDomainListMgrPtr mgr, TSIGKeyInfoMapPtr keys);
+    DdnsDomainListMgrParser(){};
 
     /// @brief Destructor
-    virtual ~DdnsDomainListMgrParser();
+    virtual ~DdnsDomainListMgrParser(){};
 
     /// @brief Performs the actual parsing of the given manager element.
     ///
@@ -1074,58 +911,14 @@ public:
     /// DdnsDomainListMgr, validates those entries, then creates a
     /// DdnsDomainListMgr.
     ///
-    /// @param mgr_config is the manager configuration to parse
-    virtual void build(isc::data::ConstElementPtr mgr_config);
-
-    /// @brief Creates a parser for the given manager member element id.
-    ///
-    /// The manager elements currently supported are (see dhcp-ddns.spec):
-    ///     1. ddns_domains
-    ///
-    /// @param config_id is the "item_name" for a specific member element of
-    /// the manager specification.
-    /// @param pos position within the configuration text (or file) of element
-    /// to be parsed.  This is passed for error messaging.
-    ///
-    /// @return returns a pointer to newly created parser.
+    /// @param mgr_config manager configuration to parse
+    /// @param mgr_name convenience label for the manager instance
+    /// @param keys map of defined TSIG keys
     ///
-    /// @throw D2CfgError if configuration contains an unknown parameter
-    virtual isc::dhcp::ParserPtr
-    createConfigParser(const std::string& config_id,
-                       const isc::data::Element::Position& pos =
-                       isc::data::Element::ZERO_POSITION());
-
-    /// @brief Commits the configured DdsnDomainListMgr
-    /// Currently this method is a NOP, as the manager instance is created
-    /// in build().
-    virtual void commit();
-
-private:
-    /// @brief Arbitrary label assigned to this parser instance.
-    std::string entry_name_;
-
-    /// @brief Pointer to manager instance to which the parser should commit
-    /// the parsed data. This is given to us as a constructor argument by an
-    /// upper level.
-    DdnsDomainListMgrPtr mgr_;
-
-    /// @brief Pointer to the map of defined TSIG keys.
-    /// This map is passed into us and contains all of the TSIG keys defined
-    /// for this configuration.  It is used to validate the key name entry of
-    /// DdnsDomains that specify one.
-    TSIGKeyInfoMapPtr keys_;
-
-    /// @brief Local storage for DdnsDomain instances. This is passed into a
-    /// DdnsDomainListParser(s), which in turn passes it into each
-    /// DdnsDomainParser.  When the DdnsDomainParsers "commit" they add their
-    /// domain instance to this storage.
-    DdnsDomainMapPtr local_domains_;
-
-    /// @brief Local storage area for scalar parameter values. Use to hold
-    /// data until time to commit.
-    /// @todo Currently, the manager has no scalars but this is likely to
-    /// change as matching capabilities expand.
-    DScalarContext local_scalars_;
+    /// @return a pointer to the new manager instance
+    DdnsDomainListMgrPtr parse(data::ConstElementPtr mgr_config,
+                               const std::string& mgr_name,
+                               const TSIGKeyInfoMapPtr keys);
 };
 
 

+ 90 - 70
src/bin/d2/d2_lexer.cc

@@ -1229,12 +1229,12 @@ int d2_parser__flex_debug = 1;
 
 static const flex_int16_t yy_rule_linenum[58] =
     {   0,
-      117,  119,  121,  126,  127,  132,  133,  134,  146,  149,
-      154,  160,  169,  179,  189,  198,  207,  216,  226,  236,
-      246,  255,  264,  274,  283,  292,  302,  311,  320,  329,
-      339,  348,  357,  366,  375,  386,  395,  404,  413,  423,
-      521,  526,  531,  536,  537,  538,  539,  540,  541,  543,
-      561,  574,  579,  583,  585,  587,  589
+      127,  129,  131,  136,  137,  142,  143,  144,  156,  159,
+      164,  170,  179,  190,  201,  210,  219,  228,  238,  248,
+      258,  267,  276,  286,  296,  306,  317,  326,  336,  346,
+      357,  366,  375,  384,  393,  406,  415,  424,  433,  443,
+      541,  546,  551,  556,  557,  558,  559,  560,  561,  563,
+      581,  594,  599,  603,  605,  607,  609
     } ;
 
 /* The intent behind this definition is that it'll catch
@@ -1610,11 +1610,21 @@ YY_DECL
             return isc::d2::D2Parser::make_TOPLEVEL_DHCPDDNS(driver.loc_);
         case D2ParserContext::PARSER_SUB_DHCPDDNS:
             return isc::d2::D2Parser::make_SUB_DHCPDDNS(driver.loc_);
+        case D2ParserContext::PARSER_TSIG_KEY:
+            return isc::d2::D2Parser::make_SUB_TSIG_KEY(driver.loc_);
+        case D2ParserContext::PARSER_TSIG_KEYS:
+            return isc::d2::D2Parser::make_SUB_TSIG_KEYS(driver.loc_);
+        case D2ParserContext::PARSER_DDNS_DOMAIN:
+            return isc::d2::D2Parser::make_SUB_DDNS_DOMAIN(driver.loc_);
+        case D2ParserContext::PARSER_DDNS_DOMAINS:
+            return isc::d2::D2Parser::make_SUB_DDNS_DOMAINS(driver.loc_);
+        case D2ParserContext::PARSER_DNS_SERVER:
+            return isc::d2::D2Parser::make_SUB_DNS_SERVER(driver.loc_);
         }
     }
 
 
-#line 1617 "d2_lexer.cc"
+#line 1627 "d2_lexer.cc"
 
 	while ( /*CONSTCOND*/1 )		/* loops until end-of-file is reached */
 		{
@@ -1692,17 +1702,17 @@ do_action:	/* This label is used only to access EOF actions. */
 
 case 1:
 YY_RULE_SETUP
-#line 117 "d2_lexer.ll"
+#line 127 "d2_lexer.ll"
 ;
 	YY_BREAK
 case 2:
 YY_RULE_SETUP
-#line 119 "d2_lexer.ll"
+#line 129 "d2_lexer.ll"
 ;
 	YY_BREAK
 case 3:
 YY_RULE_SETUP
-#line 121 "d2_lexer.ll"
+#line 131 "d2_lexer.ll"
 {
   BEGIN(COMMENT);
   comment_start_line = driver.loc_.end.line;;
@@ -1710,33 +1720,33 @@ YY_RULE_SETUP
 	YY_BREAK
 case 4:
 YY_RULE_SETUP
-#line 126 "d2_lexer.ll"
+#line 136 "d2_lexer.ll"
 BEGIN(INITIAL);
 	YY_BREAK
 case 5:
 YY_RULE_SETUP
-#line 127 "d2_lexer.ll"
+#line 137 "d2_lexer.ll"
 ;
 	YY_BREAK
 case YY_STATE_EOF(COMMENT):
-#line 128 "d2_lexer.ll"
+#line 138 "d2_lexer.ll"
 {
     isc_throw(D2ParseError, "Comment not closed. (/* in line " << comment_start_line);
 }
 	YY_BREAK
 case 6:
 YY_RULE_SETUP
-#line 132 "d2_lexer.ll"
+#line 142 "d2_lexer.ll"
 BEGIN(DIR_ENTER);
 	YY_BREAK
 case 7:
 YY_RULE_SETUP
-#line 133 "d2_lexer.ll"
+#line 143 "d2_lexer.ll"
 BEGIN(DIR_INCLUDE);
 	YY_BREAK
 case 8:
 YY_RULE_SETUP
-#line 134 "d2_lexer.ll"
+#line 144 "d2_lexer.ll"
 {
     // Include directive.
 
@@ -1750,19 +1760,19 @@ YY_RULE_SETUP
 case YY_STATE_EOF(DIR_ENTER):
 case YY_STATE_EOF(DIR_INCLUDE):
 case YY_STATE_EOF(DIR_EXIT):
-#line 143 "d2_lexer.ll"
+#line 153 "d2_lexer.ll"
 {
     isc_throw(D2ParseError, "Directive not closed.");
 }
 	YY_BREAK
 case 9:
 YY_RULE_SETUP
-#line 146 "d2_lexer.ll"
+#line 156 "d2_lexer.ll"
 BEGIN(INITIAL);
 	YY_BREAK
 case 10:
 YY_RULE_SETUP
-#line 149 "d2_lexer.ll"
+#line 159 "d2_lexer.ll"
 {
     // Ok, we found a with space. Let's ignore it and update loc variable.
     driver.loc_.step();
@@ -1771,7 +1781,7 @@ YY_RULE_SETUP
 case 11:
 /* rule 11 can match eol */
 YY_RULE_SETUP
-#line 154 "d2_lexer.ll"
+#line 164 "d2_lexer.ll"
 {
     // Newline found. Let's update the location and continue.
     driver.loc_.lines(yyleng);
@@ -1780,7 +1790,7 @@ YY_RULE_SETUP
 	YY_BREAK
 case 12:
 YY_RULE_SETUP
-#line 160 "d2_lexer.ll"
+#line 170 "d2_lexer.ll"
 {
     switch(driver.ctx_) {
     case isc::d2::D2ParserContext::CONFIG:
@@ -1792,10 +1802,11 @@ YY_RULE_SETUP
 	YY_BREAK
 case 13:
 YY_RULE_SETUP
-#line 169 "d2_lexer.ll"
+#line 179 "d2_lexer.ll"
 {
     switch(driver.ctx_) {
     case isc::d2::D2ParserContext::DHCPDDNS:
+    case isc::d2::D2ParserContext::DNS_SERVER:
     case isc::d2::D2ParserContext::DNS_SERVERS:
         return isc::d2::D2Parser::make_IP_ADDRESS(driver.loc_);
     default:
@@ -1805,10 +1816,11 @@ YY_RULE_SETUP
 	YY_BREAK
 case 14:
 YY_RULE_SETUP
-#line 179 "d2_lexer.ll"
+#line 190 "d2_lexer.ll"
 {
     switch(driver.ctx_) {
     case isc::d2::D2ParserContext::DHCPDDNS:
+    case isc::d2::D2ParserContext::DNS_SERVER:
     case isc::d2::D2ParserContext::DNS_SERVERS:
         return isc::d2::D2Parser::make_PORT(driver.loc_);
     default:
@@ -1818,7 +1830,7 @@ YY_RULE_SETUP
 	YY_BREAK
 case 15:
 YY_RULE_SETUP
-#line 189 "d2_lexer.ll"
+#line 201 "d2_lexer.ll"
 {
     switch(driver.ctx_) {
     case isc::d2::D2ParserContext::DHCPDDNS:
@@ -1830,7 +1842,7 @@ YY_RULE_SETUP
 	YY_BREAK
 case 16:
 YY_RULE_SETUP
-#line 198 "d2_lexer.ll"
+#line 210 "d2_lexer.ll"
 {
     switch(driver.ctx_) {
     case isc::d2::D2ParserContext::DHCPDDNS:
@@ -1842,7 +1854,7 @@ YY_RULE_SETUP
 	YY_BREAK
 case 17:
 YY_RULE_SETUP
-#line 207 "d2_lexer.ll"
+#line 219 "d2_lexer.ll"
 {
     switch(driver.ctx_) {
     case isc::d2::D2ParserContext::DHCPDDNS:
@@ -1854,7 +1866,7 @@ YY_RULE_SETUP
 	YY_BREAK
 case 18:
 YY_RULE_SETUP
-#line 216 "d2_lexer.ll"
+#line 228 "d2_lexer.ll"
 {
     /* dhcp-ddns value keywords are case insensitive */
     if (driver.ctx_ == isc::d2::D2ParserContext::NCR_PROTOCOL) {
@@ -1867,7 +1879,7 @@ YY_RULE_SETUP
 	YY_BREAK
 case 19:
 YY_RULE_SETUP
-#line 226 "d2_lexer.ll"
+#line 238 "d2_lexer.ll"
 {
     /* dhcp-ddns value keywords are case insensitive */
     if (driver.ctx_ == isc::d2::D2ParserContext::NCR_PROTOCOL) {
@@ -1880,7 +1892,7 @@ YY_RULE_SETUP
 	YY_BREAK
 case 20:
 YY_RULE_SETUP
-#line 236 "d2_lexer.ll"
+#line 248 "d2_lexer.ll"
 {
     /* dhcp-ddns value keywords are case insensitive */
     if (driver.ctx_ == isc::d2::D2ParserContext::NCR_FORMAT) {
@@ -1893,7 +1905,7 @@ YY_RULE_SETUP
 	YY_BREAK
 case 21:
 YY_RULE_SETUP
-#line 246 "d2_lexer.ll"
+#line 258 "d2_lexer.ll"
 {
     switch(driver.ctx_) {
     case isc::d2::D2ParserContext::DHCPDDNS:
@@ -1905,7 +1917,7 @@ YY_RULE_SETUP
 	YY_BREAK
 case 22:
 YY_RULE_SETUP
-#line 255 "d2_lexer.ll"
+#line 267 "d2_lexer.ll"
 {
     switch(driver.ctx_) {
     case isc::d2::D2ParserContext::DHCPDDNS:
@@ -1917,7 +1929,7 @@ YY_RULE_SETUP
 	YY_BREAK
 case 23:
 YY_RULE_SETUP
-#line 264 "d2_lexer.ll"
+#line 276 "d2_lexer.ll"
 {
     switch(driver.ctx_) {
     case isc::d2::D2ParserContext::FORWARD_DDNS:
@@ -1930,9 +1942,10 @@ YY_RULE_SETUP
 	YY_BREAK
 case 24:
 YY_RULE_SETUP
-#line 274 "d2_lexer.ll"
+#line 286 "d2_lexer.ll"
 {
     switch(driver.ctx_) {
+    case isc::d2::D2ParserContext::DDNS_DOMAIN:
     case isc::d2::D2ParserContext::DDNS_DOMAINS:
         return isc::d2::D2Parser::make_KEY_NAME(driver.loc_);
     default:
@@ -1942,9 +1955,10 @@ YY_RULE_SETUP
 	YY_BREAK
 case 25:
 YY_RULE_SETUP
-#line 283 "d2_lexer.ll"
+#line 296 "d2_lexer.ll"
 {
     switch(driver.ctx_) {
+    case isc::d2::D2ParserContext::DDNS_DOMAIN:
     case isc::d2::D2ParserContext::DDNS_DOMAINS:
         return isc::d2::D2Parser::make_DNS_SERVERS(driver.loc_);
     default:
@@ -1954,9 +1968,10 @@ YY_RULE_SETUP
 	YY_BREAK
 case 26:
 YY_RULE_SETUP
-#line 292 "d2_lexer.ll"
+#line 306 "d2_lexer.ll"
 {
     switch(driver.ctx_) {
+    case isc::d2::D2ParserContext::DNS_SERVER:
     case isc::d2::D2ParserContext::DNS_SERVERS:
         return isc::d2::D2Parser::make_HOSTNAME(driver.loc_);
     default:
@@ -1966,7 +1981,7 @@ YY_RULE_SETUP
 	YY_BREAK
 case 27:
 YY_RULE_SETUP
-#line 302 "d2_lexer.ll"
+#line 317 "d2_lexer.ll"
 {
     switch(driver.ctx_) {
     case isc::d2::D2ParserContext::DHCPDDNS:
@@ -1978,9 +1993,10 @@ YY_RULE_SETUP
 	YY_BREAK
 case 28:
 YY_RULE_SETUP
-#line 311 "d2_lexer.ll"
+#line 326 "d2_lexer.ll"
 {
     switch(driver.ctx_) {
+    case isc::d2::D2ParserContext::TSIG_KEY:
     case isc::d2::D2ParserContext::TSIG_KEYS:
         return isc::d2::D2Parser::make_ALGORITHM(driver.loc_);
     default:
@@ -1990,9 +2006,10 @@ YY_RULE_SETUP
 	YY_BREAK
 case 29:
 YY_RULE_SETUP
-#line 320 "d2_lexer.ll"
+#line 336 "d2_lexer.ll"
 {
     switch(driver.ctx_) {
+    case isc::d2::D2ParserContext::TSIG_KEY:
     case isc::d2::D2ParserContext::TSIG_KEYS:
         return isc::d2::D2Parser::make_DIGEST_BITS(driver.loc_);
     default:
@@ -2002,9 +2019,10 @@ YY_RULE_SETUP
 	YY_BREAK
 case 30:
 YY_RULE_SETUP
-#line 329 "d2_lexer.ll"
+#line 346 "d2_lexer.ll"
 {
     switch(driver.ctx_) {
+    case isc::d2::D2ParserContext::TSIG_KEY:
     case isc::d2::D2ParserContext::TSIG_KEYS:
         return isc::d2::D2Parser::make_SECRET(driver.loc_);
     default:
@@ -2014,7 +2032,7 @@ YY_RULE_SETUP
 	YY_BREAK
 case 31:
 YY_RULE_SETUP
-#line 339 "d2_lexer.ll"
+#line 357 "d2_lexer.ll"
 {
     switch(driver.ctx_) {
     case isc::d2::D2ParserContext::CONFIG:
@@ -2026,7 +2044,7 @@ YY_RULE_SETUP
 	YY_BREAK
 case 32:
 YY_RULE_SETUP
-#line 348 "d2_lexer.ll"
+#line 366 "d2_lexer.ll"
 {
     switch(driver.ctx_) {
     case isc::d2::D2ParserContext::LOGGING:
@@ -2038,7 +2056,7 @@ YY_RULE_SETUP
 	YY_BREAK
 case 33:
 YY_RULE_SETUP
-#line 357 "d2_lexer.ll"
+#line 375 "d2_lexer.ll"
 {
     switch(driver.ctx_) {
     case isc::d2::D2ParserContext::LOGGERS:
@@ -2050,7 +2068,7 @@ YY_RULE_SETUP
 	YY_BREAK
 case 34:
 YY_RULE_SETUP
-#line 366 "d2_lexer.ll"
+#line 384 "d2_lexer.ll"
 {
     switch(driver.ctx_) {
     case isc::d2::D2ParserContext::OUTPUT_OPTIONS:
@@ -2062,11 +2080,13 @@ YY_RULE_SETUP
 	YY_BREAK
 case 35:
 YY_RULE_SETUP
-#line 375 "d2_lexer.ll"
+#line 393 "d2_lexer.ll"
 {
     switch(driver.ctx_) {
     case isc::d2::D2ParserContext::LOGGERS:
+    case isc::d2::D2ParserContext::TSIG_KEY:
     case isc::d2::D2ParserContext::TSIG_KEYS:
+    case isc::d2::D2ParserContext::DDNS_DOMAIN:
     case isc::d2::D2ParserContext::DDNS_DOMAINS:
         return isc::d2::D2Parser::make_NAME(driver.loc_);
     default:
@@ -2076,7 +2096,7 @@ YY_RULE_SETUP
 	YY_BREAK
 case 36:
 YY_RULE_SETUP
-#line 386 "d2_lexer.ll"
+#line 406 "d2_lexer.ll"
 {
     switch(driver.ctx_) {
     case isc::d2::D2ParserContext::LOGGERS:
@@ -2088,7 +2108,7 @@ YY_RULE_SETUP
 	YY_BREAK
 case 37:
 YY_RULE_SETUP
-#line 395 "d2_lexer.ll"
+#line 415 "d2_lexer.ll"
 {
     switch(driver.ctx_) {
     case isc::d2::D2ParserContext::LOGGERS:
@@ -2100,7 +2120,7 @@ YY_RULE_SETUP
 	YY_BREAK
 case 38:
 YY_RULE_SETUP
-#line 404 "d2_lexer.ll"
+#line 424 "d2_lexer.ll"
 {
     switch(driver.ctx_) {
     case isc::d2::D2ParserContext::CONFIG:
@@ -2112,7 +2132,7 @@ YY_RULE_SETUP
 	YY_BREAK
 case 39:
 YY_RULE_SETUP
-#line 413 "d2_lexer.ll"
+#line 433 "d2_lexer.ll"
 {
     switch(driver.ctx_) {
     case isc::d2::D2ParserContext::CONFIG:
@@ -2124,7 +2144,7 @@ YY_RULE_SETUP
 	YY_BREAK
 case 40:
 YY_RULE_SETUP
-#line 423 "d2_lexer.ll"
+#line 443 "d2_lexer.ll"
 {
     // A string has been matched. It contains the actual string and single quotes.
     // We need to get those quotes out of the way and just use its content, e.g.
@@ -2226,7 +2246,7 @@ YY_RULE_SETUP
 case 41:
 /* rule 41 can match eol */
 YY_RULE_SETUP
-#line 521 "d2_lexer.ll"
+#line 541 "d2_lexer.ll"
 {
     // Bad string with a forbidden control character inside
     driver.error(driver.loc_, "Invalid control in " + std::string(yytext));
@@ -2235,7 +2255,7 @@ YY_RULE_SETUP
 case 42:
 /* rule 42 can match eol */
 YY_RULE_SETUP
-#line 526 "d2_lexer.ll"
+#line 546 "d2_lexer.ll"
 {
     // Bad string with a bad escape inside
     driver.error(driver.loc_, "Bad escape in " + std::string(yytext));
@@ -2243,7 +2263,7 @@ YY_RULE_SETUP
 	YY_BREAK
 case 43:
 YY_RULE_SETUP
-#line 531 "d2_lexer.ll"
+#line 551 "d2_lexer.ll"
 {
     // Bad string with an open escape at the end
     driver.error(driver.loc_, "Overflow escape in " + std::string(yytext));
@@ -2251,37 +2271,37 @@ YY_RULE_SETUP
 	YY_BREAK
 case 44:
 YY_RULE_SETUP
-#line 536 "d2_lexer.ll"
+#line 556 "d2_lexer.ll"
 { return isc::d2::D2Parser::make_LSQUARE_BRACKET(driver.loc_); }
 	YY_BREAK
 case 45:
 YY_RULE_SETUP
-#line 537 "d2_lexer.ll"
+#line 557 "d2_lexer.ll"
 { return isc::d2::D2Parser::make_RSQUARE_BRACKET(driver.loc_); }
 	YY_BREAK
 case 46:
 YY_RULE_SETUP
-#line 538 "d2_lexer.ll"
+#line 558 "d2_lexer.ll"
 { return isc::d2::D2Parser::make_LCURLY_BRACKET(driver.loc_); }
 	YY_BREAK
 case 47:
 YY_RULE_SETUP
-#line 539 "d2_lexer.ll"
+#line 559 "d2_lexer.ll"
 { return isc::d2::D2Parser::make_RCURLY_BRACKET(driver.loc_); }
 	YY_BREAK
 case 48:
 YY_RULE_SETUP
-#line 540 "d2_lexer.ll"
+#line 560 "d2_lexer.ll"
 { return isc::d2::D2Parser::make_COMMA(driver.loc_); }
 	YY_BREAK
 case 49:
 YY_RULE_SETUP
-#line 541 "d2_lexer.ll"
+#line 561 "d2_lexer.ll"
 { return isc::d2::D2Parser::make_COLON(driver.loc_); }
 	YY_BREAK
 case 50:
 YY_RULE_SETUP
-#line 543 "d2_lexer.ll"
+#line 563 "d2_lexer.ll"
 {
     // An integer was found.
     std::string tmp(yytext);
@@ -2302,7 +2322,7 @@ YY_RULE_SETUP
 	YY_BREAK
 case 51:
 YY_RULE_SETUP
-#line 561 "d2_lexer.ll"
+#line 581 "d2_lexer.ll"
 {
     // A floating point was found.
     std::string tmp(yytext);
@@ -2318,7 +2338,7 @@ YY_RULE_SETUP
 	YY_BREAK
 case 52:
 YY_RULE_SETUP
-#line 574 "d2_lexer.ll"
+#line 594 "d2_lexer.ll"
 {
     string tmp(yytext);
     return isc::d2::D2Parser::make_BOOLEAN(tmp == "true", driver.loc_);
@@ -2326,33 +2346,33 @@ YY_RULE_SETUP
 	YY_BREAK
 case 53:
 YY_RULE_SETUP
-#line 579 "d2_lexer.ll"
+#line 599 "d2_lexer.ll"
 {
    return isc::d2::D2Parser::make_NULL_TYPE(driver.loc_);
 }
 	YY_BREAK
 case 54:
 YY_RULE_SETUP
-#line 583 "d2_lexer.ll"
+#line 603 "d2_lexer.ll"
 driver.error (driver.loc_, "JSON true reserved keyword is lower case only");
 	YY_BREAK
 case 55:
 YY_RULE_SETUP
-#line 585 "d2_lexer.ll"
+#line 605 "d2_lexer.ll"
 driver.error (driver.loc_, "JSON false reserved keyword is lower case only");
 	YY_BREAK
 case 56:
 YY_RULE_SETUP
-#line 587 "d2_lexer.ll"
+#line 607 "d2_lexer.ll"
 driver.error (driver.loc_, "JSON null reserved keyword is lower case only");
 	YY_BREAK
 case 57:
 YY_RULE_SETUP
-#line 589 "d2_lexer.ll"
+#line 609 "d2_lexer.ll"
 driver.error (driver.loc_, "Invalid character: " + std::string(yytext));
 	YY_BREAK
 case YY_STATE_EOF(INITIAL):
-#line 591 "d2_lexer.ll"
+#line 611 "d2_lexer.ll"
 {
     if (driver.states_.empty()) {
         return isc::d2::D2Parser::make_END(driver.loc_);
@@ -2378,10 +2398,10 @@ case YY_STATE_EOF(INITIAL):
 	YY_BREAK
 case 58:
 YY_RULE_SETUP
-#line 614 "d2_lexer.ll"
+#line 634 "d2_lexer.ll"
 ECHO;
 	YY_BREAK
-#line 2384 "d2_lexer.cc"
+#line 2404 "d2_lexer.cc"
 
 	case YY_END_OF_BUFFER:
 		{
@@ -3482,7 +3502,7 @@ void d2_parser_free (void * ptr )
 
 /* %ok-for-header */
 
-#line 614 "d2_lexer.ll"
+#line 634 "d2_lexer.ll"
 
 
 using namespace isc::dhcp;

+ 20 - 0
src/bin/d2/d2_lexer.ll

@@ -109,6 +109,16 @@ ControlCharacterFill            [^"\\]|\\{JSONEscapeSequence}
             return isc::d2::D2Parser::make_TOPLEVEL_DHCPDDNS(driver.loc_);
         case D2ParserContext::PARSER_SUB_DHCPDDNS:
             return isc::d2::D2Parser::make_SUB_DHCPDDNS(driver.loc_);
+        case D2ParserContext::PARSER_TSIG_KEY:
+            return isc::d2::D2Parser::make_SUB_TSIG_KEY(driver.loc_);
+        case D2ParserContext::PARSER_TSIG_KEYS:
+            return isc::d2::D2Parser::make_SUB_TSIG_KEYS(driver.loc_);
+        case D2ParserContext::PARSER_DDNS_DOMAIN:
+            return isc::d2::D2Parser::make_SUB_DDNS_DOMAIN(driver.loc_);
+        case D2ParserContext::PARSER_DDNS_DOMAINS:
+            return isc::d2::D2Parser::make_SUB_DDNS_DOMAINS(driver.loc_);
+        case D2ParserContext::PARSER_DNS_SERVER:
+            return isc::d2::D2Parser::make_SUB_DNS_SERVER(driver.loc_);
         }
     }
 %}
@@ -168,6 +178,7 @@ ControlCharacterFill            [^"\\]|\\{JSONEscapeSequence}
 \"ip-address\" {
     switch(driver.ctx_) {
     case isc::d2::D2ParserContext::DHCPDDNS:
+    case isc::d2::D2ParserContext::DNS_SERVER:
     case isc::d2::D2ParserContext::DNS_SERVERS:
         return isc::d2::D2Parser::make_IP_ADDRESS(driver.loc_);
     default:
@@ -178,6 +189,7 @@ ControlCharacterFill            [^"\\]|\\{JSONEscapeSequence}
 \"port\" {
     switch(driver.ctx_) {
     case isc::d2::D2ParserContext::DHCPDDNS:
+    case isc::d2::D2ParserContext::DNS_SERVER:
     case isc::d2::D2ParserContext::DNS_SERVERS:
         return isc::d2::D2Parser::make_PORT(driver.loc_);
     default:
@@ -272,6 +284,7 @@ ControlCharacterFill            [^"\\]|\\{JSONEscapeSequence}
 
 \"key-name\" {
     switch(driver.ctx_) {
+    case isc::d2::D2ParserContext::DDNS_DOMAIN:
     case isc::d2::D2ParserContext::DDNS_DOMAINS:
         return isc::d2::D2Parser::make_KEY_NAME(driver.loc_);
     default:
@@ -281,6 +294,7 @@ ControlCharacterFill            [^"\\]|\\{JSONEscapeSequence}
 
 \"dns-servers\" {
     switch(driver.ctx_) {
+    case isc::d2::D2ParserContext::DDNS_DOMAIN:
     case isc::d2::D2ParserContext::DDNS_DOMAINS:
         return isc::d2::D2Parser::make_DNS_SERVERS(driver.loc_);
     default:
@@ -290,6 +304,7 @@ ControlCharacterFill            [^"\\]|\\{JSONEscapeSequence}
 
 \"hostname\" {
     switch(driver.ctx_) {
+    case isc::d2::D2ParserContext::DNS_SERVER:
     case isc::d2::D2ParserContext::DNS_SERVERS:
         return isc::d2::D2Parser::make_HOSTNAME(driver.loc_);
     default:
@@ -309,6 +324,7 @@ ControlCharacterFill            [^"\\]|\\{JSONEscapeSequence}
 
 \"algorithm\" {
     switch(driver.ctx_) {
+    case isc::d2::D2ParserContext::TSIG_KEY:
     case isc::d2::D2ParserContext::TSIG_KEYS:
         return isc::d2::D2Parser::make_ALGORITHM(driver.loc_);
     default:
@@ -318,6 +334,7 @@ ControlCharacterFill            [^"\\]|\\{JSONEscapeSequence}
 
 \"digest-bits\" {
     switch(driver.ctx_) {
+    case isc::d2::D2ParserContext::TSIG_KEY:
     case isc::d2::D2ParserContext::TSIG_KEYS:
         return isc::d2::D2Parser::make_DIGEST_BITS(driver.loc_);
     default:
@@ -327,6 +344,7 @@ ControlCharacterFill            [^"\\]|\\{JSONEscapeSequence}
 
 \"secret\" {
     switch(driver.ctx_) {
+    case isc::d2::D2ParserContext::TSIG_KEY:
     case isc::d2::D2ParserContext::TSIG_KEYS:
         return isc::d2::D2Parser::make_SECRET(driver.loc_);
     default:
@@ -374,7 +392,9 @@ ControlCharacterFill            [^"\\]|\\{JSONEscapeSequence}
 \"name\" {
     switch(driver.ctx_) {
     case isc::d2::D2ParserContext::LOGGERS:
+    case isc::d2::D2ParserContext::TSIG_KEY:
     case isc::d2::D2ParserContext::TSIG_KEYS:
+    case isc::d2::D2ParserContext::DDNS_DOMAIN:
     case isc::d2::D2ParserContext::DDNS_DOMAINS:
         return isc::d2::D2Parser::make_NAME(driver.loc_);
     default:

File diff suppressed because it is too large
+ 710 - 544
src/bin/d2/d2_parser.cc


+ 104 - 36
src/bin/d2/d2_parser.h

@@ -380,10 +380,16 @@ namespace isc { namespace d2 {
         TOKEN_TOPLEVEL_JSON = 293,
         TOKEN_TOPLEVEL_DHCPDDNS = 294,
         TOKEN_SUB_DHCPDDNS = 295,
-        TOKEN_STRING = 296,
-        TOKEN_INTEGER = 297,
-        TOKEN_FLOAT = 298,
-        TOKEN_BOOLEAN = 299
+        TOKEN_SUB_TSIG_KEY = 296,
+        TOKEN_SUB_TSIG_KEYS = 297,
+        TOKEN_SUB_DDNS_DOMAIN = 298,
+        TOKEN_SUB_DDNS_DOMAINS = 299,
+        TOKEN_SUB_DNS_SERVER = 300,
+        TOKEN_SUB_DNS_SERVERS = 301,
+        TOKEN_STRING = 302,
+        TOKEN_INTEGER = 303,
+        TOKEN_FLOAT = 304,
+        TOKEN_BOOLEAN = 305
       };
     };
 
@@ -656,6 +662,30 @@ namespace isc { namespace d2 {
 
     static inline
     symbol_type
+    make_SUB_TSIG_KEY (const location_type& l);
+
+    static inline
+    symbol_type
+    make_SUB_TSIG_KEYS (const location_type& l);
+
+    static inline
+    symbol_type
+    make_SUB_DDNS_DOMAIN (const location_type& l);
+
+    static inline
+    symbol_type
+    make_SUB_DDNS_DOMAINS (const location_type& l);
+
+    static inline
+    symbol_type
+    make_SUB_DNS_SERVER (const location_type& l);
+
+    static inline
+    symbol_type
+    make_SUB_DNS_SERVERS (const location_type& l);
+
+    static inline
+    symbol_type
     make_STRING (const std::string& v, const location_type& l);
 
     static inline
@@ -875,12 +905,12 @@ namespace isc { namespace d2 {
     enum
     {
       yyeof_ = 0,
-      yylast_ = 245,     ///< Last index in yytable_.
-      yynnts_ = 110,  ///< Number of nonterminal symbols.
-      yyfinal_ = 8, ///< Termination state number.
+      yylast_ = 247,     ///< Last index in yytable_.
+      yynnts_ = 127,  ///< Number of nonterminal symbols.
+      yyfinal_ = 20, ///< Termination state number.
       yyterror_ = 1,
       yyerrcode_ = 256,
-      yyntokens_ = 45  ///< Number of tokens.
+      yyntokens_ = 51  ///< Number of tokens.
     };
 
 
@@ -926,9 +956,10 @@ namespace isc { namespace d2 {
        5,     6,     7,     8,     9,    10,    11,    12,    13,    14,
       15,    16,    17,    18,    19,    20,    21,    22,    23,    24,
       25,    26,    27,    28,    29,    30,    31,    32,    33,    34,
-      35,    36,    37,    38,    39,    40,    41,    42,    43,    44
+      35,    36,    37,    38,    39,    40,    41,    42,    43,    44,
+      45,    46,    47,    48,    49,    50
     };
-    const unsigned int user_token_number_max_ = 299;
+    const unsigned int user_token_number_max_ = 305;
     const token_number_type undef_token_ = 2;
 
     if (static_cast<int>(t) <= yyeof_)
@@ -961,24 +992,24 @@ namespace isc { namespace d2 {
   {
       switch (other.type_get ())
     {
-      case 50: // value
-      case 77: // ncr_protocol_value
+      case 62: // value
+      case 89: // ncr_protocol_value
         value.copy< ElementPtr > (other.value);
         break;
 
-      case 44: // "boolean"
+      case 50: // "boolean"
         value.copy< bool > (other.value);
         break;
 
-      case 43: // "floating point"
+      case 49: // "floating point"
         value.copy< double > (other.value);
         break;
 
-      case 42: // "integer"
+      case 48: // "integer"
         value.copy< int64_t > (other.value);
         break;
 
-      case 41: // "constant string"
+      case 47: // "constant string"
         value.copy< std::string > (other.value);
         break;
 
@@ -999,24 +1030,24 @@ namespace isc { namespace d2 {
     (void) v;
       switch (this->type_get ())
     {
-      case 50: // value
-      case 77: // ncr_protocol_value
+      case 62: // value
+      case 89: // ncr_protocol_value
         value.copy< ElementPtr > (v);
         break;
 
-      case 44: // "boolean"
+      case 50: // "boolean"
         value.copy< bool > (v);
         break;
 
-      case 43: // "floating point"
+      case 49: // "floating point"
         value.copy< double > (v);
         break;
 
-      case 42: // "integer"
+      case 48: // "integer"
         value.copy< int64_t > (v);
         break;
 
-      case 41: // "constant string"
+      case 47: // "constant string"
         value.copy< std::string > (v);
         break;
 
@@ -1096,24 +1127,24 @@ namespace isc { namespace d2 {
     // Type destructor.
     switch (yytype)
     {
-      case 50: // value
-      case 77: // ncr_protocol_value
+      case 62: // value
+      case 89: // ncr_protocol_value
         value.template destroy< ElementPtr > ();
         break;
 
-      case 44: // "boolean"
+      case 50: // "boolean"
         value.template destroy< bool > ();
         break;
 
-      case 43: // "floating point"
+      case 49: // "floating point"
         value.template destroy< double > ();
         break;
 
-      case 42: // "integer"
+      case 48: // "integer"
         value.template destroy< int64_t > ();
         break;
 
-      case 41: // "constant string"
+      case 47: // "constant string"
         value.template destroy< std::string > ();
         break;
 
@@ -1140,24 +1171,24 @@ namespace isc { namespace d2 {
     super_type::move(s);
       switch (this->type_get ())
     {
-      case 50: // value
-      case 77: // ncr_protocol_value
+      case 62: // value
+      case 89: // ncr_protocol_value
         value.move< ElementPtr > (s.value);
         break;
 
-      case 44: // "boolean"
+      case 50: // "boolean"
         value.move< bool > (s.value);
         break;
 
-      case 43: // "floating point"
+      case 49: // "floating point"
         value.move< double > (s.value);
         break;
 
-      case 42: // "integer"
+      case 48: // "integer"
         value.move< int64_t > (s.value);
         break;
 
-      case 41: // "constant string"
+      case 47: // "constant string"
         value.move< std::string > (s.value);
         break;
 
@@ -1220,7 +1251,8 @@ namespace isc { namespace d2 {
      265,   266,   267,   268,   269,   270,   271,   272,   273,   274,
      275,   276,   277,   278,   279,   280,   281,   282,   283,   284,
      285,   286,   287,   288,   289,   290,   291,   292,   293,   294,
-     295,   296,   297,   298,   299
+     295,   296,   297,   298,   299,   300,   301,   302,   303,   304,
+     305
     };
     return static_cast<token_type> (yytoken_number_[type]);
   }
@@ -1460,6 +1492,42 @@ namespace isc { namespace d2 {
   }
 
   D2Parser::symbol_type
+  D2Parser::make_SUB_TSIG_KEY (const location_type& l)
+  {
+    return symbol_type (token::TOKEN_SUB_TSIG_KEY, l);
+  }
+
+  D2Parser::symbol_type
+  D2Parser::make_SUB_TSIG_KEYS (const location_type& l)
+  {
+    return symbol_type (token::TOKEN_SUB_TSIG_KEYS, l);
+  }
+
+  D2Parser::symbol_type
+  D2Parser::make_SUB_DDNS_DOMAIN (const location_type& l)
+  {
+    return symbol_type (token::TOKEN_SUB_DDNS_DOMAIN, l);
+  }
+
+  D2Parser::symbol_type
+  D2Parser::make_SUB_DDNS_DOMAINS (const location_type& l)
+  {
+    return symbol_type (token::TOKEN_SUB_DDNS_DOMAINS, l);
+  }
+
+  D2Parser::symbol_type
+  D2Parser::make_SUB_DNS_SERVER (const location_type& l)
+  {
+    return symbol_type (token::TOKEN_SUB_DNS_SERVER, l);
+  }
+
+  D2Parser::symbol_type
+  D2Parser::make_SUB_DNS_SERVERS (const location_type& l)
+  {
+    return symbol_type (token::TOKEN_SUB_DNS_SERVERS, l);
+  }
+
+  D2Parser::symbol_type
   D2Parser::make_STRING (const std::string& v, const location_type& l)
   {
     return symbol_type (token::TOKEN_STRING, v, l);
@@ -1486,7 +1554,7 @@ namespace isc { namespace d2 {
 
 #line 14 "d2_parser.yy" // lalr1.cc:392
 } } // isc::d2
-#line 1490 "d2_parser.h" // lalr1.cc:392
+#line 1558 "d2_parser.h" // lalr1.cc:392
 
 
 

+ 79 - 31
src/bin/d2/d2_parser.yy

@@ -85,6 +85,12 @@ using namespace std;
   TOPLEVEL_JSON
   TOPLEVEL_DHCPDDNS
   SUB_DHCPDDNS
+  SUB_TSIG_KEY
+  SUB_TSIG_KEYS
+  SUB_DDNS_DOMAIN
+  SUB_DDNS_DOMAINS
+  SUB_DNS_SERVER
+  SUB_DNS_SERVERS
 ;
 
 %token <std::string> STRING "constant string"
@@ -107,6 +113,12 @@ using namespace std;
 start: TOPLEVEL_JSON { ctx.ctx_ = ctx.NO_KEYWORD; } sub_json
      | TOPLEVEL_DHCPDDNS { ctx.ctx_ = ctx.CONFIG; } syntax_map
      | SUB_DHCPDDNS { ctx.ctx_ = ctx.DHCPDDNS; } sub_dhcpddns
+     | SUB_TSIG_KEY { ctx.ctx_ = ctx.TSIG_KEY; } sub_tsig_key
+     | SUB_TSIG_KEYS { ctx.ctx_ = ctx.TSIG_KEYS; } sub_tsig_keys
+     | SUB_DDNS_DOMAIN { ctx.ctx_ = ctx.DDNS_DOMAIN; } sub_ddns_domain
+     | SUB_DDNS_DOMAINS { ctx.ctx_ = ctx.DDNS_DOMAINS; } sub_ddns_domains
+     | SUB_DNS_SERVER { ctx.ctx_ = ctx.DNS_SERVERS; } sub_dns_server
+     | SUB_DNS_SERVERS { ctx.ctx_ = ctx.DNS_SERVERS; } sub_dns_servers
      ;
 
 // ---- generic JSON parser ---------------------------------
@@ -261,7 +273,7 @@ ip_address: IP_ADDRESS {
 port: PORT COLON INTEGER {
     if ($3 <= 0) {
         error(@3, "port must be greater than zero");
-    } 
+    }
     ElementPtr i(new IntElement($3, ctx.loc2pos(@3)));
     ctx.stack_.back()->set("port", i);
 };
@@ -269,7 +281,7 @@ port: PORT COLON INTEGER {
 dns_server_timeout: DNS_SERVER_TIMEOUT COLON INTEGER {
     if ($3 <= 0) {
         error(@3, "dns-server-timeout must be greater than zero");
-    } else { 
+    } else {
         ElementPtr i(new IntElement($3, ctx.loc2pos(@3)));
         ctx.stack_.back()->set("dns-server-timeout", i);
     }
@@ -319,17 +331,16 @@ ddns_mgr_params: %empty
                | not_empty_ddns_mgr_params
                ;
 
-not_empty_ddns_mgr_params: ddns_mgr_param 
+not_empty_ddns_mgr_params: ddns_mgr_param
                          | ddns_mgr_params COMMA ddns_mgr_param
                          ;
 
-ddns_mgr_param: ddns_domains 
+ddns_mgr_param: ddns_domains
               | unknown_map_entry
               ;
 
 
 // --- ddns-domains ----------------------------------------
-
 ddns_domains: DDNS_DOMAINS {
     ElementPtr l(new ListElement(ctx.loc2pos(@1)));
     ctx.stack_.back()->set("ddns-domains", l);
@@ -340,6 +351,13 @@ ddns_domains: DDNS_DOMAINS {
     ctx.leave();
 };
 
+sub_ddns_domains: LSQUARE_BRACKET {
+    ElementPtr l(new ListElement(ctx.loc2pos(@1)));
+    ctx.stack_.push_back(l);
+} ddns_domain_list RSQUARE_BRACKET {
+    // parsing completed
+}
+
 ddns_domain_list: %empty
               | not_empty_ddns_domain_list
               ;
@@ -356,7 +374,14 @@ ddns_domain: LCURLY_BRACKET {
     ctx.stack_.pop_back();
 };
 
-ddns_domain_params: ddns_domain_param 
+sub_ddns_domain: LCURLY_BRACKET {
+    ElementPtr m(new MapElement(ctx.loc2pos(@1)));
+    ctx.stack_.push_back(m);
+} ddns_domain_params RCURLY_BRACKET {
+    // parsing completed
+};
+
+ddns_domain_params: ddns_domain_param
                   | ddns_domain_params COMMA ddns_domain_param
                   ;
 
@@ -371,8 +396,8 @@ ddns_domain_name: NAME {
     ctx.enter(ctx.NO_KEYWORD);
 } COLON STRING {
     if ($4 == "") {
-        error(@3, "name cannot be blank");
-    } 
+        error(@3, "Ddns domain name cannot be blank");
+    }
     ElementPtr elem(new StringElement($4, ctx.loc2pos(@4)));
     ElementPtr name(new StringElement($4, ctx.loc2pos(@4)));
     ctx.stack_.back()->set("name", name);
@@ -382,9 +407,6 @@ ddns_domain_name: NAME {
 ddns_domain_key_name: KEY_NAME {
     ctx.enter(ctx.NO_KEYWORD);
 } COLON STRING {
-    if ($4 == "") {
-        error(@3, "key-name cannot be blank");
-    } 
     ElementPtr elem(new StringElement($4, ctx.loc2pos(@4)));
     ElementPtr name(new StringElement($4, ctx.loc2pos(@4)));
     ctx.stack_.back()->set("key-name", name);
@@ -404,13 +426,16 @@ dns_servers: DNS_SERVERS {
     ctx.leave();
 };
 
-dns_server_list: %empty
-              | not_empty_dns_server_list
-              ;
+sub_dns_servers: LSQUARE_BRACKET {
+    ElementPtr l(new ListElement(ctx.loc2pos(@1)));
+    ctx.stack_.push_back(l);
+} dns_server_list RSQUARE_BRACKET {
+    // parsing completed
+}
 
-not_empty_dns_server_list: dns_server
-                        | not_empty_dns_server_list COMMA dns_server
-                        ;
+dns_server_list: dns_server
+               | dns_server_list COMMA dns_server
+               ;
 
 dns_server: LCURLY_BRACKET {
     ElementPtr m(new MapElement(ctx.loc2pos(@1)));
@@ -420,7 +445,14 @@ dns_server: LCURLY_BRACKET {
     ctx.stack_.pop_back();
 };
 
-dns_server_params: dns_server_param 
+sub_dns_server: LCURLY_BRACKET {
+    ElementPtr m(new MapElement(ctx.loc2pos(@1)));
+    ctx.stack_.push_back(m);
+} dns_server_params RCURLY_BRACKET {
+    // parsing completed
+};
+
+dns_server_params: dns_server_param
                | dns_server_params COMMA dns_server_param
                ;
 
@@ -433,9 +465,9 @@ dns_server_param: dns_server_hostname
 dns_server_hostname: HOSTNAME {
     ctx.enter(ctx.NO_KEYWORD);
 } COLON STRING {
-    if ($4 == "") {
-        error(@3, "hostname cannot be blank");
-    } 
+    if ($4 != "") {
+        error(@3, "hostname is not yet supported");
+    }
     ElementPtr elem(new StringElement($4, ctx.loc2pos(@4)));
     ElementPtr name(new StringElement($4, ctx.loc2pos(@4)));
     ctx.stack_.back()->set("hostname", name);
@@ -453,7 +485,7 @@ dns_server_ip_address: IP_ADDRESS {
 dns_server_port: PORT COLON INTEGER {
     if ($3 <= 0) {
         error(@3, "port must be greater than zero");
-    } 
+    }
     ElementPtr i(new IntElement($3, ctx.loc2pos(@3)));
     ctx.stack_.back()->set("port", i);
 };
@@ -474,6 +506,13 @@ tsig_keys: TSIG_KEYS {
     ctx.leave();
 };
 
+sub_tsig_keys: LSQUARE_BRACKET {
+    ElementPtr l(new ListElement(ctx.loc2pos(@1)));
+    ctx.stack_.push_back(l);
+} tsig_keys_list RSQUARE_BRACKET {
+    // parsing completed
+}
+
 tsig_keys_list: %empty
               | not_empty_tsig_keys_list
               ;
@@ -490,7 +529,16 @@ tsig_key: LCURLY_BRACKET {
     ctx.stack_.pop_back();
 };
 
-tsig_key_params: tsig_key_param 
+sub_tsig_key: LCURLY_BRACKET {
+    // Parse tsig key list entry map
+    ElementPtr m(new MapElement(ctx.loc2pos(@1)));
+    ctx.stack_.push_back(m);
+} tsig_key_params RCURLY_BRACKET {
+    // parsing completed
+};
+
+
+tsig_key_params: tsig_key_param
                | tsig_key_params COMMA tsig_key_param
                ;
 
@@ -505,8 +553,8 @@ tsig_key_name: NAME {
     ctx.enter(ctx.NO_KEYWORD);
 } COLON STRING {
     if ($4 == "") {
-        error(@3, "name cannot be blank");
-    } 
+        error(@3, "TSIG key name cannot be blank");
+    }
     ElementPtr elem(new StringElement($4, ctx.loc2pos(@4)));
     ElementPtr name(new StringElement($4, ctx.loc2pos(@4)));
     ctx.stack_.back()->set("name", name);
@@ -517,8 +565,8 @@ tsig_key_algorithm: ALGORITHM {
     ctx.enter(ctx.NO_KEYWORD);
 } COLON STRING {
     if ($4 == "") {
-        error(@3, "algorithm cannot be blank");
-    } 
+        error(@3, "TSIG key algorithm cannot be blank");
+    }
     ElementPtr elem(new StringElement($4, ctx.loc2pos(@4)));
     ctx.stack_.back()->set("algorithm", elem);
     ctx.leave();
@@ -526,8 +574,8 @@ tsig_key_algorithm: ALGORITHM {
 
 tsig_key_digest_bits: DIGEST_BITS COLON INTEGER {
     if ($3 < 0 || ($3 > 0  && ($3 % 8 != 0))) {
-        error(@3, "digest-bits must either be zero or a positive, multiple of eight");
-    } 
+        error(@3, "TSIG key digest-bits must either be zero or a positive, multiple of eight");
+    }
     ElementPtr elem(new IntElement($3, ctx.loc2pos(@3)));
     ctx.stack_.back()->set("digest-bits", elem);
 };
@@ -536,8 +584,8 @@ tsig_key_secret: SECRET {
     ctx.enter(ctx.NO_KEYWORD);
 } COLON STRING {
     if ($4 == "") {
-        error(@3, "secret cannot be blank");
-    } 
+        error(@3, "TSIG key secret cannot be blank");
+    }
     ElementPtr elem(new StringElement($4, ctx.loc2pos(@4)));
     ctx.stack_.back()->set("secret", elem);
     ctx.leave();

+ 91 - 4
src/bin/d2/d2_simple_parser.cc

@@ -36,23 +36,110 @@ namespace d2 {
 /// used.
 const SimpleDefaults D2SimpleParser::D2_GLOBAL_DEFAULTS = {
     { "ip-address",         Element::string, D2Params::DFT_IP_ADDRESS },
-    { "port",               Element::integer, D2Params::DFT_PORT },
-    { "dns-server-timeout", Element::integer, D2Params::DFT_DNS_SERVER_TIMEOUT },
+    { "port",               Element::integer, D2Params::DFT_PORT_STR },
+    { "dns-server-timeout", Element::integer, D2Params::DFT_DNS_SERVER_TIMEOUT_STR },
     { "ncr-protocol",       Element::string, D2Params::DFT_NCR_PROTOCOL },
     { "ncr-format",         Element::string, D2Params::DFT_NCR_FORMAT }
 };
 
+const SimpleDefaults D2SimpleParser::TSIG_KEY_DEFAULTS = {
+    { "digest-bits",    Element::integer, "0" }
+};
+
+const SimpleDefaults D2SimpleParser::DDNS_DOMAIN_MGR_DEFAULTS = {
+    // none yet
+};
+
+const SimpleDefaults D2SimpleParser::DDNS_DOMAIN_DEFAULTS = {
+    { "key-name",    Element::string, "" }
+};
+
+const SimpleDefaults D2SimpleParser::DNS_SERVER_DEFAULTS = {
+    { "hostname", Element::string, "" },
+    { "port",     Element::integer, DnsServerInfo::STANDARD_DNS_PORT_STR },
+};
+
 /// @}
 
 /// ---------------------------------------------------------------------------
 /// --- end of default values -------------------------------------------------
 /// ---------------------------------------------------------------------------
 
-size_t D2SimpleParser::setAllDefaults(isc::data::ElementPtr global) {
+size_t
+D2SimpleParser::setAllDefaults(isc::data::ElementPtr global) {
     size_t cnt = 0;
-
     // Set global defaults first.
     cnt = setDefaults(global, D2_GLOBAL_DEFAULTS);
+
+    // If the key list is present, set its members' defaults
+    if (global->find("tsig-keys")) {
+        ConstElementPtr keys = global->get("tsig-keys");
+        cnt += setListDefaults(keys, TSIG_KEY_DEFAULTS);
+    } else {
+        // Not present, so add an empty list.
+        ConstElementPtr list(new ListElement());
+        global->set("tsig-keys", list);
+        cnt++;
+    }
+
+    // Set the forward domain manager defaults.
+    cnt += setManagerDefaults(global, "forward-ddns", DDNS_DOMAIN_MGR_DEFAULTS);
+
+    // Set the reverse domain manager defaults.
+    cnt += setManagerDefaults(global, "reverse-ddns", DDNS_DOMAIN_MGR_DEFAULTS);
+    return (cnt);
+}
+
+size_t
+D2SimpleParser::setDdnsDomainDefaults(ElementPtr domain,
+                                      const SimpleDefaults& domain_defaults) {
+    size_t cnt = 0;
+
+    // Set the domain's scalar defaults
+    cnt += setDefaults(domain, domain_defaults);
+    if (domain->find("dns-servers")) {
+        // Now add the defaults to its server list.
+        ConstElementPtr servers = domain->get("dns-servers");
+        cnt += setListDefaults(servers, DNS_SERVER_DEFAULTS);
+    }
+
+    return (cnt);
+}
+
+
+size_t
+D2SimpleParser::setManagerDefaults(ElementPtr global,
+                                   const std::string& mgr_name,
+                                   const SimpleDefaults& mgr_defaults) {
+    size_t cnt = 0;
+
+    if (!global->find(mgr_name)) {
+        // If it's not present, then default is an empty map
+        ConstElementPtr map(new MapElement());
+        global->set(mgr_name, map);
+        ++cnt;
+    } else {
+        // Get a writable copy of the manager element map
+        ElementPtr mgr =
+            boost::const_pointer_cast<Element>(global->get(mgr_name));
+
+        // Set the manager's scalar defaults first
+        cnt += setDefaults(mgr, mgr_defaults);
+
+        // Get the domain list and set defaults for them.
+        // The domain list may not be present ddns for this
+        // manager is disabled.
+        if (mgr->find("ddns-domains")) {
+            ConstElementPtr domains = mgr->get("ddns-domains");
+            BOOST_FOREACH(ElementPtr domain, domains->listValue()) {
+                // Set the domain's defaults.  We can't use setListDefaults()
+                // as this does not handle sub-lists or maps, like server list.
+                cnt += setDdnsDomainDefaults(domain, DDNS_DOMAIN_DEFAULTS);
+            }
+        }
+
+    }
+
     return (cnt);
 }
 

+ 45 - 3
src/bin/d2/d2_simple_parser.h

@@ -18,7 +18,7 @@ namespace d2 {
 /// In particular, it contains all the default values and names of the
 /// parameters that are to be derived (inherited) between scopes.
 /// For the actual values, see @file d2_simple_parser.cc
-class D2SimpleParser : public isc::data::SimpleParser {
+class D2SimpleParser : public data::SimpleParser {
 public:
 
     /// @brief Sets all defaults for D2 configuration
@@ -27,10 +27,52 @@ public:
     ///
     /// @param global scope to be filled in with defaults.
     /// @return number of default values added
-    static size_t setAllDefaults(isc::data::ElementPtr global);
+    static size_t setAllDefaults(data::ElementPtr global);
 
     // see d2_simple_parser.cc for comments for those parameters
-    static const isc::data::SimpleDefaults D2_GLOBAL_DEFAULTS;
+    static const data::SimpleDefaults D2_GLOBAL_DEFAULTS;
+
+    // Defaults for tsig-keys list elements, TSIGKeyInfos
+    static const data::SimpleDefaults TSIG_KEY_DEFAULTS;
+
+    // Defaults for <forward|reverse>-ddns elements, DdnsDomainListMgrs
+    static const data::SimpleDefaults DDNS_DOMAIN_MGR_DEFAULTS;
+
+    // Defaults for ddns-domains list elements, DdnsDomains
+    static const data::SimpleDefaults DDNS_DOMAIN_DEFAULTS;
+
+    // Defaults for dns-servers list elements, DnsServerInfos
+    static const data::SimpleDefaults DNS_SERVER_DEFAULTS;
+
+    /// @brief Adds default values to a DDNS Domain element
+    ///
+    /// Adds the scalar default values to the given DDNS domain
+    /// element, and then adds the DNS Server defaults to the domain's
+    /// server list, "dns-servers".
+    ///
+    /// @param domain DDNS domain element to which defaults should be added
+    /// @param domain_defaults list of default values from which to add
+    /// @return returns the number of default values added
+    static size_t setDdnsDomainDefaults(data::ElementPtr domain,
+                                        const data::SimpleDefaults&
+                                        domain_defaults);
+
+    /// @brief Adds default values to a DDNS Domain List Manager
+    ///
+    /// This function looks for the named DDNS domain manager element within
+    /// the given element tree.  If it is found, it adds the scalar default
+    /// values to the manager element and then adds the DDNS Domain defaults
+    /// to its domain list, "ddns-domains".  If the manager element is not
+    /// found, then an empty map entry is added for it, thus defaulting the
+    /// manager to "disabled".
+    ///
+    /// @param domain DDNS domain manager element to which defaults should be
+    /// added
+    /// @param mgr_defaults list of default values from which to add
+    /// @return returns the number of default values added
+    static size_t setManagerDefaults(data::ElementPtr global,
+                                     const std::string& mgr_name,
+                                     const data::SimpleDefaults& mgr_defaults);
 };
 
 };

+ 7 - 2
src/bin/d2/parser_context.cc

@@ -104,11 +104,10 @@ D2ParserContext::enter(const ParserContext& ctx)
 void
 D2ParserContext::leave()
 {
-#if 1
     if (cstack_.empty()) {
         fatal("unbalanced syntactic context");
     }
-#endif
+
     ctx_ = cstack_.back();
     cstack_.pop_back();
 }
@@ -123,6 +122,8 @@ D2ParserContext::contextName()
         return ("toplevel");
     case DHCPDDNS:
         return ("DhcpDdns");
+    case TSIG_KEY:
+        return ("tsig-key");
     case TSIG_KEYS:
         return ("tsig-keys");
     case ALGORITHM:
@@ -135,8 +136,12 @@ D2ParserContext::contextName()
         return("forward-ddns");
     case REVERSE_DDNS:
         return("reverse-ddns");
+    case DDNS_DOMAIN:
+        return("ddns-domain");
     case DDNS_DOMAINS:
         return("ddns-domains");
+    case DNS_SERVER:
+        return("dns-server");
     case DNS_SERVERS:
         return("dns-servers");
     case LOGGING:

+ 33 - 6
src/bin/d2/parser_context.h

@@ -48,11 +48,29 @@ public:
         /// This parser will parse the content as generic JSON.
         PARSER_JSON,
 
-        ///< Used while parsing top level (contains DhcpDdns, Logging, others)
+        ///< Used for parsing top level (contains DhcpDdns, Logging, others)
         PARSER_DHCPDDNS,
 
-        ///< Used while parsing content of DhcpDdns.
-        PARSER_SUB_DHCPDDNS
+        ///< Used for parsing content of DhcpDdns.
+        PARSER_SUB_DHCPDDNS,
+
+        ///< Used for parsing content of a TSIG key.
+        PARSER_TSIG_KEY,
+
+        ///< Used for pasing a list of TSIG Keys.
+        PARSER_TSIG_KEYS,
+
+        ///< Used for parsing content of a DDNS Domain.
+        PARSER_DDNS_DOMAIN,
+
+        ///< Used for parsing a list a DDNS Domains.
+        PARSER_DDNS_DOMAINS,
+
+        ///< Used for parsing content of a DNS Server.
+        PARSER_DNS_SERVER,
+
+        ///< Used for pasing a list of DNS servess.
+        PARSER_DNS_SERVERS
     } ParserType;
 
     /// @brief Default constructor.
@@ -156,7 +174,10 @@ public:
         ///< Used while parsing content of DhcpDdns.
         DHCPDDNS,
 
-        ///< Used while parsing content of tsig-keys
+        ///< Used while parsing content of a tsig-key
+        TSIG_KEY,
+
+        ///< Used while parsing a list of tsig-keys
         TSIG_KEYS,
 
         ///< Used while parsing content of DhcpDdns/tsig-keys/algorithm
@@ -174,10 +195,16 @@ public:
         ///< Used while parsing content of DhcpDdns/reverse-ddns
         REVERSE_DDNS,
 
-        ///< Used while parsing content of DhcpDdns/<forward|reverse>-ddns/ddns-domains
+        ///< Used while parsing content of a ddns-domain
+        DDNS_DOMAIN,
+
+        ///< Used while parsing a list of ddns-domains
         DDNS_DOMAINS,
 
-        ///< Used while parsing content of DhcpDdns/<forward|reverse>-ddns/ddns-domains/dns-servers
+        ///< Used while parsing content of a dns-server
+        DNS_SERVER,
+
+        ///< Used while parsing content of list of dns-servers
         DNS_SERVERS,
 
         ///< Used while parsing content of Logging

File diff suppressed because it is too large
+ 151 - 1011
src/bin/d2/tests/d2_cfg_mgr_unittests.cc


+ 1 - 0
src/bin/d2/tests/d2_controller_unittests.cc

@@ -10,6 +10,7 @@
 #include <d2/d2_controller.h>
 #include <d2/d2_process.h>
 #include <process/spec_config.h>
+#include <d2/tests/nc_test_utils.h>
 #include <process/testutils/d_test_stubs.h>
 
 #include <boost/pointer_cast.hpp>

+ 1 - 0
src/bin/d2/tests/d2_process_unittests.cc

@@ -11,6 +11,7 @@
 #include <d2/d2_process.h>
 #include <dhcp_ddns/ncr_io.h>
 #include <process/testutils/d_test_stubs.h>
+#include <d2/tests/nc_test_utils.h>
 
 #include <boost/bind.hpp>
 #include <boost/date_time/posix_time/posix_time.hpp>

File diff suppressed because it is too large
+ 1076 - 41
src/bin/d2/tests/d2_simple_parser_unittest.cc


+ 25 - 0
src/bin/d2/tests/nc_test_utils.cc

@@ -22,6 +22,31 @@ using namespace isc::d2;
 namespace isc {
 namespace d2 {
 
+const char* valid_d2_config = "{ "
+                        "\"ip-address\" : \"127.0.0.1\" , "
+                        "\"port\" : 5031, "
+                        "\"tsig-keys\": ["
+                        "{ \"name\": \"d2_key.tmark.org\" , "
+                        "   \"algorithm\": \"HMAC-MD5\" ,"
+                        "   \"secret\": \"LSWXnfkKZjdPJI5QxlpnfQ==\" "
+                        "} ],"
+                        "\"forward-ddns\" : {"
+                        "\"ddns-domains\": [ "
+                        "{ \"name\": \"tmark.org.\" , "
+                        "  \"key-name\": \"d2_key.tmark.org\" , "
+                        "  \"dns-servers\" : [ "
+                        "  { \"ip-address\": \"127.0.0.101\" } "
+                        "] } ] }, "
+                        "\"reverse-ddns\" : {"
+                        "\"ddns-domains\": [ "
+                        "{ \"name\": \" 0.168.192.in.addr.arpa.\" , "
+                        "  \"key-name\": \"d2_key.tmark.org\" , "
+                        "  \"dns-servers\" : [ "
+                        "  { \"ip-address\": \"127.0.0.101\" , "
+                        "    \"port\": 100 } ] } "
+                        "] } }";
+
+
 const char* TEST_DNS_SERVER_IP = "127.0.0.1";
 size_t TEST_DNS_SERVER_PORT = 5301;
 

+ 1 - 0
src/bin/d2/tests/nc_test_utils.h

@@ -20,6 +20,7 @@
 namespace isc {
 namespace d2 {
 
+extern const char* valid_d2_config;
 extern const char* TEST_DNS_SERVER_IP;
 extern size_t TEST_DNS_SERVER_PORT;
 

+ 33 - 34
src/bin/d2/tests/testdata/d2_cfg_tests.json

@@ -27,7 +27,6 @@
 # as well as validating this as the smallest config which makes writing
 # permutations easier.
 "description" : "D2 smallest, valid config",
-"logic-error" : false,
 "data" :
     {
     "forward-ddns" : {},
@@ -37,9 +36,9 @@
 }
 
 #-----
+# Map should be supplied through setDefaults
 ,{
 "description" : "D2 missing forward-ddns map",
-"logic-error" : true,
 "data" :
     {
     "reverse-ddns" : {},
@@ -48,9 +47,9 @@
 }
 
 #-----
+# Map should be supplied through setDefaults
 ,{
 "description" : "D2 missing reverse-ddns map",
-"logic-error" : true,
 "data" :
     {
     "forward-ddns" : {},
@@ -60,9 +59,9 @@
 
 
 #-----
+# Map should be supplied through setDefaults
 ,{
 "description" : "D2 missing tsig-keys list",
-"logic-error" : true,
 "data" :
     {
     "forward-ddns" : {},
@@ -138,7 +137,7 @@
 #-----
 ,{
 "description" : "D2Params.ip-address invalid value",
-"logic-error" : true,
+"logic-error" : "invalid address (bogus) specified for parameter 'ip-address' (<string>:1:39)",
 "data" :
     {
     "ip-address" : "bogus",
@@ -241,7 +240,7 @@
 #-----
 ,{
 "description" : "D2Params.ncr-protocol, unsupported TCP",
-"logic-error" : true,
+"logic-error" : "ncr-protocol : TCP is not yet supported  (<string>:1:41)",
 "data" :
     {
     "ncr-protocol" : "TCP",
@@ -316,7 +315,7 @@
 #-----
 ,{
 "description" : "D2.tsig-keys, missing key name",
-"logic-error" : true,
+"logic-error" : "element: tsig-keys : String parameter name not found(<string>:1:62)<string>:1:47",
 "data" :
     {
     "forward-ddns" : {},
@@ -334,7 +333,7 @@
 #-----
 ,{
 "description" : "D2.tsig-keys, blank key name",
-"syntax-error" : "<string>:1.95: name cannot be blank",
+"syntax-error" : "<string>:1.95: TSIG key name cannot be blank",
 "data" :
     {
     "forward-ddns" : {},
@@ -353,7 +352,7 @@
 #-----
 ,{
 "description" : "D2.tsig-keys, duplicate key name",
-"logic-error" : true,
+"logic-error" : "Duplicate TSIG key name specified : first.key (<string>:1:185)",
 "data" :
     {
     "forward-ddns" : {},
@@ -421,7 +420,7 @@
 #----- D2.tsig-keys, algorithm tests
 ,{
 "description" : "D2.tsig-keys, missing algorithm",
-"logic-error" : true,
+"logic-error" : "element: tsig-keys : String parameter algorithm not found(<string>:1:62)<string>:1:47",
 "data" :
     {
     "forward-ddns" : {},
@@ -439,7 +438,7 @@
 #-----
 ,{
 "description" : "D2.tsig-keys, blank algorithm",
-"syntax-error" : "<string>:1.75: algorithm cannot be blank",
+"syntax-error" : "<string>:1.75: TSIG key algorithm cannot be blank",
 "data" :
     {
     "forward-ddns" : {},
@@ -458,7 +457,7 @@
 #-----
 ,{
 "description" : "D2.tsig-keys, invalid algorithm",
-"logic-error" : true,
+"logic-error" : "tsig-key : Unknown TSIG Key algorithm: bogus (<string>:1:77)",
 "data" :
     {
     "forward-ddns" : {},
@@ -526,7 +525,7 @@
 #-----
 ,{
 "description" : "D2.tsig-keys, invalid digest-bits",
-"syntax-error" : "<string>:1.104-105: digest-bits must either be zero or a positive, multiple of eight",
+"syntax-error" : "<string>:1.104-105: TSIG key digest-bits must either be zero or a positive, multiple of eight",
 "data" :
     {
     "forward-ddns" : {},
@@ -546,7 +545,7 @@
 #-----
 ,{
 "description" : "D2.tsig-keys, too small truncated HMAC-MD5",
-"logic-error" : true,
+"logic-error" : "tsig-key: digest-bits too small :  (<string>:1:104)",
 "data" :
     {
     "forward-ddns" : {},
@@ -566,7 +565,7 @@
 #-----
 ,{
 "description" : "D2.tsig-keys, too small truncated HMAC-SHA1",
-"logic-error" : true,
+"logic-error" : "tsig-key: digest-bits too small :  (<string>:1:105)",
 "data" :
     {
     "forward-ddns" : {},
@@ -586,7 +585,7 @@
 #-----
 ,{
 "description" : "D2.tsig-keys, too small truncated HMAC-SHA224",
-"logic-error" : true,
+"logic-error" : "tsig-key: digest-bits too small :  (<string>:1:107)",
 "data" :
     {
     "forward-ddns" : {},
@@ -606,7 +605,7 @@
 #-----
 ,{
 "description" : "D2.tsig-keys, too small truncated HMAC-SHA256",
-"logic-error" : true,
+"logic-error" : "tsig-key: digest-bits too small :  (<string>:1:107)",
 "data" :
     {
     "forward-ddns" : {},
@@ -626,7 +625,7 @@
 #-----
 ,{
 "description" : "D2.tsig-keys, too small truncated HMAC-SHA384",
-"logic-error" : true,
+"logic-error" : "tsig-key: digest-bits too small :  (<string>:1:107)",
 "data" :
     {
     "forward-ddns" : {},
@@ -646,7 +645,7 @@
 #-----
 ,{
 "description" : "D2.tsig-keys, too small truncated HMAC-SHA512",
-"logic-error" : true,
+"logic-error" : "tsig-key: digest-bits too small :  (<string>:1:107)",
 "data" :
     {
     "forward-ddns" : {},
@@ -666,7 +665,7 @@
 #----- D2.tsig-keys, secret tests
 ,{
 "description" : "D2.tsig-keys, missing secret",
-"logic-error" : true,
+"logic-error" : "element: tsig-keys : String parameter secret not found(<string>:1:62)<string>:1:47",
 "data" :
     {
     "forward-ddns" : {},
@@ -684,7 +683,7 @@
 #-----
 ,{
 "description" : "D2.tsig-keys, blank secret",
-"syntax-error" : "<string>:1.118: secret cannot be blank",
+"syntax-error" : "<string>:1.118: TSIG key secret cannot be blank",
 "data" :
     {
     "forward-ddns" : {},
@@ -703,7 +702,7 @@
 #-----
 ,{
 "description" : "D2.tsig-keys, invalid secret",
-"logic-error" : true,
+"logic-error" : "Cannot make TSIGKey: Incomplete input for base64: bogus (<string>:1:62)",
 "data" :
     {
     "forward-ddns" : {},
@@ -785,7 +784,7 @@
 #------
 ,{
 "description" : "D2.forward-ddns, duplicate domain",
-"logic-error" : true,
+"logic-error" : "Duplicate domain specified:four.example.com. (<string>:1:184)",
 "data" :
     {
     "forward-ddns" :
@@ -859,7 +858,7 @@
 #-----
 ,{
 "description" : "D2.forward-ddns.dhcp-ddns, blank name",
-"syntax-error" : "<string>:1.47: name cannot be blank",
+"syntax-error" : "<string>:1.47: Ddns domain name cannot be blank",
 "data" :
     {
     "forward-ddns" :
@@ -879,7 +878,7 @@
 #------ "D2.forward-ddns.dhcp-ddns, key-name tests
 ,{
 "description" : "D2.forward-ddns, no matching key name",
-"logic-error" : true,
+"logic-error" : "DdnsDomain : four.example.com. specifies an undefined key: no.such.key (<string>:1:104)",
 "data" :
     {
     "forward-ddns" :
@@ -913,7 +912,7 @@
 #----- D2.forward-ddns.dhcp-ddns.dns-servers tests
 ,{
 "description" : "D2.forward-ddns.dhcp-ddns.dns-servers, no servers",
-"logic-error" : true,
+"syntax-error" : "<string>:1.59: syntax error, unexpected ], expecting {",
 "data" :
     {
     "forward-ddns" :
@@ -960,7 +959,7 @@
 #-----
 ,{
 "description" : "D2.forward-ddns.dhcp-ddns.dns-servers.hostname unsupported",
-"logic-error" : true,
+"syntax-error" : "<string>:1.70: hostname is not yet supported",
 "data" :
     {
     "forward-ddns" :
@@ -1036,7 +1035,7 @@
 #-----
 ,{
 "description" : "D2.forward-ddns.dhcp-ddns.dns-servers.ip-address invalid address ",
-"logic-error" : true,
+"logic-error" : "Dns Server : invalid IP address : bogus (<string>:1:74)",
 "data" :
     {
     "forward-ddns" :
@@ -1179,7 +1178,7 @@
 #------
 ,{
 "description" : "D2.reverse-ddns, duplicate domain",
-"logic-error" : true,
+"logic-error" : "Duplicate domain specified:2.0.192.in-addra.arpa. (<string>:1:211)",
 "data" :
     {
     "forward-ddns" : {},
@@ -1253,7 +1252,7 @@
 #-----
 ,{
 "description" : "D2.reverse-ddns.dhcp-ddns, blank name",
-"syntax-error" : "<string>:1.69: name cannot be blank",
+"syntax-error" : "<string>:1.69: Ddns domain name cannot be blank",
 "data" :
     {
     "forward-ddns" : {},
@@ -1273,7 +1272,7 @@
 #------ "D2.reverse-ddns.dhcp-ddns, key-name tests
 ,{
 "description" : "D2.reverse-ddns, no matching key name",
-"logic-error" : true,
+"logic-error" : "DdnsDomain : 2.0.192.in-addr.arpa. specifies an undefined key: no.such.key (<string>:1:126)",
 "data" :
     {
     "forward-ddns" : {},
@@ -1307,7 +1306,7 @@
 #----- D2.reverse-ddns.dhcp-ddns.dns-servers tests
 ,{
 "description" : "D2.reverse-ddns.dhcp-ddns.dns-servers, no servers",
-"logic-error" : true,
+"syntax-error" : "<string>:1.81: syntax error, unexpected ], expecting {",
 "data" :
     {
     "forward-ddns" : {},
@@ -1354,7 +1353,7 @@
 #-----
 ,{
 "description" : "D2.reverse-ddns.dhcp-ddns.dns-servers.hostname unsupported",
-"logic-error" : true,
+"syntax-error" : "<string>:1.92: hostname is not yet supported",
 "data" :
     {
     "forward-ddns" : {},
@@ -1429,7 +1428,7 @@
 #-----
 ,{
 "description" : "D2.reverse-ddns.dhcp-ddns.dns-servers.ip-address invalid value",
-"logic-error" : true,
+"logic-error" : "Dns Server : invalid IP address : bogus (<string>:1:96)",
 "data" :
     {
     "forward-ddns" : {},

+ 0 - 24
src/lib/process/testutils/d_test_stubs.cc

@@ -15,30 +15,6 @@ using namespace boost::asio;
 namespace isc {
 namespace process {
 
-const char* valid_d2_config = "{ "
-                        "\"ip-address\" : \"127.0.0.1\" , "
-                        "\"port\" : 5031, "
-                        "\"tsig-keys\": ["
-                        "{ \"name\": \"d2_key.tmark.org\" , "
-                        "   \"algorithm\": \"HMAC-MD5\" ,"
-                        "   \"secret\": \"LSWXnfkKZjdPJI5QxlpnfQ==\" "
-                        "} ],"
-                        "\"forward-ddns\" : {"
-                        "\"ddns-domains\": [ "
-                        "{ \"name\": \"tmark.org.\" , "
-                        "  \"key-name\": \"d2_key.tmark.org\" , "
-                        "  \"dns-servers\" : [ "
-                        "  { \"ip-address\": \"127.0.0.101\" } "
-                        "] } ] }, "
-                        "\"reverse-ddns\" : {"
-                        "\"ddns-domains\": [ "
-                        "{ \"name\": \" 0.168.192.in.addr.arpa.\" , "
-                        "  \"key-name\": \"d2_key.tmark.org\" , "
-                        "  \"dns-servers\" : [ "
-                        "  { \"ip-address\": \"127.0.0.101\" , "
-                        "    \"port\": 100 } ] } "
-                        "] } }";
-
 // Initialize the static failure flag.
 SimFailure::FailureType SimFailure::failure_type_ = SimFailure::ftNoFailure;
 

+ 0 - 9
src/lib/process/testutils/d_test_stubs.h

@@ -30,11 +30,6 @@ using namespace boost::posix_time;
 namespace isc {
 namespace process {
 
-/// @brief Provides a valid DHCP-DDNS configuration for testing basic
-/// parsing fundamentals.
-extern const char* valid_d2_config;
-
-
 /// @brief Class is used to set a globally accessible value that indicates
 /// a specific type of failure to simulate.  Test derivations of base classes
 /// can exercise error handling code paths by testing for specific SimFailure
@@ -893,10 +888,6 @@ private:
     asiolink::IntervalTimerPtr timer_;
 };
 
-/// @brief Defines a small but valid DHCP-DDNS compliant configuration for
-/// testing configuration parsing fundamentals.
-extern const char* valid_d2_config;
-
 }; // namespace isc::process
 }; // namespace isc