From 110adc58dc76ec346329e7ff43bf27ccb00cd96c Mon Sep 17 00:00:00 2001 From: Matias Fontanini Date: Sun, 30 Apr 2017 10:53:21 -0700 Subject: [PATCH] Move ICMP extension helpers into their own file --- include/tins/detail/icmp_extension_helpers.h | 61 ++++++++++++++ include/tins/internals.h | 4 - src/CMakeLists.txt | 1 + src/detail/icmp_extension_helpers.cpp | 86 ++++++++++++++++++++ src/icmp.cpp | 2 +- src/icmpv6.cpp | 2 +- src/internals.cpp | 45 ---------- 7 files changed, 150 insertions(+), 51 deletions(-) create mode 100644 include/tins/detail/icmp_extension_helpers.h create mode 100644 src/detail/icmp_extension_helpers.cpp diff --git a/include/tins/detail/icmp_extension_helpers.h b/include/tins/detail/icmp_extension_helpers.h new file mode 100644 index 0000000..cfd6bd1 --- /dev/null +++ b/include/tins/detail/icmp_extension_helpers.h @@ -0,0 +1,61 @@ +/* + * 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_ICMP_EXTENSION_HELPERS_H +#define TINS_ICMP_EXTENSION_HELPERS_H + +#include + +/** + * \cond + */ +namespace Tins { + +class PDU; +class ICMPExtensionsStructure; + +namespace Memory { +class InputMemoryStream; +} // Memory + +namespace Internals { + +uint32_t get_padded_icmp_inner_pdu_size(const PDU* inner_pdu, uint32_t pad_alignment); +void try_parse_icmp_extensions(Memory::InputMemoryStream& stream, uint32_t payload_length, + ICMPExtensionsStructure& extensions); + + +} // Internals +} // Tins + +/** + * \endcond + */ + +#endif // TINS_ICMP_EXTENSION_HELPERS_H diff --git a/include/tins/internals.h b/include/tins/internals.h index 6540e1f..caddac4 100644 --- a/include/tins/internals.h +++ b/include/tins/internals.h @@ -67,10 +67,6 @@ PDU::PDUType ether_type_to_pdu_flag(Constants::Ethernet::e flag); Constants::IP::e pdu_flag_to_ip_type(PDU::PDUType flag); PDU::PDUType ip_type_to_pdu_flag(Constants::IP::e flag); -uint32_t get_padded_icmp_inner_pdu_size(const PDU* inner_pdu, uint32_t pad_alignment); -void try_parse_icmp_extensions(Memory::InputMemoryStream& stream, - uint32_t payload_length, ICMPExtensionsStructure& extensions); - // Compares sequence numbers as defined by RFC 1982. int seq_compare(uint32_t seq1, uint32_t seq2); diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 791aad7..f340fb6 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -22,6 +22,7 @@ set(SOURCES pppoe.cpp crypto.cpp detail/address_helpers.cpp + detail/icmp_extension_helpers.cpp dhcp.cpp dhcpv6.cpp dns.cpp diff --git a/src/detail/icmp_extension_helpers.cpp b/src/detail/icmp_extension_helpers.cpp new file mode 100644 index 0000000..a2eea40 --- /dev/null +++ b/src/detail/icmp_extension_helpers.cpp @@ -0,0 +1,86 @@ +/* + * 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 "detail/icmp_extension_helpers.h" +#include "memory_helpers.h" +#include "pdu.h" +#include "icmp_extension.h" + +using Tins::Memory::InputMemoryStream; + +namespace Tins { +namespace Internals { + +uint32_t get_padded_icmp_inner_pdu_size(const PDU* inner_pdu, uint32_t pad_alignment) { + // This gets the size of the next pdu, padded to the next 32 bit word boundary + if (inner_pdu) { + uint32_t inner_pdu_size = inner_pdu->size(); + uint32_t padding = inner_pdu_size % pad_alignment; + inner_pdu_size = padding ? (inner_pdu_size - padding + pad_alignment) : inner_pdu_size; + return inner_pdu_size; + } + else { + return 0; + } +} + +void try_parse_icmp_extensions(InputMemoryStream& stream, + uint32_t payload_length, + ICMPExtensionsStructure& extensions) { + if (!stream) { + return; + } + // Check if this is one of the types defined in RFC 4884 + const uint32_t minimum_payload = ICMPExtensionsStructure::MINIMUM_ICMP_PAYLOAD; + // Check if we actually have this amount of data and whether it's more than + // the minimum encapsulated packet size + const uint8_t* extensions_ptr; + uint32_t extensions_size; + if (stream.can_read(payload_length) && payload_length >= minimum_payload) { + extensions_ptr = stream.pointer() + payload_length; + extensions_size = stream.size() - payload_length; + } + else if (stream.can_read(minimum_payload)) { + // This packet might be non-rfc compliant. In that case the length + // field can contain garbage. + extensions_ptr = stream.pointer() + minimum_payload; + extensions_size = stream.size() - minimum_payload; + } + else { + // No more special cases, this doesn't have extensions + return; + } + if (ICMPExtensionsStructure::validate_extensions(extensions_ptr, extensions_size)) { + extensions = ICMPExtensionsStructure(extensions_ptr, extensions_size); + stream.size(stream.size() - extensions_size); + } +} + +} // Internals +} // Tins diff --git a/src/icmp.cpp b/src/icmp.cpp index 3404c77..419399f 100644 --- a/src/icmp.cpp +++ b/src/icmp.cpp @@ -36,8 +36,8 @@ #include "utils.h" #include "exceptions.h" #include "icmp.h" -#include "internals.h" #include "memory_helpers.h" +#include "detail/icmp_extension_helpers.h" using std::memset; using std::max; diff --git a/src/icmpv6.cpp b/src/icmpv6.cpp index 7426efd..d503eb6 100644 --- a/src/icmpv6.cpp +++ b/src/icmpv6.cpp @@ -36,7 +36,7 @@ #include "constants.h" #include "exceptions.h" #include "memory_helpers.h" -#include "internals.h" +#include "detail/icmp_extension_helpers.h" using std::memset; using std::vector; diff --git a/src/internals.cpp b/src/internals.cpp index f4122c6..740d9eb 100644 --- a/src/internals.cpp +++ b/src/internals.cpp @@ -279,51 +279,6 @@ Constants::IP::e pdu_flag_to_ip_type(PDU::PDUType flag) { }; } -uint32_t get_padded_icmp_inner_pdu_size(const PDU* inner_pdu, uint32_t pad_alignment) { - // This gets the size of the next pdu, padded to the next 32 bit word boundary - if (inner_pdu) { - uint32_t inner_pdu_size = inner_pdu->size(); - uint32_t padding = inner_pdu_size % pad_alignment; - inner_pdu_size = padding ? (inner_pdu_size - padding + pad_alignment) : inner_pdu_size; - return inner_pdu_size; - } - else { - return 0; - } -} - -void try_parse_icmp_extensions(InputMemoryStream& stream, - uint32_t payload_length, - ICMPExtensionsStructure& extensions) { - if (!stream) { - return; - } - // Check if this is one of the types defined in RFC 4884 - const uint32_t minimum_payload = ICMPExtensionsStructure::MINIMUM_ICMP_PAYLOAD; - // Check if we actually have this amount of data and whether it's more than - // the minimum encapsulated packet size - const uint8_t* extensions_ptr; - uint32_t extensions_size; - if (stream.can_read(payload_length) && payload_length >= minimum_payload) { - extensions_ptr = stream.pointer() + payload_length; - extensions_size = stream.size() - payload_length; - } - else if (stream.can_read(minimum_payload)) { - // This packet might be non-rfc compliant. In that case the length - // field can contain garbage. - extensions_ptr = stream.pointer() + minimum_payload; - extensions_size = stream.size() - minimum_payload; - } - else { - // No more special cases, this doesn't have extensions - return; - } - if (ICMPExtensionsStructure::validate_extensions(extensions_ptr, extensions_size)) { - extensions = ICMPExtensionsStructure(extensions_ptr, extensions_size); - stream.size(stream.size() - extensions_size); - } -} - PDU::PDUType ip_type_to_pdu_flag(Constants::IP::e flag) { switch(flag) { case Constants::IP::PROTO_IPIP: