]> git.gsnw.org Git - fping.git/commitdiff
fping and fping6 unification, fixes #80
authorDavid Schweikert <david@schweikert.ch>
Thu, 9 Feb 2017 10:23:59 +0000 (11:23 +0100)
committerDavid Schweikert <david@schweikert.ch>
Thu, 9 Feb 2017 10:23:59 +0000 (11:23 +0100)
24 files changed:
ChangeLog
ci/build-2-install.sh
ci/prepare-linux.sh
ci/test-01-basics.pl
ci/test-02-help.pl
ci/test-03-forbidden.pl
ci/test-04-options-a-b.pl
ci/test-05-options-c-e.pl
ci/test-06-options-f-h.pl
ci/test-09-option-r-t.pl
ci/test-11-nopriv.pl
ci/test-13-unknown-host.pl
ci/test-14-ping-internet-hosts.pl
ci/test-issue-58.pl
configure.ac
doc/Makefile.am
doc/fping.pod
src/Makefile.am
src/fping.c
src/fping.h
src/socket.c [deleted file]
src/socket4.c
src/socket6.c
src/test-c89.sh

index 8809ff4488675b2172969b26e2a0c03763b39e93..aa657acd6077e3846a10549306596d4806c41c68 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,24 @@
+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 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)
index 2eb7ccce180a0c1e928146b407b71534bca81d06..247eaefb8d131d0c69245423e140a38e5162f13f 100755 (executable)
@@ -13,7 +13,6 @@ autoreconf -i
 make CFLAGS="-g -fprofile-arcs -ftest-coverage"
 ## setcap currently doesn't work anymore on travis-ci
 #sudo setcap cap_net_raw+ep src/fping
-#sudo setcap cap_net_raw+ep src/fping6
 ## setcap debugging:
 #pwd
 #df -k .
@@ -26,6 +25,4 @@ make CFLAGS="-g -fprofile-arcs -ftest-coverage"
 
 # use setuid, since setcap is not available
 sudo chown root src/fping
-sudo chown root src/fping6
 sudo chmod u+s  src/fping
-sudo chmod u+s  src/fping6
index 41504f191db8c4ef4bb1ed122f5391e437db3df5..275a56f536c286d51aa20459f13fd9b85b644f4f 100755 (executable)
@@ -1,7 +1,6 @@
 #!/bin/bash
 
 sudo setcap cap_net_raw+ep src/fping
-sudo setcap cap_net_raw+ep src/fping6
 
 if [[ ! $PATH =~ fping/src ]]; then
     echo "# WARNING: must set PATH:"
