} 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);
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
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.
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.
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;
}
#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>
// *********************** 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,
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();
// *********************** 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,
// *********************** 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.
// *********************** 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);
// *********************** 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()) {
<< " (" << 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:
/// 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;
}
}
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
/// @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
/// 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,
///
/// 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(){};
/// @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:
};
/// 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(){};
/// @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
/// 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.
///
/// 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);
};
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
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 */
{
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;;
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.
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();
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);
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:
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:
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:
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:
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:
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:
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) {
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) {
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) {
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:
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:
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:
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:
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:
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:
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:
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:
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:
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:
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:
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:
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:
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:
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:
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:
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:
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:
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:
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.
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));
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));
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));
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);
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);
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_);
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_);
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:
{
/* %ok-for-header */
-#line 614 "d2_lexer.ll"
+#line 634 "d2_lexer.ll"
using namespace isc::dhcp;
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_);
}
}
%}
\"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:
\"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:
\"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:
\"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:
\"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:
\"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:
\"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:
\"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:
\"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:
{
switch (that.type_get ())
{
- case 50: // value
- case 77: // ncr_protocol_value
+ case 62: // value
+ case 89: // ncr_protocol_value
value.move< ElementPtr > (that.value);
break;
- case 44: // "boolean"
+ case 50: // "boolean"
value.move< bool > (that.value);
break;
- case 43: // "floating point"
+ case 49: // "floating point"
value.move< double > (that.value);
break;
- case 42: // "integer"
+ case 48: // "integer"
value.move< int64_t > (that.value);
break;
- case 41: // "constant string"
+ case 47: // "constant string"
value.move< std::string > (that.value);
break;
state = that.state;
switch (that.type_get ())
{
- case 50: // value
- case 77: // ncr_protocol_value
+ case 62: // value
+ case 89: // ncr_protocol_value
value.copy< ElementPtr > (that.value);
break;
- case 44: // "boolean"
+ case 50: // "boolean"
value.copy< bool > (that.value);
break;
- case 43: // "floating point"
+ case 49: // "floating point"
value.copy< double > (that.value);
break;
- case 42: // "integer"
+ case 48: // "integer"
value.copy< int64_t > (that.value);
break;
- case 41: // "constant string"
+ case 47: // "constant string"
value.copy< std::string > (that.value);
break;
<< yysym.location << ": ";
switch (yytype)
{
- case 41: // "constant string"
+ case 47: // "constant string"
-#line 98 "d2_parser.yy" // lalr1.cc:636
+#line 104 "d2_parser.yy" // lalr1.cc:636
{ yyoutput << yysym.value.template as< std::string > (); }
#line 354 "d2_parser.cc" // lalr1.cc:636
break;
- case 42: // "integer"
+ case 48: // "integer"
-#line 98 "d2_parser.yy" // lalr1.cc:636
+#line 104 "d2_parser.yy" // lalr1.cc:636
{ yyoutput << yysym.value.template as< int64_t > (); }
#line 361 "d2_parser.cc" // lalr1.cc:636
break;
- case 43: // "floating point"
+ case 49: // "floating point"
-#line 98 "d2_parser.yy" // lalr1.cc:636
+#line 104 "d2_parser.yy" // lalr1.cc:636
{ yyoutput << yysym.value.template as< double > (); }
#line 368 "d2_parser.cc" // lalr1.cc:636
break;
- case 44: // "boolean"
+ case 50: // "boolean"
-#line 98 "d2_parser.yy" // lalr1.cc:636
+#line 104 "d2_parser.yy" // lalr1.cc:636
{ yyoutput << yysym.value.template as< bool > (); }
#line 375 "d2_parser.cc" // lalr1.cc:636
break;
- case 50: // value
+ case 62: // value
-#line 98 "d2_parser.yy" // lalr1.cc:636
+#line 104 "d2_parser.yy" // lalr1.cc:636
{ yyoutput << yysym.value.template as< ElementPtr > (); }
#line 382 "d2_parser.cc" // lalr1.cc:636
break;
- case 77: // ncr_protocol_value
+ case 89: // ncr_protocol_value
-#line 98 "d2_parser.yy" // lalr1.cc:636
+#line 104 "d2_parser.yy" // lalr1.cc:636
{ yyoutput << yysym.value.template as< ElementPtr > (); }
#line 389 "d2_parser.cc" // lalr1.cc:636
break;
when using variants. */
switch (yyr1_[yyn])
{
- case 50: // value
- case 77: // ncr_protocol_value
+ case 62: // value
+ case 89: // ncr_protocol_value
yylhs.value.build< ElementPtr > ();
break;
- case 44: // "boolean"
+ case 50: // "boolean"
yylhs.value.build< bool > ();
break;
- case 43: // "floating point"
+ case 49: // "floating point"
yylhs.value.build< double > ();
break;
- case 42: // "integer"
+ case 48: // "integer"
yylhs.value.build< int64_t > ();
break;
- case 41: // "constant string"
+ case 47: // "constant string"
yylhs.value.build< std::string > ();
break;
switch (yyn)
{
case 2:
-#line 107 "d2_parser.yy" // lalr1.cc:859
+#line 113 "d2_parser.yy" // lalr1.cc:859
{ ctx.ctx_ = ctx.NO_KEYWORD; }
#line 630 "d2_parser.cc" // lalr1.cc:859
break;
case 4:
-#line 108 "d2_parser.yy" // lalr1.cc:859
+#line 114 "d2_parser.yy" // lalr1.cc:859
{ ctx.ctx_ = ctx.CONFIG; }
#line 636 "d2_parser.cc" // lalr1.cc:859
break;
case 6:
-#line 109 "d2_parser.yy" // lalr1.cc:859
+#line 115 "d2_parser.yy" // lalr1.cc:859
{ ctx.ctx_ = ctx.DHCPDDNS; }
#line 642 "d2_parser.cc" // lalr1.cc:859
break;
case 8:
-#line 117 "d2_parser.yy" // lalr1.cc:859
- { yylhs.value.as< ElementPtr > () = ElementPtr(new IntElement(yystack_[0].value.as< int64_t > (), ctx.loc2pos(yystack_[0].location))); }
+#line 116 "d2_parser.yy" // lalr1.cc:859
+ { ctx.ctx_ = ctx.TSIG_KEY; }
#line 648 "d2_parser.cc" // lalr1.cc:859
break;
- case 9:
-#line 118 "d2_parser.yy" // lalr1.cc:859
- { yylhs.value.as< ElementPtr > () = ElementPtr(new DoubleElement(yystack_[0].value.as< double > (), ctx.loc2pos(yystack_[0].location))); }
+ case 10:
+#line 117 "d2_parser.yy" // lalr1.cc:859
+ { ctx.ctx_ = ctx.TSIG_KEYS; }
#line 654 "d2_parser.cc" // lalr1.cc:859
break;
- case 10:
-#line 119 "d2_parser.yy" // lalr1.cc:859
- { yylhs.value.as< ElementPtr > () = ElementPtr(new BoolElement(yystack_[0].value.as< bool > (), ctx.loc2pos(yystack_[0].location))); }
+ case 12:
+#line 118 "d2_parser.yy" // lalr1.cc:859
+ { ctx.ctx_ = ctx.DDNS_DOMAIN; }
#line 660 "d2_parser.cc" // lalr1.cc:859
break;
- case 11:
-#line 120 "d2_parser.yy" // lalr1.cc:859
- { yylhs.value.as< ElementPtr > () = ElementPtr(new StringElement(yystack_[0].value.as< std::string > (), ctx.loc2pos(yystack_[0].location))); }
+ case 14:
+#line 119 "d2_parser.yy" // lalr1.cc:859
+ { ctx.ctx_ = ctx.DDNS_DOMAINS; }
#line 666 "d2_parser.cc" // lalr1.cc:859
break;
- case 12:
+ case 16:
+#line 120 "d2_parser.yy" // lalr1.cc:859
+ { ctx.ctx_ = ctx.DNS_SERVERS; }
+#line 672 "d2_parser.cc" // lalr1.cc:859
+ break;
+
+ case 18:
#line 121 "d2_parser.yy" // lalr1.cc:859
+ { ctx.ctx_ = ctx.DNS_SERVERS; }
+#line 678 "d2_parser.cc" // lalr1.cc:859
+ break;
+
+ case 20:
+#line 129 "d2_parser.yy" // lalr1.cc:859
+ { yylhs.value.as< ElementPtr > () = ElementPtr(new IntElement(yystack_[0].value.as< int64_t > (), ctx.loc2pos(yystack_[0].location))); }
+#line 684 "d2_parser.cc" // lalr1.cc:859
+ break;
+
+ case 21:
+#line 130 "d2_parser.yy" // lalr1.cc:859
+ { yylhs.value.as< ElementPtr > () = ElementPtr(new DoubleElement(yystack_[0].value.as< double > (), ctx.loc2pos(yystack_[0].location))); }
+#line 690 "d2_parser.cc" // lalr1.cc:859
+ break;
+
+ case 22:
+#line 131 "d2_parser.yy" // lalr1.cc:859
+ { yylhs.value.as< ElementPtr > () = ElementPtr(new BoolElement(yystack_[0].value.as< bool > (), ctx.loc2pos(yystack_[0].location))); }
+#line 696 "d2_parser.cc" // lalr1.cc:859
+ break;
+
+ case 23:
+#line 132 "d2_parser.yy" // lalr1.cc:859
+ { yylhs.value.as< ElementPtr > () = ElementPtr(new StringElement(yystack_[0].value.as< std::string > (), ctx.loc2pos(yystack_[0].location))); }
+#line 702 "d2_parser.cc" // lalr1.cc:859
+ break;
+
+ case 24:
+#line 133 "d2_parser.yy" // lalr1.cc:859
{ yylhs.value.as< ElementPtr > () = ElementPtr(new NullElement(ctx.loc2pos(yystack_[0].location))); }
-#line 672 "d2_parser.cc" // lalr1.cc:859
+#line 708 "d2_parser.cc" // lalr1.cc:859
break;
- case 13:
-#line 122 "d2_parser.yy" // lalr1.cc:859
+ case 25:
+#line 134 "d2_parser.yy" // lalr1.cc:859
{ yylhs.value.as< ElementPtr > () = ctx.stack_.back(); ctx.stack_.pop_back(); }
-#line 678 "d2_parser.cc" // lalr1.cc:859
+#line 714 "d2_parser.cc" // lalr1.cc:859
break;
- case 14:
-#line 123 "d2_parser.yy" // lalr1.cc:859
+ case 26:
+#line 135 "d2_parser.yy" // lalr1.cc:859
{ yylhs.value.as< ElementPtr > () = ctx.stack_.back(); ctx.stack_.pop_back(); }
-#line 684 "d2_parser.cc" // lalr1.cc:859
+#line 720 "d2_parser.cc" // lalr1.cc:859
break;
- case 15:
-#line 126 "d2_parser.yy" // lalr1.cc:859
+ case 27:
+#line 138 "d2_parser.yy" // lalr1.cc:859
{
// Push back the JSON value on the stack
ctx.stack_.push_back(yystack_[0].value.as< ElementPtr > ());
}
-#line 693 "d2_parser.cc" // lalr1.cc:859
+#line 729 "d2_parser.cc" // lalr1.cc:859
break;
- case 16:
-#line 131 "d2_parser.yy" // lalr1.cc:859
+ case 28:
+#line 143 "d2_parser.yy" // lalr1.cc:859
{
// This code is executed when we're about to start parsing
// the content of the map
ElementPtr m(new MapElement(ctx.loc2pos(yystack_[0].location)));
ctx.stack_.push_back(m);
}
-#line 704 "d2_parser.cc" // lalr1.cc:859
+#line 740 "d2_parser.cc" // lalr1.cc:859
break;
- case 17:
-#line 136 "d2_parser.yy" // lalr1.cc:859
+ case 29:
+#line 148 "d2_parser.yy" // lalr1.cc:859
{
// map parsing completed. If we ever want to do any wrap up
// (maybe some sanity checking), this would be the best place
// for it.
}
-#line 714 "d2_parser.cc" // lalr1.cc:859
+#line 750 "d2_parser.cc" // lalr1.cc:859
break;
- case 20:
-#line 147 "d2_parser.yy" // lalr1.cc:859
+ case 32:
+#line 159 "d2_parser.yy" // lalr1.cc:859
{
// map containing a single entry
ctx.stack_.back()->set(yystack_[2].value.as< std::string > (), yystack_[0].value.as< ElementPtr > ());
}
-#line 723 "d2_parser.cc" // lalr1.cc:859
+#line 759 "d2_parser.cc" // lalr1.cc:859
break;
- case 21:
-#line 151 "d2_parser.yy" // lalr1.cc:859
+ case 33:
+#line 163 "d2_parser.yy" // lalr1.cc:859
{
// map consisting of a shorter map followed by
// comma and string:value
ctx.stack_.back()->set(yystack_[2].value.as< std::string > (), yystack_[0].value.as< ElementPtr > ());
}
-#line 733 "d2_parser.cc" // lalr1.cc:859
+#line 769 "d2_parser.cc" // lalr1.cc:859
break;
- case 22:
-#line 158 "d2_parser.yy" // lalr1.cc:859
+ case 34:
+#line 170 "d2_parser.yy" // lalr1.cc:859
{
ElementPtr l(new ListElement(ctx.loc2pos(yystack_[0].location)));
ctx.stack_.push_back(l);
}
-#line 742 "d2_parser.cc" // lalr1.cc:859
+#line 778 "d2_parser.cc" // lalr1.cc:859
break;
- case 23:
-#line 161 "d2_parser.yy" // lalr1.cc:859
+ case 35:
+#line 173 "d2_parser.yy" // lalr1.cc:859
{
// list parsing complete. Put any sanity checking here
}
-#line 750 "d2_parser.cc" // lalr1.cc:859
+#line 786 "d2_parser.cc" // lalr1.cc:859
break;
- case 26:
-#line 169 "d2_parser.yy" // lalr1.cc:859
+ case 38:
+#line 181 "d2_parser.yy" // lalr1.cc:859
{
// List consisting of a single element.
ctx.stack_.back()->add(yystack_[0].value.as< ElementPtr > ());
}
-#line 759 "d2_parser.cc" // lalr1.cc:859
+#line 795 "d2_parser.cc" // lalr1.cc:859
break;
- case 27:
-#line 173 "d2_parser.yy" // lalr1.cc:859
+ case 39:
+#line 185 "d2_parser.yy" // lalr1.cc:859
{
// List ending with , and a value.
ctx.stack_.back()->add(yystack_[0].value.as< ElementPtr > ());
}
-#line 768 "d2_parser.cc" // lalr1.cc:859
+#line 804 "d2_parser.cc" // lalr1.cc:859
break;
- case 28:
-#line 184 "d2_parser.yy" // lalr1.cc:859
+ case 40:
+#line 196 "d2_parser.yy" // lalr1.cc:859
{
const std::string& where = ctx.contextName();
const std::string& keyword = yystack_[1].value.as< std::string > ();
error(yystack_[1].location,
"got unexpected keyword \"" + keyword + "\" in " + where + " map.");
}
-#line 779 "d2_parser.cc" // lalr1.cc:859
+#line 815 "d2_parser.cc" // lalr1.cc:859
break;
- case 29:
-#line 194 "d2_parser.yy" // lalr1.cc:859
+ case 41:
+#line 206 "d2_parser.yy" // lalr1.cc:859
{
// This code is executed when we're about to start parsing
// the content of the map
ElementPtr m(new MapElement(ctx.loc2pos(yystack_[0].location)));
ctx.stack_.push_back(m);
}
-#line 790 "d2_parser.cc" // lalr1.cc:859
+#line 826 "d2_parser.cc" // lalr1.cc:859
break;
- case 30:
-#line 199 "d2_parser.yy" // lalr1.cc:859
+ case 42:
+#line 211 "d2_parser.yy" // lalr1.cc:859
{
// map parsing completed. If we ever want to do any wrap up
// (maybe some sanity checking), this would be the best place
// for it.
}
-#line 800 "d2_parser.cc" // lalr1.cc:859
+#line 836 "d2_parser.cc" // lalr1.cc:859
break;
- case 38:
-#line 220 "d2_parser.yy" // lalr1.cc:859
+ case 50:
+#line 232 "d2_parser.yy" // lalr1.cc:859
{
ElementPtr m(new MapElement(ctx.loc2pos(yystack_[0].location)));
ctx.stack_.back()->set("DhcpDdns", m);
ctx.stack_.push_back(m);
ctx.enter(ctx.DHCPDDNS);
}
-#line 811 "d2_parser.cc" // lalr1.cc:859
+#line 847 "d2_parser.cc" // lalr1.cc:859
break;
- case 39:
-#line 225 "d2_parser.yy" // lalr1.cc:859
+ case 51:
+#line 237 "d2_parser.yy" // lalr1.cc:859
{
ctx.stack_.pop_back();
ctx.leave();
}
-#line 820 "d2_parser.cc" // lalr1.cc:859
+#line 856 "d2_parser.cc" // lalr1.cc:859
break;
- case 40:
-#line 230 "d2_parser.yy" // lalr1.cc:859
+ case 52:
+#line 242 "d2_parser.yy" // lalr1.cc:859
{
// Parse the dhcpddns map
ElementPtr m(new MapElement(ctx.loc2pos(yystack_[0].location)));
ctx.stack_.push_back(m);
}
-#line 830 "d2_parser.cc" // lalr1.cc:859
+#line 866 "d2_parser.cc" // lalr1.cc:859
break;
- case 41:
-#line 234 "d2_parser.yy" // lalr1.cc:859
+ case 53:
+#line 246 "d2_parser.yy" // lalr1.cc:859
{
// parsing completed
}
-#line 838 "d2_parser.cc" // lalr1.cc:859
+#line 874 "d2_parser.cc" // lalr1.cc:859
break;
- case 53:
-#line 253 "d2_parser.yy" // lalr1.cc:859
+ case 65:
+#line 265 "d2_parser.yy" // lalr1.cc:859
{
ctx.enter(ctx.NO_KEYWORD);
}
-#line 846 "d2_parser.cc" // lalr1.cc:859
+#line 882 "d2_parser.cc" // lalr1.cc:859
break;
- case 54:
-#line 255 "d2_parser.yy" // lalr1.cc:859
+ case 66:
+#line 267 "d2_parser.yy" // lalr1.cc:859
{
ElementPtr s(new StringElement(yystack_[0].value.as< std::string > (), ctx.loc2pos(yystack_[0].location)));
ctx.stack_.back()->set("ip-address", s);
ctx.leave();
}
-#line 856 "d2_parser.cc" // lalr1.cc:859
+#line 892 "d2_parser.cc" // lalr1.cc:859
break;
- case 55:
-#line 261 "d2_parser.yy" // lalr1.cc:859
+ case 67:
+#line 273 "d2_parser.yy" // lalr1.cc:859
{
if (yystack_[0].value.as< int64_t > () <= 0) {
error(yystack_[0].location, "port must be greater than zero");
- }
+ }
ElementPtr i(new IntElement(yystack_[0].value.as< int64_t > (), ctx.loc2pos(yystack_[0].location)));
ctx.stack_.back()->set("port", i);
}
-#line 868 "d2_parser.cc" // lalr1.cc:859
+#line 904 "d2_parser.cc" // lalr1.cc:859
break;
- case 56:
-#line 269 "d2_parser.yy" // lalr1.cc:859
+ case 68:
+#line 281 "d2_parser.yy" // lalr1.cc:859
{
if (yystack_[0].value.as< int64_t > () <= 0) {
error(yystack_[0].location, "dns-server-timeout must be greater than zero");
- } else {
+ } else {
ElementPtr i(new IntElement(yystack_[0].value.as< int64_t > (), ctx.loc2pos(yystack_[0].location)));
ctx.stack_.back()->set("dns-server-timeout", i);
}
}
-#line 881 "d2_parser.cc" // lalr1.cc:859
+#line 917 "d2_parser.cc" // lalr1.cc:859
break;
- case 57:
-#line 278 "d2_parser.yy" // lalr1.cc:859
+ case 69:
+#line 290 "d2_parser.yy" // lalr1.cc:859
{
ctx.enter(ctx.NCR_PROTOCOL);
}
-#line 889 "d2_parser.cc" // lalr1.cc:859
+#line 925 "d2_parser.cc" // lalr1.cc:859
break;
- case 58:
-#line 280 "d2_parser.yy" // lalr1.cc:859
+ case 70:
+#line 292 "d2_parser.yy" // lalr1.cc:859
{
ctx.stack_.back()->set("ncr-protocol", yystack_[0].value.as< ElementPtr > ());
ctx.leave();
}
-#line 898 "d2_parser.cc" // lalr1.cc:859
+#line 934 "d2_parser.cc" // lalr1.cc:859
break;
- case 59:
-#line 286 "d2_parser.yy" // lalr1.cc:859
+ case 71:
+#line 298 "d2_parser.yy" // lalr1.cc:859
{ yylhs.value.as< ElementPtr > () = ElementPtr(new StringElement("UDP", ctx.loc2pos(yystack_[0].location))); }
-#line 904 "d2_parser.cc" // lalr1.cc:859
+#line 940 "d2_parser.cc" // lalr1.cc:859
break;
- case 60:
-#line 287 "d2_parser.yy" // lalr1.cc:859
+ case 72:
+#line 299 "d2_parser.yy" // lalr1.cc:859
{ yylhs.value.as< ElementPtr > () = ElementPtr(new StringElement("TCP", ctx.loc2pos(yystack_[0].location))); }
-#line 910 "d2_parser.cc" // lalr1.cc:859
+#line 946 "d2_parser.cc" // lalr1.cc:859
break;
- case 61:
-#line 290 "d2_parser.yy" // lalr1.cc:859
+ case 73:
+#line 302 "d2_parser.yy" // lalr1.cc:859
{
ctx.enter(ctx.NCR_FORMAT);
}
-#line 918 "d2_parser.cc" // lalr1.cc:859
+#line 954 "d2_parser.cc" // lalr1.cc:859
break;
- case 62:
-#line 292 "d2_parser.yy" // lalr1.cc:859
+ case 74:
+#line 304 "d2_parser.yy" // lalr1.cc:859
{
ElementPtr json(new StringElement("JSON", ctx.loc2pos(yystack_[0].location)));
ctx.stack_.back()->set("ncr-format", json);
ctx.leave();
}
-#line 928 "d2_parser.cc" // lalr1.cc:859
+#line 964 "d2_parser.cc" // lalr1.cc:859
break;
- case 63:
-#line 298 "d2_parser.yy" // lalr1.cc:859
+ case 75:
+#line 310 "d2_parser.yy" // lalr1.cc:859
{
ElementPtr m(new MapElement(ctx.loc2pos(yystack_[0].location)));
ctx.stack_.back()->set("forward-ddns", m);
ctx.stack_.push_back(m);
ctx.enter(ctx.FORWARD_DDNS);
}
-#line 939 "d2_parser.cc" // lalr1.cc:859
+#line 975 "d2_parser.cc" // lalr1.cc:859
break;
- case 64:
-#line 303 "d2_parser.yy" // lalr1.cc:859
+ case 76:
+#line 315 "d2_parser.yy" // lalr1.cc:859
{
ctx.stack_.pop_back();
ctx.leave();
}
-#line 948 "d2_parser.cc" // lalr1.cc:859
+#line 984 "d2_parser.cc" // lalr1.cc:859
break;
- case 65:
-#line 308 "d2_parser.yy" // lalr1.cc:859
+ case 77:
+#line 320 "d2_parser.yy" // lalr1.cc:859
{
ElementPtr m(new MapElement(ctx.loc2pos(yystack_[0].location)));
ctx.stack_.back()->set("reverse-ddns", m);
ctx.stack_.push_back(m);
ctx.enter(ctx.REVERSE_DDNS);
}
-#line 959 "d2_parser.cc" // lalr1.cc:859
+#line 995 "d2_parser.cc" // lalr1.cc:859
break;
- case 66:
-#line 313 "d2_parser.yy" // lalr1.cc:859
+ case 78:
+#line 325 "d2_parser.yy" // lalr1.cc:859
{
ctx.stack_.pop_back();
ctx.leave();
}
-#line 968 "d2_parser.cc" // lalr1.cc:859
+#line 1004 "d2_parser.cc" // lalr1.cc:859
break;
- case 73:
-#line 333 "d2_parser.yy" // lalr1.cc:859
+ case 85:
+#line 344 "d2_parser.yy" // lalr1.cc:859
{
ElementPtr l(new ListElement(ctx.loc2pos(yystack_[0].location)));
ctx.stack_.back()->set("ddns-domains", l);
ctx.stack_.push_back(l);
ctx.enter(ctx.DDNS_DOMAINS);
}
-#line 979 "d2_parser.cc" // lalr1.cc:859
+#line 1015 "d2_parser.cc" // lalr1.cc:859
break;
- case 74:
-#line 338 "d2_parser.yy" // lalr1.cc:859
+ case 86:
+#line 349 "d2_parser.yy" // lalr1.cc:859
{
ctx.stack_.pop_back();
ctx.leave();
}
-#line 988 "d2_parser.cc" // lalr1.cc:859
+#line 1024 "d2_parser.cc" // lalr1.cc:859
break;
- case 79:
-#line 351 "d2_parser.yy" // lalr1.cc:859
+ case 87:
+#line 354 "d2_parser.yy" // lalr1.cc:859
+ {
+ ElementPtr l(new ListElement(ctx.loc2pos(yystack_[0].location)));
+ ctx.stack_.push_back(l);
+}
+#line 1033 "d2_parser.cc" // lalr1.cc:859
+ break;
+
+ case 88:
+#line 357 "d2_parser.yy" // lalr1.cc:859
+ {
+ // parsing completed
+}
+#line 1041 "d2_parser.cc" // lalr1.cc:859
+ break;
+
+ case 93:
+#line 369 "d2_parser.yy" // lalr1.cc:859
{
ElementPtr m(new MapElement(ctx.loc2pos(yystack_[0].location)));
ctx.stack_.back()->add(m);
ctx.stack_.push_back(m);
}
-#line 998 "d2_parser.cc" // lalr1.cc:859
+#line 1051 "d2_parser.cc" // lalr1.cc:859
break;
- case 80:
-#line 355 "d2_parser.yy" // lalr1.cc:859
+ case 94:
+#line 373 "d2_parser.yy" // lalr1.cc:859
{
ctx.stack_.pop_back();
}
-#line 1006 "d2_parser.cc" // lalr1.cc:859
+#line 1059 "d2_parser.cc" // lalr1.cc:859
break;
- case 87:
-#line 370 "d2_parser.yy" // lalr1.cc:859
+ case 95:
+#line 377 "d2_parser.yy" // lalr1.cc:859
+ {
+ ElementPtr m(new MapElement(ctx.loc2pos(yystack_[0].location)));
+ ctx.stack_.push_back(m);
+}
+#line 1068 "d2_parser.cc" // lalr1.cc:859
+ break;
+
+ case 96:
+#line 380 "d2_parser.yy" // lalr1.cc:859
+ {
+ // parsing completed
+}
+#line 1076 "d2_parser.cc" // lalr1.cc:859
+ break;
+
+ case 103:
+#line 395 "d2_parser.yy" // lalr1.cc:859
{
ctx.enter(ctx.NO_KEYWORD);
}
-#line 1014 "d2_parser.cc" // lalr1.cc:859
+#line 1084 "d2_parser.cc" // lalr1.cc:859
break;
- case 88:
-#line 372 "d2_parser.yy" // lalr1.cc:859
+ case 104:
+#line 397 "d2_parser.yy" // lalr1.cc:859
{
if (yystack_[0].value.as< std::string > () == "") {
- error(yystack_[1].location, "name cannot be blank");
- }
+ error(yystack_[1].location, "Ddns domain name cannot be blank");
+ }
ElementPtr elem(new StringElement(yystack_[0].value.as< std::string > (), ctx.loc2pos(yystack_[0].location)));
ElementPtr name(new StringElement(yystack_[0].value.as< std::string > (), ctx.loc2pos(yystack_[0].location)));
ctx.stack_.back()->set("name", name);
ctx.leave();
}
-#line 1028 "d2_parser.cc" // lalr1.cc:859
+#line 1098 "d2_parser.cc" // lalr1.cc:859
break;
- case 89:
-#line 382 "d2_parser.yy" // lalr1.cc:859
+ case 105:
+#line 407 "d2_parser.yy" // lalr1.cc:859
{
ctx.enter(ctx.NO_KEYWORD);
}
-#line 1036 "d2_parser.cc" // lalr1.cc:859
+#line 1106 "d2_parser.cc" // lalr1.cc:859
break;
- case 90:
-#line 384 "d2_parser.yy" // lalr1.cc:859
+ case 106:
+#line 409 "d2_parser.yy" // lalr1.cc:859
{
- if (yystack_[0].value.as< std::string > () == "") {
- error(yystack_[1].location, "key-name cannot be blank");
- }
ElementPtr elem(new StringElement(yystack_[0].value.as< std::string > (), ctx.loc2pos(yystack_[0].location)));
ElementPtr name(new StringElement(yystack_[0].value.as< std::string > (), ctx.loc2pos(yystack_[0].location)));
ctx.stack_.back()->set("key-name", name);
ctx.leave();
}
-#line 1050 "d2_parser.cc" // lalr1.cc:859
+#line 1117 "d2_parser.cc" // lalr1.cc:859
break;
- case 91:
-#line 397 "d2_parser.yy" // lalr1.cc:859
+ case 107:
+#line 419 "d2_parser.yy" // lalr1.cc:859
{
ElementPtr l(new ListElement(ctx.loc2pos(yystack_[0].location)));
ctx.stack_.back()->set("dns-servers", l);
ctx.stack_.push_back(l);
ctx.enter(ctx.DNS_SERVERS);
}
-#line 1061 "d2_parser.cc" // lalr1.cc:859
+#line 1128 "d2_parser.cc" // lalr1.cc:859
break;
- case 92:
-#line 402 "d2_parser.yy" // lalr1.cc:859
+ case 108:
+#line 424 "d2_parser.yy" // lalr1.cc:859
{
ctx.stack_.pop_back();
ctx.leave();
}
-#line 1070 "d2_parser.cc" // lalr1.cc:859
+#line 1137 "d2_parser.cc" // lalr1.cc:859
+ break;
+
+ case 109:
+#line 429 "d2_parser.yy" // lalr1.cc:859
+ {
+ ElementPtr l(new ListElement(ctx.loc2pos(yystack_[0].location)));
+ ctx.stack_.push_back(l);
+}
+#line 1146 "d2_parser.cc" // lalr1.cc:859
+ break;
+
+ case 110:
+#line 432 "d2_parser.yy" // lalr1.cc:859
+ {
+ // parsing completed
+}
+#line 1154 "d2_parser.cc" // lalr1.cc:859
break;
- case 97:
-#line 415 "d2_parser.yy" // lalr1.cc:859
+ case 113:
+#line 440 "d2_parser.yy" // lalr1.cc:859
{
ElementPtr m(new MapElement(ctx.loc2pos(yystack_[0].location)));
ctx.stack_.back()->add(m);
ctx.stack_.push_back(m);
}
-#line 1080 "d2_parser.cc" // lalr1.cc:859
+#line 1164 "d2_parser.cc" // lalr1.cc:859
break;
- case 98:
-#line 419 "d2_parser.yy" // lalr1.cc:859
+ case 114:
+#line 444 "d2_parser.yy" // lalr1.cc:859
{
ctx.stack_.pop_back();
}
-#line 1088 "d2_parser.cc" // lalr1.cc:859
+#line 1172 "d2_parser.cc" // lalr1.cc:859
break;
- case 105:
-#line 433 "d2_parser.yy" // lalr1.cc:859
+ case 115:
+#line 448 "d2_parser.yy" // lalr1.cc:859
+ {
+ ElementPtr m(new MapElement(ctx.loc2pos(yystack_[0].location)));
+ ctx.stack_.push_back(m);
+}
+#line 1181 "d2_parser.cc" // lalr1.cc:859
+ break;
+
+ case 116:
+#line 451 "d2_parser.yy" // lalr1.cc:859
+ {
+ // parsing completed
+}
+#line 1189 "d2_parser.cc" // lalr1.cc:859
+ break;
+
+ case 123:
+#line 465 "d2_parser.yy" // lalr1.cc:859
{
ctx.enter(ctx.NO_KEYWORD);
}
-#line 1096 "d2_parser.cc" // lalr1.cc:859
+#line 1197 "d2_parser.cc" // lalr1.cc:859
break;
- case 106:
-#line 435 "d2_parser.yy" // lalr1.cc:859
+ case 124:
+#line 467 "d2_parser.yy" // lalr1.cc:859
{
- if (yystack_[0].value.as< std::string > () == "") {
- error(yystack_[1].location, "hostname cannot be blank");
- }
+ if (yystack_[0].value.as< std::string > () != "") {
+ error(yystack_[1].location, "hostname is not yet supported");
+ }
ElementPtr elem(new StringElement(yystack_[0].value.as< std::string > (), ctx.loc2pos(yystack_[0].location)));
ElementPtr name(new StringElement(yystack_[0].value.as< std::string > (), ctx.loc2pos(yystack_[0].location)));
ctx.stack_.back()->set("hostname", name);
ctx.leave();
}
-#line 1110 "d2_parser.cc" // lalr1.cc:859
+#line 1211 "d2_parser.cc" // lalr1.cc:859
break;
- case 107:
-#line 445 "d2_parser.yy" // lalr1.cc:859
+ case 125:
+#line 477 "d2_parser.yy" // lalr1.cc:859
{
ctx.enter(ctx.NO_KEYWORD);
}
-#line 1118 "d2_parser.cc" // lalr1.cc:859
+#line 1219 "d2_parser.cc" // lalr1.cc:859
break;
- case 108:
-#line 447 "d2_parser.yy" // lalr1.cc:859
+ case 126:
+#line 479 "d2_parser.yy" // lalr1.cc:859
{
ElementPtr s(new StringElement(yystack_[0].value.as< std::string > (), ctx.loc2pos(yystack_[0].location)));
ctx.stack_.back()->set("ip-address", s);
ctx.leave();
}
-#line 1128 "d2_parser.cc" // lalr1.cc:859
+#line 1229 "d2_parser.cc" // lalr1.cc:859
break;
- case 109:
-#line 453 "d2_parser.yy" // lalr1.cc:859
+ case 127:
+#line 485 "d2_parser.yy" // lalr1.cc:859
{
if (yystack_[0].value.as< int64_t > () <= 0) {
error(yystack_[0].location, "port must be greater than zero");
- }
+ }
ElementPtr i(new IntElement(yystack_[0].value.as< int64_t > (), ctx.loc2pos(yystack_[0].location)));
ctx.stack_.back()->set("port", i);
}
-#line 1140 "d2_parser.cc" // lalr1.cc:859
+#line 1241 "d2_parser.cc" // lalr1.cc:859
break;
- case 110:
-#line 467 "d2_parser.yy" // lalr1.cc:859
+ case 128:
+#line 499 "d2_parser.yy" // lalr1.cc:859
{
ElementPtr l(new ListElement(ctx.loc2pos(yystack_[0].location)));
ctx.stack_.back()->set("tsig-keys", l);
ctx.stack_.push_back(l);
ctx.enter(ctx.TSIG_KEYS);
}
-#line 1151 "d2_parser.cc" // lalr1.cc:859
+#line 1252 "d2_parser.cc" // lalr1.cc:859
break;
- case 111:
-#line 472 "d2_parser.yy" // lalr1.cc:859
+ case 129:
+#line 504 "d2_parser.yy" // lalr1.cc:859
{
ctx.stack_.pop_back();
ctx.leave();
}
-#line 1160 "d2_parser.cc" // lalr1.cc:859
+#line 1261 "d2_parser.cc" // lalr1.cc:859
break;
- case 116:
-#line 485 "d2_parser.yy" // lalr1.cc:859
+ case 130:
+#line 509 "d2_parser.yy" // lalr1.cc:859
+ {
+ ElementPtr l(new ListElement(ctx.loc2pos(yystack_[0].location)));
+ ctx.stack_.push_back(l);
+}
+#line 1270 "d2_parser.cc" // lalr1.cc:859
+ break;
+
+ case 131:
+#line 512 "d2_parser.yy" // lalr1.cc:859
+ {
+ // parsing completed
+}
+#line 1278 "d2_parser.cc" // lalr1.cc:859
+ break;
+
+ case 136:
+#line 524 "d2_parser.yy" // lalr1.cc:859
{
ElementPtr m(new MapElement(ctx.loc2pos(yystack_[0].location)));
ctx.stack_.back()->add(m);
ctx.stack_.push_back(m);
}
-#line 1170 "d2_parser.cc" // lalr1.cc:859
+#line 1288 "d2_parser.cc" // lalr1.cc:859
break;
- case 117:
-#line 489 "d2_parser.yy" // lalr1.cc:859
+ case 137:
+#line 528 "d2_parser.yy" // lalr1.cc:859
{
ctx.stack_.pop_back();
}
-#line 1178 "d2_parser.cc" // lalr1.cc:859
+#line 1296 "d2_parser.cc" // lalr1.cc:859
break;
- case 125:
-#line 504 "d2_parser.yy" // lalr1.cc:859
+ case 138:
+#line 532 "d2_parser.yy" // lalr1.cc:859
+ {
+ // Parse tsig key list entry map
+ ElementPtr m(new MapElement(ctx.loc2pos(yystack_[0].location)));
+ ctx.stack_.push_back(m);
+}
+#line 1306 "d2_parser.cc" // lalr1.cc:859
+ break;
+
+ case 139:
+#line 536 "d2_parser.yy" // lalr1.cc:859
+ {
+ // parsing completed
+}
+#line 1314 "d2_parser.cc" // lalr1.cc:859
+ break;
+
+ case 147:
+#line 552 "d2_parser.yy" // lalr1.cc:859
{
ctx.enter(ctx.NO_KEYWORD);
}
-#line 1186 "d2_parser.cc" // lalr1.cc:859
+#line 1322 "d2_parser.cc" // lalr1.cc:859
break;
- case 126:
-#line 506 "d2_parser.yy" // lalr1.cc:859
+ case 148:
+#line 554 "d2_parser.yy" // lalr1.cc:859
{
if (yystack_[0].value.as< std::string > () == "") {
- error(yystack_[1].location, "name cannot be blank");
- }
+ error(yystack_[1].location, "TSIG key name cannot be blank");
+ }
ElementPtr elem(new StringElement(yystack_[0].value.as< std::string > (), ctx.loc2pos(yystack_[0].location)));
ElementPtr name(new StringElement(yystack_[0].value.as< std::string > (), ctx.loc2pos(yystack_[0].location)));
ctx.stack_.back()->set("name", name);
ctx.leave();
}
-#line 1200 "d2_parser.cc" // lalr1.cc:859
+#line 1336 "d2_parser.cc" // lalr1.cc:859
break;
- case 127:
-#line 516 "d2_parser.yy" // lalr1.cc:859
+ case 149:
+#line 564 "d2_parser.yy" // lalr1.cc:859
{
ctx.enter(ctx.NO_KEYWORD);
}
-#line 1208 "d2_parser.cc" // lalr1.cc:859
+#line 1344 "d2_parser.cc" // lalr1.cc:859
break;
- case 128:
-#line 518 "d2_parser.yy" // lalr1.cc:859
+ case 150:
+#line 566 "d2_parser.yy" // lalr1.cc:859
{
if (yystack_[0].value.as< std::string > () == "") {
- error(yystack_[1].location, "algorithm cannot be blank");
- }
+ error(yystack_[1].location, "TSIG key algorithm cannot be blank");
+ }
ElementPtr elem(new StringElement(yystack_[0].value.as< std::string > (), ctx.loc2pos(yystack_[0].location)));
ctx.stack_.back()->set("algorithm", elem);
ctx.leave();
}
-#line 1221 "d2_parser.cc" // lalr1.cc:859
+#line 1357 "d2_parser.cc" // lalr1.cc:859
break;
- case 129:
-#line 527 "d2_parser.yy" // lalr1.cc:859
+ case 151:
+#line 575 "d2_parser.yy" // lalr1.cc:859
{
if (yystack_[0].value.as< int64_t > () < 0 || (yystack_[0].value.as< int64_t > () > 0 && (yystack_[0].value.as< int64_t > () % 8 != 0))) {
- error(yystack_[0].location, "digest-bits must either be zero or a positive, multiple of eight");
- }
+ error(yystack_[0].location, "TSIG key digest-bits must either be zero or a positive, multiple of eight");
+ }
ElementPtr elem(new IntElement(yystack_[0].value.as< int64_t > (), ctx.loc2pos(yystack_[0].location)));
ctx.stack_.back()->set("digest-bits", elem);
}
-#line 1233 "d2_parser.cc" // lalr1.cc:859
+#line 1369 "d2_parser.cc" // lalr1.cc:859
break;
- case 130:
-#line 535 "d2_parser.yy" // lalr1.cc:859
+ case 152:
+#line 583 "d2_parser.yy" // lalr1.cc:859
{
ctx.enter(ctx.NO_KEYWORD);
}
-#line 1241 "d2_parser.cc" // lalr1.cc:859
+#line 1377 "d2_parser.cc" // lalr1.cc:859
break;
- case 131:
-#line 537 "d2_parser.yy" // lalr1.cc:859
+ case 153:
+#line 585 "d2_parser.yy" // lalr1.cc:859
{
if (yystack_[0].value.as< std::string > () == "") {
- error(yystack_[1].location, "secret cannot be blank");
- }
+ error(yystack_[1].location, "TSIG key secret cannot be blank");
+ }
ElementPtr elem(new StringElement(yystack_[0].value.as< std::string > (), ctx.loc2pos(yystack_[0].location)));
ctx.stack_.back()->set("secret", elem);
ctx.leave();
}
-#line 1254 "d2_parser.cc" // lalr1.cc:859
+#line 1390 "d2_parser.cc" // lalr1.cc:859
break;
- case 132:
-#line 550 "d2_parser.yy" // lalr1.cc:859
+ case 154:
+#line 598 "d2_parser.yy" // lalr1.cc:859
{
ctx.enter(ctx.NO_KEYWORD);
}
-#line 1262 "d2_parser.cc" // lalr1.cc:859
+#line 1398 "d2_parser.cc" // lalr1.cc:859
break;
- case 133:
-#line 552 "d2_parser.yy" // lalr1.cc:859
+ case 155:
+#line 600 "d2_parser.yy" // lalr1.cc:859
{
ctx.stack_.back()->set("Dhcp6", yystack_[0].value.as< ElementPtr > ());
ctx.leave();
}
-#line 1271 "d2_parser.cc" // lalr1.cc:859
+#line 1407 "d2_parser.cc" // lalr1.cc:859
break;
- case 134:
-#line 557 "d2_parser.yy" // lalr1.cc:859
+ case 156:
+#line 605 "d2_parser.yy" // lalr1.cc:859
{
ctx.enter(ctx.NO_KEYWORD);
}
-#line 1279 "d2_parser.cc" // lalr1.cc:859
+#line 1415 "d2_parser.cc" // lalr1.cc:859
break;
- case 135:
-#line 559 "d2_parser.yy" // lalr1.cc:859
+ case 157:
+#line 607 "d2_parser.yy" // lalr1.cc:859
{
ctx.stack_.back()->set("Dhcp4", yystack_[0].value.as< ElementPtr > ());
ctx.leave();
}
-#line 1288 "d2_parser.cc" // lalr1.cc:859
+#line 1424 "d2_parser.cc" // lalr1.cc:859
break;
- case 136:
-#line 569 "d2_parser.yy" // lalr1.cc:859
+ case 158:
+#line 617 "d2_parser.yy" // lalr1.cc:859
{
ElementPtr m(new MapElement(ctx.loc2pos(yystack_[0].location)));
ctx.stack_.back()->set("Logging", m);
ctx.stack_.push_back(m);
ctx.enter(ctx.LOGGING);
}
-#line 1299 "d2_parser.cc" // lalr1.cc:859
+#line 1435 "d2_parser.cc" // lalr1.cc:859
break;
- case 137:
-#line 574 "d2_parser.yy" // lalr1.cc:859
+ case 159:
+#line 622 "d2_parser.yy" // lalr1.cc:859
{
ctx.stack_.pop_back();
ctx.leave();
}
-#line 1308 "d2_parser.cc" // lalr1.cc:859
+#line 1444 "d2_parser.cc" // lalr1.cc:859
break;
- case 141:
-#line 591 "d2_parser.yy" // lalr1.cc:859
+ case 163:
+#line 639 "d2_parser.yy" // lalr1.cc:859
{
ElementPtr l(new ListElement(ctx.loc2pos(yystack_[0].location)));
ctx.stack_.back()->set("loggers", l);
ctx.stack_.push_back(l);
ctx.enter(ctx.LOGGERS);
}
-#line 1319 "d2_parser.cc" // lalr1.cc:859
+#line 1455 "d2_parser.cc" // lalr1.cc:859
break;
- case 142:
-#line 596 "d2_parser.yy" // lalr1.cc:859
+ case 164:
+#line 644 "d2_parser.yy" // lalr1.cc:859
{
ctx.stack_.pop_back();
ctx.leave();
}
-#line 1328 "d2_parser.cc" // lalr1.cc:859
+#line 1464 "d2_parser.cc" // lalr1.cc:859
break;
- case 145:
-#line 608 "d2_parser.yy" // lalr1.cc:859
+ case 167:
+#line 656 "d2_parser.yy" // lalr1.cc:859
{
ElementPtr l(new MapElement(ctx.loc2pos(yystack_[0].location)));
ctx.stack_.back()->add(l);
ctx.stack_.push_back(l);
}
-#line 1338 "d2_parser.cc" // lalr1.cc:859
+#line 1474 "d2_parser.cc" // lalr1.cc:859
break;
- case 146:
-#line 612 "d2_parser.yy" // lalr1.cc:859
+ case 168:
+#line 660 "d2_parser.yy" // lalr1.cc:859
{
ctx.stack_.pop_back();
}
-#line 1346 "d2_parser.cc" // lalr1.cc:859
+#line 1482 "d2_parser.cc" // lalr1.cc:859
break;
- case 154:
-#line 627 "d2_parser.yy" // lalr1.cc:859
+ case 176:
+#line 675 "d2_parser.yy" // lalr1.cc:859
{
ctx.enter(ctx.NO_KEYWORD);
}
-#line 1354 "d2_parser.cc" // lalr1.cc:859
+#line 1490 "d2_parser.cc" // lalr1.cc:859
break;
- case 155:
-#line 629 "d2_parser.yy" // lalr1.cc:859
+ case 177:
+#line 677 "d2_parser.yy" // lalr1.cc:859
{
ElementPtr name(new StringElement(yystack_[0].value.as< std::string > (), ctx.loc2pos(yystack_[0].location)));
ctx.stack_.back()->set("name", name);
ctx.leave();
}
-#line 1364 "d2_parser.cc" // lalr1.cc:859
+#line 1500 "d2_parser.cc" // lalr1.cc:859
break;
- case 156:
-#line 635 "d2_parser.yy" // lalr1.cc:859
+ case 178:
+#line 683 "d2_parser.yy" // lalr1.cc:859
{
ElementPtr dl(new IntElement(yystack_[0].value.as< int64_t > (), ctx.loc2pos(yystack_[0].location)));
ctx.stack_.back()->set("debuglevel", dl);
}
-#line 1373 "d2_parser.cc" // lalr1.cc:859
+#line 1509 "d2_parser.cc" // lalr1.cc:859
break;
- case 157:
-#line 639 "d2_parser.yy" // lalr1.cc:859
+ case 179:
+#line 687 "d2_parser.yy" // lalr1.cc:859
{
ctx.enter(ctx.NO_KEYWORD);
}
-#line 1381 "d2_parser.cc" // lalr1.cc:859
+#line 1517 "d2_parser.cc" // lalr1.cc:859
break;
- case 158:
-#line 641 "d2_parser.yy" // lalr1.cc:859
+ case 180:
+#line 689 "d2_parser.yy" // lalr1.cc:859
{
ElementPtr sev(new StringElement(yystack_[0].value.as< std::string > (), ctx.loc2pos(yystack_[0].location)));
ctx.stack_.back()->set("severity", sev);
ctx.leave();
}
-#line 1391 "d2_parser.cc" // lalr1.cc:859
+#line 1527 "d2_parser.cc" // lalr1.cc:859
break;
- case 159:
-#line 647 "d2_parser.yy" // lalr1.cc:859
+ case 181:
+#line 695 "d2_parser.yy" // lalr1.cc:859
{
ElementPtr l(new ListElement(ctx.loc2pos(yystack_[0].location)));
ctx.stack_.back()->set("output_options", l);
ctx.stack_.push_back(l);
ctx.enter(ctx.OUTPUT_OPTIONS);
}
-#line 1402 "d2_parser.cc" // lalr1.cc:859
+#line 1538 "d2_parser.cc" // lalr1.cc:859
break;
- case 160:
-#line 652 "d2_parser.yy" // lalr1.cc:859
+ case 182:
+#line 700 "d2_parser.yy" // lalr1.cc:859
{
ctx.stack_.pop_back();
ctx.leave();
}
-#line 1411 "d2_parser.cc" // lalr1.cc:859
+#line 1547 "d2_parser.cc" // lalr1.cc:859
break;
- case 163:
-#line 661 "d2_parser.yy" // lalr1.cc:859
+ case 185:
+#line 709 "d2_parser.yy" // lalr1.cc:859
{
ElementPtr m(new MapElement(ctx.loc2pos(yystack_[0].location)));
ctx.stack_.back()->add(m);
ctx.stack_.push_back(m);
}
-#line 1421 "d2_parser.cc" // lalr1.cc:859
+#line 1557 "d2_parser.cc" // lalr1.cc:859
break;
- case 164:
-#line 665 "d2_parser.yy" // lalr1.cc:859
+ case 186:
+#line 713 "d2_parser.yy" // lalr1.cc:859
{
ctx.stack_.pop_back();
}
-#line 1429 "d2_parser.cc" // lalr1.cc:859
+#line 1565 "d2_parser.cc" // lalr1.cc:859
break;
- case 167:
-#line 673 "d2_parser.yy" // lalr1.cc:859
+ case 189:
+#line 721 "d2_parser.yy" // lalr1.cc:859
{
ctx.enter(ctx.NO_KEYWORD);
}
-#line 1437 "d2_parser.cc" // lalr1.cc:859
+#line 1573 "d2_parser.cc" // lalr1.cc:859
break;
- case 168:
-#line 675 "d2_parser.yy" // lalr1.cc:859
+ case 190:
+#line 723 "d2_parser.yy" // lalr1.cc:859
{
ElementPtr sev(new StringElement(yystack_[0].value.as< std::string > (), ctx.loc2pos(yystack_[0].location)));
ctx.stack_.back()->set("output", sev);
ctx.leave();
}
-#line 1447 "d2_parser.cc" // lalr1.cc:859
+#line 1583 "d2_parser.cc" // lalr1.cc:859
break;
-#line 1451 "d2_parser.cc" // lalr1.cc:859
+#line 1587 "d2_parser.cc" // lalr1.cc:859
default:
break;
}
const short int
D2Parser::yypact_[] =
{
- -24, -104, -104, -104, 3, -3, -2, 0, -104, -104,
+ 29, -104, -104, -104, -104, -104, -104, -104, -104, -104,
+ 11, -2, 16, 28, 37, 97, 81, 98, 99, 100,
+ -104, -104, -104, -104, -104, -104, -104, -104, -104, -104,
-104, -104, -104, -104, -104, -104, -104, -104, -104, -104,
- -104, -104, -104, -104, -3, -8, 1, 4, -104, 42,
- 47, 58, 68, 79, -104, -104, -104, -104, 83, -104,
- 19, -104, -104, -104, -104, -104, -104, 88, 89, -104,
- -104, -104, -104, -104, -104, 21, -104, -104, -104, -104,
- -104, -104, -104, -104, -104, -104, -3, -3, -104, 53,
- 91, 92, 93, 94, -104, 1, -104, 95, 59, 60,
- 96, 99, 100, 101, 102, 4, -104, -104, -104, 103,
- -3, -3, 104, 105, -104, 74, -104, -104, 73, 90,
- 107, 110, 113, -104, -3, -104, -104, 4, 87, -104,
- -104, -104, -104, -104, -13, -13, 114, -104, 27, -104,
- 51, -104, -104, -104, -104, 63, -104, -104, -104, 66,
- -104, 116, 106, -104, -104, 119, 87, -104, 120, -13,
- -104, -104, 23, -104, 114, 115, -104, 121, -104, -104,
- 123, -104, -104, -104, 67, -104, -104, -104, -104, -104,
- -104, 118, 122, 124, 97, 126, 127, 23, -104, -104,
- 31, -104, -104, 128, 129, -104, 108, -104, 109, 111,
- -104, 24, 118, -104, 22, -104, 122, -104, -104, -104,
- -104, -104, 131, -104, -104, 69, -104, -104, -104, -104,
- -104, -104, -104, -104, -104, -104, 70, -104, -104, -104,
- -104, -104, 132, 133, 98, 134, 24, -104, 138, 139,
- 140, 22, -104, 112, 141, -104, 125, -104, 130, 142,
- 135, -104, -104, 144, -104, -104, 147, -104, -104, 80,
- -104, -104, 150, 145, -104, 137, 144, -104, -5, -104,
- 147, -104, 76, -104, -104, -104, 153, -104, -104, 77,
- -104, -104, -104, -104, -104, 155, 137, -104, 156, 136,
- 157, -5, -104, 143, -104, 146, -104, 148, -104, -104,
- -104, -104
+ -104, -104, -104, -104, -104, -104, -104, -104, -2, 15,
+ 2, 3, 10, 101, 4, 102, -5, 103, -104, 106,
+ 104, 110, 96, 112, -104, -104, -104, -104, 113, -104,
+ 12, -104, -104, -104, -104, -104, -104, 114, 116, -104,
+ -104, -104, -104, -104, -104, 23, -104, -104, -104, -104,
+ -104, -104, -104, -104, -104, -104, 118, -104, -104, -104,
+ 24, -104, -104, -104, -104, -104, -104, 117, 121, -104,
+ -104, -104, -104, -104, 33, -104, -104, -104, -104, -104,
+ 119, 123, -104, -104, 124, -104, -104, 51, -104, -104,
+ -104, -104, -104, 58, -104, -104, -2, -2, -104, 69,
+ 126, 127, 128, 129, -104, 2, -104, 130, 87, 88,
+ 133, 136, 137, 138, 139, 3, -104, 140, 105, 141,
+ 142, 10, -104, 10, -104, 101, 143, 144, 145, 4,
+ -104, 4, -104, 102, 146, 107, 147, -5, -104, -5,
+ 103, -104, -104, -104, 148, -2, -2, 149, 150, -104,
+ 111, -104, -104, 82, 134, 152, 153, 156, -104, 115,
+ -104, 120, 122, -104, 55, -104, 125, 158, 135, -104,
+ 57, -104, 151, -104, 154, -104, 73, -104, -2, -104,
+ -104, 3, 132, -104, -104, -104, -104, -104, -13, -13,
+ 101, -104, -104, -104, -104, -104, 103, -104, -104, -104,
+ -104, -104, -104, 74, -104, 75, -104, -104, -104, -104,
+ 76, -104, -104, -104, 77, 159, 90, -104, 162, 132,
+ -104, 164, -13, -104, -104, -104, -104, 165, -104, 168,
+ -104, 167, 102, -104, 91, -104, 169, 19, 167, -104,
+ -104, -104, -104, 172, -104, -104, 83, -104, -104, -104,
+ -104, -104, -104, 173, 176, 155, 177, 19, -104, 157,
+ 178, -104, 160, -104, -104, 179, -104, -104, 95, -104,
+ 161, 179, -104, -104, 84, -104, -104, 180, 161, -104,
+ 163, -104, -104
};
const unsigned char
D2Parser::yydefact_[] =
{
- 0, 2, 4, 6, 0, 0, 0, 0, 1, 22,
- 16, 12, 11, 8, 9, 10, 15, 3, 13, 14,
- 29, 5, 40, 7, 24, 18, 0, 0, 26, 0,
- 25, 0, 0, 19, 132, 134, 38, 136, 0, 37,
- 0, 31, 36, 33, 35, 34, 53, 0, 0, 57,
- 61, 63, 65, 110, 52, 0, 42, 44, 45, 46,
- 47, 48, 49, 50, 51, 23, 0, 0, 17, 0,
- 0, 0, 0, 0, 28, 0, 30, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 41, 27, 20, 0,
- 0, 0, 0, 0, 32, 0, 55, 56, 0, 0,
- 0, 0, 0, 43, 0, 133, 135, 0, 0, 54,
- 59, 60, 58, 62, 67, 67, 112, 21, 0, 141,
- 0, 138, 140, 73, 72, 0, 68, 69, 71, 0,
- 116, 0, 113, 114, 39, 0, 0, 137, 0, 0,
- 64, 66, 0, 111, 0, 0, 139, 0, 70, 127,
- 0, 130, 125, 124, 0, 118, 120, 121, 122, 123,
- 115, 0, 75, 0, 0, 0, 0, 0, 117, 145,
- 0, 143, 79, 0, 76, 77, 0, 129, 0, 0,
- 119, 0, 0, 142, 0, 74, 0, 128, 131, 126,
- 154, 159, 0, 157, 153, 0, 147, 149, 151, 152,
- 150, 144, 89, 91, 87, 86, 0, 81, 83, 84,
- 85, 78, 0, 0, 0, 0, 0, 146, 0, 0,
- 0, 0, 80, 0, 0, 156, 0, 148, 0, 0,
- 0, 82, 155, 0, 158, 90, 93, 88, 163, 0,
- 161, 97, 0, 94, 95, 0, 0, 160, 0, 92,
- 0, 167, 0, 165, 162, 107, 0, 105, 104, 0,
- 99, 101, 102, 103, 96, 0, 0, 164, 0, 0,
- 0, 0, 98, 0, 166, 0, 109, 0, 100, 168,
- 108, 106
+ 0, 2, 4, 6, 8, 10, 12, 14, 16, 18,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 1, 34, 28, 24, 23, 20, 21, 22, 27, 3,
+ 25, 26, 41, 5, 52, 7, 138, 9, 130, 11,
+ 95, 13, 87, 15, 115, 17, 109, 19, 36, 30,
+ 0, 0, 0, 132, 0, 89, 0, 0, 38, 0,
+ 37, 0, 0, 31, 154, 156, 50, 158, 0, 49,
+ 0, 43, 48, 45, 47, 46, 65, 0, 0, 69,
+ 73, 75, 77, 128, 64, 0, 54, 56, 57, 58,
+ 59, 60, 61, 62, 63, 149, 0, 152, 147, 146,
+ 0, 140, 142, 143, 144, 145, 136, 0, 133, 134,
+ 105, 107, 103, 102, 0, 97, 99, 100, 101, 93,
+ 0, 90, 91, 125, 0, 123, 122, 0, 117, 119,
+ 120, 121, 113, 0, 111, 35, 0, 0, 29, 0,
+ 0, 0, 0, 0, 40, 0, 42, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 53, 0, 0, 0,
+ 0, 0, 139, 0, 131, 0, 0, 0, 0, 0,
+ 96, 0, 88, 0, 0, 0, 0, 0, 116, 0,
+ 0, 110, 39, 32, 0, 0, 0, 0, 0, 44,
+ 0, 67, 68, 0, 0, 0, 0, 0, 55, 0,
+ 151, 0, 0, 141, 0, 135, 0, 0, 0, 98,
+ 0, 92, 0, 127, 0, 118, 0, 112, 0, 155,
+ 157, 0, 0, 66, 71, 72, 70, 74, 79, 79,
+ 132, 150, 153, 148, 137, 106, 0, 104, 94, 126,
+ 124, 114, 33, 0, 163, 0, 160, 162, 85, 84,
+ 0, 80, 81, 83, 0, 0, 0, 51, 0, 0,
+ 159, 0, 0, 76, 78, 129, 108, 0, 161, 0,
+ 82, 0, 89, 167, 0, 165, 0, 0, 0, 164,
+ 86, 176, 181, 0, 179, 175, 0, 169, 171, 173,
+ 174, 172, 166, 0, 0, 0, 0, 0, 168, 0,
+ 0, 178, 0, 170, 177, 0, 180, 185, 0, 183,
+ 0, 0, 182, 189, 0, 187, 184, 0, 0, 186,
+ 0, 188, 190
};
const signed char
D2Parser::yypgoto_[] =
{
- -104, -104, -104, -104, -104, -23, -104, -104, -104, -104,
- -104, -104, -104, -104, -104, -26, -104, -104, -104, 33,
- -104, -104, -104, -104, 26, 78, -104, -104, -104, -104,
- -104, -104, -104, -104, -104, -104, -104, -104, -104, 30,
- -104, 25, -104, -104, -104, -104, -21, -104, -104, -59,
- -104, -104, -104, -104, -104, -104, -104, -104, -83, -104,
- -104, -103, -104, -104, -104, -104, -104, -104, -104, -104,
- -104, 29, -104, -104, 2, -104, -104, -104, -104, -104,
- -104, -104, -104, -104, -104, -104, -104, -104, -104, 34,
- -104, -104, -104, -7, -104, -104, -42, -104, -104, -104,
- -104, -104, -104, -104, -104, -69, -104, -104, -87, -104
+ -104, -104, -104, -104, -104, -104, -104, -104, -104, -104,
+ -104, -47, -104, -104, -104, -104, -104, -104, -104, -104,
+ -104, -50, -104, -104, -104, 40, -104, -104, -104, -104,
+ -34, 34, -104, -104, -104, -104, -104, -104, -104, -104,
+ -104, -104, -104, -104, -104, -41, -104, -72, -104, -104,
+ -104, -104, -81, -104, 20, -104, -104, -104, 21, 25,
+ -104, -104, -104, -104, -104, -104, -104, -104, -39, 22,
+ -104, -104, -104, 26, 18, -104, -104, -104, -104, -104,
+ -104, -104, -104, -104, -31, -104, 35, -104, -104, -104,
+ 43, 47, -104, -104, -104, -104, -104, -104, -104, -104,
+ -104, -104, -104, -104, -104, -104, -48, -104, -104, -104,
+ -69, -104, -104, -84, -104, -104, -104, -104, -104, -104,
+ -104, -104, -97, -104, -104, -103, -104
};
const short int
D2Parser::yydefgoto_[] =
{
- -1, 4, 5, 6, 7, 16, 17, 18, 25, 32,
- 33, 19, 24, 29, 30, 54, 21, 26, 40, 41,
- 42, 72, 23, 27, 55, 56, 57, 77, 58, 59,
- 60, 80, 112, 61, 81, 62, 82, 63, 83, 125,
- 126, 127, 128, 138, 173, 174, 175, 184, 206, 207,
- 208, 220, 209, 218, 210, 219, 242, 243, 244, 248,
- 259, 260, 261, 270, 262, 268, 263, 64, 84, 131,
- 132, 133, 142, 154, 155, 156, 166, 157, 163, 158,
- 159, 165, 43, 70, 44, 71, 45, 73, 120, 121,
- 122, 135, 170, 171, 181, 195, 196, 197, 212, 198,
- 199, 215, 200, 213, 239, 240, 245, 252, 253, 265
+ -1, 10, 11, 12, 13, 14, 15, 16, 17, 18,
+ 19, 28, 29, 30, 49, 62, 63, 31, 48, 59,
+ 60, 84, 33, 50, 70, 71, 72, 142, 35, 51,
+ 85, 86, 87, 147, 88, 89, 90, 150, 226, 91,
+ 151, 92, 152, 93, 153, 250, 251, 252, 253, 261,
+ 43, 55, 120, 121, 122, 171, 41, 54, 114, 115,
+ 116, 168, 117, 166, 118, 167, 47, 57, 133, 134,
+ 179, 45, 56, 127, 128, 129, 176, 130, 174, 131,
+ 94, 154, 39, 53, 107, 108, 109, 163, 37, 52,
+ 100, 101, 102, 160, 103, 157, 104, 105, 159, 73,
+ 140, 74, 141, 75, 143, 245, 246, 247, 258, 274,
+ 275, 277, 286, 287, 288, 293, 289, 290, 296, 291,
+ 294, 308, 309, 310, 314, 315, 317
};
const unsigned short int
D2Parser::yytable_[] =
{
- 39, 28, 9, 8, 10, 20, 11, 22, 255, 256,
- 123, 34, 35, 36, 1, 2, 3, 46, 47, 48,
- 49, 257, 75, 50, 85, 51, 52, 76, 38, 86,
- 85, 53, 37, 31, 182, 134, 38, 183, 12, 13,
- 14, 15, 38, 87, 88, 38, 202, 203, 65, 39,
- 66, 149, 150, 151, 136, 204, 152, 190, 191, 137,
- 192, 193, 67, 38, 38, 38, 139, 105, 106, 139,
- 167, 140, 216, 221, 141, 168, 68, 217, 222, 266,
- 271, 117, 69, 246, 267, 272, 247, 74, 124, 124,
- 110, 111, 78, 79, 89, 90, 91, 92, 93, 95,
- 98, 96, 97, 99, 100, 101, 102, 104, 94, 144,
- 113, 107, 108, 124, 114, 109, 153, 115, 116, 119,
- 161, 130, 143, 145, 147, 169, 162, 164, 176, 172,
- 178, 179, 186, 118, 185, 214, 223, 224, 226, 177,
- 225, 153, 228, 229, 230, 129, 233, 236, 250, 187,
- 188, 238, 189, 232, 241, 194, 249, 269, 205, 273,
- 275, 277, 231, 103, 148, 211, 234, 264, 278, 180,
- 146, 235, 251, 160, 227, 201, 237, 254, 276, 274,
- 0, 0, 0, 0, 279, 0, 0, 280, 0, 281,
- 194, 0, 0, 0, 0, 205, 0, 0, 0, 0,
+ 69, 58, 99, 21, 113, 22, 126, 23, 123, 124,
+ 248, 20, 64, 65, 66, 145, 76, 77, 78, 79,
+ 146, 125, 80, 32, 81, 82, 155, 161, 110, 111,
+ 83, 156, 162, 67, 68, 34, 169, 112, 95, 96,
+ 97, 170, 68, 98, 36, 24, 25, 26, 27, 68,
+ 68, 68, 281, 282, 177, 283, 284, 68, 161, 178,
+ 169, 180, 61, 234, 181, 238, 68, 1, 2, 3,
+ 4, 5, 6, 7, 8, 9, 177, 155, 259, 262,
+ 262, 241, 257, 260, 263, 264, 297, 318, 40, 182,
+ 183, 298, 319, 180, 278, 69, 266, 279, 311, 224,
+ 225, 312, 38, 42, 138, 46, 44, 136, 106, 119,
+ 132, 99, 135, 99, 137, 139, 184, 144, 148, 113,
+ 149, 113, 158, 164, 165, 172, 173, 126, 175, 126,
+ 185, 186, 187, 188, 190, 191, 192, 193, 219, 220,
+ 194, 195, 196, 197, 199, 201, 202, 206, 207, 208,
+ 212, 214, 218, 200, 227, 213, 221, 222, 223, 228,
+ 229, 230, 231, 236, 244, 265, 267, 232, 269, 233,
+ 271, 242, 235, 272, 273, 280, 295, 299, 249, 249,
+ 300, 302, 237, 305, 320, 189, 307, 243, 254, 198,
+ 270, 276, 210, 211, 209, 215, 313, 256, 239, 255,
+ 205, 240, 217, 301, 304, 216, 204, 306, 203, 292,
+ 322, 268, 249, 303, 316, 321, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 285, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 258, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 258
+ 0, 0, 0, 0, 0, 0, 0, 285
};
const short int
D2Parser::yycheck_[] =
{
- 26, 24, 5, 0, 7, 7, 9, 7, 13, 14,
- 23, 10, 11, 12, 38, 39, 40, 13, 14, 15,
- 16, 26, 3, 19, 3, 21, 22, 8, 41, 8,
- 3, 27, 31, 41, 3, 8, 41, 6, 41, 42,
- 43, 44, 41, 66, 67, 41, 24, 25, 6, 75,
- 3, 28, 29, 30, 3, 33, 33, 33, 34, 8,
- 36, 37, 4, 41, 41, 41, 3, 90, 91, 3,
- 3, 8, 3, 3, 8, 8, 8, 8, 8, 3,
- 3, 104, 3, 3, 8, 8, 6, 4, 114, 115,
- 17, 18, 4, 4, 41, 4, 4, 4, 4, 4,
- 4, 42, 42, 4, 4, 4, 4, 4, 75, 3,
- 20, 7, 7, 139, 7, 41, 142, 7, 5, 32,
- 5, 7, 6, 4, 4, 7, 5, 4, 4, 7,
- 4, 4, 3, 107, 6, 4, 4, 4, 4, 42,
- 42, 167, 4, 4, 4, 115, 5, 5, 3, 41,
- 41, 7, 41, 41, 7, 181, 6, 4, 184, 4,
- 4, 4, 221, 85, 139, 186, 41, 250, 271, 167,
- 136, 41, 35, 144, 216, 182, 41, 246, 42, 266,
- -1, -1, -1, -1, 41, -1, -1, 41, -1, 41,
- 216, -1, -1, -1, -1, 221, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 248, -1, -1, -1, -1, -1, -1, -1,
+ 50, 48, 52, 5, 54, 7, 56, 9, 13, 14,
+ 23, 0, 10, 11, 12, 3, 13, 14, 15, 16,
+ 8, 26, 19, 7, 21, 22, 3, 3, 24, 25,
+ 27, 8, 8, 31, 47, 7, 3, 33, 28, 29,
+ 30, 8, 47, 33, 7, 47, 48, 49, 50, 47,
+ 47, 47, 33, 34, 3, 36, 37, 47, 3, 8,
+ 3, 3, 47, 8, 6, 8, 47, 38, 39, 40,
+ 41, 42, 43, 44, 45, 46, 3, 3, 3, 3,
+ 3, 8, 8, 8, 8, 8, 3, 3, 7, 136,
+ 137, 8, 8, 3, 3, 145, 6, 6, 3, 17,
+ 18, 6, 5, 5, 8, 5, 7, 3, 7, 7,
+ 7, 161, 6, 163, 4, 3, 47, 4, 4, 169,
+ 4, 171, 4, 6, 3, 6, 3, 177, 4, 179,
+ 4, 4, 4, 4, 4, 48, 48, 4, 185, 186,
+ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 48, 20, 48, 7, 7, 47, 7,
+ 7, 5, 47, 5, 32, 6, 4, 47, 4, 47,
+ 5, 218, 47, 5, 7, 6, 4, 4, 228, 229,
+ 4, 4, 47, 5, 4, 145, 7, 221, 229, 155,
+ 262, 272, 171, 173, 169, 177, 35, 236, 47, 230,
+ 165, 47, 180, 48, 47, 179, 163, 47, 161, 278,
+ 47, 259, 262, 297, 311, 318, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 277, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 271
+ -1, -1, -1, -1, -1, -1, -1, 297
};
const unsigned char
D2Parser::yystos_[] =
{
- 0, 38, 39, 40, 46, 47, 48, 49, 0, 5,
- 7, 9, 41, 42, 43, 44, 50, 51, 52, 56,
- 7, 61, 7, 67, 57, 53, 62, 68, 50, 58,
- 59, 41, 54, 55, 10, 11, 12, 31, 41, 60,
- 63, 64, 65, 127, 129, 131, 13, 14, 15, 16,
- 19, 21, 22, 27, 60, 69, 70, 71, 73, 74,
- 75, 78, 80, 82, 112, 6, 3, 4, 8, 3,
- 128, 130, 66, 132, 4, 3, 8, 72, 4, 4,
- 76, 79, 81, 83, 113, 3, 8, 50, 50, 41,
- 4, 4, 4, 4, 64, 4, 42, 42, 4, 4,
- 4, 4, 4, 70, 4, 50, 50, 7, 7, 41,
- 17, 18, 77, 20, 7, 7, 5, 50, 69, 32,
- 133, 134, 135, 23, 60, 84, 85, 86, 87, 84,
- 7, 114, 115, 116, 8, 136, 3, 8, 88, 3,
- 8, 8, 117, 6, 3, 4, 134, 4, 86, 28,
- 29, 30, 33, 60, 118, 119, 120, 122, 124, 125,
- 116, 5, 5, 123, 4, 126, 121, 3, 8, 7,
- 137, 138, 7, 89, 90, 91, 4, 42, 4, 4,
- 119, 139, 3, 6, 92, 6, 3, 41, 41, 41,
- 33, 34, 36, 37, 60, 140, 141, 142, 144, 145,
- 147, 138, 24, 25, 33, 60, 93, 94, 95, 97,
- 99, 91, 143, 148, 4, 146, 3, 8, 98, 100,
- 96, 3, 8, 4, 4, 42, 4, 141, 4, 4,
- 4, 94, 41, 5, 41, 41, 5, 41, 7, 149,
- 150, 7, 101, 102, 103, 151, 3, 6, 104, 6,
- 3, 35, 152, 153, 150, 13, 14, 26, 60, 105,
- 106, 107, 109, 111, 103, 154, 3, 8, 110, 4,
- 108, 3, 8, 4, 153, 4, 42, 4, 106, 41,
- 41, 41
+ 0, 38, 39, 40, 41, 42, 43, 44, 45, 46,
+ 52, 53, 54, 55, 56, 57, 58, 59, 60, 61,
+ 0, 5, 7, 9, 47, 48, 49, 50, 62, 63,
+ 64, 68, 7, 73, 7, 79, 7, 139, 5, 133,
+ 7, 107, 5, 101, 7, 122, 5, 117, 69, 65,
+ 74, 80, 140, 134, 108, 102, 123, 118, 62, 70,
+ 71, 47, 66, 67, 10, 11, 12, 31, 47, 72,
+ 75, 76, 77, 150, 152, 154, 13, 14, 15, 16,
+ 19, 21, 22, 27, 72, 81, 82, 83, 85, 86,
+ 87, 90, 92, 94, 131, 28, 29, 30, 33, 72,
+ 141, 142, 143, 145, 147, 148, 7, 135, 136, 137,
+ 24, 25, 33, 72, 109, 110, 111, 113, 115, 7,
+ 103, 104, 105, 13, 14, 26, 72, 124, 125, 126,
+ 128, 130, 7, 119, 120, 6, 3, 4, 8, 3,
+ 151, 153, 78, 155, 4, 3, 8, 84, 4, 4,
+ 88, 91, 93, 95, 132, 3, 8, 146, 4, 149,
+ 144, 3, 8, 138, 6, 3, 114, 116, 112, 3,
+ 8, 106, 6, 3, 129, 4, 127, 3, 8, 121,
+ 3, 6, 62, 62, 47, 4, 4, 4, 4, 76,
+ 4, 48, 48, 4, 4, 4, 4, 4, 82, 4,
+ 48, 4, 4, 142, 141, 137, 4, 4, 4, 110,
+ 109, 105, 4, 48, 4, 125, 124, 120, 4, 62,
+ 62, 7, 7, 47, 17, 18, 89, 20, 7, 7,
+ 5, 47, 47, 47, 8, 47, 5, 47, 8, 47,
+ 47, 8, 62, 81, 32, 156, 157, 158, 23, 72,
+ 96, 97, 98, 99, 96, 135, 119, 8, 159, 3,
+ 8, 100, 3, 8, 8, 6, 6, 4, 157, 4,
+ 98, 5, 5, 7, 160, 161, 103, 162, 3, 6,
+ 6, 33, 34, 36, 37, 72, 163, 164, 165, 167,
+ 168, 170, 161, 166, 171, 4, 169, 3, 8, 4,
+ 4, 48, 4, 164, 47, 5, 47, 7, 172, 173,
+ 174, 3, 6, 35, 175, 176, 173, 177, 3, 8,
+ 4, 176, 47
};
const unsigned char
D2Parser::yyr1_[] =
{
- 0, 45, 47, 46, 48, 46, 49, 46, 50, 50,
- 50, 50, 50, 50, 50, 51, 53, 52, 54, 54,
- 55, 55, 57, 56, 58, 58, 59, 59, 60, 62,
- 61, 63, 63, 64, 64, 64, 64, 64, 66, 65,
- 68, 67, 69, 69, 70, 70, 70, 70, 70, 70,
- 70, 70, 70, 72, 71, 73, 74, 76, 75, 77,
- 77, 79, 78, 81, 80, 83, 82, 84, 84, 85,
- 85, 86, 86, 88, 87, 89, 89, 90, 90, 92,
- 91, 93, 93, 94, 94, 94, 94, 96, 95, 98,
- 97, 100, 99, 101, 101, 102, 102, 104, 103, 105,
- 105, 106, 106, 106, 106, 108, 107, 110, 109, 111,
- 113, 112, 114, 114, 115, 115, 117, 116, 118, 118,
- 119, 119, 119, 119, 119, 121, 120, 123, 122, 124,
- 126, 125, 128, 127, 130, 129, 132, 131, 133, 133,
- 134, 136, 135, 137, 137, 139, 138, 140, 140, 141,
- 141, 141, 141, 141, 143, 142, 144, 146, 145, 148,
- 147, 149, 149, 151, 150, 152, 152, 154, 153
+ 0, 51, 53, 52, 54, 52, 55, 52, 56, 52,
+ 57, 52, 58, 52, 59, 52, 60, 52, 61, 52,
+ 62, 62, 62, 62, 62, 62, 62, 63, 65, 64,
+ 66, 66, 67, 67, 69, 68, 70, 70, 71, 71,
+ 72, 74, 73, 75, 75, 76, 76, 76, 76, 76,
+ 78, 77, 80, 79, 81, 81, 82, 82, 82, 82,
+ 82, 82, 82, 82, 82, 84, 83, 85, 86, 88,
+ 87, 89, 89, 91, 90, 93, 92, 95, 94, 96,
+ 96, 97, 97, 98, 98, 100, 99, 102, 101, 103,
+ 103, 104, 104, 106, 105, 108, 107, 109, 109, 110,
+ 110, 110, 110, 112, 111, 114, 113, 116, 115, 118,
+ 117, 119, 119, 121, 120, 123, 122, 124, 124, 125,
+ 125, 125, 125, 127, 126, 129, 128, 130, 132, 131,
+ 134, 133, 135, 135, 136, 136, 138, 137, 140, 139,
+ 141, 141, 142, 142, 142, 142, 142, 144, 143, 146,
+ 145, 147, 149, 148, 151, 150, 153, 152, 155, 154,
+ 156, 156, 157, 159, 158, 160, 160, 162, 161, 163,
+ 163, 164, 164, 164, 164, 164, 166, 165, 167, 169,
+ 168, 171, 170, 172, 172, 174, 173, 175, 175, 177,
+ 176
};
const unsigned char
D2Parser::yyr2_[] =
{
- 0, 2, 0, 3, 0, 3, 0, 3, 1, 1,
- 1, 1, 1, 1, 1, 1, 0, 4, 0, 1,
- 3, 5, 0, 4, 0, 1, 1, 3, 2, 0,
- 4, 1, 3, 1, 1, 1, 1, 1, 0, 6,
- 0, 4, 1, 3, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 0, 4, 3, 3, 0, 4, 1,
- 1, 0, 4, 0, 6, 0, 6, 0, 1, 1,
- 3, 1, 1, 0, 6, 0, 1, 1, 3, 0,
- 4, 1, 3, 1, 1, 1, 1, 0, 4, 0,
- 4, 0, 6, 0, 1, 1, 3, 0, 4, 1,
- 3, 1, 1, 1, 1, 0, 4, 0, 4, 3,
- 0, 6, 0, 1, 1, 3, 0, 4, 1, 3,
- 1, 1, 1, 1, 1, 0, 4, 0, 4, 3,
- 0, 4, 0, 4, 0, 4, 0, 6, 1, 3,
- 1, 0, 6, 1, 3, 0, 4, 1, 3, 1,
- 1, 1, 1, 1, 0, 4, 3, 0, 4, 0,
- 6, 1, 3, 0, 4, 1, 3, 0, 4
+ 0, 2, 0, 3, 0, 3, 0, 3, 0, 3,
+ 0, 3, 0, 3, 0, 3, 0, 3, 0, 3,
+ 1, 1, 1, 1, 1, 1, 1, 1, 0, 4,
+ 0, 1, 3, 5, 0, 4, 0, 1, 1, 3,
+ 2, 0, 4, 1, 3, 1, 1, 1, 1, 1,
+ 0, 6, 0, 4, 1, 3, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 0, 4, 3, 3, 0,
+ 4, 1, 1, 0, 4, 0, 6, 0, 6, 0,
+ 1, 1, 3, 1, 1, 0, 6, 0, 4, 0,
+ 1, 1, 3, 0, 4, 0, 4, 1, 3, 1,
+ 1, 1, 1, 0, 4, 0, 4, 0, 6, 0,
+ 4, 1, 3, 0, 4, 0, 4, 1, 3, 1,
+ 1, 1, 1, 0, 4, 0, 4, 3, 0, 6,
+ 0, 4, 0, 1, 1, 3, 0, 4, 0, 4,
+ 1, 3, 1, 1, 1, 1, 1, 0, 4, 0,
+ 4, 3, 0, 4, 0, 4, 0, 4, 0, 6,
+ 1, 3, 1, 0, 6, 1, 3, 0, 4, 1,
+ 3, 1, 1, 1, 1, 1, 0, 4, 3, 0,
+ 4, 0, 6, 1, 3, 0, 4, 1, 3, 0,
+ 4
};
"\"algorithm\"", "\"digest-bits\"", "\"secret\"", "\"Logging\"",
"\"loggers\"", "\"name\"", "\"output_options\"", "\"output\"",
"\"debuglevel\"", "\"severity\"", "TOPLEVEL_JSON", "TOPLEVEL_DHCPDDNS",
- "SUB_DHCPDDNS", "\"constant string\"", "\"integer\"",
- "\"floating point\"", "\"boolean\"", "$accept", "start", "$@1", "$@2",
- "$@3", "value", "sub_json", "map2", "$@4", "map_content",
- "not_empty_map", "list_generic", "$@5", "list_content", "not_empty_list",
- "unknown_map_entry", "syntax_map", "$@6", "global_objects",
- "global_object", "dhcpddns_object", "$@7", "sub_dhcpddns", "$@8",
- "dhcpddns_params", "dhcpddns_param", "ip_address", "$@9", "port",
- "dns_server_timeout", "ncr_protocol", "$@10", "ncr_protocol_value",
- "ncr_format", "$@11", "forward_ddns", "$@12", "reverse_ddns", "$@13",
- "ddns_mgr_params", "not_empty_ddns_mgr_params", "ddns_mgr_param",
- "ddns_domains", "$@14", "ddns_domain_list", "not_empty_ddns_domain_list",
- "ddns_domain", "$@15", "ddns_domain_params", "ddns_domain_param",
- "ddns_domain_name", "$@16", "ddns_domain_key_name", "$@17",
- "dns_servers", "$@18", "dns_server_list", "not_empty_dns_server_list",
- "dns_server", "$@19", "dns_server_params", "dns_server_param",
- "dns_server_hostname", "$@20", "dns_server_ip_address", "$@21",
- "dns_server_port", "tsig_keys", "$@22", "tsig_keys_list",
- "not_empty_tsig_keys_list", "tsig_key", "$@23", "tsig_key_params",
- "tsig_key_param", "tsig_key_name", "$@24", "tsig_key_algorithm", "$@25",
- "tsig_key_digest_bits", "tsig_key_secret", "$@26", "dhcp6_json_object",
- "$@27", "dhcp4_json_object", "$@28", "logging_object", "$@29",
- "logging_params", "logging_param", "loggers", "$@30", "loggers_entries",
- "logger_entry", "$@31", "logger_params", "logger_param", "name", "$@32",
- "debuglevel", "severity", "$@33", "output_options_list", "$@34",
- "output_options_list_content", "output_entry", "$@35", "output_params",
- "output_param", "$@36", YY_NULLPTR
+ "SUB_DHCPDDNS", "SUB_TSIG_KEY", "SUB_TSIG_KEYS", "SUB_DDNS_DOMAIN",
+ "SUB_DDNS_DOMAINS", "SUB_DNS_SERVER", "SUB_DNS_SERVERS",
+ "\"constant string\"", "\"integer\"", "\"floating point\"",
+ "\"boolean\"", "$accept", "start", "$@1", "$@2", "$@3", "$@4", "$@5",
+ "$@6", "$@7", "$@8", "$@9", "value", "sub_json", "map2", "$@10",
+ "map_content", "not_empty_map", "list_generic", "$@11", "list_content",
+ "not_empty_list", "unknown_map_entry", "syntax_map", "$@12",
+ "global_objects", "global_object", "dhcpddns_object", "$@13",
+ "sub_dhcpddns", "$@14", "dhcpddns_params", "dhcpddns_param",
+ "ip_address", "$@15", "port", "dns_server_timeout", "ncr_protocol",
+ "$@16", "ncr_protocol_value", "ncr_format", "$@17", "forward_ddns",
+ "$@18", "reverse_ddns", "$@19", "ddns_mgr_params",
+ "not_empty_ddns_mgr_params", "ddns_mgr_param", "ddns_domains", "$@20",
+ "sub_ddns_domains", "$@21", "ddns_domain_list",
+ "not_empty_ddns_domain_list", "ddns_domain", "$@22", "sub_ddns_domain",
+ "$@23", "ddns_domain_params", "ddns_domain_param", "ddns_domain_name",
+ "$@24", "ddns_domain_key_name", "$@25", "dns_servers", "$@26",
+ "sub_dns_servers", "$@27", "dns_server_list", "dns_server", "$@28",
+ "sub_dns_server", "$@29", "dns_server_params", "dns_server_param",
+ "dns_server_hostname", "$@30", "dns_server_ip_address", "$@31",
+ "dns_server_port", "tsig_keys", "$@32", "sub_tsig_keys", "$@33",
+ "tsig_keys_list", "not_empty_tsig_keys_list", "tsig_key", "$@34",
+ "sub_tsig_key", "$@35", "tsig_key_params", "tsig_key_param",
+ "tsig_key_name", "$@36", "tsig_key_algorithm", "$@37",
+ "tsig_key_digest_bits", "tsig_key_secret", "$@38", "dhcp6_json_object",
+ "$@39", "dhcp4_json_object", "$@40", "logging_object", "$@41",
+ "logging_params", "logging_param", "loggers", "$@42", "loggers_entries",
+ "logger_entry", "$@43", "logger_params", "logger_param", "name", "$@44",
+ "debuglevel", "severity", "$@45", "output_options_list", "$@46",
+ "output_options_list_content", "output_entry", "$@47", "output_params",
+ "output_param", "$@48", YY_NULLPTR
};
#if D2_PARSER_DEBUG
const unsigned short int
D2Parser::yyrline_[] =
{
- 0, 107, 107, 107, 108, 108, 109, 109, 117, 118,
- 119, 120, 121, 122, 123, 126, 131, 131, 143, 144,
- 147, 151, 158, 158, 165, 166, 169, 173, 184, 194,
- 194, 206, 207, 211, 212, 213, 214, 215, 220, 220,
- 230, 230, 238, 239, 242, 243, 244, 245, 246, 247,
- 248, 249, 250, 253, 253, 261, 269, 278, 278, 286,
- 287, 290, 290, 298, 298, 308, 308, 318, 319, 322,
- 323, 326, 327, 333, 333, 343, 344, 347, 348, 351,
- 351, 359, 360, 363, 364, 365, 366, 370, 370, 382,
- 382, 397, 397, 407, 408, 411, 412, 415, 415, 423,
- 424, 427, 428, 429, 430, 433, 433, 445, 445, 453,
- 467, 467, 477, 478, 481, 482, 485, 485, 493, 494,
- 497, 498, 499, 500, 501, 504, 504, 516, 516, 527,
- 535, 535, 550, 550, 557, 557, 569, 569, 582, 583,
- 587, 591, 591, 603, 604, 608, 608, 616, 617, 620,
- 621, 622, 623, 624, 627, 627, 635, 639, 639, 647,
- 647, 657, 658, 661, 661, 669, 670, 673, 673
+ 0, 113, 113, 113, 114, 114, 115, 115, 116, 116,
+ 117, 117, 118, 118, 119, 119, 120, 120, 121, 121,
+ 129, 130, 131, 132, 133, 134, 135, 138, 143, 143,
+ 155, 156, 159, 163, 170, 170, 177, 178, 181, 185,
+ 196, 206, 206, 218, 219, 223, 224, 225, 226, 227,
+ 232, 232, 242, 242, 250, 251, 254, 255, 256, 257,
+ 258, 259, 260, 261, 262, 265, 265, 273, 281, 290,
+ 290, 298, 299, 302, 302, 310, 310, 320, 320, 330,
+ 331, 334, 335, 338, 339, 344, 344, 354, 354, 361,
+ 362, 365, 366, 369, 369, 377, 377, 384, 385, 388,
+ 389, 390, 391, 395, 395, 407, 407, 419, 419, 429,
+ 429, 436, 437, 440, 440, 448, 448, 455, 456, 459,
+ 460, 461, 462, 465, 465, 477, 477, 485, 499, 499,
+ 509, 509, 516, 517, 520, 521, 524, 524, 532, 532,
+ 541, 542, 545, 546, 547, 548, 549, 552, 552, 564,
+ 564, 575, 583, 583, 598, 598, 605, 605, 617, 617,
+ 630, 631, 635, 639, 639, 651, 652, 656, 656, 664,
+ 665, 668, 669, 670, 671, 672, 675, 675, 683, 687,
+ 687, 695, 695, 705, 706, 709, 709, 717, 718, 721,
+ 721
};
// Print the state stack on the debug stream.
#line 14 "d2_parser.yy" // lalr1.cc:1167
} } // isc::d2
-#line 2047 "d2_parser.cc" // lalr1.cc:1167
-#line 681 "d2_parser.yy" // lalr1.cc:1168
+#line 2213 "d2_parser.cc" // lalr1.cc:1167
+#line 729 "d2_parser.yy" // lalr1.cc:1168
void
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
};
};
symbol_type
make_SUB_DHCPDDNS (const location_type& l);
+ 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);
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.
};
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_)
{
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;
(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;
// 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;
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;
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]);
}
return symbol_type (token::TOKEN_SUB_DHCPDDNS, l);
}
+ 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)
{
#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
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"
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 ---------------------------------
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);
};
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);
}
| 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);
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
;
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
;
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);
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);
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)));
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
;
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);
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);
};
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
;
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
;
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);
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();
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);
};
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();
/// 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);
}
/// 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
///
/// @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);
};
};
void
D2ParserContext::leave()
{
-#if 1
if (cstack_.empty()) {
fatal("unbalanced syntactic context");
}
-#endif
+
ctx_ = cstack_.back();
cstack_.pop_back();
}
return ("toplevel");
case DHCPDDNS:
return ("DhcpDdns");
+ case TSIG_KEY:
+ return ("tsig-key");
case TSIG_KEYS:
return ("tsig-keys");
case ALGORITHM:
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:
/// 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.
///< 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
///< 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
return (config.str());
}
+
/// @brief Enumeration to select between expected configuration outcomes
enum RunConfigMode {
- SHOULD_PASS,
- SHOULD_FAIL
+ NO_ERROR,
+ SYNTAX_ERROR,
+ LOGIC_ERROR
};
/// @brief Parses a configuration string and tests against a given outcome
///
/// Convenience method which accepts JSON text and an expected pass or fail
- /// outcome. It converts the text into an ElementPtr and passes that to
- /// configuration manager's parseConfig method. It then tests the
- /// parse result against the expected outcome If they do not match it
- /// the method asserts a failure. If they do match, it refreshes the
- /// the D2Params pointer with the newly parsed instance.
+ /// outcome. It uses the D2ParserContext to parse the text under the
+ /// PARSE_SUB_DHCPDDNS context, then adds the D2 defaults to the resultant
+ /// element tree. Assuming that's successful the element tree is passed
+ /// to D2CfgMgr::parseConfig() method.
///
/// @param config_str the JSON configuration text to parse
- /// @param mode indicator if the parsing should fail or not. It defaults
+ /// @param error_type indicates the type error expected, NONE, SYNTAX,
+ /// or LOGIC. SYNTAX errors are emitted by JSON parser, logic errors
+ /// are emitted by element parser(s).
+ /// @param exp_error exact text of the error message expected
/// defaults to SHOULD_PASS.
///
- void runConfig(std::string config_str, RunConfigMode mode=SHOULD_PASS) {
- // We assume the config string is valid JSON.
- ASSERT_TRUE(fromJSON(config_str));
+ /// @return AssertionSuccess if test passes, AssertionFailure otherwise
+ ::testing::AssertionResult runConfigOrFail(const std::string& json,
+ const RunConfigMode mode,
+ const std::string& exp_error) {
- // Parse the configuration and verify we got the expected outcome.
- answer_ = cfg_mgr_->parseConfig(config_set_);
- ASSERT_TRUE(checkAnswer(mode == SHOULD_FAIL));
+ try {
+ // Invoke the JSON parser, casting the returned element tree
+ // into mutable form.
+ D2ParserContext parser_context;
+ data::ElementPtr elem =
+ boost::const_pointer_cast<Element>
+ (parser_context.parseString(json, D2ParserContext::
+ PARSER_SUB_DHCPDDNS));
+
+ // If parsing succeeded when we expected a syntax error, then fail.
+ if (mode == SYNTAX_ERROR) {
+ return ::testing::AssertionFailure()
+ << "Unexpected JSON parsing success"
+ << "\njson: [" << json << " ]";
+ }
- // Verify that the D2 context can be retrieved and is not null.
- D2CfgContextPtr context;
- ASSERT_NO_THROW(context = cfg_mgr_->getD2CfgContext());
+ // JSON parsed ok, so the defaults to the element tree it produced.
+ D2SimpleParser::setAllDefaults(elem);
+ config_set_ = elem;
+ } catch (const std::exception& ex) {
+ // JSON Parsing failed
+ if (exp_error.empty()) {
+ // We did not expect an error, so fail.
+ return ::testing::AssertionFailure()
+ << "Unexpected sytnax error:" << ex.what()
+ << "\njson: [" << json << " ]";
+ }
- // Verify that the global scalars have the proper values.
- d2_params_ = context->getD2Params();
- ASSERT_TRUE(d2_params_);
- }
+ if (ex.what() != exp_error) {
+ // Expected an error not the one we got, so fail
+ return ::testing::AssertionFailure()
+ << "Wrong syntax error detected, expected: "
+ << exp_error << ", got: " << ex.what()
+ << "\njson: [" << json << " ]";
+ }
- /// @brief Check parse result against expected outcome and position info
- ///
- /// This method analyzes the given parsing result against an expected outcome
- /// of SHOULD_PASS or SHOULD_FAIL. If it is expected to fail, the comment
- /// contained within the result is searched for Element::Position information
- /// which should contain the given file name. It does not attempt to verify
- /// the numerical values for line number and col.
- ///
- /// @param answer Element set containing an integer result code and string
- /// comment.
- /// @param mode indicator if the parsing should fail or not.
- /// @param file_name name of the file containing the configuration text
- /// parsed. It defaults to "<string>" which is the value present if the
- /// configuration text did not originate from a file. (i.e. one did not use
- /// isc::data::Element::fromJSONFile() to read the JSON text).
- void
- checkAnswerWithError(isc::data::ConstElementPtr answer,
- RunConfigMode mode, std::string file_name="<string>") {
+ // We go the syntax error we expected, so return success
+ return ::testing::AssertionSuccess();
+ }
+
+ // The JSON parsed ok and we've added the defaults, pass the config
+ // into the Element parser and check for the expected outcome.
+ data::ConstElementPtr answer = cfg_mgr_->parseConfig(config_set_);
+
+ // Extract the result and error text from the anwser.
int rcode = 0;
isc::data::ConstElementPtr comment;
comment = isc::config::parseAnswer(rcode, answer);
- if (mode == SHOULD_PASS) {
- if (rcode == 0) {
- return;
+ if (rcode != 0) {
+ // Element Parsing failed.
+ if (exp_error.empty()) {
+ // We didn't expect it to, fail the test.
+ return ::testing::AssertionFailure()
+ << "Unexpected logic error: " << *comment
+ << "\njson: [" << json << " ]";
}
- FAIL() << "Parsing was expected to pass but failed : " << rcode
- << " comment: " << *comment;
+ if (comment->stringValue() != exp_error) {
+ // We 't expect a different error, fail the test.
+ return ::testing::AssertionFailure()
+ << "Wrong logic error detected, expected: "
+ << exp_error << ", got: " << *comment
+ << "\njson: [" << json << " ]";
+ }
+ } else {
+ // Element parsing succeeded.
+ if (!exp_error.empty()) {
+ // It was supposed to fail, so fail the test.
+ return ::testing::AssertionFailure()
+ << "Unexpected logic success, expected error:"
+ << exp_error
+ << "\njson: [" << json << " ]";
+ }
}
- if (rcode == 0) {
- FAIL() << "Parsing was expected to fail but passed : "
- << " comment: " << *comment;
+ // Verify that the D2 context can be retrieved and is not null.
+ D2CfgContextPtr context;
+ context = cfg_mgr_->getD2CfgContext();
+ if (!context) {
+ return ::testing::AssertionFailure() << "D2CfgContext is null";
}
- // Parsing was expected to fail, test for position info.
- if (isc::dhcp::test::errorContainsPosition(answer, file_name)) {
- return;
+ // Verify that the global scalar container has been created.
+ d2_params_ = context->getD2Params();
+ if (!d2_params_) {
+ return ::testing::AssertionFailure() << "D2Params is null";
}
- FAIL() << "Parsing failed as expected but lacks position : " << *comment
- << ", filename:" << file_name;
+ return ::testing::AssertionSuccess();
}
+
/// @brief Pointer the D2Params most recently parsed.
D2ParamsPtr d2_params_;
};
+/// @brief Convenience macros for invoking runOrConfig()
+#define RUN_CONFIG_OK(a) (runConfigOrFail(a, NO_ERROR, ""))
+#define SYNTAX_ERROR(a,b) ASSERT_TRUE(runConfigOrFail(a,SYNTAX_ERROR,b))
+#define LOGIC_ERROR(a,b) ASSERT_TRUE(runConfigOrFail(a,LOGIC_ERROR,b))
+
/// @brief Tests that the spec file is valid.
/// Verifies that the DHCP-DDNS configuration specification file
-// is valid.
+/// is valid.
TEST(D2SpecTest, basicSpec) {
ASSERT_NO_THROW(isc::config::
moduleSpecFromFile(specfile("dhcp-ddns.spec")));
}
-/// @brief Convenience function which compares the contents of the given
-/// DnsServerInfo against the given set of values.
-///
-/// It is structured in such a way that each value is checked, and output
-/// is generate for all that do not match.
-///
-/// @param server is a pointer to the server to check against.
-/// @param hostname is the value to compare against server's hostname_.
-/// @param ip_address is the string value to compare against server's
-/// ip_address_.
-/// @param port is the value to compare against server's port.
-///
-/// @return returns true if there is a match across the board, otherwise it
-/// returns false.
-bool checkServer(DnsServerInfoPtr server, const char* hostname,
- const char *ip_address, uint32_t port)
-{
- // Return value, assume its a match.
- bool result = true;
-
- if (!server) {
- EXPECT_TRUE(server);
- return false;
- }
-
- // Check hostname.
- if (server->getHostname() != hostname) {
- EXPECT_EQ(hostname, server->getHostname());
- result = false;
- }
-
- // Check IP address.
- if (server->getIpAddress().toText() != ip_address) {
- EXPECT_EQ(ip_address, server->getIpAddress().toText());
- result = false;
- }
-
- // Check port.
- if (server->getPort() != port) {
- EXPECT_EQ (port, server->getPort());
- result = false;
- }
-
- return (result);
-}
-
-/// @brief Convenience function which compares the contents of the given
-/// TSIGKeyInfo against the given set of values, and that the TSIGKey
-/// member points to a key.
-///
-/// @param key is a pointer to the TSIGKeyInfo instance to verify
-/// @param name is the value to compare against key's name_.
-/// @param algorithm is the string value to compare against key's algorithm.
-/// @param secret is the value to compare against key's secret.
-///
-/// @return returns true if there is a match across the board, otherwise it
-/// returns false.
-bool checkKey(TSIGKeyInfoPtr key, const std::string& name,
- const std::string& algorithm, const std::string& secret,
- uint32_t digestbits = 0) {
- // Return value, assume its a match.
- return (((key) &&
- (key->getName() == name) &&
- (key->getAlgorithm() == algorithm) &&
- (key->getDigestbits() == digestbits) &&
- (key->getSecret() == secret) &&
- (key->getTSIGKey())));
-}
-
-/// @brief Test fixture class for testing DnsServerInfo parsing.
-class TSIGKeyInfoTest : public ConfigParseTest {
-public:
-
- /// @brief Constructor
- TSIGKeyInfoTest() {
- }
-
- /// @brief Destructor
- ~TSIGKeyInfoTest() {
- }
-
- /// @brief Pointer to the current parser instance.
- TSIGKeyInfoParser parser_;
-};
-
-/// @brief Test fixture class for testing DnsServerInfo parsing.
-class TSIGKeyInfoListTest : public ConfigParseTest {
-public:
-
- /// @brief Constructor
- TSIGKeyInfoListTest() {
- }
-
- /// @brief Destructor
- ~TSIGKeyInfoListTest() {
- }
-
- /// @brief Pointer to the current parser instance.
- TSIGKeyInfoListParser parser_;
-};
-
-
-/// @brief Test fixture class for testing DnsServerInfo parsing.
-class DnsServerInfoTest : public ConfigParseTest {
-public:
-
- /// @brief Constructor
- DnsServerInfoTest() {
- reset();
- }
-
- /// @brief Destructor
- ~DnsServerInfoTest() {
- }
-
- /// @brief Wipe out the current storage and parser and replace
- /// them with new ones.
- void reset() {
- servers_.reset(new DnsServerInfoStorage());
- parser_.reset(new DnsServerInfoParser("test", servers_));
- }
-
- /// @brief Storage for "committing" servers.
- DnsServerInfoStoragePtr servers_;
-
- /// @brief Pointer to the current parser instance.
- isc::dhcp::ParserPtr parser_;
-};
-
-
-/// @brief Test fixture class for testing DDnsDomain parsing.
-class DdnsDomainTest : public ConfigParseTest {
-public:
-
- /// @brief Constructor
- DdnsDomainTest() {
- reset();
- }
-
- /// @brief Destructor
- ~DdnsDomainTest() {
- }
-
- /// @brief Wipe out the current storage and parser and replace
- /// them with new ones.
- void reset() {
- keys_.reset(new TSIGKeyInfoMap());
- domains_.reset(new DdnsDomainMap());
- parser_.reset(new DdnsDomainParser("test", domains_, keys_));
- }
-
- /// @brief Add TSIGKeyInfos to the key map
- ///
- /// @param name the name of the key
- /// @param algorithm the algorithm of the key
- /// @param secret the secret value of the key
- void addKey(const std::string& name, const std::string& algorithm,
- const std::string& secret) {
- TSIGKeyInfoPtr key_info(new TSIGKeyInfo(name, algorithm, secret));
- (*keys_)[name]=key_info;
- }
-
- /// @brief Storage for "committing" domains.
- DdnsDomainMapPtr domains_;
-
- /// @brief Storage for TSIGKeys
- TSIGKeyInfoMapPtr keys_;
-
- /// @brief Pointer to the current parser instance.
- isc::dhcp::ParserPtr parser_;
-};
-
/// @brief Tests a basic valid configuration for D2Param.
TEST_F(D2CfgMgrTest, validParamsEntry) {
// Verify that ip_address can be valid v4 address.
std::string config = makeParamsConfigString ("192.0.0.1", 777, 333,
"UDP", "JSON");
- runConfig(config);
+ RUN_CONFIG_OK(config);
EXPECT_EQ(isc::asiolink::IOAddress("192.0.0.1"),
d2_params_->getIpAddress());
// Verify that ip_address can be valid v6 address.
config = makeParamsConfigString ("3001::5", 777, 333, "UDP", "JSON");
- runConfig(config);
+ RUN_CONFIG_OK(config);
// Verify that the global scalars have the proper values.
EXPECT_EQ(isc::asiolink::IOAddress("3001::5"),
"\"reverse-ddns\" : {} "
"}";
- runConfig(config);
+ RUN_CONFIG_OK(config);
ConstElementPtr deflt;
ASSERT_NO_THROW(deflt = defaults->get("ip-address"));
ASSERT_TRUE(deflt);
"\"reverse-ddns\" : {} "
"}";
- runConfig(config);
+ RUN_CONFIG_OK(config);
ASSERT_NO_THROW(deflt = defaults->get("port"));
ASSERT_TRUE(deflt);
EXPECT_EQ(deflt->intValue(), d2_params_->getPort());
"\"reverse-ddns\" : {} "
"}";
- runConfig(config);
+ RUN_CONFIG_OK(config);
ASSERT_NO_THROW(deflt = defaults->get("dns-server-timeout"));
ASSERT_TRUE(deflt);
EXPECT_EQ(deflt->intValue(), d2_params_->getDnsServerTimeout());
"\"reverse-ddns\" : {} "
"}";
- runConfig(config);
+ RUN_CONFIG_OK(config);
ASSERT_NO_THROW(deflt = defaults->get("ncr-protocol"));
ASSERT_TRUE(deflt);
EXPECT_EQ(dhcp_ddns::stringToNcrProtocol(deflt->stringValue()),
"\"reverse-ddns\" : {} "
"}";
- runConfig(config);
+ RUN_CONFIG_OK(config);
ASSERT_NO_THROW(deflt = defaults->get("ncr-format"));
ASSERT_TRUE(deflt);
EXPECT_EQ(dhcp_ddns::stringToNcrFormat(deflt->stringValue()),
"\"bogus-param\" : true "
"}";
- runConfig(config, SHOULD_FAIL);
+ SYNTAX_ERROR(config, "<string>:1.181-193: got unexpected "
+ "keyword \"bogus-param\" in DhcpDdns map.");
// Check that unsupported top level objects fails. For
// D2 these fail as they are not in the parse order.
"\"bogus-object-two\" : {} "
"}";
- runConfig(config, SHOULD_FAIL);
+ SYNTAX_ERROR(config, "<string>:1.139-156: got unexpected"
+ " keyword \"bogus-object-one\" in DhcpDdns map.");
}
// Cannot use IPv4 ANY address
std::string config = makeParamsConfigString ("0.0.0.0", 777, 333,
"UDP", "JSON");
- runConfig(config, SHOULD_FAIL);
+ LOGIC_ERROR(config, "IP address cannot be \"0.0.0.0\" (<string>:1:17)");
// Cannot use IPv6 ANY address
config = makeParamsConfigString ("::", 777, 333, "UDP", "JSON");
- runConfig(config, SHOULD_FAIL);
+ LOGIC_ERROR(config, "IP address cannot be \"::\" (<string>:1:17)");
// Cannot use port 0
config = makeParamsConfigString ("127.0.0.1", 0, 333, "UDP", "JSON");
- runConfig(config, SHOULD_FAIL);
+ SYNTAX_ERROR(config, "<string>:1.40: port must be greater than zero");
// Cannot use dns server timeout of 0
config = makeParamsConfigString ("127.0.0.1", 777, 0, "UDP", "JSON");
- runConfig(config, SHOULD_FAIL);
+ SYNTAX_ERROR(config, "<string>:1.69: dns-server-timeout"
+ " must be greater than zero");
// Invalid protocol
config = makeParamsConfigString ("127.0.0.1", 777, 333, "BOGUS", "JSON");
- runConfig(config, SHOULD_FAIL);
+ SYNTAX_ERROR(config, "<string>:1.92-98: syntax error,"
+ " unexpected constant string, expecting UDP or TCP");
// Unsupported protocol
config = makeParamsConfigString ("127.0.0.1", 777, 333, "TCP", "JSON");
- runConfig(config, SHOULD_FAIL);
+ LOGIC_ERROR(config, "ncr-protocol : TCP is not yet supported"
+ " (<string>:1:92)");
// Invalid format
config = makeParamsConfigString ("127.0.0.1", 777, 333, "UDP", "BOGUS");
- runConfig(config, SHOULD_FAIL);
-}
-
-/// @brief Tests the enforcement of data validation when parsing TSIGKeyInfos.
-/// It verifies that:
-/// 1. Name cannot be blank.
-/// 2. Algorithm cannot be blank.
-/// 3. Secret cannot be blank.
-TEST_F(TSIGKeyInfoTest, invalidEntry) {
- // Config with a blank name entry.
- std::string config = "{"
- " \"name\": \"\" , "
- " \"algorithm\": \"HMAC-MD5\" , "
- " \"secret\": \"LSWXnfkKZjdPJI5QxlpnfQ==\" "
- "}";
- ASSERT_TRUE(fromJSON(config));
-
- // Verify that build fails on blank name.
- EXPECT_THROW(parser_.parse(config_set_), D2CfgError);
-
- // Config with a blank algorithm entry.
- config = "{"
- " \"name\": \"d2_key_one\" , "
- " \"algorithm\": \"\" , "
- " \"secret\": \"LSWXnfkKZjdPJI5QxlpnfQ==\" "
- "}";
-
- ASSERT_TRUE(fromJSON(config));
-
- // Verify that build fails on blank algorithm.
- EXPECT_THROW(parser_.parse(config_set_), D2CfgError);
-
- // Config with an invalid algorithm entry.
- config = "{"
- " \"name\": \"d2_key_one\" , "
- " \"algorithm\": \"bogus\" , "
- " \"secret\": \"LSWXnfkKZjdPJI5QxlpnfQ==\" "
- "}";
-
- ASSERT_TRUE(fromJSON(config));
-
- // Verify that build fails on blank algorithm.
- EXPECT_THROW(parser_.parse(config_set_), D2CfgError);
-
- // Config with a blank secret entry.
- config = "{"
- " \"name\": \"d2_key_one\" , "
- " \"algorithm\": \"HMAC-MD5\" , "
- " \"secret\": \"\" "
- "}";
-
- ASSERT_TRUE(fromJSON(config));
-
- // Verify that build fails blank secret
- EXPECT_THROW(parser_.parse(config_set_), D2CfgError);
-
- // Config with an invalid secret entry.
- config = "{"
- " \"name\": \"d2_key_one\" , "
- " \"algorithm\": \"HMAC-MD5\" , "
- " \"secret\": \"bogus\" "
- "}";
-
- ASSERT_TRUE(fromJSON(config));
-
- // Verify that build fails an invalid secret
- EXPECT_THROW(parser_.parse(config_set_), D2CfgError);
-}
-
-/// @brief Verifies that TSIGKeyInfo parsing creates a proper TSIGKeyInfo
-/// when given a valid combination of entries.
-TEST_F(TSIGKeyInfoTest, validEntry) {
- // Valid entries for TSIG key, all items are required.
- std::string config = "{"
- " \"name\": \"d2_key_one\" , "
- " \"algorithm\": \"HMAC-MD5\" , "
- " \"digest-bits\": 120 , "
- " \"secret\": \"dGhpcyBrZXkgd2lsbCBtYXRjaA==\" "
- "}";
- ASSERT_TRUE(fromJSON(config));
-
- // Verify that it builds and commits without throwing.
- //ASSERT_NO_THROW(parser_->build(config_set_));
- TSIGKeyInfoPtr key;
- ASSERT_NO_THROW(key = parser_.parse(config_set_));
- ASSERT_TRUE(key);
-
- // Verify the key contents.
- EXPECT_TRUE(checkKey(key, "d2_key_one", "HMAC-MD5",
- "dGhpcyBrZXkgd2lsbCBtYXRjaA==", 120));
-}
-
-/// @brief Verifies that attempting to parse an invalid list of TSIGKeyInfo
-/// entries is detected.
-TEST_F(TSIGKeyInfoListTest, invalidTSIGKeyList) {
- // Construct a list of keys with an invalid key entry.
- std::string config = "["
-
- " { \"name\": \"key1\" , "
- " \"algorithm\": \"HMAC-MD5\" ,"
- " \"digest-bits\": 120 , "
- " \"secret\": \"GWG/Xfbju4O2iXGqkSu4PQ==\" "
- " },"
- // this entry has an invalid algorithm
- " { \"name\": \"key2\" , "
- " \"algorithm\": \"\" ,"
- " \"digest-bits\": 120 , "
- " \"secret\": \"GWG/Xfbju4O2iXGqkSu4PQ==\" "
- " },"
- " { \"name\": \"key3\" , "
- " \"algorithm\": \"HMAC-MD5\" ,"
- " \"secret\": \"GWG/Xfbju4O2iXGqkSu4PQ==\" "
- " }"
- " ]";
-
- ASSERT_TRUE(fromJSON(config));
-
- // Verify that the list builds with errors.
- EXPECT_THROW(parser_.parse(config_set_), D2CfgError);
-}
-
-/// @brief Verifies that attempting to parse an invalid list of TSIGKeyInfo
-/// entries is detected.
-TEST_F(TSIGKeyInfoListTest, duplicateTSIGKey) {
- // Construct a list of keys with an invalid key entry.
- std::string config = "["
- " { \"name\": \"key1\" , "
- " \"algorithm\": \"HMAC-MD5\" ,"
- " \"digest-bits\": 120 , "
- " \"secret\": \"GWG/Xfbju4O2iXGqkSu4PQ==\" "
- " },"
- " { \"name\": \"key2\" , "
- " \"algorithm\": \"HMAC-MD5\" ,"
- " \"digest-bits\": 120 , "
- " \"secret\": \"GWG/Xfbju4O2iXGqkSu4PQ==\" "
- " },"
- " { \"name\": \"key1\" , "
- " \"algorithm\": \"HMAC-MD5\" ,"
- " \"secret\": \"GWG/Xfbju4O2iXGqkSu4PQ==\" "
- " }"
- " ]";
-
- ASSERT_TRUE(fromJSON(config));
-
- // Verify that the list builds without errors.
- EXPECT_THROW(parser_.parse(config_set_), D2CfgError);
-}
-
-/// @brief Verifies a valid list of TSIG Keys parses correctly.
-/// Also verifies that all of the supported algorithm names work.
-TEST_F(TSIGKeyInfoListTest, validTSIGKeyList) {
- // Construct a valid list of keys.
- std::string config = "["
-
- " { \"name\": \"key1\" , "
- " \"algorithm\": \"HMAC-MD5\" ,"
- " \"digest-bits\": 80 , "
- " \"secret\": \"dGhpcyBrZXkgd2lsbCBtYXRjaA==\" "
- " },"
- " { \"name\": \"key2\" , "
- " \"algorithm\": \"HMAC-SHA1\" ,"
- " \"digest-bits\": 80 , "
- " \"secret\": \"dGhpcyBrZXkgd2lsbCBtYXRjaA==\" "
- " },"
- " { \"name\": \"key3\" , "
- " \"algorithm\": \"HMAC-SHA256\" ,"
- " \"digest-bits\": 128 , "
- " \"secret\": \"dGhpcyBrZXkgd2lsbCBtYXRjaA==\" "
- " },"
- " { \"name\": \"key4\" , "
- " \"algorithm\": \"HMAC-SHA224\" ,"
- " \"digest-bits\": 112 , "
- " \"secret\": \"dGhpcyBrZXkgd2lsbCBtYXRjaA==\" "
- " },"
- " { \"name\": \"key5\" , "
- " \"algorithm\": \"HMAC-SHA384\" ,"
- " \"digest-bits\": 192 , "
- " \"secret\": \"dGhpcyBrZXkgd2lsbCBtYXRjaA==\" "
- " },"
- " { \"name\": \"key6\" , "
- " \"algorithm\": \"HMAC-SHA512\" ,"
- " \"digest-bits\": 256 , "
- " \"secret\": \"dGhpcyBrZXkgd2lsbCBtYXRjaA==\" "
- " }"
- " ]";
-
- ASSERT_TRUE(fromJSON(config));
- TSIGKeyInfoMapPtr keys;
- ASSERT_NO_THROW(keys = parser_.parse(config_set_));
-
- std::string ref_secret = "dGhpcyBrZXkgd2lsbCBtYXRjaA==";
- // Verify the correct number of keys are present
- int count = keys->size();
- ASSERT_EQ(6, count);
-
- // Find the 1st key and retrieve it.
- TSIGKeyInfoMap::iterator gotit = keys->find("key1");
- ASSERT_TRUE(gotit != keys->end());
- TSIGKeyInfoPtr& key = gotit->second;
-
- // Verify the key contents.
- EXPECT_TRUE(checkKey(key, "key1", TSIGKeyInfo::HMAC_MD5_STR,
- ref_secret, 80));
-
- // Find the 2nd key and retrieve it.
- gotit = keys->find("key2");
- ASSERT_TRUE(gotit != keys->end());
- key = gotit->second;
-
- // Verify the key contents.
- EXPECT_TRUE(checkKey(key, "key2", TSIGKeyInfo::HMAC_SHA1_STR,
- ref_secret, 80));
-
- // Find the 3rd key and retrieve it.
- gotit = keys->find("key3");
- ASSERT_TRUE(gotit != keys->end());
- key = gotit->second;
-
- // Verify the key contents.
- EXPECT_TRUE(checkKey(key, "key3", TSIGKeyInfo::HMAC_SHA256_STR,
- ref_secret, 128));
-
- // Find the 4th key and retrieve it.
- gotit = keys->find("key4");
- ASSERT_TRUE(gotit != keys->end());
- key = gotit->second;
-
- // Verify the key contents.
- EXPECT_TRUE(checkKey(key, "key4", TSIGKeyInfo::HMAC_SHA224_STR,
- ref_secret, 112));
-
- // Find the 5th key and retrieve it.
- gotit = keys->find("key5");
- ASSERT_TRUE(gotit != keys->end());
- key = gotit->second;
-
- // Verify the key contents.
- EXPECT_TRUE(checkKey(key, "key5", TSIGKeyInfo::HMAC_SHA384_STR,
- ref_secret, 192));
-
- // Find the 6th key and retrieve it.
- gotit = keys->find("key6");
- ASSERT_TRUE(gotit != keys->end());
- key = gotit->second;
-
- // Verify the key contents.
- EXPECT_TRUE(checkKey(key, "key6", TSIGKeyInfo::HMAC_SHA512_STR,
- ref_secret, 256));
-}
-
-/// @brief Tests the enforcement of data validation when parsing DnsServerInfos.
-/// It verifies that:
-/// 1. Specifying both a hostname and an ip address is not allowed.
-/// 2. Specifying both blank a hostname and blank ip address is not allowed.
-/// 3. Specifying a negative port number is not allowed.
-TEST_F(DnsServerInfoTest, invalidEntry) {
- // Create a config in which both host and ip address are supplied.
- // Verify that build fails.
- std::string config = "{ \"hostname\": \"pegasus.tmark\", "
- " \"ip-address\": \"127.0.0.1\" } ";
- ASSERT_TRUE(fromJSON(config));
- EXPECT_THROW(parser_->build(config_set_), D2CfgError);
-
- // Neither host nor ip address supplied
- // Verify that builds fails.
- config = "{ \"hostname\": \"\", "
- " \"ip-address\": \"\" } ";
- ASSERT_TRUE(fromJSON(config));
- EXPECT_THROW(parser_->build(config_set_), D2CfgError);
-
- // Create a config with a negative port number.
- // Verify that build fails.
- config = "{ \"ip-address\": \"192.168.5.6\" ,"
- " \"port\": -100 }";
- ASSERT_TRUE(fromJSON(config));
- EXPECT_THROW (parser_->build(config_set_), isc::BadValue);
-}
-
-
-/// @brief Verifies that DnsServerInfo parsing creates a proper DnsServerInfo
-/// when given a valid combination of entries.
-/// It verifies that:
-/// 1. A DnsServerInfo entry is correctly made, when given only a hostname.
-/// 2. A DnsServerInfo entry is correctly made, when given ip address and port.
-/// 3. A DnsServerInfo entry is correctly made, when given only an ip address.
-TEST_F(DnsServerInfoTest, validEntry) {
- /// @todo When resolvable hostname is supported you'll need this test.
- /// // Valid entries for dynamic host
- /// std::string config = "{ \"hostname\": \"pegasus.tmark\" }";
- /// ASSERT_TRUE(fromJSON(config));
-
- /// // Verify that it builds and commits without throwing.
- /// ASSERT_NO_THROW(parser_->build(config_set_));
- /// ASSERT_NO_THROW(parser_->commit());
-
- /// //Verify the correct number of servers are present
- /// int count = servers_->size();
- /// EXPECT_EQ(1, count);
-
- /// Verify the server exists and has the correct values.
- /// DnsServerInfoPtr server = (*servers_)[0];
- /// EXPECT_TRUE(checkServer(server, "pegasus.tmark",
- /// DnsServerInfo::EMPTY_IP_STR,
- /// DnsServerInfo::STANDARD_DNS_PORT));
-
- /// // Start over for a new test.
- /// reset();
-
- // Valid entries for static ip
- std::string config = " { \"ip-address\": \"127.0.0.1\" , "
- " \"port\": 100 }";
- ASSERT_TRUE(fromJSON(config));
-
- // Verify that it builds and commits without throwing.
- ASSERT_NO_THROW(parser_->build(config_set_));
- ASSERT_NO_THROW(parser_->commit());
-
- // Verify the correct number of servers are present
- int count = servers_->size();
- EXPECT_EQ(1, count);
-
- // Verify the server exists and has the correct values.
- DnsServerInfoPtr server = (*servers_)[0];
- EXPECT_TRUE(checkServer(server, "", "127.0.0.1", 100));
-
- // Start over for a new test.
- reset();
-
- // Valid entries for static ip, no port
- config = " { \"ip-address\": \"192.168.2.5\" }";
- ASSERT_TRUE(fromJSON(config));
-
- // Verify that it builds and commits without throwing.
- ASSERT_NO_THROW(parser_->build(config_set_));
- ASSERT_NO_THROW(parser_->commit());
-
- // Verify the correct number of servers are present
- count = servers_->size();
- EXPECT_EQ(1, count);
-
- // Verify the server exists and has the correct values.
- server = (*servers_)[0];
- EXPECT_TRUE(checkServer(server, "", "192.168.2.5",
- DnsServerInfo::STANDARD_DNS_PORT));
-}
-
-/// @brief Verifies that attempting to parse an invalid list of DnsServerInfo
-/// entries is detected.
-TEST_F(ConfigParseTest, invalidServerList) {
- // Construct a list of servers with an invalid server entry.
- std::string config = "[ { \"ip-address\": \"127.0.0.1\" }, "
- "{ \"ip-address\": \"\" }, "
- "{ \"ip-address\": \"127.0.0.2\" } ]";
- ASSERT_TRUE(fromJSON(config));
-
- // Create the server storage and list parser.
- DnsServerInfoStoragePtr servers(new DnsServerInfoStorage());
- isc::dhcp::ParserPtr parser;
- ASSERT_NO_THROW(parser.reset(new DnsServerInfoListParser("test", servers)));
-
- // Verify that build fails.
- EXPECT_THROW(parser->build(config_set_), D2CfgError);
-}
-
-/// @brief Verifies that a list of DnsServerInfo entries parses correctly given
-/// a valid configuration.
-TEST_F(ConfigParseTest, validServerList) {
- // Create a valid list of servers.
- std::string config = "[ { \"ip-address\": \"127.0.0.1\" }, "
- "{ \"ip-address\": \"127.0.0.2\" }, "
- "{ \"ip-address\": \"127.0.0.3\" } ]";
- ASSERT_TRUE(fromJSON(config));
-
- // Create the server storage and list parser.
- DnsServerInfoStoragePtr servers(new DnsServerInfoStorage());
- isc::dhcp::ParserPtr parser;
- ASSERT_NO_THROW(parser.reset(new DnsServerInfoListParser("test", servers)));
-
- // Verfiy that the list builds and commits without error.
- ASSERT_NO_THROW(parser->build(config_set_));
- ASSERT_NO_THROW(parser->commit());
-
- // Verify that the server storage contains the correct number of servers.
- int count = servers->size();
- EXPECT_EQ(3, count);
-
- // Verify the first server exists and has the correct values.
- DnsServerInfoPtr server = (*servers)[0];
- EXPECT_TRUE(checkServer(server, "", "127.0.0.1",
- DnsServerInfo::STANDARD_DNS_PORT));
-
- // Verify the second server exists and has the correct values.
- server = (*servers)[1];
- EXPECT_TRUE(checkServer(server, "", "127.0.0.2",
- DnsServerInfo::STANDARD_DNS_PORT));
-
- // Verify the third server exists and has the correct values.
- server = (*servers)[2];
- EXPECT_TRUE(checkServer(server, "", "127.0.0.3",
- DnsServerInfo::STANDARD_DNS_PORT));
-}
-
-/// @brief Tests the enforcement of data validation when parsing DdnsDomains.
-/// It verifies that:
-/// 1. Domain storage cannot be null when constructing a DdnsDomainParser.
-/// 2. The name entry is not optional.
-/// 3. The server list man not be empty.
-/// 4. That a mal-formed server entry is detected.
-/// 5. That an undefined key name is detected.
-TEST_F(DdnsDomainTest, invalidDdnsDomainEntry) {
- // Verify that attempting to construct the parser with null storage fails.
- DdnsDomainMapPtr domains;
- ASSERT_THROW(isc::dhcp::ParserPtr(
- new DdnsDomainParser("test", domains, keys_)), D2CfgError);
-
- // Create a domain configuration without a name
- std::string config = "{ \"key-name\": \"d2_key.tmark.org\" , "
- " \"dns-servers\" : [ "
- " { \"ip-address\": \"127.0.0.1\" , "
- " \"port\": 100 },"
- " { \"ip-address\": \"127.0.0.2\" , "
- " \"port\": 200 },"
- " { \"ip-address\": \"127.0.0.3\" , "
- " \"port\": 300 } ] } ";
- ASSERT_TRUE(fromJSON(config));
-
- // Verify that the domain configuration builds fails.
- EXPECT_THROW(parser_->build(config_set_), D2CfgError);
-
- // Create a domain configuration with an empty server list.
- config = "{ \"name\": \"tmark.org\" , "
- " \"key-name\": \"d2_key.tmark.org\" , "
- " \"dns-servers\" : [ "
- " ] } ";
- ASSERT_TRUE(fromJSON(config));
-
- // Verify that the domain configuration build fails.
- EXPECT_THROW(parser_->build(config_set_), D2CfgError);
-
- // Create a domain configuration with a mal-formed server entry.
- config = "{ \"name\": \"tmark.org\" , "
- " \"key-name\": \"d2_key.tmark.org\" , "
- " \"dns-servers\" : [ "
- " { \"ip-address\": \"127.0.0.3\" , "
- " \"port\": -1 } ] } ";
- ASSERT_TRUE(fromJSON(config));
-
- // Verify that the domain configuration build fails.
- EXPECT_THROW(parser_->build(config_set_), isc::BadValue);
-
- // Create a domain configuration without an defined key name
- config = "{ \"name\": \"tmark.org\" , "
- " \"key-name\": \"d2_key.tmark.org\" , "
- " \"dns-servers\" : [ "
- " { \"ip-address\": \"127.0.0.3\" , "
- " \"port\": 300 } ] } ";
- ASSERT_TRUE(fromJSON(config));
-
- // Verify that the domain configuration build fails.
- EXPECT_THROW(parser_->build(config_set_), D2CfgError);
-}
-
-/// @brief Verifies the basics of parsing DdnsDomains.
-/// It verifies that:
-/// 1. Valid construction of DdnsDomainParser functions.
-/// 2. Given a valid, configuration entry, DdnsDomainParser parses
-/// correctly.
-/// (It indirectly verifies the operation of DdnsDomainMap).
-TEST_F(DdnsDomainTest, ddnsDomainParsing) {
- // Create a valid domain configuration entry containing three valid
- // servers.
- std::string config =
- "{ \"name\": \"tmark.org\" , "
- " \"key-name\": \"d2_key.tmark.org\" , "
- " \"dns-servers\" : [ "
- " { \"ip-address\": \"127.0.0.1\" , "
- " \"port\": 100 },"
- " { \"ip-address\": \"127.0.0.2\" , "
- " \"port\": 200 },"
- " { \"ip-address\": \"127.0.0.3\" , "
- " \"port\": 300 } ] } ";
- ASSERT_TRUE(fromJSON(config));
-
- // Add a TSIG key to the test key map, so key validation will pass.
- addKey("d2_key.tmark.org", "HMAC-MD5", "GWG/Xfbju4O2iXGqkSu4PQ==");
-
- // Verify that the domain configuration builds and commits without error.
- ASSERT_NO_THROW(parser_->build(config_set_));
- ASSERT_NO_THROW(parser_->commit());
-
- // Verify that the domain storage contains the correct number of domains.
- int count = domains_->size();
- EXPECT_EQ(1, count);
-
- // Verify that the expected domain exists and can be retrieved from
- // the storage.
- DdnsDomainMap::iterator gotit = domains_->find("tmark.org");
- ASSERT_TRUE(gotit != domains_->end());
- DdnsDomainPtr& domain = gotit->second;
-
- // Verify the name and key_name values.
- EXPECT_EQ("tmark.org", domain->getName());
- EXPECT_EQ("d2_key.tmark.org", domain->getKeyName());
- ASSERT_TRUE(domain->getTSIGKeyInfo());
- ASSERT_TRUE(domain->getTSIGKeyInfo()->getTSIGKey());
-
- // Verify that the server list exists and contains the correct number of
- // servers.
- const DnsServerInfoStoragePtr& servers = domain->getServers();
- EXPECT_TRUE(servers);
- count = servers->size();
- EXPECT_EQ(3, count);
-
- // Fetch each server and verify its contents.
- DnsServerInfoPtr server = (*servers)[0];
- EXPECT_TRUE(server);
-
- EXPECT_TRUE(checkServer(server, "", "127.0.0.1", 100));
-
- server = (*servers)[1];
- EXPECT_TRUE(server);
-
- EXPECT_TRUE(checkServer(server, "", "127.0.0.2", 200));
-
- server = (*servers)[2];
- EXPECT_TRUE(server);
-
- EXPECT_TRUE(checkServer(server, "", "127.0.0.3", 300));
-}
-
-/// @brief Tests the fundamentals of parsing DdnsDomain lists.
-/// This test verifies that given a valid domain list configuration
-/// it will accurately parse and populate each domain in the list.
-TEST_F(DdnsDomainTest, DdnsDomainListParsing) {
- // Create a valid domain list configuration, with two domains
- // that have three servers each.
- std::string config =
- "[ "
- "{ \"name\": \"tmark.org\" , "
- " \"key-name\": \"d2_key.tmark.org\" , "
- " \"dns-servers\" : [ "
- " { \"ip-address\": \"127.0.0.1\" , "
- " \"port\": 100 },"
- " { \"ip-address\": \"127.0.0.2\" , "
- " \"port\": 200 },"
- " { \"ip-address\": \"127.0.0.3\" , "
- " \"port\": 300 } ] } "
- ", "
- "{ \"name\": \"billcat.net\" , "
- " \"key-name\": \"d2_key.billcat.net\" , "
- " \"dns-servers\" : [ "
- " { \"ip-address\": \"127.0.0.4\" , "
- " \"port\": 400 },"
- " { \"ip-address\": \"127.0.0.5\" , "
- " \"port\": 500 },"
- " { \"ip-address\": \"127.0.0.6\" , "
- " \"port\": 600 } ] } "
- "] ";
-
- ASSERT_TRUE(fromJSON(config));
-
- // Add keys to key map so key validation passes.
- addKey("d2_key.tmark.org", "HMAC-MD5", "GWG/Xfbju4O2iXGqkSu4PQ==");
- addKey("d2_key.billcat.net", "HMAC-MD5", "GWG/Xfbju4O2iXGqkSu4PQ==");
-
- // Create the list parser
- isc::dhcp::ParserPtr list_parser;
- ASSERT_NO_THROW(list_parser.reset(
- new DdnsDomainListParser("test", domains_, keys_)));
-
- // Verify that the domain configuration builds and commits without error.
- ASSERT_NO_THROW(list_parser->build(config_set_));
- ASSERT_NO_THROW(list_parser->commit());
-
- // Verify that the domain storage contains the correct number of domains.
- int count = domains_->size();
- EXPECT_EQ(2, count);
-
- // Verify that the first domain exists and can be retrieved.
- DdnsDomainMap::iterator gotit = domains_->find("tmark.org");
- ASSERT_TRUE(gotit != domains_->end());
- DdnsDomainPtr& domain = gotit->second;
-
- // Verify the name and key_name values of the first domain.
- EXPECT_EQ("tmark.org", domain->getName());
- EXPECT_EQ("d2_key.tmark.org", domain->getKeyName());
- ASSERT_TRUE(domain->getTSIGKeyInfo());
- ASSERT_TRUE(domain->getTSIGKeyInfo()->getTSIGKey());
-
- // Verify the each of the first domain's servers
- DnsServerInfoStoragePtr servers = domain->getServers();
- EXPECT_TRUE(servers);
- count = servers->size();
- EXPECT_EQ(3, count);
-
- DnsServerInfoPtr server = (*servers)[0];
- EXPECT_TRUE(server);
- EXPECT_TRUE(checkServer(server, "", "127.0.0.1", 100));
-
- server = (*servers)[1];
- EXPECT_TRUE(server);
- EXPECT_TRUE(checkServer(server, "", "127.0.0.2", 200));
-
- server = (*servers)[2];
- EXPECT_TRUE(server);
- EXPECT_TRUE(checkServer(server, "", "127.0.0.3", 300));
-
- // Verify second domain
- gotit = domains_->find("billcat.net");
- ASSERT_TRUE(gotit != domains_->end());
- domain = gotit->second;
-
- // Verify the name and key_name values of the second domain.
- EXPECT_EQ("billcat.net", domain->getName());
- EXPECT_EQ("d2_key.billcat.net", domain->getKeyName());
- ASSERT_TRUE(domain->getTSIGKeyInfo());
- ASSERT_TRUE(domain->getTSIGKeyInfo()->getTSIGKey());
-
- // Verify the each of second domain's servers
- servers = domain->getServers();
- EXPECT_TRUE(servers);
- count = servers->size();
- EXPECT_EQ(3, count);
-
- server = (*servers)[0];
- EXPECT_TRUE(server);
- EXPECT_TRUE(checkServer(server, "", "127.0.0.4", 400));
-
- server = (*servers)[1];
- EXPECT_TRUE(server);
- EXPECT_TRUE(checkServer(server, "", "127.0.0.5", 500));
-
- server = (*servers)[2];
- EXPECT_TRUE(server);
- EXPECT_TRUE(checkServer(server, "", "127.0.0.6", 600));
-}
-
-/// @brief Tests that a domain list configuration cannot contain duplicates.
-TEST_F(DdnsDomainTest, duplicateDomain) {
- // Create a domain list configuration that contains two domains with
- // the same name.
- std::string config =
- "[ "
- "{ \"name\": \"tmark.org\" , "
- " \"dns-servers\" : [ "
- " { \"ip-address\": \"127.0.0.3\" , "
- " \"port\": 300 } ] } "
- ", "
- "{ \"name\": \"tmark.org\" , "
- " \"dns-servers\" : [ "
- " { \"ip-address\": \"127.0.0.3\" , "
- " \"port\": 300 } ] } "
- "] ";
- ASSERT_TRUE(fromJSON(config));
-
- // Create the list parser
- isc::dhcp::ParserPtr list_parser;
- ASSERT_NO_THROW(list_parser.reset(
- new DdnsDomainListParser("test", domains_, keys_)));
-
- // Verify that the parse build fails.
- EXPECT_THROW(list_parser->build(config_set_), D2CfgError);
-}
-
-/// @brief Tests construction of D2CfgMgr
-/// This test verifies that a D2CfgMgr constructs properly.
-TEST(D2CfgMgr, construction) {
- boost::scoped_ptr<D2CfgMgr> cfg_mgr;
-
- // Verify that configuration manager constructions without error.
- ASSERT_NO_THROW(cfg_mgr.reset(new D2CfgMgr()));
-
- // Verify that the context can be retrieved and is not null.
- D2CfgContextPtr context;
- ASSERT_NO_THROW(context = cfg_mgr->getD2CfgContext());
- EXPECT_TRUE(context);
-
- // Verify that the forward manager can be retrieved and is not null.
- EXPECT_TRUE(context->getForwardMgr());
-
- // Verify that the reverse manager can be retrieved and is not null.
- EXPECT_TRUE(context->getReverseMgr());
-
- // Verify that the manager can be destructed without error.
- EXPECT_NO_THROW(cfg_mgr.reset());
+ SYNTAX_ERROR(config, "<string>:1.115-121: syntax error,"
+ " unexpected constant string, expecting JSON");
}
/// @brief Tests the parsing of a complete, valid DHCP-DDNS configuration.
" ] } "
"] } }";
- ASSERT_TRUE(fromJSON(config));
-
- // Verify that we can parse the configuration.
- answer_ = cfg_mgr_->parseConfig(config_set_);
- ASSERT_TRUE(checkAnswer(0));
+ // Should parse without error.
+ RUN_CONFIG_OK(config);
// Verify that the D2 context can be retrieved and is not null.
D2CfgContextPtr context;
"\"reverse-ddns\" : {} "
"}";
-
- ASSERT_TRUE(fromJSON(config));
// Verify that we can parse the configuration.
- answer_ = cfg_mgr_->parseConfig(config_set_);
- ASSERT_TRUE(checkAnswer(0));
+ RUN_CONFIG_OK(config);
// Verify that the D2 context can be retrieved and is not null.
D2CfgContextPtr context;
"\"reverse-ddns\" : {} "
" }";
- ASSERT_TRUE(fromJSON(config));
-
// Verify that we can parse the configuration.
- answer_ = cfg_mgr_->parseConfig(config_set_);
- ASSERT_TRUE(checkAnswer(0));
+ RUN_CONFIG_OK(config);
// Verify that the D2 context can be retrieved and is not null.
D2CfgContextPtr context;
"\"reverse-ddns\" : {} "
"}";
- ASSERT_TRUE(fromJSON(config));
-
// Verify that we can parse the configuration.
- answer_ = cfg_mgr_->parseConfig(config_set_);
- ASSERT_TRUE(checkAnswer(0));
+ RUN_CONFIG_OK(config);
// Verify that the D2 context can be retrieved and is not null.
D2CfgContextPtr context;
" ] } "
"] } }";
- ASSERT_TRUE(fromJSON(config));
-
// Verify that we can parse the configuration.
- answer_ = cfg_mgr_->parseConfig(config_set_);
- ASSERT_TRUE(checkAnswer(0));
+ RUN_CONFIG_OK(config);
// Verify that the D2 context can be retrieved and is not null.
D2CfgContextPtr context;
///
/// # Each test has:
/// # 1. description - optional text description
-/// # 2. syntax-error - text of syntax error D2Parser is expected to emit
-/// # (defaults to blank = no error expected)
-/// # 3. logic-error - indicator if post-parsing element logic should fail
-/// # (defaults to false)
+/// # 2. syntax-error - error JSON parser should emit (omit if none)
+/// # 3. logic-error - error element parser(s) should emit (omit if none)
/// # 4. data - configuration text to parse
/// #
/// "description" : "<text describing test>",
-/// "syntax-error" : ""|"<exact text from parser including position>" ,
-/// "logic_error" : <true|false> ,
+/// "syntax-error" : "<exact text from JSON parser including position>" ,
+/// "logic-error" : "<exact text from element parser including position>" ,
/// "data" :
/// {
/// # configuration elements here
// Read in each test For each test, read:
//
// 1. description - optional text description
- // 2. syntax-error - error text JSON parser should emit including position,
- // defaults to blank (i.e. no error)
- // 3. logic-error - bool indicator if post-JSON element processing should
- // fail
- // (defaults to false)
- // 4. data - configuration text to parse
- //
- // Next attempt to parse the configuration by passing it into
- // D2CfgMgr::parseConfig(). Then check the parsing outcome against the
- // expected outcome as given by logic-error.
+ // 2. syntax-error or logic-error or neither
+ // 3. data - configuration text to parse
+ // 4. convert data into JSON text
+ // 5. submit JSON for parsing
isc::data::ConstElementPtr test;
ASSERT_TRUE(tests->get("test-list"));
BOOST_FOREACH(test, tests->get("test-list")->listValue()) {
-
// Grab the description.
std::string description = "<no desc>";
isc::data::ConstElementPtr elem = test->get("description");
elem->getValue(description);
}
- // Grab the outcome flag, logic-error, defaults to false if it's
- // not specified.
- bool logic_error = false;
- elem = test->get("logic-error");
- if (elem) {
- elem->getValue(logic_error);
- }
-
- // If the JSON parsing is expected to detect an error, the test
- // should have specified the error message text.
- std::string expected_syntax_error = "";
+ // Grab the expected error message, if there is one.
+ std::string expected_error = "";
+ RunConfigMode mode = NO_ERROR;
elem = test->get("syntax-error");
if (elem) {
- elem->getValue(expected_syntax_error);
+ elem->getValue(expected_error);
+ mode = SYNTAX_ERROR;
+ } else {
+ elem = test->get("logic-error");
+ if (elem) {
+ elem->getValue(expected_error);
+ mode = LOGIC_ERROR;
+ }
}
// Grab the test's configuration data.
ASSERT_TRUE(data) << "No data for test: "
<< " : " << test->getPosition();
- // Submit the configuration text to the D2Parser. This is somewhat
- // artifical as normally the JSON parsing is invoked by @c
- // DController::configFromFile(). Doing it here, explicitly, allows us
- // test both syntax and logic errors without the weight of a full
- // server. Currently the assumption is that the test data is the
- // content permitted within a DhcpDdns element only.
- try {
- // First we turn the test data back into JSON text
- D2ParserContext context;
- stringstream os;
- data->toJSON(os);
- // Parse the test data
- data = context.parseString(os.str(),
- D2ParserContext::PARSER_SUB_DHCPDDNS);
- } catch (const std::exception& ex) {
- if (expected_syntax_error.empty()) {
- // We have an unexpected syntax error.
- ADD_FAILURE() << description << ", "
- << "Unexpected syntax error:" << ex.what();
- } else {
- // We expected and got a syntax error, we need to make sure
- // we got the right one.
- EXPECT_EQ(expected_syntax_error, ex.what())
- << description << ", syntax error mismatch";
-
- }
-
- // Expected or not, skip logic testing on syntax errors.
- continue;
- }
-
- // Attempt to Element parse the configuration. We verify that we get the
- // expected outcome, and if it was supposed to fail that the explanation
- // contains position information.
- checkAnswerWithError(cfg_mgr_->parseConfig(data),
- (logic_error ? SHOULD_FAIL : SHOULD_PASS));
+ // Convert the test data back to JSON text, then submit it for parsing.
+ stringstream os;
+ data->toJSON(os);
+ EXPECT_TRUE(runConfigOrFail(os.str(), mode, expected_error))
+ << " failed for test: " << test->getPosition() << std::endl;
}
}
+
} // end of anonymous namespace
#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>
#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>
namespace {
-/// @brief Text fixture class for D2SimpleParser
+/// @brief Checks if specified element matches the given integer default
+///
+/// @param element defaulted element to check
+/// @param deflt SimpleDefault which supplied the default valaue
+void checkIntegerValue(const ConstElementPtr& element,
+ const SimpleDefault& deflt) {
+ ASSERT_TRUE(element);
+
+ // Verify it is an integer.
+ ASSERT_EQ(Element::integer, element->getType());
+
+ // Turn default value string into an int.
+ int64_t default_value = 0;
+ ASSERT_NO_THROW(default_value = boost::lexical_cast<int64_t>(deflt.value_));
+
+ // Verify it has the expected value.
+ EXPECT_EQ(default_value, element->intValue());
+}
+
+/// @brief Checks if specified element matches the given boolean default
+///
+/// @param element defaulted element to check
+/// @param deflt SimpleDefault which supplied the default valaue
+void checkBooleanValue(const ConstElementPtr& element,
+ const SimpleDefault& deflt) {
+ ASSERT_TRUE(element);
+
+ // Verify it is a bool.
+ ASSERT_EQ(Element::boolean, element->getType());
+
+ // Turn default value string into a bool.
+ bool default_value = false;
+ ASSERT_NO_THROW(boost::lexical_cast<bool>(deflt.value_));
+
+ // Verify it has the expected value.
+ EXPECT_EQ(default_value, element->boolValue());
+}
+
+/// @brief Checks if specified element matches the given string default
+///
+/// @param element defaulted element to check
+/// @param deflt SimpleDefault which supplied the default valaue
+void checkStringValue(const ConstElementPtr& element,
+ const SimpleDefault& deflt) {
+ ASSERT_TRUE(element);
+
+ // Verify it's a string
+ ASSERT_EQ(Element::string, element->getType());
+
+ // Verify it has the expected value
+ EXPECT_EQ(deflt.value_, element->stringValue());
+ }
+
+/// TSIGKeyInfo against the given set of values, and that the TSIGKey
+/// member points to a key.
+///
+/// @param key is a pointer to the TSIGKeyInfo instance to verify
+/// @param name is the value to compare against key's name_.
+/// @param algorithm is the string value to compare against key's algorithm.
+/// @param secret is the value to compare against key's secret.
+///
+/// @return returns true if there is a match across the board, otherwise it
+/// returns false.
+bool checkKey(TSIGKeyInfoPtr key, const std::string& name,
+ const std::string& algorithm, const std::string& secret,
+ uint32_t digestbits = 0) {
+ // Return value, assume its a match.
+ return (((key) &&
+ (key->getName() == name) &&
+ (key->getAlgorithm() == algorithm) &&
+ (key->getDigestbits() == digestbits) &&
+ (key->getSecret() == secret) &&
+ (key->getTSIGKey())));
+}
+
+/// @brief Convenience function which compares the contents of the given
+/// DnsServerInfo against the given set of values.
+///
+/// It is structured in such a way that each value is checked, and output
+/// is generate for all that do not match.
+///
+/// @param server is a pointer to the server to check against.
+/// @param hostname is the value to compare against server's hostname_.
+/// @param ip_address is the string value to compare against server's
+/// ip_address_.
+/// @param port is the value to compare against server's port.
+///
+/// @return returns true if there is a match across the board, otherwise it
+/// returns false.
+bool checkServer(DnsServerInfoPtr server, const char* hostname,
+ const char *ip_address, uint32_t port)
+{
+ // Return value, assume its a match.
+ bool result = true;
+
+ if (!server) {
+ EXPECT_TRUE(server);
+ return false;
+ }
+
+ // Check hostname.
+ if (server->getHostname() != hostname) {
+ EXPECT_EQ(hostname, server->getHostname());
+ result = false;
+ }
+
+ // Check IP address.
+ if (server->getIpAddress().toText() != ip_address) {
+ EXPECT_EQ(ip_address, server->getIpAddress().toText());
+ result = false;
+ }
+
+ // Check port.
+ if (server->getPort() != port) {
+ EXPECT_EQ (port, server->getPort());
+ result = false;
+ }
+
+ return (result);
+}
+
+/// @brief Base class test fixture for testing JSON and element parsing
+/// for D2 configuration elements. It combines the three phases of
+/// configuration parsing normally orchestrated by D2CfgMgr:
+/// 1. Submit the JSON text to the JSON parser
+/// 2. Add defaults to the element tree produced by the JSON parser
+/// 3. Pass the element tree into the appropriate SimpleParser derivation
+/// to parse the element tree into D2 objects.
class D2SimpleParserTest : public ::testing::Test {
public:
- /// @brief Checks if specified element matches the given integer default
+ /// @brief Constructor
///
- /// @param element defaulted element to check
- /// @param deflt SimpleDefault which supplied the default valaue
- void checkIntegerValue(const ConstElementPtr& element, const SimpleDefault& deflt) {
- ASSERT_TRUE(element);
-
- // Verify it is an integer.
- ASSERT_EQ(Element::integer, element->getType());
-
- // Turn default value string into an int.
- int64_t default_value = 0;
- ASSERT_NO_THROW(default_value = boost::lexical_cast<int64_t>(deflt.value_));
+ /// @param parser_type specifices the parsing starting point at which
+ /// the JSON parser should begin. It defaults to PARSER_JSON. See @c
+ /// D2ParserContext::ParserType for all possible values.
+ D2SimpleParserTest(const D2ParserContext::ParserType&
+ parser_type = D2ParserContext::PARSER_JSON)
+ : parser_type_(parser_type) {
+ reset();
+ }
- // Verify it has the expected value.
- EXPECT_EQ(default_value, element->intValue());
+ /// @brief Destructor
+ virtual ~D2SimpleParserTest() {
+ reset();
}
- /// @brief Checks if specified element matches the given boolean default
+ /// @brief Parses JSON text and compares the results against an expected
+ /// outcome.
///
- /// @param element defaulted element to check
- /// @param deflt SimpleDefault which supplied the default valaue
- void checkBooleanValue(const ConstElementPtr& element, const SimpleDefault& deflt) {
- ASSERT_TRUE(element);
+ /// The JSON text is submitted to the D2ParserContext for parsing. Any
+ /// errors emitted here are caught and compared against the expected
+ /// error or flagged as unexpected.
+ /// Next, the virtural method, setDefaults()is invoked. his method should
+ /// be used by derivations to add default values to the element tree
+ /// produced by the JSON parser.
+ /// Lastly, it passes the element tree into the virtual method,
+ /// parseElement(). This method should be used by derivations to create
+ /// the appropriate element parser to parse the element tree into the
+ /// approprate D2 object(s).
+ ///
+ /// @param json JSON text to parse
+ /// @param exp_error exact text of the error message expected or ""
+ /// if parsing should succeed.
+ ::testing::AssertionResult parseOrFail(const std::string& json,
+ const std::string& exp_error) {
+ bool failed = false;
+ try {
+ // Free up objects created by previous invocation
+ reset();
+
+ // Submit JSON text to JSON parser. We convert the result to
+ // a mutable element tree to allow defaults to be added.
+ D2ParserContext context;
+ data::ElementPtr elem = boost::const_pointer_cast<Element>
+ (context.parseString(json, parser_type_));
+ // Add any defaults
+ setDefaults(elem);
- // Verify it is a bool.
- ASSERT_EQ(Element::boolean, element->getType());
+ // Now pares the element tree into object(s).
+ parseElement(elem);
+ } catch (const std::exception& ex) {
+ std::string caught_error = ex.what();
+ if (exp_error.empty()) {
+ return ::testing::AssertionFailure()
+ << "Unexpected error: " << caught_error
+ << "\n json: [" << json << "]";
+ }
+
+ if (exp_error != caught_error) {
+ return ::testing::AssertionFailure()
+ << "Wrong error detected, expected: "
+ << exp_error << ", got: " << caught_error
+ << "\n json: [" << json << "]";
+ }
+ return ::testing::AssertionSuccess();
+ }
- // Turn default value string into a bool.
- bool default_value = false;
- ASSERT_NO_THROW(boost::lexical_cast<bool>(deflt.value_));
+ if (!exp_error.empty()) {
+ return ::testing::AssertionFailure()
+ << "Unexpected parsing success "
+ << exp_error << "\n json: [" << json << "]";
+ }
- // Verify it has the expected value.
- EXPECT_EQ(default_value, element->boolValue());
+ return ::testing::AssertionSuccess();
}
- /// @brief Checks if specified element matches the given string default
+
+protected:
+ /// @brief Free up objects created by element parsing
+ /// This method is invoked at the beginning of @c parseOrFail() to
+ /// ensure any D2 object(s) that were created by a prior invocation are
+ /// destroyed. This permits parsing to be conducted more than once
+ /// in the same test.
+ virtual void reset(){};
+
+ /// @brief Adds default values to the given element tree
+ ///
+ /// Derivations are expected to use the appropriate methods in
+ /// D2SimpleParser to add defaults values.
///
- /// @param element defaulted element to check
- /// @param deflt SimpleDefault which supplied the default valaue
- void checkStringValue(const ConstElementPtr& element, const SimpleDefault& deflt) {
- ASSERT_TRUE(element);
+ /// @param config element tree in which defaults should be added
+ /// @return the number of default items added to the tree
+ virtual size_t setDefaults(data::ElementPtr config) { return (0); }
- // Verify it's a string
- ASSERT_EQ(Element::string, element->getType());
+ /// @brief Parses a given element tree into D2 object(s)
+ ///
+ /// Derivations are expected to create the appropriate element
+ /// parser and pass it the element tree for parsing. Any object(s)
+ /// created should likely be saved for content verification
+ /// outside of this method.
+ ///
+ /// @param config element tree to parse
+ virtual void parseElement(data::ConstElementPtr config) {};
- // Verify it has the expected value
- EXPECT_EQ(deflt.value_, element->stringValue());
- }
+ D2ParserContext::ParserType parser_type_;
};
+/// @brief Convenience macros for calling parseOrFail
+#define PARSE_OK(a) EXPECT_TRUE((parseOrFail(a, "")))
+#define PARSE_FAIL(a,b) EXPECT_TRUE((parseOrFail(a, b)))
+
// This test checks if global defaults are properly set for D2.
TEST_F(D2SimpleParserTest, globalD2Defaults) {
EXPECT_NO_THROW(num = D2SimpleParser::setAllDefaults(empty));
// We expect 5 parameters to be inserted.
- EXPECT_EQ(num, 5);
+ EXPECT_EQ(num, 8);
// Let's go over all parameters we have defaults for.
BOOST_FOREACH(SimpleDefault deflt, D2SimpleParser::D2_GLOBAL_DEFAULTS) {
ConstElementPtr x;
ASSERT_NO_THROW(x = empty->get(deflt.name_));
-
- EXPECT_TRUE(x);
+
+ EXPECT_TRUE(x);
if (x) {
if (deflt.type_ == Element::integer) {
checkIntegerValue(x, deflt);
// add them if we need to. Like what do you if it's a map?
ADD_FAILURE() << "default type not supported:" << deflt.name_
<< " ,type: " << deflt.type_;
- }
+ }
+ }
+ }
+}
+
+/// @brief Test fixture class for testing TSIGKeyInfo parsing.
+class TSIGKeyInfoParserTest : public D2SimpleParserTest {
+public:
+ /// @brief Constructor
+ TSIGKeyInfoParserTest()
+ : D2SimpleParserTest(D2ParserContext::PARSER_TSIG_KEY) {
+ }
+
+ /// @brief Free up the keys created by parsing
+ virtual void reset() {
+ key_.reset();
+ };
+
+ /// @brief Destructor
+ virtual ~TSIGKeyInfoParserTest() {
+ reset();
+ };
+
+ /// @brief Adds TSIG Key default values to the given TSIG Key element
+ ///
+ /// @param config TSIG Key element to which defaults should be added
+ ///
+ /// @return the number of default items added to the tree
+ size_t setDefaults(data::ElementPtr config) {
+ return (SimpleParser::setDefaults(config, D2SimpleParser::
+ TSIG_KEY_DEFAULTS));
+ }
+
+ /// @brief Attempts to parse the given element into a TSIGKeyInfo
+ ///
+ /// Assumes the given element is a Map containing the attributes for
+ /// a TSIG Key. If parsing is successful the new TSIGKeyInfo instance
+ /// is retained in the member, key_;
+ ///
+ /// @param config element to parse
+ void parseElement(data::ConstElementPtr config) {
+ TSIGKeyInfoParser parser;
+ key_ = parser.parse(config);
+ }
+
+ /// @brief Retains the TSIGKeyInfo created by a successful parsing
+ TSIGKeyInfoPtr key_;
+};
+
+
+/// @brief Test fixture class for testing TSIGKeyInfo list parsing.
+class TSIGKeyInfoListParserTest : public D2SimpleParserTest {
+public:
+ /// @brief Constructor
+ TSIGKeyInfoListParserTest()
+ : D2SimpleParserTest(D2ParserContext::PARSER_TSIG_KEYS) {
+ }
+
+ /// @brief Destructor
+ virtual ~TSIGKeyInfoListParserTest() {
+ reset();
+ }
+
+ /// @brief Free up the keys created by parsing
+ virtual void reset() {
+ keys_.reset();
+ };
+
+ /// @brief Adds TSIG Key default values to a list of TSIG Key elements
+ ///
+ /// @param config list of TSIG Key elements to which defaults should be
+ /// added
+ ///
+ /// @return the number of default items added to the tree
+ size_t setDefaults(data::ElementPtr config) {
+ return (SimpleParser::setListDefaults(config, D2SimpleParser::
+ TSIG_KEY_DEFAULTS));
+ }
+
+ /// @brief Attempts to parse the given element into a list of TSIGKeyInfos
+ ///
+ /// Assumes the given element is a list containing one or more TSIG Keys
+ /// elements. If parsing is successful the list of TSIGKeyInfo instances
+ /// is retained in the member, keys_;
+ ///
+ /// @param config element to parse
+ void parseElement(data::ConstElementPtr config) {
+ TSIGKeyInfoListParser parser;
+ keys_ = parser.parse(config);
+ }
+
+ /// @brief Retains the TSIGKeyInfos created by a successful parsing
+ TSIGKeyInfoMapPtr keys_;
+};
+
+/// @brief Test fixture class for testing DnsServerInfo parsing.
+class DnsServerInfoParserTest : public D2SimpleParserTest {
+public:
+ /// @brief Constructor
+ DnsServerInfoParserTest()
+ : D2SimpleParserTest(D2ParserContext::PARSER_DNS_SERVER) {
+ }
+
+ /// @brief Destructor
+ virtual ~DnsServerInfoParserTest() {
+ reset();
+ }
+
+ /// @brief Free up the server created by parsing
+ virtual void reset() {
+ server_.reset();
+ }
+
+ /// @brief Adds DNS Server default values to the given DNS Server element
+ ///
+ /// @param config DNS Server element to which defaults should be added
+ ///
+ /// @return the number of default items added to the tree
+ virtual size_t setDefaults(data::ElementPtr config) {
+ return (SimpleParser::setDefaults(config, D2SimpleParser::
+ DNS_SERVER_DEFAULTS));
+ }
+
+ /// @brief Attempts to parse the given element into a DnsServerInfo
+ ///
+ /// Assumes the given element is a map containing the attributes for
+ /// a DNS Server. If parsing is successful the new DnsServerInfo instance
+ /// is retained in the member, server_;
+ ///
+ /// @param config element to parse
+ virtual void parseElement(data::ConstElementPtr config) {
+ DnsServerInfoParser parser;
+ server_ = parser.parse(config);
+ }
+
+ /// @brief Retains the DnsServerInfo created by a successful parsing
+ DnsServerInfoPtr server_;
+};
+
+/// @brief Test fixture class for testing DnsServerInfoList parsing.
+class DnsServerInfoListParserTest : public D2SimpleParserTest {
+public:
+ /// @brief Constructor
+ DnsServerInfoListParserTest()
+ : D2SimpleParserTest(D2ParserContext::PARSER_DNS_SERVERS) {
+ }
+
+ /// @brief Destructor
+ virtual ~DnsServerInfoListParserTest() {
+ reset();
+ }
+
+ /// @brief Free up the servers created by parsing
+ virtual void reset() {
+ servers_.reset();
+ }
+
+ /// @brief Adds DNS Server default values to a list of DNS Server elements
+ ///
+ /// @param config list of DNS Server elements to which defaults should be
+ /// added
+ ///
+ /// @return the number of default items added to the tree
+ virtual size_t setDefaults(data::ElementPtr config) {
+ return (SimpleParser::setListDefaults(config, D2SimpleParser::
+ DNS_SERVER_DEFAULTS));
+ }
+
+ /// @brief Attempts to parse the given element into a list of DnsServerInfos
+ ///
+ /// Assumes the given element is a list containing one or more DNS Servers
+ /// elements. If parsing is successful the list of DnsServerInfo instances
+ /// is retained in the member, keys_;
+ ///
+ /// @param config element to parse
+ virtual void parseElement(data::ConstElementPtr config) {
+ DnsServerInfoListParser parser;
+ servers_ = parser.parse(config);
+ }
+
+ /// @brief Retains the DnsServerInfos created by a successful parsing
+ DnsServerInfoStoragePtr servers_;
+};
+
+
+/// @brief Test fixture class for testing DDnsDomain parsing.
+class DdnsDomainParserTest : public D2SimpleParserTest {
+public:
+
+ /// @brief Constructor
+ DdnsDomainParserTest(const D2ParserContext::ParserType& parser_type
+ = D2ParserContext::PARSER_DDNS_DOMAIN)
+ : D2SimpleParserTest(parser_type), keys_(new TSIGKeyInfoMap()) {
+ }
+
+ /// @brief Destructor
+ virtual ~DdnsDomainParserTest() {
+ reset();
+ }
+
+ /// @brief Free up the domain created by parsing
+ virtual void reset() {
+ domain_.reset();
+ }
+
+ /// @brief Add TSIGKeyInfos to the key map
+ ///
+ /// @param name the name of the key
+ /// @param algorithm the algorithm of the key
+ /// @param secret the secret value of the key
+ void addKey(const std::string& name, const std::string& algorithm,
+ const std::string& secret) {
+ TSIGKeyInfoPtr key_info(new TSIGKeyInfo(name, algorithm, secret));
+ (*keys_)[name]=key_info;
+ }
+
+ /// @brief Adds DDNS Domain values to the given DDNS Domain element
+ ///
+ /// @param config DDNS Domain element to which defaults should be added
+ ///
+ /// @return the number of default items added to the tree
+ virtual size_t setDefaults(data::ElementPtr config) {
+ return (D2SimpleParser::setDdnsDomainDefaults(config, D2SimpleParser::
+ DDNS_DOMAIN_DEFAULTS));
+ }
+
+ /// @brief Attempts to parse the given element into a DdnsDomain
+ ///
+ /// Assumes the given element is a map containing the attributes for
+ /// a DDNS Domain. If parsing is successful the new DdnsDomain instance
+ /// is retained in the member, server_;
+ ///
+ /// @param config element to parse
+ virtual void parseElement(data::ConstElementPtr config) {
+ DdnsDomainParser parser;
+ domain_ = parser.parse(config, keys_);
+ }
+
+ /// @brief Retains the DdnsDomain created by a successful parsing
+ DdnsDomainPtr domain_;
+
+ /// @brief Storage for TSIGKeys, used by DdnsDomainParser to validate
+ /// domain keys
+ TSIGKeyInfoMapPtr keys_;
+};
+
+class DdnsDomainListParserTest : public DdnsDomainParserTest {
+public:
+ /// @brief Constructor
+ DdnsDomainListParserTest()
+ // We need the list context type to parse lists correctly
+ : DdnsDomainParserTest(D2ParserContext::PARSER_DDNS_DOMAINS) {
+ }
+
+ /// @brief Destructor
+ virtual ~DdnsDomainListParserTest() {
+ reset();
+ }
+
+ /// @brief Free up domains created by parsing
+ virtual void reset() {
+ domains_.reset();
+ }
+
+ /// @brief Adds DDNS Domain default values to a list of DDNS Domain elements
+ ///
+ /// @param config list of DDNS Domain elements to which defaults should be
+ /// added
+ ///
+ /// @return the number of default items added to the tree
+ virtual size_t setDefaults(data::ElementPtr config) {
+ size_t cnt = 0;
+ // We don't use SimpleParser::setListDefaults() as this does
+ // not handle sub-lists or sub-maps
+ BOOST_FOREACH(ElementPtr domain, config->listValue()) {
+ cnt += D2SimpleParser::
+ setDdnsDomainDefaults(domain, D2SimpleParser::
+ DDNS_DOMAIN_DEFAULTS);
}
+
+ return (cnt);
}
+
+ /// @brief Attempts to parse the given element into a list of DdnsDomains
+ ///
+ /// Assumes the given element is a list containing one or more DDNS Domains
+ /// elements. If parsing is successful the list of DdnsDomain instances
+ /// is retained in the member, keys_;
+ ///
+ /// @param config element to parse
+ virtual void parseElement(data::ConstElementPtr config) {
+ DdnsDomainListParser parser;
+ domains_ = parser.parse(config, keys_);
+ }
+
+ /// @brief Retains the DdnsDomains created by a successful parsing
+ DdnsDomainMapPtr domains_;
+};
+
+/// @brief Tests the enforcement of data validation when parsing TSIGKeyInfos.
+/// It verifies that:
+/// 1. Name cannot be blank.
+/// 2. Algorithm cannot be blank.
+/// 3. Secret cannot be blank.
+TEST_F(TSIGKeyInfoParserTest, invalidEntry) {
+ // Name cannot be blank.
+ std::string config = "{"
+ " \"name\": \"\" , "
+ " \"algorithm\": \"HMAC-MD5\" , "
+ " \"secret\": \"LSWXnfkKZjdPJI5QxlpnfQ==\" "
+ "}";
+ PARSE_FAIL(config, "<string>:1.9: TSIG key name cannot be blank");
+
+ // Algorithm cannot be be blank.
+ config = "{"
+ " \"name\": \"d2_key_one\" , "
+ " \"algorithm\": \"\" , "
+ " \"secret\": \"LSWXnfkKZjdPJI5QxlpnfQ==\" "
+ "}";
+ PARSE_FAIL(config, "<string>:1.38: TSIG key algorithm cannot be blank");
+
+ // Algorithm must be a valid algorithm
+ config = "{"
+ " \"name\": \"d2_key_one\" , "
+ " \"algorithm\": \"bogus\" , "
+ " \"secret\": \"LSWXnfkKZjdPJI5QxlpnfQ==\" "
+ "}";
+ PARSE_FAIL(config, "tsig-key : Unknown TSIG Key algorithm:"
+ " bogus (<string>:1:40)");
+
+ // Secret cannot be blank
+ config = "{"
+ " \"name\": \"d2_key_one\" , "
+ " \"algorithm\": \"HMAC-MD5\" , "
+ " \"secret\": \"\" "
+ "}";
+ PARSE_FAIL(config, "<string>:1.62: TSIG key secret cannot be blank");
+
+ // Secret must be valid for alogorithm
+ config = "{"
+ " \"name\": \"d2_key_one\" , "
+ " \"algorithm\": \"HMAC-MD5\" , "
+ " \"digest-bits\": 120 , "
+ " \"secret\": \"bogus\" "
+ "}";
+ PARSE_FAIL(config, "Cannot make TSIGKey: Incomplete input for base64:"
+ " bogus (<string>:1:1)");
+}
+
+
+/// @brief Verifies that TSIGKeyInfo parsing creates a proper TSIGKeyInfo
+/// when given a valid combination of entries.
+TEST_F(TSIGKeyInfoParserTest, validEntry) {
+ // Valid entries for TSIG key, all items are required.
+ std::string config = "{"
+ " \"name\": \"d2_key_one\" , "
+ " \"algorithm\": \"HMAC-MD5\" , "
+ " \"digest-bits\": 120 , "
+ " \"secret\": \"dGhpcyBrZXkgd2lsbCBtYXRjaA==\" "
+ "}";
+ // Verify that it parses.
+ PARSE_OK(config);
+ ASSERT_TRUE(key_);
+
+ // Verify the key contents.
+ EXPECT_TRUE(checkKey(key_, "d2_key_one", "HMAC-MD5",
+ "dGhpcyBrZXkgd2lsbCBtYXRjaA==", 120));
+}
+
+/// @brief Verifies that attempting to parse an invalid list of TSIGKeyInfo
+/// entries is detected.
+TEST_F(TSIGKeyInfoListParserTest, invalidTSIGKeyList) {
+ // Construct a list of keys with an invalid key entry.
+ std::string config = "["
+ " { \"name\": \"key1\" , "
+ " \"algorithm\": \"HMAC-MD5\" ,"
+ " \"digest-bits\": 120 , "
+ " \"secret\": \"GWG/Xfbju4O2iXGqkSu4PQ==\" "
+ " },"
+ // this entry has an invalid algorithm
+ " { \"name\": \"key2\" , "
+ " \"algorithm\": \"\" ,"
+ " \"digest-bits\": 120 , "
+ " \"secret\": \"GWG/Xfbju4O2iXGqkSu4PQ==\" "
+ " },"
+ " { \"name\": \"key3\" , "
+ " \"algorithm\": \"HMAC-MD5\" ,"
+ " \"secret\": \"GWG/Xfbju4O2iXGqkSu4PQ==\" "
+ " }"
+ " ]";
+
+ PARSE_FAIL(config, "<string>:1.151: TSIG key algorithm cannot be blank");
+}
+
+/// @brief Verifies that attempting to parse an invalid list of TSIGKeyInfo
+/// entries is detected.
+TEST_F(TSIGKeyInfoListParserTest, duplicateTSIGKey) {
+ // Construct a list of keys with an invalid key entry.
+ std::string config = "["
+ " { \"name\": \"key1\" , "
+ " \"algorithm\": \"HMAC-MD5\" ,"
+ " \"digest-bits\": 120 , "
+ " \"secret\": \"GWG/Xfbju4O2iXGqkSu4PQ==\" "
+ " },"
+ " { \"name\": \"key2\" , "
+ " \"algorithm\": \"HMAC-MD5\" ,"
+ " \"digest-bits\": 120 , "
+ " \"secret\": \"GWG/Xfbju4O2iXGqkSu4PQ==\" "
+ " },"
+ " { \"name\": \"key1\" , "
+ " \"algorithm\": \"HMAC-MD5\" ,"
+ " \"secret\": \"GWG/Xfbju4O2iXGqkSu4PQ==\" "
+ " }"
+ " ]";
+
+ PARSE_FAIL(config,
+ "Duplicate TSIG key name specified : key1 (<string>:1:239)");
+}
+
+/// @brief Verifies a valid list of TSIG Keys parses correctly.
+/// Also verifies that all of the supported algorithm names work.
+TEST_F(TSIGKeyInfoListParserTest, validTSIGKeyList) {
+ // Construct a valid list of keys.
+ std::string config = "["
+ " { \"name\": \"key1\" , "
+ " \"algorithm\": \"HMAC-MD5\" ,"
+ " \"digest-bits\": 80 , "
+ " \"secret\": \"dGhpcyBrZXkgd2lsbCBtYXRjaA==\" "
+ " },"
+ " { \"name\": \"key2\" , "
+ " \"algorithm\": \"HMAC-SHA1\" ,"
+ " \"digest-bits\": 80 , "
+ " \"secret\": \"dGhpcyBrZXkgd2lsbCBtYXRjaA==\" "
+ " },"
+ " { \"name\": \"key3\" , "
+ " \"algorithm\": \"HMAC-SHA256\" ,"
+ " \"digest-bits\": 128 , "
+ " \"secret\": \"dGhpcyBrZXkgd2lsbCBtYXRjaA==\" "
+ " },"
+ " { \"name\": \"key4\" , "
+ " \"algorithm\": \"HMAC-SHA224\" ,"
+ " \"digest-bits\": 112 , "
+ " \"secret\": \"dGhpcyBrZXkgd2lsbCBtYXRjaA==\" "
+ " },"
+ " { \"name\": \"key5\" , "
+ " \"algorithm\": \"HMAC-SHA384\" ,"
+ " \"digest-bits\": 192 , "
+ " \"secret\": \"dGhpcyBrZXkgd2lsbCBtYXRjaA==\" "
+ " },"
+ " { \"name\": \"key6\" , "
+ " \"algorithm\": \"HMAC-SHA512\" ,"
+ " \"digest-bits\": 256 , "
+ " \"secret\": \"dGhpcyBrZXkgd2lsbCBtYXRjaA==\" "
+ " }"
+ " ]";
+
+ PARSE_OK(config);
+ ASSERT_TRUE(keys_);
+
+ std::string ref_secret = "dGhpcyBrZXkgd2lsbCBtYXRjaA==";
+ // Verify the correct number of keys are present
+ int count = keys_->size();
+ ASSERT_EQ(6, count);
+
+ // Find the 1st key and retrieve it.
+ TSIGKeyInfoMap::iterator gotit = keys_->find("key1");
+ ASSERT_TRUE(gotit != keys_->end());
+ TSIGKeyInfoPtr& key = gotit->second;
+
+ // Verify the key contents.
+ EXPECT_TRUE(checkKey(key, "key1", TSIGKeyInfo::HMAC_MD5_STR,
+ ref_secret, 80));
+
+ // Find the 2nd key and retrieve it.
+ gotit = keys_->find("key2");
+ ASSERT_TRUE(gotit != keys_->end());
+ key = gotit->second;
+
+ // Verify the key contents.
+ EXPECT_TRUE(checkKey(key, "key2", TSIGKeyInfo::HMAC_SHA1_STR,
+ ref_secret, 80));
+
+ // Find the 3rd key and retrieve it.
+ gotit = keys_->find("key3");
+ ASSERT_TRUE(gotit != keys_->end());
+ key = gotit->second;
+
+ // Verify the key contents.
+ EXPECT_TRUE(checkKey(key, "key3", TSIGKeyInfo::HMAC_SHA256_STR,
+ ref_secret, 128));
+
+ // Find the 4th key and retrieve it.
+ gotit = keys_->find("key4");
+ ASSERT_TRUE(gotit != keys_->end());
+ key = gotit->second;
+
+ // Verify the key contents.
+ EXPECT_TRUE(checkKey(key, "key4", TSIGKeyInfo::HMAC_SHA224_STR,
+ ref_secret, 112));
+
+ // Find the 5th key and retrieve it.
+ gotit = keys_->find("key5");
+ ASSERT_TRUE(gotit != keys_->end());
+ key = gotit->second;
+
+ // Verify the key contents.
+ EXPECT_TRUE(checkKey(key, "key5", TSIGKeyInfo::HMAC_SHA384_STR,
+ ref_secret, 192));
+
+ // Find the 6th key and retrieve it.
+ gotit = keys_->find("key6");
+ ASSERT_TRUE(gotit != keys_->end());
+ key = gotit->second;
+
+ // Verify the key contents.
+ EXPECT_TRUE(checkKey(key, "key6", TSIGKeyInfo::HMAC_SHA512_STR,
+ ref_secret, 256));
+}
+
+/// @brief Tests the enforcement of data validation when parsing DnsServerInfos.
+/// It verifies that:
+/// 1. Specifying both a hostname and an ip address is not allowed.
+/// 2. Specifying both blank a hostname and blank ip address is not allowed.
+/// 3. Specifying a negative port number is not allowed.
+
+TEST_F(DnsServerInfoParserTest, invalidEntry) {
+ // Create a config in which both host and ip address are supplied.
+ // Verify that parsing fails.
+ std::string config = "{ \"hostname\": \"pegasus.tmark\", "
+ " \"ip-address\": \"127.0.0.1\", "
+ " \"port\": 100} ";
+ PARSE_FAIL(config, "<string>:1.13: hostname is not yet supported");
+
+
+ // Neither host nor ip address supplied
+ // Verify that builds fails.
+ config = "{ \"hostname\": \"\", "
+ " \"ip-address\": \"\", "
+ " \"port\": 100} ";
+ PARSE_FAIL(config, "Dns Server must specify one or the other"
+ " of hostname or IP address (<string>:1:1)");
+
+ // Create a config with a negative port number.
+ // Verify that build fails.
+ config = "{ \"hostname\": \"\", "
+ " \"ip-address\": \"192.168.5.6\" ,"
+ " \"port\": -100 }";
+ PARSE_FAIL(config, "<string>:1.60-63: port must be greater than zero");
+}
+
+
+/// @brief Verifies that DnsServerInfo parsing creates a proper DnsServerInfo
+/// when given a valid combination of entries.
+/// It verifies that:
+/// 1. A DnsServerInfo entry is correctly made, when given only a hostname.
+/// 2. A DnsServerInfo entry is correctly made, when given ip address and port.
+/// 3. A DnsServerInfo entry is correctly made, when given only an ip address.
+TEST_F(DnsServerInfoParserTest, validEntry) {
+ /// @todo When resolvable hostname is supported you'll need this test.
+ /// // Valid entries for dynamic host
+ /// std::string config = "{ \"hostname\": \"pegasus.tmark\" }";
+ /// ASSERT_TRUE(fromJSON(config));
+
+ /// // Verify that it builds and commits without throwing.
+ /// ASSERT_NO_THROW(parser_->build(config_set_));
+ /// ASSERT_NO_THROW(parser_->commit());
+
+ /// //Verify the correct number of servers are present
+ /// int count = servers_->size();
+ /// EXPECT_EQ(1, count);
+
+ /// Verify the server exists and has the correct values.
+ /// DnsServerInfoPtr server = (*servers_)[0];
+ /// EXPECT_TRUE(checkServer(server, "pegasus.tmark",
+ /// DnsServerInfo::EMPTY_IP_STR,
+ /// DnsServerInfo::STANDARD_DNS_PORT));
+
+ /// // Start over for a new test.
+ /// reset();
+
+ // Valid entries for static ip
+ std::string config = " { \"hostname\" : \"\", "
+ " \"ip-address\": \"127.0.0.1\" , "
+ " \"port\": 100 }";
+ PARSE_OK(config);
+ ASSERT_TRUE(server_);
+ EXPECT_TRUE(checkServer(server_, "", "127.0.0.1", 100));
+
+ // Valid entries for static ip, no port
+ // This will fail without invoking set defaults
+ config = " { \"ip-address\": \"192.168.2.5\" }";
+ PARSE_OK(config);
+ ASSERT_TRUE(server_);
+ EXPECT_TRUE(checkServer(server_, "", "192.168.2.5",
+ DnsServerInfo::STANDARD_DNS_PORT));
+}
+
+/// @brief Verifies that attempting to parse an invalid list of DnsServerInfo
+/// entries is detected.
+TEST_F(DnsServerInfoListParserTest, invalidServerList) {
+ // Construct a list of servers with an invalid server entry.
+ std::string config = "[ { \"ip-address\": \"127.0.0.1\" }, "
+ "{ \"ip-address\": \"\" }, "
+ "{ \"ip-address\": \"127.0.0.2\" } ]";
+ PARSE_FAIL(config, "Dns Server must specify one or the other"
+ " of hostname or IP address (<string>:1:34)");
+ ASSERT_FALSE(servers_);
+}
+
+/// @brief Verifies that a list of DnsServerInfo entries parses correctly given
+/// a valid configuration.
+TEST_F(DnsServerInfoListParserTest, validServerList) {
+ // Create a valid list of servers.
+ std::string config = "[ { \"ip-address\": \"127.0.0.1\" }, "
+ "{ \"ip-address\": \"127.0.0.2\" }, "
+ "{ \"ip-address\": \"127.0.0.3\" } ]";
+ PARSE_OK(config);
+
+ // Verify that the server storage contains the correct number of servers.
+ ASSERT_EQ(3, servers_->size());
+
+ // Verify the first server exists and has the correct values.
+ DnsServerInfoPtr server = (*servers_)[0];
+ EXPECT_TRUE(checkServer(server, "", "127.0.0.1",
+ DnsServerInfo::STANDARD_DNS_PORT));
+
+ // Verify the second server exists and has the correct values.
+ server = (*servers_)[1];
+ EXPECT_TRUE(checkServer(server, "", "127.0.0.2",
+ DnsServerInfo::STANDARD_DNS_PORT));
+
+ // Verify the third server exists and has the correct values.
+ server = (*servers_)[2];
+ EXPECT_TRUE(checkServer(server, "", "127.0.0.3",
+ DnsServerInfo::STANDARD_DNS_PORT));
+}
+
+/// @brief Tests the enforcement of data validation when parsing DdnsDomains.
+/// It verifies that:
+/// 1. Domain storage cannot be null when constructing a DdnsDomainParser.
+/// 2. The name entry is not optional.
+/// 3. The server list may not be empty.
+/// 4. That a mal-formed server entry is detected.
+/// 5. That an undefined key name is detected.
+TEST_F(DdnsDomainParserTest, invalidDomain) {
+ // Create a domain configuration without a name
+ std::string config = "{ \"key-name\": \"d2_key.tmark.org\" , "
+ " \"dns-servers\" : [ "
+ " { \"ip-address\": \"127.0.0.1\" , "
+ " \"port\": 100 },"
+ " { \"ip-address\": \"127.0.0.2\" , "
+ " \"port\": 200 },"
+ " { \"ip-address\": \"127.0.0.3\" , "
+ " \"port\": 300 } ] } ";
+ PARSE_FAIL(config, "String parameter name not found(<string>:1:1)");
+
+ // Create a domain configuration with an empty server list.
+ config = "{ \"name\": \"tmark.org\" , "
+ " \"key-name\": \"\" , "
+ " \"dns-servers\" : [ "
+ " ] } ";
+ PARSE_FAIL(config, "<string>:1.67: syntax error, unexpected ], expecting {");
+
+ // Create a domain configuration with a mal-formed server entry.
+ config = "{ \"name\": \"tmark.org\" , "
+ " \"key-name\": \"\" , "
+ " \"dns-servers\" : [ "
+ " { \"ip-address\": \"127.0.0.3\" , "
+ " \"port\": -1 } ] } ";
+ PARSE_FAIL(config, "<string>:1.109-110: port must be greater than zero");
+
+ // Create a domain configuration without an defined key name
+ config = "{ \"name\": \"tmark.org\" , "
+ " \"key-name\": \"d2_key.tmark.org\" , "
+ " \"dns-servers\" : [ "
+ " { \"ip-address\": \"127.0.0.3\" , "
+ " \"port\": 300 } ] } ";
+ PARSE_FAIL(config, "DdnsDomain : tmark.org specifies"
+ " an undefined key: d2_key.tmark.org (<string>:1:39)");
+}
+
+/// @brief Verifies the basics of parsing of a DdnsDomain.
+TEST_F(DdnsDomainParserTest, validDomain) {
+ // Add a TSIG key to the test key map, so key validation will pass.
+ addKey("d2_key.tmark.org", "HMAC-MD5", "GWG/Xfbju4O2iXGqkSu4PQ==");
+
+ // Create a valid domain configuration entry containing three valid
+ // servers.
+ std::string config =
+ "{ \"name\": \"tmark.org\" , "
+ " \"key-name\": \"d2_key.tmark.org\" , "
+ " \"dns-servers\" : [ "
+ " { \"ip-address\": \"127.0.0.1\" , "
+ " \"port\": 100 },"
+ " { \"ip-address\": \"127.0.0.2\" , "
+ " \"port\": 200 },"
+ " { \"ip-address\": \"127.0.0.3\" , "
+ " \"port\": 300 } ] } ";
+ PARSE_OK(config);
+
+ // Domain should exist
+ ASSERT_TRUE(domain_);
+
+ // Verify the name and key_name values.
+ EXPECT_EQ("tmark.org", domain_->getName());
+ EXPECT_EQ("d2_key.tmark.org", domain_->getKeyName());
+ ASSERT_TRUE(domain_->getTSIGKeyInfo());
+ ASSERT_TRUE(domain_->getTSIGKeyInfo()->getTSIGKey());
+
+ // Verify that the server list exists and contains the correct number of
+ // servers.
+ const DnsServerInfoStoragePtr& servers = domain_->getServers();
+ EXPECT_TRUE(servers);
+ EXPECT_EQ(3, servers->size());
+
+ // Fetch each server and verify its contents.
+ DnsServerInfoPtr server = (*servers)[0];
+ EXPECT_TRUE(server);
+
+ EXPECT_TRUE(checkServer(server, "", "127.0.0.1", 100));
+
+ server = (*servers)[1];
+ EXPECT_TRUE(server);
+
+ EXPECT_TRUE(checkServer(server, "", "127.0.0.2", 200));
+
+ server = (*servers)[2];
+ EXPECT_TRUE(server);
+
+ EXPECT_TRUE(checkServer(server, "", "127.0.0.3", 300));
+}
+
+/// @brief Tests the fundamentals of parsing DdnsDomain lists.
+/// This test verifies that given a valid domain list configuration
+/// it will accurately parse and populate each domain in the list.
+TEST_F(DdnsDomainListParserTest, validList) {
+ // Add keys to key map so key validation passes.
+ addKey("d2_key.tmark.org", "HMAC-MD5", "GWG/Xfbju4O2iXGqkSu4PQ==");
+ addKey("d2_key.billcat.net", "HMAC-MD5", "GWG/Xfbju4O2iXGqkSu4PQ==");
+
+ // Create a valid domain list configuration, with two domains
+ // that have three servers each.
+ std::string config =
+ "[ "
+ "{ \"name\": \"tmark.org\" , "
+ " \"key-name\": \"d2_key.tmark.org\" , "
+ " \"dns-servers\" : [ "
+ " { \"ip-address\": \"127.0.0.1\" , "
+ " \"port\": 100 },"
+ " { \"ip-address\": \"127.0.0.2\" , "
+ " \"port\": 200 },"
+ " { \"ip-address\": \"127.0.0.3\" , "
+ " \"port\": 300 } ] } "
+ ", "
+ "{ \"name\": \"billcat.net\" , "
+ " \"key-name\": \"d2_key.billcat.net\" , "
+ " \"dns-servers\" : [ "
+ " { \"ip-address\": \"127.0.0.4\" , "
+ " \"port\": 400 },"
+ " { \"ip-address\": \"127.0.0.5\" , "
+ " \"port\": 500 },"
+ " { \"ip-address\": \"127.0.0.6\" , "
+ " \"port\": 600 } ] } "
+ "] ";
+
+ // Verify that the domain list parses without error.
+ PARSE_OK(config);
+ ASSERT_TRUE(domains_);
+ EXPECT_EQ(2, domains_->size());
+
+ // Verify that the first domain exists and can be retrieved.
+ DdnsDomainMap::iterator gotit = domains_->find("tmark.org");
+ ASSERT_TRUE(gotit != domains_->end());
+ DdnsDomainPtr& domain = gotit->second;
+
+ // Verify the name and key_name values of the first domain.
+ EXPECT_EQ("tmark.org", domain->getName());
+ EXPECT_EQ("d2_key.tmark.org", domain->getKeyName());
+
+ // Verify the TSIGKeyInfo name and that the actual key was created
+ ASSERT_TRUE(domain->getTSIGKeyInfo());
+ EXPECT_EQ(domain->getKeyName(), domain->getTSIGKeyInfo()->getName());
+ EXPECT_TRUE(domain->getTSIGKeyInfo()->getTSIGKey());
+
+ // Verify the each of the first domain's servers
+ DnsServerInfoStoragePtr servers = domain->getServers();
+ EXPECT_TRUE(servers);
+ EXPECT_EQ(3, servers->size());
+
+ DnsServerInfoPtr server = (*servers)[0];
+ EXPECT_TRUE(server);
+ EXPECT_TRUE(checkServer(server, "", "127.0.0.1", 100));
+
+ server = (*servers)[1];
+ EXPECT_TRUE(server);
+ EXPECT_TRUE(checkServer(server, "", "127.0.0.2", 200));
+
+ server = (*servers)[2];
+ EXPECT_TRUE(server);
+ EXPECT_TRUE(checkServer(server, "", "127.0.0.3", 300));
+
+ // Verify second domain
+ gotit = domains_->find("billcat.net");
+ ASSERT_TRUE(gotit != domains_->end());
+ domain = gotit->second;
+
+ // Verify the name and key_name values of the second domain.
+ EXPECT_EQ("billcat.net", domain->getName());
+ EXPECT_EQ("d2_key.billcat.net", domain->getKeyName());
+ ASSERT_TRUE(domain->getTSIGKeyInfo());
+ EXPECT_EQ(domain->getKeyName(), domain->getTSIGKeyInfo()->getName());
+ EXPECT_TRUE(domain->getTSIGKeyInfo()->getTSIGKey());
+
+ // Verify the each of second domain's servers
+ servers = domain->getServers();
+ EXPECT_TRUE(servers);
+ servers->size();
+ EXPECT_EQ(3, servers->size());
+
+ server = (*servers)[0];
+ EXPECT_TRUE(server);
+ EXPECT_TRUE(checkServer(server, "", "127.0.0.4", 400));
+
+ server = (*servers)[1];
+ EXPECT_TRUE(server);
+ EXPECT_TRUE(checkServer(server, "", "127.0.0.5", 500));
+
+ server = (*servers)[2];
+ EXPECT_TRUE(server);
+ EXPECT_TRUE(checkServer(server, "", "127.0.0.6", 600));
+}
+
+/// @brief Tests that a domain list configuration cannot contain duplicates.
+TEST_F(DdnsDomainListParserTest, duplicateDomain) {
+ // Create a domain list configuration that contains two domains with
+ // the same name.
+ std::string config =
+ "[ "
+ "{ \"name\": \"tmark.org\" , "
+ " \"dns-servers\" : [ "
+ " { \"ip-address\": \"127.0.0.3\" , "
+ " \"port\": 300 } ] } "
+ ", "
+ "{ \"name\": \"tmark.org\" , "
+ " \"dns-servers\" : [ "
+ " { \"ip-address\": \"127.0.0.3\" , "
+ " \"port\": 300 } ] } "
+ "] ";
+ // Verify that the parsing fails.
+ PARSE_FAIL(config,
+ "Duplicate domain specified:tmark.org (<string>:1:113)");
}
};
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;
namespace isc {
namespace d2 {
+extern const char* valid_d2_config;
extern const char* TEST_DNS_SERVER_IP;
extern size_t TEST_DNS_SERVER_PORT;
# 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" : {},
}
#-----
+# Map should be supplied through setDefaults
,{
"description" : "D2 missing forward-ddns map",
-"logic-error" : true,
"data" :
{
"reverse-ddns" : {},
}
#-----
+# Map should be supplied through setDefaults
,{
"description" : "D2 missing reverse-ddns map",
-"logic-error" : true,
"data" :
{
"forward-ddns" : {},
#-----
+# Map should be supplied through setDefaults
,{
"description" : "D2 missing tsig-keys list",
-"logic-error" : true,
"data" :
{
"forward-ddns" : {},
#-----
,{
"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",
#-----
,{
"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",
#-----
,{
"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" : {},
#-----
,{
"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" : {},
#-----
,{
"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" : {},
#----- 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" : {},
#-----
,{
"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" : {},
#-----
,{
"description" : "D2.tsig-keys, invalid algorithm",
-"logic-error" : true,
+"logic-error" : "tsig-key : Unknown TSIG Key algorithm: bogus (<string>:1:77)",
"data" :
{
"forward-ddns" : {},
#-----
,{
"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" : {},
#-----
,{
"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" : {},
#-----
,{
"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" : {},
#-----
,{
"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" : {},
#-----
,{
"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" : {},
#-----
,{
"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" : {},
#-----
,{
"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" : {},
#----- 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" : {},
#-----
,{
"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" : {},
#-----
,{
"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" : {},
#------
,{
"description" : "D2.forward-ddns, duplicate domain",
-"logic-error" : true,
+"logic-error" : "Duplicate domain specified:four.example.com. (<string>:1:184)",
"data" :
{
"forward-ddns" :
#-----
,{
"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" :
#------ "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" :
#----- 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" :
#-----
,{
"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" :
#-----
,{
"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" :
#------
,{
"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" : {},
#-----
,{
"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" : {},
#------ "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" : {},
#----- 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" : {},
#-----
,{
"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" : {},
#-----
,{
"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" : {},
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;
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
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