unification work

pull/89/merge
David Schweikert 8 years ago
parent 12971e5409
commit 98269fb83e

@ -1,9 +1,15 @@
Unreleased
* (feature) Unified 'fping' and 'fping6' into one binary
* (feature) New option '-4' to force IPv4
* (feature) New option '-6' to force IPv6
* (feature) Support kernel-timestamping of received packets (#46)
* (feature) Simplify restrictions: only -i >= 1 and -p >= 10 are enforced now
* (bugfix) Fix option -H (ttl) for IPv6
* (bugfix) Fix option -M (don't fragment) for IPv6
* (bugfix) Fix option -O (ToS) for IPv6
* (bugfix) Fix compatibility issue with AIX (#69, @blentzgh)
* (bugfix) Fix -q not suppressing some ICMP error messages (#83)
* (bugfix) Fix -M expecting an argument, when it shouldn't
* (bugfix) Fix option -q not suppressing some ICMP error messages (#83)
* (bugfix) Fix option -M expecting an argument, when it shouldn't
* (bugfix) Fix minor issues found by Coverity Scan
2017-01-11 David Schweikert <david@schweikert.ch>

@ -13,7 +13,7 @@ use Test::More;
# ping ::1
SKIP: {
system("/sbin/ifconfig >&2");
#system("/sbin/ifconfig >&2");
if(system("/sbin/ifconfig | grep inet6") != 0) {
skip 'No IPv6 on this host', 3;
}

@ -11,6 +11,8 @@ $cmd1->exit_is_num(0);
$cmd1->stdout_is_eq(<<END);
Usage: fping [options] [targets...]
-4 only use IPv4 addresses
-6 only use IPv6 addresses
-a show targets that are alive
-A show targets by address
-b n amount of ping data to send, in bytes (default 56)

@ -24,7 +24,7 @@ END
my $cmd5 = Test::Command->new(cmd => "fping -H 300 127.0.0.1");
$cmd5->exit_is_num(1);
$cmd5->stdout_is_eq("");
$cmd5->stderr_is_eq("ttl 300 out of range\n");
$cmd5->stderr_is_eq("fping: ttl 300 out of range\n");
# fping -a -u
my $cmd6 = Test::Command->new(cmd => "fping -a -u 127.0.0.1");

@ -1,14 +1,57 @@
#!/usr/bin/perl -w
use Test::Command tests => 14;
use Test::Command tests => 29;
use Test::More;
use Time::HiRes qw(gettimeofday tv_interval);
# -4 only use IPv4 addresses
# -6 only use IPv6 addresses
# -a show targets that are alive
# -A show targets by address
# -b n amount of ping data to send, in bytes (default 56)
# -B f set exponential backoff factor to f
# fping -4 -6
{
my $cmd = Test::Command->new(cmd => "fping -4 -6 127.0.0.1");
$cmd->exit_is_num(1);
$cmd->stdout_is_eq("");
$cmd->stderr_is_eq("fping: can't specify both -4 and -6\n");
}
# fping -4
{
my $cmd = Test::Command->new(cmd => "fping -4 127.0.0.1");
$cmd->exit_is_num(0);
$cmd->stdout_is_eq("127.0.0.1 is alive\n");
$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");
}
# fping -6
SKIP: {
if(system("/sbin/ifconfig | grep inet6") != 0) {
skip 'No IPv6 on this host', 3;
}
my $cmd = Test::Command->new(cmd => "fping -6 ::1");
$cmd->exit_is_num(0);
$cmd->stdout_is_eq("::1 is alive\n");
$cmd->stderr_is_eq("");
}
{
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");
}
# fping -a
{
my $cmd = Test::Command->new(cmd => "fping -a 127.0.0.1 127.0.0.2");

@ -66,7 +66,7 @@ $cmd->stderr_is_eq("");
my $cmd = Test::Command->new(cmd => "fping -g 127.0.0.2/33");
$cmd->exit_is_num(1);
$cmd->stdout_is_eq("");
$cmd->stderr_is_eq("Error: netmask must be between 1 and 32 (is: 33)\n");
$cmd->stderr_is_eq("fping: netmask must be between 1 and 32 (is: 33)\n");
}
# fping -H

@ -33,9 +33,9 @@ $cmd->stdout_is_eq("google-public-dns-a.google.com (8.8.8.8) is alive\n");
$cmd->stderr_is_eq("");
}
# fping -A -n
# fping -4 -A -n
{
my $cmd = Test::Command->new(cmd => "fping -A -n google-public-dns-a.google.com");
my $cmd = Test::Command->new(cmd => "fping -4 -A -n google-public-dns-a.google.com");
$cmd->exit_is_num(0);
$cmd->stdout_is_eq("google-public-dns-a.google.com (8.8.8.8) is alive\n");
$cmd->stderr_is_eq("");
@ -46,7 +46,7 @@ SKIP: {
if(system("/sbin/ifconfig | grep inet6.*Scope:Global") != 0) {
skip 'No IPv6 on this host', 3;
}
my $cmd = Test::Command->new(cmd => "fping -n -A 2001:4860:4860::8888");
my $cmd = Test::Command->new(cmd => "fping -6 -n -A google-public-dns-a.google.com");
$cmd->exit_is_num(0);
$cmd->stdout_is_eq("google-public-dns-a.google.com (2001:4860:4860::8888) is alive\n");
$cmd->stderr_is_eq("");

@ -7,4 +7,4 @@ use Test::Command tests => 3;
my $cmd1 = Test::Command->new(cmd => "fping -a -g 2001:db8:120:4161::4/64");
$cmd1->exit_is_num(1);
$cmd1->stdout_is_eq("");
$cmd1->stderr_is_eq("Error: -g works only with IPv4 addresses\n");
$cmd1->stderr_is_eq("fping: -g works only with IPv4 addresses\n");

@ -7,26 +7,16 @@ AC_INIT([fping],[3.16-rc1])
dnl make ipv4 and ipv6 options
AC_ARG_ENABLE([ipv4],
[ --enable-ipv4 Build IPv4 capable fping],
[case "${enableval}" in
yes) ipv4=true ;;
no) ipv4=false ;;
*) AC_MSG_ERROR([bad value ${enableval} for --enable-ipv4]) ;;
esac],[ipv4=true])
AM_CONDITIONAL([IPV4], [test x$ipv4 = xtrue])
AS_HELP_STRING([--enable-ipv4], [(ignored for compatibility with previous versions)]))
AC_ARG_ENABLE([ipv6],
[ --enable-ipv6 Build IPv6 capable fping6],
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=false])
AM_CONDITIONAL([IPV6], [test x$ipv6 = xtrue])
if test x$ipv4 = xfalse && test x$ipv6 = xfalse; then
AC_MSG_ERROR([You must enable at least one of IPv4 and IPv6.])
fi
esac],[ipv6=true])
AM_CONDITIONAL([IPV6], [test x$ipv6 = xtrue])
AC_ARG_ENABLE([timestamp],
AS_HELP_STRING([--disable-timestamp], [Disable kernel-based packet timestaping (SO_TIMESTAMP)]))

