From 9750f46c6dd93eeb723cee95b2c8df54978052af Mon Sep 17 00:00:00 2001 From: Matias Fontanini Date: Fri, 25 Dec 2015 06:30:27 -0800 Subject: [PATCH] Port all PDUs to use InputMemoryStream on constructors from buffer --- include/tins/dot11/dot11_base.h | 6 +- include/tins/memory_helpers.h | 10 + include/tins/radiotap.h | 938 ++++++++++++++++---------------- src/dot11/dot11_assoc.cpp | 74 +-- src/dot11/dot11_auth.cpp | 29 +- src/dot11/dot11_base.cpp | 31 +- src/dot11/dot11_beacon.cpp | 16 +- src/dot11/dot11_control.cpp | 52 +- src/dot11/dot11_data.cpp | 64 +-- src/dot11/dot11_mgmt.cpp | 25 +- src/dot11/dot11_probe.cpp | 26 +- src/ipv6.cpp | 52 +- src/llc.cpp | 52 +- src/loopback.cpp | 21 +- src/pktap.cpp | 23 +- src/ppi.cpp | 39 +- src/pppoe.cpp | 46 +- src/radiotap.cpp | 3 +- src/rsn_information.cpp | 75 +-- src/sll.cpp | 17 +- src/snap.cpp | 34 +- src/stp.cpp | 8 +- src/udp.cpp | 19 +- 23 files changed, 786 insertions(+), 874 deletions(-) diff --git a/include/tins/dot11/dot11_base.h b/include/tins/dot11/dot11_base.h index 2888054..a17fc36 100644 --- a/include/tins/dot11/dot11_base.h +++ b/include/tins/dot11/dot11_base.h @@ -42,6 +42,10 @@ #include "../macros.h" namespace Tins { +namespace Memory { +class InputMemoryStream; +} // Memory + class RSNInformation; /** @@ -477,7 +481,7 @@ public: protected: virtual uint32_t write_ext_header(uint8_t *buffer, uint32_t total_sz) { return 0; } virtual uint32_t write_fixed_parameters(uint8_t *buffer, uint32_t total_sz) { return 0; } - void parse_tagged_parameters(const uint8_t *buffer, uint32_t total_sz); + void parse_tagged_parameters(Memory::InputMemoryStream& stream); void add_tagged_option(OptionTypes opt, uint8_t len, const uint8_t *val); protected: /** diff --git a/include/tins/memory_helpers.h b/include/tins/memory_helpers.h index d705482..8a9a5f1 100644 --- a/include/tins/memory_helpers.h +++ b/include/tins/memory_helpers.h @@ -6,6 +6,7 @@ #include "exceptions.h" #include "ip_address.h" #include "ipv6_address.h" +#include "hw_address.h" namespace Tins { namespace Memory { @@ -67,6 +68,15 @@ public: skip(IPv6Address::address_size); } + template + void read(HWAddress& address) { + if (!can_read(HWAddress::address_size)) { + throw malformed_packet(); + } + address = pointer(); + skip(HWAddress::address_size); + } + void read(void* output_buffer, uint32_t output_buffer_size) { if (!can_read(output_buffer_size)) { throw malformed_packet(); diff --git a/include/tins/radiotap.h b/include/tins/radiotap.h index be1811b..805da11 100644 --- a/include/tins/radiotap.h +++ b/include/tins/radiotap.h @@ -37,478 +37,478 @@ #include "endianness.h" namespace Tins { - class PacketSender; - - /** - * \brief Class that represents the IEEE 802.11 radio tap header. - * - * By default, RadioTap PDUs set the necesary fields to send an 802.11 - * PDU as its inner pdu, avoiding packet drops. As a consequence, - * the FCS-at-end flag is on, the channel is set to 1, TSFT is set to 0, - * dbm_signal is set to -50, and the rx_flag and antenna fields to 0. +class PacketSender; + +/** + * \brief Class that represents the IEEE 802.11 radio tap header. + * + * By default, RadioTap PDUs set the necesary fields to send an 802.11 + * PDU as its inner pdu, avoiding packet drops. As a consequence, + * the FCS-at-end flag is on, the channel is set to 1, TSFT is set to 0, + * dbm_signal is set to -50, and the rx_flag and antenna fields to 0. + */ +class RadioTap : public PDU { +public: + /** + * \brief This PDU's flag. */ - class RadioTap : public PDU { - public: - /** - * \brief This PDU's flag. - */ - static const PDU::PDUType pdu_flag = PDU::RADIOTAP; - - /** - * \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 << 0, - FLAGS = 1 << 1, - RATE = 1 << 2, - CHANNEL = 1 << 3, - FHSS = 1 << 4, - DBM_SIGNAL = 1 << 5, - DBM_NOISE = 1 << 6, - LOCK_QUALITY = 1 << 7, - TX_ATTENUATION = 1 << 8, - DB_TX_ATTENUATION = 1 << 9, - DBM_TX_ATTENUATION = 1 << 10, - ANTENNA = 1 << 11, - DB_SIGNAL = 1 << 12, - DB_NOISE = 1 << 13, - RX_FLAGS = 1 << 14, - TX_FLAGS = 1 << 15, - DATA_RETRIES = 1 << 17, - CHANNEL_PLUS = 1 << 18, - MCS = 1 << 19 - }; - - /** - * \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, - SHORT_GI = 128 - }; + static const PDU::PDUType pdu_flag = PDU::RADIOTAP; - /** - * \brief The type used to represent the MCS flags field - */ - TINS_BEGIN_PACK - struct mcs_type { - uint8_t known; - uint8_t flags; - uint8_t mcs; - } TINS_END_PACK; - - /** - * \brief Default constructor. - */ - RadioTap(); - - /** - * \brief Constructs a RadioTap object from a buffer and adds all - * identifiable PDUs found in the buffer as children of this one. - * - * If there is not enough size for a RadioTap header, a - * malformed_packet exception is thrown. - * - * \param buffer The buffer from which this PDU will be constructed. - * \param total_sz The total size of the buffer. - */ - RadioTap(const uint8_t *buffer, uint32_t total_sz); - - /* Setters */ - - #ifndef _WIN32 - /** - * \sa PDU::send() - */ - void send(PacketSender &sender, const NetworkInterface &iface); - #endif - - /** - * \brief Setter for the version field. - * \param new_version The new version. - */ - void version(uint8_t new_version); - - /** - * \brief Setter for the padding field. - * \param new_padding The new padding. - */ - void padding(uint8_t new_padding); - - /** - * \brief Setter for the length field. - * \param new_length The new length. - */ - void length(uint16_t new_length); - - /** - * \brief Setter for the TSFT field. - * \param new_tsft The new TSFT - */ - void tsft(uint64_t new_tsft); - - /** - * \brief Setter for the flags field. - * \param new_flags The new flags. - */ - void flags(FrameFlags 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(int8_t new_dbm_signal); - - /** - * \brief Setter for the dbm noise field. - * \param new_dbm_noise The new dbm noise. - */ - void dbm_noise(int8_t new_dbm_noise); - - /** - * \brief Setter for the signal quality field. - * \param new_antenna The signal quality signal. - */ - void signal_quality(uint8_t new_signal_quality); - - /** - * \brief Setter for the antenna field. - * \param new_antenna The antenna signal. - */ - void antenna(uint8_t new_antenna); - - /** - * \brief Setter for the db signal field. - * \param new_antenna The db signal signal. - */ - void db_signal(uint8_t new_db_signal); - - /** - * \brief Setter for the rx flag field. - * \param new_rx_flag The rx flags. - */ - void rx_flags(uint16_t new_rx_flag); - - /** - * \brief Setter for the tx flag field. - * \param new_tx_flag The tx flags. - */ - void tx_flags(uint16_t new_tx_flag); - - /** - * \brief Setter for the data retries field. - * \param new_rx_flag The data retries. - */ - void data_retries(uint8_t new_data_retries); - - /** - * \brief Setter for the MCS field. - * \param new_rx_flag The MCS retries. - */ - void mcs(const mcs_type& new_mcs); - - /* Getters */ - - /** - * \brief Getter for the version field. - * \return The version field. - */ - uint8_t version() const; - - /** - * \brief Getter for the padding field. - * \return The padding field. - */ - uint8_t padding() const; - - /** - * \brief Getter for the length field. - * \return The length field. - */ - uint16_t length() const; - - /** - * \brief Getter for the tsft field. - * \return The tsft field. - */ - uint64_t tsft() const; - - /** - * \brief Getter for the flags field. - * \return The flags field. - */ - FrameFlags flags() const; - - /** - * \brief Getter for the rate field. - * \return The rate field. - */ - uint8_t rate() const; - - /** - * \brief Getter for the channel frequency field. - * \return The channel frequency field. - */ - uint16_t channel_freq() const; - - /** - * \brief Getter for the channel type field. - * \return The channel type field. - */ - uint16_t channel_type() const; - - /** - * \brief Getter for the dbm signal field. - * \return The dbm signal field. - */ - int8_t dbm_signal() const; - - /** - * \brief Getter for the dbm noise field. - * \return The dbm noise field. - */ - int8_t dbm_noise() const; - - /** - * \brief Getter for the signal quality field. - * \return The signal quality field. - */ - uint16_t signal_quality() const; - - /** - * \brief Getter for the antenna field. - * \return The antenna field. - */ - uint8_t antenna() const; - - /** - * \brief Getter for the db signal field. - * \return The db signal field. - */ - uint8_t db_signal() const; - - /** - * \brief Getter for the channel+ field. - * \return The channel+ field. - */ - uint32_t channel_plus() const; - - /** - * \brief Getter for the data retries field - * \return The data retries field. - */ - uint8_t data_retries() const; - - /** - * \brief Getter for the rx flags field. - * \return The rx flags field. - */ - uint16_t rx_flags() const; - - /** - * \brief Getter for the tx flags field. - * \return The tx flags field. - */ - uint16_t tx_flags() const; - - /** - * \brief Getter for the MCS field. - * \return The MCS field. - */ - mcs_type mcs() const; - - /** - * \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. - * Accessing non-initialized fields, the behaviour is undefined - * 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); - return (PresentFlags)Endian::le_to_host(_radio.flags_32); - } - - /** \brief Check wether ptr points to a valid response for this PDU. - * - * \sa PDU::matches_response - * \param ptr The pointer to the buffer. - * \param total_sz The size of the buffer. - */ - bool matches_response(const uint8_t *ptr, uint32_t total_sz) const; - - /** - * \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; - - /** - * \sa PDU::clone - */ - RadioTap *clone() const { - return new RadioTap(*this); - } - - /** - * \brief Getter for the PDU's type. - * \sa PDU::pdu_type - */ - PDUType pdu_type() const { return PDU::RADIOTAP; } - private: - TINS_BEGIN_PACK - #if TINS_IS_LITTLE_ENDIAN - struct flags_type { - uint32_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_power:1, - antenna:1, - db_signal:1, - db_noise:1, - rx_flags:1, - tx_flags:1, - - reserved1:1, - data_retries:1, - channel_plus:1, - mcs:1, - reserved2:4, - - reserved3:7, - ext:1; - } TINS_END_PACK; - #else - struct flags_type { - uint32_t - lock_quality:1, - dbm_noise:1, - dbm_signal:1, - fhss:1, - channel:1, - rate:1, - flags:1, - tsft:1, - - tx_flags:1, - rx_flags:1, - db_noise:1, - db_signal:1, - antenna:1, - dbm_tx_power:1, - db_tx_attenuation:1, - tx_attenuation:1, - - reserved2:4, - mcs:1, - channel_plus:1, - data_retries:1, - reserved1:1, - - ext:1, - reserved3:7; - } TINS_END_PACK; - #endif - - TINS_BEGIN_PACK - struct radiotap_hdr { - #if TINS_IS_LITTLE_ENDIAN - uint8_t it_version; - uint8_t it_pad; - #else - uint8_t it_pad; - uint8_t it_version; - #endif // TINS_IS_LITTLE_ENDIAN - uint16_t it_len; - union { - flags_type flags; - uint32_t flags_32; - }; - } TINS_END_PACK; - - void init(); - void write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *parent); - uint32_t find_extra_flag_fields_size(const uint8_t* buffer, uint32_t total_sz); - - template - void align_buffer(const uint8_t* buffer_start, const uint8_t*& buffer, uint32_t& size) { - uint32_t offset = ((buffer - buffer_start) % n); - if(offset) { - offset = n - offset; - if (offset > size) { - throw malformed_packet(); - } - buffer += offset; - size -= offset; - } - } - - - radiotap_hdr _radio; - // present fields... - uint64_t _tsft; - uint16_t _channel_type, _channel_freq, _rx_flags, _signal_quality, _tx_flags; - mcs_type _mcs; - uint8_t _antenna, _flags, _rate, _channel, _max_power, _db_signal, _data_retries; - int8_t _dbm_signal, _dbm_noise; + /** + * \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 << 0, + FLAGS = 1 << 1, + RATE = 1 << 2, + CHANNEL = 1 << 3, + FHSS = 1 << 4, + DBM_SIGNAL = 1 << 5, + DBM_NOISE = 1 << 6, + LOCK_QUALITY = 1 << 7, + TX_ATTENUATION = 1 << 8, + DB_TX_ATTENUATION = 1 << 9, + DBM_TX_ATTENUATION = 1 << 10, + ANTENNA = 1 << 11, + DB_SIGNAL = 1 << 12, + DB_NOISE = 1 << 13, + RX_FLAGS = 1 << 14, + TX_FLAGS = 1 << 15, + DATA_RETRIES = 1 << 17, + CHANNEL_PLUS = 1 << 18, + MCS = 1 << 19 + }; + + /** + * \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, + SHORT_GI = 128 + }; + + /** + * \brief The type used to represent the MCS flags field + */ + TINS_BEGIN_PACK + struct mcs_type { + uint8_t known; + uint8_t flags; + uint8_t mcs; + } TINS_END_PACK; + + /** + * \brief Default constructor. + */ + RadioTap(); + + /** + * \brief Constructs a RadioTap object from a buffer and adds all + * identifiable PDUs found in the buffer as children of this one. + * + * If there is not enough size for a RadioTap header, a + * malformed_packet exception is thrown. + * + * \param buffer The buffer from which this PDU will be constructed. + * \param total_sz The total size of the buffer. + */ + RadioTap(const uint8_t *buffer, uint32_t total_sz); + + /* Setters */ + + #ifndef _WIN32 + /** + * \sa PDU::send() + */ + void send(PacketSender &sender, const NetworkInterface &iface); + #endif + + /** + * \brief Setter for the version field. + * \param new_version The new version. + */ + void version(uint8_t new_version); + + /** + * \brief Setter for the padding field. + * \param new_padding The new padding. + */ + void padding(uint8_t new_padding); + + /** + * \brief Setter for the length field. + * \param new_length The new length. + */ + void length(uint16_t new_length); + + /** + * \brief Setter for the TSFT field. + * \param new_tsft The new TSFT + */ + void tsft(uint64_t new_tsft); + + /** + * \brief Setter for the flags field. + * \param new_flags The new flags. + */ + void flags(FrameFlags 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(int8_t new_dbm_signal); + + /** + * \brief Setter for the dbm noise field. + * \param new_dbm_noise The new dbm noise. + */ + void dbm_noise(int8_t new_dbm_noise); + + /** + * \brief Setter for the signal quality field. + * \param new_antenna The signal quality signal. + */ + void signal_quality(uint8_t new_signal_quality); + + /** + * \brief Setter for the antenna field. + * \param new_antenna The antenna signal. + */ + void antenna(uint8_t new_antenna); + + /** + * \brief Setter for the db signal field. + * \param new_antenna The db signal signal. + */ + void db_signal(uint8_t new_db_signal); + + /** + * \brief Setter for the rx flag field. + * \param new_rx_flag The rx flags. + */ + void rx_flags(uint16_t new_rx_flag); + + /** + * \brief Setter for the tx flag field. + * \param new_tx_flag The tx flags. + */ + void tx_flags(uint16_t new_tx_flag); + + /** + * \brief Setter for the data retries field. + * \param new_rx_flag The data retries. + */ + void data_retries(uint8_t new_data_retries); + + /** + * \brief Setter for the MCS field. + * \param new_rx_flag The MCS retries. + */ + void mcs(const mcs_type& new_mcs); + + /* Getters */ + + /** + * \brief Getter for the version field. + * \return The version field. + */ + uint8_t version() const; + + /** + * \brief Getter for the padding field. + * \return The padding field. + */ + uint8_t padding() const; + + /** + * \brief Getter for the length field. + * \return The length field. + */ + uint16_t length() const; + + /** + * \brief Getter for the tsft field. + * \return The tsft field. + */ + uint64_t tsft() const; + + /** + * \brief Getter for the flags field. + * \return The flags field. + */ + FrameFlags flags() const; + + /** + * \brief Getter for the rate field. + * \return The rate field. + */ + uint8_t rate() const; + + /** + * \brief Getter for the channel frequency field. + * \return The channel frequency field. + */ + uint16_t channel_freq() const; + + /** + * \brief Getter for the channel type field. + * \return The channel type field. + */ + uint16_t channel_type() const; + + /** + * \brief Getter for the dbm signal field. + * \return The dbm signal field. + */ + int8_t dbm_signal() const; + + /** + * \brief Getter for the dbm noise field. + * \return The dbm noise field. + */ + int8_t dbm_noise() const; + + /** + * \brief Getter for the signal quality field. + * \return The signal quality field. + */ + uint16_t signal_quality() const; + + /** + * \brief Getter for the antenna field. + * \return The antenna field. + */ + uint8_t antenna() const; + + /** + * \brief Getter for the db signal field. + * \return The db signal field. + */ + uint8_t db_signal() const; + + /** + * \brief Getter for the channel+ field. + * \return The channel+ field. + */ + uint32_t channel_plus() const; + + /** + * \brief Getter for the data retries field + * \return The data retries field. + */ + uint8_t data_retries() const; + + /** + * \brief Getter for the rx flags field. + * \return The rx flags field. + */ + uint16_t rx_flags() const; + + /** + * \brief Getter for the tx flags field. + * \return The tx flags field. + */ + uint16_t tx_flags() const; + + /** + * \brief Getter for the MCS field. + * \return The MCS field. + */ + mcs_type mcs() const; + + /** + * \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. + * Accessing non-initialized fields, the behaviour is undefined + * 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); + return (PresentFlags)Endian::le_to_host(_radio.flags_32); + } + + /** \brief Check wether ptr points to a valid response for this PDU. + * + * \sa PDU::matches_response + * \param ptr The pointer to the buffer. + * \param total_sz The size of the buffer. + */ + bool matches_response(const uint8_t *ptr, uint32_t total_sz) const; + + /** + * \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; + + /** + * \sa PDU::clone + */ + RadioTap *clone() const { + return new RadioTap(*this); + } + + /** + * \brief Getter for the PDU's type. + * \sa PDU::pdu_type + */ + PDUType pdu_type() const { return PDU::RADIOTAP; } +private: + TINS_BEGIN_PACK + #if TINS_IS_LITTLE_ENDIAN + struct flags_type { + uint32_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_power:1, + antenna:1, + db_signal:1, + db_noise:1, + rx_flags:1, + tx_flags:1, + + reserved1:1, + data_retries:1, + channel_plus:1, + mcs:1, + reserved2:4, + + reserved3:7, + ext:1; + } TINS_END_PACK; + #else + struct flags_type { + uint32_t + lock_quality:1, + dbm_noise:1, + dbm_signal:1, + fhss:1, + channel:1, + rate:1, + flags:1, + tsft:1, + + tx_flags:1, + rx_flags:1, + db_noise:1, + db_signal:1, + antenna:1, + dbm_tx_power:1, + db_tx_attenuation:1, + tx_attenuation:1, + + reserved2:4, + mcs:1, + channel_plus:1, + data_retries:1, + reserved1:1, + + ext:1, + reserved3:7; + } TINS_END_PACK; + #endif + + TINS_BEGIN_PACK + struct radiotap_hdr { + #if TINS_IS_LITTLE_ENDIAN + uint8_t it_version; + uint8_t it_pad; + #else + uint8_t it_pad; + uint8_t it_version; + #endif // TINS_IS_LITTLE_ENDIAN + uint16_t it_len; + union { + flags_type flags; + uint32_t flags_32; + }; + } TINS_END_PACK; + + void init(); + void write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *parent); + uint32_t find_extra_flag_fields_size(const uint8_t* buffer, uint32_t total_sz); + + template + void align_buffer(const uint8_t* buffer_start, const uint8_t*& buffer, uint32_t& size) { + uint32_t offset = ((buffer - buffer_start) % n); + if(offset) { + offset = n - offset; + if (offset > size) { + throw malformed_packet(); + } + buffer += offset; + size -= offset; + } + } + + + radiotap_hdr _radio; + // present fields... + uint64_t _tsft; + uint16_t _channel_type, _channel_freq, _rx_flags, _signal_quality, _tx_flags; + mcs_type _mcs; + uint8_t _antenna, _flags, _rate, _channel, _max_power, _db_signal, _data_retries; + int8_t _dbm_signal, _dbm_noise; +}; } #endif // TINS_RADIOTAP_H diff --git a/src/dot11/dot11_assoc.cpp b/src/dot11/dot11_assoc.cpp index b2069b0..80260a3 100644 --- a/src/dot11/dot11_assoc.cpp +++ b/src/dot11/dot11_assoc.cpp @@ -32,29 +32,26 @@ #include #include +#include "memory_helpers.h" + +using Tins::Memory::InputMemoryStream; namespace Tins { /* Diassoc */ Dot11Disassoc::Dot11Disassoc(const address_type &dst_hw_addr, const address_type &src_hw_addr) -: Dot11ManagementFrame(dst_hw_addr, src_hw_addr) +: Dot11ManagementFrame(dst_hw_addr, src_hw_addr), _body() { this->subtype(Dot11::DISASSOC); - memset(&_body, 0, sizeof(_body)); } Dot11Disassoc::Dot11Disassoc(const uint8_t *buffer, uint32_t total_sz) : Dot11ManagementFrame(buffer, total_sz) { - uint32_t sz = management_frame_size(); - buffer += sz; - total_sz -= sz; - if(total_sz < sizeof(_body)) - throw malformed_packet(); - memcpy(&_body, buffer, sizeof(_body)); - buffer += sizeof(_body); - total_sz -= sizeof(_body); - parse_tagged_parameters(buffer, total_sz); + InputMemoryStream stream(buffer, total_sz); + stream.skip(management_frame_size()); + stream.read(_body); + parse_tagged_parameters(stream); } void Dot11Disassoc::reason_code(uint16_t new_reason_code) { @@ -78,24 +75,18 @@ uint32_t Dot11Disassoc::write_fixed_parameters(uint8_t *buffer, uint32_t total_s Dot11AssocRequest::Dot11AssocRequest(const address_type &dst_hw_addr, const address_type &src_hw_addr) -: Dot11ManagementFrame(dst_hw_addr, src_hw_addr) +: Dot11ManagementFrame(dst_hw_addr, src_hw_addr), _body() { subtype(Dot11::ASSOC_REQ); - memset(&_body, 0, sizeof(_body)); } Dot11AssocRequest::Dot11AssocRequest(const uint8_t *buffer, uint32_t total_sz) : Dot11ManagementFrame(buffer, total_sz) { - uint32_t sz = management_frame_size(); - buffer += sz; - total_sz -= sz; - if(total_sz < sizeof(_body)) - throw malformed_packet(); - memcpy(&_body, buffer, sizeof(_body)); - buffer += sizeof(_body); - total_sz -= sizeof(_body); - parse_tagged_parameters(buffer, total_sz); + InputMemoryStream stream(buffer, total_sz); + stream.skip(management_frame_size()); + stream.read(_body); + parse_tagged_parameters(stream); } void Dot11AssocRequest::listen_interval(uint16_t new_listen_interval) { @@ -128,15 +119,10 @@ Dot11AssocResponse::Dot11AssocResponse(const address_type &dst_hw_addr, Dot11AssocResponse::Dot11AssocResponse(const uint8_t *buffer, uint32_t total_sz) : Dot11ManagementFrame(buffer, total_sz) { - uint32_t sz = management_frame_size(); - buffer += sz; - total_sz -= sz; - if(total_sz < sizeof(_body)) - throw malformed_packet(); - memcpy(&_body, buffer, sizeof(_body)); - buffer += sizeof(_body); - total_sz -= sizeof(_body); - parse_tagged_parameters(buffer, total_sz); + InputMemoryStream stream(buffer, total_sz); + stream.skip(management_frame_size()); + stream.read(_body); + parse_tagged_parameters(stream); } void Dot11AssocResponse::status_code(uint16_t new_status_code) { @@ -173,15 +159,10 @@ Dot11ReAssocRequest::Dot11ReAssocRequest(const address_type &dst_hw_addr, Dot11ReAssocRequest::Dot11ReAssocRequest(const uint8_t *buffer, uint32_t total_sz) : Dot11ManagementFrame(buffer, total_sz) { - uint32_t sz = management_frame_size(); - buffer += sz; - total_sz -= sz; - if(total_sz < sizeof(_body)) - throw malformed_packet(); - memcpy(&_body, buffer, sizeof(_body)); - buffer += sizeof(_body); - total_sz -= sizeof(_body); - parse_tagged_parameters(buffer, total_sz); + InputMemoryStream stream(buffer, total_sz); + stream.skip(management_frame_size()); + stream.read(_body); + parse_tagged_parameters(stream); } void Dot11ReAssocRequest::listen_interval(uint16_t new_listen_interval) { @@ -217,15 +198,10 @@ Dot11ReAssocResponse::Dot11ReAssocResponse(const address_type &dst_hw_addr, Dot11ReAssocResponse::Dot11ReAssocResponse(const uint8_t *buffer, uint32_t total_sz) : Dot11ManagementFrame(buffer, total_sz) { - uint32_t sz = management_frame_size(); - buffer += sz; - total_sz -= sz; - if(total_sz < sizeof(_body)) - throw malformed_packet(); - memcpy(&_body, buffer, sizeof(_body)); - buffer += sizeof(_body); - total_sz -= sizeof(_body); - parse_tagged_parameters(buffer, total_sz); + InputMemoryStream stream(buffer, total_sz); + stream.skip(management_frame_size()); + stream.read(_body); + parse_tagged_parameters(stream); } void Dot11ReAssocResponse::status_code(uint16_t new_status_code) { diff --git a/src/dot11/dot11_auth.cpp b/src/dot11/dot11_auth.cpp index ea6a275..e9f9321 100644 --- a/src/dot11/dot11_auth.cpp +++ b/src/dot11/dot11_auth.cpp @@ -32,6 +32,9 @@ #include #include +#include "memory_helpers.h" + +using Tins::Memory::InputMemoryStream; namespace Tins { /* Auth */ @@ -47,15 +50,10 @@ const address_type &src_hw_addr) Dot11Authentication::Dot11Authentication(const uint8_t *buffer, uint32_t total_sz) : Dot11ManagementFrame(buffer, total_sz) { - uint32_t sz = management_frame_size(); - buffer += sz; - total_sz -= sz; - if(total_sz < sizeof(_body)) - throw malformed_packet(); - memcpy(&_body, buffer, sizeof(_body)); - buffer += sizeof(_body); - total_sz -= sizeof(_body); - parse_tagged_parameters(buffer, total_sz); + InputMemoryStream stream(buffer, total_sz); + stream.skip(management_frame_size()); + stream.read(_body); + parse_tagged_parameters(stream); } void Dot11Authentication::auth_algorithm(uint16_t new_auth_algorithm) { @@ -95,15 +93,10 @@ Dot11Deauthentication::Dot11Deauthentication(const address_type &dst_hw_addr, Dot11Deauthentication::Dot11Deauthentication(const uint8_t *buffer, uint32_t total_sz) : Dot11ManagementFrame(buffer, total_sz) { - uint32_t sz = management_frame_size(); - buffer += sz; - total_sz -= sz; - if(total_sz < sizeof(_body)) - throw malformed_packet(); - memcpy(&_body, buffer, sizeof(_body)); - buffer += sizeof(_body); - total_sz -= sizeof(_body); - parse_tagged_parameters(buffer, total_sz); + InputMemoryStream stream(buffer, total_sz); + stream.skip(management_frame_size()); + stream.read(_body); + parse_tagged_parameters(stream); } void Dot11Deauthentication::reason_code(uint16_t new_reason_code) { diff --git a/src/dot11/dot11_base.cpp b/src/dot11/dot11_base.cpp index eb65746..aa6e958 100644 --- a/src/dot11/dot11_base.cpp +++ b/src/dot11/dot11_base.cpp @@ -54,14 +54,16 @@ #include "rsn_information.h" #include "packet_sender.h" #include "snap.h" +#include "memory_helpers.h" + +using Tins::Memory::InputMemoryStream; namespace Tins { const Dot11::address_type Dot11::BROADCAST = "ff:ff:ff:ff:ff:ff"; Dot11::Dot11(const address_type &dst_hw_addr) -: _options_size(0) +: _header(), _options_size(0) { - memset(&_header, 0, sizeof(ieee80211_header)); addr1(dst_hw_addr); } @@ -73,25 +75,20 @@ Dot11::Dot11(const ieee80211_header *header_ptr) Dot11::Dot11(const uint8_t *buffer, uint32_t total_sz) : _options_size(0) { - if(total_sz < sizeof(_header)) - throw malformed_packet(); - std::memcpy(&_header, buffer, sizeof(_header)); + InputMemoryStream stream(buffer, total_sz); + stream.read(_header); } -void Dot11::parse_tagged_parameters(const uint8_t *buffer, uint32_t total_sz) { - if(total_sz > 0) { - uint8_t opcode, length; - while(total_sz >= 2) { - opcode = buffer[0]; - length = buffer[1]; - buffer += 2; - total_sz -= 2; - if(length > total_sz) { +void Dot11::parse_tagged_parameters(InputMemoryStream& stream) { + if (stream) { + while (stream.size() >= 2) { + OptionTypes opcode = static_cast(stream.read()); + uint8_t length = stream.read(); + if (!stream.can_read(length)) { throw malformed_packet(); } - add_tagged_option((OptionTypes)opcode, length, buffer); - buffer += length; - total_sz -= length; + add_tagged_option(opcode, length, stream.pointer()); + stream.skip(length); } } } diff --git a/src/dot11/dot11_beacon.cpp b/src/dot11/dot11_beacon.cpp index 0c64433..b4c0e4d 100644 --- a/src/dot11/dot11_beacon.cpp +++ b/src/dot11/dot11_beacon.cpp @@ -32,6 +32,9 @@ #include #include +#include "memory_helpers.h" + +using Tins::Memory::InputMemoryStream; namespace Tins { /* Dot11Beacon */ @@ -47,15 +50,10 @@ const address_type &src_hw_addr) Dot11Beacon::Dot11Beacon(const uint8_t *buffer, uint32_t total_sz) : Dot11ManagementFrame(buffer, total_sz) { - uint32_t sz = management_frame_size(); - buffer += sz; - total_sz -= sz; - if(total_sz < sizeof(_body)) - throw malformed_packet(); - std::memcpy(&_body, buffer, sizeof(_body)); - buffer += sizeof(_body); - total_sz -= sizeof(_body); - parse_tagged_parameters(buffer, total_sz); + InputMemoryStream stream(buffer, total_sz); + stream.skip(management_frame_size()); + stream.read(_body); + parse_tagged_parameters(stream); } void Dot11Beacon::timestamp(uint64_t new_timestamp) { diff --git a/src/dot11/dot11_control.cpp b/src/dot11/dot11_control.cpp index facf1b7..06e43fe 100644 --- a/src/dot11/dot11_control.cpp +++ b/src/dot11/dot11_control.cpp @@ -32,6 +32,9 @@ #include #include +#include "memory_helpers.h" + +using Tins::Memory::InputMemoryStream; namespace Tins { /* Dot11Control */ @@ -57,12 +60,9 @@ Dot11ControlTA::Dot11ControlTA(const address_type &dst_addr, } Dot11ControlTA::Dot11ControlTA(const uint8_t *buffer, uint32_t total_sz) : Dot11Control(buffer, total_sz) { - buffer += sizeof(ieee80211_header); - total_sz -= sizeof(ieee80211_header); - if(total_sz < sizeof(_taddr)) - throw malformed_packet(); - //std::memcpy(_taddr, buffer, sizeof(_taddr)); - _taddr = buffer; + InputMemoryStream stream(buffer, total_sz); + stream.skip(sizeof(ieee80211_header)); + stream.read(_taddr); } uint32_t Dot11ControlTA::header_size() const { @@ -164,14 +164,10 @@ Dot11BlockAckRequest::Dot11BlockAckRequest(const address_type &dst_addr, Dot11BlockAckRequest::Dot11BlockAckRequest(const uint8_t *buffer, uint32_t total_sz) : Dot11ControlTA(buffer, total_sz) { - uint32_t padding = controlta_size(); - buffer += padding; - total_sz -= padding; - if(total_sz < sizeof(_bar_control) + sizeof(_start_sequence)) - throw malformed_packet(); - std::memcpy(&_bar_control, buffer, sizeof(_bar_control)); - buffer += sizeof(_bar_control); - std::memcpy(&_start_sequence, buffer, sizeof(_start_sequence)); + InputMemoryStream stream(buffer, total_sz); + stream.skip(controlta_size()); + stream.read(_bar_control); + stream.read(_start_sequence); } void Dot11BlockAckRequest::init_block_ack() { @@ -228,16 +224,11 @@ Dot11BlockAck::Dot11BlockAck(const address_type &dst_addr, } Dot11BlockAck::Dot11BlockAck(const uint8_t *buffer, uint32_t total_sz) : Dot11ControlTA(buffer, total_sz) { - uint32_t padding = controlta_size(); - buffer += padding; - total_sz -= padding; - if(total_sz < sizeof(_bitmap) + sizeof(_bar_control) + sizeof(_start_sequence)) - throw malformed_packet(); - std::memcpy(&_bar_control, buffer, sizeof(_bar_control)); - buffer += sizeof(_bar_control); - std::memcpy(&_start_sequence, buffer, sizeof(_start_sequence)); - buffer += sizeof(_start_sequence); - std::memcpy(&_bitmap, buffer, sizeof(_bitmap)); + InputMemoryStream stream(buffer, total_sz); + stream.skip(controlta_size()); + stream.read(_bar_control); + stream.read(_start_sequence); + stream.read(_bitmap); } void Dot11BlockAck::bar_control(small_uint<4> bar) { @@ -270,13 +261,12 @@ void Dot11BlockAck::bitmap(const uint8_t *bit) { uint32_t Dot11BlockAck::write_ext_header(uint8_t *buffer, uint32_t total_sz) { uint32_t parent_size = Dot11ControlTA::write_ext_header(buffer, total_sz); - buffer += parent_size; - std::memcpy(buffer, &_bar_control, sizeof(_bar_control)); - buffer += sizeof(_bar_control); - std::memcpy(buffer, &_start_sequence, sizeof(_start_sequence)); - buffer += sizeof(_start_sequence); - std::memcpy(buffer, _bitmap, sizeof(_bitmap)); - return parent_size + sizeof(_bitmap) + sizeof(_bar_control) + sizeof(_start_sequence); + InputMemoryStream stream(buffer, total_sz); + stream.skip(parent_size); + stream.read(_bar_control); + stream.read(_start_sequence); + stream.read(_bitmap); + return total_sz - stream.size(); } uint32_t Dot11BlockAck::header_size() const { diff --git a/src/dot11/dot11_data.cpp b/src/dot11/dot11_data.cpp index e18138b..54a5224 100644 --- a/src/dot11/dot11_data.cpp +++ b/src/dot11/dot11_data.cpp @@ -34,6 +34,9 @@ #include #include "rawpdu.h" #include "snap.h" +#include "memory_helpers.h" + +using Tins::Memory::InputMemoryStream; namespace Tins { /* Dot11Data */ @@ -42,14 +45,16 @@ Dot11Data::Dot11Data(const uint8_t *buffer, uint32_t total_sz) : Dot11(buffer, total_sz) { const uint32_t offset = init(buffer, total_sz); - buffer += offset; - total_sz -= offset; - if(total_sz) { + InputMemoryStream stream(buffer, total_sz); + stream.skip(offset); + if (stream) { // If the wep bit is on, then just use a RawPDU - if(wep()) - inner_pdu(new Tins::RawPDU(buffer, total_sz)); - else - inner_pdu(new Tins::SNAP(buffer, total_sz)); + if(wep()) { + inner_pdu(new Tins::RawPDU(stream.pointer(), stream.size())); + } + else { + inner_pdu(new Tins::SNAP(stream.pointer(), stream.size())); + } } } @@ -60,23 +65,13 @@ Dot11Data::Dot11Data(const uint8_t *buffer, uint32_t total_sz, no_inner_pdu) } uint32_t Dot11Data::init(const uint8_t *buffer, uint32_t total_sz) { - const uint8_t *start_ptr = buffer; - uint32_t sz = Dot11::header_size(); - buffer += sz; - total_sz -= sz; - if(total_sz < sizeof(_ext_header)) - throw malformed_packet(); - std::memcpy(&_ext_header, buffer, sizeof(_ext_header)); - buffer += sizeof(_ext_header); - total_sz -= sizeof(_ext_header); - if(from_ds() && to_ds()) { - if(total_sz < _addr4.size()) - throw malformed_packet(); - _addr4 = buffer; - buffer += _addr4.size(); - total_sz -= static_cast(_addr4.size()); + InputMemoryStream stream(buffer, total_sz); + stream.skip(Dot11::header_size()); + stream.read(_ext_header); + if (from_ds() && to_ds()) { + stream.read(_addr4); } - return static_cast(buffer - start_ptr); + return total_sz - stream.size(); } Dot11Data::Dot11Data(const address_type &dst_hw_addr, @@ -148,20 +143,17 @@ Dot11QoSData::Dot11QoSData(const address_type &dst_hw_addr, Dot11QoSData::Dot11QoSData(const uint8_t *buffer, uint32_t total_sz) // Am I breaking something? :S : Dot11Data(buffer, total_sz, no_inner_pdu()) { - uint32_t sz = data_frame_size(); - buffer += sz; - total_sz -= sz; - if(total_sz < sizeof(_qos_control)) - throw malformed_packet(); - std::memcpy(&_qos_control, buffer, sizeof(uint16_t)); - total_sz -= sizeof(uint16_t); - buffer += sizeof(uint16_t); - if(total_sz) { + InputMemoryStream stream(buffer, total_sz); + stream.skip(data_frame_size()); + stream.read(_qos_control); + if (total_sz) { // If the wep bit is on, then just use a RawPDU - if(wep()) - inner_pdu(new Tins::RawPDU(buffer, total_sz)); - else - inner_pdu(new Tins::SNAP(buffer, total_sz)); + if (wep()) { + inner_pdu(new Tins::RawPDU(stream.pointer(), stream.size())); + } + else { + inner_pdu(new Tins::SNAP(stream.pointer(), stream.size())); + } } } diff --git a/src/dot11/dot11_mgmt.cpp b/src/dot11/dot11_mgmt.cpp index 9ebf1b8..f22a497 100644 --- a/src/dot11/dot11_mgmt.cpp +++ b/src/dot11/dot11_mgmt.cpp @@ -32,6 +32,9 @@ #include #include "rsn_information.h" +#include "memory_helpers.h" + +using Tins::Memory::InputMemoryStream; namespace Tins { /* Dot11ManagementFrame */ @@ -39,33 +42,27 @@ namespace Tins { Dot11ManagementFrame::Dot11ManagementFrame(const uint8_t *buffer, uint32_t total_sz) : Dot11(buffer, total_sz) { - buffer += sizeof(ieee80211_header); - total_sz -= sizeof(ieee80211_header); - if(total_sz < sizeof(_ext_header)) - throw malformed_packet(); - std::memcpy(&_ext_header, buffer, sizeof(_ext_header)); - total_sz -= sizeof(_ext_header); - if(from_ds() && to_ds()) { - if(total_sz >= _addr4.size()) - _addr4 = buffer + sizeof(_ext_header); - else - throw malformed_packet(); + InputMemoryStream stream(buffer, total_sz); + stream.skip(sizeof(ieee80211_header)); + stream.read(_ext_header); + if (from_ds() && to_ds()) { + stream.read(_addr4); } } Dot11ManagementFrame::Dot11ManagementFrame(const address_type &dst_hw_addr, const address_type &src_hw_addr) -: Dot11(dst_hw_addr) +: Dot11(dst_hw_addr), _ext_header() { type(Dot11::MANAGEMENT); - memset(&_ext_header, 0, sizeof(_ext_header)); addr2(src_hw_addr); } uint32_t Dot11ManagementFrame::header_size() const { uint32_t sz = Dot11::header_size() + sizeof(_ext_header); - if (this->from_ds() && this->to_ds()) + if (this->from_ds() && this->to_ds()) { sz += 6; + } return sz; } diff --git a/src/dot11/dot11_probe.cpp b/src/dot11/dot11_probe.cpp index de2cfef..93252fe 100644 --- a/src/dot11/dot11_probe.cpp +++ b/src/dot11/dot11_probe.cpp @@ -33,6 +33,9 @@ #include #include +#include "memory_helpers.h" + +using Tins::Memory::InputMemoryStream; namespace Tins { /* Probe Request */ @@ -47,34 +50,27 @@ Dot11ProbeRequest::Dot11ProbeRequest(const address_type &dst_hw_addr, Dot11ProbeRequest::Dot11ProbeRequest(const uint8_t *buffer, uint32_t total_sz) : Dot11ManagementFrame(buffer, total_sz) { - uint32_t sz = management_frame_size(); - buffer += sz; - total_sz -= sz; - parse_tagged_parameters(buffer, total_sz); + InputMemoryStream stream(buffer, total_sz); + stream.skip(management_frame_size()); + parse_tagged_parameters(stream); } /* Probe Response */ Dot11ProbeResponse::Dot11ProbeResponse(const address_type &dst_hw_addr, const address_type &src_hw_addr) -: Dot11ManagementFrame(dst_hw_addr, src_hw_addr) +: Dot11ManagementFrame(dst_hw_addr, src_hw_addr), _body() { this->subtype(Dot11::PROBE_RESP); - memset(&_body, 0, sizeof(_body)); } Dot11ProbeResponse::Dot11ProbeResponse(const uint8_t *buffer, uint32_t total_sz) : Dot11ManagementFrame(buffer, total_sz) { - uint32_t sz = management_frame_size(); - buffer += sz; - total_sz -= sz; - if(total_sz < sizeof(_body)) - throw malformed_packet(); - memcpy(&_body, buffer, sizeof(_body)); - buffer += sizeof(_body); - total_sz -= sizeof(_body); - parse_tagged_parameters(buffer, total_sz); + InputMemoryStream stream(buffer, total_sz); + stream.skip(management_frame_size()); + stream.read(_body); + parse_tagged_parameters(stream); } void Dot11ProbeResponse::timestamp(uint64_t new_timestamp) { diff --git a/src/ipv6.cpp b/src/ipv6.cpp index 6ff1dbc..eb9be58 100644 --- a/src/ipv6.cpp +++ b/src/ipv6.cpp @@ -45,50 +45,48 @@ #include "exceptions.h" #include "pdu_allocator.h" #include "internals.h" +#include "memory_helpers.h" + +using Tins::Memory::InputMemoryStream; namespace Tins { IPv6::IPv6(address_type ip_dst, address_type ip_src, PDU *child) -: headers_size(0) +: _header(), headers_size(0) { - std::memset(&_header, 0, sizeof(_header)); version(6); dst_addr(ip_dst); src_addr(ip_src); } IPv6::IPv6(const uint8_t *buffer, uint32_t total_sz) -: headers_size(0) { - if(total_sz < sizeof(_header)) - throw malformed_packet(); - std::memcpy(&_header, buffer, sizeof(_header)); - buffer += sizeof(_header); - total_sz -= sizeof(_header); +: headers_size(0) +{ + InputMemoryStream stream(buffer, total_sz); + stream.read(_header); uint8_t current_header = _header.next_header; - while(total_sz) { + while (stream) { if(is_extension_header(current_header)) { - if(total_sz < 8) - throw malformed_packet(); + const uint8_t ext_type = stream.read(); // every ext header is at least 8 bytes long // minus one, from the next_header field. - uint32_t size = static_cast(buffer[1]) + 8; + const uint32_t ext_size = static_cast(stream.read()) + 8; + const uint32_t payload_size = ext_size - sizeof(uint8_t) * 2; // -1 -> next header identifier - if(total_sz < size) + if(!stream.can_read(ext_size)) { throw malformed_packet(); + } // minus one, from the size field - add_ext_header( - ext_header(buffer[0], size - sizeof(uint8_t)*2, buffer + 2) - ); - current_header = buffer[0]; - buffer += size; - total_sz -= size; + add_ext_header(ext_header(ext_type, payload_size, stream.pointer())); + current_header = ext_type; + stream.skip(payload_size); } else { inner_pdu( Internals::pdu_from_flag( static_cast(current_header), - buffer, - total_sz, + stream.pointer(), + stream.size(), false ) ); @@ -96,14 +94,16 @@ IPv6::IPv6(const uint8_t *buffer, uint32_t total_sz) inner_pdu( Internals::allocate( current_header, - buffer, - total_sz + stream.pointer(), + stream.size() ) ); - if(!inner_pdu()) - inner_pdu(new Tins::RawPDU(buffer, total_sz)); + if(!inner_pdu()) { + inner_pdu(new Tins::RawPDU(stream.pointer(), stream.size())); + } } - total_sz = 0; + // We got to an actual PDU, we're done + break; } } } diff --git a/src/llc.cpp b/src/llc.cpp index fc1efbf..dd9a67a 100644 --- a/src/llc.cpp +++ b/src/llc.cpp @@ -36,61 +36,55 @@ #include "stp.h" #include "rawpdu.h" #include "exceptions.h" +#include "memory_helpers.h" + +using Tins::Memory::InputMemoryStream; namespace Tins { + const uint8_t LLC::GLOBAL_DSAP_ADDR = 0xFF; const uint8_t LLC::NULL_ADDR = 0x00; LLC::LLC() -: _type(LLC::INFORMATION) +: _header(), control_field(), _type(LLC::INFORMATION) { - memset(&_header, 0, sizeof(llchdr)); control_field_length = 2; - memset(&control_field, 0, sizeof(control_field)); information_field_length = 0; } LLC::LLC(uint8_t dsap, uint8_t ssap) -: _type(LLC::INFORMATION) +: control_field(), _type(LLC::INFORMATION) { _header.dsap = dsap; _header.ssap = ssap; control_field_length = 2; - memset(&control_field, 0, sizeof(control_field)); information_field_length = 0; } LLC::LLC(const uint8_t *buffer, uint32_t total_sz) { - // header + 1 info byte - if(total_sz < sizeof(_header) + 1) - throw malformed_packet(); - std::memcpy(&_header, buffer, sizeof(_header)); - buffer += sizeof(_header); - total_sz -= sizeof(_header); + InputMemoryStream stream(buffer, total_sz); + stream.read(_header); + if (!stream) { + throw malformed_packet(); + } information_field_length = 0; - if ((buffer[0] & 0x03) == LLC::UNNUMBERED) { - if(total_sz < sizeof(un_control_field)) - throw malformed_packet(); + if ((*stream.pointer() & 0x03) == LLC::UNNUMBERED) { type(LLC::UNNUMBERED); - std::memcpy(&control_field.unnumbered, buffer, sizeof(un_control_field)); - buffer += sizeof(un_control_field); - total_sz -= sizeof(un_control_field); - //TODO: Create information fields if corresponding. + stream.read(control_field.unnumbered); + // TODO: Create information fields if corresponding. } else { - if(total_sz < sizeof(info_control_field)) - throw malformed_packet(); - type((Format)(buffer[0] & 0x03)); + type((Format)(*stream.pointer() & 0x03)); control_field_length = 2; - std::memcpy(&control_field.info, buffer, sizeof(info_control_field)); - buffer += 2; - total_sz -= 2; + stream.read(control_field.info); } - if(total_sz > 0) { - if(dsap() == 0x42 && ssap() == 0x42) - inner_pdu(new Tins::STP(buffer, total_sz)); - else - inner_pdu(new Tins::RawPDU(buffer, total_sz)); + if (stream) { + if (dsap() == 0x42 && ssap() == 0x42) { + inner_pdu(new Tins::STP(stream.pointer(), stream.size())); + } + else { + inner_pdu(new Tins::RawPDU(stream.pointer(), stream.size())); + } } } diff --git a/src/loopback.cpp b/src/loopback.cpp index ff52373..6e33c9c 100644 --- a/src/loopback.cpp +++ b/src/loopback.cpp @@ -48,13 +48,17 @@ #include "llc.h" #include "rawpdu.h" #include "exceptions.h" +#include "memory_helpers.h" #if !defined(PF_LLC) // compilation fix, nasty but at least works on BSD #define PF_LLC 26 #endif +using Tins::Memory::InputMemoryStream; + namespace Tins { + Loopback::Loopback() : _family() { @@ -63,22 +67,19 @@ Loopback::Loopback() Loopback::Loopback(const uint8_t *buffer, uint32_t total_sz) { - if(total_sz < sizeof(_family)) - throw malformed_packet(); - _family = *reinterpret_cast(buffer); - buffer += sizeof(uint32_t); - total_sz -= sizeof(uint32_t); + InputMemoryStream stream(buffer, total_sz); + _family = stream.read(); #ifndef _WIN32 - if(total_sz) { - switch(_family) { + if (total_sz) { + switch (_family) { case PF_INET: - inner_pdu(new Tins::IP(buffer, total_sz)); + inner_pdu(new Tins::IP(stream.pointer(), stream.size())); break; case PF_LLC: - inner_pdu(new Tins::LLC(buffer, total_sz)); + inner_pdu(new Tins::LLC(stream.pointer(), stream.size())); break; default: - inner_pdu(new Tins::RawPDU(buffer, total_sz)); + inner_pdu(new Tins::RawPDU(stream.pointer(), stream.size())); break; }; } diff --git a/src/pktap.cpp b/src/pktap.cpp index c76359f..bc9d7cb 100644 --- a/src/pktap.cpp +++ b/src/pktap.cpp @@ -32,30 +32,29 @@ #include "exceptions.h" #include "pktap.h" #include "internals.h" +#include "memory_helpers.h" + +using Tins::Memory::InputMemoryStream; namespace Tins { -PKTAP::PKTAP() { - memset(&header_, 0, sizeof(header_)); +PKTAP::PKTAP() : header_() { } PKTAP::PKTAP(const uint8_t* buffer, uint32_t total_sz) { - if (total_sz < sizeof(pktap_header)) { - throw malformed_packet(); - } - memcpy(&header_, buffer, sizeof(header_)); + InputMemoryStream stream(buffer, total_sz); + stream.read(header_); uint32_t header_length = header_.length; - if (header_length > total_sz) { + if (header_length > total_sz || header_length < sizeof(header_)) { throw malformed_packet(); } - buffer += header_length; - total_sz -= header_length; - if (header_.next && total_sz > 0) { + stream.skip(header_length - sizeof(header_)); + if (header_.next && stream) { inner_pdu( Internals::pdu_from_dlt_flag( header_.dlt, - buffer, - total_sz + stream.pointer(), + stream.size() ) ); } diff --git a/src/ppi.cpp b/src/ppi.cpp index 9c63b20..4ca1a48 100644 --- a/src/ppi.cpp +++ b/src/ppi.cpp @@ -42,50 +42,51 @@ #include "ppi.h" #include "internals.h" #include "exceptions.h" +#include "memory_helpers.h" + +using Tins::Memory::InputMemoryStream; namespace Tins { + PPI::PPI(const uint8_t *buffer, uint32_t total_sz) { - if(total_sz < sizeof(_header)) + InputMemoryStream stream(buffer, total_sz); + stream.read(_header); + if (length() > total_sz || length() < sizeof(_header)) { throw malformed_packet(); - std::memcpy(&_header, buffer, sizeof(_header)); - if(length() > total_sz || length() < sizeof(_header)) - throw malformed_packet(); - buffer += sizeof(_header); - total_sz -= sizeof(_header); + } // There are some options const size_t options_length = length() - sizeof(_header); - if(options_length > 0) { - _data.assign(buffer, buffer + options_length); - buffer += options_length; - total_sz -= static_cast(options_length); + if (options_length > 0) { + _data.assign(stream.pointer(), stream.pointer() + options_length); + stream.skip(options_length); } - if(total_sz > 0) { - switch(dlt()) { + if (stream) { + switch (dlt()) { case DLT_IEEE802_11: #ifdef HAVE_DOT11 - parse_80211(buffer, total_sz); + parse_80211(stream.pointer(), stream.size()); #else throw protocol_disabled(); #endif break; case DLT_EN10MB: - if(Internals::is_dot3(buffer, total_sz)) - inner_pdu(new Dot3(buffer, total_sz)); + if(Internals::is_dot3(stream.pointer(), stream.size())) + inner_pdu(new Dot3(stream.pointer(), stream.size())); else - inner_pdu(new EthernetII(buffer, total_sz)); + inner_pdu(new EthernetII(stream.pointer(), stream.size())); break; case DLT_IEEE802_11_RADIO: #ifdef HAVE_DOT11 - inner_pdu(new RadioTap(buffer, total_sz)); + inner_pdu(new RadioTap(stream.pointer(), stream.size())); #else throw protocol_disabled(); #endif break; case DLT_NULL: - inner_pdu(new Loopback(buffer, total_sz)); + inner_pdu(new Loopback(stream.pointer(), stream.size())); break; case DLT_LINUX_SLL: - inner_pdu(new Tins::SLL(buffer, total_sz)); + inner_pdu(new Tins::SLL(stream.pointer(), stream.size())); break; } } diff --git a/src/pppoe.cpp b/src/pppoe.cpp index 563134e..82a92f5 100644 --- a/src/pppoe.cpp +++ b/src/pppoe.cpp @@ -34,6 +34,9 @@ #include "pppoe.h" #include "rawpdu.h" #include "exceptions.h" +#include "memory_helpers.h" + +using Tins::Memory::InputMemoryStream; namespace Tins { @@ -47,42 +50,27 @@ PPPoE::PPPoE() PPPoE::PPPoE(const uint8_t *buffer, uint32_t total_sz) : _tags_size() { - if(total_sz < sizeof(_header)) - throw malformed_packet(); - std::memcpy(&_header, buffer, sizeof(_header)); - buffer += sizeof(_header); - total_sz -= sizeof(_header); - total_sz = std::min(total_sz, (uint32_t)payload_length()); + InputMemoryStream stream(buffer, total_sz); + stream.read(_header); + stream.size(std::min(stream.size(), (uint32_t)payload_length())); // If this is a session data packet - if(code() == 0) { - if(total_sz > 0) { + if (code() == 0) { + if (stream) { inner_pdu( - new RawPDU(buffer, total_sz) + new RawPDU(stream.pointer(), stream.size()) ); } } else { - const uint8_t *end = buffer + total_sz; - while(buffer < end) { - if(buffer + sizeof(uint32_t) * 2 > end) + const uint8_t *end = stream.pointer() + stream.size(); + while (stream.pointer() < end) { + TagTypes opt_type = static_cast(stream.read()); + uint16_t opt_len = Endian::be_to_host(stream.read()); + if(!stream.can_read(opt_len)) { throw malformed_packet(); - uint16_t opt_type; - std::memcpy(&opt_type, buffer, sizeof(uint16_t)); - uint16_t opt_len; - std::memcpy(&opt_len, buffer + sizeof(uint16_t), sizeof(uint16_t)); - buffer += sizeof(uint16_t) * 2; - total_sz -= sizeof(uint16_t) * 2; - if(Endian::be_to_host(opt_len) > total_sz) - throw malformed_packet(); - add_tag( - tag( - static_cast(opt_type), - Endian::be_to_host(opt_len), - buffer - ) - ); - buffer += Endian::be_to_host(opt_len); - total_sz -= Endian::be_to_host(opt_len); + } + add_tag(tag(opt_type, opt_len, stream.pointer())); + stream.skip(opt_len); } } } diff --git a/src/radiotap.cpp b/src/radiotap.cpp index d2a919f..6031cdd 100644 --- a/src/radiotap.cpp +++ b/src/radiotap.cpp @@ -65,9 +65,8 @@ void read_field(const uint8_t* &buffer, uint32_t &total_sz, T& field) { total_sz -= sizeof(field); } -RadioTap::RadioTap() +RadioTap::RadioTap() : _radio() { - std::memset(&_radio, 0, sizeof(_radio)); init(); } diff --git a/src/rsn_information.cpp b/src/rsn_information.cpp index 9bf5ccb..0b89994 100644 --- a/src/rsn_information.cpp +++ b/src/rsn_information.cpp @@ -34,15 +34,13 @@ #include #include "exceptions.h" #include "pdu_option.h" +#include "memory_helpers.h" #include "dot11/dot11_base.h" +using Tins::Memory::InputMemoryStream; + namespace Tins { -template -void check_size(uint32_t total_sz) { - if(total_sz < sizeof(T)) - throw malformed_packet(); -} - + RSNInformation::RSNInformation() : _version(1), _capabilities(0) { } @@ -56,55 +54,28 @@ RSNInformation::RSNInformation(const uint8_t *buffer, uint32_t total_sz) { } void RSNInformation::init(const uint8_t *buffer, uint32_t total_sz) { - if(total_sz <= sizeof(uint16_t) * 2 + sizeof(uint32_t)) + InputMemoryStream stream(buffer, total_sz); + version(Endian::le_to_host(stream.read())); + group_suite((RSNInformation::CypherSuites)Endian::le_to_host(stream.read())); + int pairwise_cyphers_size = Endian::le_to_host(stream.read()); + if (!stream.can_read(pairwise_cyphers_size)) { throw malformed_packet(); - - uint16_t uint16_t_buffer; - uint32_t uint32_t_buffer; - - std::memcpy(&uint16_t_buffer, buffer, sizeof(uint16_t)); - version(Endian::le_to_host(uint16_t_buffer)); - buffer += sizeof(uint16_t); - total_sz -= sizeof(uint16_t); - - std::memcpy(&uint32_t_buffer, buffer, sizeof(uint32_t)); - group_suite((RSNInformation::CypherSuites)Endian::le_to_host(uint32_t_buffer)); - buffer += sizeof(uint32_t); - total_sz -= sizeof(uint32_t); - - std::memcpy(&uint16_t_buffer, buffer, sizeof(uint16_t)); - uint16_t_buffer = Endian::le_to_host(uint16_t_buffer); - buffer += sizeof(uint16_t); - total_sz -= sizeof(uint16_t); - - if(uint16_t_buffer * sizeof(uint32_t) > total_sz) - throw malformed_packet(); - total_sz -= uint16_t_buffer * sizeof(uint32_t); - while(uint16_t_buffer--) { - std::memcpy(&uint32_t_buffer, buffer, sizeof(uint32_t)); - uint32_t_buffer = Endian::le_to_host(uint32_t_buffer); - add_pairwise_cypher((RSNInformation::CypherSuites)uint32_t_buffer); - buffer += sizeof(uint32_t); } - check_size(total_sz); - - std::memcpy(&uint16_t_buffer, buffer, sizeof(uint16_t)); - buffer += sizeof(uint16_t); - total_sz -= sizeof(uint16_t); - uint16_t_buffer = Endian::le_to_host(uint16_t_buffer); - - if(uint16_t_buffer * sizeof(uint32_t) > total_sz) - throw malformed_packet(); - total_sz -= uint16_t_buffer * sizeof(uint32_t); - while(uint16_t_buffer--) { - std::memcpy(&uint32_t_buffer, buffer, sizeof(uint32_t)); - add_akm_cypher((RSNInformation::AKMSuites)Endian::le_to_host(uint32_t_buffer)); - buffer += sizeof(uint32_t); + while (pairwise_cyphers_size--) { + add_pairwise_cypher( + (RSNInformation::CypherSuites)Endian::le_to_host(stream.read()) + ); } - check_size(total_sz); - - std::memcpy(&uint16_t_buffer, buffer, sizeof(uint16_t)); - capabilities(Endian::le_to_host(uint16_t_buffer)); + int akm_cyphers_size = Endian::le_to_host(stream.read()); + if (!stream.can_read(akm_cyphers_size)) { + throw malformed_packet(); + } + while (akm_cyphers_size--) { + add_akm_cypher( + (RSNInformation::AKMSuites)Endian::le_to_host(stream.read()) + ); + } + capabilities(Endian::le_to_host(stream.read())); } void RSNInformation::add_pairwise_cypher(CypherSuites cypher) { diff --git a/src/sll.cpp b/src/sll.cpp index acc2735..8bfbb64 100644 --- a/src/sll.cpp +++ b/src/sll.cpp @@ -32,24 +32,25 @@ #include "sll.h" #include "internals.h" #include "exceptions.h" +#include "memory_helpers.h" + +using Tins::Memory::InputMemoryStream; namespace Tins { + SLL::SLL() : _header() { } SLL::SLL(const uint8_t *buffer, uint32_t total_sz) { - if(total_sz < sizeof(_header)) - throw malformed_packet(); - std::memcpy(&_header, buffer, sizeof(_header)); - buffer += sizeof(_header); - total_sz -= sizeof(_header); - if(total_sz) { + InputMemoryStream stream(buffer, total_sz); + stream.read(_header); + if (stream) { inner_pdu( Internals::pdu_from_flag( (Constants::Ethernet::e)protocol(), - buffer, - total_sz + stream.pointer(), + stream.size() ) ); } diff --git a/src/snap.cpp b/src/snap.cpp index bce9470..fce6b6b 100644 --- a/src/snap.cpp +++ b/src/snap.cpp @@ -43,34 +43,34 @@ #include "eapol.h" #include "internals.h" #include "exceptions.h" +#include "memory_helpers.h" +using Tins::Memory::InputMemoryStream; -Tins::SNAP::SNAP() +namespace Tins { + +SNAP::SNAP() : _snap() { - std::memset(&_snap, 0, sizeof(_snap)); _snap.dsap = _snap.ssap = 0xaa; control(3); } -Tins::SNAP::SNAP(const uint8_t *buffer, uint32_t total_sz) +SNAP::SNAP(const uint8_t *buffer, uint32_t total_sz) { - if(total_sz < sizeof(_snap)) - throw malformed_packet(); - std::memcpy(&_snap, buffer, sizeof(_snap)); - buffer += sizeof(_snap); - total_sz -= sizeof(_snap); - if(total_sz) { + InputMemoryStream stream(buffer, total_sz); + stream.read(_snap); + if (stream) { inner_pdu( Internals::pdu_from_flag( (Constants::Ethernet::e)eth_type(), - buffer, - total_sz + stream.pointer(), + stream.size() ) ); } } -void Tins::SNAP::control(uint8_t new_control) { +void SNAP::control(uint8_t new_control) { #if TINS_IS_LITTLE_ENDIAN _snap.control_org = (_snap.control_org & 0xffffff00) | (new_control); #else @@ -78,7 +78,7 @@ void Tins::SNAP::control(uint8_t new_control) { #endif } -void Tins::SNAP::org_code(small_uint<24> new_org) { +void SNAP::org_code(small_uint<24> new_org) { #if TINS_IS_LITTLE_ENDIAN _snap.control_org = Endian::host_to_be(new_org) | control(); #else @@ -86,15 +86,15 @@ void Tins::SNAP::org_code(small_uint<24> new_org) { #endif } -void Tins::SNAP::eth_type(uint16_t new_eth) { +void SNAP::eth_type(uint16_t new_eth) { _snap.eth_type = Endian::host_to_be(new_eth); } -uint32_t Tins::SNAP::header_size() const { +uint32_t SNAP::header_size() const { return sizeof(_snap); } -void Tins::SNAP::write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *parent) { +void SNAP::write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *parent) { #ifdef TINS_DEBUG assert(total_sz >= sizeof(_snap)); #endif @@ -108,3 +108,5 @@ void Tins::SNAP::write_serialization(uint8_t *buffer, uint32_t total_sz, const P } std::memcpy(buffer, &_snap, sizeof(_snap)); } + +} // Tins diff --git a/src/stp.cpp b/src/stp.cpp index f0358ca..71f85ca 100644 --- a/src/stp.cpp +++ b/src/stp.cpp @@ -34,6 +34,9 @@ #include #include "stp.h" #include "exceptions.h" +#include "memory_helpers.h" + +using Tins::Memory::InputMemoryStream; namespace Tins { @@ -45,9 +48,8 @@ STP::STP() STP::STP(const uint8_t *buffer, uint32_t total_sz) { - if(total_sz < sizeof(_header)) - throw malformed_packet(); - std::memcpy(&_header, buffer ,sizeof(_header)); + InputMemoryStream stream(buffer, total_sz); + stream.read(_header); } void STP::proto_id(uint16_t new_proto_id) { diff --git a/src/udp.cpp b/src/udp.cpp index 9cd505a..3b4b6e1 100644 --- a/src/udp.cpp +++ b/src/udp.cpp @@ -39,24 +39,25 @@ #include "ipv6.h" #include "rawpdu.h" #include "exceptions.h" +#include "memory_helpers.h" + +using Tins::Memory::InputMemoryStream; namespace Tins { -UDP::UDP(uint16_t dport, uint16_t sport) + +UDP::UDP(uint16_t dport, uint16_t sport) : _udp() { this->dport(dport); this->sport(sport); - _udp.check = 0; - _udp.len = 0; } UDP::UDP(const uint8_t *buffer, uint32_t total_sz) { - if(total_sz < sizeof(udphdr)) - throw malformed_packet(); - std::memcpy(&_udp, buffer, sizeof(udphdr)); - total_sz -= sizeof(udphdr); - if(total_sz) - inner_pdu(new RawPDU(buffer + sizeof(udphdr), total_sz)); + InputMemoryStream stream(buffer, total_sz); + stream.read(_udp); + if (stream) { + inner_pdu(new RawPDU(stream.pointer(), stream.size())); + } } void UDP::dport(uint16_t new_dport) {