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

Added malformed_packet exception. Every class except Dot11* use it.

This commit is contained in:
Matias Fontanini
2013-04-18 00:12:20 -03:00
parent 923f51ae15
commit 3fd1b3d37d
53 changed files with 267 additions and 159 deletions

View File

@@ -97,4 +97,5 @@ libtins_include_HEADERS = include/internals.h \
include/constants.h \
include/utils.h \
include/cxxstd.h \
include/stp.h
include/stp.h \
include/exceptions.h

View File

@@ -57,7 +57,8 @@ subdir = .
DIST_COMMON = README $(am__configure_deps) $(libtins_include_HEADERS) \
$(srcdir)/Makefile.am $(srcdir)/Makefile.in \
$(srcdir)/libtins.pc.in $(top_srcdir)/configure AUTHORS THANKS \
config.guess config.sub depcomp install-sh ltmain.sh missing
TODO config.guess config.sub depcomp install-sh ltmain.sh \
missing
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
am__aclocal_m4_deps = $(top_srcdir)/m4/libtool.m4 \
$(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \

View File

@@ -82,8 +82,14 @@ namespace Tins {
const hwaddress_type &sender_hw = hwaddress_type());
/**
* \brief Constructor which creates an ARP object from a buffer and adds all identifiable
* PDUs found in the buffer as children of this one.
* \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.
*/

View File

@@ -84,8 +84,11 @@ namespace Tins {
BootP();
/**
* \brief Constructor which creates a BootP object from a buffer and adds all identifiable
* PDUs found in the buffer as children of this one.
* \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.

View File

@@ -163,8 +163,12 @@ namespace Tins {
DHCP();
/**
* \brief Constructor which creates a DHCP object from a buffer and adds all identifiable
* PDUs found in the buffer as children of this one.
* \brief Constructs a DHCP object from a buffer.
*
* If there is not enough size for a BootP header, or any of
* the TLV options contain 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.
* Subclasses might use 0 to provide their own interpretation of this field.

View File

@@ -388,9 +388,12 @@ public:
DHCPv6();
/**
* \brief Constructor which constructs a DHCPv6 object from a buffer
* and adds all identifiable PDUs found in the buffer as children
* of this one.
* \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.
*/

View File

@@ -252,7 +252,11 @@ namespace Tins {
DNS();
/**
* \brief Constructor which creates a DNS object from a buffer.
* \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.

View File

@@ -68,6 +68,10 @@ public:
/**
* \brief Constructs a record.
*
* If the input data is malformed, a malformed_packet exception
* is thrown.
*
* \param buffer A pointer to the start of the data buffer.
* \param len The length of the data.
*/

View File

@@ -48,9 +48,14 @@ public:
Dot1Q(small_uint<12> tag_id = 0, bool append_pad = true);
/**
* \brief Constructor which creates an Dot1Q object from a buffer and
* adds all identifiable PDUs found in the buffer as children of this
* one.
* \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.

View File

@@ -76,8 +76,12 @@ namespace Tins {
PDU* child = 0);
/**
* \brief Constructor which creates an Dot3 object from a buffer and adds all identifiable
* PDUs found in the buffer as children of this one.
* \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.
*/

View File

@@ -67,6 +67,12 @@ namespace Tins {
/**
* \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.
*/
@@ -197,12 +203,16 @@ namespace Tins {
static const size_t key_sign_size = 16;
/**
* \brief Creates an instance of RC4EAPOL
* \brief Default constructor.
*/
RC4EAPOL();
/**
* \brief Constructor which creates an RC4EAPOL object from a buffer.
* \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.
*/
@@ -396,7 +406,11 @@ namespace Tins {
RSNEAPOL();
/**
* \brief Constructor which creates an RSNEAPOL object from a buffer.
* \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.
*/

View File

@@ -76,8 +76,14 @@ namespace Tins {
PDU* child = 0);
/**
* \brief Constructor which creates an EthernetII object from a buffer and adds all identifiable
* PDUs found in the buffer as children of this one.
* \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.

View File

@@ -71,8 +71,13 @@ namespace Tins {
ICMP(Flags flag = ECHO_REQUEST);
/**
* \brief Constructor which creates an ICMP object from a buffer and adds all identifiable
* PDUs found in the buffer as children of this one.
* \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.
*/

View File

@@ -434,8 +434,12 @@ public:
ICMPv6(Types tp = ECHO_REQUEST);
/**
* \brief Constructor which creates an ICMP object from a buffer and
* adds all identifiable PDUs found in the buffer as children of this one.
* \brief Constructs an ICMPv6 object from a buffer.
*
* If there is not enough size for an ICMPv6 header, a
* malformed_packet exception is thrown.
*
* Any 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.

View File

@@ -239,9 +239,13 @@ namespace Tins {
PDU *child = 0);
/**
* \brief Constructor which constructs an IP object from a buffer
* and adds all identifiable PDUs found in the buffer as children
* of this one.
* \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.
*/

View File

@@ -84,17 +84,6 @@ public:
NO_NEXT_HEADER = 59
};
/**
* Exception thrown when an invalid extension header size is
* encountered.
*/
class header_size_error : public std::exception {
public:
const char *what() const throw() {
return "Not enough size for an extension header";
}
};
/**
* \brief Constructs an IPv6 object.
*
@@ -108,9 +97,11 @@ public:
PDU *child = 0);
/**
* \brief Constructor which creates an IPv6 object from a buffer and
* adds all identifiable PDUs found in the buffer as children of this
* one.
* \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.

View File

@@ -104,8 +104,12 @@ namespace Tins {
LLC(uint8_t dsap, uint8_t ssap, PDU* child = 0);
/**
* \brief Constructor which creates a LLC object from a buffer and adds all identifiable
* PDUs found in the buffer as children of this one.
* \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.
*/

View File

@@ -61,7 +61,14 @@ public:
Loopback(const NetworkInterface &iface, PDU *inner_pdu = 0);
/**
* \brief Construct a Loopback object from a buffer.
* \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.

View File

@@ -133,14 +133,14 @@ namespace Tins {
*
* \param rhs The PDU to be moved.
*/
PDU(PDU &&rhs);
PDU(PDU &&rhs) noexcept;
/**
* \brief Move assignment operator.
*
* \param rhs The PDU to be moved.
*/
PDU& operator=(PDU &&rhs);
PDU& operator=(PDU &&rhs) noexcept;
#endif
/**

View File

@@ -33,18 +33,9 @@
#include <vector>
#include <iterator>
#include <stdint.h>
#include "exceptions.h"
namespace Tins {
/**
* \brief Exception thrown when an option is not found.
*/
class option_not_found : public std::exception {
public:
const char* what() const throw() {
return "Option not found";
}
};
/**
* \class PDUOption
* \brief Represents a PDU option field.

View File

@@ -107,6 +107,9 @@ public:
/**
* \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.
*/

View File

@@ -116,8 +116,12 @@ namespace Tins {
PDU *child = 0);
/**
* \brief Constructor which creates a RadioTap object from a buffer and adds all
* \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.
*/

View File

@@ -89,7 +89,10 @@ namespace Tins{
RSNInformation(const serialization_type &buffer);
/**
* \brief Constructor from 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.

View File

@@ -54,9 +54,14 @@ public:
SLL();
/**
* \brief Constructor which constructs an SLL object from a buffer
* and adds all identifiable PDUs found in the buffer as children
* of this one.
* \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.
*/

View File

@@ -61,8 +61,14 @@ namespace Tins {
SNAP(PDU *child = 0);
/**
* \brief Constructor which creates a SNAP object from a buffer and adds all identifiable
* PDUs found in the buffer as children of this one.
* \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.
*/

View File

@@ -48,9 +48,11 @@ public:
STP();
/**
* \brief Constructor which constructs an STP object from a buffer
* and adds all identifiable PDUs found in the buffer as children
* of this one.
* \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.
*/

View File

@@ -129,9 +129,14 @@ namespace Tins {
TCP(uint16_t dport = 0, uint16_t sport = 0);
/**
* \brief Constructor which creates an TCP object from a buffer
* and adds all identifiable PDUs found in the buffer as children
* of this one.
* \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.
*/

View File

@@ -60,8 +60,13 @@ namespace Tins {
UDP(uint16_t dport = 0, uint16_t sport = 0, PDU *child = 0);
/**
* \brief Constructor which creates an UDP object from a buffer and adds all identifiable
* PDUs found in the buffer as children of this one.
* \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.
*/

View File

@@ -36,6 +36,7 @@
#include "rawpdu.h"
#include "constants.h"
#include "network_interface.h"
#include "exceptions.h"
using std::runtime_error;
@@ -59,7 +60,7 @@ ARP::ARP(ipaddress_type target_ip, ipaddress_type sender_ip,
ARP::ARP(const uint8_t *buffer, uint32_t total_sz)
{
if(total_sz < sizeof(arphdr))
throw runtime_error("Not enough size for an ARP header in the buffer.");
throw malformed_packet();
memcpy(&_arp, buffer, sizeof(arphdr));
total_sz -= sizeof(arphdr);
if(total_sz)

View File

@@ -31,6 +31,7 @@
#include <cstring>
#include <cassert>
#include "bootp.h"
#include "exceptions.h"
namespace Tins{
BootP::BootP()
@@ -42,7 +43,7 @@ BootP::BootP(const uint8_t *buffer, uint32_t total_sz, uint32_t vend_field_size)
: _vend(vend_field_size)
{
if(total_sz < sizeof(bootphdr) + vend_field_size)
throw std::runtime_error("Not enough size for a BootP header in the buffer.");
throw malformed_packet();
std::memcpy(&_bootp, buffer, sizeof(bootphdr));
buffer += sizeof(bootphdr);
total_sz -= sizeof(bootphdr);

View File

@@ -32,6 +32,7 @@
#include "endianness.h"
#include "dhcp.h"
#include "ethernetII.h"
#include "exceptions.h"
using std::string;
using std::list;
@@ -52,7 +53,7 @@ DHCP::DHCP(const uint8_t *buffer, uint32_t total_sz)
total_sz -= BootP::header_size() - vend().size();
uint8_t args[2] = {0};
if(total_sz < sizeof(uint32_t) || *(uint32_t*)buffer != Endian::host_to_be<uint32_t>(0x63825363))
throw std::runtime_error("Not enough size for a DHCP header in the buffer.");
throw malformed_packet();
buffer += sizeof(uint32_t);
total_sz -= sizeof(uint32_t);
while(total_sz) {
@@ -64,11 +65,13 @@ DHCP::DHCP(const uint8_t *buffer, uint32_t total_sz)
i = 2;
}
else if(!total_sz)
throw std::runtime_error("Not enough size for a DHCP header in the buffer.");
throw malformed_packet();
}
if(total_sz < args[1])
throw std::runtime_error("Not enough size for a DHCP header in the buffer.");
add_option(option((OptionTypes)args[0], args[1], buffer));
throw malformed_packet();
add_option(
option((OptionTypes)args[0], args[1], buffer)
);
buffer += args[1];
total_sz -= args[1];
}

View File

@@ -30,6 +30,7 @@
#include <vector>
#include <algorithm>
#include "dhcpv6.h"
#include "exceptions.h"
namespace Tins {
DHCPv6::DHCPv6() : options_size() {
@@ -39,21 +40,19 @@ DHCPv6::DHCPv6() : options_size() {
DHCPv6::DHCPv6(const uint8_t *buffer, uint32_t total_sz)
: options_size()
{
const char *err_msg = "Not enough size for a DHCPv6 header",
*opt_err_msg = "Not enough size for a DHCPv6 option";
if(total_sz == 0)
throw std::runtime_error(err_msg);
throw malformed_packet();
// Relay Agent/Server Messages
bool is_relay_msg = (buffer[0] == 12 || buffer[0] == 13);
uint32_t required_size = is_relay_msg ? 2 : 4;
if(total_sz < required_size)
throw std::runtime_error(err_msg);
throw malformed_packet();
std::copy(buffer, buffer + required_size, header_data);
buffer += required_size;
total_sz -= required_size;
if(is_relay_message()) {
if(total_sz < ipaddress_type::address_size * 2)
throw std::runtime_error(err_msg);
throw malformed_packet();
link_addr = buffer;
peer_addr = buffer + ipaddress_type::address_size;
buffer += ipaddress_type::address_size * 2;
@@ -62,14 +61,14 @@ DHCPv6::DHCPv6(const uint8_t *buffer, uint32_t total_sz)
options_size = total_sz;
while(total_sz) {
if(total_sz < sizeof(uint16_t) * 2)
throw std::runtime_error(opt_err_msg);
throw malformed_packet();
const uint16_t opt = Endian::be_to_host(*(const uint16_t*)buffer);
const uint16_t data_size = Endian::be_to_host(
*(const uint16_t*)(buffer + sizeof(uint16_t))
);
if(total_sz - sizeof(uint16_t) * 2 < data_size)
throw std::runtime_error(opt_err_msg);
throw malformed_packet();
buffer += sizeof(uint16_t) * 2;
add_option(
option(opt, buffer, buffer + data_size)

View File

@@ -35,6 +35,8 @@
#include "dns.h"
#include "ip_address.h"
#include "ipv6_address.h"
#include "exceptions.h"
#include "rawpdu.h"
using std::string;
using std::list;
@@ -47,7 +49,7 @@ DNS::DNS() : extra_size(0) {
DNS::DNS(const uint8_t *buffer, uint32_t total_sz) : extra_size(0) {
if(total_sz < sizeof(dnshdr))
throw std::runtime_error("Not enough size for a DNS header in the buffer.");
throw malformed_packet();
std::memcpy(&dns, buffer, sizeof(dnshdr));
const uint8_t *end(buffer + total_sz);
uint16_t nquestions(questions_count());
@@ -59,7 +61,7 @@ DNS::DNS(const uint8_t *buffer, uint32_t total_sz) : extra_size(0) {
ptr++;
Query query;
if((ptr + (sizeof(uint16_t) * 2)) >= end)
throw std::runtime_error("Not enough size for a given query.");
throw malformed_packet();
query.dname(string(buffer, ptr));
ptr++;
const uint16_t *opt_ptr = reinterpret_cast<const uint16_t*>(ptr);
@@ -73,6 +75,8 @@ DNS::DNS(const uint8_t *buffer, uint32_t total_sz) : extra_size(0) {
buffer = build_resource_list(ans, buffer, total_sz, answers_count());
buffer = build_resource_list(arity, buffer, total_sz, authority_count());
build_resource_list(addit, buffer, total_sz, additional_count());
if(total_sz)
inner_pdu(new RawPDU(buffer, total_sz));
}
const uint8_t *DNS::build_resource_list(ResourcesType &lst, const uint8_t *ptr, uint32_t &sz, uint16_t nrecs) {
@@ -81,7 +85,7 @@ const uint8_t *DNS::build_resource_list(ResourcesType &lst, const uint8_t *ptr,
for(uint16_t i(0); i < nrecs; ++i) {
const uint8_t *this_opt_start(ptr);
if(ptr + sizeof(uint16_t) > ptr_end)
throw std::runtime_error("Not enough size for a given resource.");
throw malformed_packet();
lst.push_back(DNSResourceRecord(ptr, ptr_end - ptr));
ptr += lst.back().size();
extra_size += ptr - this_opt_start;
@@ -386,7 +390,7 @@ void DNS::compose_name(const uint8_t *ptr, uint32_t sz, std::string &out) const
// We need at least a suffix or a suffix index to compose
// the domain name
if(it == suffixes.end() && suff_it == suffix_indices.end())
throw std::runtime_error("Malformed DNS packet");
throw malformed_packet();
bool first(true);
do {
if(it != suffixes.end()) {

View File

@@ -33,6 +33,7 @@
#include <typeinfo>
#include "dns_record.h"
#include "endianness.h"
#include "exceptions.h"
namespace Tins {
bool contains_dname(uint16_t type) {
@@ -65,17 +66,17 @@ DNSResourceRecord::DNSResourceRecord(const uint8_t *buffer, uint32_t size)
while(str_end < buffer_end && *str_end)
str_end++;
if(str_end == buffer_end)
throw std::runtime_error("Not enough size for a resource domain name.");
throw malformed_packet();
//str_end++;
tmp_impl.reset(new NamedDNSRRImpl(buffer, str_end));
buffer = ++str_end;
}
if(buffer + sizeof(info_) > buffer_end)
throw std::runtime_error("Not enough size for a resource info.");
throw malformed_packet();
std::memcpy(&info_, buffer, sizeof(info_));
buffer += sizeof(info_);
if(buffer + sizeof(uint16_t) > buffer_end)
throw std::runtime_error("Not enough size for resource data size.");
throw malformed_packet();
// Store the option size.
data.resize(
@@ -83,7 +84,7 @@ DNSResourceRecord::DNSResourceRecord(const uint8_t *buffer, uint32_t size)
);
buffer += sizeof(uint16_t);
if(buffer + data.size() > buffer_end)
throw std::runtime_error("Not enough size for resource data");
throw malformed_packet();
if(contains_dname(info_.type) || data.size() != sizeof(uint32_t))
std::copy(buffer, buffer + data.size(), data.begin());
else if(data.size() == sizeof(uint32_t))

View File

@@ -32,6 +32,7 @@
#include <cassert>
#include "dot1q.h"
#include "internals.h"
#include "exceptions.h"
namespace Tins {
@@ -45,7 +46,7 @@ Dot1Q::Dot1Q(const uint8_t *buffer, uint32_t total_sz)
: _append_padding()
{
if(total_sz < sizeof(_header))
throw std::runtime_error("Not enough size for a Dot1Q header");
throw malformed_packet();
std::memcpy(&_header, buffer, sizeof(_header));
buffer += sizeof(_header);
total_sz -= sizeof(_header);

View File

@@ -44,6 +44,7 @@
#include "dot3.h"
#include "packet_sender.h"
#include "llc.h"
#include "exceptions.h"
namespace Tins {
const Dot3::address_type Dot3::BROADCAST("ff:ff:ff:ff:ff:ff");
@@ -64,7 +65,7 @@ Dot3::Dot3(const NetworkInterface& iface,
Dot3::Dot3(const uint8_t *buffer, uint32_t total_sz)
{
if(total_sz < sizeof(ethhdr))
throw std::runtime_error("Not enough size for an ethernetII header in the buffer.");
throw malformed_packet();
memcpy(&_eth, buffer, sizeof(ethhdr));
buffer += sizeof(ethhdr);
total_sz -= sizeof(ethhdr);

View File

@@ -33,7 +33,7 @@
#include "eapol.h"
#include "dot11.h"
#include "rsn_information.h"
#include "exceptions.h"
namespace Tins {
EAPOL::EAPOL(uint8_t packet_type, EAPOLTYPE type)
@@ -47,13 +47,13 @@ EAPOL::EAPOL(uint8_t packet_type, EAPOLTYPE type)
EAPOL::EAPOL(const uint8_t *buffer, uint32_t total_sz)
{
if(total_sz < sizeof(_header))
throw std::runtime_error("Not enough size for an EAPOL header in the buffer.");
throw malformed_packet();
std::memcpy(&_header, buffer, sizeof(_header));
}
EAPOL *EAPOL::from_bytes(const uint8_t *buffer, uint32_t total_sz) {
if(total_sz < sizeof(eapolhdr))
throw std::runtime_error("Not enough size for an EAPOL header in the buffer.");
throw malformed_packet();
const eapolhdr *ptr = (const eapolhdr*)buffer;
switch(ptr->type) {
case RC4:
@@ -86,8 +86,6 @@ void EAPOL::type(uint8_t new_type) {
void EAPOL::write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *) {
uint32_t sz = header_size();
assert(total_sz >= sz);
//if(!_header.length)
// length(sz - sizeof(_header.version) - sizeof(_header.length) - sizeof(_header.type));
std::memcpy(buffer, &_header, sizeof(_header));
write_body(buffer + sizeof(_header), total_sz - sizeof(_header));
}
@@ -106,7 +104,7 @@ RC4EAPOL::RC4EAPOL(const uint8_t *buffer, uint32_t total_sz)
buffer += sizeof(eapolhdr);
total_sz -= sizeof(eapolhdr);
if(total_sz < sizeof(_header))
throw std::runtime_error("Not enough size for an EAPOL header in the buffer.");
throw malformed_packet();
std::memcpy(&_header, buffer, sizeof(_header));
buffer += sizeof(_header);
total_sz -= sizeof(_header);
@@ -171,7 +169,7 @@ RSNEAPOL::RSNEAPOL(const uint8_t *buffer, uint32_t total_sz)
buffer += sizeof(eapolhdr);
total_sz -= sizeof(eapolhdr);
if(total_sz < sizeof(_header))
throw std::runtime_error("Not enough size for an EAPOL header in the buffer.");
throw malformed_packet();
std::memcpy(&_header, buffer, sizeof(_header));
buffer += sizeof(_header);
total_sz -= sizeof(_header);

View File

@@ -49,6 +49,7 @@
#include "arp.h"
#include "constants.h"
#include "internals.h"
#include "exceptions.h"
namespace Tins {
const EthernetII::address_type EthernetII::BROADCAST("ff:ff:ff:ff:ff:ff");
@@ -69,7 +70,7 @@ EthernetII::EthernetII(const NetworkInterface& iface,
EthernetII::EthernetII(const uint8_t *buffer, uint32_t total_sz)
{
if(total_sz < sizeof(ethhdr))
throw std::runtime_error("Not enough size for an ethernetII header in the buffer.");
throw malformed_packet();
memcpy(&_eth, buffer, sizeof(ethhdr));
buffer += sizeof(ethhdr);
total_sz -= sizeof(ethhdr);

View File

@@ -37,6 +37,7 @@
#include "icmp.h"
#include "rawpdu.h"
#include "utils.h"
#include "exceptions.h"
Tins::ICMP::ICMP(Flags flag)
{
@@ -47,7 +48,7 @@ Tins::ICMP::ICMP(Flags flag)
Tins::ICMP::ICMP(const uint8_t *buffer, uint32_t total_sz)
{
if(total_sz < sizeof(icmphdr))
throw std::runtime_error("Not enough size for an ICMP header in the buffer.");
throw malformed_packet();
std::memcpy(&_icmp, buffer, sizeof(icmphdr));
total_sz -= sizeof(icmphdr);
if(total_sz)

View File

@@ -34,6 +34,7 @@
#include "rawpdu.h"
#include "utils.h"
#include "constants.h"
#include "exceptions.h"
namespace Tins {
@@ -48,27 +49,27 @@ ICMPv6::ICMPv6(const uint8_t *buffer, uint32_t total_sz)
: _options_size(), reach_time(0), retrans_timer(0)
{
if(total_sz < sizeof(_header))
throw std::runtime_error("Not enough size for an ICMPv6 header");
throw malformed_packet();
std::memcpy(&_header, buffer, sizeof(_header));
buffer += sizeof(_header);
total_sz -= sizeof(_header);
if(has_target_addr()) {
if(total_sz < ipaddress_type::address_size)
throw std::runtime_error("Not enough size for the target address");
throw malformed_packet();
target_addr(buffer);
buffer += ipaddress_type::address_size;
total_sz -= ipaddress_type::address_size;
}
if(has_dest_addr()) {
if(total_sz < ipaddress_type::address_size)
throw std::runtime_error("Not enough size for the destination address");
throw malformed_packet();
dest_addr(buffer);
buffer += ipaddress_type::address_size;
total_sz -= ipaddress_type::address_size;
}
if(type() == ROUTER_ADVERT) {
if(total_sz < sizeof(uint32_t) * 2)
throw std::runtime_error("Not enough size for router advert fields");
throw malformed_packet();
const uint32_t *ptr_32 = (const uint32_t*)buffer;
reach_time = *ptr_32++;
retrans_timer = *ptr_32++;
@@ -85,9 +86,15 @@ ICMPv6::ICMPv6(const uint8_t *buffer, uint32_t total_sz)
void ICMPv6::parse_options(const uint8_t *&buffer, uint32_t &total_sz) {
while(total_sz > 0) {
if(total_sz < 8 || (static_cast<uint32_t>(buffer[1]) * 8) > total_sz || buffer[1] < 1)
throw std::runtime_error("Not enough size for options");
throw malformed_packet();
// size(option) = option_size - identifier_size - length_identifier_size
add_option(option(buffer[0], static_cast<uint32_t>(buffer[1]) * 8 - sizeof(uint8_t) * 2, buffer + 2));
add_option(
option(
buffer[0],
static_cast<uint32_t>(buffer[1]) * 8 - sizeof(uint8_t) * 2,
buffer + 2
)
);
total_sz -= buffer[1] * 8;
buffer += buffer[1] * 8;
}

View File

@@ -49,6 +49,7 @@
#include "packet_sender.h"
#include "constants.h"
#include "network_interface.h"
#include "exceptions.h"
using std::list;
@@ -66,18 +67,17 @@ IP::IP(address_type ip_dst, address_type ip_src, PDU *child)
IP::IP(const uint8_t *buffer, uint32_t total_sz)
{
const char *msg = "Not enough size for an IP header in the buffer.";
if(total_sz < sizeof(iphdr))
throw std::runtime_error(msg);
throw malformed_packet();
std::memcpy(&_ip, buffer, sizeof(iphdr));
/* Options... */
/* Establish beginning and ending of the options */
const uint8_t* ptr_buffer = buffer + sizeof(iphdr);
if(total_sz < head_len() * sizeof(uint32_t))
throw std::runtime_error(msg);
throw malformed_packet();
if(head_len() * sizeof(uint32_t) < sizeof(iphdr))
throw std::runtime_error("Malformed head len field");
throw malformed_packet();
buffer += head_len() * sizeof(uint32_t);
_options_size = 0;
@@ -91,13 +91,13 @@ IP::IP(const uint8_t *buffer, uint32_t total_sz)
if(opt_type.number > NOOP) {
/* Multibyte options with length as second byte */
if(ptr_buffer == buffer || *ptr_buffer == 0)
throw std::runtime_error(msg);
throw malformed_packet();
const uint8_t data_size = *ptr_buffer - 2;
if(data_size > 0) {
ptr_buffer++;
if(buffer - ptr_buffer < data_size)
throw std::runtime_error(msg);
throw malformed_packet();
_ip_options.push_back(option(opt_type, ptr_buffer, ptr_buffer + data_size));
}
else

View File

@@ -45,6 +45,7 @@
#include "icmp.h"
#include "icmpv6.h"
#include "rawpdu.h"
#include "exceptions.h"
namespace Tins {
@@ -60,7 +61,7 @@ IPv6::IPv6(address_type ip_dst, address_type ip_src, PDU *child)
IPv6::IPv6(const uint8_t *buffer, uint32_t total_sz)
: headers_size(0) {
if(total_sz < sizeof(_header))
throw std::runtime_error("Not enough size for an IPv6 PDU");
throw malformed_packet();
std::memcpy(&_header, buffer, sizeof(_header));
buffer += sizeof(_header);
total_sz -= sizeof(_header);
@@ -68,13 +69,13 @@ IPv6::IPv6(const uint8_t *buffer, uint32_t total_sz)
while(total_sz) {
if(is_extension_header(current_header)) {
if(total_sz < 8)
throw header_size_error();
throw malformed_packet();
// every ext header is at least 8 bytes long
// minus one, from the next_header field.
uint32_t size = static_cast<uint32_t>(buffer[1]) + 8;
// -1 -> next header identifier
if(total_sz < size)
throw header_size_error();
throw malformed_packet();
// minus one, from the size field
add_ext_header(
ext_header(buffer[0], size - sizeof(uint8_t)*2, buffer + 2)

View File

@@ -33,6 +33,7 @@
#include "llc.h"
#include "stp.h"
#include "rawpdu.h"
#include "exceptions.h"
using std::list;
@@ -62,14 +63,14 @@ LLC::LLC(uint8_t dsap, uint8_t ssap, PDU *child)
LLC::LLC(const uint8_t *buffer, uint32_t total_sz) {
// header + 1 info byte
if(total_sz < sizeof(_header) + 1)
throw std::runtime_error("Not enough size for a LLC header in the buffer.");
throw malformed_packet();
std::memcpy(&_header, buffer, sizeof(_header));
buffer += sizeof(_header);
total_sz -= sizeof(_header);
information_field_length = 0;
if ((buffer[0] & 0x03) == LLC::UNNUMBERED) {
if(total_sz < sizeof(un_control_field))
throw std::runtime_error("Not enough size for a LLC header in the buffer.");
throw malformed_packet();
type(LLC::UNNUMBERED);
std::memcpy(&control_field.unnumbered, buffer, sizeof(un_control_field));
buffer += sizeof(un_control_field);
@@ -78,7 +79,7 @@ LLC::LLC(const uint8_t *buffer, uint32_t total_sz) {
}
else {
if(total_sz < sizeof(info_control_field))
throw std::runtime_error("Not enough size for a LLC header in the buffer.");
throw malformed_packet();
type((Format)(buffer[0] & 0x03));
control_field_length = 2;
std::memcpy(&control_field.info, buffer, sizeof(info_control_field));

View File

@@ -43,6 +43,7 @@
#include "ip.h"
#include "llc.h"
#include "rawpdu.h"
#include "exceptions.h"
#if !defined(PF_LLC)
// compilation fix, nasty but at least works on BSD
@@ -65,7 +66,7 @@ Loopback::Loopback(const NetworkInterface &iface, PDU *inner_pdu)
Loopback::Loopback(const uint8_t *buffer, uint32_t total_sz)
{
if(total_sz < sizeof(_family))
throw std::runtime_error("Not enough size for a loopback PDU");
throw malformed_packet();
_family = *reinterpret_cast<const uint32_t*>(buffer);
buffer += sizeof(uint32_t);
total_sz -= sizeof(uint32_t);

View File

@@ -39,13 +39,13 @@ PDU::PDU(PDU *next_pdu) : _inner_pdu(next_pdu) {
}
#if TINS_IS_CXX11
PDU::PDU(PDU &&rhs)
PDU::PDU(PDU &&rhs) noexcept
: _inner_pdu(0)
{
std::swap(_inner_pdu, rhs._inner_pdu);
}
PDU& PDU::operator=(PDU &&rhs) {
PDU& PDU::operator=(PDU &&rhs) noexcept {
std::swap(_inner_pdu, rhs._inner_pdu);
return *this;
}

View File

@@ -32,6 +32,7 @@
#endif
#include <cstring>
#include "pppoe.h"
#include "exceptions.h"
namespace Tins {
@@ -45,22 +46,21 @@ PPPoE::PPPoE()
PPPoE::PPPoE(const uint8_t *buffer, uint32_t total_sz)
: _tags_size()
{
const char *err_msg = "Not enough size for a PPPoE";
if(total_sz < sizeof(_header))
throw std::runtime_error(err_msg);
throw malformed_packet();
std::memcpy(&_header, buffer, sizeof(_header));
buffer += sizeof(_header);
total_sz -= sizeof(_header);
const uint8_t *end = buffer + total_sz;
while(buffer < end) {
if(buffer + sizeof(uint32_t) * 2 > end)
throw std::runtime_error(err_msg);
throw malformed_packet();
uint16_t opt_type = *(const uint16_t*)buffer;
uint16_t opt_len = *(const uint16_t*)(buffer + sizeof(uint16_t));
buffer += sizeof(uint16_t) * 2;
total_sz -= sizeof(uint16_t) * 2;
if(Endian::be_to_host(opt_len) > total_sz)
throw std::runtime_error(err_msg);
throw malformed_packet();
add_tag(
tag(
static_cast<TagTypes>(opt_type),

View File

@@ -43,12 +43,12 @@
#include "dot11.h"
#include "utils.h"
#include "packet_sender.h"
#include "exceptions.h"
namespace Tins {
void check_size(uint32_t total_sz, size_t field_size) {
static const std::string msg("Not enough size for an RadioTap header in the buffer.");
if(total_sz < field_size)
throw std::runtime_error(msg);
throw malformed_packet();
}
template<typename T>

View File

@@ -29,12 +29,13 @@
#include <stdexcept>
#include "rsn_information.h"
#include "exceptions.h"
namespace Tins {
template<typename T>
void check_size(uint32_t total_sz, const char* err_msg) {
void check_size(uint32_t total_sz) {
if(total_sz < sizeof(T))
throw std::runtime_error(err_msg);
throw malformed_packet();
}
RSNInformation::RSNInformation() : _version(1), _capabilities(0) {
@@ -50,9 +51,8 @@ RSNInformation::RSNInformation(const uint8_t *buffer, uint32_t total_sz) {
}
void RSNInformation::init(const uint8_t *buffer, uint32_t total_sz) {
const char *err_msg = "Malformed RSN information structure";
if(total_sz <= sizeof(uint16_t) * 2 + sizeof(uint32_t))
throw std::runtime_error(err_msg);
throw malformed_packet();
version(Endian::le_to_host(*(uint16_t*)buffer));
buffer += sizeof(uint16_t);
total_sz -= sizeof(uint16_t);
@@ -66,25 +66,25 @@ void RSNInformation::init(const uint8_t *buffer, uint32_t total_sz) {
total_sz -= sizeof(uint16_t);
if(count * sizeof(uint32_t) > total_sz)
throw std::runtime_error(err_msg);
throw malformed_packet();
total_sz -= count * sizeof(uint32_t);
while(count--) {
add_pairwise_cypher((RSNInformation::CypherSuites)*(uint32_t*)buffer);
buffer += sizeof(uint32_t);
}
check_size<uint16_t>(total_sz, err_msg);
check_size<uint16_t>(total_sz);
count = *(uint16_t*)buffer;
buffer += sizeof(uint16_t);
total_sz -= sizeof(uint16_t);
if(count * sizeof(uint32_t) > total_sz)
throw std::runtime_error(err_msg);
throw malformed_packet();
total_sz -= count * sizeof(uint32_t);
while(count--) {
add_akm_cypher((RSNInformation::AKMSuites)*(uint32_t*)buffer);
buffer += sizeof(uint32_t);
}
check_size<uint16_t>(total_sz, err_msg);
check_size<uint16_t>(total_sz);
capabilities(Endian::le_to_host(*(uint16_t*)buffer));
}

View File

@@ -31,6 +31,7 @@
#include <cstring>
#include "sll.h"
#include "internals.h"
#include "exceptions.h"
namespace Tins {
SLL::SLL() : _header() {
@@ -38,9 +39,8 @@ SLL::SLL() : _header() {
}
SLL::SLL(const uint8_t *buffer, uint32_t total_sz) {
const char *err_msg = "Not enough size for a SLL header";
if(total_sz < sizeof(_header))
throw std::runtime_error(err_msg);
throw malformed_packet();
std::memcpy(&_header, buffer, sizeof(_header));
buffer += sizeof(_header);
total_sz -= sizeof(_header);

View File

@@ -39,6 +39,7 @@
#include "ip.h"
#include "eapol.h"
#include "internals.h"
#include "exceptions.h"
Tins::SNAP::SNAP(PDU *child) : PDU(child)
@@ -51,22 +52,11 @@ Tins::SNAP::SNAP(PDU *child) : PDU(child)
Tins::SNAP::SNAP(const uint8_t *buffer, uint32_t total_sz)
{
if(total_sz < sizeof(_snap))
throw std::runtime_error("Not enough size for a SNAP header in the buffer.");
throw malformed_packet();
std::memcpy(&_snap, buffer, sizeof(_snap));
buffer += sizeof(_snap);
total_sz -= sizeof(_snap);
if(total_sz) {
/*switch(eth_type()) {
case Tins::Constants::Ethernet::IP:
inner_pdu(new Tins::IP(buffer, total_sz));
break;
case Tins::Constants::Ethernet::ARP:
inner_pdu(new Tins::ARP(buffer, total_sz));
break;
case Tins::Constants::Ethernet::EAPOL:
inner_pdu(Tins::EAPOL::from_bytes(buffer, total_sz));
break;
};*/
inner_pdu(
Internals::pdu_from_flag(
(Constants::Ethernet::e)eth_type(),

View File

@@ -30,6 +30,7 @@
#include <cstring>
#include <cassert>
#include "stp.h"
#include "exceptions.h"
namespace Tins {
@@ -42,7 +43,7 @@ STP::STP()
STP::STP(const uint8_t *buffer, uint32_t total_sz)
{
if(total_sz < sizeof(_header))
throw std::runtime_error("Not enough size.");
throw malformed_packet();
std::memcpy(&_header, buffer ,sizeof(_header));
}

View File

@@ -35,6 +35,7 @@
#include "constants.h"
#include "rawpdu.h"
#include "utils.h"
#include "exceptions.h"
namespace Tins {
@@ -53,7 +54,7 @@ TCP::TCP(uint16_t dport, uint16_t sport)
TCP::TCP(const uint8_t *buffer, uint32_t total_sz)
{
if(total_sz < sizeof(tcphdr))
throw std::runtime_error("Not enough size for an TCP header in the buffer.");
throw malformed_packet();
std::memcpy(&_tcp, buffer, sizeof(tcphdr));
buffer += sizeof(tcphdr);
total_sz -= sizeof(tcphdr);
@@ -67,7 +68,7 @@ TCP::TCP(const uint8_t *buffer, uint32_t total_sz)
while(index < header_end) {
for(unsigned i(0); i < 2; ++i) {
if(index == header_end)
throw std::runtime_error("Not enough size for a TCP header in the buffer.");
throw malformed_packet();
args[i] = buffer[index++];
// NOP and EOL contain no length field
if(args[0] == NOP || args[0] == EOL)
@@ -78,7 +79,7 @@ TCP::TCP(const uint8_t *buffer, uint32_t total_sz)
// Not enough size for this option
args[1] -= (sizeof(uint8_t) << 1);
if(header_end - index < args[1])
throw std::runtime_error("Not enough size for a TCP header in the buffer.");
throw malformed_packet();
if(args[1])
add_option(option((OptionTypes)args[0], buffer + index, buffer + index + args[1]));
else

View File

@@ -35,6 +35,7 @@
#include "utils.h"
#include "ip.h"
#include "rawpdu.h"
#include "exceptions.h"
namespace Tins {
UDP::UDP(uint16_t dport, uint16_t sport, PDU *child)
@@ -49,7 +50,7 @@ UDP::UDP(uint16_t dport, uint16_t sport, PDU *child)
UDP::UDP(const uint8_t *buffer, uint32_t total_sz)
{
if(total_sz < sizeof(udphdr))
throw std::runtime_error("Not enough size for an UDP header in the buffer.");
throw malformed_packet();
std::memcpy(&_udp, buffer, sizeof(udphdr));
total_sz -= sizeof(udphdr);
if(total_sz)