From 53dfad8bf22be9d49e68aceced4e0d2c4a7939cf Mon Sep 17 00:00:00 2001 From: Matias Fontanini Date: Tue, 6 Mar 2012 08:31:10 -0300 Subject: [PATCH] Done minor modifications. --- include/dot11.h | 57 ++++++++++++++++++++++++++++++++---------------- include/ip.h | 17 ++++++++++++--- src/dot11.cpp | 23 ++++++++++--------- src/ip.cpp | 16 +++++++++++--- tests/src/ip.cpp | 47 ++++++++++++++++++++++++++++++++++++--- 5 files changed, 120 insertions(+), 40 deletions(-) diff --git a/include/dot11.h b/include/dot11.h index bd4e730..eebd1b8 100644 --- a/include/dot11.h +++ b/include/dot11.h @@ -41,6 +41,11 @@ namespace Tins { * \brief Broadcast hardware address. */ static const uint8_t *BROADCAST; + + /** + * \brief Dot11 address size. + */ + static const uint32_t ADDR_SIZE = 6; /** * \brief Enum for the different types of 802.11 frames. @@ -147,22 +152,12 @@ namespace Tins { /** * \brief IEEE 802.11 options struct. */ - struct Dot11_Option { + struct Dot11Option { + friend class Dot11; + friend class Dot11Beacon; + friend class Dot11ManagementFrame; /** - * \brief The option number. - */ - uint8_t option; - /** - * \brief The value's length in bytes. - */ - uint8_t length; - /** - * \brief The option's value. - */ - uint8_t *value; - - /** - * \brief Creates an instance of Dot11_Option. + * \brief Creates an instance of Dot11Option. * * The option's value is copied, therefore the user should * manually free any memory pointed by the "val" parameter. @@ -170,7 +165,31 @@ namespace Tins { * \param len The length of the option's value in bytes. * \param val The option's value. */ - Dot11_Option(uint8_t opt, uint8_t len, const uint8_t *val); + Dot11Option(uint8_t opt, uint8_t len, const uint8_t *val); + + /** + * \brief Getter for Dot11 options' data pointer. + */ + const uint8_t* data_ptr() const { return value; } + + /** + * \brief Getter for the data size field + */ + uint8_t data_size() const { return length; } + + /** + * \brief The option number. + */ + uint8_t option; + private: + /** + * \brief The value's length in bytes. + */ + uint8_t length; + /** + * \brief The option's value. + */ + uint8_t *value; }; /** @@ -450,7 +469,7 @@ namespace Tins { * \param opt The option identifier. * \return The option found, or 0 if no such option has been set. */ - const Dot11_Option *lookup_option(TaggedOption opt) const; + const Dot11Option *search_option(TaggedOption opt) const; /** * \brief Getter for the PDU's type. @@ -512,7 +531,7 @@ namespace Tins { #endif } __attribute__((__packed__)) control; uint16_t duration_id; - uint8_t addr1[6]; + uint8_t addr1[ADDR_SIZE]; } __attribute__((__packed__)); private: @@ -524,7 +543,7 @@ namespace Tins { ieee80211_header _header; uint32_t _iface_index, _options_size; - std::list _options; + std::list _options; }; /** diff --git a/include/ip.h b/include/ip.h index 010f044..c6afacd 100644 --- a/include/ip.h +++ b/include/ip.h @@ -89,6 +89,7 @@ namespace Tins { * \brief This class represents an IP option. */ struct IPOption { + friend class IP; struct { #if __BYTE_ORDER == __LITTLE_ENDIAN unsigned int number:5; @@ -100,10 +101,20 @@ namespace Tins { unsigned int number:5; #endif } type; - uint8_t* optional_data; - uint32_t optional_data_size; - + uint8_t* write(uint8_t* buffer); + + /** + * \brief Getter for IP options' data pointer. + */ + const uint8_t* data_ptr() const; + + /** + * \brief Getter for the data size field + */ + uint8_t data_size() const; + private: + uint8_t* optional_data, optional_data_size; } __attribute__((__packed__)); /** diff --git a/src/dot11.cpp b/src/dot11.cpp index 5719864..229573d 100644 --- a/src/dot11.cpp +++ b/src/dot11.cpp @@ -40,13 +40,12 @@ using namespace std; const uint8_t *Tins::Dot11::BROADCAST = (const uint8_t*)"\xff\xff\xff\xff\xff\xff"; +const uint32_t Tins::Dot11::ADDR_SIZE; Tins::Dot11::Dot11(const uint8_t* dst_hw_addr, PDU* child) : PDU(ETHERTYPE_IP, child), _options_size(0) { memset(&this->_header, 0, sizeof(ieee80211_header)); - if(dst_hw_addr) { - + if(dst_hw_addr) this->addr1(dst_hw_addr); - } } Tins::Dot11::Dot11(const std::string& iface, const uint8_t* dst_hw_addr, PDU* child) throw (std::runtime_error) : PDU(ETHERTYPE_IP, child), _options_size(0) { @@ -109,19 +108,19 @@ void Tins::Dot11::parse_tagged_parameters(const uint8_t *buffer, uint32_t total_ } } -Tins::Dot11::Dot11_Option::Dot11_Option(uint8_t opt, uint8_t len, const uint8_t *val) : option(opt), length(len) { +Tins::Dot11::Dot11Option::Dot11Option(uint8_t opt, uint8_t len, const uint8_t *val) : option(opt), length(len) { value = new uint8_t[len]; std::memcpy(value, val, len); } void Tins::Dot11::add_tagged_option(TaggedOption opt, uint8_t len, const uint8_t *val) { uint32_t opt_size = len + (sizeof(uint8_t) << 1); - _options.push_back(Dot11_Option((uint8_t)opt, len, val)); + _options.push_back(Dot11Option((uint8_t)opt, len, val)); _options_size += opt_size; } -const Tins::Dot11::Dot11_Option *Tins::Dot11::lookup_option(TaggedOption opt) const { - for(std::list::const_iterator it = _options.begin(); it != _options.end(); ++it) +const Tins::Dot11::Dot11Option *Tins::Dot11::search_option(TaggedOption opt) const { + for(std::list::const_iterator it = _options.begin(); it != _options.end(); ++it) if(it->option == (uint8_t)opt) return &(*it); return 0; @@ -218,7 +217,7 @@ void Tins::Dot11::write_serialization(uint8_t *buffer, uint32_t total_sz, const uint32_t child_len = write_fixed_parameters(buffer, total_sz - _options_size); buffer += child_len; assert(total_sz >= child_len + _options_size); - for(std::list::const_iterator it = _options.begin(); it != _options.end(); ++it) { + for(std::list::const_iterator it = _options.begin(); it != _options.end(); ++it) { *(buffer++) = it->option; *(buffer++) = it->length; std::memcpy(buffer, it->value, it->length); @@ -268,8 +267,8 @@ void Tins::Dot11::copy_80211_fields(const Dot11 *other) { std::memcpy(&_header, &other->_header, sizeof(_header)); _iface_index = other->_iface_index; _options_size = other->_options_size; - for(std::list::const_iterator it = other->_options.begin(); it != other->_options.end(); ++it) - _options.push_back(Dot11_Option(it->option, it->length, it->value)); + for(std::list::const_iterator it = other->_options.begin(); it != other->_options.end(); ++it) + _options.push_back(Dot11Option(it->option, it->length, it->value)); } /* Dot11ManagementFrame */ @@ -753,12 +752,12 @@ void Tins::Dot11Beacon::qos_capabilities(uint8_t qos_info) { } string Tins::Dot11Beacon::essid() const { - const Dot11::Dot11_Option *option = lookup_option(SSID); + const Dot11::Dot11Option *option = search_option(SSID); return (option) ? string((const char*)option->value, option->length) : 0; } bool Tins::Dot11Beacon::rsn_information(RSNInformation *rsn) { - const Dot11::Dot11_Option *option = lookup_option(RSN); + const Dot11::Dot11Option *option = search_option(RSN); if(!option || option->length < (sizeof(uint16_t) << 1) + sizeof(uint32_t)) return false; const uint8_t *buffer = option->value; diff --git a/src/ip.cpp b/src/ip.cpp index a26a193..e70f986 100644 --- a/src/ip.cpp +++ b/src/ip.cpp @@ -246,8 +246,10 @@ void Tins::IP::set_option(uint8_t copied, option.type.number = number; uint8_t* buffer(0); if (data_size) { - buffer = new uint8_t[data_size]; - memcpy(buffer, data, data_size); + buffer = new uint8_t[data_size + 1]; + buffer[0] = data_size; + memcpy(buffer + 1, data, data_size); + data_size++; } option.optional_data = buffer; option.optional_data_size = data_size; @@ -275,6 +277,14 @@ uint8_t* Tins::IP::IPOption::write(uint8_t* buffer) { return buffer; } +const uint8_t* Tins::IP::IPOption::data_ptr() const { + return optional_data ? optional_data + 1 : 0; +} + +uint8_t Tins::IP::IPOption::data_size() const { + return optional_data_size ? optional_data_size - 1 : 0; +} + /* Virtual method overriding. */ uint32_t Tins::IP::header_size() const { @@ -318,7 +328,7 @@ void Tins::IP::write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU this->flag(new_flag); } this->tot_len(total_sz); - this->head_len (my_sz / sizeof(uint32_t)); + this->head_len(my_sz / sizeof(uint32_t)); memcpy(buffer, &_ip, sizeof(_ip)); diff --git a/tests/src/ip.cpp b/tests/src/ip.cpp index ae34d89..2b53cdb 100644 --- a/tests/src/ip.cpp +++ b/tests/src/ip.cpp @@ -12,9 +12,14 @@ class IPTest : public testing::Test { public: static const uint8_t expected_packet[]; - void test_equals(const IP &tcp1, const IP &tcp2); + void test_equals(const IP &ip1, const IP &ip2); }; +const uint8_t IPTest::expected_packet[] = { '(', '\x7f', '\x00', ' ', +'\x00', 'z', '\x00', 'C', '\x15', '\x01', '\xfb', 'g', 'T', '4', '\xfe', +'\x05', '\xc0', '\xa8', '\t', '+', '\x82', '\x0b', 't', 'j', 'g', '\xab', +'w', '\xab', 'h', 'e', 'l', '\x00' }; + TEST_F(IPTest, DefaultConstructor) { IP ip; @@ -128,6 +133,42 @@ TEST_F(IPTest, SecOption) { ip.set_sec_option(data, sizeof(data)); const IP::IPOption *option; ASSERT_TRUE((option = ip.search_option(IP::CONTROL, IP::SEC))); - ASSERT_EQ(option->optional_data_size, sizeof(data)); - EXPECT_TRUE(memcmp(option->optional_data, data, sizeof(data)) == 0); + ASSERT_EQ(option->data_size(), sizeof(data)); + EXPECT_TRUE(memcmp(option->data_ptr(), data, sizeof(data)) == 0); +} + +void IPTest::test_equals(const IP &ip1, const IP &ip2) { + EXPECT_EQ(ip1.dst_addr(), ip2.dst_addr()); + EXPECT_EQ(ip1.src_addr(), ip2.src_addr()); + EXPECT_EQ(ip1.id(), ip2.id()); + EXPECT_EQ(ip1.frag_off(), ip2.frag_off()); + EXPECT_EQ(ip1.tos(), ip2.tos()); + EXPECT_EQ(ip1.ttl(), ip2.ttl()); + EXPECT_EQ(ip1.version(), ip2.version()); +} + +TEST_F(IPTest, ConstructorFromBuffer) { + IP ip1(expected_packet, sizeof(expected_packet)); + const uint8_t opt_sec[] = { 't', 'j', 'g', '\xab', 'w', '\xab', 'h', 'e', 'l' }; + + EXPECT_EQ(ip1.dst_addr(), Utils::ip_to_int("192.168.9.43")); + EXPECT_EQ(ip1.src_addr(), Utils::ip_to_int("84.52.254.5")); + EXPECT_EQ(ip1.id(), 0x7a); + EXPECT_EQ(ip1.tos(), 0x7f); + EXPECT_EQ(ip1.frag_off(), 0x43); + EXPECT_EQ(ip1.protocol(), 1); + EXPECT_EQ(ip1.ttl(), 0x15); + EXPECT_EQ(ip1.version(), 2); + const IP::IPOption *option; + ASSERT_TRUE((option = ip1.search_option(IP::CONTROL, IP::SEC))); + EXPECT_EQ(option->type.number, IP::SEC); + EXPECT_EQ(option->type.op_class, IP::CONTROL); + ASSERT_EQ(option->data_size(), sizeof(opt_sec)); + EXPECT_TRUE(memcmp(option->data_ptr(), opt_sec, sizeof(opt_sec)) == 0); + + uint32_t size; + uint8_t *buffer = ip1.serialize(size); + ASSERT_TRUE(buffer); + + IP ip2(buffer, size); }