1
0
mirror of https://github.com/mfontanini/libtins synced 2026-01-27 04:11:35 +01:00

Add OutputMemoryStream and port most classes to use it

This commit is contained in:
Matias Fontanini
2015-12-26 06:30:00 -08:00
parent 9750f46c6d
commit 02e2b278de
34 changed files with 438 additions and 418 deletions

View File

@@ -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());
}
}