BIND 10 trac1956, updated. ff1617fd13a786d41439b7d653e798352e3789b7 [1956] PerfPkt6 class code improvements.

BIND 10 source code commits bind10-changes at lists.isc.org
Thu May 31 16:39:40 UTC 2012


The branch, trac1956 has been updated
       via  ff1617fd13a786d41439b7d653e798352e3789b7 (commit)
      from  9cd5b8d800ba00b9e0d3d07609853e1221550a2f (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
commit ff1617fd13a786d41439b7d653e798352e3789b7
Author: Marcin Siodelski <marcin at isc.org>
Date:   Thu May 31 18:39:11 2012 +0200

    [1956] PerfPkt6 class code improvements.
    
    Improved error checks, comments, additional unit tests added.

-----------------------------------------------------------------------

Summary of changes:
 tests/tools/perfdhcp/Makefile.am                 |    1 +
 tests/tools/perfdhcp/localized_option.h          |   26 ++-
 tests/tools/perfdhcp/perf_pkt6.cc                |  127 ++++++++----
 tests/tools/perfdhcp/perf_pkt6.h                 |   79 ++++++--
 tests/tools/perfdhcp/tests/perf_pkt6_unittest.cc |  223 +++++++++++++++++++---
 5 files changed, 367 insertions(+), 89 deletions(-)

-----------------------------------------------------------------------
diff --git a/tests/tools/perfdhcp/Makefile.am b/tests/tools/perfdhcp/Makefile.am
index c1fa582..31a75e1 100644
--- a/tests/tools/perfdhcp/Makefile.am
+++ b/tests/tools/perfdhcp/Makefile.am
@@ -25,6 +25,7 @@ endif
 
 pkglibexec_PROGRAMS  = perfdhcp
 perfdhcp_SOURCES  = perfdhcp.cc
+perfdhcp_SOURCES += localized_option.h
 perfdhcp_SOURCES += command_options.cc command_options.h
 perfdhcp_SOURCES += perf_pkt6.cc perf_pkt6.h
 
diff --git a/tests/tools/perfdhcp/localized_option.h b/tests/tools/perfdhcp/localized_option.h
index a69c560..19d74cd 100644
--- a/tests/tools/perfdhcp/localized_option.h
+++ b/tests/tools/perfdhcp/localized_option.h
@@ -22,13 +22,13 @@ namespace perfdhcp {
 
 /// \brief DHCP option at specific offset
 ///
-/// This class represents DHCP option at specified
+/// This class represents DHCP option with data placed at specified
 /// offset in DHCP message.
 /// Objects of this type are intended to be used when DHCP packets
 /// are created from templates (e.g. read from template file).
-/// Such packets have number of that have to be replaced before
-/// sending: e.g. DUID can be randomized. If option of this type
-/// is added to \ref PerfPkt6 options collection,
+/// Such packets have number of options with contents that have to be
+/// replaced before sending: e.g. DUID can be randomized.
+/// If option of this type is added to \ref PerfPkt6 options collection,
 /// \ref perfdhcp::PerfPkt6 will call \ref getOffset on this object
 /// to retrieve user-defined option position and replace contents of
 /// the output buffer at this offset before packet is sent to the server.
@@ -47,7 +47,9 @@ public:
     /// \param u specifies universe (V4 or V6)
     /// \param type option type (0-255 for V4 and 0-65535 for V6)
     /// \param data content of the option
-    LocalizedOption(dhcp::Option::Universe u, uint16_t type, const dhcp::OptionBuffer& data) :
+    LocalizedOption(dhcp::Option::Universe u,
+                    uint16_t type,
+                    const dhcp::OptionBuffer& data) :
         dhcp::Option(u, type, data),
         offset_(0) {
     }
@@ -59,7 +61,9 @@ public:
     /// \param type option type (0-255 for V4 and 0-65535 for V6)
     /// \param data content of the option
     /// \param offset location of option in a packet (zero is default)
-    LocalizedOption(dhcp::Option::Universe u, uint16_t type, const dhcp::OptionBuffer& data,
+    LocalizedOption(dhcp::Option::Universe u,
+                    uint16_t type,
+                    const dhcp::OptionBuffer& data,
                     const size_t offset) :
         dhcp::Option(u, type, data),
         offset_(offset) {
@@ -75,14 +79,16 @@ public:
     /// \param first iterator to the first element that should be copied
     /// \param last iterator to the next element after the last one
     ///        to be copied.
-    LocalizedOption(dhcp::Option::Universe u, uint16_t type, dhcp::OptionBufferConstIter first,
+    LocalizedOption(dhcp::Option::Universe u,
+                    uint16_t type,
+                    dhcp::OptionBufferConstIter first,
                     dhcp::OptionBufferConstIter last) :
         dhcp::Option(u, type, first, last),
         offset_(0) {
     }
 
 
-    /// \brief Constructor, used to create positioned option from buffer iterators
+    /// \brief Constructor, used to create option from buffer iterators
     ///
     /// This contructor is similar to the previous one, but it does not take
     /// the whole vector<uint8_t>, but rather subset of it.
@@ -93,7 +99,9 @@ public:
     /// \param last iterator to the next element after the last one
     ///        to be copied.
     /// \param offset offset of option in a packet (zero is default)
-    LocalizedOption(dhcp::Option::Universe u, uint16_t type, dhcp::OptionBufferConstIter first,
+    LocalizedOption(dhcp::Option::Universe u,
+                    uint16_t type,
+                    dhcp::OptionBufferConstIter first,
                     dhcp::OptionBufferConstIter last, const size_t offset) :
         dhcp::Option(u, type, first, last),
         offset_(offset) {
diff --git a/tests/tools/perfdhcp/perf_pkt6.cc b/tests/tools/perfdhcp/perf_pkt6.cc
index 1f1aefd..de3983c 100644
--- a/tests/tools/perfdhcp/perf_pkt6.cc
+++ b/tests/tools/perfdhcp/perf_pkt6.cc
@@ -21,31 +21,62 @@
 
 using namespace std;
 using namespace isc;
+using namespace dhcp;
 
 namespace isc {
 namespace perfdhcp {
 
-PerfPkt6::PerfPkt6(const uint8_t* buf, uint32_t len, size_t transid_offset) :
-    Pkt6(buf, len, dhcp::Pkt6::UDP),
-    transid_offset_(transid_offset) {
+PerfPkt6::PerfPkt6(const uint8_t* buf, uint32_t len,
+                   uint32_t transid, const Offset& transid_offset) :
+    Pkt6(buf, len, Pkt6::UDP),
+    transid_offset_(transid_offset.get()) {
+    transid_ = transid;
+}
 
-    // Let's reset timestamp of the packet
-    memset(static_cast<void*>(&time_stamp_), 0, sizeof(time_stamp_));
+PerfPkt6::PerfPkt6(const uint8_t* buf,
+                   uint32_t len,
+                   const Offset&
+                   transid_offset) :
+    Pkt6(buf, len, Pkt6::UDP),
+    transid_offset_(transid_offset.get()) {
 }
 
 bool
 PerfPkt6::rawPack() {
+    // Always override the packet if function is called.
+    bufferOut_.clear();
+    // Write whole buffer to output buffer.
+    bufferOut_.writeData(&data_[0], data_.size());
+
+    if ((transid_offset_ + 4 > data_.size()) ||
+        (transid_offset_ == 0)) {
+        cout << "Failed to build packet: provided transaction id offset: "
+             << transid_offset_ <<  " is out of bounds (expected 1.."
+             << data_.size()-1 << ")." << endl;
+        return (false);
+    }
+
+    // Seek to the transaction id position in output buffer.
+    bufferOut_.clear();
+    bufferOut_.skip(transid_offset_);
+
     try {
-        // Always override the packet if function is called.
-        bufferOut_.clear();
-        // Write whole buffer to output buffer.
-        bufferOut_.writeData(&data_[0], data_.size());
-        // We already have packet template stored in out buffer
+        // Write 3 octets of transaction id
+        bufferOut_.writeUint8(transid_ >> 16 & 0xFF);
+        bufferOut_.writeUint8(transid_ >> 8 & 0xFF);
+        bufferOut_.writeUint8(transid_ & 0xFF);
+
+        // Buffer pointer is at the end of transaction id.
+        // We have to seek to the end of buffer so as data don't
+        // get truncated.
+        bufferOut_.skip(data_.size() - bufferOut_.getLength());
+
+        // We already have packet template stored in output buffer
         // but still some options have to be updated if client
         // specified them along with their offsets in the buffer.
         rawPackOptions();
-    } catch (isc::Unexpected& e) {
-        cout << "Failed to build packet: " << e.what() << endl;
+    } catch (isc::BadValue& e) {
+        cout << "Building packet failed: " << e.what() << endl;
         return (false);
     }
     return (true);
@@ -53,6 +84,15 @@ PerfPkt6::rawPack() {
 
 bool
 PerfPkt6::rawUnpack() {
+    // Validate transaction id offset.
+    if ((transid_offset_ + 4 > data_.size()) ||
+        (transid_offset_ == 0)) {
+        cout << "Failed to parse packet: provided transaction id offset: "
+             << transid_offset_ <<  " is out of bounds (expected 1.."
+             << data_.size()-1 << ")." << endl;
+        return (false);
+    }
+
     // Read transaction id from the packet at the given offset.
     transid_ = ( (data_[transid_offset_]) << 16 ) +
         ((data_[transid_offset_ + 1]) << 8) + (data_[transid_offset_ + 2]);
@@ -62,7 +102,7 @@ PerfPkt6::rawUnpack() {
     msg_type_ = data_[0];
     try {
         rawUnpackOptions();
-    } catch (isc::Unexpected& e) {
+    } catch (isc::BadValue& e) {
         cout << "Packet parsing failed: " << e.what() << endl;
         return (false);
     }
@@ -73,66 +113,77 @@ PerfPkt6::rawUnpack() {
 void
 PerfPkt6::rawPackOptions() {
     try {
-        // If there are any options on the list we will use provided options offsets
-        // to override them in the output buffer with new contents.
-        for (dhcp::Option::OptionCollection::const_iterator it = options_.begin();
+        // If there are any options on the list, we will use provided
+        // options offsets to override them in the output buffer
+        // with new contents.
+        for (Option::OptionCollection::const_iterator it = options_.begin();
              it != options_.end(); ++it) {
             // Get options with their position (offset).
-            boost::shared_ptr<LocalizedOption> option = boost::dynamic_pointer_cast<LocalizedOption>(it->second);
-            uint32_t position = option->getOffset();
-            if (position > 0) {
-                bufferOut_.clear();
-                bufferOut_.skip(position);
+            boost::shared_ptr<LocalizedOption> option =
+                boost::dynamic_pointer_cast<LocalizedOption>(it->second);
+            uint32_t offset = option->getOffset();
+            if ((offset == 0) ||
+                (offset + option->len() > data_.size())) {
+                isc_throw(isc::BadValue,
+                          "option offset for option: " << option->getType()
+                          << " is out of bounds (expected 1.."
+                          << data_.size() - option->len() << ")");
             }
+            bufferOut_.clear();
+            bufferOut_.skip(offset);
+
             // Replace existing option with new value.
             option->pack(bufferOut_);
         }
-        // Seek to the end of the buffer to make sure size is correct.
+        // Seek to the end of the buffer to make sure its size is correct.
         bufferOut_.skip(data_.size() - bufferOut_.getLength());
     }
     catch (const Exception&) {
-        isc_throw(isc::Unexpected, "Failed to build packet (Option build failed");
+        isc_throw(isc::BadValue, "failed to pack options into buffer.");
     }
 }
 
 void
 PerfPkt6::rawUnpackOptions() {
-    for (dhcp::Option::OptionCollection::const_iterator it = options_.begin();
+    for (Option::OptionCollection::const_iterator it = options_.begin();
          it != options_.end(); ++it) {
 
-        LocalizedOptionPtr option = boost::dynamic_pointer_cast<LocalizedOption>(it->second);
+        LocalizedOptionPtr option =
+            boost::dynamic_pointer_cast<LocalizedOption>(it->second);
         size_t opt_pos = option->getOffset();
-
         if (opt_pos == 0) {
-            isc_throw(isc::BadValue, "Failed to unpack packet from raw buffer "
+            isc_throw(isc::BadValue, "failed to unpack packet from raw buffer "
                       "(Option position not specified)");
         } else if (opt_pos + 4 > data_.size()) {
-            isc_throw(isc::BadValue, "Failed to unpack options from from raw buffer "
+            isc_throw(isc::BadValue,
+                      "failed to unpack options from from raw buffer "
                       "(Option position out of bounds)");
         }
 
         size_t offset = opt_pos;
+
+        // Get option type from first two octets.
         uint16_t opt_type = data_[offset] * 256 + data_[offset + 1];
         if (opt_type != option->getType()) {
             isc_throw(isc::BadValue,
-                      "Failed to unpack option from raw buffer (Option type mismatch)");
+                      "failed to unpack option from raw buffer "
+                      "(option type mismatch)");
         }
+
+        // Get length from next two octets.
         offset += 2;
         uint16_t opt_len = data_[offset] * 256 + data_[offset + 1];
-        offset += 2;
 
         if (offset + opt_len > data_.size()) {
             isc_throw(isc::BadValue,
-                      "Failed to unpack option from raw buffer (Option truncated)");
+                      "failed to unpack option from raw buffer "
+                      "(option truncated)");
         }
-        option->setData(data_.begin() + offset, data_.begin() + offset + opt_len);
-    }
-}
 
-void
-PerfPkt6::updateTimestamp() {
-    if (clock_gettime(CLOCK_REALTIME, &time_stamp_) < 0) {
-        isc_throw(isc::Unexpected, "Failed to get timestamp for packet");
+        // Seek to actual option data and replace it.
+        offset += 2;
+        option->setData(data_.begin() + offset,
+                        data_.begin() + offset + opt_len);
     }
 }
 
diff --git a/tests/tools/perfdhcp/perf_pkt6.h b/tests/tools/perfdhcp/perf_pkt6.h
index b98044c..590fb9e 100644
--- a/tests/tools/perfdhcp/perf_pkt6.h
+++ b/tests/tools/perfdhcp/perf_pkt6.h
@@ -52,10 +52,63 @@ namespace perfdhcp {
 ///
 class PerfPkt6 : public dhcp::Pkt6 {
 public:
+
+    /// \brief Represents offset value.
+    ///
+    /// This class represent offsets for DHCP message fields
+    /// like transaction id. Constructors of PerfPkt6 take
+    /// number of arguments of integer type so it is easy to
+    /// mess up arguments of constructors and for example
+    /// swap transaction id with its offset.
+    /// Use of this class implies that client class has to
+    /// explicitely use constructor of this class to pass
+    /// offset value. This should prevent mistakes and save some
+    /// time on debugging.
+    class Offset {
+    public:
+        /// \brief Default constructor
+        explicit Offset() :
+            offset_(1) { };
+
+        /// \brief Constructor
+        ///
+        /// \param offset offset value
+        explicit Offset(size_t offset) :
+            offset_(offset) { };
+
+        /// \brief Returns offset value.
+        ///
+        /// \return offset value.
+        size_t get() const { return offset_; };
+    private:
+        size_t offset_;    ///< offset value
+    };
+
     /// Localized option pointer type.
     typedef boost::shared_ptr<LocalizedOption> LocalizedOptionPtr;
 
-    /// Constructor, used in message transmission
+    /// \brief Constructor, used for outgoing DHCP messages.
+    ///
+    /// Creates new DHCPv6 message using provided buffer.
+    /// Transaction id and its offset are specified through this
+    /// constructor so as they are stored in outgoing message
+    /// when client class calls \ref PerfPkt6::rawPack.
+    ///
+    /// \note This constructor should be used only for outgoing
+    /// messages that are created from raw buffer (e.g. read from
+    /// template files).
+    ///
+    /// \param buf buffer holiding contents of the message (this can
+    /// be directly read from template file).
+    /// \param len length of the data in the buffer.
+    /// \param transid transaction id to be stored in outgoing message.
+    /// \param transid_offset transaction id offset in outgoing message.
+    PerfPkt6(const uint8_t* buf,
+             uint32_t len,
+             uint32_t transid,
+             const Offset& transid_offset);
+
+    /// Constructor, used for incoming DHCP messages.
     ///
     /// Creates new DHCPv6 message using provided buffer. New object
     /// will keep copy of contents of provided buffer. If buffer contains
@@ -64,33 +117,28 @@ public:
     /// offsets has to be provided - see
     /// \ref isc::perfdhcp::LocalizedOption for details.
     ///
-    /// Transaction id is not considered DHCP option so
-    /// we pass it to constructor as extra argument. This is
-    /// required if transaction id offset differs from the
-    /// default one for DHCPv6 messages (ocets 2-4).
+    /// Transaction id offset point to location of raw data where
+    /// transaction id field is stored. The transaction id will
+    /// be read from this location when PerfPkt6::rawUnpack is
+    /// called. The transid_ class member will be updated accordingly.
     ///
     /// \note use this constructor only in case you want to create
-    /// DHCPv6 message (incoming or outgoing) from the raw buffer
+    /// incoming DHCPv6 object from the raw buffer
     /// and you know options offsets. Options offsets are
     /// specified from perfdhcp command line by the user.
     ///
-    /// \param buf pointer to a buffer of received packet content
-    /// \param len size of buffer of packet content
-    /// \param xid_off transaction id offset in a packet
+    /// \param buf pointer to a buffer of received packet content.
+    /// \param len size of buffer of packet content.
+    /// \param transid_offset transaction id offset in a message.
     PerfPkt6(const uint8_t* buf,
              uint32_t len,
-             size_t transid_offset_);
+             const Offset& transid_offset);
 
     /// \brief Returns transaction id offset in packet buffer
     ///
     /// return transaction id offset in packet buffer
     size_t getTransIdOffset() const { return transid_offset_; };
 
-    /// \brief Returns current packet timestamp
-    ///
-    /// \return current packet timestamp
-    timespec getTimestamp() const { return time_stamp_; }
-
     /// \brief Prepares on-wire format from raw buffer
     ///
     /// The method copies user buffer to output buffer and
@@ -154,7 +202,6 @@ private:
     void rawUnpackOptions();
 
     size_t transid_offset_;      ///< transaction id offset
-    timespec time_stamp_;        ///< time stamp of last pack or unpack
 
 };
 
diff --git a/tests/tools/perfdhcp/tests/perf_pkt6_unittest.cc b/tests/tools/perfdhcp/tests/perf_pkt6_unittest.cc
index 0acda00..8a23a51 100644
--- a/tests/tools/perfdhcp/tests/perf_pkt6_unittest.cc
+++ b/tests/tools/perfdhcp/tests/perf_pkt6_unittest.cc
@@ -33,20 +33,22 @@ using namespace isc::perfdhcp;
 typedef PerfPkt6::LocalizedOptionPtr LocalizedOptionPtr;
 
 namespace {
+
 class PerfPkt6Test : public ::testing::Test {
 public:
     PerfPkt6Test() {
     }
 
-    /// @brief returns captured actual SOLICIT packet
+    /// \brief Returns captured SOLICIT packet.
     ///
     /// Captured SOLICIT packet with transid=0x3d79fb and options: client-id,
     /// in_na, dns-server, elapsed-time, option-request
-    /// This code was autogenerated (see src/bin/dhcp6/tests/iface_mgr_unittest.c),
+    /// This code was autogenerated
+    /// (see src/bin/dhcp6/tests/iface_mgr_unittest.c),
     /// but we spent some time to make is less ugly than it used to be.
     ///
-    /// @return pointer to Pkt6 that represents received SOLICIT
-    PerfPkt6* capture1() {
+    /// \return pointer to Pkt6 that represents received SOLICIT
+    PerfPkt6* capture() {
         uint8_t data[98];
         data[0]  = 1;
         data[1]  = 1;       data[2]  = 2;     data[3] = 3;      data[4]  = 0;
@@ -75,40 +77,86 @@ public:
         data[93] = 6;       data[94] = 0;     data[95] = 2;     data[96] = 0;
         data[97] = 23;
 
-        PerfPkt6* pkt = new PerfPkt6(data, sizeof(data), 0);
+        PerfPkt6* pkt = new PerfPkt6(data, sizeof(data),
+                                     0x1, PerfPkt6::Offset());
+
+        return (pkt);
+    }
+
+    /// \brief Returns truncated SOLICIT packet.
+    ///
+    /// Returns truncated SOLICIT packet which will be used for
+    /// negative tests: e.g. pack options out of packet.
+    ///
+    /// \return pointer to Pkt6 that represents truncated SOLICIT
+    PerfPkt6* captureTruncated() {
+        uint8_t data[17];
+        data[0]  = 1;
+        data[1]  = 1;       data[2]  = 2;     data[3] = 3;      data[4]  = 0;
+        data[5]  = 1;       data[6]  = 0;     data[7] = 14;     data[8]  = 0;
+        data[9]  = 1;       data[10] = 0;     data[11] = 1;     data[12] = 21;
+        data[13] = 158;     data[14] = 60;    data[15] = 22;    data[16] = 0;
+
+        PerfPkt6* pkt = new PerfPkt6(data, sizeof(data),
+                                     0x1, PerfPkt6::Offset());
 
         return (pkt);
     }
 
+
 };
 
 TEST_F(PerfPkt6Test, Constructor) {
+    // Data to be used to create packet.
     uint8_t data[] = { 0, 1, 2, 3, 4, 5 };
-    timespec zero_t_spec;
-    memset(&zero_t_spec, 0, sizeof(zero_t_spec));
 
-    boost::scoped_ptr<PerfPkt6> pkt1(new PerfPkt6(data, sizeof(data), 1));
-    timespec packet_t_spec = pkt1->getTimestamp();
+    // Test constructors of Offset class.
+    PerfPkt6::Offset of1(0);
+    EXPECT_EQ(0, of1.get());
+
+    PerfPkt6::Offset of2;
+    EXPECT_EQ(1, of2.get());
 
+    PerfPkt6::Offset of3(10);
+    EXPECT_EQ(10, of3.get());
+
+    // Test constructor to be used for incoming messages.
+    // Use default (1) offset value and don't specify transaction id.
+    boost::scoped_ptr<PerfPkt6> pkt1(new PerfPkt6(data, sizeof(data),
+                                                  PerfPkt6::Offset()));
     EXPECT_EQ(6, pkt1->getData().size());
-    EXPECT_EQ(0, memcmp( &pkt1->getData()[0], data, sizeof(data)));
+    EXPECT_EQ(0, memcmp(&pkt1->getData()[0], data, sizeof(data)));
     EXPECT_EQ(1, pkt1->getTransIdOffset());
-    EXPECT_EQ(0, memcmp(&packet_t_spec, &zero_t_spec, sizeof(zero_t_spec)));
+
+    // Test constructor to be used for outgoing messages.
+    // Use non-zero offset and specify transaction id.
+    boost::scoped_ptr<PerfPkt6> pkt2(new PerfPkt6(data, sizeof(data), 0x010203,
+                                                  PerfPkt6::Offset(10)));
+    EXPECT_EQ(6, pkt2->getData().size());
+    EXPECT_EQ(0, memcmp(&pkt2->getData()[0], data, sizeof(data)));
+    EXPECT_EQ(0x010203, pkt2->getTransid());
+    EXPECT_EQ(10, pkt2->getTransIdOffset());
 }
 
 TEST_F(PerfPkt6Test, RawPackUnpack) {
     // Create first packet.
-    boost::scoped_ptr<PerfPkt6> pkt1(capture1());
+    boost::scoped_ptr<PerfPkt6> pkt1(capture());
 
     // Create some input buffers to initialize options.
     uint8_t buf_elapsed_time[] = { 1, 1 };
     uint8_t buf_duid[14] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14 };
 
     // Create options.
-    dhcp::OptionBuffer vec_elapsed_time(buf_elapsed_time, buf_elapsed_time + 2);
-    dhcp::OptionBuffer vec_duid(buf_duid, buf_duid + 14);
-    LocalizedOptionPtr pkt1_elapsed_time(new LocalizedOption(Option::V6, 8, vec_elapsed_time, 86));
-    LocalizedOptionPtr pkt1_duid(new LocalizedOption(Option::V6, D6O_CLIENTID, vec_duid, 4));
+    OptionBuffer vec_elapsed_time(buf_elapsed_time, buf_elapsed_time + 2);
+    OptionBuffer vec_duid(buf_duid, buf_duid + 14);
+    LocalizedOptionPtr pkt1_elapsed_time(new LocalizedOption(Option::V6,
+                                                             D6O_ELAPSED_TIME,
+                                                             vec_elapsed_time,
+                                                             86));
+    LocalizedOptionPtr pkt1_duid(new LocalizedOption(Option::V6,
+                                                     D6O_CLIENTID,
+                                                     vec_duid,
+                                                     4));
 
     // Add option to packet and create on-wire format from added options.
     // Contents of options will override contents of packet buffer.
@@ -120,17 +168,26 @@ TEST_F(PerfPkt6Test, RawPackUnpack) {
     vec_elapsed_time.clear();
     vec_duid.clear();
 
-    // Get output buffer from packet 1 to create new packet 
+    // Get output buffer from packet 1 to create new packet
     // that will be later validated.
-    isc::util::OutputBuffer pkt1_output = pkt1->getBuffer();
+    util::OutputBuffer pkt1_output = pkt1->getBuffer();
     ASSERT_EQ(pkt1_output.getLength(), pkt1->getData().size());
-    boost::scoped_ptr<PerfPkt6> pkt2(new PerfPkt6(static_cast<const uint8_t*>(pkt1_output.getData()), 
-                                                  pkt1_output.getLength(), 1));
+    const uint8_t* pkt1_output_data = static_cast<const uint8_t*>
+        (pkt1_output.getData());
+    boost::scoped_ptr<PerfPkt6> pkt2(new PerfPkt6(pkt1_output_data,
+                                                  pkt1_output.getLength(),
+                                                  PerfPkt6::Offset()));
 
-    // Create objects specifying options offset in a packet. 
+    // Create objects specifying options offset in a packet.
     // Offsets will inform pkt2 object where to read data from.
-    LocalizedOptionPtr pkt2_elapsed_time(new LocalizedOption(Option::V6, D6O_ELAPSED_TIME, vec_elapsed_time, 86));
-    LocalizedOptionPtr pkt2_duid(new LocalizedOption(Option::V6, D6O_CLIENTID, vec_duid, 4));
+    LocalizedOptionPtr pkt2_elapsed_time(new LocalizedOption(Option::V6,
+                                                             D6O_ELAPSED_TIME,
+                                                             vec_elapsed_time,
+                                                             86));
+    LocalizedOptionPtr pkt2_duid(new LocalizedOption(Option::V6,
+                                                     D6O_CLIENTID,
+                                                     vec_duid,
+                                                     4));
     // Add options to packet to pass their offsets.
     pkt2->addOption(pkt2_elapsed_time);
     pkt2->addOption(pkt2_duid);
@@ -139,8 +196,10 @@ TEST_F(PerfPkt6Test, RawPackUnpack) {
     ASSERT_TRUE(pkt2->rawUnpack());
 
     // Once option data is stored in options objects we pull it out.
-    pkt2_elapsed_time = boost::dynamic_pointer_cast<LocalizedOption>(pkt2->getOption(D6O_ELAPSED_TIME));
-    pkt2_duid = boost::dynamic_pointer_cast<LocalizedOption>(pkt2->getOption(D6O_CLIENTID));
+    pkt2_elapsed_time = boost::dynamic_pointer_cast<LocalizedOption>
+        (pkt2->getOption(D6O_ELAPSED_TIME));
+    pkt2_duid = boost::dynamic_pointer_cast<LocalizedOption>
+        (pkt2->getOption(D6O_CLIENTID));
 
     // Check if options are present. They have to be there since
     // we have added them ourselfs.
@@ -151,7 +210,119 @@ TEST_F(PerfPkt6Test, RawPackUnpack) {
     OptionBuffer pkt2_elapsed_time_data = pkt2_elapsed_time->getData();
     OptionBuffer pkt2_duid_data = pkt2_duid->getData();
     EXPECT_EQ(0x0101, pkt2_elapsed_time->getUint16());
-    EXPECT_TRUE(std::equal(pkt2_duid_data.begin(), pkt2_duid_data.end(), buf_duid));
+    EXPECT_TRUE(std::equal(pkt2_duid_data.begin(),
+                           pkt2_duid_data.end(),
+                           buf_duid));
+}
+
+TEST_F(PerfPkt6Test, InvalidOptions) {
+    // Create packet.
+    boost::scoped_ptr<PerfPkt6> pkt1(capture());
+    OptionBuffer vec_server_id;
+    vec_server_id.resize(10);
+    // Testing invalid offset of the option (greater than packet size)
+    LocalizedOptionPtr pkt1_serverid(new LocalizedOption(Option::V6,
+                                                         D6O_SERVERID,
+                                                         vec_server_id,
+                                                         150));
+    pkt1->addOption(pkt1_serverid);
+    // Pack has to fail due to invalid offset.
+    EXPECT_FALSE(pkt1->rawPack());
+
+    // Create packet.
+    boost::scoped_ptr<PerfPkt6> pkt2(capture());
+    // Testing offset of the option (lower than pakcet size but
+    // tail of the option out of bounds).
+    LocalizedOptionPtr pkt2_serverid(new LocalizedOption(Option::V6,
+                                                         D6O_SERVERID,
+                                                         vec_server_id,
+                                                         85));
+    pkt2->addOption(pkt2_serverid);
+    // Pack must fail due to invalid offset.
+    EXPECT_FALSE(pkt2->rawPack());
+}
+
+
+TEST_F(PerfPkt6Test, TruncatedPacket) {
+    cout << "Testing parsing options from truncated packet."
+         << "This may produce spurious errors" << endl;
+
+    // Create truncated (in the middle of duid options)
+    boost::scoped_ptr<PerfPkt6> pkt1(captureTruncated());
+    OptionBuffer vec_duid;
+    vec_duid.resize(30);
+    LocalizedOptionPtr pkt1_duid(new LocalizedOption(Option::V6,
+                                                     D6O_CLIENTID,
+                                                     vec_duid,
+                                                     4));
+    pkt1->addOption(pkt1_duid);
+    // Pack/unpack must fail because length of the option read from buffer
+    // will extend over the actual packet length.
+    EXPECT_FALSE(pkt1->rawUnpack());
+    EXPECT_FALSE(pkt1->rawPack());
+}
+
+TEST_F(PerfPkt6Test, PackTransactionId) {
+    uint8_t data[100] = { 0 };
+
+    // Create dummy packet that is simply filled with zeros.
+    boost::scoped_ptr<PerfPkt6> pkt1(new PerfPkt6(data,
+                                                  sizeof(data),
+                                                  0x010203,
+                                                  PerfPkt6::Offset(50)));
+
+    // Reference data are non zero so we can detect them in dummy packet.
+    uint8_t ref_data[3] = { 1, 2, 3 };
+
+    // This will store given transaction id in the packet data at
+    // offset of 50.
+    ASSERT_TRUE(pkt1->rawPack());
+
+    // Get the output buffer so we can validate it.
+    util::OutputBuffer out_buf = pkt1->getBuffer();
+    ASSERT_EQ(sizeof(data), out_buf.getLength());
+    const uint8_t *out_buf_data = static_cast<const uint8_t*>
+        (out_buf.getData());
+
+    // Validate transaction id.
+    EXPECT_EQ(0, memcmp(out_buf_data + 50, ref_data, 3));
+
+    // Out of bounds transaction id offset.
+    boost::scoped_ptr<PerfPkt6> pkt2(new PerfPkt6(data,
+                                                  sizeof(data),
+                                                  0x010202,
+                                                  PerfPkt6::Offset(100)));
+    cout << "Testing out of bounds offset. "
+        "This may produce spurious errors ..." << endl;
+    EXPECT_FALSE(pkt2->rawPack());
+}
+
+TEST_F(PerfPkt6Test, UnpackTransactionId) {
+    // Initialize data for dummy packet (zeros only).
+    uint8_t data[100] = { 0 };
+
+    // Generate transaction id = 0x010203 and inject at offset = 50.
+    for (int i = 50; i <  53; ++i) {
+        data[i] = i - 49;
+    }
+    // Create packet and point out that transaction id is at offset 50.
+    boost::scoped_ptr<PerfPkt6> pkt1(new PerfPkt6(data,
+                                                  sizeof(data),
+                                                  PerfPkt6::Offset(50)));
+
+    // Get transaction id out of buffer and store in class member.
+    ASSERT_TRUE(pkt1->rawUnpack());
+    // Test value of transaction id.
+    EXPECT_EQ(0x010203, pkt1->getTransid());
+
+    // Out of bounds transaction id offset.
+    boost::scoped_ptr<PerfPkt6> pkt2(new PerfPkt6(data,
+                                                  sizeof(data),
+                                                  PerfPkt6::Offset(300)));
+    cout << "Testing out of bounds offset. "
+        "This may produce spurious errors ..." << endl;
+    EXPECT_FALSE(pkt2->rawUnpack());
+
 }
 
 }



More information about the bind10-changes mailing list