diff options
-rw-r--r-- | src/bin/dhcp4/tests/config_parser_unittest.cc | 2 | ||||
-rw-r--r-- | src/bin/dhcp6/tests/config_parser_unittest.cc | 2 | ||||
-rw-r--r-- | src/lib/dhcp/tests/libdhcp++_unittest.cc | 85 | ||||
-rw-r--r-- | src/lib/dhcp/tests/option_unittest.cc | 4 | ||||
-rw-r--r-- | src/lib/dhcpsrv/tests/dhcp_parsers_unittest.cc | 78 |
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. |