From c6f4e816aa7bb311bcfae925354d19604ce5e235 Mon Sep 17 00:00:00 2001 From: Matias Fontanini Date: Sat, 13 May 2017 10:22:24 -0700 Subject: [PATCH] Split pdu_option.h into a source file as well --- include/tins/detail/type_traits.h | 5 + include/tins/pdu_option.h | 347 ++++++++++-------------------- src/CMakeLists.txt | 1 + src/pdu_option.cpp | 276 ++++++++++++++++++++++++ src/rsn_information.cpp | 1 + 5 files changed, 394 insertions(+), 236 deletions(-) create mode 100644 src/pdu_option.cpp diff --git a/include/tins/detail/type_traits.h b/include/tins/detail/type_traits.h index 99fbc4b..6c2c21a 100644 --- a/include/tins/detail/type_traits.h +++ b/include/tins/detail/type_traits.h @@ -53,6 +53,11 @@ struct enable_if { }; +template +struct type_to_type { + typedef T type; +}; + template struct is_unsigned_integral { static const bool value = false; diff --git a/include/tins/pdu_option.h b/include/tins/pdu_option.h index 0f435c1..c614828 100644 --- a/include/tins/pdu_option.h +++ b/include/tins/pdu_option.h @@ -31,18 +31,19 @@ #define TINS_PDU_OPTION_H #include -#include -#include #include +#include #include #include "exceptions.h" -#include "endianness.h" -#include "ip_address.h" -#include "ipv6_address.h" -#include "hw_address.h" #include "detail/type_traits.h" namespace Tins { + +class IPv4Address; +class IPv6Address; +template +class HWAddress; + /** * \cond */ @@ -50,251 +51,125 @@ template class PDUOption; namespace Internals { - template - T convert_to_integral(const PDUOption & opt) { - if (opt.data_size() != sizeof(T)) { - throw malformed_option(); - } - T data = *(T*)opt.data_ptr(); - if (PDUType::endianness == PDUType::BE) { - data = Endian::be_to_host(data); - } - else { - data = Endian::le_to_host(data); - } - return data; - } + namespace Converters { + uint8_t convert(const uint8_t* ptr, uint32_t data_size, PDU::endian_type endian, + type_to_type); + uint16_t convert(const uint8_t* ptr, uint32_t data_size, PDU::endian_type endian, + type_to_type); + uint32_t convert(const uint8_t* ptr, uint32_t data_size, PDU::endian_type endian, + type_to_type); + uint64_t convert(const uint8_t* ptr, uint32_t data_size, PDU::endian_type endian, + type_to_type); + HWAddress<6> convert(const uint8_t* ptr, uint32_t data_size, + PDU::endian_type endian, type_to_type >); + IPv4Address convert(const uint8_t* ptr, uint32_t data_size, + PDU::endian_type endian, type_to_type); + IPv6Address convert(const uint8_t* ptr, uint32_t data_size, PDU::endian_type endian, + type_to_type); + std::string convert(const uint8_t* ptr, uint32_t data_size, + PDU::endian_type endian, type_to_type); + std::vector convert(const uint8_t* ptr, uint32_t data_size, + PDU::endian_type endian, type_to_type >); + std::vector convert(const uint8_t* ptr, uint32_t data_size, + PDU::endian_type endian, type_to_type >); + std::vector convert(const uint8_t* ptr, uint32_t data_size, + PDU::endian_type endian, + type_to_type >); + std::vector convert(const uint8_t* ptr, uint32_t data_size, + PDU::endian_type endian, + type_to_type >); + std::vector convert(const uint8_t* ptr, uint32_t data_size, + PDU::endian_type endian, + type_to_type >); + std::vector convert(const uint8_t* ptr, uint32_t data_size, + PDU::endian_type endian, + type_to_type >); + std::vector > convert(const uint8_t* ptr, uint32_t data_size, + PDU::endian_type endian, + type_to_type > >); + std::pair convert(const uint8_t* ptr, uint32_t data_size, + PDU::endian_type endian, + type_to_type >); + std::pair convert(const uint8_t* ptr, uint32_t data_size, + PDU::endian_type endian, + type_to_type >); + std::pair convert(const uint8_t* ptr, uint32_t data_size, + PDU::endian_type endian, + type_to_type >); + } // Converters - template struct converter { - template - static T convert(const PDUOption& opt) { + template + static T do_convert(const PDUOption& opt, type_to_type) { return T::from_option(opt); } - }; - - template <> - struct converter { - template - static uint8_t convert(const PDUOption& opt) { - if (opt.data_size() != 1) { - throw malformed_option(); - } - return* opt.data_ptr(); - } - }; - - template<> - struct converter { - template - static uint16_t convert(const PDUOption& opt) { - return convert_to_integral(opt); - } - }; - - template<> - struct converter { - template - static uint32_t convert(const PDUOption& opt) { - return convert_to_integral(opt); - } - }; - - template<> - struct converter { - template - static uint64_t convert(const PDUOption& opt) { - return convert_to_integral(opt); - } - }; - template - struct converter > { - template - static HWAddress convert(const PDUOption& opt) { - if (opt.data_size() != n) { - throw malformed_option(); - } - return HWAddress(opt.data_ptr()); + template + static U do_convert(const PDUOption& opt, type_to_type type) { + return Converters::convert(opt.data_ptr(), opt.data_size(), + PDUType::endianness, type); } - }; - template<> - struct converter { - template - static IPv4Address convert(const PDUOption& opt) { - if (opt.data_size() != sizeof(uint32_t)) { - throw malformed_option(); - } - const uint32_t* ptr = (const uint32_t*)opt.data_ptr(); - if (PDUType::endianness == PDUType::BE) { - return IPv4Address(*ptr); - } - else { - return IPv4Address(Endian::change_endian(*ptr)); - } + template + static U do_convert(const PDUOption& opt, type_to_type type) { + return Converters::convert(opt.data_ptr(), opt.data_size(), + PDUType::endianness, type); } - }; - template<> - struct converter { - template - static IPv6Address convert(const PDUOption& opt) { - if (opt.data_size() != IPv6Address::address_size) { - throw malformed_option(); - } - return IPv6Address(opt.data_ptr()); + template + static U do_convert(const PDUOption& opt, type_to_type type) { + return Converters::convert(opt.data_ptr(), opt.data_size(), + PDUType::endianness, type); } - }; - - template<> - struct converter { - template - static std::string convert(const PDUOption& opt) { - return std::string( - opt.data_ptr(), - opt.data_ptr() + opt.data_size() - ); + + template + static U do_convert(const PDUOption& opt, type_to_type type) { + return Converters::convert(opt.data_ptr(), opt.data_size(), + PDUType::endianness, type); } - }; - - template<> - struct converter > { - template - static std::vector convert(const PDUOption& opt) { - std::vector output; - const uint8_t* ptr = opt.data_ptr(), *end = ptr + opt.data_size(); - while (ptr != end) { - output.push_back(float(*(ptr++) & 0x7f) / 2); - } - return output; + + template + static U do_convert(const PDUOption& opt, type_to_type > type) { + return Converters::convert(opt.data_ptr(), opt.data_size(), + PDUType::endianness, type); } - }; - - template - struct converter, typename enable_if::value>::type> { - template - static std::vector convert(const PDUOption& opt) { - if (opt.data_size() % sizeof(T) != 0) { - throw malformed_option(); - } - const T* ptr = (const T*)opt.data_ptr(); - const T* end = (const T*)(opt.data_ptr() + opt.data_size()); - - std::vector output(std::distance(ptr, end)); - typename std::vector::iterator it = output.begin(); - while (ptr < end) { - if (PDUType::endianness == PDUType::BE) { - *it++ = Endian::be_to_host(*ptr++); - } - else { - *it++ = Endian::le_to_host(*ptr++); - } - } - return output; + + template + static U do_convert(const PDUOption& opt, type_to_type type) { + return Converters::convert(opt.data_ptr(), opt.data_size(), + PDUType::endianness, type); } - }; - - template - struct converter< - std::vector >, - typename enable_if< - is_unsigned_integral::value && is_unsigned_integral::value - >::type - > { - template - static std::vector > convert(const PDUOption& opt) { - if (opt.data_size() % (sizeof(T) + sizeof(U)) != 0) { - throw malformed_option(); - } - const uint8_t* ptr = opt.data_ptr(), *end = ptr + opt.data_size(); - - std::vector > output; - while (ptr < end) { - std::pair data; - data.first = *(const T*)ptr; - ptr += sizeof(T); - data.second = *(const U*)ptr; - ptr += sizeof(U); - if (PDUType::endianness == PDUType::BE) { - data.first = Endian::be_to_host(data.first); - data.second = Endian::be_to_host(data.second); - } - else { - data.first = Endian::le_to_host(data.first); - data.second = Endian::le_to_host(data.second); - } - output.push_back(data); - } - return output; + + template + static U do_convert(const PDUOption& opt, type_to_type type) { + return Converters::convert(opt.data_ptr(), opt.data_size(), + PDUType::endianness, type); } - }; - - template<> - struct converter > { - template - static std::vector convert(const PDUOption& opt) { - if (opt.data_size() % 4 != 0) { - throw malformed_option(); - } - const uint32_t* ptr = (const uint32_t*)opt.data_ptr(); - const uint32_t* end = (const uint32_t*)(opt.data_ptr() + opt.data_size()); - - std::vector output(std::distance(ptr, end)); - std::vector::iterator it = output.begin(); - while (ptr < end) { - if (PDUType::endianness == PDUType::BE) { - *it++ = IPv4Address(*ptr++); - } - else { - *it++ = IPv4Address(Endian::change_endian(*ptr++)); - } - } - return output; + + template + static U do_convert(const PDUOption& opt, + type_to_type type) { + return Converters::convert(opt.data_ptr(), opt.data_size(), + PDUType::endianness, type); } - }; - - template<> - struct converter > { - template - static std::vector convert(const PDUOption& opt) { - if (opt.data_size() % IPv6Address::address_size != 0) { - throw malformed_option(); - } - const uint8_t* ptr = opt.data_ptr(), *end = opt.data_ptr() + opt.data_size(); - std::vector output; - while (ptr < end) { - output.push_back(IPv6Address(ptr)); - ptr += IPv6Address::address_size; - } - return output; + + template + static U do_convert(const PDUOption& opt, + type_to_type > type) { + return Converters::convert(opt.data_ptr(), opt.data_size(), + PDUType::endianness, type); } - }; - - template - struct converter< - std::pair, - typename enable_if< - is_unsigned_integral::value && is_unsigned_integral::value - >::type - > { - template - static std::pair convert(const PDUOption& opt) { - if (opt.data_size() != sizeof(T) + sizeof(U)) { - throw malformed_option(); - } - std::pair output; - std::memcpy(&output.first, opt.data_ptr(), sizeof(T)); - std::memcpy(&output.second, opt.data_ptr() + sizeof(T), sizeof(U)); - if (PDUType::endianness == PDUType::BE) { - output.first = Endian::be_to_host(output.first); - output.second = Endian::be_to_host(output.second); - } - else { - output.first = Endian::le_to_host(output.first); - output.second = Endian::le_to_host(output.second); - } - return output; + + template + static U do_convert(const PDUOption& opt, + type_to_type > type) { + return Converters::convert(opt.data_ptr(), opt.data_size(), + PDUType::endianness, type); + } + + template + static T convert(const PDUOption& opt) { + return do_convert(opt, type_to_type()); } }; } @@ -504,7 +379,7 @@ public: */ template T to() const { - return Internals::converter::convert(*this); + return Internals::converter::convert(*this); } private: template diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 3302606..d2dbcb4 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -52,6 +52,7 @@ set(SOURCES radiotap.cpp address_range.cpp pdu_iterator.cpp + pdu_option.cpp rawpdu.cpp rsn_information.cpp sll.cpp diff --git a/src/pdu_option.cpp b/src/pdu_option.cpp new file mode 100644 index 0000000..90b2450 --- /dev/null +++ b/src/pdu_option.cpp @@ -0,0 +1,276 @@ +/* + * Copyright (c) 2017, Matias Fontanini + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include +#include "pdu.h" +#include "ip_address.h" +#include "ipv6_address.h" +#include "hw_address.h" +#include "endianness.h" +#include "pdu_option.h" + +using std::vector; +using std::pair; +using std::string; +using std::memcpy; +using std::distance; + +namespace Tins { +namespace Internals { +namespace Converters { + +template +T convert_to_integral(const uint8_t* ptr, uint32_t data_size, PDU::endian_type endian) { + if (data_size != sizeof(T)) { + throw malformed_option(); + } + T data = *(T*)ptr; + if (endian == PDU::BE) { + data = Endian::be_to_host(data); + } + else { + data = Endian::le_to_host(data); + } + return data; +} + +template +vector convert_vector(const uint8_t* u8_ptr, uint32_t data_size, PDU::endian_type endian) { + if (data_size % sizeof(T) != 0) { + throw malformed_option(); + } + const T* ptr = (const T*)u8_ptr; + const T* end = (const T*)(ptr + data_size / sizeof(T)); + + vector output(distance(ptr, end)); + typename vector::iterator it = output.begin(); + while (ptr < end) { + if (endian == PDU::BE) { + *it++ = Endian::be_to_host(*ptr++); + } + else { + *it++ = Endian::le_to_host(*ptr++); + } + } + return output; +} + +template::value && + is_unsigned_integral::value>::type> +vector > convert_vector(const uint8_t* ptr, uint32_t data_size, + PDU::endian_type endian) { + if (data_size % (sizeof(T) + sizeof(U)) != 0) { + throw malformed_option(); + } + const uint8_t* end = ptr + data_size; + + std::vector > output; + while (ptr < end) { + pair data; + data.first = *(const T*)ptr; + ptr += sizeof(T); + data.second = *(const U*)ptr; + ptr += sizeof(U); + if (endian == PDU::BE) { + data.first = Endian::be_to_host(data.first); + data.second = Endian::be_to_host(data.second); + } + else { + data.first = Endian::le_to_host(data.first); + data.second = Endian::le_to_host(data.second); + } + output.push_back(data); + } + return output; +} + +template::value && + is_unsigned_integral::value>::type> +std::pair convert_pair(const uint8_t* ptr, uint32_t data_size, PDU::endian_type endian) { + if (data_size != sizeof(T) + sizeof(U)) { + throw malformed_option(); + } + pair output; + memcpy(&output.first, ptr, sizeof(T)); + memcpy(&output.second, ptr + sizeof(T), sizeof(U)); + if (endian == PDU::BE) { + output.first = Endian::be_to_host(output.first); + output.second = Endian::be_to_host(output.second); + } + else { + output.first = Endian::le_to_host(output.first); + output.second = Endian::le_to_host(output.second); + } + return output; +} + +uint8_t convert(const uint8_t* ptr, uint32_t data_size, PDU::endian_type, type_to_type) { + if (data_size != 1) { + throw malformed_option(); + } + return *ptr; +} + +uint16_t convert(const uint8_t* ptr, uint32_t data_size, PDU::endian_type endian, + type_to_type) { + return convert_to_integral(ptr, data_size, endian); + +} + +uint32_t convert(const uint8_t* ptr, uint32_t data_size, PDU::endian_type endian, + type_to_type) { + return convert_to_integral(ptr, data_size, endian); +} + +uint64_t convert(const uint8_t* ptr, uint32_t data_size, + PDU::endian_type endian, type_to_type) { + return convert_to_integral(ptr, data_size, endian); +} + +HWAddress<6> convert(const uint8_t* ptr, uint32_t data_size, PDU::endian_type, + type_to_type >) { + if (data_size != 6) { + throw malformed_option(); + } + return HWAddress<6>(ptr); +} + +IPv4Address convert(const uint8_t* u8_ptr, uint32_t data_size, PDU::endian_type endian, + type_to_type) { + if (data_size != sizeof(uint32_t)) { + throw malformed_option(); + } + const uint32_t* ptr = (const uint32_t*)u8_ptr; + if (endian == PDU::BE) { + return IPv4Address(*ptr); + } + else { + return IPv4Address(Endian::change_endian(*ptr)); + } +} + +IPv6Address convert(const uint8_t* ptr, uint32_t data_size, PDU::endian_type, + type_to_type) { + if (data_size != IPv6Address::address_size) { + throw malformed_option(); + } + return IPv6Address(ptr); +} + +string convert(const uint8_t* ptr, uint32_t data_size, PDU::endian_type, + type_to_type) { + return string(ptr, ptr + data_size); +} + +vector convert(const uint8_t* ptr, uint32_t data_size, PDU::endian_type, + type_to_type >) { + vector output; + const uint8_t* end = ptr + data_size; + while (ptr != end) { + output.push_back(float(*(ptr++) & 0x7f) / 2); + } + return output; +} + +vector convert(const uint8_t* ptr, uint32_t data_size, PDU::endian_type endian, + type_to_type >) { + return convert_vector(ptr, data_size, endian); +} + +vector convert(const uint8_t* ptr, uint32_t data_size, PDU::endian_type endian, + type_to_type >) { + return convert_vector(ptr, data_size, endian); +} + +vector convert(const uint8_t* ptr, uint32_t data_size, PDU::endian_type endian, + type_to_type >) { + return convert_vector(ptr, data_size, endian); +} + +vector convert(const uint8_t* u8_ptr, uint32_t data_size, PDU::endian_type endian, + type_to_type >) { + if (data_size % 4 != 0) { + throw malformed_option(); + } + const uint32_t* ptr = (const uint32_t*)u8_ptr; + const uint32_t* end = (const uint32_t*)(ptr + data_size / sizeof(uint32_t)); + + vector output(distance(ptr, end)); + vector::iterator it = output.begin(); + while (ptr < end) { + if (endian == PDU::BE) { + *it++ = IPv4Address(*ptr++); + } + else { + *it++ = IPv4Address(Endian::change_endian(*ptr++)); + } + } + return output; +} + +vector convert(const uint8_t* ptr, uint32_t data_size, PDU::endian_type, + type_to_type >) { + if (data_size % IPv6Address::address_size != 0) { + throw malformed_option(); + } + const uint8_t* end = ptr + data_size; + vector output; + while (ptr < end) { + output.push_back(IPv6Address(ptr)); + ptr += IPv6Address::address_size; + } + return output; +} + +vector> convert(const uint8_t* ptr, uint32_t data_size, + PDU::endian_type endian, + type_to_type > >) { + return convert_vector(ptr, data_size, endian); +} + +pair convert(const uint8_t* ptr, uint32_t data_size, PDU::endian_type endian, + type_to_type >) { + return convert_pair(ptr, data_size, endian); +} + +pair convert(const uint8_t* ptr, uint32_t data_size, PDU::endian_type endian, + type_to_type >) { + return convert_pair(ptr, data_size, endian); +} + +pair convert(const uint8_t* ptr, uint32_t data_size, PDU::endian_type endian, + type_to_type >) { + return convert_pair(ptr, data_size, endian); +} + +} // Converters +} // Internals +} // Tins diff --git a/src/rsn_information.cpp b/src/rsn_information.cpp index 55c67ba..9ab4408 100644 --- a/src/rsn_information.cpp +++ b/src/rsn_information.cpp @@ -33,6 +33,7 @@ #include #include #include "exceptions.h" +#include "pdu.h" #include "pdu_option.h" #include "memory_helpers.h" #include "dot11/dot11_base.h"