diff --git a/include/radiotap.h b/include/radiotap.h index fe702ab..ef08d7b 100644 --- a/include/radiotap.h +++ b/include/radiotap.h @@ -32,6 +32,59 @@ namespace Tins { */ class RadioTap : public PDU { public: + /** + * \brief Enumeration of the different channel type flags. + * + * These channel type flags can be OR'd and set using the + * RadioTap::channel() method. + */ + enum ChannelType { + TURBO = 0x10, + CCK = 0x20, + OFDM = 0x40, + TWO_GZ = 0x80, + FIVE_GZ = 0x100, + PASSIVE = 0x200, + DYN_CCK_OFDM = 0x400, + GFSK = 0x800 + }; + + /** + * \brief Flags used in the present field. + * + * \sa RadioTap::present() + */ + enum PresentFlags { + TSTF = 1, + FLAGS = 2, + RATE = 4, + CHANNEL = 8, + FHSS = 16, + DBM_SIGNAL = 32, + DBM_NOISE = 64, + LOCK_QUALITY = 128, + TX_ATTENUATION = 256, + DB_TX_ATTENUATION = 512, + DBM_TX_ATTENUATION = 1024, + ANTENNA = 2048, + DB_SIGNAL = 4096, + DB_NOISE = 8192, + RX_FLAGS = 16382 + }; + + /** + * \brief Flags used in the RadioTap::flags() method. + */ + enum FrameFlags { + CFP = 1, + PREAMBLE = 2, + WEP = 4, + FRAGMENTATION = 8, + FCS = 16, + PADDING = 32, + FAILED_FCS = 64 + }; + /** * \brief Creates an instance of RadioTap. * \param iface The name of the interface in which to send this PDU. @@ -87,7 +140,7 @@ namespace Tins { * \brief Setter for the flags field. * \param new_flags The new flags. */ - void flags(uint8_t new_flags); + void flags(FrameFlags new_flags); /** * \brief Setter for the rate field. @@ -150,7 +203,7 @@ namespace Tins { * \brief Getter for the flags field. * \return The flags field. */ - inline uint8_t flags() const { return _flags; } + inline FrameFlags flags() const { return (FrameFlags)_flags; } /** * \brief Getter for the rate field. @@ -188,6 +241,16 @@ namespace Tins { */ inline uint16_t rx_flags() const { return _rx_flags; } + /** + * \brief Getter for the present bit fields. + * + * Use this method and masks created from the values taken from + * the PresentFlags enum to find out which fields are set. If any + * getter is used for a non-initialized field, the return value + * will be undefined. It is only safe to use the getter of a field + * if its corresponding bit flag is set in the present field. + */ + PresentFlags present() const { return (PresentFlags)*(uint32_t*)(&_radio.it_len + 1); } /** * \brief Returns the RadioTap frame's header length. @@ -210,10 +273,10 @@ namespace Tins { PDUType pdu_type() const { return PDU::RADIOTAP; } private: struct radiotap_hdr { - u_int8_t it_version; - u_int8_t it_pad; - u_int16_t it_len; - u_int32_t tsft:1, + uint8_t it_version; + uint8_t it_pad; + uint16_t it_len; + uint32_t tsft:1, flags:1, rate:1, channel:1, @@ -236,6 +299,7 @@ namespace Tins { void write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *parent); + radiotap_hdr _radio; uint32_t _iface_index, _options_size; // present fields... diff --git a/src/radiotap.cpp b/src/radiotap.cpp index 0a47e36..e129a08 100644 --- a/src/radiotap.cpp +++ b/src/radiotap.cpp @@ -41,29 +41,30 @@ Tins::RadioTap::RadioTap(uint32_t iface_index) : PDU(0xff), _iface_index(iface_i } Tins::RadioTap::RadioTap(const uint8_t *buffer, uint32_t total_sz) : PDU(0xff) { + static const std::string msg("Not enough size for an RadioTap header in the buffer."); if(total_sz < sizeof(_radio)) - throw std::runtime_error("Not enough size for an RadioTap header in the buffer."); + throw std::runtime_error(msg); const uint8_t *buffer_start = buffer; std::memcpy(&_radio, buffer, sizeof(_radio)); buffer += sizeof(_radio); total_sz -= sizeof(_radio); if(_radio.tsft) { if(total_sz < sizeof(_tsft)) - throw std::runtime_error("Not enough size for an RadioTap header in the buffer."); + throw std::runtime_error(msg); memcpy(&_tsft, buffer, sizeof(_tsft)); buffer += sizeof(_tsft); total_sz -= sizeof(_tsft); } if(_radio.flags) { if(total_sz < sizeof(_flags)) - throw std::runtime_error("Not enough size for an RadioTap header in the buffer."); + throw std::runtime_error(msg); memcpy(&_flags, buffer, sizeof(_flags)); buffer += sizeof(_flags); total_sz -= sizeof(_flags); } if(_radio.rate) { if(total_sz < sizeof(_rate)) - throw std::runtime_error("Not enough size for an RadioTap header in the buffer."); + throw std::runtime_error(msg); memcpy(&_rate, buffer, sizeof(_rate)); buffer += sizeof(_rate); total_sz -= sizeof(_rate); @@ -74,7 +75,7 @@ Tins::RadioTap::RadioTap(const uint8_t *buffer, uint32_t total_sz) : PDU(0xff) { total_sz--; } if(total_sz < sizeof(uint32_t)) - throw std::runtime_error("Not enough size for an RadioTap header in the buffer."); + throw std::runtime_error(msg); memcpy(&_channel_freq, buffer, sizeof(_channel_freq)); buffer += sizeof(_channel_freq); memcpy(&_channel_type, buffer, sizeof(_channel_type)); @@ -83,14 +84,14 @@ Tins::RadioTap::RadioTap(const uint8_t *buffer, uint32_t total_sz) : PDU(0xff) { } if(_radio.dbm_signal) { if(total_sz < sizeof(_dbm_signal)) - throw std::runtime_error("Not enough size for an RadioTap header in the buffer."); + throw std::runtime_error(msg); memcpy(&_dbm_signal, buffer, sizeof(_dbm_signal)); buffer += sizeof(_dbm_signal); total_sz -= sizeof(_dbm_signal); } if(_radio.antenna) { if(total_sz < sizeof(_antenna)) - throw std::runtime_error("Not enough size for an RadioTap header in the buffer."); + throw std::runtime_error(msg); memcpy(&_antenna, buffer, sizeof(_antenna)); buffer += sizeof(_antenna); total_sz -= sizeof(_antenna); @@ -101,7 +102,7 @@ Tins::RadioTap::RadioTap(const uint8_t *buffer, uint32_t total_sz) : PDU(0xff) { total_sz--; } if(total_sz < sizeof(_rx_flags)) - throw std::runtime_error("Not enough size for an RadioTap header in the buffer."); + throw std::runtime_error(msg); memcpy(&_rx_flags, buffer, sizeof(_rx_flags)); buffer += sizeof(_rx_flags); total_sz -= sizeof(_rx_flags); @@ -129,8 +130,8 @@ void Tins::RadioTap::tsft(uint64_t new_tsft) { _radio.tsft = 1; } -void Tins::RadioTap::flags(uint8_t new_flags) { - _flags = new_flags; +void Tins::RadioTap::flags(FrameFlags new_flags) { + _flags = (uint8_t)new_flags; if(!_radio.flags) _options_size += sizeof(_flags); _radio.flags = 1;