1
0
mirror of https://github.com/mfontanini/libtins synced 2026-01-23 02:35:57 +01:00

Fix merging problems

This commit is contained in:
Santiago Alessandri
2011-09-07 10:09:14 -03:00
15 changed files with 493 additions and 718 deletions

View File

@@ -307,7 +307,7 @@ namespace Tins {
*
* \return The value of the duration/id field in an uint16_t.
*/
inline uint16_t duration_id() const { return Utils::net_to_host_s(this->_header.duration_id); }
inline uint16_t duration_id() const { return this->_header.duration_id; }
/**
* \brief Getter for the first address.
@@ -938,7 +938,7 @@ namespace Tins {
*
* \return The sequence number as an uint16_t.
*/
inline uint16_t seq_num() const { return Utils::net_to_host_s(this->_ext_header.seq_control.seq_number); }
inline uint16_t seq_num() const { return this->_ext_header.seq_control.seq_number; }
/**
* \brief Getter for the fourth address.
@@ -995,11 +995,11 @@ namespace Tins {
uint8_t addr3[6];
struct {
#if __BYTE_ORDER == __LITTLE_ENDIAN
unsigned int seq_number:12;
unsigned int frag_number:4;
unsigned int seq_number:12;
#elif __BYTE_ORDER == __BIG_ENDIAN
unsigned int frag_number:4;
unsigned int seq_number:12;
unsigned int frag_number:4;
#endif
} __attribute__((__packed__)) seq_control;
} __attribute__((__packed__));
@@ -1042,125 +1042,6 @@ namespace Tins {
uint32_t write_ext_header(uint8_t *buffer, uint32_t total_sz);
void copy_ext_header(const Dot11ManagementFrame *other);
private:
ExtendedHeader _ext_header;
uint8_t _addr4[6];
};
class Dot11DataFrame : public Dot11 {
public:
/**
* \brief Constructor which creates a Dot11DataFrame object from a buffer and adds all identifiable
* PDUs found in the buffer as children of this one.
* \param buffer The buffer from which this PDU will be constructed.
* \param total_sz The total size of the buffer.
*/
Dot11DataFrame(uint32_t iface_index, const uint8_t *dst_hw_addr = 0, const uint8_t *src_hw_addr = 0, PDU* child = 0);
Dot11DataFrame(const uint8_t *dst_hw_addr = 0, const uint8_t *src_hw_addr = 0, PDU* child = 0);
Dot11DataFrame(const std::string &iface, const uint8_t *dst_hw_addr, const uint8_t *src_hw_addr, PDU* child = 0) throw (std::runtime_error);
Dot11DataFrame(const uint8_t *buffer, uint32_t total_sz);
Dot11DataFrame(const Dot11DataFrame &other);
/**
* \brief Getter for the second address.
*
* \return The second address as a constant uint8_t pointer.
*/
inline const uint8_t* addr2() const { return this->_ext_header.addr2; }
/**
* \brief Getter for the third address.
*
* \return The third address as a constant uint8_t pointer.
*/
inline const uint8_t* addr3() const { return this->_ext_header.addr3; }
/**
* \brief Getter for the fragment number.
*
* \return The fragment number as an uint8_t.
*/
inline uint8_t frag_num() const { return this->_ext_header.seq_control.frag_number; }
/**
* \brief Getter for the sequence number.
*
* \return The sequence number as an uint16_t.
*/
inline uint16_t seq_num() const { return Utils::net_to_host_s(this->_ext_header.seq_control.seq_number); }
/**
* \brief Getter for the fourth address.
*
* \return The fourth address as a constant uint8_t pointer.
*/
inline const uint8_t* addr4() const { return this->_addr4; }
/**
* \brief Setter for the second address.
*
* \param new_addr2 const uint8_t array of 6 bytes containing the new second's address.
*/
void addr2(const uint8_t* new_addr2);
/**
* \brief Setter for the third address.
*
* \param new_addr3 const uint8_t array of 6 bytes containing the new third address.
*/
void addr3(const uint8_t* new_addr3);
/**
* \brief Setter for the fragment number.
*
* \param new_frag_num uint8_t with the new fragment number.
*/
void frag_num(uint8_t new_frag_num);
/**
* \brief Setter for the sequence number.
*
* \param new_seq_num uint16_t with the new sequence number.
*/
void seq_num(uint16_t new_seq_num);
/**
* \brief Setter for the fourth address.
*
* \param new_addr4 const uint8_t array of 6 bytes containing the new fourth address.
*/
void addr4(const uint8_t* new_addr4);
/**
* \brief Returns the 802.11 frame's header length.
*
* \return An uint32_t with the header's size.
* \sa PDU::header_size()
*/
uint32_t header_size() const;
/**
* \brief Getter for the PDU's type.
* \sa PDU::pdu_type
*/
PDUType pdu_type() const { return PDU::DOT11_DATA; }
protected:
struct ExtendedHeader {
uint8_t addr2[6];
uint8_t addr3[6];
struct {
#if __BYTE_ORDER == __LITTLE_ENDIAN
unsigned int seq_number:12;
unsigned int frag_number:4;
#elif __BYTE_ORDER == __BIG_ENDIAN
unsigned int frag_number:4;
unsigned int seq_number:12;
#endif
} __attribute__((__packed__)) seq_control;
} __attribute__((__packed__));
uint32_t write_ext_header(uint8_t *buffer, uint32_t total_sz);
void copy_ext_header(const Dot11DataFrame *other);
private:
ExtendedHeader _ext_header;
@@ -1224,7 +1105,7 @@ namespace Tins {
/**
* \brief Getter for the interval field.
*
* \return Timestamp value in an uint64_t.
* \return Timestamp value in an uint16_t.
*/
inline uint16_t interval() const { return Utils::net_to_host_s(this->_body.interval); }
@@ -1304,6 +1185,19 @@ namespace Tins {
* \sa PDU::header_size()
*/
uint32_t header_size() const;
/**
* \brief Clones this PDU.
*
* \sa PDU::clone_pdu
*/
PDU *clone_pdu() const;
/**
* \brief Getter for the PDU's type.
* \sa PDU::pdu_type
*/
PDUType pdu_type() const { return PDU::DOT11_BEACON; }
private:
struct BeaconBody {
uint64_t timestamp;
@@ -1374,6 +1268,13 @@ namespace Tins {
* \sa PDU::header_size()
*/
uint32_t header_size() const;
/**
* \brief Clones this PDU.
*
* \sa PDU::clone_pdu
*/
PDU *clone_pdu() const;
private:
struct DisassocBody {
uint16_t reason_code;
@@ -1516,6 +1417,13 @@ namespace Tins {
* \sa PDU::header_size()
*/
uint32_t header_size() const;
/**
* \brief Clones this PDU.
*
* \sa PDU::clone_pdu
*/
PDU *clone_pdu() const;
private:
struct AssocReqBody {
CapabilityInformation capability;
@@ -1646,6 +1554,13 @@ namespace Tins {
* \sa PDU::header_size()
*/
uint32_t header_size() const;
/**
* \brief Clones this PDU.
*
* \sa PDU::clone_pdu
*/
PDU *clone_pdu() const;
private:
struct AssocRespBody {
CapabilityInformation capability;
@@ -1659,303 +1574,129 @@ namespace Tins {
AssocRespBody _body;
};
/**
* \brief Class representing an ReAssociation Request frame in the IEEE 802.11 Protocol.
*
*/
class Dot11ReAssocRequest : public Dot11ManagementFrame {
class Dot11Data : public Dot11 {
public:
/**
* \brief Default constructor for the ReAssociation Request frame.
*
*/
Dot11ReAssocRequest();
/**
* \brief Constructor for creating a 802.11 ReAssociation Request.
*
* Constructor that builds a 802.11 ReAssociation Request taking the interface name,
* destination's and source's MAC.
*
* \param iface string containing the interface's name from where to send the packet.
* \param dst_hw_addr uint8_t array of 6 bytes containing the destination's MAC(optional).
* \param src_hw_addr uint8_t array of 6 bytes containing the source's MAC(optional).
*/
Dot11ReAssocRequest(const std::string& iface, const uint8_t* dst_hw_addr = 0, const uint8_t* src_hw_addr = 0) throw (std::runtime_error);
/**
* \brief Constructor which creates a Dot11ReAssocRequest object from a
* buffer and adds all identifiable PDUs found in the buffer as children of this one.
*
* \brief Constructor which creates a Dot11Data object from a buffer and adds all identifiable
* PDUs found in the buffer as children of this one.
* \param buffer The buffer from which this PDU will be constructed.
* \param total_sz The total size of the buffer.
*/
Dot11ReAssocRequest(const uint8_t *buffer, uint32_t total_sz);
Dot11Data(uint32_t iface_index, const uint8_t *dst_hw_addr = 0, const uint8_t *src_hw_addr = 0, PDU* child = 0);
Dot11Data(const uint8_t *dst_hw_addr = 0, const uint8_t *src_hw_addr = 0, PDU* child = 0);
Dot11Data(const std::string &iface, const uint8_t *dst_hw_addr, const uint8_t *src_hw_addr, PDU* child = 0) throw (std::runtime_error);
Dot11Data(const uint8_t *buffer, uint32_t total_sz);
/**
* \brief Copy constructor.
*/
Dot11ReAssocRequest(const Dot11ReAssocRequest &other);
/**
* \brief Copy assignment operator.
*/
Dot11ReAssocRequest &operator= (const Dot11ReAssocRequest &other);
/**
* \brief Getter for the Capabilities Information.
* \brief Getter for the second address.
*
* \return CapabilityInformation Structure in a CapabilityInformation&.
* \return The second address as a constant uint8_t pointer.
*/
inline const CapabilityInformation& capabilities() const { return this->_body.capability;}
inline const uint8_t* addr2() const { return this->_ext_header.addr2; }
/**
* \brief Getter for the Capabilities Information.
* \brief Getter for the third address.
*
* \return CapabilityInformation Structure in a CapabilityInformation&.
* \return The third address as a constant uint8_t pointer.
*/
inline CapabilityInformation& capabilities() { return this->_body.capability;}
inline const uint8_t* addr3() const { return this->_ext_header.addr3; }
/**
* \brief Getter for the listen interval.
* \brief Getter for the fragment number.
*
* \return The listen interval in an uint16_t.
* \return The fragment number as an uint8_t.
*/
inline uint16_t listen_interval() const { return this->_body.listen_interval; }
inline uint8_t frag_num() const { return this->_ext_header.seq_control.frag_number; }
/**
* \brief Getter for the current AP field.
* \brief Getter for the sequence number.
*
* \return The current AP value in an uint8_t*.
* \return The sequence number as an uint16_t.
*/
inline const uint8_t* current_ap() const {return this->_body.current_ap; }
inline uint16_t seq_num() const { return this->_ext_header.seq_control.seq_number; }
/**
* \brief Setter for the listen interval.
* \brief Getter for the fourth address.
*
* \param new_listen_interval uint16_t with the new listen interval.
* \return The fourth address as a constant uint8_t pointer.
*/
void listen_interval(uint16_t new_listen_interval);
inline const uint8_t* addr4() const { return this->_addr4; }
/**
* \brief Setter for the current AP field.
* \brief Setter for the second address.
*
* \param new_current_ap uint8_t array of 6 bytes with the new current_ap
* \param new_addr2 const uint8_t array of 6 bytes containing the new second's address.
*/
void current_ap(const uint8_t* new_current_ap);
void addr2(const uint8_t* new_addr2);
/**
* \brief Helper method to set the essid.
* \brief Setter for the third address.
*
* \param new_ssid The ssid to be set.
* \param new_addr3 const uint8_t array of 6 bytes containing the new third address.
*/
void ssid(const std::string &new_ssid);
void addr3(const uint8_t* new_addr3);
/**
* \brief Helper method to set the supported rates.
* \brief Setter for the fragment number.
*
* \param new_rates A list of rates to be set.
* \param new_frag_num uint8_t with the new fragment number.
*/
void supported_rates(const std::list<float> &new_rates);
void frag_num(uint8_t new_frag_num);
/**
* \brief Helper method to set the extended supported rates.
* \brief Setter for the sequence number.
*
* \param new_rates A list of rates to be set.
* \param new_seq_num uint16_t with the new sequence number.
*/
void extended_supported_rates(const std::list<float> &new_rates);
void seq_num(uint16_t new_seq_num);
/**
* \brief Helper method to set the power capabilities.
* \brief Setter for the fourth address.
*
* \param min_power uint8_t indicating the minimum transmiting power capability.
* \param max_power uint8_t indicating the maximum transmiting power capability.
* \param new_addr4 const uint8_t array of 6 bytes containing the new fourth address.
*/
void power_capabilities(uint8_t min_power, uint8_t max_power);
void addr4(const uint8_t* new_addr4);
/**
* \brief Helper method to set the supported channels.
*
* \param new_channels A list of channels to be set.
*/
void supported_channels(const std::list<std::pair<uint8_t, uint8_t> > &new_channels);
/**
* \brief Helper method to set the RSN information option.
*
* \param info The RSNInformation structure to be set.
*/
void rsn_information(const RSNInformation& info);
/**
* \brief Helper method to set the QoS capabilities.
*
* \param new_qos_capabilities uint8_t with the capabilities.
*/
void qos_capabilities(uint8_t new_qos_capabilities);
/**
* \brief Returns the frame's header length.
* \brief Returns the 802.11 frame's header length.
*
* \return An uint32_t with the header's size.
* \sa PDU::header_size()
*/
uint32_t header_size() const;
/**
* \brief Getter for the PDU's type.
* \sa PDU::pdu_type
*/
PDUType pdu_type() const { return PDU::DOT11_DATA; }
/**
* \brief Clones this PDU.
*
* \sa PDU::clone_pdu
*/
PDU *clone_pdu() const;
protected:
struct ExtendedHeader {
uint8_t addr2[6];
uint8_t addr3[6];
struct {
#if __BYTE_ORDER == __LITTLE_ENDIAN
unsigned int seq_number:12;
unsigned int frag_number:4;
#elif __BYTE_ORDER == __BIG_ENDIAN
unsigned int frag_number:4;
unsigned int seq_number:12;
#endif
} __attribute__((__packed__)) seq_control;
} __attribute__((__packed__));
uint32_t write_ext_header(uint8_t *buffer, uint32_t total_sz);
void copy_ext_header(const Dot11Data *other);
private:
struct ReAssocReqBody {
CapabilityInformation capability;
uint16_t listen_interval;
uint8_t current_ap[6];
};
void copy_fields(const Dot11ReAssocRequest* other);
uint32_t write_fixed_parameters(uint8_t* buffer, uint32_t total_sz);
ReAssocReqBody _body;
};
/**
* \brief Class representing an ReAssociation Response frame in the IEEE 802.11 Protocol.
*
*/
class Dot11ReAssocResponse : public Dot11ManagementFrame {
public:
/**
* \brief Default constructor for the Association Response frame.
*
*/
Dot11ReAssocResponse();
/**
* \brief Constructor for creating a 802.11 ReAssociation Response.
*
* Constructor that builds a 802.11 ReAssociation Response taking the interface name,
* destination's and source's MAC.
*
* \param iface string containing the interface's name from where to send the packet.
* \param dst_hw_addr uint8_t array of 6 bytes containing the destination's MAC(optional).
* \param src_hw_addr uint8_t array of 6 bytes containing the source's MAC(optional).
*/
Dot11ReAssocResponse(const std::string& iface, const uint8_t* dst_hw_addr = 0, const uint8_t* src_hw_addr = 0) throw (std::runtime_error);
/**
* \brief Constructor which creates a Dot11ReAssocResponse object from a
* buffer and adds all identifiable PDUs found in the buffer as children of this one.
*
* \param buffer The buffer from which this PDU will be constructed.
* \param total_sz The total size of the buffer.
*/
Dot11ReAssocResponse(const uint8_t *buffer, uint32_t total_sz);
/**
* \brief Copy constructor.
*/
Dot11ReAssocResponse(const Dot11ReAssocResponse &other);
/**
* \brief Copy assignment operator
*/
Dot11ReAssocResponse &operator= (const Dot11ReAssocResponse &other);
/**
* \brief Getter for the Capabilities Information.
*
* \return CapabilityInformation Structure in a CapabilityInformation&.
*/
inline const CapabilityInformation& capabilities() const { return this->_body.capability;}
/**
* \brief Getter for the Capabilities Information.
*
* \return CapabilityInformation Structure in a CapabilityInformation&.
*/
inline CapabilityInformation& capabilities() { return this->_body.capability;}
/**
* \brief Getter for the status code.
*
* \return The status code in an uint16_t.
*/
inline uint16_t status_code() const { return this->_body.status_code; }
/**
* \brief Getter for the AID field.
*
* \return The AID field value in an uint16_t.
*/
inline uint16_t aid() const { return this->_body.aid; }
/**
* \brief Setter for the status code.
*
* \param new_status_code uint16_t with the new status code.
*/
void status_code(uint16_t new_status_code);
/**
* \brief Setter for the AID field.
*
* \param new_aid uint16_t with the new AID value.
*/
void aid(uint16_t new_aid);
/**
* \brief Helper method to set the supported rates.
*
* \param new_rates A list of rates to be set.
*/
void supported_rates(const std::list<float> &new_rates);
/**
* \brief Helper method to set the extended supported rates.
*
* \param new_rates A list of rates to be set.
*/
void extended_supported_rates(const std::list<float> &new_rates);
/**
* \brief Helper method to set the EDCA Parameter Set.
*
* \param ac_be uint32_t with the value of the ac_be field.
* \param ac_bk uint32_t with the value of the ac_bk field.
* \param ac_vi uint32_t with the value of the ac_vi field.
* \param ac_vo uint32_t with the value of the ac_vo field.
*/
void edca_parameter_set(uint32_t ac_be, uint32_t ac_bk, uint32_t ac_vi, uint32_t ac_vo);
/**
* \brief Returns the frame's header length.
*
* \return An uint32_t with the header's size.
* \sa PDU::header_size()
*/
uint32_t header_size() const;
protected:
private:
struct ReAssocRespBody {
CapabilityInformation capability;
uint16_t status_code;
uint16_t aid;
};
void copy_fields(const Dot11ReAssocResponse *other);
uint32_t write_fixed_parameters(uint8_t *buffer, uint32_t total_sz);
ReAssocRespBody _body;
ExtendedHeader _ext_header;
uint8_t _addr4[6];
};
/**
@@ -2093,7 +1834,7 @@ namespace Tins {
};
class Dot11QoSData : public Dot11DataFrame {
class Dot11QoSData : public Dot11Data {
public:
@@ -2174,6 +1915,13 @@ namespace Tins {
*/
uint32_t header_size() const;
/**
* \brief Clones this PDU.
*
* \sa PDU::clone_pdu
*/
PDU *clone_pdu() const;
/**
* \brief Getter for the PDU's type.
* \sa PDU::pdu_type
@@ -2369,6 +2117,13 @@ namespace Tins {
*/
Dot11RTS(const uint8_t *buffer, uint32_t total_sz);
/**
* \brief Clones this PDU.
*
* \sa PDU::clone_pdu
*/
PDU *clone_pdu() const;
/**
* \brief Getter for the PDU's type.
* \sa PDU::pdu_type
@@ -2422,6 +2177,13 @@ namespace Tins {
* \param total_sz The total size of the buffer.
*/
Dot11PSPoll(const uint8_t *buffer, uint32_t total_sz);
/**
* \brief Clones this PDU.
*
* \sa PDU::clone_pdu
*/
PDU *clone_pdu() const;
};
class Dot11CFEnd : public Dot11ControlTA {
@@ -2470,6 +2232,13 @@ namespace Tins {
* \param total_sz The total size of the buffer.
*/
Dot11CFEnd(const uint8_t *buffer, uint32_t total_sz);
/**
* \brief Clones this PDU.
*
* \sa PDU::clone_pdu
*/
PDU *clone_pdu() const;
};
class Dot11EndCFAck : public Dot11ControlTA {
@@ -2515,6 +2284,13 @@ namespace Tins {
* \param total_sz The total size of the buffer.
*/
Dot11EndCFAck(const uint8_t *buffer, uint32_t total_sz);
/**
* \brief Clones this PDU.
*
* \sa PDU::clone_pdu
*/
PDU *clone_pdu() const;
};
class Dot11Ack : public Dot11Control {
@@ -2567,6 +2343,14 @@ namespace Tins {
* \sa PDU::pdu_type
*/
PDUType pdu_type() const { return PDU::DOT11_ACK; }
/**
* \brief Clones this PDU.
*
* \sa PDU::clone_pdu
*/
PDU *clone_pdu() const;
};
/**
@@ -2650,6 +2434,13 @@ namespace Tins {
* \param bar The new start sequence field.
*/
void start_sequence(uint16_t seq);
/**
* \brief Clones this PDU.
*
* \sa PDU::clone_pdu
*/
PDU *clone_pdu() const;
protected:
/**
* \brief Getter for the control ta additional fields size.
@@ -2746,6 +2537,13 @@ namespace Tins {
* \sa PDU::pdu_type
*/
PDUType pdu_type() const { return PDU::DOT11_BLOCK_ACK; }
/**
* \brief Clones this PDU.
*
* \sa PDU::clone_pdu
*/
PDU *clone_pdu() const;
private:
uint32_t write_ext_header(uint8_t *buffer, uint32_t total_sz);

View File

@@ -55,6 +55,7 @@ namespace Tins {
DOT11,
DOT11_DATA,
DOT11_QOS_DATA,
DOT11_BEACON,
DOT11_CONTROL,
DOT11_ACK,
DOT11_BLOCK_ACK,
@@ -174,7 +175,7 @@ namespace Tins {
/* Should be pure virtual. It's this way to avoid compiling issues.
* Once every pdu has implemented it, make it pure virtual. */
return 0;
}
}
/** \brief Send the stack of PDUs through a PacketSender.
*
@@ -259,27 +260,6 @@ namespace Tins {
* \param parent The PDU that's one level below this one on the stack. Might be 0.
*/
virtual void write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *parent) = 0;
/** \brief Does the 16 bits sum of all 2 bytes elements between start and end.
*
* This is the checksum used by IP, UDP and TCP. If there's and odd number of
* bytes, the last one is padded and added to the checksum. The checksum is performed
* using network endiannes.
* \param start The pointer to the start of the buffer.
* \param end The pointer to the end of the buffer(excluding the last element).
* \return Returns the checksum between start and end(non inclusive).
*/
static uint32_t do_checksum(uint8_t *start, uint8_t *end);
/** \brief Performs the pseudo header checksum used in TCP and UDP PDUs.
*
* \param source_ip The source ip address.
* \param dest_ip The destination ip address.
* \param len The length to be included in the pseudo header.
* \param flag The flag to use in the protocol field of the pseudo header.
* \return The pseudo header checksum.
*/
static uint32_t pseudoheader_checksum(uint32_t source_ip, uint32_t dest_ip, uint32_t len, uint32_t flag);
private:
uint32_t _flag;
PDU *_inner_pdu;

View File

@@ -29,6 +29,11 @@ namespace Tins {
/**
* \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 0xce, and the rx_flag and antenna fields to 0.
*/
class RadioTap : public PDU {
public:
@@ -88,14 +93,16 @@ namespace Tins {
/**
* \brief Creates an instance of RadioTap.
* \param iface The name of the interface in which to send this PDU.
* \param child The child PDU.(optional)
*/
RadioTap(const std::string &iface) throw (std::runtime_error);
RadioTap(const std::string &iface, PDU *child = 0) throw (std::runtime_error);
/**
* \brief Creates an instance of RadioTap.
* \param iface_index The index of the interface in which to send this PDU.
* \param child The child PDU.(optional)
*/
RadioTap(uint32_t iface_index);
RadioTap(uint32_t iface_index, PDU *child = 0);
/**
* \brief Constructor which creates a RadioTap object from a buffer and adds all
@@ -297,6 +304,7 @@ namespace Tins {
ext:1;
} __attribute__((__packed__));
void init();
void write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *parent);

View File

@@ -26,6 +26,7 @@
#include <pcap.h>
#include <string>
#include <stdexcept>
#include "pdu.h"
namespace Tins {
@@ -65,8 +66,9 @@ namespace Tins {
* \brief Creates an instance of sniffer.
* \param device The device which will be sniffed.
* \param max_packet_size The maximum packet size to be read.
* \param filter A capture filter to compile and use for sniffing sessions.(optional);
*/
Sniffer(const std::string &device, unsigned max_packet_size);
Sniffer(const std::string &device, unsigned max_packet_size, const std::string &filter = "") throw(std::runtime_error);
/**
* \brief Sniffer destructor.
@@ -77,15 +79,13 @@ namespace Tins {
/**
* \brief Compiles a filter and uses it to capture one packet.
*
* This method returns the first sniffed PDU that matches the given
* filter. If no filter is given, the previously set filter will be used.
* If no filter has been set, then no filtering is applied to sniffed
* packets.
* \param filter The filter which will be used while sniffing.
* This method returns the first sniffed packet that matches the
* sniffer's filter, or the first sniffed packet if no filter has
* been set.
* \return The captured packet, matching the given filter, 0 if an
* error occured(probably compiling the filter).
*/
PDU *next_packet(const std::string &filter = "");
PDU *next_packet();
/**
* \brief Starts a sniffing loop, using a callback object for every
@@ -95,10 +95,9 @@ namespace Tins {
* or it could be a specific SnifferHandler specialization. This method deletes
* packets after they are handled, therefore the handlers MUST NOT delete them.
* \param cback_handler The callback handler object which should process packets.
* \param filter The filter to use when sniffing(optional).
* \param max_packets The maximum amount of packets to sniff. 0 == infinite.
*/
void sniff_loop(AbstractSnifferHandler *cback_handler, const std::string &filter = "", uint32_t max_packets = 0);
void sniff_loop(AbstractSnifferHandler *cback_handler, uint32_t max_packets = 0);
/**
* \brief Sets a filter on this sniffer.

View File

@@ -368,6 +368,8 @@ namespace Tins {
static const uint16_t DEFAULT_WINDOW;
void copy_fields(const TCP *other);
void cleanup();
/** \brief Serialices this TCP PDU.
* \param buffer The buffer in which the PDU will be serialized.
* \param total_sz The size available in the buffer.

View File

@@ -177,6 +177,27 @@ namespace Tins {
*/
uint16_t channel_to_mhz(uint16_t channel);
/** \brief Does the 16 bits sum of all 2 bytes elements between start and end.
*
* This is the checksum used by IP, UDP and TCP. If there's and odd number of
* bytes, the last one is padded and added to the checksum. The checksum is performed
* using network endiannes.
* \param start The pointer to the start of the buffer.
* \param end The pointer to the end of the buffer(excluding the last element).
* \return Returns the checksum between start and end(non inclusive).
*/
uint32_t do_checksum(uint8_t *start, uint8_t *end);
/** \brief Performs the pseudo header checksum used in TCP and UDP PDUs.
*
* \param source_ip The source ip address.
* \param dest_ip The destination ip address.
* \param len The length to be included in the pseudo header.
* \param flag The flag to use in the protocol field of the pseudo header.
* \return The pseudo header checksum.
*/
uint32_t pseudoheader_checksum(uint32_t source_ip, uint32_t dest_ip, uint32_t len, uint32_t flag);
/** \brief Generic function to iterate through interface and collect
* data.
*

View File

@@ -24,6 +24,7 @@
#include <stdexcept>
#include <algorithm>
#include <utility>
#include <iostream>
#ifndef WIN32
#include <net/ethernet.h>
#include <netpacket/packet.h>
@@ -42,8 +43,10 @@ const uint8_t *Tins::Dot11::BROADCAST = (const uint8_t*)"\xff\xff\xff\xff\xff\xf
Tins::Dot11::Dot11(const uint8_t* dst_hw_addr, PDU* child) : PDU(ETHERTYPE_IP, child), _options_size(0) {
memset(&this->_header, 0, sizeof(ieee80211_header));
if(dst_hw_addr)
if(dst_hw_addr) {
this->addr1(dst_hw_addr);
}
}
Tins::Dot11::Dot11(const std::string& iface, const uint8_t* dst_hw_addr, PDU* child) throw (std::runtime_error) : PDU(ETHERTYPE_IP, child), _options_size(0) {
@@ -72,10 +75,6 @@ Tins::Dot11::Dot11(const uint8_t *buffer, uint32_t total_sz) : PDU(ETHERTYPE_IP)
std::memcpy(&_header, buffer, sz);
buffer += sz;
total_sz -= sz;
if(type() == 2 && subtype() < 4) {
// It's a data packet
inner_pdu(new Tins::SNAP(buffer, total_sz));
}
}
Tins::Dot11::Dot11(const Dot11 &other) : PDU(other) {
@@ -169,7 +168,7 @@ void Tins::Dot11::order(bool new_value) {
}
void Tins::Dot11::duration_id(uint16_t new_duration_id) {
this->_header.duration_id = Utils::net_to_host_s(new_duration_id);
this->_header.duration_id = new_duration_id;
}
void Tins::Dot11::addr1(const uint8_t* new_addr1) {
@@ -240,7 +239,7 @@ Tins::PDU *Tins::Dot11::from_bytes(const uint8_t *buffer, uint32_t total_sz) {
}
else if(hdr->control.type == DATA){
if(hdr->control.subtype <= 4)
ret = new Dot11DataFrame(buffer, total_sz);
ret = new Dot11Data(buffer, total_sz);
else
ret = new Dot11QoSData(buffer, total_sz);
}
@@ -273,12 +272,16 @@ void Tins::Dot11::copy_80211_fields(const Dot11 *other) {
_options.push_back(Dot11_Option(it->option, it->length, it->value));
}
/*
* Dot11ManagementFrame
*/
/* Dot11ManagementFrame */
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 std::runtime_error("Not enough size for an IEEE 802.11 header in the buffer.");
std::memcpy(&_ext_header, buffer, sizeof(_ext_header));
if(from_ds() && to_ds())
std::memcpy(_addr4, buffer + sizeof(_ext_header), sizeof(_addr4));
}
Tins::Dot11ManagementFrame::Dot11ManagementFrame(const uint8_t *dst_hw_addr, const uint8_t *src_hw_addr) : Dot11(dst_hw_addr) {
@@ -290,8 +293,8 @@ Tins::Dot11ManagementFrame::Dot11ManagementFrame(const uint8_t *dst_hw_addr, con
}
Tins::Dot11ManagementFrame::Dot11ManagementFrame(const std::string &iface,
const uint8_t *dst_hw_addr,
const uint8_t *src_hw_addr) throw (std::runtime_error) : Dot11(iface, dst_hw_addr) {
const uint8_t *dst_hw_addr,
const uint8_t *src_hw_addr) throw (std::runtime_error) : Dot11(iface, dst_hw_addr) {
this->type(Dot11::MANAGEMENT);
if(src_hw_addr)
addr2(src_hw_addr);
@@ -329,7 +332,7 @@ void Tins::Dot11ManagementFrame::frag_num(uint8_t new_frag_num) {
}
void Tins::Dot11ManagementFrame::seq_num(uint16_t new_seq_num) {
this->_ext_header.seq_control.seq_number = Utils::net_to_host_s(new_seq_num);
this->_ext_header.seq_control.seq_number = new_seq_num;
}
void Tins::Dot11ManagementFrame::addr4(const uint8_t* new_addr4) {
@@ -589,82 +592,6 @@ void Tins::Dot11ManagementFrame::tpc_report(uint8_t transmit_power, uint8_t link
}
/*
* Dot11DataFrame
*/
Tins::Dot11DataFrame::Dot11DataFrame(const uint8_t *buffer, uint32_t total_sz) : Dot11(buffer, total_sz) {
}
Tins::Dot11DataFrame::Dot11DataFrame(uint32_t iface_index, const uint8_t *dst_hw_addr, const uint8_t *src_hw_addr, PDU* child) : Dot11(iface_index, dst_hw_addr, child) {
this->type(Dot11::DATA);
this->addr2(src_hw_addr);
}
Tins::Dot11DataFrame::Dot11DataFrame(const uint8_t *dst_hw_addr, const uint8_t *src_hw_addr, PDU* child) : Dot11(dst_hw_addr, child) {
this->type(Dot11::DATA);
this->addr2(src_hw_addr);
}
Tins::Dot11DataFrame::Dot11DataFrame(const std::string &iface,
const uint8_t *dst_hw_addr,
const uint8_t *src_hw_addr,
PDU* child) throw (std::runtime_error) : Dot11(iface, dst_hw_addr, child) {
this->type(Dot11::DATA);
this->addr2(src_hw_addr);
}
Tins::Dot11DataFrame::Dot11DataFrame(const Dot11DataFrame &other) : Dot11(other) {
}
void Tins::Dot11DataFrame::copy_ext_header(const Dot11DataFrame* other) {
Dot11::copy_80211_fields(other);
std::memcpy(&this->_ext_header, &other->_ext_header, sizeof(this->_ext_header));
std::memcpy(this->_addr4, other->_addr4, 6);
}
uint32_t Tins::Dot11DataFrame::header_size() const {
uint32_t sz = Dot11::header_size() + sizeof(_ext_header);
if (this->from_ds() && this->to_ds())
sz += 6;
return sz;
}
void Tins::Dot11DataFrame::addr2(const uint8_t* new_addr2) {
memcpy(this->_ext_header.addr2, new_addr2, 6);
}
void Tins::Dot11DataFrame::addr3(const uint8_t* new_addr3) {
memcpy(this->_ext_header.addr3, new_addr3, 6);
}
void Tins::Dot11DataFrame::frag_num(uint8_t new_frag_num) {
this->_ext_header.seq_control.frag_number = new_frag_num;
}
void Tins::Dot11DataFrame::seq_num(uint16_t new_seq_num) {
this->_ext_header.seq_control.seq_number = Utils::net_to_host_s(new_seq_num);
}
void Tins::Dot11DataFrame::addr4(const uint8_t* new_addr4) {
memcpy(this->_addr4, new_addr4, 6);
}
uint32_t Tins::Dot11DataFrame::write_ext_header(uint8_t *buffer, uint32_t total_sz) {
uint32_t written = sizeof(this->_ext_header);
memcpy(buffer, &this->_ext_header, sizeof(this->_ext_header));
buffer += sizeof(this->_ext_header);
if (this->from_ds() && this->to_ds()) {
written += 6;
memcpy(buffer, this->_addr4, 6);
}
return written;
}
/* Dot11Beacon */
Tins::Dot11Beacon::Dot11Beacon(const uint8_t* dst_hw_addr, const uint8_t* src_hw_addr) : Dot11ManagementFrame() {
@@ -680,8 +607,9 @@ Tins::Dot11Beacon::Dot11Beacon(const std::string& iface,
}
Tins::Dot11Beacon::Dot11Beacon(const uint8_t *buffer, uint32_t total_sz) : Dot11ManagementFrame(buffer, total_sz) {
buffer += sizeof(ieee80211_header);
total_sz -= sizeof(ieee80211_header);
uint32_t sz = Dot11ManagementFrame::header_size();
buffer += sz;
total_sz -= sz;
if(total_sz < sizeof(_body))
throw std::runtime_error("Not enough size for a IEEE 802.11 beacon header in the buffer.");
memcpy(&_body, buffer, sizeof(_body));
@@ -786,6 +714,12 @@ uint32_t Tins::Dot11Beacon::write_fixed_parameters(uint8_t *buffer, uint32_t tot
return sz;
}
Tins::PDU *Tins::Dot11Beacon::clone_pdu() const {
Dot11Beacon *new_pdu = new Dot11Beacon();
new_pdu->copy_80211_fields(this);
return new_pdu;
}
/* 802.11 diassoc */
Tins::Dot11Disassoc::Dot11Disassoc() : Dot11ManagementFrame() {
@@ -830,9 +764,14 @@ uint32_t Tins::Dot11Disassoc::write_fixed_parameters(uint8_t *buffer, uint32_t t
return sz;
}
/*
* RSNInformation class
*/
Tins::PDU *Tins::Dot11Disassoc::clone_pdu() const {
Dot11Disassoc *new_pdu = new Dot11Disassoc();
new_pdu->copy_80211_fields(this);
return new_pdu;
}
/* RSNInformation */
Tins::RSNInformation::RSNInformation() : _version(1), _capabilities(0) {
}
@@ -906,8 +845,9 @@ Tins::Dot11AssocRequest::Dot11AssocRequest(const std::string& iface,
}
Tins::Dot11AssocRequest::Dot11AssocRequest(const uint8_t *buffer, uint32_t total_sz) : Dot11ManagementFrame(buffer, total_sz) {
buffer += sizeof(ieee80211_header);
total_sz -= sizeof(ieee80211_header);
uint32_t sz = Dot11ManagementFrame::header_size();
buffer += sz;
total_sz -= sz;
if(total_sz < sizeof(_body))
throw std::runtime_error("Not enough size for an IEEE 802.11 association header in the buffer.");
memcpy(&_body, buffer, sizeof(_body));
@@ -974,6 +914,12 @@ uint32_t Tins::Dot11AssocRequest::write_fixed_parameters(uint8_t *buffer, uint32
return sz;
}
Tins::PDU *Tins::Dot11AssocRequest::clone_pdu() const {
Dot11AssocRequest *new_pdu = new Dot11AssocRequest();
new_pdu->copy_80211_fields(this);
return new_pdu;
}
/* Assoc response. */
Tins::Dot11AssocResponse::Dot11AssocResponse() : Dot11ManagementFrame() {
@@ -1045,164 +991,116 @@ uint32_t Tins::Dot11AssocResponse::write_fixed_parameters(uint8_t *buffer, uint3
return sz;
}
/* ReAssoc Request */
Tins::Dot11ReAssocRequest::Dot11ReAssocRequest() : Dot11ManagementFrame() {
this->subtype(Dot11::REASSOC_REQ);
memset(&_body, 0, sizeof(_body));
Tins::PDU *Tins::Dot11AssocResponse::clone_pdu() const {
Dot11AssocResponse *new_pdu = new Dot11AssocResponse();
new_pdu->copy_80211_fields(this);
return new_pdu;
}
Tins::Dot11ReAssocRequest::Dot11ReAssocRequest(const std::string& iface,
const uint8_t* dst_hw_addr,
const uint8_t* src_hw_addr) throw (std::runtime_error) : Dot11ManagementFrame(iface, dst_hw_addr, src_hw_addr) {
this->subtype(Dot11::REASSOC_REQ);
memset(&_body, 0, sizeof(_body));
}
/* Dot11Data */
Tins::Dot11ReAssocRequest::Dot11ReAssocRequest(const uint8_t *buffer, uint32_t total_sz) : Dot11ManagementFrame(buffer, total_sz) {
uint32_t sz = Dot11ManagementFrame::header_size();
Tins::Dot11Data::Dot11Data(const uint8_t *buffer, uint32_t total_sz) : Dot11(buffer, total_sz) {
uint32_t sz = Dot11::header_size();
buffer += sz;
total_sz -= sz;
if(total_sz < sizeof(_body))
throw std::runtime_error("Not enough size for an IEEE 802.11 association header in the buffer.");
memcpy(&_body, buffer, sizeof(_body));
buffer += sizeof(_body);
total_sz -= sizeof(_body);
parse_tagged_parameters(buffer, total_sz);
if(total_sz < sizeof(_ext_header))
throw std::runtime_error("Not enough size for an IEEE 802.11 data header in the buffer.");
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 < sizeof(_addr4))
throw std::runtime_error("Not enough size for an IEEE 802.11 data header in the buffer.");
std::memcpy(&_addr4, buffer, sizeof(_addr4));
buffer += sizeof(_addr4);
total_sz -= sizeof(_addr4);
}
inner_pdu(new Tins::SNAP(buffer, total_sz));
}
Tins::Dot11ReAssocRequest::Dot11ReAssocRequest(const Dot11ReAssocRequest &other) : Dot11ManagementFrame(other) {
copy_fields(&other);
Tins::Dot11Data::Dot11Data(uint32_t iface_index, const uint8_t *dst_hw_addr, const uint8_t *src_hw_addr, PDU* child) : Dot11(iface_index, dst_hw_addr, child) {
this->type(Dot11::DATA);
if(src_hw_addr)
this->addr2(src_hw_addr);
else
std::memset(_ext_header.addr2, 0, sizeof(_ext_header.addr2));
}
Tins::Dot11ReAssocRequest &Tins::Dot11ReAssocRequest::operator= (const Dot11ReAssocRequest &other) {
copy_inner_pdu(other);
copy_fields(&other);
return *this;
Tins::Dot11Data::Dot11Data(const uint8_t *dst_hw_addr, const uint8_t *src_hw_addr, PDU* child) : Dot11(dst_hw_addr, child) {
this->type(Dot11::DATA);
if(src_hw_addr)
this->addr2(src_hw_addr);
else
std::memset(_ext_header.addr2, 0, sizeof(_ext_header.addr2));
}
void Tins::Dot11ReAssocRequest::copy_fields(const Dot11ReAssocRequest *other) {
Dot11ManagementFrame::copy_ext_header(other);
std::memcpy(&_body, &other->_body, sizeof(_body));
Tins::Dot11Data::Dot11Data(const std::string &iface,
const uint8_t *dst_hw_addr,
const uint8_t *src_hw_addr,
PDU* child) throw (std::runtime_error) : Dot11(iface, dst_hw_addr, child) {
this->type(Dot11::DATA);
if(src_hw_addr)
this->addr2(src_hw_addr);
else
std::memset(_ext_header.addr2, 0, sizeof(_ext_header.addr2));
}
void Tins::Dot11ReAssocRequest::listen_interval(uint16_t new_listen_interval) {
this->_body.listen_interval = new_listen_interval;
void Tins::Dot11Data::copy_ext_header(const Dot11Data* other) {
Dot11::copy_80211_fields(other);
std::memcpy(&this->_ext_header, &other->_ext_header, sizeof(this->_ext_header));
std::memcpy(this->_addr4, other->_addr4, 6);
}
void Tins::Dot11ReAssocRequest::current_ap(const uint8_t* new_current_ap) {
memcpy(this->_body.current_ap, new_current_ap, 6);
}
void Tins::Dot11ReAssocRequest::ssid(const std::string &new_ssid) {
Dot11ManagementFrame::ssid(new_ssid);
}
void Tins::Dot11ReAssocRequest::supported_rates(const std::list<float> &new_rates) {
Dot11ManagementFrame::supported_rates(new_rates);
}
void Tins::Dot11ReAssocRequest::extended_supported_rates(const std::list<float> &new_rates) {
Dot11ManagementFrame::extended_supported_rates(new_rates);
}
void Tins::Dot11ReAssocRequest::power_capabilities(uint8_t min_power, uint8_t max_power) {
Dot11ManagementFrame::power_capabilities(min_power, max_power);
}
void Tins::Dot11ReAssocRequest::supported_channels(const std::list<pair<uint8_t, uint8_t> > &new_channels) {
Dot11ManagementFrame::supported_channels(new_channels);
}
void Tins::Dot11ReAssocRequest::rsn_information(const RSNInformation& info) {
Dot11ManagementFrame::rsn_information(info);
}
void Tins::Dot11ReAssocRequest::qos_capabilities(uint8_t new_qos_capabilities) {
Dot11ManagementFrame::qos_capabilities(new_qos_capabilities);
}
uint32_t Tins::Dot11ReAssocRequest::header_size() const {
return Dot11ManagementFrame::header_size() + sizeof(this->_body);
}
uint32_t Tins::Dot11ReAssocRequest::write_fixed_parameters(uint8_t *buffer, uint32_t total_sz) {
uint32_t sz = sizeof(this->_body);
assert(sz <= total_sz);
memcpy(buffer, &this->_body, sz);
uint32_t Tins::Dot11Data::header_size() const {
uint32_t sz = Dot11::header_size() + sizeof(_ext_header);
if (this->from_ds() && this->to_ds())
sz += 6;
return sz;
}
/* ReAssociation Response */
Tins::Dot11ReAssocResponse::Dot11ReAssocResponse() : Dot11ManagementFrame() {
this->subtype(Dot11::REASSOC_RESP);
memset(&_body, 0, sizeof(_body));
void Tins::Dot11Data::addr2(const uint8_t* new_addr2) {
memcpy(this->_ext_header.addr2, new_addr2, 6);
}
Tins::Dot11ReAssocResponse::Dot11ReAssocResponse(const std::string& iface,
const uint8_t* dst_hw_addr,
const uint8_t* src_hw_addr) throw (std::runtime_error) : Dot11ManagementFrame(iface, dst_hw_addr, src_hw_addr) {
this->subtype(Dot11::REASSOC_RESP);
memset(&_body, 0, sizeof(_body));
void Tins::Dot11Data::addr3(const uint8_t* new_addr3) {
memcpy(this->_ext_header.addr3, new_addr3, 6);
}
Tins::Dot11ReAssocResponse::Dot11ReAssocResponse(const uint8_t *buffer, uint32_t total_sz) : Dot11ManagementFrame(buffer, total_sz) {
uint32_t sz = Dot11ManagementFrame::header_size();
buffer += sz;
total_sz -= sz;
if(total_sz < sizeof(_body))
throw std::runtime_error("Not enough size for an IEEE 802.11 reassociation response header in the buffer.");
memcpy(&_body, buffer, sizeof(_body));
buffer += sizeof(_body);
total_sz -= sizeof(_body);
parse_tagged_parameters(buffer, total_sz);
void Tins::Dot11Data::frag_num(uint8_t new_frag_num) {
this->_ext_header.seq_control.frag_number = new_frag_num;
}
Tins::Dot11ReAssocResponse::Dot11ReAssocResponse(const Dot11ReAssocResponse &other) : Dot11ManagementFrame(other) {
copy_fields(&other);
void Tins::Dot11Data::seq_num(uint16_t new_seq_num) {
this->_ext_header.seq_control.seq_number = new_seq_num;
}
Tins::Dot11ReAssocResponse &Tins::Dot11ReAssocResponse::operator= (const Dot11ReAssocResponse &other) {
copy_inner_pdu(other);
copy_fields(&other);
return *this;
void Tins::Dot11Data::addr4(const uint8_t* new_addr4) {
memcpy(this->_addr4, new_addr4, 6);
}
void Tins::Dot11ReAssocResponse::copy_fields(const Dot11ReAssocResponse *other) {
Dot11ManagementFrame::copy_ext_header(other);
std::memcpy(&_body, &other->_body, sizeof(_body));
uint32_t Tins::Dot11Data::write_ext_header(uint8_t *buffer, uint32_t total_sz) {
uint32_t written = sizeof(this->_ext_header);
memcpy(buffer, &this->_ext_header, sizeof(this->_ext_header));
buffer += sizeof(this->_ext_header);
if (this->from_ds() && this->to_ds()) {
written += 6;
memcpy(buffer, this->_addr4, 6);
}
return written;
}
void Tins::Dot11ReAssocResponse::status_code(uint16_t new_status_code) {
this->_body.status_code = new_status_code;
Tins::PDU *Tins::Dot11Data::clone_pdu() const {
Dot11Data *new_pdu = new Dot11Data();
new_pdu->copy_80211_fields(this);
return new_pdu;
}
void Tins::Dot11ReAssocResponse::aid(uint16_t new_aid) {
this->_body.aid = new_aid;
}
/* QoS data. */
void Tins::Dot11ReAssocResponse::supported_rates(const std::list<float> &new_rates) {
Dot11ManagementFrame::supported_rates(new_rates);
}
Tins::Dot11QoSData::Dot11QoSData(const uint8_t* dst_hw_addr, const uint8_t* src_hw_addr, PDU* child) : Dot11Data(dst_hw_addr, src_hw_addr, child) {
void Tins::Dot11ReAssocResponse::extended_supported_rates(const std::list<float> &new_rates) {
Dot11ManagementFrame::extended_supported_rates(new_rates);
}
void Tins::Dot11ReAssocResponse::edca_parameter_set(uint32_t ac_be, uint32_t ac_bk, uint32_t ac_vi, uint32_t ac_vo) {
Dot11ManagementFrame::edca_parameter_set(ac_be, ac_bk, ac_vi, ac_vo);
}
uint32_t Tins::Dot11ReAssocResponse::header_size() const {
return Dot11ManagementFrame::header_size() + sizeof(this->_body);
}
uint32_t Tins::Dot11ReAssocResponse::write_fixed_parameters(uint8_t *buffer, uint32_t total_sz) {
uint32_t sz = sizeof(this->_body);
assert(sz <= total_sz);
memcpy(buffer, &this->_body, sz);
return sz;
}
/* Probe Request */
@@ -1245,18 +1143,18 @@ Tins::PDU* Tins::Dot11ProbeRequest::clone_pdu() const {
/* QoS data. */
Tins::Dot11QoSData::Dot11QoSData(const std::string& iface, const uint8_t* dst_hw_addr, const uint8_t* src_hw_addr, PDU* child) throw (std::runtime_error) : Dot11DataFrame(iface, dst_hw_addr, src_hw_addr, child) {
Tins::Dot11QoSData::Dot11QoSData(const std::string& iface, const uint8_t* dst_hw_addr, const uint8_t* src_hw_addr, PDU* child) throw (std::runtime_error) : Dot11Data(iface, dst_hw_addr, src_hw_addr, child) {
this->subtype(Dot11::QOS_DATA_DATA);
this->_qos_control = 0;
}
Tins::Dot11QoSData::Dot11QoSData(uint32_t iface_index, const uint8_t* dst_hw_addr, const uint8_t* src_hw_addr, PDU* child) : Dot11DataFrame(iface_index, dst_hw_addr, src_hw_addr, child) {
Tins::Dot11QoSData::Dot11QoSData(uint32_t iface_index, const uint8_t* dst_hw_addr, const uint8_t* src_hw_addr, PDU* child) : Dot11Data(iface_index, dst_hw_addr, src_hw_addr, child) {
this->subtype(Dot11::QOS_DATA_DATA);
this->_qos_control = 0;
}
Tins::Dot11QoSData::Dot11QoSData(const uint8_t *buffer, uint32_t total_sz) : Dot11DataFrame(buffer, total_sz) {
uint32_t sz = Dot11DataFrame::header_size();
Tins::Dot11QoSData::Dot11QoSData(const uint8_t *buffer, uint32_t total_sz) : Dot11Data(buffer, total_sz) {
uint32_t sz = Dot11Data::header_size();
buffer += sz;
total_sz -= sz;
assert(total_sz >= sizeof(this->_qos_control));
@@ -1267,7 +1165,7 @@ Tins::Dot11QoSData::Dot11QoSData(const uint8_t *buffer, uint32_t total_sz) : Dot
inner_pdu(new Tins::SNAP(buffer, total_sz));
}
Tins::Dot11QoSData::Dot11QoSData(const Dot11QoSData &other) : Dot11DataFrame(other) {
Tins::Dot11QoSData::Dot11QoSData(const Dot11QoSData &other) : Dot11Data(other) {
copy_fields(&other);
}
@@ -1278,7 +1176,7 @@ Tins::Dot11QoSData &Tins::Dot11QoSData::operator= (const Dot11QoSData &other) {
}
void Tins::Dot11QoSData::copy_fields(const Dot11QoSData *other) {
Dot11DataFrame::copy_ext_header(other);
Dot11Data::copy_ext_header(other);
_qos_control = other->_qos_control;
}
@@ -1297,7 +1195,14 @@ uint32_t Tins::Dot11QoSData::write_fixed_parameters(uint8_t *buffer, uint32_t to
return sz;
}
Tins::PDU *Tins::Dot11QoSData::clone_pdu() const {
Dot11QoSData *new_pdu = new Dot11QoSData();
new_pdu->copy_80211_fields(this);
return new_pdu;
}
/* Dot11Control */
Tins::Dot11Control::Dot11Control(const uint8_t* dst_addr, PDU* child) : Dot11(dst_addr, child) {
type(CONTROL);
}
@@ -1375,6 +1280,12 @@ Tins::Dot11RTS::Dot11RTS(const uint8_t *buffer, uint32_t total_sz) : Dot11Contro
}
Tins::PDU *Tins::Dot11RTS::clone_pdu() const {
Dot11RTS *new_pdu = new Dot11RTS();
new_pdu->copy_80211_fields(this);
return new_pdu;
}
/* Dot11PSPoll */
Tins::Dot11PSPoll::Dot11PSPoll(const uint8_t* dst_addr , const uint8_t* target_addr, PDU* child) : Dot11ControlTA(dst_addr, target_addr, child) {
@@ -1393,6 +1304,12 @@ Tins::Dot11PSPoll::Dot11PSPoll(const uint8_t *buffer, uint32_t total_sz) : Dot11
}
Tins::PDU *Tins::Dot11PSPoll::clone_pdu() const {
Dot11PSPoll *new_pdu = new Dot11PSPoll();
new_pdu->copy_80211_fields(this);
return new_pdu;
}
/* Dot11CFEnd */
Tins::Dot11CFEnd::Dot11CFEnd(const uint8_t* dst_addr , const uint8_t* target_addr, PDU* child) : Dot11ControlTA(dst_addr, target_addr, child) {
@@ -1411,6 +1328,12 @@ Tins::Dot11CFEnd::Dot11CFEnd(const uint8_t *buffer, uint32_t total_sz) : Dot11Co
}
Tins::PDU *Tins::Dot11CFEnd::clone_pdu() const {
Dot11CFEnd *new_pdu = new Dot11CFEnd();
new_pdu->copy_80211_fields(this);
return new_pdu;
}
/* Dot11EndCFAck */
Tins::Dot11EndCFAck::Dot11EndCFAck(const uint8_t* dst_addr , const uint8_t* target_addr, PDU* child) : Dot11ControlTA(dst_addr, target_addr, child) {
@@ -1429,6 +1352,12 @@ Tins::Dot11EndCFAck::Dot11EndCFAck(const uint8_t *buffer, uint32_t total_sz) : D
}
Tins::PDU *Tins::Dot11EndCFAck::clone_pdu() const {
Dot11EndCFAck *new_pdu = new Dot11EndCFAck();
new_pdu->copy_80211_fields(this);
return new_pdu;
}
/* Dot11Ack */
Tins::Dot11Ack::Dot11Ack(const uint8_t* dst_addr, PDU* child) : Dot11Control(dst_addr, child) {
@@ -1447,6 +1376,12 @@ Tins::Dot11Ack::Dot11Ack(const uint8_t *buffer, uint32_t total_sz) : Dot11Contro
}
Tins::PDU *Tins::Dot11Ack::clone_pdu() const {
Dot11Ack *ack = new Dot11Ack();
ack->copy_80211_fields(this);
return ack;
}
/* Dot11BlockAck */
Tins::Dot11BlockAckRequest::Dot11BlockAckRequest(const uint8_t* dst_addr , const uint8_t* target_addr, PDU* child) : Dot11ControlTA(dst_addr, target_addr, child) {
@@ -1499,6 +1434,12 @@ uint32_t Tins::Dot11BlockAckRequest::header_size() const {
return Dot11ControlTA::header_size() + sizeof(_start_sequence) + sizeof(_start_sequence);
}
Tins::PDU *Tins::Dot11BlockAckRequest::clone_pdu() const {
Dot11BlockAckRequest *new_pdu = new Dot11BlockAckRequest();
new_pdu->copy_80211_fields(this);
return new_pdu;
}
/* Dot11BlockAck */
Tins::Dot11BlockAck::Dot11BlockAck(const uint8_t* dst_addr , const uint8_t* target_addr, PDU* child) : Dot11BlockAckRequest(dst_addr, target_addr, child) {
subtype(BLOCK_ACK);
@@ -1538,3 +1479,9 @@ uint32_t Tins::Dot11BlockAck::write_ext_header(uint8_t *buffer, uint32_t total_s
uint32_t Tins::Dot11BlockAck::header_size() const {
return Dot11BlockAckRequest::header_size() + sizeof(_bitmap);
}
Tins::PDU *Tins::Dot11BlockAck::clone_pdu() const {
Dot11BlockAck *new_pdu = new Dot11BlockAck();
new_pdu->copy_80211_fields(this);
return new_pdu;
}

View File

@@ -177,7 +177,8 @@ void Tins::ICMP::set_redirect(uint8_t icode, uint32_t address) {
void Tins::ICMP::write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *) {
assert(total_sz >= sizeof(icmphdr));
if(!_icmp.check) {
uint32_t checksum = PDU::do_checksum(buffer + sizeof(icmphdr), buffer + total_sz) + PDU::do_checksum((uint8_t*)&_icmp, ((uint8_t*)&_icmp) + sizeof(icmphdr));
uint32_t checksum = Utils::do_checksum(buffer + sizeof(icmphdr), buffer + total_sz) +
Utils::do_checksum((uint8_t*)&_icmp, ((uint8_t*)&_icmp) + sizeof(icmphdr));
while (checksum >> 16)
checksum = (checksum & 0xffff) + (checksum >> 16);
_icmp.check = Utils::net_to_host_s(~checksum);

View File

@@ -105,23 +105,22 @@ Tins::IP::IP(const uint8_t *buffer, uint32_t total_sz) : PDU(IPPROTO_IP) {
this->_ip_options.push_back(opt_to_add);
this->_options_size += 1 + opt_to_add.optional_data_size;
}
total_sz -= head_len() * sizeof(uint32_t);
if (total_sz == 0)
return;
switch(_ip.protocol) {
case IPPROTO_TCP:
inner_pdu(new Tins::TCP(buffer, total_sz));
break;
case IPPROTO_UDP:
inner_pdu(new Tins::UDP(buffer, total_sz));
break;
case IPPROTO_ICMP:
inner_pdu(new Tins::ICMP(buffer, total_sz));
break;
default:
inner_pdu(new Tins::RawPDU(buffer, total_sz));
break;
if (total_sz) {
switch(_ip.protocol) {
case IPPROTO_TCP:
inner_pdu(new Tins::TCP(buffer, total_sz));
break;
case IPPROTO_UDP:
inner_pdu(new Tins::UDP(buffer, total_sz));
break;
case IPPROTO_ICMP:
inner_pdu(new Tins::ICMP(buffer, total_sz));
break;
default:
inner_pdu(new Tins::RawPDU(buffer, total_sz));
break;
}
}
}
@@ -302,7 +301,7 @@ void Tins::IP::write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU
memset(buffer + sizeof(iphdr) + this->_options_size, 0, this->_padded_options_size - this->_options_size);
if (parent && !_ip.check) {
uint32_t checksum = PDU::do_checksum(buffer, buffer + sizeof(iphdr) + _padded_options_size);
uint32_t checksum = Utils::do_checksum(buffer, buffer + sizeof(iphdr) + _padded_options_size);
while (checksum >> 16)
checksum = (checksum & 0xffff) + (checksum >> 16);
((iphdr*)buffer)->check = Utils::net_to_host_s(~checksum);

View File

@@ -102,30 +102,3 @@ Tins::PDU *Tins::PDU::clone_packet() const {
}
return ret;
}
/* Static methods */
uint32_t Tins::PDU::do_checksum(uint8_t *start, uint8_t *end) {
uint32_t checksum(0);
uint16_t *ptr = (uint16_t*)start, *last = (uint16_t*)end, padding(0);
if(((end - start) & 1) == 1) {
last = (uint16_t*)end - 1;
padding = *(end - 1) << 8;
}
while(ptr < last)
checksum += Utils::net_to_host_s(*(ptr++));
return checksum + padding;
}
uint32_t Tins::PDU::pseudoheader_checksum(uint32_t source_ip, uint32_t dest_ip, uint32_t len, uint32_t flag) {
uint32_t checksum(0);
source_ip = Utils::net_to_host_l(source_ip);
dest_ip = Utils::net_to_host_l(dest_ip);
uint16_t *ptr = (uint16_t*)&source_ip;
checksum += (uint32_t)(*ptr) + (uint32_t)(*(ptr+1));
ptr = (uint16_t*)&dest_ip;
checksum += (uint32_t)(*ptr) + (uint32_t)(*(ptr+1));
checksum += flag + len;
return checksum;
}

View File

@@ -30,14 +30,16 @@
#include "utils.h"
Tins::RadioTap::RadioTap(const std::string &iface) throw (std::runtime_error) : PDU(0xff), _options_size(0) {
Tins::RadioTap::RadioTap(const std::string &iface, PDU *child) throw (std::runtime_error) : PDU(0xff, child), _options_size(0) {
if(!Utils::interface_id(iface, _iface_index))
throw std::runtime_error("Invalid interface name!");
std::memset(&_radio, 0, sizeof(_radio));
init();
}
Tins::RadioTap::RadioTap(uint32_t iface_index) : PDU(0xff), _iface_index(iface_index) {
Tins::RadioTap::RadioTap(uint32_t iface_index, PDU *child) : PDU(0xff, child), _iface_index(iface_index) {
std::memset(&_radio, 0, sizeof(_radio));
init();
}
Tins::RadioTap::RadioTap(const uint8_t *buffer, uint32_t total_sz) : PDU(0xff) {
@@ -111,6 +113,15 @@ Tins::RadioTap::RadioTap(const uint8_t *buffer, uint32_t total_sz) : PDU(0xff) {
inner_pdu(Dot11::from_bytes(buffer, total_sz));
}
void Tins::RadioTap::init() {
channel(Utils::channel_to_mhz(1), 0xa0);
flags(FCS);
tsft(0);
dbm_signal(0xce);
rx_flag(0);
antenna(0);
}
void Tins::RadioTap::version(uint8_t new_version) {
_radio.it_version = new_version;
}

View File

@@ -20,7 +20,6 @@
*/
#include <stdexcept>
#include "sniffer.h"
#include "ethernetII.h"
#include "radiotap.h"
@@ -41,7 +40,7 @@ struct LoopData {
/** \endcond */
Tins::Sniffer::Sniffer(const string &device, unsigned max_packet_size) {
Tins::Sniffer::Sniffer(const string &device, unsigned max_packet_size, const string &filter) throw(std::runtime_error) {
char error[PCAP_ERRBUF_SIZE];
if (pcap_lookupnet(device.c_str(), &ip, &mask, error) == -1) {
ip = 0;
@@ -52,6 +51,8 @@ Tins::Sniffer::Sniffer(const string &device, unsigned max_packet_size) {
throw runtime_error(error);
wired = (pcap_datalink (handle) != DLT_IEEE802_11_RADIO); //better plx
actual_filter.bf_insns = 0;
if(filter.size() && !set_filter(filter))
throw runtime_error("Invalid filter");
}
Tins::Sniffer::~Sniffer() {
@@ -65,9 +66,7 @@ bool Tins::Sniffer::compile_set_filter(const string &filter, bpf_program &prog)
return (pcap_compile(handle, &prog, filter.c_str(), 0, ip) != -1 && pcap_setfilter(handle, &prog) != -1);
}
Tins::PDU *Tins::Sniffer::next_packet(const string &filter) {
if(filter.size())
set_filter(filter);
Tins::PDU *Tins::Sniffer::next_packet() {
pcap_pkthdr header;
PDU *ret = 0;
while(!ret) {
@@ -91,9 +90,7 @@ void Tins::Sniffer::stop_sniff() {
pcap_breakloop(handle);
}
void Tins::Sniffer::sniff_loop(AbstractSnifferHandler *cback_handler, const string &filter, uint32_t max_packets) {
if(filter.size())
set_filter(filter);
void Tins::Sniffer::sniff_loop(AbstractSnifferHandler *cback_handler, uint32_t max_packets) {
LoopData data(handle, cback_handler, wired);
pcap_loop(handle, max_packets, Sniffer::callback_handler, (u_char*)&data);
}

View File

@@ -56,48 +56,58 @@ Tins::TCP::TCP(const uint8_t *buffer, uint32_t total_sz) : PDU(IPPROTO_TCP) {
if(total_sz < sizeof(tcphdr))
throw std::runtime_error("Not enough size for an TCP header in the buffer.");
std::memcpy(&_tcp, buffer, sizeof(tcphdr));
buffer += sizeof(tcphdr);
total_sz -= sizeof(tcphdr);
uint32_t index = 0, header_end = (data_offset() * sizeof(uint32_t)) - sizeof(tcphdr);
if(total_sz >= header_end) {
uint8_t args[2] = {0};
while(index < header_end) {
for(unsigned i(0); i < 2 && args[0] != NOP; ++i) {
args[i] = buffer[index++];
if(index == header_end)
throw std::runtime_error("Not enought size for a TCP header in the buffer.");
}
// We don't want to store NOPs and EOLs
if(args[0] != NOP && args[0] != EOL) {
if(args[1]) {
// Not enough size for this option
if(header_end - index < args[1] - (sizeof(uint8_t) << 1)) {
try {
buffer += sizeof(tcphdr);
total_sz -= sizeof(tcphdr);
_total_options_size = 0;
_options_size = 0;
uint32_t index = 0, header_end = (data_offset() * sizeof(uint32_t)) - sizeof(tcphdr);
if(total_sz >= header_end) {
uint8_t args[2] = {0};
while(index < header_end) {
for(unsigned i(0); i < 2 && args[0] != NOP; ++i) {
args[i] = buffer[index++];
if(index == header_end)
throw std::runtime_error("Not enought size for a TCP header in the buffer.");
}
args[1] -= (sizeof(uint8_t) << 1);
add_option((Options)args[0], args[1], buffer + index);
}
index += args[1];
// We don't want to store NOPs and EOLs
if(args[0] != NOP && args[0] != EOL) {
args[1] -= (sizeof(uint8_t) << 1);
if(args[1]) {
// Not enough size for this option
if(header_end - index < args[1])
throw std::runtime_error("Not enought size for a TCP header in the buffer.");
add_option((Options)args[0], args[1], buffer + index);
}
index += args[1];
}
else if(args[0] == EOL)
index = header_end;
else // Skip the NOP
args[0] = 0;
}
else if(args[0] == EOL)
index = header_end;
else // Skip the NOP
args[0] = 0;
buffer += index;
total_sz -= index;
}
buffer += index;
total_sz -= index;
_total_options_size = header_end;
_options_size = (_total_options_size / 4) * 4;
}
catch(std::runtime_error &err) {
cleanup();
throw;
}
if(total_sz)
inner_pdu(new RawPDU(buffer, total_sz));
}
Tins::TCP::~TCP() {
cleanup();
}
void Tins::TCP::cleanup() {
for(std::list<TCPOption>::iterator it = _options.begin(); it != _options.end(); ++it)
delete[] it->data;
_options.clear();
}
void Tins::TCP::dport(uint16_t new_dport) {
@@ -208,8 +218,11 @@ void Tins::TCP::set_flag(Flags tcp_flag, uint8_t value) {
}
void Tins::TCP::add_option(Options tcp_option, uint8_t length, const uint8_t *data) {
uint8_t *new_data = new uint8_t[length], padding;
memcpy(new_data, data, length);
uint8_t *new_data = 0, padding;
if(length) {
new_data = new uint8_t[length];
memcpy(new_data, data, length);
}
_options.push_back(TCPOption(tcp_option, length, new_data));
_options_size += length + (sizeof(uint8_t) << 1);
padding = _options_size & 3;
@@ -239,8 +252,8 @@ void Tins::TCP::write_serialization(uint8_t *buffer, uint32_t total_sz, const PD
const Tins::IP *ip_packet = dynamic_cast<const Tins::IP*>(parent);
memcpy(tcp_start, &_tcp, sizeof(tcphdr));
if(!_tcp.check && ip_packet) {
uint32_t checksum = PDU::pseudoheader_checksum(ip_packet->src_addr(), ip_packet->dst_addr(), size(), IPPROTO_TCP) +
PDU::do_checksum(tcp_start, tcp_start + total_sz);
uint32_t checksum = Utils::pseudoheader_checksum(ip_packet->src_addr(), ip_packet->dst_addr(), size(), IPPROTO_TCP) +
Utils::do_checksum(tcp_start, tcp_start + total_sz);
while (checksum >> 16)
checksum = (checksum & 0xffff) + (checksum >> 16);
((tcphdr*)tcp_start)->check = Utils::net_to_host_s(~checksum);
@@ -259,8 +272,9 @@ uint8_t *Tins::TCP::TCPOption::write(uint8_t *buffer) {
else {
buffer[0] = kind;
buffer[1] = length + (sizeof(uint8_t) << 1);
memcpy(buffer + 2, data, length);
return buffer + length + (sizeof(uint8_t) << 1);
if(data)
memcpy(buffer + 2, data, length);
return buffer + buffer[1];
}
}

View File

@@ -83,8 +83,8 @@ void Tins::UDP::write_serialization(uint8_t *buffer, uint32_t total_sz, const PD
length(sizeof(udphdr) + inner_pdu()->size());
std::memcpy(buffer, &_udp, sizeof(udphdr));
if(!_udp.check && ip_packet) {
uint32_t checksum = PDU::pseudoheader_checksum(ip_packet->src_addr(), ip_packet->dst_addr(), size(), IPPROTO_UDP) +
PDU::do_checksum(buffer, buffer + total_sz);
uint32_t checksum = Utils::pseudoheader_checksum(ip_packet->src_addr(), ip_packet->dst_addr(), size(), IPPROTO_UDP) +
Utils::do_checksum(buffer, buffer + total_sz);
while (checksum >> 16)
checksum = (checksum & 0xffff)+(checksum >> 16);
((udphdr*)buffer)->check = Utils::net_to_host_s(~checksum);

View File

@@ -252,6 +252,31 @@ uint16_t Tins::Utils::channel_to_mhz(uint16_t channel) {
return 2407 + (channel * 5);
}
uint32_t Tins::Utils::do_checksum(uint8_t *start, uint8_t *end) {
uint32_t checksum(0);
uint16_t *ptr = (uint16_t*)start, *last = (uint16_t*)end, padding(0);
if(((end - start) & 1) == 1) {
last = (uint16_t*)end - 1;
padding = *(end - 1) << 8;
}
while(ptr < last)
checksum += Utils::net_to_host_s(*(ptr++));
return checksum + padding;
}
uint32_t Tins::Utils::pseudoheader_checksum(uint32_t source_ip, uint32_t dest_ip, uint32_t len, uint32_t flag) {
uint32_t checksum(0);
source_ip = Utils::net_to_host_l(source_ip);
dest_ip = Utils::net_to_host_l(dest_ip);
uint16_t *ptr = (uint16_t*)&source_ip;
checksum += (uint32_t)(*ptr) + (uint32_t)(*(ptr+1));
ptr = (uint16_t*)&dest_ip;
checksum += (uint32_t)(*ptr) + (uint32_t)(*(ptr+1));
checksum += flag + len;
return checksum;
}
uint32_t Tins::Utils::crc32(uint8_t* data, uint32_t data_size) {
uint32_t i, crc = 0;
static uint32_t crc_table[] = {