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" #include "../macros.h"
namespace Tins { namespace Tins {
namespace Memory {
class InputMemoryStream;
} // Memory
class RSNInformation; class RSNInformation;
/** /**
@@ -477,7 +481,7 @@ public:
protected: protected:
virtual uint32_t write_ext_header(uint8_t *buffer, uint32_t total_sz) { return 0; } 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; } 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); void add_tagged_option(OptionTypes opt, uint8_t len, const uint8_t *val);
protected: protected:
/** /**

View File

@@ -6,6 +6,7 @@
#include "exceptions.h" #include "exceptions.h"
#include "ip_address.h" #include "ip_address.h"
#include "ipv6_address.h" #include "ipv6_address.h"
#include "hw_address.h"
namespace Tins { namespace Tins {
namespace Memory { namespace Memory {
@@ -67,6 +68,15 @@ public:
skip(IPv6Address::address_size); 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) { void read(void* output_buffer, uint32_t output_buffer_size) {
if (!can_read(output_buffer_size)) { if (!can_read(output_buffer_size)) {
throw malformed_packet(); throw malformed_packet();

View File

@@ -37,478 +37,478 @@
#include "endianness.h" #include "endianness.h"
namespace Tins { namespace Tins {
class PacketSender; class PacketSender;
/** /**
* \brief Class that represents the IEEE 802.11 radio tap header. * \brief Class that represents the IEEE 802.11 radio tap header.
* *
* By default, RadioTap PDUs set the necesary fields to send an 802.11 * By default, RadioTap PDUs set the necesary fields to send an 802.11
* PDU as its inner pdu, avoiding packet drops. As a consequence, * 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, * 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. * 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 { static const PDU::PDUType pdu_flag = PDU::RADIOTAP;
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
};
/** /**
* \brief The type used to represent the MCS flags field * \brief Enumeration of the different channel type flags.
*/ *
TINS_BEGIN_PACK * These channel type flags can be OR'd and set using the
struct mcs_type { * RadioTap::channel() method.
uint8_t known; */
uint8_t flags; enum ChannelType {
uint8_t mcs; TURBO = 0x10,
} TINS_END_PACK; CCK = 0x20,
OFDM = 0x40,
/** TWO_GZ = 0x80,
* \brief Default constructor. FIVE_GZ = 0x100,
*/ PASSIVE = 0x200,
RadioTap(); DYN_CCK_OFDM = 0x400,
GFSK = 0x800
/**
* \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 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 #endif // TINS_RADIOTAP_H

View File

@@ -32,29 +32,26 @@
#include <cassert> #include <cassert>
#include <cstring> #include <cstring>
#include "memory_helpers.h"
using Tins::Memory::InputMemoryStream;
namespace Tins { namespace Tins {
/* Diassoc */ /* Diassoc */
Dot11Disassoc::Dot11Disassoc(const address_type &dst_hw_addr, Dot11Disassoc::Dot11Disassoc(const address_type &dst_hw_addr,
const address_type &src_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); this->subtype(Dot11::DISASSOC);
memset(&_body, 0, sizeof(_body));
} }
Dot11Disassoc::Dot11Disassoc(const uint8_t *buffer, uint32_t total_sz) Dot11Disassoc::Dot11Disassoc(const uint8_t *buffer, uint32_t total_sz)
: Dot11ManagementFrame(buffer, total_sz) { : Dot11ManagementFrame(buffer, total_sz) {
uint32_t sz = management_frame_size(); InputMemoryStream stream(buffer, total_sz);
buffer += sz; stream.skip(management_frame_size());
total_sz -= sz; stream.read(_body);
if(total_sz < sizeof(_body)) parse_tagged_parameters(stream);
throw malformed_packet();
memcpy(&_body, buffer, sizeof(_body));
buffer += sizeof(_body);
total_sz -= sizeof(_body);
parse_tagged_parameters(buffer, total_sz);
} }
void Dot11Disassoc::reason_code(uint16_t new_reason_code) { 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, Dot11AssocRequest::Dot11AssocRequest(const address_type &dst_hw_addr,
const address_type &src_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); subtype(Dot11::ASSOC_REQ);
memset(&_body, 0, sizeof(_body));
} }
Dot11AssocRequest::Dot11AssocRequest(const uint8_t *buffer, uint32_t total_sz) Dot11AssocRequest::Dot11AssocRequest(const uint8_t *buffer, uint32_t total_sz)
: Dot11ManagementFrame(buffer, total_sz) : Dot11ManagementFrame(buffer, total_sz)
{ {
uint32_t sz = management_frame_size(); InputMemoryStream stream(buffer, total_sz);
buffer += sz; stream.skip(management_frame_size());
total_sz -= sz; stream.read(_body);
if(total_sz < sizeof(_body)) parse_tagged_parameters(stream);
throw malformed_packet();
memcpy(&_body, buffer, sizeof(_body));
buffer += sizeof(_body);
total_sz -= sizeof(_body);
parse_tagged_parameters(buffer, total_sz);
} }
void Dot11AssocRequest::listen_interval(uint16_t new_listen_interval) { 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) Dot11AssocResponse::Dot11AssocResponse(const uint8_t *buffer, uint32_t total_sz)
: Dot11ManagementFrame(buffer, total_sz) : Dot11ManagementFrame(buffer, total_sz)
{ {
uint32_t sz = management_frame_size(); InputMemoryStream stream(buffer, total_sz);
buffer += sz; stream.skip(management_frame_size());
total_sz -= sz; stream.read(_body);
if(total_sz < sizeof(_body)) parse_tagged_parameters(stream);
throw malformed_packet();
memcpy(&_body, buffer, sizeof(_body));
buffer += sizeof(_body);
total_sz -= sizeof(_body);
parse_tagged_parameters(buffer, total_sz);
} }
void Dot11AssocResponse::status_code(uint16_t new_status_code) { 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) Dot11ReAssocRequest::Dot11ReAssocRequest(const uint8_t *buffer, uint32_t total_sz)
: Dot11ManagementFrame(buffer, total_sz) : Dot11ManagementFrame(buffer, total_sz)
{ {
uint32_t sz = management_frame_size(); InputMemoryStream stream(buffer, total_sz);
buffer += sz; stream.skip(management_frame_size());
total_sz -= sz; stream.read(_body);
if(total_sz < sizeof(_body)) parse_tagged_parameters(stream);
throw malformed_packet();
memcpy(&_body, buffer, sizeof(_body));
buffer += sizeof(_body);
total_sz -= sizeof(_body);
parse_tagged_parameters(buffer, total_sz);
} }
void Dot11ReAssocRequest::listen_interval(uint16_t new_listen_interval) { 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) Dot11ReAssocResponse::Dot11ReAssocResponse(const uint8_t *buffer, uint32_t total_sz)
: Dot11ManagementFrame(buffer, total_sz) { : Dot11ManagementFrame(buffer, total_sz) {
uint32_t sz = management_frame_size(); InputMemoryStream stream(buffer, total_sz);
buffer += sz; stream.skip(management_frame_size());
total_sz -= sz; stream.read(_body);
if(total_sz < sizeof(_body)) parse_tagged_parameters(stream);
throw malformed_packet();
memcpy(&_body, buffer, sizeof(_body));
buffer += sizeof(_body);
total_sz -= sizeof(_body);
parse_tagged_parameters(buffer, total_sz);
} }
void Dot11ReAssocResponse::status_code(uint16_t new_status_code) { void Dot11ReAssocResponse::status_code(uint16_t new_status_code) {

View File

@@ -32,6 +32,9 @@
#include <cassert> #include <cassert>
#include <cstring> #include <cstring>
#include "memory_helpers.h"
using Tins::Memory::InputMemoryStream;
namespace Tins { namespace Tins {
/* Auth */ /* Auth */
@@ -47,15 +50,10 @@ const address_type &src_hw_addr)
Dot11Authentication::Dot11Authentication(const uint8_t *buffer, uint32_t total_sz) Dot11Authentication::Dot11Authentication(const uint8_t *buffer, uint32_t total_sz)
: Dot11ManagementFrame(buffer, total_sz) : Dot11ManagementFrame(buffer, total_sz)
{ {
uint32_t sz = management_frame_size(); InputMemoryStream stream(buffer, total_sz);
buffer += sz; stream.skip(management_frame_size());
total_sz -= sz; stream.read(_body);
if(total_sz < sizeof(_body)) parse_tagged_parameters(stream);
throw malformed_packet();
memcpy(&_body, buffer, sizeof(_body));
buffer += sizeof(_body);
total_sz -= sizeof(_body);
parse_tagged_parameters(buffer, total_sz);
} }
void Dot11Authentication::auth_algorithm(uint16_t new_auth_algorithm) { 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) Dot11Deauthentication::Dot11Deauthentication(const uint8_t *buffer, uint32_t total_sz)
: Dot11ManagementFrame(buffer, total_sz) { : Dot11ManagementFrame(buffer, total_sz) {
uint32_t sz = management_frame_size(); InputMemoryStream stream(buffer, total_sz);
buffer += sz; stream.skip(management_frame_size());
total_sz -= sz; stream.read(_body);
if(total_sz < sizeof(_body)) parse_tagged_parameters(stream);
throw malformed_packet();
memcpy(&_body, buffer, sizeof(_body));
buffer += sizeof(_body);
total_sz -= sizeof(_body);
parse_tagged_parameters(buffer, total_sz);
} }
void Dot11Deauthentication::reason_code(uint16_t new_reason_code) { void Dot11Deauthentication::reason_code(uint16_t new_reason_code) {

View File

@@ -54,14 +54,16 @@
#include "rsn_information.h" #include "rsn_information.h"
#include "packet_sender.h" #include "packet_sender.h"
#include "snap.h" #include "snap.h"
#include "memory_helpers.h"
using Tins::Memory::InputMemoryStream;
namespace Tins { namespace Tins {
const Dot11::address_type Dot11::BROADCAST = "ff:ff:ff:ff:ff:ff"; const Dot11::address_type Dot11::BROADCAST = "ff:ff:ff:ff:ff:ff";
Dot11::Dot11(const address_type &dst_hw_addr) 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); 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) Dot11::Dot11(const uint8_t *buffer, uint32_t total_sz)
: _options_size(0) : _options_size(0)
{ {
if(total_sz < sizeof(_header)) InputMemoryStream stream(buffer, total_sz);
throw malformed_packet(); stream.read(_header);
std::memcpy(&_header, buffer, sizeof(_header));
} }
void Dot11::parse_tagged_parameters(const uint8_t *buffer, uint32_t total_sz) { void Dot11::parse_tagged_parameters(InputMemoryStream& stream) {
if(total_sz > 0) { if (stream) {
uint8_t opcode, length; while (stream.size() >= 2) {
while(total_sz >= 2) { OptionTypes opcode = static_cast<OptionTypes>(stream.read<uint8_t>());
opcode = buffer[0]; uint8_t length = stream.read<uint8_t>();
length = buffer[1]; if (!stream.can_read(length)) {
buffer += 2;
total_sz -= 2;
if(length > total_sz) {
throw malformed_packet(); throw malformed_packet();
} }
add_tagged_option((OptionTypes)opcode, length, buffer); add_tagged_option(opcode, length, stream.pointer());
buffer += length; stream.skip(length);
total_sz -= length;
} }
} }
} }

View File

@@ -32,6 +32,9 @@
#include <cstring> #include <cstring>
#include <cassert> #include <cassert>
#include "memory_helpers.h"
using Tins::Memory::InputMemoryStream;
namespace Tins { namespace Tins {
/* Dot11Beacon */ /* Dot11Beacon */
@@ -47,15 +50,10 @@ const address_type &src_hw_addr)
Dot11Beacon::Dot11Beacon(const uint8_t *buffer, uint32_t total_sz) Dot11Beacon::Dot11Beacon(const uint8_t *buffer, uint32_t total_sz)
: Dot11ManagementFrame(buffer, total_sz) : Dot11ManagementFrame(buffer, total_sz)
{ {
uint32_t sz = management_frame_size(); InputMemoryStream stream(buffer, total_sz);
buffer += sz; stream.skip(management_frame_size());
total_sz -= sz; stream.read(_body);
if(total_sz < sizeof(_body)) parse_tagged_parameters(stream);
throw malformed_packet();
std::memcpy(&_body, buffer, sizeof(_body));
buffer += sizeof(_body);
total_sz -= sizeof(_body);
parse_tagged_parameters(buffer, total_sz);
} }
void Dot11Beacon::timestamp(uint64_t new_timestamp) { void Dot11Beacon::timestamp(uint64_t new_timestamp) {

View File

@@ -32,6 +32,9 @@
#include <cassert> #include <cassert>
#include <cstring> #include <cstring>
#include "memory_helpers.h"
using Tins::Memory::InputMemoryStream;
namespace Tins { namespace Tins {
/* Dot11Control */ /* 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) { Dot11ControlTA::Dot11ControlTA(const uint8_t *buffer, uint32_t total_sz) : Dot11Control(buffer, total_sz) {
buffer += sizeof(ieee80211_header); InputMemoryStream stream(buffer, total_sz);
total_sz -= sizeof(ieee80211_header); stream.skip(sizeof(ieee80211_header));
if(total_sz < sizeof(_taddr)) stream.read(_taddr);
throw malformed_packet();
//std::memcpy(_taddr, buffer, sizeof(_taddr));
_taddr = buffer;
} }
uint32_t Dot11ControlTA::header_size() const { 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) Dot11BlockAckRequest::Dot11BlockAckRequest(const uint8_t *buffer, uint32_t total_sz)
: Dot11ControlTA(buffer, total_sz) : Dot11ControlTA(buffer, total_sz)
{ {
uint32_t padding = controlta_size(); InputMemoryStream stream(buffer, total_sz);
buffer += padding; stream.skip(controlta_size());
total_sz -= padding; stream.read(_bar_control);
if(total_sz < sizeof(_bar_control) + sizeof(_start_sequence)) stream.read(_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));
} }
void Dot11BlockAckRequest::init_block_ack() { 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) { Dot11BlockAck::Dot11BlockAck(const uint8_t *buffer, uint32_t total_sz) : Dot11ControlTA(buffer, total_sz) {
uint32_t padding = controlta_size(); InputMemoryStream stream(buffer, total_sz);
buffer += padding; stream.skip(controlta_size());
total_sz -= padding; stream.read(_bar_control);
if(total_sz < sizeof(_bitmap) + sizeof(_bar_control) + sizeof(_start_sequence)) stream.read(_start_sequence);
throw malformed_packet(); stream.read(_bitmap);
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));
} }
void Dot11BlockAck::bar_control(small_uint<4> bar) { 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 Dot11BlockAck::write_ext_header(uint8_t *buffer, uint32_t total_sz) {
uint32_t parent_size = Dot11ControlTA::write_ext_header(buffer, total_sz); uint32_t parent_size = Dot11ControlTA::write_ext_header(buffer, total_sz);
buffer += parent_size; InputMemoryStream stream(buffer, total_sz);
std::memcpy(buffer, &_bar_control, sizeof(_bar_control)); stream.skip(parent_size);
buffer += sizeof(_bar_control); stream.read(_bar_control);
std::memcpy(buffer, &_start_sequence, sizeof(_start_sequence)); stream.read(_start_sequence);
buffer += sizeof(_start_sequence); stream.read(_bitmap);
std::memcpy(buffer, _bitmap, sizeof(_bitmap)); return total_sz - stream.size();
return parent_size + sizeof(_bitmap) + sizeof(_bar_control) + sizeof(_start_sequence);
} }
uint32_t Dot11BlockAck::header_size() const { uint32_t Dot11BlockAck::header_size() const {

View File

@@ -34,6 +34,9 @@
#include <cassert> #include <cassert>
#include "rawpdu.h" #include "rawpdu.h"
#include "snap.h" #include "snap.h"
#include "memory_helpers.h"
using Tins::Memory::InputMemoryStream;
namespace Tins { namespace Tins {
/* Dot11Data */ /* Dot11Data */
@@ -42,14 +45,16 @@ Dot11Data::Dot11Data(const uint8_t *buffer, uint32_t total_sz)
: Dot11(buffer, total_sz) : Dot11(buffer, total_sz)
{ {
const uint32_t offset = init(buffer, total_sz); const uint32_t offset = init(buffer, total_sz);
buffer += offset; InputMemoryStream stream(buffer, total_sz);
total_sz -= offset; stream.skip(offset);
if(total_sz) { if (stream) {
// If the wep bit is on, then just use a RawPDU // If the wep bit is on, then just use a RawPDU
if(wep()) if(wep()) {
inner_pdu(new Tins::RawPDU(buffer, total_sz)); inner_pdu(new Tins::RawPDU(stream.pointer(), stream.size()));
else }
inner_pdu(new Tins::SNAP(buffer, total_sz)); 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) { uint32_t Dot11Data::init(const uint8_t *buffer, uint32_t total_sz) {
const uint8_t *start_ptr = buffer; InputMemoryStream stream(buffer, total_sz);
uint32_t sz = Dot11::header_size(); stream.skip(Dot11::header_size());
buffer += sz; stream.read(_ext_header);
total_sz -= sz; if (from_ds() && to_ds()) {
if(total_sz < sizeof(_ext_header)) stream.read(_addr4);
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());
} }
return static_cast<uint32_t>(buffer - start_ptr); return total_sz - stream.size();
} }
Dot11Data::Dot11Data(const address_type &dst_hw_addr, 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) Dot11QoSData::Dot11QoSData(const uint8_t *buffer, uint32_t total_sz)
// Am I breaking something? :S // Am I breaking something? :S
: Dot11Data(buffer, total_sz, no_inner_pdu()) { : Dot11Data(buffer, total_sz, no_inner_pdu()) {
uint32_t sz = data_frame_size(); InputMemoryStream stream(buffer, total_sz);
buffer += sz; stream.skip(data_frame_size());
total_sz -= sz; stream.read(_qos_control);
if(total_sz < sizeof(_qos_control)) if (total_sz) {
throw malformed_packet();
std::memcpy(&_qos_control, buffer, sizeof(uint16_t));
total_sz -= sizeof(uint16_t);
buffer += sizeof(uint16_t);
if(total_sz) {
// If the wep bit is on, then just use a RawPDU // If the wep bit is on, then just use a RawPDU
if(wep()) if (wep()) {
inner_pdu(new Tins::RawPDU(buffer, total_sz)); inner_pdu(new Tins::RawPDU(stream.pointer(), stream.size()));
else }
inner_pdu(new Tins::SNAP(buffer, total_sz)); else {
inner_pdu(new Tins::SNAP(stream.pointer(), stream.size()));
}
} }
} }

View File

@@ -32,6 +32,9 @@
#include <cstring> #include <cstring>
#include "rsn_information.h" #include "rsn_information.h"
#include "memory_helpers.h"
using Tins::Memory::InputMemoryStream;
namespace Tins { namespace Tins {
/* Dot11ManagementFrame */ /* Dot11ManagementFrame */
@@ -39,33 +42,27 @@ namespace Tins {
Dot11ManagementFrame::Dot11ManagementFrame(const uint8_t *buffer, uint32_t total_sz) Dot11ManagementFrame::Dot11ManagementFrame(const uint8_t *buffer, uint32_t total_sz)
: Dot11(buffer, total_sz) : Dot11(buffer, total_sz)
{ {
buffer += sizeof(ieee80211_header); InputMemoryStream stream(buffer, total_sz);
total_sz -= sizeof(ieee80211_header); stream.skip(sizeof(ieee80211_header));
if(total_sz < sizeof(_ext_header)) stream.read(_ext_header);
throw malformed_packet(); if (from_ds() && to_ds()) {
std::memcpy(&_ext_header, buffer, sizeof(_ext_header)); stream.read(_addr4);
total_sz -= sizeof(_ext_header);
if(from_ds() && to_ds()) {
if(total_sz >= _addr4.size())
_addr4 = buffer + sizeof(_ext_header);
else
throw malformed_packet();
} }
} }
Dot11ManagementFrame::Dot11ManagementFrame(const address_type &dst_hw_addr, Dot11ManagementFrame::Dot11ManagementFrame(const address_type &dst_hw_addr,
const address_type &src_hw_addr) const address_type &src_hw_addr)
: Dot11(dst_hw_addr) : Dot11(dst_hw_addr), _ext_header()
{ {
type(Dot11::MANAGEMENT); type(Dot11::MANAGEMENT);
memset(&_ext_header, 0, sizeof(_ext_header));
addr2(src_hw_addr); addr2(src_hw_addr);
} }
uint32_t Dot11ManagementFrame::header_size() const { uint32_t Dot11ManagementFrame::header_size() const {
uint32_t sz = Dot11::header_size() + sizeof(_ext_header); 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; sz += 6;
}
return sz; return sz;
} }

View File

@@ -33,6 +33,9 @@
#include <cstring> #include <cstring>
#include <cassert> #include <cassert>
#include "memory_helpers.h"
using Tins::Memory::InputMemoryStream;
namespace Tins { namespace Tins {
/* Probe Request */ /* Probe Request */
@@ -47,34 +50,27 @@ Dot11ProbeRequest::Dot11ProbeRequest(const address_type &dst_hw_addr,
Dot11ProbeRequest::Dot11ProbeRequest(const uint8_t *buffer, uint32_t total_sz) Dot11ProbeRequest::Dot11ProbeRequest(const uint8_t *buffer, uint32_t total_sz)
: Dot11ManagementFrame(buffer, total_sz) : Dot11ManagementFrame(buffer, total_sz)
{ {
uint32_t sz = management_frame_size(); InputMemoryStream stream(buffer, total_sz);
buffer += sz; stream.skip(management_frame_size());
total_sz -= sz; parse_tagged_parameters(stream);
parse_tagged_parameters(buffer, total_sz);
} }
/* Probe Response */ /* Probe Response */
Dot11ProbeResponse::Dot11ProbeResponse(const address_type &dst_hw_addr, Dot11ProbeResponse::Dot11ProbeResponse(const address_type &dst_hw_addr,
const address_type &src_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); this->subtype(Dot11::PROBE_RESP);
memset(&_body, 0, sizeof(_body));
} }
Dot11ProbeResponse::Dot11ProbeResponse(const uint8_t *buffer, uint32_t total_sz) Dot11ProbeResponse::Dot11ProbeResponse(const uint8_t *buffer, uint32_t total_sz)
: Dot11ManagementFrame(buffer, total_sz) : Dot11ManagementFrame(buffer, total_sz)
{ {
uint32_t sz = management_frame_size(); InputMemoryStream stream(buffer, total_sz);
buffer += sz; stream.skip(management_frame_size());
total_sz -= sz; stream.read(_body);
if(total_sz < sizeof(_body)) parse_tagged_parameters(stream);
throw malformed_packet();
memcpy(&_body, buffer, sizeof(_body));
buffer += sizeof(_body);
total_sz -= sizeof(_body);
parse_tagged_parameters(buffer, total_sz);
} }
void Dot11ProbeResponse::timestamp(uint64_t new_timestamp) { void Dot11ProbeResponse::timestamp(uint64_t new_timestamp) {

View File

@@ -45,50 +45,48 @@
#include "exceptions.h" #include "exceptions.h"
#include "pdu_allocator.h" #include "pdu_allocator.h"
#include "internals.h" #include "internals.h"
#include "memory_helpers.h"
using Tins::Memory::InputMemoryStream;
namespace Tins { namespace Tins {
IPv6::IPv6(address_type ip_dst, address_type ip_src, PDU *child) 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); version(6);
dst_addr(ip_dst); dst_addr(ip_dst);
src_addr(ip_src); src_addr(ip_src);
} }
IPv6::IPv6(const uint8_t *buffer, uint32_t total_sz) IPv6::IPv6(const uint8_t *buffer, uint32_t total_sz)
: headers_size(0) { : headers_size(0)
if(total_sz < sizeof(_header)) {
throw malformed_packet(); InputMemoryStream stream(buffer, total_sz);
std::memcpy(&_header, buffer, sizeof(_header)); stream.read(_header);
buffer += sizeof(_header);
total_sz -= sizeof(_header);
uint8_t current_header = _header.next_header; uint8_t current_header = _header.next_header;
while(total_sz) { while (stream) {
if(is_extension_header(current_header)) { if(is_extension_header(current_header)) {
if(total_sz < 8) const uint8_t ext_type = stream.read<uint8_t>();
throw malformed_packet();
// every ext header is at least 8 bytes long // every ext header is at least 8 bytes long
// minus one, from the next_header field. // 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 // -1 -> next header identifier
if(total_sz < size) if(!stream.can_read(ext_size)) {
throw malformed_packet(); throw malformed_packet();
}
// minus one, from the size field // minus one, from the size field
add_ext_header( add_ext_header(ext_header(ext_type, payload_size, stream.pointer()));
ext_header(buffer[0], size - sizeof(uint8_t)*2, buffer + 2) current_header = ext_type;
); stream.skip(payload_size);
current_header = buffer[0];
buffer += size;
total_sz -= size;
} }
else { else {
inner_pdu( inner_pdu(
Internals::pdu_from_flag( Internals::pdu_from_flag(
static_cast<Constants::IP::e>(current_header), static_cast<Constants::IP::e>(current_header),
buffer, stream.pointer(),
total_sz, stream.size(),
false false
) )
); );
@@ -96,14 +94,16 @@ IPv6::IPv6(const uint8_t *buffer, uint32_t total_sz)
inner_pdu( inner_pdu(
Internals::allocate<IPv6>( Internals::allocate<IPv6>(
current_header, current_header,
buffer, stream.pointer(),
total_sz stream.size()
) )
); );
if(!inner_pdu()) if(!inner_pdu()) {
inner_pdu(new Tins::RawPDU(buffer, total_sz)); 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 "stp.h"
#include "rawpdu.h" #include "rawpdu.h"
#include "exceptions.h" #include "exceptions.h"
#include "memory_helpers.h"
using Tins::Memory::InputMemoryStream;
namespace Tins { namespace Tins {
const uint8_t LLC::GLOBAL_DSAP_ADDR = 0xFF; const uint8_t LLC::GLOBAL_DSAP_ADDR = 0xFF;
const uint8_t LLC::NULL_ADDR = 0x00; const uint8_t LLC::NULL_ADDR = 0x00;
LLC::LLC() LLC::LLC()
: _type(LLC::INFORMATION) : _header(), control_field(), _type(LLC::INFORMATION)
{ {
memset(&_header, 0, sizeof(llchdr));
control_field_length = 2; control_field_length = 2;
memset(&control_field, 0, sizeof(control_field));
information_field_length = 0; information_field_length = 0;
} }
LLC::LLC(uint8_t dsap, uint8_t ssap) LLC::LLC(uint8_t dsap, uint8_t ssap)
: _type(LLC::INFORMATION) : control_field(), _type(LLC::INFORMATION)
{ {
_header.dsap = dsap; _header.dsap = dsap;
_header.ssap = ssap; _header.ssap = ssap;
control_field_length = 2; control_field_length = 2;
memset(&control_field, 0, sizeof(control_field));
information_field_length = 0; information_field_length = 0;
} }
LLC::LLC(const uint8_t *buffer, uint32_t total_sz) { LLC::LLC(const uint8_t *buffer, uint32_t total_sz) {
// header + 1 info byte InputMemoryStream stream(buffer, total_sz);
if(total_sz < sizeof(_header) + 1) stream.read(_header);
throw malformed_packet(); if (!stream) {
std::memcpy(&_header, buffer, sizeof(_header)); throw malformed_packet();
buffer += sizeof(_header); }
total_sz -= sizeof(_header);
information_field_length = 0; information_field_length = 0;
if ((buffer[0] & 0x03) == LLC::UNNUMBERED) { if ((*stream.pointer() & 0x03) == LLC::UNNUMBERED) {
if(total_sz < sizeof(un_control_field))
throw malformed_packet();
type(LLC::UNNUMBERED); type(LLC::UNNUMBERED);
std::memcpy(&control_field.unnumbered, buffer, sizeof(un_control_field)); stream.read(control_field.unnumbered);
buffer += sizeof(un_control_field); // TODO: Create information fields if corresponding.
total_sz -= sizeof(un_control_field);
//TODO: Create information fields if corresponding.
} }
else { else {
if(total_sz < sizeof(info_control_field)) type((Format)(*stream.pointer() & 0x03));
throw malformed_packet();
type((Format)(buffer[0] & 0x03));
control_field_length = 2; control_field_length = 2;
std::memcpy(&control_field.info, buffer, sizeof(info_control_field)); stream.read(control_field.info);
buffer += 2;
total_sz -= 2;
} }
if(total_sz > 0) { if (stream) {
if(dsap() == 0x42 && ssap() == 0x42) if (dsap() == 0x42 && ssap() == 0x42) {
inner_pdu(new Tins::STP(buffer, total_sz)); inner_pdu(new Tins::STP(stream.pointer(), stream.size()));
else }
inner_pdu(new Tins::RawPDU(buffer, total_sz)); else {
inner_pdu(new Tins::RawPDU(stream.pointer(), stream.size()));
}
} }
} }

View File

@@ -48,13 +48,17 @@
#include "llc.h" #include "llc.h"
#include "rawpdu.h" #include "rawpdu.h"
#include "exceptions.h" #include "exceptions.h"
#include "memory_helpers.h"
#if !defined(PF_LLC) #if !defined(PF_LLC)
// compilation fix, nasty but at least works on BSD // compilation fix, nasty but at least works on BSD
#define PF_LLC 26 #define PF_LLC 26
#endif #endif
using Tins::Memory::InputMemoryStream;
namespace Tins { namespace Tins {
Loopback::Loopback() Loopback::Loopback()
: _family() : _family()
{ {
@@ -63,22 +67,19 @@ Loopback::Loopback()
Loopback::Loopback(const uint8_t *buffer, uint32_t total_sz) Loopback::Loopback(const uint8_t *buffer, uint32_t total_sz)
{ {
if(total_sz < sizeof(_family)) InputMemoryStream stream(buffer, total_sz);
throw malformed_packet(); _family = stream.read<uint32_t>();
_family = *reinterpret_cast<const uint32_t*>(buffer);
buffer += sizeof(uint32_t);
total_sz -= sizeof(uint32_t);
#ifndef _WIN32 #ifndef _WIN32
if(total_sz) { if (total_sz) {
switch(_family) { switch (_family) {
case PF_INET: case PF_INET:
inner_pdu(new Tins::IP(buffer, total_sz)); inner_pdu(new Tins::IP(stream.pointer(), stream.size()));
break; break;
case PF_LLC: case PF_LLC:
inner_pdu(new Tins::LLC(buffer, total_sz)); inner_pdu(new Tins::LLC(stream.pointer(), stream.size()));
break; break;
default: default:
inner_pdu(new Tins::RawPDU(buffer, total_sz)); inner_pdu(new Tins::RawPDU(stream.pointer(), stream.size()));
break; break;
}; };
} }

View File

@@ -32,30 +32,29 @@
#include "exceptions.h" #include "exceptions.h"
#include "pktap.h" #include "pktap.h"
#include "internals.h" #include "internals.h"
#include "memory_helpers.h"
using Tins::Memory::InputMemoryStream;
namespace Tins { namespace Tins {
PKTAP::PKTAP() { PKTAP::PKTAP() : header_() {
memset(&header_, 0, sizeof(header_));
} }
PKTAP::PKTAP(const uint8_t* buffer, uint32_t total_sz) { PKTAP::PKTAP(const uint8_t* buffer, uint32_t total_sz) {
if (total_sz < sizeof(pktap_header)) { InputMemoryStream stream(buffer, total_sz);
throw malformed_packet(); stream.read(header_);
}
memcpy(&header_, buffer, sizeof(header_));
uint32_t header_length = header_.length; uint32_t header_length = header_.length;
if (header_length > total_sz) { if (header_length > total_sz || header_length < sizeof(header_)) {
throw malformed_packet(); throw malformed_packet();
} }
buffer += header_length; stream.skip(header_length - sizeof(header_));
total_sz -= header_length; if (header_.next && stream) {
if (header_.next && total_sz > 0) {
inner_pdu( inner_pdu(
Internals::pdu_from_dlt_flag( Internals::pdu_from_dlt_flag(
header_.dlt, header_.dlt,
buffer, stream.pointer(),
total_sz stream.size()
) )
); );
} }

View File

@@ -42,50 +42,51 @@
#include "ppi.h" #include "ppi.h"
#include "internals.h" #include "internals.h"
#include "exceptions.h" #include "exceptions.h"
#include "memory_helpers.h"
using Tins::Memory::InputMemoryStream;
namespace Tins { namespace Tins {
PPI::PPI(const uint8_t *buffer, uint32_t total_sz) { 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(); 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 // There are some options
const size_t options_length = length() - sizeof(_header); const size_t options_length = length() - sizeof(_header);
if(options_length > 0) { if (options_length > 0) {
_data.assign(buffer, buffer + options_length); _data.assign(stream.pointer(), stream.pointer() + options_length);
buffer += options_length; stream.skip(options_length);
total_sz -= static_cast<uint32_t>(options_length);
} }
if(total_sz > 0) { if (stream) {
switch(dlt()) { switch (dlt()) {
case DLT_IEEE802_11: case DLT_IEEE802_11:
#ifdef HAVE_DOT11 #ifdef HAVE_DOT11
parse_80211(buffer, total_sz); parse_80211(stream.pointer(), stream.size());
#else #else
throw protocol_disabled(); throw protocol_disabled();
#endif #endif
break; break;
case DLT_EN10MB: case DLT_EN10MB:
if(Internals::is_dot3(buffer, total_sz)) if(Internals::is_dot3(stream.pointer(), stream.size()))
inner_pdu(new Dot3(buffer, total_sz)); inner_pdu(new Dot3(stream.pointer(), stream.size()));
else else
inner_pdu(new EthernetII(buffer, total_sz)); inner_pdu(new EthernetII(stream.pointer(), stream.size()));
break; break;
case DLT_IEEE802_11_RADIO: case DLT_IEEE802_11_RADIO:
#ifdef HAVE_DOT11 #ifdef HAVE_DOT11
inner_pdu(new RadioTap(buffer, total_sz)); inner_pdu(new RadioTap(stream.pointer(), stream.size()));
#else #else
throw protocol_disabled(); throw protocol_disabled();
#endif #endif
break; break;
case DLT_NULL: case DLT_NULL:
inner_pdu(new Loopback(buffer, total_sz)); inner_pdu(new Loopback(stream.pointer(), stream.size()));
break; break;
case DLT_LINUX_SLL: case DLT_LINUX_SLL:
inner_pdu(new Tins::SLL(buffer, total_sz)); inner_pdu(new Tins::SLL(stream.pointer(), stream.size()));
break; break;
} }
} }

View File

@@ -34,6 +34,9 @@
#include "pppoe.h" #include "pppoe.h"
#include "rawpdu.h" #include "rawpdu.h"
#include "exceptions.h" #include "exceptions.h"
#include "memory_helpers.h"
using Tins::Memory::InputMemoryStream;
namespace Tins { namespace Tins {
@@ -47,42 +50,27 @@ PPPoE::PPPoE()
PPPoE::PPPoE(const uint8_t *buffer, uint32_t total_sz) PPPoE::PPPoE(const uint8_t *buffer, uint32_t total_sz)
: _tags_size() : _tags_size()
{ {
if(total_sz < sizeof(_header)) InputMemoryStream stream(buffer, total_sz);
throw malformed_packet(); stream.read(_header);
std::memcpy(&_header, buffer, sizeof(_header)); stream.size(std::min(stream.size(), (uint32_t)payload_length()));
buffer += sizeof(_header);
total_sz -= sizeof(_header);
total_sz = std::min(total_sz, (uint32_t)payload_length());
// If this is a session data packet // If this is a session data packet
if(code() == 0) { if (code() == 0) {
if(total_sz > 0) { if (stream) {
inner_pdu( inner_pdu(
new RawPDU(buffer, total_sz) new RawPDU(stream.pointer(), stream.size())
); );
} }
} }
else { else {
const uint8_t *end = buffer + total_sz; const uint8_t *end = stream.pointer() + stream.size();
while(buffer < end) { while (stream.pointer() < end) {
if(buffer + sizeof(uint32_t) * 2 > 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(); throw malformed_packet();
uint16_t opt_type; }
std::memcpy(&opt_type, buffer, sizeof(uint16_t)); add_tag(tag(opt_type, opt_len, stream.pointer()));
uint16_t opt_len; stream.skip(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);
} }
} }
} }

View File

@@ -65,9 +65,8 @@ void read_field(const uint8_t* &buffer, uint32_t &total_sz, T& field) {
total_sz -= sizeof(field); total_sz -= sizeof(field);
} }
RadioTap::RadioTap() RadioTap::RadioTap() : _radio()
{ {
std::memset(&_radio, 0, sizeof(_radio));
init(); init();
} }

View File

@@ -34,15 +34,13 @@
#include <stdexcept> #include <stdexcept>
#include "exceptions.h" #include "exceptions.h"
#include "pdu_option.h" #include "pdu_option.h"
#include "memory_helpers.h"
#include "dot11/dot11_base.h" #include "dot11/dot11_base.h"
using Tins::Memory::InputMemoryStream;
namespace Tins { 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) { 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) { 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(); 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); while (pairwise_cyphers_size--) {
add_pairwise_cypher(
std::memcpy(&uint16_t_buffer, buffer, sizeof(uint16_t)); (RSNInformation::CypherSuites)Endian::le_to_host(stream.read<uint32_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);
} }
check_size<uint16_t>(total_sz); int akm_cyphers_size = Endian::le_to_host(stream.read<uint16_t>());
if (!stream.can_read(akm_cyphers_size)) {
std::memcpy(&uint16_t_buffer, buffer, sizeof(uint16_t)); throw malformed_packet();
capabilities(Endian::le_to_host(uint16_t_buffer)); }
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) { void RSNInformation::add_pairwise_cypher(CypherSuites cypher) {

View File

@@ -32,24 +32,25 @@
#include "sll.h" #include "sll.h"
#include "internals.h" #include "internals.h"
#include "exceptions.h" #include "exceptions.h"
#include "memory_helpers.h"
using Tins::Memory::InputMemoryStream;
namespace Tins { namespace Tins {
SLL::SLL() : _header() { SLL::SLL() : _header() {
} }
SLL::SLL(const uint8_t *buffer, uint32_t total_sz) { SLL::SLL(const uint8_t *buffer, uint32_t total_sz) {
if(total_sz < sizeof(_header)) InputMemoryStream stream(buffer, total_sz);
throw malformed_packet(); stream.read(_header);
std::memcpy(&_header, buffer, sizeof(_header)); if (stream) {
buffer += sizeof(_header);
total_sz -= sizeof(_header);
if(total_sz) {
inner_pdu( inner_pdu(
Internals::pdu_from_flag( Internals::pdu_from_flag(
(Constants::Ethernet::e)protocol(), (Constants::Ethernet::e)protocol(),
buffer, stream.pointer(),
total_sz stream.size()
) )
); );
} }

View File

@@ -43,34 +43,34 @@
#include "eapol.h" #include "eapol.h"
#include "internals.h" #include "internals.h"
#include "exceptions.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; _snap.dsap = _snap.ssap = 0xaa;
control(3); 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)) InputMemoryStream stream(buffer, total_sz);
throw malformed_packet(); stream.read(_snap);
std::memcpy(&_snap, buffer, sizeof(_snap)); if (stream) {
buffer += sizeof(_snap);
total_sz -= sizeof(_snap);
if(total_sz) {
inner_pdu( inner_pdu(
Internals::pdu_from_flag( Internals::pdu_from_flag(
(Constants::Ethernet::e)eth_type(), (Constants::Ethernet::e)eth_type(),
buffer, stream.pointer(),
total_sz stream.size()
) )
); );
} }
} }
void Tins::SNAP::control(uint8_t new_control) { void SNAP::control(uint8_t new_control) {
#if TINS_IS_LITTLE_ENDIAN #if TINS_IS_LITTLE_ENDIAN
_snap.control_org = (_snap.control_org & 0xffffff00) | (new_control); _snap.control_org = (_snap.control_org & 0xffffff00) | (new_control);
#else #else
@@ -78,7 +78,7 @@ void Tins::SNAP::control(uint8_t new_control) {
#endif #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 #if TINS_IS_LITTLE_ENDIAN
_snap.control_org = Endian::host_to_be<uint32_t>(new_org) | control(); _snap.control_org = Endian::host_to_be<uint32_t>(new_org) | control();
#else #else
@@ -86,15 +86,15 @@ void Tins::SNAP::org_code(small_uint<24> new_org) {
#endif #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); _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); 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 #ifdef TINS_DEBUG
assert(total_sz >= sizeof(_snap)); assert(total_sz >= sizeof(_snap));
#endif #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)); std::memcpy(buffer, &_snap, sizeof(_snap));
} }
} // Tins

View File

@@ -34,6 +34,9 @@
#include <algorithm> #include <algorithm>
#include "stp.h" #include "stp.h"
#include "exceptions.h" #include "exceptions.h"
#include "memory_helpers.h"
using Tins::Memory::InputMemoryStream;
namespace Tins { namespace Tins {
@@ -45,9 +48,8 @@ STP::STP()
STP::STP(const uint8_t *buffer, uint32_t total_sz) STP::STP(const uint8_t *buffer, uint32_t total_sz)
{ {
if(total_sz < sizeof(_header)) InputMemoryStream stream(buffer, total_sz);
throw malformed_packet(); stream.read(_header);
std::memcpy(&_header, buffer ,sizeof(_header));
} }
void STP::proto_id(uint16_t new_proto_id) { void STP::proto_id(uint16_t new_proto_id) {

View File

@@ -39,24 +39,25 @@
#include "ipv6.h" #include "ipv6.h"
#include "rawpdu.h" #include "rawpdu.h"
#include "exceptions.h" #include "exceptions.h"
#include "memory_helpers.h"
using Tins::Memory::InputMemoryStream;
namespace Tins { namespace Tins {
UDP::UDP(uint16_t dport, uint16_t sport)
UDP::UDP(uint16_t dport, uint16_t sport) : _udp()
{ {
this->dport(dport); this->dport(dport);
this->sport(sport); this->sport(sport);
_udp.check = 0;
_udp.len = 0;
} }
UDP::UDP(const uint8_t *buffer, uint32_t total_sz) UDP::UDP(const uint8_t *buffer, uint32_t total_sz)
{ {
if(total_sz < sizeof(udphdr)) InputMemoryStream stream(buffer, total_sz);
throw malformed_packet(); stream.read(_udp);
std::memcpy(&_udp, buffer, sizeof(udphdr)); if (stream) {
total_sz -= sizeof(udphdr); inner_pdu(new RawPDU(stream.pointer(), stream.size()));
if(total_sz) }
inner_pdu(new RawPDU(buffer + sizeof(udphdr), total_sz));
} }
void UDP::dport(uint16_t new_dport) { void UDP::dport(uint16_t new_dport) {