mirror of
https://github.com/mfontanini/libtins
synced 2026-01-23 02:35:57 +01:00
Add OutputMemoryStream and port most classes to use it
This commit is contained in:
@@ -38,7 +38,11 @@
|
||||
#include "ipv6_address.h"
|
||||
#include "pdu_option.h"
|
||||
|
||||
namespace Tins {
|
||||
namespace Tins {
|
||||
namespace Memory {
|
||||
class OutputMemoryStream;
|
||||
} // Memory
|
||||
|
||||
/**
|
||||
* \class DHCPv6
|
||||
* \brief Represents a DHCPv6 PDU.
|
||||
@@ -869,7 +873,7 @@ public:
|
||||
}
|
||||
private:
|
||||
void write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *);
|
||||
uint8_t* write_option(const option &option, uint8_t* buffer) const;
|
||||
void write_option(const option &option, Memory::OutputMemoryStream& stream) const;
|
||||
options_type::const_iterator search_option_iterator(OptionTypes type) const;
|
||||
options_type::iterator search_option_iterator(OptionTypes type);
|
||||
|
||||
|
||||
@@ -38,7 +38,10 @@
|
||||
|
||||
|
||||
namespace Tins {
|
||||
|
||||
namespace Memory {
|
||||
class OutputMemoryStream;
|
||||
} // Memory
|
||||
|
||||
/** \cond
|
||||
* Forward declaration. Avoid header inclusion.
|
||||
*/
|
||||
@@ -163,7 +166,7 @@ namespace Tins {
|
||||
* \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;
|
||||
virtual void write_body(Memory::OutputMemoryStream& stream) = 0;
|
||||
private:
|
||||
/**
|
||||
* \brief Serialices this EAPOL PDU.
|
||||
@@ -353,7 +356,7 @@ namespace Tins {
|
||||
uint8_t key_sign[16];
|
||||
} TINS_END_PACK;
|
||||
|
||||
void write_body(uint8_t *buffer, uint32_t total_sz);
|
||||
void write_body(Memory::OutputMemoryStream& stream);
|
||||
|
||||
|
||||
key_type _key;
|
||||
@@ -731,7 +734,7 @@ namespace Tins {
|
||||
#endif
|
||||
} TINS_END_PACK;
|
||||
|
||||
void write_body(uint8_t *buffer, uint32_t total_sz);
|
||||
void write_body(Memory::OutputMemoryStream& stream);
|
||||
|
||||
|
||||
rsnhdr _header;
|
||||
|
||||
@@ -49,7 +49,7 @@ public:
|
||||
/**
|
||||
* \brief Exception thrown when an option is not found.
|
||||
*/
|
||||
class option_not_found : exception_base {
|
||||
class option_not_found : public exception_base {
|
||||
public:
|
||||
// try to avoid allocations by doing this.
|
||||
const char* what() const throw() {
|
||||
@@ -67,6 +67,16 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Exception thrown when serializing a packet fails.
|
||||
*/
|
||||
class serialization_error : public exception_base {
|
||||
public:
|
||||
const char* what() const throw() {
|
||||
return "Serialization error";
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Exception thrown when a PDU is not found when using PDU::rfind_pdu.
|
||||
*/
|
||||
|
||||
@@ -46,6 +46,7 @@
|
||||
namespace Tins {
|
||||
namespace Memory {
|
||||
class InputMemoryStream;
|
||||
class OutputMemoryStream;
|
||||
} // memory
|
||||
|
||||
/**
|
||||
@@ -1379,7 +1380,7 @@ private:
|
||||
void internal_add_option(const option &option);
|
||||
void write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *parent);
|
||||
bool has_options() const;
|
||||
uint8_t *write_option(const option &opt, uint8_t *buffer);
|
||||
void write_option(const option &opt, Memory::OutputMemoryStream& stream);
|
||||
void parse_options(Memory::InputMemoryStream& stream);
|
||||
void add_addr_list(uint8_t type, const addr_list_type &value);
|
||||
addr_list_type search_addr_list(OptionTypes type) const;
|
||||
|
||||
@@ -40,6 +40,9 @@
|
||||
#include "cxxstd.h"
|
||||
|
||||
namespace Tins {
|
||||
namespace Memory {
|
||||
class OutputMemoryStream;
|
||||
} // Memory
|
||||
|
||||
/**
|
||||
* \class IP
|
||||
@@ -725,7 +728,7 @@ namespace Tins {
|
||||
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 write_option(const option &opt, Memory::OutputMemoryStream& stream);
|
||||
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);
|
||||
|
||||
@@ -40,6 +40,10 @@
|
||||
#include "ipv6_address.h"
|
||||
|
||||
namespace Tins {
|
||||
namespace Memory {
|
||||
class OutputMemoryStream;
|
||||
} // Memory
|
||||
|
||||
class PacketSender;
|
||||
|
||||
/**
|
||||
@@ -299,7 +303,7 @@ public:
|
||||
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 void write_header(const ext_header &header, Memory::OutputMemoryStream& stream);
|
||||
static bool is_extension_header(uint8_t header_id);
|
||||
|
||||
TINS_BEGIN_PACK
|
||||
|
||||
@@ -383,6 +383,7 @@ namespace Tins {
|
||||
#endif
|
||||
|
||||
typedef std::vector<uint8_t> field_type;
|
||||
typedef std::list<field_type> field_list;
|
||||
|
||||
void write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *parent);
|
||||
|
||||
@@ -395,7 +396,7 @@ namespace Tins {
|
||||
} control_field;
|
||||
Format _type;
|
||||
uint8_t information_field_length;
|
||||
std::list<field_type> information_fields;
|
||||
field_list information_fields;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
|
||||
#include <stdint.h>
|
||||
#include <cstring>
|
||||
#include <algorithm>
|
||||
#include "exceptions.h"
|
||||
#include "ip_address.h"
|
||||
#include "ipv6_address.h"
|
||||
@@ -20,6 +21,10 @@ void read_value(const uint8_t* buffer, T& value) {
|
||||
std::memcpy(&value, buffer, sizeof(value));
|
||||
}
|
||||
|
||||
inline void write_data(uint8_t* buffer, const uint8_t* ptr, uint32_t size) {
|
||||
std::memcpy(buffer, ptr, size);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void write_value(uint8_t* buffer, const T& value) {
|
||||
std::memcpy(buffer, &value, sizeof(value));
|
||||
@@ -105,6 +110,73 @@ private:
|
||||
uint32_t size_;
|
||||
};
|
||||
|
||||
class OutputMemoryStream {
|
||||
public:
|
||||
OutputMemoryStream(uint8_t* buffer, uint32_t total_sz)
|
||||
: buffer_(buffer), size_(total_sz) {
|
||||
}
|
||||
|
||||
void skip(uint32_t size) {
|
||||
buffer_ += size;
|
||||
size_ -= size;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void write(const T& value) {
|
||||
if (TINS_UNLIKELY(size_ < sizeof(value))) {
|
||||
throw serialization_error();
|
||||
}
|
||||
write_value(buffer_, value);
|
||||
skip(sizeof(value));
|
||||
}
|
||||
|
||||
template <typename ForwardIterator>
|
||||
void write(ForwardIterator start, ForwardIterator end) {
|
||||
const uint32_t length = std::distance(start, end);
|
||||
if (TINS_UNLIKELY(size_ < length)) {
|
||||
throw serialization_error();
|
||||
}
|
||||
std::copy(start, end, buffer_);
|
||||
skip(length);
|
||||
}
|
||||
|
||||
void write(const uint8_t* ptr, uint32_t length) {
|
||||
write(ptr, ptr + length);
|
||||
}
|
||||
|
||||
void write(const IPv4Address& address) {
|
||||
write(static_cast<uint32_t>(address));
|
||||
}
|
||||
|
||||
void write(const IPv6Address& address) {
|
||||
write(address.begin(), address.end());
|
||||
}
|
||||
|
||||
template <size_t n>
|
||||
void write(const HWAddress<n>& address) {
|
||||
write(address.begin(), address.end());
|
||||
}
|
||||
|
||||
void fill(uint32_t size, uint8_t value) {
|
||||
if (TINS_UNLIKELY(size_ < size)) {
|
||||
throw serialization_error();
|
||||
}
|
||||
std::fill(buffer_, buffer_ + size, value);
|
||||
skip(size);
|
||||
}
|
||||
|
||||
uint8_t* pointer() {
|
||||
return buffer_;
|
||||
}
|
||||
|
||||
uint32_t size() const {
|
||||
return size_;
|
||||
}
|
||||
private:
|
||||
uint8_t* buffer_;
|
||||
uint32_t size_;
|
||||
};
|
||||
|
||||
} // Memory
|
||||
} // Tins
|
||||
|
||||
|
||||
@@ -44,6 +44,10 @@
|
||||
#include "cxxstd.h"
|
||||
|
||||
namespace Tins {
|
||||
namespace Memory {
|
||||
class OutputMemoryStream;
|
||||
} // Memory
|
||||
|
||||
/**
|
||||
* \class TCP
|
||||
* \brief Represents a TCP PDU.
|
||||
@@ -583,7 +587,7 @@ namespace Tins {
|
||||
options_type::const_iterator search_option_iterator(OptionTypes type) const;
|
||||
options_type::iterator search_option_iterator(OptionTypes type);
|
||||
|
||||
uint8_t *write_option(const option &opt, uint8_t *buffer);
|
||||
void write_option(const option &opt, Memory::OutputMemoryStream& stream);
|
||||
|
||||
tcphdr _tcp;
|
||||
uint16_t _options_size, _total_options_size;
|
||||
|
||||
@@ -28,7 +28,6 @@
|
||||
*/
|
||||
|
||||
#include <cstring>
|
||||
#include <cassert>
|
||||
#include <algorithm>
|
||||
#include "arp.h"
|
||||
#include "ip.h"
|
||||
@@ -42,6 +41,7 @@
|
||||
using std::runtime_error;
|
||||
|
||||
using Tins::Memory::InputMemoryStream;
|
||||
using Tins::Memory::OutputMemoryStream;
|
||||
|
||||
namespace Tins {
|
||||
|
||||
@@ -109,10 +109,8 @@ uint32_t ARP::header_size() const {
|
||||
}
|
||||
|
||||
void ARP::write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *) {
|
||||
#ifdef TINS_DEBUG
|
||||
assert(total_sz >= sizeof(arphdr));
|
||||
#endif
|
||||
memcpy(buffer, &_arp, sizeof(arphdr));
|
||||
OutputMemoryStream stream(buffer, total_sz);
|
||||
stream.write(_arp);
|
||||
}
|
||||
|
||||
bool ARP::matches_response(const uint8_t *ptr, uint32_t total_sz) const {
|
||||
|
||||
@@ -29,12 +29,12 @@
|
||||
|
||||
#include <stdexcept>
|
||||
#include <cstring>
|
||||
#include <cassert>
|
||||
#include "bootp.h"
|
||||
#include "exceptions.h"
|
||||
#include "memory_helpers.h"
|
||||
|
||||
using Tins::Memory::InputMemoryStream;
|
||||
using Tins::Memory::OutputMemoryStream;
|
||||
|
||||
namespace Tins{
|
||||
|
||||
@@ -116,11 +116,9 @@ void BootP::vend(const vend_type &new_vend) {
|
||||
}
|
||||
|
||||
void BootP::write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *parent) {
|
||||
#ifdef TINS_DEBUG
|
||||
assert(total_sz >= sizeof(bootphdr) + _vend.size());
|
||||
#endif
|
||||
std::memcpy(buffer, &_bootp, sizeof(bootphdr));
|
||||
std::copy(_vend.begin(), _vend.end(), buffer + sizeof(bootphdr));
|
||||
OutputMemoryStream stream(buffer, total_sz);
|
||||
stream.write(_bootp);
|
||||
stream.write(_vend.begin(), _vend.end());
|
||||
}
|
||||
|
||||
bool BootP::matches_response(const uint8_t *ptr, uint32_t total_sz) const {
|
||||
|
||||
29
src/dhcp.cpp
29
src/dhcp.cpp
@@ -28,7 +28,6 @@
|
||||
*/
|
||||
|
||||
#include <stdexcept>
|
||||
#include <cassert>
|
||||
#include <cstring>
|
||||
#include "endianness.h"
|
||||
#include "dhcp.h"
|
||||
@@ -43,6 +42,7 @@ using std::runtime_error;
|
||||
using std::find_if;
|
||||
|
||||
using Tins::Memory::InputMemoryStream;
|
||||
using Tins::Memory::OutputMemoryStream;
|
||||
|
||||
namespace Tins {
|
||||
|
||||
@@ -57,8 +57,8 @@ DHCP::DHCP()
|
||||
DHCP::DHCP(const uint8_t *buffer, uint32_t total_sz)
|
||||
: BootP(buffer, total_sz, 0), _size(sizeof(uint32_t))
|
||||
{
|
||||
const uint32_t bootp_size = BootP::header_size() - vend().size();
|
||||
InputMemoryStream stream(buffer + bootp_size, total_sz - bootp_size);
|
||||
InputMemoryStream stream(buffer, total_sz);
|
||||
stream.skip(BootP::header_size() - vend().size());
|
||||
const uint32_t magic_number = stream.read<uint32_t>();
|
||||
if (magic_number != Endian::host_to_be<uint32_t>(0x63825363))
|
||||
throw malformed_packet();
|
||||
@@ -238,22 +238,19 @@ uint32_t DHCP::header_size() const {
|
||||
}
|
||||
|
||||
void DHCP::write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *parent) {
|
||||
#ifdef TINS_DEBUG
|
||||
assert(total_sz >= header_size());
|
||||
#endif
|
||||
if(_size) {
|
||||
vend_type &result(BootP::vend());
|
||||
if (_size) {
|
||||
vend_type &result = BootP::vend();
|
||||
result.resize(_size);
|
||||
uint8_t *ptr = &result[0] + sizeof(uint32_t);
|
||||
// Build a stream over the vend vector
|
||||
OutputMemoryStream stream(&result[0], result.size());
|
||||
// Magic cookie
|
||||
*((uint32_t*)&result[0]) = Endian::host_to_be<uint32_t>(0x63825363);
|
||||
for(options_type::const_iterator it = _options.begin(); it != _options.end(); ++it) {
|
||||
*(ptr++) = it->option();
|
||||
*(ptr++) = static_cast<uint8_t>(it->length_field());
|
||||
std::copy(it->data_ptr(), it->data_ptr() + it->data_size(), ptr);
|
||||
ptr += it->data_size();
|
||||
stream.write(Endian::host_to_be<uint32_t>(0x63825363));
|
||||
for (options_type::const_iterator it = _options.begin(); it != _options.end(); ++it) {
|
||||
stream.write(it->option());
|
||||
stream.write<uint8_t>(it->length_field());
|
||||
stream.write(it->data_ptr(), it->data_size());
|
||||
}
|
||||
}
|
||||
BootP::write_serialization(buffer, total_sz, parent);
|
||||
}
|
||||
}
|
||||
} // Tins
|
||||
|
||||
@@ -36,6 +36,7 @@
|
||||
using std::find_if;
|
||||
|
||||
using Tins::Memory::InputMemoryStream;
|
||||
using Tins::Memory::OutputMemoryStream;
|
||||
|
||||
namespace Tins {
|
||||
|
||||
@@ -109,16 +110,10 @@ DHCPv6::options_type::iterator DHCPv6::search_option_iterator(OptionTypes type)
|
||||
return find_if(options_.begin(), options_.end(), comparator);
|
||||
}
|
||||
|
||||
uint8_t* DHCPv6::write_option(const option &opt, uint8_t* buffer) const {
|
||||
uint16_t uint16_t_buffer = Endian::host_to_be(opt.option());
|
||||
std::memcpy(buffer, &uint16_t_buffer, sizeof(uint16_t));
|
||||
uint16_t_buffer = Endian::host_to_be(static_cast<uint16_t>(opt.length_field()));
|
||||
std::memcpy(&buffer[sizeof(uint16_t)], &uint16_t_buffer, sizeof(uint16_t));
|
||||
return std::copy(
|
||||
opt.data_ptr(),
|
||||
opt.data_ptr() + opt.data_size(),
|
||||
buffer + sizeof(uint16_t) * 2
|
||||
);
|
||||
void DHCPv6::write_option(const option &opt, OutputMemoryStream& stream) const {
|
||||
stream.write(Endian::host_to_be<uint16_t>(opt.option()));
|
||||
stream.write(Endian::host_to_be<uint16_t>(opt.length_field()));
|
||||
stream.write(opt.data_ptr(), opt.data_size());
|
||||
}
|
||||
|
||||
void DHCPv6::msg_type(MessageType type) {
|
||||
@@ -163,13 +158,14 @@ bool DHCPv6::matches_response(const uint8_t *ptr, uint32_t total_sz) const {
|
||||
|
||||
void DHCPv6::write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *) {
|
||||
const uint32_t required_size = is_relay_message() ? 2 : 4;
|
||||
buffer = std::copy(header_data, header_data + required_size, buffer);
|
||||
if(is_relay_message()) {
|
||||
buffer = link_addr.copy(buffer);
|
||||
buffer = peer_addr.copy(buffer);
|
||||
OutputMemoryStream stream(buffer, total_sz);
|
||||
stream.write(header_data, required_size);
|
||||
if (is_relay_message()) {
|
||||
stream.write(link_addr);
|
||||
stream.write(peer_addr);
|
||||
}
|
||||
for(options_type::const_iterator it = options_.begin(); it != options_.end(); ++it) {
|
||||
buffer = write_option(*it, buffer);
|
||||
for (options_type::const_iterator it = options_.begin(); it != options_.end(); ++it) {
|
||||
write_option(*it, stream);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
11
src/dns.cpp
11
src/dns.cpp
@@ -29,7 +29,6 @@
|
||||
|
||||
#include <utility>
|
||||
#include <stdexcept>
|
||||
#include <cassert>
|
||||
#include <sstream>
|
||||
#include <memory>
|
||||
#include <cstdio>
|
||||
@@ -45,6 +44,7 @@ using std::string;
|
||||
using std::list;
|
||||
|
||||
using Tins::Memory::InputMemoryStream;
|
||||
using Tins::Memory::OutputMemoryStream;
|
||||
|
||||
namespace Tins {
|
||||
|
||||
@@ -361,12 +361,9 @@ const uint8_t* DNS::compose_name(const uint8_t *ptr, char *out_ptr) const {
|
||||
}
|
||||
|
||||
void DNS::write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *parent) {
|
||||
#ifdef TINS_DEBUG
|
||||
assert(total_sz >= sizeof(dns) + records_data.size());//extra_size);
|
||||
#endif
|
||||
std::memcpy(buffer, &dns, sizeof(dns));
|
||||
buffer += sizeof(dns);
|
||||
std::copy(records_data.begin(), records_data.end(), buffer);
|
||||
OutputMemoryStream stream(buffer, total_sz);
|
||||
stream.write(dns);
|
||||
stream.write(records_data.begin(), records_data.end());
|
||||
}
|
||||
|
||||
// Optimization. Creating an IPv4Address and then using IPv4Address::to_string
|
||||
|
||||
@@ -29,13 +29,13 @@
|
||||
|
||||
#include <stdexcept>
|
||||
#include <cstring>
|
||||
#include <cassert>
|
||||
#include "dot1q.h"
|
||||
#include "internals.h"
|
||||
#include "exceptions.h"
|
||||
#include "memory_helpers.h"
|
||||
|
||||
using Tins::Memory::InputMemoryStream;
|
||||
using Tins::Memory::OutputMemoryStream;
|
||||
|
||||
namespace Tins {
|
||||
|
||||
@@ -88,33 +88,35 @@ uint32_t Dot1Q::header_size() const {
|
||||
}
|
||||
|
||||
uint32_t Dot1Q::trailer_size() const {
|
||||
if(_append_padding) {
|
||||
if (_append_padding) {
|
||||
uint32_t total_size = sizeof(_header);
|
||||
if(inner_pdu())
|
||||
if (inner_pdu()) {
|
||||
total_size += inner_pdu()->size();
|
||||
}
|
||||
return (total_size > 50) ? 0 : (50 - total_size);
|
||||
}
|
||||
else
|
||||
else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
void Dot1Q::write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *) {
|
||||
uint32_t trailer = trailer_size();
|
||||
#ifdef TINS_DEBUG
|
||||
assert(total_sz >= sizeof(_header) + trailer);
|
||||
#endif
|
||||
OutputMemoryStream stream(buffer, total_sz);
|
||||
if (inner_pdu()) {
|
||||
// Set the appropriate payload type flag
|
||||
Constants::Ethernet::e flag = Internals::pdu_flag_to_ether_type(
|
||||
inner_pdu()->pdu_type()
|
||||
);
|
||||
payload_type(static_cast<uint16_t>(flag));
|
||||
}
|
||||
std::memcpy(buffer, &_header, sizeof(_header));
|
||||
|
||||
buffer += sizeof(_header);
|
||||
if(inner_pdu())
|
||||
buffer += inner_pdu()->size();
|
||||
std::fill(buffer, buffer + trailer, 0);
|
||||
stream.write(_header);
|
||||
|
||||
// Skip inner PDU size
|
||||
if (inner_pdu()) {
|
||||
stream.skip(inner_pdu()->size());
|
||||
}
|
||||
// Write trailer
|
||||
stream.fill(trailer_size(), 0);
|
||||
}
|
||||
|
||||
#if TINS_IS_LITTLE_ENDIAN
|
||||
|
||||
10
src/dot3.cpp
10
src/dot3.cpp
@@ -50,6 +50,7 @@
|
||||
#include "memory_helpers.h"
|
||||
|
||||
using Tins::Memory::InputMemoryStream;
|
||||
using Tins::Memory::OutputMemoryStream;
|
||||
|
||||
namespace Tins {
|
||||
|
||||
@@ -129,12 +130,9 @@ bool Dot3::matches_response(const uint8_t *ptr, uint32_t total_sz) const {
|
||||
}
|
||||
|
||||
void Dot3::write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *parent) {
|
||||
#ifdef TINS_DEBUG
|
||||
assert(total_sz >= header_size());
|
||||
#endif
|
||||
_eth.length = Endian::host_to_be(static_cast<uint16_t>(size() - sizeof(_eth)));
|
||||
|
||||
memcpy(buffer, &_eth, sizeof(ethhdr));
|
||||
OutputMemoryStream stream(buffer, total_sz);
|
||||
_eth.length = Endian::host_to_be<uint16_t>(size() - sizeof(_eth));
|
||||
stream.write(_eth);
|
||||
}
|
||||
|
||||
#ifndef _WIN32
|
||||
|
||||
@@ -39,6 +39,7 @@
|
||||
#include "memory_helpers.h"
|
||||
|
||||
using Tins::Memory::InputMemoryStream;
|
||||
using Tins::Memory::OutputMemoryStream;
|
||||
|
||||
namespace Tins {
|
||||
|
||||
@@ -96,11 +97,10 @@ void EAPOL::type(uint8_t new_type) {
|
||||
}
|
||||
|
||||
void EAPOL::write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *) {
|
||||
#ifdef TINS_DEBUG
|
||||
assert(total_sz >= header_size());
|
||||
#endif
|
||||
OutputMemoryStream stream(buffer, total_sz);
|
||||
stream.write(_header);
|
||||
std::memcpy(buffer, &_header, sizeof(_header));
|
||||
write_body(buffer + sizeof(_header), total_sz - sizeof(_header));
|
||||
write_body(stream);
|
||||
}
|
||||
|
||||
/* RC4EAPOL */
|
||||
@@ -157,16 +157,12 @@ uint32_t RC4EAPOL::header_size() const {
|
||||
return static_cast<uint32_t>(sizeof(eapolhdr) + sizeof(_header) + _key.size());
|
||||
}
|
||||
|
||||
void RC4EAPOL::write_body(uint8_t *buffer, uint32_t total_sz) {
|
||||
#ifdef TINS_DEBUG
|
||||
assert(total_sz >= sizeof(_header) + _key.size());
|
||||
#endif
|
||||
if(_key.size()) {
|
||||
void RC4EAPOL::write_body(OutputMemoryStream& stream) {
|
||||
if (_key.size()) {
|
||||
_header.key_length = Endian::host_to_be(static_cast<uint16_t>(_key.size()));
|
||||
}
|
||||
std::memcpy(buffer, &_header, sizeof(_header));
|
||||
buffer += sizeof(_header);
|
||||
std::copy(_key.begin(), _key.end(), buffer);
|
||||
stream.write(_header);
|
||||
stream.write(_key.begin(), _key.end());
|
||||
}
|
||||
|
||||
/* RSNEAPOL */
|
||||
@@ -273,21 +269,17 @@ uint32_t RSNEAPOL::header_size() const {
|
||||
return static_cast<uint32_t>(sizeof(eapolhdr) + sizeof(_header) + _key.size());
|
||||
}
|
||||
|
||||
void RSNEAPOL::write_body(uint8_t *buffer, uint32_t total_sz) {
|
||||
#ifdef TINS_DEBUG
|
||||
assert(total_sz >= header_size() - sizeof(eapolhdr));
|
||||
#endif
|
||||
if(_key.size()) {
|
||||
if(!_header.key_t) {
|
||||
void RSNEAPOL::write_body(OutputMemoryStream& stream) {
|
||||
if (_key.size()) {
|
||||
if (!_header.key_t) {
|
||||
_header.key_length = Endian::host_to_be<uint16_t>(32);
|
||||
wpa_length(static_cast<uint16_t>(_key.size()));
|
||||
}
|
||||
else if(_key.size()) {
|
||||
else if (_key.size()) {
|
||||
wpa_length(static_cast<uint16_t>(_key.size()));
|
||||
}
|
||||
}
|
||||
std::memcpy(buffer, &_header, sizeof(_header));
|
||||
buffer += sizeof(_header);
|
||||
std::copy(_key.begin(), _key.end(), buffer);
|
||||
stream.write(_header);
|
||||
stream.write(_key.begin(), _key.end());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -56,6 +56,7 @@
|
||||
#include "memory_helpers.h"
|
||||
|
||||
using Tins::Memory::InputMemoryStream;
|
||||
using Tins::Memory::OutputMemoryStream;
|
||||
|
||||
namespace Tins {
|
||||
|
||||
@@ -152,11 +153,7 @@ bool EthernetII::matches_response(const uint8_t *ptr, uint32_t total_sz) const {
|
||||
}
|
||||
|
||||
void EthernetII::write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *parent) {
|
||||
#ifdef TINS_DEBUG
|
||||
assert(total_sz >= header_size() + trailer_size());
|
||||
#endif
|
||||
|
||||
/* Inner type defaults to IP */
|
||||
OutputMemoryStream stream(buffer, total_sz);
|
||||
if (inner_pdu()) {
|
||||
Constants::Ethernet::e flag = Internals::pdu_flag_to_ether_type(
|
||||
inner_pdu()->pdu_type()
|
||||
@@ -165,13 +162,13 @@ void EthernetII::write_serialization(uint8_t *buffer, uint32_t total_sz, const P
|
||||
payload_type(static_cast<uint16_t>(flag));
|
||||
}
|
||||
}
|
||||
memcpy(buffer, &_eth, sizeof(ethhdr));
|
||||
uint32_t trailer = trailer_size();
|
||||
stream.write(_eth);
|
||||
const uint32_t trailer = trailer_size();
|
||||
if (trailer) {
|
||||
uint32_t trailer_offset = header_size();
|
||||
if (inner_pdu())
|
||||
trailer_offset += inner_pdu()->size();
|
||||
memset(buffer + trailer_offset, 0, trailer);
|
||||
if (inner_pdu()) {
|
||||
stream.skip(inner_pdu()->size());
|
||||
}
|
||||
stream.fill(trailer, 0);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
42
src/icmp.cpp
42
src/icmp.cpp
@@ -42,6 +42,7 @@
|
||||
#include "memory_helpers.h"
|
||||
|
||||
using Tins::Memory::InputMemoryStream;
|
||||
using Tins::Memory::OutputMemoryStream;
|
||||
|
||||
namespace Tins {
|
||||
|
||||
@@ -207,23 +208,7 @@ void ICMP::use_length_field(bool value) {
|
||||
}
|
||||
|
||||
void ICMP::write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *) {
|
||||
#ifdef TINS_DEBUG
|
||||
assert(total_sz >= sizeof(icmphdr));
|
||||
#endif
|
||||
|
||||
uint32_t uint32_t_buffer;
|
||||
if(type() == TIMESTAMP_REQUEST || type() == TIMESTAMP_REPLY) {
|
||||
uint32_t_buffer = original_timestamp();
|
||||
memcpy(buffer + sizeof(icmphdr), &uint32_t_buffer, sizeof(uint32_t));
|
||||
uint32_t_buffer = receive_timestamp();
|
||||
memcpy(buffer + sizeof(icmphdr) + sizeof(uint32_t), &uint32_t_buffer, sizeof(uint32_t));
|
||||
uint32_t_buffer = transmit_timestamp();
|
||||
memcpy(buffer + sizeof(icmphdr) + 2 * sizeof(uint32_t), &uint32_t_buffer, sizeof(uint32_t));
|
||||
}
|
||||
else if(type() == ADDRESS_MASK_REQUEST || type() == ADDRESS_MASK_REPLY) {
|
||||
uint32_t_buffer = address_mask();
|
||||
memcpy(buffer + sizeof(icmphdr), &uint32_t_buffer, sizeof(uint32_t));
|
||||
}
|
||||
OutputMemoryStream stream(buffer, total_sz);
|
||||
|
||||
// If extensions are allowed and we have to set the length field
|
||||
if (are_extensions_allowed()) {
|
||||
@@ -236,6 +221,19 @@ void ICMP::write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *)
|
||||
}
|
||||
}
|
||||
|
||||
// Write the header using checksum 0
|
||||
_icmp.check = 0;
|
||||
stream.write(_icmp);
|
||||
|
||||
if(type() == TIMESTAMP_REQUEST || type() == TIMESTAMP_REPLY) {
|
||||
stream.write(original_timestamp());
|
||||
stream.write(receive_timestamp());
|
||||
stream.write(transmit_timestamp());
|
||||
}
|
||||
else if(type() == ADDRESS_MASK_REQUEST || type() == ADDRESS_MASK_REPLY) {
|
||||
stream.write(address_mask());
|
||||
}
|
||||
|
||||
if (has_extensions()) {
|
||||
uint8_t* extensions_ptr = buffer + sizeof(icmphdr);
|
||||
if (inner_pdu()) {
|
||||
@@ -258,14 +256,12 @@ void ICMP::write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *)
|
||||
extensions_.serialize(extensions_ptr, total_sz - (extensions_ptr - buffer));
|
||||
}
|
||||
|
||||
// checksum calc
|
||||
_icmp.check = 0;
|
||||
memcpy(buffer, &_icmp, sizeof(icmphdr));
|
||||
// Calculate checksum
|
||||
uint32_t checksum = Utils::do_checksum(buffer, buffer + total_sz);
|
||||
|
||||
while (checksum >> 16)
|
||||
while (checksum >> 16) {
|
||||
checksum = (checksum & 0xffff) + (checksum >> 16);
|
||||
|
||||
}
|
||||
// Write back only the 2 checksum bytes
|
||||
_icmp.check = Endian::host_to_be<uint16_t>(~checksum);
|
||||
memcpy(buffer + 2, &_icmp.check, sizeof(uint16_t));
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
using std::runtime_error;
|
||||
|
||||
using Tins::Memory::InputMemoryStream;
|
||||
using Tins::Memory::OutputMemoryStream;
|
||||
|
||||
namespace Tins {
|
||||
|
||||
@@ -57,16 +58,11 @@ uint32_t ICMPExtension::size() const {
|
||||
}
|
||||
|
||||
void ICMPExtension::serialize(uint8_t* buffer, uint32_t buffer_size) const {
|
||||
if (buffer_size < size()) {
|
||||
throw runtime_error("Serialization buffer is too small");
|
||||
}
|
||||
*(uint16_t*)buffer = Endian::host_to_be<uint16_t>(size());
|
||||
buffer += sizeof(uint16_t);
|
||||
*buffer = extension_class_;
|
||||
buffer += sizeof(uint8_t);
|
||||
*buffer = extension_type_;
|
||||
buffer += sizeof(uint8_t);
|
||||
copy(payload_.begin(), payload_.end(), buffer);
|
||||
OutputMemoryStream stream(buffer, buffer_size);
|
||||
stream.write(Endian::host_to_be<uint16_t>(size()));
|
||||
stream.write(extension_class_);
|
||||
stream.write(extension_type_);
|
||||
stream.write(payload_.begin(), payload_.end());
|
||||
}
|
||||
|
||||
ICMPExtension::serialization_type ICMPExtension::serialize() const {
|
||||
@@ -140,25 +136,18 @@ void ICMPExtensionsStructure::add_extension(const ICMPExtension& extension) {
|
||||
}
|
||||
|
||||
void ICMPExtensionsStructure::serialize(uint8_t* buffer, uint32_t buffer_size) {
|
||||
const uint32_t structure_size = size();
|
||||
if (buffer_size < structure_size) {
|
||||
throw malformed_packet();
|
||||
}
|
||||
OutputMemoryStream stream(buffer, buffer_size);
|
||||
uint8_t* original_ptr = buffer;
|
||||
memcpy(buffer, &version_and_reserved_, sizeof(version_and_reserved_));
|
||||
buffer += sizeof(uint16_t);
|
||||
stream.write(version_and_reserved_);
|
||||
// Make checksum 0, for now, we'll compute it at the end
|
||||
memset(buffer, 0, sizeof(uint16_t));
|
||||
buffer += sizeof(uint16_t);
|
||||
buffer_size -= BASE_HEADER_SIZE;
|
||||
stream.write<uint16_t>(0);
|
||||
|
||||
typedef extensions_type::const_iterator iterator;
|
||||
for (iterator iter = extensions_.begin(); iter != extensions_.end(); ++iter) {
|
||||
iter->serialize(buffer, buffer_size);
|
||||
buffer += iter->size();
|
||||
buffer_size -= iter->size();
|
||||
iter->serialize(stream.pointer(), stream.size());
|
||||
stream.skip(iter->size());
|
||||
}
|
||||
uint16_t checksum = ~Utils::sum_range(original_ptr, original_ptr + structure_size);
|
||||
uint16_t checksum = ~Utils::sum_range(original_ptr, original_ptr + size());
|
||||
memcpy(original_ptr + sizeof(uint16_t), &checksum, sizeof(checksum));
|
||||
checksum_ = checksum;
|
||||
}
|
||||
|
||||
@@ -40,6 +40,7 @@
|
||||
#include "memory_helpers.h"
|
||||
|
||||
using Tins::Memory::InputMemoryStream;
|
||||
using Tins::Memory::OutputMemoryStream;
|
||||
|
||||
namespace Tins {
|
||||
|
||||
@@ -213,12 +214,7 @@ bool ICMPv6::matches_response(const uint8_t *ptr, uint32_t total_sz) const {
|
||||
}
|
||||
|
||||
void ICMPv6::write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *parent) {
|
||||
#ifdef TINS_DEBUG
|
||||
assert(total_sz >= header_size());
|
||||
#endif
|
||||
uint32_t full_sz = total_sz;
|
||||
uint8_t *buffer_start = buffer;
|
||||
_header.cksum = 0;
|
||||
OutputMemoryStream stream(buffer, total_sz);
|
||||
|
||||
// If extensions are allowed and we have to set the length field
|
||||
if (are_extensions_allowed()) {
|
||||
@@ -230,36 +226,26 @@ void ICMPv6::write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *
|
||||
_header.rfc4884.length = length_value / sizeof(uint64_t);
|
||||
}
|
||||
}
|
||||
// Initially set checksum to 0, we'll calculate it at the end
|
||||
_header.cksum = 0;
|
||||
stream.write(_header);
|
||||
|
||||
std::memcpy(buffer, &_header, sizeof(_header));
|
||||
buffer += sizeof(_header);
|
||||
total_sz -= sizeof(_header);
|
||||
if(has_target_addr()) {
|
||||
buffer = _target_address.copy(buffer);
|
||||
total_sz -= sizeof(ipaddress_type::address_size);
|
||||
if (has_target_addr()) {
|
||||
stream.write(_target_address);
|
||||
}
|
||||
if(has_dest_addr()) {
|
||||
buffer = _dest_address.copy(buffer);
|
||||
total_sz -= sizeof(ipaddress_type::address_size);
|
||||
if (has_dest_addr()) {
|
||||
stream.write(_dest_address);
|
||||
}
|
||||
if(type() == ROUTER_ADVERT) {
|
||||
std::memcpy(buffer, &reach_time, sizeof(uint32_t));
|
||||
buffer += sizeof(uint32_t);
|
||||
std::memcpy(buffer, &retrans_timer, sizeof(uint32_t));
|
||||
buffer += sizeof(uint32_t);
|
||||
total_sz -= sizeof(uint32_t) * 2;
|
||||
if (type() == ROUTER_ADVERT) {
|
||||
stream.write(reach_time);
|
||||
stream.write(retrans_timer);
|
||||
}
|
||||
for(options_type::const_iterator it = _options.begin(); it != _options.end(); ++it) {
|
||||
#ifdef TINS_DEBUG
|
||||
assert(total_sz >= it->data_size() + sizeof(uint8_t) * 2);
|
||||
// total_sz is only used if TINS_DEBUG is defined.
|
||||
total_sz -= it->data_size() + sizeof(uint8_t) * 2;
|
||||
#endif
|
||||
buffer = write_option(*it, buffer);
|
||||
write_option(*it, stream);
|
||||
}
|
||||
|
||||
if (has_extensions()) {
|
||||
uint8_t* extensions_ptr = buffer;
|
||||
uint8_t* extensions_ptr = stream.pointer();
|
||||
if (inner_pdu()) {
|
||||
// Get the size of the next pdu, padded to the next 32 bit boundary
|
||||
uint32_t inner_pdu_size = get_adjusted_inner_pdu_size();
|
||||
@@ -278,21 +264,25 @@ void ICMPv6::write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *
|
||||
extensions_ptr += inner_pdu_size;
|
||||
}
|
||||
// Now serialize the exensions where they should be
|
||||
extensions_.serialize(extensions_ptr, total_sz - (extensions_ptr - buffer));
|
||||
extensions_.serialize(
|
||||
extensions_ptr,
|
||||
total_sz - (extensions_ptr - stream.pointer())
|
||||
);
|
||||
}
|
||||
|
||||
const Tins::IPv6 *ipv6 = tins_cast<const Tins::IPv6*>(parent);
|
||||
if(ipv6) {
|
||||
if (ipv6) {
|
||||
uint32_t checksum = Utils::pseudoheader_checksum(
|
||||
ipv6->src_addr(),
|
||||
ipv6->dst_addr(),
|
||||
size(),
|
||||
Constants::IP::PROTO_ICMPV6
|
||||
) + Utils::do_checksum(buffer_start, buffer_start + full_sz);
|
||||
while (checksum >> 16)
|
||||
ipv6->src_addr(),
|
||||
ipv6->dst_addr(),
|
||||
size(),
|
||||
Constants::IP::PROTO_ICMPV6
|
||||
) + Utils::do_checksum(buffer, buffer + total_sz);
|
||||
while (checksum >> 16) {
|
||||
checksum = (checksum & 0xffff) + (checksum >> 16);
|
||||
}
|
||||
this->checksum(~checksum);
|
||||
memcpy(buffer_start + 2, &_header.cksum, sizeof(uint16_t));
|
||||
memcpy(buffer + 2, &_header.cksum, sizeof(uint16_t));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -329,10 +319,10 @@ bool ICMPv6::remove_option(OptionTypes type) {
|
||||
return true;
|
||||
}
|
||||
|
||||
uint8_t *ICMPv6::write_option(const option &opt, uint8_t *buffer) {
|
||||
*buffer++ = opt.option();
|
||||
*buffer++ = static_cast<uint8_t>((opt.length_field() + sizeof(uint8_t) * 2) / 8);
|
||||
return std::copy(opt.data_ptr(), opt.data_ptr() + opt.data_size(), buffer);
|
||||
void ICMPv6::write_option(const option &opt, OutputMemoryStream& stream) {
|
||||
stream.write(opt.option());
|
||||
stream.write<uint8_t>((opt.length_field() + sizeof(uint8_t) * 2) / 8);
|
||||
stream.write(opt.data_ptr(), opt.data_size());
|
||||
}
|
||||
|
||||
const ICMPv6::option *ICMPv6::search_option(OptionTypes type) const {
|
||||
|
||||
51
src/ip.cpp
51
src/ip.cpp
@@ -53,6 +53,7 @@
|
||||
using std::list;
|
||||
|
||||
using Tins::Memory::InputMemoryStream;
|
||||
using Tins::Memory::OutputMemoryStream;
|
||||
|
||||
namespace Tins {
|
||||
|
||||
@@ -353,17 +354,17 @@ IP::options_type::iterator IP::search_option_iterator(option_identifier id) {
|
||||
return find_if(_ip_options.begin(), _ip_options.end(), comparator);
|
||||
}
|
||||
|
||||
uint8_t* IP::write_option(const option &opt, uint8_t* buffer) {
|
||||
option_identifier opt_type = opt.option();
|
||||
memcpy(buffer, &opt_type, 1);
|
||||
if(*buffer <= 1)
|
||||
return ++buffer;
|
||||
buffer++;
|
||||
*buffer = static_cast<uint8_t>(opt.length_field());
|
||||
if(opt.data_size() == opt.length_field())
|
||||
*buffer += 2;
|
||||
buffer++;
|
||||
return std::copy(opt.data_ptr(), opt.data_ptr() + opt.data_size(), buffer);
|
||||
void IP::write_option(const option &opt, OutputMemoryStream& stream) {
|
||||
stream.write(opt.option());
|
||||
// Check what we wrote. We'll do this for any option != [END, NOOP]
|
||||
if (*(stream.pointer() - 1) > NOOP) {
|
||||
uint8_t length = opt.length_field();
|
||||
if (opt.data_size() == opt.length_field()) {
|
||||
length += 2;
|
||||
}
|
||||
stream.write(length);
|
||||
stream.write(opt.data_ptr(), opt.data_size());
|
||||
}
|
||||
}
|
||||
|
||||
/* Virtual method overriding. */
|
||||
@@ -415,40 +416,40 @@ void IP::prepare_for_serialize(const PDU *parent) {
|
||||
}
|
||||
|
||||
void IP::write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU* parent) {
|
||||
uint32_t my_sz = header_size();
|
||||
#ifdef TINS_DEBUG
|
||||
assert(total_sz >= my_sz);
|
||||
#endif
|
||||
OutputMemoryStream stream(buffer, total_sz);
|
||||
checksum(0);
|
||||
if(inner_pdu()) {
|
||||
if (inner_pdu()) {
|
||||
uint32_t new_flag = Internals::pdu_flag_to_ip_type(inner_pdu()->pdu_type());
|
||||
if(new_flag == 0xff && Internals::pdu_type_registered<IP>(inner_pdu()->pdu_type())) {
|
||||
if (new_flag == 0xff && Internals::pdu_type_registered<IP>(inner_pdu()->pdu_type())) {
|
||||
new_flag = static_cast<Constants::IP::e>(
|
||||
Internals::pdu_type_to_id<IP>(inner_pdu()->pdu_type())
|
||||
);
|
||||
}
|
||||
if(!is_fragmented() && new_flag != 0xff)
|
||||
if (!is_fragmented() && new_flag != 0xff) {
|
||||
protocol(new_flag);
|
||||
}
|
||||
}
|
||||
|
||||
#if __FreeBSD__ || defined(__FreeBSD_kernel__) || __APPLE__
|
||||
if(!parent)
|
||||
if(!parent) {
|
||||
total_sz = Endian::host_to_be<uint16_t>(total_sz);
|
||||
}
|
||||
#endif
|
||||
tot_len(total_sz);
|
||||
head_len(static_cast<uint8_t>(my_sz / sizeof(uint32_t)));
|
||||
head_len(static_cast<uint8_t>(header_size() / sizeof(uint32_t)));
|
||||
|
||||
memcpy(buffer, &_ip, sizeof(_ip));
|
||||
stream.write(_ip);
|
||||
|
||||
uint8_t* ptr_buffer = buffer + sizeof(_ip);
|
||||
for(options_type::const_iterator it = _ip_options.begin(); it != _ip_options.end(); ++it) {
|
||||
ptr_buffer = write_option(*it, ptr_buffer);
|
||||
write_option(*it, stream);
|
||||
}
|
||||
memset(buffer + sizeof(_ip) + _options_size, 0, _padded_options_size - _options_size);
|
||||
// Add option padding
|
||||
stream.fill(_padded_options_size - _options_size, 0);
|
||||
|
||||
uint32_t check = Utils::do_checksum(buffer, buffer + sizeof(_ip) + _padded_options_size);
|
||||
while (check >> 16)
|
||||
while (check >> 16) {
|
||||
check = (check & 0xffff) + (check >> 16);
|
||||
}
|
||||
checksum(~check);
|
||||
((iphdr*)buffer)->check = _ip.check;
|
||||
}
|
||||
|
||||
25
src/ipv6.cpp
25
src/ipv6.cpp
@@ -48,6 +48,7 @@
|
||||
#include "memory_helpers.h"
|
||||
|
||||
using Tins::Memory::InputMemoryStream;
|
||||
using Tins::Memory::OutputMemoryStream;
|
||||
|
||||
namespace Tins {
|
||||
|
||||
@@ -191,12 +192,10 @@ bool IPv6::matches_response(const uint8_t *ptr, uint32_t total_sz) const {
|
||||
}
|
||||
|
||||
void IPv6::write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *parent) {
|
||||
#ifdef TINS_DEBUG
|
||||
assert(total_sz >= header_size());
|
||||
#endif
|
||||
if(inner_pdu()) {
|
||||
OutputMemoryStream stream(buffer, total_sz);
|
||||
if (inner_pdu()) {
|
||||
uint8_t new_flag = Internals::pdu_flag_to_ip_type(inner_pdu()->pdu_type());
|
||||
if(new_flag == 0xff && Internals::pdu_type_registered<IPv6>(inner_pdu()->pdu_type())) {
|
||||
if (new_flag == 0xff && Internals::pdu_type_registered<IPv6>(inner_pdu()->pdu_type())) {
|
||||
new_flag = static_cast<Constants::IP::e>(
|
||||
Internals::pdu_type_to_id<IPv6>(inner_pdu()->pdu_type())
|
||||
);
|
||||
@@ -204,10 +203,9 @@ void IPv6::write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *pa
|
||||
set_last_next_header(new_flag);
|
||||
}
|
||||
payload_length(static_cast<uint16_t>(total_sz - sizeof(_header)));
|
||||
std::memcpy(buffer, &_header, sizeof(_header));
|
||||
buffer += sizeof(_header);
|
||||
stream.write(_header);
|
||||
for(headers_type::const_iterator it = ext_headers.begin(); it != ext_headers.end(); ++it) {
|
||||
buffer = write_header(*it, buffer);
|
||||
write_header(*it, stream);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -249,10 +247,11 @@ void IPv6::set_last_next_header(uint8_t value) {
|
||||
ext_headers.back().option(value);
|
||||
}
|
||||
|
||||
uint8_t *IPv6::write_header(const ext_header &header, uint8_t *buffer) {
|
||||
*buffer++ = header.option();
|
||||
*buffer++ = static_cast<uint8_t>((header.length_field() > 8) ? (header.length_field() - 8) : 0);
|
||||
return std::copy(header.data_ptr(), header.data_ptr() + header.data_size(), buffer);
|
||||
void IPv6::write_header(const ext_header &header, OutputMemoryStream& stream) {
|
||||
const uint8_t length = (header.length_field() > 8) ? (header.length_field() - 8) : 0;
|
||||
stream.write(header.option());
|
||||
stream.write(length);
|
||||
stream.write(header.data_ptr(), header.data_size());
|
||||
}
|
||||
|
||||
}
|
||||
} // Tins
|
||||
|
||||
24
src/llc.cpp
24
src/llc.cpp
@@ -39,6 +39,7 @@
|
||||
#include "memory_helpers.h"
|
||||
|
||||
using Tins::Memory::InputMemoryStream;
|
||||
using Tins::Memory::OutputMemoryStream;
|
||||
|
||||
namespace Tins {
|
||||
|
||||
@@ -198,33 +199,26 @@ void LLC::clear_information_fields() {
|
||||
}
|
||||
|
||||
void LLC::write_serialization(uint8_t *buffer, uint32_t total_sz, const Tins::PDU *parent) {
|
||||
#ifdef TINS_DEBUG
|
||||
assert(total_sz >= header_size());
|
||||
#endif
|
||||
if(inner_pdu() && inner_pdu()->pdu_type() == PDU::STP) {
|
||||
OutputMemoryStream stream(buffer, total_sz);
|
||||
if (inner_pdu() && inner_pdu()->pdu_type() == PDU::STP) {
|
||||
dsap(0x42);
|
||||
ssap(0x42);
|
||||
}
|
||||
std::memcpy(buffer, &_header, sizeof(_header));
|
||||
buffer += sizeof(_header);
|
||||
stream.write(_header);
|
||||
switch (type()) {
|
||||
case LLC::UNNUMBERED:
|
||||
std::memcpy(buffer, &(control_field.unnumbered), sizeof(un_control_field));
|
||||
buffer += sizeof(un_control_field);
|
||||
stream.write(control_field.unnumbered);
|
||||
break;
|
||||
case LLC::INFORMATION:
|
||||
std::memcpy(buffer, &(control_field.info), sizeof(info_control_field));
|
||||
buffer += sizeof(info_control_field);
|
||||
stream.write(control_field.info);
|
||||
break;
|
||||
case LLC::SUPERVISORY:
|
||||
std::memcpy(buffer, &(control_field.super), sizeof(super_control_field));
|
||||
buffer += sizeof(super_control_field);
|
||||
stream.write(control_field.super);
|
||||
break;
|
||||
}
|
||||
|
||||
for (std::list<field_type>::const_iterator it = information_fields.begin(); it != information_fields.end(); it++) {
|
||||
std::copy(it->begin(), it->end(), buffer);
|
||||
buffer += it->size();
|
||||
for (field_list::const_iterator it = information_fields.begin(); it != information_fields.end(); it++) {
|
||||
stream.write(it->begin(), it->end());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -56,6 +56,7 @@
|
||||
#endif
|
||||
|
||||
using Tins::Memory::InputMemoryStream;
|
||||
using Tins::Memory::OutputMemoryStream;
|
||||
|
||||
namespace Tins {
|
||||
|
||||
@@ -95,15 +96,15 @@ uint32_t Loopback::header_size() const {
|
||||
}
|
||||
|
||||
void Loopback::write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *) {
|
||||
#ifdef TINS_DEBUG
|
||||
assert(total_sz >= sizeof(_family));
|
||||
#endif
|
||||
OutputMemoryStream stream(buffer, total_sz);
|
||||
#ifndef _WIN32
|
||||
if(tins_cast<const Tins::IP*>(inner_pdu()))
|
||||
if (tins_cast<const Tins::IP*>(inner_pdu())) {
|
||||
_family = PF_INET;
|
||||
else if(tins_cast<const Tins::LLC*>(inner_pdu()))
|
||||
}
|
||||
else if (tins_cast<const Tins::LLC*>(inner_pdu())) {
|
||||
_family = PF_LLC;
|
||||
*reinterpret_cast<uint32_t*>(buffer) = _family;
|
||||
}
|
||||
stream.write(_family);
|
||||
#endif // _WIN32
|
||||
}
|
||||
|
||||
|
||||
@@ -37,6 +37,7 @@
|
||||
#include "memory_helpers.h"
|
||||
|
||||
using Tins::Memory::InputMemoryStream;
|
||||
using Tins::Memory::OutputMemoryStream;
|
||||
|
||||
namespace Tins {
|
||||
|
||||
@@ -109,25 +110,15 @@ uint32_t PPPoE::header_size() const {
|
||||
|
||||
void PPPoE::write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *)
|
||||
{
|
||||
#ifdef TINS_DEBUG
|
||||
assert(total_sz == sizeof(_header) + _tags_size);
|
||||
#endif
|
||||
std::memcpy(buffer, &_header, sizeof(_header));
|
||||
if(_tags_size > 0)
|
||||
((pppoe_hdr*)buffer)->payload_length = Endian::host_to_be(_tags_size);
|
||||
buffer += sizeof(_header);
|
||||
uint16_t uint16_t_buffer;
|
||||
OutputMemoryStream stream(buffer, total_sz);
|
||||
if (_tags_size > 0) {
|
||||
payload_length(_tags_size);
|
||||
}
|
||||
stream.write(_header);
|
||||
for(tags_type::const_iterator it = _tags.begin(); it != _tags.end(); ++it) {
|
||||
uint16_t_buffer = it->option();
|
||||
std::memcpy(buffer, &uint16_t_buffer, sizeof(uint16_t));
|
||||
uint16_t_buffer = Endian::host_to_be(static_cast<uint16_t>(it->length_field()));
|
||||
std::memcpy(buffer + sizeof(uint16_t), &uint16_t_buffer, sizeof(uint16_t));
|
||||
std::copy(
|
||||
it->data_ptr(),
|
||||
it->data_ptr() + it->data_size(),
|
||||
buffer + sizeof(uint16_t) * 2
|
||||
);
|
||||
buffer += sizeof(uint16_t) * 2 + it->data_size();
|
||||
stream.write<uint16_t>(it->option());
|
||||
stream.write(Endian::host_to_be<uint16_t>(it->length_field()));
|
||||
stream.write(it->data_ptr(), it->data_size());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -50,8 +50,12 @@
|
||||
#include "utils.h"
|
||||
#include "packet_sender.h"
|
||||
#include "exceptions.h"
|
||||
#include "memory_helpers.h"
|
||||
|
||||
using Tins::Memory::OutputMemoryStream;
|
||||
|
||||
namespace Tins {
|
||||
|
||||
void check_size(uint32_t total_sz, size_t field_size) {
|
||||
if(total_sz < field_size)
|
||||
throw malformed_packet();
|
||||
@@ -471,87 +475,69 @@ bool RadioTap::matches_response(const uint8_t *ptr, uint32_t total_sz) const {
|
||||
}
|
||||
|
||||
void RadioTap::write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *parent) {
|
||||
uint32_t sz = header_size();
|
||||
OutputMemoryStream stream(buffer, total_sz);
|
||||
uint8_t *buffer_start = buffer;
|
||||
#ifdef TINS_DEBUG
|
||||
assert(total_sz >= sz);
|
||||
#endif
|
||||
_radio.it_len = Endian::host_to_le<uint16_t>(sz);
|
||||
memcpy(buffer, &_radio, sizeof(_radio));
|
||||
buffer += sizeof(_radio);
|
||||
_radio.it_len = Endian::host_to_le<uint16_t>(header_size());
|
||||
stream.write(_radio);
|
||||
if(_radio.flags.tsft) {
|
||||
memcpy(buffer, &_tsft, sizeof(_tsft));
|
||||
buffer += sizeof(_tsft);
|
||||
stream.write(_tsft);
|
||||
}
|
||||
if(_radio.flags.flags) {
|
||||
memcpy(buffer, &_flags, sizeof(_flags));
|
||||
buffer += sizeof(_flags);
|
||||
stream.write(_flags);
|
||||
}
|
||||
if(_radio.flags.rate) {
|
||||
memcpy(buffer, &_rate, sizeof(_rate));
|
||||
buffer += sizeof(_rate);
|
||||
stream.write(_rate);
|
||||
}
|
||||
if(_radio.flags.channel) {
|
||||
if(((buffer - buffer_start) & 1) == 1)
|
||||
*(buffer++) = 0;
|
||||
memcpy(buffer, &_channel_freq, sizeof(_channel_freq));
|
||||
buffer += sizeof(_channel_freq);
|
||||
memcpy(buffer, &_channel_type, sizeof(_channel_type));
|
||||
buffer += sizeof(_channel_type);
|
||||
if(((buffer - buffer_start) & 1) == 1) {
|
||||
stream.write<uint8_t>(0);
|
||||
}
|
||||
stream.write(_channel_freq);
|
||||
stream.write(_channel_type);
|
||||
}
|
||||
if(_radio.flags.dbm_signal) {
|
||||
memcpy(buffer, &_dbm_signal, sizeof(_dbm_signal));
|
||||
buffer += sizeof(_dbm_signal);
|
||||
stream.write(_dbm_signal);
|
||||
}
|
||||
if(_radio.flags.dbm_noise) {
|
||||
memcpy(buffer, &_dbm_noise, sizeof(_dbm_noise));
|
||||
buffer += sizeof(_dbm_noise);
|
||||
stream.write(_dbm_noise);
|
||||
}
|
||||
if(_radio.flags.lock_quality) {
|
||||
if(((buffer - buffer_start) & 1) == 1)
|
||||
*(buffer++) = 0;
|
||||
memcpy(buffer, &_signal_quality, sizeof(_signal_quality));
|
||||
buffer += sizeof(_signal_quality);
|
||||
if(((buffer - buffer_start) & 1) == 1) {
|
||||
stream.write<uint8_t>(0);
|
||||
}
|
||||
stream.write(_signal_quality);
|
||||
}
|
||||
if(_radio.flags.antenna) {
|
||||
memcpy(buffer, &_antenna, sizeof(_antenna));
|
||||
buffer += sizeof(_antenna);
|
||||
stream.write(_antenna);
|
||||
}
|
||||
if(_radio.flags.db_signal) {
|
||||
memcpy(buffer, &_db_signal, sizeof(_db_signal));
|
||||
buffer += sizeof(_db_signal);
|
||||
stream.write(_db_signal);
|
||||
}
|
||||
if(_radio.flags.rx_flags) {
|
||||
if(((buffer - buffer_start) & 1) == 1)
|
||||
*(buffer++) = 0;
|
||||
memcpy(buffer, &_rx_flags, sizeof(_rx_flags));
|
||||
buffer += sizeof(_rx_flags);
|
||||
if(((buffer - buffer_start) & 1) == 1) {
|
||||
stream.write<uint8_t>(0);
|
||||
}
|
||||
stream.write(_rx_flags);
|
||||
}
|
||||
if(_radio.flags.channel_plus) {
|
||||
uint32_t offset = ((buffer - buffer_start) % 4);
|
||||
if(offset) {
|
||||
offset = 4 - offset;
|
||||
while(offset--) {
|
||||
*buffer++ = 0;
|
||||
}
|
||||
const uint32_t padding = ((stream.pointer() - buffer_start) % 4);
|
||||
if (padding != 0) {
|
||||
stream.fill(4 - padding, 0);
|
||||
}
|
||||
uint32_t dummy = _channel_type;
|
||||
// nasty Big Endian fix
|
||||
dummy = Endian::le_to_host<uint32_t>(Endian::host_to_le<uint16_t>(dummy));
|
||||
memcpy(buffer, &dummy, sizeof(dummy));
|
||||
buffer += sizeof(dummy);
|
||||
memcpy(buffer, &_channel_freq, sizeof(_channel_freq));
|
||||
buffer += sizeof(_channel_freq);
|
||||
memcpy(buffer, &_channel, sizeof(_channel));
|
||||
buffer += sizeof(_channel);
|
||||
memcpy(buffer, &_max_power, sizeof(_max_power));
|
||||
buffer += sizeof(_max_power);
|
||||
stream.write(dummy);
|
||||
stream.write(_channel_freq);
|
||||
stream.write(_channel);
|
||||
stream.write(_max_power);
|
||||
}
|
||||
if((_flags & 0x10) != 0 && inner_pdu()) {
|
||||
if ((_flags & 0x10) != 0 && inner_pdu()) {
|
||||
uint32_t crc32 = Endian::host_to_le(
|
||||
Utils::crc32(buffer, inner_pdu()->size())
|
||||
Utils::crc32(stream.pointer(), inner_pdu()->size())
|
||||
);
|
||||
memcpy(buffer + inner_pdu()->size(), &crc32, sizeof(uint32_t));
|
||||
stream.skip(inner_pdu()->size());
|
||||
stream.write(crc32);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,7 +32,9 @@
|
||||
#endif
|
||||
#include <algorithm>
|
||||
#include "rawpdu.h"
|
||||
#include "memory_helpers.h"
|
||||
|
||||
using Tins::Memory::OutputMemoryStream;
|
||||
|
||||
namespace Tins {
|
||||
RawPDU::RawPDU(const uint8_t *pload, uint32_t size)
|
||||
@@ -51,10 +53,8 @@ uint32_t RawPDU::header_size() const {
|
||||
}
|
||||
|
||||
void RawPDU::write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *) {
|
||||
#ifdef TINS_DEBUG
|
||||
assert(total_sz >= _payload.size());
|
||||
#endif
|
||||
std::copy(_payload.begin(), _payload.end(), buffer);
|
||||
OutputMemoryStream stream(buffer, total_sz);
|
||||
stream.write(_payload.begin(), _payload.end());
|
||||
}
|
||||
|
||||
void RawPDU::payload(const payload_type &pload) {
|
||||
|
||||
@@ -38,6 +38,7 @@
|
||||
#include "dot11/dot11_base.h"
|
||||
|
||||
using Tins::Memory::InputMemoryStream;
|
||||
using Tins::Memory::OutputMemoryStream;
|
||||
|
||||
namespace Tins {
|
||||
|
||||
@@ -107,27 +108,18 @@ RSNInformation::serialization_type RSNInformation::serialize() const {
|
||||
const uint16_t akm_cyphers_size = Endian::host_to_le<uint16_t>(_akm_cyphers.size());
|
||||
|
||||
serialization_type buffer(size);
|
||||
serialization_type::value_type *ptr = &buffer[0];
|
||||
std::memcpy(ptr, &_version, sizeof(_version));
|
||||
ptr += sizeof(uint16_t);
|
||||
std::memcpy(ptr, &_group_suite, sizeof(uint32_t));
|
||||
ptr += sizeof(uint32_t);
|
||||
std::memcpy(ptr, &pairwise_cyphers_size, sizeof(pairwise_cyphers_size));
|
||||
ptr += sizeof(uint16_t);
|
||||
for(cyphers_type::const_iterator it = _pairwise_cyphers.begin(); it != _pairwise_cyphers.end(); ++it) {
|
||||
const uint32_t value = Endian::host_to_le<uint32_t>(*it);
|
||||
std::memcpy(ptr, &value, sizeof(uint32_t));
|
||||
ptr += sizeof(uint32_t);
|
||||
OutputMemoryStream stream(&buffer[0], buffer.size());
|
||||
stream.write(_version);
|
||||
stream.write(_group_suite);
|
||||
stream.write(pairwise_cyphers_size);
|
||||
for (cyphers_type::const_iterator it = _pairwise_cyphers.begin(); it != _pairwise_cyphers.end(); ++it) {
|
||||
stream.write(Endian::host_to_le<uint32_t>(*it));
|
||||
}
|
||||
std::memcpy(ptr, &akm_cyphers_size, sizeof(akm_cyphers_size));
|
||||
ptr += sizeof(uint16_t);
|
||||
for(akm_type::const_iterator it = _akm_cyphers.begin(); it != _akm_cyphers.end(); ++it) {
|
||||
const uint32_t value = Endian::host_to_le<uint32_t>(*it);
|
||||
std::memcpy(ptr, &value, sizeof(uint32_t));
|
||||
ptr += sizeof(uint32_t);
|
||||
stream.write(akm_cyphers_size);
|
||||
for (akm_type::const_iterator it = _akm_cyphers.begin(); it != _akm_cyphers.end(); ++it) {
|
||||
stream.write(Endian::host_to_le<uint32_t>(*it));
|
||||
}
|
||||
std::memcpy(ptr, &_capabilities, sizeof(uint16_t));
|
||||
|
||||
stream.write(_capabilities);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
|
||||
@@ -35,6 +35,7 @@
|
||||
#include "memory_helpers.h"
|
||||
|
||||
using Tins::Memory::InputMemoryStream;
|
||||
using Tins::Memory::OutputMemoryStream;
|
||||
|
||||
namespace Tins {
|
||||
|
||||
@@ -81,12 +82,14 @@ uint32_t SLL::header_size() const {
|
||||
}
|
||||
|
||||
void SLL::write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *) {
|
||||
if(inner_pdu()) {
|
||||
OutputMemoryStream stream(buffer, total_sz);
|
||||
if (inner_pdu()) {
|
||||
Constants::Ethernet::e flag = Internals::pdu_flag_to_ether_type(
|
||||
inner_pdu()->pdu_type()
|
||||
);
|
||||
protocol(static_cast<uint16_t>(flag));
|
||||
}
|
||||
std::memcpy(buffer, &_header, sizeof(_header));
|
||||
}
|
||||
stream.write(_header);
|
||||
}
|
||||
|
||||
} // Tins
|
||||
|
||||
@@ -46,6 +46,7 @@
|
||||
#include "memory_helpers.h"
|
||||
|
||||
using Tins::Memory::InputMemoryStream;
|
||||
using Tins::Memory::OutputMemoryStream;
|
||||
|
||||
namespace Tins {
|
||||
|
||||
@@ -95,9 +96,7 @@ uint32_t SNAP::header_size() const {
|
||||
}
|
||||
|
||||
void SNAP::write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *parent) {
|
||||
#ifdef TINS_DEBUG
|
||||
assert(total_sz >= sizeof(_snap));
|
||||
#endif
|
||||
OutputMemoryStream stream(buffer, total_sz);
|
||||
if (inner_pdu()) {
|
||||
Constants::Ethernet::e flag = Internals::pdu_flag_to_ether_type(
|
||||
inner_pdu()->pdu_type()
|
||||
@@ -106,7 +105,7 @@ void SNAP::write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *pa
|
||||
static_cast<uint16_t>(flag)
|
||||
);
|
||||
}
|
||||
std::memcpy(buffer, &_snap, sizeof(_snap));
|
||||
stream.write(_snap);
|
||||
}
|
||||
|
||||
} // Tins
|
||||
|
||||
@@ -37,6 +37,7 @@
|
||||
#include "memory_helpers.h"
|
||||
|
||||
using Tins::Memory::InputMemoryStream;
|
||||
using Tins::Memory::OutputMemoryStream;
|
||||
|
||||
namespace Tins {
|
||||
|
||||
@@ -109,10 +110,8 @@ void STP::bridge_id(const bpdu_id_type &id) {
|
||||
}
|
||||
|
||||
void STP::write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *) {
|
||||
#ifdef TINS_DEBUG
|
||||
assert(total_sz >= sizeof(_header));
|
||||
#endif
|
||||
std::memcpy(buffer, &_header, sizeof(_header));
|
||||
OutputMemoryStream stream(buffer, total_sz);
|
||||
stream.write(_header);
|
||||
}
|
||||
|
||||
uint32_t STP::header_size() const {
|
||||
|
||||
75
src/tcp.cpp
75
src/tcp.cpp
@@ -41,7 +41,9 @@
|
||||
#include "memory_helpers.h"
|
||||
|
||||
using std::find_if;
|
||||
|
||||
using Tins::Memory::InputMemoryStream;
|
||||
using Tins::Memory::OutputMemoryStream;
|
||||
|
||||
namespace Tins {
|
||||
|
||||
@@ -291,46 +293,46 @@ uint32_t TCP::header_size() const {
|
||||
}
|
||||
|
||||
void TCP::write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *parent) {
|
||||
assert(total_sz >= header_size());
|
||||
uint8_t *tcp_start = buffer;
|
||||
OutputMemoryStream stream(buffer, total_sz);
|
||||
// Set checksum to 0, we'll calculate it at the end
|
||||
checksum(0);
|
||||
buffer += sizeof(tcphdr);
|
||||
_tcp.doff = (sizeof(tcphdr) + _total_options_size) / sizeof(uint32_t);
|
||||
for(options_type::iterator it = _options.begin(); it != _options.end(); ++it)
|
||||
buffer = write_option(*it, buffer);
|
||||
|
||||
if(_options_size < _total_options_size) {
|
||||
uint16_t padding = _options_size;
|
||||
while(padding < _total_options_size) {
|
||||
*(buffer++) = 1;
|
||||
padding++;
|
||||
}
|
||||
stream.write(_tcp);
|
||||
for(options_type::const_iterator it = _options.begin(); it != _options.end(); ++it) {
|
||||
write_option(*it, stream);
|
||||
}
|
||||
|
||||
memcpy(tcp_start, &_tcp, sizeof(tcphdr));
|
||||
if (_options_size < _total_options_size) {
|
||||
const uint16_t padding = _total_options_size - _options_size;
|
||||
stream.fill(padding, 1);
|
||||
}
|
||||
|
||||
const Tins::IP *ip_packet = tins_cast<const Tins::IP*>(parent);
|
||||
if(ip_packet) {
|
||||
uint32_t check = Utils::pseudoheader_checksum(ip_packet->src_addr(),
|
||||
ip_packet->dst_addr(),
|
||||
size(), Constants::IP::PROTO_TCP) +
|
||||
Utils::do_checksum(tcp_start, tcp_start + total_sz);
|
||||
while (check >> 16)
|
||||
uint32_t check = Utils::pseudoheader_checksum(
|
||||
ip_packet->src_addr(),
|
||||
ip_packet->dst_addr(),
|
||||
size(),
|
||||
Constants::IP::PROTO_TCP) + Utils::do_checksum(buffer, buffer + total_sz);
|
||||
while (check >> 16) {
|
||||
check = (check & 0xffff) + (check >> 16);
|
||||
}
|
||||
checksum(~check);
|
||||
((tcphdr*)tcp_start)->check = _tcp.check;
|
||||
((tcphdr*)buffer)->check = _tcp.check;
|
||||
}
|
||||
else {
|
||||
const Tins::IPv6 *ipv6_packet = tins_cast<const Tins::IPv6*>(parent);
|
||||
if(ipv6_packet) {
|
||||
uint32_t check = Utils::pseudoheader_checksum(ipv6_packet->src_addr(),
|
||||
ipv6_packet->dst_addr(),
|
||||
size(), Constants::IP::PROTO_TCP) +
|
||||
Utils::do_checksum(tcp_start, tcp_start + total_sz);
|
||||
while (check >> 16)
|
||||
uint32_t check = Utils::pseudoheader_checksum(
|
||||
ipv6_packet->src_addr(),
|
||||
ipv6_packet->dst_addr(),
|
||||
size(),
|
||||
Constants::IP::PROTO_TCP) + Utils::do_checksum(buffer, buffer + total_sz);
|
||||
while (check >> 16) {
|
||||
check = (check & 0xffff) + (check >> 16);
|
||||
}
|
||||
checksum(~check);
|
||||
((tcphdr*)tcp_start)->check = _tcp.check;
|
||||
((tcphdr*)buffer)->check = _tcp.check;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -353,19 +355,18 @@ TCP::options_type::iterator TCP::search_option_iterator(OptionTypes type) {
|
||||
|
||||
/* options */
|
||||
|
||||
uint8_t *TCP::write_option(const option &opt, uint8_t *buffer) {
|
||||
if(opt.option() == 0 || opt.option() == 1) {
|
||||
*buffer = opt.option();
|
||||
return buffer + 1;
|
||||
}
|
||||
else {
|
||||
buffer[0] = opt.option();
|
||||
buffer[1] = static_cast<uint8_t>(opt.length_field());
|
||||
// only add the identifier and size field sizes if the length
|
||||
void TCP::write_option(const option &opt, OutputMemoryStream& stream) {
|
||||
stream.write<uint8_t>(opt.option());
|
||||
// Only do this for non EOL nor NOP options
|
||||
if(opt.option() > 1) {
|
||||
uint8_t length = opt.length_field();
|
||||
// Only add the identifier and size field sizes if the length
|
||||
// field hasn't been spoofed.
|
||||
if(opt.length_field() == opt.data_size())
|
||||
buffer[1] += (sizeof(uint8_t) << 1);
|
||||
return std::copy(opt.data_ptr(), opt.data_ptr() + opt.data_size(), buffer + 2);
|
||||
if(opt.length_field() == opt.data_size()) {
|
||||
length += (sizeof(uint8_t) << 1);
|
||||
}
|
||||
stream.write(length);
|
||||
stream.write(opt.data_ptr(), opt.data_size());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
34
src/udp.cpp
34
src/udp.cpp
@@ -42,6 +42,7 @@
|
||||
#include "memory_helpers.h"
|
||||
|
||||
using Tins::Memory::InputMemoryStream;
|
||||
using Tins::Memory::OutputMemoryStream;
|
||||
|
||||
namespace Tins {
|
||||
|
||||
@@ -77,9 +78,8 @@ uint32_t UDP::header_size() const {
|
||||
}
|
||||
|
||||
void UDP::write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *parent) {
|
||||
#ifdef TINS_DEBUG
|
||||
assert(total_sz >= sizeof(udphdr));
|
||||
#endif
|
||||
OutputMemoryStream stream(buffer, total_sz);
|
||||
// Set checksum to 0, we'll calculate it at the end
|
||||
_udp.check = 0;
|
||||
if(inner_pdu()) {
|
||||
length(static_cast<uint16_t>(sizeof(udphdr) + inner_pdu()->size()));
|
||||
@@ -87,17 +87,18 @@ void UDP::write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *par
|
||||
else {
|
||||
length(static_cast<uint16_t>(sizeof(udphdr)));
|
||||
}
|
||||
std::memcpy(buffer, &_udp, sizeof(udphdr));
|
||||
stream.write(_udp);
|
||||
const Tins::IP *ip_packet = tins_cast<const Tins::IP*>(parent);
|
||||
if(ip_packet) {
|
||||
uint32_t checksum = Utils::pseudoheader_checksum(
|
||||
ip_packet->src_addr(),
|
||||
ip_packet->dst_addr(),
|
||||
size(),
|
||||
Constants::IP::PROTO_UDP
|
||||
) + Utils::do_checksum(buffer, buffer + total_sz);
|
||||
while (checksum >> 16)
|
||||
ip_packet->src_addr(),
|
||||
ip_packet->dst_addr(),
|
||||
size(),
|
||||
Constants::IP::PROTO_UDP
|
||||
) + Utils::do_checksum(buffer, buffer + total_sz);
|
||||
while (checksum >> 16) {
|
||||
checksum = (checksum & 0xffff)+(checksum >> 16);
|
||||
}
|
||||
_udp.check = Endian::host_to_be<uint16_t>(~checksum);
|
||||
((udphdr*)buffer)->check = _udp.check;
|
||||
}
|
||||
@@ -105,13 +106,14 @@ void UDP::write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *par
|
||||
const Tins::IPv6 *ip6_packet = tins_cast<const Tins::IPv6*>(parent);
|
||||
if(ip6_packet) {
|
||||
uint32_t checksum = Utils::pseudoheader_checksum(
|
||||
ip6_packet->src_addr(),
|
||||
ip6_packet->dst_addr(),
|
||||
size(),
|
||||
Constants::IP::PROTO_UDP
|
||||
) + Utils::do_checksum(buffer, buffer + total_sz);
|
||||
while (checksum >> 16)
|
||||
ip6_packet->src_addr(),
|
||||
ip6_packet->dst_addr(),
|
||||
size(),
|
||||
Constants::IP::PROTO_UDP
|
||||
) + Utils::do_checksum(buffer, buffer + total_sz);
|
||||
while (checksum >> 16) {
|
||||
checksum = (checksum & 0xffff)+(checksum >> 16);
|
||||
}
|
||||
_udp.check = Endian::host_to_be<uint16_t>(~checksum);
|
||||
((udphdr*)buffer)->check = _udp.check;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user