mirror of
https://github.com/mfontanini/libtins
synced 2026-01-23 02:35:57 +01:00
Moved headers to include/tins.
This commit is contained in:
7
include/tins/CMakeLists.txt
Normal file
7
include/tins/CMakeLists.txt
Normal file
@@ -0,0 +1,7 @@
|
||||
FILE(GLOB INCLUDE_FILES "*.h")
|
||||
INSTALL(
|
||||
FILES ${INCLUDE_FILES}
|
||||
DESTINATION include/tins
|
||||
COMPONENT Headers
|
||||
)
|
||||
ADD_SUBDIRECTORY(dot11)
|
||||
331
include/tins/address_range.h
Normal file
331
include/tins/address_range.h
Normal file
@@ -0,0 +1,331 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Matias Fontanini
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following disclaimer
|
||||
* in the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef TINS_ADDRESS_RANGE
|
||||
#define TINS_ADDRESS_RANGE
|
||||
|
||||
#include <stdexcept>
|
||||
#include <iterator>
|
||||
#include "endianness.h"
|
||||
#include "internals.h"
|
||||
|
||||
namespace Tins {
|
||||
/**
|
||||
* \brief AddressRange iterator class.
|
||||
*/
|
||||
template<typename Address>
|
||||
class AddressRangeIterator : public std::iterator<std::forward_iterator_tag, const Address> {
|
||||
public:
|
||||
typedef typename std::iterator<std::forward_iterator_tag, const Address>::value_type value_type;
|
||||
|
||||
struct end_iterator {
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Constructs an iterator.
|
||||
*
|
||||
* \param first The address held by this iterator.
|
||||
*/
|
||||
AddressRangeIterator(const value_type &addr)
|
||||
: addr(addr), reached_end(false)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs an iterator.
|
||||
*
|
||||
* \param first The address held by this iterator.
|
||||
*/
|
||||
AddressRangeIterator(const value_type &address, end_iterator)
|
||||
: addr(address)
|
||||
{
|
||||
reached_end = Internals::increment(addr);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the current address pointed by this iterator.
|
||||
*/
|
||||
const value_type& operator*() const {
|
||||
return addr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves a pointer to the current address pointed by this iterator.
|
||||
*/
|
||||
const value_type* operator->() const {
|
||||
return &addr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compares two iterators for equality.
|
||||
*
|
||||
* \param rhs The iterator with which to compare.
|
||||
*/
|
||||
bool operator==(const AddressRangeIterator &rhs) const {
|
||||
return reached_end == rhs.reached_end && addr == rhs.addr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compares two iterators for inequality.
|
||||
*
|
||||
* \param rhs The iterator with which to compare.
|
||||
*/
|
||||
bool operator!=(const AddressRangeIterator &rhs) const {
|
||||
return !(*this == rhs);
|
||||
}
|
||||
|
||||
/**
|
||||
* Increments this iterator.
|
||||
*/
|
||||
AddressRangeIterator& operator++() {
|
||||
reached_end = Internals::increment(addr);
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Increments this iterator.
|
||||
*/
|
||||
AddressRangeIterator operator++(int) {
|
||||
AddressRangeIterator copy(*this);
|
||||
(*this)++;
|
||||
return copy;
|
||||
}
|
||||
private:
|
||||
Address addr;
|
||||
bool reached_end;
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Represents a range of addresses.
|
||||
*
|
||||
* This class provides a begin()/end() interface which allows
|
||||
* iterating through every address stored in it.
|
||||
*
|
||||
* Note that when iterating a range that was created using
|
||||
* operator/(IPv4Address, int) and the analog for IPv6, the
|
||||
* network and broadcast addresses are discarded:
|
||||
*
|
||||
* \code
|
||||
* auto range = IPv4Address("192.168.5.0") / 24;
|
||||
* for(const auto &addr : range) {
|
||||
* // process 192.168.5.1-254, .0 and .255 are discarded
|
||||
* process(addr);
|
||||
* }
|
||||
*
|
||||
* // That's only valid for iteration, not for AddressRange<>::contains
|
||||
*
|
||||
* assert(range.contains("192.168.5.0")); // works
|
||||
* assert(range.contains("192.168.5.255")); // works
|
||||
* \endcode
|
||||
*
|
||||
* Ranges created using AddressRange(address_type, address_type)
|
||||
* will allow the iteration over the entire range:
|
||||
*
|
||||
* \code
|
||||
* AddressRange<IPv4Address> range("192.168.5.0", "192.168.5.255");
|
||||
* for(const auto &addr : range) {
|
||||
* // process 192.168.5.0-255, no addresses are discarded
|
||||
* process(addr);
|
||||
* }
|
||||
*
|
||||
* assert(range.contains("192.168.5.0")); // still valid
|
||||
* assert(range.contains("192.168.5.255")); // still valid
|
||||
* \endcode
|
||||
*
|
||||
*/
|
||||
template<typename Address>
|
||||
class AddressRange {
|
||||
public:
|
||||
/**
|
||||
* The type of addresses stored in the range.
|
||||
*/
|
||||
typedef Address address_type;
|
||||
|
||||
/**
|
||||
* The iterator type.
|
||||
*/
|
||||
typedef AddressRangeIterator<address_type> const_iterator;
|
||||
|
||||
/**
|
||||
* \brief The iterator type.
|
||||
*
|
||||
* This is the same type as const_iterator, since the
|
||||
* addresses stored in this range are read only.
|
||||
*/
|
||||
typedef const_iterator iterator;
|
||||
|
||||
/**
|
||||
* \brief Constructs an address range from two addresses.
|
||||
*
|
||||
* The range will consist of the addresses [first, last].
|
||||
*
|
||||
* If only_hosts is true, then the network and broadcast addresses
|
||||
* will not be available when iterating the range.
|
||||
*
|
||||
* If last < first, an std::runtime_error exception is thrown.
|
||||
*
|
||||
* \param first The first address in the range.
|
||||
* \param last The last address(inclusive) in the range.
|
||||
* \param only_hosts Indicates whether only host addresses
|
||||
* should be accessed when using iterators.
|
||||
*/
|
||||
AddressRange(const address_type &first, const address_type &last, bool only_hosts = false)
|
||||
: first(first), last(last), only_hosts(only_hosts)
|
||||
{
|
||||
if(last < first)
|
||||
throw std::runtime_error("Invalid address range");
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Creates an address range from a base address
|
||||
* and a network mask.
|
||||
*
|
||||
* \param first The base address.
|
||||
* \param mask The network mask to be used.
|
||||
*/
|
||||
static AddressRange from_mask(const address_type &first, const address_type &mask) {
|
||||
return AddressRange<address_type>(
|
||||
first,
|
||||
Internals::last_address_from_mask(first, mask),
|
||||
true
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Indicates whether an address is included in this range.
|
||||
* \param addr The address to test.
|
||||
* \return a bool indicating whether the address is in the range.
|
||||
*/
|
||||
bool contains(const address_type &addr) const {
|
||||
return (first < addr && addr < last) || addr == first || addr == last;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Returns an interator to the beginning of this range.
|
||||
* \brief const_iterator pointing to the beginning of this range.
|
||||
*/
|
||||
const_iterator begin() const {
|
||||
address_type addr = first;
|
||||
if(only_hosts)
|
||||
Internals::increment(addr);
|
||||
return const_iterator(addr);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Returns an interator to the end of this range.
|
||||
* \brief const_iterator pointing to the end of this range.
|
||||
*/
|
||||
const_iterator end() const {
|
||||
address_type addr = last;
|
||||
if(only_hosts)
|
||||
Internals::decrement(addr);
|
||||
return const_iterator(addr, typename const_iterator::end_iterator());
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Indicates whether this range is iterable.
|
||||
*
|
||||
* Iterable ranges are those for which there is at least one
|
||||
* address that could represent a host. For IPv4 ranges, a /31 or
|
||||
* /32 ranges does not contain any, therefore it's not iterable.
|
||||
* The same is true for /127 and /128 IPv6 ranges.
|
||||
*
|
||||
* If is_iterable returns false for a range, then iterating it
|
||||
* through the iterators returned by begin() and end() is
|
||||
* undefined.
|
||||
*
|
||||
* \return bool indicating whether this range is iterable.
|
||||
*/
|
||||
bool is_iterable() const {
|
||||
// Since first < last, it's iterable
|
||||
if(!only_hosts)
|
||||
return true;
|
||||
// We need that distance(first, last) >= 4
|
||||
address_type addr(first);
|
||||
for(int i = 0; i < 3; ++i) {
|
||||
// If there's overflow before the last iteration, we're done
|
||||
if(Internals::increment(addr) && i != 2)
|
||||
return false;
|
||||
}
|
||||
// If addr <= last, it's OK.
|
||||
return addr < last || addr == last;
|
||||
}
|
||||
private:
|
||||
address_type first, last;
|
||||
bool only_hosts;
|
||||
};
|
||||
|
||||
/**
|
||||
* An IPv4 address range.
|
||||
*/
|
||||
typedef AddressRange<IPv4Address> IPv4Range;
|
||||
|
||||
/**
|
||||
* An IPv6 address range.
|
||||
*/
|
||||
typedef AddressRange<IPv6Address> IPv6Range;
|
||||
|
||||
/**
|
||||
* \brief Constructs an AddressRange from a base address and a mask.
|
||||
* \param addr The range's first address.
|
||||
* \param mask The bit-length of the prefix.
|
||||
*/
|
||||
template<size_t n>
|
||||
AddressRange<HWAddress<n> > operator/(const HWAddress<n> &addr, int mask) {
|
||||
if(mask > 48)
|
||||
throw std::logic_error("Prefix length cannot exceed 48");
|
||||
HWAddress<n> last_addr;
|
||||
typename HWAddress<n>::iterator it = last_addr.begin();
|
||||
while(mask > 8) {
|
||||
*it = 0xff;
|
||||
++it;
|
||||
mask -= 8;
|
||||
}
|
||||
*it = 0xff << (8 - mask);
|
||||
return AddressRange<HWAddress<6> >::from_mask(addr, last_addr);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Constructs an IPv6Range from a base IPv6Address and a mask.
|
||||
* \param addr The range's first address.
|
||||
* \param mask The bit-length of the prefix.
|
||||
*/
|
||||
IPv6Range operator/(const IPv6Address &addr, int mask);
|
||||
|
||||
/**
|
||||
* \brief Constructs an IPv4Range from a base IPv4Address and a mask.
|
||||
* \param addr The range's first address.
|
||||
* \param mask The bit-length of the prefix.
|
||||
*/
|
||||
IPv4Range operator/(const IPv4Address &addr, int mask);
|
||||
} // namespace Tins
|
||||
|
||||
#endif // TINS_ADDRESS_RANGE
|
||||
317
include/tins/arp.h
Normal file
317
include/tins/arp.h
Normal file
@@ -0,0 +1,317 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Matias Fontanini
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following disclaimer
|
||||
* in the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#ifndef TINS_ARP_H
|
||||
#define TINS_ARP_H
|
||||
|
||||
#include "macros.h"
|
||||
#include "pdu.h"
|
||||
#include "endianness.h"
|
||||
#include "hw_address.h"
|
||||
#include "ip_address.h"
|
||||
|
||||
namespace Tins {
|
||||
class NetworkInterface;
|
||||
class EthernetII;
|
||||
|
||||
/**
|
||||
* \class ARP
|
||||
* \brief Represents an ARP PDU.
|
||||
*
|
||||
*/
|
||||
class ARP : public PDU {
|
||||
public:
|
||||
/**
|
||||
* The type of the hardware address.
|
||||
*/
|
||||
typedef HWAddress<6> hwaddress_type;
|
||||
|
||||
/**
|
||||
* The type of the IP address.
|
||||
*/
|
||||
typedef IPv4Address ipaddress_type;
|
||||
|
||||
/**
|
||||
* \brief This PDU's flag.
|
||||
*/
|
||||
static const PDU::PDUType pdu_flag = PDU::ARP;
|
||||
|
||||
/**
|
||||
* \brief Enum which indicates the type of ARP packet.
|
||||
*/
|
||||
enum Flags {
|
||||
REQUEST = 0x0001,
|
||||
REPLY = 0x0002
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Constructs an ARP object using the provided addresses.
|
||||
*
|
||||
* ARP requests and replies can be constructed easily using
|
||||
* ARP::make_arp_request/reply static member functions.
|
||||
*
|
||||
* \sa ARP::make_arp_request
|
||||
* \sa ARP::make_arp_reply
|
||||
*
|
||||
* \param target_ip The target IP address.
|
||||
* \param sender_ip The sender IP address.
|
||||
* \param target_hw The target hardware address.
|
||||
* \param sender_hw The sender hardware address.
|
||||
*/
|
||||
ARP(ipaddress_type target_ip = ipaddress_type(),
|
||||
ipaddress_type sender_ip = ipaddress_type(),
|
||||
const hwaddress_type &target_hw = hwaddress_type(),
|
||||
const hwaddress_type &sender_hw = hwaddress_type());
|
||||
|
||||
/**
|
||||
* \brief Constructs an ARP object from a buffer.
|
||||
*
|
||||
* If there is not enough size for an ARP header in the buffer,
|
||||
* a malformed_packet exception is thrown.
|
||||
*
|
||||
* If the buffer is bigger than the size of the ARP header,
|
||||
* then the extra data is stored in a RawPDU.
|
||||
*
|
||||
* \param buffer The buffer from which this PDU will be constructed.
|
||||
* \param total_sz The total size of the buffer.
|
||||
*/
|
||||
ARP(const uint8_t *buffer, uint32_t total_sz);
|
||||
|
||||
/* Getters */
|
||||
/**
|
||||
* \brief Getter for the sender's hardware address.
|
||||
*
|
||||
* \return The sender hardware address.
|
||||
*/
|
||||
hwaddress_type sender_hw_addr() const { return _arp.ar_sha; }
|
||||
|
||||
/**
|
||||
* \brief Getter for the sender's IP address.
|
||||
*
|
||||
* \return The sender IP address.
|
||||
*/
|
||||
ipaddress_type sender_ip_addr() const { return ipaddress_type(_arp.ar_sip); }
|
||||
|
||||
/**
|
||||
* \brief Getter for the target's hardware address.
|
||||
*
|
||||
* \return The target hardware address.
|
||||
*/
|
||||
hwaddress_type target_hw_addr() const { return _arp.ar_tha; }
|
||||
|
||||
/**
|
||||
* \brief Getter for the target's IP address.
|
||||
*
|
||||
* \return The target IP address.
|
||||
*/
|
||||
ipaddress_type target_ip_addr() const { return ipaddress_type(_arp.ar_tip); }
|
||||
|
||||
/**
|
||||
* \brief Getter for the hardware address format field.
|
||||
*
|
||||
* \return The hardware address format.
|
||||
*/
|
||||
uint16_t hw_addr_format() const { return Endian::be_to_host(_arp.ar_hrd); }
|
||||
|
||||
/**
|
||||
* \brief Getter for the protocol address format field.
|
||||
*
|
||||
* \return The protocol address format.
|
||||
*/
|
||||
uint16_t prot_addr_format() const { return Endian::be_to_host(_arp.ar_pro); }
|
||||
|
||||
/**
|
||||
* \brief Getter for the hardware address length field.
|
||||
*
|
||||
* \return The hardware address length.
|
||||
*/
|
||||
uint8_t hw_addr_length() const { return _arp.ar_hln; }
|
||||
|
||||
/**
|
||||
* \brief Getter for the protocol address length field.
|
||||
*
|
||||
* \return The protocol address length.
|
||||
*/
|
||||
uint8_t prot_addr_length() const { return _arp.ar_pln; }
|
||||
|
||||
/**
|
||||
* \brief Getter for the ARP opcode field.
|
||||
*
|
||||
* \return The ARP opcode.
|
||||
*/
|
||||
uint16_t opcode() const { return Endian::be_to_host(_arp.ar_op); }
|
||||
|
||||
/**
|
||||
* \brief Getter for the header size.
|
||||
* \return Returns the ARP header size.
|
||||
* \sa PDU::header_size
|
||||
*/
|
||||
uint32_t header_size() const;
|
||||
/* Setters */
|
||||
|
||||
/**
|
||||
* \brief Setter for the sender's hardware address.
|
||||
*
|
||||
* \param new_snd_hw_addr The new sender hardware address.
|
||||
*/
|
||||
void sender_hw_addr(const hwaddress_type &new_snd_hw_addr);
|
||||
|
||||
/**
|
||||
* \brief Setter for the sender's IP address.
|
||||
*
|
||||
* \param new_snd_ip_addr The new sender IP address.
|
||||
*/
|
||||
void sender_ip_addr(ipaddress_type new_snd_ip_addr);
|
||||
|
||||
/**
|
||||
* \brief Setter for the target's hardware address.
|
||||
*
|
||||
* \param new_tgt_hw_addr The new target hardware address.
|
||||
*/
|
||||
void target_hw_addr(const hwaddress_type &new_tgt_hw_addr);
|
||||
|
||||
/**
|
||||
* \brief Setter for the target's IP address.
|
||||
*
|
||||
* \param new_tgt_ip_addr The new target IP address.
|
||||
*/
|
||||
void target_ip_addr(ipaddress_type new_tgt_ip_addr);
|
||||
|
||||
/**
|
||||
* \brief Setter for the hardware address format field.
|
||||
*
|
||||
* \param new_hw_addr_fmt The new hardware address format.
|
||||
*/
|
||||
void hw_addr_format(uint16_t new_hw_addr_fmt);
|
||||
|
||||
/**
|
||||
* \brief Setter for the protocol address format field.
|
||||
*
|
||||
* \param new_prot_addr_fmt The new protocol address format.
|
||||
*/
|
||||
void prot_addr_format(uint16_t new_prot_addr_fmt);
|
||||
|
||||
/**
|
||||
* \brief Setter for the hardware address length field.
|
||||
*
|
||||
* \param new_hw_addr_len The new hardware address length.
|
||||
*/
|
||||
void hw_addr_length(uint8_t new_hw_addr_len);
|
||||
|
||||
/**
|
||||
* \brief Setter for the protocol address length field.
|
||||
*
|
||||
* \param new_prot_addr_len The new protocol address length.
|
||||
*/
|
||||
void prot_addr_length(uint8_t new_prot_addr_len);
|
||||
|
||||
/**
|
||||
* \brief Setter for the ARP opcode field.
|
||||
*
|
||||
* \param new_opcode Flag enum value of the ARP opcode to set.
|
||||
*/
|
||||
void opcode(Flags new_opcode);
|
||||
|
||||
/**
|
||||
* \brief Getter for the PDU's type.
|
||||
* \sa PDU::pdu_type
|
||||
*/
|
||||
PDUType pdu_type() const { return pdu_flag; }
|
||||
|
||||
/**
|
||||
* \brief Creates an ARP Request within an EthernetII PDU.
|
||||
*
|
||||
* Creates an ARP Request PDU and embeds it inside an EthernetII
|
||||
* PDU.
|
||||
*
|
||||
* \param target The target's IP address.
|
||||
* \param sender The sender's IP address.
|
||||
* \param hw_snd The sender's hardware address.
|
||||
* \return EthernetII object containing the ARP Request.
|
||||
*/
|
||||
static EthernetII make_arp_request(ipaddress_type target,
|
||||
ipaddress_type sender, const hwaddress_type &hw_snd = hwaddress_type());
|
||||
|
||||
/**
|
||||
* \brief Creates an ARP Reply within an EthernetII PDU.
|
||||
*
|
||||
* Creates an ARP Reply PDU and embeds it inside an EthernetII
|
||||
* PDU.
|
||||
*
|
||||
* \param target The target's IP address.
|
||||
* \param sender The sender's IP address.
|
||||
* \param hw_tgt The target's hardware address.
|
||||
* \param hw_snd The sender's hardware address.
|
||||
* \return EthetnetII containing the ARP Replay.
|
||||
*/
|
||||
static EthernetII make_arp_reply(ipaddress_type target,
|
||||
ipaddress_type sender, const hwaddress_type &hw_tgt = hwaddress_type(),
|
||||
const hwaddress_type &hw_snd = hwaddress_type());
|
||||
|
||||
/**
|
||||
* \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;
|
||||
|
||||
/**
|
||||
* \sa PDU::clone
|
||||
*/
|
||||
ARP *clone() const {
|
||||
return new ARP(*this);
|
||||
}
|
||||
private:
|
||||
TINS_BEGIN_PACK
|
||||
struct arphdr {
|
||||
uint16_t ar_hrd; /* format of hardware address */
|
||||
uint16_t ar_pro; /* format of protocol address */
|
||||
uint8_t ar_hln; /* length of hardware address */
|
||||
uint8_t ar_pln; /* length of protocol address */
|
||||
uint16_t ar_op; /* ARP opcode (command) */
|
||||
|
||||
/* sender hardware address */
|
||||
uint8_t ar_sha[hwaddress_type::address_size];
|
||||
/* sender IP address */
|
||||
uint32_t ar_sip;
|
||||
/* target hardware address */
|
||||
uint8_t ar_tha[hwaddress_type::address_size];
|
||||
/* target IP address */
|
||||
uint32_t ar_tip;
|
||||
} TINS_END_PACK;
|
||||
|
||||
void write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *parent);
|
||||
|
||||
arphdr _arp;
|
||||
};
|
||||
}
|
||||
#endif //TINS_ARP_H
|
||||
363
include/tins/bootp.h
Normal file
363
include/tins/bootp.h
Normal file
@@ -0,0 +1,363 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Matias Fontanini
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following disclaimer
|
||||
* in the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef TINS_BOOTP_H
|
||||
#define TINS_BOOTP_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <algorithm>
|
||||
#include <vector>
|
||||
#include "pdu.h"
|
||||
#include "macros.h"
|
||||
#include "endianness.h"
|
||||
#include "ip_address.h"
|
||||
#include "hw_address.h"
|
||||
|
||||
|
||||
namespace Tins {
|
||||
|
||||
/**
|
||||
* \class BootP
|
||||
* \brief Class representing a BootP packet.
|
||||
*/
|
||||
class BootP : public PDU {
|
||||
public:
|
||||
/**
|
||||
* The type of the IP addresses.
|
||||
*/
|
||||
typedef IPv4Address ipaddress_type;
|
||||
|
||||
/**
|
||||
* The type of the chaddr field.
|
||||
*/
|
||||
typedef HWAddress<16> chaddr_type;
|
||||
|
||||
/**
|
||||
* The type of the vend field.
|
||||
*/
|
||||
typedef std::vector<uint8_t> vend_type;
|
||||
|
||||
/**
|
||||
* \brief This PDU's flag.
|
||||
*/
|
||||
static const PDU::PDUType pdu_flag = PDU::BOOTP;
|
||||
|
||||
/**
|
||||
* \brief Enum which contains the different opcodes BootP messages.
|
||||
*/
|
||||
enum OpCodes {
|
||||
BOOTREQUEST = 1,
|
||||
BOOTREPLY = 2
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Creates an instance of BootP.
|
||||
*
|
||||
* This sets the size of the vend field to 64, as the BootP RFC
|
||||
* states.
|
||||
*/
|
||||
BootP();
|
||||
|
||||
/**
|
||||
* \brief Constructs a BootP object from a buffer .
|
||||
*
|
||||
* If there's not enough size for a BootP header, then 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.
|
||||
* \param vend_field_size The vend field size to allocate.
|
||||
* Subclasses might use 0 to provide their own interpretation of this field.
|
||||
*/
|
||||
BootP(const uint8_t *buffer, uint32_t total_sz, uint32_t vend_field_size = 64);
|
||||
|
||||
/* Getters */
|
||||
|
||||
/**
|
||||
* \brief Getter for the opcode field.
|
||||
* \return The opcode field for this BootP PDU.
|
||||
*/
|
||||
uint8_t opcode() const { return _bootp.opcode; }
|
||||
|
||||
/**
|
||||
* \brief Getter for the htype field.
|
||||
* \return The htype field for this BootP PDU.
|
||||
*/
|
||||
uint8_t htype() const { return _bootp.htype; }
|
||||
|
||||
/**
|
||||
* \brief Getter for the hlen field.
|
||||
* \return The hlen field for this BootP PDU.
|
||||
*/
|
||||
uint8_t hlen() const { return _bootp.hlen; }
|
||||
|
||||
/**
|
||||
* \brief Getter for the hops field.
|
||||
* \return The hops field for this BootP PDU.
|
||||
*/
|
||||
uint8_t hops() const { return _bootp.hops; }
|
||||
|
||||
/**
|
||||
* \brief Getter for the xid field.
|
||||
* \return The xid field for this BootP PDU.
|
||||
*/
|
||||
uint32_t xid() const { return Endian::be_to_host(_bootp.xid); }
|
||||
|
||||
/**
|
||||
* \brief Getter for the secs field.
|
||||
* \return The secs field for this BootP PDU.
|
||||
*/
|
||||
uint16_t secs() const { return Endian::be_to_host(_bootp.secs); }
|
||||
|
||||
/** \brief Getter for the padding field.
|
||||
* \return The padding field for this BootP PDU.
|
||||
*/
|
||||
uint16_t padding() const { return Endian::be_to_host(_bootp.padding); }
|
||||
|
||||
/**
|
||||
* \brief Getter for the ciaddr field.
|
||||
* \return The ciaddr field for this BootP PDU.
|
||||
*/
|
||||
ipaddress_type ciaddr() const { return ipaddress_type(_bootp.ciaddr); }
|
||||
|
||||
/**
|
||||
* \brief Getter for the yiaddr field.
|
||||
* \return The yiaddr field for this BootP PDU.
|
||||
*/
|
||||
ipaddress_type yiaddr() const { return ipaddress_type(_bootp.yiaddr); }
|
||||
|
||||
/**
|
||||
* \brief Getter for the siaddr field.
|
||||
* \return The siaddr field for this BootP PDU.
|
||||
*/
|
||||
ipaddress_type siaddr() const { return ipaddress_type(_bootp.siaddr); }
|
||||
|
||||
/**
|
||||
* \brief Getter for the giaddr field.
|
||||
* \return The giaddr field for this BootP PDU.
|
||||
*/
|
||||
ipaddress_type giaddr() const { return ipaddress_type(_bootp.giaddr); }
|
||||
|
||||
/**
|
||||
* \brief Getter for the chaddr field.
|
||||
* \return The chddr field for this BootP PDU.
|
||||
*/
|
||||
chaddr_type chaddr() const { return _bootp.chaddr; }
|
||||
|
||||
/**
|
||||
* \brief Getter for the sname field.
|
||||
* \return The sname field for this BootP PDU.
|
||||
*/
|
||||
const uint8_t *sname() const { return _bootp.sname; }
|
||||
|
||||
/**
|
||||
* \brief Getter for the file field.
|
||||
* \return The file field for this BootP PDU.
|
||||
*/
|
||||
const uint8_t *file() const { return _bootp.file; }
|
||||
|
||||
/**
|
||||
* \brief Getter for the vend field.
|
||||
* \return The vend field for this BootP PDU.
|
||||
*/
|
||||
const vend_type &vend() const { return _vend; }
|
||||
|
||||
/**
|
||||
* \brief Getter for the header size.
|
||||
* \return Returns the BOOTP header size.
|
||||
* \sa PDU::header_size
|
||||
*/
|
||||
uint32_t header_size() const;
|
||||
/* Setters */
|
||||
|
||||
/**
|
||||
* \brief Setter for the opcode field.
|
||||
* \param new_opcode The opcode to be set.
|
||||
*/
|
||||
void opcode(uint8_t new_opcode);
|
||||
|
||||
/**
|
||||
* \brief Setter for the htype field.
|
||||
* \param new_htype The htype to be set.
|
||||
*/
|
||||
void htype(uint8_t new_htype);
|
||||
|
||||
/**
|
||||
* \brief Setter for the hlen field.
|
||||
* \param new_hlen The hlen to be set.
|
||||
*/
|
||||
void hlen(uint8_t new_hlen);
|
||||
|
||||
/**
|
||||
* \brief Setter for the hops field.
|
||||
* \param new_hops The hops to be set.
|
||||
*/
|
||||
void hops(uint8_t new_hops);
|
||||
|
||||
/**
|
||||
* \brief Setter for the xid field.
|
||||
* \param new_xid The xid to be set.
|
||||
*/
|
||||
void xid(uint32_t new_xid);
|
||||
|
||||
/**
|
||||
* \brief Setter for the secs field.
|
||||
* \param new_secs The secs to be set.
|
||||
*/
|
||||
void secs(uint16_t new_secs);
|
||||
|
||||
/**
|
||||
* \brief Setter for the padding field.
|
||||
* \param new_padding The padding to be set.
|
||||
*/
|
||||
void padding(uint16_t new_padding);
|
||||
|
||||
/**
|
||||
* \brief Setter for the ciaddr field.
|
||||
* \param new_ciaddr The ciaddr to be set.
|
||||
*/
|
||||
void ciaddr(ipaddress_type new_ciaddr);
|
||||
|
||||
/**
|
||||
* \brief Setter for the yiaddr field.
|
||||
* \param new_yiaddr The yiaddr to be set.
|
||||
*/
|
||||
void yiaddr(ipaddress_type new_yiaddr);
|
||||
|
||||
/**
|
||||
* \brief Setter for the siaddr field.
|
||||
* \param new_siaddr The siaddr to be set.
|
||||
*/
|
||||
void siaddr(ipaddress_type new_siaddr);
|
||||
|
||||
/**
|
||||
* \brief Setter for the giaddr field.
|
||||
* \param new_giaddr The giaddr to be set.
|
||||
*/
|
||||
void giaddr(ipaddress_type new_giaddr);
|
||||
|
||||
/**
|
||||
* \brief Setter for the chaddr field.
|
||||
* The new_chaddr pointer must be at least BOOTP::hlen() bytes long.
|
||||
* \param new_chaddr The chaddr to be set.
|
||||
*/
|
||||
template<size_t n>
|
||||
void chaddr(const HWAddress<n> &new_chaddr) {
|
||||
// Copy the new addr
|
||||
uint8_t *end = std::copy(
|
||||
new_chaddr.begin(),
|
||||
new_chaddr.begin() + std::min(n, sizeof(_bootp.chaddr)),
|
||||
_bootp.chaddr
|
||||
);
|
||||
// Fill what's left with zeros
|
||||
if(end < _bootp.chaddr + chaddr_type::address_size)
|
||||
std::fill(end, _bootp.chaddr + chaddr_type::address_size, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Setter for the sname field.
|
||||
* \param new_sname The sname to be set.
|
||||
*/
|
||||
void sname(const uint8_t *new_sname);
|
||||
|
||||
/**
|
||||
* \brief Setter for the file field.
|
||||
* \param new_file The file to be set.
|
||||
*/
|
||||
void file(const uint8_t *new_file);
|
||||
|
||||
/**
|
||||
* \brief Setter for the vend field.
|
||||
* \param new_vend The vend to be set.
|
||||
*/
|
||||
void vend(const vend_type &new_vend);
|
||||
|
||||
/**
|
||||
* \brief Check wether ptr points to a valid response for this PDU.
|
||||
*
|
||||
* This returns true if the xid field is equal.
|
||||
*
|
||||
* \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 Getter for the PDU's type.
|
||||
* \sa PDU::pdu_type
|
||||
*/
|
||||
PDUType pdu_type() const { return pdu_flag; }
|
||||
|
||||
/**
|
||||
* \sa PDU::clone
|
||||
*/
|
||||
BootP *clone() const {
|
||||
return new BootP(*this);
|
||||
}
|
||||
protected:
|
||||
/**
|
||||
* \brief Getter for the vend field.
|
||||
*
|
||||
* This getter can be used by subclasses to avoid copying the
|
||||
* vend field around.
|
||||
*
|
||||
* \return The vend field for this BootP PDU.
|
||||
*/
|
||||
vend_type &vend() { return _vend; }
|
||||
|
||||
void write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *parent);
|
||||
private:
|
||||
/**
|
||||
* Struct that represents the Bootp datagram.
|
||||
*/
|
||||
TINS_BEGIN_PACK
|
||||
struct bootphdr {
|
||||
uint8_t opcode;
|
||||
uint8_t htype;
|
||||
uint8_t hlen;
|
||||
uint8_t hops;
|
||||
uint32_t xid;
|
||||
uint16_t secs;
|
||||
uint16_t padding;
|
||||
uint32_t ciaddr;
|
||||
uint32_t yiaddr;
|
||||
uint32_t siaddr;
|
||||
uint32_t giaddr;
|
||||
uint8_t chaddr[16];
|
||||
uint8_t sname[64];
|
||||
uint8_t file[128];
|
||||
} TINS_END_PACK;
|
||||
|
||||
bootphdr _bootp;
|
||||
vend_type _vend;
|
||||
};
|
||||
}
|
||||
|
||||
#endif // TINS_BOOTP_H
|
||||
9
include/tins/config.h
Normal file
9
include/tins/config.h
Normal file
@@ -0,0 +1,9 @@
|
||||
|
||||
/* Define if the compiler supports basic C++11 syntax */
|
||||
#define HAVE_CXX11
|
||||
|
||||
/* Have IEEE 802.11 support */
|
||||
#define HAVE_DOT11
|
||||
|
||||
/* Have WPA2 decryption library */
|
||||
#define HAVE_WPA2_DECRYPTION
|
||||
9
include/tins/config.h.in
Normal file
9
include/tins/config.h.in
Normal file
@@ -0,0 +1,9 @@
|
||||
|
||||
/* Define if the compiler supports basic C++11 syntax */
|
||||
#cmakedefine HAVE_CXX11
|
||||
|
||||
/* Have IEEE 802.11 support */
|
||||
#cmakedefine HAVE_DOT11
|
||||
|
||||
/* Have WPA2 decryption library */
|
||||
#cmakedefine HAVE_WPA2_DECRYPTION
|
||||
160
include/tins/constants.h
Normal file
160
include/tins/constants.h
Normal file
@@ -0,0 +1,160 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Matias Fontanini
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following disclaimer
|
||||
* in the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef TINS_CONSTANTS_H
|
||||
#define TINS_CONSTANTS_H
|
||||
|
||||
namespace Tins {
|
||||
/**
|
||||
* \brief Constants used in protocols.
|
||||
*/
|
||||
namespace Constants {
|
||||
/** \cond */
|
||||
struct IP {
|
||||
/** \endcond */
|
||||
enum e {
|
||||
PROTO_IP = 0, /* Dummy protocol for TCP. */
|
||||
PROTO_HOPOPTS = 0, /* IPv6 Hop-by-Hop options. */
|
||||
PROTO_ICMP = 1, /* Internet Control Message Protocol. */
|
||||
PROTO_IGMP = 2, /* Internet Group Management Protocol. */
|
||||
PROTO_IPIP = 4, /* IPIP tunnels (older KA9Q tunnels use 94). */
|
||||
PROTO_TCP = 6, /* Transmission Control Protocol. */
|
||||
PROTO_EGP = 8, /* Exterior Gateway Protocol. */
|
||||
PROTO_PUP = 12, /* PUP protocol. */
|
||||
PROTO_UDP = 17, /* User Datagram Protocol. */
|
||||
PROTO_IDP = 22, /* XNS IDP protocol. */
|
||||
PROTO_TP = 29, /* SO Transport Protocol Class 4. */
|
||||
PROTO_DCCP = 33, /* Datagram Congestion Control Protocol. */
|
||||
PROTO_IPV6 = 41, /* IPv6 header. */
|
||||
PROTO_ROUTING = 43, /* IPv6 routing header. */
|
||||
PROTO_FRAGMENT = 44, /* IPv6 fragmentation header. */
|
||||
PROTO_RSVP = 46, /* Reservation Protocol. */
|
||||
PROTO_GRE = 47, /* General Routing Encapsulation. */
|
||||
PROTO_ESP = 50, /* encapsulating security payload. */
|
||||
PROTO_AH = 51, /* authentication header. */
|
||||
PROTO_ICMPV6 = 58, /* ICMPv6. */
|
||||
PROTO_NONE = 59, /* IPv6 no next header. */
|
||||
PROTO_DSTOPTS = 60, /* IPv6 destination options. */
|
||||
PROTO_MTP = 92, /* Multicast Transport Protocol. */
|
||||
PROTO_ENCAP = 98, /* Encapsulation Header. */
|
||||
PROTO_PIM = 103, /* Protocol Independent Multicast. */
|
||||
PROTO_COMP = 108, /* Compression Header Protocol. */
|
||||
PROTO_SCTP = 132, /* Stream Control Transmission Protocol. */
|
||||
PROTO_UDPLITE = 136, /* UDP-Lite protocol. */
|
||||
PROTO_RAW = 255 /* Raw IP packets. */
|
||||
};
|
||||
};
|
||||
|
||||
struct Ethernet {
|
||||
enum e {
|
||||
UNKNOWN = 0,
|
||||
//~ PUP = 0x0200, /* Xerox PUP */
|
||||
SPRITE = 0x0500, /* Sprite */
|
||||
IP = 0x0800, /* IP */
|
||||
ARP = 0x0806, /* Address resolution */
|
||||
REVARP = 0x8035, /* Reverse ARP */
|
||||
AT = 0x809B, /* AppleTalk protocol */
|
||||
AARP = 0x80F3, /* AppleTalk ARP */
|
||||
VLAN = 0x8100, /* IEEE 802.1Q VLAN tagging */
|
||||
IPX = 0x8137, /* IPX */
|
||||
IPV6 = 0x86dd, /* IP protocol version 6 */
|
||||
PPPOED = 0x8863, /* PPPoE Discovery */
|
||||
PPPOES = 0x8864, /* PPPoE Session */
|
||||
EAPOL = 0x888e, /* EAPOL */
|
||||
LOOPBACK = 0x9000 /* used to test interfaces */
|
||||
};
|
||||
};
|
||||
|
||||
struct ARP {
|
||||
enum e {
|
||||
NETROM = 0, /* From KA9Q: NET/ROM pseudo. */
|
||||
ETHER = 1, /* Ethernet 10/100Mbps. */
|
||||
EETHER = 2, /* Experimental Ethernet. */
|
||||
AX25 = 3, /* AX.25 Level 2. */
|
||||
PRONET = 4, /* PROnet token ring. */
|
||||
CHAOS = 5, /* Chaosnet. */
|
||||
IEEE802 = 6, /* IEEE 802.2 Ethernet/TR/TB. */
|
||||
ARCNET = 7, /* ARCnet. */
|
||||
APPLETLK = 8, /* APPLEtalk. */
|
||||
DLCI = 15, /* Frame Relay DLCI. */
|
||||
ATM = 19, /* ATM. */
|
||||
METRICOM = 23, /* Metricom STRIP (new IANA id). */
|
||||
IEEE1394 = 24, /* IEEE 1394 IPv4 - RFC 2734. */
|
||||
EUI64 = 27, /* EUI-64. */
|
||||
INFINIBAND = 32, /* InfiniBand. */
|
||||
SLIP = 256,
|
||||
CSLIP = 257,
|
||||
SLIP6 = 258,
|
||||
CSLIP6 = 259,
|
||||
RSRVD = 260, /* Notional KISS type. */
|
||||
ADAPT = 264,
|
||||
ROSE = 270,
|
||||
X25 = 271, /* CCITT X.25. */
|
||||
HWX25 = 272, /* Boards with X.25 in firmware. */
|
||||
PPP = 512,
|
||||
CISCO = 513, /* Cisco HDLC. */
|
||||
HDLC = CISCO,
|
||||
LAPB = 516, /* LAPB. */
|
||||
DDCMP = 517, /* Digital's DDCMP. */
|
||||
RAWHDLC = 518, /* Raw HDLC. */
|
||||
TUNNEL = 768, /* IPIP tunnel. */
|
||||
TUNNEL6 = 769, /* IPIP6 tunnel. */
|
||||
FRAD = 770, /* Frame Relay Access Device. */
|
||||
SKIP = 771, /* SKIP vif. */
|
||||
LOOPBACK = 772, /* Loopback device. */
|
||||
LOCALTLK = 773, /* Localtalk device. */
|
||||
FDDI = 774, /* Fiber Distributed Data Interface. */
|
||||
BIF = 775, /* AP1000 BIF. */
|
||||
SIT = 776, /* sit0 device - IPv6-in-IPv4. */
|
||||
IPDDP = 777, /* IP-in-DDP tunnel. */
|
||||
IPGRE = 778, /* GRE over IP. */
|
||||
PIMREG = 779, /* PIMSM register interface. */
|
||||
HIPPI = 780, /* High Performance Parallel I'face. */
|
||||
ASH = 781, /* (Nexus Electronics) Ash. */
|
||||
ECONET = 782, /* Acorn Econet. */
|
||||
IRDA = 783, /* Linux-IrDA. */
|
||||
FCPP = 784, /* Point to point fibrechanel. */
|
||||
FCAL = 785, /* Fibrechanel arbitrated loop. */
|
||||
FCPL = 786, /* Fibrechanel public loop. */
|
||||
FCFABRIC = 787, /* Fibrechanel fabric. */
|
||||
IEEE802_TR = 800, /* Magic type ident for TR. */
|
||||
IEEE80211 = 801, /* IEEE 802.11. */
|
||||
IEEE80211_PRISM = 802, /* IEEE 802.11 + Prism2 header. */
|
||||
IEEE80211_RADIOTAP = 803, /* IEEE 802.11 + radiotap header. */
|
||||
IEEE802154 = 804, /* IEEE 802.15.4 header. */
|
||||
IEEE802154_PHY = 805, /* IEEE 802.15.4 PHY header. */
|
||||
VOID_TYPE = 0xFFFF, /* Void type, nothing is known. */
|
||||
NONE = 0xFFFE /* Zero header length. */
|
||||
};
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#endif // TINS_CONSTANTS_H
|
||||
415
include/tins/crypto.h
Normal file
415
include/tins/crypto.h
Normal file
@@ -0,0 +1,415 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Matias Fontanini
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following disclaimer
|
||||
* in the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#if !defined(TINS_CRYPTO_H) && defined(HAVE_DOT11)
|
||||
#define TINS_CRYPTO_H
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <algorithm>
|
||||
#include <vector>
|
||||
#include "utils.h"
|
||||
#include "snap.h"
|
||||
#include "rawpdu.h"
|
||||
#include "handshake_capturer.h"
|
||||
|
||||
namespace Tins {
|
||||
class PDU;
|
||||
class Dot11;
|
||||
class Dot11Data;
|
||||
|
||||
namespace Crypto {
|
||||
/**
|
||||
* \cond
|
||||
*/
|
||||
struct RC4Key;
|
||||
#ifdef HAVE_WPA2_DECRYPTION
|
||||
namespace WPA2 {
|
||||
class invalid_handshake : public std::exception {
|
||||
public:
|
||||
const char *what() const throw() {
|
||||
return "invalid handshake";
|
||||
}
|
||||
};
|
||||
class SessionKeys {
|
||||
public:
|
||||
typedef Internals::byte_array<80> ptk_type;
|
||||
typedef Internals::byte_array<32> pmk_type;
|
||||
|
||||
SessionKeys();
|
||||
SessionKeys(const RSNHandshake &hs, const pmk_type &pmk);
|
||||
SNAP *decrypt_unicast(const Dot11Data &dot11, RawPDU &raw) const;
|
||||
private:
|
||||
SNAP *ccmp_decrypt_unicast(const Dot11Data &dot11, RawPDU &raw) const;
|
||||
SNAP *tkip_decrypt_unicast(const Dot11Data &dot11, RawPDU &raw) const;
|
||||
RC4Key generate_rc4_key(const Dot11Data &dot11, const RawPDU &raw) const;
|
||||
|
||||
ptk_type ptk;
|
||||
bool is_ccmp;
|
||||
};
|
||||
|
||||
class SupplicantData {
|
||||
public:
|
||||
typedef HWAddress<6> address_type;
|
||||
typedef SessionKeys::pmk_type pmk_type;
|
||||
|
||||
SupplicantData(const std::string &psk, const std::string &ssid);
|
||||
|
||||
const pmk_type &pmk() const;
|
||||
private:
|
||||
pmk_type pmk_;
|
||||
};
|
||||
}
|
||||
#endif // HAVE_WPA2_DECRYPTION
|
||||
/**
|
||||
* \endcond
|
||||
*/
|
||||
|
||||
/**
|
||||
* \brief RC4 Key abstraction.
|
||||
*/
|
||||
struct RC4Key {
|
||||
static const size_t data_size = 256;
|
||||
|
||||
/**
|
||||
* \brief Initializes the key using the provided iterator range.
|
||||
*
|
||||
* \param start The start of the range.
|
||||
* \param end The end of the range.
|
||||
*/
|
||||
template<typename ForwardIterator>
|
||||
RC4Key(ForwardIterator start, ForwardIterator end);
|
||||
|
||||
/**
|
||||
* The actual key data.
|
||||
*/
|
||||
uint8_t data[data_size];
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Decrypts WEP-encrypted traffic.
|
||||
*/
|
||||
class WEPDecrypter {
|
||||
public:
|
||||
typedef HWAddress<6> address_type;
|
||||
|
||||
/**
|
||||
* \brief Constructs a WEPDecrypter object.
|
||||
*/
|
||||
WEPDecrypter();
|
||||
|
||||
/**
|
||||
* \brief Adds a decryption password.
|
||||
*
|
||||
* \param addr The access point's BSSID.
|
||||
* \param password The password which will be used to decrypt
|
||||
* packets sent from and to the AP identifier by the BSSID addr.
|
||||
*/
|
||||
void add_password(const address_type &addr, const std::string &password);
|
||||
|
||||
/**
|
||||
* \brief Removes a decryption password
|
||||
*
|
||||
* \param addr The BSSID of the access point.
|
||||
*/
|
||||
void remove_password(const address_type &addr);
|
||||
|
||||
/**
|
||||
* \brief Decrypts the provided PDU.
|
||||
*
|
||||
* A Dot11Data PDU is looked up inside the provided PDU chain.
|
||||
* If no such PDU exists or there is no password associated
|
||||
* with the Dot11 packet's BSSID, then the PDU is left intact.
|
||||
*
|
||||
* Otherwise, the packet is decrypted using the given password.
|
||||
* If the CRC found after decrypting is invalid, false is
|
||||
* returned.
|
||||
*
|
||||
* \return false if no decryption was performed or decryption
|
||||
* failed, true otherwise.
|
||||
*/
|
||||
bool decrypt(PDU &pdu);
|
||||
private:
|
||||
typedef std::map<address_type, std::string> passwords_type;
|
||||
|
||||
PDU *decrypt(RawPDU &raw, const std::string &password);
|
||||
|
||||
passwords_type passwords;
|
||||
std::vector<uint8_t> key_buffer;
|
||||
};
|
||||
|
||||
#ifdef HAVE_WPA2_DECRYPTION
|
||||
/**
|
||||
* \brief Decrypts WPA2-encrypted traffic.
|
||||
*
|
||||
* This class takes valid PSK and SSID tuples, captures client handshakes,
|
||||
* and decrypts their traffic afterwards.
|
||||
*/
|
||||
class WPA2Decrypter {
|
||||
public:
|
||||
/*
|
||||
* \brief The type used to store Dot11 addresses.
|
||||
*/
|
||||
typedef HWAddress<6> address_type;
|
||||
|
||||
/**
|
||||
* \brief Adds an access points's information.
|
||||
*
|
||||
* This associates an SSID with a PSK, and allows the decryption of
|
||||
* any BSSIDs that broadcast the same SSID.
|
||||
*
|
||||
* The decrypter will inspect beacon frames, looking for SSID tags
|
||||
* that contain the given SSID.
|
||||
*
|
||||
* Note that using this overload, the decryption of data frames and
|
||||
* handshake capturing will be disabled until any access point
|
||||
* broadcasts the provided SSID(this shouldn't take long at all).
|
||||
* If this is not the desired behaviour, then you should check out
|
||||
* the ovther add_ap_data overload.
|
||||
*
|
||||
* \param psk The PSK associated with the SSID.
|
||||
* \param ssid The network's SSID.
|
||||
*/
|
||||
void add_ap_data(const std::string &psk, const std::string &ssid);
|
||||
|
||||
/**
|
||||
* \brief Adds a access points's information, including its BSSID.
|
||||
*
|
||||
* This overload can be used if the BSSID associated with this SSID is
|
||||
* known beforehand. The addr parameter indicates which specific BSSID
|
||||
* is associated to the SSID.
|
||||
*
|
||||
* Note that if any other access point broadcasts the provided SSID,
|
||||
* it will be taken into account as well.
|
||||
*
|
||||
* \param psk The PSK associated with this SSID.
|
||||
* \param ssid The network's SSID.
|
||||
* \param addr The access point's BSSID.
|
||||
*/
|
||||
void add_ap_data(const std::string &psk, const std::string &ssid, const address_type &addr);
|
||||
|
||||
/**
|
||||
* \brief Decrypts the provided PDU.
|
||||
*
|
||||
* A Dot11Data PDU is looked up inside the provided PDU chain.
|
||||
* If no such PDU exists or no PSK was associated with the SSID
|
||||
* broadcasted by the Dot11 packet's BSSID, or no EAPOL handshake
|
||||
* was captured for the client involved in the communication,
|
||||
* then the PDU is left intact.
|
||||
*
|
||||
* Otherwise, the packet is decrypted using the generated PTK.
|
||||
* If the resulting MIC is invalid, then the packet is left intact.
|
||||
*
|
||||
* \return false if no decryption was performed, or the decryption
|
||||
* failed, true otherwise.
|
||||
*/
|
||||
bool decrypt(PDU &pdu);
|
||||
private:
|
||||
typedef std::map<std::string, WPA2::SupplicantData> pmks_map;
|
||||
typedef std::map<address_type, WPA2::SupplicantData> bssids_map;
|
||||
typedef std::pair<address_type, address_type> addr_pair;
|
||||
typedef std::map<addr_pair, WPA2::SessionKeys> keys_map;
|
||||
|
||||
void try_add_keys(const Dot11Data &dot11, const RSNHandshake &hs);
|
||||
addr_pair make_addr_pair(const address_type &addr1, const address_type &addr2) {
|
||||
return (addr1 < addr2) ?
|
||||
std::make_pair(addr1, addr2) :
|
||||
std::make_pair(addr2, addr1);
|
||||
}
|
||||
addr_pair extract_addr_pair(const Dot11Data &dot11);
|
||||
addr_pair extract_addr_pair_dst(const Dot11Data &dot11);
|
||||
bssids_map::const_iterator find_ap(const Dot11Data &dot11);
|
||||
void add_access_point(const std::string &ssid, const address_type &addr);
|
||||
|
||||
RSNHandshakeCapturer capturer;
|
||||
pmks_map pmks;
|
||||
bssids_map aps;
|
||||
keys_map keys;
|
||||
};
|
||||
#endif // HAVE_WPA2_DECRYPTION
|
||||
|
||||
/**
|
||||
* \brief Pluggable decrypter object which can be used to decrypt
|
||||
* data on sniffing sessions.
|
||||
*
|
||||
* This class holds a decrypter object and a functor, and implements
|
||||
* a suitable operator() to be used on BaseSniffer::sniff_loop, which
|
||||
* decrypts packets and forwards them to the given functor.
|
||||
*/
|
||||
template<typename Functor, typename Decrypter>
|
||||
class DecrypterProxy {
|
||||
public:
|
||||
/**
|
||||
* The type of the functor object.
|
||||
*/
|
||||
typedef Functor functor_type;
|
||||
|
||||
/**
|
||||
* The type of the decrypter object.
|
||||
*/
|
||||
typedef Decrypter decrypter_type;
|
||||
|
||||
/**
|
||||
* \brief Constructs an object from a functor and a decrypter.
|
||||
* \param func The functor to be used to forward decrypted
|
||||
* packets.
|
||||
* \param decrypter The decrypter which will be used to decrypt
|
||||
* packets
|
||||
*/
|
||||
DecrypterProxy(const functor_type &func,
|
||||
const decrypter_type &decr = decrypter_type());
|
||||
|
||||
/**
|
||||
* \brief Retrieves a reference to the decrypter object.
|
||||
*/
|
||||
decrypter_type &decrypter();
|
||||
|
||||
/**
|
||||
* \brief Retrieves a const reference to the decrypter object.
|
||||
*/
|
||||
const decrypter_type &decrypter() const;
|
||||
|
||||
/**
|
||||
* \brief The operator() which decrypts packets and forwards
|
||||
* them to the functor.
|
||||
*/
|
||||
bool operator() (PDU &pdu);
|
||||
private:
|
||||
Functor functor_;
|
||||
decrypter_type decrypter_;
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Performs RC4 encription/decryption of the given byte range,
|
||||
* using the provided key.
|
||||
*
|
||||
* The decrypted range will be copied to the OutputIterator provided.
|
||||
*
|
||||
* \param start The beginning of the range.
|
||||
* \param start The end of the range.
|
||||
* \param key The key to be used.
|
||||
* \param output The iterator in which to write the output.
|
||||
*/
|
||||
template<typename ForwardIterator, typename OutputIterator>
|
||||
void rc4(ForwardIterator start, ForwardIterator end, RC4Key &key, OutputIterator output);
|
||||
|
||||
/**
|
||||
* \brief Wrapper function to create a DecrypterProxy using a
|
||||
* WEPDecrypter as the Decrypter template parameter.
|
||||
*
|
||||
* \param functor The functor to be forwarded to the DecrypterProxy
|
||||
* constructor.
|
||||
*/
|
||||
template<typename Functor>
|
||||
DecrypterProxy<Functor, WEPDecrypter> make_wep_decrypter_proxy(const Functor &functor);
|
||||
|
||||
#ifdef HAVE_WPA2_DECRYPTION
|
||||
/**
|
||||
* \brief Wrapper function to create a DecrypterProxy using a
|
||||
* WPA2Decrypter as the Decrypter template parameter.
|
||||
*
|
||||
* \param functor The functor to be forwarded to the DecrypterProxy
|
||||
* constructor.
|
||||
*/
|
||||
template<typename Functor>
|
||||
DecrypterProxy<Functor, WPA2Decrypter> make_wpa2_decrypter_proxy(const Functor &functor) {
|
||||
return DecrypterProxy<Functor, WPA2Decrypter>(functor);
|
||||
}
|
||||
#endif // HAVE_WPA2_DECRYPTION
|
||||
|
||||
// Implementation section
|
||||
|
||||
// DecrypterProxy
|
||||
|
||||
template<typename Functor, typename Decrypter>
|
||||
DecrypterProxy<Functor, Decrypter>::DecrypterProxy(
|
||||
const functor_type &func, const decrypter_type& decr)
|
||||
: functor_(func), decrypter_(decr)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
template<typename Functor, typename Decrypter>
|
||||
typename DecrypterProxy<Functor, Decrypter>::decrypter_type &
|
||||
DecrypterProxy<Functor, Decrypter>::decrypter()
|
||||
{
|
||||
return decrypter_;
|
||||
}
|
||||
|
||||
template<typename Functor, typename Decrypter>
|
||||
const typename DecrypterProxy<Functor, Decrypter>::decrypter_type &
|
||||
DecrypterProxy<Functor, Decrypter>::decrypter() const
|
||||
{
|
||||
return decrypter_;
|
||||
}
|
||||
|
||||
template<typename Functor, typename Decrypter>
|
||||
bool DecrypterProxy<Functor, Decrypter>::operator() (PDU &pdu)
|
||||
{
|
||||
return decrypter_.decrypt(pdu) ? functor_(pdu) : true;
|
||||
}
|
||||
|
||||
template<typename Functor>
|
||||
DecrypterProxy<Functor, WEPDecrypter> make_wep_decrypter_proxy(const Functor &functor)
|
||||
{
|
||||
return DecrypterProxy<Functor, WEPDecrypter>(functor);
|
||||
}
|
||||
|
||||
// RC4 stuff
|
||||
|
||||
template<typename ForwardIterator>
|
||||
RC4Key::RC4Key(ForwardIterator start, ForwardIterator end) {
|
||||
for(size_t i = 0; i < data_size; ++i)
|
||||
data[i] = i;
|
||||
size_t j = 0;
|
||||
ForwardIterator iter = start;
|
||||
for(size_t i = 0; i < data_size; ++i) {
|
||||
j = (j + data[i] + *iter++) % 256;
|
||||
if(iter == end)
|
||||
iter = start;
|
||||
std::swap(data[i], data[j]);
|
||||
}
|
||||
}
|
||||
|
||||
template<typename ForwardIterator, typename OutputIterator>
|
||||
void rc4(ForwardIterator start, ForwardIterator end, RC4Key &key, OutputIterator output) {
|
||||
size_t i = 0, j = 0;
|
||||
while(start != end) {
|
||||
i = (i + 1) % RC4Key::data_size;
|
||||
j = (j + key.data[i]) % RC4Key::data_size;
|
||||
std::swap(key.data[i], key.data[j]);
|
||||
*output++ = *start++ ^ key.data[(key.data[i] + key.data[j]) % RC4Key::data_size];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif // TINS_CRYPTO_H
|
||||
58
include/tins/cxxstd.h
Normal file
58
include/tins/cxxstd.h
Normal file
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Matias Fontanini
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following disclaimer
|
||||
* in the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef TINS_CXXSTD_H
|
||||
#define TINS_CXXSTD_H
|
||||
|
||||
#include <memory>
|
||||
|
||||
#ifdef __GXX_EXPERIMENTAL_CXX0X__
|
||||
#define TINS_CXXSTD_GCC_FIX 1
|
||||
#else
|
||||
#define TINS_CXXSTD_GCC_FIX 0
|
||||
#endif // __GXX_EXPERIMENTAL_CXX0X__
|
||||
|
||||
#ifndef TINS_IS_CXX11
|
||||
#define TINS_IS_CXX11 (__cplusplus > 199711L || TINS_CXXSTD_GCC_FIX == 1 || _MSC_VER >= 1800)
|
||||
#endif // TINS_IS_CXX11
|
||||
|
||||
namespace Tins{
|
||||
namespace Internals {
|
||||
template<typename T>
|
||||
struct smart_ptr {
|
||||
#if TINS_IS_CXX11
|
||||
typedef std::unique_ptr<T> type;
|
||||
#else
|
||||
typedef std::auto_ptr<T> type;
|
||||
#endif
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#endif // TINS_CXXSTD_H
|
||||
81
include/tins/data_link_type.h
Normal file
81
include/tins/data_link_type.h
Normal file
@@ -0,0 +1,81 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Matias Fontanini
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following disclaimer
|
||||
* in the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef TINS_DATA_LINK_TYPE_H
|
||||
#define TINS_DATA_LINK_TYPE_H
|
||||
|
||||
#include <pcap.h>
|
||||
|
||||
namespace Tins {
|
||||
|
||||
class EthernetII;
|
||||
class RadioTap;
|
||||
class Dot11;
|
||||
class Dot3;
|
||||
class SLL;
|
||||
class Loopback;
|
||||
class PPI;
|
||||
|
||||
/**
|
||||
* \struct DataLinkType
|
||||
* \brief Maps a libtins link layer PDU to a libpcap data link identifier.
|
||||
*
|
||||
* This is an empty class that should be instantiated with any object that
|
||||
* represents a link layer PDU (EthernetII, Dot11, RadioTap, etc):
|
||||
*
|
||||
* \code
|
||||
* // Instantiate it and pass it to PacketWriter's constructor.
|
||||
* PacketWriter writer("file.pcap", DataLinkType<RadioTap>());
|
||||
* \endcode
|
||||
*/
|
||||
template<typename T>
|
||||
struct DataLinkType;
|
||||
|
||||
#define TINS_MAKE_DATA_LINK_TYPE(tins_type, pcap_type) \
|
||||
template<> \
|
||||
struct DataLinkType<tins_type> { \
|
||||
static const int type = pcap_type; \
|
||||
int get_type() const { \
|
||||
return type; \
|
||||
} \
|
||||
};
|
||||
|
||||
TINS_MAKE_DATA_LINK_TYPE(EthernetII, DLT_EN10MB)
|
||||
TINS_MAKE_DATA_LINK_TYPE(Dot3, DLT_EN10MB)
|
||||
TINS_MAKE_DATA_LINK_TYPE(SLL, DLT_LINUX_SLL)
|
||||
TINS_MAKE_DATA_LINK_TYPE(Loopback, DLT_LOOP)
|
||||
TINS_MAKE_DATA_LINK_TYPE(PPI, DLT_PPI)
|
||||
TINS_MAKE_DATA_LINK_TYPE(Dot11, DLT_IEEE802_11)
|
||||
TINS_MAKE_DATA_LINK_TYPE(RadioTap, DLT_IEEE802_11_RADIO)
|
||||
|
||||
#undef TINS_MAKE_DATA_LINK_TYPE
|
||||
|
||||
} // Tins
|
||||
|
||||
#endif // TINS_DATA_LINK_TYPE_H
|
||||
510
include/tins/dhcp.h
Normal file
510
include/tins/dhcp.h
Normal file
@@ -0,0 +1,510 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Matias Fontanini
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following disclaimer
|
||||
* in the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef TINS_DHCP_H
|
||||
#define TINS_DHCP_H
|
||||
|
||||
|
||||
#include <list>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include "bootp.h"
|
||||
#include "pdu_option.h"
|
||||
#include "cxxstd.h"
|
||||
|
||||
namespace Tins {
|
||||
/**
|
||||
* \class DHCP
|
||||
* \brief Represents the DHCP PDU.
|
||||
*
|
||||
* This class represents a DHCP PDU. It contains helpers methods
|
||||
* which make it easy to set/get specific option values.
|
||||
*
|
||||
* Note that when adding options, the "End" option is not added
|
||||
* automatically, so you will have to add it yourself.
|
||||
*
|
||||
* Options can be retrieved easily from DHCP PDUs:
|
||||
*
|
||||
* \code
|
||||
* // Sniff a packet from somewhere
|
||||
* DHCP dhcp = get_dhcp_from_somewhere();
|
||||
*
|
||||
* // This retrieves the Domain Name Servers option and converts
|
||||
* // it to a std::vector<IPv4Address>. Note that if this option
|
||||
* // is not present, an option_not_found exception is thrown.
|
||||
* for(const auto& address : dhcp.domain_name_servers()) {
|
||||
* // address is an ip
|
||||
* }
|
||||
*
|
||||
* \endcode
|
||||
*/
|
||||
class DHCP : public BootP {
|
||||
public:
|
||||
/**
|
||||
* This PDU's flag.
|
||||
*/
|
||||
static const PDU::PDUType pdu_flag = PDU::DHCP;
|
||||
|
||||
/**
|
||||
* DHCP flags.
|
||||
*/
|
||||
enum Flags {
|
||||
DISCOVER = 1,
|
||||
OFFER = 2,
|
||||
REQUEST = 3,
|
||||
DECLINE = 4,
|
||||
ACK = 5,
|
||||
NAK = 6,
|
||||
RELEASE = 7,
|
||||
INFORM = 8
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief DHCP options enum.
|
||||
*/
|
||||
enum OptionTypes {
|
||||
PAD,
|
||||
SUBNET_MASK,
|
||||
TIME_OFFSET,
|
||||
ROUTERS,
|
||||
TIME_SERVERS,
|
||||
NAME_SERVERS,
|
||||
DOMAIN_NAME_SERVERS,
|
||||
LOG_SERVERS,
|
||||
COOKIE_SERVERS,
|
||||
LPR_SERVERS,
|
||||
IMPRESS_SERVERS,
|
||||
RESOURCE_LOCATION_SERVERS,
|
||||
HOST_NAME,
|
||||
BOOT_SIZE,
|
||||
MERIT_DUMP,
|
||||
DOMAIN_NAME,
|
||||
SWAP_SERVER,
|
||||
ROOT_PATH,
|
||||
EXTENSIONS_PATH,
|
||||
IP_FORWARDING,
|
||||
NON_LOCAL_SOURCE_ROUTING,
|
||||
POLICY_FILTER,
|
||||
MAX_DGRAM_REASSEMBLY,
|
||||
DEFAULT_IP_TTL,
|
||||
PATH_MTU_AGING_TIMEOUT,
|
||||
PATH_MTU_PLATEAU_TABLE,
|
||||
INTERFACE_MTU,
|
||||
ALL_SUBNETS_LOCAL,
|
||||
BROADCAST_ADDRESS,
|
||||
PERFORM_MASK_DISCOVERY,
|
||||
MASK_SUPPLIER,
|
||||
ROUTER_DISCOVERY,
|
||||
ROUTER_SOLICITATION_ADDRESS,
|
||||
STATIC_ROUTES,
|
||||
TRAILER_ENCAPSULATION,
|
||||
ARP_CACHE_TIMEOUT,
|
||||
IEEE802_3_ENCAPSULATION,
|
||||
DEFAULT_TCP_TTL,
|
||||
TCP_KEEPALIVE_INTERVAL,
|
||||
TCP_KEEPALIVE_GARBAGE,
|
||||
NIS_DOMAIN,
|
||||
NIS_SERVERS,
|
||||
NTP_SERVERS,
|
||||
VENDOR_ENCAPSULATED_OPTIONS,
|
||||
NETBIOS_NAME_SERVERS,
|
||||
NETBIOS_DD_SERVER,
|
||||
NETBIOS_NODE_TYPE,
|
||||
NETBIOS_SCOPE,
|
||||
FONT_SERVERS,
|
||||
X_DISPLAY_MANAGER,
|
||||
DHCP_REQUESTED_ADDRESS,
|
||||
DHCP_LEASE_TIME,
|
||||
DHCP_OPTION_OVERLOAD,
|
||||
DHCP_MESSAGE_TYPE,
|
||||
DHCP_SERVER_IDENTIFIER,
|
||||
DHCP_PARAMETER_REQUEST_LIST,
|
||||
DHCP_MESSAGE,
|
||||
DHCP_MAX_MESSAGE_SIZE,
|
||||
DHCP_RENEWAL_TIME,
|
||||
DHCP_REBINDING_TIME,
|
||||
VENDOR_CLASS_IDENTIFIER,
|
||||
DHCP_CLIENT_IDENTIFIER,
|
||||
NWIP_DOMAIN_NAME,
|
||||
NWIP_SUBOPTIONS,
|
||||
USER_CLASS = 77,
|
||||
FQDN = 81,
|
||||
DHCP_AGENT_OPTIONS = 82,
|
||||
SUBNET_SELECTION = 118,
|
||||
AUTHENTICATE = 210,
|
||||
END = 255
|
||||
};
|
||||
|
||||
/**
|
||||
* The DHCP option type.
|
||||
*/
|
||||
typedef PDUOption<uint8_t, DHCP> option;
|
||||
|
||||
/**
|
||||
* The type used to store the DHCP options.
|
||||
*/
|
||||
typedef std::list<option> options_type;
|
||||
|
||||
/**
|
||||
* \brief Creates an instance of DHCP.
|
||||
*
|
||||
* This sets the hwtype and hlen fields to match the ethernet
|
||||
* type and length.
|
||||
*/
|
||||
DHCP();
|
||||
|
||||
/**
|
||||
* \brief Constructs a DHCP object from a buffer.
|
||||
*
|
||||
* If there is not enough size for a BootP header, or any of
|
||||
* the TLV options contains an invalid size field, then 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.
|
||||
*/
|
||||
DHCP(const uint8_t *buffer, uint32_t total_sz);
|
||||
|
||||
/**
|
||||
* \brief Adds a new option to this DHCP PDU.
|
||||
* \param opt The option to be added.
|
||||
*/
|
||||
void add_option(const option &opt);
|
||||
|
||||
#if TINS_IS_CXX11
|
||||
/**
|
||||
* \brief Adds a new option to this DHCP PDU.
|
||||
*
|
||||
* The option is move-constructed.
|
||||
*
|
||||
* \param opt The option to be added.
|
||||
*/
|
||||
void add_option(option &&opt) {
|
||||
internal_add_option(opt);
|
||||
_options.push_back(std::move(opt));
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* \brief Searchs for an option that matchs the given flag.
|
||||
* \param opt_flag The flag to be searched.
|
||||
* \return A pointer to the option, or 0 if it was not found.
|
||||
*/
|
||||
const option *search_option(OptionTypes opt) const;
|
||||
|
||||
/**
|
||||
* \brief Adds a type option to the option list.
|
||||
*
|
||||
* The new option is appended at the end of the list.
|
||||
*
|
||||
* \param type The type of this DHCP PDU.
|
||||
*/
|
||||
void type(Flags type);
|
||||
|
||||
/**
|
||||
* \brief Adds an end option to the option list.
|
||||
*
|
||||
* The new option is appended at the end of the list.
|
||||
*
|
||||
* The END option is not added automatically. You should explicitly
|
||||
* add it at the end of the DHCP options for the PDU to be
|
||||
* standard-compliant.
|
||||
*/
|
||||
void end();
|
||||
|
||||
/**
|
||||
* \brief Adds a server identifier option.
|
||||
*
|
||||
* The new option is appended at the end of the list.
|
||||
*
|
||||
* \param ip The server's IP address.
|
||||
*/
|
||||
void server_identifier(ipaddress_type ip);
|
||||
|
||||
/**
|
||||
* \brief Adds an IP address lease time option.
|
||||
*
|
||||
* The new option is appended at the end of the list.
|
||||
*
|
||||
* \param time The lease time.
|
||||
*/
|
||||
void lease_time(uint32_t time);
|
||||
|
||||
/**
|
||||
* \brief Adds a lease renewal time option.
|
||||
*
|
||||
* The new option is appended at the end of the list.
|
||||
*
|
||||
* \param time The lease renew time.
|
||||
*/
|
||||
void renewal_time(uint32_t time);
|
||||
|
||||
/**
|
||||
* \brief Adds a rebind time option.
|
||||
*
|
||||
* The new option is appended at the end of the list.
|
||||
*
|
||||
* \param time The lease rebind time.
|
||||
*/
|
||||
void rebind_time(uint32_t time);
|
||||
|
||||
/**
|
||||
* \brief Adds a subnet mask option.
|
||||
*
|
||||
* The new option is appended at the end of the list.
|
||||
*
|
||||
* \param mask The subnet mask.
|
||||
*/
|
||||
void subnet_mask(ipaddress_type mask);
|
||||
|
||||
/**
|
||||
* \brief Adds a routers option.
|
||||
*
|
||||
* The new option is appended at the end of the list.
|
||||
*
|
||||
* \param routers A list of ip addresses.
|
||||
*/
|
||||
void routers(const std::vector<ipaddress_type> &routers);
|
||||
|
||||
/**
|
||||
* \brief Adds a domain name servers option.
|
||||
*
|
||||
* The new option is appended at the end of the list.
|
||||
*
|
||||
* \param dns A list of ip addresses.
|
||||
*/
|
||||
void domain_name_servers(const std::vector<ipaddress_type> &dns);
|
||||
|
||||
/**
|
||||
* \brief Adds a broadcast address option.
|
||||
*
|
||||
* The new option is appended at the end of the list.
|
||||
*
|
||||
* \param addr The broadcast address.
|
||||
*/
|
||||
void broadcast(ipaddress_type addr);
|
||||
|
||||
/**
|
||||
* \brief Adds a requested address option.
|
||||
*
|
||||
* The new option is appended at the end of the list.
|
||||
*
|
||||
* \param addr The requested address.
|
||||
*/
|
||||
void requested_ip(ipaddress_type addr);
|
||||
|
||||
/**
|
||||
* \brief Adds a domain name option.
|
||||
*
|
||||
* The new option is appended at the end of the list.
|
||||
*
|
||||
* \param name The domain name.
|
||||
*/
|
||||
void domain_name(const std::string &name);
|
||||
|
||||
/**
|
||||
* \brief Adds a hostname option.
|
||||
*
|
||||
* The new option is appended at the end of the list.
|
||||
*
|
||||
* \param name The hostname.
|
||||
*/
|
||||
void hostname(const std::string &name);
|
||||
|
||||
// Option getters
|
||||
|
||||
/**
|
||||
* \brief Searchs for a type option.
|
||||
*
|
||||
* If the option is not found, an option_not_found exception
|
||||
* is thrown.
|
||||
*
|
||||
* \return uint8_t containing the type option.
|
||||
*/
|
||||
uint8_t type() const;
|
||||
|
||||
/**
|
||||
* \brief Searchs for a server identifier option.
|
||||
*
|
||||
* If the option is not found, an option_not_found exception
|
||||
* is thrown.
|
||||
*
|
||||
* \return ipaddress_type Containing the server identifier.
|
||||
*/
|
||||
ipaddress_type server_identifier() const;
|
||||
|
||||
/**
|
||||
* \brief Searchs for a lease time option.
|
||||
*
|
||||
* If the option is not found, an option_not_found exception
|
||||
* is thrown.
|
||||
*
|
||||
* \return uint32_t Containing the lease time.
|
||||
*/
|
||||
uint32_t lease_time() const;
|
||||
|
||||
/**
|
||||
* \brief Searchs for a lease renewal time option.
|
||||
*
|
||||
* If the option is not found, an option_not_found exception
|
||||
* is thrown.
|
||||
*
|
||||
* \return uint32_t Containing the renewal time.
|
||||
*/
|
||||
uint32_t renewal_time() const;
|
||||
|
||||
/**
|
||||
* \brief Searchs for a rebind time option.
|
||||
*
|
||||
* If the option is not found, an option_not_found exception
|
||||
* is thrown.
|
||||
*
|
||||
* \return uint32_t Containing the rebind time.
|
||||
*/
|
||||
uint32_t rebind_time() const;
|
||||
|
||||
/**
|
||||
* \brief Searchs for a subnet mask option.
|
||||
*
|
||||
* If the option is not found, an option_not_found exception
|
||||
* is thrown.
|
||||
*
|
||||
* \return ipaddress_type Containing the subnet mask.
|
||||
*/
|
||||
ipaddress_type subnet_mask() const;
|
||||
|
||||
/**
|
||||
* \brief Searchs for a routers option.
|
||||
*
|
||||
* If the option is not found, an option_not_found exception
|
||||
* is thrown.
|
||||
*
|
||||
* \return std::vector<ipaddress_type> Containing the routers
|
||||
* option data.
|
||||
*/
|
||||
std::vector<ipaddress_type> routers() const;
|
||||
|
||||
/**
|
||||
* \brief Searchs for a dns option.
|
||||
*
|
||||
* If the option is not found, an option_not_found exception
|
||||
* is thrown.
|
||||
*
|
||||
* \return std::list<ipaddress_type> Contanining the DNS servers
|
||||
* provided.
|
||||
*/
|
||||
std::vector<ipaddress_type> domain_name_servers() const;
|
||||
|
||||
/**
|
||||
* \brief Searchs for a broadcast option.
|
||||
*
|
||||
* If the option is not found, an option_not_found exception
|
||||
* is thrown.
|
||||
*
|
||||
* \return ipaddress_type Containing the broadcast address.
|
||||
*/
|
||||
ipaddress_type broadcast() const;
|
||||
|
||||
/**
|
||||
* \brief Searchs for a requested option.
|
||||
*
|
||||
* If the option is not found, an option_not_found exception
|
||||
* is thrown.
|
||||
*
|
||||
* \return ipaddress_type Containing the requested IP address.
|
||||
*/
|
||||
ipaddress_type requested_ip() const;
|
||||
|
||||
/**
|
||||
* \brief Searchs for a domain name option.
|
||||
*
|
||||
* If the option is not found, an option_not_found exception
|
||||
* is thrown.
|
||||
*
|
||||
* \return std::string Containing the domain name.
|
||||
*/
|
||||
std::string domain_name() const;
|
||||
|
||||
/**
|
||||
* \brief Searchs for a hostname option.
|
||||
*
|
||||
* If the option is not found, an option_not_found exception
|
||||
* is thrown.
|
||||
*
|
||||
* \return std::string Containing the hostname.
|
||||
*/
|
||||
std::string hostname() const;
|
||||
|
||||
/**
|
||||
* \brief Getter for the options list.
|
||||
* \return The option list.
|
||||
*/
|
||||
const options_type options() const { return _options; }
|
||||
|
||||
/**
|
||||
* \brief Getter for the PDU's type.
|
||||
* \sa PDU::pdu_type
|
||||
*/
|
||||
PDUType pdu_type() const { return pdu_flag; }
|
||||
|
||||
/**
|
||||
* \brief Getter for the header size.
|
||||
* \return Returns the BOOTP header size.
|
||||
* \sa PDU::header_size
|
||||
*/
|
||||
uint32_t header_size() const;
|
||||
|
||||
/**
|
||||
* \sa PDU::clone
|
||||
*/
|
||||
DHCP *clone() const {
|
||||
return new DHCP(*this);
|
||||
}
|
||||
private:
|
||||
static const uint32_t MAX_DHCP_SIZE;
|
||||
|
||||
void write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *parent);
|
||||
|
||||
template<class T>
|
||||
T search_and_convert(OptionTypes opt) const {
|
||||
const option *option = search_option(opt);
|
||||
if(!option)
|
||||
throw option_not_found();
|
||||
return option->to<T>();
|
||||
}
|
||||
|
||||
void internal_add_option(const option &opt);
|
||||
serialization_type serialize_list(const std::vector<ipaddress_type> &ip_list);
|
||||
|
||||
options_type _options;
|
||||
uint32_t _size;
|
||||
};
|
||||
}
|
||||
|
||||
#endif // TINS_DHCP_H
|
||||
929
include/tins/dhcpv6.h
Normal file
929
include/tins/dhcpv6.h
Normal file
@@ -0,0 +1,929 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Matias Fontanini
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following disclaimer
|
||||
* in the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef TINS_DHCPV6_H
|
||||
#define TINS_DHCPV6_H
|
||||
|
||||
#include <cstring>
|
||||
#include <list>
|
||||
#include "pdu.h"
|
||||
#include "endianness.h"
|
||||
#include "small_uint.h"
|
||||
#include "ipv6_address.h"
|
||||
#include "pdu_option.h"
|
||||
|
||||
namespace Tins {
|
||||
/**
|
||||
* \class DHCPv6
|
||||
* \brief Represents a DHCPv6 PDU.
|
||||
*/
|
||||
class DHCPv6 : public PDU {
|
||||
public:
|
||||
/**
|
||||
* Represents a DHCPv6 option.
|
||||
*/
|
||||
typedef PDUOption<uint16_t, DHCPv6> option;
|
||||
|
||||
/**
|
||||
* The message types.
|
||||
*/
|
||||
enum MessageType {
|
||||
SOLICIT = 1,
|
||||
ADVERTISE,
|
||||
REQUEST,
|
||||
CONFIRM,
|
||||
RENEW,
|
||||
REBIND,
|
||||
REPLY,
|
||||
RELEASE,
|
||||
DECLINE,
|
||||
RECONFIGURE,
|
||||
INFO_REQUEST,
|
||||
RELAY_FORWARD,
|
||||
RELAY_REPLY,
|
||||
LEASE_QUERY,
|
||||
LEASE_QUERY_REPLY,
|
||||
LEASE_QUERY_DONE,
|
||||
LEASE_QUERY_DATA
|
||||
};
|
||||
|
||||
/**
|
||||
* The DHCPv6 options.
|
||||
*/
|
||||
enum OptionTypes {
|
||||
CLIENTID = 1,
|
||||
SERVERID,
|
||||
IA_NA,
|
||||
IA_TA,
|
||||
IA_ADDR,
|
||||
OPTION_REQUEST,
|
||||
PREFERENCE,
|
||||
ELAPSED_TIME,
|
||||
RELAY_MSG,
|
||||
AUTH = 11,
|
||||
UNICAST,
|
||||
STATUS_CODE,
|
||||
RAPID_COMMIT,
|
||||
USER_CLASS,
|
||||
VENDOR_CLASS,
|
||||
VENDOR_OPTS,
|
||||
INTERFACE_ID,
|
||||
RECONF_MSG,
|
||||
RECONF_ACCEPT,
|
||||
SIP_SERVER_D,
|
||||
SIP_SERVER_A,
|
||||
DNS_SERVERS,
|
||||
DOMAIN_LIST,
|
||||
IA_PD,
|
||||
IAPREFIX,
|
||||
NIS_SERVERS,
|
||||
NISP_SERVERS,
|
||||
NIS_DOMAIN_NAME,
|
||||
NISP_DOMAIN_NAME,
|
||||
SNTP_SERVERS,
|
||||
INFORMATION_REFRESH_TIME,
|
||||
BCMCS_SERVER_D,
|
||||
BCMCS_SERVER_A,
|
||||
GEOCONF_CIVIC = 36,
|
||||
REMOTE_ID,
|
||||
SUBSCRIBER_ID,
|
||||
CLIENT_FQDN,
|
||||
PANA_AGENT,
|
||||
NEW_POSIX_TIMEZONE,
|
||||
NEW_TZDB_TIMEZONE,
|
||||
ERO,
|
||||
LQ_QUERY,
|
||||
CLIENT_DATA,
|
||||
CLT_TIME,
|
||||
LQ_RELAY_DATA,
|
||||
LQ_CLIENT_LINK,
|
||||
MIP6_HNIDF,
|
||||
MIP6_VDINF,
|
||||
V6_LOST,
|
||||
CAPWAP_AC_V6,
|
||||
RELAY_ID,
|
||||
NTP_SERVER,
|
||||
V6_ACCESS_DOMAIN,
|
||||
SIP_UA_CS_LIST,
|
||||
BOOTFILE_URL,
|
||||
BOOTFILE_PARAM,
|
||||
CLIENT_ARCH_TYPE,
|
||||
NII,
|
||||
GEOLOCATION,
|
||||
AFTR_NAME,
|
||||
ERP_LOCAL_DOMAIN_NAME,
|
||||
RSOO,
|
||||
PD_EXCLUDE,
|
||||
VSS,
|
||||
MIP6_IDINF,
|
||||
MIP6_UDINF,
|
||||
MIP6_HNP,
|
||||
MIP6_HAA,
|
||||
MIP6_HAF,
|
||||
RDNSS_SELECTION,
|
||||
KRB_PRINCIPAL_NAME,
|
||||
KRB_REALM_NAME,
|
||||
KRB_DEFAULT_REALM_NAME,
|
||||
KRB_KDC
|
||||
};
|
||||
|
||||
/**
|
||||
* The type used to store the DHCPv6 options.
|
||||
*/
|
||||
typedef std::list<option> options_type;
|
||||
|
||||
/**
|
||||
* The type used to store IP addresses.
|
||||
*/
|
||||
typedef IPv6Address ipaddress_type;
|
||||
|
||||
/**
|
||||
* This PDU's flag.
|
||||
*/
|
||||
static const PDU::PDUType pdu_flag = PDU::DHCPv6;
|
||||
|
||||
/**
|
||||
* The type used to store the Identity Association for Non-Temporary
|
||||
* Addresses option.
|
||||
*/
|
||||
struct ia_na_type {
|
||||
typedef std::vector<uint8_t> options_type;
|
||||
|
||||
uint32_t id, t1, t2;
|
||||
options_type options;
|
||||
|
||||
ia_na_type(uint32_t id = 0, uint32_t t1 = 0, uint32_t t2 = 0,
|
||||
const options_type& options = options_type())
|
||||
: id(id), t1(t1), t2(t2), options(options) {}
|
||||
|
||||
static ia_na_type from_option(const option &opt);
|
||||
};
|
||||
|
||||
/**
|
||||
* The type used to store the Identity Association for Temporary
|
||||
* Addresses option.
|
||||
*/
|
||||
struct ia_ta_type {
|
||||
typedef std::vector<uint8_t> options_type;
|
||||
|
||||
uint32_t id;
|
||||
options_type options;
|
||||
|
||||
ia_ta_type(uint32_t id = 0,
|
||||
const options_type& options = options_type())
|
||||
: id(id), options(options) {}
|
||||
|
||||
static ia_ta_type from_option(const option &opt);
|
||||
};
|
||||
|
||||
/**
|
||||
* The type used to store the Identity Association Address option.
|
||||
*/
|
||||
struct ia_address_type {
|
||||
typedef std::vector<uint8_t> options_type;
|
||||
|
||||
ipaddress_type address;
|
||||
uint32_t preferred_lifetime, valid_lifetime;
|
||||
options_type options;
|
||||
|
||||
ia_address_type(ipaddress_type address = ipaddress_type(),
|
||||
uint32_t preferred_lifetime = 0, uint32_t valid_lifetime = 0,
|
||||
const options_type& options = options_type())
|
||||
: address(address), preferred_lifetime(preferred_lifetime),
|
||||
valid_lifetime(valid_lifetime), options(options) {}
|
||||
|
||||
static ia_address_type from_option(const option &opt);
|
||||
};
|
||||
|
||||
/**
|
||||
* The type used to store the Authentication option.
|
||||
*/
|
||||
struct authentication_type {
|
||||
typedef std::vector<uint8_t> auth_info_type;
|
||||
|
||||
uint8_t protocol, algorithm, rdm;
|
||||
uint64_t replay_detection;
|
||||
auth_info_type auth_info;
|
||||
|
||||
authentication_type(uint8_t protocol = 0, uint8_t algorithm = 0,
|
||||
uint8_t rdm = 0, uint64_t replay_detection = 0,
|
||||
const auth_info_type &auth_info = auth_info_type())
|
||||
: protocol(protocol), algorithm(algorithm), rdm(rdm),
|
||||
replay_detection(replay_detection), auth_info(auth_info) {}
|
||||
|
||||
static authentication_type from_option(const option &opt);
|
||||
};
|
||||
|
||||
/**
|
||||
* The type used to store the Status Code option.
|
||||
*/
|
||||
struct status_code_type {
|
||||
uint16_t code;
|
||||
std::string message;
|
||||
|
||||
status_code_type(uint16_t code = 0, const std::string &message = "")
|
||||
: code(code), message(message) { }
|
||||
|
||||
static status_code_type from_option(const option &opt);
|
||||
};
|
||||
|
||||
/**
|
||||
* The type used to store the Vendor-specific Information option.
|
||||
*/
|
||||
struct vendor_info_type {
|
||||
typedef std::vector<uint8_t> data_type;
|
||||
|
||||
uint32_t enterprise_number;
|
||||
data_type data;
|
||||
|
||||
vendor_info_type(uint32_t enterprise_number = 0,
|
||||
const data_type &data = data_type())
|
||||
: enterprise_number(enterprise_number), data(data) { }
|
||||
|
||||
static vendor_info_type from_option(const option &opt);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* The type used to store the User Class option's user class data.
|
||||
*/
|
||||
typedef std::vector<uint8_t> class_option_data_type;
|
||||
|
||||
/**
|
||||
* The type used to store the User Class option.
|
||||
*/
|
||||
//typedef std::vector<class_option_data_type> user_class_type;
|
||||
struct user_class_type {
|
||||
typedef std::vector<class_option_data_type> data_type;
|
||||
data_type data;
|
||||
|
||||
user_class_type(const data_type &data = data_type())
|
||||
: data(data)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
static user_class_type from_option(const option &opt);
|
||||
};
|
||||
|
||||
/**
|
||||
* The type used to store the Vendor Class option.
|
||||
*/
|
||||
struct vendor_class_type {
|
||||
typedef std::vector<class_option_data_type> class_data_type;
|
||||
|
||||
uint32_t enterprise_number;
|
||||
class_data_type vendor_class_data;
|
||||
|
||||
vendor_class_type(uint32_t enterprise_number = 0,
|
||||
const class_data_type &vendor_class_data = class_data_type())
|
||||
: enterprise_number(enterprise_number),
|
||||
vendor_class_data(vendor_class_data) { }
|
||||
|
||||
static vendor_class_type from_option(const option &opt);
|
||||
};
|
||||
|
||||
/**
|
||||
* The type used to represent DUIDs Based on Link-layer Address Plus
|
||||
* Time.
|
||||
*/
|
||||
struct duid_llt {
|
||||
static const uint16_t duid_id = 1;
|
||||
typedef std::vector<uint8_t> lladdress_type;
|
||||
|
||||
uint16_t hw_type;
|
||||
uint32_t time;
|
||||
lladdress_type lladdress;
|
||||
|
||||
duid_llt(uint16_t hw_type = 0, uint32_t time = 0,
|
||||
const lladdress_type &lladdress = lladdress_type())
|
||||
: hw_type(hw_type), time(time), lladdress(lladdress) {}
|
||||
|
||||
PDU::serialization_type serialize() const;
|
||||
|
||||
static duid_llt from_bytes(const uint8_t *buffer, uint32_t total_sz);
|
||||
};
|
||||
|
||||
/**
|
||||
* The type used to represent DUIDs Based on Enterprise Number
|
||||
*/
|
||||
struct duid_en {
|
||||
static const uint16_t duid_id = 2;
|
||||
typedef std::vector<uint8_t> identifier_type;
|
||||
|
||||
uint32_t enterprise_number;
|
||||
identifier_type identifier;
|
||||
|
||||
duid_en(uint32_t enterprise_number = 0,
|
||||
const identifier_type &identifier = identifier_type())
|
||||
: enterprise_number(enterprise_number), identifier(identifier) {}
|
||||
|
||||
PDU::serialization_type serialize() const;
|
||||
|
||||
static duid_en from_bytes(const uint8_t *buffer, uint32_t total_sz);
|
||||
};
|
||||
|
||||
/**
|
||||
* The type used to represent DUIDs Based on Link-layer Address.
|
||||
*/
|
||||
struct duid_ll {
|
||||
static const uint16_t duid_id = 3;
|
||||
typedef std::vector<uint8_t> lladdress_type;
|
||||
|
||||
uint16_t hw_type;
|
||||
lladdress_type lladdress;
|
||||
|
||||
duid_ll(uint16_t hw_type = 0,
|
||||
const lladdress_type &lladdress = lladdress_type())
|
||||
: hw_type(hw_type), lladdress(lladdress) {}
|
||||
|
||||
PDU::serialization_type serialize() const;
|
||||
|
||||
static duid_ll from_bytes(const uint8_t *buffer, uint32_t total_sz);
|
||||
};
|
||||
|
||||
/**
|
||||
* Type type used to represent DUIDs. This will be stored as the
|
||||
* value for the Client/Server Identifier options.
|
||||
*/
|
||||
struct duid_type {
|
||||
typedef PDU::serialization_type data_type;
|
||||
|
||||
uint16_t id;
|
||||
data_type data;
|
||||
|
||||
duid_type(uint16_t id = 0, const data_type &data = data_type())
|
||||
: id(id), data(data) {}
|
||||
|
||||
duid_type(const duid_llt &identifier)
|
||||
: id(duid_llt::duid_id), data(identifier.serialize()) {}
|
||||
|
||||
duid_type(const duid_en &identifier)
|
||||
: id(duid_en::duid_id), data(identifier.serialize()) {}
|
||||
|
||||
duid_type(const duid_ll &identifier)
|
||||
: id(duid_en::duid_id), data(identifier.serialize()) {}
|
||||
|
||||
static duid_type from_option(const option &opt);
|
||||
};
|
||||
|
||||
/**
|
||||
* The type used to store the Option Request option.
|
||||
*/
|
||||
typedef std::vector<uint16_t> option_request_type;
|
||||
|
||||
/**
|
||||
* The type used to store the Relay Message option.
|
||||
*/
|
||||
typedef std::vector<uint8_t> relay_msg_type;
|
||||
|
||||
/**
|
||||
* The type used to store the Interface-ID option.
|
||||
*/
|
||||
typedef std::vector<uint8_t> interface_id_type;
|
||||
|
||||
/**
|
||||
* Default constructor.
|
||||
*/
|
||||
DHCPv6();
|
||||
|
||||
/**
|
||||
* \brief Constructs a DHCPv6 object from a buffer.
|
||||
*
|
||||
* If there is not enough size for the DHCPv6 header, or any
|
||||
* of the TLV options contains an invalid size field, 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.
|
||||
*/
|
||||
DHCPv6(const uint8_t *buffer, uint32_t total_sz);
|
||||
|
||||
// Getters
|
||||
|
||||
/**
|
||||
* \brief Getter for the message type field.
|
||||
*
|
||||
* \return The stored message type field.
|
||||
*/
|
||||
MessageType msg_type() const {
|
||||
return static_cast<MessageType>(header_data[0]);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the hop count field.
|
||||
*
|
||||
* \return The stored hop count field.
|
||||
*/
|
||||
uint8_t hop_count() const { return header_data[1]; }
|
||||
|
||||
/**
|
||||
* \brief Getter for the transaction id field.
|
||||
*
|
||||
* \return The stored transaction id field.
|
||||
*/
|
||||
small_uint<24> transaction_id() const {
|
||||
return (header_data[1] << 16) | (header_data[2] << 8) | header_data[3];
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the peer address field.
|
||||
*
|
||||
* \return The stored peer address field.
|
||||
*/
|
||||
const ipaddress_type &peer_address() const { return peer_addr; }
|
||||
|
||||
/**
|
||||
* \brief Getter for the link address field.
|
||||
*
|
||||
* \return The stored link address field.
|
||||
*/
|
||||
const ipaddress_type &link_address() const { return link_addr; }
|
||||
|
||||
/**
|
||||
* \brief Getter for the DHCPv6 options.
|
||||
*
|
||||
* \return The stored options.
|
||||
*/
|
||||
const options_type &options() const { return options_; }
|
||||
|
||||
// Setters
|
||||
/**
|
||||
* \brief Setter for the message type field.
|
||||
*
|
||||
* \param type The new message type.
|
||||
*/
|
||||
void msg_type(MessageType type);
|
||||
|
||||
/**
|
||||
* \brief Setter for the hop count field.
|
||||
*
|
||||
* \param count The new hop count.
|
||||
*/
|
||||
void hop_count(uint8_t count);
|
||||
|
||||
/**
|
||||
* \brief Setter for the transaction id field.
|
||||
*
|
||||
* \param id The new transaction id.
|
||||
*/
|
||||
void transaction_id(small_uint<24> id);
|
||||
|
||||
/**
|
||||
* \brief Setter for the peer address field.
|
||||
*
|
||||
* \param count The new peer address.
|
||||
*/
|
||||
void peer_address(const ipaddress_type &addr);
|
||||
|
||||
/**
|
||||
* \brief Setter for the link address field.
|
||||
*
|
||||
* \param count The new link address.
|
||||
*/
|
||||
void link_address(const ipaddress_type &addr);
|
||||
|
||||
// Option getters
|
||||
|
||||
/**
|
||||
* \brief Getter for the Identity Association for Non-Temporary
|
||||
* Addresses option.
|
||||
*
|
||||
* This method will throw an option_not_found exception if the
|
||||
* option is not found.
|
||||
*/
|
||||
ia_na_type ia_na() const;
|
||||
|
||||
/**
|
||||
* \brief Getter for the Identity Association for Temporary
|
||||
* Addresses option.
|
||||
*
|
||||
* This method will throw an option_not_found exception if the
|
||||
* option is not found.
|
||||
*/
|
||||
ia_ta_type ia_ta() const;
|
||||
|
||||
/**
|
||||
* \brief Getter for the Identity Association Address option.
|
||||
*
|
||||
* This method will throw an option_not_found exception if the
|
||||
* option is not found.
|
||||
*/
|
||||
ia_address_type ia_address() const;
|
||||
|
||||
/**
|
||||
* \brief Getter for the Option Request option.
|
||||
*
|
||||
* This method will throw an option_not_found exception if the
|
||||
* option is not found.
|
||||
*/
|
||||
option_request_type option_request() const;
|
||||
|
||||
/**
|
||||
* \brief Getter for the Preference option.
|
||||
*
|
||||
* This method will throw an option_not_found exception if the
|
||||
* option is not found.
|
||||
*/
|
||||
uint8_t preference() const;
|
||||
|
||||
/**
|
||||
* \brief Getter for the Elapsed Time option.
|
||||
*
|
||||
* This method will throw an option_not_found exception if the
|
||||
* option is not found.
|
||||
*/
|
||||
uint16_t elapsed_time() const;
|
||||
|
||||
/**
|
||||
* \brief Getter for the Relay Message option.
|
||||
*
|
||||
* This method will throw an option_not_found exception if the
|
||||
* option is not found.
|
||||
*/
|
||||
relay_msg_type relay_message() const;
|
||||
|
||||
/**
|
||||
* \brief Getter for the Authentication option.
|
||||
*
|
||||
* This method will throw an option_not_found exception if the
|
||||
* option is not found.
|
||||
*/
|
||||
authentication_type authentication() const;
|
||||
|
||||
/**
|
||||
* \brief Getter for the Server Unicast option.
|
||||
*
|
||||
* This method will throw an option_not_found exception if the
|
||||
* option is not found.
|
||||
*/
|
||||
ipaddress_type server_unicast() const;
|
||||
|
||||
/**
|
||||
* \brief Getter for the Server Unicast option.
|
||||
*
|
||||
* This method will throw an option_not_found exception if the
|
||||
* option is not found.
|
||||
*/
|
||||
status_code_type status_code() const;
|
||||
|
||||
/**
|
||||
* \brief Getter for the Rapid Commit option.
|
||||
*
|
||||
* This method will throw an option_not_found exception if the
|
||||
* option is not found.
|
||||
*/
|
||||
bool has_rapid_commit() const;
|
||||
|
||||
/**
|
||||
* \brief Getter for the User Class option.
|
||||
*
|
||||
* This method will throw an option_not_found exception if the
|
||||
* option is not found.
|
||||
*/
|
||||
user_class_type user_class() const;
|
||||
|
||||
/**
|
||||
* \brief Getter for the Vendor Class option.
|
||||
*
|
||||
* This method will throw an option_not_found exception if the
|
||||
* option is not found.
|
||||
*/
|
||||
vendor_class_type vendor_class() const;
|
||||
|
||||
/**
|
||||
* \brief Getter for the Vendor-specific Information option.
|
||||
*
|
||||
* This method will throw an option_not_found exception if the
|
||||
* option is not found.
|
||||
*/
|
||||
vendor_info_type vendor_info() const;
|
||||
|
||||
/**
|
||||
* \brief Getter for the Interface ID option.
|
||||
*
|
||||
* This method will throw an option_not_found exception if the
|
||||
* option is not found.
|
||||
*/
|
||||
interface_id_type interface_id() const;
|
||||
|
||||
/**
|
||||
* \brief Getter for the Reconfigure Message option.
|
||||
*
|
||||
* This method will throw an option_not_found exception if the
|
||||
* option is not found.
|
||||
*/
|
||||
uint8_t reconfigure_msg() const;
|
||||
|
||||
/**
|
||||
* \brief Getter for the Reconfigure Accept option.
|
||||
*
|
||||
* This method will throw an option_not_found exception if the
|
||||
* option is not found.
|
||||
*/
|
||||
bool has_reconfigure_accept() const;
|
||||
|
||||
/**
|
||||
* \brief Getter for the Client Identifier option.
|
||||
*
|
||||
* This method will throw an option_not_found exception if the
|
||||
* option is not found.
|
||||
*/
|
||||
duid_type client_id() const;
|
||||
|
||||
/**
|
||||
* \brief Getter for the Server Identifier option.
|
||||
*
|
||||
* This method will throw an option_not_found exception if the
|
||||
* option is not found.
|
||||
*/
|
||||
duid_type server_id() const;
|
||||
|
||||
// Option setters
|
||||
|
||||
/**
|
||||
* \brief Setter for the Identity Association for Non-Temporary
|
||||
* Addresses option.
|
||||
*
|
||||
* \param value The new IA_NA option data.
|
||||
*/
|
||||
void ia_na(const ia_na_type &value);
|
||||
|
||||
/**
|
||||
* \brief Setter for the Identity Association for Temporary
|
||||
* Addresses option.
|
||||
*
|
||||
* \param value The new IA_TA option data.
|
||||
*/
|
||||
void ia_ta(const ia_ta_type &value);
|
||||
|
||||
/**
|
||||
* \brief Setter for the Identity Association Address option.
|
||||
*
|
||||
* \param value The new IA Address option data.
|
||||
*/
|
||||
void ia_address(const ia_address_type &value);
|
||||
|
||||
/**
|
||||
* \brief Setter for the Identity Association Address option.
|
||||
*
|
||||
* \param value The new Option Request option data.
|
||||
*/
|
||||
void option_request(const option_request_type &value);
|
||||
|
||||
/**
|
||||
* \brief Setter for the Preference option.
|
||||
*
|
||||
* \param value The new Preference option data.
|
||||
*/
|
||||
void preference(uint8_t value);
|
||||
|
||||
/**
|
||||
* \brief Setter for the Elapsed Time option.
|
||||
*
|
||||
* \param value The new Elapsed Time option data.
|
||||
*/
|
||||
void elapsed_time(uint16_t value);
|
||||
|
||||
/**
|
||||
* \brief Setter for the Relay Message option.
|
||||
*
|
||||
* \param value The new Relay Message option data.
|
||||
*/
|
||||
void relay_message(const relay_msg_type &value);
|
||||
|
||||
/**
|
||||
* \brief Setter for the Authentication option.
|
||||
*
|
||||
* \param value The new Authentication option data.
|
||||
*/
|
||||
void authentication(const authentication_type &value);
|
||||
|
||||
/**
|
||||
* \brief Setter for the Server Unicast option.
|
||||
*
|
||||
* \param value The new Server Unicast option data.
|
||||
*/
|
||||
void server_unicast(const ipaddress_type &value);
|
||||
|
||||
/**
|
||||
* \brief Setter for the Status Code option.
|
||||
*
|
||||
* \param value The new Status Code option data.
|
||||
*/
|
||||
void status_code(const status_code_type &value);
|
||||
|
||||
/**
|
||||
* \brief Adds a Rapid Commit option.
|
||||
*/
|
||||
void rapid_commit();
|
||||
|
||||
/**
|
||||
* \brief Setter for the User Class option.
|
||||
*
|
||||
* \param value The new User Class option data.
|
||||
*/
|
||||
void user_class(const user_class_type &value);
|
||||
|
||||
/**
|
||||
* \brief Setter for the Vendor Class option.
|
||||
*
|
||||
* \param value The new Vendor Class option data.
|
||||
*/
|
||||
void vendor_class(const vendor_class_type &value);
|
||||
|
||||
/**
|
||||
* \brief Setter for the Vendor-specific Information option.
|
||||
*
|
||||
* \param value The new Vendor-specific Information option data.
|
||||
*/
|
||||
void vendor_info(const vendor_info_type &value);
|
||||
|
||||
/**
|
||||
* \brief Setter for the Interface ID option.
|
||||
*
|
||||
* \param value The new Interface ID option data.
|
||||
*/
|
||||
void interface_id(const interface_id_type &value);
|
||||
|
||||
/**
|
||||
* \brief Setter for the Reconfigure Message option.
|
||||
*
|
||||
* \param value The new Reconfigure Message option data.
|
||||
*/
|
||||
void reconfigure_msg(uint8_t value);
|
||||
|
||||
/**
|
||||
* \brief Adds a Reconfigure Accept option.
|
||||
*/
|
||||
void reconfigure_accept();
|
||||
|
||||
/**
|
||||
* \brief Setter for the Client Identifier option.
|
||||
*
|
||||
* \param value The new Client Identifier option data.
|
||||
*/
|
||||
void client_id(const duid_type &value);
|
||||
|
||||
/**
|
||||
* \brief Setter for the Server Identifier option.
|
||||
*
|
||||
* \param value The new Server Identifier option data.
|
||||
*/
|
||||
void server_id(const duid_type &value);
|
||||
|
||||
// Other stuff
|
||||
|
||||
/**
|
||||
* Indicates whether this is a relay agent/server message
|
||||
*/
|
||||
bool is_relay_message() const;
|
||||
|
||||
/**
|
||||
* \brief Adds a DHCPv6 option.
|
||||
*
|
||||
* The option is added after the last option in the option
|
||||
* fields.
|
||||
*
|
||||
* \param opt The option to be added
|
||||
*/
|
||||
void add_option(const option &opt);
|
||||
|
||||
/**
|
||||
* \brief Searchs for an option that matchs the given flag.
|
||||
*
|
||||
* If the option is not found, a null pointer is returned.
|
||||
* Deleting the returned pointer will result in <b>undefined
|
||||
* behaviour</b>.
|
||||
*
|
||||
* \param id The option identifier to be searched.
|
||||
*/
|
||||
const option *search_option(OptionTypes id) const;
|
||||
|
||||
// PDU stuff
|
||||
|
||||
/**
|
||||
* \brief Returns the header size.
|
||||
*
|
||||
* This metod overrides PDU::header_size. \sa PDU::header_size
|
||||
*/
|
||||
uint32_t header_size() const;
|
||||
|
||||
/**
|
||||
* \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 Getter for the PDU's type.
|
||||
* \sa PDU::pdu_type
|
||||
*/
|
||||
PDUType pdu_type() const { return pdu_flag; }
|
||||
|
||||
/**
|
||||
* \sa PDU::clone
|
||||
*/
|
||||
DHCPv6 *clone() const {
|
||||
return new DHCPv6(*this);
|
||||
}
|
||||
private:
|
||||
void write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *);
|
||||
uint8_t* write_option(const option &option, uint8_t* buffer) const;
|
||||
|
||||
template<template <typename> class Functor>
|
||||
const option *safe_search_option(OptionTypes opt, uint32_t size) const {
|
||||
const option *option = search_option(opt);
|
||||
if(!option || Functor<uint32_t>()(option->data_size(), size))
|
||||
throw option_not_found();
|
||||
return option;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T search_and_convert(OptionTypes opt) const {
|
||||
const option *option = search_option(opt);
|
||||
if(!option)
|
||||
throw option_not_found();
|
||||
return option->to<T>();
|
||||
}
|
||||
|
||||
uint8_t header_data[4];
|
||||
uint32_t options_size;
|
||||
ipaddress_type link_addr, peer_addr;
|
||||
options_type options_;
|
||||
};
|
||||
|
||||
namespace Internals {
|
||||
template<typename InputIterator>
|
||||
void class_option_data2option(InputIterator start, InputIterator end,
|
||||
std::vector<uint8_t>& buffer, size_t start_index = 0)
|
||||
{
|
||||
size_t index = start_index;
|
||||
uint16_t uint16_t_buffer;
|
||||
while(start != end) {
|
||||
buffer.resize(buffer.size() + sizeof(uint16_t) + start->size());
|
||||
uint16_t_buffer = Endian::host_to_be<uint16_t>(start->size());
|
||||
std::memcpy(&buffer[index], &uint16_t_buffer, sizeof(uint16_t));
|
||||
index += sizeof(uint16_t);
|
||||
std::copy(start->begin(), start->end(), buffer.begin() + index);
|
||||
index += start->size();
|
||||
|
||||
start++;
|
||||
}
|
||||
}
|
||||
|
||||
template<typename OutputType>
|
||||
OutputType option2class_option_data(const uint8_t *ptr, uint32_t total_sz)
|
||||
{
|
||||
typedef typename OutputType::value_type value_type;
|
||||
OutputType output;
|
||||
size_t index = 0;
|
||||
while(index + 2 < total_sz) {
|
||||
uint16_t size;
|
||||
std::memcpy(&size, ptr + index, sizeof(uint16_t));
|
||||
size = Endian::be_to_host(size);
|
||||
index += sizeof(uint16_t);
|
||||
if(index + size > total_sz)
|
||||
throw option_not_found();
|
||||
output.push_back(
|
||||
value_type(ptr + index, ptr + index + size)
|
||||
);
|
||||
index += size;
|
||||
}
|
||||
if(index != total_sz)
|
||||
throw malformed_option();
|
||||
return output;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif // TINS_DHCPV6_H
|
||||
693
include/tins/dns.h
Normal file
693
include/tins/dns.h
Normal file
@@ -0,0 +1,693 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Matias Fontanini
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following disclaimer
|
||||
* in the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef TINS_DNS_H
|
||||
#define TINS_DNS_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <list>
|
||||
#include <vector>
|
||||
#include <cstring>
|
||||
#include <string>
|
||||
#include <map>
|
||||
#include "macros.h"
|
||||
#include "pdu.h"
|
||||
#include "endianness.h"
|
||||
|
||||
namespace Tins {
|
||||
class IPv4Address;
|
||||
class IPv6Address;
|
||||
|
||||
/**
|
||||
* \class DNS
|
||||
* \brief Represents a DNS PDU.
|
||||
*
|
||||
* This class represents the DNS PDU, and allows easy access
|
||||
* to queries and answer records.
|
||||
*
|
||||
* The DNS PDU is not parsed automatically while sniffing, so you will
|
||||
* have to parse it manually from an UDP packet's payload, for example:
|
||||
*
|
||||
* \code
|
||||
* // Assume we get an udp packet from somewhere.
|
||||
* UDP udp = get_udp_packet();
|
||||
*
|
||||
* // Now:
|
||||
* // 1 - Get the RawPDU layer (contains the payload).
|
||||
* // 2 - Construct a DNS object over its contents.
|
||||
* DNS dns = udp.rfind_pdu<RawPDU>().to<DNS>();
|
||||
*
|
||||
* // Now use the DNS object!
|
||||
* for(const auto& query : dns.queries()) {
|
||||
* // Process a query
|
||||
* }
|
||||
* \endcode
|
||||
*/
|
||||
class DNS : public PDU {
|
||||
public:
|
||||
/**
|
||||
* \brief This PDU's flag.
|
||||
*/
|
||||
static const PDU::PDUType pdu_flag = PDU::DNS;
|
||||
|
||||
/**
|
||||
* The DNS type.
|
||||
*/
|
||||
enum QRType {
|
||||
QUERY = 0,
|
||||
RESPONSE = 1
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Query types enum.
|
||||
*/
|
||||
enum QueryType {
|
||||
A = 1,
|
||||
NS,
|
||||
MD,
|
||||
MF,
|
||||
CNAME,
|
||||
SOA,
|
||||
MB,
|
||||
MG,
|
||||
MR,
|
||||
NULL_R,
|
||||
WKS,
|
||||
PTR,
|
||||
HINFO,
|
||||
MINFO,
|
||||
MX,
|
||||
TXT,
|
||||
RP,
|
||||
AFSDB,
|
||||
X25,
|
||||
ISDN,
|
||||
RT,
|
||||
NSAP,
|
||||
NSAP_PTR,
|
||||
SIG,
|
||||
KEY,
|
||||
PX,
|
||||
GPOS,
|
||||
AAAA,
|
||||
LOC,
|
||||
NXT,
|
||||
EID,
|
||||
NIMLOC,
|
||||
SRV,
|
||||
ATMA,
|
||||
NAPTR,
|
||||
KX,
|
||||
CERT,
|
||||
A6,
|
||||
DNAM,
|
||||
SINK,
|
||||
OPT,
|
||||
APL,
|
||||
DS,
|
||||
SSHFP,
|
||||
IPSECKEY,
|
||||
RRSIG,
|
||||
NSEC,
|
||||
DNSKEY,
|
||||
DHCID,
|
||||
NSEC3,
|
||||
NSEC3PARAM
|
||||
};
|
||||
|
||||
enum QueryClass {
|
||||
IN = 1,
|
||||
CH = 3,
|
||||
HS = 4,
|
||||
ANY = 255
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Struct that represent DNS queries.
|
||||
*/
|
||||
class Query {
|
||||
public:
|
||||
/**
|
||||
* \brief Constructs a DNS query.
|
||||
*
|
||||
* \param nm The name of the domain being resolved.
|
||||
* \param tp The query type.
|
||||
* \param cl The query class.
|
||||
*/
|
||||
Query(const std::string &nm, QueryType tp, QueryClass cl)
|
||||
: name_(nm), type_(tp), qclass_(cl) {}
|
||||
|
||||
/**
|
||||
* \brief Default constructs this Query.
|
||||
*/
|
||||
Query() : type_(), qclass_() {}
|
||||
|
||||
/**
|
||||
* \brief Setter for the name field.
|
||||
*
|
||||
* \param nm The name to be set.
|
||||
*/
|
||||
void dname(const std::string &nm) {
|
||||
name_ = nm;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Setter for the query type field.
|
||||
*
|
||||
* \param tp The query type to be set.
|
||||
*/
|
||||
void type(QueryType tp) {
|
||||
type_ = tp;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Setter for the query class field.
|
||||
*
|
||||
* \param cl The query class to be set.
|
||||
*/
|
||||
void query_class(QueryClass cl) {
|
||||
qclass_ = cl;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the name field.
|
||||
*/
|
||||
const std::string &dname() const { return name_; }
|
||||
|
||||
/**
|
||||
* \brief Getter for the query type field.
|
||||
*/
|
||||
QueryType type() const { return type_; }
|
||||
|
||||
/**
|
||||
* \brief Getter for the query class field.
|
||||
*/
|
||||
QueryClass query_class() const { return qclass_; }
|
||||
private:
|
||||
std::string name_;
|
||||
QueryType type_;
|
||||
QueryClass qclass_;
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Struct that represent DNS resource records.
|
||||
*/
|
||||
class Resource {
|
||||
public:
|
||||
/**
|
||||
* Constructs a Resource object.
|
||||
*
|
||||
* \param dname The domain name for which this records
|
||||
* provides an answer.
|
||||
* \param data The resource's payload.
|
||||
* \param type The type of this record.
|
||||
* \param rclass The class of this record.
|
||||
* \param ttl The time-to-live of this record.
|
||||
*/
|
||||
Resource(const std::string &dname, const std::string &data,
|
||||
uint16_t type, uint16_t rclass, uint32_t ttl)
|
||||
: dname_(dname), data_(data), type_(type), qclass_(rclass), ttl_(ttl) {}
|
||||
|
||||
Resource() : type_(), qclass_(), ttl_() {}
|
||||
|
||||
/**
|
||||
* \brief Getter for the domain name field.
|
||||
*
|
||||
* This returns the domain name for which this record
|
||||
* provides an answer.
|
||||
*/
|
||||
const std::string &dname() const { return dname_; }
|
||||
|
||||
/**
|
||||
* Getter for the data field.
|
||||
*/
|
||||
const std::string &data() const { return data_; }
|
||||
|
||||
/**
|
||||
* Getter for the query type field.
|
||||
*/
|
||||
uint16_t type() const { return type_; }
|
||||
|
||||
/**
|
||||
* Getter for the query class field.
|
||||
*/
|
||||
uint16_t query_class() const { return qclass_; }
|
||||
|
||||
/**
|
||||
* Getter for the type field.
|
||||
*/
|
||||
uint32_t ttl() const { return ttl_; }
|
||||
|
||||
/**
|
||||
* Setter for the domain name field.
|
||||
*/
|
||||
void dname(const std::string &data) {
|
||||
dname_ = data;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Setter for the data field.
|
||||
*
|
||||
* The data will be encoded properly by the DNS class before
|
||||
* being added to this packet. That means that if the type is
|
||||
* A or AAAA, it will be properly encoded as an IPv4 or
|
||||
* IPv6 address.
|
||||
*
|
||||
* The same happens for records that contain domain names,
|
||||
* such as NS or CNAME. This data will be encoded using
|
||||
* DNS domain name encoding.
|
||||
*/
|
||||
void data(const std::string &data) {
|
||||
data_ = data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Setter for the type field.
|
||||
*/
|
||||
void type(uint16_t data) {
|
||||
type_ = data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Setter for the class field.
|
||||
*/
|
||||
void query_class(uint16_t data) {
|
||||
qclass_ = data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Setter for the time-to-live field.
|
||||
*/
|
||||
void ttl(uint16_t data) {
|
||||
ttl_ = data;
|
||||
}
|
||||
private:
|
||||
std::string dname_, data_;
|
||||
uint16_t type_, qclass_;
|
||||
uint32_t ttl_;
|
||||
};
|
||||
|
||||
typedef std::list<Query> queries_type;
|
||||
typedef std::list<Resource> resources_type;
|
||||
typedef IPv4Address address_type;
|
||||
typedef IPv6Address address_v6_type;
|
||||
|
||||
/**
|
||||
* \brief Default constructor.
|
||||
*
|
||||
* This constructor initializes every field to 0.
|
||||
*/
|
||||
DNS();
|
||||
|
||||
/**
|
||||
* \brief Constructs a DNS object from a buffer.
|
||||
*
|
||||
* If there's not enough size for the DNS header, or any of the
|
||||
* records are malformed, a malformed_packet is be thrown.
|
||||
*
|
||||
* \param buffer The buffer from which this PDU will be
|
||||
* constructed.
|
||||
* \param total_sz The total size of the buffer.
|
||||
*/
|
||||
DNS(const uint8_t *buffer, uint32_t total_sz);
|
||||
|
||||
// Getters
|
||||
|
||||
/**
|
||||
* \brief Setter for the id field.
|
||||
*
|
||||
* \return uint16_t containing the value of the id field.
|
||||
*/
|
||||
uint16_t id() const { return Endian::be_to_host(dns.id); }
|
||||
|
||||
/**
|
||||
* \brief Setter for the query response field.
|
||||
*
|
||||
* \return QRType containing the value of the query response
|
||||
* field.
|
||||
*/
|
||||
QRType type() const { return static_cast<QRType>(dns.qr); }
|
||||
|
||||
/**
|
||||
* \brief Setter for the opcode field.
|
||||
*
|
||||
* \return uint8_t containing the value of the opcode field.
|
||||
*/
|
||||
uint8_t opcode() const { return dns.opcode; }
|
||||
|
||||
/**
|
||||
* \brief Setter for the authoritative answer field.
|
||||
*
|
||||
* \return uint8_t containing the value of the authoritative
|
||||
* answer field.
|
||||
*/
|
||||
uint8_t authoritative_answer() const { return dns.aa; }
|
||||
|
||||
/**
|
||||
* \brief Setter for the truncated field.
|
||||
*
|
||||
* \return uint8_t containing the value of the truncated field.
|
||||
*/
|
||||
uint8_t truncated() const { return dns.tc; }
|
||||
|
||||
/**
|
||||
* \brief Setter for the recursion desired field.
|
||||
*
|
||||
* \return uint8_t containing the value of the recursion
|
||||
* desired field.
|
||||
*/
|
||||
uint8_t recursion_desired() const { return dns.rd; }
|
||||
|
||||
/**
|
||||
* \brief Setter for the recursion available field.
|
||||
*
|
||||
* \return uint8_t containing the value of the recursion
|
||||
* available field.
|
||||
*/
|
||||
uint8_t recursion_available() const { return dns.ra; }
|
||||
|
||||
/**
|
||||
* \brief Setter for the z desired field.
|
||||
*
|
||||
* \return uint8_t containing the value of the z field.
|
||||
*/
|
||||
uint8_t z() const { return dns.z; }
|
||||
|
||||
/**
|
||||
* \brief Setter for the authenticated data field.
|
||||
*
|
||||
* \return uint8_t containing the value of the authenticated
|
||||
* data field.
|
||||
*/
|
||||
uint8_t authenticated_data() const { return dns.ad; }
|
||||
|
||||
/**
|
||||
* \brief Setter for the checking disabled field.
|
||||
*
|
||||
* \return uint8_t containing the value of the checking
|
||||
* disabled field.
|
||||
*/
|
||||
uint8_t checking_disabled() const { return dns.cd; }
|
||||
|
||||
/**
|
||||
* \brief Setter for the rcode field.
|
||||
*
|
||||
* \return uint8_t containing the value of the rcode field.
|
||||
*/
|
||||
uint8_t rcode() const { return dns.rcode; }
|
||||
|
||||
/**
|
||||
* \brief Setter for the questions field.
|
||||
*
|
||||
* \return uint16_t containing the value of the questions field.
|
||||
*/
|
||||
uint16_t questions_count() const { return Endian::be_to_host(dns.questions); }
|
||||
|
||||
/**
|
||||
* \brief Setter for the answers field.
|
||||
*
|
||||
* \return uint16_t containing the value of the answers field.
|
||||
*/
|
||||
uint16_t answers_count() const { return Endian::be_to_host(dns.answers); }
|
||||
|
||||
/**
|
||||
* \brief Setter for the authority field.
|
||||
*
|
||||
* \return uint16_t containing the value of the authority field.
|
||||
*/
|
||||
uint16_t authority_count() const { return Endian::be_to_host(dns.authority); }
|
||||
|
||||
/**
|
||||
* \brief Setter for the additional field.
|
||||
*
|
||||
* \return uint16_t containing the value of the additional field.
|
||||
*/
|
||||
uint16_t additional_count() const { return Endian::be_to_host(dns.additional); }
|
||||
|
||||
/**
|
||||
* \brief Getter for the PDU's type.
|
||||
*
|
||||
* \return Returns the PDUType corresponding to the PDU.
|
||||
*/
|
||||
PDUType pdu_type() const { return PDU::DNS; }
|
||||
|
||||
/**
|
||||
* \brief The header's size
|
||||
*/
|
||||
uint32_t header_size() const;
|
||||
|
||||
// Setters
|
||||
|
||||
/**
|
||||
* \brief Setter for the id field.
|
||||
*
|
||||
* \param new_id The new id to be set.
|
||||
*/
|
||||
void id(uint16_t new_id);
|
||||
|
||||
/**
|
||||
* \brief Setter for the query response field.
|
||||
*
|
||||
* \param new_qr The new qr to be set.
|
||||
*/
|
||||
void type(QRType new_qr);
|
||||
|
||||
/**
|
||||
* \brief Setter for the opcode field.
|
||||
*
|
||||
* \param new_opcode The new opcode to be set.
|
||||
*/
|
||||
void opcode(uint8_t new_opcode);
|
||||
|
||||
/**
|
||||
* \brief Setter for the authoritative answer field.
|
||||
*
|
||||
* \param new_aa The new authoritative answer field value to
|
||||
* be set.
|
||||
*/
|
||||
void authoritative_answer(uint8_t new_aa);
|
||||
|
||||
/**
|
||||
* \brief Setter for the truncated field.
|
||||
*
|
||||
* \param new_tc The new truncated field value to
|
||||
* be set.
|
||||
*/
|
||||
void truncated(uint8_t new_tc);
|
||||
|
||||
/**
|
||||
* \brief Setter for the recursion desired field.
|
||||
*
|
||||
* \param new_rd The new recursion desired value to
|
||||
* be set.
|
||||
*/
|
||||
void recursion_desired(uint8_t new_rd);
|
||||
|
||||
/**
|
||||
* \brief Setter for the recursion available field.
|
||||
*
|
||||
* \param new_ra The new recursion available value to
|
||||
* be set.
|
||||
*/
|
||||
void recursion_available(uint8_t new_ra);
|
||||
|
||||
/**
|
||||
* \brief Setter for the z(reserved) field.
|
||||
*
|
||||
* \param new_z The new z value to be set.
|
||||
*/
|
||||
void z(uint8_t new_z);
|
||||
|
||||
/**
|
||||
* \brief Setter for the authenticated data field.
|
||||
*
|
||||
* \param new_ad The new authenticated data value to
|
||||
* be set.
|
||||
*/
|
||||
void authenticated_data(uint8_t new_ad);
|
||||
|
||||
/**
|
||||
* \brief Setter for the checking disabled field.
|
||||
*
|
||||
* \param new_z The new checking disabled value to be set.
|
||||
*/
|
||||
void checking_disabled(uint8_t new_cd);
|
||||
|
||||
/**
|
||||
* \brief Setter for the rcode field.
|
||||
*
|
||||
* \param new_rcode The new rcode value to be set.
|
||||
*/
|
||||
void rcode(uint8_t new_rcode);
|
||||
|
||||
// Methods
|
||||
|
||||
/**
|
||||
* \brief Add a query to perform.
|
||||
*
|
||||
* \param query The query to be added.
|
||||
*/
|
||||
void add_query(const Query &query);
|
||||
|
||||
/**
|
||||
* \brief Add an answer resource record.
|
||||
*
|
||||
* \param resource The resource to be added.
|
||||
*/
|
||||
void add_answer(const Resource &resource);
|
||||
|
||||
/**
|
||||
* \brief Add an authority resource record.
|
||||
*
|
||||
* \param resource The resource to be added.
|
||||
*/
|
||||
void add_authority(const Resource &resource);
|
||||
|
||||
/**
|
||||
* \brief Add an additional resource record.
|
||||
*
|
||||
* \param resource The resource to be added.
|
||||
*/
|
||||
void add_additional(const Resource &resource);
|
||||
|
||||
/**
|
||||
* \brief Getter for this PDU's DNS queries.
|
||||
*
|
||||
* \return The query records in this PDU.
|
||||
*/
|
||||
queries_type queries() const;
|
||||
|
||||
/**
|
||||
* \brief Getter for this PDU's DNS answers
|
||||
*
|
||||
* \return The answer records in this PDU.
|
||||
*/
|
||||
resources_type answers() const;
|
||||
|
||||
/**
|
||||
* \brief Getter for this PDU's DNS authority records.
|
||||
*
|
||||
* \return The authority records in this PDU.
|
||||
*/
|
||||
resources_type authority() const;
|
||||
|
||||
/**
|
||||
* \brief Getter for this PDU's DNS additional records.
|
||||
*
|
||||
* \return The additional records in this PDU.
|
||||
*/
|
||||
resources_type additional() const;
|
||||
|
||||
/**
|
||||
* \brief Encodes a domain name.
|
||||
*
|
||||
* This processes the input domain name and returns the encoded
|
||||
* version. Each label in the original domain name will be
|
||||
* prefixed with a byte that indicates the label's length.
|
||||
* The null-terminator byte <b>will</b> be included in the encoded
|
||||
* string. No compression is performed.
|
||||
*
|
||||
* For example, given the input "www.example.com", the output would
|
||||
* be "\x03www\x07example\x03com\x00".
|
||||
*
|
||||
* \param domain_name The domain name to encode.
|
||||
* \return The encoded domain name.
|
||||
*/
|
||||
static std::string encode_domain_name(const std::string &domain_name);
|
||||
|
||||
/**
|
||||
* \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;
|
||||
|
||||
/**
|
||||
* \sa PDU::clone
|
||||
*/
|
||||
DNS *clone() const {
|
||||
return new DNS(*this);
|
||||
}
|
||||
private:
|
||||
TINS_BEGIN_PACK
|
||||
struct dnshdr {
|
||||
uint16_t id;
|
||||
#if TINS_IS_LITTLE_ENDIAN
|
||||
uint16_t
|
||||
rd:1,
|
||||
tc:1,
|
||||
aa:1,
|
||||
opcode:4,
|
||||
qr:1,
|
||||
rcode:4,
|
||||
cd:1,
|
||||
ad:1,
|
||||
z:1,
|
||||
ra:1;
|
||||
#elif TINS_IS_BIG_ENDIAN
|
||||
uint16_t
|
||||
qr:1,
|
||||
opcode:4,
|
||||
aa:1,
|
||||
tc:1,
|
||||
rd:1,
|
||||
ra:1,
|
||||
z:1,
|
||||
ad:1,
|
||||
cd:1,
|
||||
rcode:4;
|
||||
#endif
|
||||
uint16_t questions, answers,
|
||||
authority, additional;
|
||||
} TINS_END_PACK;
|
||||
|
||||
typedef std::list<Query> QueriesType;
|
||||
typedef std::vector<std::pair<uint32_t*, uint32_t> > sections_type;
|
||||
|
||||
const uint8_t* compose_name(const uint8_t *ptr, char *out_ptr) const;
|
||||
void convert_records(const uint8_t *ptr, const uint8_t *end, resources_type &res) const;
|
||||
const uint8_t* find_section_end(const uint8_t *ptr, const uint32_t num_records) const;
|
||||
const uint8_t* find_dname_end(const uint8_t *ptr) const;
|
||||
void update_records(uint32_t §ion_start, uint32_t num_records, uint32_t threshold, uint32_t offset);
|
||||
uint8_t *update_dname(uint8_t *ptr, uint32_t threshold, uint32_t offset);
|
||||
static void inline_convert_v4(uint32_t value, char *output);
|
||||
static bool contains_dname(uint16_t type);
|
||||
void write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *parent);
|
||||
void add_record(const Resource &resource, const sections_type §ions);
|
||||
|
||||
dnshdr dns;
|
||||
byte_array records_data;
|
||||
uint32_t answers_idx, authority_idx, additional_idx;
|
||||
};
|
||||
}
|
||||
|
||||
#endif // TINS_DNS_H
|
||||
|
||||
44
include/tins/dot11.h
Normal file
44
include/tins/dot11.h
Normal file
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Matias Fontanini
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following disclaimer
|
||||
* in the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#if !defined(TINS_DOT_11) && defined(HAVE_DOT11)
|
||||
#define TINS_DOT_11
|
||||
|
||||
#include "dot11/dot11_base.h"
|
||||
#include "dot11/dot11_data.h"
|
||||
#include "dot11/dot11_mgmt.h"
|
||||
#include "dot11/dot11_beacon.h"
|
||||
#include "dot11/dot11_assoc.h"
|
||||
#include "dot11/dot11_auth.h"
|
||||
#include "dot11/dot11_probe.h"
|
||||
#include "dot11/dot11_control.h"
|
||||
|
||||
#endif // TINS_DOT_11
|
||||
6
include/tins/dot11/CMakeLists.txt
Normal file
6
include/tins/dot11/CMakeLists.txt
Normal file
@@ -0,0 +1,6 @@
|
||||
FILE(GLOB INCLUDE_FILES "*.h")
|
||||
INSTALL(
|
||||
FILES ${INCLUDE_FILES}
|
||||
DESTINATION include/tins/dot11
|
||||
COMPONENT Headers
|
||||
)
|
||||
622
include/tins/dot11/dot11_assoc.h
Normal file
622
include/tins/dot11/dot11_assoc.h
Normal file
@@ -0,0 +1,622 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Matias Fontanini
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following disclaimer
|
||||
* in the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "../config.h"
|
||||
|
||||
#if !defined(TINS_DOT11_DOT11_ASSOC_H) && defined(HAVE_DOT11)
|
||||
#define TINS_DOT11_DOT11_ASSOC_H
|
||||
|
||||
#include "../dot11/dot11_mgmt.h"
|
||||
|
||||
namespace Tins {
|
||||
/**
|
||||
* \brief Class representing a Disassociation frame in the IEEE 802.11 Protocol.
|
||||
*
|
||||
*/
|
||||
class Dot11Disassoc : public Dot11ManagementFrame {
|
||||
public:
|
||||
/**
|
||||
* \brief This PDU's flag.
|
||||
*/
|
||||
static const PDU::PDUType pdu_flag = PDU::DOT11_DIASSOC;
|
||||
|
||||
/**
|
||||
* \brief Constructor for creating a 802.11 Disassociation.
|
||||
*
|
||||
* Constructs a 802.11 Disassociation taking the destination
|
||||
* and source hardware address.
|
||||
*
|
||||
* \param dst_hw_addr The destination hardware address.
|
||||
* \param src_hw_addr The source hardware address.
|
||||
*/
|
||||
Dot11Disassoc(const address_type &dst_hw_addr = address_type(),
|
||||
const address_type &src_hw_addr = address_type());
|
||||
|
||||
/**
|
||||
* \brief Constructs a Dot11Disassoc object from a buffer and
|
||||
* adds all identifiable PDUs found in the buffer as children
|
||||
* of this one.
|
||||
*
|
||||
* If the next PDU is not recognized, then a RawPDU is used.
|
||||
*
|
||||
* If there is not enough size for the header in the buffer
|
||||
* or the input data is malformed, 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.
|
||||
*/
|
||||
Dot11Disassoc(const uint8_t *buffer, uint32_t total_sz);
|
||||
|
||||
/**
|
||||
* \brief Getter for the reason code field.
|
||||
*
|
||||
* \return The stored reason code.
|
||||
*/
|
||||
uint16_t reason_code() const { return Endian::le_to_host(_body.reason_code); }
|
||||
|
||||
/**
|
||||
* \brief Setter for the reason code field.
|
||||
*
|
||||
* \param new_reason_code The reason code to be set.
|
||||
*/
|
||||
void reason_code(uint16_t new_reason_code);
|
||||
|
||||
/**
|
||||
* \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;
|
||||
|
||||
/**
|
||||
* \brief Getter for the PDU's type.
|
||||
* \sa PDU::pdu_type
|
||||
*/
|
||||
PDUType pdu_type() const { return pdu_flag; }
|
||||
|
||||
/**
|
||||
* \brief Check wether this PDU matches the specified flag.
|
||||
* \param flag The flag to match
|
||||
* \sa PDU::matches_flag
|
||||
*/
|
||||
bool matches_flag(PDUType flag) const {
|
||||
return flag == pdu_flag || Dot11ManagementFrame::matches_flag(flag);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Clones this PDU.
|
||||
*
|
||||
* \sa PDU::clone
|
||||
*/
|
||||
Dot11Disassoc *clone() const {
|
||||
return new Dot11Disassoc(*this);
|
||||
}
|
||||
private:
|
||||
struct DisassocBody {
|
||||
uint16_t reason_code;
|
||||
};
|
||||
|
||||
uint32_t write_fixed_parameters(uint8_t *buffer, uint32_t total_sz);
|
||||
|
||||
DisassocBody _body;
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Class representing an Association Request frame in the IEEE 802.11 Protocol.
|
||||
*
|
||||
*/
|
||||
class Dot11AssocRequest : public Dot11ManagementFrame {
|
||||
public:
|
||||
/**
|
||||
* \brief This PDU's flag.
|
||||
*/
|
||||
static const PDU::PDUType pdu_flag = PDU::DOT11_ASSOC_REQ;
|
||||
|
||||
/**
|
||||
* \brief Constructor for creating a 802.11 Association Request.
|
||||
*
|
||||
* Constructs a 802.11 Association Request taking the
|
||||
* destination and source hardware address.
|
||||
*
|
||||
* \param dst_hw_addr The destination hardware address.
|
||||
* \param src_hw_addr The source hardware address.
|
||||
*/
|
||||
Dot11AssocRequest(const address_type &dst_hw_addr = address_type(),
|
||||
const address_type &src_hw_addr = address_type());
|
||||
|
||||
/**
|
||||
* \brief Constructs a Dot11AssocRequest object from a buffer
|
||||
* and adds all identifiable PDUs found in the buffer as children
|
||||
* of this one.
|
||||
*
|
||||
* If the next PDU is not recognized, then a RawPDU is used.
|
||||
*
|
||||
* If there is not enough size for the header in the buffer
|
||||
* or the input data is malformed, 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.
|
||||
*/
|
||||
Dot11AssocRequest(const uint8_t *buffer, uint32_t total_sz);
|
||||
|
||||
/**
|
||||
* \brief Getter for the Capabilities Information.
|
||||
*
|
||||
* \return A constant refereence to the stored Capabilities
|
||||
* Information field.
|
||||
*/
|
||||
const capability_information& capabilities() const { return _body.capability;}
|
||||
|
||||
/**
|
||||
* \brief Getter for the Capabilities Information.
|
||||
*
|
||||
* \return A refereence to the stored Capabilities Information
|
||||
* field.
|
||||
*/
|
||||
capability_information& capabilities() { return _body.capability;}
|
||||
|
||||
/**
|
||||
* \brief Getter for the listen interval field.
|
||||
*
|
||||
* \return The stored listen interval field.
|
||||
*/
|
||||
uint16_t listen_interval() const { return Endian::le_to_host(_body.listen_interval); }
|
||||
|
||||
/**
|
||||
* \brief Setter for the listen interval field.
|
||||
*
|
||||
* \param new_listen_interval The listen interval to be set.
|
||||
*/
|
||||
void listen_interval(uint16_t new_listen_interval);
|
||||
|
||||
/**
|
||||
* \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;
|
||||
|
||||
/**
|
||||
* \brief Getter for the PDU's type.
|
||||
* \sa PDU::pdu_type
|
||||
*/
|
||||
PDUType pdu_type() const { return pdu_flag; }
|
||||
|
||||
/**
|
||||
* \brief Check wether this PDU matches the specified flag.
|
||||
* \param flag The flag to match
|
||||
* \sa PDU::matches_flag
|
||||
*/
|
||||
bool matches_flag(PDUType flag) const {
|
||||
return flag == pdu_flag || Dot11ManagementFrame::matches_flag(flag);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Clones this PDU.
|
||||
*
|
||||
* \sa PDU::clone
|
||||
*/
|
||||
Dot11AssocRequest *clone() const {
|
||||
return new Dot11AssocRequest(*this);
|
||||
}
|
||||
private:
|
||||
struct AssocReqBody {
|
||||
capability_information capability;
|
||||
uint16_t listen_interval;
|
||||
};
|
||||
|
||||
uint32_t write_fixed_parameters(uint8_t *buffer, uint32_t total_sz);
|
||||
|
||||
AssocReqBody _body;
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Class representing an Association Response frame in the IEEE 802.11 Protocol.
|
||||
*
|
||||
*/
|
||||
class Dot11AssocResponse : public Dot11ManagementFrame {
|
||||
public:
|
||||
/**
|
||||
* \brief This PDU's flag.
|
||||
*/
|
||||
static const PDU::PDUType pdu_flag = PDU::DOT11_ASSOC_RESP;
|
||||
|
||||
/**
|
||||
* \brief Constructor for creating a 802.11 Association Response.
|
||||
*
|
||||
* Constructors a 802.11 Association Response taking destination
|
||||
* and source hardware address.
|
||||
*
|
||||
* \param dst_hw_addr The destination hardware address.
|
||||
* \param src_hw_addr The source hardware address.
|
||||
*/
|
||||
Dot11AssocResponse(const address_type &dst_hw_addr = address_type(),
|
||||
const address_type &src_hw_addr = address_type());
|
||||
|
||||
/**
|
||||
* \brief Constructor which creates a Dot11AssocResponse object
|
||||
* from a buffer and adds all identifiable PDUs found in the
|
||||
* buffer as children of this one.
|
||||
*
|
||||
* If the next PDU is not recognized, then a RawPDU is used.
|
||||
*
|
||||
* If there is not enough size for the header in the buffer
|
||||
* or the input data is malformed, 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.
|
||||
*/
|
||||
Dot11AssocResponse(const uint8_t *buffer, uint32_t total_sz);
|
||||
|
||||
/**
|
||||
* \brief Getter for the Capabilities Information field.
|
||||
*
|
||||
* \return A constant reference to the stored Capabilities
|
||||
* Information field.
|
||||
*/
|
||||
const capability_information& capabilities() const { return _body.capability;}
|
||||
|
||||
/**
|
||||
* \brief Getter for the Capabilities Information field.
|
||||
*
|
||||
* \return A reference to the stored Capabilities
|
||||
* Information field.
|
||||
*/
|
||||
capability_information& capabilities() { return _body.capability;}
|
||||
|
||||
/**
|
||||
* \brief Getter for the status code field.
|
||||
*
|
||||
* \return The stored status code.
|
||||
*/
|
||||
uint16_t status_code() const { return Endian::le_to_host(_body.status_code); }
|
||||
|
||||
/**
|
||||
* \brief Getter for the AID field.
|
||||
*
|
||||
* \return The stored AID field.
|
||||
*/
|
||||
uint16_t aid() const { return Endian::le_to_host(_body.aid); }
|
||||
|
||||
/**
|
||||
* \brief Setter for the status code.
|
||||
*
|
||||
* \param new_status_code The status code to be set.
|
||||
*/
|
||||
void status_code(uint16_t new_status_code);
|
||||
|
||||
/**
|
||||
* \brief Setter for the AID field.
|
||||
*
|
||||
* \param new_aid The AID value to be set.
|
||||
*/
|
||||
void aid(uint16_t new_aid);
|
||||
|
||||
/**
|
||||
* \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;
|
||||
|
||||
/**
|
||||
* \brief Getter for the PDU's type.
|
||||
* \sa PDU::pdu_type
|
||||
*/
|
||||
PDUType pdu_type() const { return pdu_flag; }
|
||||
|
||||
/**
|
||||
* \brief Check wether this PDU matches the specified flag.
|
||||
* \param flag The flag to match
|
||||
* \sa PDU::matches_flag
|
||||
*/
|
||||
bool matches_flag(PDUType flag) const {
|
||||
return flag == pdu_flag || Dot11ManagementFrame::matches_flag(flag);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Clones this PDU.
|
||||
*
|
||||
* \sa PDU::clone
|
||||
*/
|
||||
Dot11AssocResponse *clone() const {
|
||||
return new Dot11AssocResponse(*this);
|
||||
}
|
||||
private:
|
||||
struct AssocRespBody {
|
||||
capability_information capability;
|
||||
uint16_t status_code;
|
||||
uint16_t aid;
|
||||
};
|
||||
|
||||
uint32_t write_fixed_parameters(uint8_t *buffer, uint32_t total_sz);
|
||||
|
||||
AssocRespBody _body;
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Class representing an ReAssociation Request frame in the IEEE 802.11 Protocol.
|
||||
*
|
||||
*/
|
||||
class Dot11ReAssocRequest : public Dot11ManagementFrame {
|
||||
public:
|
||||
/**
|
||||
* \brief This PDU's flag.
|
||||
*/
|
||||
static const PDU::PDUType pdu_flag = PDU::DOT11_REASSOC_REQ;
|
||||
|
||||
/**
|
||||
* \brief Constructor for creating a 802.11 ReAssociation Request.
|
||||
*
|
||||
* Constructors a 802.11 Association Request taking the destination
|
||||
* and source hardware address.
|
||||
*
|
||||
* \param dst_hw_addr The destination hardware address.
|
||||
* \param src_hw_addr The source hardware address.
|
||||
*/
|
||||
Dot11ReAssocRequest(const address_type &dst_hw_addr = address_type(),
|
||||
const address_type &src_hw_addr = address_type());
|
||||
|
||||
/**
|
||||
* \brief Constructs a Dot11AssocRequest object from a buffer
|
||||
* and adds all identifiable PDUs found in the buffer as
|
||||
* children of this one.
|
||||
*
|
||||
* If the next PDU is not recognized, then a RawPDU is used.
|
||||
*
|
||||
* If there is not enough size for the header in the buffer
|
||||
* or the input data is malformed, 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.
|
||||
*/
|
||||
Dot11ReAssocRequest(const uint8_t *buffer, uint32_t total_sz);
|
||||
|
||||
/**
|
||||
* \brief Getter for the Capabilities Information.
|
||||
*
|
||||
* \return A constant reference to the stored Capabilities
|
||||
* Information field.
|
||||
*/
|
||||
const capability_information& capabilities() const { return _body.capability;}
|
||||
|
||||
/**
|
||||
* \brief Getter for the Capabilities Information.
|
||||
*
|
||||
* \return A reference to the stored Capabilities Information
|
||||
* field.
|
||||
*/
|
||||
capability_information& capabilities() { return _body.capability;}
|
||||
|
||||
/**
|
||||
* \brief Getter for the listen interval field.
|
||||
*
|
||||
* \return The stored listen interval.
|
||||
*/
|
||||
uint16_t listen_interval() const { return Endian::le_to_host(_body.listen_interval); }
|
||||
|
||||
/**
|
||||
* \brief Getter for the current ap field.
|
||||
*
|
||||
* \return The current ap.
|
||||
*/
|
||||
address_type current_ap() const { return _body.current_ap; }
|
||||
|
||||
/**
|
||||
* \brief Setter for the listen interval field.
|
||||
*
|
||||
* \param new_listen_interval The listen interval to be set.
|
||||
*/
|
||||
void listen_interval(uint16_t new_listen_interval);
|
||||
|
||||
/**
|
||||
* \brief Setter for the current ap.
|
||||
*
|
||||
* \param new_current_ap The address of the current ap.
|
||||
*/
|
||||
void current_ap(const address_type &new_current_ap);
|
||||
|
||||
/**
|
||||
* \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;
|
||||
|
||||
/**
|
||||
* \brief Getter for the PDU's type.
|
||||
* \sa PDU::pdu_type
|
||||
*/
|
||||
PDUType pdu_type() const { return pdu_flag; }
|
||||
|
||||
/**
|
||||
* \brief Check wether this PDU matches the specified flag.
|
||||
* \param flag The flag to match
|
||||
* \sa PDU::matches_flag
|
||||
*/
|
||||
bool matches_flag(PDUType flag) const {
|
||||
return flag == pdu_flag || Dot11ManagementFrame::matches_flag(flag);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Clones this PDU.
|
||||
*
|
||||
* \sa PDU::clone
|
||||
*/
|
||||
Dot11ReAssocRequest *clone() const {
|
||||
return new Dot11ReAssocRequest(*this);
|
||||
}
|
||||
private:
|
||||
struct ReAssocReqBody {
|
||||
capability_information capability;
|
||||
uint16_t listen_interval;
|
||||
uint8_t current_ap[address_type::address_size];
|
||||
};
|
||||
|
||||
uint32_t write_fixed_parameters(uint8_t *buffer, uint32_t total_sz);
|
||||
|
||||
ReAssocReqBody _body;
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief IEEE 802.11 ReAssociation Response frame.
|
||||
*
|
||||
*/
|
||||
class Dot11ReAssocResponse : public Dot11ManagementFrame {
|
||||
public:
|
||||
/**
|
||||
* \brief This PDU's flag.
|
||||
*/
|
||||
static const PDU::PDUType pdu_flag = PDU::DOT11_REASSOC_RESP;
|
||||
|
||||
/**
|
||||
* \brief Constructor for creating a 802.11 Association Response.
|
||||
*
|
||||
* Constructs a 802.11 ReAssociation Response taking the
|
||||
* destination and source hardware address.
|
||||
*
|
||||
* \param dst_hw_addr The destination hardware address.
|
||||
* \param src_hw_addr The source hardware address.
|
||||
*/
|
||||
Dot11ReAssocResponse(const address_type &dst_hw_addr = address_type(),
|
||||
const address_type &src_hw_addr = address_type());
|
||||
|
||||
/**
|
||||
* \brief Constructs a Dot11ReAssocResponse object from a buffer
|
||||
* and adds all identifiable PDUs found in the buffer as children
|
||||
* of this one.
|
||||
*
|
||||
* If the next PDU is not recognized, then a RawPDU is used.
|
||||
*
|
||||
* If there is not enough size for the header in the buffer
|
||||
* or the input data is malformed, 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.
|
||||
*/
|
||||
Dot11ReAssocResponse(const uint8_t *buffer, uint32_t total_sz);
|
||||
|
||||
/**
|
||||
* \brief Getter for the Capabilities Information.
|
||||
*
|
||||
* \return A constant reference to the stored Capabilities
|
||||
* Information field.
|
||||
*/
|
||||
const capability_information& capabilities() const { return _body.capability;}
|
||||
|
||||
/**
|
||||
* \brief Getter for the Capabilities Information.
|
||||
*
|
||||
* \return A reference to the stored Capabilities Information
|
||||
* field.
|
||||
*/
|
||||
capability_information& capabilities() { return _body.capability;}
|
||||
|
||||
/**
|
||||
* \brief Getter for the status code field.
|
||||
*
|
||||
* \return The stored status code.
|
||||
*/
|
||||
uint16_t status_code() const { return Endian::le_to_host(_body.status_code); }
|
||||
|
||||
/**
|
||||
* \brief Getter for the AID field.
|
||||
*
|
||||
* \return The stored AID field value.
|
||||
*/
|
||||
uint16_t aid() const { return Endian::le_to_host(_body.aid); }
|
||||
|
||||
/**
|
||||
* \brief Setter for the status code field.
|
||||
*
|
||||
* \param new_status_code The status code to be set.
|
||||
*/
|
||||
void status_code(uint16_t new_status_code);
|
||||
|
||||
/**
|
||||
* \brief Setter for the AID field.
|
||||
*
|
||||
* \param new_aid The AID to be set.
|
||||
*/
|
||||
void aid(uint16_t new_aid);
|
||||
|
||||
/**
|
||||
* \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;
|
||||
|
||||
/**
|
||||
* \brief Getter for the PDU's type.
|
||||
* \sa PDU::pdu_type
|
||||
*/
|
||||
PDUType pdu_type() const { return pdu_flag; }
|
||||
|
||||
/**
|
||||
* \brief Check wether this PDU matches the specified flag.
|
||||
* \param flag The flag to match
|
||||
* \sa PDU::matches_flag
|
||||
*/
|
||||
bool matches_flag(PDUType flag) const {
|
||||
return flag == pdu_flag || Dot11ManagementFrame::matches_flag(flag);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Clones this PDU.
|
||||
*
|
||||
* \sa PDU::clone
|
||||
*/
|
||||
Dot11ReAssocResponse *clone() const {
|
||||
return new Dot11ReAssocResponse(*this);
|
||||
}
|
||||
private:
|
||||
struct ReAssocRespBody {
|
||||
capability_information capability;
|
||||
uint16_t status_code;
|
||||
uint16_t aid;
|
||||
};
|
||||
|
||||
uint32_t write_fixed_parameters(uint8_t *buffer, uint32_t total_sz);
|
||||
|
||||
ReAssocRespBody _body;
|
||||
};
|
||||
} // namespace Tins
|
||||
|
||||
#endif // TINS_DOT11_DOT11_ASSOC_H
|
||||
260
include/tins/dot11/dot11_auth.h
Normal file
260
include/tins/dot11/dot11_auth.h
Normal file
@@ -0,0 +1,260 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Matias Fontanini
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following disclaimer
|
||||
* in the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "../config.h"
|
||||
|
||||
#if !defined(TINS_DOT11_DOT11_AUTH_H) && defined(HAVE_DOT11)
|
||||
#define TINS_DOT11_DOT11_AUTH_H
|
||||
|
||||
#include "../dot11/dot11_mgmt.h"
|
||||
|
||||
namespace Tins {
|
||||
/**
|
||||
* \brief IEEE 802.11 Authentication Request frame.
|
||||
*/
|
||||
class Dot11Authentication : public Dot11ManagementFrame {
|
||||
public:
|
||||
/**
|
||||
* \brief This PDU's flag.
|
||||
*/
|
||||
static const PDU::PDUType pdu_flag = PDU::DOT11_AUTH;
|
||||
|
||||
/**
|
||||
* \brief Constructor for creating a 802.11 Authentication.
|
||||
*
|
||||
* Constructs a 802.11 Dot11Authentication taking the
|
||||
* destination and source hardware address.
|
||||
*
|
||||
* \param dst_hw_addr The destination hardware address.
|
||||
* \param src_hw_addr The source hardware address.
|
||||
*/
|
||||
Dot11Authentication(const address_type &dst_hw_addr = address_type(),
|
||||
const address_type &src_hw_addr = address_type());
|
||||
|
||||
/**
|
||||
* \brief Constructs a Dot11Authentication object from a buffer
|
||||
* and adds all identifiable PDUs found in the buffer as children
|
||||
* of this one.
|
||||
*
|
||||
* If the next PDU is not recognized, then a RawPDU is used.
|
||||
*
|
||||
* If there is not enough size for the header in the buffer
|
||||
* or the input data is malformed, 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.
|
||||
*/
|
||||
Dot11Authentication(const uint8_t *buffer, uint32_t total_sz);
|
||||
|
||||
/**
|
||||
* \brief Getter for the Authetication Algorithm Number field.
|
||||
*
|
||||
* \return The stored authentication algorithm number.
|
||||
*/
|
||||
uint16_t auth_algorithm() const {return Endian::le_to_host(_body.auth_algorithm); }
|
||||
|
||||
/**
|
||||
* \brief Getter for the Authetication Sequence Number field.
|
||||
*
|
||||
* \return The stored authentication sequence number.
|
||||
*/
|
||||
uint16_t auth_seq_number() const {return Endian::le_to_host(_body.auth_seq_number); }
|
||||
|
||||
/**
|
||||
* \brief Getter for the status code field.
|
||||
*
|
||||
* \return The stored status code.
|
||||
*/
|
||||
uint16_t status_code() const { return Endian::le_to_host(_body.status_code); }
|
||||
|
||||
/**
|
||||
* \brief Setter for the Authetication Algorithm Number field.
|
||||
*
|
||||
* \param new_auth_algorithm The Authetication Algorithm Number
|
||||
* to be set.
|
||||
*/
|
||||
void auth_algorithm(uint16_t new_auth_algorithm);
|
||||
|
||||
/**
|
||||
* \brief Setter for the Authetication Sequence Number field.
|
||||
*
|
||||
* \param new_auth_seq_number The Authetication Sequence Number
|
||||
* to be set.
|
||||
*/
|
||||
void auth_seq_number(uint16_t new_auth_seq_number);
|
||||
|
||||
/**
|
||||
* \brief Setter for the status code field.
|
||||
*
|
||||
* \param new_status_code The status code to be set.
|
||||
*/
|
||||
void status_code(uint16_t new_status_code);
|
||||
|
||||
/**
|
||||
* \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;
|
||||
|
||||
/**
|
||||
* \brief Getter for the PDU's type.
|
||||
* \sa PDU::pdu_type
|
||||
*/
|
||||
PDUType pdu_type() const { return pdu_flag; }
|
||||
|
||||
/**
|
||||
* \brief Check wether this PDU matches the specified flag.
|
||||
* \param flag The flag to match
|
||||
* \sa PDU::matches_flag
|
||||
*/
|
||||
bool matches_flag(PDUType flag) const {
|
||||
return flag == pdu_flag || Dot11ManagementFrame::matches_flag(flag);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Clones this PDU.
|
||||
*
|
||||
* \sa PDU::clone
|
||||
*/
|
||||
Dot11Authentication *clone() const {
|
||||
return new Dot11Authentication(*this);
|
||||
}
|
||||
private:
|
||||
struct AuthBody {
|
||||
uint16_t auth_algorithm;
|
||||
uint16_t auth_seq_number;
|
||||
uint16_t status_code;
|
||||
};
|
||||
|
||||
uint32_t write_fixed_parameters(uint8_t *buffer, uint32_t total_sz);
|
||||
|
||||
AuthBody _body;
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief IEEE 802.11 Deauthentication frame.
|
||||
*
|
||||
*/
|
||||
class Dot11Deauthentication : public Dot11ManagementFrame {
|
||||
public:
|
||||
/**
|
||||
* \brief This PDU's flag.
|
||||
*/
|
||||
static const PDU::PDUType pdu_flag = PDU::DOT11_DEAUTH;
|
||||
|
||||
/**
|
||||
* \brief Constructor for creating a 802.11 Deauthentication.
|
||||
*
|
||||
* Constructs a 802.11 Deauthentication taking the
|
||||
* destination and source hardware address.
|
||||
*
|
||||
* \param dst_hw_addr The destination hardware address.
|
||||
* \param src_hw_addr The source hardware address.
|
||||
*/
|
||||
Dot11Deauthentication(const address_type &dst_hw_addr = address_type(),
|
||||
const address_type &src_hw_addr = address_type());
|
||||
|
||||
/**
|
||||
* \brief Constructs a Dot11Deauthentication object from a buffer
|
||||
* and adds all identifiable PDUs found in the buffer as children
|
||||
* of this one.
|
||||
*
|
||||
* If the next PDU is not recognized, then a RawPDU is used.
|
||||
*
|
||||
* If there is not enough size for the header in the buffer
|
||||
* or the input data is malformed, 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.
|
||||
*/
|
||||
Dot11Deauthentication(const uint8_t *buffer, uint32_t total_sz);
|
||||
|
||||
/**
|
||||
* \brief Getter for the reason code field.
|
||||
*
|
||||
* \return The reason code to be set.
|
||||
*/
|
||||
uint16_t reason_code() const { return Endian::le_to_host(_body.reason_code); }
|
||||
|
||||
/**
|
||||
* \brief Setter for the reason code field.
|
||||
*
|
||||
* \param new_reason_code The reason code to be set.
|
||||
*/
|
||||
void reason_code(uint16_t new_reason_code);
|
||||
|
||||
/**
|
||||
* \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;
|
||||
|
||||
/**
|
||||
* \brief Getter for the PDU's type.
|
||||
* \sa PDU::pdu_type
|
||||
*/
|
||||
PDUType pdu_type() const { return pdu_flag; }
|
||||
|
||||
/**
|
||||
* \brief Check wether this PDU matches the specified flag.
|
||||
* \param flag The flag to match
|
||||
* \sa PDU::matches_flag
|
||||
*/
|
||||
bool matches_flag(PDUType flag) const {
|
||||
return flag == pdu_flag || Dot11ManagementFrame::matches_flag(flag);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Clones this PDU.
|
||||
*
|
||||
* \sa PDU::clone
|
||||
*/
|
||||
Dot11Deauthentication *clone() const {
|
||||
return new Dot11Deauthentication(*this);
|
||||
}
|
||||
private:
|
||||
struct DeauthBody {
|
||||
uint16_t reason_code;
|
||||
};
|
||||
|
||||
uint32_t write_fixed_parameters(uint8_t *buffer, uint32_t total_sz);
|
||||
|
||||
DeauthBody _body;
|
||||
};
|
||||
} // namespace Tins
|
||||
|
||||
|
||||
#endif // TINS_DOT11_DOT11_AUTH_H
|
||||
522
include/tins/dot11/dot11_base.h
Normal file
522
include/tins/dot11/dot11_base.h
Normal file
@@ -0,0 +1,522 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Matias Fontanini
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following disclaimer
|
||||
* in the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "../config.h"
|
||||
|
||||
#if !defined(TINS_DOT11_DOT11_H) && defined(HAVE_DOT11)
|
||||
#define TINS_DOT11_DOT11_H
|
||||
|
||||
#include <list>
|
||||
#include "../pdu.h"
|
||||
#include "../pdu_option.h"
|
||||
#include "../small_uint.h"
|
||||
#include "../hw_address.h"
|
||||
#include "../endianness.h"
|
||||
#include "../cxxstd.h"
|
||||
#include "../macros.h"
|
||||
|
||||
namespace Tins {
|
||||
class RSNInformation;
|
||||
|
||||
/**
|
||||
* \brief Class representing an 802.11 frame.
|
||||
*/
|
||||
class Dot11 : public PDU {
|
||||
public:
|
||||
/**
|
||||
* The type used to store hardware addresses.
|
||||
*/
|
||||
typedef HWAddress<6> address_type;
|
||||
|
||||
/**
|
||||
* \brief IEEE 802.11 options struct.
|
||||
*/
|
||||
typedef PDUOption<uint8_t, Dot11> option;
|
||||
|
||||
/**
|
||||
* The type used to store tagged options.
|
||||
*/
|
||||
typedef std::list<option> options_type;
|
||||
|
||||
/**
|
||||
* \brief This PDU's flag.
|
||||
*/
|
||||
static const PDU::PDUType pdu_flag = PDU::DOT11;
|
||||
|
||||
/**
|
||||
* \brief Broadcast hardware address.
|
||||
*/
|
||||
static const address_type BROADCAST;
|
||||
|
||||
/**
|
||||
* The endianness used by Dot11.
|
||||
*/
|
||||
static const endian_type endianness = LE;
|
||||
|
||||
/**
|
||||
* \brief Enum for the different types of 802.11 frames.
|
||||
*
|
||||
*/
|
||||
enum Types {
|
||||
MANAGEMENT = 0,
|
||||
CONTROL = 1,
|
||||
DATA = 2
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Enum for the different types of tagged options.
|
||||
*/
|
||||
enum OptionTypes {
|
||||
SSID,
|
||||
SUPPORTED_RATES,
|
||||
FH_SET,
|
||||
DS_SET,
|
||||
CF_SET,
|
||||
TIM,
|
||||
IBSS_SET,
|
||||
COUNTRY,
|
||||
HOPPING_PATTERN_PARAMS,
|
||||
HOPPING_PATTERN_TABLE,
|
||||
REQUEST_INFORMATION,
|
||||
BSS_LOAD,
|
||||
EDCA,
|
||||
TSPEC,
|
||||
TCLAS,
|
||||
SCHEDULE,
|
||||
CHALLENGE_TEXT,
|
||||
POWER_CONSTRAINT = 32,
|
||||
POWER_CAPABILITY,
|
||||
TPC_REQUEST,
|
||||
TPC_REPORT,
|
||||
SUPPORTED_CHANNELS,
|
||||
CHANNEL_SWITCH,
|
||||
MEASUREMENT_REQUEST,
|
||||
MEASUREMENT_REPORT,
|
||||
QUIET,
|
||||
IBSS_DFS,
|
||||
ERP_INFORMATION,
|
||||
TS_DELAY,
|
||||
TCLAS_PROCESSING,
|
||||
QOS_CAPABILITY = 46,
|
||||
RSN = 48,
|
||||
EXT_SUPPORTED_RATES = 50,
|
||||
VENDOR_SPECIFIC = 221
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Enum for the different subtypes of 802.11 management frames.
|
||||
*
|
||||
*/
|
||||
enum ManagementSubtypes {
|
||||
ASSOC_REQ = 0,
|
||||
ASSOC_RESP = 1,
|
||||
REASSOC_REQ = 2,
|
||||
REASSOC_RESP = 3,
|
||||
PROBE_REQ = 4,
|
||||
PROBE_RESP = 5,
|
||||
BEACON = 8,
|
||||
ATIM = 9,
|
||||
DISASSOC = 10,
|
||||
AUTH = 11,
|
||||
DEAUTH = 12
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Enum for the different subtypes of 802.11 control frames.
|
||||
*
|
||||
*/
|
||||
enum ControlSubtypes {
|
||||
BLOCK_ACK_REQ = 8,
|
||||
BLOCK_ACK = 9,
|
||||
PS = 10,
|
||||
RTS = 11,
|
||||
CTS = 12,
|
||||
ACK = 13,
|
||||
CF_END = 14,
|
||||
CF_END_ACK = 15
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Enum fro the different subtypes of 802.11 data frames.
|
||||
*
|
||||
*/
|
||||
enum DataSubtypes {
|
||||
DATA_DATA = 0,
|
||||
DATA_CF_ACK = 1,
|
||||
DATA_CF_POLL = 2,
|
||||
DATA_CF_ACK_POLL = 3,
|
||||
DATA_NULL = 4,
|
||||
CF_ACK = 5,
|
||||
CF_POLL = 6,
|
||||
CF_ACK_POLL = 7,
|
||||
QOS_DATA_DATA = 8,
|
||||
QOS_DATA_CF_ACK = 9,
|
||||
QOS_DATA_CF_POLL = 10,
|
||||
QOS_DATA_CF_ACK_POLL = 11,
|
||||
QOS_DATA_NULL = 12
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Constructs an 802.11 PDU.
|
||||
*
|
||||
* \param dst_hw_addr The destination hardware address.
|
||||
*/
|
||||
Dot11(const address_type &dst_hw_addr = address_type());
|
||||
|
||||
/**
|
||||
* \brief Constructs 802.11 PDU from a buffer and adds all
|
||||
* identifiable PDUs found in the buffer as children of this one.
|
||||
*
|
||||
* If the next PDU is not recognized, then a RawPDU is used.
|
||||
*
|
||||
* If there is not enough size for a 802.11 header in the
|
||||
* buffer, 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.
|
||||
*/
|
||||
Dot11(const uint8_t *buffer, uint32_t total_sz);
|
||||
|
||||
/**
|
||||
* \brief Getter for the protocol version field.
|
||||
*
|
||||
* \return The stored protocol version field.
|
||||
*/
|
||||
small_uint<2> protocol() const { return _header.control.protocol; }
|
||||
|
||||
/**
|
||||
* \brief Getter for the Type field.
|
||||
*
|
||||
* \return The stored Type field.
|
||||
*/
|
||||
small_uint<2> type() const { return _header.control.type; }
|
||||
|
||||
/**
|
||||
* \brief Getter for the Subtype field.
|
||||
*
|
||||
* \return The stored Subtype field.
|
||||
*/
|
||||
small_uint<4> subtype() const { return _header.control.subtype; }
|
||||
|
||||
/**
|
||||
* \brief Getter for the To-DS field.
|
||||
*
|
||||
* \return The stored To-DS field.
|
||||
*/
|
||||
small_uint<1> to_ds() const { return _header.control.to_ds; }
|
||||
|
||||
/**
|
||||
* \brief Getter for the From-DS field.
|
||||
*
|
||||
* \return The stored From-DS field.
|
||||
*/
|
||||
small_uint<1> from_ds() const { return _header.control.from_ds; }
|
||||
|
||||
/**
|
||||
* \brief Getter for the More-Frag field.
|
||||
*
|
||||
* \return The stored More-Frag field.
|
||||
*/
|
||||
small_uint<1> more_frag() const { return _header.control.more_frag; }
|
||||
|
||||
/**
|
||||
* \brief Getter for the Retry field.
|
||||
*
|
||||
* \return The stored Retry field.
|
||||
*/
|
||||
small_uint<1> retry() const { return _header.control.retry; }
|
||||
|
||||
/**
|
||||
* \brief Getter for the Power-Management field.
|
||||
*
|
||||
* \return The stored Power-Management field.
|
||||
*/
|
||||
small_uint<1> power_mgmt() const { return _header.control.power_mgmt; }
|
||||
|
||||
/**
|
||||
* \brief Getter for the WEP field.
|
||||
*
|
||||
* \return The stored WEP field.
|
||||
*/
|
||||
small_uint<1> wep() const { return _header.control.wep; }
|
||||
|
||||
/**
|
||||
* \brief Getter for the Order field.
|
||||
*
|
||||
* \return The stored Order field.
|
||||
*/
|
||||
small_uint<1> order() const { return _header.control.order; }
|
||||
|
||||
/**
|
||||
* \brief Getter for the Duration-ID field.
|
||||
*
|
||||
* \return The stored Duration-ID field.
|
||||
*/
|
||||
uint16_t duration_id() const { return Endian::le_to_host(_header.duration_id); }
|
||||
|
||||
/**
|
||||
* \brief Getter for the first address.
|
||||
*
|
||||
* \return The stored first address.
|
||||
*/
|
||||
address_type addr1() const { return _header.addr1; }
|
||||
|
||||
// Setters
|
||||
|
||||
/**
|
||||
* \brief Setter for the protocol version field.
|
||||
*
|
||||
* \param new_proto The new protocol version field value.
|
||||
*/
|
||||
void protocol(small_uint<2> new_proto);
|
||||
|
||||
/**
|
||||
* \brief Setter for the type field.
|
||||
*
|
||||
* \param new_type The new type field value.
|
||||
*/
|
||||
void type(small_uint<2> new_type);
|
||||
|
||||
/**
|
||||
* \brief Setter for the subtype field.
|
||||
*
|
||||
* \param new_subtype The new subtype field value.
|
||||
*/
|
||||
void subtype(small_uint<4> new_subtype);
|
||||
|
||||
/**
|
||||
* \brief Setter for the To-DS field.
|
||||
*
|
||||
* \param new_value The new To-DS field value.
|
||||
*/
|
||||
void to_ds(small_uint<1> new_value);
|
||||
|
||||
/**
|
||||
* \brief Setter for the From-DS field.
|
||||
*
|
||||
* \param new_value The new From-DS field value.
|
||||
*/
|
||||
void from_ds(small_uint<1> new_value);
|
||||
|
||||
/**
|
||||
* \brief Setter for the More-Frag field.
|
||||
*
|
||||
* \param new_value The new More-Frag field value.
|
||||
*/
|
||||
void more_frag(small_uint<1> new_value);
|
||||
|
||||
/**
|
||||
* \brief Setter for the Retry field.
|
||||
*
|
||||
* \param new_value The new Retry field value.
|
||||
*/
|
||||
void retry(small_uint<1> new_value);
|
||||
|
||||
/**
|
||||
* \brief Setter for the Power-Management field.
|
||||
*
|
||||
* \param new_value The new Power-Management field value.
|
||||
*/
|
||||
void power_mgmt(small_uint<1> new_value);
|
||||
|
||||
/**
|
||||
* \brief Setter for the WEP field.
|
||||
*
|
||||
* \param new_value The new WEP field value.
|
||||
*/
|
||||
void wep(small_uint<1> new_value);
|
||||
|
||||
/**
|
||||
* \brief Setter for the Order field.
|
||||
*
|
||||
* \param new_value The new Order field value.
|
||||
*/
|
||||
void order(small_uint<1> new_value);
|
||||
|
||||
/**
|
||||
* \brief Setter for the Duration-ID field.
|
||||
*
|
||||
* \param new_duration_id The new Duration-ID field value.
|
||||
*/
|
||||
void duration_id(uint16_t new_duration_id);
|
||||
|
||||
/**
|
||||
* \brief Setter for the first address.
|
||||
*
|
||||
* \param new_addr1 The new first address.
|
||||
*/
|
||||
void addr1(const address_type &new_addr1);
|
||||
|
||||
/* Virtual methods */
|
||||
/**
|
||||
* \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;
|
||||
|
||||
#ifndef WIN32
|
||||
/**
|
||||
* \sa PDU::send()
|
||||
*/
|
||||
void send(PacketSender &sender, const NetworkInterface &iface);
|
||||
#endif // WIN32
|
||||
|
||||
/**
|
||||
* \brief Adds a new option to this Dot11 PDU.
|
||||
* \param opt The option to be added.
|
||||
*/
|
||||
void add_option(const option &opt);
|
||||
|
||||
#if TINS_IS_CXX11
|
||||
/**
|
||||
* \brief Adds a new option to this Dot11 PDU.
|
||||
*
|
||||
* The option is move-constructed
|
||||
*
|
||||
* \param opt The option to be added.
|
||||
*/
|
||||
void add_option(option &&opt) {
|
||||
internal_add_option(opt);
|
||||
_options.push_back(std::move(opt));
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* \brief Looks up a tagged option in the option list.
|
||||
*
|
||||
* The returned pointer <b>must not</b> be free'd.
|
||||
*
|
||||
* \param opt The option identifier.
|
||||
* \return The option found, or 0 if no such option has been set.
|
||||
*/
|
||||
const option *search_option(OptionTypes opt) const;
|
||||
|
||||
/**
|
||||
* \brief Getter for the PDU's type.
|
||||
* \sa PDU::pdu_type
|
||||
*/
|
||||
PDUType pdu_type() const { return pdu_flag; }
|
||||
|
||||
/**
|
||||
* \sa PDU::clone
|
||||
*/
|
||||
Dot11 *clone() const {
|
||||
return new Dot11(*this);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Check wether this PDU matches the specified flag.
|
||||
* \param flag The flag to match
|
||||
* \sa PDU::matches_flag
|
||||
*/
|
||||
bool matches_flag(PDUType flag) const {
|
||||
return flag == pdu_flag;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the option list.
|
||||
*
|
||||
* \return The options list.
|
||||
*/
|
||||
const options_type &options() const { return _options; }
|
||||
|
||||
/**
|
||||
* \brief Allocates an Dot11 PDU from a buffer.
|
||||
*
|
||||
* This can be used somehow as a "virtual constructor". This
|
||||
* method instantiates the appropriate subclass of Dot11 from the
|
||||
* given buffer.
|
||||
*
|
||||
* The allocated class' type will be figured out from the
|
||||
* information provided in the buffer.
|
||||
*
|
||||
* \param buffer The buffer from which to take the PDU data.
|
||||
* \param total_sz The total size of the buffer.
|
||||
* \return The allocated Dot11 PDU.
|
||||
*/
|
||||
static Dot11 *from_bytes(const uint8_t *buffer, uint32_t total_sz);
|
||||
protected:
|
||||
virtual uint32_t write_ext_header(uint8_t *buffer, uint32_t total_sz) { return 0; }
|
||||
virtual uint32_t write_fixed_parameters(uint8_t *buffer, uint32_t total_sz) { return 0; }
|
||||
void parse_tagged_parameters(const uint8_t *buffer, uint32_t total_sz);
|
||||
void add_tagged_option(OptionTypes opt, uint8_t len, const uint8_t *val);
|
||||
protected:
|
||||
/**
|
||||
* Struct that represents the 802.11 header
|
||||
*/
|
||||
TINS_BEGIN_PACK
|
||||
struct ieee80211_header {
|
||||
TINS_BEGIN_PACK
|
||||
struct {
|
||||
#if TINS_IS_LITTLE_ENDIAN
|
||||
uint16_t protocol:2,
|
||||
type:2,
|
||||
subtype:4,
|
||||
to_ds:1,
|
||||
from_ds:1,
|
||||
more_frag:1,
|
||||
retry:1,
|
||||
power_mgmt:1,
|
||||
more_data:1,
|
||||
wep:1,
|
||||
order:1;
|
||||
#elif TINS_IS_BIG_ENDIAN
|
||||
uint16_t subtype:4,
|
||||
type:2,
|
||||
protocol:2,
|
||||
order:1,
|
||||
wep:1,
|
||||
more_data:1,
|
||||
power_mgmt:1,
|
||||
retry:1,
|
||||
more_frag:1,
|
||||
from_ds:1,
|
||||
to_ds:1;
|
||||
#endif
|
||||
} TINS_END_PACK control;
|
||||
uint16_t duration_id;
|
||||
uint8_t addr1[address_type::address_size];
|
||||
|
||||
} TINS_END_PACK;
|
||||
private:
|
||||
Dot11(const ieee80211_header *header_ptr);
|
||||
|
||||
void internal_add_option(const option &opt);
|
||||
void write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *parent);
|
||||
|
||||
|
||||
ieee80211_header _header;
|
||||
uint32_t _options_size;
|
||||
options_type _options;
|
||||
};
|
||||
}
|
||||
|
||||
#endif // TINS_DOT11_DOT11_H
|
||||
166
include/tins/dot11/dot11_beacon.h
Normal file
166
include/tins/dot11/dot11_beacon.h
Normal file
@@ -0,0 +1,166 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Matias Fontanini
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following disclaimer
|
||||
* in the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "../config.h"
|
||||
|
||||
#if !defined(TINS_DOT11_DOT11_BEACON_H) && defined(HAVE_DOT11)
|
||||
#define TINS_DOT11_DOT11_BEACON_H
|
||||
|
||||
#include "../dot11/dot11_mgmt.h"
|
||||
|
||||
namespace Tins {
|
||||
/**
|
||||
* \brief Class representing an 802.11 Beacon.
|
||||
*
|
||||
*/
|
||||
class Dot11Beacon : public Dot11ManagementFrame {
|
||||
public:
|
||||
/**
|
||||
* \brief This PDU's flag.
|
||||
*/
|
||||
static const PDU::PDUType pdu_flag = PDU::DOT11_BEACON;
|
||||
|
||||
/**
|
||||
* \brief Constructor for creating a 802.11 Beacon.
|
||||
*
|
||||
* Constructs a 802.11 Beacon taking destination and source
|
||||
* hardware address.
|
||||
*
|
||||
* \param dst_hw_addr The destination hardware address.
|
||||
* \param src_hw_addr The source hardware address.
|
||||
*/
|
||||
Dot11Beacon(const address_type &dst_hw_addr = address_type(),
|
||||
const address_type &src_hw_addr = address_type());
|
||||
|
||||
/**
|
||||
* \brief Constructs a Dot11Beacon object from a buffer and adds
|
||||
* all identifiable PDUs found in the buffer as children of this
|
||||
* one.
|
||||
*
|
||||
* If the next PDU is not recognized, then a RawPDU is used.
|
||||
*
|
||||
* If there is not enough size for the header in the buffer
|
||||
* or the input data is malformed, 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.
|
||||
*/
|
||||
Dot11Beacon(const uint8_t *buffer, uint32_t total_sz);
|
||||
|
||||
/**
|
||||
* \brief Getter for the timestamp field.
|
||||
*
|
||||
* \return The stored timestamp value.
|
||||
*/
|
||||
uint64_t timestamp() const { return Endian::le_to_host(_body.timestamp); }
|
||||
|
||||
/**
|
||||
* \brief Getter for the interval field.
|
||||
*
|
||||
* \return The stored interval value.
|
||||
*/
|
||||
uint16_t interval() const { return Endian::le_to_host(_body.interval); }
|
||||
|
||||
/**
|
||||
* \brief Getter for the Capabilities Information structure.
|
||||
*
|
||||
* \return A constant refereence to the stored Capabilities
|
||||
* Information field.
|
||||
*/
|
||||
const capability_information& capabilities() const { return _body.capability; }
|
||||
|
||||
/**
|
||||
* \brief Getter for the Capabilities Information.
|
||||
*
|
||||
* \return A refereence to the stored Capabilities Information
|
||||
* field.
|
||||
*/
|
||||
capability_information& capabilities() { return _body.capability; }
|
||||
|
||||
/**
|
||||
* \brief Setter for the timestamp field.
|
||||
*
|
||||
* \param new_timestamp The timestamp to be set.
|
||||
*/
|
||||
void timestamp(uint64_t new_timestamp);
|
||||
|
||||
/**
|
||||
* \brief Setter for the interval field.
|
||||
*
|
||||
* \param new_interval The interval to be set.
|
||||
*/
|
||||
void interval(uint16_t new_interval);
|
||||
|
||||
/**
|
||||
* \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;
|
||||
|
||||
/**
|
||||
* \brief Check wether this PDU matches the specified flag.
|
||||
* \param flag The flag to match
|
||||
* \sa PDU::matches_flag
|
||||
*/
|
||||
bool matches_flag(PDUType flag) const {
|
||||
return flag == pdu_flag || Dot11ManagementFrame::matches_flag(flag);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Clones this PDU.
|
||||
*
|
||||
* \sa PDU::clone
|
||||
*/
|
||||
Dot11Beacon *clone() const {
|
||||
return new Dot11Beacon(*this);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the PDU's type.
|
||||
* \sa PDU::pdu_type
|
||||
*/
|
||||
PDUType pdu_type() const { return pdu_flag; }
|
||||
private:
|
||||
TINS_BEGIN_PACK
|
||||
struct BeaconBody {
|
||||
uint64_t timestamp;
|
||||
uint16_t interval;
|
||||
capability_information capability;
|
||||
} TINS_END_PACK;
|
||||
|
||||
uint32_t write_fixed_parameters(uint8_t *buffer, uint32_t total_sz);
|
||||
|
||||
BeaconBody _body;
|
||||
};
|
||||
} // namespace Tins
|
||||
|
||||
#endif // TINS_DOT11_DOT11_BEACON_H
|
||||
746
include/tins/dot11/dot11_control.h
Normal file
746
include/tins/dot11/dot11_control.h
Normal file
@@ -0,0 +1,746 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Matias Fontanini
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following disclaimer
|
||||
* in the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "../config.h"
|
||||
|
||||
#if !defined(TINS_DOT11_DOT11_CONTROL_H) && defined(HAVE_DOT11)
|
||||
|
||||
#define TINS_DOT11_DOT11_CONTROL_H
|
||||
|
||||
#include "../dot11/dot11_base.h"
|
||||
|
||||
namespace Tins {
|
||||
/**
|
||||
* \brief Class that represents an 802.11 control frame.
|
||||
*/
|
||||
class Dot11Control : public Dot11 {
|
||||
public:
|
||||
/**
|
||||
* \brief This PDU's flag.
|
||||
*/
|
||||
static const PDU::PDUType pdu_flag = PDU::DOT11_CONTROL;
|
||||
|
||||
/**
|
||||
* \brief Constructor for creating a 802.11 control frame PDU
|
||||
*
|
||||
* Constructs a 802.11 Control PDU taking the destination and
|
||||
* source hardware addresses.
|
||||
*
|
||||
* \param dst_addr The destination hardware address.
|
||||
*/
|
||||
Dot11Control(const address_type &dst_addr = address_type());
|
||||
|
||||
/**
|
||||
* \brief Constructs a Dot11Control object from a buffer and
|
||||
* adds all identifiable PDUs found in the buffer as children
|
||||
* of this one.
|
||||
*
|
||||
* If the next PDU is not recognized, then a RawPDU is used.
|
||||
*
|
||||
* If there is not enough size for the header in the buffer
|
||||
* or the input data is malformed, 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.
|
||||
*/
|
||||
Dot11Control(const uint8_t *buffer, uint32_t total_sz);
|
||||
|
||||
/**
|
||||
* \brief Getter for the PDU's type.
|
||||
* \sa PDU::pdu_type
|
||||
*/
|
||||
PDUType pdu_type() const { return PDU::DOT11_CONTROL; }
|
||||
|
||||
/**
|
||||
* \brief Check wether this PDU matches the specified flag.
|
||||
* \param flag The flag to match
|
||||
* \sa PDU::matches_flag
|
||||
*/
|
||||
bool matches_flag(PDUType flag) const {
|
||||
return flag == PDU::DOT11_CONTROL || Dot11::matches_flag(flag);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Class that represents an abstraction of the 802.11 control frames
|
||||
* that contain a target address.
|
||||
*/
|
||||
class Dot11ControlTA : public Dot11Control {
|
||||
public:
|
||||
/**
|
||||
* \brief Getter for the target address field.
|
||||
*/
|
||||
address_type target_addr() const { return _taddr; }
|
||||
|
||||
/**
|
||||
* \brief Setter for the target address field.
|
||||
* \param addr The new target address.
|
||||
*/
|
||||
void target_addr(const address_type &addr);
|
||||
protected:
|
||||
/**
|
||||
* \brief Constructor for creating a 802.11 control frame TA PDU
|
||||
*
|
||||
* Constructs a 802.11 PDU taking the destination and source
|
||||
* hardware addresses.
|
||||
*
|
||||
* \param dst_addr The destination hardware address.
|
||||
* \param target_addr The source hardware address.
|
||||
*/
|
||||
Dot11ControlTA(const address_type &dst_addr = address_type(),
|
||||
const address_type &target_addr = address_type());
|
||||
|
||||
/**
|
||||
* \brief Constructs a Dot11ControlTA object from a buffer and
|
||||
* adds all identifiable PDUs found in the buffer as children
|
||||
* of this one.
|
||||
*
|
||||
* If the next PDU is not recognized, then a RawPDU is used.
|
||||
*
|
||||
* If there is not enough size for the header in the buffer
|
||||
* or the input data is malformed, 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.
|
||||
*/
|
||||
Dot11ControlTA(const uint8_t *buffer, uint32_t total_sz);
|
||||
|
||||
/**
|
||||
* \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;
|
||||
protected:
|
||||
/**
|
||||
* \brief Getter for the control ta additional fields size.
|
||||
*/
|
||||
uint32_t controlta_size() const { return _taddr.size() + sizeof(ieee80211_header); }
|
||||
|
||||
uint32_t write_ext_header(uint8_t *buffer, uint32_t total_sz);
|
||||
private:
|
||||
|
||||
address_type _taddr;
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief IEEE 802.11 RTS frame.
|
||||
*/
|
||||
class Dot11RTS : public Dot11ControlTA {
|
||||
public:
|
||||
/**
|
||||
* \brief This PDU's flag.
|
||||
*/
|
||||
static const PDU::PDUType pdu_flag = PDU::DOT11_RTS;
|
||||
|
||||
/**
|
||||
* \brief Constructor for creating a 802.11 RTS frame PDU
|
||||
*
|
||||
* Constructs a 802.11 RTS PDU taking the destination and source
|
||||
* hardware addresses.
|
||||
*
|
||||
* \param dst_addr The destination hardware address.
|
||||
* \param target_addr The source hardware address.
|
||||
*/
|
||||
Dot11RTS(const address_type &dst_addr = address_type(),
|
||||
const address_type &target_addr = address_type());
|
||||
|
||||
/**
|
||||
* \brief Constructs a Dot11RTS object from a buffer and adds all
|
||||
* identifiable PDUs found in the buffer as children of this one.
|
||||
*
|
||||
* If the next PDU is not recognized, then a RawPDU is used.
|
||||
*
|
||||
* If there is not enough size for the header in the buffer
|
||||
* or the input data is malformed, 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.
|
||||
*/
|
||||
Dot11RTS(const uint8_t *buffer, uint32_t total_sz);
|
||||
|
||||
/**
|
||||
* \brief Clones this PDU.
|
||||
*
|
||||
* \sa PDU::clone
|
||||
*/
|
||||
Dot11RTS *clone() const {
|
||||
return new Dot11RTS(*this);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the PDU's type.
|
||||
* \sa PDU::pdu_type
|
||||
*/
|
||||
PDUType pdu_type() const { return pdu_flag; }
|
||||
|
||||
/**
|
||||
* \brief Check wether this PDU matches the specified flag.
|
||||
* \param flag The flag to match
|
||||
* \sa PDU::matches_flag
|
||||
*/
|
||||
bool matches_flag(PDUType flag) const {
|
||||
return flag == pdu_flag || Dot11Control::matches_flag(flag);
|
||||
}
|
||||
};
|
||||
|
||||
class Dot11PSPoll : public Dot11ControlTA {
|
||||
public:
|
||||
/**
|
||||
* \brief This PDU's flag.
|
||||
*/
|
||||
static const PDU::PDUType pdu_flag = PDU::DOT11_PS_POLL;
|
||||
|
||||
/**
|
||||
* \brief Constructor for creating a 802.11 PS-Poll frame PDU
|
||||
*
|
||||
* Constructs a 802.11 PDU taking the destination and source
|
||||
* hardware addresses.
|
||||
*
|
||||
* \param dst_addr The destination hardware address.
|
||||
* \param target_addr The source hardware address.
|
||||
*/
|
||||
Dot11PSPoll(const address_type &dst_addr = address_type(),
|
||||
const address_type &target_addr = address_type());
|
||||
|
||||
/**
|
||||
* \brief Constructs a Dot11PSPoll object from a buffer and
|
||||
* adds all identifiable PDUs found in the buffer as children of
|
||||
* this one.
|
||||
*
|
||||
* If the next PDU is not recognized, then a RawPDU is used.
|
||||
*
|
||||
* If there is not enough size for the header in the buffer
|
||||
* or the input data is malformed, 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.
|
||||
*/
|
||||
Dot11PSPoll(const uint8_t *buffer, uint32_t total_sz);
|
||||
|
||||
/**
|
||||
* \brief Clones this PDU.
|
||||
*
|
||||
* \sa PDU::clone
|
||||
*/
|
||||
Dot11PSPoll *clone() const {
|
||||
return new Dot11PSPoll(*this);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the PDU's type.
|
||||
* \sa PDU::pdu_type
|
||||
*/
|
||||
PDUType pdu_type() const { return pdu_flag; }
|
||||
|
||||
/**
|
||||
* \brief Check wether this PDU matches the specified flag.
|
||||
* \param flag The flag to match
|
||||
* \sa PDU::matches_flag
|
||||
*/
|
||||
bool matches_flag(PDUType flag) const {
|
||||
return flag == pdu_flag || Dot11Control::matches_flag(flag);
|
||||
}
|
||||
};
|
||||
|
||||
class Dot11CFEnd : public Dot11ControlTA {
|
||||
public:
|
||||
/**
|
||||
* \brief This PDU's flag.
|
||||
*/
|
||||
static const PDU::PDUType pdu_flag = PDU::DOT11_CF_END;
|
||||
|
||||
/**
|
||||
* \brief Constructor for creating a 802.11 CF-End frame PDU
|
||||
*
|
||||
* Constructs a 802.11 PDU taking the destination and source
|
||||
* hardware addresses.
|
||||
*
|
||||
* \param dst_addr The destination hardware address.
|
||||
* \param target_addr The source hardware address.
|
||||
*/
|
||||
Dot11CFEnd(const address_type &dst_addr = address_type(),
|
||||
const address_type &target_addr = address_type());
|
||||
|
||||
/**
|
||||
* \brief Constructs a Dot11CFEnd object from a buffer and adds
|
||||
* all identifiable PDUs found in the buffer as children of this
|
||||
* one.
|
||||
*
|
||||
* If the next PDU is not recognized, then a RawPDU is used.
|
||||
*
|
||||
* If there is not enough size for the header in the buffer
|
||||
* or the input data is malformed, 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.
|
||||
*/
|
||||
Dot11CFEnd(const uint8_t *buffer, uint32_t total_sz);
|
||||
|
||||
/**
|
||||
* \brief Clones this PDU.
|
||||
*
|
||||
* \sa PDU::clone
|
||||
*/
|
||||
Dot11CFEnd *clone() const {
|
||||
return new Dot11CFEnd(*this);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the PDU's type.
|
||||
* \sa PDU::pdu_type
|
||||
*/
|
||||
PDUType pdu_type() const { return pdu_flag; }
|
||||
|
||||
/**
|
||||
* \brief Check wether this PDU matches the specified flag.
|
||||
* \param flag The flag to match
|
||||
* \sa PDU::matches_flag
|
||||
*/
|
||||
bool matches_flag(PDUType flag) const {
|
||||
return flag == pdu_flag || Dot11Control::matches_flag(flag);
|
||||
}
|
||||
};
|
||||
|
||||
class Dot11EndCFAck : public Dot11ControlTA {
|
||||
public:
|
||||
/**
|
||||
* \brief This PDU's flag.
|
||||
*/
|
||||
static const PDU::PDUType pdu_flag = PDU::DOT11_END_CF_ACK;
|
||||
|
||||
/**
|
||||
* \brief Constructor for creating a 802.11 End-CF-Ack frame PDU
|
||||
*
|
||||
* Constructs a 802.11 PDU taking the destination and source
|
||||
* hardware addresses.
|
||||
*
|
||||
* \param dst_addr The destination hardware address.
|
||||
* \param target_addr The source hardware address.
|
||||
*/
|
||||
Dot11EndCFAck(const address_type &dst_addr = address_type(),
|
||||
const address_type &target_addr = address_type());
|
||||
|
||||
/**
|
||||
* \brief Constructs a Dot11EndCFAck frame object from a buffer
|
||||
* and adds all identifiable PDUs found in the buffer as children
|
||||
* of this one.
|
||||
*
|
||||
* If the next PDU is not recognized, then a RawPDU is used.
|
||||
*
|
||||
* If there is not enough size for the header in the buffer
|
||||
* or the input data is malformed, 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.
|
||||
*/
|
||||
Dot11EndCFAck(const uint8_t *buffer, uint32_t total_sz);
|
||||
|
||||
/**
|
||||
* \brief Clones this PDU.
|
||||
*
|
||||
* \sa PDU::clone
|
||||
*/
|
||||
Dot11EndCFAck *clone() const {
|
||||
return new Dot11EndCFAck(*this);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the PDU's type.
|
||||
* \sa PDU::pdu_type
|
||||
*/
|
||||
PDUType pdu_type() const { return pdu_flag; }
|
||||
|
||||
/**
|
||||
* \brief Check wether this PDU matches the specified flag.
|
||||
* \param flag The flag to match
|
||||
* \sa PDU::matches_flag
|
||||
*/
|
||||
bool matches_flag(PDUType flag) const {
|
||||
return flag == pdu_flag || Dot11Control::matches_flag(flag);
|
||||
}
|
||||
};
|
||||
|
||||
class Dot11Ack : public Dot11Control {
|
||||
public:
|
||||
/**
|
||||
* \brief This PDU's flag.
|
||||
*/
|
||||
static const PDU::PDUType pdu_flag = PDU::DOT11_ACK;
|
||||
|
||||
/**
|
||||
* \brief Constructor for creating a 802.11 Ack frame PDU
|
||||
*
|
||||
* Constructs a 802.11 PDU taking the destination and source
|
||||
* hardware addresses.
|
||||
*
|
||||
* \param dst_addr The destination hardware address.
|
||||
*/
|
||||
Dot11Ack(const address_type &dst_addr = address_type());
|
||||
|
||||
/**
|
||||
* \brief Constructs a Dot11Ack frame object from a buffer and
|
||||
* adds all identifiable PDUs found in the buffer as children of
|
||||
* this one.
|
||||
*
|
||||
* If the next PDU is not recognized, then a RawPDU is used.
|
||||
*
|
||||
* If there is not enough size for the header in the buffer
|
||||
* or the input data is malformed, 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.
|
||||
*/
|
||||
Dot11Ack(const uint8_t *buffer, uint32_t total_sz);
|
||||
|
||||
/**
|
||||
* \brief Clones this PDU.
|
||||
*
|
||||
* \sa PDU::clone
|
||||
*/
|
||||
Dot11Ack *clone() const {
|
||||
return new Dot11Ack(*this);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the PDU's type.
|
||||
* \sa PDU::pdu_type
|
||||
*/
|
||||
PDUType pdu_type() const { return pdu_flag; }
|
||||
|
||||
/**
|
||||
* \brief Check wether this PDU matches the specified flag.
|
||||
* \param flag The flag to match
|
||||
* \sa PDU::matches_flag
|
||||
*/
|
||||
bool matches_flag(PDUType flag) const {
|
||||
return flag == pdu_flag || Dot11Control::matches_flag(flag);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Class that represents an 802.11 Block Ack Request PDU.
|
||||
*/
|
||||
class Dot11BlockAckRequest : public Dot11ControlTA {
|
||||
public:
|
||||
/**
|
||||
* \brief This PDU's flag.
|
||||
*/
|
||||
static const PDU::PDUType pdu_flag = PDU::DOT11_BLOCK_ACK_REQ;
|
||||
|
||||
/**
|
||||
* \brief Constructor for creating a 802.11 Block Ack request frame PDU
|
||||
*
|
||||
* Constructs a 802.11 PDU taking the destination and source
|
||||
* hardware addresses.
|
||||
*
|
||||
* \param dst_addr The destination hardware address.
|
||||
* \param target_addr The source hardware address.
|
||||
*/
|
||||
Dot11BlockAckRequest(const address_type &dst_addr = address_type(),
|
||||
const address_type &target_addr = address_type());
|
||||
|
||||
/**
|
||||
* \brief Constructs a Dot11BlockAckRequest object from a buffer
|
||||
* and adds all identifiable PDUs found in the buffer as children
|
||||
* of this one.
|
||||
*
|
||||
* If the next PDU is not recognized, then a RawPDU is used.
|
||||
*
|
||||
* If there is not enough size for the header in the buffer
|
||||
* or the input data is malformed, 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.
|
||||
*/
|
||||
Dot11BlockAckRequest(const uint8_t *buffer, uint32_t total_sz);
|
||||
|
||||
/* Getter */
|
||||
|
||||
/**
|
||||
* \brief Getter for the bar control field.
|
||||
* \return The stored bar control field.
|
||||
*/
|
||||
small_uint<4> bar_control() const {
|
||||
#if TINS_IS_LITTLE_ENDIAN
|
||||
return _bar_control & 0xf;
|
||||
#else
|
||||
return (_bar_control >> 8) & 0xf;
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the start sequence field.
|
||||
* \return The stored start sequence.
|
||||
*/
|
||||
small_uint<12> start_sequence() const {
|
||||
#if TINS_IS_LITTLE_ENDIAN
|
||||
return (_start_sequence >> 4) & 0xfff;
|
||||
#else
|
||||
return (Endian::le_to_host<uint16_t>(_start_sequence) >> 4) & 0xfff;
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the fragment number field.
|
||||
* \return The stored fragment number field.
|
||||
*/
|
||||
small_uint<4> fragment_number() const {
|
||||
#if TINS_IS_LITTLE_ENDIAN
|
||||
return _start_sequence & 0xf;
|
||||
#else
|
||||
return (_start_sequence >> 8) & 0xf;
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Returns the 802.11 frame's header length.
|
||||
*
|
||||
* \return The header's size.
|
||||
* \sa PDU::header_size()
|
||||
*/
|
||||
uint32_t header_size() const;
|
||||
|
||||
/* Setter */
|
||||
|
||||
/**
|
||||
* \brief Setter for the bar control field.
|
||||
* \param bar The bar control field to be set.
|
||||
*/
|
||||
void bar_control(small_uint<4> bar);
|
||||
|
||||
/**
|
||||
* \brief Setter for the start sequence field.
|
||||
* \param bar The start sequence field to be set.
|
||||
*/
|
||||
void start_sequence(small_uint<12> seq);
|
||||
|
||||
/**
|
||||
* \brief Setter for the fragment number field.
|
||||
* \param frag The fragment number field to be set.
|
||||
*/
|
||||
void fragment_number(small_uint<4> frag);
|
||||
|
||||
/**
|
||||
* \brief Clones this PDU.
|
||||
*
|
||||
* \sa PDU::clone
|
||||
*/
|
||||
Dot11BlockAckRequest *clone() const {
|
||||
return new Dot11BlockAckRequest(*this);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the PDU's type.
|
||||
* \sa PDU::pdu_type
|
||||
*/
|
||||
PDUType pdu_type() const { return pdu_flag; }
|
||||
|
||||
/**
|
||||
* \brief Check wether this PDU matches the specified flag.
|
||||
* \param flag The flag to match
|
||||
* \sa PDU::matches_flag
|
||||
*/
|
||||
bool matches_flag(PDUType flag) const {
|
||||
return flag == pdu_flag || Dot11Control::matches_flag(flag);
|
||||
}
|
||||
protected:
|
||||
uint32_t write_ext_header(uint8_t *buffer, uint32_t total_sz);
|
||||
private:
|
||||
void init_block_ack();
|
||||
|
||||
uint16_t _bar_control;
|
||||
uint16_t _start_sequence;
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Class that represents an 802.11 block ack frame.
|
||||
*/
|
||||
class Dot11BlockAck : public Dot11ControlTA {
|
||||
public:
|
||||
/**
|
||||
* \brief This PDU's flag.
|
||||
*/
|
||||
static const PDU::PDUType pdu_flag = PDU::DOT11_BLOCK_ACK;
|
||||
|
||||
/**
|
||||
* The size of the bitmap field.
|
||||
*/
|
||||
static const size_t bitmap_size = 8;
|
||||
|
||||
/**
|
||||
* \brief Constructor for creating a 802.11 Block Ack frame PDU
|
||||
*
|
||||
* Constructs a 802.11 PDU taking the destination and source
|
||||
* hardware addresses.
|
||||
*
|
||||
* \param dst_addr The destination hardware address.
|
||||
* \param target_addr The source hardware address.
|
||||
*/
|
||||
Dot11BlockAck(const address_type &dst_addr = address_type(),
|
||||
const address_type &target_addr = address_type());
|
||||
|
||||
/**
|
||||
* \brief Constructs a Dot11BlockAck frame object from a buffer
|
||||
* and adds all identifiable PDUs found in the buffer as children
|
||||
* of this one.
|
||||
*
|
||||
* If the next PDU is not recognized, then a RawPDU is used.
|
||||
*
|
||||
* If there is not enough size for the header in the buffer
|
||||
* or the input data is malformed, 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.
|
||||
*/
|
||||
Dot11BlockAck(const uint8_t *buffer, uint32_t total_sz);
|
||||
|
||||
/* Getters */
|
||||
|
||||
/**
|
||||
* \brief Getter for the bar control field.
|
||||
* \return The stored bar control field.
|
||||
*/
|
||||
small_uint<4> bar_control() const {
|
||||
#if TINS_IS_LITTLE_ENDIAN
|
||||
return _bar_control & 0xf;
|
||||
#else
|
||||
return (_bar_control >> 8) & 0xf;
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the start sequence field.
|
||||
* \return The stored start sequence.
|
||||
*/
|
||||
small_uint<12> start_sequence() const {
|
||||
#if TINS_IS_LITTLE_ENDIAN
|
||||
return (_start_sequence >> 4) & 0xfff;
|
||||
#else
|
||||
return (Endian::le_to_host<uint16_t>(_start_sequence) >> 4) & 0xfff;
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the fragment number field.
|
||||
* \return The stored fragment number field.
|
||||
*/
|
||||
small_uint<4> fragment_number() const {
|
||||
#if TINS_IS_LITTLE_ENDIAN
|
||||
return _start_sequence & 0xf;
|
||||
#else
|
||||
return (_start_sequence >> 8) & 0xf;
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* \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;
|
||||
|
||||
/* Setters */
|
||||
|
||||
/**
|
||||
* \brief Setter for the bar control field.
|
||||
* \param bar The bar control field to be set.
|
||||
*/
|
||||
void bar_control(small_uint<4> bar);
|
||||
|
||||
/**
|
||||
* \brief Setter for the start sequence field.
|
||||
* \param bar The start sequence field to be set.
|
||||
*/
|
||||
void start_sequence(small_uint<12> seq);
|
||||
|
||||
/**
|
||||
* \brief Setter for the fragment number field.
|
||||
* \param frag The fragment number field to be set.
|
||||
*/
|
||||
void fragment_number(small_uint<4> frag);
|
||||
|
||||
/**
|
||||
* \brief Getter for the bitmap field.
|
||||
*
|
||||
* The returned pointer <b>must not</b> be free'd.
|
||||
*
|
||||
* \return The bitmap field.
|
||||
*/
|
||||
const uint8_t *bitmap() const { return _bitmap; }
|
||||
|
||||
/**
|
||||
* \brief Setter for the bitmap field.
|
||||
* \param bit The new bitmap field to be set.
|
||||
*/
|
||||
void bitmap(const uint8_t *bit);
|
||||
|
||||
/**
|
||||
* \brief Getter for the PDU's type.
|
||||
* \sa PDU::pdu_type
|
||||
*/
|
||||
PDUType pdu_type() const { return pdu_flag; }
|
||||
|
||||
/**
|
||||
* \brief Check wether this PDU matches the specified flag.
|
||||
* \param flag The flag to match
|
||||
* \sa PDU::matches_flag
|
||||
*/
|
||||
bool matches_flag(PDUType flag) const {
|
||||
return flag == pdu_flag || Dot11Control::matches_flag(flag);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Clones this PDU.
|
||||
*
|
||||
* \sa PDU::clone
|
||||
*/
|
||||
Dot11BlockAck *clone() const {
|
||||
return new Dot11BlockAck(*this);
|
||||
}
|
||||
private:
|
||||
void init_block_ack();
|
||||
uint32_t write_ext_header(uint8_t *buffer, uint32_t total_sz);
|
||||
|
||||
uint16_t _bar_control, _start_sequence;
|
||||
uint8_t _bitmap[bitmap_size];
|
||||
};
|
||||
} // namespace Tins
|
||||
#endif // TINS_DOT11_DOT11_CONTROL_H
|
||||
345
include/tins/dot11/dot11_data.h
Normal file
345
include/tins/dot11/dot11_data.h
Normal file
@@ -0,0 +1,345 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Matias Fontanini
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following disclaimer
|
||||
* in the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "../config.h"
|
||||
|
||||
#if !defined(TINS_DOT11_DOT11_DATA_H) && defined(HAVE_DOT11)
|
||||
#define TINS_DOT11_DOT11_DATA_H
|
||||
|
||||
#include "../dot11/dot11_base.h"
|
||||
|
||||
namespace Tins {
|
||||
class Dot11Data : public Dot11 {
|
||||
public:
|
||||
/**
|
||||
* \brief This PDU's flag.
|
||||
*/
|
||||
static const PDU::PDUType pdu_flag = PDU::DOT11_DATA;
|
||||
|
||||
/**
|
||||
* \brief Constructor for creating a 802.11 Data frame.
|
||||
*
|
||||
* Constructs a 802.11 Data frame taking the
|
||||
* destination and source hardware addresses.
|
||||
*
|
||||
* \param dst_hw_addr The destination hardware address.
|
||||
* \param src_hw_addr The source hardware address.
|
||||
*/
|
||||
Dot11Data(const address_type &dst_hw_addr = address_type(),
|
||||
const address_type &src_hw_addr = address_type());
|
||||
|
||||
/**
|
||||
* \brief Constructs a Dot11Data object from a buffer and adds
|
||||
* all identifiable PDUs found in the buffer as children of
|
||||
* this one.
|
||||
*
|
||||
* If the next PDU is not recognized, then a RawPDU is used.
|
||||
*
|
||||
* If there is not enough size for the header in the buffer
|
||||
* or the input data is malformed, 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.
|
||||
*/
|
||||
Dot11Data(const uint8_t *buffer, uint32_t total_sz);
|
||||
|
||||
/**
|
||||
* \brief Getter for the second address.
|
||||
*
|
||||
* \return The stored second address.
|
||||
*/
|
||||
address_type addr2() const { return _ext_header.addr2; }
|
||||
|
||||
/**
|
||||
* \brief Getter for the third address.
|
||||
*
|
||||
* \return The stored third address.
|
||||
*/
|
||||
address_type addr3() const { return _ext_header.addr3; }
|
||||
|
||||
/**
|
||||
* \brief Getter for the fragment number field.
|
||||
*
|
||||
* \return The stored fragment number.
|
||||
*/
|
||||
small_uint<4> frag_num() const {
|
||||
#if TINS_IS_LITTLE_ENDIAN
|
||||
return _ext_header.frag_seq & 0xf;
|
||||
#else
|
||||
return (_ext_header.frag_seq >> 8) & 0xf;
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the sequence number field.
|
||||
*
|
||||
* \return The stored sequence number.
|
||||
*/
|
||||
small_uint<12> seq_num() const {
|
||||
#if TINS_IS_LITTLE_ENDIAN
|
||||
return (_ext_header.frag_seq >> 4) & 0xfff;
|
||||
#else
|
||||
return (Endian::le_to_host<uint16_t>(_ext_header.frag_seq) >> 4) & 0xfff;
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the fourth address.
|
||||
*
|
||||
* \return The fourth address.
|
||||
*/
|
||||
address_type addr4() const { return _addr4; }
|
||||
|
||||
/**
|
||||
* \brief Setter for the second address.
|
||||
*
|
||||
* \param new_addr2 The second address to be set.
|
||||
*/
|
||||
void addr2(const address_type &new_addr2);
|
||||
|
||||
/**
|
||||
* \brief Setter for the third address.
|
||||
*
|
||||
* \param new_addr3 The third address to be set.
|
||||
*/
|
||||
void addr3(const address_type &new_addr3);
|
||||
|
||||
/**
|
||||
* \brief Setter for the fragment number field.
|
||||
*
|
||||
* \param new_frag_num The fragment number to be set.
|
||||
*/
|
||||
void frag_num(small_uint<4> new_frag_num);
|
||||
|
||||
/**
|
||||
* \brief Setter for the sequence number field.
|
||||
*
|
||||
* \param new_seq_num The sequence number to be set.
|
||||
*/
|
||||
void seq_num(small_uint<12> new_seq_num);
|
||||
|
||||
/**
|
||||
* \brief Setter for the fourth address field.
|
||||
*
|
||||
* \param new_addr4 The fourth address to be set.
|
||||
*/
|
||||
void addr4(const address_type &new_addr4);
|
||||
|
||||
/**
|
||||
* \brief Retrieves the frame's source address.
|
||||
*
|
||||
* This is a wrapper over the addr* member functions which
|
||||
* takes into account the value of the FromDS and ToDS bits.
|
||||
*
|
||||
* If FromDS == ToDS == 1, the return value is not defined.
|
||||
*/
|
||||
address_type src_addr() const {
|
||||
if(!from_ds() && !to_ds())
|
||||
return addr2();
|
||||
if(!from_ds() && to_ds())
|
||||
return addr2();
|
||||
return addr3();
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Retrieves the frame's destination address.
|
||||
*
|
||||
* This is a wrapper over the addr* member functions which
|
||||
* takes into account the value of the FromDS and ToDS bits.
|
||||
*
|
||||
* If FromDS == ToDS == 1, the return value is not defined.
|
||||
*/
|
||||
address_type dst_addr() const {
|
||||
if(!from_ds() && !to_ds())
|
||||
return addr1();
|
||||
if(!from_ds() && to_ds())
|
||||
return addr3();
|
||||
return addr1();
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Retrieves the frame's BSSID address.
|
||||
*
|
||||
* This is a wrapper over the addr* member functions which
|
||||
* takes into account the value of the FromDS and ToDS bits.
|
||||
*
|
||||
* If FromDS == ToDS == 1, the return value is not defined.
|
||||
*/
|
||||
address_type bssid_addr() const {
|
||||
if(!from_ds() && !to_ds())
|
||||
return addr3();
|
||||
if(!from_ds() && to_ds())
|
||||
return addr1();
|
||||
return addr2();
|
||||
}
|
||||
|
||||
/**
|
||||
* \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_flag; }
|
||||
|
||||
/**
|
||||
* \brief Check wether this PDU matches the specified flag.
|
||||
* \param flag The flag to match
|
||||
* \sa PDU::matches_flag
|
||||
*/
|
||||
bool matches_flag(PDUType flag) const {
|
||||
return flag == pdu_flag || Dot11::matches_flag(flag);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Clones this PDU.
|
||||
*
|
||||
* \sa PDU::clone
|
||||
*/
|
||||
Dot11Data *clone() const {
|
||||
return new Dot11Data(*this);
|
||||
}
|
||||
protected:
|
||||
TINS_BEGIN_PACK
|
||||
struct ExtendedHeader {
|
||||
uint8_t addr2[address_type::address_size];
|
||||
uint8_t addr3[address_type::address_size];
|
||||
uint16_t frag_seq;
|
||||
} TINS_END_PACK;
|
||||
|
||||
struct no_inner_pdu { };
|
||||
Dot11Data(const uint8_t *buffer, uint32_t total_sz, no_inner_pdu);
|
||||
|
||||
uint32_t init(const uint8_t *buffer, uint32_t total_sz);
|
||||
uint32_t write_ext_header(uint8_t *buffer, uint32_t total_sz);
|
||||
|
||||
uint32_t data_frame_size() {
|
||||
return Dot11::header_size() + sizeof(_ext_header) +
|
||||
((from_ds() && to_ds()) ? _addr4.size() : 0);
|
||||
}
|
||||
private:
|
||||
ExtendedHeader _ext_header;
|
||||
address_type _addr4;
|
||||
};
|
||||
|
||||
class Dot11QoSData : public Dot11Data {
|
||||
public:
|
||||
/**
|
||||
* \brief This PDU's flag.
|
||||
*/
|
||||
static const PDU::PDUType pdu_flag = PDU::DOT11_QOS_DATA;
|
||||
|
||||
/**
|
||||
* \brief Constructor for creating a 802.11 QoS Data PDU
|
||||
*
|
||||
* Constructs a 802.11 QoS Data PDU taking the
|
||||
* destination and source hardware addresses.
|
||||
*
|
||||
* \param dst_hw_addr The destination hardware address.
|
||||
* \param src_hw_addr The source hardware address.
|
||||
*/
|
||||
Dot11QoSData(const address_type &dst_hw_addr = address_type(),
|
||||
const address_type &src_hw_addr = address_type());
|
||||
|
||||
/**
|
||||
* \brief Constructors Dot11QoSData object from a buffer and adds
|
||||
* all identifiable PDUs found in the buffer as children of this
|
||||
* one.
|
||||
*
|
||||
* If the next PDU is not recognized, then a RawPDU is used.
|
||||
*
|
||||
* If there is not enough size for the header in the buffer
|
||||
* or the input data is malformed, 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.
|
||||
*/
|
||||
Dot11QoSData(const uint8_t *buffer, uint32_t total_sz);
|
||||
|
||||
/**
|
||||
* \brief Getter for the QOS Control field.
|
||||
*
|
||||
* \return The stored QOS Control field value.
|
||||
*/
|
||||
uint16_t qos_control() const { return Endian::le_to_host(_qos_control); }
|
||||
|
||||
/**
|
||||
* \brief Setter for the QOS Control field.
|
||||
*
|
||||
* \param new_qos_control The QOS Control to be set.
|
||||
*/
|
||||
void qos_control(uint16_t new_qos_control);
|
||||
|
||||
/**
|
||||
* \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;
|
||||
|
||||
/**
|
||||
* \brief Clones this PDU.
|
||||
*
|
||||
* \sa PDU::clone
|
||||
*/
|
||||
Dot11QoSData *clone() const {
|
||||
return new Dot11QoSData(*this);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the PDU's type.
|
||||
* \sa PDU::pdu_type
|
||||
*/
|
||||
PDUType pdu_type() const { return PDU::DOT11_QOS_DATA; }
|
||||
|
||||
/**
|
||||
* \brief Check wether this PDU matches the specified flag.
|
||||
* \param flag The flag to match
|
||||
* \sa PDU::matches_flag
|
||||
*/
|
||||
bool matches_flag(PDUType flag) const {
|
||||
return flag == PDU::DOT11_QOS_DATA || Dot11Data::matches_flag(flag);
|
||||
}
|
||||
private:
|
||||
uint32_t write_fixed_parameters(uint8_t *buffer, uint32_t total_sz);
|
||||
|
||||
|
||||
uint16_t _qos_control;
|
||||
};
|
||||
}
|
||||
|
||||
#endif // TINS_DOT11_DOT11_DATA_H
|
||||
1160
include/tins/dot11/dot11_mgmt.h
Normal file
1160
include/tins/dot11/dot11_mgmt.h
Normal file
File diff suppressed because it is too large
Load Diff
233
include/tins/dot11/dot11_probe.h
Normal file
233
include/tins/dot11/dot11_probe.h
Normal file
@@ -0,0 +1,233 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Matias Fontanini
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following disclaimer
|
||||
* in the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "../config.h"
|
||||
|
||||
#if !defined(TINS_DOT11_DOT11_PROBE_H) && defined(HAVE_DOT11)
|
||||
|
||||
#define TINS_DOT11_DOT11_PROBE_H
|
||||
|
||||
#include "../dot11/dot11_mgmt.h"
|
||||
|
||||
namespace Tins {
|
||||
/**
|
||||
* \brief Class representing an Probe Request frame in the IEEE 802.11 Protocol.
|
||||
*
|
||||
*/
|
||||
class Dot11ProbeRequest : public Dot11ManagementFrame {
|
||||
public:
|
||||
/**
|
||||
* \brief This PDU's flag.
|
||||
*/
|
||||
static const PDU::PDUType pdu_flag = PDU::DOT11_PROBE_REQ;
|
||||
|
||||
/**
|
||||
* \brief Constructor for creating a 802.11 Probe Request.
|
||||
*
|
||||
* Constructs a 802.11 Probe Request taking the
|
||||
* destination and source hardware address.
|
||||
*
|
||||
* \param dst_hw_addr The destination hardware address.
|
||||
* \param src_hw_addr The source hardware address.
|
||||
*/
|
||||
Dot11ProbeRequest(const address_type &dst_hw_addr = address_type(),
|
||||
const address_type &src_hw_addr = address_type());
|
||||
|
||||
/**
|
||||
* \brief Constructs a Dot11ProbeRequest object from a buffer
|
||||
* and adds all identifiable PDUs found in the buffer as children
|
||||
* of this one.
|
||||
*
|
||||
* If the next PDU is not recognized, then a RawPDU is used.
|
||||
*
|
||||
* If there is not enough size for the header in the buffer
|
||||
* or the input data is malformed, 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.
|
||||
*/
|
||||
Dot11ProbeRequest(const uint8_t *buffer, uint32_t total_sz);
|
||||
|
||||
/**
|
||||
* \brief Getter for the PDU's type.
|
||||
* \sa PDU::pdu_type
|
||||
*/
|
||||
PDUType pdu_type() const { return PDU::DOT11_PROBE_REQ; }
|
||||
|
||||
/**
|
||||
* \brief Check wether this PDU matches the specified flag.
|
||||
* \param flag The flag to match
|
||||
* \sa PDU::matches_flag
|
||||
*/
|
||||
bool matches_flag(PDUType flag) const {
|
||||
return flag == pdu_flag || Dot11ManagementFrame::matches_flag(flag);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Clones this PDU.
|
||||
*
|
||||
* \sa PDU::clone()
|
||||
*/
|
||||
Dot11ProbeRequest* clone() const {
|
||||
return new Dot11ProbeRequest(*this);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Class representing an Probe Response frame in the IEEE 802.11 Protocol.
|
||||
*
|
||||
*/
|
||||
class Dot11ProbeResponse : public Dot11ManagementFrame {
|
||||
public:
|
||||
/**
|
||||
* \brief This PDU's flag.
|
||||
*/
|
||||
static const PDU::PDUType pdu_flag = PDU::DOT11_PROBE_RESP;
|
||||
|
||||
/**
|
||||
* \brief Constructor for creating a 802.11 Probe Response.
|
||||
*
|
||||
* Constructs a 802.11 Probe Response taking the
|
||||
* destination and source hardware addresses.
|
||||
*
|
||||
* \param dst_hw_addr The destination hardware address.
|
||||
* \param src_hw_addr The source hardware address.
|
||||
*/
|
||||
Dot11ProbeResponse(const address_type &dst_hw_addr = address_type(),
|
||||
const address_type &src_hw_addr = address_type());
|
||||
|
||||
/**
|
||||
* \brief Constructs a Dot11ProbeResponse object from a buffer
|
||||
* and adds all identifiable PDUs found in the buffer as children
|
||||
* of this one.
|
||||
*
|
||||
* If the next PDU is not recognized, then a RawPDU is used.
|
||||
*
|
||||
* If there is not enough size for the header in the buffer
|
||||
* or the input data is malformed, 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.
|
||||
*/
|
||||
Dot11ProbeResponse(const uint8_t *buffer, uint32_t total_sz);
|
||||
|
||||
/**
|
||||
* \brief Getter for the timestamp field.
|
||||
*
|
||||
* \return The stored timestamp value.
|
||||
*/
|
||||
uint64_t timestamp() const { return Endian::le_to_host(_body.timestamp); }
|
||||
|
||||
/**
|
||||
* \brief Getter for the interval field.
|
||||
*
|
||||
* \return The stored interval value.
|
||||
*/
|
||||
uint16_t interval() const { return Endian::le_to_host(_body.interval); }
|
||||
|
||||
/**
|
||||
* \brief Getter for the Capabilities Information.
|
||||
*
|
||||
* \return A constant reference to the stored Capabilities
|
||||
* Information field.
|
||||
*/
|
||||
const capability_information& capabilities() const { return _body.capability;}
|
||||
|
||||
/**
|
||||
* \brief Getter for the Capabilities Information.
|
||||
*
|
||||
* \return A reference to the stored Capabilities Information
|
||||
* field.
|
||||
*/
|
||||
capability_information& capabilities() { return _body.capability;}
|
||||
|
||||
/**
|
||||
* \brief Setter for the timestamp field.
|
||||
*
|
||||
* \param new_timestamp The timestamp to be set.
|
||||
*/
|
||||
void timestamp(uint64_t new_timestamp);
|
||||
|
||||
/**
|
||||
* \brief Setter for the interval field.
|
||||
*
|
||||
* \param new_interval The interval to be set.
|
||||
*/
|
||||
void interval(uint16_t new_interval);
|
||||
|
||||
/**
|
||||
* \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;
|
||||
|
||||
/**
|
||||
* \brief Clones this PDU.
|
||||
*
|
||||
* \sa PDU::clone()
|
||||
*/
|
||||
Dot11ProbeResponse* clone() const {
|
||||
return new Dot11ProbeResponse(*this);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the PDU's type.
|
||||
* \sa PDU::pdu_type
|
||||
*/
|
||||
PDUType pdu_type() const { return pdu_flag; }
|
||||
|
||||
/**
|
||||
* \brief Check wether this PDU matches the specified flag.
|
||||
* \param flag The flag to match
|
||||
* \sa PDU::matches_flag
|
||||
*/
|
||||
bool matches_flag(PDUType flag) const {
|
||||
return flag == pdu_flag || Dot11ManagementFrame::matches_flag(flag);
|
||||
}
|
||||
protected:
|
||||
|
||||
private:
|
||||
TINS_BEGIN_PACK
|
||||
struct ProbeResp {
|
||||
uint64_t timestamp;
|
||||
uint16_t interval;
|
||||
capability_information capability;
|
||||
} TINS_END_PACK;
|
||||
|
||||
ProbeResp _body;
|
||||
|
||||
uint32_t write_fixed_parameters(uint8_t *buffer, uint32_t total_sz);
|
||||
};
|
||||
} // namespace Tins
|
||||
#endif // TINS_DOT11_DOT11_PROBE_H
|
||||
213
include/tins/dot1q.h
Normal file
213
include/tins/dot1q.h
Normal file
@@ -0,0 +1,213 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Matias Fontanini
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following disclaimer
|
||||
* in the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef TINS_DOT1Q_H
|
||||
#define TINS_DOT1Q_H
|
||||
|
||||
#include "pdu.h"
|
||||
#include "endianness.h"
|
||||
#include "small_uint.h"
|
||||
|
||||
namespace Tins {
|
||||
/**
|
||||
* \class Dot1Q
|
||||
* Represents an IEEE 802.1q PDU.
|
||||
*/
|
||||
class Dot1Q : public PDU {
|
||||
public:
|
||||
/**
|
||||
* This PDU's flag.
|
||||
*/
|
||||
static const PDU::PDUType pdu_flag = PDU::DOT1Q;
|
||||
|
||||
/**
|
||||
* Default constructor
|
||||
*/
|
||||
Dot1Q(small_uint<12> tag_id = 0, bool append_pad = true);
|
||||
|
||||
/**
|
||||
* \brief Constructs a Dot1Q object from a buffer and adds all
|
||||
* identifiable PDUs found in the buffer as children of this
|
||||
* one.
|
||||
*
|
||||
* If the next PDU is not recognized, then a RawPDU is used.
|
||||
*
|
||||
* If there is not enough size for a Dot1Q header in the buffer,
|
||||
* 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.
|
||||
*/
|
||||
Dot1Q(const uint8_t *buffer, uint32_t total_sz);
|
||||
|
||||
// Getters
|
||||
|
||||
/**
|
||||
* \brief Returns the header size.
|
||||
*
|
||||
* This metod overrides PDU::header_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;
|
||||
|
||||
/**
|
||||
* \brief Getter for the priority field.
|
||||
* \return The stored priority field value.
|
||||
*/
|
||||
small_uint<3> priority() const {
|
||||
return _header.priority;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the Canonical Format Identifier field.
|
||||
* \return The stored CFI field value.
|
||||
*/
|
||||
small_uint<1> cfi() const {
|
||||
return _header.cfi;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the VLAN ID field.
|
||||
* \return The stored VLAN ID field value.
|
||||
*/
|
||||
small_uint<12> id() const {
|
||||
#if TINS_IS_LITTLE_ENDIAN
|
||||
return _header.idL | (_header.idH << 8);
|
||||
#else
|
||||
return _header.id;
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the payload type field.
|
||||
* \return The stored type field value.
|
||||
*/
|
||||
uint16_t payload_type() const {
|
||||
return Endian::be_to_host(_header.type);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the PDU's type.
|
||||
* \sa PDU::pdu_type
|
||||
*/
|
||||
PDUType pdu_type() const { return pdu_flag; }
|
||||
|
||||
/**
|
||||
* \sa PDU::clone
|
||||
*/
|
||||
Dot1Q *clone() const {
|
||||
return new Dot1Q(*this);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Retrieves the flag indicating whether padding will be
|
||||
* appended at the end of this packet.
|
||||
*/
|
||||
bool append_padding() const {
|
||||
return _append_padding;
|
||||
}
|
||||
|
||||
// Setters
|
||||
|
||||
/**
|
||||
* \brief Setter for the priority field.
|
||||
* \param new_priority The new priority field value.
|
||||
*/
|
||||
void priority(small_uint<3> new_priority);
|
||||
|
||||
/**
|
||||
* \brief Setter for the Canonical Format Identifie field.
|
||||
* \param new_cfi The new CFI field value.
|
||||
*/
|
||||
void cfi(small_uint<1> new_cfi);
|
||||
|
||||
/**
|
||||
* \brief Setter for the VLAN ID field.
|
||||
* \param new_id The new VLAN ID field value.
|
||||
*/
|
||||
void id(small_uint<12> new_id);
|
||||
|
||||
/**
|
||||
* \brief Setter for the payload type field.
|
||||
* \param new_type The new type field value.
|
||||
*/
|
||||
void payload_type(uint16_t new_type);
|
||||
|
||||
/**
|
||||
* \brief Indicates whether the appropriate padding will be
|
||||
* at the end of the packet.
|
||||
*
|
||||
* This flag could be disabled in case two or more contiguous Dot1Q
|
||||
* PDUs are added to a packet. In that case, only the Dot1Q which is
|
||||
* closer to the link layer should add the padding at the end.
|
||||
*
|
||||
* \param value A boolean indicating whether padding will be appended.
|
||||
*/
|
||||
void append_padding(bool value);
|
||||
|
||||
/**
|
||||
* \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;
|
||||
private:
|
||||
void write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *parent);
|
||||
|
||||
TINS_BEGIN_PACK
|
||||
struct dot1q_hdr {
|
||||
#if TINS_IS_BIG_ENDIAN
|
||||
uint16_t priority:3,
|
||||
cfi:1,
|
||||
id:12;
|
||||
uint16_t type;
|
||||
#else
|
||||
uint16_t idH:4,
|
||||
cfi:1,
|
||||
priority:3,
|
||||
idL:8;
|
||||
uint16_t type;
|
||||
#endif
|
||||
} TINS_END_PACK;
|
||||
|
||||
static uint16_t get_id(const dot1q_hdr *hdr);
|
||||
|
||||
dot1q_hdr _header;
|
||||
bool _append_padding;
|
||||
};
|
||||
}
|
||||
|
||||
#endif // TINS_DOT1Q_H
|
||||
194
include/tins/dot3.h
Normal file
194
include/tins/dot3.h
Normal file
@@ -0,0 +1,194 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Matias Fontanini
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following disclaimer
|
||||
* in the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef TINS_DOT3_H
|
||||
#define TINS_DOT3_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include "macros.h"
|
||||
#include "pdu.h"
|
||||
#include "endianness.h"
|
||||
#include "hw_address.h"
|
||||
|
||||
namespace Tins {
|
||||
|
||||
/**
|
||||
* \class Dot3
|
||||
* \brief Class representing an IEEE 802.3 PDU.
|
||||
*/
|
||||
class Dot3 : public PDU {
|
||||
public:
|
||||
/**
|
||||
* \brief The address type.
|
||||
*/
|
||||
typedef HWAddress<6> address_type;
|
||||
|
||||
/**
|
||||
* \brief This PDU's flag.
|
||||
*/
|
||||
static const PDU::PDUType pdu_flag = PDU::IEEE802_3;
|
||||
|
||||
/**
|
||||
* \brief Represents the Dot3 broadcast address.
|
||||
*/
|
||||
static const address_type BROADCAST;
|
||||
|
||||
/**
|
||||
* \brief Constructor for creating an Dot3 PDU
|
||||
*
|
||||
* Constructor that builds an Dot3 PDU taking the interface name,
|
||||
* destination's and source's MAC.
|
||||
*
|
||||
* \param dst_hw_addr The destination hardware address.
|
||||
* \param src_hw_addr The source hardware address.
|
||||
* \param child The PDU which will be set as the inner PDU.
|
||||
*/
|
||||
Dot3(const address_type &dst_hw_addr = address_type(),
|
||||
const address_type &src_hw_addr = address_type());
|
||||
|
||||
/**
|
||||
* \brief Constructs a Dot3 object from a buffer and adds a
|
||||
* LLC object with the remaining data as the inner PDU.
|
||||
*
|
||||
* If there is not enough size for a Dot3 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.
|
||||
*/
|
||||
Dot3(const uint8_t *buffer, uint32_t total_sz);
|
||||
|
||||
/* Getters */
|
||||
/**
|
||||
* \brief Getter for the destination hardware address.
|
||||
*
|
||||
* \return The destination hardware address.
|
||||
*/
|
||||
address_type dst_addr() const { return _eth.dst_mac; }
|
||||
|
||||
/**
|
||||
* \brief Getter for the source hardware address.
|
||||
*
|
||||
* \return The source hardware address.
|
||||
*/
|
||||
address_type src_addr() const { return _eth.src_mac; }
|
||||
|
||||
/**
|
||||
* \brief Getter for the length field.
|
||||
* \return The length field value.
|
||||
*/
|
||||
uint16_t length() const { return Endian::be_to_host(_eth.length); };
|
||||
|
||||
/* Setters */
|
||||
|
||||
/**
|
||||
* \brief Setter for the destination hardware address.
|
||||
*
|
||||
* \param new_dst_mac The new destination hardware address.
|
||||
*/
|
||||
void dst_addr(const address_type &new_dst_mac);
|
||||
|
||||
/**
|
||||
* \brief Setter for the source hardware address.
|
||||
*
|
||||
* \param new_src_mac The new source hardware address.
|
||||
*/
|
||||
void src_addr(const address_type &new_src_mac);
|
||||
|
||||
/**
|
||||
* \brief Setter for the length field.
|
||||
*
|
||||
* \param new_length uint16_t with the new value of the length field.
|
||||
*/
|
||||
void length(uint16_t new_length);
|
||||
|
||||
/* Virtual methods */
|
||||
/**
|
||||
* \brief Returns the Dot3 frame's header length.
|
||||
*
|
||||
* \return An uint32_t with the header's size.
|
||||
* \sa PDU::header_size()
|
||||
*/
|
||||
uint32_t header_size() const;
|
||||
|
||||
#ifndef WIN32
|
||||
/**
|
||||
* \sa PDU::send()
|
||||
*/
|
||||
void send(PacketSender &sender, const NetworkInterface &iface);
|
||||
#endif // WIN32
|
||||
|
||||
/**
|
||||
* \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;
|
||||
|
||||
#ifndef WIN32
|
||||
/**
|
||||
* \sa PDU::recv_response
|
||||
*/
|
||||
PDU *recv_response(PacketSender &sender, const NetworkInterface &iface);
|
||||
#endif // WIN32
|
||||
|
||||
/**
|
||||
* \brief Getter for the PDU's type.
|
||||
* \sa PDU::pdu_type
|
||||
*/
|
||||
PDUType pdu_type() const { return pdu_flag; }
|
||||
|
||||
/**
|
||||
* \sa PDU::clone
|
||||
*/
|
||||
Dot3 *clone() const {
|
||||
return new Dot3(*this);
|
||||
}
|
||||
private:
|
||||
/**
|
||||
* Struct that represents the Ethernet II header
|
||||
*/
|
||||
TINS_BEGIN_PACK
|
||||
struct ethhdr {
|
||||
uint8_t dst_mac[address_type::address_size];
|
||||
uint8_t src_mac[address_type::address_size];
|
||||
uint16_t length;
|
||||
} TINS_END_PACK;
|
||||
|
||||
void write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *parent);
|
||||
|
||||
|
||||
ethhdr _eth;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
#endif // TINS_DOT3_H
|
||||
742
include/tins/eapol.h
Normal file
742
include/tins/eapol.h
Normal file
@@ -0,0 +1,742 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Matias Fontanini
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following disclaimer
|
||||
* in the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef TINS_EAPOL_H
|
||||
#define TINS_EAPOL_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include "pdu.h"
|
||||
#include "macros.h"
|
||||
#include "small_uint.h"
|
||||
#include "endianness.h"
|
||||
|
||||
|
||||
namespace Tins {
|
||||
|
||||
/** \cond
|
||||
* Forward declaration. Avoid header inclusion.
|
||||
*/
|
||||
class RSNInformation;
|
||||
/** \endcond */
|
||||
|
||||
/**
|
||||
* \class EAPOL
|
||||
* \brief Represents the EAP encapsulation over LAN.
|
||||
*/
|
||||
class EAPOL : public PDU {
|
||||
public:
|
||||
/**
|
||||
* \brief This PDU's flag.
|
||||
*/
|
||||
static const PDU::PDUType pdu_flag = PDU::EAPOL;
|
||||
|
||||
/**
|
||||
* The EAPOL type enum.
|
||||
*/
|
||||
enum EAPOLTYPE {
|
||||
RC4 = 1,
|
||||
RSN,
|
||||
EAPOL_WPA = 254
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Static method to instantiate the correct EAPOL subclass
|
||||
* based on a raw buffer.
|
||||
*
|
||||
* If no valid EAPOL type is detected, a null pointer is returned.
|
||||
*
|
||||
* \sa RC4EAPOL
|
||||
* \sa RSNEAPOL
|
||||
*
|
||||
* \param buffer The buffer from which the data will be taken.
|
||||
* \param total_sz The total size of the buffer.
|
||||
*/
|
||||
static EAPOL *from_bytes(const uint8_t *buffer, uint32_t total_sz);
|
||||
|
||||
/* Getters */
|
||||
|
||||
/**
|
||||
* \brief Getter for the version field.
|
||||
* \return The version field.
|
||||
*/
|
||||
uint8_t version() const { return _header.version; }
|
||||
|
||||
/**
|
||||
* \brief Getter for the packet type field.
|
||||
* \return The packet type field.
|
||||
*/
|
||||
uint8_t packet_type() const { return _header.packet_type; }
|
||||
|
||||
/**
|
||||
* \brief Getter for the length field.
|
||||
* \return The length field.
|
||||
*/
|
||||
uint16_t length() const { return Endian::be_to_host(_header.length); }
|
||||
|
||||
/**
|
||||
* \brief Getter for the type field.
|
||||
* \return The type field.
|
||||
*/
|
||||
uint8_t type() const { return _header.type; }
|
||||
|
||||
/* Setters */
|
||||
|
||||
/**
|
||||
* \brief Sets the version field.
|
||||
* \param new_version The new version to be set.
|
||||
*/
|
||||
void version(uint8_t new_version);
|
||||
|
||||
/**
|
||||
* \brief Sets the packet type field.
|
||||
* \param new_ptype The new packet type to be set.
|
||||
*/
|
||||
void packet_type(uint8_t new_ptype);
|
||||
|
||||
/**
|
||||
* \brief Sets the length field.
|
||||
* \param new_length The new length to be set.
|
||||
*/
|
||||
void length(uint16_t new_length);
|
||||
|
||||
/**
|
||||
* \brief Sets the type field.
|
||||
* \param new_type The new type to be set.
|
||||
*/
|
||||
void type(uint8_t new_type);
|
||||
|
||||
/**
|
||||
* \brief Getter for the PDU's type.
|
||||
* \return Returns the PDUType corresponding to the PDU.
|
||||
*/
|
||||
PDUType pdu_type() const { return PDU::EAPOL; }
|
||||
protected:
|
||||
/**
|
||||
* \brief Protected constructor that sets the packet_type and type fields.
|
||||
*/
|
||||
EAPOL(uint8_t packet_type, EAPOLTYPE type);
|
||||
|
||||
/**
|
||||
* \brief Constructor which creates an EAPOL object from a buffer.
|
||||
* \param buffer The buffer from which this PDU will be constructed.
|
||||
* \param total_sz The total size of the buffer.
|
||||
*/
|
||||
EAPOL(const uint8_t *buffer, uint32_t total_sz);
|
||||
|
||||
TINS_BEGIN_PACK
|
||||
struct eapolhdr {
|
||||
uint8_t version, packet_type;
|
||||
uint16_t length;
|
||||
uint8_t type;
|
||||
} TINS_END_PACK;
|
||||
|
||||
/**
|
||||
* \brief Virtual method which should serialize the subclass specific
|
||||
* body and save it in a byte array.
|
||||
*
|
||||
* \param buffer The pointer in which to save the serialization.
|
||||
* \param total_sz The total size of the buffer.
|
||||
*/
|
||||
virtual void write_body(uint8_t *buffer, uint32_t total_sz) = 0;
|
||||
private:
|
||||
/**
|
||||
* \brief Serialices this EAPOL PDU.
|
||||
* \param buffer The buffer in which the PDU will be serialized.
|
||||
* \param total_sz The size available in the buffer.
|
||||
* \param parent The PDU that's one level below this one on the stack.
|
||||
*/
|
||||
void write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *parent);
|
||||
|
||||
eapolhdr _header;
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* \brief Class that represents the RC4 EAPOL PDU.
|
||||
*/
|
||||
class RC4EAPOL : public EAPOL {
|
||||
public:
|
||||
/**
|
||||
* The type used to store the key.
|
||||
*/
|
||||
typedef std::vector<uint8_t> key_type;
|
||||
|
||||
/**
|
||||
* This PDU's flag.
|
||||
*/
|
||||
static const PDU::PDUType pdu_flag = PDU::RC4EAPOL;
|
||||
|
||||
/**
|
||||
* The length of the key IV field
|
||||
*/
|
||||
static const size_t key_iv_size = 16;
|
||||
|
||||
/**
|
||||
* The length of the key sign field
|
||||
*/
|
||||
static const size_t key_sign_size = 16;
|
||||
|
||||
/**
|
||||
* \brief Default constructor.
|
||||
*/
|
||||
RC4EAPOL();
|
||||
|
||||
/**
|
||||
* \brief Constructs a RC4EAPOL object from a buffer.
|
||||
*
|
||||
* If there is not enough size for a RC4EAPOL header in the
|
||||
* buffer, 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.
|
||||
*/
|
||||
RC4EAPOL(const uint8_t *buffer, uint32_t total_sz);
|
||||
|
||||
/* Getters */
|
||||
|
||||
/**
|
||||
* \brief Getter for the key length field.
|
||||
* \return The key length field.
|
||||
*/
|
||||
uint16_t key_length() const { return Endian::be_to_host(_header.key_length); }
|
||||
|
||||
/**
|
||||
* \brief Getter for the replay counter field.
|
||||
* \return The replay counter field.
|
||||
*/
|
||||
uint64_t replay_counter() const { return Endian::be_to_host(_header.replay_counter); }
|
||||
|
||||
/**
|
||||
* \brief Getter for the key IV field.
|
||||
* \return The key IV field.
|
||||
*/
|
||||
const uint8_t *key_iv() const { return _header.key_iv; }
|
||||
|
||||
/**
|
||||
* \brief Getter for the key flag field.
|
||||
* \return The key flag field.
|
||||
*/
|
||||
small_uint<1> key_flag() const { return _header.key_flag; }
|
||||
|
||||
/**
|
||||
* \brief Getter for the key index field.
|
||||
* \return The key index field.
|
||||
*/
|
||||
small_uint<7> key_index() const { return _header.key_index; }
|
||||
|
||||
/**
|
||||
* \brief Getter for the key signature field.
|
||||
* \return The key signature field.
|
||||
*/
|
||||
const uint8_t *key_sign() const { return _header.key_sign; }
|
||||
|
||||
/**
|
||||
* \brief Getter for the key field.
|
||||
* \return The key field.
|
||||
*/
|
||||
const key_type &key() const { return _key; }
|
||||
|
||||
/* Setters */
|
||||
|
||||
/**
|
||||
* \brief Sets the key length field.
|
||||
* \param new_key_length The new key length to be set.
|
||||
*/
|
||||
void key_length(uint16_t new_key_length);
|
||||
|
||||
/**
|
||||
* \brief Sets the replay counter field.
|
||||
* \param new_replay_counter The new replay counter to be set.
|
||||
*/
|
||||
void replay_counter(uint64_t new_replay_counter);
|
||||
|
||||
/**
|
||||
* \brief Sets the key IV field.
|
||||
* \param new_key_iv The new key IV to be set.
|
||||
*/
|
||||
void key_iv(const uint8_t *new_key_iv);
|
||||
|
||||
/**
|
||||
* \brief Sets the key flag field.
|
||||
* \param new_key_flag The new key flag to be set.
|
||||
*/
|
||||
void key_flag(small_uint<1> new_key_flag);
|
||||
|
||||
/**
|
||||
* \brief Sets the key index field.
|
||||
* \param new_key_index The new key index to be set.
|
||||
*/
|
||||
void key_index(small_uint<7> new_key_index);
|
||||
|
||||
/**
|
||||
* \brief Sets the key signature field.
|
||||
* \param new_key_sign The new key signature to be set.
|
||||
*/
|
||||
void key_sign(const uint8_t *new_key_sign);
|
||||
|
||||
/**
|
||||
* \brief Sets the key field.
|
||||
* \param new_key The new key to be set.
|
||||
*/
|
||||
void key(const key_type &new_key);
|
||||
|
||||
/* Virtual method override. */
|
||||
|
||||
/**
|
||||
* \brief Returns the header size.
|
||||
*
|
||||
* This metod overrides PDU::header_size. This size includes the
|
||||
* payload and options size.
|
||||
*
|
||||
* \sa PDU::header_size
|
||||
*/
|
||||
uint32_t header_size() const;
|
||||
|
||||
/**
|
||||
* \brief Getter for the PDU's type.
|
||||
* \return Returns the PDUType corresponding to the PDU.
|
||||
*/
|
||||
PDUType pdu_type() const { return PDU::RC4EAPOL; }
|
||||
|
||||
/**
|
||||
* \brief Check wether this PDU matches the specified flag.
|
||||
* \param flag The flag to match
|
||||
* \sa PDU::matches_flag
|
||||
*/
|
||||
bool matches_flag(PDUType flag) const {
|
||||
return flag == PDU::RC4EAPOL || EAPOL::matches_flag(flag);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Clones this PDU.
|
||||
*
|
||||
* \sa PDU::clone
|
||||
*/
|
||||
RC4EAPOL *clone() const {
|
||||
return new RC4EAPOL(*this);
|
||||
}
|
||||
private:
|
||||
TINS_BEGIN_PACK
|
||||
struct rc4hdr {
|
||||
uint16_t key_length;
|
||||
uint64_t replay_counter;
|
||||
uint8_t key_iv[key_iv_size];
|
||||
uint8_t key_index:7,
|
||||
key_flag:1;
|
||||
uint8_t key_sign[16];
|
||||
} TINS_END_PACK;
|
||||
|
||||
void write_body(uint8_t *buffer, uint32_t total_sz);
|
||||
|
||||
|
||||
key_type _key;
|
||||
rc4hdr _header;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* \brief Class that represents the RSN EAPOL PDU.
|
||||
*/
|
||||
class RSNEAPOL : public EAPOL {
|
||||
public:
|
||||
/**
|
||||
* The type used to store the key.
|
||||
*/
|
||||
typedef std::vector<uint8_t> key_type;
|
||||
|
||||
/**
|
||||
* \brief This PDU's flag.
|
||||
*/
|
||||
static const PDU::PDUType pdu_flag = PDU::RSNEAPOL;
|
||||
|
||||
/**
|
||||
* The length of the key IV field
|
||||
*/
|
||||
static const size_t key_iv_size = 16;
|
||||
|
||||
/**
|
||||
* The length of the nonce field
|
||||
*/
|
||||
static const size_t nonce_size = 32;
|
||||
|
||||
/**
|
||||
* The length of the mic field
|
||||
*/
|
||||
static const size_t mic_size = 16;
|
||||
|
||||
/**
|
||||
* The length of the rsc field
|
||||
*/
|
||||
static const size_t rsc_size = 8;
|
||||
|
||||
/**
|
||||
* The length of the id field
|
||||
*/
|
||||
static const size_t id_size = 8;
|
||||
|
||||
/**
|
||||
* \brief Creates an instance of RSNEAPOL.
|
||||
*/
|
||||
RSNEAPOL();
|
||||
|
||||
/**
|
||||
* \brief Constructs a RSNEAPOL object from a buffer.
|
||||
*
|
||||
* If there is not enough size for the RSNEAPOL 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.
|
||||
*/
|
||||
RSNEAPOL(const uint8_t *buffer, uint32_t total_sz);
|
||||
|
||||
/* Getters */
|
||||
|
||||
/**
|
||||
* \brief Getter for the key length field.
|
||||
* \return The key length field.
|
||||
*/
|
||||
uint16_t key_length() const { return Endian::be_to_host(_header.key_length); }
|
||||
|
||||
/**
|
||||
* \brief Getter for the replay counter field.
|
||||
* \return The replay counter field.
|
||||
*/
|
||||
uint64_t replay_counter() const { return Endian::be_to_host(_header.replay_counter); }
|
||||
|
||||
/**
|
||||
* \brief Getter for the key IV field.
|
||||
* \return The key IV field.
|
||||
*/
|
||||
const uint8_t *key_iv() const { return _header.key_iv; }
|
||||
|
||||
/**
|
||||
* \brief Getter for the nonce field.
|
||||
* \return The nonce field.
|
||||
*/
|
||||
const uint8_t *nonce() const { return _header.nonce; }
|
||||
|
||||
/**
|
||||
* \brief Getter for the rsc field.
|
||||
* \return The rsc field.
|
||||
*/
|
||||
const uint8_t *rsc() const { return _header.rsc; }
|
||||
|
||||
/**
|
||||
* \brief Getter for the id field.
|
||||
* \return The id field.
|
||||
*/
|
||||
const uint8_t *id() const { return _header.id; }
|
||||
|
||||
/**
|
||||
* \brief Getter for the mic field.
|
||||
* \return The mic field.
|
||||
*/
|
||||
const uint8_t *mic() const { return _header.mic; }
|
||||
|
||||
/**
|
||||
* \brief Getter for the wpa length field.
|
||||
* \return The wpa length field.
|
||||
*/
|
||||
uint16_t wpa_length() const { return Endian::be_to_host(_header.wpa_length); }
|
||||
|
||||
/**
|
||||
* \brief Getter for the key field.
|
||||
* \return The key field.
|
||||
*/
|
||||
const key_type &key() const { return _key; }
|
||||
|
||||
/**
|
||||
* \brief Getter for the key mic field.
|
||||
* \return 1 if this EAPOL PDU contains a valid MIC, 0 otherwise.
|
||||
*/
|
||||
small_uint<1> key_mic() const { return _header.key_mic; };
|
||||
|
||||
/**
|
||||
* \brief Getter for the secure field.
|
||||
* \return The secure field.
|
||||
*/
|
||||
small_uint<1> secure() const { return _header.secure; };
|
||||
|
||||
/**
|
||||
* \brief Getter for the error field.
|
||||
* \return The error field.
|
||||
*/
|
||||
small_uint<1> error() const { return _header.error; };
|
||||
|
||||
/**
|
||||
* \brief Getter for the request field.
|
||||
* \return The request field.
|
||||
*/
|
||||
small_uint<1> request() const { return _header.request; };
|
||||
|
||||
/**
|
||||
* \brief Getter for the encrypted field.
|
||||
* \return The encrypted field.
|
||||
*/
|
||||
small_uint<1> encrypted() const { return _header.encrypted; };
|
||||
|
||||
/**
|
||||
* \brief Getter for the key descriptor field.
|
||||
* \return The key descriptor field.
|
||||
*/
|
||||
small_uint<3> key_descriptor() const { return _header.key_descriptor; };
|
||||
|
||||
/**
|
||||
* \brief Getter for the key type field.
|
||||
*
|
||||
* \return 1 if this is a pairwise key, 0 otherwise.
|
||||
*/
|
||||
small_uint<1> key_t() const { return _header.key_t; };
|
||||
|
||||
/**
|
||||
* \brief Getter for the key_index field.
|
||||
* \return The key_index field.
|
||||
*/
|
||||
small_uint<2> key_index() const { return _header.key_index; };
|
||||
|
||||
/**
|
||||
* \brief Getter for the install field.
|
||||
* \return The install field.
|
||||
*/
|
||||
small_uint<1> install() const { return _header.install; };
|
||||
|
||||
/**
|
||||
* \brief Getter for the key_ack field.
|
||||
* \return The key_ack field.
|
||||
*/
|
||||
small_uint<1> key_ack() const { return _header.key_ack; };
|
||||
|
||||
/**
|
||||
* \brief Returns the header size.
|
||||
*
|
||||
* This metod overrides PDU::header_size. This size includes the
|
||||
* payload and options size.
|
||||
*
|
||||
* \sa PDU::header_size
|
||||
*/
|
||||
uint32_t header_size() const;
|
||||
|
||||
/* Setters */
|
||||
|
||||
/**
|
||||
* \brief Sets the key length field.
|
||||
* \param new_key_length The new key length to be set.
|
||||
*/
|
||||
void key_length(uint16_t new_key_length);
|
||||
|
||||
/**
|
||||
* \brief Sets the replay counter field.
|
||||
* \param new_replay_counter The new replay counter to be set.
|
||||
*/
|
||||
void replay_counter(uint64_t new_replay_counter);
|
||||
|
||||
/**
|
||||
* \brief Sets the key IV field.
|
||||
* \param new_key_iv The new key IV to be set.
|
||||
*/
|
||||
void key_iv(const uint8_t *new_key_iv);
|
||||
|
||||
/**
|
||||
* \brief Sets the nonce field.
|
||||
*
|
||||
* This method sets the nonce field. This field is 32 bytes long,
|
||||
* therefore the input buffer should be at least that length.
|
||||
* \param new_nonce The new nonce to be set.
|
||||
*/
|
||||
void nonce(const uint8_t *new_nonce);
|
||||
|
||||
/**
|
||||
* \brief Sets the rsc field.
|
||||
* \param new_rsc The new rsc to be set.
|
||||
*/
|
||||
void rsc(const uint8_t *new_rsc);
|
||||
|
||||
/**
|
||||
* \brief Sets the id field.
|
||||
* \param new_id The new id to be set.
|
||||
*/
|
||||
void id(const uint8_t *new_id);
|
||||
|
||||
/**
|
||||
* \brief Sets the mic field.
|
||||
*
|
||||
* This method sets the mic field. This field is 16 bytes long,
|
||||
* therefore the input buffer should be at least that length.
|
||||
* \param new_mic The new mic to be set.
|
||||
*/
|
||||
void mic(const uint8_t *new_mic);
|
||||
|
||||
/**
|
||||
* \brief Sets the wpa length field.
|
||||
* \param new_wpa_length The new wpa length to be set.
|
||||
*/
|
||||
void wpa_length(uint16_t new_wpa_length);
|
||||
|
||||
/**
|
||||
* \brief Sets the key field.
|
||||
* \param new_key The new key to be set.
|
||||
*/
|
||||
void key(const key_type &new_key);
|
||||
|
||||
/**
|
||||
* \brief Setter for the key_mic field.
|
||||
* \param new_key_mic The new to be set.
|
||||
*/
|
||||
void key_mic(small_uint<1> new_key_mic);
|
||||
|
||||
/**
|
||||
* \brief Setter for the secure field.
|
||||
* \param new_secure The new to be set.
|
||||
*/
|
||||
void secure(small_uint<1> new_secure);
|
||||
|
||||
/**
|
||||
* \brief Setter for the error field.
|
||||
* \param new_error The new to be set.
|
||||
*/
|
||||
void error(small_uint<1> new_error);
|
||||
|
||||
/**
|
||||
* \brief Setter for the request field.
|
||||
* \param new_request The new to be set.
|
||||
*/
|
||||
void request(small_uint<1> new_request);
|
||||
|
||||
/**
|
||||
* \brief Setter for the encrypted field.
|
||||
* \param new_encrypted The new to be set.
|
||||
*/
|
||||
void encrypted(small_uint<1 > new_encrypted);
|
||||
|
||||
/**
|
||||
* \brief Setter for the key_descriptor field.
|
||||
* \param new_key_descriptor The new to be set.
|
||||
*/
|
||||
void key_descriptor(small_uint<3> new_key_descriptor);
|
||||
|
||||
/**
|
||||
* \brief Setter for the key_t field.
|
||||
* \param new_key_t The new to be set.
|
||||
*/
|
||||
void key_t(small_uint<1> new_key_t);
|
||||
|
||||
/**
|
||||
* \brief Setter for the key_index field.
|
||||
* \param new_key_index The new to be set.
|
||||
*/
|
||||
void key_index(small_uint<2> new_key_index);
|
||||
|
||||
/**
|
||||
* \brief Setter for the install field.
|
||||
* \param new_install The new to be set.
|
||||
*/
|
||||
void install(small_uint<1> new_install);
|
||||
|
||||
/**
|
||||
* \brief Setter for the key_ack field.
|
||||
* \param new_key_ack The new to be set.
|
||||
*/
|
||||
void key_ack(small_uint<1> new_key_ack);
|
||||
|
||||
/**
|
||||
* \brief Getter for the PDU's type.
|
||||
* \return Returns the PDUType corresponding to the PDU.
|
||||
*/
|
||||
PDUType pdu_type() const { return PDU::RSNEAPOL; }
|
||||
|
||||
/**
|
||||
* \brief Check wether this PDU matches the specified flag.
|
||||
* \param flag The flag to match
|
||||
* \sa PDU::matches_flag
|
||||
*/
|
||||
bool matches_flag(PDUType flag) const {
|
||||
return flag == PDU::RSNEAPOL || EAPOL::matches_flag(flag);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Clones this PDU.
|
||||
*
|
||||
* \sa PDU::clone
|
||||
*/
|
||||
RSNEAPOL *clone() const {
|
||||
return new RSNEAPOL(*this);
|
||||
}
|
||||
private:
|
||||
TINS_BEGIN_PACK
|
||||
struct rsnhdr {
|
||||
#if TINS_IS_LITTLE_ENDIAN
|
||||
uint16_t key_mic:1,
|
||||
secure:1,
|
||||
error:1,
|
||||
request:1,
|
||||
encrypted:1,
|
||||
reserved:3,
|
||||
key_descriptor:3,
|
||||
key_t:1,
|
||||
key_index:2,
|
||||
install:1,
|
||||
key_ack:1;
|
||||
uint16_t key_length;
|
||||
uint64_t replay_counter;
|
||||
uint8_t nonce[nonce_size], key_iv[key_iv_size];
|
||||
uint8_t rsc[rsc_size], id[id_size];
|
||||
uint8_t mic[mic_size];
|
||||
uint16_t wpa_length;
|
||||
#else
|
||||
uint16_t reserved:3,
|
||||
encrypted:1,
|
||||
request:1,
|
||||
error:1,
|
||||
secure:1,
|
||||
key_mic:1,
|
||||
key_ack:1,
|
||||
install:1,
|
||||
key_index:2,
|
||||
key_t:1,
|
||||
key_descriptor:3;
|
||||
uint16_t key_length;
|
||||
uint64_t replay_counter;
|
||||
uint8_t nonce[nonce_size], key_iv[key_iv_size];
|
||||
uint8_t rsc[rsc_size], id[id_size];
|
||||
uint8_t mic[mic_size];
|
||||
uint16_t wpa_length;
|
||||
#endif
|
||||
} TINS_END_PACK;
|
||||
|
||||
void write_body(uint8_t *buffer, uint32_t total_sz);
|
||||
|
||||
|
||||
rsnhdr _header;
|
||||
key_type _key;
|
||||
};
|
||||
}
|
||||
|
||||
#endif // TINS_EAPOL_H
|
||||
237
include/tins/endianness.h
Normal file
237
include/tins/endianness.h
Normal file
@@ -0,0 +1,237 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Matias Fontanini
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following disclaimer
|
||||
* in the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef TINS_ENDIANNESS_H
|
||||
#define TINS_ENDIANNESS_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include "macros.h"
|
||||
|
||||
#if defined(__APPLE__)
|
||||
#include <sys/types.h>
|
||||
#define TINS_IS_LITTLE_ENDIAN (BYTE_ORDER == LITTLE_ENDIAN)
|
||||
#define TINS_IS_BIG_ENDIAN (BYTE_ORDER == BIG_ENDIAN)
|
||||
#elif defined(BSD)
|
||||
#include <sys/endian.h>
|
||||
#define TINS_IS_LITTLE_ENDIAN (_BYTE_ORDER == _LITTLE_ENDIAN)
|
||||
#define TINS_IS_BIG_ENDIAN (_BYTE_ORDER == _BIG_ENDIAN)
|
||||
#elif defined(WIN32)
|
||||
// Assume windows == little endian. fixme later
|
||||
#define TINS_IS_LITTLE_ENDIAN 1
|
||||
#define TINS_IS_BIG_ENDIAN 0
|
||||
#else
|
||||
#include <endian.h>
|
||||
#define TINS_IS_LITTLE_ENDIAN (__BYTE_ORDER == __LITTLE_ENDIAN)
|
||||
#define TINS_IS_BIG_ENDIAN (__BYTE_ORDER == __BIG_ENDIAN)
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
namespace Tins {
|
||||
namespace Endian {
|
||||
/**
|
||||
* \brief "Changes" a 8-bit integral value's endianess. This is an
|
||||
* identity function.
|
||||
*
|
||||
* \param data The data to convert.
|
||||
*/
|
||||
inline uint8_t do_change_endian(uint8_t data) {
|
||||
return data;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Changes a 16-bit integral value's endianess.
|
||||
*
|
||||
* \param data The data to convert.
|
||||
*/
|
||||
inline uint16_t do_change_endian(uint16_t data) {
|
||||
return ((data & 0xff00) >> 8) | ((data & 0x00ff) << 8);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Changes a 32-bit integral value's endianess.
|
||||
*
|
||||
* \param data The data to convert.
|
||||
*/
|
||||
inline uint32_t do_change_endian(uint32_t data) {
|
||||
return (((data & 0xff000000) >> 24) | ((data & 0x00ff0000) >> 8) |
|
||||
((data & 0x0000ff00) << 8) | ((data & 0x000000ff) << 24));
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Changes a 64-bit integral value's endianess.
|
||||
*
|
||||
* \param data The data to convert.
|
||||
*/
|
||||
inline uint64_t do_change_endian(uint64_t data) {
|
||||
return (((uint64_t)(do_change_endian((uint32_t)(data & 0xffffffff))) << 32) |
|
||||
(do_change_endian(((uint32_t)(data >> 32)))));
|
||||
}
|
||||
|
||||
/**
|
||||
* \cond
|
||||
*/
|
||||
|
||||
// Helpers to convert
|
||||
template<typename T>
|
||||
struct conversion_dispatch_helper {
|
||||
static T dispatch(T data) {
|
||||
return do_change_endian(data);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template<size_t>
|
||||
struct conversion_dispatcher;
|
||||
|
||||
template<>
|
||||
struct conversion_dispatcher<sizeof(uint8_t)>
|
||||
: public conversion_dispatch_helper<uint8_t>
|
||||
{ };
|
||||
|
||||
template<>
|
||||
struct conversion_dispatcher<sizeof(uint16_t)>
|
||||
: public conversion_dispatch_helper<uint16_t>
|
||||
{ };
|
||||
|
||||
template<>
|
||||
struct conversion_dispatcher<sizeof(uint32_t)>
|
||||
: public conversion_dispatch_helper<uint32_t>
|
||||
{ };
|
||||
|
||||
template<>
|
||||
struct conversion_dispatcher<sizeof(uint64_t)>
|
||||
: public conversion_dispatch_helper<uint64_t>
|
||||
{ };
|
||||
|
||||
/**
|
||||
* \endcond
|
||||
*/
|
||||
|
||||
/**
|
||||
* \brief Changes an integral value's endianess.
|
||||
*
|
||||
* This dispatchs to the corresponding function.
|
||||
*
|
||||
* \param data The data to convert.
|
||||
*/
|
||||
template<typename T>
|
||||
inline T change_endian(T data) {
|
||||
return conversion_dispatcher<sizeof(T)>::dispatch(data);
|
||||
}
|
||||
|
||||
#if TINS_IS_LITTLE_ENDIAN
|
||||
/**
|
||||
* \brief Convert any integral type to big endian.
|
||||
*
|
||||
* \param data The data to convert.
|
||||
*/
|
||||
template<typename T>
|
||||
inline T host_to_be(T data) {
|
||||
return change_endian(data);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Convert any integral type to little endian.
|
||||
*
|
||||
* On little endian platforms, the parameter is simply returned.
|
||||
*
|
||||
* \param data The data to convert.
|
||||
*/
|
||||
template<typename T>
|
||||
inline T host_to_le(T data) {
|
||||
return data;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Convert any big endian value to the host's endianess.
|
||||
*
|
||||
* \param data The data to convert.
|
||||
*/
|
||||
template<typename T>
|
||||
inline T be_to_host(T data) {
|
||||
return change_endian(data);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Convert any little endian value to the host's endianess.
|
||||
*
|
||||
* \param data The data to convert.
|
||||
*/
|
||||
template<typename T>
|
||||
inline T le_to_host(T data) {
|
||||
return data;
|
||||
}
|
||||
#elif TINS_IS_BIG_ENDIAN
|
||||
/**
|
||||
* \brief Convert any integral type to big endian.
|
||||
*
|
||||
* \param data The data to convert.
|
||||
*/
|
||||
template<typename T>
|
||||
inline T host_to_be(T data) {
|
||||
return data;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Convert any integral type to little endian.
|
||||
*
|
||||
* On little endian platforms, the parameter is simply returned.
|
||||
*
|
||||
* \param data The data to convert.
|
||||
*/
|
||||
template<typename T>
|
||||
inline T host_to_le(T data) {
|
||||
return change_endian(data);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Convert any big endian value to the host's endianess.
|
||||
*
|
||||
* \param data The data to convert.
|
||||
*/
|
||||
template<typename T>
|
||||
inline T be_to_host(T data) {
|
||||
return data;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Convert any little endian value to the host's endianess.
|
||||
*
|
||||
* \param data The data to convert.
|
||||
*/
|
||||
template<typename T>
|
||||
inline T le_to_host(T data) {
|
||||
return change_endian(data);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
#endif // TINS_ENDIANNESS_H
|
||||
205
include/tins/ethernetII.h
Normal file
205
include/tins/ethernetII.h
Normal file
@@ -0,0 +1,205 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Matias Fontanini
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following disclaimer
|
||||
* in the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef TINS_ETHERNET_II_H
|
||||
#define TINS_ETHERNET_II_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include "macros.h"
|
||||
#include "pdu.h"
|
||||
#include "endianness.h"
|
||||
#include "hw_address.h"
|
||||
|
||||
namespace Tins {
|
||||
|
||||
/**
|
||||
* \class EthernetII
|
||||
* \brief Represents an Ethernet II PDU.
|
||||
*/
|
||||
class EthernetII : public PDU {
|
||||
public:
|
||||
/**
|
||||
* \brief The hardware address type.
|
||||
*/
|
||||
typedef HWAddress<6> address_type;
|
||||
|
||||
/**
|
||||
* \brief This PDU's flag.
|
||||
*/
|
||||
static const PDU::PDUType pdu_flag = PDU::ETHERNET_II;
|
||||
|
||||
/**
|
||||
* \brief Represents the ethernetII broadcast address.
|
||||
*/
|
||||
static const address_type BROADCAST;
|
||||
|
||||
/**
|
||||
* \brief Constructs an ethernet II PDU.
|
||||
*
|
||||
* \param dst_hw_addr address_type containing the destination's MAC.
|
||||
* \param src_hw_addr address_type containing the source's MAC.
|
||||
*/
|
||||
EthernetII(const address_type &dst_hw_addr = address_type(),
|
||||
const address_type &src_hw_addr = address_type());
|
||||
|
||||
/**
|
||||
* \brief Constructs a EthernetII object from a buffer and adds
|
||||
* all identifiable PDUs found in the buffer as children of
|
||||
* this one.
|
||||
*
|
||||
* If the next PDU is not recognized, then a RawPDU is used.
|
||||
*
|
||||
* If there is not enough size for a EthernetII header in the
|
||||
* buffer, 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.
|
||||
*/
|
||||
EthernetII(const uint8_t *buffer, uint32_t total_sz);
|
||||
|
||||
/* Getters */
|
||||
/**
|
||||
* \brief Getter for the destination's hardware address.
|
||||
*
|
||||
* \return address_type containing the destination hardware
|
||||
* address.
|
||||
*/
|
||||
address_type dst_addr() const { return _eth.dst_mac; }
|
||||
|
||||
/**
|
||||
* \brief Getter for the source's hardware address.
|
||||
*
|
||||
* \return address_type containing the source hardware address.
|
||||
*/
|
||||
address_type src_addr() const { return _eth.src_mac; }
|
||||
|
||||
/**
|
||||
* \brief Getter for the payload_type
|
||||
* \return The payload type.
|
||||
*/
|
||||
uint16_t payload_type() const { return Endian::be_to_host(_eth.payload_type); };
|
||||
|
||||
/* Setters */
|
||||
|
||||
/**
|
||||
* \brief Setter for the destination hardware address.
|
||||
*
|
||||
* \param new_dst_addr the destination hardware address to be set.
|
||||
*/
|
||||
void dst_addr(const address_type &new_dst_addr);
|
||||
|
||||
/**
|
||||
* \brief Setter for the source hardware address.
|
||||
*
|
||||
* \param new_src_addr the source hardware address to be set.
|
||||
*/
|
||||
void src_addr(const address_type &new_src_addr);
|
||||
|
||||
/**
|
||||
* \brief Setter for the payload type.
|
||||
*
|
||||
* \param new_payload_type the new value of the payload type field.
|
||||
*/
|
||||
void payload_type(uint16_t new_payload_type);
|
||||
|
||||
/* Virtual methods */
|
||||
/**
|
||||
* \brief Returns the ethernet 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 ethernet II frame's padding.
|
||||
*
|
||||
* \return An uint32_t with the padding size.
|
||||
* \sa PDU::trailer_size()
|
||||
*/
|
||||
uint32_t trailer_size() const;
|
||||
|
||||
// Windows does not support sending L2 PDUs.
|
||||
#ifndef WIN32
|
||||
/**
|
||||
* \sa PDU::send()
|
||||
*/
|
||||
void send(PacketSender &sender, const NetworkInterface &iface);
|
||||
#endif // WIN32
|
||||
|
||||
/**
|
||||
* \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;
|
||||
|
||||
#ifndef WIN32
|
||||
/**
|
||||
* \brief Receives a matching response for this packet.
|
||||
*
|
||||
* \sa PDU::recv_response
|
||||
*/
|
||||
PDU *recv_response(PacketSender &sender, const NetworkInterface &iface);
|
||||
#endif // WIN32
|
||||
|
||||
/**
|
||||
* \brief Getter for the PDU's type.
|
||||
* \sa PDU::pdu_type
|
||||
*/
|
||||
PDUType pdu_type() const { return PDU::ETHERNET_II; }
|
||||
|
||||
/**
|
||||
* \sa PDU::clone
|
||||
*/
|
||||
EthernetII *clone() const {
|
||||
return new EthernetII(*this);
|
||||
}
|
||||
private:
|
||||
/**
|
||||
* Struct that represents the Ethernet II header
|
||||
*/
|
||||
TINS_BEGIN_PACK
|
||||
struct ethhdr {
|
||||
uint8_t dst_mac[address_type::address_size];
|
||||
uint8_t src_mac[address_type::address_size];
|
||||
uint16_t payload_type;
|
||||
} TINS_END_PACK;
|
||||
|
||||
void write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *parent);
|
||||
|
||||
ethhdr _eth;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif // TINS_ETHERNET_II_H
|
||||
173
include/tins/exceptions.h
Normal file
173
include/tins/exceptions.h
Normal file
@@ -0,0 +1,173 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Matias Fontanini
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following disclaimer
|
||||
* in the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef TINS_EXCEPTIONS_H
|
||||
#define TINS_EXCEPTIONS_H
|
||||
|
||||
#include <string>
|
||||
#include <stdexcept>
|
||||
|
||||
namespace Tins {
|
||||
/**
|
||||
* \brief Exception thrown when an option is not found.
|
||||
*/
|
||||
class option_not_found : public std::runtime_error {
|
||||
public:
|
||||
option_not_found()
|
||||
: std::runtime_error(std::string()) { }
|
||||
|
||||
// try to avoid allocations by doing this.
|
||||
const char* what() const throw() {
|
||||
return "Option not found";
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Exception thrown when a malformed packet is parsed.
|
||||
*/
|
||||
class malformed_packet : public std::runtime_error {
|
||||
public:
|
||||
malformed_packet()
|
||||
: std::runtime_error(std::string()) { }
|
||||
|
||||
const char* what() const throw() {
|
||||
return "Malformed packet";
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Exception thrown when a PDU is not found when using PDU::rfind_pdu.
|
||||
*/
|
||||
class pdu_not_found : public std::runtime_error {
|
||||
public:
|
||||
pdu_not_found()
|
||||
: std::runtime_error(std::string()) { }
|
||||
|
||||
const char* what() const throw() {
|
||||
return "PDU not found";
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Exception thrown when PDU::send requires a valid interface,
|
||||
* but an invalid is used.
|
||||
*/
|
||||
class invalid_interface : public std::runtime_error {
|
||||
public:
|
||||
invalid_interface()
|
||||
: std::runtime_error(std::string()) { }
|
||||
|
||||
const char* what() const throw() {
|
||||
return "Invalid interface";
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Exception thrown when PacketSender fails to open a socket.
|
||||
*/
|
||||
class socket_open_error : public std::runtime_error {
|
||||
public:
|
||||
socket_open_error(const std::string &msg)
|
||||
: std::runtime_error(msg) { }
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Exception thrown when PacketSender fails to close a socket.
|
||||
*/
|
||||
class socket_close_error : public std::runtime_error {
|
||||
public:
|
||||
socket_close_error(const std::string &msg)
|
||||
: std::runtime_error(msg) { }
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Exception thrown when PacketSender fails to write on a socket.
|
||||
*/
|
||||
class socket_write_error : public std::runtime_error {
|
||||
public:
|
||||
socket_write_error(const std::string &msg)
|
||||
: std::runtime_error(msg) { }
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Exception thrown when an invalid socket type is provided
|
||||
* to PacketSender.
|
||||
*/
|
||||
class invalid_socket_type : public std::exception {
|
||||
public:
|
||||
const char *what() const throw() {
|
||||
return "The provided socket type is invalid";
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Exception thrown when an unkown link layer PDU type is
|
||||
* found while sniffing.
|
||||
*/
|
||||
class unknown_link_type : public std::exception {
|
||||
public:
|
||||
const char *what() const throw() {
|
||||
return "The sniffed link layer PDU type is unknown";
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Exception thrown when a malformed option is found.
|
||||
*/
|
||||
class malformed_option : public std::exception {
|
||||
public:
|
||||
const char *what() const throw() {
|
||||
return "Malformed option";
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Exception thrown when a call to tins_cast fails.
|
||||
*/
|
||||
class bad_tins_cast : public std::exception {
|
||||
public:
|
||||
const char *what() const throw() {
|
||||
return "Bad Tins cast";
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Exception thrown when sniffing a protocol that
|
||||
* has been disabled at compile time.
|
||||
*/
|
||||
class protocol_disabled : public std::exception {
|
||||
public:
|
||||
const char *what() const throw() {
|
||||
return "Protocol disabled";
|
||||
}
|
||||
};
|
||||
|
||||
} // Tins
|
||||
|
||||
#endif // TINS_EXCEPTIONS_H
|
||||
169
include/tins/handshake_capturer.h
Normal file
169
include/tins/handshake_capturer.h
Normal file
@@ -0,0 +1,169 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Matias Fontanini
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following disclaimer
|
||||
* in the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#if !defined(TINS_HANDSHAKE_CAPTURER_H) && defined(HAVE_DOT11)
|
||||
#define TINS_HANDSHAKE_CAPTURER_H
|
||||
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <utility>
|
||||
#include "hw_address.h"
|
||||
#include "eapol.h"
|
||||
|
||||
// .h
|
||||
namespace Tins {
|
||||
/**
|
||||
* \brief Generic EAPOL handshake.
|
||||
*
|
||||
* Stores both the client and supplicant addresses, as well as
|
||||
* all of the EAPOL packets used during the handshake.
|
||||
*/
|
||||
template<typename T>
|
||||
class EAPOLHandshake {
|
||||
public:
|
||||
typedef std::vector<T> container_type;
|
||||
typedef HWAddress<6> address_type;
|
||||
|
||||
/**
|
||||
* \brief Default constructor.
|
||||
*/
|
||||
EAPOLHandshake() { }
|
||||
|
||||
/**
|
||||
* Constructs an EAPOLHandshake object.
|
||||
*
|
||||
* \param client_address The client address.
|
||||
* \param supplicant_address The supplicant address.
|
||||
* \param cont The container that holds the EAPOL packets used
|
||||
* in the handshake.
|
||||
*/
|
||||
EAPOLHandshake(const address_type &client_address,
|
||||
const address_type &supplicant_address, const container_type &cont)
|
||||
: cl_address_(client_address), suppl_address_(supplicant_address),
|
||||
handshake_(cont)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* \return const address_type&
|
||||
*/
|
||||
const address_type &client_address() const {
|
||||
return cl_address_;
|
||||
}
|
||||
|
||||
/**
|
||||
* \return const address_type&
|
||||
*/
|
||||
const address_type &supplicant_address() const {
|
||||
return suppl_address_;
|
||||
}
|
||||
|
||||
/**
|
||||
* \return const container_type&
|
||||
*/
|
||||
const container_type &handshake() const {
|
||||
return handshake_;
|
||||
}
|
||||
private:
|
||||
address_type cl_address_, suppl_address_;
|
||||
container_type handshake_;
|
||||
};
|
||||
|
||||
/**
|
||||
* The type used to store RSN handshakes.
|
||||
*/
|
||||
typedef EAPOLHandshake<RSNEAPOL> RSNHandshake;
|
||||
|
||||
/**
|
||||
* Captures 802.1X RSN handshakes.
|
||||
*/
|
||||
class RSNHandshakeCapturer {
|
||||
public:
|
||||
/**
|
||||
* The type of handshakes that will be captured.
|
||||
*/
|
||||
typedef RSNHandshake handshake_type;
|
||||
|
||||
/**
|
||||
* The type in which all of the captured handshakes
|
||||
* will be stored.
|
||||
*/
|
||||
typedef std::vector<handshake_type> handshakes_type;
|
||||
|
||||
/**
|
||||
* \brief Processes a packet.
|
||||
*
|
||||
* This will fetch the RSNEAPOL layer, if any, and store
|
||||
* it in an intermediate storage. When a handshake is
|
||||
* completed, it will be stored separately.
|
||||
*
|
||||
* \sa RSNHandshakeCapturer::handshakes
|
||||
*/
|
||||
bool process_packet(const PDU &pdu);
|
||||
|
||||
/**
|
||||
* \brief Retrieves the completed handshakes.
|
||||
*
|
||||
* This will return the handshakes that have been completed
|
||||
* so far. A handshake is completed when the 4-way handshake
|
||||
* is captured.
|
||||
*
|
||||
* \sa RSNHandshakeCapturer::clear_handshakes
|
||||
*/
|
||||
const handshakes_type &handshakes() const {
|
||||
return completed_handshakes_;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Clears the completed handshakes.
|
||||
*
|
||||
* Since completed handshakes are stored in a std::vector,
|
||||
* it is advisable to remove all of them once they have been
|
||||
* processed.
|
||||
*/
|
||||
void clear_handshakes() {
|
||||
completed_handshakes_.clear();
|
||||
}
|
||||
private:
|
||||
typedef handshake_type::address_type address_type;
|
||||
typedef handshake_type::container_type eapol_list;
|
||||
typedef std::map<std::pair<address_type, address_type>, eapol_list> handshake_map;
|
||||
|
||||
bool do_insert(const handshake_map::key_type &key, const RSNEAPOL *eapol,
|
||||
size_t expected);
|
||||
|
||||
handshake_map handshakes_;
|
||||
handshakes_type completed_handshakes_;
|
||||
};
|
||||
}
|
||||
|
||||
#endif // TINS_HANDSHAKE_CAPTURER_H
|
||||
404
include/tins/hw_address.h
Normal file
404
include/tins/hw_address.h
Normal file
@@ -0,0 +1,404 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Matias Fontanini
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following disclaimer
|
||||
* in the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef TINS_HWADDRESS_H
|
||||
#define TINS_HWADDRESS_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdexcept>
|
||||
#include <iterator>
|
||||
#include <algorithm>
|
||||
#include <iomanip>
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include "cxxstd.h"
|
||||
|
||||
namespace Tins {
|
||||
/**
|
||||
* \class HWAddress
|
||||
* \brief Represents a hardware address.
|
||||
*
|
||||
* This class represents a hardware (MAC) address. It can
|
||||
* be constructed from it's string representation and you can
|
||||
* iterate over the bytes that compose it.
|
||||
*
|
||||
* For example:
|
||||
*
|
||||
* \code
|
||||
* // Construct it from a string.
|
||||
* HWAddress<6> address("00:01:fa:9e:1a:cd");
|
||||
*
|
||||
* // Iterate over its bytes.
|
||||
* for(auto element : address) {
|
||||
* // element will be each of the bytes(\x00, \x01, \xfa, etc)
|
||||
* }
|
||||
* \endcode
|
||||
*/
|
||||
template<size_t n, typename Storage = uint8_t>
|
||||
class HWAddress {
|
||||
public:
|
||||
/**
|
||||
* \brief The type of the elements stored in the hardware address.
|
||||
*
|
||||
* This is the same as the template parameter Storage.
|
||||
*/
|
||||
typedef Storage storage_type;
|
||||
|
||||
/**
|
||||
* \brief The random access iterator type.
|
||||
*/
|
||||
typedef storage_type* iterator;
|
||||
|
||||
/**
|
||||
* \brief Const iterator type.
|
||||
*/
|
||||
typedef const storage_type* const_iterator;
|
||||
|
||||
/**
|
||||
* \brief Non-member constant indicating the amount of storage_type
|
||||
* elements in this address.
|
||||
*/
|
||||
static const size_t address_size = n;
|
||||
|
||||
/**
|
||||
* \brief The broadcast address.
|
||||
*/
|
||||
static const HWAddress<n, Storage> broadcast;
|
||||
|
||||
/**
|
||||
* \brief Constructor from a const storage_type*.
|
||||
*
|
||||
* If no pointer or a null pointer is provided, the address is
|
||||
* initialized to 00:00:00:00:00:00.
|
||||
*
|
||||
* This constructor is very usefull when passing zero initialized
|
||||
* addresses as arguments to other functions. You can use a
|
||||
* literal 0, which will be implicitly converted to the empty address.
|
||||
*
|
||||
* If a pointer is provided, address_size storage_type elements
|
||||
* are copied from the pointer, into the internal address representation.
|
||||
*
|
||||
* \param ptr The pointer from which to construct this address.
|
||||
*/
|
||||
HWAddress(const storage_type* ptr = 0) {
|
||||
if(ptr)
|
||||
std::copy(ptr, ptr + address_size, buffer);
|
||||
else
|
||||
std::fill(begin(), end(), storage_type());
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Constructs an address from a hex-notation address.
|
||||
*
|
||||
* This constructor will parse strings in the form:
|
||||
*
|
||||
* "00:01:da:fa:..."
|
||||
*
|
||||
* And initialize the internal representation accordingly.
|
||||
*
|
||||
* \param address The hex-notation address to be parsed.
|
||||
*/
|
||||
HWAddress(const std::string &address) {
|
||||
convert(address, buffer);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Overload provided basically for string literals.
|
||||
*
|
||||
* This constructor takes a const char array of i elements in
|
||||
* hex-notation. \sa HWAddress::HWAddress(const std::string &address)
|
||||
*
|
||||
* This is mostly used when providing string literals. If this where
|
||||
* a const char*, then there would be an ambiguity when providing
|
||||
* a null pointer.
|
||||
*
|
||||
* \param address The array of chars containing the hex-notation
|
||||
* cstring to be parsed.
|
||||
*/
|
||||
template<size_t i>
|
||||
HWAddress(const char (&address)[i]) {
|
||||
convert(address, buffer);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Copy construct from a HWAddress of length i.
|
||||
*
|
||||
* If i is lower or equal than address_size, then i storage_type
|
||||
* elements are copied, and the last (n - i) are initialized to
|
||||
* the default storage_type value(0 most of the times).
|
||||
*
|
||||
* If i is larger than address_size, then only the first address_size
|
||||
* elements are copied.
|
||||
*
|
||||
* \param rhs The HWAddress to be constructed from.
|
||||
*/
|
||||
template<size_t i>
|
||||
HWAddress(const HWAddress<i> &rhs) {
|
||||
// Fill extra bytes
|
||||
std::fill(
|
||||
// Copy as most as we can
|
||||
std::copy(
|
||||
rhs.begin(),
|
||||
rhs.begin() + std::min(i, n),
|
||||
begin()
|
||||
),
|
||||
end(),
|
||||
0
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Retrieves an iterator pointing to the begining of the
|
||||
* address.
|
||||
*
|
||||
* \return iterator.
|
||||
*/
|
||||
iterator begin() {
|
||||
return buffer;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Retrieves a const iterator pointing to the begining of
|
||||
* the address.
|
||||
*
|
||||
* \return const_iterator.
|
||||
*/
|
||||
const_iterator begin() const {
|
||||
return buffer;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Retrieves an iterator pointing one-past-the-end of the
|
||||
* address.
|
||||
*
|
||||
* \return iterator.
|
||||
*/
|
||||
iterator end() {
|
||||
return buffer + address_size;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Retrieves a const iterator pointing one-past-the-end of
|
||||
* the address.
|
||||
*
|
||||
* \return const_iterator.
|
||||
*/
|
||||
const_iterator end() const {
|
||||
return buffer + address_size;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Compares this HWAddress for equality.
|
||||
*
|
||||
* \param rhs The HWAddress to be compared to.
|
||||
*
|
||||
* \return bool indicating whether addresses are equal.
|
||||
*/
|
||||
bool operator==(const HWAddress &rhs) const {
|
||||
return std::equal(begin(), end(), rhs.begin());
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Compares this HWAddress for in-equality.
|
||||
*
|
||||
* \param rhs The HWAddress to be compared to.
|
||||
*
|
||||
* \return bool indicating whether addresses are distinct.
|
||||
*/
|
||||
bool operator!=(const HWAddress &rhs) const {
|
||||
return !(*this == rhs);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Compares this HWAddress for less-than inequality.
|
||||
*
|
||||
* \param rhs The HWAddress to be compared to.
|
||||
*
|
||||
* \return bool indicating whether this address is less-than rhs.
|
||||
*/
|
||||
bool operator<(const HWAddress &rhs) const {
|
||||
return std::lexicographical_compare(begin(), end(), rhs.begin(), rhs.end());
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Retrieves the size of this address.
|
||||
*
|
||||
* This effectively returns the address_size constant.
|
||||
*/
|
||||
const size_t size() const {
|
||||
return address_size;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Indicates whether this is a broadcast address.
|
||||
*/
|
||||
bool is_broadcast() const {
|
||||
return *this == broadcast;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Indicates whether this is a multicast address.
|
||||
*/
|
||||
bool is_multicast() const {
|
||||
return (buffer[0] & 0x01);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Indicates whether this is an unicast address.
|
||||
*/
|
||||
bool is_unicast() const {
|
||||
return !is_broadcast() && !is_multicast();
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Convert this address to a hex-notation std::string address.
|
||||
*
|
||||
* \return std::string containing the hex-notation address.
|
||||
*/
|
||||
std::string to_string() const {
|
||||
std::ostringstream oss;
|
||||
oss << *this;
|
||||
return oss.str();
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Retrieves the i-th storage_type in this address.
|
||||
*
|
||||
* \param i The element to retrieve.
|
||||
*/
|
||||
storage_type operator[](size_t i) const {
|
||||
return buffer[i];
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Writes this HWAddress in hex-notation to a std::ostream.
|
||||
*
|
||||
* \param os The stream in which to write the address.
|
||||
* \param addr The parameter to be written.
|
||||
* \return std::ostream& pointing to the os parameter.
|
||||
*/
|
||||
friend std::ostream &operator<<(std::ostream &os, const HWAddress &addr) {
|
||||
std::transform(
|
||||
addr.begin(),
|
||||
addr.end() - 1,
|
||||
std::ostream_iterator<std::string>(os, ":"),
|
||||
&HWAddress::storage_to_string
|
||||
);
|
||||
return os << storage_to_string(addr.buffer[HWAddress::address_size-1]);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Helper function which copies the address into an output
|
||||
* iterator.
|
||||
*
|
||||
* This is the same as:
|
||||
*
|
||||
* std::copy(begin(), end(), iter);
|
||||
*
|
||||
* But since some PDUs return a HWAddress<> by value, this function
|
||||
* can be used to avoid temporaries.
|
||||
*
|
||||
* \param iter The output iterator in which to store this address.
|
||||
* \return OutputIterator pointing to one-past the last position
|
||||
* written.
|
||||
*/
|
||||
template<typename OutputIterator>
|
||||
OutputIterator copy(OutputIterator iter) const {
|
||||
return std::copy(begin(), end(), iter);
|
||||
}
|
||||
private:
|
||||
template<typename OutputIterator>
|
||||
static void convert(const std::string &hw_addr, OutputIterator output);
|
||||
|
||||
static std::string storage_to_string(storage_type element) {
|
||||
std::ostringstream oss;
|
||||
oss << std::hex;
|
||||
if(element < 0x10)
|
||||
oss << '0';
|
||||
oss << (unsigned)element;
|
||||
return oss.str();
|
||||
}
|
||||
|
||||
storage_type buffer[n];
|
||||
};
|
||||
|
||||
template<size_t n, typename Storage>
|
||||
template<typename OutputIterator>
|
||||
void HWAddress<n, Storage>::convert(const std::string &hw_addr,
|
||||
OutputIterator output)
|
||||
{
|
||||
unsigned i(0);
|
||||
size_t count(0);
|
||||
storage_type tmp;
|
||||
while(i < hw_addr.size() && count < n) {
|
||||
const unsigned end = i+2;
|
||||
tmp = storage_type();
|
||||
while(i < end) {
|
||||
if(hw_addr[i] >= 'a' && hw_addr[i] <= 'f')
|
||||
tmp = (tmp << 4) | (hw_addr[i] - 'a' + 10);
|
||||
else if(hw_addr[i] >= 'A' && hw_addr[i] <= 'F')
|
||||
tmp = (tmp << 4) | (hw_addr[i] - 'A' + 10);
|
||||
else if(hw_addr[i] >= '0' && hw_addr[i] <= '9')
|
||||
tmp = (tmp << 4) | (hw_addr[i] - '0');
|
||||
else if(hw_addr[i] == ':')
|
||||
break;
|
||||
else
|
||||
throw std::runtime_error("Invalid byte found");
|
||||
i++;
|
||||
}
|
||||
*(output++) = tmp;
|
||||
count++;
|
||||
if(i < hw_addr.size()) {
|
||||
if(hw_addr[i] == ':')
|
||||
i++;
|
||||
else
|
||||
throw std::runtime_error("Invalid separator");
|
||||
}
|
||||
}
|
||||
while(count++ < n) {
|
||||
*(output++) = storage_type();
|
||||
}
|
||||
}
|
||||
|
||||
template<size_t n, typename Storage>
|
||||
const HWAddress<n, Storage> HWAddress<n, Storage>::broadcast("ff:ff:ff:ff:ff:ff");
|
||||
} // namespace Tins
|
||||
#if TINS_IS_CXX11
|
||||
namespace std
|
||||
{
|
||||
template<size_t n>
|
||||
struct hash<Tins::HWAddress<n>> {
|
||||
size_t operator()(const Tins::HWAddress<n> &addr) const {
|
||||
return std::hash<std::string>()(addr.to_string());
|
||||
}
|
||||
};
|
||||
} // namespace std
|
||||
#endif
|
||||
#endif // TINS_HWADDRESS_H
|
||||
408
include/tins/icmp.h
Normal file
408
include/tins/icmp.h
Normal file
@@ -0,0 +1,408 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Matias Fontanini
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following disclaimer
|
||||
* in the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef TINS_ICMP_H
|
||||
#define TINS_ICMP_H
|
||||
|
||||
// Windows likes to define macros with not-so-common-names, which break
|
||||
// this code
|
||||
#ifdef WIN32
|
||||
#ifdef TIMESTAMP_REQUEST
|
||||
#undef TIMESTAMP_REQUEST
|
||||
#endif // TIMESTAMP_REQUEST
|
||||
|
||||
#ifdef TIMESTAMP_REPLY
|
||||
#undef TIMESTAMP_REPLY
|
||||
#endif // TIMESTAMP_REPLY
|
||||
#endif // WIN32
|
||||
|
||||
#include "macros.h"
|
||||
#include "pdu.h"
|
||||
#include "endianness.h"
|
||||
#include "ip_address.h"
|
||||
|
||||
namespace Tins {
|
||||
|
||||
/**
|
||||
* \class ICMP
|
||||
* \brief Class that represents an ICMP PDU.
|
||||
*
|
||||
* ICMP is the representation of the ICMP PDU. Instances of this class
|
||||
* must be sent over a level 3 PDU, this will otherwise fail.
|
||||
*/
|
||||
class ICMP : public PDU {
|
||||
public:
|
||||
/**
|
||||
* \brief This PDU's flag.
|
||||
*/
|
||||
static const PDU::PDUType pdu_flag = PDU::ICMP;
|
||||
|
||||
/**
|
||||
* The type used to store addresses.
|
||||
*/
|
||||
typedef IPv4Address address_type;
|
||||
|
||||
/** \brief ICMP flags
|
||||
*/
|
||||
enum Flags {
|
||||
ECHO_REPLY = 0,
|
||||
DEST_UNREACHABLE = 3,
|
||||
SOURCE_QUENCH = 4,
|
||||
REDIRECT = 5,
|
||||
ECHO_REQUEST = 8,
|
||||
TIME_EXCEEDED = 11,
|
||||
PARAM_PROBLEM = 12,
|
||||
TIMESTAMP_REQUEST = 13,
|
||||
TIMESTAMP_REPLY = 14,
|
||||
INFO_REQUEST = 15,
|
||||
INFO_REPLY = 16,
|
||||
ADDRESS_MASK_REQUEST = 17,
|
||||
ADDRESS_MASK_REPLY = 18
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Creates an instance of ICMP.
|
||||
*
|
||||
* If no flag is specified, then ECHO_REQUEST will be used.
|
||||
* \param flag The type flag which will be set.
|
||||
*/
|
||||
ICMP(Flags flag = ECHO_REQUEST);
|
||||
|
||||
/**
|
||||
* \brief Constructs an ICMP object from a buffer.
|
||||
*
|
||||
* If there is not enough size for an ICMP header, a
|
||||
* malformed_packet exception is thrown.
|
||||
*
|
||||
* Any extra data in the buffer will be stored in a RawPDU.
|
||||
*
|
||||
* \param buffer The buffer from which this PDU will be constructed.
|
||||
* \param total_sz The total size of the buffer.
|
||||
*/
|
||||
ICMP(const uint8_t *buffer, uint32_t total_sz);
|
||||
|
||||
/**
|
||||
* \brief Sets the code field.
|
||||
*
|
||||
* \param new_code The code which will be stored in the ICMP struct.
|
||||
*/
|
||||
void code(uint8_t new_code);
|
||||
|
||||
/** \brief Sets the type field.
|
||||
*
|
||||
* \param type The type which will be stored in the ICMP struct.
|
||||
*/
|
||||
void type(Flags type);
|
||||
|
||||
/**
|
||||
* \brief Setter for the id field.
|
||||
*
|
||||
* \param new_id uint16_t with the new id.
|
||||
*/
|
||||
void id(uint16_t new_id);
|
||||
|
||||
/**
|
||||
* \brief Setter for the sequence field.
|
||||
*
|
||||
* \param new_seq uint16_t with the new sequence.
|
||||
*/
|
||||
void sequence(uint16_t new_seq);
|
||||
|
||||
/**
|
||||
* \brief Setter for the gateway field.
|
||||
*
|
||||
* \param new_gw The new value for the gateway field.
|
||||
*/
|
||||
void gateway(address_type new_gw);
|
||||
|
||||
/**
|
||||
* \brief Setter for the mtu field.
|
||||
*
|
||||
* \param new_mtu uint16_t with the new sequence.
|
||||
*/
|
||||
void mtu(uint16_t new_mtu);
|
||||
|
||||
/**
|
||||
* \brief Setter for the pointer field.
|
||||
*
|
||||
* \param new_pointer uint8_t with the new pointer.
|
||||
*/
|
||||
void pointer(uint8_t new_pointer);
|
||||
|
||||
/**
|
||||
* \brief Setter for the original timestamp field.
|
||||
*
|
||||
* \param new_timestamp the value to be set.
|
||||
*/
|
||||
void original_timestamp(uint32_t new_timestamp);
|
||||
|
||||
/**
|
||||
* \brief Setter for the receive timestamp field.
|
||||
*
|
||||
* \param new_timestamp the value to be set.
|
||||
*/
|
||||
void receive_timestamp(uint32_t new_timestamp);
|
||||
|
||||
/**
|
||||
* \brief Setter for the transmit timestamp field.
|
||||
*
|
||||
* \param new_timestamp the value to be set.
|
||||
*/
|
||||
void transmit_timestamp(uint32_t new_timestamp);
|
||||
|
||||
/**
|
||||
* \brief Setter for the address mask field.
|
||||
*
|
||||
* \param new_mask the value to be set.
|
||||
*/
|
||||
void address_mask(address_type new_mask);
|
||||
|
||||
/**
|
||||
* \brief Sets echo request flag for this PDU.
|
||||
*
|
||||
* \param id The identifier for this request.
|
||||
* \param seq The sequence number for this request.
|
||||
*/
|
||||
void set_echo_request(uint16_t id, uint16_t seq);
|
||||
|
||||
/**
|
||||
* \brief Sets echo reply flag for this PDU.
|
||||
*
|
||||
* \param id The identifier for this request.
|
||||
* \param seq The sequence number for this request.
|
||||
*/
|
||||
void set_echo_reply(uint16_t id, uint16_t seq);
|
||||
|
||||
/**
|
||||
* \brief Sets information request flag for this PDU.
|
||||
*
|
||||
* \param id The identifier for this request.
|
||||
* \param seq The sequence number for this request.
|
||||
*/
|
||||
void set_info_request(uint16_t id, uint16_t seq);
|
||||
|
||||
/**
|
||||
* \brief Sets information reply flag for this PDU.
|
||||
*
|
||||
* \param id The identifier for this request.
|
||||
* \param seq The sequence number for this request.
|
||||
*/
|
||||
void set_info_reply(uint16_t id, uint16_t seq);
|
||||
|
||||
/**
|
||||
* \brief Sets destination unreachable for this PDU.
|
||||
*/
|
||||
void set_dest_unreachable();
|
||||
|
||||
/**
|
||||
* \brief Sets time exceeded flag for this PDU.
|
||||
*
|
||||
* \param ttl_exceeded If true this PDU will represent a ICMP ttl
|
||||
* exceeded, otherwise it will represent a fragment reassembly
|
||||
* time exceeded.
|
||||
*/
|
||||
void set_time_exceeded(bool ttl_exceeded = true);
|
||||
|
||||
/**
|
||||
* \brief Sets parameter problem flag for this PDU.
|
||||
*
|
||||
* \param set_pointer Indicates wether a pointer to the bad octet
|
||||
* is provided.
|
||||
* \param bad_octet Identifies the octet in which the error was
|
||||
* detected. If set_pointer == false, it is ignored.
|
||||
*/
|
||||
void set_param_problem(bool set_pointer = false, uint8_t bad_octet = 0);
|
||||
|
||||
/**
|
||||
* \brief Sets source quench flag for this PDU.
|
||||
*/
|
||||
void set_source_quench();
|
||||
|
||||
/**
|
||||
* \brief Sets redirect flag for this PDU.
|
||||
*
|
||||
* \param icode The code to be set.
|
||||
* \param address Address of the gateway to which traffic should
|
||||
* be sent.
|
||||
*/
|
||||
void set_redirect(uint8_t icode, address_type address);
|
||||
|
||||
/**
|
||||
* \brief Getter for the ICMP type flag.
|
||||
*
|
||||
* \return The type flag for this ICMP PDU.
|
||||
*/
|
||||
Flags type() const { return (Flags)_icmp.type; }
|
||||
|
||||
/**
|
||||
* \brief Getter for the ICMP code flag.
|
||||
*
|
||||
* \return The code flag for this ICMP PDU.
|
||||
*/
|
||||
uint8_t code() const { return _icmp.code; }
|
||||
|
||||
/**
|
||||
* \brief Getter for the checksum field.
|
||||
*
|
||||
* \return Returns the checksum as an unit16_t.
|
||||
*/
|
||||
uint16_t checksum() const { return Endian::be_to_host(_icmp.check); }
|
||||
|
||||
/**
|
||||
* \brief Getter for the echo id.
|
||||
*
|
||||
* \return Returns the echo id.
|
||||
*/
|
||||
uint16_t id() const { return Endian::be_to_host(_icmp.un.echo.id); }
|
||||
|
||||
/**
|
||||
* \brief Getter for the echo sequence number.
|
||||
*
|
||||
* \return Returns the echo sequence number.
|
||||
*/
|
||||
uint16_t sequence() const { return Endian::be_to_host(_icmp.un.echo.sequence); }
|
||||
|
||||
/**
|
||||
* \brief Getter for the gateway field.
|
||||
*
|
||||
* \return Returns the gateway field value.
|
||||
*/
|
||||
address_type gateway() const {
|
||||
return address_type(Endian::be_to_host(_icmp.un.gateway));
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the pointer field.
|
||||
*
|
||||
* \return Returns the pointer field value.
|
||||
*/
|
||||
uint8_t pointer() const { return this->_icmp.un.pointer; }
|
||||
|
||||
/**
|
||||
* \brief Getter for the mtu field.
|
||||
*
|
||||
* \return Returns the mtu field value.
|
||||
*/
|
||||
uint16_t mtu() const { return Endian::be_to_host(_icmp.un.frag.mtu); }
|
||||
|
||||
/**
|
||||
* \brief Getter for the original timestamp field.
|
||||
*
|
||||
* \return Returns the original timestamp value.
|
||||
*/
|
||||
uint32_t original_timestamp() const { return Endian::be_to_host(_orig_timestamp_or_address_mask); }
|
||||
|
||||
/**
|
||||
* \brief Getter for the receive timestamp field.
|
||||
*
|
||||
* \return Returns the receive timestamp value.
|
||||
*/
|
||||
uint32_t receive_timestamp() const { return Endian::be_to_host(_recv_timestamp); }
|
||||
|
||||
/**
|
||||
* \brief Getter for the transmit timestamp field.
|
||||
*
|
||||
* \return Returns the transmit timestamp value.
|
||||
*/
|
||||
uint32_t transmit_timestamp() const { return Endian::be_to_host(_trans_timestamp); }
|
||||
|
||||
/**
|
||||
* \brief Getter for the address mask field.
|
||||
*
|
||||
* \return Returns the address mask value.
|
||||
*/
|
||||
address_type address_mask() const {
|
||||
return address_type(Endian::be_to_host(_orig_timestamp_or_address_mask));
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Returns the header size.
|
||||
*
|
||||
* This metod overrides PDU::header_size. This size includes the
|
||||
* payload and options size. \sa PDU::header_size
|
||||
*/
|
||||
uint32_t header_size() const;
|
||||
|
||||
/**
|
||||
* \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 Getter for the PDU's type.
|
||||
*
|
||||
* \sa PDU::pdu_type
|
||||
*/
|
||||
PDUType pdu_type() const { return PDU::ICMP; }
|
||||
|
||||
/**
|
||||
* \sa PDU::clone
|
||||
*/
|
||||
ICMP *clone() const {
|
||||
return new ICMP(*this);
|
||||
}
|
||||
private:
|
||||
TINS_BEGIN_PACK
|
||||
struct icmphdr {
|
||||
uint8_t type;
|
||||
uint8_t code;
|
||||
uint16_t check;
|
||||
union {
|
||||
struct {
|
||||
uint16_t id;
|
||||
uint16_t sequence;
|
||||
} echo;
|
||||
uint32_t gateway;
|
||||
struct {
|
||||
uint16_t unused;
|
||||
uint16_t mtu;
|
||||
} frag;
|
||||
uint8_t pointer;
|
||||
} un;
|
||||
} TINS_END_PACK;
|
||||
|
||||
void checksum(uint16_t new_check);
|
||||
|
||||
/** \brief Serialices this ICMP PDU.
|
||||
* \param buffer The buffer in which the PDU will be serialized.
|
||||
* \param total_sz The size available in the buffer.
|
||||
* \param parent The PDU that's one level below this one on the stack.
|
||||
*/
|
||||
void write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *parent);
|
||||
|
||||
icmphdr _icmp;
|
||||
uint32_t _orig_timestamp_or_address_mask, _recv_timestamp, _trans_timestamp;
|
||||
};
|
||||
}
|
||||
|
||||
#endif // TINS_ICMP_H
|
||||
1338
include/tins/icmpv6.h
Normal file
1338
include/tins/icmpv6.h
Normal file
File diff suppressed because it is too large
Load Diff
40
include/tins/ieee802_3.h
Normal file
40
include/tins/ieee802_3.h
Normal file
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Matias Fontanini
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following disclaimer
|
||||
* in the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef TINS_IEEE802_3_H
|
||||
#define TINS_IEEE802_3_H
|
||||
|
||||
#include "dot3.h"
|
||||
|
||||
namespace Tins {
|
||||
typedef Dot3 IEEE802_3;
|
||||
}
|
||||
|
||||
|
||||
#endif // TINS_IEEE802_3_H
|
||||
207
include/tins/internals.h
Normal file
207
include/tins/internals.h
Normal file
@@ -0,0 +1,207 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Matias Fontanini
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following disclaimer
|
||||
* in the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef TINS_INTERNALS_H
|
||||
#define TINS_INTERNALS_H
|
||||
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <stdint.h>
|
||||
#include "constants.h"
|
||||
#include "pdu.h"
|
||||
#include "hw_address.h"
|
||||
|
||||
/**
|
||||
* \cond
|
||||
*/
|
||||
namespace Tins {
|
||||
class IPv4Address;
|
||||
class IPv6Address;
|
||||
|
||||
namespace Internals {
|
||||
template<size_t n>
|
||||
class byte_array {
|
||||
public:
|
||||
typedef uint8_t* iterator;
|
||||
typedef const uint8_t* const_iterator;
|
||||
|
||||
byte_array() {
|
||||
std::fill(begin(), end(), 0);
|
||||
}
|
||||
|
||||
template<typename InputIterator>
|
||||
byte_array(InputIterator start, InputIterator last) {
|
||||
std::copy(start, last, data);
|
||||
}
|
||||
|
||||
template<typename InputIterator>
|
||||
byte_array(InputIterator start) {
|
||||
std::copy(start, n, data);
|
||||
}
|
||||
|
||||
uint8_t &operator[](size_t i) {
|
||||
return data[i];
|
||||
}
|
||||
|
||||
uint8_t operator[](size_t i) const{
|
||||
return data[i];
|
||||
}
|
||||
|
||||
iterator begin() {
|
||||
return data;
|
||||
}
|
||||
|
||||
iterator end() {
|
||||
return data + n;
|
||||
}
|
||||
|
||||
const_iterator begin() const {
|
||||
return data;
|
||||
}
|
||||
|
||||
const_iterator end() const {
|
||||
return data + n;
|
||||
}
|
||||
|
||||
size_t size() const {
|
||||
return n;
|
||||
}
|
||||
private:
|
||||
uint8_t data[n];
|
||||
};
|
||||
|
||||
void skip_line(std::istream &input);
|
||||
bool from_hex(const std::string &str, uint32_t &result);
|
||||
|
||||
template<bool, typename T = void>
|
||||
struct enable_if {
|
||||
typedef T type;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct enable_if<false, T> {
|
||||
|
||||
};
|
||||
|
||||
PDU *pdu_from_flag(Constants::Ethernet::e flag, const uint8_t *buffer,
|
||||
uint32_t size, bool rawpdu_on_no_match = true);
|
||||
PDU *pdu_from_flag(Constants::IP::e flag, const uint8_t *buffer,
|
||||
uint32_t size, bool rawpdu_on_no_match = true);
|
||||
PDU *pdu_from_flag(PDU::PDUType type, const uint8_t *buffer, uint32_t size);
|
||||
|
||||
Constants::Ethernet::e pdu_flag_to_ether_type(PDU::PDUType flag);
|
||||
Constants::IP::e pdu_flag_to_ip_type(PDU::PDUType flag);
|
||||
|
||||
template<typename T>
|
||||
bool increment_buffer(T &addr) {
|
||||
typename T::iterator it = addr.end() - 1;
|
||||
while(it >= addr.begin() && *it == 0xff) {
|
||||
*it = 0;
|
||||
--it;
|
||||
}
|
||||
// reached end
|
||||
if(it < addr.begin())
|
||||
return true;
|
||||
(*it)++;
|
||||
return false;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool decrement_buffer(T &addr) {
|
||||
typename T::iterator it = addr.end() - 1;
|
||||
while(it >= addr.begin() && *it == 0) {
|
||||
*it = 0xff;
|
||||
--it;
|
||||
}
|
||||
// reached end
|
||||
if(it < addr.begin())
|
||||
return true;
|
||||
(*it)--;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool increment(IPv4Address &addr);
|
||||
bool increment(IPv6Address &addr);
|
||||
bool decrement(IPv4Address &addr);
|
||||
bool decrement(IPv6Address &addr);
|
||||
template<size_t n>
|
||||
bool increment(HWAddress<n> &addr) {
|
||||
return increment_buffer(addr);
|
||||
}
|
||||
template<size_t n>
|
||||
bool decrement(HWAddress<n> &addr) {
|
||||
return decrement_buffer(addr);
|
||||
}
|
||||
|
||||
IPv4Address last_address_from_mask(IPv4Address addr, IPv4Address mask);
|
||||
IPv6Address last_address_from_mask(IPv6Address addr, const IPv6Address &mask);
|
||||
template<size_t n>
|
||||
HWAddress<n> last_address_from_mask(HWAddress<n> addr, const HWAddress<n> &mask) {
|
||||
typename HWAddress<n>::iterator addr_iter = addr.begin();
|
||||
for(typename HWAddress<n>::const_iterator it = mask.begin(); it != mask.end(); ++it, ++addr_iter) {
|
||||
*addr_iter = *addr_iter | ~*it;
|
||||
}
|
||||
return addr;
|
||||
}
|
||||
|
||||
inline bool is_dot3(const uint8_t *ptr, size_t sz) {
|
||||
return (sz >= 13 && ptr[12] < 8);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
struct is_unsigned_integral {
|
||||
static const bool value = false;
|
||||
};
|
||||
|
||||
template<>
|
||||
struct is_unsigned_integral<uint8_t> {
|
||||
static const bool value = true;
|
||||
};
|
||||
|
||||
template<>
|
||||
struct is_unsigned_integral<uint16_t> {
|
||||
static const bool value = true;
|
||||
};
|
||||
|
||||
template<>
|
||||
struct is_unsigned_integral<uint32_t> {
|
||||
static const bool value = true;
|
||||
};
|
||||
|
||||
template<>
|
||||
struct is_unsigned_integral<uint64_t> {
|
||||
static const bool value = true;
|
||||
};
|
||||
} // namespace Internals
|
||||
} // namespace Tins
|
||||
/**
|
||||
* \endcond
|
||||
*/
|
||||
|
||||
#endif
|
||||
663
include/tins/ip.h
Normal file
663
include/tins/ip.h
Normal file
@@ -0,0 +1,663 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Matias Fontanini
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following disclaimer
|
||||
* in the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef TINS_IP_H
|
||||
#define TINS_IP_H
|
||||
|
||||
#include <list>
|
||||
#include "pdu.h"
|
||||
#include "small_uint.h"
|
||||
#include "endianness.h"
|
||||
#include "ip_address.h"
|
||||
#include "pdu_option.h"
|
||||
#include "macros.h"
|
||||
#include "cxxstd.h"
|
||||
|
||||
namespace Tins {
|
||||
|
||||
/**
|
||||
* \class IP
|
||||
* \brief Class that represents an IP PDU.
|
||||
*
|
||||
* By default, IP PDUs are initialized, setting TTL to IP::DEFAULT_TTL,
|
||||
* id field to 1 and version to 4. Taking this into account, users
|
||||
* should set destination and source port and would be enough to send one.
|
||||
*/
|
||||
class IP : public PDU {
|
||||
public:
|
||||
/**
|
||||
* This PDU's flag.
|
||||
*/
|
||||
static const PDU::PDUType pdu_flag = PDU::IP;
|
||||
|
||||
/**
|
||||
* The type used to store addresses.
|
||||
*/
|
||||
typedef IPv4Address address_type;
|
||||
|
||||
/**
|
||||
* \brief Enum indicating the option's class.
|
||||
*
|
||||
* Enum OptionClass represents the different classes of
|
||||
* IP Options.
|
||||
*/
|
||||
enum OptionClass {
|
||||
CONTROL = 0,
|
||||
MEASUREMENT = 2
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Enum indicating the option's id number.
|
||||
*
|
||||
* Enum Option indicates the possible IP Options.
|
||||
*/
|
||||
enum OptionNumber {
|
||||
END = 0,
|
||||
NOOP = 1,
|
||||
SEC = 2,
|
||||
LSSR = 3,
|
||||
TIMESTAMP = 4,
|
||||
EXTSEC = 5,
|
||||
RR = 7,
|
||||
SID = 8,
|
||||
SSRR = 9,
|
||||
MTUPROBE = 11,
|
||||
MTUREPLY = 12,
|
||||
EIP = 17,
|
||||
TR = 18,
|
||||
ADDEXT = 19,
|
||||
RTRALT = 20,
|
||||
SDB = 21,
|
||||
DPS = 23,
|
||||
UMP = 24,
|
||||
QS = 25
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief The type used to represent an option's type.
|
||||
*/
|
||||
TINS_BEGIN_PACK
|
||||
struct option_identifier {
|
||||
#if TINS_IS_LITTLE_ENDIAN
|
||||
uint8_t number:5,
|
||||
op_class:2,
|
||||
copied:1;
|
||||
#elif TINS_IS_BIG_ENDIAN
|
||||
uint8_t copied:1,
|
||||
op_class:2,
|
||||
number:5;
|
||||
#endif
|
||||
/**
|
||||
* \brief Default constructor.
|
||||
*
|
||||
* Initializes every field to 0.
|
||||
*/
|
||||
option_identifier()
|
||||
#if TINS_IS_LITTLE_ENDIAN
|
||||
: number(0), op_class(0), copied(0) {}
|
||||
#else
|
||||
: copied(0), op_class(0), number(0) {}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* \brief Constructs this option from a single uint8_t value.
|
||||
*
|
||||
* This parses the value and initializes each field with the
|
||||
* appropriate value.
|
||||
*
|
||||
* \param value The value to be parsed and used for
|
||||
* initialization
|
||||
*/
|
||||
option_identifier(uint8_t value)
|
||||
#if TINS_IS_LITTLE_ENDIAN
|
||||
: number(value & 0x1f),
|
||||
op_class((value >> 5) & 0x03),
|
||||
copied((value >> 7) & 0x01) {}
|
||||
#elif TINS_IS_BIG_ENDIAN
|
||||
: copied((value >> 7) & 0x01),
|
||||
op_class((value >> 5) & 0x03),
|
||||
number(value & 0x1f) {}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Constructor using user provided values for each field.
|
||||
* \param number The number field value.
|
||||
* \param op_class The option class field value.
|
||||
* \param copied The copied field value.
|
||||
*/
|
||||
option_identifier(OptionNumber number, OptionClass op_class,
|
||||
small_uint<1> copied)
|
||||
#if TINS_IS_LITTLE_ENDIAN
|
||||
: number(number), op_class(op_class), copied(copied) {}
|
||||
#else
|
||||
: copied(copied), op_class(op_class), number(number) {}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* \brief Equality operator.
|
||||
*/
|
||||
bool operator==(const option_identifier &rhs) const {
|
||||
return number == rhs.number && op_class == rhs.op_class && copied == rhs.copied;
|
||||
}
|
||||
} TINS_END_PACK;
|
||||
|
||||
/**
|
||||
* The IP options type.
|
||||
*/
|
||||
typedef PDUOption<option_identifier, IP> option;
|
||||
|
||||
/**
|
||||
* The type of the security option.
|
||||
*/
|
||||
struct security_type {
|
||||
uint16_t security, compartments;
|
||||
uint16_t handling_restrictions;
|
||||
small_uint<24> transmission_control;
|
||||
|
||||
security_type(uint16_t sec = 0, uint16_t comp = 0,
|
||||
uint16_t hand_res = 0, small_uint<24> tcc = 0)
|
||||
: security(sec), compartments(comp),
|
||||
handling_restrictions(hand_res), transmission_control(tcc)
|
||||
{}
|
||||
|
||||
static security_type from_option(const option &opt);
|
||||
};
|
||||
|
||||
/**
|
||||
* The type of the Loose Source and Record Route
|
||||
*/
|
||||
struct generic_route_option_type {
|
||||
typedef std::vector<address_type> routes_type;
|
||||
|
||||
uint8_t pointer;
|
||||
routes_type routes;
|
||||
|
||||
generic_route_option_type(uint8_t ptr = 0,
|
||||
routes_type rts = routes_type())
|
||||
: pointer(ptr), routes(rts) {}
|
||||
|
||||
static generic_route_option_type from_option(const option &opt);
|
||||
};
|
||||
|
||||
/**
|
||||
* The type of the Loose Source and Record Route
|
||||
*/
|
||||
typedef generic_route_option_type lsrr_type;
|
||||
|
||||
/**
|
||||
* The type of the Strict Source and Record Route
|
||||
*/
|
||||
typedef generic_route_option_type ssrr_type;
|
||||
|
||||
/**
|
||||
* The type of the Record Route
|
||||
*/
|
||||
typedef generic_route_option_type record_route_type;
|
||||
|
||||
/**
|
||||
* The type used to store IP options.
|
||||
*/
|
||||
typedef std::list<option> options_type;
|
||||
|
||||
/**
|
||||
* \brief Constructor for building the IP PDU.
|
||||
*
|
||||
* Both the destination and source IP address can be supplied.
|
||||
* By default, those fields are initialized using the IP
|
||||
* address 0.0.0.0.
|
||||
*
|
||||
* \param ip_dst The destination ip address(optional).
|
||||
* \param ip_src The source ip address(optional).
|
||||
*/
|
||||
IP(address_type ip_dst = address_type(),
|
||||
address_type ip_src = address_type());
|
||||
|
||||
/**
|
||||
* \brief Constructs an IP 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 an IP 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.
|
||||
*/
|
||||
IP(const uint8_t *buffer, uint32_t total_sz);
|
||||
|
||||
/* Getters */
|
||||
|
||||
/**
|
||||
* \brief Getter for the header length field.
|
||||
*
|
||||
* \return The number of dwords the header occupies in an uin8_t.
|
||||
*/
|
||||
small_uint<4> head_len() const { return this->_ip.ihl; }
|
||||
|
||||
/**
|
||||
* \brief Getter for the type of service field.
|
||||
*
|
||||
* \return The this IP PDU's type of service.
|
||||
*/
|
||||
uint8_t tos() const { return _ip.tos; }
|
||||
|
||||
/**
|
||||
* \brief Getter for the total length field.
|
||||
*
|
||||
* \return The total length of this IP PDU.
|
||||
*/
|
||||
uint16_t tot_len() const {
|
||||
return Endian::be_to_host(_ip.tot_len);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the id field.
|
||||
*
|
||||
* \return The id for this IP PDU.
|
||||
*/
|
||||
uint16_t id() const { return Endian::be_to_host(_ip.id); }
|
||||
|
||||
/**
|
||||
* \brief Getter for the fragment offset field.
|
||||
*
|
||||
* \return The fragment offset for this IP PDU.
|
||||
*/
|
||||
uint16_t frag_off() const { return Endian::be_to_host(_ip.frag_off); }
|
||||
|
||||
/**
|
||||
* \brief Getter for the time to live field.
|
||||
*
|
||||
* \return The time to live for this IP PDU.
|
||||
*/
|
||||
uint8_t ttl() const { return _ip.ttl; }
|
||||
|
||||
/**
|
||||
* \brief Getter for the protocol field.
|
||||
*
|
||||
* \return The protocol for this IP PDU.
|
||||
*/
|
||||
uint8_t protocol() const { return _ip.protocol; }
|
||||
|
||||
/**
|
||||
* \brief Getter for the checksum field.
|
||||
*
|
||||
* \return The checksum for this IP PDU.
|
||||
*/
|
||||
uint16_t checksum() const { return Endian::be_to_host(_ip.check); }
|
||||
|
||||
/**
|
||||
* \brief Getter for the source address field.
|
||||
*
|
||||
* \return The source address for this IP PDU.
|
||||
*/
|
||||
address_type src_addr() const { return address_type(_ip.saddr); }
|
||||
|
||||
/**
|
||||
* \brief Getter for the destination address field.
|
||||
* \return The destination address for this IP PDU.
|
||||
*/
|
||||
address_type dst_addr() const { return address_type(_ip.daddr); }
|
||||
|
||||
/**
|
||||
* \brief Getter for the version field.
|
||||
* \return The version for this IP PDU.
|
||||
*/
|
||||
small_uint<4> version() const { return _ip.version; }
|
||||
|
||||
/**
|
||||
* \brief Getter for the IP options.
|
||||
* \return The stored options.
|
||||
*/
|
||||
const options_type &options() const { return _ip_options; }
|
||||
|
||||
/* Setters */
|
||||
|
||||
/**
|
||||
* \brief Setter for the type of service field.
|
||||
*
|
||||
* \param new_tos The new type of service.
|
||||
*/
|
||||
void tos(uint8_t new_tos);
|
||||
|
||||
/**
|
||||
* \brief Setter for the id field.
|
||||
*
|
||||
* \param new_id The new id.
|
||||
*/
|
||||
void id(uint16_t new_id);
|
||||
|
||||
/**
|
||||
* \brief Setter for the fragment offset field.
|
||||
*
|
||||
* \param new_frag_off The new fragment offset.
|
||||
*/
|
||||
void frag_off(uint16_t new_frag_off);
|
||||
|
||||
/**
|
||||
* \brief Setter for the time to live field.
|
||||
*
|
||||
* \param new_ttl The new time to live.
|
||||
*/
|
||||
void ttl(uint8_t new_ttl);
|
||||
|
||||
/**
|
||||
* \brief Setter for the protocol field.
|
||||
*
|
||||
* Note that this protocol will be overwritten using the
|
||||
* inner_pdu's protocol type during serialization unless the IP
|
||||
* datagram is fragmented.
|
||||
*
|
||||
* If the packet is fragmented and was originally sniffed, the
|
||||
* original protocol type will be kept when serialized.
|
||||
*
|
||||
* If this packet has been crafted manually and the inner_pdu
|
||||
* is, for example, a RawPDU, then setting the protocol yourself
|
||||
* is necessary.
|
||||
*
|
||||
* \param new_protocol The new protocol.
|
||||
*/
|
||||
void protocol(uint8_t new_protocol);
|
||||
|
||||
/**
|
||||
* \brief Setter for the source address field.
|
||||
*
|
||||
* \param ip The source address to be set.
|
||||
*/
|
||||
void src_addr(address_type ip);
|
||||
|
||||
/**
|
||||
* \brief Setter for the destination address field.
|
||||
*
|
||||
* \param ip The destination address to be set.
|
||||
*/
|
||||
void dst_addr(address_type ip);
|
||||
|
||||
/**
|
||||
* \brief Setter for the version field.
|
||||
*
|
||||
* \param ver The version field to be set.
|
||||
*/
|
||||
void version(small_uint<4> ver);
|
||||
|
||||
/**
|
||||
* \brief Adds an IP option.
|
||||
*
|
||||
* The option is added after the last option in the option
|
||||
* fields.
|
||||
*
|
||||
* \param opt The option to be added
|
||||
*/
|
||||
void add_option(const option &opt);
|
||||
|
||||
#if TINS_IS_CXX11
|
||||
/**
|
||||
* \brief Adds an IP option.
|
||||
*
|
||||
* The option is move-constructed.
|
||||
*
|
||||
* \param opt The option to be added.
|
||||
*/
|
||||
void add_option(option &&opt) {
|
||||
internal_add_option(opt);
|
||||
_ip_options.push_back(std::move(opt));
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Adds an IP option.
|
||||
*
|
||||
* The option is constructed from the provided parameters.
|
||||
*
|
||||
* \param args The arguments to be used in the option's
|
||||
* constructor.
|
||||
*/
|
||||
template<typename... Args>
|
||||
void add_option(Args&&... args) {
|
||||
_ip_options.emplace_back(std::forward<Args>(args)...);
|
||||
internal_add_option(_ip_options.back());
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* \brief Searchs for an option that matchs the given flag.
|
||||
*
|
||||
* If the option is not found, a null pointer is returned.
|
||||
* Deleting the returned pointer will result in <b>undefined
|
||||
* behaviour</b>.
|
||||
*
|
||||
* \param id The option identifier to be searched.
|
||||
*/
|
||||
const option *search_option(option_identifier id) const;
|
||||
|
||||
// Option setters
|
||||
|
||||
/**
|
||||
* \brief Adds an End Of List option.
|
||||
*/
|
||||
void eol();
|
||||
|
||||
/**
|
||||
* \brief Adds a NOP option.
|
||||
*/
|
||||
void noop();
|
||||
|
||||
/**
|
||||
* \brief Adds a security option.
|
||||
*
|
||||
* \param data The data to be stored in this option.
|
||||
*/
|
||||
void security(const security_type &data);
|
||||
|
||||
/**
|
||||
* \brief Adds a Loose Source and Record Route option.
|
||||
*
|
||||
* \param data The data to be stored in this option.
|
||||
*/
|
||||
void lsrr(const lsrr_type &data) {
|
||||
add_route_option(131, data);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Adds a Strict Source and Record Route option.
|
||||
*
|
||||
* \param data The data to be stored in this option.
|
||||
*/
|
||||
void ssrr(const ssrr_type &data) {
|
||||
add_route_option(137, data);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Adds a Record Route option.
|
||||
*
|
||||
* \param data The data to be stored in this option.
|
||||
*/
|
||||
void record_route(const record_route_type &data) {
|
||||
add_route_option(7, data);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Adds a Stream Identifier option.
|
||||
*
|
||||
* \param stream_id The stream id to be stored in this option.
|
||||
*/
|
||||
void stream_identifier(uint16_t stream_id);
|
||||
|
||||
// Option getters
|
||||
|
||||
/**
|
||||
* \brief Searchs and returns a security option.
|
||||
*
|
||||
* If no such option exists, an option_not_found exception
|
||||
* is thrown.
|
||||
*
|
||||
* \return security_type containing the option found.
|
||||
*/
|
||||
security_type security() const;
|
||||
|
||||
/**
|
||||
* \brief Searchs and returns a Loose Source and Record Route
|
||||
* option.
|
||||
*
|
||||
* If no such option exists, an option_not_found exception
|
||||
* is thrown.
|
||||
*
|
||||
* \return lsrr_type containing the option found.
|
||||
*/
|
||||
lsrr_type lsrr() const {
|
||||
return search_route_option(131);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Searchs and returns a Strict Source and Record Route
|
||||
* option.
|
||||
*
|
||||
* If no such option exists, an option_not_found exception
|
||||
* is thrown.
|
||||
*
|
||||
* \return ssrr_type containing the option found.
|
||||
*/
|
||||
ssrr_type ssrr() const {
|
||||
return search_route_option(137);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Searchs and returns a Record Route option.
|
||||
*
|
||||
* If no such option exists, an option_not_found exception
|
||||
* is thrown.
|
||||
*
|
||||
* \return record_route_type containing the option found.
|
||||
*/
|
||||
record_route_type record_route() const {
|
||||
return search_route_option(7);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Searchs and returns a Stream Identifier option.
|
||||
*
|
||||
* If no such option exists, an option_not_found exception
|
||||
* is thrown.
|
||||
*
|
||||
* \return uint16_t containing the option found.
|
||||
*/
|
||||
uint16_t stream_identifier() const;
|
||||
|
||||
/* Virtual methods */
|
||||
|
||||
/**
|
||||
* \brief Returns the header size.
|
||||
*
|
||||
* This metod overrides PDU::header_size. \sa PDU::header_size
|
||||
*/
|
||||
uint32_t header_size() const;
|
||||
|
||||
/**
|
||||
* \sa PDU::send()
|
||||
*/
|
||||
void send(PacketSender &sender, const NetworkInterface &);
|
||||
|
||||
/**
|
||||
* \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 Receives a matching response for this packet.
|
||||
*
|
||||
* \sa PDU::recv_response
|
||||
* \param sender The packet sender which will receive the packet.
|
||||
*/
|
||||
PDU *recv_response(PacketSender &sender, const NetworkInterface &);
|
||||
|
||||
/**
|
||||
* Indicates whether this PDU is fragmented.
|
||||
*
|
||||
* \return true if this PDU is fragmented, false otherwise.
|
||||
*/
|
||||
bool is_fragmented() const;
|
||||
|
||||
/**
|
||||
* \brief Getter for the PDU's type.
|
||||
* \sa PDU::pdu_type
|
||||
*/
|
||||
PDUType pdu_type() const { return PDU::IP; }
|
||||
|
||||
/**
|
||||
* \sa PDU::clone
|
||||
*/
|
||||
IP *clone() const {
|
||||
return new IP(*this);
|
||||
}
|
||||
private:
|
||||
static const uint8_t DEFAULT_TTL;
|
||||
|
||||
TINS_BEGIN_PACK
|
||||
struct iphdr {
|
||||
#if TINS_IS_LITTLE_ENDIAN
|
||||
uint8_t ihl:4,
|
||||
version:4;
|
||||
#else
|
||||
uint8_t version:4,
|
||||
ihl:4;
|
||||
#endif
|
||||
uint8_t tos;
|
||||
uint16_t tot_len;
|
||||
uint16_t id;
|
||||
uint16_t frag_off;
|
||||
uint8_t ttl;
|
||||
uint8_t protocol;
|
||||
uint16_t check;
|
||||
uint32_t saddr;
|
||||
uint32_t daddr;
|
||||
/*The options start here. */
|
||||
} TINS_END_PACK;
|
||||
|
||||
|
||||
void head_len(small_uint<4> new_head_len);
|
||||
void tot_len(uint16_t new_tot_len);
|
||||
|
||||
void prepare_for_serialize(const PDU *parent);
|
||||
void internal_add_option(const option &option);
|
||||
void init_ip_fields();
|
||||
void write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *parent);
|
||||
uint8_t* write_option(const option &opt, uint8_t* buffer);
|
||||
void add_route_option(option_identifier id, const generic_route_option_type &data);
|
||||
generic_route_option_type search_route_option(option_identifier id) const;
|
||||
void checksum(uint16_t new_check);
|
||||
|
||||
iphdr _ip;
|
||||
uint16_t _options_size, _padded_options_size;
|
||||
options_type _ip_options;
|
||||
};
|
||||
}
|
||||
|
||||
#endif // TINS_IP_H
|
||||
199
include/tins/ip_address.h
Normal file
199
include/tins/ip_address.h
Normal file
@@ -0,0 +1,199 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Matias Fontanini
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following disclaimer
|
||||
* in the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef TINS_IPADDRESS_H
|
||||
#define TINS_IPADDRESS_H
|
||||
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
#include <stdint.h>
|
||||
#include "cxxstd.h"
|
||||
|
||||
namespace Tins {
|
||||
/**
|
||||
* \class IPv4Address
|
||||
* \brief Abstraction of an IPv4 address.
|
||||
*/
|
||||
class IPv4Address {
|
||||
public:
|
||||
/**
|
||||
* The address size.
|
||||
*/
|
||||
static const size_t address_size = sizeof(uint32_t);
|
||||
|
||||
/**
|
||||
* The broadcast address.
|
||||
*/
|
||||
static const IPv4Address broadcast;
|
||||
|
||||
/**
|
||||
* \brief Constructor taking a const char*.
|
||||
*
|
||||
* Constructs an IPv4Address from a dotted-notation address
|
||||
* cstring. If the pointer provided is null, then a default
|
||||
* IPv4Address object is constructed, which corresponds to
|
||||
* the 0.0.0.0 address.
|
||||
*
|
||||
* \param ip const char* containing the dotted-notation address.
|
||||
*/
|
||||
IPv4Address(const char *ip = 0);
|
||||
|
||||
/**
|
||||
* \brief Constructor taking a std::string.
|
||||
*
|
||||
* Constructs an IPv4Address from a dotted-notation std::strings
|
||||
*
|
||||
* \param ip std::string containing the dotted-notation address.
|
||||
*/
|
||||
IPv4Address(const std::string &ip);
|
||||
|
||||
/**
|
||||
* \brief Constructor taking a IP address represented as a
|
||||
* big endian integer.
|
||||
*
|
||||
* This constructor should be used internally by PDUs that
|
||||
* handle IP addresses. The provided integer <b>must</b> be
|
||||
* be in big endian.
|
||||
*/
|
||||
explicit IPv4Address(uint32_t ip);
|
||||
|
||||
/**
|
||||
* \brief User defined conversion to big endian integral value.
|
||||
*/
|
||||
operator uint32_t() const;
|
||||
|
||||
/**
|
||||
* \brief Retrieve the string representation of this address.
|
||||
*
|
||||
* \return std::string containing the representation of this address.
|
||||
*/
|
||||
std::string to_string() const;
|
||||
|
||||
/**
|
||||
* \brief Compare this IPv4Address for equality.
|
||||
*
|
||||
* \param rhs The address to be compared.
|
||||
* \return bool indicating whether this address equals rhs.
|
||||
*/
|
||||
bool operator==(const IPv4Address &rhs) const {
|
||||
return ip_addr == rhs.ip_addr;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Compare this IPv4Address for inequality.
|
||||
*
|
||||
* \param rhs The address to be compared.
|
||||
* \return bool indicating whether this address is distinct
|
||||
* from rhs.
|
||||
*/
|
||||
bool operator!=(const IPv4Address &rhs) const {
|
||||
return !(*this == rhs);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Compare this IPv4Address for less-than inequality.
|
||||
*
|
||||
* \param rhs The address to be compared.
|
||||
* \return bool indicating whether this address is less-than rhs.
|
||||
*/
|
||||
bool operator< (const IPv4Address &rhs) const {
|
||||
return ip_addr < rhs.ip_addr;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Returns true if this is a private IPv4 address.
|
||||
*
|
||||
* This takes into account the private network ranges defined in
|
||||
* RFC 1918. Therefore, this method returns true if this address
|
||||
* is in any of the following network ranges, false otherwise:
|
||||
*
|
||||
* - 192.168.0.0/16
|
||||
* - 10.0.0.0/8
|
||||
* - 172.16.0.0/12
|
||||
*/
|
||||
bool is_private() const;
|
||||
|
||||
/**
|
||||
* \brief Returns true if this is a loopback IPv4 address.
|
||||
*
|
||||
* This method returns true if this address is in the address range
|
||||
* 127.0.0.0/8, false otherwise.
|
||||
*/
|
||||
bool is_loopback() const;
|
||||
|
||||
/**
|
||||
* \brief Returns true if this is a multicast IPv4 address.
|
||||
*
|
||||
* This method returns true if this address is in the address range
|
||||
* 224.0.0.0/4, false otherwise.
|
||||
*/
|
||||
bool is_multicast() const;
|
||||
|
||||
/**
|
||||
* \brief Returns true if this is an unicast IPv4 address.
|
||||
*/
|
||||
bool is_unicast() const;
|
||||
|
||||
/**
|
||||
* \brief Returns true if this is a broadcast IPv4 address.
|
||||
*/
|
||||
bool is_broadcast() const;
|
||||
|
||||
/**
|
||||
* \brief Writes this address to a std::ostream.
|
||||
*
|
||||
* This method writes addr in a dotted-string notation address
|
||||
* to the std::ostream argument.
|
||||
*
|
||||
* \param output The std::ostream in which to write the address.
|
||||
* \param addr The IPv4Address to be written.
|
||||
* \return std::stream& pointing to output.
|
||||
*/
|
||||
friend std::ostream &operator<<(std::ostream &output, const IPv4Address &addr);
|
||||
private:
|
||||
uint32_t ip_to_int(const char* ip);
|
||||
|
||||
uint32_t ip_addr;
|
||||
};
|
||||
} //namespace Tins
|
||||
|
||||
#if TINS_IS_CXX11
|
||||
namespace std
|
||||
{
|
||||
template<>
|
||||
struct hash<Tins::IPv4Address> {
|
||||
size_t operator()(const Tins::IPv4Address &addr) const {
|
||||
return std::hash<uint32_t>()(addr);
|
||||
}
|
||||
};
|
||||
} // namespace std
|
||||
#endif
|
||||
|
||||
|
||||
#endif // TINS_IPADDRESS_H
|
||||
216
include/tins/ip_reassembler.h
Normal file
216
include/tins/ip_reassembler.h
Normal file
@@ -0,0 +1,216 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Matias Fontanini
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following disclaimer
|
||||
* in the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef TINS_IP_REASSEMBLER_H
|
||||
#define TINS_IP_REASSEMBLER_H
|
||||
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include "pdu.h"
|
||||
#include "ip_address.h"
|
||||
|
||||
namespace Tins {
|
||||
/**
|
||||
* \cond
|
||||
*/
|
||||
class IP;
|
||||
namespace Internals {
|
||||
class IPv4Fragment {
|
||||
public:
|
||||
typedef PDU::serialization_type payload_type;
|
||||
|
||||
IPv4Fragment() : offset_() { }
|
||||
|
||||
template<typename T>
|
||||
IPv4Fragment(T *pdu, uint16_t offset)
|
||||
: payload_(pdu->serialize()), offset_(offset)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
const payload_type &payload() const {
|
||||
return payload_;
|
||||
}
|
||||
|
||||
uint16_t offset() const {
|
||||
return offset_;
|
||||
}
|
||||
private:
|
||||
payload_type payload_;
|
||||
uint16_t offset_;
|
||||
};
|
||||
|
||||
class IPv4Stream {
|
||||
public:
|
||||
IPv4Stream();
|
||||
|
||||
void add_fragment(IP *ip);
|
||||
bool is_complete() const;
|
||||
PDU *allocate_pdu() const;
|
||||
private:
|
||||
typedef std::vector<IPv4Fragment> fragments_type;
|
||||
|
||||
uint16_t extract_offset(const IP *ip);
|
||||
bool extract_more_frag(const IP *ip);
|
||||
|
||||
fragments_type fragments;
|
||||
bool received_end;
|
||||
uint8_t transport_proto;
|
||||
size_t received_size, total_size;
|
||||
};
|
||||
} // namespace Internals
|
||||
|
||||
/**
|
||||
* \endcond
|
||||
*/
|
||||
|
||||
/**
|
||||
* \brief Reassembles fragmented IP packets.
|
||||
*/
|
||||
class IPv4Reassembler {
|
||||
public:
|
||||
/**
|
||||
* The status of each processed packet.
|
||||
*/
|
||||
enum packet_status {
|
||||
NOT_FRAGMENTED,
|
||||
FRAGMENTED,
|
||||
REASSEMBLED
|
||||
};
|
||||
|
||||
/**
|
||||
* The type used to represent the overlapped segment
|
||||
* reassembly technique to be used.
|
||||
*/
|
||||
enum overlapping_technique {
|
||||
NONE
|
||||
};
|
||||
|
||||
/**
|
||||
* Constructs an IPV4Reassembler.
|
||||
* \param technique The technique to be used for reassembling
|
||||
* overlapped fragments.
|
||||
*/
|
||||
IPv4Reassembler(overlapping_technique technique = NONE);
|
||||
|
||||
/**
|
||||
* \brief Processes a PDU and tries to reassemble it.
|
||||
*
|
||||
* This method tries to reassemble the provided packet. If
|
||||
* the packet is successfully reassembled using previously
|
||||
* processed packets, its contents will be modified so that
|
||||
* it contains the whole payload and not just a fragment.
|
||||
*
|
||||
* \param pdu The PDU to process.
|
||||
* \return NOT_FRAGMENTED if the PDU does not contain an IP
|
||||
* layer or is not fragmented, FRAGMENTED if the packet is
|
||||
* fragmented or REASSEMBLED if the packet was fragmented
|
||||
* but has now been reassembled.
|
||||
*/
|
||||
packet_status process(PDU &pdu);
|
||||
|
||||
/**
|
||||
* Removes all of the packets and data stored.
|
||||
*/
|
||||
void clear_streams();
|
||||
|
||||
/**
|
||||
* \brief Removes all of the packets and data stored that
|
||||
* belongs to IP headers whose identifier, source and destination
|
||||
* addresses are equal to the provided parameters.
|
||||
*
|
||||
* \param id The idenfier to search.
|
||||
* \param addr1 The source address to search.
|
||||
* \param addr2 The destinatin address to search.
|
||||
* \sa IP::id
|
||||
*/
|
||||
void remove_stream(uint16_t id, IPv4Address addr1, IPv4Address addr2);
|
||||
private:
|
||||
typedef std::pair<IPv4Address, IPv4Address> address_pair;
|
||||
typedef std::pair<uint16_t, address_pair> key_type;
|
||||
typedef std::map<key_type, Internals::IPv4Stream> streams_type;
|
||||
|
||||
key_type make_key(const IP *ip) const;
|
||||
address_pair make_address_pair(IPv4Address addr1, IPv4Address addr2) const;
|
||||
|
||||
streams_type streams;
|
||||
overlapping_technique technique;
|
||||
};
|
||||
|
||||
/**
|
||||
* Proxy functor class that reassembles PDUs.
|
||||
*/
|
||||
template<typename Functor>
|
||||
class IPv4ReassemblerProxy {
|
||||
public:
|
||||
/**
|
||||
* Constructs the proxy from a functor object.
|
||||
*
|
||||
* \param func The functor object.
|
||||
*/
|
||||
IPv4ReassemblerProxy(Functor func)
|
||||
: functor_(func)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Tries to reassemble the packet and forwards it to
|
||||
* the functor.
|
||||
*
|
||||
* \param pdu The packet to process
|
||||
* \return true if the packet wasn't forwarded, otherwise
|
||||
* the value returned by the functor.
|
||||
*/
|
||||
bool operator()(PDU &pdu) {
|
||||
// Forward it unless it's fragmented.
|
||||
if(reassembler.process(pdu) != IPv4Reassembler::FRAGMENTED)
|
||||
return functor_(pdu);
|
||||
else
|
||||
return true;
|
||||
}
|
||||
private:
|
||||
IPv4Reassembler reassembler;
|
||||
Functor functor_;
|
||||
};
|
||||
|
||||
/**
|
||||
* Helper function that creates an IPv4ReassemblerProxy.
|
||||
*
|
||||
* \param func The functor object to use in the IPv4ReassemblerProxy.
|
||||
* \return An IPv4ReassemblerProxy.
|
||||
*/
|
||||
template<typename Functor>
|
||||
IPv4ReassemblerProxy<Functor> make_ipv4_reassembler_proxy(Functor func) {
|
||||
return IPv4ReassemblerProxy<Functor>(func);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#endif // TINS_IP_REASSEMBLER_H
|
||||
265
include/tins/ipsec.h
Normal file
265
include/tins/ipsec.h
Normal file
@@ -0,0 +1,265 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Matias Fontanini
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following disclaimer
|
||||
* in the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef TINS_IPSEC_H
|
||||
#define TINS_IPSEC_H
|
||||
|
||||
#include "pdu.h"
|
||||
#include "endianness.h"
|
||||
#include "small_uint.h"
|
||||
|
||||
namespace Tins {
|
||||
/**
|
||||
* \class IPSecAH
|
||||
* \brief Represents an IPSec Authentication Header.
|
||||
*/
|
||||
class IPSecAH : public PDU {
|
||||
public:
|
||||
/**
|
||||
* This PDU's flag.
|
||||
*/
|
||||
static const PDU::PDUType pdu_flag = PDU::IPSEC_AH;
|
||||
|
||||
/**
|
||||
* \brief Default constructor.
|
||||
*
|
||||
* The ICV field is initialized with four 0 bytes. The length
|
||||
* field is initialized appropriately.
|
||||
*/
|
||||
IPSecAH();
|
||||
|
||||
/**
|
||||
* \brief Constructs an IPSecAH 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 an IPSecAH 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.
|
||||
*/
|
||||
IPSecAH(const uint8_t *buffer, uint32_t total_sz);
|
||||
|
||||
// Getters
|
||||
|
||||
/**
|
||||
* \brief Getter for the Next header field.
|
||||
* \return The stored Next header field value.
|
||||
*/
|
||||
uint8_t next_header() const {
|
||||
return _header.next_header;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the Length field.
|
||||
* \return The stored Length field value.
|
||||
*/
|
||||
uint8_t length() const {
|
||||
return _header.length;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the Security Parameters Index field.
|
||||
* \return The stored Security Parameters Index field value.
|
||||
*/
|
||||
uint32_t spi() const {
|
||||
return Endian::be_to_host(_header.spi);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the Sequence number field.
|
||||
* \return The stored Sequence number field value.
|
||||
*/
|
||||
uint32_t seq_number() const {
|
||||
return Endian::be_to_host(_header.seq_number);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the ICV field.
|
||||
* \return The stored ICV field value.
|
||||
*/
|
||||
const byte_array &icv() const {
|
||||
return _icv;
|
||||
}
|
||||
|
||||
// Setters
|
||||
|
||||
/**
|
||||
* \brief Setter for the Next header field.
|
||||
* \param new_next_header The new Next header field value.
|
||||
*/
|
||||
void next_header(uint8_t new_next_header);
|
||||
|
||||
/**
|
||||
* \brief Setter for the Length field.
|
||||
* \param new_length The new Length field value.
|
||||
*/
|
||||
void length(uint8_t new_length);
|
||||
|
||||
/**
|
||||
* \brief Setter for the Security Parameters Index field.
|
||||
* \param new_spi The new Security Parameters Index field value.
|
||||
*/
|
||||
void spi(uint32_t new_spi);
|
||||
|
||||
/**
|
||||
* \brief Setter for the Sequence number field.
|
||||
* \param new_seq_number The new Sequence number field value.
|
||||
*/
|
||||
void seq_number(uint32_t new_seq_number);
|
||||
|
||||
/**
|
||||
* \brief Setter for the ICV field.
|
||||
* \param new_icv The new ICV field value.
|
||||
*/
|
||||
void icv(const byte_array &new_icv);
|
||||
|
||||
/**
|
||||
* \brief Returns the header size.
|
||||
*
|
||||
* This metod overrides PDU::header_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_flag; }
|
||||
|
||||
/**
|
||||
* \sa PDU::clone
|
||||
*/
|
||||
IPSecAH *clone() const {
|
||||
return new IPSecAH(*this);
|
||||
}
|
||||
private:
|
||||
struct header {
|
||||
uint8_t next_header, length;
|
||||
uint32_t spi, seq_number;
|
||||
};
|
||||
|
||||
void write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *);
|
||||
|
||||
header _header;
|
||||
byte_array _icv;
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Represents an IPSec Authentication Header.
|
||||
*/
|
||||
class IPSecESP : public PDU {
|
||||
public:
|
||||
/**
|
||||
* This PDU's flag.
|
||||
*/
|
||||
static const PDU::PDUType pdu_flag = PDU::IPSEC_ESP;
|
||||
|
||||
/**
|
||||
* \brief Default constructor.
|
||||
*/
|
||||
IPSecESP();
|
||||
|
||||
/**
|
||||
* \brief Constructs an IPSecESP 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 an IPSecESP 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.
|
||||
*/
|
||||
IPSecESP(const uint8_t *buffer, uint32_t total_sz);
|
||||
|
||||
// Getters
|
||||
|
||||
/**
|
||||
* \brief Getter for the Security Parameters Index field.
|
||||
* \return The stored Security Parameters Index field value.
|
||||
*/
|
||||
uint32_t spi() const {
|
||||
return Endian::be_to_host(_header.spi);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the Sequence number field.
|
||||
* \return The stored Sequence number field value.
|
||||
*/
|
||||
uint32_t seq_number() const {
|
||||
return Endian::be_to_host(_header.seq_number);
|
||||
}
|
||||
|
||||
// Setters
|
||||
|
||||
/**
|
||||
* \brief Setter for the Security Parameters Index field.
|
||||
* \param new_spi The new Security Parameters Index field value.
|
||||
*/
|
||||
void spi(uint32_t new_spi);
|
||||
|
||||
/**
|
||||
* \brief Setter for the Sequence number field.
|
||||
* \param new_seq_number The new Sequence number field value.
|
||||
*/
|
||||
void seq_number(uint32_t new_seq_number);
|
||||
|
||||
/**
|
||||
* \brief Returns the header size.
|
||||
*
|
||||
* This metod overrides PDU::header_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_flag; }
|
||||
|
||||
/**
|
||||
* \sa PDU::clone
|
||||
*/
|
||||
IPSecESP *clone() const {
|
||||
return new IPSecESP(*this);
|
||||
}
|
||||
private:
|
||||
struct header {
|
||||
uint32_t spi, seq_number;
|
||||
};
|
||||
|
||||
void write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *);
|
||||
|
||||
header _header;
|
||||
};
|
||||
}
|
||||
|
||||
#endif // TINS_IPSEC_H
|
||||
331
include/tins/ipv6.h
Normal file
331
include/tins/ipv6.h
Normal file
@@ -0,0 +1,331 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Matias Fontanini
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following disclaimer
|
||||
* in the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef TINS_IPV6_h
|
||||
#define TINS_IPV6_h
|
||||
|
||||
#include <list>
|
||||
#include <stdexcept>
|
||||
#include "macros.h"
|
||||
#include "pdu.h"
|
||||
#include "endianness.h"
|
||||
#include "small_uint.h"
|
||||
#include "pdu_option.h"
|
||||
#include "ipv6_address.h"
|
||||
|
||||
namespace Tins {
|
||||
class PacketSender;
|
||||
|
||||
/**
|
||||
* \class IPv6
|
||||
* Represents an IPv6 PDU.
|
||||
*/
|
||||
class IPv6 : public PDU {
|
||||
public:
|
||||
/**
|
||||
* This PDU's flag.
|
||||
*/
|
||||
static const PDU::PDUType pdu_flag = PDU::IPv6;
|
||||
|
||||
/**
|
||||
* The type used to store addresses.
|
||||
*/
|
||||
typedef IPv6Address address_type;
|
||||
|
||||
/**
|
||||
* The type used to represent IPv6 extension headers.
|
||||
*/
|
||||
typedef PDUOption<uint8_t, IPv6> ext_header;
|
||||
|
||||
/**
|
||||
* The type used to store the extension headers.
|
||||
*/
|
||||
typedef std::list<ext_header> headers_type;
|
||||
|
||||
/**
|
||||
* The values used to identify extension headers.
|
||||
*/
|
||||
enum ExtensionHeader {
|
||||
HOP_BY_HOP = 0,
|
||||
DESTINATION_ROUTING_OPTIONS = 60,
|
||||
ROUTING = 43,
|
||||
FRAGMENT = 44,
|
||||
AUTHENTICATION = 51,
|
||||
SECURITY_ENCAPSULATION = 50,
|
||||
DESTINATION_OPTIONS = 60,
|
||||
MOBILITY = 135,
|
||||
NO_NEXT_HEADER = 59
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Constructs an IPv6 object.
|
||||
*
|
||||
* \param ip_dst The destination ip address(optional).
|
||||
* \param ip_src The source ip address(optional).
|
||||
* \param child pointer to a PDU which will be set as the inner_pdu
|
||||
* for the packet being constructed(optional).
|
||||
*/
|
||||
IPv6(address_type ip_dst = address_type(),
|
||||
address_type ip_src = address_type(),
|
||||
PDU *child = 0);
|
||||
|
||||
/**
|
||||
* \brief Constructs an IPv6 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 an IPv6 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.
|
||||
*/
|
||||
IPv6(const uint8_t *buffer, uint32_t total_sz);
|
||||
|
||||
// Getters
|
||||
|
||||
/**
|
||||
* \brief Getter for the version field.
|
||||
* \return The stored version field value.
|
||||
*/
|
||||
small_uint<4> version() const {
|
||||
return _header.version;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the traffic_class field.
|
||||
* \return The stored traffic_class field value.
|
||||
*/
|
||||
uint8_t traffic_class() const {
|
||||
#if TINS_IS_LITTLE_ENDIAN
|
||||
return ((_header.traffic_class << 4) & 0xf0) |
|
||||
((_header.flow_label[0] >> 4) & 0x0f);
|
||||
#else
|
||||
return _header.traffic_class;
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the flow_label field.
|
||||
* \return The stored flow_label field value.
|
||||
*/
|
||||
small_uint<20> flow_label() const {
|
||||
#if TINS_IS_LITTLE_ENDIAN
|
||||
return ((_header.flow_label[0] & 0x0f) << 16)
|
||||
| (_header.flow_label[1] << 8)
|
||||
| (_header.flow_label[2]);
|
||||
#else
|
||||
return _header.flow_label;
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the payload_length field.
|
||||
* \return The stored payload_length field value.
|
||||
*/
|
||||
uint16_t payload_length() const {
|
||||
return Endian::be_to_host(_header.payload_length);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the next_header field.
|
||||
* \return The stored next_header field value.
|
||||
*/
|
||||
uint8_t next_header() const {
|
||||
return _header.next_header;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the hop_limit field.
|
||||
* \return The stored hop_limit field value.
|
||||
*/
|
||||
uint8_t hop_limit() const {
|
||||
return _header.hop_limit;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the src_addr field.
|
||||
* \return The stored src_addr field value.
|
||||
*/
|
||||
address_type src_addr() const {
|
||||
return _header.src_addr;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the dst_addr field.
|
||||
* \return The stored dst_addr field value.
|
||||
*/
|
||||
address_type dst_addr() const {
|
||||
return _header.dst_addr;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the IPv6 extension headers.
|
||||
* \return The stored headers.
|
||||
*/
|
||||
const headers_type& headers() const {
|
||||
return ext_headers;
|
||||
}
|
||||
|
||||
// Setters
|
||||
|
||||
/**
|
||||
* \brief Setter for the version field.
|
||||
* \param new_version The new version field value.
|
||||
*/
|
||||
void version(small_uint<4> new_version);
|
||||
|
||||
/**
|
||||
* \brief Setter for the traffic_class field.
|
||||
* \param new_traffic_class The new traffic_class field value.
|
||||
*/
|
||||
void traffic_class(uint8_t new_traffic_class);
|
||||
|
||||
/**
|
||||
* \brief Setter for the flow_label field.
|
||||
* \param new_flow_label The new flow_label field value.
|
||||
*/
|
||||
void flow_label(small_uint<20> new_flow_label);
|
||||
|
||||
/**
|
||||
* \brief Setter for the payload_length field.
|
||||
* \param new_payload_length The new payload_length field value.
|
||||
*/
|
||||
void payload_length(uint16_t new_payload_length);
|
||||
|
||||
/**
|
||||
* \brief Setter for the next_header field.
|
||||
* \param new_next_header The new next_header field value.
|
||||
*/
|
||||
void next_header(uint8_t new_next_header);
|
||||
|
||||
/**
|
||||
* \brief Setter for the hop_limit field.
|
||||
* \param new_hop_limit The new hop_limit field value.
|
||||
*/
|
||||
void hop_limit(uint8_t new_hop_limit);
|
||||
|
||||
/**
|
||||
* \brief Setter for the src_addr field.
|
||||
* \param new_src_addr The new src_addr field value.
|
||||
*/
|
||||
void src_addr(const address_type &new_src_addr);
|
||||
|
||||
/**
|
||||
* \brief Setter for the dst_addr field.
|
||||
* \param new_dst_addr The new dst_addr field value.
|
||||
*/
|
||||
void dst_addr(const address_type &new_dst_addr);
|
||||
|
||||
/**
|
||||
* \brief Returns the header size.
|
||||
*
|
||||
* This metod overrides PDU::header_size. \sa PDU::header_size
|
||||
*/
|
||||
uint32_t header_size() const;
|
||||
|
||||
/**
|
||||
* \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;
|
||||
|
||||
/**
|
||||
* \sa PDU::clone
|
||||
*/
|
||||
IPv6 *clone() const {
|
||||
return new IPv6(*this);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the PDU's type.
|
||||
* \sa PDU::pdu_type
|
||||
*/
|
||||
PDUType pdu_type() const { return pdu_flag; }
|
||||
|
||||
#ifndef BSD
|
||||
/**
|
||||
* \sa PDU::send()
|
||||
*/
|
||||
void send(PacketSender &sender, const NetworkInterface &);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Adds an extension header.
|
||||
*
|
||||
* \param header The extension header to be added.
|
||||
*/
|
||||
void add_ext_header(const ext_header &header);
|
||||
|
||||
/**
|
||||
* \brief Searchs for an extension header that matchs the given
|
||||
* flag.
|
||||
*
|
||||
* If the header is not found, a null pointer is returned.
|
||||
* Deleting the returned pointer will result in <b>undefined
|
||||
* behaviour</b>.
|
||||
*
|
||||
* \param id The header identifier to be searched.
|
||||
*/
|
||||
const ext_header *search_header(ExtensionHeader id) const;
|
||||
private:
|
||||
void write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *parent);
|
||||
void set_last_next_header(uint8_t value);
|
||||
static uint8_t *write_header(const ext_header &header, uint8_t *buffer);
|
||||
static bool is_extension_header(uint8_t header_id);
|
||||
|
||||
TINS_BEGIN_PACK
|
||||
struct ipv6_header {
|
||||
#if TINS_IS_BIG_ENDIAN
|
||||
uint32_t version:4,
|
||||
traffic_class:8,
|
||||
flow_label:20;
|
||||
uint32_t payload_length:16,
|
||||
next_header:8,
|
||||
hop_limit:8;
|
||||
#else
|
||||
uint8_t traffic_class:4,
|
||||
version:4;
|
||||
uint8_t flow_label[3];
|
||||
uint16_t payload_length;
|
||||
uint8_t next_header;
|
||||
uint8_t hop_limit;
|
||||
#endif
|
||||
uint8_t src_addr[16], dst_addr[16];
|
||||
} TINS_END_PACK;
|
||||
|
||||
ipv6_header _header;
|
||||
headers_type ext_headers;
|
||||
uint32_t headers_size;
|
||||
};
|
||||
}
|
||||
|
||||
#endif // TINS_IPV6_h
|
||||
230
include/tins/ipv6_address.h
Normal file
230
include/tins/ipv6_address.h
Normal file
@@ -0,0 +1,230 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Matias Fontanini
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following disclaimer
|
||||
* in the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef TINS_IPV6_ADDRESS
|
||||
#define TINS_IPV6_ADDRESS
|
||||
|
||||
#include <string>
|
||||
#include <stdexcept>
|
||||
#include <stdint.h>
|
||||
#include "cxxstd.h"
|
||||
|
||||
namespace Tins {
|
||||
|
||||
/**
|
||||
* Represents an IPv6 address.
|
||||
*/
|
||||
class IPv6Address {
|
||||
public:
|
||||
/**
|
||||
* The exception thrown when a malformed address is parsed.
|
||||
*/
|
||||
class malformed_address : public std::exception {
|
||||
public:
|
||||
const char *what() const throw() {
|
||||
return "Malformed address";
|
||||
}
|
||||
};
|
||||
|
||||
static const size_t address_size = 16;
|
||||
|
||||
/**
|
||||
* The iterator type.
|
||||
*/
|
||||
typedef uint8_t* iterator;
|
||||
|
||||
/**
|
||||
* The const iterator type.
|
||||
*/
|
||||
typedef const uint8_t* const_iterator;
|
||||
|
||||
/**
|
||||
* \brief Default constructor.
|
||||
* Initializes this IPv6 address to "::"
|
||||
*/
|
||||
IPv6Address();
|
||||
|
||||
/**
|
||||
* \brief Constructor from a text representation char*.
|
||||
* \param addr The text representation from which to construct this
|
||||
* object.
|
||||
*/
|
||||
IPv6Address(const char *addr);
|
||||
|
||||
/**
|
||||
* \brief Constructor from a text representation std::string.
|
||||
* \param addr The text representation from which to construct this
|
||||
* object.
|
||||
*/
|
||||
IPv6Address(const std::string &addr);
|
||||
|
||||
/**
|
||||
* \brief Constructor from a buffer.
|
||||
*
|
||||
* The ptr parameter must be at least address_size bytes long.
|
||||
*
|
||||
* \param ptr The buffer from which to construct this object.
|
||||
*/
|
||||
IPv6Address(const_iterator ptr);
|
||||
|
||||
/**
|
||||
* \brief Retrieve the string representation of this address.
|
||||
*
|
||||
* \return std::string containing the representation of this address.
|
||||
*/
|
||||
std::string to_string() const;
|
||||
|
||||
/**
|
||||
* Returns an iterator to the beginning of this address.
|
||||
*/
|
||||
iterator begin() {
|
||||
return address;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a const iterator to the beginning of this address.
|
||||
*/
|
||||
const_iterator begin() const {
|
||||
return address;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an iterator to the one-past-the-end element of this address.
|
||||
*/
|
||||
iterator end() {
|
||||
return address + address_size;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a const iterator to the one-past-the-end element of this
|
||||
* address.
|
||||
*/
|
||||
const_iterator end() const {
|
||||
return address + address_size;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Compares this address for equality.
|
||||
*
|
||||
* \param rhs The address to be compared to.
|
||||
*
|
||||
* \return bool indicating whether addresses are equal.
|
||||
*/
|
||||
bool operator==(const IPv6Address &rhs) const {
|
||||
return std::equal(begin(), end(), rhs.begin());
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Compares this address for inequality.
|
||||
*
|
||||
* \param rhs The address to be compared to.
|
||||
*
|
||||
* \return bool indicating whether addresses are distinct.
|
||||
*/
|
||||
bool operator!=(const IPv6Address &rhs) const {
|
||||
return !(*this == rhs);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Compares this address for less-than inequality.
|
||||
*
|
||||
* \param rhs The address to be compared to.
|
||||
*
|
||||
* \return bool indicating whether this address is less-than rhs.
|
||||
*/
|
||||
bool operator<(const IPv6Address &rhs) const {
|
||||
return std::lexicographical_compare(begin(), end(), rhs.begin(), rhs.end());
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Helper function which copies the address into an output
|
||||
* iterator.
|
||||
*
|
||||
* This is the same as:
|
||||
*
|
||||
* std::copy(begin(), end(), iter);
|
||||
*
|
||||
* But since some PDUs return a IPv6Address by value, this function
|
||||
* can be used to avoid temporaries.
|
||||
*
|
||||
* \param iter The output iterator in which to store this address.
|
||||
* \return OutputIterator pointing to one-past the last position
|
||||
* written.
|
||||
*/
|
||||
template<typename OutputIterator>
|
||||
OutputIterator copy(OutputIterator iter) const {
|
||||
return std::copy(begin(), end(), iter);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Returns true if this is a loopback IPv6 address.
|
||||
*
|
||||
* This method returns true if this address is the ::1/128 address,
|
||||
* false otherwise.
|
||||
*/
|
||||
bool is_loopback() const;
|
||||
|
||||
/**
|
||||
* \brief Returns true if this is a multicast IPv6 address.
|
||||
*
|
||||
* This method returns true if this address is in the address range
|
||||
* ff00::/8, false otherwise.
|
||||
*/
|
||||
bool is_multicast() const;
|
||||
|
||||
/**
|
||||
* \brief Writes this address in hex-notation to a std::ostream.
|
||||
*
|
||||
* \param os The stream in which to write the address.
|
||||
* \param addr The parameter to be written.
|
||||
* \return std::ostream& pointing to the os parameter.
|
||||
*/
|
||||
friend std::ostream &operator<<(std::ostream &os, const IPv6Address &addr) {
|
||||
return os << addr.to_string();
|
||||
}
|
||||
private:
|
||||
void init(const char *addr);
|
||||
|
||||
uint8_t address[address_size];
|
||||
};
|
||||
} //namespace Tins
|
||||
|
||||
#if TINS_IS_CXX11
|
||||
namespace std
|
||||
{
|
||||
template<>
|
||||
struct hash<Tins::IPv6Address> {
|
||||
size_t operator()(const Tins::IPv6Address &addr) const {
|
||||
return std::hash<std::string>()(addr.to_string());
|
||||
}
|
||||
};
|
||||
} // namespace std
|
||||
#endif
|
||||
|
||||
#endif // TINS_IPV6_ADDRESS
|
||||
403
include/tins/llc.h
Normal file
403
include/tins/llc.h
Normal file
@@ -0,0 +1,403 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Matias Fontanini
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following disclaimer
|
||||
* in the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef TINS_IEEE8022_H
|
||||
#define TINS_IEEE8022_H
|
||||
|
||||
#include <list>
|
||||
#include <vector>
|
||||
#include <stdint.h>
|
||||
#include "macros.h"
|
||||
#include "pdu.h"
|
||||
#include "endianness.h"
|
||||
|
||||
namespace Tins {
|
||||
|
||||
/**
|
||||
* \class LLC
|
||||
* \brief Representing a LLC frame.
|
||||
*
|
||||
* This PDU follows the standard LLC frame described in the IEEE 802.2 specs.
|
||||
*/
|
||||
class LLC : public PDU {
|
||||
public:
|
||||
/**
|
||||
* \brief This PDU's flag.
|
||||
*/
|
||||
static const PDU::PDUType pdu_flag = PDU::LLC;
|
||||
|
||||
/**
|
||||
* \brief Represents the LLC global DSAP address.
|
||||
*/
|
||||
static const uint8_t GLOBAL_DSAP_ADDR;
|
||||
|
||||
/**
|
||||
* \brief Represents the LLC NULL address.
|
||||
*/
|
||||
static const uint8_t NULL_ADDR;
|
||||
|
||||
/**
|
||||
* \brief LLC Format flags.
|
||||
*/
|
||||
enum Format {
|
||||
INFORMATION = 0,
|
||||
SUPERVISORY = 1,
|
||||
UNNUMBERED = 3
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief LLC Modifier functions.
|
||||
*/
|
||||
enum ModifierFunctions {
|
||||
UI = 0x00,
|
||||
XID = 0x1D,
|
||||
TEST = 0x07,
|
||||
SABME = 0x1E,
|
||||
DISC = 0x02,
|
||||
UA = 0x06,
|
||||
DM = 0x18,
|
||||
FRMR = 0x11
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief LLC Supervisory functions
|
||||
*/
|
||||
enum SupervisoryFunctions {
|
||||
RECEIVE_READY = 0,
|
||||
REJECT = 2,
|
||||
RECEIVE_NOT_READY = 1
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Default constructor.
|
||||
*/
|
||||
LLC();
|
||||
|
||||
/**
|
||||
* \brief Constructs an instance of LLC, setting the dsap and ssap.
|
||||
* The control field is set to 0.
|
||||
* \param dsap The dsap value to be set.
|
||||
* \param ssap The ssap value to be set.
|
||||
*/
|
||||
LLC(uint8_t dsap, uint8_t ssap);
|
||||
|
||||
/**
|
||||
* \brief Constructs a LLC 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 LLC 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.
|
||||
*/
|
||||
LLC(const uint8_t *buffer, uint32_t total_sz);
|
||||
|
||||
/* Setters */
|
||||
|
||||
/**
|
||||
* \brief Setter for the group destination bit.
|
||||
* \param value The value to be set.
|
||||
*/
|
||||
void group(bool value);
|
||||
|
||||
/**
|
||||
* \brief Setter for the dsap field.
|
||||
* \param new_dsap The new dsap field.
|
||||
*/
|
||||
void dsap(uint8_t new_dsap);
|
||||
|
||||
/**
|
||||
* \brief Setter for the response bit.
|
||||
* \param value The value to be set.
|
||||
*/
|
||||
void response(bool value);
|
||||
|
||||
/**
|
||||
* \brief Setter for the ssap field.
|
||||
* \param new_ssap The new ssap field.
|
||||
*/
|
||||
void ssap(uint8_t new_ssap);
|
||||
|
||||
/**
|
||||
* \brief Setter for the LLC frame format type.
|
||||
* \param type The LLC frame format to set.
|
||||
*/
|
||||
void type(Format type);
|
||||
|
||||
/**
|
||||
* \brief Setter for sender send sequence number.
|
||||
* Only applied if format is INFORMATION.
|
||||
* \param seq_number New sender send sequence number to be set.
|
||||
*/
|
||||
void send_seq_number(uint8_t seq_number);
|
||||
|
||||
/**
|
||||
* \brief Setter for sender receive sequence number.
|
||||
* Only applied if format is INFORMATION or SUPERVISORY.
|
||||
* \param seq_number New sender receive sequence number to be set.
|
||||
*/
|
||||
void receive_seq_number(uint8_t seq_number);
|
||||
|
||||
/**
|
||||
* \brief Setter for the poll/final flag.
|
||||
* \param value Bool indicating the value of the flag.
|
||||
*/
|
||||
void poll_final(bool value);
|
||||
|
||||
/**
|
||||
* \brief Setter for the supervisory function.
|
||||
* Only applied if format is SUPERVISORY.
|
||||
* \param new_func Value to set on the supervisory function field.
|
||||
*/
|
||||
void supervisory_function(SupervisoryFunctions new_func);
|
||||
|
||||
/**
|
||||
* \brief Setter for the modifier function field.
|
||||
* Only applied if format is UNNUMBERED.
|
||||
* \param modifier_func Value to set on the modifier function field.
|
||||
*/
|
||||
void modifier_function(ModifierFunctions mod_func);
|
||||
|
||||
/**
|
||||
* \brief Add a xid information field.
|
||||
* Only applied if format is UNNUMBERED and function is XID.
|
||||
* \param xid_id XID information of the MAC sublayer.
|
||||
* \param llc_type_class Value to set the llc_type_class field.
|
||||
* \param receive_window XID sender's receive window size.
|
||||
*/
|
||||
void add_xid_information(uint8_t xid_id, uint8_t llc_type_class, uint8_t receive_window);
|
||||
|
||||
//TODO: Add Acknowledged connectionless information
|
||||
|
||||
/* Getters */
|
||||
|
||||
/**
|
||||
* \brief Getter for the group destination bit.
|
||||
* \return Whether the group bit is set or not.
|
||||
*/
|
||||
bool group() {return _header.dsap & 0x01; }
|
||||
|
||||
/**
|
||||
* \brief Getter for the dsap field.
|
||||
* \return The dsap field value
|
||||
*/
|
||||
uint8_t dsap() {return _header.dsap; }
|
||||
|
||||
/**
|
||||
* \brief Getter for the response bit.
|
||||
* \return Whether the response bit is set or not.
|
||||
*/
|
||||
bool response() {return (_header.ssap & 0x01); }
|
||||
|
||||
/**
|
||||
* \brief Getter for the ssap field.
|
||||
* \return The ssap field.
|
||||
*/
|
||||
uint8_t ssap() {return _header.ssap; }
|
||||
|
||||
/**
|
||||
* \brief Getter for the LLC frame format type.
|
||||
* \return The LLC frame format.
|
||||
*/
|
||||
uint8_t type() {return _type; }
|
||||
|
||||
/**
|
||||
* \brief Getter for sender send sequence number.
|
||||
*
|
||||
* \return The sender send sequence number if format is INFORMATION else 0.
|
||||
*/
|
||||
uint8_t send_seq_number() {
|
||||
return (type() == INFORMATION) ? (control_field.info.send_seq_num) : 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for sender receive sequence number.
|
||||
*
|
||||
* \return The sender receive sequence number if format is
|
||||
* INFORMATION or SUPERVISORY else 0.
|
||||
*/
|
||||
uint8_t receive_seq_number() {
|
||||
switch (type()) {
|
||||
case INFORMATION:
|
||||
return control_field.info.recv_seq_num;
|
||||
case SUPERVISORY:
|
||||
return control_field.super.recv_seq_num;
|
||||
case UNNUMBERED:
|
||||
return 0;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the poll/final flag.
|
||||
* \return Whether the poll/final flag is set.
|
||||
*/
|
||||
bool poll_final() {
|
||||
switch (type()) {
|
||||
case UNNUMBERED:
|
||||
return control_field.unnumbered.poll_final_bit;
|
||||
case INFORMATION:
|
||||
return control_field.info.poll_final_bit;
|
||||
case SUPERVISORY:
|
||||
return control_field.super.poll_final_bit;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the supervisory function.
|
||||
*
|
||||
* \return The supervisory function if format is SUPERVISORY else 0.
|
||||
*/
|
||||
uint8_t supervisory_function() {
|
||||
if (type() == SUPERVISORY)
|
||||
return control_field.super.supervisory_func;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the modifier function field.
|
||||
*
|
||||
* \return The modifier function if format is UNNUMBERED else 0.
|
||||
*/
|
||||
uint8_t modifier_function() {
|
||||
if (type() == UNNUMBERED)
|
||||
return (control_field.unnumbered.mod_func1 << 3) + control_field.unnumbered.mod_func2;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Returns the LLC frame's header length.
|
||||
*
|
||||
* \return 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_flag; }
|
||||
|
||||
/**
|
||||
* \brief Delete all the information fields added.
|
||||
*/
|
||||
void clear_information_fields();
|
||||
|
||||
/**
|
||||
* \brief Clones this PDU.
|
||||
*
|
||||
* \sa PDU::clone
|
||||
*/
|
||||
LLC *clone() const {
|
||||
return new LLC(*this);
|
||||
}
|
||||
private:
|
||||
TINS_BEGIN_PACK
|
||||
struct llchdr {
|
||||
uint8_t dsap;
|
||||
uint8_t ssap;
|
||||
} TINS_END_PACK;
|
||||
|
||||
#if TINS_IS_LITTLE_ENDIAN
|
||||
TINS_BEGIN_PACK
|
||||
struct info_control_field {
|
||||
uint16_t
|
||||
type_bit:1,
|
||||
send_seq_num:7,
|
||||
poll_final_bit:1,
|
||||
recv_seq_num:7;
|
||||
} TINS_END_PACK;
|
||||
|
||||
TINS_BEGIN_PACK
|
||||
struct super_control_field {
|
||||
uint16_t type_bit:2,
|
||||
supervisory_func:2,
|
||||
unused:4,
|
||||
poll_final_bit:1,
|
||||
recv_seq_num:7;
|
||||
} TINS_END_PACK;
|
||||
|
||||
TINS_BEGIN_PACK
|
||||
struct un_control_field {
|
||||
uint8_t type_bits:2,
|
||||
mod_func1:2,
|
||||
poll_final_bit:1,
|
||||
mod_func2:3;
|
||||
} TINS_END_PACK;
|
||||
#elif TINS_IS_BIG_ENDIAN
|
||||
TINS_BEGIN_PACK
|
||||
struct info_control_field {
|
||||
uint16_t send_seq_num:7,
|
||||
type_bit:1,
|
||||
recv_seq_num:7,
|
||||
poll_final_bit:1;
|
||||
} TINS_END_PACK;
|
||||
|
||||
TINS_BEGIN_PACK
|
||||
struct super_control_field {
|
||||
uint16_t unused:4,
|
||||
supervisory_func:2,
|
||||
type_bit:2,
|
||||
recv_seq_num:7,
|
||||
poll_final_bit:1;
|
||||
} TINS_END_PACK;
|
||||
|
||||
TINS_BEGIN_PACK
|
||||
struct un_control_field {
|
||||
uint8_t mod_func2:3,
|
||||
poll_final_bit:1,
|
||||
mod_func1:2,
|
||||
type_bits:2;
|
||||
} TINS_END_PACK;
|
||||
#endif
|
||||
|
||||
typedef std::vector<uint8_t> field_type;
|
||||
|
||||
void write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *parent);
|
||||
|
||||
llchdr _header;
|
||||
uint8_t control_field_length;
|
||||
union {
|
||||
info_control_field info;
|
||||
super_control_field super;
|
||||
un_control_field unnumbered;
|
||||
} control_field;
|
||||
Format _type;
|
||||
uint8_t information_field_length;
|
||||
std::list<field_type> information_fields;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // TINS_IEEE8022_H
|
||||
109
include/tins/loopback.h
Normal file
109
include/tins/loopback.h
Normal file
@@ -0,0 +1,109 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Matias Fontanini
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following disclaimer
|
||||
* in the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef TINS_LOOPBACK_H
|
||||
#define TINS_LOOPBACK_H
|
||||
|
||||
#include "pdu.h"
|
||||
#include "macros.h"
|
||||
|
||||
namespace Tins {
|
||||
class Loopback : public PDU {
|
||||
public:
|
||||
/**
|
||||
* This PDU's type.
|
||||
*/
|
||||
static const PDU::PDUType pdu_flag = PDU::LOOPBACK;
|
||||
|
||||
/**
|
||||
* \brief Default constructs a Loopback PDU.
|
||||
*
|
||||
* The family identifier is left as zero.
|
||||
*/
|
||||
Loopback();
|
||||
|
||||
/**
|
||||
* \brief Construct a Loopback object from a buffer and adds
|
||||
* all identifiable PDUs found in the buffer as children of
|
||||
* this one.
|
||||
*
|
||||
* If the next PDU is not recognized, then a RawPDU is used.
|
||||
*
|
||||
* If there is not enough size for a Loopback 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.
|
||||
*/
|
||||
Loopback(const uint8_t *buffer, uint32_t total_sz);
|
||||
|
||||
/**
|
||||
* \brief Getter for the family identifier.
|
||||
* \return The stored family identifier.
|
||||
*/
|
||||
uint32_t family() const { return _family; }
|
||||
|
||||
/**
|
||||
* \brief Setter for the family identifier.
|
||||
* \param family_id The family identifier to be set.
|
||||
*/
|
||||
void family(uint32_t family_id);
|
||||
|
||||
/**
|
||||
* \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_flag; }
|
||||
|
||||
/**
|
||||
* \sa PDU::clone
|
||||
*/
|
||||
Loopback *clone() const {
|
||||
return new Loopback(*this);
|
||||
}
|
||||
// Null/Loopback can only be sent in *BSD
|
||||
#ifdef BSD
|
||||
/**
|
||||
* \sa PDU::send()
|
||||
*/
|
||||
void send(PacketSender &sender, const NetworkInterface &iface);
|
||||
#endif // BSD
|
||||
private:
|
||||
void write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *parent);
|
||||
|
||||
uint32_t _family;
|
||||
};
|
||||
}
|
||||
|
||||
#endif // TINS_LOOPBACK_H
|
||||
52
include/tins/macros.h
Normal file
52
include/tins/macros.h
Normal file
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Matias Fontanini
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following disclaimer
|
||||
* in the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef TINS_MACROS_H
|
||||
#define TINS_MACROS_H
|
||||
|
||||
#if defined(__unix__) || (defined(__APPLE__) && defined(__MACH__))
|
||||
#include <sys/param.h>
|
||||
#endif
|
||||
|
||||
// Packing directives....
|
||||
#ifdef _MSC_VER
|
||||
#define TINS_BEGIN_PACK __pragma( pack(push, 1) )
|
||||
#define TINS_END_PACK __pragma( pack(pop) )
|
||||
#define TINS_PACKED(DECLARATION) __pragma( pack(push, 1) ) DECLARATION __pragma( pack(pop) )
|
||||
#define TINS_DEPRECATED(func) __declspec(deprecated) func
|
||||
#define TINS_NOEXCEPT
|
||||
#else
|
||||
#define TINS_BEGIN_PACK
|
||||
#define TINS_END_PACK __attribute__((packed))
|
||||
#define TINS_PACKED(DECLARATION) DECLARATION __attribute__((packed))
|
||||
#define TINS_DEPRECATED(func) func __attribute__ ((deprecated))
|
||||
#define TINS_NOEXCEPT noexcept
|
||||
#endif
|
||||
|
||||
#endif
|
||||
171
include/tins/network_interface.h
Normal file
171
include/tins/network_interface.h
Normal file
@@ -0,0 +1,171 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Matias Fontanini
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following disclaimer
|
||||
* in the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef TINS_NETWORK_INTERFACE_H
|
||||
#define TINS_NETWORK_INTERFACE_H
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <stdint.h>
|
||||
#include "hw_address.h"
|
||||
#include "ip_address.h"
|
||||
|
||||
namespace Tins {
|
||||
/**
|
||||
* \class NetworkInterface
|
||||
* \brief Abstraction of a network interface
|
||||
*/
|
||||
class NetworkInterface {
|
||||
public:
|
||||
/**
|
||||
* \brief The type used to store the interface's identifier.
|
||||
*/
|
||||
typedef uint32_t id_type;
|
||||
|
||||
/**
|
||||
* \brief The type of this interface's address.
|
||||
*/
|
||||
typedef HWAddress<6> address_type;
|
||||
|
||||
/**
|
||||
* \brief Struct that holds an interface's addresses.
|
||||
*/
|
||||
struct Info {
|
||||
IPv4Address ip_addr, netmask, bcast_addr;
|
||||
address_type hw_addr;
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns a NetworkInterface object associated with the default
|
||||
* interface.
|
||||
*/
|
||||
static NetworkInterface default_interface();
|
||||
|
||||
/**
|
||||
* Returns all available network interfaces.
|
||||
*/
|
||||
static std::vector<NetworkInterface> all();
|
||||
|
||||
/**
|
||||
* Returns a network interface for the given index.
|
||||
*/
|
||||
static NetworkInterface from_index(id_type identifier);
|
||||
|
||||
/**
|
||||
* Default constructor.
|
||||
*/
|
||||
NetworkInterface();
|
||||
|
||||
/**
|
||||
* \brief Constructor from std::string.
|
||||
*
|
||||
* \param name The name of the interface this object will abstract.
|
||||
*/
|
||||
NetworkInterface(const std::string &name);
|
||||
|
||||
/**
|
||||
* \brief Constructor from const char*.
|
||||
*
|
||||
* \param name The name of the interface this object will abstract.
|
||||
*/
|
||||
NetworkInterface(const char *name);
|
||||
|
||||
/**
|
||||
* \brief Constructs a NetworkInterface from an ip address.
|
||||
*
|
||||
* This abstracted interface will be the one that would be the gateway
|
||||
* when sending a packet to the given ip.
|
||||
*
|
||||
* \param ip The ip address being looked up.
|
||||
*/
|
||||
NetworkInterface(IPv4Address ip);
|
||||
|
||||
/**
|
||||
* \brief Getter for this interface's identifier.
|
||||
*
|
||||
* \return id_type containing the identifier.
|
||||
*/
|
||||
id_type id() const {
|
||||
return iface_id;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Retrieves this interface's name.
|
||||
*
|
||||
* This name can be used as the interface name provided to the
|
||||
* Sniffer class when starting a sniffing session.
|
||||
*
|
||||
* \sa Sniffer
|
||||
* \return std::string containing this interface's name.
|
||||
*/
|
||||
std::string name() const;
|
||||
|
||||
/**
|
||||
* \brief Retrieve this interface's addresses.
|
||||
*
|
||||
* This method iterates through all the interface's until the
|
||||
* correct one is found. Therefore it's O(N), being N the amount
|
||||
* of interfaces in the system.
|
||||
*/
|
||||
Info addresses() const;
|
||||
|
||||
/**
|
||||
* \brief Tests whether this is a valid interface;
|
||||
*
|
||||
* An interface will not be valid iff it was created using the
|
||||
* default constructor.
|
||||
*/
|
||||
operator bool() const {
|
||||
return iface_id != 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Compares this interface for equality.
|
||||
*
|
||||
* \param rhs The interface being compared.
|
||||
*/
|
||||
bool operator==(const NetworkInterface &rhs) const {
|
||||
return iface_id == rhs.iface_id;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Compares this interface for inequality.
|
||||
*
|
||||
* \param rhs The interface being compared.
|
||||
*/
|
||||
bool operator!=(const NetworkInterface &rhs) const {
|
||||
return !(*this == rhs);
|
||||
}
|
||||
private:
|
||||
id_type resolve_index(const char *name);
|
||||
|
||||
id_type iface_id;
|
||||
};
|
||||
}
|
||||
#endif // TINS_NETWORK_INTERFACE_H
|
||||
157
include/tins/offline_packet_filter.h
Normal file
157
include/tins/offline_packet_filter.h
Normal file
@@ -0,0 +1,157 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Matias Fontanini
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following disclaimer
|
||||
* in the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef TINS_OFFLINE_PACKET_FILTER_H
|
||||
#define TINS_OFFLINE_PACKET_FILTER_H
|
||||
|
||||
#include <string>
|
||||
#include <stdint.h>
|
||||
#include "data_link_type.h"
|
||||
|
||||
namespace Tins {
|
||||
class PDU;
|
||||
|
||||
/**
|
||||
* \class OfflinePacketFilter
|
||||
*
|
||||
* \brief Wraps a pcap filter and matches it against a packet or buffer.
|
||||
*
|
||||
* This is a thin wrapper over <i>pcap_offline_filter</i>. You can use
|
||||
* it to perform packet filtering outside of Sniffer instances.
|
||||
*
|
||||
* A potential use case would be if you are capturing packets that are
|
||||
* sent from another host over UDP. You would recieve UDP packets, then
|
||||
* parse their content, and apply the OfflinePacketFilter over the
|
||||
* wrapped packet. For example:
|
||||
*
|
||||
* \code
|
||||
* // Assume we get an UDP packet from somewhere.
|
||||
* // Inside the payload, there will be a complete packet
|
||||
* // including its link layer protocol.
|
||||
* UDP udp = get_packet();
|
||||
*
|
||||
* // Create the filter. We'll be expecting Ethernet packets.
|
||||
* OfflinePacketFilter filter("ip and port 80", DataLinkLayer<EthernetII>());
|
||||
*
|
||||
* // We can use this directly over the inner PDU (assuming it has one)
|
||||
* // See the notes on the efficiency of doing it this way.
|
||||
* if(filter.matches_filter(*udp.inner_pdu())) {
|
||||
* // Matches!
|
||||
* }
|
||||
*
|
||||
* // We can also use the payload. This version it faster and should
|
||||
* // be preferred over the one above
|
||||
* const RawPDU& raw = udp.rfind_pdu<RawPDU>();
|
||||
* const auto& payload = raw.payload();
|
||||
* if(filter.matches_filter(payload.data(), payload.size())) {
|
||||
* // Matches!
|
||||
* }
|
||||
* \endcode
|
||||
*/
|
||||
class OfflinePacketFilter {
|
||||
public:
|
||||
/**
|
||||
* Constructs an OfflinePacketFilter object.
|
||||
*
|
||||
* \param filter The pcap filter to use.
|
||||
* \param lt The link layer type to use.
|
||||
* \param snap_len The snapshot length to use.
|
||||
*/
|
||||
template<typename T>
|
||||
OfflinePacketFilter(const std::string& filter, const DataLinkType<T>& lt,
|
||||
unsigned int snap_len = 65535)
|
||||
: string_filter(filter)
|
||||
{
|
||||
init(filter, lt.get_type(), snap_len);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Copy constructor.
|
||||
*
|
||||
* Note that during copy construction the pcap filter is
|
||||
* recompiled. Therefore, it might be somehow expensive to
|
||||
* copy OfflinePacketFilters.
|
||||
*
|
||||
* \param other The filter to be copied.
|
||||
*/
|
||||
OfflinePacketFilter(const OfflinePacketFilter& other);
|
||||
|
||||
/**
|
||||
* \brief Copy assignment operator.
|
||||
*
|
||||
* \param other The filter to be copied.
|
||||
*
|
||||
* \sa OfflinePacketFilter
|
||||
*/
|
||||
OfflinePacketFilter& operator=(const OfflinePacketFilter& other);
|
||||
|
||||
/**
|
||||
* Releases the compiled pcap filter and handle.
|
||||
*/
|
||||
~OfflinePacketFilter();
|
||||
|
||||
/**
|
||||
* \brief Applies the compiled filter on the provided buffer.
|
||||
*
|
||||
* This method uses <i>pcap_offline_filter</i> on the provided buffer
|
||||
* and returns a bool indicating if the packet pointed by the buffer
|
||||
* matches the filter.
|
||||
*
|
||||
* \param buffer A pointer to a buffer which holds a raw packet.
|
||||
* \param total_sz The length of the buffer pointed by buffer.
|
||||
* \return true iff the packet matches the filter.
|
||||
*/
|
||||
bool matches_filter(const uint8_t* buffer, uint32_t total_sz) const;
|
||||
|
||||
/**
|
||||
* \brief Applies the compiled filter on the provided packet.
|
||||
*
|
||||
* This method checks whether the provided packet matches the filter.
|
||||
* Since this uses pcap filters and they work over a raw data buffer,
|
||||
* this method serialices the packet and then applies the filter.
|
||||
* Therefore, this can be quite expensive to use. If you have access
|
||||
* to the packet before constructing a PDU from it, it is recommended
|
||||
* to use the other overload over the raw buffer.
|
||||
*
|
||||
* \param pdu The packet to be matched against the filter.
|
||||
* \return true iff the packet matches the filter.
|
||||
*/
|
||||
bool matches_filter(PDU& pdu) const;
|
||||
private:
|
||||
void init(const std::string& pcap_filter, int link_type,
|
||||
unsigned int snap_len);
|
||||
|
||||
|
||||
pcap_t* handle;
|
||||
mutable bpf_program filter;
|
||||
std::string string_filter;
|
||||
};
|
||||
} // Tins
|
||||
|
||||
#endif // TINS_OFFLINE_PACKET_FILTER_H
|
||||
311
include/tins/packet.h
Normal file
311
include/tins/packet.h
Normal file
@@ -0,0 +1,311 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Matias Fontanini
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following disclaimer
|
||||
* in the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef TINS_PACKET_H
|
||||
#define TINS_PACKET_H
|
||||
|
||||
#include <algorithm>
|
||||
#include "cxxstd.h"
|
||||
#include "pdu.h"
|
||||
#include "timestamp.h"
|
||||
|
||||
/**
|
||||
* \namespace Tins
|
||||
*/
|
||||
namespace Tins {
|
||||
template<typename WrappedType, typename TimestampType>
|
||||
class PacketWrapper;
|
||||
|
||||
|
||||
/**
|
||||
* \brief Thin wrapper over a PDU and Timestamp reference.
|
||||
*/
|
||||
typedef PacketWrapper<PDU&, const Timestamp&> RefPacket;
|
||||
|
||||
/**
|
||||
* \brief Thin wrapper over a PDU pointer and a Timestamp.
|
||||
*/
|
||||
typedef PacketWrapper<PDU*, Timestamp> PtrPacket;
|
||||
|
||||
/**
|
||||
* \brief Represents a sniffed packet.
|
||||
*
|
||||
* RefPackets contain a PDU reference and a timestamp. The difference between
|
||||
* this class and the Packet class is that this one contains a reference
|
||||
* to a PDU, and not a pointer to one.
|
||||
*
|
||||
* This class is only used in some BaseSniffer methods as a thin wrapper
|
||||
* to a PDU pointer/reference. Only BaseSniffer and derived objects can
|
||||
* create instances of it.
|
||||
*/
|
||||
template<typename PDUType, typename TimestampType>
|
||||
class PacketWrapper {
|
||||
public:
|
||||
typedef PDUType pdu_type;
|
||||
typedef TimestampType timestamp_type;
|
||||
|
||||
/**
|
||||
* \brief User defined conversion to wrapped_type.
|
||||
*
|
||||
* This conversion is defined so that BaseSniffer::sniff_loop callback
|
||||
* or code that calls BaseSniffer::next_packet can still receive a
|
||||
* PDU pointer/reference without modifying the code at all.
|
||||
*/
|
||||
operator pdu_type() {
|
||||
return pdu_;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Returns the wrapped_type.
|
||||
*/
|
||||
pdu_type pdu() {
|
||||
return pdu_;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Returns the PDU const reference.
|
||||
*/
|
||||
const pdu_type pdu() const {
|
||||
return pdu_;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Returns the packet timestamp.
|
||||
*
|
||||
* This is the timestamp in which the packet was taken out of the
|
||||
* network interface/pcap file.
|
||||
*/
|
||||
const Timestamp ×tamp() const {
|
||||
return ts_;
|
||||
}
|
||||
private:
|
||||
friend class BaseSniffer;
|
||||
friend class SnifferIterator;
|
||||
|
||||
PacketWrapper(pdu_type pdu, const Timestamp &ts)
|
||||
: pdu_(pdu), ts_(ts) {}
|
||||
|
||||
PacketWrapper(const PacketWrapper&);
|
||||
PacketWrapper& operator=(const PacketWrapper&);
|
||||
void* operator new (size_t size);
|
||||
void operator delete (void *p);
|
||||
|
||||
pdu_type pdu_;
|
||||
timestamp_type ts_;
|
||||
};
|
||||
|
||||
/**
|
||||
* \class Represents a sniffed packet.
|
||||
*
|
||||
* A Packet contains a PDU pointer and a Timestamp object. Packets
|
||||
* <b>will delete</b> the stored PDU* unless you call release_pdu at
|
||||
* some point before destruction.
|
||||
*/
|
||||
class Packet {
|
||||
public:
|
||||
/**
|
||||
* Tag used to specify that a Packet should own a PDU pointer.
|
||||
*/
|
||||
struct own_pdu {
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Default constructs a Packet.
|
||||
*
|
||||
* The PDU* will be set to a null pointer.
|
||||
*/
|
||||
Packet()
|
||||
: pdu_(0) { }
|
||||
|
||||
/**
|
||||
* \brief Constructs a Packet from a PDU* and a Timestamp.
|
||||
*
|
||||
* The PDU* is cloned using PDU::clone.
|
||||
*/
|
||||
Packet(const PDU *apdu, const Timestamp &tstamp)
|
||||
: pdu_(apdu->clone()), ts(tstamp) { }
|
||||
|
||||
/**
|
||||
* \brief Constructs a Packet from a PDU* and a Timestamp.
|
||||
*
|
||||
* The PDU* will be owned by the Packet. This means you
|
||||
* <b>do not</b> have to explicitly delete the pointer, that
|
||||
* will be done automatically by the Packet when it goes out
|
||||
* of scope.
|
||||
*/
|
||||
Packet(PDU *apdu, const Timestamp &tstamp, own_pdu)
|
||||
: pdu_(apdu), ts(tstamp) { }
|
||||
|
||||
/**
|
||||
* \brief Constructs a Packet from a const PDU&.
|
||||
*
|
||||
* The timestamp will be set to the current time.
|
||||
*
|
||||
* This calls PDU::clone on the PDU parameter.
|
||||
*
|
||||
*/
|
||||
Packet(const PDU &rhs)
|
||||
: pdu_(rhs.clone()), ts(Timestamp::current_time()) { }
|
||||
|
||||
/**
|
||||
* \brief Constructs a Packet from a RefPacket.
|
||||
*
|
||||
* This calls PDU::clone on the RefPacket's PDU.
|
||||
*
|
||||
*/
|
||||
Packet(const RefPacket &pck)
|
||||
: pdu_(pck.pdu().clone()), ts(pck.timestamp()) { }
|
||||
|
||||
/**
|
||||
* \brief Constructs a Packet from a PtrPacket object.
|
||||
*/
|
||||
Packet(const PtrPacket &pck)
|
||||
: pdu_(pck.pdu()), ts(pck.timestamp()) { }
|
||||
|
||||
/**
|
||||
* \brief Copy constructor.
|
||||
*
|
||||
* This calls PDU::clone on the rhs's PDU* member.
|
||||
*/
|
||||
Packet(const Packet &rhs) : ts(rhs.timestamp()) {
|
||||
pdu_ = rhs.pdu() ? rhs.pdu()->clone() : 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Copy assignment operator.
|
||||
*
|
||||
* This calls PDU::clone on the rhs's PDU* member.
|
||||
*/
|
||||
Packet& operator=(const Packet &rhs) {
|
||||
if(this != &rhs) {
|
||||
delete pdu_;
|
||||
ts = rhs.timestamp();
|
||||
pdu_ = rhs.pdu() ? rhs.pdu()->clone() : 0;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
#if TINS_IS_CXX11
|
||||
/**
|
||||
* Move constructor.
|
||||
*/
|
||||
Packet(Packet &&rhs) TINS_NOEXCEPT : pdu_(rhs.pdu()), ts(rhs.timestamp()) {
|
||||
rhs.pdu_ = nullptr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Move assignment operator.
|
||||
*/
|
||||
Packet& operator=(Packet &&rhs) TINS_NOEXCEPT {
|
||||
if(this != &rhs) {
|
||||
std::swap(pdu_, rhs.pdu_);
|
||||
ts = rhs.timestamp();
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* \brief Packet destructor.
|
||||
*
|
||||
* This calls operator delete on the stored PDU*.
|
||||
*/
|
||||
~Packet() {
|
||||
delete pdu_;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns this Packet's timestamp.
|
||||
*/
|
||||
const Timestamp ×tamp() const {
|
||||
return ts;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Returns the stored PDU*.
|
||||
*
|
||||
* Caller <b>must not</b> delete the pointer. \sa Packet::release_pdu
|
||||
*/
|
||||
PDU *pdu() {
|
||||
return pdu_;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Returns the stored PDU*.
|
||||
*
|
||||
* Caller <b>must not</b> delete the pointer. \sa Packet::release_pdu
|
||||
*/
|
||||
const PDU *pdu() const {
|
||||
return pdu_;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Releases ownership of the stored PDU*.
|
||||
*
|
||||
* This method returns the stored PDU* and sets the stored PDU* to
|
||||
* a null pointer, so the destructor will be well behaved. Use this
|
||||
* method if you want to keep the internal PDU* somewhere. Otherwise,
|
||||
* when Packet's destructor is called, the stored pointer will be
|
||||
* deleted.
|
||||
*/
|
||||
PDU *release_pdu() {
|
||||
PDU *some_pdu = pdu_;
|
||||
pdu_ = 0;
|
||||
return some_pdu;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Tests whether this is Packet contains a valid PDU.
|
||||
*
|
||||
* \return true if pdu() == nullptr, false otherwise.
|
||||
*/
|
||||
operator bool() const {
|
||||
return pdu_ ? true : false;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* \brief Concatenation operator.
|
||||
*
|
||||
* Adds the PDU at the end of the PDU stack.
|
||||
*
|
||||
* \param rhs The PDU to be appended.
|
||||
*/
|
||||
Packet &operator/=(const PDU &rhs) {
|
||||
pdu_ /= rhs;
|
||||
return *this;
|
||||
}
|
||||
private:
|
||||
PDU *pdu_;
|
||||
Timestamp ts;
|
||||
};
|
||||
}
|
||||
|
||||
#endif // TINS_PACKET_H
|
||||
404
include/tins/packet_sender.h
Normal file
404
include/tins/packet_sender.h
Normal file
@@ -0,0 +1,404 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Matias Fontanini
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following disclaimer
|
||||
* in the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef TINS_PACKET_SENDER_H
|
||||
#define TINS_PACKET_SENDER_H
|
||||
|
||||
|
||||
#include <string>
|
||||
#include <stdexcept>
|
||||
#include <vector>
|
||||
#include <stdint.h>
|
||||
#include <map>
|
||||
#include "network_interface.h"
|
||||
#include "macros.h"
|
||||
#include "cxxstd.h"
|
||||
|
||||
struct timeval;
|
||||
struct sockaddr;
|
||||
|
||||
namespace Tins {
|
||||
class PDU;
|
||||
|
||||
/**
|
||||
* \class PacketSender
|
||||
* \brief Sends packets through a network interface.
|
||||
*
|
||||
* This class allows sending packets through a network interface.
|
||||
* It can send basically two types of packets:
|
||||
*
|
||||
* - Those that contain a link layer PDU (EthernetII, SLL, etc). These
|
||||
* will be serialized and sent through an interface that has to be
|
||||
* specified. This can be done by providing it when you call
|
||||
* PacketSender::send, or set a default one using
|
||||
* PacketSender::default_interface.
|
||||
* - Those that don't contain a link layer PDU. In this case, the
|
||||
* kernel will be responsible for picking the appropriate network interface
|
||||
* based on the destination address.
|
||||
*
|
||||
* Sending packets can be done via PacketSender::send:
|
||||
*
|
||||
* \code
|
||||
* // Construct a packet which uses an EthernetII link layer.
|
||||
* EthernetII pkt1 = ...;
|
||||
*
|
||||
* // Construct a packet sender, which we'll use to send packets.
|
||||
* PacketSender sender;
|
||||
*
|
||||
* // Send it through interface eth0
|
||||
* sender.send(pkt1, "eth0");
|
||||
*
|
||||
* // Set the default interface to eth0
|
||||
* sender.default_interface("eth0");
|
||||
*
|
||||
* // This is now equivalent to the previous send.
|
||||
* sender.send(pkt1);
|
||||
*
|
||||
* // Construct a packet which has no link layer protocol.
|
||||
* IP ip = IP("192.168.0.1") / TCP(22, 928);
|
||||
*
|
||||
* // Here the kernel will figure out which interface to use and it will
|
||||
* // append the appropriate link layer protocol PDU. It will also perform
|
||||
* // the necessary ARP lookups in order to use the destination host's
|
||||
* // hardware address.
|
||||
* //
|
||||
* // libtins will find which is the appropriate source IP address to use.
|
||||
* // This will be done by the kernel as well, but it's required when
|
||||
* // calculating checksums.
|
||||
* sender.send(ip);
|
||||
* \endcode
|
||||
*
|
||||
* PacketSender also supports sending a packet and waiting for a response.
|
||||
* This can be done by using PacketSender::send_recv.
|
||||
*
|
||||
* This class opens sockets as it needs to, and closes them when the object
|
||||
* is destructed.
|
||||
*
|
||||
* \sa PacketSender::send
|
||||
* \sa PacketSender::send_recv
|
||||
*/
|
||||
class PacketSender {
|
||||
public:
|
||||
/**
|
||||
* The default timeout for receive actions.
|
||||
*/
|
||||
static const uint32_t DEFAULT_TIMEOUT;
|
||||
|
||||
/**
|
||||
* Flags to indicate the socket type.
|
||||
*/
|
||||
enum SocketType {
|
||||
ETHER_SOCKET,
|
||||
IP_TCP_SOCKET,
|
||||
IP_UDP_SOCKET,
|
||||
IP_RAW_SOCKET,
|
||||
ARP_SOCKET,
|
||||
ICMP_SOCKET,
|
||||
IPV6_SOCKET,
|
||||
SOCKETS_END
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Constructor for PacketSender objects.
|
||||
*
|
||||
* \param iface The default interface in which to send the packets.
|
||||
* \param recv_timeout The timeout which will be used when receiving responses.
|
||||
*/
|
||||
PacketSender(const NetworkInterface &iface = NetworkInterface(),
|
||||
uint32_t recv_timeout = DEFAULT_TIMEOUT, uint32_t usec = 0);
|
||||
|
||||
#if TINS_IS_CXX11
|
||||
/**
|
||||
* \brief Move constructor.
|
||||
* \param rhs The sender to be moved.
|
||||
*/
|
||||
PacketSender(PacketSender &&rhs) TINS_NOEXCEPT {
|
||||
*this = std::move(rhs);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Move assignment operator.
|
||||
* \param rhs The sender to be moved.
|
||||
*/
|
||||
PacketSender& operator=(PacketSender &&rhs) TINS_NOEXCEPT {
|
||||
_sockets = std::move(rhs._sockets);
|
||||
rhs._sockets = std::vector<int>(SOCKETS_END, INVALID_RAW_SOCKET);
|
||||
#ifndef WIN32
|
||||
#if defined(BSD) || defined(__FreeBSD_kernel__)
|
||||
_ether_socket = std::move(rhs._ether_socket);
|
||||
#else
|
||||
_ether_socket = rhs._ether_socket;
|
||||
rhs._ether_socket = INVALID_RAW_SOCKET;
|
||||
#endif
|
||||
#endif
|
||||
_types = rhs._types; // no move
|
||||
_timeout = rhs._timeout;
|
||||
_timeout_usec = rhs._timeout_usec;
|
||||
default_iface = rhs.default_iface;
|
||||
return *this;
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* \brief PacketSender destructor.
|
||||
*
|
||||
* This gracefully closes all open sockets.
|
||||
*/
|
||||
~PacketSender();
|
||||
|
||||
#ifndef WIN32
|
||||
/**
|
||||
* \brief Opens a layer 2 socket.
|
||||
*
|
||||
* If this operation fails, then a socket_open_error will be thrown.
|
||||
*/
|
||||
void open_l2_socket(const NetworkInterface& iface = NetworkInterface());
|
||||
#endif // WIN32
|
||||
|
||||
/**
|
||||
* \brief Opens a layer 3 socket, using the corresponding protocol
|
||||
* for the given flag.
|
||||
*
|
||||
* If this operation fails, then a socket_open_error will be thrown.
|
||||
* If the provided socket type is not valid, an invalid_socket_type
|
||||
* exception will be throw.
|
||||
*
|
||||
* \param type The type of socket which will be used to pick the protocol flag
|
||||
* for this socket.
|
||||
*/
|
||||
void open_l3_socket(SocketType type);
|
||||
|
||||
/**
|
||||
* \brief Closes the socket associated with the given flag.
|
||||
*
|
||||
* If the provided type is invalid, meaning no such open socket
|
||||
* exists, an invalid_socket_type exception is thrown.
|
||||
*
|
||||
* If any socket close errors are encountered, a socket_close_error
|
||||
* is thrown.
|
||||
*
|
||||
* \param type The type of the socket to be closed.
|
||||
*/
|
||||
void close_socket(SocketType type, const NetworkInterface &iface = NetworkInterface());
|
||||
|
||||
/**
|
||||
* \brief Sets the default interface.
|
||||
*
|
||||
* The interface will be used whenever PacketSender::send(PDU&)
|
||||
* is called.
|
||||
*/
|
||||
void default_interface(const NetworkInterface &iface);
|
||||
|
||||
/**
|
||||
* \brief Gets the default interface.
|
||||
*
|
||||
* \sa PacketSender::default_interface
|
||||
*/
|
||||
const NetworkInterface& default_interface() const;
|
||||
|
||||
/**
|
||||
* \brief Sends a PDU.
|
||||
*
|
||||
* This method opens the appropriate socket, if it's not open yet,
|
||||
* and sends the PDU on the open socket.
|
||||
*
|
||||
* If any send error occurs, then a socket_write_error is thrown.
|
||||
*
|
||||
* If the PDU contains a link layer protocol, then default_interface
|
||||
* is used.
|
||||
*
|
||||
* \sa PacketSender::default_interface
|
||||
*
|
||||
* \param pdu The PDU to be sent.
|
||||
*/
|
||||
void send(PDU &pdu);
|
||||
|
||||
/**
|
||||
* \brief Sends a PDU.
|
||||
*
|
||||
* \sa PacketSender::send
|
||||
*
|
||||
* This overload takes a NetworkInterface. The packet is sent
|
||||
* through that interface if a link-layer PDU is present,
|
||||
* otherwise this call is equivalent to send(PDU&).
|
||||
*
|
||||
* The interface stored in the link layer PDU(if any), is restored
|
||||
* after this method ends.
|
||||
*
|
||||
* \param pdu The PDU to be sent.
|
||||
* \param iface The network interface to use.
|
||||
*/
|
||||
void send(PDU &pdu, const NetworkInterface &iface);
|
||||
|
||||
/**
|
||||
* \brief Sends a PDU and waits for its response.
|
||||
*
|
||||
* This method is used to send PDUs and receive their response.
|
||||
* The packet is sent, and then a response is awaited.
|
||||
* PDU::matches_pdu is called on the packet sent in order to
|
||||
* check whether a packet received is a response.
|
||||
*
|
||||
* This will match every response to a packet. For example,
|
||||
* if you send a TCP packet, any response matching the same
|
||||
* IP addresses and ports will be taken as a response to it.
|
||||
* This also happens for other protocols, such as ARP, ICMP,
|
||||
* DHCP, DNS, IP, etc.
|
||||
*
|
||||
* If you send a packet and get an ICMP response indicating
|
||||
* an error (such as host unreachable, ttl exceeded, etc),
|
||||
* that packet will be considered a response.
|
||||
*
|
||||
* \param pdu The PDU to send.
|
||||
* \return Returns the response PDU, 0 if not response was received.
|
||||
*/
|
||||
PDU *send_recv(PDU &pdu);
|
||||
|
||||
/**
|
||||
* \brief Sends a PDU and waits for its response.
|
||||
*
|
||||
* Sends a packet and receives a response. This overload takes
|
||||
* a NetworkInterface.
|
||||
*
|
||||
* \sa PacketSender::send_recv(PDU&);
|
||||
* \param pdu The PDU to send.
|
||||
* \param iface The network interface in which to send and receive.
|
||||
* \return Returns the response PDU, 0 if not response was received.
|
||||
*/
|
||||
PDU *send_recv(PDU &pdu, const NetworkInterface &iface);
|
||||
|
||||
#ifndef WIN32
|
||||
/**
|
||||
* \brief Receives a layer 2 PDU response to a previously sent PDU.
|
||||
*
|
||||
* This method is used internally. You should just use PacketSender::send_recv.
|
||||
*
|
||||
* This PacketSender will receive data from a raw socket, open using
|
||||
* the corresponding flag, according to the given type of protocol, until
|
||||
* a match for the given PDU is received.
|
||||
*
|
||||
* \param pdu The PDU which will try to match the responses.
|
||||
* \param link_addr The sockaddr struct which will be used to receive the PDU.
|
||||
* \param len_addr The sockaddr struct length.
|
||||
* \return Returns the response PDU. If no response is received, then 0 is returned.
|
||||
*/
|
||||
PDU *recv_l2(PDU &pdu, struct sockaddr *link_addr, uint32_t len_addr,
|
||||
const NetworkInterface &iface = NetworkInterface());
|
||||
|
||||
/**
|
||||
* \brief Sends a level 2 PDU.
|
||||
*
|
||||
* This method is used internally. You should just use PacketSender::send.
|
||||
*
|
||||
* This method sends a layer 2 PDU, using a raw socket, open
|
||||
* using the corresponding flag, according to the given type of
|
||||
* protocol.
|
||||
*
|
||||
* If any socket write error occurs, a socket_write_error is thrown.
|
||||
*
|
||||
* \param pdu The PDU to send.
|
||||
* \param link_addr The sockaddr struct which will be used to send the PDU.
|
||||
* \param len_addr The sockaddr struct length.
|
||||
*/
|
||||
void send_l2(PDU &pdu, struct sockaddr* link_addr, uint32_t len_addr,
|
||||
const NetworkInterface &iface = NetworkInterface());
|
||||
#endif // WIN32
|
||||
|
||||
/**
|
||||
* \brief Receives a layer 3 PDU response to a previously sent PDU.
|
||||
*
|
||||
* This method is used internally. You should just use PacketSender::send_recv.
|
||||
*
|
||||
* This PacketSender will receive data from a raw socket, open using the corresponding flag,
|
||||
* according to the given type of protocol, until a match for the given PDU is received.
|
||||
*
|
||||
* \param pdu The PDU which will try to match the responses.
|
||||
* \param link_addr The sockaddr struct which will be used to receive the PDU.
|
||||
* \param len_addr The sockaddr struct length.
|
||||
* \param type The socket protocol type.
|
||||
* \return Returns the response PDU. If no response is received, then 0 is returned.
|
||||
*/
|
||||
PDU *recv_l3(PDU &pdu, struct sockaddr *link_addr, uint32_t len_addr, SocketType type);
|
||||
|
||||
/**
|
||||
* \brief Sends a level 3 PDU.
|
||||
*
|
||||
* This method is used internally. You should just use PacketSender::send.
|
||||
*
|
||||
* This method sends a layer 3 PDU, using a raw socket, open using the corresponding flag,
|
||||
* according to the given type of protocol.
|
||||
*
|
||||
* If any socket write error occurs, a socket_write_error is thrown.
|
||||
*
|
||||
* \param pdu The PDU to send.
|
||||
* \param link_addr The sockaddr struct which will be used to send the PDU.
|
||||
* \param len_addr The sockaddr struct length.
|
||||
* \param type The socket protocol type.
|
||||
*/
|
||||
void send_l3(PDU &pdu, struct sockaddr *link_addr, uint32_t len_addr, SocketType type);
|
||||
private:
|
||||
static const int INVALID_RAW_SOCKET;
|
||||
|
||||
typedef std::map<SocketType, int> SocketTypeMap;
|
||||
|
||||
PacketSender(const PacketSender&);
|
||||
PacketSender& operator=(const PacketSender&);
|
||||
int find_type(SocketType type);
|
||||
int timeval_subtract (struct timeval *result, struct timeval *x, struct timeval *y);
|
||||
#ifndef WIN32
|
||||
bool ether_socket_initialized(const NetworkInterface& iface = NetworkInterface()) const;
|
||||
int get_ether_socket(const NetworkInterface& iface = NetworkInterface());
|
||||
#endif
|
||||
template<typename T>
|
||||
void send(PDU &pdu, const NetworkInterface &iface) {
|
||||
static_cast<T&>(pdu).send(*this, iface);
|
||||
}
|
||||
|
||||
PDU *recv_match_loop(const std::vector<int>& sockets, PDU &pdu, struct sockaddr* link_addr,
|
||||
uint32_t addrlen);
|
||||
|
||||
std::vector<int> _sockets;
|
||||
#ifndef WIN32
|
||||
#if defined(BSD) || defined(__FreeBSD_kernel__)
|
||||
typedef std::map<uint32_t, int> BSDEtherSockets;
|
||||
BSDEtherSockets _ether_socket;
|
||||
#else
|
||||
int _ether_socket;
|
||||
#endif
|
||||
#endif
|
||||
SocketTypeMap _types;
|
||||
uint32_t _timeout, _timeout_usec;
|
||||
NetworkInterface default_iface;
|
||||
// In BSD we need to store the buffer size, retrieved using BIOCGBLEN
|
||||
#if defined(BSD) || defined(__FreeBSD_kernel__)
|
||||
int buffer_size;
|
||||
#endif
|
||||
};
|
||||
}
|
||||
|
||||
#endif // TINS_PACKET_SENDER_H
|
||||
209
include/tins/packet_writer.h
Normal file
209
include/tins/packet_writer.h
Normal file
@@ -0,0 +1,209 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Matias Fontanini
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following disclaimer
|
||||
* in the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef TINS_PACKET_WRITER_H
|
||||
#define TINS_PACKET_WRITER_H
|
||||
|
||||
#include <string>
|
||||
#include <iterator>
|
||||
#include <pcap.h>
|
||||
#include "data_link_type.h"
|
||||
#include "utils.h"
|
||||
#include "cxxstd.h"
|
||||
|
||||
namespace Tins {
|
||||
class PDU;
|
||||
|
||||
/**
|
||||
* \class PacketWriter
|
||||
* \brief Writes PDUs to a pcap format file.
|
||||
*
|
||||
* This class can be used to write packets into a <i>pcap</i> format
|
||||
* file. It supports both writing packets one by one, or writing all
|
||||
* packets in a range (provided by iterators), so you can use it
|
||||
* to dump all packets in a vector.
|
||||
*
|
||||
* Since you might use both PDU objects and pointers to them,
|
||||
* both the PacketWriter::write overload that takes a single object
|
||||
* or the one that takes an iterator range accept a PDU reference type
|
||||
* as well as any type that can be dereferenced until a PDU type is found.
|
||||
* This means you can use both raw and smart pointers.
|
||||
*
|
||||
* For example:
|
||||
*
|
||||
* \code
|
||||
* // Differents types holding PDUs
|
||||
* EthernetII object;
|
||||
* std::shared_ptr<PDU> smart_ptr = ...;
|
||||
* std::vector<std::shared_ptr<PDU>> vt = ....;
|
||||
*
|
||||
* // The writer we'll use
|
||||
* PacketWriter writer("/tmp/file.pcap", DataLinkType<EthernetII>());
|
||||
*
|
||||
* // Now write all of them
|
||||
* writer.write(object);
|
||||
* writer.write(smart_ptr);
|
||||
* writer.write(vt.begin(), vt.end());
|
||||
* \endcode
|
||||
*/
|
||||
class PacketWriter {
|
||||
public:
|
||||
/**
|
||||
* \brief The type of PDUs that will be written to this file (deprecated).
|
||||
* \deprecated Use DataLinkType instead of this enum.
|
||||
*
|
||||
* This flag should match the type of the lowest layer PDU to be
|
||||
* written.
|
||||
*/
|
||||
enum LinkType {
|
||||
RADIOTAP = DLT_IEEE802_11_RADIO,
|
||||
DOT11 = DLT_IEEE802_11,
|
||||
ETH2 = DLT_EN10MB,
|
||||
DOT3 = DLT_EN10MB,
|
||||
SLL = DLT_LINUX_SLL
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Constructs a PacketWriter.
|
||||
*
|
||||
* This method takes a DataLinkType, which indicates the link
|
||||
* layer protocol that will be used on the packets to write.
|
||||
*
|
||||
* For example, you can write packets that contain an
|
||||
* EthernetII link layer type by doing:
|
||||
*
|
||||
* \code
|
||||
* // Construct a PacketWriter
|
||||
* PacketWriter writer("/tmp/test.pcap", DataLinkType<EthernetII>());
|
||||
* // Write some packet
|
||||
* writer.write(packet);
|
||||
* \endcode
|
||||
*
|
||||
* \param file_name The file in which to store the written PDUs.
|
||||
* \param lt A DataLinkType that represents the link layer
|
||||
* protocol to use.
|
||||
* \sa PcapIdentifier.
|
||||
*/
|
||||
template<typename T>
|
||||
PacketWriter(const std::string &file_name, const DataLinkType<T>& lt)
|
||||
{
|
||||
init(file_name, lt.get_type());
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Constructs a PacketWriter.
|
||||
*
|
||||
* \deprecated Use the PacketWriter(const std::string&, const DataLinkType<T>&)
|
||||
* constructor.
|
||||
*
|
||||
* \param file_name The file in which to store the written PDUs.
|
||||
* \param lt The link type which will be written to this file.
|
||||
* \sa LinkType.
|
||||
*/
|
||||
PacketWriter(const std::string &file_name, LinkType lt);
|
||||
|
||||
#if TINS_IS_CXX11
|
||||
/**
|
||||
* \brief Move constructor.
|
||||
*
|
||||
* Note that calling PacketWriter::write on an previously moved
|
||||
* object will lead to undefined behaviour.
|
||||
*
|
||||
* \param rhs The PacketWriter to be moved.
|
||||
*/
|
||||
PacketWriter(PacketWriter &&rhs) TINS_NOEXCEPT {
|
||||
*this = std::move(rhs);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Move assignment operator.
|
||||
*
|
||||
* Note that calling PacketWriter::write on an previously moved
|
||||
* object will lead to undefined behaviour.
|
||||
*
|
||||
* \param rhs The PacketWriter to be moved.
|
||||
*/
|
||||
PacketWriter& operator=(PacketWriter &&rhs) TINS_NOEXCEPT {
|
||||
handle = 0;
|
||||
dumper = 0;
|
||||
std::swap(handle, rhs.handle);
|
||||
std::swap(dumper, rhs.dumper);
|
||||
return *this;
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* \brief Destructor.
|
||||
*
|
||||
* Gracefully closes the output file.
|
||||
*/
|
||||
~PacketWriter();
|
||||
|
||||
/**
|
||||
* \brief Writes a PDU to this file.
|
||||
*/
|
||||
void write(PDU &pdu);
|
||||
|
||||
/**
|
||||
* \brief Writes a PDU to this file.
|
||||
*
|
||||
* The template parameter T must at some point yield a PDU& after
|
||||
* applying operator* one or more than one time. This accepts both
|
||||
* raw and smart pointers.
|
||||
*/
|
||||
template<typename T>
|
||||
void write(T &pdu) {
|
||||
write(Utils::dereference_until_pdu(pdu));
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Writes all the PDUs in the range [start, end)
|
||||
* \param start A forward iterator pointing to the first PDU
|
||||
* to be written.
|
||||
* \param end A forward iterator pointing to one past the last
|
||||
* PDU in the range.
|
||||
*/
|
||||
template<typename ForwardIterator>
|
||||
void write(ForwardIterator start, ForwardIterator end) {
|
||||
while(start != end)
|
||||
write(Utils::dereference_until_pdu(*start++));
|
||||
}
|
||||
private:
|
||||
// You shall not copy
|
||||
PacketWriter(const PacketWriter&);
|
||||
PacketWriter& operator=(const PacketWriter&);
|
||||
|
||||
void init(const std::string& file_name, int link_type);
|
||||
|
||||
pcap_t *handle;
|
||||
pcap_dumper_t *dumper;
|
||||
};
|
||||
}
|
||||
|
||||
#endif // TINS_PACKET_WRITER_H
|
||||
551
include/tins/pdu.h
Normal file
551
include/tins/pdu.h
Normal file
@@ -0,0 +1,551 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Matias Fontanini
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following disclaimer
|
||||
* in the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef TINS_PDU_H
|
||||
#define TINS_PDU_H
|
||||
|
||||
|
||||
#include <stdint.h>
|
||||
#include <vector>
|
||||
#include "macros.h"
|
||||
#include "cxxstd.h"
|
||||
#include "exceptions.h"
|
||||
|
||||
/** \brief The Tins namespace.
|
||||
*/
|
||||
namespace Tins {
|
||||
|
||||
class PacketSender;
|
||||
class NetworkInterface;
|
||||
|
||||
/**
|
||||
* The type used to store several PDU option values.
|
||||
*/
|
||||
typedef std::vector<uint8_t> byte_array;
|
||||
|
||||
/**
|
||||
* \class PDU
|
||||
* \brief Base class for protocol data units.
|
||||
*
|
||||
* Every PDU implementation inherits from this class.
|
||||
*
|
||||
* PDUs can contain 0 or 1 inner PDU. By stacking several PDUs together,
|
||||
* you can construct packets. These are created upwards: upper layers
|
||||
* will be children of the lower ones.
|
||||
*
|
||||
* If you want to find a specific protocol within a PDU chain, you can use
|
||||
* PDU::find_pdu and PDU::rfind_pdu. Both of them take a template parameter
|
||||
* that indicates the PDU type you are looking for. The first one returns a
|
||||
* pointer to the first object of that type, and the second one returns a
|
||||
* reference (and throws if it is not found).
|
||||
*
|
||||
* For example:
|
||||
*
|
||||
* \code
|
||||
* // Take a whole packet from somewhere.
|
||||
* EthernetII packet = ...;
|
||||
*
|
||||
* // Find the IP layer
|
||||
* const IP* ip = packet.find_pdu<IP>();
|
||||
* if(ip) {
|
||||
* // If the pointer is not null, then it will point to the IP layer
|
||||
* }
|
||||
*
|
||||
* // Find the TCP layer. This will throw a pdu_not_found exception
|
||||
* // if there is no TCP layer in this packet.
|
||||
* const TCP& tcp = packet.rfind_pdu<TCP>();
|
||||
* \endcode
|
||||
*
|
||||
* PDU objects can be serialized. Serialization converts the entire PDU
|
||||
* stack into a vector of bytes. This process might modify some parameters
|
||||
* on packets depending on which protocols are used in it. For example:
|
||||
*
|
||||
* - If the lowest protocol layer is IP (this means that there is no
|
||||
* link layer protocol in the packet), then it calculates the source address
|
||||
* that should be used in that IP PDU. \sa IP
|
||||
* - If a protocol contains a checksum field, its value will be calculated
|
||||
* and included in its serialized contents.
|
||||
* - If a protocol contains a "next protocol" field, it is also set based
|
||||
* on the type of the next PDU in the packet.
|
||||
*
|
||||
* If you want to serialize a packet, just use PDU::serialize:
|
||||
*
|
||||
* \code
|
||||
* // Construct a packet
|
||||
* EthernetII packet = EthernetII() / IP() / TCP() / RawPDU("hello");
|
||||
*
|
||||
* // Now serialize it. This is a std::vector<uint8_t>.
|
||||
* PDU::serialization_type buffer = packet.serialize();
|
||||
* \endcode
|
||||
*/
|
||||
class PDU {
|
||||
public:
|
||||
/**
|
||||
* The type that will be returned when serializing PDUs.
|
||||
*/
|
||||
typedef byte_array serialization_type;
|
||||
|
||||
/**
|
||||
* The typep used to identify the endianness of every PDU.
|
||||
*/
|
||||
enum endian_type {
|
||||
BE,
|
||||
LE
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Enum which identifies each type of PDU.
|
||||
*
|
||||
* This enum is used to identify the PDU type.
|
||||
*/
|
||||
enum PDUType {
|
||||
RAW,
|
||||
ETHERNET_II,
|
||||
IEEE802_3,
|
||||
RADIOTAP,
|
||||
DOT11,
|
||||
DOT11_ACK,
|
||||
DOT11_ASSOC_REQ,
|
||||
DOT11_ASSOC_RESP,
|
||||
DOT11_AUTH,
|
||||
DOT11_BEACON,
|
||||
DOT11_BLOCK_ACK,
|
||||
DOT11_BLOCK_ACK_REQ,
|
||||
DOT11_CF_END,
|
||||
DOT11_DATA,
|
||||
DOT11_CONTROL,
|
||||
DOT11_DEAUTH,
|
||||
DOT11_DIASSOC,
|
||||
DOT11_END_CF_ACK,
|
||||
DOT11_MANAGEMENT,
|
||||
DOT11_PROBE_REQ,
|
||||
DOT11_PROBE_RESP,
|
||||
DOT11_PS_POLL,
|
||||
DOT11_REASSOC_REQ,
|
||||
DOT11_REASSOC_RESP,
|
||||
DOT11_RTS,
|
||||
DOT11_QOS_DATA,
|
||||
LLC,
|
||||
SNAP,
|
||||
IP,
|
||||
ARP,
|
||||
TCP,
|
||||
UDP,
|
||||
ICMP,
|
||||
BOOTP,
|
||||
DHCP,
|
||||
EAPOL,
|
||||
RC4EAPOL,
|
||||
RSNEAPOL,
|
||||
DNS,
|
||||
LOOPBACK,
|
||||
IPv6,
|
||||
ICMPv6,
|
||||
SLL,
|
||||
DHCPv6,
|
||||
DOT1Q,
|
||||
PPPOE,
|
||||
STP,
|
||||
PPI,
|
||||
IPSEC_AH,
|
||||
IPSEC_ESP,
|
||||
USER_DEFINED_PDU = 1000
|
||||
};
|
||||
|
||||
/**
|
||||
* The endianness used by this PDU. This can be overriden
|
||||
* by subclasses.
|
||||
*/
|
||||
static const endian_type endianness = BE;
|
||||
|
||||
/**
|
||||
* \brief Default constructor.
|
||||
*/
|
||||
PDU();
|
||||
|
||||
#if TINS_IS_CXX11
|
||||
/**
|
||||
* \brief Move constructor.
|
||||
*
|
||||
* \param rhs The PDU to be moved.
|
||||
*/
|
||||
PDU(PDU &&rhs) TINS_NOEXCEPT
|
||||
: _inner_pdu(0)
|
||||
{
|
||||
std::swap(_inner_pdu, rhs._inner_pdu);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Move assignment operator.
|
||||
*
|
||||
* \param rhs The PDU to be moved.
|
||||
*/
|
||||
PDU& operator=(PDU &&rhs) TINS_NOEXCEPT {
|
||||
std::swap(_inner_pdu, rhs._inner_pdu);
|
||||
return *this;
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* \brief PDU destructor.
|
||||
*
|
||||
* Deletes the inner pdu, as a consequence every child pdu is
|
||||
* deleted.
|
||||
*/
|
||||
virtual ~PDU();
|
||||
|
||||
/** \brief The header's size
|
||||
*/
|
||||
virtual uint32_t header_size() const = 0;
|
||||
|
||||
/** \brief Trailer's size.
|
||||
*
|
||||
* Some protocols require a trailer(like Ethernet). This defaults to 0.
|
||||
*/
|
||||
virtual uint32_t trailer_size() const { return 0; }
|
||||
|
||||
/** \brief The whole chain of PDU's size, including this one.
|
||||
*
|
||||
* Returns the sum of this and all children PDUs' size.
|
||||
*/
|
||||
uint32_t size() const;
|
||||
|
||||
/**
|
||||
* \brief Getter for the inner PDU.
|
||||
* \return The current inner PDU. Might be 0.
|
||||
*/
|
||||
PDU *inner_pdu() const { return _inner_pdu; }
|
||||
|
||||
/**
|
||||
* \brief Releases the inner PDU.
|
||||
*
|
||||
* This method makes this PDU to <b>no longer own</b> the inner
|
||||
* PDU. The current inner PDU is returned, and is <b>not</b>
|
||||
* destroyed. That means after calling this function, you are
|
||||
* responsible for using operator delete on the returned pointer.
|
||||
*
|
||||
* Use this method if you want to somehow re-use a PDU that
|
||||
* is already owned by another PDU.
|
||||
*
|
||||
* \return The current inner PDU. Might be 0.
|
||||
*/
|
||||
PDU *release_inner_pdu();
|
||||
|
||||
/**
|
||||
* \brief Sets the child PDU.
|
||||
*
|
||||
* When setting a new inner_pdu, the instance takesownership of
|
||||
* the object, therefore deleting it when it's no longer required.
|
||||
*
|
||||
* \param next_pdu The new child PDU.
|
||||
*/
|
||||
void inner_pdu(PDU *next_pdu);
|
||||
|
||||
/**
|
||||
* \brief Sets the child PDU.
|
||||
*
|
||||
* The PDU parameter is cloned using PDU::clone.
|
||||
*
|
||||
* \param next_pdu The new child PDU.
|
||||
*/
|
||||
void inner_pdu(const PDU &next_pdu);
|
||||
|
||||
|
||||
/**
|
||||
* \brief Serializes the whole chain of PDU's, including this one.
|
||||
*
|
||||
* This allocates a std::vector of size size(), and fills it
|
||||
* with the serialization this PDU, and all of the inner ones'.
|
||||
*
|
||||
* \return serialization_type containing the serialization
|
||||
* of the whole stack of PDUs.
|
||||
*/
|
||||
serialization_type serialize();
|
||||
|
||||
/**
|
||||
* \brief Finds and returns the first PDU that matches the given flag.
|
||||
*
|
||||
* This method searches for the first PDU which has the same type flag as
|
||||
* the given one. If the first PDU matches that flag, it is returned.
|
||||
* If no PDU matches, 0 is returned.
|
||||
* \param flag The flag which being searched.
|
||||
*/
|
||||
template<typename T>
|
||||
T *find_pdu(PDUType type = T::pdu_flag) {
|
||||
PDU *pdu = this;
|
||||
while(pdu) {
|
||||
if(pdu->matches_flag(type))
|
||||
return static_cast<T*>(pdu);
|
||||
pdu = pdu->inner_pdu();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Finds and returns the first PDU that matches the given flag.
|
||||
*
|
||||
* \param flag The flag which being searched.
|
||||
*/
|
||||
template<typename T>
|
||||
const T *find_pdu(PDUType type = T::pdu_flag) const {
|
||||
return const_cast<PDU*>(this)->find_pdu<T>();
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Finds and returns the first PDU that matches the given flag.
|
||||
*
|
||||
* If the PDU is not found, a pdu_not_found exception is thrown.
|
||||
*
|
||||
* \sa PDU::find_pdu
|
||||
*
|
||||
* \param flag The flag which being searched.
|
||||
*/
|
||||
template<typename T>
|
||||
T &rfind_pdu(PDUType type = T::pdu_flag) {
|
||||
T *ptr = find_pdu<T>(type);
|
||||
if(!ptr)
|
||||
throw pdu_not_found();
|
||||
return *ptr;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Finds and returns the first PDU that matches the given flag.
|
||||
*
|
||||
* \param flag The flag which being searched.
|
||||
*/
|
||||
template<typename T>
|
||||
const T &rfind_pdu(PDUType type = T::pdu_flag) const {
|
||||
return const_cast<PDU*>(this)->rfind_pdu<T>();
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Clones this packet.
|
||||
*
|
||||
* This method clones this PDU and clones every inner PDU,
|
||||
* therefore obtaining a clone of the whole inner PDU chain.
|
||||
* The pointer returned must be deleted by the user.
|
||||
* \return A pointer to a clone of this packet.
|
||||
*/
|
||||
virtual PDU *clone() const = 0;
|
||||
|
||||
/**
|
||||
* \brief Send the stack of PDUs through a PacketSender.
|
||||
*
|
||||
* This method will be called only for the PDU on the bottom of the stack,
|
||||
* therefore it should only implement this method if it can be sent.
|
||||
*
|
||||
* PacketSender implements specific methods to send packets which start
|
||||
* on every valid TCP/IP stack layer; this should only be a proxy for
|
||||
* those methods.
|
||||
*
|
||||
* If this PDU does not represent a link layer protocol, then
|
||||
* the interface argument will be ignored.
|
||||
*
|
||||
* \param sender The PacketSender which will send the packet.
|
||||
* \param iface The network interface in which this packet will
|
||||
* be sent.
|
||||
*/
|
||||
virtual void send(PacketSender &sender, const NetworkInterface &iface);
|
||||
|
||||
/**
|
||||
* \brief Receives a matching response for this packet.
|
||||
*
|
||||
* This method should act as a proxy for PacketSender::recv_lX methods.
|
||||
*
|
||||
* \param sender The packet sender which will receive the packet.
|
||||
* \param iface The interface in which to expect the response.
|
||||
*/
|
||||
virtual PDU *recv_response(PacketSender &sender, const NetworkInterface &iface);
|
||||
|
||||
/**
|
||||
* \brief Check wether ptr points to a valid response for this PDU.
|
||||
*
|
||||
* This method must check wether the buffer pointed by ptr is a valid
|
||||
* response for this PDU. If it is valid, then it might want to propagate
|
||||
* the call to the next PDU. Note that in some cases, such as ICMP
|
||||
* Host Unreachable, there is no need to ask the next layer for matching.
|
||||
* \param ptr The pointer to the buffer.
|
||||
* \param total_sz The size of the buffer.
|
||||
*/
|
||||
virtual bool matches_response(const uint8_t *ptr, uint32_t total_sz) const {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Check wether this PDU matches the specified flag.
|
||||
*
|
||||
* This method should be reimplemented in PDU classes which have
|
||||
* subclasses, and try to match the given PDU to each of its parent
|
||||
* classes' flag.
|
||||
* \param flag The flag to match.
|
||||
*/
|
||||
virtual bool matches_flag(PDUType flag) const {
|
||||
return flag == pdu_type();
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the PDU's type.
|
||||
*
|
||||
* \return Returns the PDUType corresponding to the PDU.
|
||||
*/
|
||||
virtual PDUType pdu_type() const = 0;
|
||||
protected:
|
||||
/**
|
||||
* \brief Copy constructor.
|
||||
*/
|
||||
PDU(const PDU &other);
|
||||
|
||||
/**
|
||||
* \brief Copy assignment operator.
|
||||
*/
|
||||
PDU &operator=(const PDU &other);
|
||||
|
||||
/**
|
||||
* \brief Copy other PDU's inner PDU(if any).
|
||||
* \param pdu The PDU from which to copy the inner PDU.
|
||||
*/
|
||||
void copy_inner_pdu(const PDU &pdu);
|
||||
|
||||
/**
|
||||
* \brief Prepares this PDU for serialization.
|
||||
*
|
||||
* This method is called before the inner PDUs are serialized.
|
||||
* It's useful in situations such as when serializing IP PDUs,
|
||||
* which don't contain any link layer encapsulation, and therefore
|
||||
* require to set the source IP address before the TCP/UDP checksum
|
||||
* is calculated.
|
||||
*
|
||||
* By default, this method does nothing
|
||||
*
|
||||
* \param parent The parent PDU.
|
||||
*/
|
||||
virtual void prepare_for_serialize(const PDU *parent) { }
|
||||
|
||||
/**
|
||||
* \brief Serializes this PDU and propagates this action to child PDUs.
|
||||
*
|
||||
* \param buffer The buffer in which to store this PDU's serialization.
|
||||
* \param total_sz The total size of the buffer.
|
||||
* \param parent The parent PDU. Will be 0 if there's the parent does not exist.
|
||||
*/
|
||||
void serialize(uint8_t *buffer, uint32_t total_sz, const PDU *parent);
|
||||
|
||||
/**
|
||||
* \brief Serializes this TCP PDU.
|
||||
*
|
||||
* Each PDU must override this method and implement it's own
|
||||
* serialization.
|
||||
* \param buffer The buffer in which the PDU will be serialized.
|
||||
* \param total_sz The size available in the buffer.
|
||||
* \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;
|
||||
private:
|
||||
PDU *_inner_pdu;
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Concatenation operator.
|
||||
*
|
||||
* This operator concatenates several PDUs. A copy of the right
|
||||
* operand is set at the end of the left one's inner PDU chain.
|
||||
* This means that:
|
||||
*
|
||||
* IP some_ip = IP("127.0.0.1") / TCP(12, 13) / RawPDU("bleh");
|
||||
*
|
||||
* Works as expected, meaning the output PDU will look like the
|
||||
* following:
|
||||
*
|
||||
* IP - TCP - RawPDU
|
||||
*
|
||||
* \param lop The left operand, which will be the one modified.
|
||||
* \param rop The right operand, the one which will be appended
|
||||
* to lop.
|
||||
*/
|
||||
template<typename T>
|
||||
T &operator/= (T &lop, const PDU &rop) {
|
||||
PDU *last = &lop;
|
||||
while(last->inner_pdu())
|
||||
last = last->inner_pdu();
|
||||
last->inner_pdu(rop.clone());
|
||||
return lop;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Concatenation operator.
|
||||
*
|
||||
* \sa operator/=
|
||||
*/
|
||||
template<typename T>
|
||||
T operator/ (T lop, const PDU &rop) {
|
||||
lop /= rop;
|
||||
return lop;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Concatenation operator on PDU pointers.
|
||||
*
|
||||
* \sa operator/=
|
||||
*/
|
||||
template<typename T>
|
||||
T *operator/= (T* lop, const PDU &rop) {
|
||||
*lop /= rop;
|
||||
return lop;
|
||||
}
|
||||
|
||||
namespace Internals {
|
||||
template<typename T>
|
||||
struct remove_pointer {
|
||||
typedef T type;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct remove_pointer<T*> {
|
||||
typedef T type;
|
||||
};
|
||||
}
|
||||
|
||||
template<typename T, typename U>
|
||||
T tins_cast(U *pdu) {
|
||||
typedef typename Internals::remove_pointer<T>::type TrueT;
|
||||
return pdu && (TrueT::pdu_flag == pdu->pdu_type()) ?
|
||||
static_cast<T>(pdu) :
|
||||
0;
|
||||
}
|
||||
|
||||
template<typename T, typename U>
|
||||
T &tins_cast(U &pdu) {
|
||||
T *ptr = tins_cast<T*>(&pdu);
|
||||
if(!ptr)
|
||||
throw bad_tins_cast();
|
||||
return *ptr;
|
||||
}
|
||||
}
|
||||
|
||||
#endif // TINS_PDU_H
|
||||
182
include/tins/pdu_allocator.h
Normal file
182
include/tins/pdu_allocator.h
Normal file
@@ -0,0 +1,182 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Matias Fontanini
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following disclaimer
|
||||
* in the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef TINS_PDU_ALLOCATOR_H
|
||||
#define TINS_PDU_ALLOCATOR_H
|
||||
|
||||
#include <map>
|
||||
#include "pdu.h"
|
||||
|
||||
namespace Tins {
|
||||
/**
|
||||
* \cond
|
||||
*/
|
||||
class EthernetII;
|
||||
class SNAP;
|
||||
class Dot1Q;
|
||||
class SLL;
|
||||
class IP;
|
||||
class IPv6;
|
||||
|
||||
namespace Internals {
|
||||
template<typename PDUType>
|
||||
PDU *default_allocator(const uint8_t *buffer, uint32_t size)
|
||||
{
|
||||
return new PDUType(buffer, size);
|
||||
}
|
||||
|
||||
template<typename Tag>
|
||||
class PDUAllocator {
|
||||
public:
|
||||
typedef typename Tag::identifier_type id_type;
|
||||
typedef PDU *(*allocator_type)(const uint8_t *, uint32_t);
|
||||
|
||||
template<typename PDUType>
|
||||
static void register_allocator(id_type identifier)
|
||||
{
|
||||
allocators[identifier] = &default_allocator<PDUType>;
|
||||
pdu_types[PDUType::pdu_flag] = identifier;
|
||||
}
|
||||
|
||||
static PDU *allocate(id_type identifier, const uint8_t *buffer, uint32_t size)
|
||||
{
|
||||
typename allocators_type::const_iterator it = allocators.find(identifier);
|
||||
return (it == allocators.end()) ? 0 : (*it->second)(buffer, size);
|
||||
}
|
||||
|
||||
static bool pdu_type_registered(PDU::PDUType type)
|
||||
{
|
||||
return pdu_types.count(type) != 0;
|
||||
}
|
||||
|
||||
static id_type pdu_type_to_id(PDU::PDUType type)
|
||||
{
|
||||
typename pdu_map_types::const_iterator it = pdu_types.find(type);
|
||||
return it->second;
|
||||
}
|
||||
private:
|
||||
typedef std::map<id_type, allocator_type> allocators_type;
|
||||
typedef std::map<PDU::PDUType, id_type> pdu_map_types;
|
||||
|
||||
static allocators_type allocators;
|
||||
static pdu_map_types pdu_types;
|
||||
};
|
||||
|
||||
template<typename Tag>
|
||||
typename PDUAllocator<Tag>::allocators_type PDUAllocator<Tag>::allocators;
|
||||
|
||||
template<typename Tag>
|
||||
typename PDUAllocator<Tag>::pdu_map_types PDUAllocator<Tag>::pdu_types;
|
||||
|
||||
template<typename IDType>
|
||||
struct pdu_tag {
|
||||
typedef IDType identifier_type;
|
||||
};
|
||||
|
||||
template<typename PDUType>
|
||||
struct pdu_tag_mapper;
|
||||
|
||||
#define TINS_GENERATE_TAG_MAPPER(pdu, id_type) \
|
||||
template<> \
|
||||
struct pdu_tag_mapper<pdu> { \
|
||||
typedef pdu_tag<id_type> type; \
|
||||
};
|
||||
|
||||
TINS_GENERATE_TAG_MAPPER(EthernetII, uint16_t)
|
||||
TINS_GENERATE_TAG_MAPPER(SNAP, uint16_t)
|
||||
TINS_GENERATE_TAG_MAPPER(SLL, uint16_t)
|
||||
TINS_GENERATE_TAG_MAPPER(Dot1Q, uint16_t)
|
||||
TINS_GENERATE_TAG_MAPPER(IP, uint8_t)
|
||||
TINS_GENERATE_TAG_MAPPER(IPv6, uint8_t)
|
||||
|
||||
#undef TINS_GENERATE_TAG_MAPPER
|
||||
|
||||
template<typename PDUType>
|
||||
PDU* allocate(
|
||||
typename pdu_tag_mapper<PDUType>::type::identifier_type id,
|
||||
const uint8_t *buffer,
|
||||
uint32_t size)
|
||||
{
|
||||
return PDUAllocator<typename pdu_tag_mapper<PDUType>::type>::allocate(id, buffer, size);
|
||||
}
|
||||
|
||||
template<typename PDUType>
|
||||
bool pdu_type_registered(PDU::PDUType type)
|
||||
{
|
||||
return PDUAllocator<typename pdu_tag_mapper<PDUType>::type>::pdu_type_registered(type);
|
||||
}
|
||||
|
||||
template<typename PDUType>
|
||||
typename pdu_tag_mapper<PDUType>::type::identifier_type pdu_type_to_id(PDU::PDUType type)
|
||||
{
|
||||
return PDUAllocator<typename pdu_tag_mapper<PDUType>::type>::pdu_type_to_id(type);
|
||||
}
|
||||
} // namespace Interals
|
||||
/**
|
||||
* \endcond
|
||||
*/
|
||||
|
||||
/**
|
||||
* \brief Defines inner PDU allocators.
|
||||
*/
|
||||
namespace Allocators {
|
||||
/**
|
||||
* \brief Registers an allocator for the provided PDU type.
|
||||
*
|
||||
* Registering a certain allocator for a PDU type is useful for
|
||||
* extending the library. Once an allocator is registered, it will
|
||||
* be taken into account while constructing a PDU from a buffer.
|
||||
*
|
||||
* If PDU finds that it cannot define which is the protocol
|
||||
* that should be allocated based on its protocol identifier, it
|
||||
* will try using the registered allocators if any.
|
||||
*
|
||||
* \code
|
||||
* // Register the 0x666 identifer. Now if EthernetII finds a
|
||||
* // network layer identifier field whose value is 0x666, it will
|
||||
* // use SomePDUType as its inner PDU type.
|
||||
* Allocators::register_allocator<EthernetII, SomePDUType>(0x666);
|
||||
* \endcode
|
||||
*
|
||||
* Note that some PDU types are grouped together. For example,
|
||||
* registering an allocator for EthernetII will make it work for
|
||||
* the rest of the link layer protocols, sine they should all work
|
||||
* the same way.
|
||||
*/
|
||||
template<typename PDUType, typename AllocatedType>
|
||||
void register_allocator(typename Internals::pdu_tag_mapper<PDUType>::type::identifier_type id)
|
||||
{
|
||||
Internals::PDUAllocator<
|
||||
typename Internals::pdu_tag_mapper<PDUType>::type
|
||||
>::template register_allocator<AllocatedType>(id);
|
||||
}
|
||||
} // namespace Allocators
|
||||
} // namespace Tins
|
||||
|
||||
#endif // TINS_PDU_ALLOCATOR_H
|
||||
158
include/tins/pdu_cacher.h
Normal file
158
include/tins/pdu_cacher.h
Normal file
@@ -0,0 +1,158 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Matias Fontanini
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following disclaimer
|
||||
* in the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef TINS_PDU_CACHER_H
|
||||
#define TINS_PDU_CACHER_H
|
||||
|
||||
#include <algorithm>
|
||||
#include "pdu.h"
|
||||
#include "macros.h"
|
||||
|
||||
namespace Tins {
|
||||
/**
|
||||
* \class PDUCacher
|
||||
* \brief PDU wrapper that caches the result of the wrapped PDU's
|
||||
* serialization.
|
||||
*
|
||||
* This wrapper class holds a PDU of the template parameter type, and
|
||||
* forwards every PDU virtual call to the stored object. Whenever a
|
||||
* call to write_serialization is performed on this wrapper, the result
|
||||
* is cached in a PDU::serialization_type. On subsequent calls to
|
||||
* PDUCacher::write_serialization, the contents of that cache will be
|
||||
* written to the output buffer.
|
||||
*
|
||||
* This class should provide a nice performance boost if you're sending
|
||||
* over and over a packet that requires some computation while being
|
||||
* serialized, such as performing checksums, iterate and copy options,
|
||||
* etc.
|
||||
*/
|
||||
template<typename T>
|
||||
class PDUCacher : public PDU {
|
||||
public:
|
||||
/**
|
||||
* The cached PDU type.
|
||||
*/
|
||||
typedef T cached_type;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
static const PDU::PDUType pdu_flag = cached_type::pdu_flag;
|
||||
|
||||
/**
|
||||
* Default constructs the cached PDU.
|
||||
*/
|
||||
PDUCacher() : cached_size() {}
|
||||
|
||||
/**
|
||||
* Constructor from a cached_type.
|
||||
* \param pdu The PDU to be copy constructed.
|
||||
*/
|
||||
PDUCacher(const cached_type &pdu) : cached(pdu),
|
||||
cached_size() {}
|
||||
|
||||
/**
|
||||
* Forwards the call to the cached PDU.
|
||||
*
|
||||
* \sa PDU::header_size.
|
||||
*/
|
||||
uint32_t header_size() const {
|
||||
if(cached_serialization.empty())
|
||||
cached_size = cached.size();
|
||||
return cached_size;
|
||||
}
|
||||
|
||||
/**
|
||||
* Forwards the call to the cached PDU.
|
||||
*
|
||||
* \sa PDU::clone.
|
||||
*/
|
||||
PDUCacher *clone() const {
|
||||
return new PDUCacher<T>(*this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Forwards the call to the cached PDU.
|
||||
*
|
||||
* \sa PDU::send.
|
||||
*/
|
||||
void send(PacketSender &sender, const NetworkInterface &iface) {
|
||||
cached.send(sender, iface);
|
||||
}
|
||||
|
||||
/**
|
||||
* Forwards the call to the cached PDU.
|
||||
*
|
||||
* \sa PDU::recv_responde.
|
||||
*/
|
||||
PDU *recv_response(PacketSender &sender, const NetworkInterface &iface) {
|
||||
return cached.recv_response(sender, iface);
|
||||
}
|
||||
|
||||
/**
|
||||
* Forwards the call to the cached PDU.
|
||||
*
|
||||
* \sa PDU::matches_response.
|
||||
*/
|
||||
bool matches_response(const uint8_t *ptr, uint32_t total_sz) const {
|
||||
return cached.matches_response(ptr, total_sz);
|
||||
}
|
||||
|
||||
/**
|
||||
* Forwards the call to the cached PDU.
|
||||
*
|
||||
* \sa PDU::matches_flag.
|
||||
*/
|
||||
bool matches_flag(PDUType flag) const {
|
||||
return cached.matches_flag(flag);
|
||||
}
|
||||
|
||||
/**
|
||||
* Forwards the call to the cached PDU.
|
||||
*
|
||||
* \sa PDU::pdu_type.
|
||||
*/
|
||||
PDUType pdu_type() const {
|
||||
return cached.pdu_type();
|
||||
}
|
||||
private:
|
||||
void write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *parent) {
|
||||
if(cached_serialization.size() != total_sz) {
|
||||
cached_serialization = cached.serialize();
|
||||
}
|
||||
std::copy(cached_serialization.begin(), cached_serialization.end(), buffer);
|
||||
}
|
||||
|
||||
cached_type cached;
|
||||
PDU::serialization_type cached_serialization;
|
||||
mutable uint32_t cached_size;
|
||||
};
|
||||
}
|
||||
|
||||
#endif // TINS_PDU_CACHER_H
|
||||
521
include/tins/pdu_option.h
Normal file
521
include/tins/pdu_option.h
Normal file
@@ -0,0 +1,521 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Matias Fontanini
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following disclaimer
|
||||
* in the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef TINS_PDU_OPTION_H
|
||||
#define TINS_PDU_OPTION_H
|
||||
|
||||
#include <vector>
|
||||
#include <iterator>
|
||||
#include <cstring>
|
||||
#include <algorithm>
|
||||
#include <string>
|
||||
#include <stdint.h>
|
||||
#include "exceptions.h"
|
||||
#include "endianness.h"
|
||||
#include "internals.h"
|
||||
#include "ip_address.h"
|
||||
#include "ipv6_address.h"
|
||||
#include "hw_address.h"
|
||||
|
||||
namespace Tins {
|
||||
/**
|
||||
* \cond
|
||||
*/
|
||||
template<typename OptionType, class PDUType>
|
||||
class PDUOption;
|
||||
|
||||
namespace Internals {
|
||||
template<typename T, typename X, typename PDUType>
|
||||
T convert_to_integral(const PDUOption<X, PDUType> & opt) {
|
||||
if(opt.data_size() != sizeof(T))
|
||||
throw malformed_option();
|
||||
T data = *(T*)opt.data_ptr();
|
||||
if(PDUType::endianness == PDUType::BE)
|
||||
data = Endian::be_to_host(data);
|
||||
else
|
||||
data = Endian::le_to_host(data);
|
||||
return data;
|
||||
}
|
||||
|
||||
template<typename T, typename = void>
|
||||
struct converter {
|
||||
template<typename X, typename PDUType>
|
||||
static T convert(const PDUOption<X, PDUType>& opt) {
|
||||
return T::from_option(opt);
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct converter<uint8_t> {
|
||||
template<typename X, typename PDUType>
|
||||
static uint8_t convert(const PDUOption<X, PDUType>& opt) {
|
||||
if(opt.data_size() != 1)
|
||||
throw malformed_option();
|
||||
return *opt.data_ptr();
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct converter<uint16_t> {
|
||||
template<typename X, typename PDUType>
|
||||
static uint16_t convert(const PDUOption<X, PDUType>& opt) {
|
||||
return convert_to_integral<uint16_t>(opt);
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct converter<uint32_t> {
|
||||
template<typename X, typename PDUType>
|
||||
static uint32_t convert(const PDUOption<X, PDUType>& opt) {
|
||||
return convert_to_integral<uint32_t>(opt);
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct converter<uint64_t> {
|
||||
template<typename X, typename PDUType>
|
||||
static uint64_t convert(const PDUOption<X, PDUType>& opt) {
|
||||
return convert_to_integral<uint64_t>(opt);
|
||||
}
|
||||
};
|
||||
|
||||
template<size_t n>
|
||||
struct converter<HWAddress<n> > {
|
||||
template<typename X, typename PDUType>
|
||||
static HWAddress<n> convert(const PDUOption<X, PDUType>& opt) {
|
||||
if(opt.data_size() != n)
|
||||
throw malformed_option();
|
||||
return HWAddress<n>(opt.data_ptr());
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct converter<IPv4Address> {
|
||||
template<typename X, typename PDUType>
|
||||
static IPv4Address convert(const PDUOption<X, PDUType>& opt) {
|
||||
if(opt.data_size() != sizeof(uint32_t))
|
||||
throw malformed_option();
|
||||
const uint32_t *ptr = (const uint32_t*)opt.data_ptr();
|
||||
if(PDUType::endianness == PDUType::BE)
|
||||
return IPv4Address(*ptr);
|
||||
else
|
||||
return IPv4Address(Endian::change_endian(*ptr));
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct converter<IPv6Address> {
|
||||
template<typename X, typename PDUType>
|
||||
static IPv6Address convert(const PDUOption<X, PDUType>& opt) {
|
||||
if(opt.data_size() != IPv6Address::address_size)
|
||||
throw malformed_option();
|
||||
return IPv6Address(opt.data_ptr());
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct converter<std::string> {
|
||||
template<typename X, typename PDUType>
|
||||
static std::string convert(const PDUOption<X, PDUType>& opt) {
|
||||
return std::string(
|
||||
opt.data_ptr(),
|
||||
opt.data_ptr() + opt.data_size()
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct converter<std::vector<float> > {
|
||||
template<typename X, typename PDUType>
|
||||
static std::vector<float> convert(const PDUOption<X, PDUType>& opt) {
|
||||
std::vector<float> output;
|
||||
const uint8_t *ptr = opt.data_ptr(), *end = ptr + opt.data_size();
|
||||
while(ptr != end) {
|
||||
output.push_back(float(*(ptr++) & 0x7f) / 2);
|
||||
}
|
||||
return output;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct converter<std::vector<T>, typename enable_if<is_unsigned_integral<T>::value>::type> {
|
||||
template<typename X, typename PDUType>
|
||||
static std::vector<T> convert(const PDUOption<X, PDUType>& opt) {
|
||||
if(opt.data_size() % sizeof(T) != 0)
|
||||
throw malformed_option();
|
||||
const T *ptr = (const T*)opt.data_ptr();
|
||||
const T *end = (const T*)(opt.data_ptr() + opt.data_size());
|
||||
|
||||
std::vector<T> output(std::distance(ptr, end));
|
||||
typename std::vector<T>::iterator it = output.begin();
|
||||
while(ptr < end) {
|
||||
if(PDUType::endianness == PDUType::BE)
|
||||
*it++ = Endian::be_to_host(*ptr++);
|
||||
else
|
||||
*it++ = Endian::le_to_host(*ptr++);
|
||||
}
|
||||
return output;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T, typename U>
|
||||
struct converter<
|
||||
std::vector<std::pair<T, U> >,
|
||||
typename enable_if<
|
||||
is_unsigned_integral<T>::value && is_unsigned_integral<U>::value
|
||||
>::type
|
||||
> {
|
||||
template<typename X, typename PDUType>
|
||||
static std::vector<std::pair<T, U> > convert(const PDUOption<X, PDUType>& opt) {
|
||||
if(opt.data_size() % (sizeof(T) + sizeof(U)) != 0)
|
||||
throw malformed_option();
|
||||
const uint8_t *ptr = opt.data_ptr(), *end = ptr + opt.data_size();
|
||||
|
||||
std::vector<std::pair<T, U> > output;
|
||||
while(ptr < end) {
|
||||
std::pair<T, U> data;
|
||||
data.first = *(const T*)ptr;
|
||||
ptr += sizeof(T);
|
||||
data.second = *(const U*)ptr;
|
||||
ptr += sizeof(U);
|
||||
if(PDUType::endianness == PDUType::BE) {
|
||||
data.first = Endian::be_to_host(data.first);
|
||||
data.second = Endian::be_to_host(data.second);
|
||||
}
|
||||
else {
|
||||
data.first = Endian::le_to_host(data.first);
|
||||
data.second = Endian::le_to_host(data.second);
|
||||
}
|
||||
output.push_back(data);
|
||||
}
|
||||
return output;
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct converter<std::vector<IPv4Address> > {
|
||||
template<typename X, typename PDUType>
|
||||
static std::vector<IPv4Address> convert(const PDUOption<X, PDUType>& opt) {
|
||||
if(opt.data_size() % 4 != 0)
|
||||
throw malformed_option();
|
||||
const uint32_t *ptr = (const uint32_t*)opt.data_ptr();
|
||||
const uint32_t *end = (const uint32_t*)(opt.data_ptr() + opt.data_size());
|
||||
|
||||
std::vector<IPv4Address> output(std::distance(ptr, end));
|
||||
std::vector<IPv4Address>::iterator it = output.begin();
|
||||
while(ptr < end) {
|
||||
if(PDUType::endianness == PDUType::BE)
|
||||
*it++ = IPv4Address(*ptr++);
|
||||
else
|
||||
*it++ = IPv4Address(Endian::change_endian(*ptr++));
|
||||
}
|
||||
return output;
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct converter<std::vector<IPv6Address> > {
|
||||
template<typename X, typename PDUType>
|
||||
static std::vector<IPv6Address> convert(const PDUOption<X, PDUType>& opt) {
|
||||
if(opt.data_size() % IPv6Address::address_size != 0)
|
||||
throw malformed_option();
|
||||
const uint8_t *ptr = opt.data_ptr(), *end = opt.data_ptr() + opt.data_size();
|
||||
std::vector<IPv6Address> output;
|
||||
while(ptr < end) {
|
||||
output.push_back(IPv6Address(ptr));
|
||||
ptr += IPv6Address::address_size;
|
||||
}
|
||||
return output;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T, typename U>
|
||||
struct converter<
|
||||
std::pair<T, U>,
|
||||
typename enable_if<
|
||||
is_unsigned_integral<T>::value && is_unsigned_integral<U>::value
|
||||
>::type
|
||||
> {
|
||||
template<typename X, typename PDUType>
|
||||
static std::pair<T, U> convert(const PDUOption<X, PDUType>& opt) {
|
||||
if(opt.data_size() != sizeof(T) + sizeof(U))
|
||||
throw malformed_option();
|
||||
std::pair<T, U> output;
|
||||
std::memcpy(&output.first, opt.data_ptr(), sizeof(T));
|
||||
std::memcpy(&output.second, opt.data_ptr() + sizeof(T), sizeof(U));
|
||||
if(PDUType::endianness == PDUType::BE) {
|
||||
output.first = Endian::be_to_host(output.first);
|
||||
output.second = Endian::be_to_host(output.second);
|
||||
}
|
||||
else {
|
||||
output.first = Endian::le_to_host(output.first);
|
||||
output.second = Endian::le_to_host(output.second);
|
||||
}
|
||||
return output;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* \endcond
|
||||
*/
|
||||
|
||||
/**
|
||||
* \class PDUOption
|
||||
* \brief Represents a PDU option field.
|
||||
*
|
||||
* Several PDUs, such as TCP, IP, Dot11 or DHCP contain options. All
|
||||
* of them behave exactly the same way. This class represents those
|
||||
* options.
|
||||
*
|
||||
* The OptionType template parameter indicates the type that will be
|
||||
* used to store this option's identifier.
|
||||
*/
|
||||
template<typename OptionType, class PDUType>
|
||||
class PDUOption {
|
||||
private:
|
||||
static const int small_buffer_size = 8;
|
||||
public:
|
||||
typedef uint8_t data_type;
|
||||
typedef OptionType option_type;
|
||||
|
||||
/**
|
||||
* \brief Constructs a PDUOption.
|
||||
* \param opt The option type.
|
||||
* \param length The option's data length.
|
||||
* \param data The option's data(if any).
|
||||
*/
|
||||
PDUOption(option_type opt = option_type(), size_t length = 0, const data_type *data = 0)
|
||||
: option_(opt), size_(length) {
|
||||
set_payload_contents(data, data + (data ? length : 0));
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Copy constructor.
|
||||
* \param rhs The PDUOption to be copied.
|
||||
*/
|
||||
PDUOption(const PDUOption& rhs) {
|
||||
real_size_ = 0;
|
||||
*this = rhs;
|
||||
}
|
||||
|
||||
#if TINS_IS_CXX11
|
||||
/**
|
||||
* \brief Move constructor.
|
||||
* \param rhs The PDUOption to be moved.
|
||||
*/
|
||||
PDUOption(PDUOption&& rhs) {
|
||||
real_size_ = 0;
|
||||
*this = std::move(rhs);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Move assignment operator.
|
||||
* \param rhs The PDUOption to be moved.
|
||||
*/
|
||||
PDUOption& operator=(PDUOption&& rhs) {
|
||||
option_ = rhs.option_;
|
||||
size_ = rhs.size_;
|
||||
if(real_size_ > small_buffer_size) {
|
||||
delete[] payload_.big_buffer_ptr;
|
||||
}
|
||||
real_size_ = rhs.real_size_;
|
||||
if(real_size_ > small_buffer_size) {
|
||||
payload_.big_buffer_ptr = nullptr;
|
||||
std::swap(payload_.big_buffer_ptr, rhs.payload_.big_buffer_ptr);
|
||||
rhs.real_size_ = 0;
|
||||
}
|
||||
else {
|
||||
std::copy(
|
||||
rhs.data_ptr(),
|
||||
rhs.data_ptr() + rhs.data_size(),
|
||||
payload_.small_buffer
|
||||
);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
#endif // TINS_IS_CXX11
|
||||
|
||||
/**
|
||||
* \brief Copy assignment operator.
|
||||
* \param rhs The PDUOption to be copied.
|
||||
*/
|
||||
PDUOption& operator=(const PDUOption& rhs) {
|
||||
option_ = rhs.option_;
|
||||
size_ = rhs.size_;
|
||||
if(real_size_ > small_buffer_size) {
|
||||
delete[] payload_.big_buffer_ptr;
|
||||
}
|
||||
real_size_ = rhs.real_size_;
|
||||
set_payload_contents(rhs.data_ptr(), rhs.data_ptr() + rhs.data_size());
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Destructor.
|
||||
*/
|
||||
~PDUOption() {
|
||||
if(real_size_ > small_buffer_size) {
|
||||
delete[] payload_.big_buffer_ptr;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Constructs a PDUOption from iterators, which
|
||||
* indicate the data to be stored in it.
|
||||
*
|
||||
* \param opt The option type.
|
||||
* \param start The beginning of the option data.
|
||||
* \param end The end of the option data.
|
||||
*/
|
||||
template<typename ForwardIterator>
|
||||
PDUOption(option_type opt, ForwardIterator start, ForwardIterator end)
|
||||
: option_(opt), size_(std::distance(start, end)) {
|
||||
set_payload_contents(start, end);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Constructs a PDUOption from iterators, which
|
||||
* indicate the data to be stored in it.
|
||||
*
|
||||
* The length parameter indicates the contents of the length field
|
||||
* when this option is serialized. Note that this can be different
|
||||
* to std::distance(start, end).
|
||||
*
|
||||
* \sa length_field
|
||||
*
|
||||
* \param opt The option type.
|
||||
* \param length The length of this option.
|
||||
* \param start The beginning of the option data.
|
||||
* \param end The end of the option data.
|
||||
*/
|
||||
template<typename ForwardIterator>
|
||||
PDUOption(option_type opt, size_t length, ForwardIterator start, ForwardIterator end)
|
||||
: option_(opt), size_(length) {
|
||||
set_payload_contents(start, end);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves this option's type.
|
||||
* \return uint8_t containing this option's size.
|
||||
*/
|
||||
option_type option() const {
|
||||
return option_;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets this option's type
|
||||
* \param opt The option type to be set.
|
||||
*/
|
||||
void option(option_type opt) {
|
||||
option_ = opt;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves this option's data.
|
||||
*
|
||||
* If this method is called when data_size() == 0,
|
||||
* dereferencing the returned pointer will result in undefined
|
||||
* behaviour.
|
||||
*
|
||||
* \return const data_type& containing this option's value.
|
||||
*/
|
||||
const data_type *data_ptr() const {
|
||||
return real_size_ <= small_buffer_size ?
|
||||
payload_.small_buffer :
|
||||
payload_.big_buffer_ptr;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Retrieves the length of this option's data.
|
||||
*
|
||||
* This is the actual size of the data.
|
||||
*/
|
||||
size_t data_size() const {
|
||||
return real_size_;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Retrieves the data length field.
|
||||
*
|
||||
* This is what the size field will contain when this option is
|
||||
* serialized. It can differ from the actual data size.
|
||||
*
|
||||
* This will be equal to data_size unless the constructor that takes
|
||||
* both a data length and two iterators is used.
|
||||
|
||||
*
|
||||
* \sa data_size.
|
||||
*/
|
||||
size_t length_field() const {
|
||||
return size_;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Constructs a T from this PDUOption.
|
||||
*
|
||||
* Use this method to convert a PDUOption to the specific type that
|
||||
* represents it. For example, if you know an option is of type
|
||||
* PDU::SACK, you could use option.to<TCP::sack_type>().
|
||||
*/
|
||||
template<typename T>
|
||||
T to() const {
|
||||
return Internals::converter<T>::convert(*this);
|
||||
}
|
||||
private:
|
||||
template<typename ForwardIterator>
|
||||
void set_payload_contents(ForwardIterator start, ForwardIterator end) {
|
||||
real_size_ = std::distance(start, end);
|
||||
if(real_size_ <= small_buffer_size) {
|
||||
std::copy(
|
||||
start,
|
||||
end,
|
||||
payload_.small_buffer
|
||||
);
|
||||
}
|
||||
else {
|
||||
payload_.big_buffer_ptr = new data_type[real_size_];
|
||||
std::copy(
|
||||
start,
|
||||
end,
|
||||
payload_.big_buffer_ptr
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
option_type option_;
|
||||
uint16_t size_, real_size_;
|
||||
union {
|
||||
data_type small_buffer[small_buffer_size];
|
||||
data_type* big_buffer_ptr;
|
||||
} payload_;
|
||||
};
|
||||
} // namespace Tins
|
||||
#endif // TINS_PDU_OPTION_H
|
||||
135
include/tins/ppi.h
Normal file
135
include/tins/ppi.h
Normal file
@@ -0,0 +1,135 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Matias Fontanini
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following disclaimer
|
||||
* in the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef TINS_PPI_H
|
||||
#define TINS_PPI_H
|
||||
|
||||
#include "pdu.h"
|
||||
#include "endianness.h"
|
||||
#include "small_uint.h"
|
||||
|
||||
namespace Tins {
|
||||
/**
|
||||
* \class PPI
|
||||
* \brief Represents a Per-Packet Information PDU.
|
||||
*
|
||||
* This PDU can only be constructed from a buffer, and
|
||||
* cannot be serialized. Therefore, it is only useful while
|
||||
* sniffing packets.
|
||||
*/
|
||||
class PPI : public PDU {
|
||||
public:
|
||||
/**
|
||||
* This PDU's flag.
|
||||
*/
|
||||
static const PDU::PDUType pdu_flag = PDU::PPI;
|
||||
|
||||
/**
|
||||
* \brief Constructs an PPI 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 an PPI 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.
|
||||
*/
|
||||
PPI(const uint8_t *buffer, uint32_t total_sz);
|
||||
|
||||
// Getters
|
||||
|
||||
/**
|
||||
* \brief Getter for the version field.
|
||||
* \return The stored version field value.
|
||||
*/
|
||||
uint8_t version() const {
|
||||
return _header.version;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the flags field.
|
||||
* \return The stored flags field value.
|
||||
*/
|
||||
uint8_t flags() const {
|
||||
return _header.flags;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the length field.
|
||||
* \return The stored length field value.
|
||||
*/
|
||||
uint16_t length() const {
|
||||
return Endian::le_to_host(_header.length);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the Data Link Type field.
|
||||
* \return The stored Data Link Type field value.
|
||||
*/
|
||||
uint32_t dlt() const {
|
||||
return Endian::le_to_host(_header.dlt);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Returns the header size.
|
||||
*
|
||||
* This metod overrides PDU::header_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_flag; }
|
||||
|
||||
/**
|
||||
* \brief Clones this PDU.
|
||||
*
|
||||
* \sa PDU::clone
|
||||
*/
|
||||
PPI *clone() const {
|
||||
return new PPI(*this);
|
||||
}
|
||||
private:
|
||||
void write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *);
|
||||
|
||||
struct header {
|
||||
uint8_t version, flags;
|
||||
uint16_t length;
|
||||
uint32_t dlt;
|
||||
};
|
||||
|
||||
header _header;
|
||||
byte_array _data;
|
||||
};
|
||||
}
|
||||
|
||||
#endif // TINS_PPI_H
|
||||
434
include/tins/pppoe.h
Normal file
434
include/tins/pppoe.h
Normal file
@@ -0,0 +1,434 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Matias Fontanini
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following disclaimer
|
||||
* in the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef TINS_PPPoE_H
|
||||
#define TINS_PPPoE_H
|
||||
|
||||
#include <list>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include "pdu.h"
|
||||
#include "endianness.h"
|
||||
#include "small_uint.h"
|
||||
#include "pdu_option.h"
|
||||
#include "cxxstd.h"
|
||||
|
||||
namespace Tins {
|
||||
/**
|
||||
* \class PPPoE
|
||||
* \brief Represents a Point-to-point protocol over Ethernet PDU.
|
||||
*/
|
||||
class PPPoE : public PDU {
|
||||
public:
|
||||
/**
|
||||
* The tag types enum.
|
||||
*/
|
||||
enum TagTypes {
|
||||
END_OF_LIST = 0,
|
||||
SERVICE_NAME = 0x101,
|
||||
#if TINS_IS_LITTLE_ENDIAN
|
||||
AC_NAME = 0x201,
|
||||
HOST_UNIQ = 0x301,
|
||||
AC_COOKIE = 0x401,
|
||||
VENDOR_SPECIFIC = 0x501,
|
||||
RELAY_SESSION_ID = 0x101,
|
||||
SERVICE_NAME_ERROR = 0x201,
|
||||
AC_SYSTEM_ERROR = 0x202,
|
||||
GENERIC_ERROR = 0x302
|
||||
#else
|
||||
AC_NAME = 0x102,
|
||||
HOST_UNIQ = 0x103,
|
||||
AC_COOKIE = 0x104,
|
||||
VENDOR_SPECIFIC = 0x105,
|
||||
RELAY_SESSION_ID = 0x110,
|
||||
SERVICE_NAME_ERROR = 0x201,
|
||||
AC_SYSTEM_ERROR = 0x202,
|
||||
GENERIC_ERROR = 0x203
|
||||
#endif
|
||||
};
|
||||
|
||||
/**
|
||||
* The type used to store a TLV option.
|
||||
*/
|
||||
typedef PDUOption<TagTypes, PPPoE> tag;
|
||||
|
||||
/**
|
||||
* The type used to store the options.
|
||||
*/
|
||||
typedef std::list<tag> tags_type;
|
||||
|
||||
/**
|
||||
* The type used to store the Vendor-Specific tag's value.
|
||||
*/
|
||||
struct vendor_spec_type {
|
||||
typedef std::vector<uint8_t> data_type;
|
||||
|
||||
uint32_t vendor_id;
|
||||
data_type data;
|
||||
|
||||
vendor_spec_type(uint32_t vendor_id = 0, const data_type &data = data_type())
|
||||
: vendor_id(vendor_id), data(data) { }
|
||||
|
||||
static vendor_spec_type from_option(const tag &opt);
|
||||
};
|
||||
|
||||
/**
|
||||
* This PDU's flag.
|
||||
*/
|
||||
static const PDU::PDUType pdu_flag = PDU::PPPOE;
|
||||
|
||||
/**
|
||||
* \brief Default constructor.
|
||||
*
|
||||
* This sets the version and type fields to 0x1.
|
||||
*/
|
||||
PPPoE();
|
||||
|
||||
/**
|
||||
* \brief Constructor which creates an PPPoE object from a buffer.
|
||||
*
|
||||
* If there is not enough size for a PPPoE 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.
|
||||
*/
|
||||
PPPoE(const uint8_t *buffer, uint32_t total_sz);
|
||||
|
||||
// Getters
|
||||
|
||||
/**
|
||||
* \brief Getter for the version field.
|
||||
* \return The stored version field value.
|
||||
*/
|
||||
small_uint<4> version() const {
|
||||
return _header.version;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the type field.
|
||||
* \return The stored type field value.
|
||||
*/
|
||||
small_uint<4> type() const {
|
||||
return _header.type;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the code field.
|
||||
* \return The stored code field value.
|
||||
*/
|
||||
uint8_t code() const {
|
||||
return _header.code;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the session_id field.
|
||||
* \return The stored session_id field value.
|
||||
*/
|
||||
uint16_t session_id() const {
|
||||
return Endian::be_to_host(_header.session_id);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the payload_length field.
|
||||
* \return The stored payload_length field value.
|
||||
*/
|
||||
uint16_t payload_length() const {
|
||||
return Endian::be_to_host(_header.payload_length);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Returns the header size.
|
||||
*
|
||||
* This metod overrides PDU::header_size. \sa PDU::header_size
|
||||
*/
|
||||
uint32_t header_size() const;
|
||||
|
||||
/**
|
||||
* \brief Returns the list of tags.
|
||||
*/
|
||||
const tags_type &tags() const {
|
||||
return _tags;
|
||||
}
|
||||
|
||||
/**
|
||||
* \sa PDU::clone
|
||||
*/
|
||||
PPPoE *clone() const {
|
||||
return new PPPoE(*this);
|
||||
}
|
||||
|
||||
const tag *search_tag(TagTypes identifier) const;
|
||||
|
||||
/**
|
||||
* \brief Getter for the PDU's type.
|
||||
* \sa PDU::pdu_type
|
||||
*/
|
||||
PDUType pdu_type() const { return pdu_flag; }
|
||||
|
||||
// Setters
|
||||
|
||||
/**
|
||||
* \brief Setter for the version field.
|
||||
* \param new_version The new version field value.
|
||||
*/
|
||||
void version(small_uint<4> new_version);
|
||||
|
||||
/**
|
||||
* \brief Setter for the type field.
|
||||
* \param new_type The new type field value.
|
||||
*/
|
||||
void type(small_uint<4> new_type);
|
||||
|
||||
/**
|
||||
* \brief Setter for the code field.
|
||||
* \param new_code The new code field value.
|
||||
*/
|
||||
void code(uint8_t new_code);
|
||||
|
||||
/**
|
||||
* \brief Setter for the session_id field.
|
||||
* \param new_session_id The new session_id field value.
|
||||
*/
|
||||
void session_id(uint16_t new_session_id);
|
||||
|
||||
/**
|
||||
* \brief Setter for the payload_length field.
|
||||
* \param new_payload_length The new payload_length field value.
|
||||
*/
|
||||
void payload_length(uint16_t new_payload_length);
|
||||
|
||||
/**
|
||||
* \brief Adds a PPPoE tag.
|
||||
*
|
||||
* \param option The option to be added.
|
||||
*/
|
||||
void add_tag(const tag &option);
|
||||
|
||||
#if TINS_IS_CXX11
|
||||
/**
|
||||
* \brief Adds a PPPoE tag.
|
||||
*
|
||||
* This move-constructs the option.
|
||||
*
|
||||
* \param option The option to be added.
|
||||
*/
|
||||
void add_tag(tag &&option) {
|
||||
_tags_size += option.data_size() + sizeof(uint16_t) * 2;
|
||||
_tags.push_back(std::move(option));
|
||||
}
|
||||
#endif
|
||||
|
||||
// Option setters
|
||||
|
||||
/**
|
||||
* \brief Adds an end-of-list tag.
|
||||
*/
|
||||
void end_of_list();
|
||||
|
||||
/**
|
||||
* \brief Adds a service-name tag.
|
||||
*
|
||||
* \param value The service name.
|
||||
*/
|
||||
void service_name(const std::string &value);
|
||||
|
||||
/**
|
||||
* \brief Adds a AC-name tag.
|
||||
*
|
||||
* \param value The AC name.
|
||||
*/
|
||||
void ac_name(const std::string &value);
|
||||
|
||||
/**
|
||||
* \brief Adds a host-uniq tag.
|
||||
*
|
||||
* \param value The tag's value.
|
||||
*/
|
||||
void host_uniq(const byte_array &value);
|
||||
|
||||
/**
|
||||
* \brief Adds a AC-Cookie tag.
|
||||
*
|
||||
* \param value The tag's value.
|
||||
*/
|
||||
void ac_cookie(const byte_array &value);
|
||||
|
||||
/**
|
||||
* \brief Adds a Vendor-Specific tag.
|
||||
*
|
||||
* \param value The tag's value.
|
||||
*/
|
||||
void vendor_specific(const vendor_spec_type &value);
|
||||
|
||||
/**
|
||||
* \brief Adds a Relay-Session-Id tag.
|
||||
*
|
||||
* \param value The tag's value.
|
||||
*/
|
||||
void relay_session_id(const byte_array &value);
|
||||
|
||||
/**
|
||||
* \brief Adds a Service-Name-Error tag.
|
||||
*
|
||||
* \param value The tag's value.
|
||||
*/
|
||||
void service_name_error(const std::string &value);
|
||||
|
||||
/**
|
||||
* \brief Adds a AC-System-Error tag.
|
||||
*
|
||||
* \param value The tag's value.
|
||||
*/
|
||||
void ac_system_error(const std::string &value);
|
||||
|
||||
/**
|
||||
* \brief Adds a Generic-Error tag.
|
||||
*
|
||||
* \param value The tag's value.
|
||||
*/
|
||||
void generic_error(const std::string &value);
|
||||
|
||||
// Option getters
|
||||
|
||||
/**
|
||||
* \brief Getter for the service-name tag.
|
||||
*
|
||||
* This method will throw an option_not_found exception if the
|
||||
* option is not found.
|
||||
*/
|
||||
std::string service_name() const;
|
||||
|
||||
/**
|
||||
* \brief Getter for the AC-name tag.
|
||||
*
|
||||
* This method will throw an option_not_found exception if the
|
||||
* option is not found.
|
||||
*/
|
||||
std::string ac_name() const;
|
||||
|
||||
/**
|
||||
* \brief Getter for the host-uniq tag.
|
||||
*
|
||||
* This method will throw an option_not_found exception if the
|
||||
* option is not found.
|
||||
*/
|
||||
byte_array host_uniq() const;
|
||||
|
||||
/**
|
||||
* \brief Getter for the AC-Cookie tag.
|
||||
*
|
||||
* This method will throw an option_not_found exception if the
|
||||
* option is not found.
|
||||
*/
|
||||
byte_array ac_cookie() const;
|
||||
|
||||
/**
|
||||
* \brief Getter for the Vendor-Specific tag.
|
||||
*
|
||||
* This method will throw an option_not_found exception if the
|
||||
* option is not found.
|
||||
*/
|
||||
vendor_spec_type vendor_specific() const;
|
||||
|
||||
/**
|
||||
* \brief Getter for the Vendor-Specific tag.
|
||||
*
|
||||
* This method will throw an option_not_found exception if the
|
||||
* option is not found.
|
||||
*/
|
||||
byte_array relay_session_id() const;
|
||||
|
||||
/**
|
||||
* \brief Getter for the Service-Name-Error tag.
|
||||
*
|
||||
* This method will throw an option_not_found exception if the
|
||||
* option is not found.
|
||||
*/
|
||||
std::string service_name_error() const;
|
||||
|
||||
/**
|
||||
* \brief Getter for the AC-System-Error tag.
|
||||
*
|
||||
* This method will throw an option_not_found exception if the
|
||||
* option is not found.
|
||||
*/
|
||||
std::string ac_system_error() const;
|
||||
|
||||
/**
|
||||
* \brief Getter for the Generic-Error tag.
|
||||
*
|
||||
* This method will throw an option_not_found exception if the
|
||||
* option is not found.
|
||||
*/
|
||||
std::string generic_error() const;
|
||||
private:
|
||||
void write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *);
|
||||
|
||||
template<typename T>
|
||||
void add_tag_iterable(TagTypes id, const T &data) {
|
||||
add_tag(
|
||||
tag(
|
||||
id,
|
||||
data.begin(),
|
||||
data.end()
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T search_and_convert(TagTypes id) const {
|
||||
const tag *t = search_tag(id);
|
||||
if(!t)
|
||||
throw option_not_found();
|
||||
return t->to<T>();
|
||||
}
|
||||
|
||||
TINS_BEGIN_PACK
|
||||
struct pppoe_hdr {
|
||||
#if TINS_IS_LITTLE_ENDIAN
|
||||
uint8_t version:4,
|
||||
type:4;
|
||||
uint8_t code;
|
||||
#else
|
||||
uint16_t version:4,
|
||||
type:4,
|
||||
code:8;
|
||||
#endif
|
||||
uint16_t session_id;
|
||||
uint16_t payload_length;
|
||||
} TINS_END_PACK;
|
||||
|
||||
pppoe_hdr _header;
|
||||
tags_type _tags;
|
||||
uint16_t _tags_size;
|
||||
};
|
||||
}
|
||||
|
||||
#endif // TINS_PPPoE_H
|
||||
433
include/tins/radiotap.h
Normal file
433
include/tins/radiotap.h
Normal file
@@ -0,0 +1,433 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Matias Fontanini
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following disclaimer
|
||||
* in the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#if !defined(TINS_RADIOTAP_H) && defined(HAVE_DOT11)
|
||||
#define TINS_RADIOTAP_H
|
||||
|
||||
#include "macros.h"
|
||||
#include "pdu.h"
|
||||
#include "endianness.h"
|
||||
|
||||
namespace Tins {
|
||||
class PacketSender;
|
||||
|
||||
/**
|
||||
* \brief Class that represents the IEEE 802.11 radio tap header.
|
||||
*
|
||||
* By default, RadioTap PDUs set the necesary fields to send an 802.11
|
||||
* PDU as its inner pdu, avoiding packet drops. As a consequence,
|
||||
* the FCS-at-end flag is on, the channel is set to 1, TSFT is set to 0,
|
||||
* dbm_signal is set to 0xce, and the rx_flag and antenna fields to 0.
|
||||
*/
|
||||
class RadioTap : public PDU {
|
||||
public:
|
||||
/**
|
||||
* \brief This PDU's flag.
|
||||
*/
|
||||
static const PDU::PDUType pdu_flag = PDU::RADIOTAP;
|
||||
|
||||
/**
|
||||
* \brief Enumeration of the different channel type flags.
|
||||
*
|
||||
* These channel type flags can be OR'd and set using the
|
||||
* RadioTap::channel() method.
|
||||
*/
|
||||
enum ChannelType {
|
||||
TURBO = 0x10,
|
||||
CCK = 0x20,
|
||||
OFDM = 0x40,
|
||||
TWO_GZ = 0x80,
|
||||
FIVE_GZ = 0x100,
|
||||
PASSIVE = 0x200,
|
||||
DYN_CCK_OFDM = 0x400,
|
||||
GFSK = 0x800
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Flags used in the present field.
|
||||
*
|
||||
* \sa RadioTap::present()
|
||||
*/
|
||||
enum PresentFlags {
|
||||
TSTF = 1,
|
||||
FLAGS = 2,
|
||||
RATE = 4,
|
||||
CHANNEL = 8,
|
||||
FHSS = 16,
|
||||
DBM_SIGNAL = 32,
|
||||
DBM_NOISE = 64,
|
||||
LOCK_QUALITY = 128,
|
||||
TX_ATTENUATION = 256,
|
||||
DB_TX_ATTENUATION = 512,
|
||||
DBM_TX_ATTENUATION = 1024,
|
||||
ANTENNA = 2048,
|
||||
DB_SIGNAL = 4096,
|
||||
DB_NOISE = 8192,
|
||||
RX_FLAGS = 16382,
|
||||
CHANNEL_PLUS = 262144
|
||||
};
|
||||
|
||||
/**
|
||||
* \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 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(uint8_t new_dbm_signal);
|
||||
|
||||
/**
|
||||
* \brief Setter for the dbm noise field.
|
||||
* \param new_dbm_noise The new dbm noise.
|
||||
*/
|
||||
void dbm_noise(uint8_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 antenna signal.
|
||||
*/
|
||||
void rx_flags(uint16_t new_rx_flag);
|
||||
|
||||
/* Getters */
|
||||
|
||||
/**
|
||||
* \brief Getter for the version field.
|
||||
* \return The version field.
|
||||
*/
|
||||
uint8_t version() const { return _radio.it_version; }
|
||||
|
||||
/**
|
||||
* \brief Getter for the padding field.
|
||||
* \return The padding field.
|
||||
*/
|
||||
uint8_t padding() const { return _radio.it_pad; }
|
||||
|
||||
/**
|
||||
* \brief Getter for the length field.
|
||||
* \return The length field.
|
||||
*/
|
||||
uint16_t length() const { return Endian::le_to_host(_radio.it_len); }
|
||||
|
||||
/**
|
||||
* \brief Getter for the tsft field.
|
||||
* \return The tsft field.
|
||||
*/
|
||||
uint64_t tsft() const { return Endian::le_to_host(_tsft); }
|
||||
|
||||
/**
|
||||
* \brief Getter for the flags field.
|
||||
* \return The flags field.
|
||||
*/
|
||||
FrameFlags flags() const { return (FrameFlags)_flags; }
|
||||
|
||||
/**
|
||||
* \brief Getter for the rate field.
|
||||
* \return The rate field.
|
||||
*/
|
||||
uint8_t rate() const { return _rate; }
|
||||
|
||||
/**
|
||||
* \brief Getter for the channel frequency field.
|
||||
* \return The channel frequency field.
|
||||
*/
|
||||
uint16_t channel_freq() const { return Endian::le_to_host(_channel_freq); }
|
||||
|
||||
/**
|
||||
* \brief Getter for the channel type field.
|
||||
* \return The channel type field.
|
||||
*/
|
||||
uint16_t channel_type() const { return Endian::le_to_host(_channel_type); }
|
||||
|
||||
/**
|
||||
* \brief Getter for the dbm signal field.
|
||||
* \return The dbm signal field.
|
||||
*/
|
||||
uint8_t dbm_signal() const { return _dbm_signal; }
|
||||
|
||||
/**
|
||||
* \brief Getter for the dbm noise field.
|
||||
* \return The dbm noise field.
|
||||
*/
|
||||
uint8_t dbm_noise() const { return _dbm_noise; }
|
||||
|
||||
/**
|
||||
* \brief Getter for the signal quality field.
|
||||
* \return The signal quality field.
|
||||
*/
|
||||
uint16_t signal_quality() const { return _signal_quality; }
|
||||
|
||||
/**
|
||||
* \brief Getter for the antenna field.
|
||||
* \return The antenna field.
|
||||
*/
|
||||
uint8_t antenna() const { return _antenna; }
|
||||
|
||||
/**
|
||||
* \brief Getter for the db signal field.
|
||||
* \return The db signal field.
|
||||
*/
|
||||
uint8_t db_signal() const { return _db_signal; }
|
||||
|
||||
/**
|
||||
* \brief Getter for the channel+ field.
|
||||
* \return The channel+ field.
|
||||
*/
|
||||
uint32_t channel_plus() const { return Endian::le_to_host<uint32_t>(_channel_type); }
|
||||
|
||||
/**
|
||||
* \brief Getter for the rx flags field.
|
||||
* \return The rx flags field.
|
||||
*/
|
||||
uint16_t rx_flags() const { return Endian::le_to_host(_rx_flags); }
|
||||
|
||||
/**
|
||||
* \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
|
||||
struct radiotap_hdr {
|
||||
#if TINS_IS_LITTLE_ENDIAN
|
||||
uint8_t it_version;
|
||||
uint8_t it_pad;
|
||||
uint16_t it_len;
|
||||
union {
|
||||
struct {
|
||||
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_attenuation:1,
|
||||
antenna:1,
|
||||
db_signal:1,
|
||||
db_noise:1,
|
||||
rx_flags:1,
|
||||
reserved1:3,
|
||||
channel_plus:1,
|
||||
reserved2:12,
|
||||
ext:1;
|
||||
} flags;
|
||||
uint32_t flags_32;
|
||||
};
|
||||
#else
|
||||
uint8_t it_pad;
|
||||
uint8_t it_version;
|
||||
uint16_t it_len;
|
||||
union {
|
||||
struct {
|
||||
uint32_t lock_quality:1,
|
||||
dbm_noise:1,
|
||||
dbm_signal:1,
|
||||
fhss:1,
|
||||
channel:1,
|
||||
rate:1,
|
||||
flags:1,
|
||||
tsft:1,
|
||||
reserved3:1,
|
||||
rx_flags:1,
|
||||
db_tx_attenuation:1,
|
||||
dbm_tx_attenuation:1,
|
||||
antenna:1,
|
||||
db_signal:1,
|
||||
db_noise:1,
|
||||
tx_attenuation:1,
|
||||
reserved2:5,
|
||||
channel_plus:1,
|
||||
reserved1:2,
|
||||
reserved4:7,
|
||||
ext:1;
|
||||
} flags;
|
||||
uint32_t flags_32;
|
||||
};
|
||||
#endif
|
||||
} TINS_END_PACK;
|
||||
|
||||
void init();
|
||||
void write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *parent);
|
||||
|
||||
|
||||
radiotap_hdr _radio;
|
||||
// present fields...
|
||||
uint64_t _tsft;
|
||||
uint16_t _channel_type, _channel_freq, _rx_flags, _signal_quality;
|
||||
uint8_t _antenna, _flags, _rate, _dbm_signal, _dbm_noise, _channel, _max_power, _db_signal;
|
||||
};
|
||||
}
|
||||
|
||||
#endif // TINS_RADIOTAP_H
|
||||
204
include/tins/rawpdu.h
Normal file
204
include/tins/rawpdu.h
Normal file
@@ -0,0 +1,204 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Matias Fontanini
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following disclaimer
|
||||
* in the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef TINS_RAWPDU_H
|
||||
#define TINS_RAWPDU_H
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include "pdu.h"
|
||||
#include "cxxstd.h"
|
||||
|
||||
namespace Tins {
|
||||
|
||||
/**
|
||||
* \class PDU
|
||||
* \brief Represents a PDU which holds raw data.
|
||||
*
|
||||
* This class is a wrapper over a byte array. It can be used to hold
|
||||
* the payload sent over transport layer protocols (such as TCP or UDP).
|
||||
*
|
||||
* While sniffing, this class is the one that will hold transport layer
|
||||
* protocols' payload. You can simply convert a RawPDU into a specific
|
||||
* application layer protocol using the RawPDU::to method:
|
||||
*
|
||||
* \code
|
||||
* // Get a RawPDU from somewhere
|
||||
* RawPDU raw = get_raw_pdu();
|
||||
*
|
||||
* // Parse it as a DHCP PDU.
|
||||
* DHCP dhcp = raw.to<DHCP>();
|
||||
*
|
||||
* // Or parse it as DNS. Of course this will fail if the contents
|
||||
* // don't look like DNS
|
||||
* DNS dns = raw.to<DNS>();
|
||||
* \endcode
|
||||
*/
|
||||
class RawPDU : public PDU {
|
||||
public:
|
||||
/**
|
||||
* The type used to store the payload.
|
||||
*/
|
||||
typedef std::vector<uint8_t> payload_type;
|
||||
|
||||
/**
|
||||
* This PDU's flag.
|
||||
*/
|
||||
static const PDU::PDUType pdu_flag = PDU::RAW;
|
||||
|
||||
/**
|
||||
* \brief Creates an instance of RawPDU.
|
||||
*
|
||||
* The payload is copied, therefore the original payload's memory
|
||||
* must be freed by the user.
|
||||
* \param pload The payload which the RawPDU will contain.
|
||||
* \param size The size of the payload.
|
||||
*/
|
||||
RawPDU(const uint8_t *pload, uint32_t size);
|
||||
|
||||
/**
|
||||
* \brief Constructs a RawPDU from an iterator range.
|
||||
*
|
||||
* The data in the iterator range is copied into the RawPDU
|
||||
* internal buffer.
|
||||
*
|
||||
* \param start The beginning of the iterator range.
|
||||
* \param end The end of the iterator range.
|
||||
*/
|
||||
template<typename ForwardIterator>
|
||||
RawPDU(ForwardIterator start, ForwardIterator end)
|
||||
: _payload(start, end) { }
|
||||
|
||||
#if TINS_IS_CXX11
|
||||
/**
|
||||
* \brief Creates an instance of RawPDU from a payload_type.
|
||||
*
|
||||
* The payload is moved into the RawPDU's internal buffer.
|
||||
*
|
||||
* \param data The payload to use.
|
||||
*/
|
||||
RawPDU(payload_type&& data)
|
||||
: _payload(move(data)) { }
|
||||
#endif // TINS_IS_CXX11
|
||||
|
||||
/**
|
||||
* \brief Creates an instance of RawPDU from an input string.
|
||||
*
|
||||
* \param data The content of the payload.
|
||||
*/
|
||||
RawPDU(const std::string &data);
|
||||
|
||||
/**
|
||||
* \brief Setter for the payload field
|
||||
* \param pload The payload to be set.
|
||||
*/
|
||||
void payload(const payload_type &pload);
|
||||
|
||||
/**
|
||||
* \brief Setter for the payload field
|
||||
* \param start The start of the new payload.
|
||||
* \param end The end of the new payload.
|
||||
*/
|
||||
template<typename ForwardIterator>
|
||||
void payload(ForwardIterator start, ForwardIterator end) {
|
||||
_payload.assign(start, end);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Const getter for the payload.
|
||||
* \return The RawPDU's payload.
|
||||
*/
|
||||
const payload_type &payload() const { return _payload; }
|
||||
|
||||
/**
|
||||
* \brief Non-const getter for the payload.
|
||||
* \return The RawPDU's payload.
|
||||
*/
|
||||
payload_type &payload() { return _payload; }
|
||||
|
||||
/**
|
||||
* \brief Returns the header size.
|
||||
*
|
||||
* This returns the same as RawPDU::payload_size().
|
||||
*
|
||||
* This metod overrides PDU::header_size. \sa PDU::header_size
|
||||
*/
|
||||
uint32_t header_size() const;
|
||||
|
||||
/**
|
||||
* \brief Returns the payload size.
|
||||
*
|
||||
* \return uint32_t containing the payload size.
|
||||
*/
|
||||
uint32_t payload_size() const {
|
||||
return _payload.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Check wether ptr points to a valid response for this PDU.
|
||||
*
|
||||
* This always returns true, since we don't know what this
|
||||
* RawPDU is holding.
|
||||
*
|
||||
* \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 Getter for the PDU's type.
|
||||
* \sa PDU::pdu_type
|
||||
*/
|
||||
PDUType pdu_type() const { return PDU::RAW; }
|
||||
|
||||
/**
|
||||
* \brief Constructs the given PDU type from the raw data stored
|
||||
* in this RawPDU.
|
||||
*/
|
||||
template<typename T>
|
||||
T to() const {
|
||||
return T(&_payload[0], _payload.size());
|
||||
}
|
||||
|
||||
/**
|
||||
* \sa PDU::clone
|
||||
*/
|
||||
RawPDU *clone() const {
|
||||
return new RawPDU(*this);
|
||||
}
|
||||
private:
|
||||
void write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *parent);
|
||||
|
||||
payload_type _payload;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
#endif // TINS_RAWPDU_H
|
||||
196
include/tins/rsn_information.h
Normal file
196
include/tins/rsn_information.h
Normal file
@@ -0,0 +1,196 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Matias Fontanini
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following disclaimer
|
||||
* in the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#if !defined(TINS_RSN_INFORMATION) && defined(HAVE_DOT11)
|
||||
#define TINS_RSN_INFORMATION
|
||||
|
||||
#include <stdint.h>
|
||||
#include <vector>
|
||||
#include "endianness.h"
|
||||
|
||||
namespace Tins{
|
||||
class Dot11;
|
||||
template<typename T, typename U>
|
||||
class PDUOption;
|
||||
/**
|
||||
* \brief Class that models the RSN information structure.
|
||||
*/
|
||||
class RSNInformation {
|
||||
public:
|
||||
/**
|
||||
* \brief Enum that represents the different cypher suites.
|
||||
*/
|
||||
enum CypherSuites {
|
||||
WEP_40 = 0x01ac0f00,
|
||||
TKIP = 0x02ac0f00,
|
||||
CCMP = 0x04ac0f00,
|
||||
WEP_104 = 0x05ac0f00
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Enum that represents the different akm suites.
|
||||
*/
|
||||
enum AKMSuites {
|
||||
PMKSA = 0x01ac0f00,
|
||||
PSK = 0x02ac0f00
|
||||
};
|
||||
|
||||
/**
|
||||
* The type used to store the cypher suites.
|
||||
*/
|
||||
typedef std::vector<CypherSuites> cyphers_type;
|
||||
|
||||
/**
|
||||
* The type used to store the AKM suites.
|
||||
*/
|
||||
typedef std::vector<AKMSuites> akm_type;
|
||||
|
||||
/**
|
||||
* The type returned on serialization.
|
||||
*/
|
||||
typedef std::vector<uint8_t> serialization_type;
|
||||
|
||||
/**
|
||||
* \brief Constructs an RSNInformation object.
|
||||
*
|
||||
* By default, the version is set to 1.
|
||||
*/
|
||||
RSNInformation();
|
||||
|
||||
/**
|
||||
* \brief Constructs an RSNInformation object from a
|
||||
* serialization_type object.
|
||||
*
|
||||
* \param buffer The buffer from which to construct this object.
|
||||
*/
|
||||
RSNInformation(const serialization_type &buffer);
|
||||
|
||||
/**
|
||||
* \brief Constructs a RSNInformation from a buffer.
|
||||
*
|
||||
* If the input is malformed, a malformed_packet exception is
|
||||
* thrown.
|
||||
*
|
||||
* \param buffer The buffer from which this object will be constructed.
|
||||
* \param total_sz The total size of the buffer.
|
||||
*/
|
||||
RSNInformation(const uint8_t *buffer, uint32_t total_sz);
|
||||
|
||||
/**
|
||||
* \brief Helper function to create a WPA2-PSK RSNInformation
|
||||
* \return An instance RSNInformation which contains information
|
||||
* for a WPA2-PSK AP.
|
||||
*/
|
||||
static RSNInformation wpa2_psk();
|
||||
|
||||
/**
|
||||
* \brief Adds a pairwise cypher suite.
|
||||
* \param cypher The pairwise cypher suite to be added.
|
||||
*/
|
||||
void add_pairwise_cypher(CypherSuites cypher);
|
||||
|
||||
/**
|
||||
* \brief Adds an akm suite.
|
||||
* \param akm The akm suite to be added.
|
||||
*/
|
||||
void add_akm_cypher(AKMSuites akm);
|
||||
|
||||
/**
|
||||
* \brief Sets the group suite cypher.
|
||||
* \param group The group suite cypher to be set.
|
||||
*/
|
||||
void group_suite(CypherSuites group);
|
||||
|
||||
/**
|
||||
* \brief Sets the version.
|
||||
* \param ver The version to be set.
|
||||
*/
|
||||
void version(uint16_t ver);
|
||||
|
||||
/**
|
||||
* \brief Sets the capabilities field.
|
||||
* \param cap The capabilities to be set.
|
||||
*/
|
||||
void capabilities(uint16_t cap);
|
||||
|
||||
/* Getters */
|
||||
|
||||
/**
|
||||
* \brief Getter for the group suite field.
|
||||
* \return The group suite field.
|
||||
*/
|
||||
CypherSuites group_suite() const { return _group_suite; }
|
||||
|
||||
/**
|
||||
* \brief Getter for the version field.
|
||||
* \return The version field.
|
||||
*/
|
||||
uint16_t version() const { return Endian::le_to_host(_version); }
|
||||
|
||||
/**
|
||||
* \brief Getter for the capabilities field.
|
||||
* \return The version field.
|
||||
*/
|
||||
uint16_t capabilities() const { return Endian::le_to_host(_capabilities); }
|
||||
|
||||
/**
|
||||
* \brief Getter for the pairwise cypher suite list.
|
||||
* \return A list of pairwise cypher suites.
|
||||
*/
|
||||
const cyphers_type &pairwise_cyphers() const { return _pairwise_cyphers; }
|
||||
|
||||
/**
|
||||
* \brief Getter for the akm suite list.
|
||||
* \return A list of akm suites.
|
||||
*/
|
||||
const akm_type &akm_cyphers() const { return _akm_cyphers; }
|
||||
|
||||
/**
|
||||
* \brief Serializes this object.
|
||||
* \return The result of the serialization.
|
||||
*/
|
||||
serialization_type serialize() const;
|
||||
|
||||
/**
|
||||
* Constructs an RSNInformation object from a Dot11 tagged option.
|
||||
*/
|
||||
static RSNInformation from_option(const PDUOption<uint8_t, Dot11> &opt);
|
||||
private:
|
||||
void init(const uint8_t *buffer, uint32_t total_sz);
|
||||
|
||||
uint16_t _version, _capabilities;
|
||||
CypherSuites _group_suite;
|
||||
akm_type _akm_cyphers;
|
||||
cyphers_type _pairwise_cyphers;
|
||||
};
|
||||
} // namespace Tins
|
||||
|
||||
#endif // TINS_RSN_INFORMATION
|
||||
181
include/tins/sll.h
Normal file
181
include/tins/sll.h
Normal file
@@ -0,0 +1,181 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Matias Fontanini
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following disclaimer
|
||||
* in the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef TINS_SLL_H
|
||||
#define TINS_SLL_H
|
||||
|
||||
#include <vector>
|
||||
#include "pdu.h"
|
||||
#include "endianness.h"
|
||||
#include "hw_address.h"
|
||||
|
||||
namespace Tins {
|
||||
/**
|
||||
* \class SLL
|
||||
* \brief Represents a Linux cooked-mode capture (SLL) PDU.
|
||||
*/
|
||||
class SLL : public PDU {
|
||||
public:
|
||||
/**
|
||||
* This PDU's flag.
|
||||
*/
|
||||
static const PDU::PDUType pdu_flag = PDU::SLL;
|
||||
|
||||
/**
|
||||
* The type of the address type
|
||||
*/
|
||||
typedef HWAddress<8> address_type;
|
||||
|
||||
/**
|
||||
* Default constructor
|
||||
*/
|
||||
SLL();
|
||||
|
||||
/**
|
||||
* \brief Constructs a SLL object from a buffer and adds all
|
||||
* identifiable PDUs found in the buffer as children of this one.
|
||||
*
|
||||
* If the next PDU is not recognized, then a RawPDU is used.
|
||||
*
|
||||
* If there is not enough size for a SLL header in the
|
||||
* buffer, 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.
|
||||
*/
|
||||
SLL(const uint8_t *buffer, uint32_t total_sz);
|
||||
|
||||
// Getters
|
||||
|
||||
/**
|
||||
* \brief Getter for the Packet Type field.
|
||||
* \return The stored Packet Type field value.
|
||||
*/
|
||||
uint16_t packet_type() const {
|
||||
return Endian::be_to_host(_header.packet_type);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the LLADDR Type field.
|
||||
* \return The stored LLADDR Type field value.
|
||||
*/
|
||||
uint16_t lladdr_type() const {
|
||||
return Endian::be_to_host(_header.lladdr_type);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the LLADDR Length field.
|
||||
* \return The stored LLADDR Length field value.
|
||||
*/
|
||||
uint16_t lladdr_len() const {
|
||||
return Endian::be_to_host(_header.lladdr_len);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the Address field.
|
||||
* \return The stored Address field value.
|
||||
*/
|
||||
address_type address() const {
|
||||
return _header.address;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the Protocol field.
|
||||
* \return The stored Protocol field value.
|
||||
*/
|
||||
uint16_t protocol() const {
|
||||
return Endian::be_to_host(_header.protocol);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the PDU's type.
|
||||
* \sa PDU::pdu_type
|
||||
*/
|
||||
PDUType pdu_type() const { return pdu_flag; }
|
||||
|
||||
// Setters
|
||||
|
||||
/**
|
||||
* \brief Setter for the Packet Type field.
|
||||
* \param new_packet_type The new Packet Type field value.
|
||||
*/
|
||||
void packet_type(uint16_t new_packet_type);
|
||||
|
||||
/**
|
||||
* \brief Setter for the LLADDR Type field.
|
||||
* \param new_lladdr_type The new LLADDR Type field value.
|
||||
*/
|
||||
void lladdr_type(uint16_t new_lladdr_type);
|
||||
|
||||
/**
|
||||
* \brief Setter for the LLADDR Length field.
|
||||
* \param new_lladdr_len The new LLADDR Length field value.
|
||||
*/
|
||||
void lladdr_len(uint16_t new_lladdr_len);
|
||||
|
||||
/**
|
||||
* \brief Setter for the Address field.
|
||||
* \param new_address The new Address field value.
|
||||
*/
|
||||
void address(const address_type &new_address);
|
||||
|
||||
/**
|
||||
* \brief Setter for the Protocol field.
|
||||
* \param new_protocol The new Protocol field value.
|
||||
*/
|
||||
void protocol(uint16_t new_protocol);
|
||||
|
||||
/**
|
||||
* \brief Returns the header size.
|
||||
*
|
||||
* This metod overrides PDU::header_size. \sa PDU::header_size
|
||||
*/
|
||||
uint32_t header_size() const;
|
||||
|
||||
/**
|
||||
* \sa PDU::clone
|
||||
*/
|
||||
SLL *clone() const {
|
||||
return new SLL(*this);
|
||||
}
|
||||
private:
|
||||
TINS_BEGIN_PACK
|
||||
struct sllhdr {
|
||||
uint16_t packet_type, lladdr_type, lladdr_len;
|
||||
uint8_t address[8];
|
||||
uint16_t protocol;
|
||||
} TINS_END_PACK;
|
||||
|
||||
void write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *);
|
||||
|
||||
sllhdr _header;
|
||||
};
|
||||
}
|
||||
|
||||
#endif // TINS_SLL_H
|
||||
131
include/tins/small_uint.h
Normal file
131
include/tins/small_uint.h
Normal file
@@ -0,0 +1,131 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Matias Fontanini
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following disclaimer
|
||||
* in the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef TINS_SMALL_UINT_H
|
||||
#define TINS_SMALL_UINT_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdexcept>
|
||||
|
||||
namespace Tins {
|
||||
class value_too_large : public std::exception {
|
||||
public:
|
||||
const char *what() const throw() {
|
||||
return "Value is too large";
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* \class small_uint
|
||||
* \brief Represents a field of <i>n</i> bits.
|
||||
*
|
||||
* This finds the best integral type of at least <i>n</i> bits and
|
||||
* uses it to store the wrapped value.
|
||||
*/
|
||||
template<size_t n>
|
||||
class small_uint {
|
||||
private:
|
||||
template<bool cond, typename OnTrue, typename OnFalse>
|
||||
struct if_then_else {
|
||||
typedef OnTrue type;
|
||||
};
|
||||
|
||||
template<typename OnTrue, typename OnFalse>
|
||||
struct if_then_else<false, OnTrue, OnFalse> {
|
||||
typedef OnFalse type;
|
||||
};
|
||||
|
||||
template<size_t i>
|
||||
struct best_type {
|
||||
typedef typename if_then_else<
|
||||
(i <= 8),
|
||||
uint8_t,
|
||||
typename if_then_else<
|
||||
(i <= 16),
|
||||
uint16_t,
|
||||
typename if_then_else<
|
||||
(i <= 32),
|
||||
uint32_t,
|
||||
uint64_t
|
||||
>::type
|
||||
>::type
|
||||
>::type type;
|
||||
};
|
||||
|
||||
template<uint64_t base, uint64_t pow>
|
||||
struct power {
|
||||
static const uint64_t value = base * power<base, pow - 1>::value;
|
||||
};
|
||||
|
||||
template<uint64_t base>
|
||||
struct power<base, 0> {
|
||||
static const uint64_t value = 1;
|
||||
};
|
||||
public:
|
||||
/**
|
||||
* The type used to store the value.
|
||||
*/
|
||||
typedef typename best_type<n>::type repr_type;
|
||||
|
||||
/**
|
||||
* The maximum value this class can hold.
|
||||
*/
|
||||
static const repr_type max_value = power<2, n>::value - 1;
|
||||
|
||||
/**
|
||||
* Value initializes the value.
|
||||
*/
|
||||
small_uint() : value() {}
|
||||
|
||||
/**
|
||||
* \brief Copy constructs the stored value.
|
||||
*
|
||||
* This throws a value_too_large exception if the value provided
|
||||
* is larger than max_value.
|
||||
*
|
||||
* \param val The parameter from which to copy construct.
|
||||
*/
|
||||
small_uint(repr_type val) {
|
||||
if(val > max_value)
|
||||
throw value_too_large();
|
||||
value = val;
|
||||
}
|
||||
|
||||
/**
|
||||
* User defined conversion to repr_type.
|
||||
*/
|
||||
operator repr_type() const {
|
||||
return value;
|
||||
}
|
||||
private:
|
||||
repr_type value;
|
||||
};
|
||||
|
||||
} // namespace Tins
|
||||
#endif // TINS_SMALL_UINT_H
|
||||
178
include/tins/snap.h
Normal file
178
include/tins/snap.h
Normal file
@@ -0,0 +1,178 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Matias Fontanini
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following disclaimer
|
||||
* in the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef TINS_SNAP_H
|
||||
#define TINS_SNAP_H
|
||||
|
||||
|
||||
#include <stdint.h>
|
||||
#include "pdu.h"
|
||||
#include "macros.h"
|
||||
#include "endianness.h"
|
||||
#include "small_uint.h"
|
||||
|
||||
namespace Tins {
|
||||
|
||||
/**
|
||||
* \class SNAP
|
||||
* \brief Represents a SNAP frame.
|
||||
*
|
||||
* Note that this PDU contains the 802.3 LLC structure + SNAP frame.
|
||||
* So far only unnumbered information structure is supported.
|
||||
*/
|
||||
class SNAP : public PDU {
|
||||
public:
|
||||
/**
|
||||
* \brief This PDU's flag.
|
||||
*/
|
||||
static const PDU::PDUType pdu_flag = PDU::SNAP;
|
||||
|
||||
/**
|
||||
* \brief Creates an instance of SNAP
|
||||
* This constructor sets the dsap and ssap fields to 0xaa, and
|
||||
* the id field to 3.
|
||||
*/
|
||||
SNAP();
|
||||
|
||||
/**
|
||||
* \brief Constructs a SNAP object from a buffer and adds all
|
||||
* identifiable PDUs found in the buffer as children of this one.
|
||||
*
|
||||
* If the next PDU is not recognized, then a RawPDU is used.
|
||||
*
|
||||
* If there is not enough size for a SNAP header in the
|
||||
* buffer, 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.
|
||||
*/
|
||||
SNAP(const uint8_t *buffer, uint32_t total_sz);
|
||||
|
||||
/* Setters */
|
||||
|
||||
/**
|
||||
* \brief Setter for the Control field.
|
||||
* \param new_id The new Control to be set.
|
||||
*/
|
||||
void control(uint8_t new_control);
|
||||
|
||||
/**
|
||||
* \brief Setter for the Organization Code field.
|
||||
* \param new_org The new Organization Code to be set.
|
||||
*/
|
||||
void org_code(small_uint<24> new_org);
|
||||
|
||||
/**
|
||||
* \brief Setter for the Ethernet Type field.
|
||||
* \param new_eth The new Ethernet Type to be set.
|
||||
*/
|
||||
void eth_type(uint16_t new_eth);
|
||||
|
||||
/* Getters */
|
||||
|
||||
/**
|
||||
* \brief Getter for the DSAP field.
|
||||
* \return The DSAP field.
|
||||
*/
|
||||
uint8_t dsap() const { return _snap.dsap; }
|
||||
|
||||
/**
|
||||
* \brief Getter for the SSAP field.
|
||||
* \return The SSAP field.
|
||||
*/
|
||||
uint8_t ssap() const { return _snap.ssap; }
|
||||
|
||||
/**
|
||||
* \brief Getter for the Control field.
|
||||
* \return The Control field.
|
||||
*/
|
||||
uint8_t control() const {
|
||||
#if TINS_IS_LITTLE_ENDIAN
|
||||
return (_snap.control_org) & 0xff;
|
||||
#else
|
||||
return (_snap.control_org >> 24) & 0xff;
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the Organization Code field.
|
||||
* \return The Organization Code field.
|
||||
*/
|
||||
small_uint<24> org_code() const {
|
||||
#if TINS_IS_LITTLE_ENDIAN
|
||||
return Endian::be_to_host<uint32_t>(_snap.control_org & 0xffffff00);
|
||||
#else
|
||||
return _snap.control_org & 0xffffff;
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the Ethernet Type field.
|
||||
* \return The Ethernet Type field.
|
||||
*/
|
||||
uint16_t eth_type() const { return Endian::be_to_host(_snap.eth_type); }
|
||||
|
||||
/**
|
||||
* \brief Returns the SNAP frame's header length.
|
||||
*
|
||||
* \return 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_flag; }
|
||||
|
||||
/**
|
||||
* \brief Clones this PDU.
|
||||
*
|
||||
* \sa PDU::clone
|
||||
*/
|
||||
SNAP *clone() const {
|
||||
return new SNAP(*this);
|
||||
}
|
||||
private:
|
||||
TINS_BEGIN_PACK
|
||||
struct snaphdr {
|
||||
uint8_t dsap;
|
||||
uint8_t ssap;
|
||||
uint32_t control_org;
|
||||
uint16_t eth_type;
|
||||
} TINS_END_PACK;
|
||||
|
||||
void write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *parent);
|
||||
|
||||
snaphdr _snap;
|
||||
};
|
||||
}
|
||||
|
||||
#endif // TINS_SNAP_H
|
||||
592
include/tins/sniffer.h
Normal file
592
include/tins/sniffer.h
Normal file
@@ -0,0 +1,592 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Matias Fontanini
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following disclaimer
|
||||
* in the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#ifndef TINS_SNIFFER_H
|
||||
#define TINS_SNIFFER_H
|
||||
|
||||
|
||||
#include <pcap.h>
|
||||
#include <string>
|
||||
#include <memory>
|
||||
#include <stdexcept>
|
||||
#include <iterator>
|
||||
#include "pdu.h"
|
||||
#include "packet.h"
|
||||
#include "cxxstd.h"
|
||||
#include "exceptions.h"
|
||||
#include "internals.h"
|
||||
|
||||
namespace Tins {
|
||||
class SnifferIterator;
|
||||
class SnifferConfiguration;
|
||||
|
||||
/**
|
||||
* \class BaseSniffer
|
||||
* \brief Base class for sniffers.
|
||||
*
|
||||
* This class implements the basic sniffing operations. Subclasses
|
||||
* should only initialize this object using a pcap_t pointer, which
|
||||
* will be used to extract packets.
|
||||
*
|
||||
* Initialization must be done using the BaseSniffer::init method.
|
||||
*/
|
||||
class BaseSniffer {
|
||||
public:
|
||||
/**
|
||||
* The iterator type.
|
||||
*/
|
||||
typedef SnifferIterator iterator;
|
||||
|
||||
#if TINS_IS_CXX11
|
||||
/**
|
||||
* \brief Move constructor.
|
||||
* This constructor is available only in C++11.
|
||||
*/
|
||||
BaseSniffer(BaseSniffer &&rhs) TINS_NOEXCEPT
|
||||
: handle(nullptr), mask()
|
||||
{
|
||||
*this = std::move(rhs);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Move assignment operator.
|
||||
* This operator is available only in C++11.
|
||||
*/
|
||||
BaseSniffer& operator=(BaseSniffer &&rhs) TINS_NOEXCEPT
|
||||
{
|
||||
using std::swap;
|
||||
swap(handle, rhs.handle);
|
||||
swap(mask, rhs.mask);
|
||||
return *this;
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* \brief Sniffer destructor.
|
||||
* This frees all memory used by the pcap handle.
|
||||
*/
|
||||
virtual ~BaseSniffer();
|
||||
|
||||
/**
|
||||
* \brief Compiles a filter and uses it to capture one packet.
|
||||
*
|
||||
* This method returns the first valid sniffed packet that matches the
|
||||
* sniffer's filter, or the first sniffed packet if no filter has
|
||||
* been set.
|
||||
*
|
||||
* The return type is a thin wrapper over a PDU* and a Timestamp
|
||||
* object. This wrapper can be both implicitly converted to a
|
||||
* PDU* and a Packet object. So doing this:
|
||||
*
|
||||
* \code
|
||||
* Sniffer s(...);
|
||||
* std::unique_ptr<PDU> pdu(s.next_packet());
|
||||
* // Packet takes care of the PDU*.
|
||||
* Packet packet(s.next_packet());
|
||||
* \endcode
|
||||
*
|
||||
* Is fine, but this:
|
||||
*
|
||||
* \code
|
||||
* // bad!!
|
||||
* PtrPacket p = s.next_packet();
|
||||
* \endcode
|
||||
*
|
||||
* Is not, since PtrPacket can't be copy constructed.
|
||||
*
|
||||
* \sa Packet::release_pdu
|
||||
*
|
||||
* \return A captured packet. If an error occured, PtrPacket::pdu
|
||||
* will return 0. Caller takes ownership of the PDU pointer stored in
|
||||
* the PtrPacket.
|
||||
*/
|
||||
PtrPacket next_packet();
|
||||
|
||||
/**
|
||||
* \brief Starts a sniffing loop, using a callback functor for every
|
||||
* sniffed packet.
|
||||
*
|
||||
* The functor must implement an operator with one of the
|
||||
* following signatures:
|
||||
*
|
||||
* \code
|
||||
* bool(PDU&);
|
||||
* bool(const PDU&);
|
||||
* \endcode
|
||||
*
|
||||
* This functor will be called using the each of the sniffed packets
|
||||
* as its argument. Using PDU member functions that modify the PDU,
|
||||
* such as PDU::release_inner_pdu, is perfectly valid.
|
||||
*
|
||||
* Note that if you're using a functor object, it will be copied using
|
||||
* its copy constructor, so it should be some kind of proxy to
|
||||
* another object which will process the packets(e.g. std::bind).
|
||||
*
|
||||
* Sniffing will stop when either max_packets are sniffed(if it is != 0),
|
||||
* or when the functor returns false.
|
||||
*
|
||||
* This method catches both malformed_packet and pdu_not_found exceptions,
|
||||
* which allows writing much cleaner code, since you can call PDU::rfind_pdu
|
||||
* without worrying about catching the exception that can be thrown. This
|
||||
* allows writing code such as the following:
|
||||
*
|
||||
* \code
|
||||
* bool callback(const PDU& pdu) {
|
||||
* // If either RawPDU is not found, or construction of the DNS
|
||||
* // object fails, the BaseSniffer object will trap the exceptions,
|
||||
* // so we don't need to worry about it.
|
||||
* DNS dns = pdu.rfind_pdu<RawPDU>().to<DNS>();
|
||||
* return true;
|
||||
* }
|
||||
* \endcode
|
||||
*
|
||||
* \param function The callback handler object which should process packets.
|
||||
* \param max_packets The maximum amount of packets to sniff. 0 == infinite.
|
||||
*/
|
||||
template<class Functor>
|
||||
void sniff_loop(Functor function, uint32_t max_packets = 0);
|
||||
|
||||
/**
|
||||
* \brief Sets a filter on this sniffer.
|
||||
* \param filter The filter to be set.
|
||||
* \return True iif it was possible to apply the filter.
|
||||
*/
|
||||
bool set_filter(const std::string &filter);
|
||||
|
||||
/**
|
||||
* \brief Stops sniffing loops.
|
||||
*
|
||||
* This method must be called from the same thread from which
|
||||
* BaseSniffer::sniff_loop was called.
|
||||
*/
|
||||
void stop_sniff();
|
||||
|
||||
/**
|
||||
* \brief Gets the file descriptor associated with the sniffer.
|
||||
*/
|
||||
int get_fd();
|
||||
|
||||
/**
|
||||
* \brief Sets the read timeout for this sniffer.
|
||||
*
|
||||
* This calls pcap_set_timeout using the provided parameter.
|
||||
* \param ms The amount of milliseconds.
|
||||
*/
|
||||
void set_timeout(int ms);
|
||||
|
||||
/**
|
||||
* \brief Sets whether to extract RawPDUs or fully parsed packets.
|
||||
*
|
||||
* By default, packets will be parsed starting from link layer.
|
||||
* However, if you're parsing a lot of traffic, then you might
|
||||
* want to extract packets and push them into a queue,
|
||||
* so a consumer can parse them when they're popped.
|
||||
*
|
||||
* This method allows doing that. If the parameter is true,
|
||||
* then packets taken from this BaseSniffer will only contain
|
||||
* a RawPDU which will have to entire contents of the packet.
|
||||
*
|
||||
* \param value Whether to extract RawPDUs or not.
|
||||
*/
|
||||
void set_extract_raw_pdus(bool value);
|
||||
|
||||
/**
|
||||
* \brief Retrieves this sniffer's link type.
|
||||
*
|
||||
* This calls pcap_datalink on the stored pcap handle and
|
||||
* returns its result.
|
||||
*/
|
||||
int link_type() const;
|
||||
|
||||
/**
|
||||
* Retrieves an iterator to the next packet in this sniffer.
|
||||
*/
|
||||
iterator begin();
|
||||
|
||||
/**
|
||||
* Retrieves an end iterator.
|
||||
*/
|
||||
iterator end();
|
||||
|
||||
/**
|
||||
* Retrieves the pcap handle used by this sniffer.
|
||||
*/
|
||||
pcap_t* get_pcap_handle();
|
||||
|
||||
/**
|
||||
* Retrieves the pcap handle used by this sniffer.
|
||||
*/
|
||||
const pcap_t* get_pcap_handle() const;
|
||||
protected:
|
||||
/**
|
||||
* Default constructor.
|
||||
*/
|
||||
BaseSniffer();
|
||||
|
||||
void set_pcap_handle(pcap_t* const pcap_handle);
|
||||
|
||||
void set_if_mask(bpf_u_int32 if_mask);
|
||||
|
||||
bpf_u_int32 get_if_mask() const;
|
||||
private:
|
||||
BaseSniffer(const BaseSniffer&);
|
||||
BaseSniffer &operator=(const BaseSniffer&);
|
||||
|
||||
pcap_t *handle;
|
||||
bpf_u_int32 mask;
|
||||
bool extract_raw;
|
||||
};
|
||||
|
||||
/**
|
||||
* \class Sniffer
|
||||
* \brief Sniffs packets from a network interface.
|
||||
*/
|
||||
class Sniffer : public BaseSniffer {
|
||||
public:
|
||||
/**
|
||||
* \deprecated This enum is no longer necessary. You should use the
|
||||
* Sniffer(const std::string&, const SnifferConfiguration&) constructor.
|
||||
*/
|
||||
enum promisc_type {
|
||||
NON_PROMISC,
|
||||
PROMISC
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Constructs an instance of Sniffer using the provided configuration.
|
||||
*
|
||||
* This constructor was added as a way to improve the parameter bloat
|
||||
* introduced by the other ones available. You should create an instance
|
||||
* of SnifferConfiguration, set the desired parameters, and then use it
|
||||
* when constructing a Sniffer object.
|
||||
*
|
||||
* \sa SnifferConfiguration
|
||||
*
|
||||
* \param device The device which will be sniffed.
|
||||
* \param configuration The configuration object to use to setup the sniffer.
|
||||
*/
|
||||
Sniffer(const std::string &device, const SnifferConfiguration& configuration);
|
||||
|
||||
/**
|
||||
* \brief Constructs an instance of Sniffer.
|
||||
*
|
||||
* By default the interface won't be put into promiscuous mode, and won't
|
||||
* be put into monitor mode.
|
||||
*
|
||||
* \deprecated Use the Sniffer(const std::string&, const SnifferConfiguration&)
|
||||
* constructor.
|
||||
* \param device The device which will be sniffed.
|
||||
* \param max_packet_size The maximum packet size to be read.
|
||||
* \param promisc bool indicating wether to put the interface in promiscuous mode.(optional)
|
||||
* \param filter A capture filter to be used on the sniffing session.(optional);
|
||||
* \param rfmon Indicates if the interface should be put in monitor mode.(optional);
|
||||
*/
|
||||
Sniffer(const std::string &device, unsigned max_packet_size,
|
||||
bool promisc = false, const std::string &filter = "", bool rfmon = false);
|
||||
|
||||
/**
|
||||
* \brief Constructs an instance of Sniffer.
|
||||
*
|
||||
* The maximum capture size is set to 65535. By default the interface won't
|
||||
* be put into promiscuous mode, and won't be put into monitor mode.
|
||||
*
|
||||
* \deprecated Use the Sniffer(const std::string&, const SnifferConfiguration&)
|
||||
* constructor.
|
||||
* \param device The device which will be sniffed.
|
||||
* \param promisc Indicates if the interface should be put in promiscuous mode.
|
||||
* \param filter A capture filter to be used on the sniffing session.(optional);
|
||||
* \param rfmon Indicates if the interface should be put in monitor mode.(optional);
|
||||
*/
|
||||
Sniffer(const std::string &device, promisc_type promisc = NON_PROMISC,
|
||||
const std::string &filter = "", bool rfmon = false);
|
||||
|
||||
private:
|
||||
friend class SnifferConfiguration;
|
||||
|
||||
void set_snap_len(unsigned snap_len);
|
||||
|
||||
void set_buffer_size(unsigned buffer_size);
|
||||
|
||||
void set_promisc_mode(bool promisc_enabled);
|
||||
|
||||
void set_rfmon(bool rfmon_enabled);
|
||||
};
|
||||
|
||||
/**
|
||||
* \class FileSniffer
|
||||
* \brief Reads pcap files and interprets the packets in it.
|
||||
*
|
||||
* This class acts exactly in the same way that Sniffer, but reads
|
||||
* packets from a pcap file instead of an interface.
|
||||
*/
|
||||
class FileSniffer : public BaseSniffer {
|
||||
public:
|
||||
/**
|
||||
* \brief Constructs an instance of FileSniffer.
|
||||
* \param file_name The pcap file which will be parsed.
|
||||
* \param filter A capture filter to be used on the file.(optional);
|
||||
*/
|
||||
FileSniffer(const std::string &file_name, const SnifferConfiguration& configuration);
|
||||
|
||||
/**
|
||||
* \deprecated Use the constructor that takes a SnifferConfiguration instead.
|
||||
*
|
||||
* \brief Constructs an instance of FileSniffer.
|
||||
* \param file_name The pcap file which will be parsed.
|
||||
* \param filter A capture filter to be used on the file.(optional);
|
||||
*/
|
||||
FileSniffer(const std::string &file_name, const std::string &filter = "");
|
||||
};
|
||||
|
||||
template<class T>
|
||||
class HandlerProxy {
|
||||
public:
|
||||
typedef T* ptr_type;
|
||||
typedef bool (T::*fun_type)(PDU&) ;
|
||||
|
||||
HandlerProxy(ptr_type ptr, fun_type function)
|
||||
: object(ptr), fun(function) {}
|
||||
|
||||
bool operator()(PDU &pdu) {
|
||||
return (object->*fun)(pdu);
|
||||
}
|
||||
private:
|
||||
ptr_type object;
|
||||
fun_type fun;
|
||||
};
|
||||
|
||||
template<class T>
|
||||
HandlerProxy<T> make_sniffer_handler(T *ptr, typename HandlerProxy<T>::fun_type function)
|
||||
{
|
||||
return HandlerProxy<T>(ptr, function);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Iterates over packets sniffed by a BaseSniffer.
|
||||
*/
|
||||
class SnifferIterator : public std::iterator<std::forward_iterator_tag, PDU> {
|
||||
public:
|
||||
/**
|
||||
* Constructs a SnifferIterator.
|
||||
* \param sniffer The sniffer to iterate.
|
||||
*/
|
||||
SnifferIterator(BaseSniffer *sniffer = 0)
|
||||
: sniffer(sniffer)
|
||||
{
|
||||
if(sniffer)
|
||||
advance();
|
||||
}
|
||||
|
||||
/**
|
||||
* Advances the iterator.
|
||||
*/
|
||||
SnifferIterator& operator++() {
|
||||
advance();
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Advances the iterator.
|
||||
*/
|
||||
SnifferIterator operator++(int) {
|
||||
SnifferIterator other(*this);
|
||||
advance();
|
||||
return other;
|
||||
}
|
||||
|
||||
/**
|
||||
* Dereferences the iterator.
|
||||
* \return reference to the current packet.
|
||||
*/
|
||||
PDU &operator*() {
|
||||
return *pkt.pdu();
|
||||
}
|
||||
|
||||
/**
|
||||
* Dereferences the iterator.
|
||||
* \return pointer to the current packet.
|
||||
*/
|
||||
PDU *operator->() {
|
||||
return &(**this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Compares this iterator for equality.
|
||||
* \param rhs The iterator to be compared to.
|
||||
*/
|
||||
bool operator==(const SnifferIterator &rhs) const {
|
||||
return sniffer == rhs.sniffer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compares this iterator for in-equality.
|
||||
* \param rhs The iterator to be compared to.
|
||||
*/
|
||||
bool operator!=(const SnifferIterator &rhs) const {
|
||||
return !(*this == rhs);
|
||||
}
|
||||
private:
|
||||
void advance() {
|
||||
pkt = sniffer->next_packet();
|
||||
if(!pkt)
|
||||
sniffer = 0;
|
||||
}
|
||||
|
||||
BaseSniffer *sniffer;
|
||||
Packet pkt;
|
||||
};
|
||||
|
||||
/**
|
||||
* \class SnifferConfiguration
|
||||
* \brief Represents the configuration of a BaseSniffer object.
|
||||
*
|
||||
* This class can be used as an easy way to configure a Sniffer
|
||||
* or FileSniffer object.
|
||||
*
|
||||
* It can be used by constructing an object of this type,
|
||||
* setting the desired values and then passing it to the
|
||||
* Sniffer or FileSniffer object's constructor. This sets
|
||||
* default values for some attributes:
|
||||
*
|
||||
* - Snapshot length: 65535 bytes (64 KB).
|
||||
* - Timeout: 1000 milliseconds.
|
||||
* - Promiscuous mode: false.
|
||||
*
|
||||
* For any of the attributes not listed above, the associated
|
||||
* pcap function which is used to set them on a pcap handle
|
||||
* won't be called at all.
|
||||
*
|
||||
* This class can be used to configure a Sniffer object,
|
||||
* like this:
|
||||
*
|
||||
* \code
|
||||
* // Initialize the configuration.
|
||||
* SnifferConfiguration config;
|
||||
* config.set_filter("ip and port 80");
|
||||
* config.set_promisc_mode(true);
|
||||
*
|
||||
* // Use it on a Sniffer object.
|
||||
* Sniffer sniffer("eth0", config);
|
||||
* \endcode
|
||||
*/
|
||||
class SnifferConfiguration {
|
||||
public:
|
||||
/**
|
||||
* \brief The default snapshot length.
|
||||
*
|
||||
* This is 65535 by default.
|
||||
*/
|
||||
static const unsigned DEFAULT_SNAP_LEN;
|
||||
|
||||
/**
|
||||
* \brief The default timeout.
|
||||
*
|
||||
* This is 1000 by default.
|
||||
*/
|
||||
static const unsigned DEFAULT_TIMEOUT;
|
||||
|
||||
/**
|
||||
* Default constructs a SnifferConfiguration.
|
||||
*/
|
||||
SnifferConfiguration();
|
||||
|
||||
/**
|
||||
* Sets the snapshot length option.
|
||||
* \param snap_len The snapshot length to be set.
|
||||
*/
|
||||
void set_snap_len(unsigned snap_len);
|
||||
|
||||
/**
|
||||
* Sets the buffer size option.
|
||||
* \param buffer_size The buffer size to be set.
|
||||
*/
|
||||
void set_buffer_size(unsigned buffer_size);
|
||||
|
||||
/**
|
||||
* Sets the promiscuous mode option.
|
||||
* \param enabled The promiscuous mode value.
|
||||
*/
|
||||
void set_promisc_mode(bool enabled);
|
||||
|
||||
/**
|
||||
* Sets a pcap filter to use on the sniffer.
|
||||
* \param filter The pcap filter to be used.
|
||||
*/
|
||||
void set_filter(const std::string& filter);
|
||||
|
||||
/**
|
||||
* Sets the rfmon option.
|
||||
* \param enabled The rfmon option value.
|
||||
*/
|
||||
void set_rfmon(bool enabled);
|
||||
|
||||
/**
|
||||
* Sets the timeout option.
|
||||
* \param timeout The timeout to be set.
|
||||
*/
|
||||
void set_timeout(unsigned timeout);
|
||||
protected:
|
||||
friend class Sniffer;
|
||||
friend class FileSniffer;
|
||||
|
||||
void configure_sniffer_pre_activation(Sniffer& sniffer) const;
|
||||
void configure_sniffer_pre_activation(FileSniffer& sniffer) const;
|
||||
|
||||
void configure_sniffer_post_activation(Sniffer& sniffer) const;
|
||||
|
||||
unsigned _snap_len;
|
||||
bool _has_buffer_size;
|
||||
unsigned _buffer_size;
|
||||
bool _has_promisc;
|
||||
bool _promisc;
|
||||
bool _has_rfmon;
|
||||
bool _rfmon;
|
||||
bool _has_filter;
|
||||
std::string _filter;
|
||||
unsigned _timeout;
|
||||
};
|
||||
|
||||
template<class Functor>
|
||||
void Tins::BaseSniffer::sniff_loop(Functor function, uint32_t max_packets) {
|
||||
for(iterator it = begin(); it != end(); ++it) {
|
||||
try {
|
||||
// If the functor returns false, we're done
|
||||
if(!function(*it))
|
||||
return;
|
||||
}
|
||||
catch(malformed_packet&) { }
|
||||
catch(pdu_not_found&) { }
|
||||
if(max_packets && --max_packets == 0)
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif // TINS_SNIFFER_H
|
||||
311
include/tins/stp.h
Normal file
311
include/tins/stp.h
Normal file
@@ -0,0 +1,311 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Matias Fontanini
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following disclaimer
|
||||
* in the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef TINS_STP_H
|
||||
#define TINS_STP_H
|
||||
|
||||
#include "pdu.h"
|
||||
#include "endianness.h"
|
||||
#include "hw_address.h"
|
||||
#include "small_uint.h"
|
||||
|
||||
namespace Tins {
|
||||
/**
|
||||
* \class STP
|
||||
* \brief Represents a Spanning Tree Protocol PDU.
|
||||
*/
|
||||
class STP : public PDU {
|
||||
public:
|
||||
/**
|
||||
* This PDU's flag.
|
||||
*/
|
||||
static const PDU::PDUType pdu_flag = PDU::STP;
|
||||
|
||||
/**
|
||||
* The type used to store BPDU identifier addresses.
|
||||
*/
|
||||
typedef HWAddress<6> address_type;
|
||||
|
||||
/**
|
||||
* The type used to store the BPDU identifiers.
|
||||
*/
|
||||
struct bpdu_id_type {
|
||||
small_uint<4> priority;
|
||||
small_uint<12> ext_id;
|
||||
address_type id;
|
||||
|
||||
bpdu_id_type(small_uint<4> priority=0, small_uint<12> ext_id=0,
|
||||
const address_type& id=address_type())
|
||||
: priority(priority), ext_id(ext_id), id(id) { }
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Default constructor.
|
||||
*/
|
||||
STP();
|
||||
|
||||
/**
|
||||
* \brief Constructs a STP object from a buffer.
|
||||
*
|
||||
* If there is not enough size for a STP 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.
|
||||
*/
|
||||
STP(const uint8_t *buffer, uint32_t total_sz);
|
||||
|
||||
// Getters
|
||||
|
||||
/**
|
||||
* \brief Getter for the Protocol ID field.
|
||||
* \return The stored Protocol ID field value.
|
||||
*/
|
||||
uint16_t proto_id() const {
|
||||
return Endian::be_to_host(_header.proto_id);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the Protocol Version field.
|
||||
* \return The stored Protocol Version field value.
|
||||
*/
|
||||
uint8_t proto_version() const {
|
||||
return _header.proto_version;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the BDU Type field.
|
||||
* \return The stored BDU Type field value.
|
||||
*/
|
||||
uint8_t bpdu_type() const {
|
||||
return _header.bpdu_type;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the BDU Flags field.
|
||||
* \return The stored BDU Flags field value.
|
||||
*/
|
||||
uint8_t bpdu_flags() const {
|
||||
return _header.bpdu_flags;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the Root Path Cost field.
|
||||
* \return The stored Root Path Cost field value.
|
||||
*/
|
||||
uint32_t root_path_cost() const {
|
||||
return Endian::be_to_host(_header.root_path_cost);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the Port ID field.
|
||||
* \return The stored Port ID field value.
|
||||
*/
|
||||
uint16_t port_id() const {
|
||||
return Endian::be_to_host(_header.port_id);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the Message Age field.
|
||||
* \return The stored Message Age field value.
|
||||
*/
|
||||
uint16_t msg_age() const {
|
||||
return Endian::be_to_host(_header.msg_age) / 256;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the Maximum Age field.
|
||||
* \return The stored Maximum Age field value.
|
||||
*/
|
||||
uint16_t max_age() const {
|
||||
return Endian::be_to_host(_header.max_age) / 256;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the Hello Time field.
|
||||
* \return The stored Hello Time field value.
|
||||
*/
|
||||
uint16_t hello_time() const {
|
||||
return Endian::be_to_host(_header.hello_time) / 256;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the Forward Delay field.
|
||||
* \return The stored Forward Delay field value.
|
||||
*/
|
||||
uint16_t fwd_delay() const {
|
||||
return Endian::be_to_host(_header.fwd_delay) / 256;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the Root ID field.
|
||||
* \return The stored Root ID field value.
|
||||
*/
|
||||
bpdu_id_type root_id() const;
|
||||
|
||||
/**
|
||||
* \brief Getter for the Bridge ID field.
|
||||
* \return The stored Bridge ID field value.
|
||||
*/
|
||||
bpdu_id_type bridge_id() const;
|
||||
|
||||
/**
|
||||
* \brief Getter for the PDU's type.
|
||||
* \sa PDU::pdu_type
|
||||
*/
|
||||
PDUType pdu_type() const { return pdu_flag; }
|
||||
|
||||
/**
|
||||
* \sa PDU::clone
|
||||
*/
|
||||
STP *clone() const {
|
||||
return new STP(*this);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Returns the header size.
|
||||
*
|
||||
* This metod overrides PDU::header_size. \sa PDU::header_size
|
||||
*/
|
||||
uint32_t header_size() const;
|
||||
|
||||
// Setters
|
||||
|
||||
/**
|
||||
* \brief Setter for the Protocol ID field.
|
||||
* \param new_proto_id The new Protocol ID field value.
|
||||
*/
|
||||
void proto_id(uint16_t new_proto_id);
|
||||
|
||||
/**
|
||||
* \brief Setter for the Protocol Version field.
|
||||
* \param new_proto_version The new Protocol Version field value.
|
||||
*/
|
||||
void proto_version(uint8_t new_proto_version);
|
||||
|
||||
/**
|
||||
* \brief Setter for the BPDU Type field.
|
||||
* \param new_bpdu_type The new BPDU Type field value.
|
||||
*/
|
||||
void bpdu_type(uint8_t new_bpdu_type);
|
||||
|
||||
/**
|
||||
* \brief Setter for the BPDU Flags field.
|
||||
* \param new_bpdu_flags The new BPDU Flags field value.
|
||||
*/
|
||||
void bpdu_flags(uint8_t new_bpdu_flags);
|
||||
|
||||
/**
|
||||
* \brief Setter for the Root Path Cost field.
|
||||
* \param new_root_path_cost The new Root Path Cost field value.
|
||||
*/
|
||||
void root_path_cost(uint32_t new_root_path_cost);
|
||||
|
||||
/**
|
||||
* \brief Setter for the Port ID field.
|
||||
* \param new_port_id The new Port ID field value.
|
||||
*/
|
||||
void port_id(uint16_t new_port_id);
|
||||
|
||||
/**
|
||||
* \brief Setter for the Message Age field.
|
||||
* \param new_msg_age The new Message Age field value.
|
||||
*/
|
||||
void msg_age(uint16_t new_msg_age);
|
||||
|
||||
/**
|
||||
* \brief Setter for the Maximum Age field.
|
||||
* \param new_max_age The new Maximum Age field value.
|
||||
*/
|
||||
void max_age(uint16_t new_max_age);
|
||||
|
||||
/**
|
||||
* \brief Setter for the Hello Time field.
|
||||
* \param new_hello_time The new Hello Time field value.
|
||||
*/
|
||||
void hello_time(uint16_t new_hello_time);
|
||||
|
||||
/**
|
||||
* \brief Setter for the Forward Delay field.
|
||||
* \param new_fwd_delay The new Forward Delay field value.
|
||||
*/
|
||||
void fwd_delay(uint16_t new_fwd_delay);
|
||||
|
||||
/**
|
||||
* \brief Setter for the Root ID field.
|
||||
* \param new_fwd_delay The new Root ID field value.
|
||||
*/
|
||||
void root_id(const bpdu_id_type &id);
|
||||
|
||||
/**
|
||||
* \brief Setter for the Bridge ID field.
|
||||
* \param new_fwd_delay The new Bridge ID field value.
|
||||
*/
|
||||
void bridge_id(const bpdu_id_type &id);
|
||||
private:
|
||||
TINS_BEGIN_PACK
|
||||
struct pvt_bpdu_id {
|
||||
#if TINS_IS_LITTLE_ENDIAN
|
||||
// fixme
|
||||
uint16_t ext_id:4,
|
||||
priority:4,
|
||||
ext_idL:8;
|
||||
#else
|
||||
uint16_t priority:4,
|
||||
ext_id:12;
|
||||
#endif
|
||||
uint8_t id[6];
|
||||
} TINS_END_PACK;
|
||||
|
||||
TINS_BEGIN_PACK
|
||||
struct stphdr {
|
||||
uint16_t proto_id;
|
||||
uint8_t proto_version;
|
||||
uint8_t bpdu_type;
|
||||
uint8_t bpdu_flags;
|
||||
pvt_bpdu_id root_id;
|
||||
uint32_t root_path_cost;
|
||||
pvt_bpdu_id bridge_id;
|
||||
uint16_t port_id;
|
||||
uint16_t msg_age;
|
||||
uint16_t max_age;
|
||||
uint16_t hello_time;
|
||||
uint16_t fwd_delay;
|
||||
} TINS_END_PACK;
|
||||
|
||||
static bpdu_id_type convert(const pvt_bpdu_id &id);
|
||||
static pvt_bpdu_id convert(const bpdu_id_type &id);
|
||||
|
||||
void write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *parent);
|
||||
|
||||
stphdr _header;
|
||||
};
|
||||
}
|
||||
|
||||
#endif // TINS_STP_H
|
||||
568
include/tins/tcp.h
Normal file
568
include/tins/tcp.h
Normal file
@@ -0,0 +1,568 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Matias Fontanini
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following disclaimer
|
||||
* in the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef TINS_TCP_H
|
||||
#define TINS_TCP_H
|
||||
|
||||
|
||||
#include <list>
|
||||
#include <vector>
|
||||
#include <stdint.h>
|
||||
#include <stdexcept>
|
||||
#include <utility>
|
||||
#include "pdu.h"
|
||||
#include "macros.h"
|
||||
#include "endianness.h"
|
||||
#include "small_uint.h"
|
||||
#include "pdu_option.h"
|
||||
#include "cxxstd.h"
|
||||
|
||||
namespace Tins {
|
||||
/**
|
||||
* \class TCP
|
||||
* \brief Represents a TCP PDU.
|
||||
*
|
||||
* This class represents a TCP PDU.
|
||||
*
|
||||
* When sending TCP PDUs, the checksum is calculated automatically
|
||||
* every time you send the packet.
|
||||
*
|
||||
* While sniffing, the payload sent in each packet will be wrapped
|
||||
* in a RawPDU, which is set as the TCP object's inner_pdu. Therefore,
|
||||
* if you are sniffing and want to see the TCP packet's payload,
|
||||
* you need to do the following:
|
||||
*
|
||||
* \code
|
||||
* // Get a packet from somewhere.
|
||||
* TCP tcp = ...;
|
||||
*
|
||||
* // Extract the RawPDU object.
|
||||
* const RawPDU& raw = tcp.rfind_pdu<RawPDU>();
|
||||
*
|
||||
* // Finally, take the payload (this is a vector<uint8_t>)
|
||||
* const RawPDU::payload_type& payload = raw.payload();
|
||||
* \endcode
|
||||
*
|
||||
* \sa RawPDU
|
||||
*/
|
||||
|
||||
class TCP : public PDU {
|
||||
public:
|
||||
/**
|
||||
* This PDU's flag.
|
||||
*/
|
||||
static const PDU::PDUType pdu_flag = PDU::TCP;
|
||||
|
||||
/**
|
||||
* \brief TCP flags enum.
|
||||
*
|
||||
* These flags identify those supported by the TCP PDU.
|
||||
*/
|
||||
enum Flags {
|
||||
FIN = 1,
|
||||
SYN = 2,
|
||||
RST = 4,
|
||||
PSH = 8,
|
||||
ACK = 16,
|
||||
URG = 32,
|
||||
ECE = 64,
|
||||
CWR = 128
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief TCP options enum.
|
||||
*
|
||||
* This enum defines option types supported by TCP PDU.
|
||||
*/
|
||||
enum OptionTypes {
|
||||
EOL = 0,
|
||||
NOP = 1,
|
||||
MSS = 2,
|
||||
WSCALE = 3,
|
||||
SACK_OK = 4,
|
||||
SACK = 5,
|
||||
TSOPT = 8,
|
||||
ALTCHK = 14
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Alternate checksum enum.
|
||||
*/
|
||||
enum AltChecksums {
|
||||
CHK_TCP,
|
||||
CHK_8FLETCHER,
|
||||
CHK_16FLETCHER
|
||||
};
|
||||
|
||||
/**
|
||||
* The type used to store TCP options.
|
||||
*/
|
||||
typedef PDUOption<uint8_t, TCP> option;
|
||||
|
||||
/**
|
||||
* The type used to store the options.
|
||||
*/
|
||||
typedef std::list<option> options_type;
|
||||
|
||||
/**
|
||||
* The type used to store the sack option.
|
||||
*/
|
||||
typedef std::vector<uint32_t> sack_type;
|
||||
|
||||
/**
|
||||
* \brief TCP constructor.
|
||||
*
|
||||
* Creates an instance of TCP. Destination and source port can
|
||||
* be provided, otherwise both will be 0.
|
||||
*
|
||||
* \param dport Destination port.
|
||||
* \param sport Source port.
|
||||
* */
|
||||
TCP(uint16_t dport = 0, uint16_t sport = 0);
|
||||
|
||||
/**
|
||||
* \brief Constructs TCP object from a buffer.
|
||||
*
|
||||
* If there is not enough size for a TCP header, or any of the
|
||||
* TLV options are malformed, a malformed_packet exception is
|
||||
* thrown.
|
||||
*
|
||||
* Any extra data will be stored in a RawPDU.
|
||||
*
|
||||
* \param buffer The buffer from which this PDU will be constructed.
|
||||
* \param total_sz The total size of the buffer.
|
||||
*/
|
||||
TCP(const uint8_t *buffer, uint32_t total_sz);
|
||||
|
||||
/**
|
||||
* \brief Getter for the destination port field.
|
||||
*
|
||||
* \return The destination port field value.
|
||||
*/
|
||||
uint16_t dport() const { return Endian::be_to_host(_tcp.dport); }
|
||||
|
||||
/**
|
||||
* \brief Getter for the source port field.
|
||||
*
|
||||
* \return The source port field value.
|
||||
*/
|
||||
uint16_t sport() const { return Endian::be_to_host(_tcp.sport); }
|
||||
|
||||
/**
|
||||
* \brief Getter for the sequence number field.
|
||||
*
|
||||
* \return The sequence number field value.
|
||||
*/
|
||||
uint32_t seq() const { return Endian::be_to_host(_tcp.seq); }
|
||||
|
||||
/**
|
||||
* \brief Getter for the acknowledge number field.
|
||||
*
|
||||
* \return The acknowledge number field value.
|
||||
*/
|
||||
uint32_t ack_seq() const { return Endian::be_to_host(_tcp.ack_seq); }
|
||||
|
||||
/**
|
||||
* \brief Getter for the window size field.
|
||||
*
|
||||
* \return The window size field value.
|
||||
*/
|
||||
uint16_t window() const { return Endian::be_to_host(_tcp.window); }
|
||||
|
||||
/**
|
||||
* \brief Getter for the checksum field.
|
||||
*
|
||||
* \return The checksum field value.
|
||||
*/
|
||||
uint16_t checksum() const { return Endian::be_to_host(_tcp.check); }
|
||||
|
||||
/**
|
||||
* \brief Getter for the urgent pointer field.
|
||||
*
|
||||
* \return The urgent pointer field value.
|
||||
*/
|
||||
uint16_t urg_ptr() const { return Endian::be_to_host(_tcp.urg_ptr); }
|
||||
|
||||
/**
|
||||
* \brief Getter for the data offset field.
|
||||
*
|
||||
* \return The data offset field value.
|
||||
*/
|
||||
small_uint<4> data_offset() const { return this->_tcp.doff; }
|
||||
|
||||
/**
|
||||
* \brief Getter for the option list.
|
||||
*
|
||||
* \return The options list.
|
||||
*/
|
||||
const options_type &options() const { return _options; }
|
||||
|
||||
/**
|
||||
* \brief Gets the value of a flag.
|
||||
*
|
||||
* This method gets the value of a specific flag. If you
|
||||
* want to check for multiple flags at the same time,
|
||||
* use TCP::flags.
|
||||
*
|
||||
* If you want to check if this PDU has the SYN flag on,
|
||||
* you can do it like this:
|
||||
*
|
||||
* \code
|
||||
* // Get a TCP packet from somewhere.
|
||||
* TCP tcp = ...;
|
||||
*
|
||||
* if(tcp.get_flag(TCP::SYN)) {
|
||||
* // The SYN flag is on!
|
||||
* }
|
||||
* \endcode
|
||||
*
|
||||
* \sa TCP::flags
|
||||
* \param tcp_flag The polled flag.
|
||||
* \return The value of the flag.
|
||||
*/
|
||||
small_uint<1> get_flag(Flags tcp_flag) const;
|
||||
|
||||
/**
|
||||
*
|
||||
* \brief Gets the flags' values.
|
||||
*
|
||||
* All of the set flags will be joined together into
|
||||
* a 12 bit value. This way, you can check for multiple
|
||||
* flags at the same time:
|
||||
*
|
||||
* \code
|
||||
* TCP tcp = ...;
|
||||
* if(tcp.flags() == (TCP::SYN | TCP::ACK)) {
|
||||
* // It's a SYN+ACK!
|
||||
* }
|
||||
* \endcode
|
||||
*
|
||||
* \return The value of the flags field.
|
||||
*/
|
||||
small_uint<12> flags() const;
|
||||
|
||||
/* Setters */
|
||||
|
||||
/**
|
||||
* \brief Setter for the destination port field.
|
||||
*
|
||||
* \param new_dport The new destination port.
|
||||
*/
|
||||
void dport(uint16_t new_dport);
|
||||
|
||||
/**
|
||||
* \brief Setter for the source port field.
|
||||
*
|
||||
* \param new_sport The new source port.
|
||||
*/
|
||||
void sport(uint16_t new_sport);
|
||||
|
||||
/**
|
||||
* \brief Setter for the sequence number.
|
||||
*
|
||||
* \param new_seq The new sequence number.
|
||||
*/
|
||||
void seq(uint32_t new_seq);
|
||||
|
||||
/**
|
||||
* \brief Setter for the acknowledge number.
|
||||
*
|
||||
* \param new_ack_seq The new acknowledge number.
|
||||
*/
|
||||
void ack_seq(uint32_t new_ack_seq);
|
||||
|
||||
/**
|
||||
* \brief Setter for the window size.
|
||||
*
|
||||
* \param new_window The new window size.
|
||||
*/
|
||||
void window(uint16_t new_window);
|
||||
|
||||
/**
|
||||
* \brief Setter for the urgent pointer field.
|
||||
*
|
||||
* \param new_urg_ptr The new urgent pointer.
|
||||
*/
|
||||
void urg_ptr(uint16_t new_urg_ptr);
|
||||
|
||||
/**
|
||||
* \brief Setter for the data offset pointer field.
|
||||
*
|
||||
* \param new_doff The new data offset pointer.
|
||||
*/
|
||||
void data_offset(small_uint<4> new_doff);
|
||||
|
||||
// Options
|
||||
|
||||
/**
|
||||
* \brief Add a maximum segment size option.
|
||||
*
|
||||
* \param value The new maximum segment size.
|
||||
*/
|
||||
void mss(uint16_t value);
|
||||
|
||||
/**
|
||||
* \brief Searchs for a maximum segment size option.
|
||||
* \param value A pointer in which the option's value will be stored.
|
||||
* \return True if the option was found, false otherwise.
|
||||
*/
|
||||
uint16_t mss() const;
|
||||
|
||||
/**
|
||||
* \brief Add a window scale option.
|
||||
*
|
||||
* \param value The new window scale.
|
||||
*/
|
||||
void winscale(uint8_t value);
|
||||
|
||||
/**
|
||||
* \brief Searchs for a window scale option.
|
||||
* \param value A pointer in which the option's value will be stored.
|
||||
* \return True if the option was found, false otherwise.
|
||||
*/
|
||||
uint8_t winscale() const;
|
||||
|
||||
/**
|
||||
* \brief Add a sack permitted option.
|
||||
*/
|
||||
void sack_permitted();
|
||||
|
||||
/**
|
||||
* \brief Searchs for a sack permitted option.
|
||||
* \return True if the option was found, false otherwise.
|
||||
*/
|
||||
bool has_sack_permitted() const;
|
||||
|
||||
/**
|
||||
* \brief Add a sack option.
|
||||
*
|
||||
* \param value The new window scale.
|
||||
*/
|
||||
void sack(const sack_type &edges);
|
||||
|
||||
/**
|
||||
* \brief Searchs for a sack option.
|
||||
* \param value A pointer in which the option's value will be stored.
|
||||
* \return True if the option was found, false otherwise.
|
||||
*/
|
||||
sack_type sack() const;
|
||||
|
||||
/**
|
||||
* \brief Add a timestamp option.
|
||||
*
|
||||
* \param value The current value of the timestamp clock.
|
||||
* \param reply The echo reply field.
|
||||
*/
|
||||
void timestamp(uint32_t value, uint32_t reply);
|
||||
|
||||
/**
|
||||
* \brief Searchs for a timestamp option.
|
||||
* \param value A pointer in which the option's value will be stored.
|
||||
* \param reply A pointer in which the option's reply value will be stored.
|
||||
* \return True if the option was found, false otherwise.
|
||||
*/
|
||||
std::pair<uint32_t, uint32_t> timestamp() const;
|
||||
|
||||
/**
|
||||
* \brief Add a alternate checksum option.
|
||||
*
|
||||
* \param value The new alternate checksum scale.
|
||||
*/
|
||||
void altchecksum(AltChecksums value);
|
||||
|
||||
/**
|
||||
* \brief Searchs for a alternate checksum option.
|
||||
* \param value A pointer in which the option's value will be stored.
|
||||
* \return True if the option was found, false otherwise.
|
||||
*/
|
||||
AltChecksums altchecksum() const;
|
||||
|
||||
/**
|
||||
* \brief Set a TCP flag value.
|
||||
*
|
||||
* \param tcp_flag The flag to be set.
|
||||
* \param value The new value for this flag. Must be 0 or 1.
|
||||
*/
|
||||
void set_flag(Flags tcp_flag, small_uint<1> value);
|
||||
|
||||
/**
|
||||
* \brief Sets the value of the flag fields.
|
||||
*
|
||||
* This method can be used to set several flags at the
|
||||
* same time.
|
||||
*
|
||||
* \code
|
||||
* // Get a TCP packet from somewhere and set the flags to SYN && ACK
|
||||
* TCP tcp = ...;
|
||||
* tcp.flags(TCP::SYN | TCP::ACK);
|
||||
*
|
||||
* // Now also set the PSH flag, without modifying
|
||||
* // the rest of the flags.
|
||||
* tcp.flags(tcp.flags() | TCP::PSH);
|
||||
* \endcode
|
||||
*
|
||||
* \param value The new value of the flags.
|
||||
*/
|
||||
void flags(small_uint<12> value);
|
||||
|
||||
|
||||
/**
|
||||
* \brief Adds a TCP option.
|
||||
*
|
||||
* \param option The option to be added.
|
||||
*/
|
||||
void add_option(const option &opt);
|
||||
|
||||
#if TINS_IS_CXX11
|
||||
/**
|
||||
* \brief Adds a TCP option.
|
||||
*
|
||||
* This move-constructs the option.
|
||||
*
|
||||
* \param option The option to be added.
|
||||
*/
|
||||
void add_option(option &&opt) {
|
||||
internal_add_option(opt);
|
||||
_options.push_back(std::move(opt));
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Adds a TCP option using the provided arguments.
|
||||
*
|
||||
* The option is constructed from the provided parameters.
|
||||
*
|
||||
* \param args The arguments to be used in the option's
|
||||
* constructor.
|
||||
*/
|
||||
template<typename... Args>
|
||||
void add_option(Args&&... args) {
|
||||
_options.emplace_back(std::forward<Args>(args)...);
|
||||
internal_add_option(_options.back());
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* \brief Returns the header size.
|
||||
*
|
||||
* This metod overrides PDU::header_size. This size includes the
|
||||
* payload and options size.
|
||||
*
|
||||
* \sa PDU::header_size
|
||||
*/
|
||||
uint32_t header_size() const;
|
||||
|
||||
/**
|
||||
* \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 Getter for the PDU's type.
|
||||
*
|
||||
* \sa PDU::pdu_type
|
||||
*/
|
||||
PDUType pdu_type() const { return PDU::TCP; }
|
||||
|
||||
/**
|
||||
* \brief Searchs for an option that matchs the given flag.
|
||||
* \param opt_flag The flag to be searched.
|
||||
* \return A pointer to the option, or 0 if it was not found.
|
||||
*/
|
||||
const option *search_option(OptionTypes opt) const;
|
||||
|
||||
/**
|
||||
* \sa PDU::clone
|
||||
*/
|
||||
TCP *clone() const {
|
||||
return new TCP(*this);
|
||||
}
|
||||
private:
|
||||
TINS_BEGIN_PACK
|
||||
struct tcphdr {
|
||||
uint16_t sport;
|
||||
uint16_t dport;
|
||||
uint32_t seq;
|
||||
uint32_t ack_seq;
|
||||
#if TINS_IS_LITTLE_ENDIAN
|
||||
uint16_t res1:4,
|
||||
doff:4,
|
||||
fin:1,
|
||||
syn:1,
|
||||
rst:1,
|
||||
psh:1,
|
||||
ack:1,
|
||||
urg:1,
|
||||
ece:1,
|
||||
cwr:1;
|
||||
#elif TINS_IS_BIG_ENDIAN
|
||||
uint16_t doff:4,
|
||||
res1:4,
|
||||
cwr:1,
|
||||
ece:1,
|
||||
urg:1,
|
||||
ack:1,
|
||||
psh:1,
|
||||
rst:1,
|
||||
syn:1,
|
||||
fin:1;
|
||||
#else
|
||||
#error "Endian is not LE nor BE..."
|
||||
#endif
|
||||
uint16_t window;
|
||||
uint16_t check;
|
||||
uint16_t urg_ptr;
|
||||
} TINS_END_PACK;
|
||||
|
||||
static const uint16_t DEFAULT_WINDOW;
|
||||
|
||||
template<class T>
|
||||
T generic_search(OptionTypes opt_type) const {
|
||||
const option *opt = search_option(opt_type);
|
||||
if(!opt)
|
||||
throw option_not_found();
|
||||
return opt->to<T>();
|
||||
}
|
||||
|
||||
void internal_add_option(const option &option);
|
||||
void write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *parent);
|
||||
void checksum(uint16_t new_check);
|
||||
|
||||
uint8_t *write_option(const option &opt, uint8_t *buffer);
|
||||
|
||||
tcphdr _tcp;
|
||||
uint16_t _options_size, _total_options_size;
|
||||
options_type _options;
|
||||
};
|
||||
}
|
||||
|
||||
#endif // TINS_TCP_H
|
||||
376
include/tins/tcp_stream.h
Normal file
376
include/tins/tcp_stream.h
Normal file
@@ -0,0 +1,376 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Matias Fontanini
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following disclaimer
|
||||
* in the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef TINS_TCP_STREAM_H
|
||||
#define TINS_TCP_STREAM_H
|
||||
|
||||
#include <map>
|
||||
#include <utility>
|
||||
#include <iterator>
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
#include <stdint.h>
|
||||
#include "sniffer.h"
|
||||
#include "tcp.h"
|
||||
#include "utils.h"
|
||||
#include "ip.h"
|
||||
#include "ip_address.h"
|
||||
|
||||
namespace Tins {
|
||||
class Sniffer;
|
||||
class RawPDU;
|
||||
|
||||
/**
|
||||
* \class TCPStream
|
||||
* \brief Represents a TCP stream.
|
||||
*/
|
||||
class TCPStream {
|
||||
public:
|
||||
/**
|
||||
* The stream information.
|
||||
*/
|
||||
struct StreamInfo {
|
||||
IPv4Address client_addr, server_addr;
|
||||
uint16_t client_port, server_port;
|
||||
|
||||
StreamInfo() {}
|
||||
|
||||
StreamInfo(IPv4Address client, IPv4Address server,
|
||||
uint16_t cport, uint16_t sport);
|
||||
|
||||
bool operator<(const StreamInfo &rhs) const;
|
||||
};
|
||||
|
||||
/**
|
||||
* The type used to store the payload.
|
||||
*/
|
||||
typedef std::vector<uint8_t> payload_type;
|
||||
|
||||
/**
|
||||
* \brief TCPStream constructor.
|
||||
* \param ip The IP PDU from which to take the initial parameters.
|
||||
* \param tcp The TCP PDU from which to take the initial parameters.
|
||||
* \param identifier This stream's identifier number
|
||||
*/
|
||||
TCPStream(IP *ip, TCP *tcp, uint64_t identifier);
|
||||
|
||||
/**
|
||||
* Copy constructor.
|
||||
*/
|
||||
TCPStream(const TCPStream &rhs);
|
||||
|
||||
/**
|
||||
* Copy assignment operator.
|
||||
*/
|
||||
TCPStream& operator=(const TCPStream &rhs);
|
||||
|
||||
/**
|
||||
* Destructor.
|
||||
*/
|
||||
~TCPStream();
|
||||
|
||||
/**
|
||||
* \brief Retrieves the client payload.
|
||||
*
|
||||
* This is the payload that the connection's client has sent so far.
|
||||
*
|
||||
* \return const payload_type& containing the payload.
|
||||
*/
|
||||
const payload_type &client_payload() const {
|
||||
return client_payload_;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Retrieves the client payload.
|
||||
*
|
||||
* This is the payload that the connection's client has sent so far.
|
||||
*
|
||||
* \return payload_type& containing the payload.
|
||||
*/
|
||||
payload_type &client_payload() {
|
||||
return client_payload_;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Retrieves the server payload.
|
||||
*
|
||||
* This is the payload that the connection's server has sent so far.
|
||||
*
|
||||
* \return const payload_type& containing the payload.
|
||||
*/
|
||||
const payload_type &server_payload() const {
|
||||
return server_payload_;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Retrieves the server payload.
|
||||
*
|
||||
* This is the payload that the connection's server has sent so far.
|
||||
*
|
||||
* \return payload_type& containing the payload.
|
||||
*/
|
||||
payload_type &server_payload() {
|
||||
return server_payload_;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Retrieves this stream's identification number.
|
||||
* \return uint64_t containing the identification number.
|
||||
*/
|
||||
uint64_t id() const {
|
||||
return identifier;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Retrieves the stream information.
|
||||
* \return const StreamInfo& containing the stream information.
|
||||
*/
|
||||
const StreamInfo &stream_info() const {
|
||||
return info;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Checks whether this stream is finished.
|
||||
*
|
||||
* A stream is considered to be finished, if at least one of the
|
||||
* peers sends a TCP segment containing the FIN bit on.
|
||||
*
|
||||
* \return bool indicating whether the stream is finished.
|
||||
*/
|
||||
bool is_finished() const {
|
||||
return fin_sent;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Updates the stream data.
|
||||
*
|
||||
* This may update both the payload and the expected sequence numbers.
|
||||
*
|
||||
* \param ip The IP PDU from which to take information.
|
||||
* \param tcp The TCP PDU from which to take information.
|
||||
* \return bool indicating whether any changes have been done to
|
||||
* any of the stored payloads.
|
||||
*/
|
||||
bool update(IP *ip, TCP *tcp);
|
||||
private:
|
||||
typedef std::map<uint32_t, RawPDU*> fragments_type;
|
||||
|
||||
static void free_fragments(fragments_type &frags);
|
||||
static fragments_type clone_fragments(const fragments_type &frags);
|
||||
|
||||
bool generic_process(uint32_t &my_seq, uint32_t &other_seq,
|
||||
payload_type &pload, fragments_type &frags, TCP *tcp);
|
||||
|
||||
void safe_insert(fragments_type &frags, uint32_t seq, RawPDU *raw);
|
||||
|
||||
|
||||
uint32_t client_seq, server_seq;
|
||||
StreamInfo info;
|
||||
uint64_t identifier;
|
||||
payload_type client_payload_, server_payload_;
|
||||
fragments_type client_frags, server_frags;
|
||||
bool syn_ack_sent, fin_sent;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* \class TCPStreamFollower
|
||||
* \brief Follows TCP streams and notifies the user when data is available.
|
||||
*/
|
||||
class TCPStreamFollower {
|
||||
public:
|
||||
/**
|
||||
* \brief Default constructor.
|
||||
*/
|
||||
TCPStreamFollower();
|
||||
|
||||
/**
|
||||
* \brief Starts following TCP streams.
|
||||
*
|
||||
* The template functors must accept a TCPStream& as argument, which
|
||||
* will point to the stream which has been modified.
|
||||
*
|
||||
* \param sniffer The sniffer which will be used to sniff PDUs.
|
||||
* \param data_fun The function which will be called whenever one of
|
||||
* the peers in a connection sends data.
|
||||
* \param end_fun This function will be called when a stream is
|
||||
* closed.
|
||||
*/
|
||||
template<typename DataFunctor, typename EndFunctor>
|
||||
void follow_streams(BaseSniffer &sniffer, DataFunctor data_fun, EndFunctor end_fun);
|
||||
|
||||
/**
|
||||
* \brief Starts following TCP streams.
|
||||
*
|
||||
* This overload takes a range of iterators containing the PDUs
|
||||
* in which TCP streams will be looked up and followed. The iterators
|
||||
* will be dereferenced until a PDU& is found, so iterators can hold
|
||||
* not only PDUs, but also smart pointers, etc.
|
||||
*
|
||||
* The template functors must accept a TCPStream& as argument, which
|
||||
* will point to the stream which has been modified.
|
||||
*
|
||||
* The state of the PDUs stored in the iterator range provided might
|
||||
* be modified internally.
|
||||
*
|
||||
* \param start The start of the range of PDUs.
|
||||
* \param end The start of the range of PDUs.
|
||||
* \param data_fun The function which will be called whenever one of
|
||||
* the peers in a connection sends data.
|
||||
* \param end_fun This function will be called when a stream is
|
||||
* closed.
|
||||
*/
|
||||
template<typename ForwardIterator, typename DataFunctor, typename EndFunctor>
|
||||
void follow_streams(ForwardIterator start, ForwardIterator end,
|
||||
DataFunctor data_fun, EndFunctor end_fun);
|
||||
|
||||
/**
|
||||
* \brief Starts following TCP streams.
|
||||
*
|
||||
* The template functor must accept a TCPStream& as argument, which
|
||||
* will point to the stream which has been modified.
|
||||
*
|
||||
* \param sniffer The sniffer which will be used to sniff PDUs.
|
||||
* \param data_fun The function which will be called whenever one of
|
||||
* the peers in a connection sends data.
|
||||
* closed.
|
||||
*/
|
||||
template<typename DataFunctor>
|
||||
void follow_streams(BaseSniffer &sniffer, DataFunctor data_fun);
|
||||
|
||||
/**
|
||||
* \brief Starts following TCP streams.
|
||||
*
|
||||
* This overload takes a range of iterators containing the PDUs
|
||||
* in which TCP streams will be looked up and followed. The iterators
|
||||
* will be dereferenced until a PDU& is found, so iterators can hold
|
||||
* not only PDUs, but also smart pointers, etc.
|
||||
*
|
||||
* The template functors must accept a TCPStream& as argument, which
|
||||
* will point to the stream which has been modified.
|
||||
*
|
||||
* The state of the PDUs stored in the iterator range provided might
|
||||
* be modified internally.
|
||||
*
|
||||
* \param start The start of the range of PDUs.
|
||||
* \param end The start of the range of PDUs.
|
||||
* \param data_fun The function which will be called whenever one of
|
||||
* the peers in a connection sends data.
|
||||
*/
|
||||
template<typename ForwardIterator, typename DataFunctor>
|
||||
void follow_streams(ForwardIterator start, ForwardIterator end,
|
||||
DataFunctor data_fun);
|
||||
private:
|
||||
typedef std::map<TCPStream::StreamInfo, TCPStream> sessions_type;
|
||||
|
||||
template<typename DataFunctor, typename EndFunctor>
|
||||
struct proxy_caller {
|
||||
bool callback(PDU &pdu) {
|
||||
return stream->callback(pdu, data_fun, end_fun);
|
||||
}
|
||||
|
||||
TCPStreamFollower *stream;
|
||||
DataFunctor data_fun;
|
||||
EndFunctor end_fun;
|
||||
};
|
||||
|
||||
template<typename DataFunctor, typename EndFunctor>
|
||||
bool callback(PDU &pdu, const DataFunctor &fun, const EndFunctor &end_fun);
|
||||
static void dummy_function(TCPStream&) { }
|
||||
|
||||
sessions_type sessions;
|
||||
uint64_t last_identifier;
|
||||
};
|
||||
|
||||
template<typename DataFunctor, typename EndFunctor>
|
||||
void TCPStreamFollower::follow_streams(BaseSniffer &sniffer, DataFunctor data_fun, EndFunctor end_fun) {
|
||||
typedef proxy_caller<DataFunctor, EndFunctor> proxy_type;
|
||||
proxy_type proxy = { this, data_fun, end_fun };
|
||||
sniffer.sniff_loop(make_sniffer_handler(&proxy, &proxy_type::callback));
|
||||
}
|
||||
|
||||
template<typename ForwardIterator, typename DataFunctor, typename EndFunctor>
|
||||
void TCPStreamFollower::follow_streams(ForwardIterator start, ForwardIterator end,
|
||||
DataFunctor data_fun, EndFunctor end_fun)
|
||||
{
|
||||
while(start != end) {
|
||||
if(!callback(Utils::dereference_until_pdu(start), data_fun, end_fun))
|
||||
return;
|
||||
start++;
|
||||
}
|
||||
}
|
||||
|
||||
template<typename DataFunctor>
|
||||
void TCPStreamFollower::follow_streams(BaseSniffer &sniffer, DataFunctor data_fun) {
|
||||
return follow_streams(sniffer, data_fun, dummy_function);
|
||||
}
|
||||
|
||||
template<typename ForwardIterator, typename DataFunctor>
|
||||
void TCPStreamFollower::follow_streams(ForwardIterator start, ForwardIterator end,
|
||||
DataFunctor data_fun)
|
||||
{
|
||||
follow_streams(start, end, data_fun, dummy_function);
|
||||
}
|
||||
|
||||
template<typename DataFunctor, typename EndFunctor>
|
||||
bool TCPStreamFollower::callback(PDU &pdu, const DataFunctor &data_fun, const EndFunctor &end_fun) {
|
||||
IP &ip = pdu.rfind_pdu<IP>();
|
||||
TCP &tcp = pdu.rfind_pdu<TCP>();
|
||||
TCPStream::StreamInfo info(
|
||||
ip.src_addr(), ip.dst_addr(),
|
||||
tcp.sport(), tcp.dport()
|
||||
);
|
||||
sessions_type::iterator it = sessions.find(info);
|
||||
if(it == sessions.end()) {
|
||||
std::swap(info.client_addr, info.server_addr);
|
||||
std::swap(info.client_port, info.server_port);
|
||||
if((it = sessions.find(info)) == sessions.end()) {
|
||||
if(tcp.get_flag(TCP::SYN) && !tcp.get_flag(TCP::ACK)) {
|
||||
sessions.insert(
|
||||
std::make_pair(
|
||||
info,
|
||||
TCPStream(&ip, &tcp, last_identifier++)
|
||||
)
|
||||
);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if(it->second.update(&ip, &tcp))
|
||||
data_fun(it->second);
|
||||
// We're done with this stream
|
||||
if(it->second.is_finished()) {
|
||||
end_fun(it->second);
|
||||
sessions.erase(it);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
#endif // TINS_TCP_STREAM_H
|
||||
126
include/tins/timestamp.h
Normal file
126
include/tins/timestamp.h
Normal file
@@ -0,0 +1,126 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Matias Fontanini
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following disclaimer
|
||||
* in the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef TINS_TIMESTAMP_H
|
||||
#define TINS_TIMESTAMP_H
|
||||
|
||||
#ifdef WIN32
|
||||
#include <winsock2.h>
|
||||
#else
|
||||
#include <sys/time.h>
|
||||
#endif
|
||||
#include "cxxstd.h"
|
||||
#if TINS_IS_CXX11
|
||||
#include <chrono>
|
||||
#endif
|
||||
|
||||
namespace Tins {
|
||||
/**
|
||||
* \brief Represents a packet timestamp.
|
||||
*/
|
||||
class Timestamp {
|
||||
public:
|
||||
#ifdef WIN32
|
||||
typedef long seconds_type;
|
||||
typedef long microseconds_type;
|
||||
#else
|
||||
typedef time_t seconds_type;
|
||||
typedef suseconds_t microseconds_type;
|
||||
#endif
|
||||
|
||||
/**
|
||||
* \brief Constructs a Timestamp which will hold the current time.
|
||||
*/
|
||||
static Timestamp current_time() {
|
||||
#ifdef WIN32
|
||||
//fixme
|
||||
return Timestamp();
|
||||
#else
|
||||
timeval tv;
|
||||
gettimeofday(&tv, 0);
|
||||
return tv;
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* Default constructs the timestamp.
|
||||
*/
|
||||
Timestamp() : tv() {}
|
||||
|
||||
#if TINS_IS_CXX11
|
||||
/**
|
||||
* Constructs a Timestamp from a std::chrono::duration.
|
||||
*/
|
||||
template<typename Rep, typename Period>
|
||||
Timestamp(const std::chrono::duration<Rep, Period>& ts) {
|
||||
using std::chrono::duration_cast;
|
||||
using std::chrono::microseconds;
|
||||
using std::chrono::seconds;
|
||||
|
||||
tv.tv_sec = duration_cast<seconds>(ts).count();
|
||||
tv.tv_usec = duration_cast<microseconds>(
|
||||
ts - seconds(tv.tv_sec)).count();
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Constructs a timestamp from a timeval object.
|
||||
* \param time_val The timeval object.
|
||||
*/
|
||||
Timestamp(const timeval &time_val) : tv(time_val) {}
|
||||
|
||||
/**
|
||||
* Returns the amount of seconds in this timestamp.
|
||||
*/
|
||||
seconds_type seconds() const {
|
||||
return tv.tv_sec;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the amount of microseconds in this timestamp.
|
||||
*/
|
||||
microseconds_type microseconds() const {
|
||||
return tv.tv_usec;
|
||||
}
|
||||
|
||||
#if TINS_IS_CXX11
|
||||
/**
|
||||
* Converts this Timestamp to a std::chrono::microseconds
|
||||
*/
|
||||
operator std::chrono::microseconds() const {
|
||||
return std::chrono::seconds(seconds()) +
|
||||
std::chrono::microseconds(microseconds());
|
||||
}
|
||||
#endif
|
||||
private:
|
||||
timeval tv;
|
||||
};
|
||||
}
|
||||
|
||||
#endif // TINS_TIMESTAMP_H
|
||||
77
include/tins/tins.h
Normal file
77
include/tins/tins.h
Normal file
@@ -0,0 +1,77 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Matias Fontanini
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following disclaimer
|
||||
* in the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef TINS_TINS_H
|
||||
#define TINS_TINS_H
|
||||
|
||||
#include "dns.h"
|
||||
#include "arp.h"
|
||||
#include "bootp.h"
|
||||
#include "dhcp.h"
|
||||
#include "eapol.h"
|
||||
#include "ethernetII.h"
|
||||
#include "ieee802_3.h"
|
||||
#include "llc.h"
|
||||
#include "icmp.h"
|
||||
#include "icmpv6.h"
|
||||
#include "dot11.h"
|
||||
#include "dot1q.h"
|
||||
#include "dot3.h"
|
||||
#include "ip.h"
|
||||
#include "ipv6.h"
|
||||
#include "packet_sender.h"
|
||||
#include "packet_writer.h"
|
||||
#include "pdu.h"
|
||||
#include "radiotap.h"
|
||||
#include "rawpdu.h"
|
||||
#include "snap.h"
|
||||
#include "sniffer.h"
|
||||
#include "tcp.h"
|
||||
#include "udp.h"
|
||||
#include "utils.h"
|
||||
#include "tcp_stream.h"
|
||||
#include "crypto.h"
|
||||
#include "pdu_cacher.h"
|
||||
#include "rsn_information.h"
|
||||
#include "ipv6_address.h"
|
||||
#include "ip_address.h"
|
||||
#include "packet.h"
|
||||
#include "timestamp.h"
|
||||
#include "sll.h"
|
||||
#include "dhcpv6.h"
|
||||
#include "pppoe.h"
|
||||
#include "stp.h"
|
||||
#include "handshake_capturer.h"
|
||||
#include "address_range.h"
|
||||
#include "pdu_allocator.h"
|
||||
#include "ipsec.h"
|
||||
#include "ip_reassembler.h"
|
||||
#include "ppi.h"
|
||||
|
||||
#endif // TINS_TINS_H
|
||||
185
include/tins/udp.h
Normal file
185
include/tins/udp.h
Normal file
@@ -0,0 +1,185 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Matias Fontanini
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following disclaimer
|
||||
* in the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef TINS_UDP_H
|
||||
#define TINS_UDP_H
|
||||
|
||||
#include "macros.h"
|
||||
#include "pdu.h"
|
||||
#include "endianness.h"
|
||||
|
||||
namespace Tins {
|
||||
|
||||
/**
|
||||
* \class UDP
|
||||
* \brief Represents an UDP PDU.
|
||||
*
|
||||
* This class represents an UDP PDU.
|
||||
*
|
||||
* While sniffing, the payload sent in each packet will be wrapped
|
||||
* in a RawPDU, which is set as the UDP object's inner_pdu. Therefore,
|
||||
* if you are sniffing and want to see the UDP packet's payload,
|
||||
* you need to do the following:
|
||||
*
|
||||
* \code
|
||||
* // Get a packet from somewhere.
|
||||
* UDP udp = ...;
|
||||
*
|
||||
* // Extract the RawPDU object.
|
||||
* const RawPDU& raw = udp.rfind_pdu<RawPDU>();
|
||||
*
|
||||
* // Finally, take the payload (this is a vector<uint8_t>)
|
||||
* const RawPDU::payload_type& payload = raw.payload();
|
||||
* \endcode
|
||||
*
|
||||
* \sa RawPDU
|
||||
*/
|
||||
class UDP : public PDU {
|
||||
public:
|
||||
/**
|
||||
* \brief This PDU's flag.
|
||||
*/
|
||||
static const PDU::PDUType pdu_flag = PDU::UDP;
|
||||
|
||||
/**
|
||||
* \brief UDP constructor.
|
||||
*
|
||||
* Constructs an instance of UDP. The destination and source
|
||||
* port can be provided, otherwise both of them will be 0.
|
||||
*
|
||||
* \param dport Destination port.
|
||||
* \param sport Source port.
|
||||
* */
|
||||
UDP(uint16_t dport = 0, uint16_t sport = 0);
|
||||
|
||||
/**
|
||||
* \brief Constructs an UDP object from a buffer.
|
||||
*
|
||||
* If there is not enough size for a UDP header a malformed_packet
|
||||
* exception is thrown.
|
||||
*
|
||||
* Any extra data will be stored in a RawPDU.
|
||||
*
|
||||
* \param buffer The buffer from which this PDU will be constructed.
|
||||
* \param total_sz The total size of the buffer.
|
||||
*/
|
||||
UDP(const uint8_t *buffer, uint32_t total_sz);
|
||||
|
||||
/**
|
||||
* \brief Getter for the destination port.
|
||||
* \return The datagram's destination port.
|
||||
*/
|
||||
uint16_t dport() const { return Endian::be_to_host(_udp.dport); }
|
||||
|
||||
/**
|
||||
* \brief Getter for the source port.
|
||||
* \return The datagram's source port.
|
||||
*/
|
||||
uint16_t sport() const { return Endian::be_to_host(_udp.sport); }
|
||||
|
||||
/**
|
||||
* \brief Getter for the length of the datagram.
|
||||
* \return The length of the datagram.
|
||||
*/
|
||||
uint16_t length() const { return Endian::be_to_host(_udp.len); }
|
||||
|
||||
/**
|
||||
* \brief Getter for the checksum of the datagram.
|
||||
* \return The datagram's checksum.
|
||||
*/
|
||||
uint16_t checksum() const { return Endian::be_to_host(_udp.check); }
|
||||
|
||||
/**
|
||||
* \brief Set the destination port.
|
||||
* \param new_dport The new destination port.
|
||||
*/
|
||||
void dport(uint16_t new_dport);
|
||||
|
||||
/**
|
||||
* \brief Set the source port.
|
||||
*
|
||||
* \param new_sport The new source port.
|
||||
*/
|
||||
void sport(uint16_t new_sport);
|
||||
|
||||
/**
|
||||
* \brief Getter for the length field.
|
||||
* \param new_len The new length field.
|
||||
* \return The length field.
|
||||
*/
|
||||
void length(uint16_t new_len);
|
||||
|
||||
/**
|
||||
* \brief Check wether ptr points to a valid response for this PDU.
|
||||
*
|
||||
* This compares the source and destination ports in the provided
|
||||
* response with those stored in 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 header size.
|
||||
*
|
||||
* This metod overrides PDU::header_size. This size includes the
|
||||
* payload and options 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::UDP; }
|
||||
|
||||
/**
|
||||
* \sa PDU::clone
|
||||
*/
|
||||
UDP *clone() const {
|
||||
return new UDP(*this);
|
||||
}
|
||||
private:
|
||||
TINS_BEGIN_PACK
|
||||
struct udphdr {
|
||||
uint16_t sport;
|
||||
uint16_t dport;
|
||||
uint16_t len;
|
||||
uint16_t check;
|
||||
} TINS_END_PACK;
|
||||
|
||||
void write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *parent);
|
||||
|
||||
udphdr _udp;
|
||||
};
|
||||
}
|
||||
|
||||
#endif // TINS_UDP_H
|
||||
427
include/tins/utils.h
Normal file
427
include/tins/utils.h
Normal file
@@ -0,0 +1,427 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Matias Fontanini
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following disclaimer
|
||||
* in the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef TINS_UTILS_H
|
||||
#define TINS_UTILS_H
|
||||
|
||||
#ifndef WIN32
|
||||
#include <ifaddrs.h>
|
||||
#else
|
||||
#include <winsock2.h>
|
||||
#include <iphlpapi.h>
|
||||
#undef interface
|
||||
#include "network_interface.h"
|
||||
#endif
|
||||
#include "macros.h"
|
||||
#if defined(BSD) || defined(__FreeBSD_kernel__)
|
||||
#include <sys/file.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/sysctl.h>
|
||||
|
||||
#include <net/if.h>
|
||||
#include <net/route.h>
|
||||
#include <netinet/in.h>
|
||||
#endif
|
||||
#include <string>
|
||||
#include <set>
|
||||
#include <fstream>
|
||||
#include <vector>
|
||||
#include <stdint.h>
|
||||
#include "ip_address.h"
|
||||
#include "ipv6_address.h"
|
||||
#include "hw_address.h"
|
||||
#include "internals.h"
|
||||
|
||||
namespace Tins {
|
||||
class NetworkInterface;
|
||||
class PacketSender;
|
||||
class PDU;
|
||||
|
||||
/**
|
||||
* \brief Network utils namespace.
|
||||
*
|
||||
* This namespace provides utils to convert between integer IP addresses
|
||||
* and dotted notation strings, "net to host" integer conversions,
|
||||
* interface listing, etc.
|
||||
*/
|
||||
namespace Utils {
|
||||
/**
|
||||
* Struct that represents an entry in /proc/net/route
|
||||
*/
|
||||
struct RouteEntry {
|
||||
/**
|
||||
* This interface's name.
|
||||
*/
|
||||
std::string interface;
|
||||
|
||||
/**
|
||||
* This route entry's destination.
|
||||
*/
|
||||
IPv4Address destination;
|
||||
|
||||
/**
|
||||
* This route entry's gateway.
|
||||
*/
|
||||
IPv4Address gateway;
|
||||
|
||||
/**
|
||||
* This route entry's subnet mask.
|
||||
*/
|
||||
IPv4Address mask;
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Resolves a domain name and returns its corresponding ip address.
|
||||
*
|
||||
* If an ip address is given, its integer representation is returned.
|
||||
* Otherwise, the domain name is resolved and its ip address is returned.
|
||||
*
|
||||
* \param to_resolve The domain name/ip address to resolve.
|
||||
*/
|
||||
IPv4Address resolve_domain(const std::string &to_resolve);
|
||||
|
||||
/**
|
||||
* \brief Resolves a domain name and returns its corresponding ip address.
|
||||
*
|
||||
* If an ip address is given, its integer representation is returned.
|
||||
* Otherwise, the domain name is resolved and its ip address is returned.
|
||||
*
|
||||
* \param to_resolve The domain name/ip address to resolve.
|
||||
*/
|
||||
IPv6Address resolve_domain6(const std::string &to_resolve);
|
||||
|
||||
/**
|
||||
* \brief Resolves the hardware address for a given ip.
|
||||
*
|
||||
* If the address can't be resolved, a std::runtime_error
|
||||
* exception is thrown.
|
||||
*
|
||||
* \param iface The interface in which the packet will be sent.
|
||||
* \param ip The ip to resolve, in integer format.
|
||||
* \param sender The sender to use to send and receive the ARP requests.
|
||||
* \return HWAddress<6> containing the resolved hardware address.
|
||||
*/
|
||||
HWAddress<6> resolve_hwaddr(const NetworkInterface &iface,
|
||||
IPv4Address ip, PacketSender &sender);
|
||||
|
||||
/**
|
||||
* \brief Resolves the hardware address for a given ip.
|
||||
*
|
||||
* If the address can't be resolved, a std::runtime_error
|
||||
* exception is thrown.
|
||||
*
|
||||
* This method sends and receives the packet through
|
||||
* PacketSender::default_interface.
|
||||
*
|
||||
* \param ip The ip to resolve, in integer format.
|
||||
* \param sender The sender to use to send and receive the ARP requests.
|
||||
* \return HWAddress<6> containing the resolved hardware address.
|
||||
*/
|
||||
HWAddress<6> resolve_hwaddr(IPv4Address ip, PacketSender &sender);
|
||||
|
||||
/** \brief List all network interfaces.
|
||||
*
|
||||
* Returns a set of strings, each of them representing the name
|
||||
* of a network interface. These names can be used as the input
|
||||
* interface for Utils::interface_ip, Utils::interface_hwaddr, etc.
|
||||
*/
|
||||
std::set<std::string> network_interfaces();
|
||||
|
||||
/**
|
||||
* \brief Finds the gateway's IP address for the given IP
|
||||
* address.
|
||||
*
|
||||
* \param ip The IP address for which the default gateway will
|
||||
* be searched.
|
||||
* \param gw_addr This parameter will contain the gateway's IP
|
||||
* address in case it is found.
|
||||
*
|
||||
* \return bool indicating wether the lookup was successfull.
|
||||
*/
|
||||
bool gateway_from_ip(IPv4Address ip, IPv4Address &gw_addr);
|
||||
|
||||
|
||||
/**
|
||||
* \brief Retrieves entries in the routing table.
|
||||
*
|
||||
* \brief output ForwardIterator in which entries will be stored.
|
||||
*/
|
||||
template<class ForwardIterator>
|
||||
void route_entries(ForwardIterator output);
|
||||
|
||||
/**
|
||||
* \brief Retrieves entries in the routing table.
|
||||
*
|
||||
* \return a vector which contains all of the route entries.
|
||||
*/
|
||||
std::vector<RouteEntry> route_entries();
|
||||
|
||||
/** \brief Returns the 32 bit crc of the given buffer.
|
||||
*
|
||||
* \param data The input buffer.
|
||||
* \param data_size The size of the input buffer.
|
||||
*/
|
||||
uint32_t crc32(const uint8_t* data, uint32_t data_size);
|
||||
|
||||
/**
|
||||
* \brief Converts a channel number to its mhz representation.
|
||||
* \param channel The channel number.
|
||||
* \return The channel's mhz representation.
|
||||
*/
|
||||
uint16_t channel_to_mhz(uint16_t channel);
|
||||
|
||||
/**
|
||||
* \brief Converts mhz units to the appropriate channel number.
|
||||
* \param mhz The mhz units to be converted.
|
||||
* \return The channel number.
|
||||
*/
|
||||
uint16_t mhz_to_channel(uint16_t mhz);
|
||||
|
||||
/**
|
||||
* \brief Converts a PDUType to a string.
|
||||
* \param pduType The PDUType to be converted.
|
||||
* \return A string representation, for example "DOT11_QOS_DATA".
|
||||
*/
|
||||
std::string to_string(PDU::PDUType pduType);
|
||||
|
||||
/** \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(const uint8_t *start, const 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(IPv4Address source_ip, IPv4Address dest_ip, uint32_t len, uint32_t flag);
|
||||
|
||||
/** \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(IPv6Address source_ip, IPv6Address dest_ip, uint32_t len, uint32_t flag);
|
||||
|
||||
/** \brief Generic function to iterate through interface and collect
|
||||
* data.
|
||||
*
|
||||
* The parameter is applied to every interface found, allowing
|
||||
* the object to collect data from them.
|
||||
* \param functor An instance of an class which implements operator(struct ifaddrs*).
|
||||
*/
|
||||
#ifndef WIN32
|
||||
template<class Functor>
|
||||
void generic_iface_loop(Functor &functor) {
|
||||
struct ifaddrs *ifaddrs = 0;
|
||||
struct ifaddrs *if_it = 0;
|
||||
getifaddrs(&ifaddrs);
|
||||
for(if_it = ifaddrs; if_it; if_it = if_it->ifa_next) {
|
||||
if(functor(if_it))
|
||||
break;
|
||||
}
|
||||
if(ifaddrs)
|
||||
freeifaddrs(ifaddrs);
|
||||
}
|
||||
#else // WIN32
|
||||
template<class Functor>
|
||||
void generic_iface_loop(Functor &functor) {
|
||||
ULONG size;
|
||||
::GetAdaptersAddresses(AF_INET, 0, 0, 0, &size);
|
||||
std::vector<uint8_t> buffer(size);
|
||||
if (::GetAdaptersAddresses(AF_INET, 0, 0, (IP_ADAPTER_ADDRESSES *)&buffer[0], &size) == ERROR_SUCCESS) {
|
||||
PIP_ADAPTER_ADDRESSES iface = (IP_ADAPTER_ADDRESSES *)&buffer[0];
|
||||
while(iface) {
|
||||
if(functor(iface))
|
||||
break;
|
||||
iface = iface->Next;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif // WIN32
|
||||
|
||||
template <typename T>
|
||||
struct is_pdu {
|
||||
template <typename U>
|
||||
static char test(typename U::PDUType*);
|
||||
|
||||
template <typename U>
|
||||
static long test(...);
|
||||
|
||||
static const bool value = sizeof(test<T>(0)) == 1;
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns the argument.
|
||||
*/
|
||||
inline PDU& dereference_until_pdu(PDU &pdu) {
|
||||
return pdu;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Dereferences the parameter until a PDU is found.
|
||||
*
|
||||
* This function dereferences the parameter until a PDU object
|
||||
* is found. When it's found, it is returned.
|
||||
*
|
||||
* \param value The parameter to be dereferenced.
|
||||
*/
|
||||
template<typename T>
|
||||
inline typename Internals::enable_if<!is_pdu<T>::value, PDU&>::type
|
||||
dereference_until_pdu(T &value) {
|
||||
return dereference_until_pdu(*value);
|
||||
}
|
||||
#if defined(BSD) || defined(__FreeBSD_kernel__)
|
||||
inline std::vector<char> query_route_table() {
|
||||
int mib[6];
|
||||
std::vector<char> buf;
|
||||
size_t len;
|
||||
|
||||
mib[0] = CTL_NET;
|
||||
mib[1] = AF_ROUTE;
|
||||
mib[2] = 0;
|
||||
mib[3] = AF_INET;
|
||||
mib[4] = NET_RT_DUMP;
|
||||
mib[5] = 0;
|
||||
if (sysctl(mib, 6, NULL, &len, NULL, 0) < 0)
|
||||
throw std::runtime_error("sysctl failed");
|
||||
|
||||
buf.resize(len);
|
||||
if (sysctl(mib, 6, &buf[0], &len, NULL, 0) < 0) {
|
||||
throw std::runtime_error("sysctl failed");
|
||||
}
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
template<typename ForwardIterator>
|
||||
void parse_header(struct rt_msghdr *rtm, ForwardIterator iter)
|
||||
{
|
||||
char *ptr = (char *)(rtm + 1);
|
||||
sockaddr *sa = 0;
|
||||
|
||||
for (int i = 0; i < RTAX_MAX; i++) {
|
||||
if (rtm->rtm_addrs & (1 << i)) {
|
||||
sa = (struct sockaddr *)ptr;
|
||||
ptr += sa->sa_len;
|
||||
if (sa->sa_family == 0)
|
||||
sa = 0;
|
||||
}
|
||||
*iter++ = sa;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
#if defined(BSD) || defined(__FreeBSD_kernel__)
|
||||
template<class ForwardIterator>
|
||||
void Tins::Utils::route_entries(ForwardIterator output) {
|
||||
std::vector<char> buffer = query_route_table();
|
||||
char *next = &buffer[0], *end = &buffer[buffer.size()];
|
||||
rt_msghdr *rtm;
|
||||
std::vector<sockaddr*> sa(RTAX_MAX);
|
||||
char iface_name[IF_NAMESIZE];
|
||||
while(next < end) {
|
||||
rtm = (rt_msghdr*)next;
|
||||
parse_header(rtm, sa.begin());
|
||||
if (sa[RTAX_DST] && sa[RTAX_GATEWAY] && if_indextoname(rtm->rtm_index, iface_name)) {
|
||||
RouteEntry entry;
|
||||
entry.destination = IPv4Address(((struct sockaddr_in *)sa[RTAX_DST])->sin_addr.s_addr);
|
||||
entry.gateway = IPv4Address(((struct sockaddr_in *)sa[RTAX_GATEWAY])->sin_addr.s_addr);
|
||||
if(sa[RTAX_GENMASK])
|
||||
entry.mask = IPv4Address(((struct sockaddr_in *)sa[RTAX_GENMASK])->sin_addr.s_addr);
|
||||
else
|
||||
entry.mask = IPv4Address(uint32_t());
|
||||
entry.interface = iface_name;
|
||||
*output++ = entry;
|
||||
}
|
||||
next += rtm->rtm_msglen;
|
||||
}
|
||||
}
|
||||
#elif defined(WIN32)
|
||||
template<class ForwardIterator>
|
||||
void Tins::Utils::route_entries(ForwardIterator output) {
|
||||
MIB_IPFORWARDTABLE *table;
|
||||
ULONG size = 0;
|
||||
char iface_name[256];
|
||||
GetIpForwardTable(0, &size, 0);
|
||||
std::vector<uint8_t> buffer(size);
|
||||
table = (MIB_IPFORWARDTABLE*)&buffer[0];
|
||||
GetIpForwardTable(table, &size, 0);
|
||||
|
||||
for (DWORD i = 0; i < table->dwNumEntries; i++) {
|
||||
MIB_IPFORWARDROW *row = &table->table[i];
|
||||
if(row->dwForwardType == MIB_IPROUTE_TYPE_INDIRECT) {
|
||||
RouteEntry entry;
|
||||
entry.interface = NetworkInterface::from_index(row->dwForwardIfIndex).name();
|
||||
entry.destination = IPv4Address(row->dwForwardDest);
|
||||
entry.mask = IPv4Address(row->dwForwardMask);
|
||||
entry.gateway = IPv4Address(row->dwForwardNextHop);
|
||||
*output++ = entry;
|
||||
}
|
||||
}
|
||||
}
|
||||
#else
|
||||
template<class ForwardIterator>
|
||||
void Tins::Utils::route_entries(ForwardIterator output) {
|
||||
using namespace Tins::Internals;
|
||||
std::ifstream input("/proc/net/route");
|
||||
std::string destination, mask, gw;
|
||||
uint32_t dummy;
|
||||
skip_line(input);
|
||||
RouteEntry entry;
|
||||
while(input >> entry.interface >> destination >> gw) {
|
||||
for(unsigned i(0); i < 5; ++i)
|
||||
input >> mask;
|
||||
from_hex(destination, dummy);
|
||||
entry.destination = IPv4Address(dummy);
|
||||
from_hex(mask, dummy);
|
||||
entry.mask = IPv4Address(dummy);
|
||||
from_hex(gw, dummy);
|
||||
entry.gateway = IPv4Address(dummy);
|
||||
skip_line(input);
|
||||
*output = entry;
|
||||
++output;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // TINS_UTILS_H
|
||||
Reference in New Issue
Block a user