diff --git a/include/tins/exceptions.h b/include/tins/exceptions.h index be8f0f3..163e056 100644 --- a/include/tins/exceptions.h +++ b/include/tins/exceptions.h @@ -5,14 +5,14 @@ * 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 @@ -55,7 +55,7 @@ class malformed_packet : public std::runtime_error { public: malformed_packet() : std::runtime_error(std::string()) { } - + const char* what() const throw() { return "Malformed packet"; } @@ -68,7 +68,7 @@ class pdu_not_found : public std::runtime_error { public: pdu_not_found() : std::runtime_error(std::string()) { } - + const char* what() const throw() { return "PDU not found"; } @@ -82,18 +82,30 @@ class invalid_interface : public std::runtime_error { public: invalid_interface() : std::runtime_error(std::string()) { } - + const char* what() const throw() { return "Invalid interface"; } }; +/** + * \brief Exception thrown when a field is not present in frame. + */ +class field_not_present : public std::runtime_error { +public: + field_not_present() + : std::runtime_error(std::string()) { } + const char* what() const throw() { + return "Field not present"; + } +}; + /** * \brief Exception thrown when PacketSender fails to open a socket. */ class socket_open_error : public std::runtime_error { public: - socket_open_error(const std::string &msg) + socket_open_error(const std::string &msg) : std::runtime_error(msg) { } }; @@ -102,7 +114,7 @@ public: */ class socket_close_error : public std::runtime_error { public: - socket_close_error(const std::string &msg) + socket_close_error(const std::string &msg) : std::runtime_error(msg) { } }; @@ -111,7 +123,7 @@ public: */ class socket_write_error : public std::runtime_error { public: - socket_write_error(const std::string &msg) + socket_write_error(const std::string &msg) : std::runtime_error(msg) { } }; @@ -127,7 +139,7 @@ public: }; /** - * \brief Exception thrown when an unkown link layer PDU type is + * \brief Exception thrown when an unkown link layer PDU type is * found while sniffing. */ class unknown_link_type : public std::exception { diff --git a/include/tins/radiotap.h b/include/tins/radiotap.h index eb849e5..3f17e21 100644 --- a/include/tins/radiotap.h +++ b/include/tins/radiotap.h @@ -182,13 +182,13 @@ namespace Tins { * \brief Setter for the dbm signal field. * \param new_dbm_signal The new dbm signal. */ - void dbm_signal(uint8_t new_dbm_signal); + void dbm_signal(int8_t new_dbm_signal); /** * \brief Setter for the dbm noise field. * \param new_dbm_noise The new dbm noise. */ - void dbm_noise(uint8_t new_dbm_noise); + void dbm_noise(int8_t new_dbm_noise); /** * \brief Setter for the signal quality field. @@ -220,91 +220,91 @@ namespace Tins { * \brief Getter for the version field. * \return The version field. */ - uint8_t version() const { return _radio.it_version; } + uint8_t version() const; /** * \brief Getter for the padding field. * \return The padding field. */ - uint8_t padding() const { return _radio.it_pad; } + uint8_t padding() const; /** * \brief Getter for the length field. * \return The length field. */ - uint16_t length() const { return Endian::le_to_host(_radio.it_len); } + uint16_t length() const; /** * \brief Getter for the tsft field. * \return The tsft field. */ - uint64_t tsft() const { return Endian::le_to_host(_tsft); } + uint64_t tsft() const; /** * \brief Getter for the flags field. * \return The flags field. */ - FrameFlags flags() const { return (FrameFlags)_flags; } + FrameFlags flags() const; /** * \brief Getter for the rate field. * \return The rate field. */ - uint8_t rate() const { return _rate; } + uint8_t rate() const; /** * \brief Getter for the channel frequency field. * \return The channel frequency field. */ - uint16_t channel_freq() const { return Endian::le_to_host(_channel_freq); } + uint16_t channel_freq() const; /** * \brief Getter for the channel type field. * \return The channel type field. */ - uint16_t channel_type() const { return Endian::le_to_host(_channel_type); } + uint16_t channel_type() const; /** * \brief Getter for the dbm signal field. * \return The dbm signal field. */ - uint8_t dbm_signal() const { return _dbm_signal; } + int8_t dbm_signal() const; /** * \brief Getter for the dbm noise field. * \return The dbm noise field. */ - uint8_t dbm_noise() const { return _dbm_noise; } + int8_t dbm_noise() const; /** * \brief Getter for the signal quality field. * \return The signal quality field. */ - uint16_t signal_quality() const { return _signal_quality; } + uint16_t signal_quality() const; /** * \brief Getter for the antenna field. * \return The antenna field. */ - uint8_t antenna() const { return _antenna; } + uint8_t antenna() const; /** * \brief Getter for the db signal field. * \return The db signal field. */ - uint8_t db_signal() const { return _db_signal; } + uint8_t db_signal() const; /** * \brief Getter for the channel+ field. * \return The channel+ field. */ - uint32_t channel_plus() const { return Endian::le_to_host(_channel_type); } + uint32_t channel_plus() const; /** * \brief Getter for the rx flags field. * \return The rx flags field. */ - uint16_t rx_flags() const { return Endian::le_to_host(_rx_flags); } + uint16_t rx_flags() const; /** * \brief Getter for the present bit fields. @@ -368,7 +368,7 @@ namespace Tins { lock_quality:1, tx_attenuation:1, db_tx_attenuation:1, - dbm_tx_attenuation:1, + dbm_tx_power:1, antenna:1, db_signal:1, db_noise:1, @@ -391,7 +391,7 @@ namespace Tins { reserved3:1, rx_flags:1, db_tx_attenuation:1, - dbm_tx_attenuation:1, + dbm_tx_power:1, antenna:1, db_signal:1, db_noise:1, @@ -429,7 +429,8 @@ namespace Tins { // present fields... uint64_t _tsft; uint16_t _channel_type, _channel_freq, _rx_flags, _signal_quality; - uint8_t _antenna, _flags, _rate, _dbm_signal, _dbm_noise, _channel, _max_power, _db_signal; + uint8_t _antenna, _flags, _rate, _channel, _max_power, _db_signal; + int8_t _dbm_signal, _dbm_noise; }; } diff --git a/src/radiotap.cpp b/src/radiotap.cpp index 7bb1166..6f7dd82 100644 --- a/src/radiotap.cpp +++ b/src/radiotap.cpp @@ -5,14 +5,14 @@ * 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 @@ -70,7 +70,7 @@ RadioTap::RadioTap() init(); } -RadioTap::RadioTap(const uint8_t *buffer, uint32_t total_sz) +RadioTap::RadioTap(const uint8_t *buffer, uint32_t total_sz) { check_size(total_sz, sizeof(_radio)); const uint8_t *buffer_start = buffer; @@ -90,15 +90,15 @@ RadioTap::RadioTap(const uint8_t *buffer, uint32_t total_sz) while(true) { _radio.flags_32 |= *(const uint32_t*)current_flags; - if(current_flags->tsft) + if(current_flags->tsft) read_field(buffer, radiotap_hdr_size, _tsft); - - if(current_flags->flags) + + if(current_flags->flags) read_field(buffer, radiotap_hdr_size, _flags); - if(current_flags->rate) + if(current_flags->rate) read_field(buffer, radiotap_hdr_size, _rate); - + if(current_flags->channel) { if(((buffer - buffer_start) & 1) == 1) { buffer++; @@ -107,20 +107,20 @@ RadioTap::RadioTap(const uint8_t *buffer, uint32_t total_sz) read_field(buffer, radiotap_hdr_size, _channel_freq); read_field(buffer, radiotap_hdr_size, _channel_type); } - + if(current_flags->dbm_signal) read_field(buffer, radiotap_hdr_size, _dbm_signal); - - if(current_flags->dbm_noise) + + if(current_flags->dbm_noise) read_field(buffer, radiotap_hdr_size, _dbm_noise); - - if(current_flags->lock_quality) + + if(current_flags->lock_quality) read_field(buffer, radiotap_hdr_size, _signal_quality); - if(current_flags->antenna) + if(current_flags->antenna) read_field(buffer, radiotap_hdr_size, _antenna); - - if(current_flags->db_signal) + + if(current_flags->db_signal) read_field(buffer, radiotap_hdr_size, _db_signal); if(current_flags->rx_flags) { @@ -164,7 +164,7 @@ RadioTap::RadioTap(const uint8_t *buffer, uint32_t total_sz) throw malformed_packet(); } - if(total_sz) + if(total_sz) inner_pdu(Dot11::from_bytes(buffer, total_sz)); } @@ -177,7 +177,7 @@ void RadioTap::init() { antenna(0); } -// This method finds the extra flags field size, taking into account other +// This method finds the extra flags field size, taking into account other // set of flags that may appear if the "ext" bit is on/. uint32_t RadioTap::find_extra_flag_fields_size(const uint8_t* buffer, uint32_t total_sz) { const flags_type* ptr = (const flags_type*)buffer; @@ -191,10 +191,11 @@ uint32_t RadioTap::find_extra_flag_fields_size(const uint8_t* buffer, uint32_t t return (const uint8_t*)ptr - buffer; } +// Setter for RadioTap fields void RadioTap::version(uint8_t new_version) { _radio.it_version = new_version; } - + void RadioTap::padding(uint8_t new_padding) { _radio.it_pad = new_padding; } @@ -223,12 +224,12 @@ void RadioTap::channel(uint16_t new_freq, uint16_t new_type) { _channel_type = Endian::host_to_le(new_type); _radio.flags.channel = 1; } -void RadioTap::dbm_signal(uint8_t new_dbm_signal) { +void RadioTap::dbm_signal(int8_t new_dbm_signal) { _dbm_signal = new_dbm_signal; _radio.flags.dbm_signal = 1; } -void RadioTap::dbm_noise(uint8_t new_dbm_noise) { +void RadioTap::dbm_noise(int8_t new_dbm_noise) { _dbm_noise = new_dbm_noise; _radio.flags.dbm_noise = 1; } @@ -287,7 +288,7 @@ uint32_t RadioTap::header_size() const { total_bytes += 4 - offset; total_bytes += 8; } - + return sizeof(_radio) + total_bytes; } @@ -296,11 +297,96 @@ uint32_t RadioTap::trailer_size() const { return ((_flags & 0x10) != 0) ? sizeof(uint32_t) : 0; } +// Getter for RadioTap fields +uint8_t RadioTap::version() const { + return _radio.it_version; +} + +uint8_t RadioTap::padding() const { + return _radio.it_pad; +} + +uint16_t RadioTap::length() const { + return Endian::le_to_host(_radio.it_len); +} + +uint64_t RadioTap::tsft() const { + if(!_radio.flags.tsft) + throw field_not_present(); + return Endian::le_to_host(_tsft); +} + +RadioTap::FrameFlags RadioTap::flags() const { + if(!_radio.flags.flags) + throw field_not_present(); + return (FrameFlags)_flags; +} + +uint8_t RadioTap::rate() const { + if(!_radio.flags.rate) + throw field_not_present(); + return _rate; +} + +uint16_t RadioTap::channel_freq() const { + if(!_radio.flags.channel) + throw field_not_present(); + return Endian::le_to_host(_channel_freq); +} + +uint16_t RadioTap::channel_type() const { + if(!_radio.flags.channel) + throw field_not_present(); + return Endian::le_to_host(_channel_type); +} + +int8_t RadioTap::dbm_signal() const { + if(!_radio.flags.dbm_signal) + throw field_not_present(); + return _dbm_signal; +} + +int8_t RadioTap::dbm_noise() const { + if(!_radio.flags.dbm_noise) + throw field_not_present(); + return _dbm_noise; +} + +uint16_t RadioTap::signal_quality() const { + if(!_radio.flags.lock_quality) + throw field_not_present(); + return _signal_quality; +} + +uint8_t RadioTap::antenna() const { + if(!_radio.flags.antenna) + throw field_not_present(); + return _antenna; +} + +uint8_t RadioTap::db_signal() const { + if(!_radio.flags.db_signal) + throw field_not_present(); + return _db_signal; +} + +uint32_t RadioTap::channel_plus() const { + if(!_radio.flags.channel_plus) + throw field_not_present(); + return Endian::le_to_host(_channel_type); +} + +uint16_t RadioTap::rx_flags() const { + if(!_radio.flags.rx_flags) + throw field_not_present(); + return Endian::le_to_host(_rx_flags); +} + #ifndef WIN32 void RadioTap::send(PacketSender &sender, const NetworkInterface &iface) { if(!iface) throw invalid_interface(); - + #if !defined(BSD) && !defined(__FreeBSD_kernel__) struct sockaddr_ll addr; @@ -310,7 +396,7 @@ void RadioTap::send(PacketSender &sender, const NetworkInterface &iface) { addr.sll_protocol = Endian::host_to_be(ETH_P_ALL); addr.sll_halen = 6; addr.sll_ifindex = iface.id(); - + const Tins::Dot11 *wlan = tins_cast(inner_pdu()); if(wlan) { Tins::Dot11::address_type dot11_addr(wlan->addr1()); diff --git a/tests/src/radiotap.cpp b/tests/src/radiotap.cpp index 05694ef..2042a53 100644 --- a/tests/src/radiotap.cpp +++ b/tests/src/radiotap.cpp @@ -81,7 +81,7 @@ TEST_F(RadioTapTest, DefaultConstructor) { EXPECT_EQ(Utils::mhz_to_channel(radio.channel_freq()), 1); EXPECT_EQ(radio.channel_type(), 0xa0U); EXPECT_EQ(radio.tsft(), 0U); - EXPECT_EQ(radio.dbm_signal(), 0xce); + EXPECT_EQ(radio.dbm_signal(), -50); EXPECT_EQ(radio.antenna(), 0); EXPECT_EQ(radio.rx_flags(), 0); } @@ -100,11 +100,11 @@ TEST_F(RadioTapTest, ConstructorFromBuffer) { EXPECT_TRUE(radio.present() & RadioTap::CHANNEL_PLUS); EXPECT_TRUE(radio.flags() & RadioTap::FCS); - EXPECT_EQ(radio.channel_type(), 0x140); - EXPECT_EQ(radio.channel_freq(), 5180); + EXPECT_THROW(radio.channel_type(), field_not_present); + EXPECT_THROW(radio.channel_freq(), field_not_present); EXPECT_EQ(radio.tsft(), 616089172U); - EXPECT_EQ(radio.dbm_signal(), 0xda); - EXPECT_EQ(radio.dbm_noise(), 0xa0); + EXPECT_EQ(radio.dbm_signal(), -38); + EXPECT_EQ(radio.dbm_noise(), -96); EXPECT_EQ(radio.antenna(), 2); } @@ -132,7 +132,7 @@ TEST_F(RadioTapTest, ConstructorFromBuffer2) { EXPECT_EQ(radio.length(), 34); EXPECT_EQ(radio.rate(), 0x12); EXPECT_EQ(radio.flags(), 0x02); - EXPECT_EQ(radio.dbm_signal(), 0xb9); + EXPECT_EQ(radio.dbm_signal(), -71); EXPECT_EQ(radio.channel_type(), 192); EXPECT_EQ(radio.channel_freq(), 2447); EXPECT_EQ(radio.antenna(), 0); @@ -148,7 +148,7 @@ TEST_F(RadioTapTest, ConstructorFromBuffer3) { EXPECT_TRUE(radio.present() & RadioTap::RX_FLAGS); EXPECT_EQ(0, radio.antenna()); - EXPECT_EQ(0xb5, radio.dbm_signal()); + EXPECT_EQ(-75, radio.dbm_signal()); EXPECT_TRUE(radio.find_pdu()); }