Commit 35b62ac9 authored by Marcin Siodelski's avatar Marcin Siodelski
Browse files

[2902] Implemented function which decodes Ethernet frame header.

parent d8595ab6
......@@ -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);
......
......@@ -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.
......
......@@ -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.
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment