From 3aaa895321b27e7a8701a75ff253d01bd5662e2d Mon Sep 17 00:00:00 2001 From: Matias Fontanini Date: Mon, 22 Aug 2011 22:58:50 -0300 Subject: [PATCH] RadioTap is working. Added the flag field, implemented several flags' setters. --- include/radiotap.h | 129 +++++++++++++++++++++++++++++++++++++++++---- src/radiotap.cpp | 101 +++++++++++++++++++++++++++++++++-- 2 files changed, 217 insertions(+), 13 deletions(-) diff --git a/include/radiotap.h b/include/radiotap.h index 56088ea..e620d8e 100644 --- a/include/radiotap.h +++ b/include/radiotap.h @@ -70,10 +70,47 @@ namespace Tins { void length(uint8_t new_length); /** - * \brief Setter for the present field. - * \param new_present The new present. + * \brief Setter for the TSFT field. + * \param new_tsft The new TSFT */ - void present(uint8_t new_present); + void tsft(uint64_t new_tsft); + + /** + * \brief Setter for the flags field. + * \param new_flags The new flags. + */ + void flags(uint8_t new_flags); + + /** + * \brief Setter for the rate field. + * \param new_rate The new rate. + */ + void rate(uint8_t new_rate); + + /** + * \brief Setter for the channel frequency and type field. + * \param new_freq The new channel frequency. + * \param new_type The new channel type. + */ + void channel(uint16_t new_freq, uint16_t new_type); + + /** + * \brief Setter for the dbm signal field. + * \param new_dbm_signal The new dbm signal. + */ + void dbm_signal(uint8_t new_dbm_signal); + + /** + * \brief Setter for the antenna field. + * \param new_antenna The antenna signal. + */ + void antenna(uint8_t new_antenna); + + /** + * \brief Setter for the rx flag field. + * \param new_rx_flag The antenna signal. + */ + void rx_flag(uint16_t new_rx_flag); /* Getters */ @@ -96,19 +133,68 @@ namespace Tins { inline uint8_t length() const { return _radio.it_len; } /** - * \brief Getter for the present field. - * \return The present field. + * \brief Getter for the tsft field. + * \return The tsft field. */ - inline uint8_t present() const { return _radio.it_present; } + inline uint64_t tsft() const { return _tsft; } /** - * \brief Returns the 802.11 frame's header length. + * \brief Getter for the flags field. + * \return The flags field. + */ + inline uint8_t flags() const { return _flags; } + + /** + * \brief Getter for the rate field. + * \return The rate field. + */ + inline uint8_t rate() const { return _rate; } + + /** + * \brief Getter for the channel frequency field. + * \return The channel frequency field. + */ + inline uint16_t channel_freq() const { return _channel_freq; } + + /** + * \brief Getter for the channel type field. + * \return The channel type field. + */ + inline uint16_t channel_type() const { return _channel_type; } + + /** + * \brief Getter for the dbm signal field. + * \return The dbm signal field. + */ + inline uint8_t dbm_signal() const { return _dbm_signal; } + + /** + * \brief Getter for the antenna field. + * \return The antenna field. + */ + inline uint8_t antenna() const { return _antenna; } + + /** + * \brief Getter for the rx flags field. + * \return The rx flags field. + */ + inline uint16_t rx_flags() const { return _rx_flags; } + + + /** + * \brief Returns the RadioTap frame's header length. * * \return An uint32_t with the header's size. * \sa PDU::header_size() */ uint32_t header_size() const; + /** + * \brief Returns the frame's trailer size. + * \return The trailer's size. + */ + uint32_t trailer_size() const; + /** * \brief Getter for the PDU's type. * \sa PDU::pdu_type @@ -119,13 +205,38 @@ namespace Tins { u_int8_t it_version; u_int8_t it_pad; u_int16_t it_len; - u_int32_t it_present; + u_int32_t tsft:1, + flags:1, + rate:1, + channel:1, + fhss:1, + dbm_signal:1, + dbm_noise:1, + lock_quality:1, + tx_attenuation:1, + db_tx_attenuation:1, + dbm_tx_attenuation:1, + antenna:1, + db_signal:1, + db_noise:1, + rx_flags:1, + reserved1:3, + channel_plus:1, + reserved2:12, + ext:1; } __attribute__((__packed__)); void write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *parent); radiotap_hdr _radio; - uint32_t _iface_index; + uint32_t _iface_index, _options_size; + // present fields... + uint64_t _tsft; + uint8_t _flags, _rate; + uint16_t _channel_freq, _channel_type; + uint8_t _dbm_signal; + uint8_t _antenna; + uint16_t _rx_flags; }; }; #endif diff --git a/src/radiotap.cpp b/src/radiotap.cpp index d3274cf..a1826e0 100644 --- a/src/radiotap.cpp +++ b/src/radiotap.cpp @@ -30,7 +30,7 @@ #include "utils.h" -Tins::RadioTap::RadioTap(const std::string &iface) throw (std::runtime_error) : PDU(0xff) { +Tins::RadioTap::RadioTap(const std::string &iface) throw (std::runtime_error) : PDU(0xff), _options_size(0) { if(!Utils::interface_id(iface, _iface_index)) throw std::runtime_error("Invalid interface name!"); std::memset(&_radio, 0, sizeof(_radio)); @@ -52,12 +52,67 @@ void Tins::RadioTap::length(uint8_t new_length) { _radio.it_len = new_length; } -void Tins::RadioTap::present(uint8_t new_present) { - _radio.it_present = new_present; +void Tins::RadioTap::tsft(uint64_t new_tsft) { + _tsft = new_tsft; + if(!_radio.tsft) + _options_size += sizeof(_tsft); + _radio.tsft = 1; +} + +void Tins::RadioTap::flags(uint8_t new_flags) { + _flags = new_flags; + if(!_radio.flags) + _options_size += sizeof(_flags); + _radio.flags = 1; +} + +void Tins::RadioTap::rate(uint8_t new_rate) { + _rate = new_rate; + if(!_radio.rate) + _options_size += sizeof(uint8_t); + _radio.rate = 1; +} + +void Tins::RadioTap::channel(uint16_t new_freq, uint16_t new_type) { + _channel_freq = new_freq; + _channel_type = new_type; + if(!_radio.channel) + _options_size += sizeof(_channel_freq) + sizeof(_channel_type); + _radio.channel = 1; +} +void Tins::RadioTap::dbm_signal(uint8_t new_dbm_signal) { + _dbm_signal = new_dbm_signal; + if(!_radio.dbm_signal) + _options_size += sizeof(_dbm_signal); + _radio.dbm_signal = 1; +} + +void Tins::RadioTap::antenna(uint8_t new_antenna) { + _antenna = new_antenna; + if(!_radio.antenna) + _options_size += sizeof(_antenna); + _radio.antenna = 1; +} + +void Tins::RadioTap::rx_flag(uint16_t new_rx_flag) { + _rx_flags = new_rx_flag; + if(!_radio.rx_flags) + _options_size += sizeof(_rx_flags); + _radio.rx_flags = 1; } uint32_t Tins::RadioTap::header_size() const { - return sizeof(_radio); + uint8_t padding = 0; + if((_radio.flags ^ _radio.rate) == 1) + padding++; + if((_radio.dbm_signal ^ _radio.antenna) == 1) + padding++; + return sizeof(_radio) + _options_size + padding; +} + +uint32_t Tins::RadioTap::trailer_size() const { + // will be sizeof(uint32_t) if the FCS-at-the-end bit is on. + return ((_radio.flags & 0x10) == 1) ? sizeof(uint32_t) : 0; } bool Tins::RadioTap::send(PacketSender* sender) { @@ -79,8 +134,46 @@ bool Tins::RadioTap::send(PacketSender* sender) { void Tins::RadioTap::write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *parent) { uint32_t sz = header_size(); + uint8_t *buffer_start = buffer; assert(total_sz >= sz); if(!_radio.it_len) _radio.it_len = sz; memcpy(buffer, &_radio, sizeof(_radio)); + buffer += sizeof(_radio); + if(_radio.tsft) { + memcpy(buffer, &_tsft, sizeof(_tsft)); + buffer += sizeof(_tsft); + } + if(_radio.flags) { + memcpy(buffer, &_flags, sizeof(_flags)); + buffer += sizeof(_flags); + } + if(_radio.rate) { + memcpy(buffer, &_rate, sizeof(_rate)); + buffer += sizeof(_rate); + } + if(_radio.channel) { + if(((buffer_start - buffer) & 1) == 1) + *(buffer++) = 0; + memcpy(buffer, &_channel_freq, sizeof(_channel_freq)); + buffer += sizeof(_channel_freq); + memcpy(buffer, &_channel_type, sizeof(_channel_type)); + buffer += sizeof(_channel_type); + } + if(_radio.dbm_signal) { + memcpy(buffer, &_dbm_signal, sizeof(_dbm_signal)); + buffer += sizeof(_dbm_signal); + } + if(_radio.antenna) { + memcpy(buffer, &_antenna, sizeof(_antenna)); + buffer += sizeof(_antenna); + } + if(_radio.rx_flags) { + if(((buffer_start - buffer) & 1) == 1) + *(buffer++) = 0; + memcpy(buffer, &_rx_flags, sizeof(_rx_flags)); + buffer += sizeof(_rx_flags); + } + if((_radio.flags & 0x10) == 1 && inner_pdu()) + *(uint32_t*)(buffer + inner_pdu()->size()) = Utils::crc32(buffer, inner_pdu()->size()); }