mirror of
https://github.com/mfontanini/libtins
synced 2026-01-23 02:35:57 +01:00
fix armv5 alignment issues
This commit is contained in:
@@ -30,6 +30,7 @@
|
|||||||
#ifndef TINS_DHCPV6_H
|
#ifndef TINS_DHCPV6_H
|
||||||
#define TINS_DHCPV6_H
|
#define TINS_DHCPV6_H
|
||||||
|
|
||||||
|
#include <cstring>
|
||||||
#include <list>
|
#include <list>
|
||||||
#include "pdu.h"
|
#include "pdu.h"
|
||||||
#include "endianness.h"
|
#include "endianness.h"
|
||||||
@@ -886,9 +887,11 @@ void class_option_data2option(InputIterator start, InputIterator end,
|
|||||||
std::vector<uint8_t>& buffer, size_t start_index = 0)
|
std::vector<uint8_t>& buffer, size_t start_index = 0)
|
||||||
{
|
{
|
||||||
size_t index = start_index;
|
size_t index = start_index;
|
||||||
|
uint16_t uint16_t_buffer;
|
||||||
while(start != end) {
|
while(start != end) {
|
||||||
buffer.resize(buffer.size() + sizeof(uint16_t) + start->size());
|
buffer.resize(buffer.size() + sizeof(uint16_t) + start->size());
|
||||||
*(uint16_t*)&buffer[index] = Endian::host_to_be<uint16_t>(start->size());
|
uint16_t_buffer = Endian::host_to_be<uint16_t>(start->size());
|
||||||
|
std::memcpy(&buffer[index], &uint16_t_buffer, sizeof(uint16_t));
|
||||||
index += sizeof(uint16_t);
|
index += sizeof(uint16_t);
|
||||||
std::copy(start->begin(), start->end(), buffer.begin() + index);
|
std::copy(start->begin(), start->end(), buffer.begin() + index);
|
||||||
index += start->size();
|
index += start->size();
|
||||||
@@ -904,9 +907,9 @@ OutputType option2class_option_data(const uint8_t *ptr, uint32_t total_sz)
|
|||||||
OutputType output;
|
OutputType output;
|
||||||
size_t index = 0;
|
size_t index = 0;
|
||||||
while(index + 2 < total_sz) {
|
while(index + 2 < total_sz) {
|
||||||
uint16_t size = Endian::be_to_host(
|
uint16_t size;
|
||||||
*(const uint16_t*)(ptr + index)
|
std::memcpy(&size, ptr + index, sizeof(uint16_t));
|
||||||
);
|
size = Endian::be_to_host(size);
|
||||||
index += sizeof(uint16_t);
|
index += sizeof(uint16_t);
|
||||||
if(index + size > total_sz)
|
if(index + size > total_sz)
|
||||||
throw option_not_found();
|
throw option_not_found();
|
||||||
|
|||||||
@@ -32,6 +32,7 @@
|
|||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <iterator>
|
#include <iterator>
|
||||||
|
#include <cstring>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
@@ -266,8 +267,8 @@ namespace Internals {
|
|||||||
if(opt.data_size() != sizeof(T) + sizeof(U))
|
if(opt.data_size() != sizeof(T) + sizeof(U))
|
||||||
throw malformed_option();
|
throw malformed_option();
|
||||||
std::pair<T, U> output;
|
std::pair<T, U> output;
|
||||||
output.first = *(const T*)opt.data_ptr();
|
std::memcpy(&output.first, opt.data_ptr(), sizeof(T));
|
||||||
output.second = *(const U*)(opt.data_ptr() + sizeof(T));
|
std::memcpy(&output.second, opt.data_ptr() + sizeof(T), sizeof(U));
|
||||||
if(PDUType::endianness == PDUType::BE) {
|
if(PDUType::endianness == PDUType::BE) {
|
||||||
output.first = Endian::be_to_host(output.first);
|
output.first = Endian::be_to_host(output.first);
|
||||||
output.second = Endian::be_to_host(output.second);
|
output.second = Endian::be_to_host(output.second);
|
||||||
|
|||||||
@@ -29,6 +29,7 @@
|
|||||||
|
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
|
#include <cstring>
|
||||||
#include "endianness.h"
|
#include "endianness.h"
|
||||||
#include "dhcp.h"
|
#include "dhcp.h"
|
||||||
#include "ethernetII.h"
|
#include "ethernetII.h"
|
||||||
@@ -52,7 +53,9 @@ DHCP::DHCP(const uint8_t *buffer, uint32_t total_sz)
|
|||||||
buffer += BootP::header_size() - vend().size();
|
buffer += BootP::header_size() - vend().size();
|
||||||
total_sz -= BootP::header_size() - vend().size();
|
total_sz -= BootP::header_size() - vend().size();
|
||||||
uint8_t args[2] = {0};
|
uint8_t args[2] = {0};
|
||||||
if(total_sz < sizeof(uint32_t) || *(uint32_t*)buffer != Endian::host_to_be<uint32_t>(0x63825363))
|
uint32_t uint32_t_buffer;
|
||||||
|
std::memcpy(&uint32_t_buffer, buffer, sizeof(uint32_t));
|
||||||
|
if(total_sz < sizeof(uint32_t) || uint32_t_buffer != Endian::host_to_be<uint32_t>(0x63825363))
|
||||||
throw malformed_packet();
|
throw malformed_packet();
|
||||||
buffer += sizeof(uint32_t);
|
buffer += sizeof(uint32_t);
|
||||||
total_sz -= sizeof(uint32_t);
|
total_sz -= sizeof(uint32_t);
|
||||||
|
|||||||
@@ -63,10 +63,12 @@ DHCPv6::DHCPv6(const uint8_t *buffer, uint32_t total_sz)
|
|||||||
if(total_sz < sizeof(uint16_t) * 2)
|
if(total_sz < sizeof(uint16_t) * 2)
|
||||||
throw malformed_packet();
|
throw malformed_packet();
|
||||||
|
|
||||||
const uint16_t opt = Endian::be_to_host(*(const uint16_t*)buffer);
|
uint16_t opt;
|
||||||
const uint16_t data_size = Endian::be_to_host(
|
std::memcpy(&opt, buffer, sizeof(uint16_t));
|
||||||
*(const uint16_t*)(buffer + sizeof(uint16_t))
|
opt = Endian::be_to_host(opt);
|
||||||
);
|
uint16_t data_size;
|
||||||
|
std::memcpy(&data_size, buffer + sizeof(uint16_t), sizeof(uint16_t));
|
||||||
|
data_size = Endian::be_to_host(data_size);
|
||||||
if(total_sz - sizeof(uint16_t) * 2 < data_size)
|
if(total_sz - sizeof(uint16_t) * 2 < data_size)
|
||||||
throw malformed_packet();
|
throw malformed_packet();
|
||||||
buffer += sizeof(uint16_t) * 2;
|
buffer += sizeof(uint16_t) * 2;
|
||||||
@@ -91,8 +93,10 @@ const DHCPv6::option *DHCPv6::search_option(OptionTypes id) const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
uint8_t* DHCPv6::write_option(const option &opt, uint8_t* buffer) const {
|
uint8_t* DHCPv6::write_option(const option &opt, uint8_t* buffer) const {
|
||||||
*(uint16_t*)buffer = Endian::host_to_be(opt.option());
|
uint16_t uint16_t_buffer = Endian::host_to_be(opt.option());
|
||||||
*(uint16_t*)&buffer[sizeof(uint16_t)] = Endian::host_to_be<uint16_t>(opt.length_field());
|
std::memcpy(buffer, &uint16_t_buffer, sizeof(uint16_t));
|
||||||
|
uint16_t_buffer = Endian::host_to_be<uint16_t>(opt.length_field());
|
||||||
|
std::memcpy(&buffer[sizeof(uint16_t)], &uint16_t_buffer, sizeof(uint16_t));
|
||||||
return std::copy(
|
return std::copy(
|
||||||
opt.data_ptr(),
|
opt.data_ptr(),
|
||||||
opt.data_ptr() + opt.data_size(),
|
opt.data_ptr() + opt.data_size(),
|
||||||
@@ -289,8 +293,11 @@ void DHCPv6::option_request(const option_request_type &value) {
|
|||||||
|
|
||||||
std::vector<uint8_t> buffer(value.size() * sizeof(uint16_t));
|
std::vector<uint8_t> buffer(value.size() * sizeof(uint16_t));
|
||||||
size_t index = 0;
|
size_t index = 0;
|
||||||
for(iterator it = value.begin(); it != value.end(); ++it, index += 2)
|
uint16_t uint16_t_buffer;
|
||||||
*(uint16_t*)&buffer[index] = Endian::host_to_be<uint16_t>(*it);
|
for(iterator it = value.begin(); it != value.end(); ++it, index += 2) {
|
||||||
|
uint16_t_buffer = Endian::host_to_be<uint16_t>(*it);
|
||||||
|
std::memcpy(&buffer[index], &uint16_t_buffer, sizeof(uint16_t));
|
||||||
|
}
|
||||||
add_option(
|
add_option(
|
||||||
option(OPTION_REQUEST, buffer.begin(), buffer.end())
|
option(OPTION_REQUEST, buffer.begin(), buffer.end())
|
||||||
);
|
);
|
||||||
@@ -322,7 +329,8 @@ void DHCPv6::authentication(const authentication_type &value) {
|
|||||||
buffer[0] = value.protocol;
|
buffer[0] = value.protocol;
|
||||||
buffer[1] = value.algorithm;
|
buffer[1] = value.algorithm;
|
||||||
buffer[2] = value.rdm;
|
buffer[2] = value.rdm;
|
||||||
*(uint64_t*)&buffer[3] = Endian::host_to_be(value.replay_detection);
|
uint64_t uint64_t_buffer = Endian::host_to_be(value.replay_detection);
|
||||||
|
std::memcpy(&buffer[3], &uint64_t_buffer, sizeof(uint64_t));
|
||||||
std::copy(
|
std::copy(
|
||||||
value.auth_info.begin(),
|
value.auth_info.begin(),
|
||||||
value.auth_info.end(),
|
value.auth_info.end(),
|
||||||
@@ -341,7 +349,8 @@ void DHCPv6::server_unicast(const ipaddress_type &value) {
|
|||||||
|
|
||||||
void DHCPv6::status_code(const status_code_type &value) {
|
void DHCPv6::status_code(const status_code_type &value) {
|
||||||
std::vector<uint8_t> buffer(sizeof(uint16_t) + value.message.size());
|
std::vector<uint8_t> buffer(sizeof(uint16_t) + value.message.size());
|
||||||
*(uint16_t*)&buffer[0] = Endian::host_to_be(value.code);
|
uint16_t uint16_t_buffer = Endian::host_to_be(value.code);
|
||||||
|
std::memcpy(&buffer[0], &uint16_t_buffer, sizeof(uint16_t));
|
||||||
std::copy(
|
std::copy(
|
||||||
value.message.begin(),
|
value.message.begin(),
|
||||||
value.message.end(),
|
value.message.end(),
|
||||||
@@ -372,7 +381,8 @@ void DHCPv6::vendor_class(const vendor_class_type &value) {
|
|||||||
std::vector<uint8_t> buffer(
|
std::vector<uint8_t> buffer(
|
||||||
sizeof(uint32_t)
|
sizeof(uint32_t)
|
||||||
);
|
);
|
||||||
*(uint32_t*)&buffer[0] = Endian::host_to_be(value.enterprise_number);
|
uint32_t enterprise_number = Endian::host_to_be(value.enterprise_number);
|
||||||
|
std::memcpy(&buffer[0], &enterprise_number, sizeof(uint32_t));
|
||||||
Internals::class_option_data2option(
|
Internals::class_option_data2option(
|
||||||
value.vendor_class_data.begin(),
|
value.vendor_class_data.begin(),
|
||||||
value.vendor_class_data.end(),
|
value.vendor_class_data.end(),
|
||||||
@@ -386,7 +396,8 @@ void DHCPv6::vendor_class(const vendor_class_type &value) {
|
|||||||
|
|
||||||
void DHCPv6::vendor_info(const vendor_info_type &value) {
|
void DHCPv6::vendor_info(const vendor_info_type &value) {
|
||||||
std::vector<uint8_t> buffer(sizeof(uint32_t) + value.data.size());
|
std::vector<uint8_t> buffer(sizeof(uint32_t) + value.data.size());
|
||||||
*(uint32_t*)&buffer[0] = Endian::host_to_be(value.enterprise_number);
|
uint32_t enterprise_number = Endian::host_to_be(value.enterprise_number);
|
||||||
|
std::memcpy(&buffer[0], &enterprise_number, sizeof(uint32_t));
|
||||||
std::copy(
|
std::copy(
|
||||||
value.data.begin(),
|
value.data.begin(),
|
||||||
value.data.end(),
|
value.data.end(),
|
||||||
@@ -422,9 +433,11 @@ DHCPv6::duid_llt DHCPv6::duid_llt::from_bytes(const uint8_t *buffer, uint32_t to
|
|||||||
if(total_sz < sizeof(uint16_t) + sizeof(uint32_t) + 1)
|
if(total_sz < sizeof(uint16_t) + sizeof(uint32_t) + 1)
|
||||||
throw std::runtime_error("Not enough size for a DUID_LLT identifier");
|
throw std::runtime_error("Not enough size for a DUID_LLT identifier");
|
||||||
duid_llt output;
|
duid_llt output;
|
||||||
output.hw_type = Endian::be_to_host(*(const uint16_t*)buffer);
|
std::memcpy(&output.hw_type, buffer, sizeof(uint16_t));
|
||||||
|
output.hw_type = Endian::be_to_host(output.hw_type);
|
||||||
buffer += sizeof(uint16_t);
|
buffer += sizeof(uint16_t);
|
||||||
output.time = Endian::be_to_host(*(const uint32_t*)buffer);
|
std::memcpy(&output.time, buffer, sizeof(uint32_t));
|
||||||
|
output.time = Endian::be_to_host(output.time);
|
||||||
buffer += sizeof(uint32_t);
|
buffer += sizeof(uint32_t);
|
||||||
total_sz -= sizeof(uint16_t) + sizeof(uint32_t);
|
total_sz -= sizeof(uint16_t) + sizeof(uint32_t);
|
||||||
output.lladdress.assign(buffer, buffer + total_sz);
|
output.lladdress.assign(buffer, buffer + total_sz);
|
||||||
@@ -433,8 +446,10 @@ DHCPv6::duid_llt DHCPv6::duid_llt::from_bytes(const uint8_t *buffer, uint32_t to
|
|||||||
|
|
||||||
PDU::serialization_type DHCPv6::duid_llt::serialize() const {
|
PDU::serialization_type DHCPv6::duid_llt::serialize() const {
|
||||||
serialization_type output(sizeof(uint16_t) + sizeof(uint32_t) + lladdress.size());
|
serialization_type output(sizeof(uint16_t) + sizeof(uint32_t) + lladdress.size());
|
||||||
*(uint16_t*)&output[0] = Endian::host_to_be(hw_type);
|
uint16_t tmp_hw_type = Endian::host_to_be(hw_type);
|
||||||
*(uint32_t*)&output[sizeof(uint16_t)] = Endian::host_to_be(time);
|
uint32_t tmp_time = Endian::host_to_be(time);
|
||||||
|
std::memcpy(&output[0], &tmp_hw_type, sizeof(uint16_t));
|
||||||
|
std::memcpy(&output[sizeof(uint16_t)], &tmp_time, sizeof(uint32_t));
|
||||||
std::copy(
|
std::copy(
|
||||||
lladdress.begin(),
|
lladdress.begin(),
|
||||||
lladdress.end(),
|
lladdress.end(),
|
||||||
@@ -449,7 +464,8 @@ DHCPv6::duid_en DHCPv6::duid_en::from_bytes(const uint8_t *buffer, uint32_t tota
|
|||||||
if(total_sz < sizeof(uint32_t) + 1)
|
if(total_sz < sizeof(uint32_t) + 1)
|
||||||
throw std::runtime_error("Not enough size for a DUID_en identifier");
|
throw std::runtime_error("Not enough size for a DUID_en identifier");
|
||||||
duid_en output;
|
duid_en output;
|
||||||
output.enterprise_number = Endian::be_to_host(*(const uint32_t*)buffer);
|
std::memcpy(&output.enterprise_number, buffer, sizeof(uint32_t));
|
||||||
|
output.enterprise_number = Endian::be_to_host(output.enterprise_number);
|
||||||
buffer += sizeof(uint32_t);
|
buffer += sizeof(uint32_t);
|
||||||
total_sz -= sizeof(uint32_t);
|
total_sz -= sizeof(uint32_t);
|
||||||
output.identifier.assign(buffer, buffer + total_sz);
|
output.identifier.assign(buffer, buffer + total_sz);
|
||||||
@@ -458,7 +474,8 @@ DHCPv6::duid_en DHCPv6::duid_en::from_bytes(const uint8_t *buffer, uint32_t tota
|
|||||||
|
|
||||||
PDU::serialization_type DHCPv6::duid_en::serialize() const {
|
PDU::serialization_type DHCPv6::duid_en::serialize() const {
|
||||||
serialization_type output(sizeof(uint32_t) + identifier.size());
|
serialization_type output(sizeof(uint32_t) + identifier.size());
|
||||||
*(uint32_t*)&output[0] = Endian::host_to_be(enterprise_number);
|
uint32_t tmp_enterprise_number = Endian::host_to_be(enterprise_number);
|
||||||
|
std::memcpy(&output[0], &tmp_enterprise_number, sizeof(uint32_t));
|
||||||
std::copy(
|
std::copy(
|
||||||
identifier.begin(),
|
identifier.begin(),
|
||||||
identifier.end(),
|
identifier.end(),
|
||||||
@@ -473,7 +490,8 @@ DHCPv6::duid_ll DHCPv6::duid_ll::from_bytes(const uint8_t *buffer, uint32_t tota
|
|||||||
if(total_sz < sizeof(uint16_t) + 1)
|
if(total_sz < sizeof(uint16_t) + 1)
|
||||||
throw std::runtime_error("Not enough size for a DUID_en identifier");
|
throw std::runtime_error("Not enough size for a DUID_en identifier");
|
||||||
duid_ll output;
|
duid_ll output;
|
||||||
output.hw_type = Endian::be_to_host(*(const uint16_t*)buffer);
|
std::memcpy(&output.hw_type, buffer, sizeof(uint16_t));
|
||||||
|
output.hw_type = Endian::be_to_host(output.hw_type);
|
||||||
buffer += sizeof(uint16_t);
|
buffer += sizeof(uint16_t);
|
||||||
total_sz -= sizeof(uint16_t);
|
total_sz -= sizeof(uint16_t);
|
||||||
output.lladdress.assign(buffer, buffer + total_sz);
|
output.lladdress.assign(buffer, buffer + total_sz);
|
||||||
@@ -482,7 +500,8 @@ DHCPv6::duid_ll DHCPv6::duid_ll::from_bytes(const uint8_t *buffer, uint32_t tota
|
|||||||
|
|
||||||
PDU::serialization_type DHCPv6::duid_ll::serialize() const {
|
PDU::serialization_type DHCPv6::duid_ll::serialize() const {
|
||||||
serialization_type output(sizeof(uint16_t) + lladdress.size());
|
serialization_type output(sizeof(uint16_t) + lladdress.size());
|
||||||
*(uint16_t*)&output[0] = Endian::host_to_be(hw_type);
|
uint16_t tmp_hw_type = Endian::host_to_be(hw_type);
|
||||||
|
std::memcpy(&output[0], &tmp_hw_type, sizeof(uint16_t));
|
||||||
std::copy(
|
std::copy(
|
||||||
lladdress.begin(),
|
lladdress.begin(),
|
||||||
lladdress.end(),
|
lladdress.end(),
|
||||||
@@ -493,7 +512,8 @@ PDU::serialization_type DHCPv6::duid_ll::serialize() const {
|
|||||||
|
|
||||||
void DHCPv6::client_id(const duid_type &value) {
|
void DHCPv6::client_id(const duid_type &value) {
|
||||||
serialization_type buffer(sizeof(uint16_t) + value.data.size());
|
serialization_type buffer(sizeof(uint16_t) + value.data.size());
|
||||||
*(uint16_t*)&buffer[0] = Endian::host_to_be(value.id);
|
uint16_t tmp_id = Endian::host_to_be(value.id);
|
||||||
|
std::memcpy(&buffer[0], &tmp_id, sizeof(uint16_t));
|
||||||
std::copy(
|
std::copy(
|
||||||
value.data.begin(),
|
value.data.begin(),
|
||||||
value.data.end(),
|
value.data.end(),
|
||||||
@@ -506,7 +526,8 @@ void DHCPv6::client_id(const duid_type &value) {
|
|||||||
|
|
||||||
void DHCPv6::server_id(const duid_type &value) {
|
void DHCPv6::server_id(const duid_type &value) {
|
||||||
serialization_type buffer(sizeof(uint16_t) + value.data.size());
|
serialization_type buffer(sizeof(uint16_t) + value.data.size());
|
||||||
*(uint16_t*)&buffer[0] = Endian::host_to_be(value.id);
|
uint16_t tmp_id = Endian::host_to_be(value.id);
|
||||||
|
std::memcpy(&buffer[0], &tmp_id, sizeof(uint16_t));
|
||||||
std::copy(
|
std::copy(
|
||||||
value.data.begin(),
|
value.data.begin(),
|
||||||
value.data.end(),
|
value.data.end(),
|
||||||
@@ -568,9 +589,8 @@ DHCPv6::authentication_type DHCPv6::authentication_type::from_option(const optio
|
|||||||
output.protocol = *ptr++;
|
output.protocol = *ptr++;
|
||||||
output.algorithm = *ptr++;
|
output.algorithm = *ptr++;
|
||||||
output.rdm = *ptr++;
|
output.rdm = *ptr++;
|
||||||
output.replay_detection = Endian::be_to_host(
|
std::memcpy(&output.replay_detection, ptr, sizeof(uint64_t));
|
||||||
*(const uint64_t*)ptr
|
output.replay_detection = Endian::be_to_host(output.replay_detection);
|
||||||
);
|
|
||||||
ptr += sizeof(uint64_t);
|
ptr += sizeof(uint64_t);
|
||||||
output.auth_info.assign(ptr, opt.data_ptr() + opt.data_size());
|
output.auth_info.assign(ptr, opt.data_ptr() + opt.data_size());
|
||||||
return output;
|
return output;
|
||||||
@@ -581,7 +601,8 @@ DHCPv6::status_code_type DHCPv6::status_code_type::from_option(const option &opt
|
|||||||
if(opt.data_size() < sizeof(uint16_t))
|
if(opt.data_size() < sizeof(uint16_t))
|
||||||
throw malformed_option();
|
throw malformed_option();
|
||||||
status_code_type output;
|
status_code_type output;
|
||||||
output.code = Endian::be_to_host(*(const uint16_t*)opt.data_ptr());
|
std::memcpy(&output.code, opt.data_ptr(), sizeof(uint16_t));
|
||||||
|
output.code = Endian::be_to_host(output.code);
|
||||||
output.message.assign(
|
output.message.assign(
|
||||||
opt.data_ptr() + sizeof(uint16_t),
|
opt.data_ptr() + sizeof(uint16_t),
|
||||||
opt.data_ptr() + opt.data_size()
|
opt.data_ptr() + opt.data_size()
|
||||||
@@ -594,9 +615,8 @@ DHCPv6::vendor_info_type DHCPv6::vendor_info_type::from_option(const option &opt
|
|||||||
if(opt.data_size() < sizeof(uint32_t))
|
if(opt.data_size() < sizeof(uint32_t))
|
||||||
throw malformed_option();
|
throw malformed_option();
|
||||||
vendor_info_type output;
|
vendor_info_type output;
|
||||||
output.enterprise_number = Endian::be_to_host(
|
std::memcpy(&output.enterprise_number, opt.data_ptr(), sizeof(uint32_t));
|
||||||
*(const uint32_t*)opt.data_ptr()
|
output.enterprise_number = Endian::be_to_host(output.enterprise_number);
|
||||||
);
|
|
||||||
output.data.assign(
|
output.data.assign(
|
||||||
opt.data_ptr() + sizeof(uint32_t),
|
opt.data_ptr() + sizeof(uint32_t),
|
||||||
opt.data_ptr() + opt.data_size()
|
opt.data_ptr() + opt.data_size()
|
||||||
@@ -610,9 +630,8 @@ DHCPv6::vendor_class_type DHCPv6::vendor_class_type::from_option(const option &o
|
|||||||
throw malformed_option();
|
throw malformed_option();
|
||||||
typedef vendor_class_type::class_data_type data_type;
|
typedef vendor_class_type::class_data_type data_type;
|
||||||
vendor_class_type output;
|
vendor_class_type output;
|
||||||
output.enterprise_number = Endian::be_to_host(
|
std::memcpy(&output.enterprise_number, opt.data_ptr(), sizeof(uint32_t));
|
||||||
*(const uint32_t*)opt.data_ptr()
|
output.enterprise_number = Endian::be_to_host(output.enterprise_number);
|
||||||
);
|
|
||||||
output.vendor_class_data = Internals::option2class_option_data<data_type>(
|
output.vendor_class_data = Internals::option2class_option_data<data_type>(
|
||||||
opt.data_ptr() + sizeof(uint32_t),
|
opt.data_ptr() + sizeof(uint32_t),
|
||||||
opt.data_size() - sizeof(uint32_t)
|
opt.data_size() - sizeof(uint32_t)
|
||||||
@@ -625,8 +644,11 @@ DHCPv6::duid_type DHCPv6::duid_type::from_option(const option &opt)
|
|||||||
{
|
{
|
||||||
if(opt.data_size() < sizeof(uint16_t) + 1)
|
if(opt.data_size() < sizeof(uint16_t) + 1)
|
||||||
throw malformed_option();
|
throw malformed_option();
|
||||||
|
|
||||||
|
uint16_t uint16_t_buffer;
|
||||||
|
std::memcpy(&uint16_t_buffer, opt.data_ptr(), sizeof(uint16_t));
|
||||||
return duid_type(
|
return duid_type(
|
||||||
Endian::be_to_host(*(const uint16_t*)opt.data_ptr()),
|
Endian::be_to_host(uint16_t_buffer),
|
||||||
serialization_type(
|
serialization_type(
|
||||||
opt.data_ptr() + sizeof(uint16_t),
|
opt.data_ptr() + sizeof(uint16_t),
|
||||||
opt.data_ptr() + opt.data_size()
|
opt.data_ptr() + opt.data_size()
|
||||||
|
|||||||
77
src/dns.cpp
77
src/dns.cpp
@@ -97,12 +97,14 @@ const uint8_t* DNS::find_dname_end(const uint8_t *ptr) const {
|
|||||||
|
|
||||||
const uint8_t *DNS::find_section_end(const uint8_t *ptr, const uint32_t num_records) const {
|
const uint8_t *DNS::find_section_end(const uint8_t *ptr, const uint32_t num_records) const {
|
||||||
const uint8_t *end = &records_data[0] + records_data.size();
|
const uint8_t *end = &records_data[0] + records_data.size();
|
||||||
|
uint16_t uint16_t_buffer;
|
||||||
for(uint32_t i = 0; i < num_records; ++i) {
|
for(uint32_t i = 0; i < num_records; ++i) {
|
||||||
ptr = find_dname_end(ptr);
|
ptr = find_dname_end(ptr);
|
||||||
if(ptr + sizeof(uint16_t) * 3 + sizeof(uint32_t) > end)
|
if(ptr + sizeof(uint16_t) * 3 + sizeof(uint32_t) > end)
|
||||||
throw malformed_packet();
|
throw malformed_packet();
|
||||||
ptr += sizeof(uint16_t) * 2 + sizeof(uint32_t);
|
ptr += sizeof(uint16_t) * 2 + sizeof(uint32_t);
|
||||||
uint16_t data_size = Endian::be_to_host(*(uint16_t*)ptr); // Data size
|
std::memcpy(&uint16_t_buffer, ptr, sizeof(uint16_t));
|
||||||
|
uint16_t data_size = Endian::be_to_host(uint16_t_buffer); // Data size
|
||||||
ptr += sizeof(uint16_t);
|
ptr += sizeof(uint16_t);
|
||||||
if(ptr + data_size > end)
|
if(ptr + data_size > end)
|
||||||
throw malformed_packet();
|
throw malformed_packet();
|
||||||
@@ -168,8 +170,11 @@ void DNS::add_query(const Query &query) {
|
|||||||
string new_str = encode_domain_name(query.dname());
|
string new_str = encode_domain_name(query.dname());
|
||||||
// Type (2 bytes) + Class (2 Bytes)
|
// Type (2 bytes) + Class (2 Bytes)
|
||||||
new_str.insert(new_str.end(), sizeof(uint16_t) * 2, ' ');
|
new_str.insert(new_str.end(), sizeof(uint16_t) * 2, ' ');
|
||||||
*(uint16_t*)&new_str[new_str.size() - 4] = Endian::host_to_be<uint16_t>(query.type());
|
uint16_t uint16_t_buffer;
|
||||||
*(uint16_t*)&new_str[new_str.size() - 2] = Endian::host_to_be<uint16_t>(query.query_class());
|
uint16_t_buffer = Endian::host_to_be<uint16_t>(query.type());
|
||||||
|
std::memcpy(&new_str[new_str.size() - 4], &uint16_t_buffer, sizeof(uint16_t));
|
||||||
|
uint16_t_buffer = Endian::host_to_be<uint16_t>(query.query_class());
|
||||||
|
std::memcpy(&new_str[new_str.size() - 2], &uint16_t_buffer, sizeof(uint16_t));
|
||||||
|
|
||||||
uint32_t offset = new_str.size(), threshold = answers_idx;
|
uint32_t offset = new_str.size(), threshold = answers_idx;
|
||||||
update_records(answers_idx, answers_count(), threshold, offset);
|
update_records(answers_idx, answers_count(), threshold, offset);
|
||||||
@@ -235,15 +240,23 @@ void DNS::add_record(const Resource &resource, const sections_type §ions) {
|
|||||||
buffer.end(),
|
buffer.end(),
|
||||||
&records_data[threshold]
|
&records_data[threshold]
|
||||||
);
|
);
|
||||||
*(uint16_t*)ptr = Endian::host_to_be(resource.type());
|
|
||||||
|
uint16_t uint16_t_buffer;
|
||||||
|
uint32_t uint32_t_buffer;
|
||||||
|
|
||||||
|
uint16_t_buffer = Endian::host_to_be(resource.type());
|
||||||
|
std::memcpy(ptr, &uint16_t_buffer, sizeof(uint16_t));
|
||||||
ptr += sizeof(uint16_t);
|
ptr += sizeof(uint16_t);
|
||||||
*(uint16_t*)ptr = Endian::host_to_be(resource.query_class());
|
uint16_t_buffer = Endian::host_to_be(resource.query_class());
|
||||||
|
std::memcpy(ptr, &uint16_t_buffer, sizeof(uint16_t));
|
||||||
ptr += sizeof(uint16_t);
|
ptr += sizeof(uint16_t);
|
||||||
*(uint32_t*)ptr = Endian::host_to_be(resource.ttl());
|
uint32_t_buffer = Endian::host_to_be(resource.ttl());
|
||||||
|
std::memcpy(ptr, &uint32_t_buffer, sizeof(uint32_t));
|
||||||
ptr += sizeof(uint32_t);
|
ptr += sizeof(uint32_t);
|
||||||
*(uint16_t*)ptr = Endian::host_to_be<uint16_t>(
|
uint16_t_buffer = Endian::host_to_be<uint16_t>(
|
||||||
data_size + (resource.type() == MX ? 2 : 0)
|
data_size + (resource.type() == MX ? 2 : 0)
|
||||||
);
|
);
|
||||||
|
std::memcpy(ptr, &uint16_t_buffer, sizeof(uint16_t));
|
||||||
ptr += sizeof(uint16_t);
|
ptr += sizeof(uint16_t);
|
||||||
if(resource.type() == MX) {
|
if(resource.type() == MX) {
|
||||||
ptr += sizeof(uint16_t);
|
ptr += sizeof(uint16_t);
|
||||||
@@ -305,7 +318,9 @@ const uint8_t* DNS::compose_name(const uint8_t *ptr, char *out_ptr) const {
|
|||||||
if((*ptr & 0xc0)) {
|
if((*ptr & 0xc0)) {
|
||||||
if(ptr + sizeof(uint16_t) > end)
|
if(ptr + sizeof(uint16_t) > end)
|
||||||
throw malformed_packet();
|
throw malformed_packet();
|
||||||
uint16_t index = Endian::be_to_host(*(uint16_t*)ptr) & 0x3fff;
|
uint16_t index;
|
||||||
|
std::memcpy(&index, ptr, sizeof(uint16_t));
|
||||||
|
index = Endian::be_to_host(index) & 0x3fff;
|
||||||
// Check that the offset is neither too low or too high
|
// Check that the offset is neither too low or too high
|
||||||
if(index < 0x0c || &records_data[index - 0x0c] >= ptr)
|
if(index < 0x0c || &records_data[index - 0x0c] >= ptr)
|
||||||
throw malformed_packet();
|
throw malformed_packet();
|
||||||
@@ -376,13 +391,17 @@ void DNS::convert_records(const uint8_t *ptr, const uint8_t *end, resources_type
|
|||||||
// Retrieve the following fields.
|
// Retrieve the following fields.
|
||||||
uint16_t type, qclass, data_size;
|
uint16_t type, qclass, data_size;
|
||||||
uint32_t ttl;
|
uint32_t ttl;
|
||||||
type = Endian::be_to_host(*(uint16_t*)ptr); // Type
|
std::memcpy(&type, ptr, sizeof(uint16_t)); // Type
|
||||||
|
type = Endian::be_to_host(type);
|
||||||
ptr += sizeof(uint16_t);
|
ptr += sizeof(uint16_t);
|
||||||
qclass = Endian::be_to_host(*(uint16_t*)ptr); // Class
|
std::memcpy(&qclass, ptr, sizeof(uint16_t)); // Class
|
||||||
|
qclass = Endian::be_to_host(qclass);
|
||||||
ptr += sizeof(uint16_t);
|
ptr += sizeof(uint16_t);
|
||||||
ttl = Endian::be_to_host(*(uint32_t*)ptr); // TTL
|
std::memcpy(&ttl, ptr, sizeof(uint32_t)); // TTL
|
||||||
|
ttl = Endian::be_to_host(ttl);
|
||||||
ptr += sizeof(uint32_t);
|
ptr += sizeof(uint32_t);
|
||||||
data_size = Endian::be_to_host(*(uint16_t*)ptr); // Data size
|
std::memcpy(&data_size, ptr, sizeof(uint16_t)); // Data size
|
||||||
|
data_size = Endian::be_to_host(data_size);
|
||||||
ptr += sizeof(uint16_t);
|
ptr += sizeof(uint16_t);
|
||||||
// Skip the preference field if it's MX
|
// Skip the preference field if it's MX
|
||||||
if(type == MX) {
|
if(type == MX) {
|
||||||
@@ -393,6 +412,7 @@ void DNS::convert_records(const uint8_t *ptr, const uint8_t *end, resources_type
|
|||||||
}
|
}
|
||||||
if(ptr + data_size > end)
|
if(ptr + data_size > end)
|
||||||
throw malformed_packet();
|
throw malformed_packet();
|
||||||
|
|
||||||
switch(type) {
|
switch(type) {
|
||||||
case AAAA:
|
case AAAA:
|
||||||
if(data_size != 16)
|
if(data_size != 16)
|
||||||
@@ -400,10 +420,14 @@ void DNS::convert_records(const uint8_t *ptr, const uint8_t *end, resources_type
|
|||||||
addr = IPv6Address(ptr).to_string();
|
addr = IPv6Address(ptr).to_string();
|
||||||
break;
|
break;
|
||||||
case A:
|
case A:
|
||||||
if(data_size != 4)
|
if(data_size == 4) {
|
||||||
|
uint32_t uint32_t_buffer;
|
||||||
|
std::memcpy(&uint32_t_buffer, ptr, sizeof(uint32_t));
|
||||||
|
inline_convert_v4(uint32_t_buffer, small_addr_buf);
|
||||||
|
used_small_buffer = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
throw malformed_packet();
|
throw malformed_packet();
|
||||||
inline_convert_v4(*(uint32_t*)ptr, small_addr_buf);
|
|
||||||
used_small_buffer = true;
|
|
||||||
break;
|
break;
|
||||||
case NS:
|
case NS:
|
||||||
case CNAME:
|
case CNAME:
|
||||||
@@ -443,9 +467,12 @@ void DNS::convert_records(const uint8_t *ptr, const uint8_t *end, resources_type
|
|||||||
uint8_t *DNS::update_dname(uint8_t *ptr, uint32_t threshold, uint32_t offset) {
|
uint8_t *DNS::update_dname(uint8_t *ptr, uint32_t threshold, uint32_t offset) {
|
||||||
while(*ptr != 0) {
|
while(*ptr != 0) {
|
||||||
if((*ptr & 0xc0)) {
|
if((*ptr & 0xc0)) {
|
||||||
uint16_t index = Endian::be_to_host(*(uint16_t*)ptr) & 0x3fff;
|
uint16_t index;
|
||||||
|
std::memcpy(&index, ptr, sizeof(uint16_t));
|
||||||
|
index = Endian::be_to_host(index) & 0x3fff;
|
||||||
if(index > threshold) {
|
if(index > threshold) {
|
||||||
*(uint16_t*)ptr = Endian::host_to_be<uint16_t>((index + offset) | 0xc000);
|
index = Endian::host_to_be<uint16_t>((index + offset) | 0xc000);
|
||||||
|
std::memcpy(ptr, &index, sizeof(uint16_t));
|
||||||
}
|
}
|
||||||
ptr += sizeof(uint16_t);
|
ptr += sizeof(uint16_t);
|
||||||
break;
|
break;
|
||||||
@@ -463,9 +490,13 @@ void DNS::update_records(uint32_t §ion_start, uint32_t num_records, uint32_t
|
|||||||
uint8_t *ptr = &records_data[section_start];
|
uint8_t *ptr = &records_data[section_start];
|
||||||
for(uint32_t i = 0; i < num_records; ++i) {
|
for(uint32_t i = 0; i < num_records; ++i) {
|
||||||
ptr = update_dname(ptr, threshold, offset);
|
ptr = update_dname(ptr, threshold, offset);
|
||||||
uint16_t type = Endian::be_to_host(*(const uint16_t*)ptr);
|
uint16_t type;
|
||||||
|
std::memcpy(&type, ptr, sizeof(uint16_t));
|
||||||
|
type = Endian::be_to_host(type);
|
||||||
ptr += sizeof(uint16_t) * 2 + sizeof(uint32_t);
|
ptr += sizeof(uint16_t) * 2 + sizeof(uint32_t);
|
||||||
uint16_t size = Endian::be_to_host(*(uint16_t*)ptr);
|
uint16_t size;
|
||||||
|
std::memcpy(&size, ptr, sizeof(uint16_t));
|
||||||
|
size = Endian::be_to_host(size);
|
||||||
ptr += sizeof(uint16_t);
|
ptr += sizeof(uint16_t);
|
||||||
if(type == MX) {
|
if(type == MX) {
|
||||||
ptr += sizeof(uint16_t);
|
ptr += sizeof(uint16_t);
|
||||||
@@ -483,15 +514,19 @@ DNS::queries_type DNS::queries() const {
|
|||||||
queries_type output;
|
queries_type output;
|
||||||
const uint8_t *ptr = &records_data[0], *end = &records_data[answers_idx];
|
const uint8_t *ptr = &records_data[0], *end = &records_data[answers_idx];
|
||||||
char buffer[256];
|
char buffer[256];
|
||||||
|
uint16_t tmp_query_type;
|
||||||
|
uint16_t tmp_query_class;
|
||||||
while(ptr < end) {
|
while(ptr < end) {
|
||||||
ptr = compose_name(ptr, buffer);
|
ptr = compose_name(ptr, buffer);
|
||||||
if(ptr + sizeof(uint16_t) * 2 > end)
|
if(ptr + sizeof(uint16_t) * 2 > end)
|
||||||
throw malformed_packet();
|
throw malformed_packet();
|
||||||
|
std::memcpy(&tmp_query_type, ptr, sizeof(uint16_t));
|
||||||
|
std::memcpy(&tmp_query_class, ptr + 2, sizeof(uint16_t));
|
||||||
output.push_back(
|
output.push_back(
|
||||||
Query(
|
Query(
|
||||||
buffer,
|
buffer,
|
||||||
(QueryType)Endian::be_to_host(*(const uint16_t*)ptr),
|
(QueryType)Endian::be_to_host(tmp_query_type),
|
||||||
(QueryClass)Endian::be_to_host(*(const uint16_t*)(ptr + 2))
|
(QueryClass)Endian::be_to_host(tmp_query_class)
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
ptr += sizeof(uint16_t) * 2;
|
ptr += sizeof(uint16_t) * 2;
|
||||||
|
|||||||
@@ -153,7 +153,7 @@ Dot11QoSData::Dot11QoSData(const uint8_t *buffer, uint32_t total_sz)
|
|||||||
total_sz -= sz;
|
total_sz -= sz;
|
||||||
if(total_sz < sizeof(_qos_control))
|
if(total_sz < sizeof(_qos_control))
|
||||||
throw malformed_packet();
|
throw malformed_packet();
|
||||||
_qos_control = *(uint16_t*)buffer;
|
std::memcpy(&_qos_control, buffer, sizeof(uint16_t));
|
||||||
total_sz -= sizeof(uint16_t);
|
total_sz -= sizeof(uint16_t);
|
||||||
buffer += sizeof(uint16_t);
|
buffer += sizeof(uint16_t);
|
||||||
if(total_sz) {
|
if(total_sz) {
|
||||||
@@ -178,7 +178,7 @@ uint32_t Dot11QoSData::write_fixed_parameters(uint8_t *buffer, uint32_t total_sz
|
|||||||
#ifdef TINS_DEBUG
|
#ifdef TINS_DEBUG
|
||||||
assert(sz <= total_sz);
|
assert(sz <= total_sz);
|
||||||
#endif
|
#endif
|
||||||
*(uint16_t*)buffer = this->_qos_control;
|
std::memcpy(buffer, &this->_qos_control, sizeof(uint16_t));
|
||||||
return sz;
|
return sz;
|
||||||
}
|
}
|
||||||
} // namespace Tins
|
} // namespace Tins
|
||||||
|
|||||||
@@ -496,7 +496,7 @@ Dot11ManagementFrame::fh_params_set Dot11ManagementFrame::fh_params_set::from_op
|
|||||||
if(opt.data_size() != 5)
|
if(opt.data_size() != 5)
|
||||||
throw malformed_option();
|
throw malformed_option();
|
||||||
fh_params_set output;
|
fh_params_set output;
|
||||||
output.dwell_time = Endian::le_to_host(*(uint16_t*)opt.data_ptr());
|
std::memcpy(&output.dwell_time, opt.data_ptr(), sizeof(uint16_t));
|
||||||
output.hop_set = opt.data_ptr()[2];
|
output.hop_set = opt.data_ptr()[2];
|
||||||
output.hop_pattern = opt.data_ptr()[3];
|
output.hop_pattern = opt.data_ptr()[3];
|
||||||
output.hop_index = opt.data_ptr()[4];
|
output.hop_index = opt.data_ptr()[4];
|
||||||
@@ -510,8 +510,8 @@ Dot11ManagementFrame::cf_params_set Dot11ManagementFrame::cf_params_set::from_op
|
|||||||
cf_params_set output;
|
cf_params_set output;
|
||||||
output.cfp_count = *opt.data_ptr();
|
output.cfp_count = *opt.data_ptr();
|
||||||
output.cfp_period = opt.data_ptr()[1];
|
output.cfp_period = opt.data_ptr()[1];
|
||||||
output.cfp_max_duration = Endian::le_to_host(*(uint16_t*)&opt.data_ptr()[2]);
|
std::memcpy(&output.cfp_max_duration, &opt.data_ptr()[2], sizeof(uint16_t));
|
||||||
output.cfp_dur_remaining = Endian::le_to_host(*(uint16_t*)&opt.data_ptr()[4]);
|
std::memcpy(&output.cfp_dur_remaining, &opt.data_ptr()[4], sizeof(uint16_t));
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -601,9 +601,10 @@ Dot11ManagementFrame::bss_load_type Dot11ManagementFrame::bss_load_type::from_op
|
|||||||
bss_load_type output;
|
bss_load_type output;
|
||||||
|
|
||||||
const uint8_t *ptr = opt.data_ptr();
|
const uint8_t *ptr = opt.data_ptr();
|
||||||
output.station_count = Endian::le_to_host(*(uint16_t*)ptr);
|
std::memcpy(&output.station_count, ptr, sizeof(uint16_t));
|
||||||
output.channel_utilization = ptr[2];
|
output.channel_utilization = ptr[2];
|
||||||
output.available_capacity = Endian::le_to_host(*(uint16_t*)(ptr + 3));
|
std::memcpy(&output.available_capacity, ptr + 3, sizeof(uint16_t));
|
||||||
|
output.available_capacity = Endian::le_to_host(output.available_capacity);
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
32
src/icmp.cpp
32
src/icmp.cpp
@@ -55,21 +55,24 @@ ICMP::ICMP(const uint8_t *buffer, uint32_t total_sz)
|
|||||||
std::memcpy(&_icmp, buffer, sizeof(icmphdr));
|
std::memcpy(&_icmp, buffer, sizeof(icmphdr));
|
||||||
buffer += sizeof(icmphdr);
|
buffer += sizeof(icmphdr);
|
||||||
total_sz -= sizeof(icmphdr);
|
total_sz -= sizeof(icmphdr);
|
||||||
|
uint32_t uint32_t_buffer = 0;
|
||||||
if(type() == TIMESTAMP_REQUEST || type() == TIMESTAMP_REPLY) {
|
if(type() == TIMESTAMP_REQUEST || type() == TIMESTAMP_REPLY) {
|
||||||
if(total_sz < sizeof(uint32_t) * 3)
|
if(total_sz < sizeof(uint32_t) * 3)
|
||||||
throw malformed_packet();
|
throw malformed_packet();
|
||||||
const uint32_t *ptr = reinterpret_cast<const uint32_t*>(buffer);
|
memcpy(&uint32_t_buffer, buffer, sizeof(uint32_t));
|
||||||
original_timestamp(*ptr++);
|
original_timestamp(uint32_t_buffer);
|
||||||
receive_timestamp(*ptr++);
|
memcpy(&uint32_t_buffer, buffer + sizeof(uint32_t), sizeof(uint32_t));
|
||||||
transmit_timestamp(*ptr++);
|
receive_timestamp(uint32_t_buffer);
|
||||||
|
memcpy(&uint32_t_buffer, buffer + 2 * sizeof(uint32_t), sizeof(uint32_t));
|
||||||
|
transmit_timestamp(uint32_t_buffer);
|
||||||
total_sz -= sizeof(uint32_t) * 3;
|
total_sz -= sizeof(uint32_t) * 3;
|
||||||
buffer += sizeof(uint32_t) * 3;
|
buffer += sizeof(uint32_t) * 3;
|
||||||
}
|
}
|
||||||
else if(type() == ADDRESS_MASK_REQUEST || type() == ADDRESS_MASK_REPLY) {
|
else if(type() == ADDRESS_MASK_REQUEST || type() == ADDRESS_MASK_REPLY) {
|
||||||
if(total_sz < sizeof(uint32_t))
|
if(total_sz < sizeof(uint32_t))
|
||||||
throw malformed_packet();
|
throw malformed_packet();
|
||||||
const uint32_t *ptr = reinterpret_cast<const uint32_t*>(buffer);
|
memcpy(&uint32_t_buffer, buffer, sizeof(uint32_t));
|
||||||
address_mask(address_type(*ptr++));
|
address_mask(address_type(uint32_t_buffer));
|
||||||
total_sz -= sizeof(uint32_t);
|
total_sz -= sizeof(uint32_t);
|
||||||
buffer += sizeof(uint32_t);
|
buffer += sizeof(uint32_t);
|
||||||
}
|
}
|
||||||
@@ -194,15 +197,18 @@ void ICMP::write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *)
|
|||||||
assert(total_sz >= sizeof(icmphdr));
|
assert(total_sz >= sizeof(icmphdr));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
uint32_t uint32_t_buffer;
|
||||||
if(type() == TIMESTAMP_REQUEST || type() == TIMESTAMP_REPLY) {
|
if(type() == TIMESTAMP_REQUEST || type() == TIMESTAMP_REPLY) {
|
||||||
uint32_t *ptr = reinterpret_cast<uint32_t*>(buffer + sizeof(icmphdr));
|
uint32_t_buffer = original_timestamp();
|
||||||
*ptr++ = original_timestamp();
|
memcpy(buffer + sizeof(icmphdr), &uint32_t_buffer, sizeof(uint32_t));
|
||||||
*ptr++ = receive_timestamp();
|
uint32_t_buffer = receive_timestamp();
|
||||||
*ptr++ = transmit_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) {
|
else if(type() == ADDRESS_MASK_REQUEST || type() == ADDRESS_MASK_REPLY) {
|
||||||
uint32_t *ptr = reinterpret_cast<uint32_t*>(buffer + sizeof(icmphdr));
|
uint32_t_buffer = address_mask();
|
||||||
*ptr++ = address_mask();
|
memcpy(buffer + sizeof(icmphdr), &uint32_t_buffer, sizeof(uint32_t));
|
||||||
}
|
}
|
||||||
// checksum calc
|
// checksum calc
|
||||||
_icmp.check = 0;
|
_icmp.check = 0;
|
||||||
@@ -213,7 +219,7 @@ void ICMP::write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *)
|
|||||||
checksum = (checksum & 0xffff) + (checksum >> 16);
|
checksum = (checksum & 0xffff) + (checksum >> 16);
|
||||||
|
|
||||||
_icmp.check = Endian::host_to_be<uint16_t>(~checksum);
|
_icmp.check = Endian::host_to_be<uint16_t>(~checksum);
|
||||||
((icmphdr*)buffer)->check = _icmp.check;
|
memcpy(buffer + 2, &_icmp.check, sizeof(uint16_t));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ICMP::matches_response(const uint8_t *ptr, uint32_t total_sz) const {
|
bool ICMP::matches_response(const uint8_t *ptr, uint32_t total_sz) const {
|
||||||
|
|||||||
@@ -72,9 +72,8 @@ ICMPv6::ICMPv6(const uint8_t *buffer, uint32_t total_sz)
|
|||||||
if(type() == ROUTER_ADVERT) {
|
if(type() == ROUTER_ADVERT) {
|
||||||
if(total_sz < sizeof(uint32_t) * 2)
|
if(total_sz < sizeof(uint32_t) * 2)
|
||||||
throw malformed_packet();
|
throw malformed_packet();
|
||||||
const uint32_t *ptr_32 = (const uint32_t*)buffer;
|
memcpy(&reach_time, buffer, sizeof(uint32_t));
|
||||||
reach_time = *ptr_32++;
|
memcpy(&retrans_timer, buffer + sizeof(uint32_t), sizeof(uint32_t));
|
||||||
retrans_timer = *ptr_32++;
|
|
||||||
|
|
||||||
buffer += sizeof(uint32_t) * 2;
|
buffer += sizeof(uint32_t) * 2;
|
||||||
total_sz -= sizeof(uint32_t) * 2;
|
total_sz -= sizeof(uint32_t) * 2;
|
||||||
@@ -197,7 +196,7 @@ void ICMPv6::write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *
|
|||||||
#ifdef TINS_DEBUG
|
#ifdef TINS_DEBUG
|
||||||
assert(total_sz >= header_size());
|
assert(total_sz >= header_size());
|
||||||
#endif
|
#endif
|
||||||
icmp6hdr* ptr_header = (icmp6hdr*)buffer;
|
uint8_t *buffer_start = buffer;
|
||||||
_header.cksum = 0;
|
_header.cksum = 0;
|
||||||
std::memcpy(buffer, &_header, sizeof(_header));
|
std::memcpy(buffer, &_header, sizeof(_header));
|
||||||
buffer += sizeof(_header);
|
buffer += sizeof(_header);
|
||||||
@@ -211,9 +210,9 @@ void ICMPv6::write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *
|
|||||||
total_sz -= sizeof(ipaddress_type::address_size);
|
total_sz -= sizeof(ipaddress_type::address_size);
|
||||||
}
|
}
|
||||||
if(type() == ROUTER_ADVERT) {
|
if(type() == ROUTER_ADVERT) {
|
||||||
*(uint32_t*)buffer = reach_time;
|
std::memcpy(buffer, &reach_time, sizeof(uint32_t));
|
||||||
buffer += sizeof(uint32_t);
|
buffer += sizeof(uint32_t);
|
||||||
*(uint32_t*)buffer = retrans_timer;
|
std::memcpy(buffer, &retrans_timer, sizeof(uint32_t));
|
||||||
buffer += sizeof(uint32_t);
|
buffer += sizeof(uint32_t);
|
||||||
total_sz -= sizeof(uint32_t) * 2;
|
total_sz -= sizeof(uint32_t) * 2;
|
||||||
}
|
}
|
||||||
@@ -232,11 +231,11 @@ void ICMPv6::write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *
|
|||||||
ipv6->dst_addr(),
|
ipv6->dst_addr(),
|
||||||
size(),
|
size(),
|
||||||
Constants::IP::PROTO_ICMPV6
|
Constants::IP::PROTO_ICMPV6
|
||||||
) + Utils::do_checksum((uint8_t*)ptr_header, buffer);
|
) + Utils::do_checksum(buffer_start, buffer);
|
||||||
while (checksum >> 16)
|
while (checksum >> 16)
|
||||||
checksum = (checksum & 0xffff) + (checksum >> 16);
|
checksum = (checksum & 0xffff) + (checksum >> 16);
|
||||||
this->checksum(~checksum);
|
this->checksum(~checksum);
|
||||||
ptr_header->cksum = _header.cksum;
|
memcpy(&buffer_start + 2, &_header.cksum, sizeof(uint16_t));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -285,9 +284,12 @@ void ICMPv6::prefix_info(prefix_info_type info) {
|
|||||||
uint8_t buffer[2 + sizeof(uint32_t) * 3 + ipaddress_type::address_size];
|
uint8_t buffer[2 + sizeof(uint32_t) * 3 + ipaddress_type::address_size];
|
||||||
buffer[0] = info.prefix_len;
|
buffer[0] = info.prefix_len;
|
||||||
buffer[1] = (info.L << 7) | (info.A << 6);
|
buffer[1] = (info.L << 7) | (info.A << 6);
|
||||||
*(uint32_t*)(buffer + 2) = Endian::host_to_be(info.valid_lifetime);
|
uint32_t uint32_t_buffer = Endian::host_to_be(info.valid_lifetime);
|
||||||
*(uint32_t*)(buffer + 2 + sizeof(uint32_t)) = Endian::host_to_be(info.preferred_lifetime);
|
std::memcpy(buffer + 2, &uint32_t_buffer, sizeof(uint32_t));
|
||||||
*(uint32_t*)(buffer + 2 + sizeof(uint32_t) * 2) = 0;
|
uint32_t_buffer = Endian::host_to_be(info.preferred_lifetime);
|
||||||
|
std::memcpy(buffer + 2 + sizeof(uint32_t), &uint32_t_buffer, sizeof(uint32_t));
|
||||||
|
uint32_t_buffer = 0;
|
||||||
|
std::memcpy(buffer + 2 + sizeof(uint32_t) * 2, &uint32_t_buffer, sizeof(uint32_t));
|
||||||
info.prefix.copy(buffer + 2 + sizeof(uint32_t) * 3);
|
info.prefix.copy(buffer + 2 + sizeof(uint32_t) * 3);
|
||||||
add_option(
|
add_option(
|
||||||
option(PREFIX_INFO, buffer, buffer + sizeof(buffer))
|
option(PREFIX_INFO, buffer, buffer + sizeof(buffer))
|
||||||
@@ -384,7 +386,8 @@ void ICMPv6::rsa_signature(const rsa_sign_type &value) {
|
|||||||
void ICMPv6::timestamp(const timestamp_type &value) {
|
void ICMPv6::timestamp(const timestamp_type &value) {
|
||||||
std::vector<uint8_t> buffer(6 + sizeof(uint64_t));
|
std::vector<uint8_t> buffer(6 + sizeof(uint64_t));
|
||||||
std::copy(value.reserved, value.reserved + 6, buffer.begin());
|
std::copy(value.reserved, value.reserved + 6, buffer.begin());
|
||||||
*((uint64_t*)&buffer[6]) = Endian::host_to_be(value.timestamp);
|
uint64_t uint64_t_buffer = Endian::host_to_be(value.timestamp);
|
||||||
|
memcpy(&buffer[6], &uint64_t_buffer, sizeof(uint64_t));
|
||||||
add_option(option(TIMESTAMP, buffer.begin(), buffer.end()));
|
add_option(option(TIMESTAMP, buffer.begin(), buffer.end()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -424,7 +427,8 @@ void ICMPv6::map(const map_type &value) {
|
|||||||
uint8_t buffer[sizeof(uint8_t) * 2 + sizeof(uint32_t) + ipaddress_type::address_size];
|
uint8_t buffer[sizeof(uint8_t) * 2 + sizeof(uint32_t) + ipaddress_type::address_size];
|
||||||
buffer[0] = value.dist << 4 | value.pref;
|
buffer[0] = value.dist << 4 | value.pref;
|
||||||
buffer[1] = value.r << 7;
|
buffer[1] = value.r << 7;
|
||||||
*(uint32_t*)(buffer + 2) = Endian::host_to_be(value.valid_lifetime);
|
uint32_t uint32_t_buffer = Endian::host_to_be(value.valid_lifetime);
|
||||||
|
std::memcpy(buffer + 2, &uint32_t_buffer, sizeof(uint32_t));
|
||||||
value.address.copy(buffer + 2 + sizeof(uint32_t));
|
value.address.copy(buffer + 2 + sizeof(uint32_t));
|
||||||
add_option(option(MAP, buffer, buffer + sizeof(buffer)));
|
add_option(option(MAP, buffer, buffer + sizeof(buffer)));
|
||||||
}
|
}
|
||||||
@@ -436,7 +440,8 @@ void ICMPv6::route_info(const route_info_type &value) {
|
|||||||
std::vector<uint8_t> buffer(2 + sizeof(uint32_t) + value.prefix.size() + padding);
|
std::vector<uint8_t> buffer(2 + sizeof(uint32_t) + value.prefix.size() + padding);
|
||||||
buffer[0] = value.prefix_len;
|
buffer[0] = value.prefix_len;
|
||||||
buffer[1] = value.pref << 3;
|
buffer[1] = value.pref << 3;
|
||||||
*(uint32_t*)&buffer[2] = Endian::host_to_be(value.route_lifetime);
|
uint32_t uint32_t_buffer = Endian::host_to_be(value.route_lifetime);
|
||||||
|
std::memcpy(&buffer[2], &uint32_t_buffer, sizeof(uint32_t));
|
||||||
// copy the prefix and then fill with padding
|
// copy the prefix and then fill with padding
|
||||||
buffer.insert(
|
buffer.insert(
|
||||||
std::copy(value.prefix.begin(), value.prefix.end(), buffer.begin() + 2 + sizeof(uint32_t)),
|
std::copy(value.prefix.begin(), value.prefix.end(), buffer.begin() + 2 + sizeof(uint32_t)),
|
||||||
@@ -452,7 +457,8 @@ void ICMPv6::recursive_dns_servers(const recursive_dns_type &value) {
|
|||||||
);
|
);
|
||||||
|
|
||||||
buffer[0] = buffer[1] = 0;
|
buffer[0] = buffer[1] = 0;
|
||||||
*(uint32_t*)&buffer[2] = Endian::host_to_be(value.lifetime);
|
uint32_t tmp_lifetime = Endian::host_to_be(value.lifetime);
|
||||||
|
std::memcpy(&buffer[2], &tmp_lifetime, sizeof(uint32_t));
|
||||||
std::vector<uint8_t>::iterator out = buffer.begin() + 2 + sizeof(uint32_t);
|
std::vector<uint8_t>::iterator out = buffer.begin() + 2 + sizeof(uint32_t);
|
||||||
typedef recursive_dns_type::servers_type::const_iterator iterator;
|
typedef recursive_dns_type::servers_type::const_iterator iterator;
|
||||||
for(iterator it = value.servers.begin(); it != value.servers.end(); ++it)
|
for(iterator it = value.servers.begin(); it != value.servers.end(); ++it)
|
||||||
@@ -484,7 +490,8 @@ void ICMPv6::handover_key_reply(const handover_key_reply_type &value) {
|
|||||||
std::vector<uint8_t> buffer(data_size + padding);
|
std::vector<uint8_t> buffer(data_size + padding);
|
||||||
buffer[0] = padding;
|
buffer[0] = padding;
|
||||||
buffer[1] = value.AT << 4;
|
buffer[1] = value.AT << 4;
|
||||||
*(uint16_t*)&buffer[2] = Endian::host_to_be(value.lifetime);
|
uint32_t tmp_lifetime = Endian::host_to_be(value.lifetime);
|
||||||
|
std::memcpy(&buffer[2], &tmp_lifetime, sizeof(uint32_t));
|
||||||
// copy the key, and fill with padding
|
// copy the key, and fill with padding
|
||||||
std::fill(
|
std::fill(
|
||||||
std::copy(value.key.begin(), value.key.end(), buffer.begin() + 2 + sizeof(uint16_t)),
|
std::copy(value.key.begin(), value.key.end(), buffer.begin() + 2 + sizeof(uint16_t)),
|
||||||
@@ -531,7 +538,8 @@ void ICMPv6::mobile_node_identifier(const mobile_node_id_type &value) {
|
|||||||
void ICMPv6::dns_search_list(const dns_search_list_type &value) {
|
void ICMPv6::dns_search_list(const dns_search_list_type &value) {
|
||||||
// at least it's got this size
|
// at least it's got this size
|
||||||
std::vector<uint8_t> buffer(2 + sizeof(uint32_t));
|
std::vector<uint8_t> buffer(2 + sizeof(uint32_t));
|
||||||
*(uint32_t*)&buffer[2] = Endian::host_to_be(value.lifetime);
|
uint32_t tmp_lifetime = Endian::host_to_be(value.lifetime);
|
||||||
|
std::memcpy(&buffer[2], &tmp_lifetime, sizeof(uint32_t));
|
||||||
typedef dns_search_list_type::domains_type::const_iterator iterator;
|
typedef dns_search_list_type::domains_type::const_iterator iterator;
|
||||||
for(iterator it = value.domains.begin(); it != value.domains.end(); ++it) {
|
for(iterator it = value.domains.begin(); it != value.domains.end(); ++it) {
|
||||||
size_t prev = 0, index;
|
size_t prev = 0, index;
|
||||||
@@ -699,9 +707,11 @@ ICMPv6::prefix_info_type ICMPv6::prefix_info_type::from_option(const option &opt
|
|||||||
output.prefix_len = *ptr++;
|
output.prefix_len = *ptr++;
|
||||||
output.L = (*ptr >> 7) & 0x1;
|
output.L = (*ptr >> 7) & 0x1;
|
||||||
output.A = (*ptr++ >> 6) & 0x1;
|
output.A = (*ptr++ >> 6) & 0x1;
|
||||||
output.valid_lifetime = Endian::be_to_host(*(uint32_t*)ptr);
|
std::memcpy(&output.valid_lifetime, ptr, sizeof(uint32_t));
|
||||||
|
output.valid_lifetime = Endian::be_to_host(output.valid_lifetime);
|
||||||
ptr += sizeof(uint32_t);
|
ptr += sizeof(uint32_t);
|
||||||
output.preferred_lifetime = Endian::be_to_host(*(uint32_t*)ptr);
|
std::memcpy(&output.preferred_lifetime, ptr, sizeof(uint32_t));
|
||||||
|
output.preferred_lifetime = Endian::be_to_host(output.preferred_lifetime);
|
||||||
output.prefix = ptr + sizeof(uint32_t) * 2;
|
output.prefix = ptr + sizeof(uint32_t) * 2;
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
@@ -745,7 +755,7 @@ ICMPv6::map_type ICMPv6::map_type::from_option(const option &opt)
|
|||||||
output.dist = (*ptr >> 4) & 0x0f;
|
output.dist = (*ptr >> 4) & 0x0f;
|
||||||
output.pref = *ptr++ & 0x0f;
|
output.pref = *ptr++ & 0x0f;
|
||||||
output.r = (*ptr++ >> 7) & 0x01;
|
output.r = (*ptr++ >> 7) & 0x01;
|
||||||
output.valid_lifetime = *(uint32_t*)ptr;
|
std::memcpy(&output.valid_lifetime, ptr, sizeof(uint32_t));
|
||||||
ptr += sizeof(uint32_t);
|
ptr += sizeof(uint32_t);
|
||||||
output.address = ptr;
|
output.address = ptr;
|
||||||
return output;
|
return output;
|
||||||
@@ -759,7 +769,8 @@ ICMPv6::route_info_type ICMPv6::route_info_type::from_option(const option &opt)
|
|||||||
route_info_type output;
|
route_info_type output;
|
||||||
output.prefix_len = *ptr++;
|
output.prefix_len = *ptr++;
|
||||||
output.pref = (*ptr++ >> 3) & 0x3;
|
output.pref = (*ptr++ >> 3) & 0x3;
|
||||||
output.route_lifetime = Endian::be_to_host(*(uint32_t*)ptr);
|
std::memcpy(&output.route_lifetime, ptr, sizeof(uint32_t));
|
||||||
|
output.route_lifetime = Endian::be_to_host(output.route_lifetime);
|
||||||
ptr += sizeof(uint32_t);
|
ptr += sizeof(uint32_t);
|
||||||
output.prefix.assign(ptr, opt.data_ptr() + opt.data_size());
|
output.prefix.assign(ptr, opt.data_ptr() + opt.data_size());
|
||||||
return output;
|
return output;
|
||||||
@@ -771,7 +782,8 @@ ICMPv6::recursive_dns_type ICMPv6::recursive_dns_type::from_option(const option
|
|||||||
throw malformed_option();
|
throw malformed_option();
|
||||||
const uint8_t *ptr = opt.data_ptr() + 2, *end = opt.data_ptr() + opt.data_size();
|
const uint8_t *ptr = opt.data_ptr() + 2, *end = opt.data_ptr() + opt.data_size();
|
||||||
recursive_dns_type output;
|
recursive_dns_type output;
|
||||||
output.lifetime = Endian::be_to_host(*(uint32_t*)ptr);
|
std::memcpy(&output.lifetime, ptr, sizeof(uint32_t));
|
||||||
|
output.lifetime = Endian::be_to_host(output.lifetime);
|
||||||
ptr += sizeof(uint32_t);
|
ptr += sizeof(uint32_t);
|
||||||
while(ptr < end) {
|
while(ptr < end) {
|
||||||
if(ptr + ICMPv6::ipaddress_type::address_size > end)
|
if(ptr + ICMPv6::ipaddress_type::address_size > end)
|
||||||
@@ -803,7 +815,8 @@ ICMPv6::handover_key_reply_type ICMPv6::handover_key_reply_type::from_option(con
|
|||||||
const uint8_t *ptr = opt.data_ptr() + 1, *end = opt.data_ptr() + opt.data_size();
|
const uint8_t *ptr = opt.data_ptr() + 1, *end = opt.data_ptr() + opt.data_size();
|
||||||
handover_key_reply_type output;
|
handover_key_reply_type output;
|
||||||
output.AT = (*ptr++ >> 4) & 0x3;
|
output.AT = (*ptr++ >> 4) & 0x3;
|
||||||
output.lifetime = Endian::be_to_host(*(uint16_t*)ptr);
|
std::memcpy(&output.lifetime, ptr, sizeof(uint16_t));
|
||||||
|
output.lifetime = Endian::be_to_host(output.lifetime);
|
||||||
ptr += sizeof(uint16_t);
|
ptr += sizeof(uint16_t);
|
||||||
// is there enough size for the indicated padding?
|
// is there enough size for the indicated padding?
|
||||||
if(end - ptr < *opt.data_ptr())
|
if(end - ptr < *opt.data_ptr())
|
||||||
@@ -844,7 +857,8 @@ ICMPv6::dns_search_list_type ICMPv6::dns_search_list_type::from_option(const opt
|
|||||||
throw malformed_option();
|
throw malformed_option();
|
||||||
const uint8_t *ptr = opt.data_ptr(), *end = ptr + opt.data_size();
|
const uint8_t *ptr = opt.data_ptr(), *end = ptr + opt.data_size();
|
||||||
dns_search_list_type output;
|
dns_search_list_type output;
|
||||||
output.lifetime = Endian::be_to_host(*(uint32_t*)(ptr + 2));
|
std::memcpy(&output.lifetime, ptr + 2, sizeof(uint32_t));
|
||||||
|
output.lifetime = Endian::be_to_host(output.lifetime);
|
||||||
ptr += 2 + sizeof(uint32_t);
|
ptr += 2 + sizeof(uint32_t);
|
||||||
while(ptr < end && *ptr) {
|
while(ptr < end && *ptr) {
|
||||||
std::string domain;
|
std::string domain;
|
||||||
@@ -867,7 +881,9 @@ ICMPv6::timestamp_type ICMPv6::timestamp_type::from_option(const option &opt)
|
|||||||
{
|
{
|
||||||
if(opt.data_size() != 6 + sizeof(uint64_t))
|
if(opt.data_size() != 6 + sizeof(uint64_t))
|
||||||
throw malformed_option();
|
throw malformed_option();
|
||||||
timestamp_type output(Endian::be_to_host(*(uint64_t*)(opt.data_ptr() + 6)));
|
uint64_t uint64_t_buffer;
|
||||||
|
std::memcpy(&uint64_t_buffer, opt.data_ptr() + 6, sizeof(uint64_t));
|
||||||
|
timestamp_type output(Endian::be_to_host(uint64_t_buffer));
|
||||||
std::copy(opt.data_ptr(), opt.data_ptr() + 6, output.reserved);
|
std::copy(opt.data_ptr(), opt.data_ptr() + 6, output.reserved);
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
@@ -879,7 +895,8 @@ ICMPv6::shortcut_limit_type ICMPv6::shortcut_limit_type::from_option(const optio
|
|||||||
const uint8_t *ptr = opt.data_ptr();
|
const uint8_t *ptr = opt.data_ptr();
|
||||||
shortcut_limit_type output(*ptr++);
|
shortcut_limit_type output(*ptr++);
|
||||||
output.reserved1 = *ptr++;
|
output.reserved1 = *ptr++;
|
||||||
output.reserved2 = Endian::be_to_host(*(uint32_t*)ptr);
|
std::memcpy(&output.reserved2, ptr, sizeof(uint32_t));
|
||||||
|
output.reserved2 = Endian::be_to_host(output.reserved2);
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -888,8 +905,10 @@ ICMPv6::new_advert_interval_type ICMPv6::new_advert_interval_type::from_option(c
|
|||||||
if(opt.data_size() != 6)
|
if(opt.data_size() != 6)
|
||||||
throw malformed_option();
|
throw malformed_option();
|
||||||
new_advert_interval_type output;
|
new_advert_interval_type output;
|
||||||
output.reserved = Endian::be_to_host(*(uint16_t*)opt.data_ptr());
|
std::memcpy(&output.reserved, opt.data_ptr(), sizeof(uint16_t));
|
||||||
output.interval = Endian::be_to_host(*(uint32_t*)(opt.data_ptr() + sizeof(uint16_t)));
|
output.reserved = Endian::be_to_host(output.reserved);
|
||||||
|
std::memcpy(&output.interval, opt.data_ptr() + sizeof(uint16_t), sizeof(uint32_t));
|
||||||
|
output.interval = Endian::be_to_host(output.interval);
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
24
src/ip.cpp
24
src/ip.cpp
@@ -445,10 +445,13 @@ IP::security_type IP::security_type::from_option(const option &opt)
|
|||||||
if(opt.data_size() != 9)
|
if(opt.data_size() != 9)
|
||||||
throw malformed_option();
|
throw malformed_option();
|
||||||
security_type output;
|
security_type output;
|
||||||
const uint16_t *ptr = reinterpret_cast<const uint16_t*>(opt.data_ptr());
|
|
||||||
output.security = Endian::be_to_host(*ptr++);
|
memcpy(&output.security, opt.data_ptr(), sizeof(uint16_t));
|
||||||
output.compartments = Endian::be_to_host(*ptr++);
|
output.security = Endian::be_to_host(output.security);
|
||||||
output.handling_restrictions = Endian::be_to_host(*ptr++);
|
memcpy(&output.compartments, opt.data_ptr() + sizeof(uint16_t), sizeof(uint16_t));
|
||||||
|
output.compartments = Endian::be_to_host(output.compartments);
|
||||||
|
memcpy(&output.handling_restrictions, opt.data_ptr() + 2 * sizeof(uint16_t), sizeof(uint16_t));
|
||||||
|
output.handling_restrictions = Endian::be_to_host(output.handling_restrictions);
|
||||||
uint32_t tcc = opt.data_ptr()[6];
|
uint32_t tcc = opt.data_ptr()[6];
|
||||||
tcc = (tcc << 8) | opt.data_ptr()[7];
|
tcc = (tcc << 8) | opt.data_ptr()[7];
|
||||||
tcc = (tcc << 8) | opt.data_ptr()[8];
|
tcc = (tcc << 8) | opt.data_ptr()[8];
|
||||||
@@ -463,10 +466,15 @@ IP::generic_route_option_type IP::generic_route_option_type::from_option(
|
|||||||
throw malformed_option();
|
throw malformed_option();
|
||||||
generic_route_option_type output;
|
generic_route_option_type output;
|
||||||
output.pointer = *opt.data_ptr();
|
output.pointer = *opt.data_ptr();
|
||||||
const uint32_t *route = (const uint32_t*)(opt.data_ptr() + 1),
|
const uint8_t *route = opt.data_ptr() + 1;
|
||||||
*end = route + (opt.data_size() - 1) / sizeof(uint32_t);
|
const uint8_t *end = route + opt.data_size() - 1;
|
||||||
while(route < end)
|
|
||||||
output.routes.push_back(address_type(*route++));
|
uint32_t uint32_t_buffer;
|
||||||
|
while(route < end) {
|
||||||
|
memcpy(&uint32_t_buffer, route, sizeof(uint32_t));
|
||||||
|
output.routes.push_back(address_type(uint32_t_buffer));
|
||||||
|
route += sizeof(uint32_t);
|
||||||
|
}
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -56,8 +56,10 @@ PPPoE::PPPoE(const uint8_t *buffer, uint32_t total_sz)
|
|||||||
while(buffer < end) {
|
while(buffer < end) {
|
||||||
if(buffer + sizeof(uint32_t) * 2 > end)
|
if(buffer + sizeof(uint32_t) * 2 > end)
|
||||||
throw malformed_packet();
|
throw malformed_packet();
|
||||||
uint16_t opt_type = *(const uint16_t*)buffer;
|
uint16_t opt_type;
|
||||||
uint16_t opt_len = *(const uint16_t*)(buffer + sizeof(uint16_t));
|
std::memcpy(&opt_type, buffer, sizeof(uint16_t));
|
||||||
|
uint16_t opt_len;
|
||||||
|
std::memcpy(&opt_len, buffer + sizeof(uint16_t), sizeof(uint16_t));
|
||||||
buffer += sizeof(uint16_t) * 2;
|
buffer += sizeof(uint16_t) * 2;
|
||||||
total_sz -= sizeof(uint16_t) * 2;
|
total_sz -= sizeof(uint16_t) * 2;
|
||||||
if(Endian::be_to_host(opt_len) > total_sz)
|
if(Endian::be_to_host(opt_len) > total_sz)
|
||||||
@@ -115,9 +117,12 @@ void PPPoE::write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *)
|
|||||||
if(_tags_size > 0)
|
if(_tags_size > 0)
|
||||||
((pppoe_hdr*)buffer)->payload_length = Endian::host_to_be(_tags_size);
|
((pppoe_hdr*)buffer)->payload_length = Endian::host_to_be(_tags_size);
|
||||||
buffer += sizeof(_header);
|
buffer += sizeof(_header);
|
||||||
|
uint16_t uint16_t_buffer;
|
||||||
for(tags_type::const_iterator it = _tags.begin(); it != _tags.end(); ++it) {
|
for(tags_type::const_iterator it = _tags.begin(); it != _tags.end(); ++it) {
|
||||||
*(uint16_t*)buffer = it->option();
|
uint16_t_buffer = it->option();
|
||||||
*(uint16_t*)(buffer + sizeof(uint16_t)) = Endian::host_to_be<uint16_t>(it->length_field());
|
std::memcpy(buffer, &uint16_t_buffer, sizeof(uint16_t));
|
||||||
|
uint16_t_buffer = Endian::host_to_be<uint16_t>(it->length_field());
|
||||||
|
std::memcpy(buffer + sizeof(uint16_t), &uint16_t_buffer, sizeof(uint16_t));
|
||||||
std::copy(
|
std::copy(
|
||||||
it->data_ptr(),
|
it->data_ptr(),
|
||||||
it->data_ptr() + it->data_size(),
|
it->data_ptr() + it->data_size(),
|
||||||
@@ -158,7 +163,8 @@ void PPPoE::ac_cookie(const byte_array &value) {
|
|||||||
|
|
||||||
void PPPoE::vendor_specific(const vendor_spec_type &value) {
|
void PPPoE::vendor_specific(const vendor_spec_type &value) {
|
||||||
std::vector<uint8_t> buffer(sizeof(uint32_t) + value.data.size());
|
std::vector<uint8_t> buffer(sizeof(uint32_t) + value.data.size());
|
||||||
*(uint32_t*)&buffer[0] = Endian::host_to_be(value.vendor_id);
|
uint32_t tmp_vendor_id = Endian::host_to_be(value.vendor_id);
|
||||||
|
std::memcpy(&buffer[0], &tmp_vendor_id, sizeof(uint32_t));
|
||||||
std::copy(
|
std::copy(
|
||||||
value.data.begin(),
|
value.data.begin(),
|
||||||
value.data.end(),
|
value.data.end(),
|
||||||
@@ -234,7 +240,8 @@ PPPoE::vendor_spec_type PPPoE::vendor_spec_type::from_option(const tag &opt) {
|
|||||||
if(opt.data_size() < sizeof(uint32_t))
|
if(opt.data_size() < sizeof(uint32_t))
|
||||||
throw malformed_option();
|
throw malformed_option();
|
||||||
vendor_spec_type output;
|
vendor_spec_type output;
|
||||||
output.vendor_id = Endian::be_to_host(*(const uint32_t*)opt.data_ptr());
|
std::memcpy(&output.vendor_id, opt.data_ptr(), sizeof(uint32_t));
|
||||||
|
output.vendor_id = Endian::be_to_host(output.vendor_id);
|
||||||
output.data.assign(
|
output.data.assign(
|
||||||
opt.data_ptr() + sizeof(uint32_t),
|
opt.data_ptr() + sizeof(uint32_t),
|
||||||
opt.data_ptr() + opt.data_size()
|
opt.data_ptr() + opt.data_size()
|
||||||
|
|||||||
@@ -382,9 +382,10 @@ void RadioTap::write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU
|
|||||||
buffer += sizeof(_max_power);
|
buffer += sizeof(_max_power);
|
||||||
}
|
}
|
||||||
if((_flags & 0x10) != 0 && inner_pdu()) {
|
if((_flags & 0x10) != 0 && inner_pdu()) {
|
||||||
*(uint32_t*)(buffer + inner_pdu()->size()) = Endian::host_to_le(
|
uint32_t crc32 = Endian::host_to_le(
|
||||||
Utils::crc32(buffer, inner_pdu()->size())
|
Utils::crc32(buffer, inner_pdu()->size())
|
||||||
);
|
);
|
||||||
|
memcpy(buffer + inner_pdu()->size(), &crc32, sizeof(uint32_t));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,6 +30,7 @@
|
|||||||
#include "rsn_information.h"
|
#include "rsn_information.h"
|
||||||
#ifdef HAVE_DOT11
|
#ifdef HAVE_DOT11
|
||||||
|
|
||||||
|
#include <cstring>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
#include "exceptions.h"
|
#include "exceptions.h"
|
||||||
#include "pdu_option.h"
|
#include "pdu_option.h"
|
||||||
@@ -57,40 +58,49 @@ RSNInformation::RSNInformation(const uint8_t *buffer, uint32_t total_sz) {
|
|||||||
void RSNInformation::init(const uint8_t *buffer, uint32_t total_sz) {
|
void RSNInformation::init(const uint8_t *buffer, uint32_t total_sz) {
|
||||||
if(total_sz <= sizeof(uint16_t) * 2 + sizeof(uint32_t))
|
if(total_sz <= sizeof(uint16_t) * 2 + sizeof(uint32_t))
|
||||||
throw malformed_packet();
|
throw malformed_packet();
|
||||||
version(Endian::le_to_host(*(uint16_t*)buffer));
|
|
||||||
|
uint16_t uint16_t_buffer;
|
||||||
|
uint32_t uint32_t_buffer;
|
||||||
|
|
||||||
|
std::memcpy(&uint16_t_buffer, buffer, sizeof(uint16_t));
|
||||||
|
version(Endian::le_to_host(uint16_t_buffer));
|
||||||
buffer += sizeof(uint16_t);
|
buffer += sizeof(uint16_t);
|
||||||
total_sz -= sizeof(uint16_t);
|
total_sz -= sizeof(uint16_t);
|
||||||
|
|
||||||
group_suite((RSNInformation::CypherSuites)*(uint32_t*)buffer);
|
std::memcpy(&uint32_t_buffer, buffer, sizeof(uint32_t));
|
||||||
|
group_suite((RSNInformation::CypherSuites)uint32_t_buffer);
|
||||||
buffer += sizeof(uint32_t);
|
buffer += sizeof(uint32_t);
|
||||||
total_sz -= sizeof(uint32_t);
|
total_sz -= sizeof(uint32_t);
|
||||||
|
|
||||||
uint16_t count = *(uint16_t*)buffer;
|
std::memcpy(&uint16_t_buffer, buffer, sizeof(uint16_t));
|
||||||
buffer += sizeof(uint16_t);
|
buffer += sizeof(uint16_t);
|
||||||
total_sz -= sizeof(uint16_t);
|
total_sz -= sizeof(uint16_t);
|
||||||
|
|
||||||
if(count * sizeof(uint32_t) > total_sz)
|
if(uint16_t_buffer * sizeof(uint32_t) > total_sz)
|
||||||
throw malformed_packet();
|
throw malformed_packet();
|
||||||
total_sz -= count * sizeof(uint32_t);
|
total_sz -= uint16_t_buffer * sizeof(uint32_t);
|
||||||
while(count--) {
|
while(uint16_t_buffer--) {
|
||||||
add_pairwise_cypher((RSNInformation::CypherSuites)*(uint32_t*)buffer);
|
std::memcpy(&uint32_t_buffer, buffer, sizeof(uint32_t));
|
||||||
|
add_pairwise_cypher((RSNInformation::CypherSuites)uint32_t_buffer);
|
||||||
buffer += sizeof(uint32_t);
|
buffer += sizeof(uint32_t);
|
||||||
}
|
}
|
||||||
check_size<uint16_t>(total_sz);
|
check_size<uint16_t>(total_sz);
|
||||||
|
|
||||||
count = *(uint16_t*)buffer;
|
std::memcpy(&uint16_t_buffer, buffer, sizeof(uint16_t));
|
||||||
buffer += sizeof(uint16_t);
|
buffer += sizeof(uint16_t);
|
||||||
total_sz -= sizeof(uint16_t);
|
total_sz -= sizeof(uint16_t);
|
||||||
if(count * sizeof(uint32_t) > total_sz)
|
if(uint16_t_buffer * sizeof(uint32_t) > total_sz)
|
||||||
throw malformed_packet();
|
throw malformed_packet();
|
||||||
total_sz -= count * sizeof(uint32_t);
|
total_sz -= uint16_t_buffer * sizeof(uint32_t);
|
||||||
while(count--) {
|
while(uint16_t_buffer--) {
|
||||||
add_akm_cypher((RSNInformation::AKMSuites)*(uint32_t*)buffer);
|
std::memcpy(&uint32_t_buffer, buffer, sizeof(uint32_t));
|
||||||
|
add_akm_cypher((RSNInformation::AKMSuites)uint32_t_buffer);
|
||||||
buffer += sizeof(uint32_t);
|
buffer += sizeof(uint32_t);
|
||||||
}
|
}
|
||||||
check_size<uint16_t>(total_sz);
|
check_size<uint16_t>(total_sz);
|
||||||
|
|
||||||
capabilities(Endian::le_to_host(*(uint16_t*)buffer));
|
std::memcpy(&uint16_t_buffer, buffer, sizeof(uint16_t));
|
||||||
|
capabilities(Endian::le_to_host(uint16_t_buffer));
|
||||||
}
|
}
|
||||||
|
|
||||||
void RSNInformation::add_pairwise_cypher(CypherSuites cypher) {
|
void RSNInformation::add_pairwise_cypher(CypherSuites cypher) {
|
||||||
@@ -117,26 +127,31 @@ RSNInformation::serialization_type RSNInformation::serialize() const {
|
|||||||
uint32_t size = sizeof(_version) + sizeof(_capabilities) + sizeof(uint32_t);
|
uint32_t size = sizeof(_version) + sizeof(_capabilities) + sizeof(uint32_t);
|
||||||
size += (sizeof(uint16_t) << 1); // 2 lists count.
|
size += (sizeof(uint16_t) << 1); // 2 lists count.
|
||||||
size += sizeof(uint32_t) * (_akm_cyphers.size() + _pairwise_cyphers.size());
|
size += sizeof(uint32_t) * (_akm_cyphers.size() + _pairwise_cyphers.size());
|
||||||
|
|
||||||
|
uint16_t pairwise_cyphers_size = _pairwise_cyphers.size();
|
||||||
|
uint16_t akm_cyphers_size = _akm_cyphers.size();
|
||||||
|
uint16_t capabilities = Endian::host_to_le(_capabilities);
|
||||||
|
|
||||||
serialization_type buffer(size);
|
serialization_type buffer(size);
|
||||||
serialization_type::value_type *ptr = &buffer[0];
|
serialization_type::value_type *ptr = &buffer[0];
|
||||||
*(uint16_t*)ptr = _version;
|
std::memcpy(ptr, &_version, sizeof(_version));
|
||||||
ptr += sizeof(_version);
|
ptr += sizeof(uint16_t);
|
||||||
*(uint32_t*)ptr = _group_suite;
|
std::memcpy(ptr, &_group_suite, sizeof(uint32_t));
|
||||||
ptr += sizeof(uint32_t);
|
ptr += sizeof(uint32_t);
|
||||||
*(uint16_t*)ptr = _pairwise_cyphers.size();
|
std::memcpy(ptr, &pairwise_cyphers_size, sizeof(uint16_t));
|
||||||
ptr += sizeof(uint16_t);
|
ptr += sizeof(uint16_t);
|
||||||
for(cyphers_type::const_iterator it = _pairwise_cyphers.begin(); it != _pairwise_cyphers.end(); ++it) {
|
for(cyphers_type::const_iterator it = _pairwise_cyphers.begin(); it != _pairwise_cyphers.end(); ++it) {
|
||||||
*(uint32_t*)ptr = *it;
|
std::memcpy(ptr, &*it, sizeof(uint32_t));
|
||||||
ptr += sizeof(uint32_t);
|
ptr += sizeof(uint32_t);
|
||||||
}
|
}
|
||||||
*(uint16_t*)ptr = _akm_cyphers.size();
|
std::memcpy(ptr, &akm_cyphers_size, sizeof(uint16_t));
|
||||||
ptr += sizeof(uint16_t);
|
ptr += sizeof(uint16_t);
|
||||||
for(akm_type::const_iterator it = _akm_cyphers.begin(); it != _akm_cyphers.end(); ++it) {
|
for(akm_type::const_iterator it = _akm_cyphers.begin(); it != _akm_cyphers.end(); ++it) {
|
||||||
*(uint32_t*)ptr = *it;
|
std::memcpy(ptr, &*it, sizeof(uint32_t));
|
||||||
ptr += sizeof(uint32_t);
|
ptr += sizeof(uint32_t);
|
||||||
}
|
}
|
||||||
*(uint16_t*)ptr = _capabilities;
|
std::memcpy(ptr, &capabilities, sizeof(uint16_t));
|
||||||
|
|
||||||
return buffer;
|
return buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -218,13 +218,22 @@ std::string to_string(PDU::PDUType pduType) {
|
|||||||
|
|
||||||
uint32_t do_checksum(const uint8_t *start, const uint8_t *end) {
|
uint32_t do_checksum(const uint8_t *start, const uint8_t *end) {
|
||||||
uint32_t checksum(0);
|
uint32_t checksum(0);
|
||||||
uint16_t *ptr = (uint16_t*)start, *last = (uint16_t*)end, padding(0);
|
const uint8_t *last = end;
|
||||||
|
uint16_t buffer = 0;
|
||||||
|
uint16_t padding = 0;
|
||||||
|
const uint8_t *ptr = start;
|
||||||
|
|
||||||
if(((end - start) & 1) == 1) {
|
if(((end - start) & 1) == 1) {
|
||||||
last = (uint16_t*)end - 1;
|
last = end - 1;
|
||||||
padding = *(end - 1) << 8;
|
padding = *(end - 1) << 8;
|
||||||
}
|
}
|
||||||
while(ptr < last)
|
|
||||||
checksum += Endian::host_to_be(*(ptr++));
|
while(ptr < last) {
|
||||||
|
memcpy(&buffer, ptr, sizeof(uint16_t));
|
||||||
|
checksum += Endian::host_to_be(buffer);
|
||||||
|
ptr += sizeof(uint16_t);
|
||||||
|
}
|
||||||
|
|
||||||
return checksum + padding;
|
return checksum + padding;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user