From 52b0ee7ceb8d1b164473f020770a07a50d876f49 Mon Sep 17 00:00:00 2001 From: Christian Hammerl Date: Thu, 31 Jul 2014 01:05:10 +0200 Subject: [PATCH] fix armv5 alignment issues --- include/dhcpv6.h | 11 +++-- include/pdu_option.h | 5 ++- src/dhcp.cpp | 5 ++- src/dhcpv6.cpp | 88 +++++++++++++++++++++++++--------------- src/dns.cpp | 77 +++++++++++++++++++++++++---------- src/dot11/dot11_data.cpp | 4 +- src/dot11/dot11_mgmt.cpp | 11 ++--- src/icmp.cpp | 32 +++++++++------ src/icmpv6.cpp | 75 +++++++++++++++++++++------------- src/ip.cpp | 24 +++++++---- src/pppoe.cpp | 19 ++++++--- src/radiotap.cpp | 3 +- src/rsn_information.cpp | 57 ++++++++++++++++---------- src/utils.cpp | 17 ++++++-- 14 files changed, 279 insertions(+), 149 deletions(-) diff --git a/include/dhcpv6.h b/include/dhcpv6.h index dbfec3d..7480139 100644 --- a/include/dhcpv6.h +++ b/include/dhcpv6.h @@ -30,6 +30,7 @@ #ifndef TINS_DHCPV6_H #define TINS_DHCPV6_H +#include #include #include "pdu.h" #include "endianness.h" @@ -886,9 +887,11 @@ void class_option_data2option(InputIterator start, InputIterator end, std::vector& buffer, size_t start_index = 0) { size_t index = start_index; + uint16_t uint16_t_buffer; while(start != end) { buffer.resize(buffer.size() + sizeof(uint16_t) + start->size()); - *(uint16_t*)&buffer[index] = Endian::host_to_be(start->size()); + uint16_t_buffer = Endian::host_to_be(start->size()); + std::memcpy(&buffer[index], &uint16_t_buffer, sizeof(uint16_t)); index += sizeof(uint16_t); std::copy(start->begin(), start->end(), buffer.begin() + index); index += start->size(); @@ -904,9 +907,9 @@ OutputType option2class_option_data(const uint8_t *ptr, uint32_t total_sz) OutputType output; size_t index = 0; while(index + 2 < total_sz) { - uint16_t size = Endian::be_to_host( - *(const uint16_t*)(ptr + index) - ); + uint16_t size; + std::memcpy(&size, ptr + index, sizeof(uint16_t)); + size = Endian::be_to_host(size); index += sizeof(uint16_t); if(index + size > total_sz) throw option_not_found(); diff --git a/include/pdu_option.h b/include/pdu_option.h index 776fdc1..3453964 100644 --- a/include/pdu_option.h +++ b/include/pdu_option.h @@ -32,6 +32,7 @@ #include #include +#include #include #include #include @@ -266,8 +267,8 @@ namespace Internals { if(opt.data_size() != sizeof(T) + sizeof(U)) throw malformed_option(); std::pair output; - output.first = *(const T*)opt.data_ptr(); - output.second = *(const U*)(opt.data_ptr() + sizeof(T)); + std::memcpy(&output.first, opt.data_ptr(), sizeof(T)); + std::memcpy(&output.second, opt.data_ptr() + sizeof(T), sizeof(U)); if(PDUType::endianness == PDUType::BE) { output.first = Endian::be_to_host(output.first); output.second = Endian::be_to_host(output.second); diff --git a/src/dhcp.cpp b/src/dhcp.cpp index 0365e62..2914143 100644 --- a/src/dhcp.cpp +++ b/src/dhcp.cpp @@ -29,6 +29,7 @@ #include #include +#include #include "endianness.h" #include "dhcp.h" #include "ethernetII.h" @@ -52,7 +53,9 @@ DHCP::DHCP(const uint8_t *buffer, uint32_t total_sz) buffer += BootP::header_size() - vend().size(); total_sz -= BootP::header_size() - vend().size(); uint8_t args[2] = {0}; - if(total_sz < sizeof(uint32_t) || *(uint32_t*)buffer != Endian::host_to_be(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(0x63825363)) throw malformed_packet(); buffer += sizeof(uint32_t); total_sz -= sizeof(uint32_t); diff --git a/src/dhcpv6.cpp b/src/dhcpv6.cpp index da60d19..6c6abf7 100644 --- a/src/dhcpv6.cpp +++ b/src/dhcpv6.cpp @@ -63,10 +63,12 @@ DHCPv6::DHCPv6(const uint8_t *buffer, uint32_t total_sz) if(total_sz < sizeof(uint16_t) * 2) throw malformed_packet(); - const uint16_t opt = Endian::be_to_host(*(const uint16_t*)buffer); - const uint16_t data_size = Endian::be_to_host( - *(const uint16_t*)(buffer + sizeof(uint16_t)) - ); + uint16_t opt; + std::memcpy(&opt, 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) throw malformed_packet(); 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 { - *(uint16_t*)buffer = Endian::host_to_be(opt.option()); - *(uint16_t*)&buffer[sizeof(uint16_t)] = Endian::host_to_be(opt.length_field()); + 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(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(), @@ -289,8 +293,11 @@ void DHCPv6::option_request(const option_request_type &value) { std::vector buffer(value.size() * sizeof(uint16_t)); size_t index = 0; - for(iterator it = value.begin(); it != value.end(); ++it, index += 2) - *(uint16_t*)&buffer[index] = Endian::host_to_be(*it); + uint16_t uint16_t_buffer; + for(iterator it = value.begin(); it != value.end(); ++it, index += 2) { + uint16_t_buffer = Endian::host_to_be(*it); + std::memcpy(&buffer[index], &uint16_t_buffer, sizeof(uint16_t)); + } add_option( option(OPTION_REQUEST, buffer.begin(), buffer.end()) ); @@ -322,7 +329,8 @@ void DHCPv6::authentication(const authentication_type &value) { buffer[0] = value.protocol; buffer[1] = value.algorithm; 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( value.auth_info.begin(), 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) { std::vector 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( value.message.begin(), value.message.end(), @@ -372,7 +381,8 @@ void DHCPv6::vendor_class(const vendor_class_type &value) { std::vector buffer( 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( value.vendor_class_data.begin(), 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) { std::vector 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( value.data.begin(), 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) throw std::runtime_error("Not enough size for a DUID_LLT identifier"); 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); - 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); total_sz -= sizeof(uint16_t) + sizeof(uint32_t); 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 { serialization_type output(sizeof(uint16_t) + sizeof(uint32_t) + lladdress.size()); - *(uint16_t*)&output[0] = Endian::host_to_be(hw_type); - *(uint32_t*)&output[sizeof(uint16_t)] = Endian::host_to_be(time); + uint16_t tmp_hw_type = Endian::host_to_be(hw_type); + 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( lladdress.begin(), 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) throw std::runtime_error("Not enough size for a DUID_en identifier"); 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); total_sz -= sizeof(uint32_t); 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 { 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( identifier.begin(), 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) throw std::runtime_error("Not enough size for a DUID_en identifier"); 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); total_sz -= sizeof(uint16_t); 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 { 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( lladdress.begin(), lladdress.end(), @@ -493,7 +512,8 @@ PDU::serialization_type DHCPv6::duid_ll::serialize() const { void DHCPv6::client_id(const duid_type &value) { 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( value.data.begin(), value.data.end(), @@ -506,7 +526,8 @@ void DHCPv6::client_id(const duid_type &value) { void DHCPv6::server_id(const duid_type &value) { 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( value.data.begin(), value.data.end(), @@ -568,9 +589,8 @@ DHCPv6::authentication_type DHCPv6::authentication_type::from_option(const optio output.protocol = *ptr++; output.algorithm = *ptr++; output.rdm = *ptr++; - output.replay_detection = Endian::be_to_host( - *(const uint64_t*)ptr - ); + std::memcpy(&output.replay_detection, ptr, sizeof(uint64_t)); + output.replay_detection = Endian::be_to_host(output.replay_detection); ptr += sizeof(uint64_t); output.auth_info.assign(ptr, opt.data_ptr() + opt.data_size()); 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)) throw malformed_option(); 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( opt.data_ptr() + sizeof(uint16_t), 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)) throw malformed_option(); vendor_info_type output; - output.enterprise_number = Endian::be_to_host( - *(const uint32_t*)opt.data_ptr() - ); + std::memcpy(&output.enterprise_number, opt.data_ptr(), sizeof(uint32_t)); + output.enterprise_number = Endian::be_to_host(output.enterprise_number); output.data.assign( opt.data_ptr() + sizeof(uint32_t), 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(); typedef vendor_class_type::class_data_type data_type; vendor_class_type output; - output.enterprise_number = Endian::be_to_host( - *(const uint32_t*)opt.data_ptr() - ); + std::memcpy(&output.enterprise_number, opt.data_ptr(), sizeof(uint32_t)); + output.enterprise_number = Endian::be_to_host(output.enterprise_number); output.vendor_class_data = Internals::option2class_option_data( opt.data_ptr() + 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) throw malformed_option(); + + uint16_t uint16_t_buffer; + std::memcpy(&uint16_t_buffer, opt.data_ptr(), sizeof(uint16_t)); return duid_type( - Endian::be_to_host(*(const uint16_t*)opt.data_ptr()), + Endian::be_to_host(uint16_t_buffer), serialization_type( opt.data_ptr() + sizeof(uint16_t), opt.data_ptr() + opt.data_size() diff --git a/src/dns.cpp b/src/dns.cpp index bd3b062..99a0fa4 100644 --- a/src/dns.cpp +++ b/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 *end = &records_data[0] + records_data.size(); + uint16_t uint16_t_buffer; for(uint32_t i = 0; i < num_records; ++i) { ptr = find_dname_end(ptr); if(ptr + sizeof(uint16_t) * 3 + sizeof(uint32_t) > end) throw malformed_packet(); 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); if(ptr + data_size > end) throw malformed_packet(); @@ -168,8 +170,11 @@ void DNS::add_query(const Query &query) { string new_str = encode_domain_name(query.dname()); // Type (2 bytes) + Class (2 Bytes) new_str.insert(new_str.end(), sizeof(uint16_t) * 2, ' '); - *(uint16_t*)&new_str[new_str.size() - 4] = Endian::host_to_be(query.type()); - *(uint16_t*)&new_str[new_str.size() - 2] = Endian::host_to_be(query.query_class()); + uint16_t uint16_t_buffer; + uint16_t_buffer = Endian::host_to_be(query.type()); + std::memcpy(&new_str[new_str.size() - 4], &uint16_t_buffer, sizeof(uint16_t)); + uint16_t_buffer = Endian::host_to_be(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; 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(), &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); - *(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); - *(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); - *(uint16_t*)ptr = Endian::host_to_be( + uint16_t_buffer = Endian::host_to_be( data_size + (resource.type() == MX ? 2 : 0) ); + std::memcpy(ptr, &uint16_t_buffer, sizeof(uint16_t)); ptr += sizeof(uint16_t); if(resource.type() == MX) { 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 + sizeof(uint16_t) > end) 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 if(index < 0x0c || &records_data[index - 0x0c] >= ptr) 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. uint16_t type, qclass, data_size; 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); - 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); - 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); - 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); // Skip the preference field if it's 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) throw malformed_packet(); + switch(type) { case AAAA: 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(); break; 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(); - inline_convert_v4(*(uint32_t*)ptr, small_addr_buf); - used_small_buffer = true; break; case NS: 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) { while(*ptr != 0) { 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) { - *(uint16_t*)ptr = Endian::host_to_be((index + offset) | 0xc000); + index = Endian::host_to_be((index + offset) | 0xc000); + std::memcpy(ptr, &index, sizeof(uint16_t)); } ptr += sizeof(uint16_t); 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]; for(uint32_t i = 0; i < num_records; ++i) { 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); - 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); if(type == MX) { ptr += sizeof(uint16_t); @@ -483,15 +514,19 @@ DNS::queries_type DNS::queries() const { queries_type output; const uint8_t *ptr = &records_data[0], *end = &records_data[answers_idx]; char buffer[256]; + uint16_t tmp_query_type; + uint16_t tmp_query_class; while(ptr < end) { ptr = compose_name(ptr, buffer); if(ptr + sizeof(uint16_t) * 2 > end) 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( Query( buffer, - (QueryType)Endian::be_to_host(*(const uint16_t*)ptr), - (QueryClass)Endian::be_to_host(*(const uint16_t*)(ptr + 2)) + (QueryType)Endian::be_to_host(tmp_query_type), + (QueryClass)Endian::be_to_host(tmp_query_class) ) ); ptr += sizeof(uint16_t) * 2; diff --git a/src/dot11/dot11_data.cpp b/src/dot11/dot11_data.cpp index 7d70d81..7be7981 100644 --- a/src/dot11/dot11_data.cpp +++ b/src/dot11/dot11_data.cpp @@ -153,7 +153,7 @@ Dot11QoSData::Dot11QoSData(const uint8_t *buffer, uint32_t total_sz) total_sz -= sz; if(total_sz < sizeof(_qos_control)) throw malformed_packet(); - _qos_control = *(uint16_t*)buffer; + std::memcpy(&_qos_control, buffer, sizeof(uint16_t)); total_sz -= sizeof(uint16_t); buffer += sizeof(uint16_t); if(total_sz) { @@ -178,7 +178,7 @@ uint32_t Dot11QoSData::write_fixed_parameters(uint8_t *buffer, uint32_t total_sz #ifdef TINS_DEBUG assert(sz <= total_sz); #endif - *(uint16_t*)buffer = this->_qos_control; + std::memcpy(buffer, &this->_qos_control, sizeof(uint16_t)); return sz; } } // namespace Tins diff --git a/src/dot11/dot11_mgmt.cpp b/src/dot11/dot11_mgmt.cpp index 65af0ab..298f500 100644 --- a/src/dot11/dot11_mgmt.cpp +++ b/src/dot11/dot11_mgmt.cpp @@ -496,7 +496,7 @@ Dot11ManagementFrame::fh_params_set Dot11ManagementFrame::fh_params_set::from_op if(opt.data_size() != 5) throw malformed_option(); 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_pattern = opt.data_ptr()[3]; 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; output.cfp_count = *opt.data_ptr(); output.cfp_period = opt.data_ptr()[1]; - output.cfp_max_duration = Endian::le_to_host(*(uint16_t*)&opt.data_ptr()[2]); - output.cfp_dur_remaining = Endian::le_to_host(*(uint16_t*)&opt.data_ptr()[4]); + std::memcpy(&output.cfp_max_duration, &opt.data_ptr()[2], sizeof(uint16_t)); + std::memcpy(&output.cfp_dur_remaining, &opt.data_ptr()[4], sizeof(uint16_t)); return output; } @@ -601,9 +601,10 @@ Dot11ManagementFrame::bss_load_type Dot11ManagementFrame::bss_load_type::from_op bss_load_type output; 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.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; } diff --git a/src/icmp.cpp b/src/icmp.cpp index fabc31b..dfb4ea5 100644 --- a/src/icmp.cpp +++ b/src/icmp.cpp @@ -55,21 +55,24 @@ ICMP::ICMP(const uint8_t *buffer, uint32_t total_sz) std::memcpy(&_icmp, buffer, sizeof(icmphdr)); buffer += sizeof(icmphdr); total_sz -= sizeof(icmphdr); + uint32_t uint32_t_buffer = 0; if(type() == TIMESTAMP_REQUEST || type() == TIMESTAMP_REPLY) { if(total_sz < sizeof(uint32_t) * 3) throw malformed_packet(); - const uint32_t *ptr = reinterpret_cast(buffer); - original_timestamp(*ptr++); - receive_timestamp(*ptr++); - transmit_timestamp(*ptr++); + memcpy(&uint32_t_buffer, buffer, sizeof(uint32_t)); + original_timestamp(uint32_t_buffer); + memcpy(&uint32_t_buffer, buffer + sizeof(uint32_t), sizeof(uint32_t)); + 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; buffer += sizeof(uint32_t) * 3; } else if(type() == ADDRESS_MASK_REQUEST || type() == ADDRESS_MASK_REPLY) { if(total_sz < sizeof(uint32_t)) throw malformed_packet(); - const uint32_t *ptr = reinterpret_cast(buffer); - address_mask(address_type(*ptr++)); + memcpy(&uint32_t_buffer, buffer, sizeof(uint32_t)); + address_mask(address_type(uint32_t_buffer)); total_sz -= 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)); #endif + uint32_t uint32_t_buffer; if(type() == TIMESTAMP_REQUEST || type() == TIMESTAMP_REPLY) { - uint32_t *ptr = reinterpret_cast(buffer + sizeof(icmphdr)); - *ptr++ = original_timestamp(); - *ptr++ = receive_timestamp(); - *ptr++ = transmit_timestamp(); + 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 *ptr = reinterpret_cast(buffer + sizeof(icmphdr)); - *ptr++ = address_mask(); + uint32_t_buffer = address_mask(); + memcpy(buffer + sizeof(icmphdr), &uint32_t_buffer, sizeof(uint32_t)); } // checksum calc _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); _icmp.check = Endian::host_to_be(~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 { diff --git a/src/icmpv6.cpp b/src/icmpv6.cpp index 79153f8..443c9d3 100644 --- a/src/icmpv6.cpp +++ b/src/icmpv6.cpp @@ -72,9 +72,8 @@ ICMPv6::ICMPv6(const uint8_t *buffer, uint32_t total_sz) if(type() == ROUTER_ADVERT) { if(total_sz < sizeof(uint32_t) * 2) throw malformed_packet(); - const uint32_t *ptr_32 = (const uint32_t*)buffer; - reach_time = *ptr_32++; - retrans_timer = *ptr_32++; + memcpy(&reach_time, buffer, sizeof(uint32_t)); + memcpy(&retrans_timer, buffer + sizeof(uint32_t), sizeof(uint32_t)); buffer += 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 assert(total_sz >= header_size()); #endif - icmp6hdr* ptr_header = (icmp6hdr*)buffer; + uint8_t *buffer_start = buffer; _header.cksum = 0; std::memcpy(buffer, &_header, 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); } if(type() == ROUTER_ADVERT) { - *(uint32_t*)buffer = reach_time; + std::memcpy(buffer, &reach_time, sizeof(uint32_t)); buffer += sizeof(uint32_t); - *(uint32_t*)buffer = retrans_timer; + std::memcpy(buffer, &retrans_timer, sizeof(uint32_t)); buffer += sizeof(uint32_t); 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(), size(), Constants::IP::PROTO_ICMPV6 - ) + Utils::do_checksum((uint8_t*)ptr_header, buffer); + ) + Utils::do_checksum(buffer_start, buffer); while (checksum >> 16) checksum = (checksum & 0xffff) + (checksum >> 16); 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]; buffer[0] = info.prefix_len; buffer[1] = (info.L << 7) | (info.A << 6); - *(uint32_t*)(buffer + 2) = Endian::host_to_be(info.valid_lifetime); - *(uint32_t*)(buffer + 2 + sizeof(uint32_t)) = Endian::host_to_be(info.preferred_lifetime); - *(uint32_t*)(buffer + 2 + sizeof(uint32_t) * 2) = 0; + uint32_t uint32_t_buffer = Endian::host_to_be(info.valid_lifetime); + std::memcpy(buffer + 2, &uint32_t_buffer, sizeof(uint32_t)); + 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); add_option( 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) { std::vector buffer(6 + sizeof(uint64_t)); 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())); } @@ -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]; buffer[0] = value.dist << 4 | value.pref; 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)); add_option(option(MAP, buffer, buffer + sizeof(buffer))); } @@ -436,7 +440,8 @@ void ICMPv6::route_info(const route_info_type &value) { std::vector buffer(2 + sizeof(uint32_t) + value.prefix.size() + padding); buffer[0] = value.prefix_len; 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 buffer.insert( 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; - *(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::iterator out = buffer.begin() + 2 + sizeof(uint32_t); typedef recursive_dns_type::servers_type::const_iterator iterator; 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 buffer(data_size + padding); buffer[0] = padding; 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 std::fill( 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) { // at least it's got this size std::vector 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; for(iterator it = value.domains.begin(); it != value.domains.end(); ++it) { 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.L = (*ptr >> 7) & 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); - 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; return output; } @@ -745,7 +755,7 @@ ICMPv6::map_type ICMPv6::map_type::from_option(const option &opt) output.dist = (*ptr >> 4) & 0x0f; output.pref = *ptr++ & 0x0f; output.r = (*ptr++ >> 7) & 0x01; - output.valid_lifetime = *(uint32_t*)ptr; + std::memcpy(&output.valid_lifetime, ptr, sizeof(uint32_t)); ptr += sizeof(uint32_t); output.address = ptr; return output; @@ -759,7 +769,8 @@ ICMPv6::route_info_type ICMPv6::route_info_type::from_option(const option &opt) route_info_type output; output.prefix_len = *ptr++; 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); output.prefix.assign(ptr, opt.data_ptr() + opt.data_size()); return output; @@ -771,7 +782,8 @@ ICMPv6::recursive_dns_type ICMPv6::recursive_dns_type::from_option(const option throw malformed_option(); const uint8_t *ptr = opt.data_ptr() + 2, *end = opt.data_ptr() + opt.data_size(); 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); while(ptr < 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(); handover_key_reply_type output; 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); // is there enough size for the indicated padding? 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(); const uint8_t *ptr = opt.data_ptr(), *end = ptr + opt.data_size(); 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); while(ptr < end && *ptr) { 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)) 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); 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(); shortcut_limit_type output(*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; } @@ -888,8 +905,10 @@ ICMPv6::new_advert_interval_type ICMPv6::new_advert_interval_type::from_option(c if(opt.data_size() != 6) throw malformed_option(); new_advert_interval_type output; - output.reserved = Endian::be_to_host(*(uint16_t*)opt.data_ptr()); - output.interval = Endian::be_to_host(*(uint32_t*)(opt.data_ptr() + sizeof(uint16_t))); + std::memcpy(&output.reserved, 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; } } diff --git a/src/ip.cpp b/src/ip.cpp index f55825b..5c57bcb 100644 --- a/src/ip.cpp +++ b/src/ip.cpp @@ -445,10 +445,13 @@ IP::security_type IP::security_type::from_option(const option &opt) if(opt.data_size() != 9) throw malformed_option(); security_type output; - const uint16_t *ptr = reinterpret_cast(opt.data_ptr()); - output.security = Endian::be_to_host(*ptr++); - output.compartments = Endian::be_to_host(*ptr++); - output.handling_restrictions = Endian::be_to_host(*ptr++); + + memcpy(&output.security, opt.data_ptr(), sizeof(uint16_t)); + output.security = Endian::be_to_host(output.security); + 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]; tcc = (tcc << 8) | opt.data_ptr()[7]; 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(); generic_route_option_type output; output.pointer = *opt.data_ptr(); - const uint32_t *route = (const uint32_t*)(opt.data_ptr() + 1), - *end = route + (opt.data_size() - 1) / sizeof(uint32_t); - while(route < end) - output.routes.push_back(address_type(*route++)); + const uint8_t *route = opt.data_ptr() + 1; + const uint8_t *end = route + opt.data_size() - 1; + + 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; } } diff --git a/src/pppoe.cpp b/src/pppoe.cpp index c720b64..d3fe765 100644 --- a/src/pppoe.cpp +++ b/src/pppoe.cpp @@ -56,8 +56,10 @@ PPPoE::PPPoE(const uint8_t *buffer, uint32_t total_sz) while(buffer < end) { if(buffer + sizeof(uint32_t) * 2 > end) throw malformed_packet(); - uint16_t opt_type = *(const uint16_t*)buffer; - uint16_t opt_len = *(const uint16_t*)(buffer + sizeof(uint16_t)); + uint16_t opt_type; + 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; total_sz -= sizeof(uint16_t) * 2; 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) ((pppoe_hdr*)buffer)->payload_length = Endian::host_to_be(_tags_size); buffer += sizeof(_header); + uint16_t uint16_t_buffer; for(tags_type::const_iterator it = _tags.begin(); it != _tags.end(); ++it) { - *(uint16_t*)buffer = it->option(); - *(uint16_t*)(buffer + sizeof(uint16_t)) = Endian::host_to_be(it->length_field()); + uint16_t_buffer = it->option(); + std::memcpy(buffer, &uint16_t_buffer, sizeof(uint16_t)); + uint16_t_buffer = Endian::host_to_be(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(), @@ -158,7 +163,8 @@ void PPPoE::ac_cookie(const byte_array &value) { void PPPoE::vendor_specific(const vendor_spec_type &value) { std::vector 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( value.data.begin(), 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)) throw malformed_option(); 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( opt.data_ptr() + sizeof(uint32_t), opt.data_ptr() + opt.data_size() diff --git a/src/radiotap.cpp b/src/radiotap.cpp index 7d639cb..cb84a00 100644 --- a/src/radiotap.cpp +++ b/src/radiotap.cpp @@ -382,9 +382,10 @@ void RadioTap::write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU buffer += sizeof(_max_power); } 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()) ); + memcpy(buffer + inner_pdu()->size(), &crc32, sizeof(uint32_t)); } } } diff --git a/src/rsn_information.cpp b/src/rsn_information.cpp index 49a5f7c..23d9546 100644 --- a/src/rsn_information.cpp +++ b/src/rsn_information.cpp @@ -30,6 +30,7 @@ #include "rsn_information.h" #ifdef HAVE_DOT11 +#include #include #include "exceptions.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) { if(total_sz <= sizeof(uint16_t) * 2 + sizeof(uint32_t)) 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); 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); total_sz -= sizeof(uint32_t); - uint16_t count = *(uint16_t*)buffer; + std::memcpy(&uint16_t_buffer, buffer, sizeof(uint16_t)); buffer += 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(); - total_sz -= count * sizeof(uint32_t); - while(count--) { - add_pairwise_cypher((RSNInformation::CypherSuites)*(uint32_t*)buffer); + total_sz -= uint16_t_buffer * sizeof(uint32_t); + while(uint16_t_buffer--) { + std::memcpy(&uint32_t_buffer, buffer, sizeof(uint32_t)); + add_pairwise_cypher((RSNInformation::CypherSuites)uint32_t_buffer); buffer += sizeof(uint32_t); } check_size(total_sz); - count = *(uint16_t*)buffer; + std::memcpy(&uint16_t_buffer, buffer, sizeof(uint16_t)); buffer += 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(); - total_sz -= count * sizeof(uint32_t); - while(count--) { - add_akm_cypher((RSNInformation::AKMSuites)*(uint32_t*)buffer); + total_sz -= uint16_t_buffer * sizeof(uint32_t); + while(uint16_t_buffer--) { + std::memcpy(&uint32_t_buffer, buffer, sizeof(uint32_t)); + add_akm_cypher((RSNInformation::AKMSuites)uint32_t_buffer); buffer += sizeof(uint32_t); } check_size(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) { @@ -117,26 +127,31 @@ RSNInformation::serialization_type RSNInformation::serialize() const { uint32_t size = sizeof(_version) + sizeof(_capabilities) + sizeof(uint32_t); size += (sizeof(uint16_t) << 1); // 2 lists count. 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::value_type *ptr = &buffer[0]; - *(uint16_t*)ptr = _version; - ptr += sizeof(_version); - *(uint32_t*)ptr = _group_suite; + std::memcpy(ptr, &_version, sizeof(_version)); + ptr += sizeof(uint16_t); + std::memcpy(ptr, &_group_suite, 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); 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); } - *(uint16_t*)ptr = _akm_cyphers.size(); + std::memcpy(ptr, &akm_cyphers_size, sizeof(uint16_t)); ptr += sizeof(uint16_t); 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); } - *(uint16_t*)ptr = _capabilities; + std::memcpy(ptr, &capabilities, sizeof(uint16_t)); + return buffer; } diff --git a/src/utils.cpp b/src/utils.cpp index ff6f763..8b8ff66 100644 --- a/src/utils.cpp +++ b/src/utils.cpp @@ -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 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) { - last = (uint16_t*)end - 1; + last = end - 1; 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; }