Skip to content

Commit

Permalink
Use InputMemoryStream when parsing PDU options and ICMP extensions
Browse files Browse the repository at this point in the history
  • Loading branch information
mfontanini committed Jun 9, 2017
1 parent 550eea9 commit eed8229
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 27 deletions.
6 changes: 3 additions & 3 deletions src/icmp_extension.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,6 @@ ICMPExtension::ICMPExtension(uint8_t ext_class, uint8_t ext_type)

}


ICMPExtension::ICMPExtension(const uint8_t* buffer, uint32_t total_sz) {
InputMemoryStream stream(buffer, total_sz);

Expand Down Expand Up @@ -138,10 +137,11 @@ bool ICMPExtensionsStructure::validate_extensions(const uint8_t* buffer, uint32_
if (total_sz < BASE_HEADER_SIZE) {
return false;
}
uint16_t checksum = *(const uint16_t*)(buffer + sizeof(uint16_t));
InputMemoryStream input(buffer, total_sz);
// The buffer is read only, so we can't set the initial checksum to 0. Therefore,
// we sum the first 2 bytes and then the payload
uint32_t actual_checksum = *(const uint16_t*)buffer;
uint32_t actual_checksum = input.read<uint16_t>();
uint16_t checksum = input.read<uint16_t>();
buffer += BASE_HEADER_SIZE;
total_sz -= BASE_HEADER_SIZE;
// Now do the checksum over the payload
Expand Down
53 changes: 29 additions & 24 deletions src/pdu_option.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,13 +34,16 @@
#include "hw_address.h"
#include "endianness.h"
#include "pdu_option.h"
#include "memory_helpers.h"

using std::vector;
using std::pair;
using std::string;
using std::memcpy;
using std::distance;

using Tins::Memory::InputMemoryStream;

namespace Tins {
namespace Internals {
namespace Converters {
Expand All @@ -61,21 +64,21 @@ T convert_to_integral(const uint8_t* ptr, uint32_t data_size, PDU::endian_type e
}

template<typename T>
vector<T> convert_vector(const uint8_t* u8_ptr, uint32_t data_size, PDU::endian_type endian) {
vector<T> convert_vector(const uint8_t* ptr, uint32_t data_size, PDU::endian_type endian) {
if (data_size % sizeof(T) != 0) {
throw malformed_option();
}
const T* ptr = (const T*)u8_ptr;
const T* end = (const T*)(ptr + data_size / sizeof(T));
InputMemoryStream input(ptr, data_size);

vector<T> output(distance(ptr, end));
vector<T> output(data_size / sizeof(T));
typename vector<T>::iterator it = output.begin();
while (ptr < end) {
while (input) {
const T value = input.read<T>();
if (endian == PDU::BE) {
*it++ = Endian::be_to_host(*ptr++);
*it++ = Endian::be_to_host(value);
}
else {
*it++ = Endian::le_to_host(*ptr++);
*it++ = Endian::le_to_host(value);
}
}
return output;
Expand All @@ -88,14 +91,14 @@ convert_vector(const uint8_t* ptr, uint32_t data_size, PDU::endian_type endian)
if (data_size % (sizeof(T) + sizeof(U)) != 0) {
throw malformed_option();
}
const uint8_t* end = ptr + data_size;
InputMemoryStream input(ptr, data_size);

std::vector<std::pair<T, U> > output;
while (ptr < end) {
while (input) {
pair<T, U> data;
data.first = *(const T*)ptr;
data.first = input.read<T>();
ptr += sizeof(T);
data.second = *(const U*)ptr;
data.second = input.read<U>();
ptr += sizeof(U);
if (endian == PDU::BE) {
data.first = Endian::be_to_host(data.first);
Expand All @@ -117,9 +120,10 @@ convert_pair(const uint8_t* ptr, uint32_t data_size, PDU::endian_type endian) {
if (data_size != sizeof(T) + sizeof(U)) {
throw malformed_option();
}
InputMemoryStream input(ptr, data_size);
pair<T, U> output;
memcpy(&output.first, ptr, sizeof(T));
memcpy(&output.second, ptr + sizeof(T), sizeof(U));
output.first = input.read<T>();
output.second = input.read<U>();
if (endian == PDU::BE) {
output.first = Endian::be_to_host(output.first);
output.second = Endian::be_to_host(output.second);
Expand Down Expand Up @@ -169,17 +173,18 @@ HWAddress<6> convert(const uint8_t* ptr, uint32_t data_size, PDU::endian_type,
return HWAddress<6>(ptr);
}

IPv4Address convert(const uint8_t* u8_ptr, uint32_t data_size, PDU::endian_type endian,
IPv4Address convert(const uint8_t* ptr, uint32_t data_size, PDU::endian_type endian,
type_to_type<IPv4Address>) {
if (data_size != sizeof(uint32_t)) {
throw malformed_option();
}
const uint32_t* ptr = (const uint32_t*)u8_ptr;
InputMemoryStream input(ptr, data_size);
const uint32_t ip_int = input.read<uint32_t>();
if (endian == PDU::BE) {
return IPv4Address(*ptr);
return IPv4Address(ip_int);
}
else {
return IPv4Address(Endian::change_endian(*ptr));
return IPv4Address(Endian::change_endian(ip_int));
}
}

Expand Down Expand Up @@ -221,22 +226,22 @@ vector<uint32_t> convert(const uint8_t* ptr, uint32_t data_size, PDU::endian_typ
return convert_vector<uint32_t>(ptr, data_size, endian);
}

vector<IPv4Address> convert(const uint8_t* u8_ptr, uint32_t data_size, PDU::endian_type endian,
vector<IPv4Address> convert(const uint8_t* ptr, uint32_t data_size, PDU::endian_type endian,
type_to_type<vector<IPv4Address> >) {
if (data_size % 4 != 0) {
throw malformed_option();
}
const uint32_t* ptr = (const uint32_t*)u8_ptr;
const uint32_t* end = (const uint32_t*)(ptr + data_size / sizeof(uint32_t));

vector<IPv4Address> output(distance(ptr, end));
InputMemoryStream input(ptr, data_size);
vector<IPv4Address> output(data_size / sizeof(uint32_t));
vector<IPv4Address>::iterator it = output.begin();
while (ptr < end) {
while (input) {
const uint32_t ip_int = input.read<uint32_t>();
if (endian == PDU::BE) {
*it++ = IPv4Address(*ptr++);
*it++ = IPv4Address(ip_int);
}
else {
*it++ = IPv4Address(Endian::change_endian(*ptr++));
*it++ = IPv4Address(Endian::change_endian(ip_int));
}
}
return output;
Expand Down

0 comments on commit eed8229

Please sign in to comment.