]> git.ipfire.org Git - thirdparty/kea.git/commitdiff
[#939] Adding more unit tests
authorPiotrek Zadroga <piotrek@isc.org>
Wed, 22 Mar 2023 12:07:23 +0000 (13:07 +0100)
committerPiotrek Zadroga <piotrek@isc.org>
Thu, 23 Mar 2023 13:51:23 +0000 (14:51 +0100)
Also removing OutOfRange check from OptionOpaqueDataTuples#unpack(begin, end).
Also updating AUTHORS and the ChangeLog.

AUTHORS
ChangeLog
src/lib/dhcp/option_opaque_data_tuples.cc
src/lib/dhcp/option_opaque_data_tuples.h
src/lib/dhcp/tests/option_opaque_data_tuples_unittest.cc

diff --git a/AUTHORS b/AUTHORS
index b82b030e921f33aba6d13674b55e921b8b0d92ae..5d79917a53c2c39bc8fa6c396d1204748a849198 100644 (file)
--- a/AUTHORS
+++ b/AUTHORS
@@ -31,7 +31,7 @@ Primary developers:
  - Slawek Figiel (documentation)
  - Dan Theisen (documentation, option handling, shell scripts)
  - Marcin Godzina (documentation, release engineering, testing)
- - Piotrek Zadroga (documentation)
+ - Piotrek Zadroga (documentation, options handling)
 
 Former developers who are no longer active:
  - Stephen Morris (Hooks, MySQL)
index b5742af4cec7b19ec0f6669909ddd8e8d0d1cdbb..ed2d36e83d2bdf38cefeedc666c120a0a622bd0a 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,8 @@
+2116.   [func]      piotrek
+    Added support of Secure Zero Touch Provisioning options as per
+    RFC8572. Kea can now handle DHCPv4 Option code #143 and DHCPv6
+    Option code #136.
+
 2115.  [func]          tmark
        Added the parameter, offer-lifetime, to kea-dhcp4.  When
        greater than zero, the server temporarily allocates and
index f70c4356676025898f214697b77249f36d1f2d73..ea8fa7c91a7440d4f3f6d099252b661f29001fab 100644 (file)
@@ -55,10 +55,9 @@ OptionOpaqueDataTuples::pack(isc::util::OutputBuffer& buf, bool check) const {
 void
 OptionOpaqueDataTuples::unpack(OptionBufferConstIter begin,
                                OptionBufferConstIter end) {
-    if (std::distance(begin, end) < getMinimalLength() - getHeaderLen()) {
-        isc_throw(OutOfRange, "parsed data tuples option data truncated to"
-                  " size " << std::distance(begin, end));
-    }
+    // We are skipping typical OutOfRange check for Option#unpack(begin, end),
+    // since empty collection of tuples is also a valid case where
+    // std::distance(begin, end) = 0
 
     // Start reading opaque data.
     size_t offset = 0;
index 99fce83d522784162d7ca26b67bf29d30c4f2f51..8bd93af99d1169d9f050bb0b74c44baba3a36a08 100644 (file)
@@ -149,13 +149,6 @@ private:
     /// @brief length of the field which holds he size of the tuple.
     OpaqueDataTuple::LengthFieldType length_field_type_;
 
-    /// @brief Returns minimal length of the option for the given universe.
-    /// Currently this class is only used for a DHCPv6 option it may be expanded
-    /// for DHCPv4 in the future.
-    uint16_t getMinimalLength() const {
-        return (4);
-    }
-
     /// @brief Collection of opaque data tuples carried by the option.
     TuplesCollection tuples_;
 
index cf2f7bf03645fff575e157ddadde2ad6830ef48f..6a2c1cb814a4632b75c1116683593ee4ae3a5047 100644 (file)
@@ -17,6 +17,16 @@ using namespace isc::util;
 
 namespace {
 
+// This test checks that the DHCPv4 option constructor sets the default
+// properties to the expected values.
+TEST(OptionOpaqueDataTuples, constructor4) {
+    OptionOpaqueDataTuples data_tuple(Option::V4, 200);
+    // Option length is 1 byte for option code + 1 byte for option size
+    EXPECT_EQ(2, data_tuple.len());
+    // There should be no tuples.
+    EXPECT_EQ(0, data_tuple.getTuplesNum());
+}
+
 // This test checks that the DHCPv6 option constructor sets the default
 // properties to the expected values.
 TEST(OptionOpaqueDataTuples, constructor6) {
@@ -98,6 +108,23 @@ TEST(OptionOpaqueDataTuples, setTuple) {
     EXPECT_THROW(data_tuple.setTuple(2, tuple), isc::OutOfRange);
 }
 
+// Check that the returned length of the DHCPv4 option is correct.
+TEST(OptionOpaqueDataTuples, len4) {
+    OptionOpaqueDataTuples data_tuple(Option::V4, 200);
+    ASSERT_EQ(2, data_tuple.len());
+    // Add first tuple.
+    OpaqueDataTuple tuple(OpaqueDataTuple::LENGTH_1_BYTE);
+    tuple = "xyz";
+    ASSERT_NO_THROW(data_tuple.addTuple(tuple));
+    // The total length grows by 1 byte of the length field and 3 bytes
+    // consumed by 'xyz'.
+    EXPECT_EQ(6, data_tuple.len());
+    // Add another tuple and check that the total size gets increased.
+    tuple = "abc";
+    data_tuple.addTuple(tuple);
+    EXPECT_EQ(10, data_tuple.len());
+}
+
 // Check that the returned length of the DHCPv4 option is correct when
 // LTF is passed explicitly in constructor.
 TEST(OptionOpaqueDataTuples, len4_constructor_with_ltf) {
@@ -134,6 +161,71 @@ TEST(OptionOpaqueDataTuples, len6) {
     EXPECT_EQ(14, data_tuple.len());
 }
 
+// Check that the DHCPv4 option is rendered to the buffer in wire format.
+TEST(OptionOpaqueDataTuples, pack4) {
+    OptionOpaqueDataTuples data_tuple(Option::V4, 200);
+    ASSERT_EQ(0, data_tuple.getTuplesNum());
+    // Add tuple.
+    OpaqueDataTuple tuple(OpaqueDataTuple::LENGTH_1_BYTE);
+    tuple = "Hello world";
+    data_tuple.addTuple(tuple);
+    // And add another tuple so as resulting option is a bit more complex.
+    tuple = "foo";
+    data_tuple.addTuple(tuple);
+
+    // Render the data to the buffer.
+    OutputBuffer buf(10);
+    ASSERT_NO_THROW(data_tuple.pack(buf));
+    ASSERT_EQ(18, buf.getLength());
+
+    // Prepare reference data.
+    const uint8_t ref[] = {
+        0xC8, 0x10,                         // option 200, length 16
+        0x0B,                               // tuple length is 11
+        0x48, 0x65, 0x6C, 0x6C, 0x6F, 0x20, // Hello<space>
+        0x77, 0x6F, 0x72, 0x6C, 0x64,       // world
+        0x03,                               // tuple length is 3
+        0x66, 0x6F, 0x6F                    // foo
+    };
+    // Compare the buffer with reference data.
+    EXPECT_EQ(0, memcmp(static_cast<const void*>(ref),
+                        static_cast<const void*>(buf.getData()),
+                        buf.getLength()));
+}
+
+// Check that the DHCPv4 option is rendered to the buffer in wire format,
+// when tuple's length field is coded on 2 octets.
+TEST(OptionOpaqueDataTuples, pack4_with_ltf) {
+    OptionOpaqueDataTuples data_tuple(Option::V4, 143, OpaqueDataTuple::LENGTH_2_BYTES);
+    ASSERT_EQ(0, data_tuple.getTuplesNum());
+    // Add tuple.
+    OpaqueDataTuple tuple(OpaqueDataTuple::LENGTH_2_BYTES);
+    tuple = "Hello world";
+    data_tuple.addTuple(tuple);
+    // And add another tuple so as resulting option is a bit more complex.
+    tuple = "foo";
+    data_tuple.addTuple(tuple);
+
+    // Render the data to the buffer.
+    OutputBuffer buf(10);
+    ASSERT_NO_THROW(data_tuple.pack(buf));
+    ASSERT_EQ(20, buf.getLength());
+
+    // Prepare reference data.
+    const uint8_t ref[] = {
+        0x8F, 0x12,                         // option 143, length 18
+        0x00, 0x0B,                         // tuple length is 11
+        0x48, 0x65, 0x6C, 0x6C, 0x6F, 0x20, // Hello<space>
+        0x77, 0x6F, 0x72, 0x6C, 0x64,       // world
+        0x00, 0x03,                         // tuple length is 3
+        0x66, 0x6F, 0x6F                    // foo
+    };
+    // Compare the buffer with reference data.
+    EXPECT_EQ(0, memcmp(static_cast<const void*>(ref),
+                        static_cast<const void*>(buf.getData()),
+                        buf.getLength()));
+}
+
 // Check that the DHCPv6 option is rendered to the buffer in wire format.
 TEST(OptionOpaqueDataTuples, pack6) {
     OptionOpaqueDataTuples data_tuple(Option::V6, 60);
@@ -166,6 +258,33 @@ TEST(OptionOpaqueDataTuples, pack6) {
                         buf.getLength()));
 }
 
+// This function checks that the DHCPv4 option with two opaque data tuples
+// is parsed correctly.
+TEST(OptionOpaqueDataTuples, unpack4) {
+    // Prepare data to decode.
+    const uint8_t buf_data[] = {
+        0x0B,                               // tuple length is 11
+        0x48, 0x65, 0x6C, 0x6C, 0x6F, 0x20, // Hello<space>
+        0x77, 0x6F, 0x72, 0x6C, 0x64,       // world
+        0x03,                               // tuple length is 3
+        0x66, 0x6F, 0x6F                    // foo
+    };
+    OptionBuffer buf(buf_data, buf_data + sizeof(buf_data));
+
+    OptionOpaqueDataTuplesPtr data_tuple;
+    ASSERT_NO_THROW(
+        data_tuple = OptionOpaqueDataTuplesPtr(
+            new OptionOpaqueDataTuples(Option::V4,
+                                       143,
+                                       buf.begin(),
+                                       buf.end()));
+    );
+    EXPECT_EQ(DHO_V4_SZTP_REDIRECT, data_tuple->getType());
+    ASSERT_EQ(2, data_tuple->getTuplesNum());
+    EXPECT_EQ("Hello world", data_tuple->getTuple(0).getText());
+    EXPECT_EQ("foo", data_tuple->getTuple(1).getText());
+}
+
 // This function checks that the DHCPv4 option with two opaque data tuples
 // is parsed correctly. Tuple's LTF is passed explicitly in constructor.
 TEST(OptionOpaqueDataTuples, unpack4_constructor_with_ltf) {
@@ -220,6 +339,46 @@ TEST(OptionOpaqueDataTuples, unpack6) {
     EXPECT_EQ("foo", data_tuple->getTuple(1).getText());
 }
 
+// This test checks that the DHCPv4 option with opaque data of size 0
+// is correctly parsed.
+TEST(OptionOpaqueDataTuples, unpack4EmptyTuple) {
+    // Prepare data to decode.
+    const uint8_t buf_data[] = {0x00}; // tuple length is 0
+    OptionBuffer buf(buf_data, buf_data + sizeof(buf_data));
+
+    OptionOpaqueDataTuplesPtr data_tuple;
+    ASSERT_NO_THROW(
+        data_tuple = OptionOpaqueDataTuplesPtr(new OptionOpaqueDataTuples(Option::V4,
+                                                                          124,
+                                                                          buf.begin(),
+                                                                          buf.end()));
+    );
+    EXPECT_EQ(DHO_VIVCO_SUBOPTIONS, data_tuple->getType());
+    ASSERT_EQ(1, data_tuple->getTuplesNum());
+    EXPECT_TRUE(data_tuple->getTuple(0).getText().empty());
+}
+
+// This test checks that the DHCPv4 option with opaque data of size 0
+// is correctly parsed. Tuple's LTF is passed explicitly in constructor.
+TEST(OptionOpaqueDataTuples, unpack4EmptyTuple_constructor_with_ltf) {
+    // Prepare data to decode.
+    const uint8_t buf_data[] = {0x00, 0x00}; // tuple length is 0
+    OptionBuffer buf(buf_data, buf_data + sizeof(buf_data));
+
+    OptionOpaqueDataTuplesPtr data_tuple;
+    ASSERT_NO_THROW(
+        data_tuple = OptionOpaqueDataTuplesPtr(
+            new OptionOpaqueDataTuples(Option::V4,
+                                       143,
+                                       buf.begin(),
+                                       buf.end(),
+                                       OpaqueDataTuple::LENGTH_2_BYTES));
+    );
+    EXPECT_EQ(DHO_V4_SZTP_REDIRECT, data_tuple->getType());
+    ASSERT_EQ(1, data_tuple->getTuplesNum());
+    EXPECT_TRUE(data_tuple->getTuple(0).getText().empty());
+}
+
 // This test checks that the DHCPv6 option with opaque data of size 0
 // is correctly parsed.
 TEST(OptionOpaqueDataTuples, unpack6EmptyTuple) {
@@ -239,6 +398,39 @@ TEST(OptionOpaqueDataTuples, unpack6EmptyTuple) {
     EXPECT_TRUE(data_tuple->getTuple(0).getText().empty());
 }
 
+// This test checks that exception is thrown when parsing truncated DHCPv4 option
+TEST(OptionOpaqueDataTuples, unpack4Truncated) {
+    // Prepare data to decode.
+    const uint8_t buf_data[] = {
+        0x0B,                               // tuple length is 11
+        0x48, 0x65, 0x6C, 0x6C, 0x6F, 0x20, // Hello<space>
+        0x77, 0x6F, 0x72, 0x6C              // worl (truncated d!)
+    };
+    OptionBuffer buf(buf_data, buf_data + sizeof(buf_data));
+
+    EXPECT_THROW(OptionOpaqueDataTuples (Option::V4, 200, buf.begin(), buf.end()),
+                 isc::dhcp::OpaqueDataTupleError);
+}
+
+// This test checks that exception is thrown when parsing truncated DHCPv4 option,
+// when tuple's length field is coded on 2 octets.
+TEST(OptionOpaqueDataTuples, unpack4Truncated_with_ltf) {
+    // Prepare data to decode.
+    const uint8_t buf_data[] = {
+        0x00, 0x0B,                         // tuple length is 11
+        0x48, 0x65, 0x6C, 0x6C, 0x6F, 0x20, // Hello<space>
+        0x77, 0x6F, 0x72, 0x6C              // worl (truncated d!)
+    };
+    OptionBuffer buf(buf_data, buf_data + sizeof(buf_data));
+
+    EXPECT_THROW(OptionOpaqueDataTuples (Option::V4,
+                                        143,
+                                        buf.begin(),
+                                        buf.end(),
+                                        OpaqueDataTuple::LENGTH_2_BYTES),
+                 isc::dhcp::OpaqueDataTupleError);
+}
+
 // This test checks that exception is thrown when parsing truncated DHCPv6
 // bootfile-param option
 TEST(OptionOpaqueDataTuples, unpack6Truncated) {
@@ -254,6 +446,27 @@ TEST(OptionOpaqueDataTuples, unpack6Truncated) {
                  isc::dhcp::OpaqueDataTupleError);
 }
 
+// This test checks that the DHCPv4 option containing no opaque
+// data is parsed correctly.
+TEST(OptionOpaqueDataTuples, unpack4NoTuple) {
+    // Prepare data to decode.
+    const uint8_t buf_data[] = {
+    };
+    OptionBuffer buf(buf_data, buf_data + sizeof(buf_data));
+
+    OptionOpaqueDataTuplesPtr data_tuple;
+    ASSERT_NO_THROW(
+        data_tuple = OptionOpaqueDataTuplesPtr(
+            new OptionOpaqueDataTuples(Option::V4,
+                                       143,
+                                       buf.begin(),
+                                       buf.end(),
+                                       OpaqueDataTuple::LENGTH_2_BYTES));
+    );
+    EXPECT_EQ(DHO_V4_SZTP_REDIRECT, data_tuple->getType());
+    EXPECT_EQ(0, data_tuple->getTuplesNum());
+}
+
 // This test checks that the DHCPv6 bootfile-param option containing no opaque
 // data is parsed correctly.
 TEST(OptionOpaqueDataTuples, unpack6NoTuple) {
@@ -273,6 +486,30 @@ TEST(OptionOpaqueDataTuples, unpack6NoTuple) {
     EXPECT_EQ(0, data_tuple->getTuplesNum());
 }
 
+// Verifies correctness of the text representation of the DHCPv4 option.
+TEST(OptionOpaqueDataTuples, toText4) {
+    OptionOpaqueDataTuples data_tuple(Option::V4, 143, OpaqueDataTuple::LENGTH_2_BYTES);
+    ASSERT_EQ(0, data_tuple.getTuplesNum());
+    // Lets add a tuple
+    OpaqueDataTuple tuple(OpaqueDataTuple::LENGTH_2_BYTES);
+    tuple = "Hello world";
+    data_tuple.addTuple(tuple);
+    // And add another tuple so as resulting option is a bit more complex.
+    tuple = "foo";
+    data_tuple.addTuple(tuple);
+    // Check that the text representation of the option is as expected.
+    EXPECT_EQ("type=143, len=18,"
+              " data-len0=11, data0='Hello world',"
+              " data-len1=3, data1='foo'",
+              data_tuple.toText());
+
+    // Check that indentation works.
+    EXPECT_EQ("  type=143, len=18,"
+              " data-len0=11, data0='Hello world',"
+              " data-len1=3, data1='foo'",
+              data_tuple.toText(2));
+}
+
 // Verifies correctness of the text representation of the DHCPv6 option.
 TEST(OptionOpaqueDataTuples, toText6) {
     OptionOpaqueDataTuples data_tuple(Option::V6, 60);