mirror of
https://gitlab.isc.org/isc-projects/kea
synced 2025-08-29 04:57:52 +00:00
[#2826] Options in db are not encapsulated
Returned options from db are not encapsulated and have to be encapsulated before the server returns them to a client. Parsers, depending on the use case, may or may not encapsulate options. When they are used for parsing a config file, the options are encapsulated. When they are used by the host_cmds or cb_cmds, they are not.
This commit is contained in:
parent
659b251df9
commit
132ef88b47
@ -420,6 +420,13 @@ AllocEngine::findReservation(ClientContext6& ctx) {
|
||||
// done here.
|
||||
subnet = subnet->getNextSubnet(ctx.subnet_, classes);
|
||||
}
|
||||
|
||||
// The hosts can be used by the server to return reserved options to
|
||||
// the DHCP client. Such options must be encapsulated (i.e., they must
|
||||
// include suboptions).
|
||||
for (auto host : ctx.hosts_) {
|
||||
host.second->encapsulateOptions();
|
||||
}
|
||||
}
|
||||
|
||||
ConstHostPtr
|
||||
@ -3776,6 +3783,13 @@ AllocEngine::findReservation(ClientContext4& ctx) {
|
||||
// done here.
|
||||
subnet = subnet->getNextSubnet(ctx.subnet_, classes);
|
||||
}
|
||||
|
||||
// The hosts can be used by the server to return reserved options to
|
||||
// the DHCP client. Such options must be encapsulated (i.e., they must
|
||||
// include suboptions).
|
||||
for (auto host : ctx.hosts_) {
|
||||
host.second->encapsulateOptions();
|
||||
}
|
||||
}
|
||||
|
||||
ConstHostPtr
|
||||
|
@ -51,7 +51,8 @@ OptionDescriptor::equals(const OptionDescriptor& other) const {
|
||||
option_->equals(other.option_));
|
||||
}
|
||||
|
||||
CfgOption::CfgOption() {
|
||||
CfgOption::CfgOption()
|
||||
: encapsulated_(false) {
|
||||
}
|
||||
|
||||
bool
|
||||
@ -263,6 +264,7 @@ CfgOption::encapsulate() {
|
||||
encapsulateInternal(DHCP4_OPTION_SPACE);
|
||||
// Append sub-options to the top level "dhcp6" option space.
|
||||
encapsulateInternal(DHCP6_OPTION_SPACE);
|
||||
encapsulated_ = true;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -543,6 +543,13 @@ public:
|
||||
/// options from this option space are appended to top-level options.
|
||||
void encapsulate();
|
||||
|
||||
/// @brief Checks if options have been encapsulated.
|
||||
///
|
||||
/// @return true if options have been encapsulated, false otherwise.
|
||||
bool isEncapsulated() const {
|
||||
return (encapsulated_);
|
||||
}
|
||||
|
||||
/// @brief Returns all options for the specified option space.
|
||||
///
|
||||
/// This method will not return vendor options, i.e. having option space
|
||||
@ -774,6 +781,9 @@ private:
|
||||
OptionSpaceContainer<OptionContainer,
|
||||
OptionDescriptor, Selector>& dest_container) const;
|
||||
|
||||
/// @brief A flag indicating if options have been encapsulated.
|
||||
bool encapsulated_;
|
||||
|
||||
/// @brief Type of the container holding options grouped by option space.
|
||||
typedef OptionSpaceContainer<OptionContainer, OptionDescriptor,
|
||||
std::string> OptionSpaceCollection;
|
||||
|
@ -637,6 +637,16 @@ Host::toElement6() const {
|
||||
return (map);
|
||||
}
|
||||
|
||||
void
|
||||
Host::encapsulateOptions() const {
|
||||
if (!cfg_option4_->isEncapsulated()) {
|
||||
cfg_option4_->encapsulate();
|
||||
}
|
||||
if (!cfg_option6_->isEncapsulated()) {
|
||||
cfg_option6_->encapsulate();
|
||||
}
|
||||
}
|
||||
|
||||
std::string
|
||||
Host::toText() const {
|
||||
std::ostringstream s;
|
||||
|
@ -669,6 +669,12 @@ public:
|
||||
return (cfg_option6_);
|
||||
}
|
||||
|
||||
/// @brief Encapsulates host-specific options with their suboptions.
|
||||
///
|
||||
/// This function must be called before the server returns host-specific
|
||||
/// DHCP options to the client.
|
||||
void encapsulateOptions() const;
|
||||
|
||||
/// @brief Returns information about the host in the textual format.
|
||||
std::string toText() const;
|
||||
|
||||
|
@ -994,13 +994,27 @@ private:
|
||||
def = LibDHCP::getRuntimeOptionDef(space, code_);
|
||||
}
|
||||
|
||||
// Finish with a last resort option definition.
|
||||
if (!def) {
|
||||
def = LibDHCP::getLastResortOptionDef(space, code_);
|
||||
}
|
||||
|
||||
OptionPtr option;
|
||||
|
||||
// If no definition found, we use generic option type.
|
||||
if (!def) {
|
||||
// If no definition found, we use generic option type.
|
||||
OptionBuffer buf(value_, value_ + value_length_);
|
||||
option.reset(new Option(universe_, code_, buf.begin(),
|
||||
buf.end()));
|
||||
// We have to pay attention if the value is NULL. If it is,
|
||||
// we must create an empty option instance. We can't rely on
|
||||
// the value_length_ because it may contain garbage for the
|
||||
// null values. Thus we check explicitly whether or not the
|
||||
// NULL flag is set.
|
||||
if (value_null_ == MLM_FALSE) {
|
||||
OptionBuffer buf(value_, value_ + value_length_);
|
||||
option.reset(new Option(universe_, code_, buf.begin(),
|
||||
buf.end()));
|
||||
} else {
|
||||
option.reset(new Option(universe_, code_));
|
||||
}
|
||||
} else {
|
||||
// The option value may be specified in textual or binary format
|
||||
// in the database. If formatted_value is empty, the binary
|
||||
@ -1008,9 +1022,12 @@ private:
|
||||
// variant of the optionFactory function.
|
||||
if (formatted_value.empty()) {
|
||||
OptionBuffer buf(value_, value_ + value_length_);
|
||||
// Again, check if the value is null before submitting the
|
||||
// buffer to the factory function.
|
||||
option = def->optionFactory(universe_, code_, buf.begin(),
|
||||
buf.end());
|
||||
} else {
|
||||
value_null_ == MLM_FALSE ? buf.end() :
|
||||
buf.begin());
|
||||
} else {
|
||||
// Spit the value specified in comma separated values
|
||||
// format.
|
||||
std::vector<std::string> split_vec;
|
||||
|
@ -350,7 +350,8 @@ RelayInfoParser::addAddress(const std::string& name,
|
||||
void
|
||||
PoolParser::parse(PoolStoragePtr pools,
|
||||
ConstElementPtr pool_structure,
|
||||
const uint16_t address_family) {
|
||||
const uint16_t address_family,
|
||||
bool encapsulate_options) {
|
||||
|
||||
if (address_family == AF_INET) {
|
||||
checkKeywords(SimpleParser4::POOL4_PARAMETERS, pool_structure);
|
||||
@ -484,7 +485,7 @@ PoolParser::parse(PoolStoragePtr pools,
|
||||
try {
|
||||
CfgOptionPtr cfg = pool->getCfgOption();
|
||||
auto option_parser = createOptionDataListParser(address_family);
|
||||
option_parser->parse(cfg, option_data);
|
||||
option_parser->parse(cfg, option_data, encapsulate_options);
|
||||
} catch (const std::exception& ex) {
|
||||
isc_throw(isc::dhcp::DhcpConfigError, ex.what()
|
||||
<< " (" << option_data->getPosition() << ")");
|
||||
@ -537,10 +538,11 @@ Pool4Parser::poolMaker (IOAddress &min, IOAddress &max, int32_t) {
|
||||
//****************************** Pools4ListParser *************************
|
||||
|
||||
void
|
||||
Pools4ListParser::parse(PoolStoragePtr pools, ConstElementPtr pools_list) {
|
||||
Pools4ListParser::parse(PoolStoragePtr pools, ConstElementPtr pools_list,
|
||||
bool encapsulate_options) {
|
||||
BOOST_FOREACH(ConstElementPtr pool, pools_list->listValue()) {
|
||||
auto parser = createPoolConfigParser();
|
||||
parser->parse(pools, pool, AF_INET);
|
||||
parser->parse(pools, pool, AF_INET, encapsulate_options);
|
||||
}
|
||||
}
|
||||
|
||||
@ -555,19 +557,12 @@ Pools4ListParser::createPoolConfigParser() const {
|
||||
SubnetConfigParser::SubnetConfigParser(uint16_t family, bool check_iface)
|
||||
: pools_(new PoolStorage()),
|
||||
address_family_(family),
|
||||
options_(new CfgOption()),
|
||||
check_iface_(check_iface) {
|
||||
relay_info_.reset(new isc::dhcp::Network::RelayInfo());
|
||||
}
|
||||
|
||||
SubnetPtr
|
||||
SubnetConfigParser::parse(ConstElementPtr subnet) {
|
||||
|
||||
ConstElementPtr options_params = subnet->get("option-data");
|
||||
if (options_params) {
|
||||
auto opt_parser = createOptionDataListParser();
|
||||
opt_parser->parse(options_, options_params);
|
||||
}
|
||||
SubnetConfigParser::parse(ConstElementPtr subnet, bool encapsulate_options) {
|
||||
|
||||
ConstElementPtr relay_params = subnet->get("relay");
|
||||
if (relay_params) {
|
||||
@ -584,6 +579,12 @@ SubnetConfigParser::parse(ConstElementPtr subnet) {
|
||||
"subnet configuration failed: " << ex.what());
|
||||
}
|
||||
|
||||
ConstElementPtr options_params = subnet->get("option-data");
|
||||
if (options_params) {
|
||||
auto opt_parser = createOptionDataListParser();
|
||||
opt_parser->parse(subnet_->getCfgOption(), options_params, encapsulate_options);
|
||||
}
|
||||
|
||||
return (subnet_);
|
||||
}
|
||||
|
||||
@ -686,7 +687,7 @@ Subnet4ConfigParser::Subnet4ConfigParser(bool check_iface)
|
||||
}
|
||||
|
||||
Subnet4Ptr
|
||||
Subnet4ConfigParser::parse(ConstElementPtr subnet) {
|
||||
Subnet4ConfigParser::parse(ConstElementPtr subnet, bool encapsulate_options) {
|
||||
// Check parameters.
|
||||
checkKeywords(SimpleParser4::SUBNET4_PARAMETERS, subnet);
|
||||
|
||||
@ -694,10 +695,10 @@ Subnet4ConfigParser::parse(ConstElementPtr subnet) {
|
||||
ConstElementPtr pools = subnet->get("pools");
|
||||
if (pools) {
|
||||
auto parser = createPoolsListParser();
|
||||
parser->parse(pools_, pools);
|
||||
parser->parse(pools_, pools, encapsulate_options);
|
||||
}
|
||||
|
||||
SubnetPtr generic = SubnetConfigParser::parse(subnet);
|
||||
SubnetPtr generic = SubnetConfigParser::parse(subnet, encapsulate_options);
|
||||
|
||||
if (!generic) {
|
||||
// Sanity check: not supposed to fail.
|
||||
@ -945,9 +946,6 @@ Subnet4ConfigParser::initSubnet(data::ConstElementPtr params,
|
||||
// options but this is no longer the case (they have a different
|
||||
// and not consecutive priority).
|
||||
|
||||
// Copy options to the subnet configuration.
|
||||
options_->copyTo(*subnet4->getCfgOption());
|
||||
|
||||
// Parse t1-percent and t2-percent
|
||||
parseTeePercents(params, network);
|
||||
|
||||
@ -993,12 +991,13 @@ Subnets4ListConfigParser::Subnets4ListConfigParser(bool check_iface)
|
||||
|
||||
size_t
|
||||
Subnets4ListConfigParser::parse(SrvConfigPtr cfg,
|
||||
ConstElementPtr subnets_list) {
|
||||
ConstElementPtr subnets_list,
|
||||
bool encapsulate_options) {
|
||||
size_t cnt = 0;
|
||||
BOOST_FOREACH(ConstElementPtr subnet_json, subnets_list->listValue()) {
|
||||
|
||||
auto parser = createSubnetConfigParser();
|
||||
Subnet4Ptr subnet = parser->parse(subnet_json);
|
||||
Subnet4Ptr subnet = parser->parse(subnet_json, encapsulate_options);
|
||||
if (subnet) {
|
||||
|
||||
// Adding a subnet to the Configuration Manager may fail if the
|
||||
@ -1018,12 +1017,13 @@ Subnets4ListConfigParser::parse(SrvConfigPtr cfg,
|
||||
|
||||
size_t
|
||||
Subnets4ListConfigParser::parse(Subnet4Collection& subnets,
|
||||
data::ConstElementPtr subnets_list) {
|
||||
data::ConstElementPtr subnets_list,
|
||||
bool encapsulate_options) {
|
||||
size_t cnt = 0;
|
||||
BOOST_FOREACH(ConstElementPtr subnet_json, subnets_list->listValue()) {
|
||||
|
||||
auto parser = createSubnetConfigParser();
|
||||
Subnet4Ptr subnet = parser->parse(subnet_json);
|
||||
Subnet4Ptr subnet = parser->parse(subnet_json, encapsulate_options);
|
||||
if (subnet) {
|
||||
try {
|
||||
auto ret = subnets.insert(subnet);
|
||||
@ -1067,10 +1067,11 @@ Pool6Parser::poolMaker(IOAddress &min, IOAddress &max, int32_t ptype)
|
||||
//**************************** Pool6ListParser ***************************
|
||||
|
||||
void
|
||||
Pools6ListParser::parse(PoolStoragePtr pools, ConstElementPtr pools_list) {
|
||||
Pools6ListParser::parse(PoolStoragePtr pools, ConstElementPtr pools_list,
|
||||
bool encapsulate_options) {
|
||||
BOOST_FOREACH(ConstElementPtr pool, pools_list->listValue()) {
|
||||
auto parser = createPoolConfigParser();
|
||||
parser->parse(pools, pool, AF_INET6);
|
||||
parser->parse(pools, pool, AF_INET6, encapsulate_options);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1082,11 +1083,12 @@ Pools6ListParser::createPoolConfigParser() const {
|
||||
|
||||
//**************************** PdPoolParser ******************************
|
||||
|
||||
PdPoolParser::PdPoolParser() : options_(new CfgOption()) {
|
||||
PdPoolParser::PdPoolParser() {
|
||||
}
|
||||
|
||||
void
|
||||
PdPoolParser::parse(PoolStoragePtr pools, ConstElementPtr pd_pool_) {
|
||||
PdPoolParser::parse(PoolStoragePtr pools, ConstElementPtr pd_pool_,
|
||||
bool encapsulate_options) {
|
||||
checkKeywords(SimpleParser6::PD_POOL6_PARAMETERS, pd_pool_);
|
||||
|
||||
std::string addr_str = getString(pd_pool_, "prefix");
|
||||
@ -1105,12 +1107,6 @@ PdPoolParser::parse(PoolStoragePtr pools, ConstElementPtr pd_pool_) {
|
||||
excluded_prefix_len = getUint8(pd_pool_, "excluded-prefix-len");
|
||||
}
|
||||
|
||||
ConstElementPtr option_data = pd_pool_->get("option-data");
|
||||
if (option_data) {
|
||||
auto opts_parser = createOptionDataListParser();
|
||||
opts_parser->parse(options_, option_data);
|
||||
}
|
||||
|
||||
ConstElementPtr user_context = pd_pool_->get("user-context");
|
||||
if (user_context) {
|
||||
user_context_ = user_context;
|
||||
@ -1132,8 +1128,6 @@ PdPoolParser::parse(PoolStoragePtr pools, ConstElementPtr pd_pool_) {
|
||||
delegated_len,
|
||||
IOAddress(excluded_prefix_str),
|
||||
excluded_prefix_len));
|
||||
// Merge options specified for a pool into pool configuration.
|
||||
options_->copyTo(*pool_->getCfgOption());
|
||||
} catch (const std::exception& ex) {
|
||||
// Some parameters don't exist or are invalid. Since we are not
|
||||
// aware whether they don't exist or are invalid, let's append
|
||||
@ -1142,6 +1136,12 @@ PdPoolParser::parse(PoolStoragePtr pools, ConstElementPtr pd_pool_) {
|
||||
<< " (" << pd_pool_->getPosition() << ")");
|
||||
}
|
||||
|
||||
ConstElementPtr option_data = pd_pool_->get("option-data");
|
||||
if (option_data) {
|
||||
auto opts_parser = createOptionDataListParser();
|
||||
opts_parser->parse(pool_->getCfgOption(), option_data, encapsulate_options);
|
||||
}
|
||||
|
||||
if (user_context_) {
|
||||
pool_->setContext(user_context_);
|
||||
}
|
||||
@ -1200,7 +1200,7 @@ Subnet6ConfigParser::Subnet6ConfigParser(bool check_iface)
|
||||
}
|
||||
|
||||
Subnet6Ptr
|
||||
Subnet6ConfigParser::parse(ConstElementPtr subnet) {
|
||||
Subnet6ConfigParser::parse(ConstElementPtr subnet, bool encapsulate_options) {
|
||||
// Check parameters.
|
||||
checkKeywords(SimpleParser6::SUBNET6_PARAMETERS, subnet);
|
||||
|
||||
@ -1208,7 +1208,7 @@ Subnet6ConfigParser::parse(ConstElementPtr subnet) {
|
||||
ConstElementPtr pools = subnet->get("pools");
|
||||
if (pools) {
|
||||
auto parser = createPoolsListParser();
|
||||
parser->parse(pools_, pools);
|
||||
parser->parse(pools_, pools, encapsulate_options);
|
||||
}
|
||||
ConstElementPtr pd_pools = subnet->get("pd-pools");
|
||||
if (pd_pools) {
|
||||
@ -1216,7 +1216,7 @@ Subnet6ConfigParser::parse(ConstElementPtr subnet) {
|
||||
parser->parse(pools_, pd_pools);
|
||||
}
|
||||
|
||||
SubnetPtr generic = SubnetConfigParser::parse(subnet);
|
||||
SubnetPtr generic = SubnetConfigParser::parse(subnet, encapsulate_options);
|
||||
|
||||
if (!generic) {
|
||||
// Sanity check: not supposed to fail.
|
||||
@ -1420,9 +1420,6 @@ Subnet6ConfigParser::initSubnet(data::ConstElementPtr params,
|
||||
/// client-class processing is now generic and handled in the common
|
||||
/// code (see isc::data::SubnetConfigParser::createSubnet)
|
||||
|
||||
// Copy options to the subnet configuration.
|
||||
options_->copyTo(*subnet6->getCfgOption());
|
||||
|
||||
// Parse t1-percent and t2-percent
|
||||
parseTeePercents(params, network);
|
||||
|
||||
@ -1466,12 +1463,13 @@ Subnets6ListConfigParser::Subnets6ListConfigParser(bool check_iface)
|
||||
|
||||
size_t
|
||||
Subnets6ListConfigParser::parse(SrvConfigPtr cfg,
|
||||
ConstElementPtr subnets_list) {
|
||||
ConstElementPtr subnets_list,
|
||||
bool encapsulate_options) {
|
||||
size_t cnt = 0;
|
||||
BOOST_FOREACH(ConstElementPtr subnet_json, subnets_list->listValue()) {
|
||||
|
||||
auto parser = createSubnetConfigParser();
|
||||
Subnet6Ptr subnet = parser->parse(subnet_json);
|
||||
Subnet6Ptr subnet = parser->parse(subnet_json, encapsulate_options);
|
||||
|
||||
// Adding a subnet to the Configuration Manager may fail if the
|
||||
// subnet id is invalid (duplicate). Thus, we catch exceptions
|
||||
@ -1489,12 +1487,13 @@ Subnets6ListConfigParser::parse(SrvConfigPtr cfg,
|
||||
|
||||
size_t
|
||||
Subnets6ListConfigParser::parse(Subnet6Collection& subnets,
|
||||
ConstElementPtr subnets_list) {
|
||||
ConstElementPtr subnets_list,
|
||||
bool encapsulate_options) {
|
||||
size_t cnt = 0;
|
||||
BOOST_FOREACH(ConstElementPtr subnet_json, subnets_list->listValue()) {
|
||||
|
||||
auto parser = createSubnetConfigParser();
|
||||
Subnet6Ptr subnet = parser->parse(subnet_json);
|
||||
Subnet6Ptr subnet = parser->parse(subnet_json, encapsulate_options);
|
||||
if (subnet) {
|
||||
try {
|
||||
auto ret = subnets.insert(subnet);
|
||||
|
@ -302,10 +302,13 @@ public:
|
||||
/// @param pools is the storage in which to store the parsed pool
|
||||
/// @param pool_structure a single entry on a list of pools
|
||||
/// @param address_family AF_INET (for DHCPv4) or AF_INET6 (for DHCPv6).
|
||||
/// @param encapsulate_options a boolean parameter indicating if the
|
||||
/// parsed options should be encapsulated with suboptions.
|
||||
/// @throw isc::dhcp::DhcpConfigError when pool parsing fails
|
||||
virtual void parse(PoolStoragePtr pools,
|
||||
isc::data::ConstElementPtr pool_structure,
|
||||
const uint16_t address_family);
|
||||
const uint16_t address_family,
|
||||
bool encapsulate_options = true);
|
||||
|
||||
protected:
|
||||
/// @brief Creates a Pool object given a IPv4 prefix and the prefix length.
|
||||
@ -389,9 +392,12 @@ public:
|
||||
///
|
||||
/// @param pools is the storage in which to store the parsed pools.
|
||||
/// @param pools_list a list of pool structures
|
||||
/// @param encapsulate_options a boolean parameter indicating if the
|
||||
/// parsed options should be encapsulated with suboptions.
|
||||
/// @throw isc::dhcp::DhcpConfigError when pool parsing fails
|
||||
virtual void parse(PoolStoragePtr pools,
|
||||
isc::data::ConstElementPtr pools_list) = 0;
|
||||
isc::data::ConstElementPtr pools_list,
|
||||
bool encapsulate_options) = 0;
|
||||
|
||||
protected:
|
||||
|
||||
@ -415,8 +421,11 @@ public:
|
||||
///
|
||||
/// @param pools storage container in which to store the parsed pool.
|
||||
/// @param pools_list a list of pool structures
|
||||
/// @param encapsulate_options a boolean parameter indicating if the
|
||||
/// parsed options should be encapsulated with suboptions.
|
||||
/// @throw isc::dhcp::DhcpConfigError when pool parsing fails
|
||||
void parse(PoolStoragePtr pools, data::ConstElementPtr pools_list);
|
||||
void parse(PoolStoragePtr pools, data::ConstElementPtr pools_list,
|
||||
bool encapsulate_options = true);
|
||||
|
||||
protected:
|
||||
|
||||
@ -520,10 +529,13 @@ protected:
|
||||
/// Subnet6ConfigParser) classes.
|
||||
///
|
||||
/// @param subnet pointer to the content of subnet definition
|
||||
/// @param encapsulate_options a boolean parameter indicating if the
|
||||
/// parsed options should be encapsulated with suboptions.
|
||||
/// @return a pointer to newly created subnet
|
||||
///
|
||||
/// @throw isc::DhcpConfigError if subnet configuration parsing failed.
|
||||
SubnetPtr parse(isc::data::ConstElementPtr subnet);
|
||||
SubnetPtr parse(isc::data::ConstElementPtr subnet,
|
||||
bool encapsulate_options);
|
||||
|
||||
/// @brief Instantiates the subnet based on a given IP prefix and prefix
|
||||
/// length.
|
||||
@ -574,9 +586,6 @@ protected:
|
||||
/// Pointer to relay information
|
||||
isc::dhcp::Network::RelayInfoPtr relay_info_;
|
||||
|
||||
/// Pointer to the options configuration.
|
||||
CfgOptionPtr options_;
|
||||
|
||||
/// Check if the specified interface exists in the system.
|
||||
bool check_iface_;
|
||||
};
|
||||
@ -601,8 +610,11 @@ public:
|
||||
/// Configuration Manager.
|
||||
///
|
||||
/// @param subnet A new subnet being configured.
|
||||
/// @param encapsulate_options a boolean parameter indicating if the
|
||||
/// parsed options should be encapsulated with suboptions.
|
||||
/// @return a pointer to created Subnet4 object
|
||||
Subnet4Ptr parse(data::ConstElementPtr subnet);
|
||||
Subnet4Ptr parse(data::ConstElementPtr subnet,
|
||||
bool encapsulate_options = true);
|
||||
|
||||
protected:
|
||||
|
||||
@ -659,16 +671,22 @@ public:
|
||||
///
|
||||
/// @param cfg Pointer to server configuration.
|
||||
/// @param subnets_list pointer to a list of IPv4 subnets
|
||||
/// @param encapsulate_options a boolean parameter indicating if the
|
||||
/// parsed options should be encapsulated with suboptions.
|
||||
/// @return number of subnets created
|
||||
size_t parse(SrvConfigPtr cfg, data::ConstElementPtr subnets_list);
|
||||
size_t parse(SrvConfigPtr cfg, data::ConstElementPtr subnets_list,
|
||||
bool encapsulate_options = true);
|
||||
|
||||
/// @brief Parses contents of the subnet4 list.
|
||||
///
|
||||
/// @param [out] subnets Container where parsed subnets will be stored.
|
||||
/// @param subnets_list pointer to a list of IPv4 subnets
|
||||
/// @param encapsulate_options a boolean parameter indicating if the
|
||||
/// parsed options should be encapsulated with suboptions.
|
||||
/// @return Number of subnets created.
|
||||
size_t parse(Subnet4Collection& subnets,
|
||||
data::ConstElementPtr subnets_list);
|
||||
data::ConstElementPtr subnets_list,
|
||||
bool encapsulate_options = true);
|
||||
|
||||
protected:
|
||||
|
||||
@ -727,8 +745,11 @@ public:
|
||||
///
|
||||
/// @param pools storage container in which to store the parsed pool.
|
||||
/// @param pools_list a list of pool structures
|
||||
/// @param encapsulate_options a boolean parameter indicating if the
|
||||
/// parsed options should be encapsulated with suboptions.
|
||||
/// @throw isc::dhcp::DhcpConfigError when pool parsing fails
|
||||
void parse(PoolStoragePtr pools, data::ConstElementPtr pools_list);
|
||||
void parse(PoolStoragePtr pools, data::ConstElementPtr pools_list,
|
||||
bool encapsulate_options = true);
|
||||
|
||||
protected:
|
||||
|
||||
@ -778,9 +799,12 @@ public:
|
||||
/// @param pools storage container in which to store the parsed pool.
|
||||
/// @param pd_pool_ pointer to an element that holds configuration entries
|
||||
/// that define a prefix delegation pool.
|
||||
/// @param encapsulate_options a boolean parameter indicating if the
|
||||
/// parsed options should be encapsulated with suboptions.
|
||||
///
|
||||
/// @throw DhcpConfigError if configuration parsing fails.
|
||||
void parse(PoolStoragePtr pools, data::ConstElementPtr pd_pool_);
|
||||
void parse(PoolStoragePtr pools, data::ConstElementPtr pd_pool_,
|
||||
bool encapsulate_options = true);
|
||||
|
||||
protected:
|
||||
|
||||
@ -797,9 +821,6 @@ protected:
|
||||
/// Pointer to the created pool object.
|
||||
isc::dhcp::Pool6Ptr pool_;
|
||||
|
||||
/// A storage for pool specific option values.
|
||||
CfgOptionPtr options_;
|
||||
|
||||
/// @brief User context (optional, may be null)
|
||||
///
|
||||
/// User context is arbitrary user data, to be used by hooks.
|
||||
@ -869,8 +890,11 @@ public:
|
||||
/// Configuration Manager.
|
||||
///
|
||||
/// @param subnet A new subnet being configured.
|
||||
/// @param encapsulate_options a boolean parameter indicating if the
|
||||
/// parsed options should be encapsulated with suboptions.
|
||||
/// @return a pointer to created Subnet6 object
|
||||
Subnet6Ptr parse(data::ConstElementPtr subnet);
|
||||
Subnet6Ptr parse(data::ConstElementPtr subnet,
|
||||
bool encapsulate_options = true);
|
||||
|
||||
protected:
|
||||
/// @brief Issues a DHCP6 server specific warning regarding duplicate subnet
|
||||
@ -947,8 +971,11 @@ public:
|
||||
///
|
||||
/// @param cfg configuration (parsed subnets will be stored here)
|
||||
/// @param subnets_list pointer to a list of IPv6 subnets
|
||||
/// @param encapsulate_options a boolean parameter indicating if the
|
||||
/// parsed options should be encapsulated with suboptions.
|
||||
/// @throw DhcpConfigError if CfgMgr rejects the subnet (e.g. subnet-id is a duplicate)
|
||||
size_t parse(SrvConfigPtr cfg, data::ConstElementPtr subnets_list);
|
||||
size_t parse(SrvConfigPtr cfg, data::ConstElementPtr subnets_list,
|
||||
bool encapsulate_options = true);
|
||||
|
||||
/// @brief Parses contents of the subnet6 list.
|
||||
///
|
||||
@ -956,7 +983,8 @@ public:
|
||||
/// @param subnets_list pointer to a list of IPv6 subnets
|
||||
/// @return Number of subnets created.
|
||||
size_t parse(Subnet6Collection& subnets,
|
||||
data::ConstElementPtr subnets_list);
|
||||
data::ConstElementPtr subnets_list,
|
||||
bool encapsulate_options = true);
|
||||
|
||||
protected:
|
||||
|
||||
|
@ -101,13 +101,15 @@ namespace dhcp {
|
||||
|
||||
HostPtr
|
||||
HostReservationParser::parse(const SubnetID& subnet_id,
|
||||
isc::data::ConstElementPtr reservation_data) {
|
||||
return (parseInternal(subnet_id, reservation_data));
|
||||
isc::data::ConstElementPtr reservation_data,
|
||||
bool encapsulate_options) {
|
||||
return (parseInternal(subnet_id, reservation_data, encapsulate_options));
|
||||
}
|
||||
|
||||
HostPtr
|
||||
HostReservationParser::parseInternal(const SubnetID&,
|
||||
isc::data::ConstElementPtr reservation_data) {
|
||||
isc::data::ConstElementPtr reservation_data,
|
||||
bool) {
|
||||
std::string identifier;
|
||||
std::string identifier_name;
|
||||
std::string hostname;
|
||||
@ -187,8 +189,10 @@ HostReservationParser::isSupportedParameter(const std::string& param_name) const
|
||||
|
||||
HostPtr
|
||||
HostReservationParser4::parseInternal(const SubnetID& subnet_id,
|
||||
isc::data::ConstElementPtr reservation_data) {
|
||||
HostPtr host = HostReservationParser::parseInternal(subnet_id, reservation_data);
|
||||
isc::data::ConstElementPtr reservation_data,
|
||||
bool encapsulate_options) {
|
||||
HostPtr host = HostReservationParser::parseInternal(subnet_id, reservation_data,
|
||||
encapsulate_options);
|
||||
|
||||
host->setIPv4SubnetID(subnet_id);
|
||||
|
||||
@ -203,7 +207,7 @@ HostReservationParser4::parseInternal(const SubnetID& subnet_id,
|
||||
// parses the Element structure immediately, there's no need
|
||||
// to go through build/commit phases.
|
||||
OptionDataListParser parser(AF_INET);
|
||||
parser.parse(cfg_option, element.second);
|
||||
parser.parse(cfg_option, element.second, encapsulate_options);
|
||||
|
||||
// Everything else should be surrounded with try-catch to append
|
||||
// position.
|
||||
@ -246,8 +250,10 @@ HostReservationParser4::getSupportedParameters(const bool identifiers_only) cons
|
||||
|
||||
HostPtr
|
||||
HostReservationParser6::parseInternal(const SubnetID& subnet_id,
|
||||
isc::data::ConstElementPtr reservation_data) {
|
||||
HostPtr host = HostReservationParser::parseInternal(subnet_id, reservation_data);
|
||||
isc::data::ConstElementPtr reservation_data,
|
||||
bool encapsulate_options) {
|
||||
HostPtr host = HostReservationParser::parseInternal(subnet_id, reservation_data,
|
||||
encapsulate_options);
|
||||
|
||||
host->setIPv6SubnetID(subnet_id);
|
||||
|
||||
@ -263,7 +269,7 @@ HostReservationParser6::parseInternal(const SubnetID& subnet_id,
|
||||
// parses the Element structure immediately, there's no need
|
||||
// to go through build/commit phases.
|
||||
OptionDataListParser parser(AF_INET6);
|
||||
parser.parse(cfg_option, element.second);
|
||||
parser.parse(cfg_option, element.second, encapsulate_options);
|
||||
|
||||
} else if (element.first == "ip-addresses" || element.first == "prefixes") {
|
||||
BOOST_FOREACH(ConstElementPtr prefix_element,
|
||||
|
@ -27,12 +27,15 @@ public:
|
||||
/// connected to.
|
||||
/// @param reservation_data Data element holding map with a host
|
||||
/// reservation configuration.
|
||||
/// @param encapsulate_options a boolean parameter indicating if the
|
||||
/// parsed options should be encapsulated with suboptions.
|
||||
///
|
||||
/// @return Pointer to the object representing parsed host.
|
||||
/// @throw DhcpConfigError If the configuration is invalid.
|
||||
virtual HostPtr
|
||||
parse(const SubnetID& subnet_id,
|
||||
isc::data::ConstElementPtr reservation_data) final;
|
||||
isc::data::ConstElementPtr reservation_data,
|
||||
bool encapsulate_options = true) final;
|
||||
|
||||
protected:
|
||||
|
||||
@ -45,11 +48,14 @@ protected:
|
||||
/// connected to.
|
||||
/// @param reservation_data Data element holding map with a host
|
||||
/// reservation configuration.
|
||||
/// @param encapsulate_options a boolean parameter indicating if the
|
||||
/// parsed options should be encapsulated with suboptions.
|
||||
///
|
||||
/// @return Pointer to the object representing parsed host.
|
||||
/// @throw DhcpConfigError If the configuration is invalid.
|
||||
virtual HostPtr parseInternal(const SubnetID& subnet_id,
|
||||
isc::data::ConstElementPtr reservation_data);
|
||||
isc::data::ConstElementPtr reservation_data,
|
||||
bool encapsulate_options);
|
||||
|
||||
/// @brief Checks if the specified parameter is a host identifier.
|
||||
///
|
||||
@ -87,11 +93,14 @@ protected:
|
||||
/// connected to.
|
||||
/// @param reservation_data Data element holding map with a host
|
||||
/// reservation configuration.
|
||||
/// @param encapsulate_options a boolean parameter indicating if the
|
||||
/// parsed options should be encapsulated with suboptions.
|
||||
///
|
||||
/// @return Pointer to the object representing parsed host.
|
||||
/// @throw DhcpConfigError If the configuration is invalid.
|
||||
virtual HostPtr parseInternal(const SubnetID& subnet_id,
|
||||
isc::data::ConstElementPtr reservation_data);
|
||||
isc::data::ConstElementPtr reservation_data,
|
||||
bool encapsulate_options);
|
||||
|
||||
/// @brief Returns set of the supported parameters for DHCPv4.
|
||||
///
|
||||
@ -114,11 +123,14 @@ protected:
|
||||
/// connected to.
|
||||
/// @param reservation_data Data element holding map with a host
|
||||
/// reservation configuration.
|
||||
/// @param encapsulate_options a boolean parameter indicating if the
|
||||
/// parsed options should be encapsulated with suboptions.
|
||||
///
|
||||
/// @return Pointer to the object representing parsed host.
|
||||
/// @throw DhcpConfigError If the configuration is invalid.
|
||||
virtual HostPtr parseInternal(const SubnetID& subnet_id,
|
||||
isc::data::ConstElementPtr reservation_data);
|
||||
isc::data::ConstElementPtr reservation_data,
|
||||
bool encapsulate_options);
|
||||
|
||||
/// @brief Returns set of the supported parameters for DHCPv6.
|
||||
///
|
||||
|
@ -455,14 +455,17 @@ OptionDataListParser::OptionDataListParser(//const std::string&,
|
||||
|
||||
|
||||
void OptionDataListParser::parse(const CfgOptionPtr& cfg,
|
||||
isc::data::ConstElementPtr option_data_list) {
|
||||
isc::data::ConstElementPtr option_data_list,
|
||||
bool encapsulate) {
|
||||
auto option_parser = createOptionDataParser();
|
||||
BOOST_FOREACH(ConstElementPtr data, option_data_list->listValue()) {
|
||||
std::pair<OptionDescriptor, std::string> option =
|
||||
option_parser->parse(data);
|
||||
// Use the option description to keep the formatted value
|
||||
cfg->add(option.first, option.second);
|
||||
cfg->encapsulate();
|
||||
if (encapsulate) {
|
||||
cfg->encapsulate();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -209,8 +209,12 @@ public:
|
||||
///
|
||||
/// @param cfg created options will be stored here
|
||||
/// @param option_data_list configuration that describes the options
|
||||
/// @param encapsulate a boolean value indicating whether or not the
|
||||
/// parser should encapsulate options with suboptions. The default
|
||||
/// value is true (encapsulate).
|
||||
void parse(const CfgOptionPtr& cfg,
|
||||
isc::data::ConstElementPtr option_data_list);
|
||||
isc::data::ConstElementPtr option_data_list,
|
||||
bool encapsulate = true);
|
||||
protected:
|
||||
|
||||
/// @brief Returns an instance of the @c OptionDataListParser to
|
||||
|
@ -31,7 +31,8 @@ SharedNetwork4Parser::SharedNetwork4Parser(bool check_iface)
|
||||
}
|
||||
|
||||
SharedNetwork4Ptr
|
||||
SharedNetwork4Parser::parse(const data::ConstElementPtr& shared_network_data) {
|
||||
SharedNetwork4Parser::parse(const data::ConstElementPtr& shared_network_data,
|
||||
bool encapsulate_options) {
|
||||
SharedNetwork4Ptr shared_network;
|
||||
try {
|
||||
|
||||
@ -75,7 +76,7 @@ SharedNetwork4Parser::parse(const data::ConstElementPtr& shared_network_data) {
|
||||
// Create parser instance for option-data.
|
||||
CfgOptionPtr cfg_option = shared_network->getCfgOption();
|
||||
auto parser = createOptionDataListParser();
|
||||
parser->parse(cfg_option, json);
|
||||
parser->parse(cfg_option, json, encapsulate_options);
|
||||
}
|
||||
|
||||
if (shared_network_data->contains("subnet4")) {
|
||||
@ -240,7 +241,8 @@ SharedNetwork6Parser::SharedNetwork6Parser(bool check_iface)
|
||||
}
|
||||
|
||||
SharedNetwork6Ptr
|
||||
SharedNetwork6Parser::parse(const data::ConstElementPtr& shared_network_data) {
|
||||
SharedNetwork6Parser::parse(const data::ConstElementPtr& shared_network_data,
|
||||
bool encapsulate_options) {
|
||||
SharedNetwork6Ptr shared_network;
|
||||
std::string name;
|
||||
try {
|
||||
@ -324,7 +326,7 @@ SharedNetwork6Parser::parse(const data::ConstElementPtr& shared_network_data) {
|
||||
// Create parser instance for option-data.
|
||||
CfgOptionPtr cfg_option = shared_network->getCfgOption();
|
||||
auto parser = createOptionDataListParser();
|
||||
parser->parse(cfg_option, json);
|
||||
parser->parse(cfg_option, json, encapsulate_options);
|
||||
}
|
||||
|
||||
if (shared_network_data->contains("client-class")) {
|
||||
|
@ -37,11 +37,14 @@ public:
|
||||
///
|
||||
/// @param shared_network_data Data element holding shared network
|
||||
/// configuration to be parsed.
|
||||
/// @param encapsulate_options a boolean parameter indicating if the
|
||||
/// parsed options should be encapsulated with suboptions.
|
||||
///
|
||||
/// @return Pointer to an object representing shared network.
|
||||
/// @throw DhcpConfigError when shared network configuration is invalid.
|
||||
SharedNetwork4Ptr
|
||||
parse(const data::ConstElementPtr& shared_network_data);
|
||||
parse(const data::ConstElementPtr& shared_network_data,
|
||||
bool encapsulate_options = true);
|
||||
|
||||
protected:
|
||||
|
||||
@ -84,11 +87,14 @@ public:
|
||||
///
|
||||
/// @param shared_network_data Data element holding shared network
|
||||
/// configuration to be parsed.
|
||||
/// @param encapsulate_options a boolean parameter indicating if the
|
||||
/// parsed options should be encapsulated with suboptions.
|
||||
///
|
||||
/// @return Pointer to an object representing shared network.
|
||||
/// @throw DhcpConfigError when shared network configuration is invalid.
|
||||
SharedNetwork6Ptr
|
||||
parse(const data::ConstElementPtr& shared_network_data);
|
||||
parse(const data::ConstElementPtr& shared_network_data,
|
||||
bool encapsulate_options = true);
|
||||
|
||||
protected:
|
||||
|
||||
|
@ -651,6 +651,11 @@ private:
|
||||
def = LibDHCP::getRuntimeOptionDef(space, code);
|
||||
}
|
||||
|
||||
// Finish with a last resort option definition.
|
||||
if (!def) {
|
||||
def = LibDHCP::getLastResortOptionDef(space, code);
|
||||
}
|
||||
|
||||
OptionPtr option;
|
||||
|
||||
if (!def) {
|
||||
|
@ -694,11 +694,15 @@ TEST_F(CfgOptionTest, encapsulate) {
|
||||
|
||||
generateEncapsulatedOptions(cfg);
|
||||
|
||||
EXPECT_FALSE(cfg.isEncapsulated());
|
||||
|
||||
// Append options from "foo" and "bar" space as sub-options and options
|
||||
// from "foo-subs" and "bar-subs" as sub-options of "foo" and "bar"
|
||||
// options.
|
||||
ASSERT_NO_THROW(cfg.encapsulate());
|
||||
|
||||
EXPECT_TRUE(cfg.isEncapsulated());
|
||||
|
||||
// Verify that we have 40 top-level options.
|
||||
OptionContainerPtr options = cfg.getAll(DHCP6_OPTION_SPACE);
|
||||
ASSERT_EQ(40, options->size());
|
||||
|
@ -951,6 +951,29 @@ TEST_F(HostTest, addOptions4) {
|
||||
EXPECT_TRUE(options->empty());
|
||||
}
|
||||
|
||||
// This test checks that host-specific DHCPv4 options can be encapsulated.
|
||||
TEST_F(HostTest, encapsulateOptions4) {
|
||||
Host host("01:02:03:04:05:06", "hw-address", SubnetID(1), SubnetID(2),
|
||||
IOAddress("192.0.2.3"));
|
||||
|
||||
OptionPtr option43(new Option(Option::V4, DHO_VENDOR_ENCAPSULATED_OPTIONS));
|
||||
option43->setEncapsulatedSpace(VENDOR_ENCAPSULATED_OPTION_SPACE);
|
||||
ASSERT_NO_THROW(host.getCfgOption4()->add(option43, false, false, DHCP4_OPTION_SPACE));
|
||||
|
||||
OptionPtr option1(new Option(Option::V4, 1));
|
||||
ASSERT_NO_THROW(host.getCfgOption4()->add(option1, false, false,
|
||||
VENDOR_ENCAPSULATED_OPTION_SPACE));
|
||||
|
||||
ASSERT_NO_THROW(host.encapsulateOptions());
|
||||
|
||||
auto returned_option43 = host.getCfgOption4()->get(DHCP4_OPTION_SPACE,
|
||||
DHO_VENDOR_ENCAPSULATED_OPTIONS);
|
||||
ASSERT_TRUE(returned_option43.option_);
|
||||
|
||||
auto returned_option1 = returned_option43.option_->getOption(1);
|
||||
ASSERT_TRUE(returned_option1);
|
||||
}
|
||||
|
||||
// This test checks that it is possible to add DHCPv6 options for a host.
|
||||
TEST_F(HostTest, addOptions6) {
|
||||
Host host("01:02:03:04:05:06", "hw-address", SubnetID(1), SubnetID(2),
|
||||
@ -1016,6 +1039,29 @@ TEST_F(HostTest, addOptions6) {
|
||||
EXPECT_TRUE(options->empty());
|
||||
}
|
||||
|
||||
// This test checks that it is possible to add DHCPv6 options for a host.
|
||||
TEST_F(HostTest, encapsulateOptions6) {
|
||||
Host host("01:02:03:04:05:06", "hw-address", SubnetID(1), SubnetID(2),
|
||||
IOAddress("192.0.2.3"));
|
||||
|
||||
OptionPtr option94(new Option(Option::V6, D6O_S46_CONT_MAPE));
|
||||
option94->setEncapsulatedSpace(MAPE_V6_OPTION_SPACE);
|
||||
ASSERT_NO_THROW(host.getCfgOption6()->add(option94, false, false, DHCP6_OPTION_SPACE));
|
||||
|
||||
OptionPtr option1(new Option(Option::V6, 1));
|
||||
ASSERT_NO_THROW(host.getCfgOption6()->add(option1, false, false,
|
||||
MAPE_V6_OPTION_SPACE));
|
||||
|
||||
ASSERT_NO_THROW(host.encapsulateOptions());
|
||||
|
||||
auto returned_option94 = host.getCfgOption6()->get(DHCP6_OPTION_SPACE,
|
||||
D6O_S46_CONT_MAPE);
|
||||
ASSERT_TRUE(returned_option94.option_);
|
||||
|
||||
auto returned_option1 = returned_option94.option_->getOption(1);
|
||||
ASSERT_TRUE(returned_option1);
|
||||
}
|
||||
|
||||
// This test verifies that it is possible to retrieve a textual
|
||||
// representation of the host identifier.
|
||||
TEST_F(HostTest, getIdentifierAsText) {
|
||||
|
@ -128,7 +128,7 @@ GenericHostDataSourceTest::addTestOptions(const HostPtr& host,
|
||||
DHCP4_OPTION_SPACE);
|
||||
opts->add(createOption<OptionUint32>(Option::V4, 1, false, false,
|
||||
formatted, 312131),
|
||||
"vendor-encapsulated-options");
|
||||
"vendor-encapsulated-options-space");
|
||||
opts->add(createAddressOption<Option4AddrLst>(254, false, false,
|
||||
formatted, "192.0.2.3"),
|
||||
DHCP4_OPTION_SPACE);
|
||||
@ -137,11 +137,17 @@ GenericHostDataSourceTest::addTestOptions(const HostPtr& host,
|
||||
formatted, "10.0.0.5",
|
||||
"10.0.0.3", "10.0.3.4"),
|
||||
"isc");
|
||||
auto def = LibDHCP::getLastResortOptionDef(DHCP4_OPTION_SPACE,
|
||||
DHO_VENDOR_ENCAPSULATED_OPTIONS);
|
||||
opts->add(OptionDescriptor(def->optionFactory(Option::V4,
|
||||
DHO_VENDOR_ENCAPSULATED_OPTIONS,
|
||||
OptionBuffer()),
|
||||
true, false), DHCP4_OPTION_SPACE);
|
||||
|
||||
// Add definitions for DHCPv4 non-standard options.
|
||||
defs.addItem(OptionDefinitionPtr(new OptionDefinition(
|
||||
"vendor-encapsulated-1", 1,
|
||||
"vendor-encapsulated-options", "uint32")));
|
||||
"vendor-encapsulated-options-space", "uint32")));
|
||||
defs.addItem(OptionDefinitionPtr(new OptionDefinition(
|
||||
"option-254", 254, DHCP4_OPTION_SPACE,
|
||||
"ipv4-address", true)));
|
||||
@ -2047,6 +2053,18 @@ GenericHostDataSourceTest::testOptionsReservations4(const bool formatted,
|
||||
ASSERT_EQ(1, hosts_by_subnet.size());
|
||||
ASSERT_NO_FATAL_FAILURE(HostDataSourceUtils::compareHosts(host, *hosts_by_subnet.begin()));
|
||||
|
||||
auto returned_host = *hosts_by_subnet.begin();
|
||||
ASSERT_NO_THROW(returned_host->encapsulateOptions());
|
||||
auto cfg_option = returned_host->getCfgOption4();
|
||||
|
||||
auto option43 = cfg_option->get(DHCP4_OPTION_SPACE, DHO_VENDOR_ENCAPSULATED_OPTIONS);
|
||||
ASSERT_TRUE(option43.option_);
|
||||
|
||||
EXPECT_TRUE(cfg_option->get("vendor-encapsulated-options-space", 1).option_);
|
||||
|
||||
auto option43_1 = option43.option_->getOption(1);
|
||||
EXPECT_TRUE(option43_1);
|
||||
|
||||
// getAll4(address)
|
||||
ConstHostCollection hosts_by_addr =
|
||||
hdsptr_->getAll4(host->getIPv4Reservation());
|
||||
|
Loading…
x
Reference in New Issue
Block a user