]> git.ipfire.org Git - thirdparty/kea.git/commitdiff
[5495] Updated code, .ll and .yy
authorFrancis Dupont <fdupont@isc.org>
Tue, 2 Jan 2018 02:07:30 +0000 (03:07 +0100)
committerFrancis Dupont <fdupont@isc.org>
Tue, 2 Jan 2018 02:07:30 +0000 (03:07 +0100)
16 files changed:
src/bin/agent/agent_lexer.ll
src/bin/agent/agent_parser.yy
src/bin/agent/ca_cfg_mgr.cc
src/bin/agent/simple_parser.cc
src/bin/d2/d2_cfg_mgr.cc
src/bin/d2/d2_cfg_mgr.h
src/bin/d2/d2_config.cc
src/bin/d2/d2_config.h
src/bin/d2/d2_lexer.ll
src/bin/d2/d2_parser.yy
src/lib/cc/tests/Makefile.am
src/lib/cc/user_context.cc
src/lib/cc/user_context.h
src/lib/dhcpsrv/srv_config.cc
src/lib/process/d_cfg_mgr.cc
src/lib/process/d_cfg_mgr.h

index 91f95b26536b3a68c1134522cf77cd221ecd955c..aa1f92c825b11585b13ef292dd030a30124a514a 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (C) 2017 Internet Systems Consortium, Inc. ("ISC")
+/* Copyright (C) 2017-2018 Internet Systems Consortium, Inc. ("ISC")
 
    This Source Code Form is subject to the terms of the Mozilla Public
    License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -200,6 +200,28 @@ ControlCharacterFill            [^"\\]|\\{JSONEscapeSequence}
     }
 }
 
+\"user-context\" {
+    switch(driver.ctx_) {
+    case ParserContext::AGENT:
+    case ParserContext::SERVER:
+    case ParserContext::LOGGERS:
+        return AgentParser::make_USER_CONTEXT(driver.loc_);
+    default:
+        return AgentParser::make_STRING("user-context", driver.loc_);
+    }
+}
+
+\"comment\" {
+    switch(driver.ctx_) {
+    case ParserContext::AGENT:
+    case ParserContext::SERVER:
+    case ParserContext::LOGGERS:
+        return AgentParser::make_COMMENT(driver.loc_);
+    default:
+        return AgentParser::make_STRING("comment", driver.loc_);
+    }
+}
+
 \"control-sockets\" {
     switch(driver.ctx_) {
     case ParserContext::AGENT:
index 592a3228c246303716ac7410d0c95ff2cbdc69d2..a7cc9177432cea8f77c31000306462d8659df230 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (C) 2017 Internet Systems Consortium, Inc. ("ISC")
+/* Copyright (C) 2017-2018 Internet Systems Consortium, Inc. ("ISC")
 
    This Source Code Form is subject to the terms of the Mozilla Public
    License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -52,6 +52,9 @@ using namespace std;
   HTTP_HOST "http-host"
   HTTP_PORT "http-port"
 
+  USER_CONTEXT "user-context"
+  COMMENT "comment"
+
   CONTROL_SOCKETS "control-sockets"
   DHCP4_SERVER "dhcp4"
   DHCP6_SERVER "dhcp6"
@@ -155,6 +158,8 @@ map: LCURLY_BRACKET {
     // for it.
 };
 
+map_value: map { $$ = ctx.stack_.back(); ctx.stack_.pop_back(); };
+
 // Rule for map content. In some cases it is allowed to have an empty map,
 // so we should say that explicitly. In most cases, though, there will
 // be some actual content inside. That's defined by not_empty_map
@@ -267,6 +272,8 @@ global_param: http_host
             | http_port
             | control_sockets
             | hooks_libraries
+            | user_context
+            | comment
             | unknown_map_entry
             ;
 
@@ -283,6 +290,58 @@ http_port: HTTP_PORT COLON INTEGER {
     ctx.stack_.back()->set("http-port", prf);
 };
 
+user_context: USER_CONTEXT {
+    ctx.enter(ctx.NO_KEYWORD);
+} COLON map_value {
+    ElementPtr parent = ctx.stack_.back();
+    ElementPtr user_context = $4;
+    ConstElementPtr old = parent->get("user-context");
+
+    // Handle already existing user context
+    if (old) {
+        // Check if it was a comment or a duplicate
+        if ((old->size() != 1) || !old->contains("comment")) {
+            std::stringstream msg;
+            msg << "duplicate user-context entries (previous at "
+                << old->getPosition().str() << ")";
+            error(@1, msg.str());
+        }
+        // Merge the comment
+        user_context->set("comment", old->get("comment"));
+    }
+
+    // Set the user context
+    parent->set("user-context", user_context);
+    ctx.leave();
+};
+
+comment: COMMENT {
+    ctx.enter(ctx.NO_KEYWORD);
+} COLON STRING {
+    ElementPtr parent = ctx.stack_.back();
+    ElementPtr user_context(new MapElement(ctx.loc2pos(@1)));
+    ElementPtr comment(new StringElement($4, ctx.loc2pos(@4)));
+    user_context->set("comment", comment);
+
+    // Handle already existing user context
+    ConstElementPtr old = parent->get("user-context");
+    if (old) {
+        // Check for duplicate comment
+        if (old->contains("comment")) {
+            std::stringstream msg;
+            msg << "duplicate user-context/comment entries (previous at "
+                << old->getPosition().str() << ")";
+            error(@1, msg.str());
+        }
+        // Merge the user context in the comment
+        merge(user_context, old);
+    }
+
+    // Set the user context
+    parent->set("user-context", user_context);
+    ctx.leave();
+};
+
 // --- hooks-libraries ---------------------------------------------------------
 hooks_libraries: HOOKS_LIBRARIES {
     ElementPtr l(new ListElement(ctx.loc2pos(@1)));
@@ -403,6 +462,9 @@ control_socket_params: control_socket_param
 // We currently support two socket parameters: type and name.
 control_socket_param: socket_name
                     | socket_type
+                    | user_context
+                    | comment
+                    | unknown_map_entry
                     ;
 
 // This rule defines socket-name parameter.
@@ -510,6 +572,8 @@ logger_param: name
             | output_options_list
             | debuglevel
             | severity
+            | user_context
+            | comment
             | unknown_map_entry
             ;
 
index bece1c9deeb18188d83af30410b6a8378dc127ae..166defde412c288d59824ae801607212112a76c4 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright (C) 2016-2017 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2016-2018 Internet Systems Consortium, Inc. ("ISC")
 //
 // This Source Code Form is subject to the terms of the Mozilla Public
 // License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -143,6 +143,8 @@ CtrlAgentCfgContext::getControlSocketInfoSummary() const {
 ElementPtr
 CtrlAgentCfgContext::toElement() const {
     ElementPtr ca = Element::createMap();
+    // Set user-context
+    contextToElement(ca);
     // Set http-host
     ca->set("http-host", Element::create(http_host_));
     // Set http-port
@@ -152,7 +154,8 @@ CtrlAgentCfgContext::toElement() const {
     // Set control-sockets
     ElementPtr control_sockets = Element::createMap();
     for (auto si = ctrl_sockets_.cbegin(); si != ctrl_sockets_.cend(); ++si) {
-        control_sockets->set(si->first, si->second);
+        ConstElementPtr socket = UserContext::toElement(si->second);
+        control_sockets->set(si->first, socket);
     }
     ca->set("control-sockets", control_sockets);
     // Set Control-agent
index 8eb77005924a3988aaf5f54175d1b929af299fc2..39d182f8297691bd076ccf77c2be61816e16ed3a 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright (C) 2017 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2017-2018 Internet Systems Consortium, Inc. ("ISC")
 //
 // This Source Code Form is subject to the terms of the Mozilla Public
 // License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -95,6 +95,12 @@ AgentSimpleParser::parse(const CtrlAgentCfgContextPtr& ctx,
         }
     }
 
+    // User context can be done at anytime.
+    ConstElementPtr user_context = config->get("user-context");
+    if (user_context) {
+        ctx->setContext(user_context);
+    }
+
     // Finally, let's get the hook libs!
     
     using namespace isc::hooks;
index 9a94b08643b5590c4692c3a7d44085eca6245747..c3e87f037f37c7b27070dec2efc04b842d36f8c8 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright (C) 2014-2017 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2014-2018 Internet Systems Consortium, Inc. ("ISC")
 //
 // This Source Code Form is subject to the terms of the Mozilla Public
 // License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -56,6 +56,8 @@ D2CfgContext::~D2CfgContext() {
 ElementPtr
 D2CfgContext::toElement() const {
     ElementPtr d2 = Element::createMap();
+    // Set user-context
+    contextToElement(d2);
     // Set ip-address
     const IOAddress& ip_address = d2_params_->getIpAddress();
     d2->set("ip-address", Element::create(ip_address.toText()));
@@ -247,7 +249,7 @@ D2CfgMgr::getConfigSummary(const uint32_t) {
 namespace {
 
 template <typename int_type> int_type
-getInt(const std::string& name, isc::data::ConstElementPtr value) {
+getInt(const std::string& name, ConstElementPtr value) {
     int64_t val_int = value->intValue();
     if ((val_int < std::numeric_limits<int_type>::min()) ||
         (val_int > std::numeric_limits<int_type>::max())) {
@@ -259,7 +261,7 @@ getInt(const std::string& name, isc::data::ConstElementPtr value) {
 }
 
 isc::asiolink::IOAddress
-getIOAddress(const std::string& name, isc::data::ConstElementPtr value) {
+getIOAddress(const std::string& name, ConstElementPtr value) {
     std::string str = value->stringValue();
     try {
         return (isc::asiolink::IOAddress(str));
@@ -271,7 +273,7 @@ getIOAddress(const std::string& name, isc::data::ConstElementPtr value) {
 }
 
 dhcp_ddns::NameChangeProtocol
-getProtocol(const std::string& name, isc::data::ConstElementPtr value) {
+getProtocol(const std::string& name, ConstElementPtr value) {
     std::string str = value->stringValue();
     try {
         return (dhcp_ddns::stringToNcrProtocol(str));
@@ -284,7 +286,7 @@ getProtocol(const std::string& name, isc::data::ConstElementPtr value) {
 }
 
 dhcp_ddns::NameChangeFormat
-getFormat(const std::string& name, isc::data::ConstElementPtr value) {
+getFormat(const std::string& name, ConstElementPtr value) {
     std::string str = value->stringValue();
     try {
         return (dhcp_ddns::stringToNcrFormat(str));
@@ -300,7 +302,7 @@ getFormat(const std::string& name, isc::data::ConstElementPtr value) {
 
 void
 D2CfgMgr::parseElement(const std::string& element_id,
-                       isc::data::ConstElementPtr element) {
+                       ConstElementPtr element) {
     try {
         // Get D2 specific context.
         D2CfgContextPtr context = getD2CfgContext();
@@ -311,6 +313,10 @@ D2CfgMgr::parseElement(const std::string& element_id,
             (element_id == "port")  ||
             (element_id == "dns-server-timeout"))  {
             // global scalar params require nothing extra be done
+        } else if (element_id == "user-context") {
+            if (element->getType() == Element::map) {
+                context->setContext(element);
+            }
         } else if (element_id == "tsig-keys") {
             TSIGKeyInfoListParser parser;
             context->setKeys(parser.parse(element));
@@ -339,12 +345,12 @@ D2CfgMgr::parseElement(const std::string& element_id,
 };
 
 void
-D2CfgMgr::setCfgDefaults(isc::data::ElementPtr mutable_config) {
+D2CfgMgr::setCfgDefaults(ElementPtr mutable_config) {
     D2SimpleParser::setAllDefaults(mutable_config);
 }
 
 void
-D2CfgMgr::buildParams(isc::data::ConstElementPtr params_config) {
+D2CfgMgr::buildParams(ConstElementPtr params_config) {
 
     // Base class build creates parses and invokes build on each parser.
     // This populate the context scalar stores with all of the parameters.
@@ -361,7 +367,7 @@ D2CfgMgr::buildParams(isc::data::ConstElementPtr params_config) {
     // Assumes that params_config has had defaults added
     BOOST_FOREACH(isc::dhcp::ConfigPair param, params_config->mapValue()) {
         std::string entry(param.first);
-        isc::data::ConstElementPtr value(param.second);
+        ConstElementPtr value(param.second);
         try {
             if (entry == "ip-address") {
                 ip_address = getIOAddress(entry, value);
index ca3f77940edb009149f8486b2b679717b73437cb..564a551ae822d0105b5766a19fbc6d3c42fc8eed 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright (C) 2014-2017 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2014-2018 Internet Systems Consortium, Inc. ("ISC")
 //
 // This Source Code Form is subject to the terms of the Mozilla Public
 // License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -270,7 +270,7 @@ protected:
     /// it to be processed by SimpleParser derivations if they've been
     /// implemented. The method should return true if it has processed the
     /// element or false if the element should be passed onto the original
-    /// DhcpConfigParer mechanisms.  This method is invoked in both
+    /// DhcpConfigParser mechanisms.  This method is invoked in both
     /// @c DCfgMgrBase::buildParams() and DCfgMgrBase::buildAndCommit().
     ///
     /// @param element_id name of the element as it is expected in the cfg
index 37dba622c6582394e12b89b696c12eb847f6d395..7a02fb5a8b0ae2c5b9b05249645db8db19ce8e5b 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright (C) 2013-2017 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2013-2018 Internet Systems Consortium, Inc. ("ISC")
 //
 // This Source Code Form is subject to the terms of the Mozilla Public
 // License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -184,6 +184,8 @@ TSIGKeyInfo::remakeKey() {
 ElementPtr
 TSIGKeyInfo::toElement() const {
     ElementPtr result = Element::createMap();
+    // Set user-context
+    contextToElement(result);
     // Set name
     result->set("name", Element::create(name_));
     // Set algorithm
@@ -218,6 +220,8 @@ DnsServerInfo::toText() const {
 ElementPtr
 DnsServerInfo::toElement() const {
     ElementPtr result = Element::createMap();
+    // Set user-context
+    contextToElement(result);
     // Set hostname
     result->set("hostname", Element::create(hostname_));
     // Set ip-address
@@ -259,6 +263,8 @@ DdnsDomain::getKeyName() const {
 ElementPtr
 DdnsDomain::toElement() const {
     ElementPtr result = Element::createMap();
+    // Set user-context
+    contextToElement(result);
     // Set name
     result->set("name", Element::create(name_));
     // Set servers
@@ -393,11 +399,12 @@ DdnsDomainListMgr::toElement() const {
 // *********************** TSIGKeyInfoParser  *************************
 
 TSIGKeyInfoPtr
-TSIGKeyInfoParser::parse(data::ConstElementPtr key_config) {
+TSIGKeyInfoParser::parse(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");
+    ConstElementPtr user_context = key_config->get("user-context");
 
     // Algorithm must be valid.
     try {
@@ -435,15 +442,20 @@ TSIGKeyInfoParser::parse(data::ConstElementPtr key_config) {
                   << key_config->getPosition() << ")");
     }
 
+    // Add user-context
+    if (user_context) {
+        key_info->setContext(user_context);
+    }
+
     return (key_info);
 }
 
 // *********************** TSIGKeyInfoListParser  *************************
 
 TSIGKeyInfoMapPtr
-TSIGKeyInfoListParser::parse(data::ConstElementPtr key_list) {
+TSIGKeyInfoListParser::parse(ConstElementPtr key_list) {
     TSIGKeyInfoMapPtr keys(new TSIGKeyInfoMap());
-    data::ConstElementPtr key_config;
+    ConstElementPtr key_config;
     TSIGKeyInfoParser key_parser;
     BOOST_FOREACH(key_config, key_list->listValue()) {
         TSIGKeyInfoPtr key = key_parser.parse(key_config);
@@ -464,10 +476,11 @@ TSIGKeyInfoListParser::parse(data::ConstElementPtr key_list) {
 // *********************** DnsServerInfoParser  *************************
 
 DnsServerInfoPtr
-DnsServerInfoParser::parse(data::ConstElementPtr server_config) {
+DnsServerInfoParser::parse(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");
+    ConstElementPtr user_context = server_config->get("user-context");
 
     // The configuration must specify one or the other.
     if (hostname.empty() == ip_address.empty()) {
@@ -506,15 +519,20 @@ DnsServerInfoParser::parse(data::ConstElementPtr server_config) {
         }
     }
 
-    return(server_info);
+    // Add user-context
+    if (user_context) {
+        server_info->setContext(user_context);
+    }
+
+    return (server_info);
 }
 
 // *********************** DnsServerInfoListParser  *************************
 
 DnsServerInfoStoragePtr
-DnsServerInfoListParser::parse(data::ConstElementPtr server_list) {
+DnsServerInfoListParser::parse(ConstElementPtr server_list) {
     DnsServerInfoStoragePtr servers(new DnsServerInfoStorage());
-    data::ConstElementPtr server_config;
+    ConstElementPtr server_config;
     DnsServerInfoParser parser;
     BOOST_FOREACH(server_config, server_list->listValue()) {
         DnsServerInfoPtr server = parser.parse(server_config);
@@ -526,10 +544,11 @@ DnsServerInfoListParser::parse(data::ConstElementPtr server_list) {
 
 // *********************** DdnsDomainParser  *************************
 
-DdnsDomainPtr DdnsDomainParser::parse(data::ConstElementPtr domain_config,
+DdnsDomainPtr DdnsDomainParser::parse(ConstElementPtr domain_config,
                                       const TSIGKeyInfoMapPtr keys) {
     std::string name = getString(domain_config, "name");
     std::string key_name = getString(domain_config, "key-name");
+    ConstElementPtr user_context = domain_config->get("user-context");
 
     // Key name is optional. If it is not blank, then find the key in the
     // list of defined keys.
@@ -550,7 +569,7 @@ DdnsDomainPtr DdnsDomainParser::parse(data::ConstElementPtr domain_config,
     }
 
     // Parse the list of DNS servers
-    data::ConstElementPtr servers_config;
+    ConstElementPtr servers_config;
     try {
         servers_config = domain_config->get("dns-servers");
     } catch (const std::exception& ex) {
@@ -568,16 +587,21 @@ DdnsDomainPtr DdnsDomainParser::parse(data::ConstElementPtr domain_config,
     // Instantiate the new domain and add it to domain storage.
     DdnsDomainPtr domain(new DdnsDomain(name, servers, tsig_key_info));
 
-    return(domain);
+    // Add user-context
+    if (user_context) {
+        domain->setContext(user_context);
+    }
+
+    return (domain);
 }
 
 // *********************** DdnsDomainListParser  *************************
 
-DdnsDomainMapPtr DdnsDomainListParser::parse(data::ConstElementPtr domain_list,
+DdnsDomainMapPtr DdnsDomainListParser::parse(ConstElementPtr domain_list,
                                              const TSIGKeyInfoMapPtr keys) {
     DdnsDomainMapPtr domains(new DdnsDomainMap());
     DdnsDomainParser parser;
-    data::ConstElementPtr domain_config;
+    ConstElementPtr domain_config;
     BOOST_FOREACH(domain_config, domain_list->listValue()) {
         DdnsDomainPtr domain = parser.parse(domain_config, keys);
 
@@ -597,13 +621,13 @@ DdnsDomainMapPtr DdnsDomainListParser::parse(data::ConstElementPtr domain_list,
 // *********************** DdnsDomainListMgrParser  *************************
 
 DdnsDomainListMgrPtr
-DdnsDomainListMgrParser::parse(data::ConstElementPtr mgr_config,
+DdnsDomainListMgrParser::parse(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");
+    ConstElementPtr domains_config = mgr_config->get("ddns-domains");
     if (domains_config) {
         DdnsDomainListParser domain_parser;
         DdnsDomainMapPtr domains =  domain_parser.parse(domains_config, keys);
index 8eb7e6a2dbb506b7d6d53e90756b2cde41b40b94..13bf87532134d0a39272644fb86d44ec6512445e 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright (C) 2013-2017 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2013-2018 Internet Systems Consortium, Inc. ("ISC")
 //
 // This Source Code Form is subject to the terms of the Mozilla Public
 // License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -11,6 +11,7 @@
 #include <cc/data.h>
 #include <cc/simple_parser.h>
 #include <cc/cfg_to_element.h>
+#include <cc/user_context.h>
 #include <dhcpsrv/parsers/dhcp_parsers.h>
 #include <dns/tsig.h>
 #include <exceptions/exceptions.h>
@@ -256,7 +257,7 @@ typedef boost::shared_ptr<D2Params> D2ParamsPtr;
 /// instance of the actual key (@ref isc::dns::TSIGKey) that can be used
 /// by the IO layer for signing and verifying messages.
 ///
-class TSIGKeyInfo : public isc::data::CfgToElement {
+class TSIGKeyInfo : public isc::dhcp::UserContext, public isc::data::CfgToElement {
 public:
     /// @brief Defines string values for the supported TSIG algorithms
     //@{
@@ -411,7 +412,7 @@ typedef boost::shared_ptr<TSIGKeyInfoMap> TSIGKeyInfoMapPtr;
 /// belongs to a list of servers supporting DNS for a given domain. It will
 /// be used to establish communications with the server to carry out DNS
 /// updates.
-class DnsServerInfo : public isc::data::CfgToElement {
+class DnsServerInfo : public isc::dhcp::UserContext, public isc::data::CfgToElement {
 public:
     /// @brief defines DNS standard port value
     static const uint32_t STANDARD_DNS_PORT = 53;
@@ -521,7 +522,7 @@ typedef boost::shared_ptr<DnsServerInfoStorage> DnsServerInfoStoragePtr;
 /// @todo Currently the name entry for a domain is just an std::string. It
 /// may be worthwhile to change this to a dns::Name for purposes of better
 /// validation and matching capabilities.
-class DdnsDomain : public isc::data::CfgToElement {
+class DdnsDomain : public isc::dhcp::UserContext, public isc::data::CfgToElement {
 public:
     /// @brief Constructor
     ///
@@ -742,7 +743,7 @@ typedef boost::shared_ptr<DScalarContext> DScalarContextPtr;
 ///
 /// This class parses the configuration element "tsig-key"
 /// and creates an instance of a TSIGKeyInfo.
-class TSIGKeyInfoParser : public  data::SimpleParser {
+class TSIGKeyInfoParser : public data::SimpleParser {
 public:
     /// @brief Performs the actual parsing of the given "tsig-key" element.
     ///
@@ -781,7 +782,7 @@ public:
 ///
 /// This class parses the configuration element "dns-server"
 /// and creates an instance of a DnsServerInfo.
-class DnsServerInfoParser : public  data::SimpleParser {
+class DnsServerInfoParser : public data::SimpleParser {
 public:
     /// @brief Performs the actual parsing of the given  "dns-server" element.
     ///
index 887e01878c9e7fb12c6f17a50b9c1ed9c5c91592..bc26b334bd61a89c3d5b031e7b123f11d070c499 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (C) 2017 Internet Systems Consortium, Inc. ("ISC")
+/* Copyright (C) 2017-2018 Internet Systems Consortium, Inc. ("ISC")
 
    This Source Code Form is subject to the terms of the Mozilla Public
    License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -260,6 +260,38 @@ ControlCharacterFill            [^"\\]|\\{JSONEscapeSequence}
     return isc::d2::D2Parser::make_STRING(tmp, driver.loc_);
 }
 
+\"user-context\" {
+    switch(driver.ctx_) {
+    case isc::d2::D2ParserContext::DHCPDDNS:
+    case isc::d2::D2ParserContext::DDNS_DOMAIN:
+    case isc::d2::D2ParserContext::DDNS_DOMAINS:
+    case isc::d2::D2ParserContext::DNS_SERVER:
+    case isc::d2::D2ParserContext::DNS_SERVERS:
+    case isc::d2::D2ParserContext::TSIG_KEY:
+    case isc::d2::D2ParserContext::TSIG_KEYS:
+    case isc::d2::D2ParserContext::LOGGERS:
+        return isc::d2::D2Parser::make_USER_CONTEXT(driver.loc_);
+    default:
+        return isc::d2::D2Parser::make_STRING("user-context", driver.loc_);
+    }
+}
+
+\"comment\" {
+    switch(driver.ctx_) {
+    case isc::d2::D2ParserContext::DHCPDDNS:
+    case isc::d2::D2ParserContext::DDNS_DOMAIN:
+    case isc::d2::D2ParserContext::DDNS_DOMAINS:
+    case isc::d2::D2ParserContext::DNS_SERVER:
+    case isc::d2::D2ParserContext::DNS_SERVERS:
+    case isc::d2::D2ParserContext::TSIG_KEY:
+    case isc::d2::D2ParserContext::TSIG_KEYS:
+    case isc::d2::D2ParserContext::LOGGERS:
+        return isc::d2::D2Parser::make_COMMENT(driver.loc_);
+    default:
+        return isc::d2::D2Parser::make_STRING("comment", driver.loc_);
+    }
+}
+
 \"forward-ddns\" {
     switch(driver.ctx_) {
     case isc::d2::D2ParserContext::DHCPDDNS:
index 0a4e45744e8ae3ad3b4fe760f1bca25479f988b2..8ab35cdcf25efac0c475c61c5cdad242ba610861 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (C) 2017 Internet Systems Consortium, Inc. ("ISC")
+/* Copyright (C) 2017-2018 Internet Systems Consortium, Inc. ("ISC")
 
    This Source Code Form is subject to the terms of the Mozilla Public
    License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -62,6 +62,8 @@ using namespace std;
   TCP "TCP"
   NCR_FORMAT "ncr-format"
   JSON "JSON"
+  USER_CONTEXT "user-context"
+  COMMENT "comment"
   FORWARD_DDNS "forward-ddns"
   REVERSE_DDNS "reverse-ddns"
   DDNS_DOMAINS "ddns-domains"
@@ -155,6 +157,8 @@ map2: LCURLY_BRACKET {
     // for it.
 };
 
+map_value: map2 { $$ = ctx.stack_.back(); ctx.stack_.pop_back(); };
+
 // Assignments rule
 map_content: %empty // empty map
            | not_empty_map
@@ -265,6 +269,8 @@ dhcpddns_param: ip_address
               | forward_ddns
               | reverse_ddns
               | tsig_keys
+              | user_context
+              | comment
               | unknown_map_entry
               ;
 
@@ -313,6 +319,58 @@ ncr_format: NCR_FORMAT {
     ctx.leave();
 };
 
+user_context: USER_CONTEXT {
+    ctx.enter(ctx.NO_KEYWORD);
+} COLON map_value {
+    ElementPtr parent = ctx.stack_.back();
+    ElementPtr user_context = $4;
+    ConstElementPtr old = parent->get("user-context");
+
+    // Handle already existing user context
+    if (old) {
+        // Check if it was a comment or a duplicate
+        if ((old->size() != 1) || !old->contains("comment")) {
+            std::stringstream msg;
+            msg << "duplicate user-context entries (previous at "
+                << old->getPosition().str() << ")";
+            error(@1, msg.str());
+        }
+        // Merge the comment
+        user_context->set("comment", old->get("comment"));
+    }
+
+    // Set the user context
+    parent->set("user-context", user_context);
+    ctx.leave();
+};
+
+comment: COMMENT {
+    ctx.enter(ctx.NO_KEYWORD);
+} COLON STRING {
+    ElementPtr parent = ctx.stack_.back();
+    ElementPtr user_context(new MapElement(ctx.loc2pos(@1)));
+    ElementPtr comment(new StringElement($4, ctx.loc2pos(@4)));
+    user_context->set("comment", comment);
+
+    // Handle already existing user context
+    ConstElementPtr old = parent->get("user-context");
+    if (old) {
+        // Check for duplicate comment
+        if (old->contains("comment")) {
+            std::stringstream msg;
+            msg << "duplicate user-context/comment entries (previous at "
+                << old->getPosition().str() << ")";
+            error(@1, msg.str());
+        }
+        // Merge the user context in the comment
+        merge(user_context, old);
+    }
+
+    // Set the user context
+    parent->set("user-context", user_context);
+    ctx.leave();
+};
+
 forward_ddns : FORWARD_DDNS {
     ElementPtr m(new MapElement(ctx.loc2pos(@1)));
     ctx.stack_.back()->set("forward-ddns", m);
@@ -394,6 +452,8 @@ ddns_domain_params: ddns_domain_param
 ddns_domain_param: ddns_domain_name
                  | ddns_domain_key_name
                  | dns_servers
+                 | user_context
+                 | comment
                  | unknown_map_entry
                  ;
 
@@ -465,6 +525,8 @@ dns_server_params: dns_server_param
 dns_server_param: dns_server_hostname
               | dns_server_ip_address
               | dns_server_port
+              | user_context
+              | comment
               | unknown_map_entry
               ;
 
@@ -552,6 +614,8 @@ tsig_key_param: tsig_key_name
               | tsig_key_algorithm
               | tsig_key_digest_bits
               | tsig_key_secret
+              | user_context
+              | comment
               | unknown_map_entry
               ;
 
@@ -682,6 +746,8 @@ logger_param: name
             | output_options_list
             | debuglevel
             | severity
+            | user_context
+            | comment
             | unknown_map_entry
             ;
 
index f07e9c75cb394e81e5c822b03a4d96117321960c..452926e36c7105f96d7ca74996209d1fe6a01775 100644 (file)
@@ -14,11 +14,13 @@ TESTS_ENVIRONMENT = \
 TESTS =
 if HAVE_GTEST
 TESTS += run_unittests
-run_unittests_SOURCES = command_interpreter_unittests.cc data_unittests.cc
+run_unittests_SOURCES = command_interpreter_unittests.cc
+run_unittests_SOURCES += data_unittests.cc
 run_unittests_SOURCES += data_file_unittests.cc
 run_unittests_SOURCES += json_feed_unittests.cc
-run_unittests_SOURCES += run_unittests.cc
 run_unittests_SOURCES += simple_parser_unittest.cc
+run_unittests_SOURCES += user_context_unittests.cc
+run_unittests_SOURCES += run_unittests.cc
 run_unittests_CPPFLAGS = $(AM_CPPFLAGS) $(GTEST_INCLUDES)
 run_unittests_LDFLAGS = $(AM_LDFLAGS) $(GTEST_LDFLAGS)
 
index e7086d4f4af9d518da361dfe0dcec7e43ad79de4..e4e239919877870c4f5d39165552f17352a6a914 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright (C) 2017 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2017-2018 Internet Systems Consortium, Inc. ("ISC")
 //
 // This Source Code Form is subject to the terms of the Mozilla Public
 // License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -12,7 +12,7 @@ namespace isc {
 namespace dhcp {
 
 void
-UserContext::contextToElement(ElementPtr map) const{
+UserContext::contextToElement(ElementPtr map) const {
     // Set user-context extracting comment
     ConstElementPtr context = getContext();
     if (!isNull(context)) {
@@ -30,5 +30,30 @@ UserContext::contextToElement(ElementPtr map) const{
     }
 }
 
+ElementPtr
+UserContext::toElement(ConstElementPtr map) {
+    ElementPtr result = isc::data::copy(map);
+    // Protect against argument not map
+    if (result->getType() != Element::map) {
+        return (result);
+    }
+    ConstElementPtr ctx = result->get("user-context");
+    // Protect against user context not map
+    if (!ctx || (ctx->getType() != Element::map)) {
+        return (result);
+    }
+    // Extract comment
+    if (ctx->contains("comment")) {
+        ElementPtr ctx_copy = isc::data::copy(ctx);
+        result->set("comment", ctx_copy->get("comment"));
+        ctx_copy->remove("comment");
+        result->remove("user-context");
+        if (ctx_copy->size() > 0) {
+            result->set("user-context", ctx_copy);
+        }
+    }
+    return (result);
+}
+
 }; // end of isc::dhcp namespace
 }; // end of isc namespace
index c1d92e2c061e6051de487c8829278acdcbd5766a..58067b4438a0e8007f6be79d669d4f86be46e8f9 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright (C) 2017 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2017-2018 Internet Systems Consortium, Inc. ("ISC")
 //
 // This Source Code Form is subject to the terms of the Mozilla Public
 // License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -39,6 +39,12 @@ struct UserContext {
     /// @param map A pointer to map where the user context will be unparsed.
     void contextToElement(data::ElementPtr map) const;
 
+    /// @brief Copy extracting comments an Element map
+    ///
+    /// @param map A pointer to map.
+    /// @return a copy of map where comment is extracted.
+    static data::ElementPtr toElement(data::ConstElementPtr map);
+
 protected:
 
     /// @brief Pointer to the user context (may be NULL)
index fef466d19f10b215038168592036440c05370e12..a5bc6c9ce91507f47c7785e20cf34d03260d4f73 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright (C) 2014-2017 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2014-2018 Internet Systems Consortium, Inc. ("ISC")
 //
 // This Source Code Form is subject to the terms of the Mozilla Public
 // License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -363,23 +363,7 @@ SrvConfig::toElement() const {
     }
     // Set control-socket (skip if null as empty is not legal)
     if (!isNull(control_socket_)) {
-        ElementPtr csocket = isc::data::copy(control_socket_);
-        ConstElementPtr ctx = csocket->get("user-context");
-        // Protect against not map
-        if (ctx && (ctx->getType() != Element::map)) {
-            ctx.reset();
-        }
-        // Extract comment
-        if (ctx && ctx->contains("comment")) {
-            ElementPtr ctx_copy = isc::data::copy(ctx);
-            csocket->set("comment", ctx_copy->get("comment"));
-            ctx_copy->remove("comment");
-            csocket->remove("user-context");
-            if (ctx_copy->size() > 0) {
-                csocket->set("user-context", ctx_copy);
-            }
-        }
-        dhcp->set("control-socket", csocket);
+        dhcp->set("control-socket", UserContext::toElement(control_socket_));
     }
     // Set client-classes
     ConstElementPtr client_classes = class_dictionary_->toElement();
index c68a1397ad6c4fc5a96c59d361843e95c4abb51f..b67b5000b560dd9a1348d85a13d4caf7ed87fa23 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright (C) 2013-2017 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2013-2018 Internet Systems Consortium, Inc. ("ISC")
 //
 // This Source Code Form is subject to the terms of the Mozilla Public
 // License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -213,6 +213,15 @@ DCfgMgrBase::parseConfig(isc::data::ConstElementPtr config_set,
                 }
             }
 
+            // Handle user context here as it is really optional.
+            std::string user_context_id("user-context");
+            it = objects_map.find(user_context_id);
+            if (it != objects_map.end()) {
+                buildAndCommit(user_context_id, it->second);
+                // We parsed it, take it out of the list.
+                objects_map.erase(it);
+            }
+
             // NOTE: When using ordered parsing, the parse order list MUST
             // include every possible element id that the value_map may contain.
             // Entries in the map that are not in the parse order, will not be
index 1d9e736aff02d14b95a228179a7ab857d74fb601..d9ff933ea0d8fc64c6645cdeca36a626bca31101 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright (C) 2013-2017 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2013-2018 Internet Systems Consortium, Inc. ("ISC")
 //
 // This Source Code Form is subject to the terms of the Mozilla Public
 // License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -9,6 +9,7 @@
 
 #include <cc/data.h>
 #include <cc/cfg_to_element.h>
+#include <cc/user_context.h>
 #include <exceptions/exceptions.h>
 #include <dhcpsrv/parsers/dhcp_parsers.h>
 #include <functional>
@@ -59,7 +60,7 @@ typedef boost::shared_ptr<DCfgContextBase> DCfgContextBasePtr;
 ///    // Restore from backup
 ///    context_ = backup_copy;
 ///
-class DCfgContextBase : public isc::data::CfgToElement {
+class DCfgContextBase : public isc::dhcp::UserContext, public isc::data::CfgToElement {
 public:
     /// @brief Indicator that a configuration parameter is optional.
     static const bool OPTIONAL = true;