From fa9c260d851477ede3e37d85271f315a06444dc1 Mon Sep 17 00:00:00 2001 From: Matias Fontanini Date: Tue, 20 Mar 2012 12:07:08 -0300 Subject: [PATCH] Added Utils::ping_address. Fixed bugs in PacketSender::recv_match_loop. --- include/packetsender.h | 2 ++ include/utils.h | 17 +++++++++++++++++ src/packetsender.cpp | 37 ++++++++++++++++++++++++++++++------- src/utils.cpp | 14 +++++++++++++- 4 files changed, 62 insertions(+), 8 deletions(-) diff --git a/include/packetsender.h b/include/packetsender.h index 2ea0678..72cf9da 100644 --- a/include/packetsender.h +++ b/include/packetsender.h @@ -29,6 +29,7 @@ #ifndef WIN32 #include + #include #endif #include "pdu.h" @@ -169,6 +170,7 @@ namespace Tins { typedef std::map SocketTypeMap; int find_type(SocketType type); + int timeval_subtract (struct timeval *result, struct timeval *x, struct timeval *y); PDU *recv_match_loop(int sock, PDU *pdu, struct sockaddr* link_addr, socklen_t addrlen); diff --git a/include/utils.h b/include/utils.h index 7409fff..552042d 100644 --- a/include/utils.h +++ b/include/utils.h @@ -78,6 +78,23 @@ namespace Tins { * \param to_resolve The domain name/ip address to resolve. */ uint32_t resolve_ip(const std::string &to_resolve) throw (std::runtime_error); + + /** + * \brief Pings an ip address. + * + * This function pings an IP address and returns the ICMP response. + * If no response is received, 0 is returned + * + * \param ip The IP address to ping. + * \param sender The PacketSender that will send the ping request. + * \param ip_src The source IP address that will be used in the packet. + * If 0, or no parameter is provided, then that IP address is looked + * up using Utils::interface_ip. + * + * \return PDU * containing either 0 if no response was received, + * or the ICMP response otherwise. + */ + PDU *ping_address(uint32_t ip, PacketSender *sender, uint32_t ip_src = 0); /** \brief Resolves the hardware address for a given ip. * diff --git a/src/packetsender.cpp b/src/packetsender.cpp index 5f4afa9..1f0c2d6 100644 --- a/src/packetsender.cpp +++ b/src/packetsender.cpp @@ -22,16 +22,15 @@ #ifndef WIN32 #include #include - #include #include #include #include #include #include #endif -#include +#include #include -#include +#include #include #include "packetsender.h" @@ -156,16 +155,40 @@ Tins::PDU *Tins::PacketSender::recv_match_loop(int sock, PDU *pdu, struct sockad if(pdu->matches_response(buffer, size)) return pdu->clone_packet(buffer, size); } - struct timeval this_time; + struct timeval this_time, diff; gettimeofday(&this_time, 0); - if(end_time.tv_sec <= this_time.tv_sec && end_time.tv_usec <= this_time.tv_usec) + if(timeval_subtract(&diff, &this_time, &end_time)) { return 0; - timeout.tv_sec = end_time.tv_sec - this_time.tv_sec; - timeout.tv_usec = end_time.tv_usec; + } + timeout.tv_sec = diff.tv_sec; + timeout.tv_usec = diff.tv_usec; } return 0; } +int Tins::PacketSender::timeval_subtract (struct timeval *result, struct timeval *x, struct timeval *y) { + /* Perform the carry for the later subtraction by updating y. */ + if (x->tv_usec < y->tv_usec) { + int nsec = (y->tv_usec - x->tv_usec) / 1000000 + 1; + y->tv_usec -= 1000000 * nsec; + y->tv_sec += nsec; + } + + if (x->tv_usec - y->tv_usec > 1000000) { + int nsec = (x->tv_usec - y->tv_usec) / 1000000; + y->tv_usec += 1000000 * nsec; + y->tv_sec -= nsec; + } + + /* Compute the time remaining to wait. + tv_usec is certainly positive. */ + result->tv_sec = x->tv_sec - y->tv_sec; + result->tv_usec = x->tv_usec - y->tv_usec; + + /* Return 1 if result is negative. */ + return x->tv_sec < y->tv_sec; +} + int Tins::PacketSender::find_type(SocketType type) { SocketTypeMap::iterator it = _types.find(type); if(it == _types.end()) diff --git a/src/utils.cpp b/src/utils.cpp index fb56855..f52623c 100644 --- a/src/utils.cpp +++ b/src/utils.cpp @@ -23,7 +23,6 @@ #include #include #include -#include //borrame #include #include #ifndef WIN32 @@ -33,6 +32,8 @@ #endif #include "utils.h" #include "pdu.h" +#include "ip.h" +#include "icmp.h" #include "arp.h" @@ -187,6 +188,17 @@ uint32_t Tins::Utils::resolve_ip(const string &to_resolve) throw (std::runtime_e return Utils::net_to_host_l(((struct in_addr**)data->h_addr_list)[0]->s_addr); } +Tins::PDU *Tins::Utils::ping_address(uint32_t ip, PacketSender *sender, uint32_t ip_src) { + ICMP *icmp = new ICMP(ICMP::ECHO_REQUEST); + if(!ip_src) { + std::string iface(Utils::interface_from_ip(ip)); + if(!iface.size() || !Utils::interface_ip(iface, ip_src)) + return 0; + } + IP ip_packet(ip, ip_src, icmp); + return sender->send_recv(&ip_packet); +} + bool Tins::Utils::resolve_hwaddr(const string &iface, uint32_t ip, uint8_t *buffer, PacketSender *sender) { uint32_t my_ip; uint8_t my_hw[6];