// from the option spaces they encapsulate.
for (OptionContainer::const_iterator opt = options->begin();
opt != options->end(); ++opt) {
- // Get encapsulated option space for the option.
- const std::string& encap_space = opt->option_->getEncapsulatedSpace();
- // Empty value means that no option space is encapsulated.
- if (!encap_space.empty()) {
- // Retrieve all options from the encapsulated option space.
- OptionContainerPtr encap_options = getAll(encap_space);
- for (OptionContainer::const_iterator encap_opt =
- encap_options->begin(); encap_opt != encap_options->end();
- ++encap_opt) {
- // Add sub-option if there isn't one added already.
- if (!opt->option_->getOption(encap_opt->option_->getType())) {
- opt->option_->addOption(encap_opt->option_);
- }
+ encapsulateInternal(opt->option_);
+ }
+}
+
+void
+CfgOption::encapsulateInternal(const OptionPtr& option) {
+ // Get encapsulated option space for the option.
+ const std::string& encap_space = option->getEncapsulatedSpace();
+ // Empty value means that no option space is encapsulated.
+ if (!encap_space.empty()) {
+ // Retrieve all options from the encapsulated option space.
+ OptionContainerPtr encap_options = getAll(encap_space);
+ for (OptionContainer::const_iterator encap_opt =
+ encap_options->begin(); encap_opt != encap_options->end();
+ ++encap_opt) {
+ // Add sub-option if there isn't one added already.
+ if (!option->getOption(encap_opt->option_->getType())) {
+ option->addOption(encap_opt->option_);
+ }
+ // This is a workaround for preventing infinite recursion when
+ // trying to encapsulate options created with default global option
+ // spaces.
+ if (encap_space != DHCP4_OPTION_SPACE &&
+ encap_space != DHCP6_OPTION_SPACE) {
+ encapsulateInternal(encap_opt->option_);
}
}
}
/// which encapsulated options are appended.
void encapsulateInternal(const std::string& option_space);
+ /// @brief Appends encapsulated options from the option space encapsulated
+ /// by the specified option.
+ ///
+ /// This method will go over all options belonging to the encapsulated space
+ /// and will check which option spaces they encapsulate recursively,
+ /// adding these options to the current option
+ ///
+ /// @param option which encapsulated options.
+ void encapsulateInternal(const OptionPtr& option);
+
/// @brief Merges data from two option containers.
///
/// This method merges options from one option container to another
}
// Create sub-options belonging to "bar-subs" option space.
- for (uint16_t code = 500; code < 510; ++code) {
+ for (uint16_t code = 501; code < 510; ++code) {
OptionUint8Ptr option = OptionUint8Ptr(new OptionUint8(Option::V6,
code, 0x04));
ASSERT_NO_THROW(cfg.add(option, false, "bar-subs"));
EXPECT_EQ(2, value);
}
- // Each first level sub-option should include 10 second level
+ // Each first level sub-option should include 9 second level
// sub options.
const OptionCollection& second_level = first_level_uint8->getOptions();
- ASSERT_EQ(10, second_level.size());
+ ASSERT_EQ(9, second_level.size());
// Iterate over sub-options and make sure they include the expected
// values.
std::pair<unsigned int, OptionPtr> second_level_opt;
BOOST_FOREACH(second_level_opt, second_level) {
OptionUint8Ptr second_level_uint8 = boost::dynamic_pointer_cast<
- OptionUint8>(second_level_uint8);
+ OptionUint8>(second_level_opt.second);
+ ASSERT_TRUE(second_level_uint8);
const unsigned value = static_cast<
unsigned>(second_level_uint8->getValue());
// Certain sub-options should have a value of 3, other the values