Commit 0a1a4fc3 authored by Tomek Mrugalski's avatar Tomek Mrugalski 🛰
Browse files

[5087] Changes after review:

 - split FQDN test into 3 smaller ones
 - added test for truncated option
 - added sanity check for empty/truncated options
 - extended config example to showcase domain-search option
parent f82a806d
...@@ -83,6 +83,14 @@ ...@@ -83,6 +83,14 @@
{ {
"code": 15, "code": 15,
"data": "example.org" "data": "example.org"
},
// Domain search is also a popular option. It tells the client to
// attempt to resolve names within those specificed domains. For
// example, name "foo" would be attempted to be resolved as
// foo.mydomain.example.com and if it fails, then as foo.example.com
{
"name": "domain-search",
"data": "mydomain.example.com, example.com"
}, },
// String options that have a comma in their values need to have // String options that have a comma in their values need to have
// it escaped (i.e. each comma is predeced by two backslashes). // it escaped (i.e. each comma is predeced by two backslashes).
......
...@@ -786,6 +786,9 @@ OptionDefinition::factoryFqdnList(Option::Universe u, ...@@ -786,6 +786,9 @@ OptionDefinition::factoryFqdnList(Option::Universe u,
OptionBufferConstIter end) const { OptionBufferConstIter end) const {
const std::vector<uint8_t> data(begin, end); const std::vector<uint8_t> data(begin, end);
if (data.empty()) {
isc_throw(InvalidOptionValue, "FQDN list option has invalid length of 0");
}
InputBuffer in_buf(static_cast<const void*>(&data[0]), data.size()); InputBuffer in_buf(static_cast<const void*>(&data[0]), data.size());
std::vector<uint8_t> out_buf; std::vector<uint8_t> out_buf;
out_buf.reserve(data.size()); out_buf.reserve(data.size());
......
...@@ -1667,7 +1667,7 @@ TEST_F(LibDhcpTest, getVendorOptionDefByName4) { ...@@ -1667,7 +1667,7 @@ TEST_F(LibDhcpTest, getVendorOptionDefByName4) {
} }
} }
// This test checks handling of compressed FQDN list. // This test checks handling of uncompressed FQDN list.
TEST_F(LibDhcpTest, fqdnList) { TEST_F(LibDhcpTest, fqdnList) {
OptionDefinitionPtr def = LibDHCP::getOptionDef(DHCP4_OPTION_SPACE, OptionDefinitionPtr def = LibDHCP::getOptionDef(DHCP4_OPTION_SPACE,
DHO_DOMAIN_SEARCH); DHO_DOMAIN_SEARCH);
...@@ -1704,6 +1704,15 @@ TEST_F(LibDhcpTest, fqdnList) { ...@@ -1704,6 +1704,15 @@ TEST_F(LibDhcpTest, fqdnList) {
LibDhcpTest::testStdOptionDefs4(DHO_DOMAIN_SEARCH, fqdn_buf.begin(), LibDhcpTest::testStdOptionDefs4(DHO_DOMAIN_SEARCH, fqdn_buf.begin(),
fqdn_buf.end(), typeid(OptionCustom)); fqdn_buf.end(), typeid(OptionCustom));
}
// This test checks handling of compressed FQDN list.
// See RFC3397, section 2 (and 4.1.4 of RFC1035 for the actual
// compression algorithm).
TEST_F(LibDhcpTest, fqdnListCompressed) {
OptionDefinitionPtr def = LibDHCP::getOptionDef(DHCP4_OPTION_SPACE,
DHO_DOMAIN_SEARCH);
ASSERT_TRUE(def);
const uint8_t compressed[] = { const uint8_t compressed[] = {
8, 109, 121, 100, 111, 109, 97, 105, 110, // "mydomain" 8, 109, 121, 100, 111, 109, 97, 105, 110, // "mydomain"
...@@ -1715,19 +1724,29 @@ TEST_F(LibDhcpTest, fqdnList) { ...@@ -1715,19 +1724,29 @@ TEST_F(LibDhcpTest, fqdnList) {
}; };
std::vector<uint8_t> compressed_buf(compressed, std::vector<uint8_t> compressed_buf(compressed,
compressed + sizeof(compressed)); compressed + sizeof(compressed));
OptionPtr option;
ASSERT_NO_THROW(option = def->optionFactory(Option::V4, ASSERT_NO_THROW(option = def->optionFactory(Option::V4,
DHO_DOMAIN_SEARCH, DHO_DOMAIN_SEARCH,
compressed_buf.begin(), compressed_buf.begin(),
compressed_buf.end())); compressed_buf.end()));
ASSERT_TRUE(option); ASSERT_TRUE(option);
names = boost::dynamic_pointer_cast<OptionCustom>(option); OptionCustomPtr names = boost::dynamic_pointer_cast<OptionCustom>(option);
ASSERT_TRUE(names); ASSERT_TRUE(names);
EXPECT_EQ(sizeof(fqdn), names->len() - names->getHeaderLen()); // Why is this failing? It seems the option does not use compression.
EXPECT_EQ(sizeof(compressed), names->len() - names->getHeaderLen());
ASSERT_EQ(3, names->getDataFieldsNum()); ASSERT_EQ(3, names->getDataFieldsNum());
EXPECT_EQ("mydomain.example.com.", names->readFqdn(0)); EXPECT_EQ("mydomain.example.com.", names->readFqdn(0));
EXPECT_EQ("example.com.", names->readFqdn(1)); EXPECT_EQ("example.com.", names->readFqdn(1));
EXPECT_EQ("com.", names->readFqdn(2)); EXPECT_EQ("com.", names->readFqdn(2));
}
// Check that incorrect FQDN list compression is rejected.
// See RFC3397, section 2 (and 4.1.4 of RFC1035 for the actual
// compression algorithm).
TEST_F(LibDhcpTest, fqdnListBad) {
OptionDefinitionPtr def = LibDHCP::getOptionDef(DHCP4_OPTION_SPACE,
DHO_DOMAIN_SEARCH);
ASSERT_TRUE(def);
const uint8_t bad[] = { const uint8_t bad[] = {
8, 109, 121, 100, 111, 109, 97, 105, 110, // "mydomain" 8, 109, 121, 100, 111, 109, 97, 105, 110, // "mydomain"
...@@ -1739,13 +1758,30 @@ TEST_F(LibDhcpTest, fqdnList) { ...@@ -1739,13 +1758,30 @@ TEST_F(LibDhcpTest, fqdnList) {
}; };
std::vector<uint8_t> bad_buf(bad, bad + sizeof(bad)); std::vector<uint8_t> bad_buf(bad, bad + sizeof(bad));
EXPECT_THROW(option = def->optionFactory(Option::V4, OptionPtr option;
EXPECT_THROW(option = def->optionFactory(Option::V4,
DHO_DOMAIN_SEARCH, DHO_DOMAIN_SEARCH,
bad_buf.begin(), bad_buf.begin(),
bad_buf.end()), bad_buf.end()),
InvalidOptionValue); InvalidOptionValue);
} }
// Check that empty (truncated) option is rejected.
TEST_F(LibDhcpTest, fqdnListTrunc) {
OptionDefinitionPtr def = LibDHCP::getOptionDef(DHCP4_OPTION_SPACE,
DHO_DOMAIN_SEARCH);
ASSERT_TRUE(def);
std::vector<uint8_t> empty;
OptionPtr option;
EXPECT_THROW(option = def->optionFactory(Option::V4,
DHO_DOMAIN_SEARCH,
empty.begin(),
empty.end()),
InvalidOptionValue);
}
// tests whether v6 vendor-class option can be parsed properly. // tests whether v6 vendor-class option can be parsed properly.
TEST_F(LibDhcpTest, vendorClass6) { TEST_F(LibDhcpTest, vendorClass6) {
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment