]> git.gsnw.org Git - fping.git/commitdiff
unification work
authorDavid Schweikert <david@schweikert.ch>
Tue, 31 Jan 2017 10:56:19 +0000 (11:56 +0100)
committerDavid Schweikert <david@schweikert.ch>
Tue, 31 Jan 2017 10:56:19 +0000 (11:56 +0100)
12 files changed:
ChangeLog
ci/test-01-basics.pl
ci/test-02-help.pl
ci/test-03-forbidden.pl
ci/test-04-options-a-b.pl
ci/test-06-options-f-h.pl
ci/test-14-ping-internet-hosts.pl
ci/test-issue-58.pl
configure.ac
doc/Makefile.am
doc/fping.pod
src/fping.c

index 22d313ae6511b9f2b98bfa44f0753ec94ba86d65..087ecbdf37efe5760531a51d301acf254f7724ea 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -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>
index c855a27fadc28a39bfb634a809e263c74b89edec..f18aa365ff9664a39d7c8334f80c576abef6ae84 100755 (executable)
@@ -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;
     }
index 2c70b53d451e787f4b5e83af361d8d17b7e1eabd..717a9b0f91a1cbc85184e7432a90c21e17550d7f 100755 (executable)
@@ -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)
index 800c2810894997abe9966bb2180bf8516952b247..d7ec1d3b2cf0a2beeb15870bbf3755a5ce7dca3c 100755 (executable)
@@ -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");
index 6619597e72355b58361b6b018d6a778b76e1e326..fa716b69cae2e46f4f25a6928a233d6c5443765e 100755 (executable)
@@ -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");
index b5eaac5b3a58a3c16ef9f7cfa9aa4503078f6f28..a0e299886b91e9fd7e82bebafed96b27d414a7f8 100755 (executable)
@@ -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
index 6e31053dcb19f6a12d535ed33f6ab0b7c33e28be..a71a8500d929913ec833a1c7f9d5a56fba42921f 100755 (executable)
@@ -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("");
index 46c70100eefbe971943b590cb863da25148ea168..db5161a19a8a098364268fc5ea1c9c0a5065a830 100755 (executable)
@@ -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");
index b6bbc4919476d7329833cd10383f362619da3c92..acb1ebcbecc8da9872258ac1cf189144f28dd465 100644 (file)
@@ -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)]))
index f4529555a055f7be333366f5f69d518cbc8bc32e..33e4cffb1326a9ad3c8de490e4d761d4f09259e4 100644 (file)
@@ -1,8 +1,6 @@
 man_MANS =
 
-if IPV4
 man_MANS += fping.8
-endif
 
 if IPV6
 man_MANS += fping6.8
index d38bec22489c960cb7fee9eb94b1e50e08f443c8..922ea932ca747b4df817a400f53025a9d72f03de 100644 (file)
@@ -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. 
index 011f02114ac43a4b2aa694cfb3d81175ca42fe45..df5d934cb5ee991bd2ed4ffb8baf841acc756cfa 100644 (file)
@@ -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);