\"user-context\" {
switch(driver.ctx_) {
+ case isc::dhcp::Parser4Context::DHCP4:
case isc::dhcp::Parser4Context::SUBNET4:
case isc::dhcp::Parser4Context::POOLS:
case isc::dhcp::Parser4Context::SHARED_NETWORK:
+ case isc::dhcp::Parser4Context::OPTION_DEF:
return isc::dhcp::Dhcp4Parser::make_USER_CONTEXT(driver.loc_);
default:
return isc::dhcp::Dhcp4Parser::make_STRING("user-context", driver.loc_);
\"comment\" {
switch(driver.ctx_) {
+ case isc::dhcp::Parser4Context::DHCP4:
case isc::dhcp::Parser4Context::SUBNET4:
case isc::dhcp::Parser4Context::POOLS:
case isc::dhcp::Parser4Context::SHARED_NETWORK:
+ case isc::dhcp::Parser4Context::OPTION_DEF:
return isc::dhcp::Dhcp4Parser::make_COMMENT(driver.loc_);
default:
return isc::dhcp::Dhcp4Parser::make_STRING("comment", driver.loc_);
| next_server
| server_hostname
| boot_file_name
+ | user_context
+ | comment
| unknown_map_entry
;
| option_def_space
| option_def_encapsulate
| option_def_array
+ | user_context
+ | comment
| unknown_map_entry
;
/// - echo-client-id
/// - decline-probation-period
/// - dhcp4o6-port
+ /// - user-context
///
/// @throw DhcpConfigError if parameters are missing or
/// or having incorrect values.
// Set the DHCPv4-over-DHCPv6 interserver port.
uint16_t dhcp4o6_port = getUint16(global, "dhcp4o6-port");
cfg->setDhcp4o6Port(dhcp4o6_port);
+
+ // Set the global user context.
+ ConstElementPtr user_context = global->get("user-context");
+ if (user_context) {
+ cfg->setContext(user_context);
+ }
}
/// @brief Copies subnets from shared networks to regular subnets container
// Timers are not used in the global scope. Their values are derived
// to specific subnets (see SimpleParser6::deriveParameters).
- // decline-probation-period, dhcp4o6-port, echo-client-id are
- // handled in global_parser.parse() which sets global parameters.
+ // decline-probation-period, dhcp4o6-port, echo-client-id,
+ // user-context are handled in global_parser.parse() which
+ // sets global parameters.
// match-client-id is derived to subnet scope level.
if ( (config_pair.first == "renew-timer") ||
(config_pair.first == "rebind-timer") ||
(config_pair.first == "decline-probation-period") ||
(config_pair.first == "dhcp4o6-port") ||
(config_pair.first == "echo-client-id") ||
+ (config_pair.first == "user-context") ||
(config_pair.first == "match-client-id") ||
(config_pair.first == "next-server") ||
(config_pair.first == "server-hostname") ||
TEST_F(Dhcp4ParserTest, comments) {
string config = "{\n"
+ "\"comment\": \"A DHCPv4 server\",\n"
+ "\"option-def\": [ {\n"
+ " \"name\": \"foo\",\n"
+ " \"code\": 100,\n"
+ " \"comment\": \"An option definition\",\n"
+ " \"type\": \"ipv4-address\",\n"
+ " \"space\": \"isc\"\n"
+ " } ],\n"
"\"shared-networks\": [ {\n"
" \"name\": \"foo\"\n,"
- " \"comment\": \"A shared-network\"\n,"
+ " \"comment\": \"A shared network\"\n,"
" \"subnet4\": [\n"
" { \n"
" \"subnet\": \"192.0.1.0/24\",\n"
extractConfig(config);
configure(config, CONTROL_RESULT_SUCCESS, "");
+ // Check global user context.
+ ConstElementPtr ctx = CfgMgr::instance().getStagingCfg()->getContext();
+ ASSERT_TRUE(ctx);
+ ASSERT_EQ(1, ctx->size());
+ ASSERT_TRUE(ctx->get("comment"));
+ EXPECT_EQ("\"A DHCPv4 server\"", ctx->get("comment")->str());
+
+ // Make the option definition available.
+ LibDHCP::commitRuntimeOptionDefs();
+
+ // Get and verify the option definition.
+ OptionDefinitionPtr opt_def = LibDHCP::getRuntimeOptionDef("isc", 100);
+ ASSERT_TRUE(opt_def);
+ EXPECT_EQ("foo", opt_def->getName());
+ EXPECT_EQ(1, opt_def->getCode());
+ EXPECT_FALSE(opt_def->getArrayType());
+ EXPECT_EQ(OPT_IPV4_ADDRESS_TYPE, opt_def->getType());
+ EXPECT_TRUE(opt_def->getEncapsulatedSpace().empty());
+
+ // Check option definition user context
+ ConstElementPtr ctx_opt_def = opt_def->getContext();
+ ASSERT_TRUE(ctx_opt_def);
+ ASSERT_EQ(1, ctx_opt_def->size());
+ ASSERT_TRUE(ctx_opt_def->get("comment"));
+ EXPECT_EQ("\"An option definition\"", ctx_opt_def->get("comment")->str());
+
// Now verify that the shared network was indeed configured.
CfgSharedNetworks4Ptr cfg_net = CfgMgr::instance().getStagingCfg()
->getCfgSharedNetworks4();
ASSERT_TRUE(ctx_net);
ASSERT_EQ(1, ctx_net->size());
ASSERT_TRUE(ctx_net->get("comment"));
- EXPECT_EQ("\"A shared-network\"", ctx_net->get("comment")->str());
+ EXPECT_EQ("\"A shared network\"", ctx_net->get("comment")->str());
// The shared network has a subnet.
const Subnet4Collection * subs = net->getAllSubnets();
ConstElementPtr comment = config::parseAnswer(rcode, status);
ASSERT_EQ(0, rcode);
ASSERT_NO_THROW( {
- CfgDbAccessPtr cfg_db = CfgMgr::instance().getStagingCfg()->getCfgDbAccess();
- cfg_db->setAppendedParameters("universe=4");
- cfg_db->createManagers();
+ CfgDbAccessPtr cfg_db = CfgMgr::instance().getStagingCfg()->getCfgDbAccess();
+ cfg_db->setAppendedParameters("universe=4");
+ cfg_db->createManagers();
} );
CfgMgr::instance().commit();
\"user-context\" {
switch(driver.ctx_) {
+ case isc::dhcp::Parser6Context::DHCP6:
case isc::dhcp::Parser6Context::POOLS:
case isc::dhcp::Parser6Context::PD_POOLS:
case isc::dhcp::Parser6Context::SUBNET6:
case isc::dhcp::Parser6Context::SHARED_NETWORK:
+ case isc::dhcp::Parser6Context::OPTION_DEF:
return isc::dhcp::Dhcp6Parser::make_USER_CONTEXT(driver.loc_);
default:
return isc::dhcp::Dhcp6Parser::make_STRING("user-context", driver.loc_);
\"comment\" {
switch(driver.ctx_) {
+ case isc::dhcp::Parser6Context::DHCP6:
case isc::dhcp::Parser6Context::POOLS:
case isc::dhcp::Parser6Context::PD_POOLS:
case isc::dhcp::Parser6Context::SUBNET6:
case isc::dhcp::Parser6Context::SHARED_NETWORK:
+ case isc::dhcp::Parser6Context::OPTION_DEF:
return isc::dhcp::Dhcp6Parser::make_COMMENT(driver.loc_);
default:
return isc::dhcp::Dhcp6Parser::make_STRING("comment", driver.loc_);
| dhcp4o6_port
| control_socket
| dhcp_ddns
+ | user_context
+ | comment
| unknown_map_entry
;
| option_def_space
| option_def_encapsulate
| option_def_array
+ | user_context
+ | comment
| unknown_map_entry
;
///
/// - decline-probation-period
/// - dhcp4o6-port
+ /// - user-context
///
/// @throw DhcpConfigError if parameters are missing or
/// or having incorrect values.
// Set the DHCPv4-over-DHCPv6 interserver port.
uint16_t dhcp4o6_port = getUint16(global, "dhcp4o6-port");
srv_config->setDhcp4o6Port(dhcp4o6_port);
+
+ // Set the global user context.
+ ConstElementPtr user_context = global->get("user-context");
+ if (user_context) {
+ srv_config->setContext(user_context);
+ }
}
/// @brief Copies subnets from shared networks to regular subnets container
// Timers are not used in the global scope. Their values are derived
// to specific subnets (see SimpleParser6::deriveParameters).
- // decline-probation-period and dhcp4o6-port are handled in the
- // global_parser.parse() which sets global parameters.
+ // decline-probation-period, dhcp4o6-port and user-context
+ // are handled in the global_parser.parse() which sets
+ // global parameters.
if ( (config_pair.first == "renew-timer") ||
(config_pair.first == "rebind-timer") ||
(config_pair.first == "preferred-lifetime") ||
(config_pair.first == "valid-lifetime") ||
(config_pair.first == "decline-probation-period") ||
- (config_pair.first == "dhcp4o6-port")) {
+ (config_pair.first == "dhcp4o6-port") ||
+ (config_pair.first == "user-context")) {
continue;
}
TEST_F(Dhcp6ParserTest, comments) {
string config = "{\n"
+ "\"comment\": \"A DHCPv6 server\",\n"
+ "\"option-def\": [ {\n"
+ " \"name\": \"foo\",\n"
+ " \"code\": 100,\n"
+ " \"comment\": \"An option definition\",\n"
+ " \"type\": \"ipv6-address\",\n"
+ " \"space\": \"isc\"\n"
+ " } ],\n"
"\"shared-networks\": [ {\n"
" \"name\": \"foo\"\n,"
- " \"comment\": \"A shared-network\"\n,"
+ " \"comment\": \"A shared network\"\n,"
" \"subnet6\": [\n"
" { \n"
" \"subnet\": \"2001:db1::/48\",\n"
extractConfig(config);
configure(config, CONTROL_RESULT_SUCCESS, "");
+ // Check global user context
+ ConstElementPtr ctx = CfgMgr::instance().getStagingCfg()->getContext();
+ ASSERT_TRUE(ctx);
+ ASSERT_EQ(1, ctx->size());
+ ASSERT_TRUE(ctx->get("comment"));
+ EXPECT_EQ("\"A DHCPv6 server\"", ctx->get("comment")->str());
+
+ // Make the option definition available.
+ LibDHCP::commitRuntimeOptionDefs();
+
+ // Get and verify the option definition.
+ OptionDefinitionPtr opt_def = LibDHCP::getRuntimeOptionDef("isc", 100);
+ ASSERT_TRUE(opt_def);
+ EXPECT_EQ("foo", opt_def->getName());
+ EXPECT_EQ(1, opt_def->getCode());
+ EXPECT_FALSE(opt_def->getArrayType());
+ EXPECT_EQ(OPT_IPV6_ADDRESS_TYPE, opt_def->getType());
+ EXPECT_TRUE(opt_def->getEncapsulatedSpace().empty());
+
+ // Check option definition user context
+ ConstElementPtr ctx_opt_def = opt_def->getContext();
+ ASSERT_TRUE(ctx_opt_def);
+ ASSERT_EQ(1, ctx_opt_def->size());
+ ASSERT_TRUE(ctx_opt_def->get("comment"));
+ EXPECT_EQ("\"An option definition\"", ctx_opt_def->get("comment")->str());
+
// Now verify that the shared network was indeed configured.
CfgSharedNetworks6Ptr cfg_net = CfgMgr::instance().getStagingCfg()
->getCfgSharedNetworks6();
ASSERT_TRUE(ctx_net);
ASSERT_EQ(1, ctx_net->size());
ASSERT_TRUE(ctx_net->get("comment"));
- EXPECT_EQ("\"A shared-network\"", ctx_net->get("comment")->str());
+ EXPECT_EQ("\"A shared network\"", ctx_net->get("comment")->str());
// The shared network has a subnet.
const Subnet6Collection * subs = net->getAllSubnets();
libkea_cc_la_SOURCES += command_interpreter.cc command_interpreter.h
libkea_cc_la_SOURCES += json_feed.cc json_feed.h
libkea_cc_la_SOURCES += simple_parser.cc simple_parser.h
+libkea_cc_la_SOURCES += user_context.cc user_context.h
libkea_cc_la_LIBADD = $(top_builddir)/src/lib/util/libkea-util.la
libkea_cc_la_LIBADD += $(top_builddir)/src/lib/asiolink/libkea-asiolink.la
data.h \
dhcp_config_error.h \
json_feed.h \
- simple_parser.h
-
+ simple_parser.h \
+ user_context.h
EXTRA_DIST = cc.dox
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
-#include <dhcpsrv/user_context.h>
+#include <cc/user_context.h>
using namespace isc::data;
#include <dhcp/option.h>
#include <dhcp/option_data_types.h>
#include <dhcp/option_space_container.h>
+#include <cc/user_context.h>
#include <boost/multi_index/hashed_index.hpp>
#include <boost/multi_index/mem_fun.hpp>
/// @todo Extend the comment to describe "generic factories".
/// @todo Extend this class to use custom namespaces.
/// @todo Extend this class with more factory functions.
+/// @todo Derive from UserContext without breaking the multi index.
class OptionDefinition {
public:
/// @return option data type.
OptionDataType getType() const { return (type_); };
+ /// @brief Returns const pointer to the user context
+ data::ConstElementPtr getContext() const {
+ return (user_context_.getContext());
+ }
+
+ /// @brief Sets user context.
+ /// @param ctx user context to be stored.
+ void setContext(const data::ConstElementPtr& ctx) {
+ user_context_.setContext(ctx);
+ }
+
+ /// @brief Merge unparse a user_context object.
+ ///
+ /// Add user-context to map, but only if defined. Omit if it was not.
+ /// Extract comment so it will be pretty-printed first.
+ ///
+ /// @param map A pointer to map where the user context will be unparsed.
+ void contextToElement(data::ElementPtr map) const {
+ user_context_.contextToElement(map);
+ }
+
/// @brief Check if the option definition is valid.
///
/// Note that it is a responsibility of the code that created
std::string encapsulated_space_;
/// Collection of data fields within the record.
RecordFieldsCollection record_fields_;
+ /// User context
+ UserContext user_context_;
};
libkea_dhcpsrv_la_SOURCES += subnet_selector.h
libkea_dhcpsrv_la_SOURCES += timer_mgr.cc timer_mgr.h
libkea_dhcpsrv_la_SOURCES += triplet.h
-libkea_dhcpsrv_la_SOURCES += user_context.cc user_context.h
libkea_dhcpsrv_la_SOURCES += utils.h
libkea_dhcpsrv_la_SOURCES += writable_host_data_source.h
subnet_selector.h \
timer_mgr.h \
triplet.h \
- user_context.h \
utils.h \
writable_host_data_source.h
def != defs->end(); ++def) {
// Get and fill the map for this definition
ElementPtr map = Element::createMap();
- // First set space from parent iterator
+ // Set user context
+ (*def)->contextToElement(map);
+ // Set space from parent iterator
map->set("space", Element::create(*name));
// Set required items: name, code and type
map->set("name", Element::create((*def)->getName()));
return (result);
}
-
} // end of namespace isc::dhcp
} // end of namespace isc
#include <asiolink/io_address.h>
#include <cc/cfg_to_element.h>
#include <cc/data.h>
+#include <cc/user_context.h>
#include <dhcp/classify.h>
#include <dhcp/option.h>
#include <dhcpsrv/cfg_option.h>
#include <dhcpsrv/cfg_4o6.h>
#include <dhcpsrv/triplet.h>
-#include <dhcpsrv/user_context.h>
#include <boost/shared_ptr.hpp>
#include <boost/weak_ptr.hpp>
#include <cstdint>
srv_cfg.setControlSocketInfo(value);
}
-
-
-
-
-
-
template<typename SearchKey>
OptionDefinitionPtr
OptionDataParser::findOptionDefinition(const std::string& option_space,
std::string record_types = getString(option_def, "record-types");
std::string space = getString(option_def, "space");
std::string encapsulates = getString(option_def, "encapsulate");
+ ConstElementPtr user_context = option_def->get("user-context");
if (!OptionSpace::validateName(space)) {
isc_throw(DhcpConfigError, "invalid option space name '"
}
+ if (user_context) {
+ def->setContext(user_context);
+ }
+
// Split the list of record types into tokens.
std::vector<std::string> record_tokens =
isc::util::str::tokens(record_types, ",");
#include <dhcp/option6_pdexclude.h>
#include <boost/shared_ptr.hpp>
#include <cc/data.h>
+#include <cc/user_context.h>
#include <dhcpsrv/cfg_option.h>
#include <dhcpsrv/lease.h>
-#include <dhcpsrv/user_context.h>
#include <boost/shared_ptr.hpp>
#include <vector>
ElementPtr result = Element::createMap();
// DhcpX global map
ElementPtr dhcp = Element::createMap();
+ // Set user-context
+ contextToElement(dhcp);
// Set decline-probation-period
dhcp->set("decline-probation-period",
Element::create(static_cast<long long>(decline_timer_)));
#include <dhcpsrv/logging_info.h>
#include <hooks/hooks_config.h>
#include <cc/data.h>
+#include <cc/user_context.h>
#include <boost/shared_ptr.hpp>
#include <vector>
#include <stdint.h>
/// @brief Specifies current DHCP configuration
///
/// @todo Migrate all other configuration parameters from cfgmgr.h here
-class SrvConfig : public isc::data::CfgToElement {
+class SrvConfig : public UserContext, public isc::data::CfgToElement {
public:
/// @name Constants for selection of parameters returned by @c getConfigSummary
///
#include <asiolink/io_address.h>
#include <cc/data.h>
+#include <cc/user_context.h>
#include <dhcp/option_space_container.h>
#include <dhcpsrv/assignable_network.h>
#include <dhcpsrv/lease.h>
#include <dhcpsrv/pool.h>
#include <dhcpsrv/subnet_id.h>
#include <dhcpsrv/triplet.h>
-#include <dhcpsrv/user_context.h>
#include <boost/multi_index/mem_fun.hpp>
#include <boost/multi_index/indexed_by.hpp>
cfg.add(OptionDefinitionPtr(new
OptionDefinition("option-baz", 6, "uint16", "dns")), "isc");
OptionDefinitionPtr rec(new OptionDefinition("option-rec", 6, "record"));
+ std::string json = "{ \"comment\": \"foo\" }";
+ rec->setContext(data::Element::fromJSON(json));
rec->addRecordField("uint16");
rec->addRecordField("uint16");
cfg.add(rec, "dns");
"},{\n"
" \"name\": \"option-rec\",\n"
" \"code\": 6,\n"
+ " \"comment\": \"foo\",\n"
" \"type\": \"record\",\n"
" \"array\": false,\n"
" \"record-types\": \"uint16, uint16\",\n"