BIND 10 trac2902, updated. decee38f00f3efac436fa899bf6160fff787e318 [2902] Implemented a function decoding IP and UDP header.

BIND 10 source code commits bind10-changes at lists.isc.org
Tue Apr 23 16:54:42 UTC 2013


The branch, trac2902 has been updated
       via  decee38f00f3efac436fa899bf6160fff787e318 (commit)
      from  35b62ac905d85ea7216a2d61b1cfb62a890bdea6 (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 decee38f00f3efac436fa899bf6160fff787e318
Author: Marcin Siodelski <marcin at isc.org>
Date:   Tue Apr 23 18:54:24 2013 +0200

    [2902] Implemented a function decoding IP and UDP header.

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

Summary of changes:
 src/lib/dhcp/protocol_util.cc                |   48 ++++++++++++++++++-
 src/lib/dhcp/protocol_util.h                 |   21 +++++++++
 src/lib/dhcp/tests/protocol_util_unittest.cc |   64 ++++++++++++++++++++++++++
 3 files changed, 132 insertions(+), 1 deletion(-)

-----------------------------------------------------------------------
diff --git a/src/lib/dhcp/protocol_util.cc b/src/lib/dhcp/protocol_util.cc
index 842c038..63bb59d 100644
--- a/src/lib/dhcp/protocol_util.cc
+++ b/src/lib/dhcp/protocol_util.cc
@@ -12,17 +12,20 @@
 // OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
 // PERFORMANCE OF THIS SOFTWARE.
 
+#include <asiolink/io_address.h>
 #include <dhcp/dhcp6.h> // defines HWTYPE_ETHERNET
 #include <dhcp/protocol_util.h>
 #include <boost/static_assert.hpp>
 #include <netinet/ip.h>
 
+using namespace isc::asiolink;
 using namespace isc::util;
 
 namespace isc {
 namespace dhcp {
 
-void decodeEthernetHeader(InputBuffer& buf, Pkt4Ptr& pkt) {
+void
+decodeEthernetHeader(InputBuffer& buf, Pkt4Ptr& pkt) {
     // The size of the buffer to be parsed must not be lower
     // then the size of the Ethernet frame header.
     if (buf.getLength() - buf.getPosition() < ETHERNET_HEADER_LEN) {
@@ -54,6 +57,49 @@ void decodeEthernetHeader(InputBuffer& buf, Pkt4Ptr& pkt) {
 }
 
 void
+decodeIpUdpHeader(InputBuffer& buf, Pkt4Ptr& pkt) {
+    // The size of the buffer must be at least equal to the minimal size of
+    // the IPv4 packet header plus UDP header length.
+    if (buf.getLength() - buf.getPosition() < MIN_IP_HEADER_LEN + UDP_HEADER_LEN) {
+        isc_throw(InvalidPacketHeader, "the total size of the IP and UDP headers in "
+                  << "received packet is invalid, expected at least "
+                  << MIN_IP_HEADER_LEN + UDP_HEADER_LEN
+                  << " bytes, received " << buf.getLength() - buf.getPosition()
+                  << " bytes");
+    }
+
+    // Packet object must not be NULL.
+    if (!pkt) {
+        isc_throw(BadValue, "NULL packet object provided when parsing IP and UDP"
+                  " packet headers");
+    }
+
+    BOOST_STATIC_ASSERT(IP_SRC_ADDR_OFFSET < MIN_IP_HEADER_LEN);
+
+    // Read IP header length (mask most significant bits as they indicate IP version).
+    uint8_t ip_len = buf.readUint8() & 0xF;
+    // IP length is the number of 4 byte chunks that construct IPv4 header.
+    // It must not be lower than 5 because first 20 bytes are fixed.
+    if (ip_len < 5) {
+        ip_len = 5;
+    }
+
+    // Seek to the position of source IP address.
+    buf.setPosition(IP_SRC_ADDR_OFFSET);
+    // Read source address.
+    pkt->setRemoteAddr(IOAddress(buf.readUint32()));
+    // Read destination address.
+    pkt->setLocalAddr(IOAddress(buf.readUint32()));
+    // Read source port from UDP header.
+    pkt->setRemotePort(buf.readUint16());
+    // Read destination port from UDP header.
+    pkt->setLocalPort(buf.readUint16());
+
+    // Set the pointer position to the tail of UDP header.
+    buf.setPosition(ip_len * 4 + UDP_HEADER_LEN);
+}
+
+void
 writeEthernetHeader(const uint8_t* src_hw_addr, const uint8_t* dest_hw_addr,
                     OutputBuffer& out_buf) {
     // Write destination and source address.
diff --git a/src/lib/dhcp/protocol_util.h b/src/lib/dhcp/protocol_util.h
index c34bba4..00aa9b2 100644
--- a/src/lib/dhcp/protocol_util.h
+++ b/src/lib/dhcp/protocol_util.h
@@ -35,6 +35,12 @@ public:
 
 /// Size of the Ethernet frame header.
 static const size_t ETHERNET_HEADER_LEN = 14;
+/// Minimal IPv4 header length.
+static const size_t MIN_IP_HEADER_LEN = 20;
+/// UDP header length.
+static const size_t UDP_HEADER_LEN = 8;
+/// Offset of source address in the IPv4 header.
+static const size_t IP_SRC_ADDR_OFFSET = 12;
 
 /// @brief Decode the Ethernet header.
 ///
@@ -51,6 +57,21 @@ static const size_t ETHERNET_HEADER_LEN = 14;
 /// @throw BadValue if pkt object is NULL.
 void decodeEthernetHeader(util::InputBuffer& buf, Pkt4Ptr& pkt);
 
+/// @brief Decode IP and UDP header.
+///
+/// This function reads IP and UDP headers from the provided buffer
+/// at the current read position. The source and destination IP
+/// addresses and ports and read from these headers and stored in
+/// the appropriate members of pkt object.
+///
+/// @param buf input buffer holding headers to be parsed.
+/// @param [out] pkt packet object where IP addresses and ports
+/// are stored.
+///
+/// @throw InvalidPacketHeader if packet header is truncated
+/// @throw BadValue if pkt object is NULL.
+void decodeIpUdpHeader(util::InputBuffer& buf, Pkt4Ptr& pkt);
+
 /// @brief Writes ethernet frame header into a buffer.
 ///
 /// @param src_hw_addr source HW address.
diff --git a/src/lib/dhcp/tests/protocol_util_unittest.cc b/src/lib/dhcp/tests/protocol_util_unittest.cc
index 3fe9a9f..d492787 100644
--- a/src/lib/dhcp/tests/protocol_util_unittest.cc
+++ b/src/lib/dhcp/tests/protocol_util_unittest.cc
@@ -124,6 +124,70 @@ TEST(ProtocolUtilTest, decodeEthernetHeader) {
     EXPECT_EQ(0x01020304, dummy_data);
 }
 
+/// The purpose of this test is to verify that the IP and UDP header
+/// is decoded correctly and appropriate values of IP addresses and
+/// ports are assigned to a Pkt4 object.
+TEST(ProtocolUtilTest, decodeIpUdpHeader) {
+    // IPv4 header to be parsed.
+    const uint8_t hdr[] = {
+        0x45,                      // IP version and header length
+        0x00,                      // TOS
+        0x00, 0x3c,                // Total length of the IP packet.
+        0x1c, 0x46,                // Identification field.
+        0x40, 0x00,                // Fragmentation.
+        0x40,                      // TTL
+        IPPROTO_UDP,               // Protocol
+        0x00, 0x00,                // Checksum (reset to 0x00).
+        0xc0, 0x00, 0x02, 0x63,    // Source IP address.
+        0xc0, 0x00, 0x02, 0x0c,    // Destination IP address.
+        0x27, 0x54,                // Source port
+        0x27, 0x53,                // Destination port
+        0x00, 0x08,                // UDP length
+        0x00, 0x00                 // Checksum
+    };
+
+    // Write header data to the buffer.
+    OutputBuffer buf(1);
+    buf.writeData(hdr, sizeof(hdr));
+    // Append some dummy data.
+    buf.writeUint32(0x01020304);
+
+    // Create an input buffer holding truncated headers.
+    InputBuffer in_buf_truncated(buf.getData(), buf.getLength() - 10);
+    // Create non NULL Pkt4 object to make sure that the function under
+    // test does not throw due to invalid Pkt4 object.
+    Pkt4Ptr pkt(new Pkt4(DHCPDISCOVER, 0));
+    // Function should throw because buffer holds truncated data.
+    EXPECT_THROW(decodeIpUdpHeader(in_buf_truncated, pkt), InvalidPacketHeader);
+
+    // Create a valid input buffer (not truncated).
+    InputBuffer in_buf(buf.getData(), buf.getLength());
+    // Set NULL Pkt4 object to verify that function under test will
+    // return exception as expected.
+    pkt.reset();
+    // And check whether it throws exception.
+    EXPECT_THROW(decodeIpUdpHeader(in_buf, pkt), BadValue);
+
+    // Now, let's provide valid arguments and make sure it doesn't throw.
+    pkt.reset(new Pkt4(DHCPDISCOVER, 0));
+    ASSERT_TRUE(pkt);
+    EXPECT_NO_THROW(decodeIpUdpHeader(in_buf, pkt));
+
+    // Verify the source address and port.
+    EXPECT_EQ("192.0.2.99", pkt->getRemoteAddr().toText());
+    EXPECT_EQ(10068, pkt->getRemotePort());
+
+    // Verify the destination address and port.
+    EXPECT_EQ("192.0.2.12", pkt->getLocalAddr().toText());
+    EXPECT_EQ(10067, pkt->getLocalPort());
+
+    // Verify that the dummy data has not been corrupted and that the
+    // internal read pointer has been moved to the tail of the UDP
+    // header.
+    ASSERT_EQ(MIN_IP_HEADER_LEN + UDP_HEADER_LEN, in_buf.getPosition());
+    EXPECT_EQ(0x01020304, in_buf.readUint32());
+}
+
 /// The purpose of this test is to verify that the ethernet
 /// header is correctly constructed from the destination and
 /// hardware addresses.



More information about the bind10-changes mailing list