From: Marcin Siodelski Date: Thu, 25 Oct 2012 13:34:57 +0000 (+0200) Subject: [2318] Parsing and setting option data. X-Git-Tag: trac2487_base~28^2~10 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=08e5c7f5394f449a3e5b7128eacdf5b7a096aa5e;p=thirdparty%2Fkea.git [2318] Parsing and setting option data. --- diff --git a/src/bin/dhcp6/Makefile.am b/src/bin/dhcp6/Makefile.am index 68aadea5ad..55fe619da0 100644 --- a/src/bin/dhcp6/Makefile.am +++ b/src/bin/dhcp6/Makefile.am @@ -60,6 +60,7 @@ b10_dhcp6_CXXFLAGS = -Wno-unused-parameter endif b10_dhcp6_LDADD = $(top_builddir)/src/lib/exceptions/libb10-exceptions.la +b10_dhcp6_LDADD += $(top_builddir)/src/lib/util/libb10-util.la b10_dhcp6_LDADD += $(top_builddir)/src/lib/asiolink/libb10-asiolink.la b10_dhcp6_LDADD += $(top_builddir)/src/lib/log/libb10-log.la b10_dhcp6_LDADD += $(top_builddir)/src/lib/dhcp/libb10-dhcp++.la diff --git a/src/bin/dhcp6/config_parser.cc b/src/bin/dhcp6/config_parser.cc index ac389b4ca5..38879a5ec5 100644 --- a/src/bin/dhcp6/config_parser.cc +++ b/src/bin/dhcp6/config_parser.cc @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -557,12 +558,22 @@ private: isc_throw(Dhcp6ConfigError, "Parser error: option name must not contain" << " spaces"); } + + std::string option_data = getStringParam("data"); + std::vector binary; + try { + util::encode::decodeHex(option_data, binary); + } catch (...) { + isc_throw(Dhcp6ConfigError, "Parser error: option data is not a valid" + << " string of hexadecimal digits: " << option_data); + } + // Create the actual option. // @todo Currently we simply create dhcp::Option instance here but we will // need to use dedicated factory functions once the option definitions are // created for all options. OptionPtr option(new Option(Option::V6, static_cast(option_code), - OptionBuffer())); + binary)); // If option is created succesfully, add it to the storage. options_->push_back(option); } @@ -647,7 +658,7 @@ public: void commit() { } /// @brief Create DhcpDataListParser object - /// + /// /// @param param_name param name. /// /// @return DhcpConfigParser object. @@ -762,6 +773,7 @@ public: subnet->addOption(option); } + std::cout << "ADDING SUBNET" << std::endl; CfgMgr::instance().addSubnet6(subnet); } @@ -927,7 +939,6 @@ public: DhcpConfigParser* createGlobalDhcpConfigParser(const std::string& config_id) { FactoryMap factories; - // factories.insert(pair( "preferred-lifetime", Uint32Parser::Factory)); factories.insert(pair( diff --git a/src/bin/dhcp6/tests/Makefile.am b/src/bin/dhcp6/tests/Makefile.am index 1629ae62ce..78caa2f755 100644 --- a/src/bin/dhcp6/tests/Makefile.am +++ b/src/bin/dhcp6/tests/Makefile.am @@ -63,6 +63,7 @@ dhcp6_unittests_CPPFLAGS = $(AM_CPPFLAGS) $(GTEST_INCLUDES) dhcp6_unittests_LDFLAGS = $(AM_LDFLAGS) $(GTEST_LDFLAGS) dhcp6_unittests_LDADD = $(GTEST_LDADD) dhcp6_unittests_LDADD += $(top_builddir)/src/lib/asiolink/libb10-asiolink.la +dhcp6_unittests_LDADD += $(top_builddir)/src/lib/util/libb10-util.la dhcp6_unittests_LDADD += $(top_builddir)/src/lib/dhcp/libb10-dhcp++.la dhcp6_unittests_LDADD += $(top_builddir)/src/lib/dhcp/libb10-dhcpsrv.la dhcp6_unittests_LDADD += $(top_builddir)/src/lib/log/libb10-log.la diff --git a/src/bin/dhcp6/tests/config_parser_unittest.cc b/src/bin/dhcp6/tests/config_parser_unittest.cc index 0fc953ff0e..2fd3116741 100644 --- a/src/bin/dhcp6/tests/config_parser_unittest.cc +++ b/src/bin/dhcp6/tests/config_parser_unittest.cc @@ -272,7 +272,7 @@ TEST_F(Dhcp6ParserTest, pool_prefix_len) { EXPECT_EQ(4000, subnet->getValid()); } -TEST_F(Dhcp6ParserTest, multipleOptionValues) { +TEST_F(Dhcp6ParserTest, optionValuesInSingleSubnet) { ConstElementPtr x; string config = "{ \"interface\": [ \"all\" ]," "\"preferred-lifetime\": 3000," @@ -284,23 +284,22 @@ TEST_F(Dhcp6ParserTest, multipleOptionValues) { " \"option-data\": [ {" " \"name\": \"option_foo\"," " \"code\": 100," - " \"data\": \"ABCDEF 01 05\"" + " \"data\": \"AB CDEF0105\"" " }," " {" " \"name\": \"option_foo2\"," " \"code\": 101," - " \"data\": \"1\"" + " \"data\": \"01\"" " } ]" " } ]," "\"valid-lifetime\": 4000 }"; - cout << config << endl; ElementPtr json = Element::fromJSON(config); EXPECT_NO_THROW(x = configureDhcp6Server(*srv_, json)); ASSERT_TRUE(x); comment_ = parseAnswer(rcode_, x); - EXPECT_EQ(0, rcode_); + ASSERT_EQ(0, rcode_); Subnet6Ptr subnet = CfgMgr::instance().getSubnet6(IOAddress("2001:db8:1::5")); ASSERT_TRUE(subnet); @@ -333,4 +332,84 @@ TEST_F(Dhcp6ParserTest, multipleOptionValues) { testOption(*range.first, 101, foo2_expected, sizeof(foo2_expected)); } +TEST_F(Dhcp6ParserTest, optionValuesInMultipleSubnets) { + ConstElementPtr x; + string config = "{ \"interface\": [ \"all\" ]," + "\"preferred-lifetime\": 3000," + "\"rebind-timer\": 2000, " + "\"renew-timer\": 1000, " + "\"subnet6\": [ { " + " \"pool\": [ \"2001:db8:1::/80\" ]," + " \"subnet\": \"2001:db8:1::/64\", " + " \"option-data\": [ {" + " \"name\": \"option_foo\"," + " \"code\": 100," + " \"data\": \"0102030405060708090A\"" + " } ]" + " }," + " {" + " \"pool\": [ \"2001:db8:2::/80\" ]," + " \"subnet\": \"2001:db8:2::/64\", " + " \"option-data\": [ {" + " \"name\": \"option_foo2\"," + " \"code\": 101," + " \"data\": \"FFFEFDFCFB\"" + " } ]" + " } ]," + "\"valid-lifetime\": 4000 }"; + + ElementPtr json = Element::fromJSON(config); + + EXPECT_NO_THROW(x = configureDhcp6Server(*srv_, json)); + ASSERT_TRUE(x); + comment_ = parseAnswer(rcode_, x); + ASSERT_EQ(0, rcode_); + + Subnet6Ptr subnet1 = CfgMgr::instance().getSubnet6(IOAddress("2001:db8:1::5")); + ASSERT_TRUE(subnet1); + const Subnet::OptionContainer& options1 = subnet1->getOptions(); + ASSERT_EQ(1, options1.size()); + + for (Subnet::OptionContainer::iterator it = options1.begin(); + it != options1.end(); ++it) { + std::cout << it->option->getType() << std::endl; + } + + // Get the search index. Index #1 is to search using option code. + const Subnet::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 range1 = + idx1.equal_range(100); + // Expect single option with the code equal to 100. + ASSERT_EQ(1, std::distance(range1.first, range1.second)); + const uint8_t foo_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, 100, foo_expected, sizeof(foo_expected)); + + // Test another subnet in the same way. + Subnet6Ptr subnet2 = CfgMgr::instance().getSubnet6(IOAddress("2001:db8:2::4")); + ASSERT_TRUE(subnet2); + const Subnet::OptionContainer& options2 = subnet2->getOptions(); + ASSERT_EQ(1, options2.size()); + + const Subnet::OptionContainerTypeIndex& idx2 = options2.get<1>(); + std::pair range2 = + idx2.equal_range(101); + ASSERT_EQ(1, std::distance(range2.first, range2.second)); + + const uint8_t foo2_expected[] = { + 0xFF, 0xFE, 0xFD, 0xFC, 0xFB + }; + testOption(*range2.first, 101, foo2_expected, sizeof(foo2_expected)); +} + + };