mirror of
https://github.com/mfontanini/libtins
synced 2026-01-23 02:35:57 +01:00
Port all PDUs to use InputMemoryStream on constructors from buffer
This commit is contained in:
@@ -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:
|
||||
/**
|
||||
|
||||
@@ -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 <size_t n>
|
||||
void read(HWAddress<n>& address) {
|
||||
if (!can_read(HWAddress<n>::address_size)) {
|
||||
throw malformed_packet();
|
||||
}
|
||||
address = pointer();
|
||||
skip(HWAddress<n>::address_size);
|
||||
}
|
||||
|
||||
void read(void* output_buffer, uint32_t output_buffer_size) {
|
||||
if (!can_read(output_buffer_size)) {
|
||||
throw malformed_packet();
|
||||
|
||||
@@ -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 <size_t n>
|
||||
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 <size_t n>
|
||||
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
|
||||
|
||||
@@ -32,29 +32,26 @@
|
||||
|
||||
#include <cassert>
|
||||
#include <cstring>
|
||||
#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) {
|
||||
|
||||
@@ -32,6 +32,9 @@
|
||||
|
||||
#include <cassert>
|
||||
#include <cstring>
|
||||
#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) {
|
||||
|
||||
@@ -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<OptionTypes>(stream.read<uint8_t>());
|
||||
uint8_t length = stream.read<uint8_t>();
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,6 +32,9 @@
|
||||
|
||||
#include <cstring>
|
||||
#include <cassert>
|
||||
#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) {
|
||||
|
||||
@@ -32,6 +32,9 @@
|
||||
|
||||
#include <cassert>
|
||||
#include <cstring>
|
||||
#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 {
|
||||
|
||||
@@ -34,6 +34,9 @@
|
||||
#include <cassert>
|
||||
#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<uint32_t>(_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<uint32_t>(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()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -32,6 +32,9 @@
|
||||
|
||||
#include <cstring>
|
||||
#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;
|
||||
}
|
||||
|
||||
|
||||
@@ -33,6 +33,9 @@
|
||||
|
||||
#include <cstring>
|
||||
#include <cassert>
|
||||
#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) {
|
||||
|
||||
52
src/ipv6.cpp
52
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<uint8_t>();
|
||||
// every ext header is at least 8 bytes long
|
||||
// minus one, from the next_header field.
|
||||
uint32_t size = static_cast<uint32_t>(buffer[1]) + 8;
|
||||
const uint32_t ext_size = static_cast<uint32_t>(stream.read<uint8_t>()) + 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<Constants::IP::e>(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<IPv6>(
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
52
src/llc.cpp
52
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()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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<const uint32_t*>(buffer);
|
||||
buffer += sizeof(uint32_t);
|
||||
total_sz -= sizeof(uint32_t);
|
||||
InputMemoryStream stream(buffer, total_sz);
|
||||
_family = stream.read<uint32_t>();
|
||||
#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;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -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()
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
39
src/ppi.cpp
39
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<uint32_t>(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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<TagTypes>(stream.read<uint16_t>());
|
||||
uint16_t opt_len = Endian::be_to_host(stream.read<uint16_t>());
|
||||
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<TagTypes>(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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
|
||||
@@ -34,15 +34,13 @@
|
||||
#include <stdexcept>
|
||||
#include "exceptions.h"
|
||||
#include "pdu_option.h"
|
||||
#include "memory_helpers.h"
|
||||
#include "dot11/dot11_base.h"
|
||||
|
||||
using Tins::Memory::InputMemoryStream;
|
||||
|
||||
namespace Tins {
|
||||
template<typename T>
|
||||
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<uint16_t>()));
|
||||
group_suite((RSNInformation::CypherSuites)Endian::le_to_host(stream.read<uint32_t>()));
|
||||
int pairwise_cyphers_size = Endian::le_to_host(stream.read<uint16_t>());
|
||||
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<uint16_t>(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<uint32_t>())
|
||||
);
|
||||
}
|
||||
check_size<uint16_t>(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<uint16_t>());
|
||||
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<uint32_t>())
|
||||
);
|
||||
}
|
||||
capabilities(Endian::le_to_host(stream.read<uint16_t>()));
|
||||
}
|
||||
|
||||
void RSNInformation::add_pairwise_cypher(CypherSuites cypher) {
|
||||
|
||||
17
src/sll.cpp
17
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()
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
34
src/snap.cpp
34
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<uint32_t>(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
|
||||
|
||||
@@ -34,6 +34,9 @@
|
||||
#include <algorithm>
|
||||
#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) {
|
||||
|
||||
19
src/udp.cpp
19
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) {
|
||||
|
||||
Reference in New Issue
Block a user