diff --git a/include/dot11/dot11_base.h b/include/dot11/dot11_base.h index 8d01373..87d2779 100644 --- a/include/dot11/dot11_base.h +++ b/include/dot11/dot11_base.h @@ -74,6 +74,11 @@ public: */ static const address_type BROADCAST; + /** + * The endianness used by Dot11. + */ + static const endian_type endianness = LE; + /** * \brief Enum for the different types of 802.11 frames. * diff --git a/include/dot11/dot11_mgmt.h b/include/dot11/dot11_mgmt.h index c7a0255..fe13d40 100644 --- a/include/dot11/dot11_mgmt.h +++ b/include/dot11/dot11_mgmt.h @@ -523,6 +523,11 @@ public: static vendor_specific_type from_bytes(const uint8_t *buffer, uint32_t sz); }; + + /** + * The type used to store the QOS capability tagged option data. + */ + typedef uint8_t qos_capability_type; /** * \brief Getter for the second address. @@ -641,7 +646,7 @@ public: * * \param new_qos_capabilities uint8_t with the capabilities. */ - void qos_capability(uint8_t new_qos_capability); + void qos_capability(qos_capability_type new_qos_capability); /** * \brief Helper method to set the power capabilities option. @@ -851,7 +856,7 @@ public: * * \return uint8_t containing the QOS capability. */ - uint8_t qos_capability() const; + qos_capability_type qos_capability() const; /** * \brief Helper method to get the power capability. @@ -1120,6 +1125,14 @@ protected: private: static uint8_t *serialize_rates(const rates_type &rates); static rates_type deserialize_rates(const option *option); + + template + T search_and_convert(OptionTypes opt_type) const { + const option *opt = search_option(opt_type); + if(!opt) + throw option_not_found(); + return opt->to(); + } ExtendedHeader _ext_header; address_type _addr4; diff --git a/include/pdu_option.h b/include/pdu_option.h index 628d8ae..bb94b48 100644 --- a/include/pdu_option.h +++ b/include/pdu_option.h @@ -33,6 +33,7 @@ #include #include #include +#include #include #include "exceptions.h" #include "endianness.h" @@ -113,6 +114,30 @@ namespace Internals { } }; + template<> + struct converter { + template + static std::string convert(const PDUOption& opt) { + return std::string( + opt.data_ptr(), + opt.data_ptr() + opt.data_size() + ); + } + }; + + 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 struct converter, typename enable_if::value>::type> { template @@ -134,6 +159,40 @@ namespace Internals { } }; + 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<> struct converter > { template @@ -172,7 +231,12 @@ namespace Internals { }; template - struct converter, typename enable_if::value>::type> { + 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)) diff --git a/include/pppoe.h b/include/pppoe.h index 7ab729b..94bb798 100644 --- a/include/pppoe.h +++ b/include/pppoe.h @@ -90,6 +90,8 @@ public: vendor_spec_type(uint32_t vendor_id = 0, const data_type &data = data_type()) : vendor_id(vendor_id), data(data) { } + + static vendor_spec_type from_option(const tag &opt); }; /** @@ -397,19 +399,11 @@ private: } template - T retrieve_tag_iterable(TagTypes id) const { - const tag *tag = search_tag(id); - if(!tag) + T search_and_convert(TagTypes id) const { + const tag *t = search_tag(id); + if(!t) throw option_not_found(); - return T(tag->data_ptr(), tag->data_ptr() + tag->data_size()); - } - - template