1
0
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:
Matias Fontanini
2015-12-25 06:30:27 -08:00
parent 13c05fbdb1
commit 9750f46c6d
23 changed files with 786 additions and 874 deletions

View File

@@ -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:
/**

View File

@@ -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();

View File

@@ -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

View File

@@ -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) {

View File

@@ -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) {

View File

@@ -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);
}
}
}

View File

@@ -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) {

View File

@@ -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 {

View File

@@ -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()));
}
}
}

View File

@@ -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;
}

View File

@@ -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) {

View File

@@ -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;
}
}
}

View File

@@ -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()));
}
}
}

View File

@@ -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;
};
}

View File

@@ -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()
)
);
}

View File

@@ -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;
}
}

View File

@@ -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);
}
}
}

View File

@@ -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();
}

View File

@@ -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) {

View File

@@ -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()
)
);
}

View File

@@ -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

View File

@@ -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) {

View File

@@ -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) {