BIND 10 trac2902, updated. 35b62ac905d85ea7216a2d61b1cfb62a890bdea6 [2902] Implemented function which decodes Ethernet frame header.
BIND 10 source code commits
bind10-changes at lists.isc.org
Tue Apr 23 15:50:19 UTC 2013
The branch, trac2902 has been updated
via 35b62ac905d85ea7216a2d61b1cfb62a890bdea6 (commit)
from d8595ab6bd85996c00019da0b086fdb40374e1f9 (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 35b62ac905d85ea7216a2d61b1cfb62a890bdea6
Author: Marcin Siodelski <marcin at isc.org>
Date: Tue Apr 23 17:50:08 2013 +0200
[2902] Implemented function which decodes Ethernet frame header.
-----------------------------------------------------------------------
Summary of changes:
src/lib/dhcp/protocol_util.cc | 39 +++++++++++++++-
src/lib/dhcp/protocol_util.h | 28 ++++++++++++
src/lib/dhcp/tests/protocol_util_unittest.cc | 61 ++++++++++++++++++++++++++
3 files changed, 126 insertions(+), 2 deletions(-)
-----------------------------------------------------------------------
diff --git a/src/lib/dhcp/protocol_util.cc b/src/lib/dhcp/protocol_util.cc
index b73436b..842c038 100644
--- a/src/lib/dhcp/protocol_util.cc
+++ b/src/lib/dhcp/protocol_util.cc
@@ -12,15 +12,50 @@
// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE.
-#include <protocol_util.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::util;
+
namespace isc {
namespace dhcp {
+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) {
+ isc_throw(InvalidPacketHeader, "size of ethernet header in received "
+ << "packet is invalid, expected at least 14 bytes, received "
+ << buf.getLength() - buf.getPosition() << " bytes");
+ }
+ // Packet object must not be NULL. We want to output some values
+ // to this object.
+ if (!pkt) {
+ isc_throw(BadValue, "NULL packet object provided when parsing ethernet"
+ " frame header");
+ }
+
+ // The size of the single address is always lower then the size of
+ // the header that holds this address. Otherwise, it is a programming
+ // error that we want to detect in the compilation time.
+ BOOST_STATIC_ASSERT(ETHERNET_HEADER_LEN > HWAddr::ETHERNET_HWADDR_LEN);
+
+ // Skip destination address.
+ buf.setPosition(HWAddr::ETHERNET_HWADDR_LEN);
+ // Read the source HW address.
+ std::vector<uint8_t> dest_addr;
+ buf.readVector(dest_addr, HWAddr::ETHERNET_HWADDR_LEN);
+ // Set the address we have read.
+ pkt->setHWAddr(HWTYPE_ETHERNET, HWAddr::ETHERNET_HWADDR_LEN, dest_addr);
+ // Move the buffer read pointer to the end of the Ethernet frame header.
+ buf.setPosition(ETHERNET_HEADER_LEN);
+}
+
void
writeEthernetHeader(const uint8_t* src_hw_addr, const uint8_t* dest_hw_addr,
- util::OutputBuffer& out_buf) {
+ OutputBuffer& out_buf) {
// Write destination and source address.
out_buf.writeData(dest_hw_addr, HWAddr::ETHERNET_HWADDR_LEN);
out_buf.writeData(src_hw_addr, HWAddr::ETHERNET_HWADDR_LEN);
diff --git a/src/lib/dhcp/protocol_util.h b/src/lib/dhcp/protocol_util.h
index 5a6cfb4..c34bba4 100644
--- a/src/lib/dhcp/protocol_util.h
+++ b/src/lib/dhcp/protocol_util.h
@@ -23,6 +23,34 @@
namespace isc {
namespace dhcp {
+/// @brief Exception thrown when error occured during parsing packet's headers.
+///
+/// This exception is thrown when parsing link, Internet or Transport layer
+/// header has failed.
+class InvalidPacketHeader : public Exception {
+public:
+ InvalidPacketHeader(const char* file, size_t line, const char* what) :
+ isc::Exception(file, line, what) { };
+};
+
+/// Size of the Ethernet frame header.
+static const size_t ETHERNET_HEADER_LEN = 14;
+
+/// @brief Decode the Ethernet header.
+///
+/// This function reads Ethernet frame header from the provided
+/// buffer at the current read position. The source HW address
+/// is read from the header and assigned as client address in
+/// a pkt object. The buffer read pointer is set to the end
+/// of the Ethernet frame header if read was successful.
+///
+/// @param buf input buffer holding header to be parsed.
+/// @param [out] pkt packet object receiving HW source address read from header.
+///
+/// @throw InvalidPacketHeader if packet header is truncated
+/// @throw BadValue if pkt object is NULL.
+void decodeEthernetHeader(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 ffdf0d3..3fe9a9f 100644
--- a/src/lib/dhcp/tests/protocol_util_unittest.cc
+++ b/src/lib/dhcp/tests/protocol_util_unittest.cc
@@ -14,6 +14,8 @@
#include <config.h>
#include <asiolink/io_address.h>
+#include <dhcp/dhcp6.h>
+#include <dhcp/hwaddr.h>
#include <dhcp/protocol_util.h>
#include <util/buffer.h>
@@ -63,6 +65,65 @@ TEST(ProtocolUtilTest, checksum) {
EXPECT_EQ(0xb1e4, chksum);
}
+// The purpose of this test is to verify that the Ethernet frame header
+// can be decoded correctly. In particular it verifies that the source
+// HW address can be extracted from it.
+TEST(ProtocolUtilTest, decodeEthernetHeader) {
+ // Source HW address, 6 bytes.
+ const uint8_t src_hw_addr[6] = {
+ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15
+ };
+ // Destination HW address, 6 bytes.
+ const uint8_t dest_hw_addr[6] = {
+ 0x20, 0x31, 0x42, 0x53, 0x64, 0x75
+ };
+
+ // Prepare a buffer holding Ethernet frame header and 4 bytes of
+ // dummy data.
+ OutputBuffer buf(1);
+ buf.writeData(dest_hw_addr, sizeof(src_hw_addr));
+ buf.writeData(src_hw_addr, sizeof(src_hw_addr));
+ buf.writeUint16(0x800);
+ // Append dummy data. We will later check that this data is not
+ // removed or corrupted when reading the ethernet header.
+ buf.writeUint32(0x01020304);
+
+ // Create a buffer with truncated ethernet frame header..
+ InputBuffer in_buf_truncated(buf.getData(), buf.getLength() - 6);
+ // But provide valid packet object to make sure that the function
+ // under test does not throw due to NULL pointer packet.
+ Pkt4Ptr pkt(new Pkt4(DHCPDISCOVER, 0));
+ // Function should throw because header data is truncated.
+ EXPECT_THROW(decodeEthernetHeader(in_buf_truncated, pkt),
+ InvalidPacketHeader);
+
+ // Get not truncated buffer.
+ InputBuffer in_buf(buf.getData(), buf.getLength());
+ // But provide NULL packet object instead.
+ pkt.reset();
+ // It should throw again but a different exception.
+ EXPECT_THROW(decodeEthernetHeader(in_buf, pkt),
+ BadValue);
+ // Now provide, correct data.
+ pkt.reset(new Pkt4(DHCPDISCOVER, 0));
+ // It should not throw now.
+ ASSERT_NO_THROW(decodeEthernetHeader(in_buf, pkt));
+ // Verify that the HW address of the source has been initialized.
+ HWAddrPtr hwaddr = pkt->getHWAddr();
+ ASSERT_TRUE(hwaddr);
+ // And that it is correct.
+ EXPECT_EQ(HWTYPE_ETHERNET, hwaddr->htype_);
+ ASSERT_EQ(sizeof(dest_hw_addr), hwaddr->hwaddr_.size());
+ EXPECT_TRUE(std::equal(src_hw_addr, src_hw_addr + sizeof(src_hw_addr),
+ hwaddr->hwaddr_.begin()));
+ // The entire ethernet packet header should have been read. This means
+ // that the internal buffer pointer should now point to its tail.
+ ASSERT_EQ(ETHERNET_HEADER_LEN, in_buf.getPosition());
+ // And the dummy data should be still readable and correct.
+ uint32_t dummy_data = in_buf.readUint32();
+ EXPECT_EQ(0x01020304, dummy_data);
+}
+
/// 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