summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/bin/dhcp4/tests/config_parser_unittest.cc2
-rw-r--r--src/bin/dhcp6/tests/config_parser_unittest.cc2
-rw-r--r--src/lib/dhcp/tests/libdhcp++_unittest.cc85
-rw-r--r--src/lib/dhcp/tests/option_unittest.cc4
-rw-r--r--src/lib/dhcpsrv/tests/dhcp_parsers_unittest.cc78
5 files changed, 169 insertions, 2 deletions
diff --git a/src/bin/dhcp4/tests/config_parser_unittest.cc b/src/bin/dhcp4/tests/config_parser_unittest.cc
index d492e43fb0..7c035595bb 100644
--- a/src/bin/dhcp4/tests/config_parser_unittest.cc
+++ b/src/bin/dhcp4/tests/config_parser_unittest.cc
@@ -3351,7 +3351,7 @@ TEST_F(Dhcp4ParserTest, optionCodeNonUint8) {
}
// Verify that zero option code is rejected in the configuration.
-TEST_F(Dhcp4ParserTest, optionCodeZero) {
+TEST_F(Dhcp4ParserTest, DISABLED_optionCodeZero) {
// Option code 0 is reserved and should not be accepted
// by configuration parser.
testInvalidOptionParam("0", "code");
diff --git a/src/bin/dhcp6/tests/config_parser_unittest.cc b/src/bin/dhcp6/tests/config_parser_unittest.cc
index 64e1c95f26..5458e4f41b 100644
--- a/src/bin/dhcp6/tests/config_parser_unittest.cc
+++ b/src/bin/dhcp6/tests/config_parser_unittest.cc
@@ -3555,7 +3555,7 @@ TEST_F(Dhcp6ParserTest, optionCodeHighNonUint16) {
}
// Verify that zero option code is rejected in the configuration.
-TEST_F(Dhcp6ParserTest, optionCodeZero) {
+TEST_F(Dhcp6ParserTest, DISABLED_optionCodeZero) {
// Option code 0 is reserved and should not be accepted
// by configuration parser.
testInvalidOptionParam("0", "code");
diff --git a/src/lib/dhcp/tests/libdhcp++_unittest.cc b/src/lib/dhcp/tests/libdhcp++_unittest.cc
index 43f64e7bbe..90471943e2 100644
--- a/src/lib/dhcp/tests/libdhcp++_unittest.cc
+++ b/src/lib/dhcp/tests/libdhcp++_unittest.cc
@@ -1016,6 +1016,91 @@ TEST_F(LibDhcpTest, unpackSubOptions4) {
EXPECT_EQ(0x0, option_bar->getValue());
}
+// Verifies that options 0 (PAD) and 255 (END) are handled as PAD and END
+// in and only in the dhcp4 space.
+TEST_F(LibDhcpTest, unpackPadEnd) {
+ // Create option definition for the container.
+ OptionDefinitionPtr opt_def(new OptionDefinition("container", 200,
+ "empty", "my-space"));
+ // Create option definition for option 0.
+ OptionDefinitionPtr opt_def0(new OptionDefinition("zero", 0, "uint8"));
+
+ // Create option definition for option 255.
+ OptionDefinitionPtr opt_def255(new OptionDefinition("max", 255, "uint8"));
+
+ // Create option definition for another option.
+ OptionDefinitionPtr opt_def2(new OptionDefinition("my-option", 1,
+ "string"));
+
+ // Register created option definitions as runtime option definitions.
+ OptionDefSpaceContainer defs;
+ ASSERT_NO_THROW(defs.addItem(opt_def, DHCP4_OPTION_SPACE));
+ ASSERT_NO_THROW(defs.addItem(opt_def0, "my-space"));
+ ASSERT_NO_THROW(defs.addItem(opt_def255, "my-space"));
+ ASSERT_NO_THROW(defs.addItem(opt_def2, "my-space"));
+ LibDHCP::setRuntimeOptionDefs(defs);
+ LibDHCP::commitRuntimeOptionDefs();
+
+ // Create the buffer holding the structure of options.
+ const uint8_t raw_data[] = {
+ // Add a PAD
+ 0x00, // option code = 0 (PAD)
+ // Container option starts here.
+ 0xc8, // option code = 200 (container)
+ 0x0b, // option length = 11
+ // Suboption 0.
+ 0x00, 0x01, 0x00, // code = 0, length = 1, content = 0
+ // Suboption 255.
+ 0xff, 0x01, 0xff, // code = 255, length = 1, content = 255
+ // Suboption 1.
+ 0x01, 0x03, 0x66, 0x6f, 0x6f, // code = 1, length = 2, content = "foo"
+ // END
+ 0xff
+ };
+ size_t raw_data_len = sizeof(raw_data) / sizeof(uint8_t);
+ OptionBuffer buf(raw_data, raw_data + raw_data_len);
+
+ // Parse options.
+ OptionCollection options;
+ list<uint16_t> deferred;
+ ASSERT_NO_THROW(LibDHCP::unpackOptions4(buf, DHCP4_OPTION_SPACE,
+ options, deferred));
+
+ // There should be one top level option.
+ ASSERT_EQ(1, options.size());
+
+ // Get it.
+ OptionPtr option = options.begin()->second;
+ ASSERT_TRUE(option);
+ EXPECT_EQ(200, option->getType());
+
+ // There should be 3 suboptions.
+ EXPECT_EQ(3, option->getOptions().size());
+
+ // Get suboption 0.
+ boost::shared_ptr<OptionInt<uint8_t> > sub0 =
+ boost::dynamic_pointer_cast<OptionInt<uint8_t> >
+ (option->getOption(0));
+ ASSERT_TRUE(sub0);
+ EXPECT_EQ(0, sub0->getType());
+ EXPECT_EQ(0, sub0->getValue());
+
+ // Get suboption 255.
+ boost::shared_ptr<OptionInt<uint8_t> > sub255 =
+ boost::dynamic_pointer_cast<OptionInt<uint8_t> >
+ (option->getOption(255));
+ ASSERT_TRUE(sub255);
+ EXPECT_EQ(255, sub255->getType());
+ EXPECT_EQ(255, sub255->getValue());
+
+ // Get suboption 1.
+ boost::shared_ptr<OptionString> sub =
+ boost::dynamic_pointer_cast<OptionString>(option->getOption(1));
+ ASSERT_TRUE(sub);
+ EXPECT_EQ(1, sub->getType());
+ EXPECT_EQ("foo", sub->getValue());
+}
+
// Verifies that an Host Name (option 12), will be dropped when empty,
// while subsequent options will still be unpacked.
TEST_F(LibDhcpTest, emptyHostName) {
diff --git a/src/lib/dhcp/tests/option_unittest.cc b/src/lib/dhcp/tests/option_unittest.cc
index a86a26d882..62a69c5a88 100644
--- a/src/lib/dhcp/tests/option_unittest.cc
+++ b/src/lib/dhcp/tests/option_unittest.cc
@@ -71,6 +71,10 @@ TEST_F(OptionTest, v4_basic) {
// V4 options have type 0...255
EXPECT_THROW(opt.reset(new Option(Option::V4, 256)), OutOfRange);
+
+ // 0 / PAD and 255 / END are no longer forbidden
+ EXPECT_NO_THROW(opt.reset(new Option(Option::V4, 0)));
+ EXPECT_NO_THROW(opt.reset(new Option(Option::V4, 255)));
}
const uint8_t dummyPayload[] =
diff --git a/src/lib/dhcpsrv/tests/dhcp_parsers_unittest.cc b/src/lib/dhcpsrv/tests/dhcp_parsers_unittest.cc
index 1909d4157f..94ba6c0da3 100644
--- a/src/lib/dhcpsrv/tests/dhcp_parsers_unittest.cc
+++ b/src/lib/dhcpsrv/tests/dhcp_parsers_unittest.cc
@@ -833,6 +833,84 @@ TEST_F(ParseConfigTest, basicOptionDataTest) {
cfg.runCfgOptionsTest(family_, config);
}
+/// @brief Check parsing of options with code 0.
+TEST_F(ParseConfigTest, optionDataTest0) {
+
+ // Configuration string.
+ std::string config =
+ "{ \"option-def\": [ {"
+ " \"name\": \"foo\","
+ " \"code\": 0,"
+ " \"type\": \"ipv4-address\","
+ " \"space\": \"isc\""
+ " } ], "
+ " \"option-data\": [ {"
+ " \"name\": \"foo\","
+ " \"space\": \"isc\","
+ " \"code\": 0,"
+ " \"data\": \"192.0.2.0\","
+ " \"csv-format\": true,"
+ " \"always-send\": false"
+ " } ]"
+ "}";
+
+ // Verify that the configuration string parses.
+ int rcode = parseConfiguration(config);
+ ASSERT_EQ(0, rcode);
+
+ // Verify that the option can be retrieved.
+ OptionPtr opt_ptr = getOptionPtr("isc", 0);
+ ASSERT_TRUE(opt_ptr);
+
+ // Verify that the option data is correct.
+ std::string val = "type=00000, len=00004: 192.0.2.0 (ipv4-address)";
+
+ EXPECT_EQ(val, opt_ptr->toText());
+
+ // Check if it can be unparsed.
+ CfgOptionsTest cfg(CfgMgr::instance().getStagingCfg());
+ cfg.runCfgOptionsTest(family_, config);
+}
+
+/// @brief Check parsing of options with code 255.
+TEST_F(ParseConfigTest, optionDataTest255) {
+
+ // Configuration string.
+ std::string config =
+ "{ \"option-def\": [ {"
+ " \"name\": \"foo\","
+ " \"code\": 255,"
+ " \"type\": \"ipv4-address\","
+ " \"space\": \"isc\""
+ " } ], "
+ " \"option-data\": [ {"
+ " \"name\": \"foo\","
+ " \"space\": \"isc\","
+ " \"code\": 255,"
+ " \"data\": \"192.0.2.0\","
+ " \"csv-format\": true,"
+ " \"always-send\": false"
+ " } ]"
+ "}";
+
+ // Verify that the configuration string parses.
+ int rcode = parseConfiguration(config);
+ ASSERT_EQ(0, rcode);
+
+ // Verify that the option can be retrieved.
+ OptionPtr opt_ptr = getOptionPtr("isc", 255);
+ ASSERT_TRUE(opt_ptr);
+
+ // Verify that the option data is correct.
+ std::string val = "type=00255, len=00004: 192.0.2.0 (ipv4-address)";
+
+ EXPECT_EQ(val, opt_ptr->toText());
+
+ // Check if it can be unparsed.
+ CfgOptionsTest cfg(CfgMgr::instance().getStagingCfg());
+ cfg.runCfgOptionsTest(family_, config);
+}
+
/// @brief Check minimal parsing of options.
///
/// Same than basic but without optional parameters set to their default.