/// upon "commit"
PdPoolParser(const std::string&, PoolStoragePtr pools)
: uint32_values_(new Uint32Storage()),
- string_values_(new StringStorage()), pools_(pools) {
+ string_values_(new StringStorage()), pools_(pools),
+ options_(new CfgOption()) {
if (!pools_) {
isc_throw(isc::dhcp::DhcpConfigError,
"PdPoolParser context storage may not be NULL");
Uint32ParserPtr code_parser(new Uint32Parser(entry,
uint32_values_));
parser = code_parser;
+ } else if (entry == "option-data") {
+ OptionDataListParserPtr option_parser(new OptionDataListParser(entry,
+ options_,
+ AF_INET6));
+ parser = option_parser;
+
} else {
isc_throw(DhcpConfigError, "unsupported parameter: " << entry
<< " (" << param.second->getPosition() << ")");
/// Pointer to storage to which the local pool is written upon commit.
isc::dhcp::PoolStoragePtr pools_;
+
+ /// A storage for pool specific option values.
+ CfgOptionPtr options_;
};
/// @brief Parser for a list of prefix delegation pools.
sizeof(user_class_expected));
}
+TEST_F(Dhcp6ParserTest, optionDataInMultiplePools) {
+ ConstElementPtr x;
+ string config = "{ " + genIfaceConfig() + ","
+ "\"preferred-lifetime\": 3000,"
+ "\"rebind-timer\": 2000, "
+ "\"renew-timer\": 1000, "
+ "\"subnet6\": [ { "
+ " \"pools\": [ { "
+ " \"pool\": \"2001:db8:1::10 - 2001:db8:1::100\""
+/* " \"option-data\": [ {"
+ " \"name\": \"subscriber-id\","
+ " \"data\": \"0102030405060708090A\","
+ " \"csv-format\": False"
+ " } ]" */
+ " },"
+ " {"
+ " \"pool\": \"2001:db8:1::300 - 2001:db8:1::400\""
+/* " \"option-data\": [ {"
+ " \"name\": \"user-class\","
+ " \"data\": \"FFFEFDFCFB\","
+ " \"csv-format\": False"
+ " } ]" */
+ " } ],"
+ " \"pd-pools\": [ { "
+ " \"prefix\": \"3000::\","
+ " \"prefix-len\": 48,"
+ " \"delegated-len\": 64,"
+ " \"option-data\": [ {"
+ " \"name\": \"subscriber-id\","
+ " \"data\": \"112233445566\","
+ " \"csv-format\": False"
+ " } ]"
+ " },"
+ " {"
+ " \"prefix\": \"3001::\","
+ " \"prefix-len\": 48,"
+ " \"delegated-len\": 64,"
+ " \"option-data\": [ {"
+ " \"name\": \"user-class\","
+ " \"data\": \"aabbccddee\","
+ " \"csv-format\": False"
+ " } ]"
+ " } ],"
+ " \"subnet\": \"2001:db8:1::/64\""
+ " } ],"
+ "\"valid-lifetime\": 4000 }";
+
+ ElementPtr json = Element::fromJSON(config);
+
+ EXPECT_NO_THROW(x = configureDhcp6Server(srv_, json));
+ checkResult(x, 0);
+
+ Subnet6Ptr subnet = CfgMgr::instance().getStagingCfg()->getCfgSubnets6()->
+ selectSubnet(IOAddress("2001:db8:1::5"), classify_);
+ ASSERT_TRUE(subnet);
+
+ PoolPtr pool = subnet->getPool(Lease::TYPE_PD, IOAddress("3000::"), false);
+ ASSERT_TRUE(pool);
+ Pool6Ptr pool6 = boost::dynamic_pointer_cast<Pool6>(pool);
+
+
+ OptionContainerPtr options1 = pool6->getCfgOption()->getAll("dhcp6");
+ ASSERT_EQ(1, options1->size());
+
+ // Get the search index. Index #1 is to search using option code.
+ const OptionContainerTypeIndex& idx1 = options1->get<1>();
+
+ // Get the options for specified index. Expecting one option to be
+ // returned but in theory we may have multiple options with the same
+ // code so we get the range.
+ std::pair<OptionContainerTypeIndex::const_iterator,
+ OptionContainerTypeIndex::const_iterator> range1 =
+ idx1.equal_range(D6O_SUBSCRIBER_ID);
+ // Expect single option with the code equal to 38.
+ ASSERT_EQ(1, std::distance(range1.first, range1.second));
+ const uint8_t subid_expected[] = {
+ 0x01, 0x02, 0x03, 0x04, 0x05,
+ 0x06, 0x07, 0x08, 0x09, 0x0A
+ };
+ // Check if option is valid in terms of code and carried data.
+ testOption(*range1.first, D6O_SUBSCRIBER_ID, subid_expected,
+ sizeof(subid_expected));
+
+/* // Test another subnet in the same way.
+ Subnet6Ptr subnet2 = CfgMgr::instance().getStagingCfg()->getCfgSubnets6()->
+ selectSubnet(IOAddress("2001:db8:2::4"), classify_);
+ ASSERT_TRUE(subnet2);
+ OptionContainerPtr options2 = subnet2->getCfgOption()->getAll("dhcp6");
+ ASSERT_EQ(1, options2->size());
+
+ const OptionContainerTypeIndex& idx2 = options2->get<1>();
+ std::pair<OptionContainerTypeIndex::const_iterator,
+ OptionContainerTypeIndex::const_iterator> range2 =
+ idx2.equal_range(D6O_USER_CLASS);
+ ASSERT_EQ(1, std::distance(range2.first, range2.second));
+
+ const uint8_t user_class_expected[] = {
+ 0xFF, 0xFE, 0xFD, 0xFC, 0xFB
+ };
+ testOption(*range2.first, D6O_USER_CLASS, user_class_expected,
+ sizeof(user_class_expected)); */
+
+}
+
// The goal of this test is to check that the option carrying a boolean
// value can be configured using one of the values: "true", "false", "0"
// or "1".
-// Copyright (C) 2012-2015 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2012-2016 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
Pool::Pool(Lease::Type type, const isc::asiolink::IOAddress& first,
const isc::asiolink::IOAddress& last)
:id_(getNextID()), first_(first), last_(last), type_(type),
- capacity_(0) {
+ capacity_(0), cfg_option_(new CfgOption()) {
}
bool Pool::inRange(const isc::asiolink::IOAddress& addr) const {
-// Copyright (C) 2012-2015 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2012-2016 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
#include <asiolink/io_address.h>
#include <boost/shared_ptr.hpp>
+#include <dhcpsrv/cfg_option.h>
#include <dhcpsrv/lease.h>
#include <vector>
uint64_t getCapacity() const {
return (capacity_);
}
+
+ /// @brief Returns pointer to the option data configuration for this pool.
+ CfgOptionPtr getCfgOption() {
+ return (cfg_option_);
+ }
+
+ /// @brief Returns const pointer to the option data configuration for
+ /// this pool.
+ ConstCfgOptionPtr getCfgOption() const {
+ return (cfg_option_);
+ }
+
protected:
/// @brief protected constructor
/// the result. Note that for very large pools, the number is capped at
/// max value of uint64_t.
uint64_t capacity_;
+
+ /// @brief Pointer to the option data configuration for this pool.
+ CfgOptionPtr cfg_option_;
};
/// @brief Pool information for IPv4 addresses
-// Copyright (C) 2012-2015 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2012-2016 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
EXPECT_EQ(65536, pool2.getCapacity());
}
+// This test checks that it is possible to specify pool specific options.
+TEST(Pool6Test, addOptions) {
+ // Create a pool to add options to it.
+ Pool6Ptr pool(new Pool6(Lease::TYPE_PD, IOAddress("3000::"), 64, 128));
+
+ // Differentiate options by their codes (100-109)
+ for (uint16_t code = 100; code < 110; ++code) {
+ OptionPtr option(new Option(Option::V6, code, OptionBuffer(10, 0xFF)));
+ ASSERT_NO_THROW(pool->getCfgOption()->add(option, false, "dhcp6"));
+ }
+
+ // Add 7 options to another option space. The option codes partially overlap
+ // with option codes that we have added to dhcp6 option space.
+ for (uint16_t code = 105; code < 112; ++code) {
+ OptionPtr option(new Option(Option::V6, code, OptionBuffer(10, 0xFF)));
+ ASSERT_NO_THROW(pool->getCfgOption()->add(option, false, "isc"));
+ }
+
+ // Get options from the pool and check if all 10 are there.
+ OptionContainerPtr options = pool->getCfgOption()->getAll("dhcp6");
+ ASSERT_TRUE(options);
+ ASSERT_EQ(10, options->size());
+
+ // Validate codes of options added to dhcp6 option space.
+ uint16_t expected_code = 100;
+ for (OptionContainer::const_iterator option_desc = options->begin();
+ option_desc != options->end(); ++option_desc) {
+ ASSERT_TRUE(option_desc->option_);
+ EXPECT_EQ(expected_code, option_desc->option_->getType());
+ ++expected_code;
+ }
+
+ options = pool->getCfgOption()->getAll("isc");
+ ASSERT_TRUE(options);
+ ASSERT_EQ(7, options->size());
+
+ // Validate codes of options added to isc option space.
+ expected_code = 105;
+ for (OptionContainer::const_iterator option_desc = options->begin();
+ option_desc != options->end(); ++option_desc) {
+ ASSERT_TRUE(option_desc->option_);
+ EXPECT_EQ(expected_code, option_desc->option_->getType());
+ ++expected_code;
+ }
+
+ // Try to get options from a non-existing option space.
+ options = pool->getCfgOption()->getAll("abcd");
+ ASSERT_TRUE(options);
+ EXPECT_TRUE(options->empty());
+}
}; // end of anonymous namespace