Skip to content

Commit

Permalink
Fixed some bugs. Added documentation.
Browse files Browse the repository at this point in the history
  • Loading branch information
mfontanini committed Oct 20, 2012
1 parent abaa2bf commit 5fd892c
Show file tree
Hide file tree
Showing 10 changed files with 115 additions and 82 deletions.
20 changes: 2 additions & 18 deletions include/packet_writer.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
#include <string>
#include <iterator>
#include <pcap.h>
#include "utils.h"

namespace Tins {
class PDU;
Expand Down Expand Up @@ -82,27 +83,10 @@ class PacketWriter {
*/
template<typename ForwardIterator>
void write(ForwardIterator start, ForwardIterator end) {
typedef typename std::iterator_traits<ForwardIterator>::value_type value_type;
typedef derefer<value_type> deref_type;

while(start != end)
write(deref_type::deref(*start++));
write(Utils::dereference_until_pdu(*start++));
}
private:
template<typename T>
struct derefer {
static T &deref(T &value) {
return value;
}
};

template<typename T>
struct derefer<T*> {
static T &deref(T *value) {
return *value;
}
};

// You shall not copy
PacketWriter(const PacketWriter&);
PacketWriter& operator=(const PacketWriter&);
Expand Down
24 changes: 11 additions & 13 deletions include/pdu_cacher.h
Original file line number Diff line number Diff line change
Expand Up @@ -66,26 +66,22 @@ class PDUCacher : public PDU {
/**
* Default constructs the cached PDU.
*/
PDUCacher() {}
PDUCacher() : cached_size() {}

/**
* Constructor from a cached_type.
* \param pdu The PDU to be copy constructed.
*/
PDUCacher(const cached_type &pdu) : cached(pdu) {}
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 {
return cached.header_size();
}

/**
* Forwards the call to the cached PDU. \sa PDU::trailer_size.
*/
uint32_t trailer_size() const {
return cached.trailer_size();
if(cached_serialization.empty())
cached_size = cached.size();
return cached_size;
}

/**
Expand All @@ -98,8 +94,8 @@ class PDUCacher : public PDU {
/**
* Forwards the call to the cached PDU. \sa PDU::send.
*/
bool send(PacketSender &sender) {
return cached.send(sender);
void send(PacketSender &sender) {
cached.send(sender);
}

/**
Expand Down Expand Up @@ -138,13 +134,15 @@ class PDUCacher : public PDU {
}
private:
void write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *parent) {
if(cached_serialization.size() != total_sz)
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;
};
}

Expand Down
44 changes: 36 additions & 8 deletions include/small_uint.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,20 @@
#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:
Expand Down Expand Up @@ -74,24 +88,38 @@ class small_uint {
static const uint64_t value = 1;
};
public:
class value_to_large : public std::exception {
public:
const char *what() const throw() {
return "Value is too large";
}
};

/**
* 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_to_large();
throw value_too_large();
value = val;
}

/**
* User defined conversion to repr_type.
*/
operator repr_type() const {
return value;
}
Expand Down
34 changes: 2 additions & 32 deletions include/tcp_stream.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
#include <stdint.h>
#include "sniffer.h"
#include "tcp.h"
#include "utils.h"
#include "ip.h"
#include "ip_address.h"

Expand Down Expand Up @@ -297,37 +298,6 @@ class TCPStreamFollower {
EndFunctor end_fun;
};

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

template<bool, typename>
struct enable_if {

};

template<typename T>
struct enable_if<true, T> {
typedef T type;
};

static PDU& recursive_dereference(PDU &pdu) {
return pdu;
}

template<typename T>
static typename enable_if<!is_pdu<T>::value, PDU&>::type
recursive_dereference(T &value) {
return recursive_dereference(*value);
}

void clear_state() {
sessions.clear();
last_identifier = 0;
Expand Down Expand Up @@ -355,7 +325,7 @@ void TCPStreamFollower::follow_streams(ForwardIterator start, ForwardIterator en
{
clear_state();
while(start != end) {
if(!callback(recursive_dereference(start), data_fun, end_fun))
if(!callback(Utils::dereference_until_pdu(start), data_fun, end_fun))
return;
start++;
}
Expand Down
1 change: 1 addition & 0 deletions include/tins.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,5 +54,6 @@
#include "tcp_stream.h"
#include "crypto.h"
#include "pdu_cacher.h"
#include "rsn_information.h"

#endif // TINS_TINS_H
48 changes: 48 additions & 0 deletions include/utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -228,9 +228,57 @@ namespace Tins {
}
#endif // WIN32

/**
* \cond
*/
namespace Internals {
void skip_line(std::istream &input);
bool from_hex(const std::string &str, uint32_t &result);

template<bool, typename>
struct enable_if {

};

template<typename T>
struct enable_if<true, T> {
typedef T type;
};
}
/**
* \endcond
*/

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);
}
}
}
Expand Down
7 changes: 5 additions & 2 deletions src/dns_record.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@

#include <cstring>
#include <stdexcept>
#include <memory>
#include <typeinfo>
#include "dns_record.h"
#include "endianness.h"
Expand All @@ -50,10 +51,11 @@ DNSResourceRecord::DNSResourceRecord(DNSRRImpl *impl,
DNSResourceRecord::DNSResourceRecord(const uint8_t *buffer, uint32_t size)
{
const uint8_t *buffer_end = buffer + size;
std::auto_ptr<DNSRRImpl> tmp_impl;
if((*buffer & 0xc0)) {
uint16_t offset(*reinterpret_cast<const uint16_t*>(buffer));
offset = Endian::be_to_host(offset) & 0x3fff;
impl = new OffsetedDNSRRImpl(Endian::host_to_be(offset));
tmp_impl.reset(new OffsetedDNSRRImpl(Endian::host_to_be(offset)));
buffer += sizeof(uint16_t);
}
else {
Expand All @@ -63,7 +65,7 @@ DNSResourceRecord::DNSResourceRecord(const uint8_t *buffer, uint32_t size)
if(str_end == buffer_end)
throw std::runtime_error("Not enough size for a resource domain name.");
//str_end++;
impl = new NamedDNSRRImpl(buffer, str_end);
tmp_impl.reset(new NamedDNSRRImpl(buffer, str_end));
buffer = ++str_end;
}
if(buffer + sizeof(info_) > buffer_end)
Expand All @@ -86,6 +88,7 @@ DNSResourceRecord::DNSResourceRecord(const uint8_t *buffer, uint32_t size)
*(uint32_t*)&data[0] = *(uint32_t*)buffer;
else
throw std::runtime_error("Not enough size for resource data");
impl = tmp_impl.release();
}

DNSResourceRecord::DNSResourceRecord(const DNSResourceRecord &rhs)
Expand Down
6 changes: 4 additions & 2 deletions src/ip.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ IP::IP(const uint8_t *buffer, uint32_t total_sz)
buffer += head_len() * sizeof(uint32_t);

_options_size = 0;
_padded_options_size = head_len() * sizeof(uint32_t) - sizeof(iphdr);
//_padded_options_size = head_len() * sizeof(uint32_t) - sizeof(iphdr);
/* While the end of the options is not reached read an option */
while (ptr_buffer < buffer && (*ptr_buffer != 0)) {
//ip_option opt_to_add;
Expand Down Expand Up @@ -126,6 +126,8 @@ IP::IP(const uint8_t *buffer, uint32_t total_sz)
}
_options_size += _ip_options.back().data_size() + 2;
}
uint8_t padding = _options_size % 4;
_padded_options_size = padding ? (_options_size - padding + 4) : _options_size;
// check this line PLX
total_sz -= head_len() * sizeof(uint32_t);
if (total_sz) {
Expand Down Expand Up @@ -304,7 +306,7 @@ uint16_t IP::stream_identifier() const {
void IP::add_option(const ip_option &option) {
_ip_options.push_back(option);
_options_size += 1 + option.data_size();
uint8_t padding = _options_size & 3;
uint8_t padding = _options_size % 4;
_padded_options_size = padding ? (_options_size - padding + 4) : _options_size;
}

Expand Down
9 changes: 4 additions & 5 deletions src/rsn_information.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -51,21 +51,20 @@ 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";
check_size<uint16_t>(total_sz, err_msg);
if(total_sz <= sizeof(uint16_t) * 2 + sizeof(uint32_t))
throw std::runtime_error(err_msg);
version(Endian::le_to_host(*(uint16_t*)buffer));
buffer += sizeof(uint16_t);
total_sz -= sizeof(uint16_t);
group_suite((RSNInformation::CypherSuites)*(uint32_t*)buffer);

check_size<uint32_t>(total_sz, err_msg);
group_suite((RSNInformation::CypherSuites)*(uint32_t*)buffer);
buffer += sizeof(uint32_t);
total_sz -= sizeof(uint32_t);

check_size<uint16_t>(total_sz, err_msg);

uint16_t 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);
total_sz -= count * sizeof(uint32_t);
Expand Down
4 changes: 2 additions & 2 deletions tests/src/utils_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -77,12 +77,12 @@ TEST_F(UtilsTest, Crc32) {
// FIXME
TEST_F(UtilsTest, Checksum) {

uint16_t checksum = Utils::do_checksum(data, data + data_len);
/*uint16_t checksum = Utils::do_checksum(data, data + data_len);
//EXPECT_EQ(checksum, 0x231a);
uint8_t my_data[] = {0, 0, 0, 0};
checksum = Utils::do_checksum(my_data, my_data + 4);
//EXPECT_EQ(checksum, 0xFFFF);

*/
}

0 comments on commit 5fd892c

Please sign in to comment.