Parcourir la source

[4093] Implemented Option::toHexString method.

Marcin Siodelski il y a 9 ans
Parent
commit
0d6a66ecfb
3 fichiers modifiés avec 91 ajouts et 0 suppressions
  1. 35 0
      src/lib/dhcp/option.cc
  2. 8 0
      src/lib/dhcp/option.h
  3. 48 0
      src/lib/dhcp/tests/option_unittest.cc

+ 35 - 0
src/lib/dhcp/option.cc

@@ -16,6 +16,7 @@
 #include <dhcp/libdhcp++.h>
 #include <dhcp/option.h>
 #include <exceptions/exceptions.h>
+#include <util/encode/hex.h>
 #include <util/io_utilities.h>
 
 #include <iomanip>
@@ -219,6 +220,40 @@ Option::toString() {
     return (toText(0));
 }
 
+std::string
+Option::toHexString(const bool include_header) {
+    OutputBuffer buf(len());
+    try {
+        // If the option is too long, exception will be thrown. We allow
+        // for this exception to propagate to not mask this error.
+        pack(buf);
+
+    } catch (const std::exception &ex) {
+        isc_throw(OutOfRange, "unable to obtain hexadecimal representation"
+                  " of option " << getType() << ": " << ex.what());
+    }
+    const uint8_t* option_data = static_cast<const uint8_t*>(buf.getData());
+    std::vector<uint8_t> option_vec;
+
+    // Exclude header.
+    if (!include_header) {
+        if (buf.getLength() > getHeaderLen()) {
+            option_vec.assign(option_data + getHeaderLen(),
+                              option_data + buf.getLength());
+        }
+
+    } else {
+        option_vec.assign(option_data, option_data + buf.getLength());
+    }
+
+    // Return hexadecimal representation prepended with 0x or empty string
+    // if option has no payload and the header fields are excluded.
+    std::ostringstream s;
+    if (!option_vec.empty()) {
+        s << "0x" << encode::encodeHex(option_vec);
+    }
+    return (s.str());
+}
 
 std::string
 Option::headerToText(const int indent, const std::string& type_name) {

+ 8 - 0
src/lib/dhcp/option.h

@@ -216,6 +216,14 @@ public:
     /// @return string that represents the value of the option.
     virtual std::string toString();
 
+    /// @brief Returns string containing hexadecimal representation of option.
+    ///
+    /// @param include_header Boolean flag which indicates if the output should
+    /// also contain header fields. The default is that it shouldn't.
+    ///
+    /// @return String containing hexadecimal representation of the option.
+    virtual std::string toHexString(const bool include_header = false);
+
     /// Returns option type (0-255 for DHCPv4, 0-65535 for DHCPv6)
     ///
     /// @return option type

+ 48 - 0
src/lib/dhcp/tests/option_unittest.cc

@@ -236,6 +236,38 @@ TEST_F(OptionTest, v4_toText) {
     EXPECT_EQ("type=253, len=003: 00:0f:ff", opt.toText());
 }
 
+// Test converting option to the hexadecimal representation.
+TEST_F(OptionTest, v4_toHexString) {
+    std::vector<uint8_t> payload;
+    for (unsigned int i = 0; i < 16; ++i) {
+        payload.push_back(static_cast<uint8_t>(i));
+    }
+    Option opt(Option::V4, 122, payload);
+    EXPECT_EQ("0x000102030405060708090A0B0C0D0E0F", opt.toHexString());
+    EXPECT_EQ("0x7A10000102030405060708090A0B0C0D0E0F",
+              opt.toHexString(true));
+
+    // Test empty option.
+    Option opt_empty(Option::V4, 65, std::vector<uint8_t>());
+    EXPECT_TRUE(opt_empty.toHexString().empty());
+    EXPECT_EQ("0x4100", opt_empty.toHexString(true));
+
+    // Test too long option. We can't simply create such option by
+    // providing a long payload, because class constructor would not
+    // accept it. Instead we'll add two long sub options after we
+    // create an option instance.
+    Option opt_too_long(Option::V4, 33);
+    // Both suboptions have payloads of 150 bytes.
+    std::vector<uint8_t> long_payload(150, 1);
+    OptionPtr sub1(new Option(Option::V4, 100, long_payload));
+    OptionPtr sub2(new Option(Option::V4, 101, long_payload));
+    opt_too_long.addOption(sub1);
+    opt_too_long.addOption(sub2);
+
+    // The toHexString() should throw exception.
+    EXPECT_THROW(opt_too_long.toHexString(), isc::OutOfRange);
+}
+
 // Tests simple constructor
 TEST_F(OptionTest, v6_basic) {
 
@@ -446,6 +478,22 @@ TEST_F(OptionTest, v6_toText) {
     EXPECT_EQ("type=00258, len=00003: 00:0f:ff", opt->toText());
 }
 
+// Test converting option to the hexadecimal representation.
+TEST_F(OptionTest, v6_toHexString) {
+    std::vector<uint8_t> payload;
+    for (unsigned int i = 0; i < 16; ++i) {
+        payload.push_back(static_cast<uint8_t>(i));
+    }
+    Option opt(Option::V6, 12202, payload);
+    EXPECT_EQ("0x000102030405060708090A0B0C0D0E0F", opt.toHexString());
+    EXPECT_EQ("0x2FAA0010000102030405060708090A0B0C0D0E0F",
+              opt.toHexString(true));
+
+    // Test empty option.
+    Option opt_empty(Option::V6, 65000, std::vector<uint8_t>());
+    EXPECT_TRUE(opt_empty.toHexString().empty());
+    EXPECT_EQ("0xFDE80000", opt_empty.toHexString(true));
+}
 
 TEST_F(OptionTest, getUintX) {