Compare commits

22 Commits
Author SHA1 Message Date
David Schweikert bda0744d2c Give due credit 2013-11-08 11:17:05 +01:00
David Schweikert d6808efd81 Fix segmentation fault introduced in version 3.7 with loop mode (#55) 2013-11-08 11:13:11 +01:00
David Schweikert 3a714b275f prepare release 2013-11-04 23:13:07 +01:00
David Schweikert d141744adb Fix fping hanging forever on permanent sendto failure (Shawn Chu, #52) 2013-11-04 23:08:19 +01:00
David Schweikert e1cdf8e1d3 Fix again compatibility issue with FreeBSD (Shawn Chu) 2013-11-04 23:04:00 +01:00
David Schweikert d862dd962b release preparations 2013-11-01 16:11:07 +01:00
David Schweikert 5c68d6f338 don't consider duplicate pings as successful replies (#53) 2013-11-01 15:01:11 +01:00
David Schweikert a2ac5d0fae Remove unnecessary IPv6 socket options 2013-10-15 09:21:14 +02:00
David Schweikert b01f282727 merge latest changes 2013-10-14 20:28:11 +02:00
David Schweikert 0ab66f80de Refactor socket handling, allow running as non-root on Mac OS X by using non-privileged ICMP (#7) 2013-10-13 12:42:37 +02:00
David Schweikert 741236e576 Release version 3.6 2013-10-10 22:05:45 +02:00
David Schweikert 9fca2a141b Fix wrong min RTT value with -Q option (reported by Alexander Ivanov, #51) 2013-10-10 21:58:13 +02:00
David Schweikert 9ee22bd46a prepare 3.6-rc2 2013-07-25 22:34:31 +02:00
David Schweikert f55397336b increase SEQMAP_MAX to 65355 2013-07-25 22:29:56 +02:00
David Schweikert 82722a31fe update README file 2013-07-25 22:29:44 +02:00
David Schweikert 4aad0b2c14 fix compilation issue 2013-07-25 22:29:33 +02:00
David Schweikert fb5f5779cc Merge seqmap branch, fixes #12 2013-07-24 21:38:41 +02:00
David Schweikert a0252f6e79 Removed setsockopt IPV6_CHECKSUM, which shouldn't be set and breaks compiling on Solaris (reported by Juergen Arndt) 2013-07-24 21:36:02 +02:00
David Schweikert 3dee903b41 3.5 is released 2013-07-23 23:54:27 +02:00
David Schweikert 7e55f0b073 Fix loop issue after 65536 pings (reported by Peter Folk and GBert, #12), Minimum ping data size is now 0 2013-07-23 23:40:17 +02:00
David Schweikert 8daad08e1d work on seqmap 2013-07-23 23:24:04 +02:00
David Schweikert b7343ed256 start work on seqmap 2013-07-23 00:25:53 +02:00
12 changed files with 483 additions and 206 deletions
+1
View File
@@ -1,3 +1,4 @@
.*.swp
*.tar.gz
*~
.deps
+22
View File
@@ -1,3 +1,25 @@
2013-11-08 David Schweikert <david@schweikert.ch>
* Version 3.8
* Fix segmentation fault introduced in version 3.7 with loop mode (reported
by Vlad Glagolev, #55)
2013-11-04 David Schweikert <david@schweikert.ch>
* Version 3.7
* Allow running as non-root on Mac OS X by using non-privileged ICMP (#7)
* Remove unnecessary IPv6 socket options
* Fix again compatibility issue with FreeBSD (Shawn Chu)
* Fix fping hanging forever on permanent sendto failure (Shawn Chu)
* Fix duplicate echo reply packets causing early stop in count mode
(reported by Ramon Schwammberger, #53)
2013-10-10 David Schweikert <david@schweikert.ch>
* Version 3.6
* Fix loop issue after 65536 pings (reported by Peter Folk and GBert, #12)
* Minimum ping data size is now 0
* Removed setsockopt IPV6_CHECKSUM, which shouldn't be set and breaks
compiling on Solaris (reported by Juergen Arndt)
* Fix wrong min RTT value with -Q option (reported by Alexander Ivanov, #51)
2013-05-22 David Schweikert <david@schweikert.ch>
* Version 3.5
* Fix sprint_tm buffer size crash (reported by Japheth Cleaver)
+7 -1
View File
@@ -9,7 +9,11 @@ Current maintainer:
David Schweikert <david@schweikert.ch>
Website:
http://www.fping.org/
http://fping.org/
Mailing-list:
https://groups.google.com/group/fping-users
Installation
------------
@@ -27,6 +31,7 @@ If you want to install fping from source, proceed as follows:
4. Have a look at the fping(8) manual for usage help
(fping -h will also give a minimal help output)
IPv6 support
------------
You can can compile fping with support for IPv6 addresses. A separate binary
@@ -38,6 +43,7 @@ is used for that, called fping6. To build it, use ./configure --enable-ipv6
# make install
# sudo setcap cap_net_raw+ep /usr/local/bin/fping*
Credits
-------
Original author: Roland Schemers (schemers@stanford.edu)
+1 -1
View File
@@ -3,7 +3,7 @@ dnl Process this file with autoconf to produce a configure script.
dnl Minimum Autoconf version required.
AC_PREREQ(2.59)
AC_INIT([fping],[3.4])
AC_INIT([fping],[3.7])
dnl make ipv4 and ipv6 options
AC_ARG_ENABLE([ipv4],
+2 -2
View File
@@ -9,8 +9,8 @@ endif
sbin_PROGRAMS = ${prog}
fping_SOURCES = fping.c options.h
fping_SOURCES = fping.c seqmap.c socket.c socket4.c fping.h options.h seqmap.h
fping_DEPENDENCIES = ../config.h
fping6_SOURCES = fping.c options.h
fping6_SOURCES = fping.c seqmap.c socket.c socket6.c fping.h options.h seqmap.h
fping6_DEPENDENCIES = ../config.h
fping6_CFLAGS = $(AM_CFLAGS) -DIPV6
+78 -202
View File
@@ -35,6 +35,9 @@ extern "C"
{
#endif /* __cplusplus */
#include "fping.h"
#include "options.h"
/* if compiling for Windows, use this separate set
(too difficult to ifdef all the autoconf defines) */
#ifdef WIN32
@@ -54,10 +57,8 @@ extern "C"
#include <getopt.h>
#include <stdarg.h>
#define __APPLE_USE_RFC_3542 1
#include <netinet/in.h>
#include "config.h"
#include "seqmap.h"
#ifdef HAVE_UNISTD_H
#include <unistd.h>
@@ -96,8 +97,6 @@ extern "C"
#endif /* WIN32 */
#include "options.h"
/*** externals ***/
extern char *optarg;
@@ -114,16 +113,7 @@ extern int h_errno;
/*** Ping packet defines ***/
/* data added after ICMP header for our nefarious purposes */
typedef struct ping_data
{
int ping_count; /* counts up to -c count or 1 */
struct timeval ping_ts; /* time sent */
} PING_DATA;
#define MIN_PING_DATA sizeof( PING_DATA )
#define MIN_PING_DATA 0
#define MAX_IP_PACKET 65536 /* (theoretical) max IP packet size */
#define SIZE_IP_HDR 20
#ifndef IPV6
@@ -202,13 +192,6 @@ char *icmp_unreach_str[16] =
};
#define ICMP_UNREACH_MAXTYPE 15
#ifndef IPV6
#define FPING_SOCKADDR struct sockaddr_in
#define FPING_ICMPHDR struct icmp
#else
#define FPING_SOCKADDR struct sockaddr_in6
#define FPING_ICMPHDR struct icmp6_hdr
#endif
/* entry used to keep track of each host we are pinging */
@@ -234,10 +217,12 @@ typedef struct host_entry
unsigned char waiting; /* waiting for response */
struct timeval last_send_time; /* time of last packet sent */
int num_sent; /* number of ping packets sent */
int num_recv; /* number of pings received */
int num_recv; /* number of pings received (duplicates ignored) */
int num_recv_total; /* number of pings received, including duplicates */
int max_reply; /* longest response time */
int min_reply; /* shortest response time */
int total_time; /* sum of response times */
/* _i -> splits (reset on every report interval) */
int num_sent_i; /* number of ping packets sent */
int num_recv_i; /* number of pings received */
int max_reply_i; /* longest response time */
@@ -286,13 +271,12 @@ struct in6_addr src_addr;
/* global stats */
long max_reply = 0;
long min_reply = 1000000;
long min_reply = 0;
int total_replies = 0;
double sum_replies = 0;
int max_hostname_len = 0;
int num_jobs = 0; /* number of hosts still to do */
int num_hosts; /* total number of hosts */
int max_seq_sent = 0; /* maximum sequence number sent so far */
int num_alive = 0, /* total number alive */
num_unreachable = 0, /* total number unreachable */
num_noaddress = 0; /* total number of addresses not found */
@@ -376,117 +360,19 @@ void print_warning(char *fmt, ...);
int main( int argc, char **argv )
{
int c, i, n;
#ifdef IPV6
int opton = 1;
#endif
struct protoent *proto;
char *buf;
uid_t uid;
int tos = 0;
#ifndef IPV6
struct sockaddr_in sa;
#else
struct sockaddr_in6 sa;
#endif
int tos = 0;
HOST_ENTRY *cursor;
prog = argv[0];
s = open_ping_socket();
/* confirm that ICMP is available on this machine */
#ifndef IPV6
if( ( proto = getprotobyname( "icmp" ) ) == NULL )
#else
if( ( proto = getprotobyname( "ipv6-icmp" ) ) == NULL )
#endif
crash_and_burn( "icmp: unknown protocol" );
/* create raw socket for ICMP calls (ping) */
#ifndef IPV6
s = socket( AF_INET, SOCK_RAW, proto->p_proto );
#else
s = socket( AF_INET6, SOCK_RAW, proto->p_proto );
#endif
if( s < 0 )
errno_crash_and_burn( "can't create raw socket (must run as root?)" );
#ifdef IPV6
/*
* let the kernel pass extension headers of incoming packets,
* for privileged socket options
*/
#ifdef IPV6_RECVHOPOPTS
if (setsockopt(s, IPPROTO_IPV6, IPV6_RECVHOPOPTS, &opton,
sizeof(opton)))
err(1, "setsockopt(IPV6_RECVHOPOPTS)");
#else /* old adv. API */
if (setsockopt(s, IPPROTO_IPV6, IPV6_HOPOPTS, &opton,
sizeof(opton)))
err(1, "setsockopt(IPV6_HOPOPTS)");
#endif
#ifdef IPV6_RECVDSTOPTS
if (setsockopt(s, IPPROTO_IPV6, IPV6_RECVDSTOPTS, &opton,
sizeof(opton)))
err(1, "setsockopt(IPV6_RECVDSTOPTS)");
#else /* old adv. API */
if (setsockopt(s, IPPROTO_IPV6, IPV6_DSTOPTS, &opton,
sizeof(opton)))
err(1, "setsockopt(IPV6_DSTOPTS)");
#endif
#ifdef IPV6_RECVRTHDRDSTOPTS
if (setsockopt(s, IPPROTO_IPV6, IPV6_RECVRTHDRDSTOPTS, &opton,
sizeof(opton)))
err(1, "setsockopt(IPV6_RECVRTHDRDSTOPTS)");
#endif
#ifdef IPV6_RECVRTHDR
if (setsockopt(s, IPPROTO_IPV6, IPV6_RECVRTHDR, &opton,
sizeof(opton)))
err(1, "setsockopt(IPV6_RECVRTHDR)");
#else /* old adv. API */
if (setsockopt(s, IPPROTO_IPV6, IPV6_RTHDR, &opton,
sizeof(opton)))
err(1, "setsockopt(IPV6_RTHDR)");
#endif
#ifndef USE_SIN6_SCOPE_ID
#ifdef IPV6_RECVPKTINFO
if (setsockopt(s, IPPROTO_IPV6, IPV6_RECVPKTINFO, &opton,
sizeof(opton)))
err(1, "setsockopt(IPV6_RECVPKTINFO)");
#else /* old adv. API */
if (setsockopt(s, IPPROTO_IPV6, IPV6_PKTINFO, &opton,
sizeof(opton)))
err(1, "setsockopt(IPV6_PKTINFO)");
#endif
#endif /* USE_SIN6_SCOPE_ID */
#ifdef IPV6_RECVHOPLIMIT
if (setsockopt(s, IPPROTO_IPV6, IPV6_RECVHOPLIMIT, &opton,
sizeof(opton)))
err(1, "setsockopt(IPV6_RECVHOPLIMIT)");
#else /* old adv. API */
if (setsockopt(s, IPPROTO_IPV6, IPV6_HOPLIMIT, &opton,
sizeof(opton)))
err(1, "setsockopt(IPV6_HOPLIMIT)");
#endif
#ifdef IPV6_CHECKSUM
#ifndef SOL_RAW
#define SOL_RAW IPPROTO_IPV6
#endif
opton = 2;
if (setsockopt(s, SOL_RAW, IPV6_CHECKSUM, &opton,
sizeof(opton)))
err(1, "setsockopt(SOL_RAW,IPV6_CHECKSUM)");
#endif
#endif
if( ( uid = getuid() ) )
{
if(uid = getuid()) {
seteuid( getuid() );
}
}/* IF */
prog = argv[0];
ident = getpid() & 0xFFFF;
verbose_flag = 1;
backoff_flag = 1;
opterr = 1;
@@ -535,7 +421,9 @@ int main( int argc, char **argv )
break;
case 'b':
if( !( ping_data_size = ( unsigned int )atoi( optarg ) ) )
errno = 0;
ping_data_size = (unsigned int) strtol(optarg, (char **)NULL, 10);
if( errno )
usage(1);
break;
@@ -907,20 +795,8 @@ int main( int argc, char **argv )
if( !num_hosts )
exit( 2 );
/* set the source address */
if( src_addr_present )
{
memset( &sa, 0, sizeof( sa ) );
#ifndef IPV6
sa.sin_family = AF_INET;
sa.sin_addr = src_addr;
#else
sa.sin6_family = AF_INET6;
sa.sin6_addr = src_addr;
#endif
if ( bind( s, (struct sockaddr *)&sa, sizeof( sa ) ) < 0 )
errno_crash_and_burn( "cannot bind source address" );
if(src_addr_present) {
socket_set_src_addr(s, src_addr);
}
/* allocate array to hold outstanding ping requests */
@@ -973,6 +849,8 @@ int main( int argc, char **argv )
srandom( start_time.tv_usec );
#endif /* DEBUG || _DEBUG */
seqmap_init();
/* main loop */
main_loop();
@@ -1531,7 +1409,6 @@ int send_ping( int s, HOST_ENTRY *h )
{
char *buffer;
FPING_ICMPHDR *icp;
PING_DATA *pdp;
int n;
int myseq;
@@ -1543,8 +1420,7 @@ int send_ping( int s, HOST_ENTRY *h )
icp = ( FPING_ICMPHDR* )buffer;
gettimeofday( &h->last_send_time, &tz );
myseq = h->num_sent * num_hosts + h->i;
max_seq_sent = myseq > max_seq_sent ? myseq : max_seq_sent;
myseq = seqmap_add(h->i, h->num_sent, &h->last_send_time);
#ifndef IPV6
icp->icmp_type = ICMP_ECHO;
@@ -1553,10 +1429,6 @@ int send_ping( int s, HOST_ENTRY *h )
icp->icmp_seq = htons(myseq);
icp->icmp_id = htons(ident);
pdp = ( PING_DATA* )( buffer + SIZE_ICMP_HDR );
pdp->ping_ts = h->last_send_time;
pdp->ping_count = h->num_sent;
icp->icmp_cksum = in_cksum( ( unsigned short* )icp, ping_pkt_size );
#else
icp->icmp6_type = ICMP6_ECHO_REQUEST;
@@ -1564,10 +1436,6 @@ int send_ping( int s, HOST_ENTRY *h )
icp->icmp6_seq = htons(myseq);
icp->icmp6_id = htons(ident);
pdp = ( PING_DATA* )( buffer + SIZE_ICMP_HDR );
pdp->ping_ts = h->last_send_time;
pdp->ping_count = h->num_sent;
icp->icmp6_cksum = 0; // The IPv6 stack calculates the checksum for us...
#endif
#if defined(DEBUG) || defined(_DEBUG)
@@ -1578,7 +1446,6 @@ int send_ping( int s, HOST_ENTRY *h )
n = sendto( s, buffer, ping_pkt_size, 0,
( struct sockaddr* )&h->saddr, sizeof( FPING_SOCKADDR ) );
if( n < 0 || n != ping_pkt_size )
if(
(n < 0 || n != ping_pkt_size)
#if defined( EHOSTDOWN )
@@ -1597,7 +1464,9 @@ int send_ping( int s, HOST_ENTRY *h )
h->num_sent++;
h->num_sent_i++;
h->waiting++;
num_pingsent++;
last_send_time = h->last_send_time;
free( buffer );
return(1);
}
@@ -1649,7 +1518,8 @@ int wait_for_reply(long wait_time)
HOST_ENTRY *h;
long this_reply;
int this_count;
struct timeval sent_time;
struct timeval *sent_time;
SEQMAP_VALUE *seqmap_value;
result = recvfrom_wto( s, buffer, sizeof(buffer), &response_addr, wait_time );
@@ -1695,6 +1565,8 @@ int wait_for_reply(long wait_time)
return( 1 ); /* too short */
}/* IF */
gettimeofday( &current_time, &tz );
icp = ( FPING_ICMPHDR* )( buffer + hlen );
#ifndef IPV6
if( icp->icmp_type != ICMP_ECHOREPLY )
@@ -1715,54 +1587,51 @@ int wait_for_reply(long wait_time)
#endif
return 1; /* packet received, but not the one we are looking for! */
#ifndef IPV6
seqmap_value = seqmap_fetch(ntohs(icp->icmp_seq), &current_time);
#else
seqmap_value = seqmap_fetch(ntohs(icp->icmp6_seq), &current_time);
#endif
if(seqmap_value == NULL) {
return 1;
}
num_pingreceived++;
#ifndef IPV6
if( ntohs(icp->icmp_seq) > max_seq_sent )
#else
if( ntohs(icp->icmp6_seq) > max_seq_sent )
#endif
return( 1 ); /* packet received, don't worry about it anymore */
#ifndef IPV6
n = ntohs(icp->icmp_seq) % num_hosts;
#else
n = ntohs(icp->icmp6_seq) % num_hosts;
#endif
n = seqmap_value->host_nr;
h = table[n];
sent_time = &seqmap_value->ping_ts;
this_count = seqmap_value->ping_count;
this_reply = timeval_diff( &current_time, sent_time );
if( loop_flag || h->resp_times[this_count] == RESP_WAITING )
{
/* only for non-duplicates: */
h->waiting = 0;
h->timeout = timeout;
h->num_recv++;
h->num_recv_i++;
if( !max_reply || this_reply > max_reply ) max_reply = this_reply;
if( !min_reply || this_reply < min_reply ) min_reply = this_reply;
if( !h->max_reply || this_reply > h->max_reply ) h->max_reply = this_reply;
if( !h->min_reply || this_reply < h->min_reply ) h->min_reply = this_reply;
if( !h->max_reply_i || this_reply > h->max_reply_i ) h->max_reply_i = this_reply;
if( !h->min_reply_i || this_reply < h->min_reply_i ) h->min_reply_i = this_reply;
sum_replies += this_reply;
h->total_time += this_reply;
h->total_time_i += this_reply;
total_replies++;
}
/* received ping is cool, so process it */
gettimeofday( &current_time, &tz );
h->waiting = 0;
h->timeout = timeout;
h->num_recv++;
h->num_recv_i++;
#ifndef IPV6
memcpy( &sent_time, icp->icmp_data + offsetof( PING_DATA, ping_ts ), sizeof( sent_time ) );
memcpy( &this_count, icp->icmp_data, sizeof( this_count ) );
#else
memcpy( &sent_time, ((char *)icp->icmp6_data32)+4+offsetof(PING_DATA, ping_ts), sizeof( sent_time ) );
memcpy( &this_count, ((char *)icp->icmp6_data32)+4, sizeof( this_count ) );
#endif
h->num_recv_total++;
#if defined( DEBUG ) || defined( _DEBUG )
if( trace_flag )
printf( "received [%d] from %s\n", this_count, h->host );
#endif /* DEBUG || _DEBUG */
this_reply = timeval_diff( &current_time, &sent_time );
if( this_reply > max_reply ) max_reply = this_reply;
if( this_reply < min_reply ) min_reply = this_reply;
if( this_reply > h->max_reply ) h->max_reply = this_reply;
if( this_reply < h->min_reply ) h->min_reply = this_reply;
if( this_reply > h->max_reply_i ) h->max_reply_i = this_reply;
if( this_reply < h->min_reply_i ) h->min_reply_i = this_reply;
sum_replies += this_reply;
h->total_time += this_reply;
h->total_time_i += this_reply;
total_replies++;
/* note reply time in array, probably */
if( !loop_flag )
{
@@ -1852,7 +1721,7 @@ int wait_for_reply(long wait_time)
else
{
printf( "%d%% return)",
( h->num_recv * 100 ) / h->num_sent );
( h->num_recv_total * 100 ) / h->num_sent );
}/* ELSE */
#ifndef IPV6
@@ -1903,6 +1772,7 @@ int handle_random_icmp( FPING_ICMPHDR *p, int psize, FPING_SOCKADDR *addr )
FPING_ICMPHDR *sent_icmp;
unsigned char *c;
HOST_ENTRY *h;
SEQMAP_VALUE *seqmap_value;
#ifdef IPV6
char addr_ascii[INET6_ADDRSTRLEN];
inet_ntop(addr->sin6_family, &addr->sin6_addr, addr_ascii, INET6_ADDRSTRLEN);
@@ -1919,14 +1789,14 @@ int handle_random_icmp( FPING_ICMPHDR *p, int psize, FPING_SOCKADDR *addr )
sent_icmp = ( FPING_ICMPHDR* )( c + 28 );
#ifndef IPV6
sent_icmp = ( struct icmp* )( c + 28 );
seqmap_value = seqmap_fetch(ntohs(sent_icmp->icmp_seq), &current_time);
if( ( sent_icmp->icmp_type == ICMP_ECHO ) &&
( ntohs(sent_icmp->icmp_id) == ident ) &&
( ntohs(sent_icmp->icmp_seq) <= ( n_short )max_seq_sent ) )
( seqmap_value != NULL ) )
{
/* this is a response to a ping we sent */
h = table[ntohs(sent_icmp->icmp_seq) % num_hosts];
h = table[seqmap_value->host_nr];
if( p->icmp_code > ICMP_UNREACH_MAXTYPE )
{
@@ -1934,9 +1804,11 @@ int handle_random_icmp( FPING_ICMPHDR *p, int psize, FPING_SOCKADDR *addr )
inet_ntoa( addr->sin_addr ), h->host );
#else
seqmap_value = seqmap_fetch(ntohs(sent_icmp->icmp6_seq), &current_time);
if( ( sent_icmp->icmp6_type == ICMP_ECHO ) &&
( ntohs(sent_icmp->icmp6_id) == ident ) &&
( ntohs(sent_icmp->icmp6_seq) <= ( n_short )max_seq_sent ) )
( seqmap_value != NULL ) )
{
/* this is a response to a ping we sent */
h = table[ntohs(sent_icmp->icmp6_seq) % num_hosts];
@@ -1977,21 +1849,25 @@ int handle_random_icmp( FPING_ICMPHDR *p, int psize, FPING_SOCKADDR *addr )
case ICMP_PARAMPROB:
sent_icmp = ( FPING_ICMPHDR* )( c + 28 );
#ifndef IPV6
seqmap_value = seqmap_fetch(ntohs(sent_icmp->icmp_seq), &current_time);
if( ( sent_icmp->icmp_type == ICMP_ECHO ) &&
( ntohs(sent_icmp->icmp_id) == ident ) &&
( ntohs(sent_icmp->icmp_seq) <= ( n_short )max_seq_sent ) )
( seqmap_value != NULL ) )
{
/* this is a response to a ping we sent */
h = table[ntohs(sent_icmp->icmp_seq) % num_hosts];
h = table[seqmap_value->host_nr];
fprintf( stderr, "%s from %s for ICMP Echo sent to %s",
icmp_type_str[p->icmp_type], inet_ntoa( addr->sin_addr ), h->host );
if( inet_addr( h->host ) == -1 )
fprintf( stderr, " (%s)", inet_ntoa( h->saddr.sin_addr ) );
#else
seqmap_value = seqmap_fetch(ntohs(sent_icmp->icmp6_seq), &current_time);
if( ( sent_icmp->icmp6_type == ICMP_ECHO ) &&
( ntohs(sent_icmp->icmp6_id) == ident ) &&
( ntohs(sent_icmp->icmp6_seq) <= ( n_short )max_seq_sent ) )
( seqmap_value != NULL ) )
{
/* this is a response to a ping we sent */
h = table[ntohs(sent_icmp->icmp6_seq) % num_hosts];
@@ -2321,7 +2197,7 @@ void add_addr( char *name, char *host, FPING_SOCKADDR *ipaddr )
#endif
p->timeout = timeout;
p->running = 1;
p->min_reply = 10000000;
p->min_reply = 0;
if( strlen( p->host ) > max_hostname_len )
max_hostname_len = strlen( p->host );
+27
View File
@@ -0,0 +1,27 @@
#ifndef _FPING_H
#define _FPING_H
#define __APPLE_USE_RFC_3542 1
#include <sys/socket.h>
#include <netinet/in.h>
#ifndef IPV6
#define FPING_SOCKADDR struct sockaddr_in
#define FPING_INADDR struct in_addr
#define FPING_ICMPHDR struct icmp
#else
#define FPING_SOCKADDR struct sockaddr_in6
#define FPING_INADDR struct in6_addr
#define FPING_ICMPHDR struct icmp6_hdr
#endif
/* fping.c */
void crash_and_burn( char *message );
void errno_crash_and_burn( char *message );
/* socket.c */
int open_ping_socket();
void socket_set_src_addr(int s, FPING_INADDR src_addr);
#endif
+119
View File
@@ -0,0 +1,119 @@
/*
* fping: fast-ping, file-ping, favorite-ping, funky-ping
*
* Ping a list of target hosts in a round robin fashion.
* A better ping overall.
*
* fping website: http://www.fping.org
*
* Current maintainer of fping: David Schweikert
* Please send suggestions and patches to: david@schweikert.ch
*
*
* Original author: Roland Schemers <schemers@stanford.edu>
* IPv6 Support: Jeroen Massar <jeroen@unfix.org / jeroen@ipng.nl>
* Improved main loop: David Schweikert <david@schweikert.ch>
* Debian Merge, TOS settings: Tobi Oetiker <tobi@oetiker.ch>
* Bugfixes, byte order & senseful seq.-numbers: Stephan Fuhrmann (stephan.fuhrmann AT 1und1.de)
*
*
* Redistribution and use in source and binary forms are permitted
* provided that the above copyright notice and this paragraph are
* duplicated in all such forms and that any documentation,
* advertising materials, and other materials related to such
* distribution and use acknowledge that the software was developed
* by Stanford University. The name of the University may not be used
* to endorse or promote products derived from this software without
* specific prior written permission.
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*
* seqmap.c: implementation of a mapping between sequence number and (host, ping_nr)
* we can't just use ping_nr*host_count + host_nr, because it can
* overflow the 16 bit of the icmp header field. See also:
* https://github.com/schweikert/fping/issues/48
*/
#include "seqmap.h"
#include "options.h"
#include "limits.h"
#include <stdlib.h>
#include <stdio.h>
/* description of the data structure used:
*
* - we assume that no more than SEQMAP_MAXSEQ (65535) pings are sent in
* the timeout interval (SEQMAP_TIMEOUT_IN_S)
* - we store the values in an array with SEQMAP_MAXSEQ elements
* - current sequence number % SEQMAP_MAXSEQ gives the current index
* - when entering a value, we check that the current entry is expired
*/
static SEQMAP_VALUE *seqmap_map = NULL;
static unsigned int seqmap_next_id = 0;
static SEQMAP_VALUE *seqmap_free_list;
#define SEQMAP_TIMEOUT_IN_S 10
#define SEQMAP_UNASSIGNED_HOST_NR UINT_MAX
void seqmap_init()
{
unsigned int i;
seqmap_map = calloc(SEQMAP_MAXSEQ, sizeof(SEQMAP_VALUE));
if(seqmap_map == NULL) {
perror("malloc error (can't allocate seqmap_map)");
}
}
unsigned int seqmap_add(unsigned int host_nr, unsigned int ping_count, struct timeval *now)
{
unsigned int current_id;
SEQMAP_VALUE *next_value;
if(!seqmap_map) {
fprintf(stderr, "fping internal error: seqmap not initialized.\n");
exit(4);
}
/* check if expired (note that unused seqmap values will have fields set to
* 0, so will be seen as expired */
next_value = &seqmap_map[seqmap_next_id];
if(next_value->ping_ts.tv_sec != 0 && (now->tv_sec - next_value->ping_ts.tv_sec) < SEQMAP_TIMEOUT_IN_S) {
fprintf(stderr, "fping error: not enough sequence numbers available! (expire_timeout=%d, host_nr=%d, ping_count=%d, seqmap_next_id=%d)\n",
SEQMAP_TIMEOUT_IN_S, host_nr, ping_count, seqmap_next_id);
exit(4);
}
/* store the value */
next_value->host_nr = host_nr;
next_value->ping_count = ping_count;
next_value->ping_ts.tv_sec = now->tv_sec;
next_value->ping_ts.tv_usec = now->tv_usec;
/* increase next id */
current_id = seqmap_next_id;
seqmap_next_id = (seqmap_next_id + 1) % SEQMAP_MAXSEQ;
return current_id;
}
SEQMAP_VALUE *seqmap_fetch(unsigned int id, struct timeval *now)
{
SEQMAP_VALUE *value;
if(id > SEQMAP_MAXSEQ) {
return NULL;
}
value = &seqmap_map[id];
/* verify that value is not expired */
if(now->tv_sec - value->ping_ts.tv_sec >= SEQMAP_TIMEOUT_IN_S) {
return NULL;
}
return value;
}
+20
View File
@@ -0,0 +1,20 @@
#ifndef SEQMAP_H
#define SEQMAP_H
#include <sys/time.h>
typedef struct seqmap_value
{
unsigned int host_nr;
unsigned int ping_count;
struct timeval ping_ts;
} SEQMAP_VALUE;
#define SEQMAP_MAXSEQ 65535
void seqmap_init();
unsigned int seqmap_add(unsigned int host_nr, unsigned int ping_count, struct timeval *now);
SEQMAP_VALUE *seqmap_fetch(unsigned int id, struct timeval *now);
#endif
+57
View File
@@ -0,0 +1,57 @@
/*
* fping: fast-ping, file-ping, favorite-ping, funky-ping
*
* Ping a list of target hosts in a round robin fashion.
* A better ping overall.
*
* fping website: http://www.fping.org
*
* Current maintainer of fping: David Schweikert
* Please send suggestions and patches to: david@schweikert.ch
*
*
* Original author: Roland Schemers <schemers@stanford.edu>
* IPv6 Support: Jeroen Massar <jeroen@unfix.org / jeroen@ipng.nl>
* Improved main loop: David Schweikert <david@schweikert.ch>
* Debian Merge, TOS settings: Tobi Oetiker <tobi@oetiker.ch>
* Bugfixes, byte order & senseful seq.-numbers: Stephan Fuhrmann (stephan.fuhrmann AT 1und1.de)
*
*
* Redistribution and use in source and binary forms are permitted
* provided that the above copyright notice and this paragraph are
* duplicated in all such forms and that any documentation,
* advertising materials, and other materials related to such
* distribution and use acknowledge that the software was developed
* by Stanford University. The name of the University may not be used
* to endorse or promote products derived from this software without
* specific prior written permission.
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*/
#include "fping.h"
#include "config.h"
int open_ping_socket_ipv4();
int open_ping_socket_ipv6();
void socket_set_src_addr_ipv4(int s, FPING_INADDR src_addr);
void socket_set_src_addr_ipv6(int s, FPING_INADDR src_addr);
int open_ping_socket()
{
#ifndef IPV6
return open_ping_socket_ipv4();
#else
return open_ping_socket_ipv6();
#endif
}
void socket_set_src_addr(int s, FPING_INADDR src_addr)
{
#ifndef IPV6
socket_set_src_addr_ipv4(s, src_addr);
#else
socket_set_src_addr_ipv6(s, src_addr);
#endif
}
+73
View File
@@ -0,0 +1,73 @@
/*
* fping: fast-ping, file-ping, favorite-ping, funky-ping
*
* Ping a list of target hosts in a round robin fashion.
* A better ping overall.
*
* fping website: http://www.fping.org
*
* Current maintainer of fping: David Schweikert
* Please send suggestions and patches to: david@schweikert.ch
*
*
* Original author: Roland Schemers <schemers@stanford.edu>
* IPv6 Support: Jeroen Massar <jeroen@unfix.org / jeroen@ipng.nl>
* Improved main loop: David Schweikert <david@schweikert.ch>
* Debian Merge, TOS settings: Tobi Oetiker <tobi@oetiker.ch>
* Bugfixes, byte order & senseful seq.-numbers: Stephan Fuhrmann (stephan.fuhrmann AT 1und1.de)
*
*
* Redistribution and use in source and binary forms are permitted
* provided that the above copyright notice and this paragraph are
* duplicated in all such forms and that any documentation,
* advertising materials, and other materials related to such
* distribution and use acknowledge that the software was developed
* by Stanford University. The name of the University may not be used
* to endorse or promote products derived from this software without
* specific prior written permission.
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*/
#include "fping.h"
#include "config.h"
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <stdio.h>
#include <string.h>
int open_ping_socket_ipv4()
{
struct protoent *proto;
int s;
/* confirm that ICMP is available on this machine */
if( ( proto = getprotobyname( "icmp" ) ) == NULL )
crash_and_burn( "icmp: unknown protocol" );
/* create raw socket for ICMP calls (ping) */
s = socket( AF_INET, SOCK_RAW, proto->p_proto );
if( s < 0 ) {
/* try non-privileged icmp (works on Mac OSX without privileges, for example) */
s = socket( AF_INET, SOCK_DGRAM, proto->p_proto );
if( s < 0 ) {
errno_crash_and_burn( "can't create socket (must run as root?)" );
}
}
return s;
}
void socket_set_src_addr_ipv4(int s, FPING_INADDR src_addr)
{
struct sockaddr_in sa;
memset( &sa, 0, sizeof( sa ) );
sa.sin_family = AF_INET;
sa.sin_addr = src_addr;
if ( bind( s, (struct sockaddr *)&sa, sizeof( sa ) ) < 0 )
errno_crash_and_burn( "cannot bind source address" );
}
+76
View File
@@ -0,0 +1,76 @@
/*
* fping: fast-ping, file-ping, favorite-ping, funky-ping
*
* Ping a list of target hosts in a round robin fashion.
* A better ping overall.
*
* fping website: http://www.fping.org
*
* Current maintainer of fping: David Schweikert
* Please send suggestions and patches to: david@schweikert.ch
*
*
* Original author: Roland Schemers <schemers@stanford.edu>
* IPv6 Support: Jeroen Massar <jeroen@unfix.org / jeroen@ipng.nl>
* Improved main loop: David Schweikert <david@schweikert.ch>
* Debian Merge, TOS settings: Tobi Oetiker <tobi@oetiker.ch>
* Bugfixes, byte order & senseful seq.-numbers: Stephan Fuhrmann (stephan.fuhrmann AT 1und1.de)
*
*
* Redistribution and use in source and binary forms are permitted
* provided that the above copyright notice and this paragraph are
* duplicated in all such forms and that any documentation,
* advertising materials, and other materials related to such
* distribution and use acknowledge that the software was developed
* by Stanford University. The name of the University may not be used
* to endorse or promote products derived from this software without
* specific prior written permission.
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*/
#include "fping.h"
#include "config.h"
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <stdio.h>
#include <string.h>
#include <netinet/icmp6.h>
int open_ping_socket_ipv6()
{
struct protoent *proto;
int opton = 1;
int s;
/* confirm that ICMP is available on this machine */
if( ( proto = getprotobyname( "ipv6-icmp" ) ) == NULL )
crash_and_burn( "icmp: unknown protocol" );
/* create raw socket for ICMP calls (ping) */
s = socket( AF_INET6, SOCK_RAW, proto->p_proto );
if( s < 0 ) {
/* try non-privileged icmp (works on Mac OSX without privileges, for example) */
s = socket( AF_INET6, SOCK_DGRAM, proto->p_proto );
if( s < 0 ) {
errno_crash_and_burn( "can't create raw socket (must run as root?)" );
}
}
return s;
}
void socket_set_src_addr_ipv6(int s, FPING_INADDR src_addr)
{
struct sockaddr_in6 sa;
memset( &sa, 0, sizeof( sa ) );
sa.sin6_family = AF_INET6;
sa.sin6_addr = src_addr;
if ( bind( s, (struct sockaddr *)&sa, sizeof( sa ) ) < 0 )
errno_crash_and_burn( "cannot bind source address" );
}