sync with develop

pull/89/merge
David Schweikert 8 years ago
parent c5612265ae
commit 9787dd0136

@ -1,18 +1,28 @@
Unreleased
* INCOMPATIBILITY WARNING:
fping and fping6 are now unified into one binary. This means that for
example doing 'fping www.google.com' is going to ping the IPv6 IP of
www.google.com on IPv6-enabled hosts. If you need exact compatibility with
old versions, you can:
- compile fping with --disable-ipv6 (or use a wrapper, and call 'fping -4')
- compile fping with --enable-ipv6 and rename it to fping6 (same as 'fping -6')
fping and fping6 are now unified into one binary. This means that, for
example, doing 'fping www.google.com' is going to ping the IPv6 IP of
www.google.com on IPv6-enabled hosts.
If you need exact compatibility with old versions, you can configure,
compile, and install fping twice: once for ipv4 and once for ipv6:
- ./configure --disable-ipv6; make clean install
- ./configure --disable-ipv4 --program-suffix=6; make clean install
Or, alternatively, you could write two wrappers 'fping' and 'fping6',
that set respectively the options '-4' and '-6' when calling the original
fping binary.
* Version 4.0
* (feature) Unified 'fping' and 'fping6' into one binary (#80)
* (feature) --enable-ipv6 is now default
* (feature) New option '-4' to force IPv4
* (feature) New option '-6' to force IPv6
2017-02-09 David Schweikert <david@schweikert.ch>
* Version 3.16
* (feature) Support kernel-timestamping of received packets (#46)
* (feature) Simplify restrictions: only -i >= 1 and -p >= 10 are enforced now
* (feature) --enable-ipv6 is now default (you can use --disable-ipv6 to disable IPv6 support)
* (bugfix) Fix option -m to return all IPs of a hostname
* (bugfix) Fix option -H (ttl) for IPv6
* (bugfix) Fix option -M (don't fragment) for IPv6

@ -1,5 +0,0 @@
- implement -4
- implement -6
- test -4
- test -6
- fix -m

@ -10,9 +10,9 @@ set -e
# exit 0
#fi
# do this only for the master branch
if [ "$TRAVIS_BRANCH" != "master" ]; then
echo "skipped upload branch $TRAVIS_BRANCH isn't master"
# do this only for the master and version3 branch
if [ "$TRAVIS_BRANCH" != "master" -a "$TRAVIS_BRANCH" != "version3" ]; then
echo "skipped upload branch $TRAVIS_BRANCH isn't master/version3"
exit 0
fi

@ -31,7 +31,7 @@ $cmd->stderr_is_eq("");
my $cmd = Test::Command->new(cmd => "fping -4 ::1");
$cmd->exit_is_num(2);
$cmd->stdout_is_eq("");
$cmd->stderr_is_eq("::1: Address family for hostname not supported\n");
$cmd->stderr_like(qr{^::1:.*(not supported|not known)});
}
# fping -6
@ -49,7 +49,7 @@ SKIP: {
my $cmd = Test::Command->new(cmd => "fping -6 127.0.0.1");
$cmd->exit_is_num(2);
$cmd->stdout_is_eq("");
$cmd->stderr_is_eq("127.0.0.1: Address family for hostname not supported\n");
$cmd->stderr_like(qr{127\.0\.0\.1:.*(not supported|not known)});
}
# fping -a

@ -1,6 +1,7 @@
#!/usr/bin/perl -w
use Test::Command tests => 7;
use Test::More;
# -i n interval between sending ping packets (in millisec) (default 25)
# -l loop sending pings forever
@ -24,11 +25,14 @@ $cmd->stdout_like(qr{127\.0\.0\.1 : \[0\], 84 bytes, 0\.\d+ ms \(0.\d+ avg, 0% l
}
# fping -M
{
my $cmd = Test::Command->new(cmd => "fping -M 127.0.0.1");
$cmd->exit_is_num(0);
$cmd->stdout_is_eq("127.0.0.1 is alive\n");
$cmd->stderr_is_eq("");
SKIP: {
if($^O eq 'darwin') {
skip '-M option not supported on macOS', 3;
}
my $cmd = Test::Command->new(cmd => "fping -M 127.0.0.1");
$cmd->exit_is_num(0);
$cmd->stdout_is_eq("127.0.0.1 is alive\n");
$cmd->stderr_is_eq("");
}
# fping -m -> test-14-internet-hosts

@ -72,9 +72,12 @@ $cmd->stderr_is_eq("");
}
# fping -M
{
my $cmd = Test::Command->new(cmd => "fping -r 0 -b 10000 -M 8.8.8.8");
$cmd->exit_is_num(1);
$cmd->stdout_is_eq("8.8.8.8 is unreachable\n");
$cmd->stderr_is_eq("8.8.8.8: error while sending ping: Message too long\n");
SKIP: {
if($^O eq 'darwin') {
skip '-M option not supported on macOS', 3;
}
my $cmd = Test::Command->new(cmd => "fping -r 0 -b 10000 -M 8.8.8.8");
$cmd->exit_is_num(1);
$cmd->stdout_is_eq("8.8.8.8 is unreachable\n");
$cmd->stderr_is_eq("8.8.8.8: error while sending ping: Message too long\n");
}

@ -5,23 +5,36 @@ AC_PREREQ(2.59)
AC_INIT([fping],[3.16-rc2])
dnl make ipv4 and ipv6 options
dnl --disable-ipv4
AC_ARG_ENABLE([ipv4],
AS_HELP_STRING([--enable-ipv4], [(ignored for compatibility with previous versions)]))
AS_HELP_STRING([--disable-ipv4], [Disable support for pinging IPv4 hosts]))
AM_CONDITIONAL([IPV4], [test "x$enable_ipv4" != "xno"])
AM_COND_IF([IPV4], [AC_DEFINE([IPV4], [1], [IPv4 enabled])])
dnl --disable-ipv6
AC_ARG_ENABLE([ipv6],
AS_HELP_STRING([--enable-ipv6], [Build IPv6 capable fping6]),
[case "${enableval}" in
yes) ipv6=true ;;
no) ipv6=false ;;
*) AC_MSG_ERROR([bad value ${enableval} for --enable-ipv6]) ;;
esac],[ipv6=true])
AM_CONDITIONAL([IPV6], [test x$ipv6 = xtrue])
AS_HELP_STRING([--disable-ipv6], [Disable support for pinging IPv6 hosts]))
AS_IF([test "x$enable_ipv6" != "xno"], [
dnl Test if IPv6 is supported
AC_CHECK_HEADERS([netinet/icmp6.h], [have_ipv6="yes"], [], [[
#include <netinet/in.h>
]])
])
dnl Can't disable both IPv4 and IPv6
AS_IF([test "x$enable_ipv4" = "xno" -a "x$enable_ipv6" = "xno"], [
AC_MSG_ERROR([Need to enable IPv4 or IPv6. Can't disable both!)])
])
dnl IPv6 required, but not supported?
AS_IF([test \( "x$enable_ipv6" = "xyes" -o "x$enable_ipv4" = "xno" \) -a "x$have_ipv6" != "xyes" ], [
AC_MSG_ERROR([IPv6 not supported on this platform (netinet/icmp6.h header not found)])
])
AM_CONDITIONAL([IPV6], [test "x$have_ipv6" = "xyes"])
AM_COND_IF([IPV6], [AC_DEFINE([IPV6], [1], [IPv6 enabled])])
AC_ARG_ENABLE([timestamp],
AS_HELP_STRING([--disable-timestamp], [Disable kernel-based packet timestaping (SO_TIMESTAMP)]))
AS_IF([test "x$enable_timestamp" != "xno"], [
AC_CHECK_DECL([SO_TIMESTAMP], [AC_DEFINE(HAVE_SO_TIMESTAMP, [1], [set define])], [have_so_timestamp="no"], [#include <sys/types.h>
AC_CHECK_DECL([SO_TIMESTAMP], [AC_DEFINE(HAVE_SO_TIMESTAMP, [1], [SO_TIMESTAMP is defined])], [have_so_timestamp="no"], [#include <sys/types.h>
#include <sys/socket.h>])
])
dnl Test if --enable-timestamp is explicitely enabled and make an error if this platform doesn't support it
@ -70,7 +83,7 @@ AH_BOTTOM([
])
dnl Checks for header files.
AC_CHECK_HEADERS(unistd.h sys/file.h stdlib.h sys/select.h)
AC_CHECK_HEADERS([unistd.h sys/file.h stdlib.h sys/select.h])
AC_CONFIG_FILES([Makefile
doc/Makefile

@ -1,15 +1,6 @@
man_MANS =
man_MANS = fping.8
man_MANS += fping.8
if IPV6
man_MANS += fping6.8
endif
EXTRA_DIST = fping.8 fping6.8 fping.pod README.1992
EXTRA_DIST = fping.8 fping.pod README.1992
fping.8: fping.pod
pod2man -c "" -s 8 -r "fping" $< >$@
fping6.8: fping.pod
pod2man -c "" -s 8 -r "fping" -n fping6 $< >$@

@ -0,0 +1 @@
BasedOnStyle: WebKit

@ -8,6 +8,4 @@ fping_DEPENDENCIES = ../config.h
if IPV6
fping_SOURCES += socket6.c
fping_CFLAGS = $(AM_CFLAGS) -DIPV6
install-exec-hook:
ln -s fping$(EXEEXT) $(DESTDIR)$(sbindir)/fping6
endif

File diff suppressed because it is too large Load Diff

@ -36,11 +36,11 @@
*/
#include "seqmap.h"
#include "options.h"
#include "limits.h"
#include "options.h"
#include <stdlib.h>
#include <stdio.h>
#include <stdlib.h>
/* description of the data structure used:
*
@ -51,26 +51,26 @@
* - when entering a value, we check that the current entry is expired
*/
static SEQMAP_VALUE *seqmap_map = NULL;
static SEQMAP_VALUE* seqmap_map = NULL;
static unsigned int seqmap_next_id = 0;
#define SEQMAP_TIMEOUT_IN_S 10
#define SEQMAP_TIMEOUT_IN_S 10
#define SEQMAP_UNASSIGNED_HOST_NR UINT_MAX
void seqmap_init()
{
seqmap_map = calloc(SEQMAP_MAXSEQ, sizeof(SEQMAP_VALUE));
if(seqmap_map == NULL) {
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 seqmap_add(unsigned int host_nr, unsigned int ping_count, struct timeval* now)
{
unsigned int current_id;
SEQMAP_VALUE *next_value;
SEQMAP_VALUE* next_value;
if(!seqmap_map) {
if (!seqmap_map) {
fprintf(stderr, "fping internal error: seqmap not initialized.\n");
exit(4);
}
@ -78,7 +78,7 @@ unsigned int seqmap_add(unsigned int host_nr, unsigned int ping_count, struct ti
/* 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) {
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);
@ -97,18 +97,18 @@ unsigned int seqmap_add(unsigned int host_nr, unsigned int ping_count, struct ti
return current_id;
}
SEQMAP_VALUE *seqmap_fetch(unsigned int id, struct timeval *now)
SEQMAP_VALUE* seqmap_fetch(unsigned int id, struct timeval* now)
{
SEQMAP_VALUE *value;
SEQMAP_VALUE* value;
if(id > SEQMAP_MAXSEQ) {
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) {
if (now->tv_sec - value->ping_ts.tv_sec >= SEQMAP_TIMEOUT_IN_S) {
return NULL;
}

@ -30,39 +30,39 @@
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*/
#include "fping.h"
#include "config.h"
#include "fping.h"
#include <sys/socket.h>
#include <fcntl.h>
#include <netdb.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <netinet/in_systm.h>
#include <netinet/ip.h>
#include <netinet/ip_icmp.h>
#include <netdb.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <fcntl.h>
#include <string.h>
#include <sys/socket.h>
char *ping_buffer_ipv4 = 0;
char* ping_buffer_ipv4 = 0;
size_t ping_pkt_size_ipv4;
int open_ping_socket_ipv4()
{
struct protoent *proto;
struct protoent* proto;
int s;
/* confirm that ICMP is available on this machine */
if( ( proto = getprotobyname( "icmp" ) ) == NULL )
crash_and_burn( "icmp: unknown protocol" );
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 ) {
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?)" );
s = socket(AF_INET, SOCK_DGRAM, proto->p_proto);
if (s < 0) {
errno_crash_and_burn("can't create socket (must run as root?)");
}
}
@ -70,10 +70,10 @@ int open_ping_socket_ipv4()
{
int flags;
if((flags = fcntl(s, F_GETFL, 0)) < 0)
if ((flags = fcntl(s, F_GETFL, 0)) < 0)
perror("fcntl");
if(fcntl(s, F_SETFL, flags | O_NONBLOCK) < 0)
if (fcntl(s, F_SETFL, flags | O_NONBLOCK) < 0)
perror("fcntl");
}
@ -84,45 +84,45 @@ void init_ping_buffer_ipv4(size_t ping_data_size)
{
/* allocate ping buffer */
ping_pkt_size_ipv4 = ping_data_size + ICMP_MINLEN;
ping_buffer_ipv4 = (char *) calloc(1, ping_pkt_size_ipv4);
if(!ping_buffer_ipv4)
crash_and_burn( "can't malloc ping packet" );
ping_buffer_ipv4 = (char*)calloc(1, ping_pkt_size_ipv4);
if (!ping_buffer_ipv4)
crash_and_burn("can't malloc ping packet");
}
void socket_set_src_addr_ipv4(int s, struct in_addr *src_addr)
void socket_set_src_addr_ipv4(int s, struct in_addr* src_addr)
{
struct sockaddr_in sa;
memset( &sa, 0, sizeof( 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" );
if (bind(s, (struct sockaddr*)&sa, sizeof(sa)) < 0)
errno_crash_and_burn("cannot bind source address");
}
unsigned short calcsum(unsigned short *buffer, int length)
unsigned short calcsum(unsigned short* buffer, int length)
{
unsigned long sum;
/* initialize sum to zero and loop until length (in words) is 0 */
for (sum=0; length>1; length-=2) /* sizeof() returns number of bytes, we're interested in number of words */
sum += *buffer++; /* add 1 word of buffer to sum and proceed to the next */
for (sum = 0; length > 1; length -= 2) /* sizeof() returns number of bytes, we're interested in number of words */
sum += *buffer++; /* add 1 word of buffer to sum and proceed to the next */
/* we may have an extra byte */
if (length==1)
sum += (char)*buffer;
if (length == 1)
sum += (char)*buffer;
sum = (sum >> 16) + (sum & 0xFFFF); /* add high 16 to low 16 */
sum += (sum >> 16); /* add carry */
sum += (sum >> 16); /* add carry */
return ~sum;
}
int socket_sendto_ping_ipv4(int s, struct sockaddr *saddr, socklen_t saddr_len, uint16_t icmp_seq_nr, uint16_t icmp_id_nr)
int socket_sendto_ping_ipv4(int s, struct sockaddr* saddr, socklen_t saddr_len, uint16_t icmp_seq_nr, uint16_t icmp_id_nr)
{
struct icmp *icp;
struct icmp* icp;
int n;
icp = (struct icmp *) ping_buffer_ipv4;
icp = (struct icmp*)ping_buffer_ipv4;
icp->icmp_type = ICMP_ECHO;
icp->icmp_code = 0;
@ -131,12 +131,12 @@ int socket_sendto_ping_ipv4(int s, struct sockaddr *saddr, socklen_t saddr_len,
icp->icmp_id = htons(icmp_id_nr);
if (random_data_flag) {
for (n = ((char*)&icp->icmp_data - (char *)icp); n < ping_pkt_size_ipv4; ++n) {
for (n = ((char*)&icp->icmp_data - (char*)icp); n < ping_pkt_size_ipv4; ++n) {
ping_buffer_ipv4[n] = random() & 0xFF;
}
}
icp->icmp_cksum = calcsum((unsigned short *) icp, ping_pkt_size_ipv4);
icp->icmp_cksum = calcsum((unsigned short*)icp, ping_pkt_size_ipv4);
n = sendto(s, icp, ping_pkt_size_ipv4, 0, saddr, saddr_len);

@ -30,38 +30,38 @@
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*/
#include "fping.h"
#include "config.h"
#include "fping.h"
#include <sys/socket.h>
#include <netinet/in.h>
#include <fcntl.h>
#include <netdb.h>
#include <netinet/in.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <fcntl.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/icmp6.h>
char *ping_buffer_ipv6 = 0;
char* ping_buffer_ipv6 = 0;
size_t ping_pkt_size_ipv6;
int open_ping_socket_ipv6()
{
struct protoent *proto;
struct protoent* proto;
int s;
/* confirm that ICMP is available on this machine */
if( ( proto = getprotobyname( "ipv6-icmp" ) ) == NULL )
crash_and_burn( "icmp: unknown protocol" );
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 ) {
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?)" );
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?)");
}
}
@ -69,10 +69,10 @@ int open_ping_socket_ipv6()
{
int flags;
if((flags = fcntl(s, F_GETFL, 0)) < 0)
if ((flags = fcntl(s, F_GETFL, 0)) < 0)
perror("fcntl");
if(fcntl(s, F_SETFL, flags | O_NONBLOCK) < 0)
if (fcntl(s, F_SETFL, flags | O_NONBLOCK) < 0)
perror("fcntl");
}
@ -83,32 +83,32 @@ void init_ping_buffer_ipv6(size_t ping_data_size)
{
/* allocate ping buffer */
ping_pkt_size_ipv6 = ping_data_size + sizeof(struct icmp6_hdr);
ping_buffer_ipv6 = (char *) calloc(1, ping_pkt_size_ipv6);
if(!ping_buffer_ipv6)
crash_and_burn( "can't malloc ping packet" );
ping_buffer_ipv6 = (char*)calloc(1, ping_pkt_size_ipv6);
if (!ping_buffer_ipv6)
crash_and_burn("can't malloc ping packet");
}
void socket_set_src_addr_ipv6(int s, struct in6_addr *src_addr)
void socket_set_src_addr_ipv6(int s, struct in6_addr* src_addr)
{
struct sockaddr_in6 sa;
memset( &sa, 0, sizeof( 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" );
if (bind(s, (struct sockaddr*)&sa, sizeof(sa)) < 0)
errno_crash_and_burn("cannot bind source address");
}
int socket_sendto_ping_ipv6(int s, struct sockaddr *saddr, socklen_t saddr_len, uint16_t icmp_seq_nr, uint16_t icmp_id_nr)
int socket_sendto_ping_ipv6(int s, struct sockaddr* saddr, socklen_t saddr_len, uint16_t icmp_seq_nr, uint16_t icmp_id_nr)
{
struct icmp6_hdr *icp;
struct icmp6_hdr* icp;
int n;
icp = (struct icmp6_hdr *) ping_buffer_ipv6;
icp->icmp6_type = ICMP6_ECHO_REQUEST;
icp->icmp6_code = 0;
icp->icmp6_seq = htons(icmp_seq_nr);
icp->icmp6_id = htons(icmp_id_nr);
icp = (struct icmp6_hdr*)ping_buffer_ipv6;
icp->icmp6_type = ICMP6_ECHO_REQUEST;
icp->icmp6_code = 0;
icp->icmp6_seq = htons(icmp_seq_nr);
icp->icmp6_id = htons(icmp_id_nr);
if (random_data_flag) {
for (n = sizeof(struct icmp6_hdr); n < ping_pkt_size_ipv6; ++n) {
@ -116,7 +116,7 @@ int socket_sendto_ping_ipv6(int s, struct sockaddr *saddr, socklen_t saddr_len,
}
}
icp->icmp6_cksum = 0; /* The IPv6 stack calculates the checksum for us... */
icp->icmp6_cksum = 0; /* The IPv6 stack calculates the checksum for us... */
n = sendto(s, icp, ping_pkt_size_ipv6, 0, saddr, saddr_len);

Loading…
Cancel
Save