From e64eb11f1c0ad25cf803f6a1735cfdd4654cc912 Mon Sep 17 00:00:00 2001 From: Matias Fontanini Date: Tue, 7 Aug 2012 16:12:40 -0300 Subject: [PATCH] HWAddress class is working. EthernetII now uses this classes instead of raw uint8_t* --- include/ethernetII.h | 22 ++++++++++++----- include/hwaddress.h | 45 +++++++++++++++++++++++++---------- src/ethernetII.cpp | 43 +++++++++++++++++++-------------- tests/src/ethernetII_test.cpp | 38 ++++++++++++++--------------- tests/src/hwaddress.cpp | 5 ++++ 5 files changed, 97 insertions(+), 56 deletions(-) diff --git a/include/ethernetII.h b/include/ethernetII.h index 40a81ec..efb4a04 100644 --- a/include/ethernetII.h +++ b/include/ethernetII.h @@ -27,6 +27,7 @@ #include "pdu.h" #include "utils.h" +#include "hwaddress.h" namespace Tins { @@ -35,6 +36,8 @@ namespace Tins { */ class EthernetII : public PDU { public: + typedef HWAddress<6> address_type; + /** * \brief This PDU's flag. */ @@ -61,7 +64,11 @@ namespace Tins { * \param src_hw_addr uint8_t array of 6 bytes containing the source's MAC(optional). * \param child PDU* with the PDU contained by the ethernet PDU (optional). */ - EthernetII(const std::string& iface, const uint8_t* dst_hw_addr = 0, const uint8_t* src_hw_addr = 0, PDU* child = 0) throw (std::runtime_error); + //EthernetII(const std::string& iface, const uint8_t* dst_hw_addr = 0, const uint8_t* src_hw_addr = 0, PDU* child = 0); + EthernetII(const std::string& iface, + const address_type &dst_hw_addr = address_type(), + const address_type &src_hw_addr = address_type(), + PDU* child = 0); /** * \brief Constructor for creating an ethernet PDU @@ -74,7 +81,10 @@ namespace Tins { * \param src_hw_addr uint8_t array of 6 bytes containing the source's MAC(optional). * \param child PDU* with the PDU contained by the ethernet PDU (optional). */ - EthernetII(uint32_t iface_index, const uint8_t* dst_hw_addr = 0, const uint8_t* src_hw_addr = 0, PDU* child = 0); + EthernetII(uint32_t iface_index, + const address_type &dst_hw_addr = address_type(), + const address_type &src_hw_addr = address_type(), + PDU* child = 0); /** * \brief Constructor which creates an EthernetII object from a buffer and adds all identifiable @@ -90,14 +100,14 @@ namespace Tins { * * \return Returns the destination's mac address as a constant uint8_t pointer. */ - const uint8_t* dst_addr() const { return _eth.dst_mac; } + address_type dst_addr() const { return _eth.dst_mac; } /** * \brief Getter for the source's mac address. * * \return Returns the source's mac address as a constant uint8_t pointer. */ - const uint8_t* src_addr() const { return _eth.src_mac; } + address_type src_addr() const { return _eth.src_mac; } /** * \brief Getter for the interface. @@ -119,14 +129,14 @@ namespace Tins { * * \param new_dst_mac uint8_t array of 6 bytes containing the new destination's MAC. */ - void dst_addr(const uint8_t* new_dst_mac); + void dst_addr(const address_type &new_dst_mac); /** * \brief Setter for the source's MAC. * * \param new_src_mac uint8_t array of 6 bytes containing the new source's MAC. */ - void src_addr(const uint8_t* new_src_mac); + void src_addr(const address_type &new_src_mac); /** * \brief Setter for the interface. diff --git a/include/hwaddress.h b/include/hwaddress.h index 85a2d2d..caecefe 100644 --- a/include/hwaddress.h +++ b/include/hwaddress.h @@ -24,26 +24,37 @@ #include #include +#include +#include +#include #include -#include //borrame +#include namespace Tins { -template +template class HWAddress { public: - typedef uint8_t element_type; - typedef element_type* iterator; - typedef const element_type* const_iterator; + typedef Storage storage_type; + typedef storage_type* iterator; + typedef const storage_type* const_iterator; static const size_t address_size = n; HWAddress() { - std::fill(buffer, buffer + address_size, element_type()); + std::fill(buffer, buffer + address_size, storage_type()); + } + + HWAddress(const storage_type* ptr) { + std::copy(ptr, ptr + address_size, buffer); } HWAddress(const std::string &address) { convert(address, buffer); } + HWAddress& operator=(const std::string &address) { + convert(address, buffer); + } + iterator begin() { return buffer; } @@ -60,6 +71,14 @@ public: return buffer + address_size; } + bool operator==(const HWAddress &rhs) const { + return std::equal(begin(), end(), rhs.begin()); + } + + bool operator!=(const HWAddress &rhs) const { + return !(*this == rhs); + } + friend std::ostream &operator<<(std::ostream &os, const HWAddress &addr) { std::transform( addr.buffer, @@ -73,7 +92,7 @@ private: template static void convert(const std::string &hw_addr, OutputIterator output); - static std::string to_string(element_type element) { + static std::string to_string(storage_type element) { std::ostringstream oss; oss << std::hex; if(element < 0x10) @@ -82,17 +101,19 @@ private: return oss.str(); } - element_type buffer[n]; + storage_type buffer[n]; }; -template +template template -void HWAddress::convert(const std::string &hw_addr, OutputIterator output) { +void HWAddress::convert(const std::string &hw_addr, + OutputIterator output) +{ unsigned i(0); - element_type tmp; + storage_type tmp; while(i < hw_addr.size()) { const unsigned end = i+2; - tmp = element_type(); + tmp = storage_type(); while(i < end) { if(hw_addr[i] >= 'a' && hw_addr[i] <= 'f') tmp = (tmp << 4) | (hw_addr[i] - 'a' + 10); diff --git a/src/ethernetII.cpp b/src/ethernetII.cpp index a3eaa3e..c3dc724 100644 --- a/src/ethernetII.cpp +++ b/src/ethernetII.cpp @@ -22,6 +22,7 @@ #include #include #include +#include #ifndef WIN32 #include #include @@ -35,28 +36,34 @@ const uint8_t* Tins::EthernetII::BROADCAST = (const uint8_t*)"\xff\xff\xff\xff\xff\xff"; const uint32_t Tins::EthernetII::ADDR_SIZE; -Tins::EthernetII::EthernetII(const std::string& iface, const uint8_t* dst_hw_addr, const uint8_t* src_hw_addr, PDU* child) throw (std::runtime_error) : PDU(ETHERTYPE_IP, child) { +Tins::EthernetII::EthernetII(const std::string& iface, + const address_type &dst_hw_addr, const address_type &src_hw_addr, + PDU* child) +: PDU(ETHERTYPE_IP, child) +{ memset(&_eth, 0, sizeof(ethhdr)); - if(dst_hw_addr) - this->dst_addr(dst_hw_addr); - if(src_hw_addr) - this->src_addr(src_hw_addr); + dst_addr(dst_hw_addr); + src_addr(src_hw_addr); this->iface(iface); - this->_eth.payload_type = 0; + _eth.payload_type = 0; } -Tins::EthernetII::EthernetII(uint32_t iface_index, const uint8_t* dst_hw_addr, const uint8_t* src_hw_addr, PDU* child) : PDU(ETHERTYPE_IP, child) { +Tins::EthernetII::EthernetII(uint32_t iface_index, + const address_type &dst_hw_addr, const address_type &src_hw_addr, + PDU* child) +: PDU(ETHERTYPE_IP, child) +{ memset(&_eth, 0, sizeof(ethhdr)); - if(dst_hw_addr) - this->dst_addr(dst_hw_addr); - if(src_hw_addr) - this->src_addr(src_hw_addr); - this->iface(iface_index); - this->_eth.payload_type = 0; + dst_addr(dst_hw_addr); + src_addr(src_hw_addr); + iface(iface_index); + _eth.payload_type = 0; } -Tins::EthernetII::EthernetII(const uint8_t *buffer, uint32_t total_sz) : PDU(ETHERTYPE_IP) { +Tins::EthernetII::EthernetII(const uint8_t *buffer, uint32_t total_sz) +: PDU(ETHERTYPE_IP) +{ if(total_sz < sizeof(ethhdr)) throw std::runtime_error("Not enough size for an ethernetII header in the buffer."); memcpy(&_eth, buffer, sizeof(ethhdr)); @@ -77,12 +84,12 @@ Tins::EthernetII::EthernetII(const uint8_t *buffer, uint32_t total_sz) : PDU(ETH } } -void Tins::EthernetII::dst_addr(const uint8_t* new_dst_mac) { - memcpy(_eth.dst_mac, new_dst_mac, sizeof(_eth.dst_mac)); +void Tins::EthernetII::dst_addr(const address_type &new_dst_mac) { + std::copy(new_dst_mac.begin(), new_dst_mac.end(), _eth.dst_mac); } -void Tins::EthernetII::src_addr(const uint8_t* new_src_mac) { - memcpy(_eth.src_mac, new_src_mac, sizeof(_eth.src_mac)); +void Tins::EthernetII::src_addr(const address_type &new_src_mac) { + std::copy(new_src_mac.begin(), new_src_mac.end(), _eth.src_mac); } void Tins::EthernetII::iface(uint32_t new_iface_index) { diff --git a/tests/src/ethernetII_test.cpp b/tests/src/ethernetII_test.cpp index 5b08b64..16734a5 100644 --- a/tests/src/ethernetII_test.cpp +++ b/tests/src/ethernetII_test.cpp @@ -5,12 +5,14 @@ using namespace Tins; +typedef EthernetII::address_type address_type; + class EthernetIITest : public ::testing::Test { public: static const uint8_t expected_packet[]; - static const uint8_t s_addr[]; - static const uint8_t d_addr[]; - static const uint8_t empty_addr[6]; + static address_type s_addr; + static address_type d_addr; + static address_type empty_addr; static const uint16_t p_type; static const uint32_t iface; @@ -24,23 +26,19 @@ const uint8_t EthernetIITest::expected_packet[] = { '\xd0', '\xab' }; -const uint8_t EthernetIITest::s_addr[] = { -'\x8a', '\x8b', '\x8c', '\x8d', '\x8e', '\x8f' -}; +address_type EthernetIITest::s_addr("8a:8b:8c:8d:8e:8f"); -const uint8_t EthernetIITest::d_addr[] = { -'\xaa', '\xbb', '\xcc', '\xdd', '\xee', '\xff' -}; +address_type EthernetIITest::d_addr("aa:bb:cc:dd:ee:ff"); -const uint8_t EthernetIITest::empty_addr[6] = {0}; +address_type EthernetIITest::empty_addr; const uint16_t EthernetIITest::p_type = 0xd0ab; const uint32_t EthernetIITest::iface = 0x12345678; void EthernetIITest::test_equals(const EthernetII ð1, const EthernetII ð2) { - EXPECT_TRUE(std::equal(eth1.dst_addr(), eth1.dst_addr() + EthernetII::ADDR_SIZE, eth2.dst_addr())); - EXPECT_TRUE(std::equal(eth1.src_addr(), eth1.src_addr() + EthernetII::ADDR_SIZE, eth2.src_addr())); + EXPECT_EQ(eth1.dst_addr(), eth2.dst_addr()); + EXPECT_EQ(eth1.src_addr(), eth2.src_addr()); EXPECT_EQ(eth1.payload_type(), eth2.payload_type()); EXPECT_EQ(eth1.iface(), eth2.iface()); EXPECT_EQ((bool)eth1.inner_pdu(), (bool)eth2.inner_pdu()); @@ -49,8 +47,8 @@ void EthernetIITest::test_equals(const EthernetII ð1, const EthernetII ð2) TEST_F(EthernetIITest, DefaultConstructor) { EthernetII eth(0); EXPECT_EQ(eth.iface(), 0); - EXPECT_TRUE(memcmp(eth.dst_addr(), empty_addr, 6) == 0); - EXPECT_TRUE(memcmp(eth.src_addr(), empty_addr, 6) == 0); + EXPECT_EQ(eth.dst_addr(), empty_addr); + EXPECT_EQ(eth.src_addr(), empty_addr); EXPECT_EQ(eth.payload_type(), 0); EXPECT_FALSE(eth.inner_pdu()); EXPECT_EQ(eth.pdu_type(), PDU::ETHERNET_II); @@ -84,13 +82,13 @@ TEST_F(EthernetIITest, NestedCopy) { TEST_F(EthernetIITest, SourceAddress) { EthernetII eth(0); eth.src_addr(s_addr); - ASSERT_TRUE(memcmp(eth.src_addr(), s_addr, 6) == 0); + ASSERT_EQ(eth.src_addr(), s_addr); } TEST_F(EthernetIITest, DestinationAddress) { EthernetII eth(0); eth.dst_addr(d_addr); - ASSERT_TRUE(memcmp(eth.dst_addr(), d_addr, 6) == 0); + ASSERT_EQ(eth.dst_addr(), d_addr); } TEST_F(EthernetIITest, PayloadType) { @@ -110,8 +108,8 @@ TEST_F(EthernetIITest, Interface) { TEST_F(EthernetIITest, CompleteConstructor) { EthernetII* eth2 = new EthernetII(0); EthernetII eth(iface, d_addr, s_addr, eth2); - EXPECT_TRUE(memcmp(eth.dst_addr(), d_addr, 6) == 0); - EXPECT_TRUE(memcmp(eth.src_addr(), s_addr, 6) == 0); + EXPECT_EQ(eth.dst_addr(), d_addr); + EXPECT_EQ(eth.src_addr(), s_addr); EXPECT_TRUE(eth.inner_pdu() == eth2); EXPECT_EQ(eth.payload_type(), 0); EXPECT_EQ(eth.iface(), iface); @@ -130,8 +128,8 @@ TEST_F(EthernetIITest, Serialize) { TEST_F(EthernetIITest, ConstructorFromBuffer) { EthernetII eth(expected_packet, sizeof(expected_packet)); - EXPECT_TRUE(memcmp(eth.src_addr(), s_addr, sizeof(s_addr)) == 0); - EXPECT_TRUE(memcmp(eth.dst_addr(), d_addr, sizeof(d_addr)) == 0); + EXPECT_EQ(eth.src_addr(), s_addr); + EXPECT_EQ(eth.dst_addr(), d_addr); EXPECT_EQ(eth.payload_type(), p_type); } diff --git a/tests/src/hwaddress.cpp b/tests/src/hwaddress.cpp index 4e93d42..7a5fb66 100644 --- a/tests/src/hwaddress.cpp +++ b/tests/src/hwaddress.cpp @@ -25,6 +25,11 @@ TEST_F(HWAddressTest, DefaultConstructor) { EXPECT_TRUE(std::equal(addr.begin(), addr.end(), empty_addr)); } +TEST_F(HWAddressTest, ConstructorFromBytes) { + HWAddress<6> addr(byte_address); + EXPECT_TRUE(std::equal(addr.begin(), addr.end(), byte_address)); +} + TEST_F(HWAddressTest, ConstructorFromAddress) { HWAddress<6> addr(address); EXPECT_TRUE(std::equal(addr.begin(), addr.end(), byte_address));