index 15fc5f816fdc50629c2dd58b1616287c0e6b1da2..f18aa365ff9664a39d7c8334f80c576abef6ae84 100755 (executable)
@@ -17,7 +17,7 @@ SKIP: {
     if(system("/sbin/ifconfig | grep inet6") != 0) {
         skip 'No IPv6 on this host', 3;
     }
-    my $cmd = Test::Command->new(cmd => "fping6 ::1");
+    my $cmd = Test::Command->new(cmd => "fping ::1");
     $cmd->exit_is_num(0);
     $cmd->stdout_is_eq("::1 is alive\n");
     $cmd->stderr_is_eq("");
index 83446ac5367cf363a510258ecbdec1b177e7f5c8..d3efe26f73e52f188d25f9bf5a6496632e31d948 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 9e16134e2e3f67fed2b33e98e08a42d6621815c2..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");
@@ -38,11 +38,11 @@ $cmd7->exit_is_num(1);
 $cmd7->stdout_is_eq("");
 $cmd7->stderr_is_eq("fping: specify only one of c, l\n");
 
-# fping -b 65489
-my $cmd8 = Test::Command->new(cmd => "fping -b 65489 127.0.0.1");
+# fping -b 65509
+my $cmd8 = Test::Command->new(cmd => "fping -b 65509 127.0.0.1");
 $cmd8->exit_is_num(1);
 $cmd8->stdout_is_eq("");
-$cmd8->stderr_is_eq("fping: data size 65489 not valid, must be lower than 65488\n");
+$cmd8->stderr_is_eq("fping: data size 65509 not valid, must be lower than 65488\n");
 
 # fping -B 0.9
 my $cmd9 = Test::Command->new(cmd => "fping -B 0.9 127.0.0.1");
index 22889315b77545d1bf98922052ec7bc9ed04d876..7958a3c3ef206de550c4eb23daa89b63bcc069cc 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_like(qr{^::1:.*(not supported|not known)});
+}
+
+# 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_like(qr{127\.0\.0\.1:.*(not supported|not known)});
+}
+
 # fping -a
 {
 my $cmd = Test::Command->new(cmd => "fping -a 127.0.0.1 127.0.0.2");
@@ -19,7 +62,7 @@ $cmd->stderr_is_eq("");
 
 # fping -A
 {
-my $cmd = Test::Command->new(cmd => "fping -A localhost");
+my $cmd = Test::Command->new(cmd => "fping -4 -A localhost");
 $cmd->exit_is_num(0);
 $cmd->stdout_is_eq("127.0.0.1 is alive\n");
 $cmd->stderr_is_eq("");
index ec84817a2efb3c692383a3a6e0d720b8e7ecdf04..b9f95000b57fe90603ae6688525bf7561c781a0e 100755 (executable)
@@ -9,7 +9,7 @@ use Test::Command tests => 12;
 
 # fping -c n
 {
-my $cmd = Test::Command->new(cmd => "fping -c 2 -p 100 localhost 127.0.0.1");
+my $cmd = Test::Command->new(cmd => "fping -4 -c 2 -p 100 localhost 127.0.0.1");
 $cmd->exit_is_num(0);
 $cmd->stdout_like(qr{localhost : \[0\], 84 bytes, 0\.\d+ ms \(0\.\d+ avg, 0% loss\)
 127\.0\.0\.1 : \[0\], 84 bytes, 0\.\d+ ms \(0.\d+ avg, 0% loss\)
@@ -24,7 +24,7 @@ $cmd->stderr_like(qr{localhost : xmt/rcv/%loss = 2/2/0%, min/avg/max = 0\.\d+/0\
 
 # fping -C n
 {
-my $cmd = Test::Command->new(cmd => "fping -C 2 -p 100 localhost 127.0.0.1");
+my $cmd = Test::Command->new(cmd => "fping -4 -C 2 -p 100 localhost 127.0.0.1");
 $cmd->exit_is_num(0);
 $cmd->stdout_like(qr{localhost : \[0\], 84 bytes, 0\.\d+ ms \(0\.\d+ avg, 0% loss\)
 127\.0\.0\.1 : \[0\], 84 bytes, 0\.\d+ ms \(0.\d+ avg, 0% loss\)
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 501f70e2325ec2bc37060cea47efd94183afb763..eae162dcab1e6af03fe167562a1c7b416f483835 100755 (executable)
@@ -22,7 +22,7 @@ SKIP: {
     if(system("/sbin/ifconfig | grep inet6") != 0) {
         skip 'No IPv6 on this host', 3;
     }
-    my $cmd = Test::Command->new(cmd => "fping6 -q -R -c3 -p100 ::1");
+    my $cmd = Test::Command->new(cmd => "fping -q -R -c3 -p100 ::1");
     $cmd->exit_is_num(0);
     $cmd->stdout_is_eq("");
     $cmd->stderr_like(qr{::1 : xmt/rcv/%loss = 3/3/0%.*});
@@ -84,12 +84,12 @@ $cmd->stdout_is_eq("127.0.0.1 is alive\n");
 $cmd->stderr_is_eq("");
 }
 
-# fping6 -S
+# fping -S
 SKIP: {
     if(system("/sbin/ifconfig | grep inet6") != 0) {
         skip 'No IPv6 on this host', 3;
     }
-    my $cmd = Test::Command->new(cmd => "fping6 -S ::1 ::1");
+    my $cmd = Test::Command->new(cmd => "fping -S ::1 ::1");
     $cmd->exit_is_num(0);
     $cmd->stdout_is_eq("::1 is alive\n");
     $cmd->stderr_is_eq("");
index bd2065fda27747d13a752b25fb2bcd8d3ba5a4c8..904b38294c0cdff01909d7fa5c1d55170a7de6f7 100755 (executable)
@@ -7,13 +7,11 @@ if( $^O eq 'darwin' ) {
     plan skip_all => 'Test irrelevant on MacOS';
     exit 0;
 }
-plan tests => 6;
+plan tests => 3;
 
 # run without privileges
 my $fping_bin = `which fping`; chomp $fping_bin;
-my $fping6_bin = `which fping6`; chomp $fping6_bin;
 system("cp $fping_bin /tmp/fping.copy; chmod +x /tmp/fping.copy");
-system("cp $fping6_bin /tmp/fping6.copy; chmod +x /tmp/fping6.copy");
 
 # fping
 {
@@ -22,11 +20,3 @@ $cmd->exit_is_num(4);
 $cmd->stdout_is_eq("");
 $cmd->stderr_like(qr{: can't create socket \(must run as root\?\) : .*\n});
 }
-
-# fping6
-{
-my $cmd = Test::Command->new(cmd => "/tmp/fping6.copy ::1");
-$cmd->exit_is_num(4);
-$cmd->stdout_is_eq("");
-$cmd->stderr_like(qr{: can't create raw socket \(must run as root\?\) : .*\n});
-}
index 8094c05e80fed591a4e45b5fdbb5414196b2325d..65c8312fb7846cfe9e857f179971be3591b729f7 100755 (executable)
@@ -1,6 +1,6 @@
 #!/usr/bin/perl -w
 
-use Test::Command tests => 6;
+use Test::Command tests => 3;
 
 # fping
 {
@@ -9,11 +9,3 @@ $cmd->exit_is_num(2);
 $cmd->stdout_is_eq("");
 $cmd->stderr_like(qr{^nosuchname\.example\.com: .*not (known|found)});
 }
-
-# fping6
-{
-my $cmd = Test::Command->new(cmd => "fping6 nosuchname.example.com");
-$cmd->exit_is_num(2);
-$cmd->stdout_is_eq("");
-$cmd->stderr_like(qr{^nosuchname\.example\.com: .*not (known|found)});
-}
index 4b395e1f3fc093809e795707e6e4127db9346468..ed6cfcd8649c67bae41537de0431d52cc0cc232e 100755 (executable)
@@ -9,7 +9,7 @@ if(!gethostbyname("www.google.com")) {
     exit 0;
 }
 
-plan tests => 18;
+plan tests => 21;
 
 my $re_num = qr{\d+(?:\.\d+)?};
 
@@ -33,35 +33,35 @@ $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("");
 }
 
-# fping6 -A -n
+# fping -A -n (IPv6)
 SKIP: {
     if(system("/sbin/ifconfig | grep inet6.*Scope:Global") != 0) {
         skip 'No IPv6 on this host', 3;
     }
-    my $cmd = Test::Command->new(cmd => "fping6 -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("");
 }
 
 # fping -m
-#SKIP: {
-#    if(system("/sbin/ifconfig | grep inet6.*Scope:Global") != 0) {
-#        skip 'No IPv6 on this host', 3;
-#    }
-#    my $cmd = Test::Command->new(cmd => "fping -A -m google-public-dns-a.google.com");
-#    $cmd->exit_is_num(0);
-#    $cmd->stdout_is_eq("2001:4860:4860::8888 is alive\n8.8.8.8 is alive\n");
-#    $cmd->stderr_is_eq("");
-#}
+SKIP: {
+    if(system("/sbin/ifconfig | grep inet6.*Scope:Global") != 0) {
+        skip 'No IPv6 on this host', 3;
+    }
+    my $cmd = Test::Command->new(cmd => "fping -A -m google-public-dns-a.google.com");
+    $cmd->exit_is_num(0);
+    $cmd->stdout_is_eq("2001:4860:4860::8888 is alive\n8.8.8.8 is alive\n");
+    $cmd->stderr_is_eq("");
+}
 
 # fping -n
 {
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 f2ea4f757badcbb3d1469d1794d5e77b83725d87..94a6db73abe7ce6f8721d7f5c1a85d5a035cb11b 100644 (file)
@@ -3,35 +3,38 @@ dnl Process this file with autoconf to produce a configure script.
 dnl Minimum Autoconf version required.
 AC_PREREQ(2.59)
 
-AC_INIT([fping],[3.16])
+AC_INIT([fping],[3.16-rc2])
 
-dnl make ipv4 and ipv6 options
+dnl --disable-ipv4
 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([--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],
-  [  --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
+  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
@@ -80,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
index f4529555a055f7be333366f5f69d518cbc8bc32e..450e1584addf61c300627a198ec16d96c1303edc 100644 (file)
@@ -1,17 +1,6 @@
-man_MANS =
+man_MANS = fping.8
 
-if IPV4
-man_MANS += fping.8
-endif
-
-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 $< >$@
index e4acfd29d06c99ba82b78b0881f9834a875596de..0b3917f2b7bbdc9e0276ddf18bce89b3285a780f 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 4dcfae892f25aa42431347c6e6df1bf97910283d..c518d34d4d153555c9eac20ba5a2f17691114be7 100644 (file)
@@ -1,18 +1,11 @@
 AM_CFLAGS = -Wall -Wextra -Wno-sign-compare
 
-prog =
+sbin_PROGRAMS = fping
+
+fping_SOURCES = fping.c seqmap.c socket4.c fping.h options.h seqmap.h
+fping_DEPENDENCIES = ../config.h
 
-if IPV4
-prog += fping
-endif
 if IPV6
-prog += fping6
+fping_SOURCES += socket6.c
+fping_CFLAGS = $(AM_CFLAGS) -DIPV6
 endif
-
-sbin_PROGRAMS = ${prog}
-
-fping_SOURCES = fping.c seqmap.c socket.c socket4.c fping.h options.h seqmap.h
-fping_DEPENDENCIES = ../config.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
index 0b958e9175c6c4cea50b71b96da8ecf806334f6e..f00a13eaae7d740fe5143b5d270cb8c85b04935a 100644 (file)
@@ -79,15 +79,9 @@ extern "C" {
 #include <ctype.h>
 #include <netdb.h>
 
-/* RS6000 hasn't getopt.h */
-#ifdef HAVE_GETOPT_H
 #include <getopt.h>
-#endif /* HAVE_GETOPT_H */
 
-/* RS6000 has sys/select.h */
-#ifdef HAVE_SYS_SELECT_H
 #include <sys/select.h>
-#endif /* HAVE_SYS_SELECT_H */
 
 /*** externals ***/
 
@@ -109,11 +103,7 @@ extern int h_errno;
 
 #define MAX_IP_PACKET 65536 /* (theoretical) max IP packet size */
 #define SIZE_IP_HDR 40
-#ifndef IPV6
-#define SIZE_ICMP_HDR ICMP_MINLEN /* from ip_icmp.h */
-#else
-#define SIZE_ICMP_HDR sizeof(FPING_ICMPHDR)
-#endif
+#define SIZE_ICMP_HDR 8 /* from ip_icmp.h */
 #define MAX_PING_DATA (MAX_IP_PACKET - SIZE_IP_HDR - SIZE_ICMP_HDR)
 
 #define MAX_GENERATE 100000 /* maximum number of hosts that -g can generate */
@@ -239,7 +229,14 @@ HOST_ENTRY* ev_last;
 
 char* prog;
 int ident; /* our pid */
-int s; /* socket */
+int socket4 = 0;
+#ifndef IPV6
+int hints_ai_family = AF_INET;
+#else
+int socket6 = 0;
+int hints_ai_family = AF_UNSPEC;
+#endif
+
 unsigned int debugging = 0;
 
 /* times get *100 because all times are calculated in 10 usec units, not ms */
@@ -253,11 +250,11 @@ unsigned int count = 1;
 unsigned int trials;
 unsigned int report_interval = 0;
 unsigned int ttl = 0;
-int src_addr_present = 0;
-#ifndef IPV6
+int src_addr_set = 0;
 struct in_addr src_addr;
-#else
-struct in6_addr src_addr;
+#ifdef IPV6
+int src_addr6_set = 0;
+struct in6_addr src_addr6;
 #endif
 
 /* global stats */
@@ -307,9 +304,8 @@ char* na_cat(char* name, struct in_addr ipaddr);
 void crash_and_burn(char* message);
 void errno_crash_and_burn(char* message);
 char* get_host_by_address(struct in_addr in);
-int recvfrom_wto(int s, char* buf, int len, struct sockaddr* saddr, socklen_t* saddr_len, long timo);
 void remove_job(HOST_ENTRY* h);
-int send_ping(int s, HOST_ENTRY* h);
+int send_ping(HOST_ENTRY* h);
 long timeval_diff(struct timeval* a, struct timeval* b);
 void timeval_add(struct timeval* a, long t_10u);
 void usage(int);
@@ -320,7 +316,6 @@ void print_netdata(void);
 void print_global_stats(void);
 void main_loop();
 void finish();
-int handle_random_icmp(FPING_ICMPHDR* p, struct sockaddr* addr, socklen_t addr_len);
 char* sprint_tm(int t);
 void ev_enqueue(HOST_ENTRY* h);
 HOST_ENTRY* ev_dequeue();
@@ -356,7 +351,10 @@ int main(int argc, char** argv)
 
     prog = argv[0];
 
-    s = open_ping_socket(ping_data_size);
+    socket4 = open_ping_socket_ipv4(ping_data_size);
+#ifdef IPV6
+    socket6 = open_ping_socket_ipv6(ping_data_size);
+#endif
 
     if ((uid = getuid())) {
         /* drop privileges */
@@ -371,25 +369,48 @@ int main(int argc, char** argv)
 
     /* get command line options */
 
-    while ((c = getopt(argc, argv, "ADMNRadeghlmnoqsuvzB:C:H:I:O:Q:S:T:b:c:f:i:p:r:t:")) != EOF) {
+    while ((c = getopt(argc, argv, "46ADMNRadeghlmnoqsuvzB:C:H:I:O:Q:S:T:b:c:f:i:p:r:t:")) != EOF) {
         switch (c) {
-        case 'M':
-#ifdef IP_MTU_DISCOVER
-        {
-            int val = IP_PMTUDISC_DO;
-#ifndef IPV6
-            if (setsockopt(s, IPPROTO_IP, IP_MTU_DISCOVER, &val, sizeof(val))) {
+        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;
+            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;
 #else
-            if (setsockopt(s, IPPROTO_IPV6, IPV6_MTU_DISCOVER, &val, sizeof(val))) {
+            fprintf(stderr, "%s: IPv6 not supported by this binary\n", prog);
+            exit(1);
 #endif
-                perror("setsockopt IP_MTU_DISCOVER");
+            break;
+        case 'M':
+#ifdef IP_MTU_DISCOVER
+            if (socket4) {
+                int val = IP_PMTUDISC_DO;
+                if (setsockopt(socket4, IPPROTO_IP, IP_MTU_DISCOVER, &val, sizeof(val))) {
+                    perror("setsockopt IP_MTU_DISCOVER");
+                }
             }
-        }
+#ifdef IPV6
+            if (socket6) {
+                int val = IPV6_PMTUDISC_DO;
+                if (setsockopt(socket6, IPPROTO_IPV6, IPV6_MTU_DISCOVER, &val, sizeof(val))) {
+                    perror("setsockopt IPV6_MTU_DISCOVER");
+                }
+            }
+#endif
 #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;
+            break;
 
         case 't':
             if (!(timeout = (unsigned int)atoi(optarg) * 100))
@@ -533,20 +554,33 @@ int main(int argc, char** argv)
             break;
 
         case 'S':
-#ifndef IPV6
-            if (!inet_pton(AF_INET, optarg, &src_addr))
-#else
-            if (!inet_pton(AF_INET6, optarg, &src_addr))
+            if (inet_pton(AF_INET, optarg, &src_addr)) {
+                src_addr_set = 1;
+                break;
+            }
+#ifdef IPV6
+            if (inet_pton(AF_INET6, optarg, &src_addr6)) {
+                src_addr6_set = 1;
+                break;
+            }
 #endif
-                usage(1);
-            src_addr_present = 1;
+            usage(1);
             break;
 
         case 'I':
 #ifdef SO_BINDTODEVICE
-            if (setsockopt(s, 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);
@@ -560,13 +594,18 @@ int main(int argc, char** argv)
 
         case 'O':
             if (sscanf(optarg, "%i", &tos)) {
-#ifndef IPV6
-                if (setsockopt(s, IPPROTO_IP, IP_TOS, &tos, sizeof(tos))) {
-#else
-                if (setsockopt(s, IPPROTO_IPV6, IPV6_TCLASS, &tos, sizeof(tos))) {
-#endif
-                    perror("setting type of service octet IP_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);
             }
@@ -580,24 +619,29 @@ int main(int argc, char** argv)
             fprintf(stderr, "see 'fping -h' for usage information\n");
             exit(1);
             break;
+
         }
     }
 
+    /* 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 (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);
     }
 
@@ -714,21 +758,35 @@ int main(int argc, char** argv)
 
     /* set the TTL, if the -H option was set (otherwise ttl will be = 0) */
     if (ttl > 0) {
-#ifndef IPV6
-        if (setsockopt(s, IPPROTO_IP, IP_TTL, &ttl, sizeof(ttl))) {
-#else
-        if (setsockopt(s, IPPROTO_IPV6, IPV6_UNICAST_HOPS, &ttl, sizeof(ttl))) {
-#endif
-            perror("setting time to live");
+        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;
-        if (setsockopt(s, SOL_SOCKET, SO_TIMESTAMP, &opt, sizeof(opt))) {
-            perror("setting SO_TIMESTAMP option");
+        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
 
@@ -798,9 +856,15 @@ int main(int argc, char** argv)
         exit(num_noaddress ? 2 : 1);
     }
 
-    if (src_addr_present) {
-        socket_set_src_addr(s, src_addr);
+#ifndef IPV6
+    if (src_addr_set) {
+        socket_set_src_addr_ipv4(socket4, &src_addr);
+    }
+#else
+    if (src_addr6_set) {
+        socket_set_src_addr_ipv6(socket6, &src_addr6);
     }
+#endif
 
     /* allocate array to hold outstanding ping requests */
 
@@ -832,7 +896,10 @@ int main(int argc, char** argv)
         cursor = cursor->ev_next;
     }
 
-    init_ping_buffer(ping_data_size);
+    init_ping_buffer_ipv4(ping_data_size);
+#ifdef IPV6
+    init_ping_buffer_ipv6(ping_data_size);
+#endif
 
     signal(SIGINT, finish);
 
@@ -888,18 +955,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);
     }
 
@@ -942,12 +1009,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);
@@ -958,15 +1025,15 @@ 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);
+    end_long = ntohl(((struct sockaddr_in*)addr_res->ai_addr)->sin_addr.s_addr);
     freeaddrinfo(addr_res);
 
     if (end_long > start_long + MAX_GENERATE) {
@@ -1005,8 +1072,7 @@ void main_loop()
                 h = ev_dequeue();
 
                 /* Send the ping */
-                /*printf("Sending ping after %d ms\n", lt/100); */
-                send_ping(s, h);
+                send_ping(h);
 
                 /* Check what needs to be done next */
                 if (!loop_flag && !count_flag) {
@@ -1055,7 +1121,7 @@ void main_loop()
             }
         }
 
-        wait_for_reply:
+    wait_for_reply:
 
         /* When can we expect the next event? */
         if (ev_first) {
@@ -1177,7 +1243,6 @@ void finish()
         exit(1);
 
     exit(0);
-
 }
 
 /************************************************************
@@ -1477,7 +1542,7 @@ void print_global_stats(void)
 
 ************************************************************/
 
-int send_ping(int s, HOST_ENTRY* h)
+int send_ping(HOST_ENTRY* h)
 {
     int n;
     int myseq;
@@ -1491,7 +1556,17 @@ int send_ping(int s, HOST_ENTRY* h)
         printf("sending [%d] to %s\n", h->num_sent, h->host);
 #endif /* DEBUG || _DEBUG */
 
-    n = socket_sendto_ping(s, (struct sockaddr*)&h->saddr, h->saddr_len, myseq, ident);
+    if (h->saddr.ss_family == AF_INET) {
+        n = socket_sendto_ping_ipv4(socket4, (struct sockaddr*)&h->saddr, h->saddr_len, myseq, ident);
+    }
+#ifdef IPV6
+    else if (h->saddr.ss_family == AF_INET6) {
+        n = socket_sendto_ping_ipv6(socket6, (struct sockaddr*)&h->saddr, h->saddr_len, myseq, ident);
+    }
+#endif
+    else {
+        return 0;
+    }
 
     if (
         (n < 0)
@@ -1528,17 +1603,27 @@ int send_ping(int s, HOST_ENTRY* h)
     return (ret);
 }
 
-int wait_on_socket(int socket, struct timeval* timeout)
+int socket_can_read(struct timeval* timeout)
 {
     int nfound;
     fd_set readset, writeset;
+    int socketmax;
+
+#ifndef IPV6
+    socketmax = socket4;
+#else
+    socketmax = socket4 > socket6 ? socket4 : socket6;
+#endif
 
 select_again:
     FD_ZERO(&readset);
     FD_ZERO(&writeset);
-    FD_SET(s, &readset);
+    FD_SET(socket4, &readset);
+#ifdef IPV6
+    FD_SET(socket6, &readset);
+#endif
 
-    nfound = select(socket + 1, &readset, &writeset, NULL, timeout);
+    nfound = select(socketmax + 1, &readset, &writeset, NULL, timeout);
     if (nfound < 0) {
         if (errno == EINTR) {
             /* interrupted system call: redo the select */
@@ -1548,14 +1633,21 @@ select_again:
         }
     }
 
-    if (nfound == 0)
-        return 0;
-    else
-        return 1;
+    if (nfound > 0) {
+        if (FD_ISSET(socket4, &readset)) {
+            return socket4;
+        }
+#ifdef IPV6
+        if (FD_ISSET(socket6, &readset)) {
+            return socket6;
+        }
+#endif
+    }
+
+    return 0;
 }
 
-int receive_reply(int socket,
-    struct timeval* timeout,
+int receive_packet(int socket,
     struct timeval* reply_timestamp,
     struct sockaddr* reply_src_addr,
     size_t reply_src_addr_len,
@@ -1563,63 +1655,252 @@ int receive_reply(int socket,
     size_t reply_buf_len)
 {
     int recv_len;
+    static unsigned char msg_control[40];
+    struct iovec msg_iov = {
+        reply_buf,
+        reply_buf_len
+    };
+    struct msghdr recv_msghdr = {
+        reply_src_addr,
+        reply_src_addr_len,
+        &msg_iov,
+        1,
+        &msg_control,
+        sizeof(msg_control),
+        0
+    };
+    int timestamp_set = 0;
+    struct cmsghdr* cmsg;
+
+    recv_len = recvmsg(socket, &recv_msghdr, 0);
+    if (recv_len <= 0) {
+        return 0;
+    }
 
-    /* Wait for input on the socket */
-    if (timeout && !wait_on_socket(socket, timeout)) {
-        return 0; /* timeout */
+#if HAVE_SO_TIMESTAMP
+    /* ancilliary data */
+    for (cmsg = CMSG_FIRSTHDR(&recv_msghdr);
+         cmsg != NULL;
+         cmsg = CMSG_NXTHDR(&recv_msghdr, cmsg)) {
+        if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_TIMESTAMP) {
+            memcpy(reply_timestamp, CMSG_DATA(cmsg), sizeof(*reply_timestamp));
+            timestamp_set = 1;
+        }
     }
+#endif
 
-    /* Receive data */
-    {
-        static unsigned char msg_control[40];
-        struct iovec msg_iov = {
-            reply_buf,
-            reply_buf_len
-        };
-        struct msghdr recv_msghdr = {
-            reply_src_addr,
-            reply_src_addr_len,
-            &msg_iov,
-            1,
-            &msg_control,
-            sizeof(msg_control),
-            0
-        };
-        int timestamp_set = 0;
-
-        recv_len = recvmsg(socket, &recv_msghdr, 0);
-        if (recv_len <= 0) {
+    if (!timestamp_set) {
+        gettimeofday(reply_timestamp, NULL);
+    }
+
+#if defined(DEBUG) || defined(_DEBUG)
+    if (randomly_lose_flag) {
+        if ((random() & 0x07) <= lose_factor)
+            return 0;
+    }
+#endif
+
+    return recv_len;
+}
+
+int decode_icmp_ipv4(
+    struct sockaddr* response_addr,
+    size_t response_addr_len,
+    char* reply_buf,
+    size_t reply_buf_len,
+    unsigned short* id,
+    unsigned short* seq)
+{
+    struct ip* ip = (struct ip*)reply_buf;
+    struct icmp* icp;
+    int hlen = 0;
+
+#if defined(__alpha__) && __STDC__ && !defined(__GLIBC__)
+    /* The alpha headers are decidedly broken.
+     * Using an ANSI compiler, it provides ip_vhl instead of ip_hl and
+     * ip_v.  So, to get ip_hl, we mask off the bottom four bits.
+     */
+    hlen = (ip->ip_vhl & 0x0F) << 2;
+#else
+    hlen = ip->ip_hl << 2;
+#endif
+
+    if (reply_buf_len < hlen + ICMP_MINLEN) {
+        /* too short */
+        if (verbose_flag) {
+            char buf[INET6_ADDRSTRLEN];
+            getnameinfo((struct sockaddr*)&response_addr, sizeof(response_addr), buf, INET6_ADDRSTRLEN, NULL, 0, NI_NUMERICHOST);
+            printf("received packet too short for ICMP (%d bytes from %s)\n", (int)reply_buf_len, buf);
+        }
+        return 0;
+    }
+
+    icp = (struct icmp*)(reply_buf + hlen);
+
+    if (icp->icmp_type != ICMP_ECHOREPLY) {
+        /* Handle other ICMP packets */
+        struct icmp* sent_icmp;
+        SEQMAP_VALUE* seqmap_value;
+        char addr_ascii[INET6_ADDRSTRLEN];
+        HOST_ENTRY* h;
+
+        /* reply icmp packet (hlen + ICMP_MINLEN) followed by "sent packet" (ip + icmp headers) */
+        if (reply_buf_len < hlen + ICMP_MINLEN + sizeof(struct ip) + ICMP_MINLEN) {
+            /* discard ICMP message if we can't tell that it was caused by us (i.e. if the "sent packet" is not included). */
             return 0;
         }
 
-#if HAVE_SO_TIMESTAMP
-        /* ancilliary data */
-        struct cmsghdr* cmsg;
-        for (cmsg = CMSG_FIRSTHDR(&recv_msghdr);
-             cmsg != NULL;
-             cmsg = CMSG_NXTHDR(&recv_msghdr, cmsg)) {
-            if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_TIMESTAMP) {
-                memcpy(reply_timestamp, CMSG_DATA(cmsg), sizeof(*reply_timestamp));
-                timestamp_set = 1;
+        sent_icmp = (struct icmp*)(reply_buf + hlen + ICMP_MINLEN + sizeof(struct ip));
+
+        if (sent_icmp->icmp_type != ICMP_ECHO || ntohs(sent_icmp->icmp_id) != ident) {
+            /* not caused by us */
+            return 0;
+        }
+
+        seqmap_value = seqmap_fetch(ntohs(sent_icmp->icmp_seq), &current_time);
+        if (seqmap_value == NULL) {
+            return 0;
+        }
+
+        getnameinfo(response_addr, response_addr_len, addr_ascii, INET6_ADDRSTRLEN, NULL, 0, NI_NUMERICHOST);
+
+        switch (icp->icmp_type) {
+        case ICMP_UNREACH:
+            h = table[seqmap_value->host_nr];
+            if (icp->icmp_code > ICMP_UNREACH_MAXTYPE) {
+                print_warning("ICMP Unreachable (Invalid Code) from %s for ICMP Echo sent to %s",
+                    addr_ascii, h->host);
+            } else {
+                print_warning("%s from %s for ICMP Echo sent to %s",
+                    icmp_unreach_str[icp->icmp_code], addr_ascii, h->host);
+            }
+
+            print_warning("\n");
+            num_othericmprcvd++;
+            break;
+
+        case ICMP_SOURCEQUENCH:
+        case ICMP_REDIRECT:
+        case ICMP_TIMXCEED:
+        case ICMP_PARAMPROB:
+            h = table[seqmap_value->host_nr];
+            if (icp->icmp_type <= ICMP_TYPE_STR_MAX) {
+                print_warning("%s from %s for ICMP Echo sent to %s",
+                    icmp_type_str[icp->icmp_type], addr_ascii, h->host);
+            } else {
+                print_warning("ICMP %d from %s for ICMP Echo sent to %s",
+                    icp->icmp_type, addr_ascii, h->host);
             }
+            print_warning("\n");
+            num_othericmprcvd++;
+            break;
         }
-#endif
 
-        if (!timestamp_set) {
-            gettimeofday(reply_timestamp, NULL);
+        return 0;
+    }
+
+    *id = ntohs(icp->icmp_id);
+    *seq = ntohs(icp->icmp_seq);
+
+    return 1;
+}
+
+#ifdef IPV6
+int decode_icmp_ipv6(
+    struct sockaddr* response_addr,
+    size_t response_addr_len,
+    char* reply_buf,
+    size_t reply_buf_len,
+    unsigned short* id,
+    unsigned short* seq)
+{
+    struct icmp6_hdr* icp;
+
+    if (reply_buf_len < sizeof(struct icmp6_hdr)) {
+        if (verbose_flag) {
+            char buf[INET6_ADDRSTRLEN];
+            getnameinfo((struct sockaddr*)&response_addr, sizeof(response_addr), buf, INET6_ADDRSTRLEN, NULL, 0, NI_NUMERICHOST);
+            printf("received packet too short for ICMP (%d bytes from %s)\n", (int)reply_buf_len, buf);
         }
+        return 0; /* too short */
     }
 
-    return recv_len;
+    icp = (struct icmp6_hdr*)reply_buf;
+
+    if (icp->icmp6_type != ICMP6_ECHO_REPLY) {
+        /* Handle other ICMP packets */
+        struct icmp6_hdr* sent_icmp;
+        SEQMAP_VALUE* seqmap_value;
+        char addr_ascii[INET6_ADDRSTRLEN];
+        HOST_ENTRY* h;
+
+        /* reply icmp packet (ICMP_MINLEN) followed by "sent packet" (ip + icmp headers) */
+        if (reply_buf_len < ICMP_MINLEN + sizeof(struct ip) + ICMP_MINLEN) {
+            /* discard ICMP message if we can't tell that it was caused by us (i.e. if the "sent packet" is not included). */
+            return 0;
+        }
+
+        sent_icmp = (struct icmp6_hdr*)(reply_buf + sizeof(struct icmp6_hdr) + sizeof(struct ip));
+
+        if (sent_icmp->icmp6_type != ICMP_ECHO || ntohs(sent_icmp->icmp6_id) != ident) {
+            /* not caused by us */
+            return 0;
+        }
+
+        seqmap_value = seqmap_fetch(ntohs(sent_icmp->icmp6_seq), &current_time);
+        if (seqmap_value == NULL) {
+            return 0;
+        }
+
+        getnameinfo(response_addr, response_addr_len, addr_ascii, INET6_ADDRSTRLEN, NULL, 0, NI_NUMERICHOST);
+
+        switch (icp->icmp6_type) {
+        case ICMP_UNREACH:
+            h = table[seqmap_value->host_nr];
+            if (icp->icmp6_code > ICMP_UNREACH_MAXTYPE) {
+                print_warning("ICMP Unreachable (Invalid Code) from %s for ICMP Echo sent to %s",
+                    addr_ascii, h->host);
+            } else {
+                print_warning("%s from %s for ICMP Echo sent to %s",
+                    icmp_unreach_str[icp->icmp6_code], addr_ascii, h->host);
+            }
+
+            print_warning("\n");
+            num_othericmprcvd++;
+            break;
+
+        case ICMP_SOURCEQUENCH:
+        case ICMP_REDIRECT:
+        case ICMP_TIMXCEED:
+        case ICMP_PARAMPROB:
+            h = table[seqmap_value->host_nr];
+            if (icp->icmp6_type <= ICMP_TYPE_STR_MAX) {
+                print_warning("%s from %s for ICMP Echo sent to %s",
+                    icmp_type_str[icp->icmp6_type], addr_ascii, h->host);
+            } else {
+                print_warning("ICMP %d from %s for ICMP Echo sent to %s",
+                    icp->icmp6_type, addr_ascii, h->host);
+            }
+            print_warning("\n");
+            num_othericmprcvd++;
+            break;
+        }
+
+        return 0;
+    }
+
+    *id = ntohs(icp->icmp6_id);
+    *seq = ntohs(icp->icmp6_seq);
+
+    return 1;
 }
+#endif
 
 int wait_for_reply(long wait_time)
 {
     int result;
     static char buffer[4096];
     struct sockaddr_storage response_addr;
-    int hlen = 0;
-    FPING_ICMPHDR* icp;
     int n, avg;
     HOST_ENTRY* h;
     long this_reply;
@@ -1627,95 +1908,78 @@ int wait_for_reply(long wait_time)
     struct timeval* sent_time;
     struct timeval recv_time;
     SEQMAP_VALUE* seqmap_value;
-#ifndef IPV6
-    struct ip* ip;
-#endif
-
-    /* receive packet */
-    {
-        struct timeval to;
-        if (wait_time) {
-            if (wait_time < 100000) {
-                to.tv_sec = 0;
-                to.tv_usec = wait_time * 10;
-            } else {
-                to.tv_sec = wait_time / 100000;
-                to.tv_usec = (wait_time % 100000) * 10;
-            }
-        }
-
-        result = receive_reply(s, /* socket */
-            wait_time ? &to : NULL, /* timeout */
-            &recv_time, /* reply_timestamp */
-            (struct sockaddr*)&response_addr, /* reply_src_addr */
-            sizeof(response_addr), /* reply_src_addr_len */
-            buffer, /* reply_buf */
-            sizeof(buffer) /* reply_buf_len */
-            );
+    unsigned short id;
+    unsigned short seq;
+    struct timeval to;
+    int s = 0;
 
-        if (result <= 0) {
-            return 0;
+    /* Wait for a socket to become ready */
+    if (wait_time) {
+        if (wait_time < 100000) {
+            to.tv_sec = 0;
+            to.tv_usec = wait_time * 10;
+        } else {
+            to.tv_sec = wait_time / 100000;
+            to.tv_usec = (wait_time % 100000) * 10;
         }
+    } else {
+        to.tv_sec = 0;
+        to.tv_usec = 0;
     }
-
-#if defined(DEBUG) || defined(_DEBUG)
-    if (randomly_lose_flag) {
-        if ((random() & 0x07) <= lose_factor)
-            return 0;
+    s = socket_can_read(&to);
+    if (s == 0) {
+        return 0; /* timeout */
     }
-#endif
 
-#ifndef IPV6
-    ip = (struct ip*)buffer;
-#if defined(__alpha__) && __STDC__ && !defined(__GLIBC__)
-    /* The alpha headers are decidedly broken.
-     * Using an ANSI compiler, it provides ip_vhl instead of ip_hl and
-     * ip_v.  So, to get ip_hl, we mask off the bottom four bits.
-     */
-    hlen = (ip->ip_vhl & 0x0F) << 2;
-#else
-    hlen = ip->ip_hl << 2;
-#endif /* defined(__alpha__) && __STDC__ */
-    if (result < hlen + ICMP_MINLEN)
-#else
-    if (result < sizeof(FPING_ICMPHDR))
-#endif
-    {
-        if (verbose_flag) {
-            char buf[INET6_ADDRSTRLEN];
-            getnameinfo((struct sockaddr*)&response_addr, sizeof(response_addr), buf, INET6_ADDRSTRLEN, NULL, 0, NI_NUMERICHOST);
-            printf("received packet too short for ICMP (%d bytes from %s)\n", result, buf);
-        }
-        return (1); /* too short */
+    /* Receive packet */
+    result = receive_packet(s, /* socket */
+        &recv_time, /* reply_timestamp */
+        (struct sockaddr*)&response_addr, /* reply_src_addr */
+        sizeof(response_addr), /* reply_src_addr_len */
+        buffer, /* reply_buf */
+        sizeof(buffer) /* reply_buf_len */
+        );
+
+    if (result <= 0) {
+        return 0;
     }
 
     gettimeofday(&current_time, &tz);
 
-    icp = (FPING_ICMPHDR*)(buffer + hlen);
-#ifndef IPV6
-    if (icp->icmp_type != ICMP_ECHOREPLY)
-#else
-    if (icp->icmp6_type != ICMP6_ECHO_REPLY)
+    /* Process ICMP packet and retrieve id/seq */
+    if (response_addr.ss_family == AF_INET) {
+        if (!decode_icmp_ipv4(
+                (struct sockaddr*)&response_addr,
+                sizeof(response_addr),
+                buffer,
+                sizeof(buffer),
+                &id,
+                &seq)) {
+            return 1;
+        }
+    }
+#ifdef IPV6
+    else if (response_addr.ss_family == AF_INET6) {
+        if (!decode_icmp_ipv6(
+                (struct sockaddr*)&response_addr,
+                sizeof(response_addr),
+                buffer,
+                sizeof(buffer),
+                &id,
+                &seq)) {
+            return 1;
+        }
+    }
 #endif
-    {
-        /* handle some problem */
-        if (handle_random_icmp(icp, (struct sockaddr*)&response_addr, sizeof(response_addr)))
-            num_othericmprcvd++;
+    else {
         return 1;
     }
 
-#ifndef IPV6
-    if (ntohs(icp->icmp_id) != ident)
-#else
-    if (ntohs(icp->icmp6_id) != ident)
-#endif
+    if (id != ident) {
         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
+    seqmap_value = seqmap_fetch(seq, &current_time);
     if (seqmap_value == NULL) {
         return 1;
     }
@@ -1855,107 +2119,6 @@ int wait_for_reply(long wait_time)
     return num_jobs;
 }
 
-/************************************************************
-
-  Function: handle_random_icmp
-
-************************************************************/
-
-int handle_random_icmp(FPING_ICMPHDR* p, struct sockaddr* addr, socklen_t addr_len)
-{
-    FPING_ICMPHDR* sent_icmp;
-    unsigned char* c;
-    HOST_ENTRY* h;
-    SEQMAP_VALUE* seqmap_value;
-    char addr_ascii[INET6_ADDRSTRLEN];
-    unsigned short icmp_type;
-    unsigned short icmp_code;
-    unsigned short sent_icmp_type;
-    unsigned short sent_icmp_seq;
-    unsigned short sent_icmp_id;
-
-    getnameinfo((struct sockaddr*)addr, addr_len, addr_ascii, INET6_ADDRSTRLEN, NULL, 0, NI_NUMERICHOST);
-
-    c = (unsigned char*)p;
-
-    sent_icmp = (FPING_ICMPHDR*)(c + 28);
-#ifndef IPV6
-    icmp_type = p->icmp_type;
-    icmp_code = p->icmp_code;
-    sent_icmp_type = sent_icmp->icmp_type;
-    sent_icmp_seq = sent_icmp->icmp_seq;
-    sent_icmp_id = sent_icmp->icmp_id;
-#else
-    icmp_type = p->icmp6_type;
-    icmp_code = p->icmp6_code;
-    sent_icmp_type = sent_icmp->icmp6_type;
-    sent_icmp_seq = sent_icmp->icmp6_seq;
-    sent_icmp_id = sent_icmp->icmp6_id;
-#endif
-
-    switch (icmp_type) {
-    case ICMP_UNREACH:
-        seqmap_value = seqmap_fetch(ntohs(sent_icmp_seq), &current_time);
-
-        if ((sent_icmp_type == ICMP_ECHO) && (ntohs(sent_icmp_id) == ident) && (seqmap_value != NULL)) {
-            /* this is a response to a ping we sent */
-            h = table[ntohs(sent_icmp_seq) % num_hosts];
-
-            if (icmp_code > ICMP_UNREACH_MAXTYPE) {
-                print_warning("ICMP Unreachable (Invalid Code) from %s for ICMP Echo sent to %s",
-                    addr_ascii, h->host);
-            } else {
-                print_warning("%s from %s for ICMP Echo sent to %s",
-                    icmp_unreach_str[icmp_code], addr_ascii, h->host);
-            }
-
-            if (inet_addr(h->host) == INADDR_NONE)
-                print_warning(" (%s)", addr_ascii);
-
-            print_warning("\n");
-        }
-        return 1;
-
-    case ICMP_SOURCEQUENCH:
-    case ICMP_REDIRECT:
-    case ICMP_TIMXCEED:
-    case ICMP_PARAMPROB:
-        seqmap_value = seqmap_fetch(ntohs(sent_icmp_seq), &current_time);
-
-        if ((sent_icmp_type == ICMP_ECHO) && (ntohs(sent_icmp_id) == ident) && (seqmap_value != NULL)) {
-            /* this is a response to a ping we sent */
-            h = table[ntohs(sent_icmp_seq) % num_hosts];
-            if (icmp_type <= ICMP_TYPE_STR_MAX) {
-                print_warning("%s from %s for ICMP Echo sent to %s",
-                    icmp_type_str[icmp_type], addr_ascii, h->host);
-            } else {
-                print_warning("ICMP %d from %s for ICMP Echo sent to %s",
-                    icmp_type, addr_ascii, h->host);
-            }
-
-            if (inet_addr(h->host) == INADDR_NONE)
-                print_warning(" (%s)", addr_ascii);
-
-            print_warning("\n");
-
-        }
-
-        return 2;
-
-    /* no way to tell whether any of these are sent due to our ping */
-    /* or not (shouldn't be, of course), so just discard            */
-    case ICMP_TSTAMP:
-    case ICMP_TSTAMPREPLY:
-    case ICMP_IREQ:
-    case ICMP_IREQREPLY:
-    case ICMP_MASKREQ:
-    case ICMP_MASKREPLY:
-    default:
-        return 0;
-
-    }
-}
-
 /************************************************************
 
   Function: add_name
@@ -1984,13 +2147,18 @@ void add_name(char* name)
     bzero(&hints, sizeof(struct addrinfo));
     hints.ai_flags = 0;
     hints.ai_socktype = SOCK_RAW;
-#ifndef IPV6
-    hints.ai_family = AF_INET;
-    hints.ai_protocol = IPPROTO_ICMP;
-#else
-    hints.ai_family = AF_INET6;
-    hints.ai_protocol = IPPROTO_ICMPV6;
+    hints.ai_family = hints_ai_family;
+    if (hints_ai_family == AF_INET) {
+        hints.ai_protocol = IPPROTO_ICMP;
+    }
+#ifdef IPV6
+    else if (hints_ai_family == AF_INET6) {
+        hints.ai_protocol = IPPROTO_ICMPV6;
+    }
 #endif
+    else {
+        hints.ai_protocol = 0;
+    }
     ret_ga = getaddrinfo(name, NULL, &hints, &res0);
     if (ret_ga) {
         if (!quiet_flag)
@@ -2107,7 +2275,6 @@ void add_addr(char* name, char* host, struct sockaddr* ipaddr, socklen_t ipaddr_
             i[n] = RESP_UNUSED;
 
         p->resp_times = i;
-
     }
 
 #if defined(DEBUG) || defined(_DEBUG)
@@ -2121,7 +2288,6 @@ void add_addr(char* name, char* host, struct sockaddr* ipaddr, socklen_t ipaddr_
             i[n] = RESP_UNUSED;
 
         p->sent_times = i;
-
     }
 #endif /* DEBUG || _DEBUG */
 
@@ -2301,56 +2467,6 @@ char* sprint_tm(int t)
     return (buf);
 }
 
-/************************************************************
-  Function: recvfrom_wto
-*************************************************************
-  Description:
-
-  receive with timeout
-  returns length of data read or -1 if timeout
-  crash_and_burn on any other errrors
-************************************************************/
-
-int recvfrom_wto(int s, char* buf, int len, struct sockaddr* saddr, socklen_t* saddr_len, long timo)
-{
-    int nfound, n;
-    struct timeval to;
-    fd_set readset, writeset;
-
-select_again:
-    if (timo < 100000) {
-        to.tv_sec = 0;
-        to.tv_usec = timo * 10;
-    } else {
-        to.tv_sec = timo / 100000;
-        to.tv_usec = (timo % 100000) * 10;
-    }
-
-    FD_ZERO(&readset);
-    FD_ZERO(&writeset);
-    FD_SET(s, &readset);
-
-    nfound = select(s + 1, &readset, &writeset, NULL, &to);
-    if (nfound < 0) {
-        if (errno == EINTR) {
-            /* interrupted system call: redo the select */
-            goto select_again;
-        } else {
-            errno_crash_and_burn("select");
-        }
-    }
-
-    if (nfound == 0)
-        return -1; /* timeout */
-
-    /* recvfrom(int socket, void *restrict buffer, size_t length, int flags, struct sockaddr *restrict address, socklen_t *restrict address_len); */
-    n = recvfrom(s, buf, len, 0, saddr, saddr_len);
-    if (n < 0)
-        errno_crash_and_burn("recvfrom");
-
-    return n;
-}
-
 /************************************************************
 
   Function: addr_cmp
@@ -2495,6 +2611,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);
index 20661737c4141bfaa24ae997384d7b8863ee3e5b..44be99959910122c5f4d355adb7f4c130d207786 100644 (file)
@@ -7,14 +7,6 @@
 #include <sys/types.h>
 #include <netinet/in.h>
 
-#ifndef IPV6
-#define FPING_INADDR   struct in_addr
-#define FPING_ICMPHDR  struct icmp
-#else
-#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 );
@@ -22,9 +14,15 @@ int in_cksum( unsigned short *p, int n );
 int random_data_flag;
 
 /* socket.c */
-int  open_ping_socket();
-void init_ping_buffer(size_t ping_data_size);
-void socket_set_src_addr(int s, FPING_INADDR src_addr);
-int  socket_sendto_ping(int s, struct sockaddr *saddr, socklen_t saddr_len, uint16_t icmp_seq, uint16_t icmp_id);
+int  open_ping_socket_ipv4();
+void init_ping_buffer_ipv4(size_t ping_data_size);
+void socket_set_src_addr_ipv4(int s, struct in_addr *src_addr);
+int  socket_sendto_ping_ipv4(int s, struct sockaddr *saddr, socklen_t saddr_len, uint16_t icmp_seq, uint16_t icmp_id);
+#ifdef IPV6
+int  open_ping_socket_ipv6();
+void init_ping_buffer_ipv6(size_t ping_data_size);
+void socket_set_src_addr_ipv6(int s, struct in6_addr *src_addr);
+int  socket_sendto_ping_ipv6(int s, struct sockaddr *saddr, socklen_t saddr_len, uint16_t icmp_seq, uint16_t icmp_id);
+#endif
 
 #endif
diff --git a/src/socket.c b/src/socket.c
deleted file mode 100644 (file)
index 1d9d542..0000000
+++ /dev/null
@@ -1,79 +0,0 @@
-/* 
- * 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 "config.h"
-#include "fping.h"
-
-int open_ping_socket_ipv4();
-int open_ping_socket_ipv6();
-void init_ping_buffer_ipv4(size_t ping_data_size);
-void init_ping_buffer_ipv6(size_t ping_data_size);
-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 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_ipv6(int s, struct sockaddr* saddr, socklen_t saddr_len, uint16_t icmp_seq_nr, uint16_t icmp_id_nr);
-
-int open_ping_socket()
-{
-#ifndef IPV6
-    return open_ping_socket_ipv4();
-#else
-    return open_ping_socket_ipv6();
-#endif
-}
-
-void init_ping_buffer(size_t ping_data_size)
-{
-#ifndef IPV6
-    return init_ping_buffer_ipv4(ping_data_size);
-#else
-    return init_ping_buffer_ipv6(ping_data_size);
-#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
-}
-
-int socket_sendto_ping(int s, struct sockaddr* saddr, socklen_t saddr_len, uint16_t icmp_seq_nr, uint16_t icmp_id_nr)
-{
-#ifndef IPV6
-    return socket_sendto_ping_ipv4(s, saddr, saddr_len, icmp_seq_nr, icmp_id_nr);
-#else
-    return socket_sendto_ping_ipv6(s, saddr, saddr_len, icmp_seq_nr, icmp_id_nr);
-#endif
-}
index 28cfda4f081187cb6d96f9465fbbae1196ac353c..d6130596983b983996bc805eba18ef0f85b0e3ff 100644 (file)
@@ -44,8 +44,8 @@
 #include <string.h>
 #include <sys/socket.h>
 
-char* ping_buffer = 0;
-size_t ping_pkt_size;
+char* ping_buffer_ipv4 = 0;
+size_t ping_pkt_size_ipv4;
 
 int open_ping_socket_ipv4()
 {
@@ -83,18 +83,18 @@ int open_ping_socket_ipv4()
 void init_ping_buffer_ipv4(size_t ping_data_size)
 {
     /* allocate ping buffer */
-    ping_pkt_size = ping_data_size + ICMP_MINLEN;
-    ping_buffer = (char*)calloc(1, ping_pkt_size);
-    if (!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");
 }
 
-void socket_set_src_addr_ipv4(int s, FPING_INADDR src_addr)
+void socket_set_src_addr_ipv4(int s, struct in_addr* src_addr)
 {
     struct sockaddr_in sa;
     memset(&sa, 0, sizeof(sa));
     sa.sin_family = AF_INET;
-    sa.sin_addr = src_addr;
+    sa.sin_addr = *src_addr;
 
     if (bind(s, (struct sockaddr*)&sa, sizeof(sa)) < 0)
         errno_crash_and_burn("cannot bind source address");
@@ -122,7 +122,7 @@ int socket_sendto_ping_ipv4(int s, struct sockaddr* saddr, socklen_t saddr_len,
     struct icmp* icp;
     int n;
 
-    icp = (struct icmp*)ping_buffer;
+    icp = (struct icmp*)ping_buffer_ipv4;
 
     icp->icmp_type = ICMP_ECHO;
     icp->icmp_code = 0;
@@ -131,14 +131,14 @@ 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 = ((void*)&icp->icmp_data - (void*)icp); n < ping_pkt_size; ++n) {
-            ping_buffer[n] = random() & 0xFF;
+        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);
+    icp->icmp_cksum = calcsum((unsigned short*)icp, ping_pkt_size_ipv4);
 
-    n = sendto(s, icp, ping_pkt_size, 0, saddr, saddr_len);
+    n = sendto(s, icp, ping_pkt_size_ipv4, 0, saddr, saddr_len);
 
     return n;
 }
index c32a8b566fde6008e7fcdbfb2dbf0b0844566f64..03f2ade81ea3d90419e2152b540a072bb64a8068 100644 (file)
@@ -43,8 +43,8 @@
 
 #include <netinet/icmp6.h>
 
-char* ping_buffer = 0;
-size_t ping_pkt_size;
+char* ping_buffer_ipv6 = 0;
+size_t ping_pkt_size_ipv6;
 
 int open_ping_socket_ipv6()
 {
@@ -82,18 +82,18 @@ int open_ping_socket_ipv6()
 void init_ping_buffer_ipv6(size_t ping_data_size)
 {
     /* allocate ping buffer */
-    ping_pkt_size = ping_data_size + sizeof(struct icmp6_hdr);
-    ping_buffer = (char*)calloc(1, ping_pkt_size);
-    if (!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");
 }
 
-void socket_set_src_addr_ipv6(int s, FPING_INADDR src_addr)
+void socket_set_src_addr_ipv6(int s, struct in6_addr* src_addr)
 {
     struct sockaddr_in6 sa;
     memset(&sa, 0, sizeof(sa));
     sa.sin6_family = AF_INET6;
-    sa.sin6_addr = src_addr;
+    sa.sin6_addr = *src_addr;
 
     if (bind(s, (struct sockaddr*)&sa, sizeof(sa)) < 0)
         errno_crash_and_burn("cannot bind source address");
@@ -104,21 +104,21 @@ int socket_sendto_ping_ipv6(int s, struct sockaddr* saddr, socklen_t saddr_len,
     struct icmp6_hdr* icp;
     int n;
 
-    icp = (struct icmp6_hdr*)ping_buffer;
+    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; ++n) {
-            ping_buffer[n] = random() & 0xFF;
+        for (n = sizeof(struct icmp6_hdr); n < ping_pkt_size_ipv6; ++n) {
+            ping_buffer_ipv6[n] = random() & 0xFF;
         }
     }
 
     icp->icmp6_cksum = 0; /* The IPv6 stack calculates the checksum for us... */
 
-    n = sendto(s, icp, ping_pkt_size, 0, saddr, saddr_len);
+    n = sendto(s, icp, ping_pkt_size_ipv6, 0, saddr, saddr_len);
 
     return n;
 }
index aa5f3e9877aecab9d6ab9335e0884e00fa0d0b42..c90a1483184e5da30896e50a3a608869d0a000fc 100755 (executable)
@@ -1 +1,5 @@
-gcc -DHAVE_CONFIG_H -D_BSD_SOURCE -D_POSIX_SOURCE -I.. -Wall -std=c89 -pedantic -c -o fping.o fping.c
+#!/bin/sh
+
+for f in fping.c socket4.c socket6.c seqmap.c; do
+    gcc -DHAVE_CONFIG_H -D_BSD_SOURCE -D_POSIX_SOURCE -I.. -Wall -std=c89 -pedantic -c -o /dev/null $f
+done