diff --git a/include/tins/CMakeLists.txt b/include/tins/CMakeLists.txt index 1f55d3a..1b67728 100644 --- a/include/tins/CMakeLists.txt +++ b/include/tins/CMakeLists.txt @@ -7,3 +7,4 @@ INSTALL( ADD_SUBDIRECTORY(dot11) ADD_SUBDIRECTORY(tcp_ip) ADD_SUBDIRECTORY(detail) +ADD_SUBDIRECTORY(utils) diff --git a/include/tins/utils.h b/include/tins/utils.h index 0e9c341..e2a54e2 100644 --- a/include/tins/utils.h +++ b/include/tins/utils.h @@ -39,6 +39,7 @@ #include "ipv6_address.h" #include "pdu.h" #include "detail/type_traits.h" +#include "utils/checksum_utils.h" // Fix for Windows interface define on combaseapi.h #undef interface @@ -215,13 +216,6 @@ TINS_API std::vector route_entries(); */ TINS_API std::vector route6_entries(); -/** \brief Returns the 32 bit crc of the given buffer. - * - * \param data The input buffer. - * \param data_size The size of the input buffer. - */ -TINS_API uint32_t crc32(const uint8_t* data, uint32_t data_size); - /** * \brief Converts a channel number to its mhz representation. * \param channel The channel number. @@ -243,56 +237,6 @@ TINS_API uint16_t mhz_to_channel(uint16_t mhz); */ TINS_API std::string to_string(PDU::PDUType pduType); -/** - * \brief Does the 16 bits sum of all 2 bytes elements between start and end. - * - * This is the checksum used by IP, UDP and TCP. If there's and odd number of - * bytes, the last one is padded and added to the checksum. - * \param start The pointer to the start of the buffer. - * \param end The pointer to the end of the buffer(excluding the last element). - * \return Returns the checksum between start and end (non inclusive) - * in network endian - */ -TINS_API uint32_t do_checksum(const uint8_t* start, const uint8_t* end); - -/** - * \brief Computes the 16 bit sum of the input buffer. - * - * If there's and odd number of bytes in the buffer, the last one is padded and - * added to the checksum. - * \param start The pointer to the start of the buffer. - * \param end The pointer to the end of the buffer(excluding the last element). - * \return Returns the checksum between start and end (non inclusive) - * in network endian - */ -TINS_API uint16_t sum_range(const uint8_t* start, const uint8_t* end); - -/** \brief Performs the pseudo header checksum used in TCP and UDP PDUs. - * - * \param source_ip The source ip address. - * \param dest_ip The destination ip address. - * \param len The length to be included in the pseudo header. - * \param flag The flag to use in the protocol field of the pseudo header. - * \return The pseudo header checksum. - */ -TINS_API uint32_t pseudoheader_checksum(IPv4Address source_ip, - IPv4Address dest_ip, - uint16_t len, - uint16_t flag); - -/** \brief Performs the pseudo header checksum used in TCP and UDP PDUs. - * - * \param source_ip The source ip address. - * \param dest_ip The destination ip address. - * \param len The length to be included in the pseudo header. - * \param flag The flag to use in the protocol field of the pseudo header. - * \return The pseudo header checksum. - */ -TINS_API uint32_t pseudoheader_checksum(IPv6Address source_ip, - IPv6Address dest_ip, - uint16_t len, - uint16_t flag); - template struct is_pdu { template diff --git a/include/tins/utils/CMakeLists.txt b/include/tins/utils/CMakeLists.txt new file mode 100644 index 0000000..04ddc8b --- /dev/null +++ b/include/tins/utils/CMakeLists.txt @@ -0,0 +1,6 @@ +FILE(GLOB INCLUDE_FILES "*.h") +INSTALL( + FILES ${INCLUDE_FILES} + DESTINATION include/tins/utils + COMPONENT Headers +) diff --git a/include/tins/utils/checksum_utils.h b/include/tins/utils/checksum_utils.h new file mode 100644 index 0000000..1c4b407 --- /dev/null +++ b/include/tins/utils/checksum_utils.h @@ -0,0 +1,106 @@ +/* + * Copyright (c) 2017, Matias Fontanini + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef TINS_CHECKSUM_UTILS_H +#define TINS_CHECKSUM_UTILS_H + +#include +#include "../macros.h" + +namespace Tins { + +class IPv4Address; +class IPv6Address; + +namespace Utils { + +/** + * \brief Does the 16 bits sum of all 2 bytes elements between start and end. + * + * This is the checksum used by IP, UDP and TCP. If there's and odd number of + * bytes, the last one is padded and added to the checksum. + * \param start The pointer to the start of the buffer. + * \param end The pointer to the end of the buffer(excluding the last element). + * \return Returns the checksum between start and end (non inclusive) + * in network endian + */ +TINS_API uint32_t do_checksum(const uint8_t* start, const uint8_t* end); + +/** + * \brief Computes the 16 bit sum of the input buffer. + * + * If there's and odd number of bytes in the buffer, the last one is padded and + * added to the checksum. + * \param start The pointer to the start of the buffer. + * \param end The pointer to the end of the buffer(excluding the last element). + * \return Returns the checksum between start and end (non inclusive) + * in network endian + */ +TINS_API uint16_t sum_range(const uint8_t* start, const uint8_t* end); + +/** + * \brief Performs the pseudo header checksum used in TCP and UDP PDUs. + * + * \param source_ip The source ip address. + * \param dest_ip The destination ip address. + * \param len The length to be included in the pseudo header. + * \param flag The flag to use in the protocol field of the pseudo header. + * \return The pseudo header checksum. + */ +TINS_API uint32_t pseudoheader_checksum(IPv4Address source_ip, + IPv4Address dest_ip, + uint16_t len, + uint16_t flag); + +/** + * \brief Performs the pseudo header checksum used in TCP and UDP PDUs. + * + * \param source_ip The source ip address. + * \param dest_ip The destination ip address. + * \param len The length to be included in the pseudo header. + * \param flag The flag to use in the protocol field of the pseudo header. + * \return The pseudo header checksum. + */ +TINS_API uint32_t pseudoheader_checksum(IPv6Address source_ip, + IPv6Address dest_ip, + uint16_t len, + uint16_t flag); + +/** + * \brief Returns the 32 bit crc of the given buffer. + * + * \param data The input buffer. + * \param data_size The size of the input buffer. + */ +TINS_API uint32_t crc32(const uint8_t* data, uint32_t data_size); + +} // Utils +} // Tins + +#endif // TINS_CHECKSUM_UTILS_H diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index f340fb6..07334c0 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -72,6 +72,7 @@ set(SOURCES dot11/dot11_auth.cpp dot11/dot11_probe.cpp dot11/dot11_control.cpp + utils/checksum_utils.cpp ) SET(PCAP_DEPENDENT_SOURCES diff --git a/src/icmp.cpp b/src/icmp.cpp index 419399f..5b14f0c 100644 --- a/src/icmp.cpp +++ b/src/icmp.cpp @@ -33,11 +33,11 @@ #include #endif #include "rawpdu.h" -#include "utils.h" #include "exceptions.h" #include "icmp.h" #include "memory_helpers.h" #include "detail/icmp_extension_helpers.h" +#include "utils/checksum_utils.h" using std::memset; using std::max; diff --git a/src/icmpv6.cpp b/src/icmpv6.cpp index d503eb6..457ca46 100644 --- a/src/icmpv6.cpp +++ b/src/icmpv6.cpp @@ -32,11 +32,11 @@ #include "icmpv6.h" #include "ipv6.h" #include "rawpdu.h" -#include "utils.h" #include "constants.h" #include "exceptions.h" #include "memory_helpers.h" #include "detail/icmp_extension_helpers.h" +#include "utils/checksum_utils.h" using std::memset; using std::vector; diff --git a/src/ip.cpp b/src/ip.cpp index 3bcbdb3..6eb0c7a 100644 --- a/src/ip.cpp +++ b/src/ip.cpp @@ -39,7 +39,6 @@ #endif #include "ip.h" #include "rawpdu.h" -#include "utils.h" #include "packet_sender.h" #include "constants.h" #include "network_interface.h" @@ -47,6 +46,7 @@ #include "pdu_allocator.h" #include "memory_helpers.h" #include "internals.h" +#include "utils/checksum_utils.h" using std::list; using std::min; diff --git a/src/radiotap.cpp b/src/radiotap.cpp index 1477360..6198fa1 100644 --- a/src/radiotap.cpp +++ b/src/radiotap.cpp @@ -48,6 +48,7 @@ #include "packet_sender.h" #include "exceptions.h" #include "memory_helpers.h" +#include "utils/checksum_utils.h" using std::memcpy; diff --git a/src/tcp.cpp b/src/tcp.cpp index 6a7ffe2..fec72fa 100644 --- a/src/tcp.cpp +++ b/src/tcp.cpp @@ -34,10 +34,10 @@ #include "ipv6.h" #include "constants.h" #include "rawpdu.h" -#include "utils.h" #include "exceptions.h" #include "internals.h" #include "memory_helpers.h" +#include "utils/checksum_utils.h" using std::find_if; using std::min; diff --git a/src/udp.cpp b/src/udp.cpp index 74cd93d..fbec788 100644 --- a/src/udp.cpp +++ b/src/udp.cpp @@ -31,12 +31,12 @@ #include #include "udp.h" #include "constants.h" -#include "utils.h" #include "ip.h" #include "ipv6.h" #include "rawpdu.h" #include "exceptions.h" #include "memory_helpers.h" +#include "utils/checksum_utils.h" using Tins::Memory::InputMemoryStream; using Tins::Memory::OutputMemoryStream; diff --git a/src/utils.cpp b/src/utils.cpp index 8645607..f815e99 100644 --- a/src/utils.cpp +++ b/src/utils.cpp @@ -595,89 +595,5 @@ string to_string(PDU::PDUType pduType) { #undef ENUM_TEXT } -uint32_t do_checksum(const uint8_t* start, const uint8_t* end) { - return Endian::host_to_be(sum_range(start, end)); -} - -uint16_t sum_range(const uint8_t* start, const uint8_t* end) { - uint32_t checksum(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 = end - 1; - padding = Endian::host_to_le(*(end - 1)); - } - - while (ptr < last) { - memcpy(&buffer, ptr, sizeof(uint16_t)); - checksum += buffer; - ptr += sizeof(uint16_t); - } - - checksum += padding; - while (checksum >> 16) { - checksum = (checksum & 0xffff) + (checksum >> 16); - } - return checksum; -} - -template -uint32_t generic_pseudoheader_checksum(const AddressType& source_ip, - const AddressType& dest_ip, - uint16_t len, - uint16_t flag) { - uint8_t buffer[buffer_size]; - OutputMemoryStream stream(buffer, sizeof(buffer)); - stream.write(source_ip); - stream.write(dest_ip); - stream.write(Endian::host_to_be(flag)); - stream.write(Endian::host_to_be(len)); - - InputMemoryStream input_stream(buffer, sizeof(buffer)); - uint32_t checksum = 0; - while (input_stream) { - checksum += input_stream.read(); - } - return checksum; -} - -uint32_t pseudoheader_checksum(IPv4Address source_ip, - IPv4Address dest_ip, - uint16_t len, - uint16_t flag) { - return generic_pseudoheader_checksum( - source_ip, dest_ip, len, flag - ); -} - -uint32_t pseudoheader_checksum(IPv6Address source_ip, - IPv6Address dest_ip, - uint16_t len, - uint16_t flag) { - return generic_pseudoheader_checksum( - source_ip, dest_ip, len, flag - ); -} - -uint32_t crc32(const uint8_t* data, uint32_t data_size) { - uint32_t i, crc = 0; - static uint32_t crc_table[] = { - 0x4DBDF21C, 0x500AE278, 0x76D3D2D4, 0x6B64C2B0, - 0x3B61B38C, 0x26D6A3E8, 0x000F9344, 0x1DB88320, - 0xA005713C, 0xBDB26158, 0x9B6B51F4, 0x86DC4190, - 0xD6D930AC, 0xCB6E20C8, 0xEDB71064, 0xF0000000 - }; - - for (i = 0; i < data_size; ++i) { - crc = (crc >> 4) ^ crc_table[(crc ^ data[i]) & 0x0F]; - crc = (crc >> 4) ^ crc_table[(crc ^ (data[i] >> 4)) & 0x0F]; - } - - return crc; -} - } // Utils } // Tins diff --git a/src/utils/checksum_utils.cpp b/src/utils/checksum_utils.cpp new file mode 100644 index 0000000..3038ec0 --- /dev/null +++ b/src/utils/checksum_utils.cpp @@ -0,0 +1,131 @@ +/* + * Copyright (c) 2017, Matias Fontanini + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "utils/checksum_utils.h" +#include +#include "ip_address.h" +#include "ipv6_address.h" +#include "endianness.h" +#include "memory_helpers.h" + +using std::memcpy; + +using Tins::Memory::InputMemoryStream; +using Tins::Memory::OutputMemoryStream; + +namespace Tins { +namespace Utils { + +uint32_t do_checksum(const uint8_t* start, const uint8_t* end) { + return Endian::host_to_be(sum_range(start, end)); +} + +uint16_t sum_range(const uint8_t* start, const uint8_t* end) { + uint32_t checksum(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 = end - 1; + padding = Endian::host_to_le(*(end - 1)); + } + + while (ptr < last) { + memcpy(&buffer, ptr, sizeof(uint16_t)); + checksum += buffer; + ptr += sizeof(uint16_t); + } + + checksum += padding; + while (checksum >> 16) { + checksum = (checksum & 0xffff) + (checksum >> 16); + } + return checksum; +} + +template +uint32_t generic_pseudoheader_checksum(const AddressType& source_ip, + const AddressType& dest_ip, + uint16_t len, + uint16_t flag) { + uint8_t buffer[buffer_size]; + OutputMemoryStream stream(buffer, sizeof(buffer)); + stream.write(source_ip); + stream.write(dest_ip); + stream.write(Endian::host_to_be(flag)); + stream.write(Endian::host_to_be(len)); + + InputMemoryStream input_stream(buffer, sizeof(buffer)); + uint32_t checksum = 0; + while (input_stream) { + checksum += input_stream.read(); + } + return checksum; +} + +uint32_t pseudoheader_checksum(IPv4Address source_ip, + IPv4Address dest_ip, + uint16_t len, + uint16_t flag) { + return generic_pseudoheader_checksum( + source_ip, dest_ip, len, flag + ); +} + +uint32_t pseudoheader_checksum(IPv6Address source_ip, + IPv6Address dest_ip, + uint16_t len, + uint16_t flag) { + return generic_pseudoheader_checksum( + source_ip, dest_ip, len, flag + ); +} + +uint32_t crc32(const uint8_t* data, uint32_t data_size) { + uint32_t i, crc = 0; + static uint32_t crc_table[] = { + 0x4DBDF21C, 0x500AE278, 0x76D3D2D4, 0x6B64C2B0, + 0x3B61B38C, 0x26D6A3E8, 0x000F9344, 0x1DB88320, + 0xA005713C, 0xBDB26158, 0x9B6B51F4, 0x86DC4190, + 0xD6D930AC, 0xCB6E20C8, 0xEDB71064, 0xF0000000 + }; + + for (i = 0; i < data_size; ++i) { + crc = (crc >> 4) ^ crc_table[(crc ^ data[i]) & 0x0F]; + crc = (crc >> 4) ^ crc_table[(crc ^ (data[i] >> 4)) & 0x0F]; + } + + return crc; +} + + +} // Utils +} // Tins