From e556f4147f01dd2daa359c708b815ab3baebb9fe Mon Sep 17 00:00:00 2001 From: Matias Fontanini Date: Sun, 30 Apr 2017 13:21:13 -0700 Subject: [PATCH] Move resolution utils into their own file --- include/tins/utils.h | 51 +---------- include/tins/utils/resolve_utils.h | 100 ++++++++++++++++++++++ src/CMakeLists.txt | 1 + src/utils.cpp | 64 -------------- src/utils/resolve_utils.cpp | 133 +++++++++++++++++++++++++++++ 5 files changed, 235 insertions(+), 114 deletions(-) create mode 100644 include/tins/utils/resolve_utils.h create mode 100644 src/utils/resolve_utils.cpp diff --git a/include/tins/utils.h b/include/tins/utils.h index d4665cb..249ec8c 100644 --- a/include/tins/utils.h +++ b/include/tins/utils.h @@ -40,6 +40,7 @@ #include "utils/checksum_utils.h" #include "utils/frequency_utils.h" #include "utils/routing_utils.h" +#include "utils/resolve_utils.h" // Fix for Windows interface define on combaseapi.h #undef interface @@ -62,56 +63,6 @@ class HWAddress; */ namespace Utils { -/** - * \brief Resolves a domain name and returns its corresponding ip address. - * - * If an ip address is given, its integer representation is returned. - * Otherwise, the domain name is resolved and its ip address is returned. - * - * \param to_resolve The domain name/ip address to resolve. - */ -TINS_API IPv4Address resolve_domain(const std::string& to_resolve); - -/** - * \brief Resolves a domain name and returns its corresponding ip address. - * - * If an ip address is given, its integer representation is returned. - * Otherwise, the domain name is resolved and its ip address is returned. - * - * \param to_resolve The domain name/ip address to resolve. - */ -TINS_API IPv6Address resolve_domain6(const std::string& to_resolve); - -/** - * \brief Resolves the hardware address for a given ip. - * - * If the address can't be resolved, a std::runtime_error - * exception is thrown. - * - * \param iface The interface in which the packet will be sent. - * \param ip The ip to resolve, in integer format. - * \param sender The sender to use to send and receive the ARP requests. - * \return HWAddress<6> containing the resolved hardware address. - */ -TINS_API HWAddress<6> resolve_hwaddr(const NetworkInterface& iface, - IPv4Address ip, - PacketSender& sender); - -/** - * \brief Resolves the hardware address for a given ip. - * - * If the address can't be resolved, a std::runtime_error - * exception is thrown. - * - * This method sends and receives the packet through - * PacketSender::default_interface. - * - * \param ip The ip to resolve, in integer format. - * \param sender The sender to use to send and receive the ARP requests. - * \return HWAddress<6> containing the resolved hardware address. - */ -TINS_API HWAddress<6> resolve_hwaddr(IPv4Address ip, PacketSender& sender); - /** * \brief Converts a PDUType to a string. * \param pduType The PDUType to be converted. diff --git a/include/tins/utils/resolve_utils.h b/include/tins/utils/resolve_utils.h new file mode 100644 index 0000000..b3c45d8 --- /dev/null +++ b/include/tins/utils/resolve_utils.h @@ -0,0 +1,100 @@ +/* + * 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_RESOLVE_UTILS_H +#define TINS_RESOLVE_UTILS_H + +#include +#include "../macros.h" + +namespace Tins { + +class PacketSender; +class NetworkInterface; +class IPv4Address; +class IPv6Address; +template +class HWAddress; + +namespace Utils { + +/** + * \brief Resolves a domain name and returns its corresponding ip address. + * + * If an ip address is given, its integer representation is returned. + * Otherwise, the domain name is resolved and its ip address is returned. + * + * \param to_resolve The domain name/ip address to resolve. + */ +TINS_API IPv4Address resolve_domain(const std::string& to_resolve); + +/** + * \brief Resolves a domain name and returns its corresponding ip address. + * + * If an ip address is given, its integer representation is returned. + * Otherwise, the domain name is resolved and its ip address is returned. + * + * \param to_resolve The domain name/ip address to resolve. + */ +TINS_API IPv6Address resolve_domain6(const std::string& to_resolve); + +/** + * \brief Resolves the hardware address for a given ip. + * + * If the address can't be resolved, a std::runtime_error + * exception is thrown. + * + * \param iface The interface in which the packet will be sent. + * \param ip The ip to resolve, in integer format. + * \param sender The sender to use to send and receive the ARP requests. + * \return HWAddress<6> containing the resolved hardware address. + */ +TINS_API HWAddress<6> resolve_hwaddr(const NetworkInterface& iface, + IPv4Address ip, + PacketSender& sender); + +/** + * \brief Resolves the hardware address for a given ip. + * + * If the address can't be resolved, a std::runtime_error + * exception is thrown. + * + * This method sends and receives the packet through + * PacketSender::default_interface. + * + * \param ip The ip to resolve, in integer format. + * \param sender The sender to use to send and receive the ARP requests. + * \return HWAddress<6> containing the resolved hardware address. + */ +TINS_API HWAddress<6> resolve_hwaddr(IPv4Address ip, PacketSender& sender); + +} // Utils +} // Tins + +#endif // TINS_RESOLVE_UTILS_H diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 9e709e5..6279a2f 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -75,6 +75,7 @@ set(SOURCES utils/checksum_utils.cpp utils/frequency_utils.cpp utils/routing_utils.cpp + utils/resolve_utils.cpp ) SET(PCAP_DEPENDENT_SOURCES diff --git a/src/utils.cpp b/src/utils.cpp index 8d91f8b..d5f9300 100644 --- a/src/utils.cpp +++ b/src/utils.cpp @@ -76,72 +76,8 @@ using std::runtime_error; using Tins::Memory::InputMemoryStream; using Tins::Memory::OutputMemoryStream; -/** \cond */ - -addrinfo* resolve_domain(const string& to_resolve, int family) { - addrinfo* result, hints = addrinfo(); - hints.ai_socktype = SOCK_STREAM; - hints.ai_protocol = IPPROTO_TCP; - hints.ai_family = family; - if (!getaddrinfo(to_resolve.c_str(), 0, &hints, &result)) { - return result; - } - else { - throw runtime_error("Could not resolve address"); - } -} - namespace Tins { - -/** \endcond */ namespace Utils { - -IPv4Address resolve_domain(const string& to_resolve) { - addrinfo* result = ::resolve_domain(to_resolve, AF_INET); - IPv4Address addr(((sockaddr_in*)result->ai_addr)->sin_addr.s_addr); - freeaddrinfo(result); - return addr; -} - -IPv6Address resolve_domain6(const string& to_resolve) { - addrinfo* result = ::resolve_domain(to_resolve, AF_INET6); - IPv6Address addr((const uint8_t*)&((sockaddr_in6*)result->ai_addr)->sin6_addr); - freeaddrinfo(result); - return addr; -} - -HWAddress<6> resolve_hwaddr(const NetworkInterface& iface, - IPv4Address ip, - PacketSender& sender) { - NetworkInterface::Info info(iface.addresses()); - #ifdef _WIN32 - // On Windows, use SendARP - IPAddr source; - IPAddr dest; - ULONG hw_address[2]; - ULONG address_length = 6; - source = static_cast(info.ip_addr); - dest = static_cast(ip); - if (SendARP(dest, source, &hw_address, &address_length) == NO_ERROR && address_length == 6) { - return HWAddress<6>((const uint8_t*)hw_address); - } - #else - // On other platforms, just do the ARP resolution ourselves - EthernetII packet = ARP::make_arp_request(ip, info.ip_addr, info.hw_addr); - Internals::smart_ptr::type response(sender.send_recv(packet, iface)); - if (response.get()) { - const ARP* arp_resp = response->find_pdu(); - if (arp_resp) { - return arp_resp->sender_hw_addr(); - } - } - #endif - throw runtime_error("Could not resolve hardware address"); -} - -HWAddress<6> resolve_hwaddr(IPv4Address ip, PacketSender& sender) { - return resolve_hwaddr(sender.default_interface(), ip, sender); -} string to_string(PDU::PDUType pduType) { #define ENUM_TEXT(p) case(PDU::p): return #p; diff --git a/src/utils/resolve_utils.cpp b/src/utils/resolve_utils.cpp new file mode 100644 index 0000000..05c6747 --- /dev/null +++ b/src/utils/resolve_utils.cpp @@ -0,0 +1,133 @@ +/* + * 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/resolve_utils.h" + #ifndef _WIN32 + #if defined(BSD) || defined(__FreeBSD_kernel__) + #include + #include + #else + #include + #endif + #include + #include + #include + #ifdef __ANDROID_API__ + #include + #include + #endif +#else + #include + #include + #include + #undef interface +#endif +#include +#include "ip_address.h" +#include "ipv6_address.h" +#include "hw_address.h" +#include "ethernetII.h" +#include "arp.h" +#include "packet_sender.h" +#include "network_interface.h" +#include "detail/smart_ptr.h" + +using std::string; +using std::runtime_error; + +/** \cond */ + +addrinfo* resolve_domain(const string& to_resolve, int family) { + addrinfo* result, hints = addrinfo(); + hints.ai_socktype = SOCK_STREAM; + hints.ai_protocol = IPPROTO_TCP; + hints.ai_family = family; + if (!getaddrinfo(to_resolve.c_str(), 0, &hints, &result)) { + return result; + } + else { + throw runtime_error("Could not resolve address"); + } +} + +/** \endcond */ + +namespace Tins { +namespace Utils { + +IPv4Address resolve_domain(const string& to_resolve) { + addrinfo* result = ::resolve_domain(to_resolve, AF_INET); + IPv4Address addr(((sockaddr_in*)result->ai_addr)->sin_addr.s_addr); + freeaddrinfo(result); + return addr; +} + +IPv6Address resolve_domain6(const string& to_resolve) { + addrinfo* result = ::resolve_domain(to_resolve, AF_INET6); + IPv6Address addr((const uint8_t*)&((sockaddr_in6*)result->ai_addr)->sin6_addr); + freeaddrinfo(result); + return addr; +} + +HWAddress<6> resolve_hwaddr(const NetworkInterface& iface, + IPv4Address ip, + PacketSender& sender) { + NetworkInterface::Info info(iface.addresses()); + #ifdef _WIN32 + // On Windows, use SendARP + IPAddr source; + IPAddr dest; + ULONG hw_address[2]; + ULONG address_length = 6; + source = static_cast(info.ip_addr); + dest = static_cast(ip); + if (SendARP(dest, source, &hw_address, &address_length) == NO_ERROR && address_length == 6) { + return HWAddress<6>((const uint8_t*)hw_address); + } + #else + // On other platforms, just do the ARP resolution ourselves + EthernetII packet = ARP::make_arp_request(ip, info.ip_addr, info.hw_addr); + Internals::smart_ptr::type response(sender.send_recv(packet, iface)); + if (response.get()) { + const ARP* arp_resp = response->find_pdu(); + if (arp_resp) { + return arp_resp->sender_hw_addr(); + } + } + #endif + throw runtime_error("Could not resolve hardware address"); +} + +HWAddress<6> resolve_hwaddr(IPv4Address ip, PacketSender& sender) { + return resolve_hwaddr(sender.default_interface(), ip, sender); +} + + +} // Utils +} // Tins