@ -1,8 +1,6 @@
man_MANS =
if IPV4
man_MANS += fping.8
endif
if IPV6
man_MANS += fping6.8

@ -29,6 +29,15 @@ addresses instead of IPv4.
=over 5
=item B<-4>
Restrict name resolution and IPs to IPv4 addresses.
=item B<-6>
Restrict name resolution and IPs to IPv6 addresses. If the program name is
'fping6' (via a sym-link, for example), then '-6' is implicitly added.
=item B<-a>
Show systems that are alive.

@ -236,11 +236,9 @@ char *prog;
int ident; /* our pid */
int socket4 = 0;
#ifndef IPV6
int *allsocket[2] = { &socket4, NULL };
int hints_ai_family = AF_INET;
#else
int socket6 = 0;
int *allsocket[3] = { &socket4, &socket6, NULL };
int hints_ai_family = AF_UNSPEC;
#endif
@ -381,26 +379,40 @@ int main( int argc, char **argv )
switch( c )
{
case '4':
if(hints_ai_family != AF_UNSPEC) {
fprintf(stderr, "%s: can't specify both -4 and -6\n", prog);
exit(1);
}
hints_ai_family = AF_INET;
// FIXME: check that -4 and -6 not used together
break;
case '6':
#ifdef IPV6
if(hints_ai_family != AF_UNSPEC) {
fprintf(stderr, "%s: can't specify both -4 and -6\n", prog);
exit(1);
}
hints_ai_family = AF_INET6;
// FIXME: check that -4 and -6 not used together
#else
fprintf(stderr, "%s: IPv6 not supported by this binary\n", prog);
exit(1);
#endif
break;
case 'M':
#ifdef IP_MTU_DISCOVER
{
if(socket4) {
int val = IP_PMTUDISC_DO;
int **sp;
for(sp=&allsocket[0]; *sp; sp++) {
if (setsockopt(**sp, IPPROTO_IP, IP_MTU_DISCOVER, &val, sizeof(val))) {
perror("setsockopt IP_MTU_DISCOVER");
}
if (setsockopt(socket4, IPPROTO_IP, IP_MTU_DISCOVER, &val, sizeof(val))) {
perror("setsockopt IP_MTU_DISCOVER");
}
}
if(socket6) {
int val = IPV6_PMTUDISC_DO;
if (setsockopt(socket6, IPPROTO_IPV6, IPV6_MTU_DISCOVER, &val, sizeof(val))) {
perror("setsockopt IPV6_MTU_DISCOVER");
}
}
#else
fprintf(stderr, "-M option not supported on this platform\n");
fprintf(stderr, "%s, -M option not supported on this platform\n", prog);
exit(1);
#endif
break;
@ -564,14 +576,18 @@ int main( int argc, char **argv )
case 'I':
#ifdef SO_BINDTODEVICE
{
int **sp;
for(sp=&allsocket[0]; *sp; sp++) {
if (setsockopt(**sp, SOL_SOCKET, SO_BINDTODEVICE, optarg, strlen(optarg))) {
perror("binding to specific interface (SO_BINTODEVICE)");
}
if(socket4) {
if (setsockopt(socket4, SOL_SOCKET, SO_BINDTODEVICE, optarg, strlen(optarg))) {
perror("binding to specific interface (SO_BINTODEVICE)");
}
}
#ifdef IPV6
if(socket6) {
if (setsockopt(socket6, SOL_SOCKET, SO_BINDTODEVICE, optarg, strlen(optarg))) {
perror("binding to specific interface (SO_BINTODEVICE), IPV6");
}
}
#endif
#else
printf( "%s: cant bind to a particular net interface since SO_BINDTODEVICE is not supported on your os.\n", argv[0] );
exit(3);;
@ -584,12 +600,18 @@ int main( int argc, char **argv )
case 'O':
if (sscanf(optarg,"%i",&tos)){
int **sp;
for(sp=&allsocket[0]; *sp; sp++) {
if ( setsockopt(**sp, IPPROTO_IP, IP_TOS, &tos, sizeof(tos))) {
if(socket4) {
if ( setsockopt(socket4, IPPROTO_IP, IP_TOS, &tos, sizeof(tos))) {
perror("setting type of service octet IP_TOS");
}
}
#ifdef IPV6
if(socket6) {
if ( setsockopt(socket6, IPPROTO_IPV6, IPV6_TCLASS, &tos, sizeof(tos))) {
perror("setting type of service octet IPV6_TCLASS");
}
}
#endif
}
else {
usage(1);
@ -608,23 +630,28 @@ int main( int argc, char **argv )
}/* SWITCH */
}/* WHILE */
/* if we are called 'fping6', assume '-6' */
if(strstr(argv[0], "fping6")) {
hints_ai_family = AF_INET6;
}
/* validate various option settings */
if (ttl > 255) {
fprintf(stderr, "ttl %u out of range\n", ttl);
fprintf(stderr, "%s: ttl %u out of range\n", prog, ttl);
exit(1);
}
if( unreachable_flag && alive_flag )
{
fprintf( stderr, "%s: specify only one of a, u\n", argv[0] );
fprintf( stderr, "%s: specify only one of a, u\n", prog);
exit(1);
}/* IF */
if( count_flag && loop_flag )
{
fprintf( stderr, "%s: specify only one of c, l\n", argv[0] );
fprintf( stderr, "%s: specify only one of c, l\n", prog);
exit(1);
}/* IF */
@ -740,23 +767,35 @@ int main( int argc, char **argv )
/* set the TTL, if the -H option was set (otherwise ttl will be = 0) */
if(ttl > 0) {
int **sp;
for(sp=&allsocket[0]; *sp; sp++) {
if (setsockopt(**sp, IPPROTO_IP, IP_TTL, &ttl, sizeof(ttl))) {
if(socket4) {
if (setsockopt(socket4, IPPROTO_IP, IP_TTL, &ttl, sizeof(ttl))) {
perror("setting time to live");
}
}
#ifdef IPV6
if(socket6) {
if (setsockopt(socket6, IPPROTO_IPV6, IPV6_UNICAST_HOPS, &ttl, sizeof(ttl))) {
perror("setting time to live");
}
}
#endif
}
#if HAVE_SO_TIMESTAMP
{
int opt = 1;
int **sp;
for(sp=&allsocket[0]; *sp; sp++) {
if (setsockopt(**sp, SOL_SOCKET, SO_TIMESTAMP, &opt, sizeof(opt))) {
if(socket4) {
if (setsockopt(socket4, SOL_SOCKET, SO_TIMESTAMP, &opt, sizeof(opt))) {
perror("setting SO_TIMESTAMP option");
}
}
#ifdef IPV6
if(socket6) {
if (setsockopt(socket6, SOL_SOCKET, SO_TIMESTAMP, &opt, sizeof(opt))) {
perror("setting SO_TIMESTAMP option (IPv6)");
}
}
#endif
}
#endif
@ -937,18 +976,18 @@ void add_cidr(char *addr)
addr_hints.ai_flags = AI_NUMERICHOST;
ret = getaddrinfo(addr, NULL, &addr_hints, &addr_res);
if(ret) {
fprintf(stderr, "Error: can't parse address %s: %s\n", addr, gai_strerror(ret));
fprintf(stderr, "%s, can't parse address %s: %s\n", prog, addr, gai_strerror(ret));
exit(1);
}
if(addr_res->ai_family != AF_INET) {
fprintf(stderr, "Error: -g works only with IPv4 addresses\n");
fprintf(stderr, "%s: -g works only with IPv4 addresses\n", prog);
exit(1);
}
net_addr = ntohl(((struct sockaddr_in *) addr_res->ai_addr)->sin_addr.s_addr);
/* check mask */
if(mask < 1 || mask > 32) {
fprintf(stderr, "Error: netmask must be between 1 and 32 (is: %s)\n", mask_str);
fprintf(stderr, "%s: netmask must be between 1 and 32 (is: %s)\n", prog, mask_str);
exit(1);
}
@ -992,12 +1031,12 @@ void add_range(char *start, char *end)
addr_hints.ai_flags = AI_NUMERICHOST;
ret = getaddrinfo(start, NULL, &addr_hints, &addr_res);
if(ret) {
fprintf(stderr, "Error: can't parse address %s: %s\n", start, gai_strerror(ret));
fprintf(stderr, "%s: can't parse address %s: %s\n", prog, start, gai_strerror(ret));
exit(1);
}
if(addr_res->ai_family != AF_INET) {
freeaddrinfo(addr_res);
fprintf(stderr, "Error: -g works only with IPv4 addresses\n");
fprintf(stderr, "%s: -g works only with IPv4 addresses\n", prog);
exit(1);
}
start_long = ntohl(((struct sockaddr_in *) addr_res->ai_addr)->sin_addr.s_addr);
@ -1008,19 +1047,19 @@ void add_range(char *start, char *end)
addr_hints.ai_flags = AI_NUMERICHOST;
ret = getaddrinfo(end, NULL, &addr_hints, &addr_res);
if(ret) {
fprintf(stderr, "Error: can't parse address %s: %s\n", end, gai_strerror(ret));
fprintf(stderr, "%s: can't parse address %s: %s\n", prog, end, gai_strerror(ret));
exit(1);
}
if(addr_res->ai_family != AF_INET) {
freeaddrinfo(addr_res);
fprintf(stderr, "Error: -g works only with IPv4 addresses\n");
fprintf(stderr, "%s: -g works only with IPv4 addresses\n", prog);
exit(1);
}
end_long = ntohl(((struct sockaddr_in *) addr_res->ai_addr)->sin_addr.s_addr);
freeaddrinfo(addr_res);
if(end_long > start_long + MAX_GENERATE) {
fprintf(stderr, "Error: -g parameter generates too many addresses\n");
fprintf(stderr, "%s: -g parameter generates too many addresses\n", prog);
exit(1);
}
@ -2688,6 +2727,8 @@ void usage(int is_error)
FILE *out = is_error ? stderr : stdout;
fprintf(out, "\n" );
fprintf(out, "Usage: %s [options] [targets...]\n", prog );
fprintf(out, " -4 only use IPv4 addresses\n" );
fprintf(out, " -6 only use IPv6 addresses\n" );
fprintf(out, " -a show targets that are alive\n" );
fprintf(out, " -A show targets by address\n" );
fprintf(out, " -b n amount of ping data to send, in bytes (default %d)\n", DEFAULT_PING_DATA_SIZE);

Loading…
Cancel
Save