case isc::dhcp::Parser4Context::POOLS:
case isc::dhcp::Parser4Context::SHARED_NETWORK:
case isc::dhcp::Parser4Context::OPTION_DEF:
+ case isc::dhcp::Parser4Context::OPTION_DATA:
return isc::dhcp::Dhcp4Parser::make_USER_CONTEXT(driver.loc_);
default:
return isc::dhcp::Dhcp4Parser::make_STRING("user-context", driver.loc_);
case isc::dhcp::Parser4Context::POOLS:
case isc::dhcp::Parser4Context::SHARED_NETWORK:
case isc::dhcp::Parser4Context::OPTION_DEF:
+ case isc::dhcp::Parser4Context::OPTION_DATA:
return isc::dhcp::Dhcp4Parser::make_COMMENT(driver.loc_);
default:
return isc::dhcp::Dhcp4Parser::make_STRING("comment", driver.loc_);
| option_data_space
| option_data_csv_format
| option_data_always_send
+ | user_context
+ | comment
| unknown_map_entry
;
" \"type\": \"ipv4-address\",\n"
" \"space\": \"isc\"\n"
" } ],\n"
+ "\"option-data\": [ {\n"
+ " \"name\": \"dhcp-message\",\n"
+ " \"comment\": \"Set option value\",\n"
+ " \"data\": \"ABCDEF0105\",\n"
+ " \"csv-format\": false\n"
+ " } ],\n"
"\"shared-networks\": [ {\n"
" \"name\": \"foo\"\n,"
" \"comment\": \"A shared network\"\n,"
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.
+ // There is a global option definition.
OptionDefinitionPtr opt_def = LibDHCP::getRuntimeOptionDef("isc", 100);
ASSERT_TRUE(opt_def);
EXPECT_EQ("foo", opt_def->getName());
EXPECT_EQ(OPT_IPV4_ADDRESS_TYPE, opt_def->getType());
EXPECT_TRUE(opt_def->getEncapsulatedSpace().empty());
- // Check option definition user context
+ // 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());
+ // There is an option descriptor aka option data.
+ OptionDescriptor opt_desc =
+ CfgMgr::instance().getStagingCfg()->getCfgOption()->
+ get(DHCP4_OPTION_SPACE, DHO_DHCP_MESSAGE);
+ ASSERT_TRUE(opt_desc.option_);
+ EXPECT_EQ(DHO_DHCP_MESSAGE, opt_desc.option_->getType());
+
+ // Check option descriptor user context.
+ ConstElementPtr ctx_opt_desc = opt_desc.getContext();
+ ASSERT_TRUE(ctx_opt_desc);
+ ASSERT_EQ(1, ctx_opt_desc->size());
+ ASSERT_TRUE(ctx_opt_desc->get("comment"));
+ EXPECT_EQ("\"Set option value\"", ctx_opt_desc->get("comment")->str());
+
// Now verify that the shared network was indeed configured.
CfgSharedNetworks4Ptr cfg_net = CfgMgr::instance().getStagingCfg()
->getCfgSharedNetworks4();
SharedNetwork4Ptr net = nets->at(0);
ASSERT_TRUE(net);
- // Check shared network user context
+ // Check shared network user context.
ConstElementPtr ctx_net = net->getContext();
ASSERT_TRUE(ctx_net);
ASSERT_EQ(1, ctx_net->size());
Subnet4Ptr sub = subs->at(0);
ASSERT_TRUE(sub);
- // Check subnet user context
+ // Check subnet user context.
ConstElementPtr ctx_sub = sub->getContext();
ASSERT_TRUE(ctx_sub);
ASSERT_EQ(1, ctx_sub->size());
ASSERT_TRUE(ctx_sub->get("comment"));
EXPECT_EQ("\"A subnet\"", ctx_sub->get("comment")->str());
- // The subnet has a pool
+ // The subnet has a pool.
const PoolCollection& pools = sub->getPools(Lease::TYPE_V4);
ASSERT_EQ(1, pools.size());
PoolPtr pool = pools.at(0);
ASSERT_TRUE(pool);
- // Check pool user context
+ // Check pool user context.
ConstElementPtr ctx_pool = pool->getContext();
ASSERT_TRUE(ctx_pool);
ASSERT_EQ(1, ctx_pool->size());
case isc::dhcp::Parser6Context::SUBNET6:
case isc::dhcp::Parser6Context::SHARED_NETWORK:
case isc::dhcp::Parser6Context::OPTION_DEF:
+ case isc::dhcp::Parser6Context::OPTION_DATA:
return isc::dhcp::Dhcp6Parser::make_USER_CONTEXT(driver.loc_);
default:
return isc::dhcp::Dhcp6Parser::make_STRING("user-context", driver.loc_);
case isc::dhcp::Parser6Context::SUBNET6:
case isc::dhcp::Parser6Context::SHARED_NETWORK:
case isc::dhcp::Parser6Context::OPTION_DEF:
+ case isc::dhcp::Parser6Context::OPTION_DATA:
return isc::dhcp::Dhcp6Parser::make_COMMENT(driver.loc_);
default:
return isc::dhcp::Dhcp6Parser::make_STRING("comment", driver.loc_);
| option_data_space
| option_data_csv_format
| option_data_always_send
+ | user_context
+ | comment
| unknown_map_entry
;
" \"type\": \"ipv6-address\",\n"
" \"space\": \"isc\"\n"
" } ],\n"
+ "\"option-data\": [ {\n"
+ " \"name\": \"subscriber-id\",\n"
+ " \"comment\": \"Set option value\",\n"
+ " \"data\": \"ABCDEF0105\",\n"
+ " \"csv-format\": false\n"
+ " } ],\n"
"\"shared-networks\": [ {\n"
" \"name\": \"foo\"\n,"
" \"comment\": \"A shared network\"\n,"
extractConfig(config);
configure(config, CONTROL_RESULT_SUCCESS, "");
- // Check global user context
+ // 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.
+ // There is a global option definition.
OptionDefinitionPtr opt_def = LibDHCP::getRuntimeOptionDef("isc", 100);
ASSERT_TRUE(opt_def);
EXPECT_EQ("foo", opt_def->getName());
EXPECT_EQ(OPT_IPV6_ADDRESS_TYPE, opt_def->getType());
EXPECT_TRUE(opt_def->getEncapsulatedSpace().empty());
- // Check option definition user context
+ // 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());
+ // There is an option descriptor aka option data.
+ OptionDescriptor opt_desc =
+ CfgMgr::instance().getStagingCfg()->getCfgOption()->
+ get(DHCP6_OPTION_SPACE, D6O_SUBSCRIBER_ID);
+ ASSERT_TRUE(opt_desc.option_);
+ EXPECT_EQ(D6O_SUBSCRIBER_ID, opt_desc.option_->getType());
+
+ // Check option descriptor user context.
+ ConstElementPtr ctx_opt_desc = opt_desc.getContext();
+ ASSERT_TRUE(ctx_opt_desc);
+ ASSERT_EQ(1, ctx_opt_desc->size());
+ ASSERT_TRUE(ctx_opt_desc->get("comment"));
+ EXPECT_EQ("\"Set option value\"", ctx_opt_desc->get("comment")->str());
+
// Now verify that the shared network was indeed configured.
CfgSharedNetworks6Ptr cfg_net = CfgMgr::instance().getStagingCfg()
->getCfgSharedNetworks6();
SharedNetwork6Ptr net = nets->at(0);
ASSERT_TRUE(net);
- // Check shared network user context
+ // Check shared network user context.
ConstElementPtr ctx_net = net->getContext();
ASSERT_TRUE(ctx_net);
ASSERT_EQ(1, ctx_net->size());
Subnet6Ptr sub = subs->at(0);
ASSERT_TRUE(sub);
- // Check subnet user context
+ // Check subnet user context.
ConstElementPtr ctx_sub = sub->getContext();
ASSERT_TRUE(ctx_sub);
ASSERT_EQ(1, ctx_sub->size());
ASSERT_TRUE(ctx_sub->get("comment"));
EXPECT_EQ("\"A subnet\"", ctx_sub->get("comment")->str());
- // The subnet has a pool
+ // The subnet has a pool.
const PoolCollection& pools = sub->getPools(Lease::TYPE_NA);
ASSERT_EQ(1, pools.size());
PoolPtr pool = pools.at(0);
ASSERT_TRUE(pool);
- // Check pool user context
+ // Check pool user context.
ConstElementPtr ctx_pool = pool->getContext();
ASSERT_TRUE(ctx_pool);
ASSERT_EQ(1, ctx_pool->size());
ASSERT_TRUE(ctx_pool->get("comment"));
EXPECT_EQ("\"A pool\"", ctx_pool->get("comment")->str());
- // The subnet has a prefix pool
+ // The subnet has a prefix pool.
const PoolCollection& pdpools = sub->getPools(Lease::TYPE_PD);
ASSERT_EQ(1, pdpools.size());
PoolPtr pdpool = pdpools.at(0);
ASSERT_TRUE(pdpool);
- // Check prefix pool user context
+ // Check prefix pool user context.
ConstElementPtr ctx_pdpool = pdpool->getContext();
ASSERT_TRUE(ctx_pdpool);
ASSERT_EQ(1, ctx_pdpool->size());
opt != opts->end(); ++opt) {
// Get and fill the map for this option
ElementPtr map = Element::createMap();
- // First set space from parent iterator
+ // Set user context
+ opt->contextToElement(map);
+ // Set space from parent iterator
map->set("space", Element::create(*name));
// Set the code
uint16_t code = opt->option_->getType();
opt != opts->end(); ++opt) {
// Get and fill the map for this option
ElementPtr map = Element::createMap();
- // First set space from parent iterator
+ // Set user context
+ opt->contextToElement(map);
+ // Set space from parent iterator
std::ostringstream oss;
oss << "vendor-" << *id;
map->set("space", Element::create(oss.str()));
#include <dhcp/option.h>
#include <dhcp/option_space_container.h>
#include <cc/cfg_to_element.h>
+#include <cc/user_context.h>
#include <dhcpsrv/key_from_key.h>
#include <boost/multi_index_container.hpp>
#include <boost/multi_index/hashed_index.hpp>
/// for this option. This information comprises whether this option is sent
/// to DHCP client only on request (persistent = false) or always
/// (persistent = true).
-struct OptionDescriptor {
+class OptionDescriptor : public UserContext {
+public:
/// @brief Option instance.
OptionPtr option_;
OptionalValue<bool> persist_param = extractPersistent(option_data);
std::string data_param = extractData(option_data);
std::string space_param = extractSpace(option_data);
+ ConstElementPtr user_context = option_data->get("user-context");
// Require that option code or option name is specified.
if (!code_param.isSpecified() && !name_param.isSpecified()) {
}
}
+ // Add user context
+ if (user_context) {
+ desc.setContext(user_context);
+ }
+
// All went good, so we can set the option space name.
return make_pair(desc, space_param);
}
cfg.add(opt1, false, "dns");
OptionPtr opt2(new Option(Option::V6, 101, OptionBuffer(4, 12)));
OptionDescriptor desc2(opt2, false, "12, 12, 12, 12");
+ desc2.setContext(data::Element::fromJSON("{ \"comment\": \"foo\" }"));
cfg.add(desc2, "dns");
OptionPtr opt3(new Option(Option::V6, D6O_STATUS_CODE, OptionBuffer(2, 0)));
cfg.add(opt3, false, DHCP6_OPTION_SPACE);
" \"data\": \"12121212\",\n"
" \"always-send\": false\n"
"},{\n"
+ " \"comment\": \"foo\",\n"
" \"code\": 101,\n"
" \"space\": \"dns\",\n"
" \"csv-format\": true,\n"