Compare commits

71 Commits
Author SHA1 Message Date
David Schweikert 3a714b275f prepare release 2013-11-04 23:13:07 +01:00
David Schweikert d141744adb Fix fping hanging forever on permanent sendto failure (Shawn Chu, #52) 2013-11-04 23:08:19 +01:00
David Schweikert e1cdf8e1d3 Fix again compatibility issue with FreeBSD (Shawn Chu) 2013-11-04 23:04:00 +01:00
David Schweikert d862dd962b release preparations 2013-11-01 16:11:07 +01:00
David Schweikert 5c68d6f338 don't consider duplicate pings as successful replies (#53) 2013-11-01 15:01:11 +01:00
David Schweikert a2ac5d0fae Remove unnecessary IPv6 socket options 2013-10-15 09:21:14 +02:00
David Schweikert b01f282727 merge latest changes 2013-10-14 20:28:11 +02:00
David Schweikert 0ab66f80de Refactor socket handling, allow running as non-root on Mac OS X by using non-privileged ICMP (#7) 2013-10-13 12:42:37 +02:00
David Schweikert 741236e576 Release version 3.6 2013-10-10 22:05:45 +02:00
David Schweikert 9fca2a141b Fix wrong min RTT value with -Q option (reported by Alexander Ivanov, #51) 2013-10-10 21:58:13 +02:00
David Schweikert 9ee22bd46a prepare 3.6-rc2 2013-07-25 22:34:31 +02:00
David Schweikert f55397336b increase SEQMAP_MAX to 65355 2013-07-25 22:29:56 +02:00
David Schweikert 82722a31fe update README file 2013-07-25 22:29:44 +02:00
David Schweikert 4aad0b2c14 fix compilation issue 2013-07-25 22:29:33 +02:00
David Schweikert fb5f5779cc Merge seqmap branch, fixes #12 2013-07-24 21:38:41 +02:00
David Schweikert a0252f6e79 Removed setsockopt IPV6_CHECKSUM, which shouldn't be set and breaks compiling on Solaris (reported by Juergen Arndt) 2013-07-24 21:36:02 +02:00
David Schweikert 3dee903b41 3.5 is released 2013-07-23 23:54:27 +02:00
David Schweikert 7e55f0b073 Fix loop issue after 65536 pings (reported by Peter Folk and GBert, #12), Minimum ping data size is now 0 2013-07-23 23:40:17 +02:00
David Schweikert 8daad08e1d work on seqmap 2013-07-23 23:24:04 +02:00
David Schweikert b7343ed256 start work on seqmap 2013-07-23 00:25:53 +02:00
David Schweikert ecba31b2dd Release 3.5 2013-05-22 08:56:44 +02:00
David Schweikert 28eea9c273 Re-create configure script with autoconf 2.69 for aarch64 support (Chuck Anderson, #45) 2013-05-22 08:48:08 +02:00
David Schweikert 121bea1d24 Fix compatibility issue with FreeBSD (Alexandre Raynaud, Jason Harris, #39) 2013-05-21 22:02:39 +02:00
David Schweikert 5d6db6f08d document new -D flag 2013-05-21 21:47:33 +02:00
David Schweikert 543d22122d Merge pull request #42 from tohojo/master
Add -D flag to print timestamp in front of output lines.
2013-05-21 12:43:02 -07:00
David Schweikert 70a29a11af fix sprint_tm buffer size crash (reported by Japheth Cleaver) 2013-05-21 21:36:36 +02:00
David Schweikert b0e09ce6fe Coverity: remove pointless expression 2013-04-23 21:59:32 +02:00
David Schweikert 6400ffb339 Merge branch 'master' of github.com:schweikert/fping 2013-04-23 21:26:02 +02:00
David Schweikert 98d44d02bb Merge pull request #47 from dlad/fix-warning
fix clang warning: comparison of unsigned expression < 0 is always false
2013-04-23 12:12:20 -07:00
Dipen Lad 69fff78ca4 fix clang warning: comparison of unsigned expression < 0 is always false 2013-04-20 21:50:22 +01:00
Toke Høiland-Jørgensen 5b6784a4ea Fix formatting of usec part of timestamp output. 2013-03-17 16:33:52 +01:00
Toke Høiland-Jørgensen 25dc120355 Add -D flag to print timestamps before output lines (like Linux ping). 2013-03-11 09:29:58 -04:00
David Schweikert f906225fbd update changelog 2013-02-17 23:09:58 +01:00
David Schweikert 3e29f0631c Merge pull request #35 from ghost/patch-1
Fixes failing fping6 build on OS X 10.8
2013-02-17 14:08:46 -08:00
David Schweikert 10d0a54c07 remove version information from man-page (#31) 2013-02-17 23:06:27 +01:00
David Schweikert ad4ca1609d Update ChangeLog 2013-02-17 23:05:38 +01:00
David Schweikert e0edbf28fc Merge pull request #34 from mv/fix-spec-file
Fix setuid permissions. Provides fping6.
2013-02-17 14:04:04 -08:00
Simon Hitzemann 1c85a422c1 Fixes failing fping6 build on OS X 10.8 2012-12-28 16:52:25 +01:00
Marcus Vinicius Ferreira 86cfc7cf74 Fix setuid permissions. Provides fping6. 2012-12-24 12:51:34 -02:00
David Schweikert fd020977b5 Prepare 3.4 2012-09-04 09:32:09 +02:00
David Schweikert 81c96c0807 Revert "Output statistics to stdout instead of stderr (suggested by Simon Leinen, #9)"
This reverts commit b4d0a93b70.
2012-09-04 09:27:52 +02:00
David Schweikert aff259bbd0 release 3.3 2012-08-19 23:06:18 +02:00
David Schweikert 4cab2f8598 Fix -n flag in fping6 (#28) 2012-08-16 13:59:42 +02:00
David Schweikert aa5f849c5d Fix error message on DNS error for IPv6 hosts (#27) 2012-08-16 11:26:16 +02:00
David Schweikert 1bb43dc07f fix wrong use of pointer (causing segfault) 2012-08-16 11:24:02 +02:00
David Schweikert 02ac0090e1 Call this 3.3-rc1, not 3.3rc1 2012-07-20 00:39:44 +02:00
David Schweikert b4d0a93b70 Output statistics to stdout instead of stderr (suggested by Simon Leinen, #9) 2012-07-20 00:28:10 +02:00
David Schweikert a19c537fc5 Fix "options inet6" breaking IPv4 name resolution (reported by Matt LaPlante, #17) 2012-07-20 00:11:20 +02:00
David Schweikert 6af4d71188 Fix -A for fping6 (reported by Matt LaPlante, #14) 2012-07-20 00:05:36 +02:00
David Schweikert ed4202f84f Fix removing of unreachable hosts when doing loop (Thomas Liske, #13 #23) 2012-07-19 22:54:34 +02:00
David Schweikert a4ef8142b3 Update documentation for --enable-ipv6 2012-07-19 22:43:16 +02:00
David Schweikert 421abc41b1 update ChangeLog 2012-07-19 22:26:03 +02:00
David Schweikert 67d7a10f83 Merge pull request #25 from zeising/master
Add --with-ipv4 and --with-ipv6 options to cnfigure
2012-07-19 13:17:14 -07:00
Niclas Zeising bdef483f4b Add --with-ipv4 and --with-ipv6 options to cnfigure
Currently, to get IPv6 fping you have to pass -DIPV6 to to make while
compiling, and the resulting fping will not handle ipv4.  This patch
adds --with-ipv4 (enabled by default) and --with-ipv6 (disabled by
default) that gives a IPv4 capable fping, and a IPv6 capable fping6
respectively.  Both can be enabled, or either one.  If both the IPv4 and
the IPv6 versions are disabled, configure will throw an error.
2012-07-19 18:52:25 +02:00
David Schweikert e92a68dc4d Added contrib/fping.spec (Stephen Schaefer, #24) 2012-07-16 22:40:53 +02:00
David Schweikert 13ce2eae48 Man-page fix: better description of option -q (#15) 2012-07-16 18:53:19 +02:00
David Schweikert b16d117a17 Set default data size to 56 bytes on all architectures (#18) 2012-07-16 18:47:51 +02:00
David Schweikert 0e3e404a3d improve autoclean 2012-07-16 01:14:55 +02:00
David Schweikert 5f3ab12ca9 man page inconsistency in regards to numeric arguments (#21) 2012-07-16 01:05:15 +02:00
David Schweikert 4a5c82f6a5 start calling this 3.3rc1 2012-07-16 00:57:31 +02:00
David Schweikert 7d4eeb403a convert man-page to pod, for easier editing 2012-07-16 00:53:11 +02:00
David Schweikert 88d54f4505 convert man-page to pod, for easier editing 2012-07-16 00:33:39 +02:00
David Schweikert 5cf3f7fa4d Update Changelog 2012-07-15 23:27:03 +02:00
Thomas Liske 2f09ff2d40 Fix TOS option typo. 2012-07-15 23:25:29 +02:00
David Schweikert 2a53cdc62b Update Changelog 2012-07-15 23:15:40 +02:00
Thomas Liske a5828a2795 This commit fixes #13 (Debian #308695): don't remove hosts if sendto returns an error. The error might recover and fping should still try to reach the host and count it as packet loss. 2012-07-06 22:33:20 +02:00
Thomas Liske 546ba7eb93 Fix TOS option typo. 2012-07-06 20:56:12 +02:00
David Schweikert f062f00568 #1: do not output icmp errors with -q 2012-05-29 14:23:07 +02:00
David Schweikert 3f0f49da64 update Changelog 2012-05-29 10:26:42 +02:00
David Schweikert 780865c8ee release 3.2 2012-05-29 10:25:21 +02:00
David Schweikert 063ee44417 Add missing changelog entry 2012-05-22 10:13:20 +02:00
17 changed files with 1062 additions and 589 deletions
+4
View File
@@ -1,3 +1,4 @@
.*.swp
*.tar.gz
*~
.deps
@@ -17,4 +18,7 @@ install-sh
missing
src/*.o
src/fping
src/fping6
stamp-h1
doc/fping.8
doc/fping6.8
+51 -2
View File
@@ -1,5 +1,54 @@
2012-05-22 David Schweikert <david@schweikert.ch>
* Version 3.2rc1
2013-11-04 David Schweikert <david@schweikert.ch>
* Version 3.7
* Allow running as non-root on Mac OS X by using non-privileged ICMP (#7)
* Remove unnecessary IPv6 socket options
* Fix again compatibility issue with FreeBSD (Shawn Chu)
* Fix fping hanging forever on permanent sendto failure (Shawn Chu)
* Fix duplicate echo reply packets causing early stop in count mode
(reported by Ramon Schwammberger, #53)
2013-10-10 David Schweikert <david@schweikert.ch>
* Version 3.6
* Fix loop issue after 65536 pings (reported by Peter Folk and GBert, #12)
* Minimum ping data size is now 0
* Removed setsockopt IPV6_CHECKSUM, which shouldn't be set and breaks
compiling on Solaris (reported by Juergen Arndt)
* Fix wrong min RTT value with -Q option (reported by Alexander Ivanov, #51)
2013-05-22 David Schweikert <david@schweikert.ch>
* Version 3.5
* Fix sprint_tm buffer size crash (reported by Japheth Cleaver)
* Addded -D flag to print timestamps (Toke Høiland-Jørgensen)
* Fix fping6 build on OS X 10.8 (unknown contributor)
* Fix compatibility issue with FreeBSD (Alexandre Raynaud, Jason Harris, #39)
* Fping.spec: fix setuid permissions and provides fping6 (Marcus Vinicius Ferreira)
* Re-create configure script with autoconf 2.69 for aarch64 support (Chuck Anderson, #45)
2012-09-04 David Schweikert <david@schweikert.ch>
* Version 3.4
* Revert "Output statistics to stdout instead of stderr", because it breaks
tools assuming the output goes to stderr
2012-08-19 David Schweikert <david@schweikert.ch>
* Version 3.3
* Do not output icmp errors with -q (#1)
* Add --enable-ipv4 and --enable-ipv6 options to configure (Niclas Zeising)
* Fix removing of unreachable hosts when doing loop (Thomas Liske, #13 #23)
* Fix -A for fping6 (reported by Matt LaPlante, #14)
* Fix "options inet6" breaking IPv4 name resolution (reported by Matt LaPlante, #17)
* Output statistics to stdout instead of stderr (suggested by Simon Leinen, #9)
* Set default data size to 56 bytes on all architectures (#18)
* Added contrib/fping.spec (Stephen Schaefer, #24)
* Convert man-page source to POD for easier maintenance
* Fix error message on DNS error for IPv6 hosts (#27)
* Fix -n flag in fping6 (#28)
* Man-page fix: TOS option typo (Thomas Liske, #23)
* Man-page fix: inconsistency in regards to numeric arguments (Robert Henney)
* Man-page fix: better description of option -q (#15)
2012-05-29 David Schweikert <david@schweikert.ch>
* Version 3.2
* Improve documentation for -g option (G.W. Haywood)
* Performance optimization for big select timeouts (#10, Andrey Bondarenko)
* Fix restart of select call after interrupt signal (#8, Boian Bonev)
* Fix infinite loop caused by linked list corruption (#11, Boian Bonev)
+21 -4
View File
@@ -9,7 +9,11 @@ Current maintainer:
David Schweikert <david@schweikert.ch>
Website:
http://www.fping.org
http://fping.org/
Mailing-list:
https://groups.google.com/group/fping-users
Installation
------------
@@ -24,12 +28,25 @@ If you want to install fping from source, proceed as follows:
sudo setcap cap_net_raw+ep fping
4. Have a look at the fping(1) manual for usage help
4. Have a look at the fping(8) manual for usage help
(fping -h will also give a minimal help output)
IPv6 support
------------
You can can compile fping with support for IPv6 addresses. A separate binary
is used for that, called fping6. To build it, use ./configure --enable-ipv6
(possibly combined with --enable-ipv4 to also build fping for IPv4). E.g.:
# ./configure --prefix=/usr/local --enable-ipv4 --enable-ipv6
# make
# make install
# sudo setcap cap_net_raw+ep /usr/local/bin/fping*
Credits
-------
Original author: Roland Schemers (schemers@stanford.edu)
Previous maintainer: RL "Bob" Morgan (morgan@stanford.edu)
IPv6 Support: Jeroen Massar (jeroen@unfix.org / jeroen@ipng.nl)
to enable IPV6 compile with -DIPV6
Initial IPv6 Support: Jeroen Massar (jeroen@unfix.org / jeroen@ipng.nl)
Other contributors: see ChangeLog
+2
View File
@@ -1,4 +1,5 @@
#!/bin/sh
[ -f Makefile ] && make clean
rm -f Makefile
rm -f Makefile.in
rm -f aclocal.m4
@@ -17,3 +18,4 @@ rm -f mkinstalldirs
rm -f stamp-h1
rm -f doc/Makefile.in
rm -f src/Makefile.in
rm -f doc/fping.8
+24 -1
View File
@@ -3,7 +3,30 @@ dnl Process this file with autoconf to produce a configure script.
dnl Minimum Autoconf version required.
AC_PREREQ(2.59)
AC_INIT([fping],[3.2-rc1])
AC_INIT([fping],[3.7])
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])
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
AC_CANONICAL_TARGET
AM_INIT_AUTOMAKE([foreign])
+73
View File
@@ -0,0 +1,73 @@
Summary: send ICMP echo probes to multiple hosts
Name: fping
Version: 3.4
Release: 1
License: MIT
Group: Applications/System
Source0: http://fping.org/dist/%{name}-%{version}.tar.gz
BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-buildroot
%description
fping is a program to send ICMP echo probes to network hosts, similar to ping,
but much better performing when pinging multiple hosts. fping has a very long
history: Roland Schemers did publish a first version of it in 1992 and it has
established itself since then as a standard tool for network diagnostics and
statistics.
%prep
%setup -q
%build
if [ ! -f ./configure ] ; then
./autogen.sh
fi
# fping
%configure --enable-ipv4
make
# fping6
%configure --enable-ipv6
make
%{__mv} -f src/fping src/fping6
%install
rm -rf $RPM_BUILD_ROOT
make DESTDIR=$RPM_BUILD_ROOT install
# fping6
%{__install} -Dp -m4755 src/fping6 %{buildroot}%{_sbindir}/fping6
%{__ln_s} -f fping.8 %{buildroot}%{_mandir}/man8/fping6.8
%clean
rm -rf $RPM_BUILD_ROOT
%files
%defattr(-,root,root,-)
%attr(4755, root, root) /usr/sbin/fping
%attr(4755, root, root) /usr/sbin/fping6
%doc README COPYING ChangeLog
/usr/share/man/man8/fping.8.gz
/usr/share/man/man8/fping6.8.gz
%post
if [ -x /usr/sbin/setcap ]; then
/bin/chmod 0755 /usr/sbin/fping*
/usr/sbin/setcap cap_net_raw+ep /usr/sbin/fping*
fi
%changelog
* Mon Dec 24 2012 Marcus Vinicius Ferreira <ferreira.mv@gmail.com>
- Missing './configure' script when cloning from master.
- Making 'fping6'.
- Fix setuid permission to 'rwsr-xr-x'.
- doc files.
- Replacing setuid permission if 'setcap' is present on post-install.
- Using 'http://fping.org/dist/' for release source distributions.
* Mon Jul 16 2012 Stephen Schaefer <sschaefer@acm.org>
- Initial build
# vim:ft=spec:
+17 -2
View File
@@ -1,2 +1,17 @@
man_MANS = fping.8
EXTRA_DIST = $(man_MANS)
man_MANS =
if IPV4
man_MANS += fping.8
endif
if IPV6
man_MANS += fping6.8
endif
EXTRA_DIST = fping.8 fping6.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 $< >$@
-227
View File
@@ -1,227 +0,0 @@
.TH fping 8
.SH NAME
fping \- send ICMP ECHO_REQUEST packets to network hosts
.SH SYNOPSIS
.B fping
[ \fIoptions\fR ]
[ \fIsystems...\fR ]
.SH DESCRIPTION
.B fping
is a program like
.B ping(8)
which uses the Internet Control
Message Protocol (ICMP) echo request to determine if a target host is
responding.
.B fping
differs from ping in that you can specify any
number of targets on the command line, or specify a file containing
the lists of targets to ping. Instead of sending to one target until it
times out or replies,
.B fping
will send out a ping packet and move
on to the next target in a round-robin fashion.
.PP
In the default mode, if a target replies,
it is noted and removed from the list of targets to check; if a target
does not respond within a certain time limit and/or retry limit it
is designated as unreachable.
.B fping
also supports sending a specified number of pings to a target, or
looping indefinitely (as in
.B ping
).
.PP
Unlike
.B ping,
.B fping
is meant to be used in scripts, so its output is designed to be
easy to parse.
.SH OPTIONS
.IP \fB\-a\fR 5
Show systems that are alive.
.IP \fB\-A\fR 5
Display targets by address rather than DNS name.
.IP \fB\-b\fIn\fR 5
Number of bytes of ping data to send. The minimum size (normally 12)
allows room for the data that
.B fping
needs to do its work (sequence number, timestamp). The reported
received data size includes the IP header (normally 20 bytes) and ICMP
header (8 bytes), so the minimum total size is 40 bytes. Default is
56, as in
.B ping.
Maximum is the theoretical maximum IP datagram size (64K), though most
systems limit this to a smaller, system-dependent number.
.IP \fB\-B\fIn\fR 5
In the default mode,
.B fping
sends several requests to a target before giving up, waiting longer for
a reply on each successive request. This parameter is the value by
which the wait time is multiplied on each successive request; it must
be entered as a floating-point number (x.y). The default is 1.5.
.IP \fB\-c\fR 5
Number of request packets to send to each target. In this mode, a
line is displayed for each received response (this can suppressed with
\-q or \-Q). Also, statistics about responses for each target are displayed
when all requests have been sent (or when interrupted).
.IP \fB-C\fR 5
Similar to \-c, but the per-target statistics are displayed in a format
designed for automated response-time statistics gathering. For
example:
% fping \-C 5 \-q somehost
somehost : 91.7 37.0 29.2 \- 36.8
shows the response time in milliseconds for each of the five requests,
with the "\-" indicating that no response was received to the fourth
request.
.IP \fB\-d\fR 5
Use DNS to lookup address of return ping packet. This allows you to give
fping a list of IP addresses as input and print hostnames in the output.
.IP \fB\-e\fR 5
Show elapsed (round-trip) time of packets.
.IP \fB\-f\fR 5
Read list of targets from a file. This option can only be used by the
root user. Regular users should pipe in the file via stdin:
% fping < targets_file
.IP \fB\-g\fR 5
Generate a target list from a supplied IP netmask, or a starting and ending IP.
Specify the netmask or start/end in the targets portion of the command line. If
a network with netmask is given, the network and broadcast addresses will be
excluded.
ex. To ping the network 192.168.1.0/24, the specified command line could look like either:
fping \-g 192.168.1.0/24
or
fping -g 192.168.1.1 192.168.1.254
.IP \fB\-h\fR 5
Print usage message.
.IP \fB\-i\fIn\fR 5
The minimum amount of time (in milliseconds) between sending a ping packet to any target (default is 25).
.IP \fB\-l\fR 5
Loop sending packets to each target indefinitely. Can be interrupted
with Ctrl-C; statistics about responses for each target are then displayed.
.IP \fB\-m\fR 5
Send pings to each of a target host's multiple interfaces.
.IP \fB\-n\fR 5
Same as \-d.
.IP \fB\-p\fR 5
In looping or counting modes (\-l, \-c, or \-C), this parameter sets the
time in milliseconds that
.B fping
waits between successive packets to an individual target. Default is
1000.
.IP \fB\-q\fR 5
Quiet. Don't show per-target results, just set final exit status.
.IP \fB\-Q\fIn\fR 5
Like \-q, but show summary results every n seconds.
.IP \fB\-r\fIn\fR 5
Retry limit (default 3). This is the number of times an attempt at pinging
a target will be made, not including the first try.
.IP \fB\-s\fR 5
Print cumulative statistics upon exit.
.IP \fB\-S\fIaddr\fR 5
Set source address.
.IP \fB\-I\fIif\fR 5
Set the interface (requires SO_BINDTODEVICE support)
.IP \fB\-t\fIn\fR 5
Initial target timeout in milliseconds (default 500). In the default
mode, this is the amount of time that
.B fping
waits for a response to its first request. Successive timeouts are
multiplied by the backoff factor.
.IP \fB\-T\fIn\fR 5
Ignored (for compatibility with fping 2.4).
.IP \fB\-u\fR 5
Show targets that are unreachable.
.IP \fB\-T\fIn\fR 5
Set the typ of service flag (TOS). \fIn\fR can be either decimal or hexadecimal (0xh) format.
.IP \fB\-v\fR 5
Print
.B fping
version information.
.IP \fB-H\fIn\fR 5
Set the IP TTL field (time to live hops).
.SH EXAMPLES
The following perl script will check a list of hosts and send mail if
any are unreachable. It uses the open2 function which allows a program
to be opened for reading and writing. fping does not start pinging the
list of systems until it reads EOF, which it gets after INPUT is closed.
Sure the open2 usage is not needed in this example, but it's a good open2
example none the less.
.nf
#!/usr/bin/perl
require 'open2.pl';
$MAILTO = "root";
$pid = &open2("OUTPUT","INPUT","/usr/local/bin/fping -u");
@check=("slapshot","foo","foobar");
foreach(@check) { print INPUT "$_\\n"; }
close(INPUT);
@output=<OUTPUT>;
if ($#output != -1) {
chop($date=`date`);
open(MAIL,"|mail -s 'unreachable systems' $MAILTO");
print MAIL "\\nThe following systems are unreachable as of: $date\\n\\n";
print MAIL @output;
close MAIL;
}
.fi
Another good example is when you want to perform an action only on hosts
that are currently reachable.
.nf
#!/usr/bin/perl
$hosts_to_backup = `cat /etc/hosts.backup | fping -a`;
foreach $host (split(/\\n/,$hosts_to_backup)) {
# do it
}
.fi
.SH AUTHORS
.nf
Roland J. Schemers III, Stanford University, concept and versions 1.x
RL "Bob" Morgan, Stanford University, versions 2.x
David Papp, versions 2.3x and up,
David Schweikert, versions 3.0 and up
fping website: http://www.fping.org
.fi
.SH DIAGNOSTICS
Exit status is 0 if all the hosts are reachable, 1 if some hosts were
unreachable, 2 if any IP addresses were not found, 3 for invalid
command line arguments, and 4 for a system call failure.
.SH BUGS
Ha! If we knew of any we would have fixed them!
.SH RESTRICTIONS
If certain options are used (i.e, a low value for \-i and \-t, and a
high value for \-r) it is possible to flood the network. This program
must be installed as setuid root in order to open up a raw socket,
or must be run by root. In order to stop mere mortals from hosing the
network (when fping is installed setuid root) , normal users can't specify
the following:
.nf
-i n where n < 10 msec
-r n where n > 20
-t n where n < 250 msec
.fi
.SH SEE ALSO
netstat(1), ping(8), ifconfig(8c)
+248
View File
@@ -0,0 +1,248 @@
=head1 NAME
fping - send ICMP ECHO_REQUEST packets to network hosts
=head1 SYNOPSIS
B<fping> [ I<options> ] [ I<systems...> ]
B<fping6> [ I<options> ] [ I<systems...> ]
=head1 DESCRIPTION
B<fping> is a program like B<ping> which uses the Internet Control Message
Protocol (ICMP) echo request to determine if a target host is responding.
B<fping> differs from B<ping> in that you can specify any number of targets on the
command line, or specify a file containing the lists of targets to ping.
Instead of sending to one target until it times out or replies, B<fping> will
send out a ping packet and move on to the next target in a round-robin fashion.
In the default mode, if a target replies, it is noted and removed from the list
of targets to check; if a target does not respond within a certain time limit
and/or retry limit it is designated as unreachable. B<fping> also supports
sending a specified number of pings to a target, or looping indefinitely (as in
B<ping> ). Unlike B<ping>, B<fping> is meant to be used in scripts, so its
output is designed to be easy to parse.
The binary named B<fping6> is the same as B<fping>, except that it uses IPv6
addresses instead of IPv4.
=head1 OPTIONS
=over 5
=item B<-a>
Show systems that are alive.
=item B<-A>
Display targets by address rather than DNS name.
=item B<-b> I<n>
Number of bytes of ping data to send. The minimum size (normally 12) allows
room for the data that B<fping> needs to do its work (sequence number,
timestamp). The reported received data size includes the IP header (normally
20 bytes) and ICMP header (8 bytes), so the minimum total size is 40 bytes.
Default is 56, as in B<ping>. Maximum is the theoretical maximum IP datagram
size (64K), though most systems limit this to a smaller, system-dependent
number.
=item B<-B> I<n>
In the default mode, B<fping> sends several requests to a target before giving
up, waiting longer for a reply on each successive request. This parameter is
the value by which the wait time is multiplied on each successive request; it
must be entered as a floating-point number (x.y). The default is 1.5.
=item B<-c> I<n>
Number of request packets to send to each target. In this mode, a line is
displayed for each received response (this can suppressed with B<-q> or B<-Q>).
Also, statistics about responses for each target are displayed when all
requests have been sent (or when interrupted).
=item B<-C> I<n>
Similar to B<-c>, but the per-target statistics are displayed in a format
designed for automated response-time statistics gathering. For example:
% fping -C 5 -q somehost
somehost : 91.7 37.0 29.2 - 36.8
shows the response time in milliseconds for each of the five requests, with the
C<-> indicating that no response was received to the fourth request.
=item B<-d>
Use DNS to lookup address of return ping packet. This allows you to give fping
a list of IP addresses as input and print hostnames in the output.
=item B<-D>
Add Unix timestamps in front of output lines generated with in looping or counting
modes (B<-l>, B<-c>, or B<-C>).
=item B<-e>
Show elapsed (round-trip) time of packets.
=item B<-f>
Read list of targets from a file. This option can only be used by the root
user. Regular users should pipe in the file via stdin:
% fping < targets_file
=item B<-g> I<addr/mask>
Generate a target list from a supplied IP netmask, or a starting and ending IP.
Specify the netmask or start/end in the targets portion of the command line. If
a network with netmask is given, the network and broadcast addresses will be
excluded. ex. To ping the network 192.168.1.0/24, the specified command line
could look like either:
fping -g 192.168.1.0/24
or
fping -g 192.168.1.1 192.168.1.254
=item B<-h>
Print usage message.
=item B<-i> I<n>
The minimum amount of time (in milliseconds) between sending a ping packet
to any target (default is 25).
=item B<-l>
Loop sending packets to each target indefinitely. Can be interrupted with
Ctrl-C; statistics about responses for each target are then displayed.
=item B<-m>
Send pings to each of a target host's multiple interfaces.
=item B<-n>
Same as -d.
=item B<-p> <n>
In looping or counting modes (B<-l>, B<-c>, or B<-C>), this parameter sets
the time in milliseconds that B<fping> waits between successive packets to
an individual target. Default is 1000.
=item B<-q>
Quiet. Don't show per-probe results, but only the final summary. Also don't
show ICMP error messages.
=item B<-Q> I<n>
Like B<-q>, but show summary results every n seconds.
=item B<-r> I<n>
Retry limit (default 3). This is the number of times an attempt at pinging
a target will be made, not including the first try.
=item B<-s>
Print cumulative statistics upon exit.
=item B<-S> I<addr>
Set source address.
=item B<-I> I<if>
Set the interface (requires SO_BINDTODEVICE support)
=item B<-t> I<n>
Initial target timeout in milliseconds (default 500). In the default mode, this
is the amount of time that B<fping> waits for a response to its first request.
Successive timeouts are multiplied by the backoff factor.
=item B<-T> I<n>
Ignored (for compatibility with fping 2.4).
=item B<-u>
Show targets that are unreachable.
=item B<-O> I<n>
Set the typ of service flag (TOS). I<n> can be either decimal or hexadecimal
(0xh) format.
=item B<-v>
Print B<fping> version information.
=item B<-H> I<n>
Set the IP TTL field (time to live hops).
=back
=head1 AUTHORS
=over 4
=item *
Roland J. Schemers III, Stanford University, concept and versions 1.x
=item *
RL "Bob" Morgan, Stanford University, versions 2.x
=item *
David Papp, versions 2.3x and up
=item *
David Schweikert, versions 3.0 and up
=back
B<fping website: L<http://www.fping.org>>
=head1 DIAGNOSTICS
Exit status is 0 if all the hosts are reachable, 1 if some hosts
were unreachable, 2 if any IP addresses were not found, 3 for invalid command
line arguments, and 4 for a system call failure.
=head1 RESTRICTIONS
If certain options are used (i.e, a low value for B<-i> and B<-t>, and a high value
for B<-r>) it is possible to flood the network. This program must be installed as
setuid root in order to open up a raw socket, or must be run by root. In order
to stop mere mortals from hosing the network, normal users can't specify the following:
=over 4
=item *
B<-i> I<n>, where I<n> < 10 msec
=item *
B<-r> I<n>, where I<n> > 20
=item *
B<-t> I<n>, where n < 250 msec
=back
=head1 SEE ALSO
C<ping(8)>
+15 -2
View File
@@ -1,3 +1,16 @@
sbin_PROGRAMS = fping
fping_SOURCES = fping.c options.h
prog =
if IPV4
prog += fping
endif
if IPV6
prog += fping6
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
+235 -351
View File
@@ -35,6 +35,9 @@ extern "C"
{
#endif /* __cplusplus */
#include "fping.h"
#include "options.h"
/* if compiling for Windows, use this separate set
(too difficult to ifdef all the autoconf defines) */
#ifdef WIN32
@@ -52,10 +55,10 @@ extern "C"
#include <time.h>
#include <signal.h>
#include <getopt.h>
#include <netinet/in.h>
#include <stdarg.h>
#include "config.h"
#include "seqmap.h"
#ifdef HAVE_UNISTD_H
#include <unistd.h>
@@ -94,8 +97,6 @@ extern "C"
#endif /* WIN32 */
#include "options.h"
/*** externals ***/
extern char *optarg;
@@ -112,16 +113,7 @@ extern int h_errno;
/*** Ping packet defines ***/
/* data added after ICMP header for our nefarious purposes */
typedef struct ping_data
{
int ping_count; /* counts up to -c count or 1 */
struct timeval ping_ts; /* time sent */
} PING_DATA;
#define MIN_PING_DATA sizeof( PING_DATA )
#define MIN_PING_DATA 0
#define MAX_IP_PACKET 65536 /* (theoretical) max IP packet size */
#define SIZE_IP_HDR 20
#ifndef IPV6
@@ -132,7 +124,7 @@ typedef struct ping_data
#define MAX_PING_DATA ( MAX_IP_PACKET - SIZE_IP_HDR - SIZE_ICMP_HDR )
/* sized so as to be like traditional ping */
#define DEFAULT_PING_DATA_SIZE ( MIN_PING_DATA + 44 )
#define DEFAULT_PING_DATA_SIZE 56
/* maxima and minima */
#define MAX_COUNT 10000
@@ -200,13 +192,6 @@ char *icmp_unreach_str[16] =
};
#define ICMP_UNREACH_MAXTYPE 15
#ifndef IPV6
#define FPING_SOCKADDR struct sockaddr_in
#define FPING_ICMPHDR struct icmp
#else
#define FPING_SOCKADDR struct sockaddr_in6
#define FPING_ICMPHDR struct icmp6_hdr
#endif
/* entry used to keep track of each host we are pinging */
@@ -232,10 +217,12 @@ typedef struct host_entry
unsigned char waiting; /* waiting for response */
struct timeval last_send_time; /* time of last packet sent */
int num_sent; /* number of ping packets sent */
int num_recv; /* number of pings received */
int num_recv; /* number of pings received (duplicates ignored) */
int num_recv_total; /* number of pings received, including duplicates */
int max_reply; /* longest response time */
int min_reply; /* shortest response time */
int total_time; /* sum of response times */
/* _i -> splits (reset on every report interval) */
int num_sent_i; /* number of ping packets sent */
int num_recv_i; /* number of pings received */
int max_reply_i; /* longest response time */
@@ -284,13 +271,12 @@ struct in6_addr src_addr;
/* global stats */
long max_reply = 0;
long min_reply = 1000000;
long min_reply = 0;
int total_replies = 0;
double sum_replies = 0;
int max_hostname_len = 0;
int num_jobs = 0; /* number of hosts still to do */
int num_hosts; /* total number of hosts */
int max_seq_sent = 0; /* maximum sequence number sent so far */
int num_alive = 0, /* total number alive */
num_unreachable = 0, /* total number unreachable */
num_noaddress = 0; /* total number of addresses not found */
@@ -312,6 +298,7 @@ int verbose_flag, quiet_flag, stats_flag, unreachable_flag, alive_flag;
int elapsed_flag, version_flag, count_flag, loop_flag;
int per_recv_flag, report_all_rtts_flag, name_flag, addr_flag, backoff_flag;
int multif_flag;
int timestamp_flag = 0;
#if defined( DEBUG ) || defined( _DEBUG )
int randomly_lose_flag, sent_times_flag, trace_flag, print_per_system_flag;
int lose_factor;
@@ -328,7 +315,6 @@ void add_addr( char *name, char *host, struct in_addr ipaddr );
void add_addr( char *name, char *host, FPING_SOCKADDR *ipaddr );
#endif
char *na_cat( char *name, struct in_addr ipaddr );
char *cpystr( char *string );
void crash_and_burn( char *message );
void errno_crash_and_burn( char *message );
char *get_host_by_address( struct in_addr in );
@@ -353,6 +339,7 @@ HOST_ENTRY *ev_dequeue();
void ev_remove(HOST_ENTRY *h);
void add_cidr(char *);
void add_range(char *, char *);
void print_warning(char *fmt, ...);
/*** function definitions ***/
@@ -373,124 +360,26 @@ void add_range(char *, char *);
int main( int argc, char **argv )
{
int c, i, n;
#ifdef IPV6
int opton = 1;
#endif
struct protoent *proto;
char *buf;
uid_t uid;
int tos = 0;
#ifndef IPV6
struct sockaddr_in sa;
#else
struct sockaddr_in6 sa;
#endif
int tos = 0;
HOST_ENTRY *cursor;
prog = argv[0];
s = open_ping_socket();
/* confirm that ICMP is available on this machine */
#ifndef IPV6
if( ( proto = getprotobyname( "icmp" ) ) == NULL )
#else
if( ( proto = getprotobyname( "ipv6-icmp" ) ) == NULL )
#endif
crash_and_burn( "icmp: unknown protocol" );
/* create raw socket for ICMP calls (ping) */
#ifndef IPV6
s = socket( AF_INET, SOCK_RAW, proto->p_proto );
#else
s = socket( AF_INET6, SOCK_RAW, proto->p_proto );
#endif
if( s < 0 )
errno_crash_and_burn( "can't create raw socket (must run as root?)" );
#ifdef IPV6
/*
* let the kernel pass extension headers of incoming packets,
* for privileged socket options
*/
#ifdef IPV6_RECVHOPOPTS
if (setsockopt(s, IPPROTO_IPV6, IPV6_RECVHOPOPTS, &opton,
sizeof(opton)))
err(1, "setsockopt(IPV6_RECVHOPOPTS)");
#else /* old adv. API */
if (setsockopt(s, IPPROTO_IPV6, IPV6_HOPOPTS, &opton,
sizeof(opton)))
err(1, "setsockopt(IPV6_HOPOPTS)");
#endif
#ifdef IPV6_RECVDSTOPTS
if (setsockopt(s, IPPROTO_IPV6, IPV6_RECVDSTOPTS, &opton,
sizeof(opton)))
err(1, "setsockopt(IPV6_RECVDSTOPTS)");
#else /* old adv. API */
if (setsockopt(s, IPPROTO_IPV6, IPV6_DSTOPTS, &opton,
sizeof(opton)))
err(1, "setsockopt(IPV6_DSTOPTS)");
#endif
#ifdef IPV6_RECVRTHDRDSTOPTS
if (setsockopt(s, IPPROTO_IPV6, IPV6_RECVRTHDRDSTOPTS, &opton,
sizeof(opton)))
err(1, "setsockopt(IPV6_RECVRTHDRDSTOPTS)");
#endif
#ifdef IPV6_RECVRTHDR
if (setsockopt(s, IPPROTO_IPV6, IPV6_RECVRTHDR, &opton,
sizeof(opton)))
err(1, "setsockopt(IPV6_RECVRTHDR)");
#else /* old adv. API */
if (setsockopt(s, IPPROTO_IPV6, IPV6_RTHDR, &opton,
sizeof(opton)))
err(1, "setsockopt(IPV6_RTHDR)");
#endif
#ifndef USE_SIN6_SCOPE_ID
#ifdef IPV6_RECVPKTINFO
if (setsockopt(s, IPPROTO_IPV6, IPV6_RECVPKTINFO, &opton,
sizeof(opton)))
err(1, "setsockopt(IPV6_RECVPKTINFO)");
#else /* old adv. API */
if (setsockopt(s, IPPROTO_IPV6, IPV6_PKTINFO, &opton,
sizeof(opton)))
err(1, "setsockopt(IPV6_PKTINFO)");
#endif
#endif /* USE_SIN6_SCOPE_ID */
#ifdef IPV6_RECVHOPLIMIT
if (setsockopt(s, IPPROTO_IPV6, IPV6_RECVHOPLIMIT, &opton,
sizeof(opton)))
err(1, "setsockopt(IPV6_RECVHOPLIMIT)");
#else /* old adv. API */
if (setsockopt(s, IPPROTO_IPV6, IPV6_HOPLIMIT, &opton,
sizeof(opton)))
err(1, "setsockopt(IPV6_HOPLIMIT)");
#endif
#ifdef IPV6_CHECKSUM
#ifndef SOL_RAW
#define SOL_RAW IPPROTO_IPV6
#endif
opton = 2;
if (setsockopt(s, SOL_RAW, IPV6_CHECKSUM, &opton,
sizeof(opton)))
err(1, "setsockopt(SOL_RAW,IPV6_CHECKSUM)");
#endif
#endif
if( ( uid = getuid() ) )
{
if(uid = getuid()) {
seteuid( getuid() );
}
}/* IF */
prog = argv[0];
ident = getpid() & 0xFFFF;
verbose_flag = 1;
backoff_flag = 1;
opterr = 1;
/* get command line options */
while( ( c = getopt( argc, argv, "gedhlmnqusaAvz:t:H:i:p:f:r:c:b:C:Q:B:S:I:T:O:" ) ) != EOF )
while( ( c = getopt( argc, argv, "gedhlmnqusaAvDz:t:H:i:p:f:r:c:b:C:Q:B:S:I:T:O:" ) ) != EOF )
{
switch( c )
{
@@ -532,7 +421,9 @@ int main( int argc, char **argv )
break;
case 'b':
if( !( ping_data_size = ( unsigned int )atoi( optarg ) ) )
errno = 0;
ping_data_size = (unsigned int) strtol(optarg, (char **)NULL, 10);
if( errno )
usage(1);
break;
@@ -581,6 +472,10 @@ int main( int argc, char **argv )
stats_flag = 1;
break;
case 'D':
timestamp_flag = 1;
break;
case 'l':
loop_flag = 1;
backoff_flag = 0;
@@ -682,7 +577,7 @@ int main( int argc, char **argv )
/* validate various option settings */
if (ttl < 0 || ttl > 255) {
if (ttl > 255) {
fprintf(stderr, "ping: ttl %u out of range\n", ttl);
usage(1);
}
@@ -858,7 +753,6 @@ int main( int argc, char **argv )
FILE *ping_file;
char line[132];
char host[132];
char *p;
if( strcmp( filename, "-" ) == 0 )
ping_file = fdopen( 0, "r" );
@@ -877,9 +771,7 @@ int main( int argc, char **argv )
if( ( !*host ) || ( host[0] == '#' ) ) /* magic to avoid comments */
continue;
p = cpystr( host );
add_name( p );
add_name(host);
}/* WHILE */
fclose( ping_file );
@@ -903,20 +795,8 @@ int main( int argc, char **argv )
if( !num_hosts )
exit( 2 );
/* set the source address */
if( src_addr_present )
{
memset( &sa, 0, sizeof( sa ) );
#ifndef IPV6
sa.sin_family = AF_INET;
sa.sin_addr = src_addr;
#else
sa.sin6_family = AF_INET6;
sa.sin6_addr = src_addr;
#endif
if ( bind( s, (struct sockaddr *)&sa, sizeof( sa ) ) < 0 )
errno_crash_and_burn( "cannot bind source address" );
if(src_addr_present) {
socket_set_src_addr(s, src_addr);
}
/* allocate array to hold outstanding ping requests */
@@ -969,6 +849,8 @@ int main( int argc, char **argv )
srandom( start_time.tv_usec );
#endif /* DEBUG || _DEBUG */
seqmap_init();
/* main loop */
main_loop();
@@ -1030,7 +912,7 @@ void add_cidr(char *addr)
char buffer[20];
in_addr_tmp.s_addr = htonl(net_addr);
inet_ntop(AF_INET, &in_addr_tmp, buffer, sizeof(buffer));
add_name(cpystr(buffer));
add_name(buffer);
}
freeaddrinfo(addr_res);
@@ -1080,7 +962,7 @@ void add_range(char *start, char *end)
char buffer[20];
in_addr_tmp.s_addr = htonl(start_long);
inet_ntop(AF_INET, &in_addr_tmp, buffer, sizeof(buffer));
add_name(cpystr(buffer));
add_name(buffer);
start_long++;
}
}
@@ -1144,7 +1026,7 @@ void main_loop()
ev_enqueue(h);
}
/* Count mode: schedule timeout after last ping */
else if(count_flag && count_flag && h->num_sent >= count) {
else if(count_flag && h->num_sent >= count) {
h->ev_type = EV_TYPE_TIMEOUT;
h->ev_time.tv_sec = last_send_time.tv_sec;
h->ev_time.tv_usec = last_send_time.tv_usec;
@@ -1527,7 +1409,6 @@ int send_ping( int s, HOST_ENTRY *h )
{
char *buffer;
FPING_ICMPHDR *icp;
PING_DATA *pdp;
int n;
int myseq;
@@ -1539,8 +1420,7 @@ int send_ping( int s, HOST_ENTRY *h )
icp = ( FPING_ICMPHDR* )buffer;
gettimeofday( &h->last_send_time, &tz );
myseq = h->num_sent * num_hosts + h->i;
max_seq_sent = myseq > max_seq_sent ? myseq : max_seq_sent;
myseq = seqmap_add(h->i, h->num_sent, &h->last_send_time);
#ifndef IPV6
icp->icmp_type = ICMP_ECHO;
@@ -1549,10 +1429,6 @@ int send_ping( int s, HOST_ENTRY *h )
icp->icmp_seq = htons(myseq);
icp->icmp_id = htons(ident);
pdp = ( PING_DATA* )( buffer + SIZE_ICMP_HDR );
pdp->ping_ts = h->last_send_time;
pdp->ping_count = h->num_sent;
icp->icmp_cksum = in_cksum( ( unsigned short* )icp, ping_pkt_size );
#else
icp->icmp6_type = ICMP6_ECHO_REQUEST;
@@ -1560,10 +1436,6 @@ int send_ping( int s, HOST_ENTRY *h )
icp->icmp6_seq = htons(myseq);
icp->icmp6_id = htons(ident);
pdp = ( PING_DATA* )( buffer + SIZE_ICMP_HDR );
pdp->ping_ts = h->last_send_time;
pdp->ping_count = h->num_sent;
icp->icmp6_cksum = 0; // The IPv6 stack calculates the checksum for us...
#endif
#if defined(DEBUG) || defined(_DEBUG)
@@ -1574,8 +1446,12 @@ int send_ping( int s, HOST_ENTRY *h )
n = sendto( s, buffer, ping_pkt_size, 0,
( struct sockaddr* )&h->saddr, sizeof( FPING_SOCKADDR ) );
if( n < 0 || n != ping_pkt_size )
{
if(
(n < 0 || n != ping_pkt_size)
#if defined( EHOSTDOWN )
&& errno != EHOSTDOWN
#endif
) {
if( verbose_flag || unreachable_flag )
{
printf( "%s", h->host );
@@ -1586,10 +1462,13 @@ int send_ping( int s, HOST_ENTRY *h )
}/* IF */
num_unreachable++;
remove_job( h );
h->num_sent++;
h->num_sent_i++;
h->waiting++;
num_pingsent++;
last_send_time = h->last_send_time;
free( buffer );
return(0);
return(1);
}
/* mark this trial as outstanding */
@@ -1639,7 +1518,8 @@ int wait_for_reply(long wait_time)
HOST_ENTRY *h;
long this_reply;
int this_count;
struct timeval sent_time;
struct timeval *sent_time;
SEQMAP_VALUE *seqmap_value;
result = recvfrom_wto( s, buffer, sizeof(buffer), &response_addr, wait_time );
@@ -1685,6 +1565,8 @@ int wait_for_reply(long wait_time)
return( 1 ); /* too short */
}/* IF */
gettimeofday( &current_time, &tz );
icp = ( FPING_ICMPHDR* )( buffer + hlen );
#ifndef IPV6
if( icp->icmp_type != ICMP_ECHOREPLY )
@@ -1705,54 +1587,51 @@ int wait_for_reply(long wait_time)
#endif
return 1; /* packet received, but not the one we are looking for! */
#ifndef IPV6
seqmap_value = seqmap_fetch(ntohs(icp->icmp_seq), &current_time);
#else
seqmap_value = seqmap_fetch(ntohs(icp->icmp6_seq), &current_time);
#endif
if(seqmap_value == NULL) {
return 1;
}
num_pingreceived++;
#ifndef IPV6
if( ntohs(icp->icmp_seq) > max_seq_sent )
#else
if( ntohs(icp->icmp6_seq) > max_seq_sent )
#endif
return( 1 ); /* packet received, don't worry about it anymore */
#ifndef IPV6
n = ntohs(icp->icmp_seq) % num_hosts;
#else
n = ntohs(icp->icmp6_seq) % num_hosts;
#endif
n = seqmap_value->host_nr;
h = table[n];
sent_time = &seqmap_value->ping_ts;
this_count = seqmap_value->ping_count;
this_reply = timeval_diff( &current_time, sent_time );
if( h->resp_times[this_count] == RESP_WAITING )
{
/* only for non-duplicates: */
h->waiting = 0;
h->timeout = timeout;
h->num_recv++;
h->num_recv_i++;
if( !max_reply || this_reply > max_reply ) max_reply = this_reply;
if( !min_reply || this_reply < min_reply ) min_reply = this_reply;
if( !h->max_reply || this_reply > h->max_reply ) h->max_reply = this_reply;
if( !h->min_reply || this_reply < h->min_reply ) h->min_reply = this_reply;
if( !h->max_reply_i || this_reply > h->max_reply_i ) h->max_reply_i = this_reply;
if( !h->min_reply_i || this_reply < h->min_reply_i ) h->min_reply_i = this_reply;
sum_replies += this_reply;
h->total_time += this_reply;
h->total_time_i += this_reply;
total_replies++;
}
/* received ping is cool, so process it */
gettimeofday( &current_time, &tz );
h->waiting = 0;
h->timeout = timeout;
h->num_recv++;
h->num_recv_i++;
#ifndef IPV6
memcpy( &sent_time, icp->icmp_data + offsetof( PING_DATA, ping_ts ), sizeof( sent_time ) );
memcpy( &this_count, icp->icmp_data, sizeof( this_count ) );
#else
memcpy( &sent_time, ((char *)icp->icmp6_data32)+4+offsetof(PING_DATA, ping_ts), sizeof( sent_time ) );
memcpy( &this_count, ((char *)icp->icmp6_data32)+4, sizeof( this_count ) );
#endif
h->num_recv_total++;
#if defined( DEBUG ) || defined( _DEBUG )
if( trace_flag )
printf( "received [%d] from %s\n", this_count, h->host );
#endif /* DEBUG || _DEBUG */
this_reply = timeval_diff( &current_time, &sent_time );
if( this_reply > max_reply ) max_reply = this_reply;
if( this_reply < min_reply ) min_reply = this_reply;
if( this_reply > h->max_reply ) h->max_reply = this_reply;
if( this_reply < h->min_reply ) h->min_reply = this_reply;
if( this_reply > h->max_reply_i ) h->max_reply_i = this_reply;
if( this_reply < h->min_reply_i ) h->min_reply_i = this_reply;
sum_replies += this_reply;
h->total_time += this_reply;
h->total_time_i += this_reply;
total_replies++;
/* note reply time in array, probably */
if( !loop_flag )
{
@@ -1823,6 +1702,11 @@ int wait_for_reply(long wait_time)
if( per_recv_flag )
{
if(timestamp_flag) {
printf("[%lu.%06lu] ",
(unsigned long)current_time.tv_sec,
(unsigned long)current_time.tv_usec);
}
avg = h->total_time / h->num_recv;
printf( "%s%s : [%d], %d bytes, %s ms",
h->host, h->pad, this_count, result, sprint_tm( this_reply ) );
@@ -1837,7 +1721,7 @@ int wait_for_reply(long wait_time)
else
{
printf( "%d%% return)",
( h->num_recv * 100 ) / h->num_sent );
( h->num_recv_total * 100 ) / h->num_sent );
}/* ELSE */
#ifndef IPV6
@@ -1888,6 +1772,7 @@ int handle_random_icmp( FPING_ICMPHDR *p, int psize, FPING_SOCKADDR *addr )
FPING_ICMPHDR *sent_icmp;
unsigned char *c;
HOST_ENTRY *h;
SEQMAP_VALUE *seqmap_value;
#ifdef IPV6
char addr_ascii[INET6_ADDRSTRLEN];
inet_ntop(addr->sin6_family, &addr->sin6_addr, addr_ascii, INET6_ADDRSTRLEN);
@@ -1904,37 +1789,39 @@ int handle_random_icmp( FPING_ICMPHDR *p, int psize, FPING_SOCKADDR *addr )
sent_icmp = ( FPING_ICMPHDR* )( c + 28 );
#ifndef IPV6
sent_icmp = ( struct icmp* )( c + 28 );
seqmap_value = seqmap_fetch(ntohs(sent_icmp->icmp_seq), &current_time);
if( ( sent_icmp->icmp_type == ICMP_ECHO ) &&
( ntohs(sent_icmp->icmp_id) == ident ) &&
( ntohs(sent_icmp->icmp_seq) <= ( n_short )max_seq_sent ) )
( seqmap_value != NULL ) )
{
/* this is a response to a ping we sent */
h = table[ntohs(sent_icmp->icmp_seq) % num_hosts];
h = table[seqmap_value->host_nr];
if( p->icmp_code > ICMP_UNREACH_MAXTYPE )
{
fprintf( stderr, "ICMP Unreachable (Invalid Code) from %s for ICMP Echo sent to %s",
print_warning("ICMP Unreachable (Invalid Code) from %s for ICMP Echo sent to %s",
inet_ntoa( addr->sin_addr ), h->host );
#else
seqmap_value = seqmap_fetch(ntohs(sent_icmp->icmp6_seq), &current_time);
if( ( sent_icmp->icmp6_type == ICMP_ECHO ) &&
( ntohs(sent_icmp->icmp6_id) == ident ) &&
( ntohs(sent_icmp->icmp6_seq) <= ( n_short )max_seq_sent ) )
( seqmap_value != NULL ) )
{
/* this is a response to a ping we sent */
h = table[ntohs(sent_icmp->icmp6_seq) % num_hosts];
if( p->icmp6_code > ICMP_UNREACH_MAXTYPE )
{
fprintf( stderr, "ICMP Unreachable (Invalid Code) from %s for ICMP Echo sent to %s",
print_warning("ICMP Unreachable (Invalid Code) from %s for ICMP Echo sent to %s",
addr_ascii, h->host );
#endif
}/* IF */
else
{
fprintf( stderr, "%s from %s for ICMP Echo sent to %s",
print_warning("%s from %s for ICMP Echo sent to %s",
#ifndef IPV6
icmp_unreach_str[p->icmp_code], inet_ntoa( addr->sin_addr ), h->host );
#else
@@ -1945,12 +1832,12 @@ int handle_random_icmp( FPING_ICMPHDR *p, int psize, FPING_SOCKADDR *addr )
if( inet_addr( h->host ) == -1 )
#ifndef IPV6
fprintf( stderr, " (%s)", inet_ntoa( h->saddr.sin_addr ) );
print_warning(" (%s)", inet_ntoa( h->saddr.sin_addr ) );
#else
fprintf( stderr, " (%s)", addr_ascii);
print_warning(" (%s)", addr_ascii);
#endif
fprintf( stderr, "\n" );
print_warning("\n" );
}/* IF */
@@ -1962,21 +1849,25 @@ int handle_random_icmp( FPING_ICMPHDR *p, int psize, FPING_SOCKADDR *addr )
case ICMP_PARAMPROB:
sent_icmp = ( FPING_ICMPHDR* )( c + 28 );
#ifndef IPV6
seqmap_value = seqmap_fetch(ntohs(sent_icmp->icmp_seq), &current_time);
if( ( sent_icmp->icmp_type == ICMP_ECHO ) &&
( ntohs(sent_icmp->icmp_id) == ident ) &&
( ntohs(sent_icmp->icmp_seq) <= ( n_short )max_seq_sent ) )
( seqmap_value != NULL ) )
{
/* this is a response to a ping we sent */
h = table[ntohs(sent_icmp->icmp_seq) % num_hosts];
h = table[seqmap_value->host_nr];
fprintf( stderr, "%s from %s for ICMP Echo sent to %s",
icmp_type_str[p->icmp_type], inet_ntoa( addr->sin_addr ), h->host );
if( inet_addr( h->host ) == -1 )
fprintf( stderr, " (%s)", inet_ntoa( h->saddr.sin_addr ) );
#else
seqmap_value = seqmap_fetch(ntohs(sent_icmp->icmp6_seq), &current_time);
if( ( sent_icmp->icmp6_type == ICMP_ECHO ) &&
( ntohs(sent_icmp->icmp6_id) == ident ) &&
( ntohs(sent_icmp->icmp6_seq) <= ( n_short )max_seq_sent ) )
( seqmap_value != NULL ) )
{
/* this is a response to a ping we sent */
h = table[ntohs(sent_icmp->icmp6_seq) % num_hosts];
@@ -2088,11 +1979,14 @@ void add_name( char *name )
/* input name is an IP addr, go with it */
if( name_flag )
{
if( addr_flag )
add_addr( name, na_cat( get_host_by_address( *ipa ), *ipa ), *ipa );
if( addr_flag ) {
char namebuf[256];
snprintf(namebuf, 256, "%s (%s)", get_host_by_address(*ipa), name);
add_addr(name, namebuf, *ipa);
}
else
{
nm = cpystr( get_host_by_address( *ipa ) );
nm = get_host_by_address( *ipa );
add_addr( name, nm, *ipa );
}/* ELSE */
@@ -2125,36 +2019,39 @@ void add_name( char *name )
if( getnetgrent( &machine, &user_ignored, &domain_ignored ) == 0 )
{
endnetgrent();
if( !quiet_flag )
fprintf( stderr, "%s address not found\n", name );
print_warning("%s address not found\n", name );
num_noaddress++;
return;
}/* IF */
else
add_name( cpystr( machine ) );
add_name(machine);
while( getnetgrent( &machine, &user_ignored, &domain_ignored ) )
add_name( cpystr( machine ) );
add_name(machine);
endnetgrent();
return;
#else
if( !quiet_flag )
fprintf( stderr, "%s address not found\n", name );
print_warning("%s address not found\n", name );
num_noaddress++;
return ;
#endif /* NIS_GROUPS */
}/* IF */
}/* IF */
if(host_ent->h_addrtype != AF_INET) {
print_warning("%s: IPv6 address returned by gethostbyname (options inet6 in resolv.conf?)\n", name );
num_noaddress++;
return;
}
host_add = ( struct in_addr* )*( host_ent->h_addr_list );
if( host_add == NULL )
{
if( !quiet_flag )
fprintf( stderr, "%s has no address data\n", name );
print_warning("%s has no address data\n", name );
num_noaddress++;
return;
@@ -2165,11 +2062,15 @@ void add_name( char *name )
/* it is indeed a hostname with a real address */
while( host_add )
{
if( name_flag && addr_flag )
add_addr( name, na_cat( name, *host_add ), *host_add );
if( name_flag && addr_flag ) {
char namebuf[256];
nm = inet_ntoa(*host_add);
snprintf(namebuf, 256, "%s (%s)", name, nm);
add_addr( name, namebuf, *host_add );
}
else if( addr_flag )
{
nm = cpystr( inet_ntoa( *host_add ) );
nm = inet_ntoa(*host_add);
add_addr( name, nm, *host_add );
}/* ELSE IF */
else
@@ -2183,76 +2084,78 @@ void add_name( char *name )
}/* WHILE */
}/* ELSE */
#else
FPING_SOCKADDR dst;
struct addrinfo *res, hints;
int ret_ga;
char *hostname;
size_t len;
FPING_SOCKADDR dst;
struct addrinfo *res, hints;
int ret_ga;
size_t len;
char *printname;
char namebuf[256];
char addrbuf[256];
/* getaddrinfo */
bzero(&hints, sizeof(struct addrinfo));
hints.ai_flags = name_flag ? AI_CANONNAME : 0;
hints.ai_flags = 0;
hints.ai_family = AF_INET6;
hints.ai_socktype = SOCK_RAW;
hints.ai_protocol = IPPROTO_ICMPV6;
ret_ga = getaddrinfo(name, NULL, &hints, &res);
if (ret_ga) {
if(!quiet_flag)
warnx("%s", gai_strerror(ret_ga));
num_noaddress++;
return;
}
if (res->ai_canonname) hostname = res->ai_canonname;
else hostname = name;
if (!res->ai_addr) {
if(!quiet_flag)
warnx("getaddrinfo failed");
print_warning("%s: %s\n", name, gai_strerror(ret_ga));
num_noaddress++;
return;
}
len = res->ai_addrlen;
if (len > sizeof(FPING_SOCKADDR)) len = sizeof(FPING_SOCKADDR);
(void)memcpy(&dst, res->ai_addr, len);
add_addr(name, name, &dst);
/* name_flag: addr -> name lookup requested) */
if(!name_flag) {
printname = name;
}
else {
int ret;
ret = getnameinfo(res->ai_addr, res->ai_addrlen, namebuf,
sizeof(namebuf)/sizeof(char), NULL, 0, 0);
if (ret) {
if(!quiet_flag) {
print_warning("%s: %s\n", name, gai_strerror(ret_ga));
}
num_noaddress++;
return;
}
printname = namebuf;
}
/* addr_flag: name -> addr lookup requested */
if(addr_flag) {
int ret;
ret = getnameinfo(res->ai_addr, res->ai_addrlen, addrbuf,
sizeof(addrbuf)/sizeof(char), NULL, 0, NI_NUMERICHOST);
if (ret) {
if(!quiet_flag) {
print_warning("%s: %s\n", name, gai_strerror(ret_ga));
}
num_noaddress++;
return;
}
if(name_flag) {
char nameaddrbuf[512];
snprintf(nameaddrbuf, sizeof(nameaddrbuf)/sizeof(char), "%s (%s)", printname, addrbuf);
add_addr(name, nameaddrbuf, &dst);
}
else {
add_addr(name, addrbuf, &dst);
}
}
else {
add_addr(name, printname, &dst);
}
#endif
} /* add_name() */
/************************************************************
Function: na_cat
*************************************************************
Inputs: char* name, struct in_addr ipaddr
Returns: char*
Description:
************************************************************/
char *na_cat( char *name, struct in_addr ipaddr )
{
char *nm, *as;
as = inet_ntoa( ipaddr );
nm = ( char* )malloc( strlen( name ) + strlen( as ) + 4 );
if( !nm )
crash_and_burn( "can't allocate some space for a string" );
strcpy( nm, name );
strcat( nm, " (" );
strcat( nm, as );
strcat( nm, ")" );
return( nm );
} /* na_cat() */
/************************************************************
Function: add_addr
@@ -2283,8 +2186,8 @@ void add_addr( char *name, char *host, FPING_SOCKADDR *ipaddr )
memset( ( char* ) p, 0, sizeof( HOST_ENTRY ) );
p->name = name;
p->host = host;
p->name = strdup(name);
p->host = strdup(host);
#ifndef IPV6
p->saddr.sin_family = AF_INET;
p->saddr.sin_addr = ipaddr;
@@ -2294,7 +2197,7 @@ void add_addr( char *name, char *host, FPING_SOCKADDR *ipaddr )
#endif
p->timeout = timeout;
p->running = 1;
p->min_reply = 10000000;
p->min_reply = 0;
if( strlen( p->host ) > max_hostname_len )
max_hostname_len = strlen( p->host );
@@ -2398,41 +2301,6 @@ char *get_host_by_address( struct in_addr in )
} /* get_host_by_address() */
/************************************************************
Function: cpystr
*************************************************************
Inputs: char* string
Returns: char*
Description:
************************************************************/
char *cpystr( char *string )
{
char *dst;
if( string )
{
dst = ( char* )malloc( 1 + strlen( string ) );
if( !dst )
crash_and_burn( "can't allocate some space for a string" );
strcpy( dst, string );
return dst;
}/* IF */
else
return NULL;
} /* cpystr() */
/************************************************************
Function: crash_and_burn
@@ -2474,6 +2342,25 @@ void errno_crash_and_burn( char *message )
} /* errno_crash_and_burn() */
/************************************************************
Function: print_warning
Description: fprintf(stderr, ...), unless running with -q
*************************************************************/
void print_warning(char *format, ...) {
va_list args;
if(!quiet_flag) {
va_start(args, format );
vfprintf(stderr, format, args);
va_end(args);
}
}
/************************************************************
Function: timeval_diff
@@ -2539,36 +2426,32 @@ char * sprint_tm( int t )
{
static char buf[10];
/* <= 0.99 ms */
if( t < 100 )
{
if( t < 0 ) {
/* negative (unexpected) */
sprintf( buf, "%.2g", (double) t / 100 );
}
else if( t < 100 ) {
/* <= 0.99 ms */
sprintf( buf, "0.%02d", t );
return( buf );
}/* IF */
/* 1.00 - 9.99 ms */
if( t < 1000 )
{
}
else if( t < 1000 ) {
/* 1.00 - 9.99 ms */
sprintf( buf, "%d.%02d", t / 100, t % 100 );
return( buf );
}/* IF */
/* 10.0 - 99.9 ms */
if( t < 10000 )
{
}
else if( t < 10000 ) {
/* 10.0 - 99.9 ms */
sprintf( buf, "%d.%d", t / 100, ( t % 100 ) / 10 );
return( buf );
}/* IF */
/* >= 100 ms */
sprintf( buf, "%d", t / 100 );
}
else if( t < 100000000 ) {
/* 100 - 1'000'000 ms */
sprintf( buf, "%d", t / 100 );
}
else {
sprintf( buf, "%.2e", (double) (t / 100) );
}
return( buf );
} /* sprint_tm() */
}
/************************************************************
@@ -2810,10 +2693,11 @@ void usage(int is_error)
fprintf(out, "Usage: %s [options] [targets...]\n", prog );
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", ping_data_size );
fprintf(out, " -b n amount of ping data to send, in bytes (default %d)\n", DEFAULT_PING_DATA_SIZE);
fprintf(out, " -B f set exponential backoff factor to f\n" );
fprintf(out, " -c n count of pings to send to each target (default %d)\n", count );
fprintf(out, " -C n same as -c, report results in verbose format\n" );
fprintf(out, " -D print timestamp before each output line\n" );
fprintf(out, " -e show elapsed time on return packets\n" );
fprintf(out, " -f file read list of targets from a file ( - means stdin) (only if no -g specified)\n" );
fprintf(out, " -g generate target list (only if no -f specified)\n" );
+27
View File
@@ -0,0 +1,27 @@
#ifndef _FPING_H
#define _FPING_H
#define __APPLE_USE_RFC_3542 1
#include <sys/socket.h>
#include <netinet/in.h>
#ifndef IPV6
#define FPING_SOCKADDR struct sockaddr_in
#define FPING_INADDR struct in_addr
#define FPING_ICMPHDR struct icmp
#else
#define FPING_SOCKADDR struct sockaddr_in6
#define FPING_INADDR struct in6_addr
#define FPING_ICMPHDR struct icmp6_hdr
#endif
/* fping.c */
void crash_and_burn( char *message );
void errno_crash_and_burn( char *message );
/* socket.c */
int open_ping_socket();
void socket_set_src_addr(int s, FPING_INADDR src_addr);
#endif
+119
View File
@@ -0,0 +1,119 @@
/*
* fping: fast-ping, file-ping, favorite-ping, funky-ping
*
* Ping a list of target hosts in a round robin fashion.
* A better ping overall.
*
* fping website: http://www.fping.org
*
* Current maintainer of fping: David Schweikert
* Please send suggestions and patches to: david@schweikert.ch
*
*
* Original author: Roland Schemers <schemers@stanford.edu>
* IPv6 Support: Jeroen Massar <jeroen@unfix.org / jeroen@ipng.nl>
* Improved main loop: David Schweikert <david@schweikert.ch>
* Debian Merge, TOS settings: Tobi Oetiker <tobi@oetiker.ch>
* Bugfixes, byte order & senseful seq.-numbers: Stephan Fuhrmann (stephan.fuhrmann AT 1und1.de)
*
*
* Redistribution and use in source and binary forms are permitted
* provided that the above copyright notice and this paragraph are
* duplicated in all such forms and that any documentation,
* advertising materials, and other materials related to such
* distribution and use acknowledge that the software was developed
* by Stanford University. The name of the University may not be used
* to endorse or promote products derived from this software without
* specific prior written permission.
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*
* seqmap.c: implementation of a mapping between sequence number and (host, ping_nr)
* we can't just use ping_nr*host_count + host_nr, because it can
* overflow the 16 bit of the icmp header field. See also:
* https://github.com/schweikert/fping/issues/48
*/
#include "seqmap.h"
#include "options.h"
#include "limits.h"
#include <stdlib.h>
#include <stdio.h>
/* description of the data structure used:
*
* - we assume that no more than SEQMAP_MAXSEQ (65535) pings are sent in
* the timeout interval (SEQMAP_TIMEOUT_IN_S)
* - we store the values in an array with SEQMAP_MAXSEQ elements
* - current sequence number % SEQMAP_MAXSEQ gives the current index
* - when entering a value, we check that the current entry is expired
*/
static SEQMAP_VALUE *seqmap_map = NULL;
static unsigned int seqmap_next_id = 0;
static SEQMAP_VALUE *seqmap_free_list;
#define SEQMAP_TIMEOUT_IN_S 10
#define SEQMAP_UNASSIGNED_HOST_NR UINT_MAX
void seqmap_init()
{
unsigned int i;
seqmap_map = calloc(SEQMAP_MAXSEQ, sizeof(SEQMAP_VALUE));
if(seqmap_map == NULL) {
perror("malloc error (can't allocate seqmap_map)");
}
}
unsigned int seqmap_add(unsigned int host_nr, unsigned int ping_count, struct timeval *now)
{
unsigned int current_id;
SEQMAP_VALUE *next_value;
if(!seqmap_map) {
fprintf(stderr, "fping internal error: seqmap not initialized.\n");
exit(4);
}
/* check if expired (note that unused seqmap values will have fields set to
* 0, so will be seen as expired */
next_value = &seqmap_map[seqmap_next_id];
if(next_value->ping_ts.tv_sec != 0 && (now->tv_sec - next_value->ping_ts.tv_sec) < SEQMAP_TIMEOUT_IN_S) {
fprintf(stderr, "fping error: not enough sequence numbers available! (expire_timeout=%d, host_nr=%d, ping_count=%d, seqmap_next_id=%d)\n",
SEQMAP_TIMEOUT_IN_S, host_nr, ping_count, seqmap_next_id);
exit(4);
}
/* store the value */
next_value->host_nr = host_nr;
next_value->ping_count = ping_count;
next_value->ping_ts.tv_sec = now->tv_sec;
next_value->ping_ts.tv_usec = now->tv_usec;
/* increase next id */
current_id = seqmap_next_id;
seqmap_next_id = (seqmap_next_id + 1) % SEQMAP_MAXSEQ;
return current_id;
}
SEQMAP_VALUE *seqmap_fetch(unsigned int id, struct timeval *now)
{
SEQMAP_VALUE *value;
if(id > SEQMAP_MAXSEQ) {
return NULL;
}
value = &seqmap_map[id];
/* verify that value is not expired */
if(now->tv_sec - value->ping_ts.tv_sec >= SEQMAP_TIMEOUT_IN_S) {
return NULL;
}
return value;
}
+20
View File
@@ -0,0 +1,20 @@
#ifndef SEQMAP_H
#define SEQMAP_H
#include <sys/time.h>
typedef struct seqmap_value
{
unsigned int host_nr;
unsigned int ping_count;
struct timeval ping_ts;
} SEQMAP_VALUE;
#define SEQMAP_MAXSEQ 65535
void seqmap_init();
unsigned int seqmap_add(unsigned int host_nr, unsigned int ping_count, struct timeval *now);
SEQMAP_VALUE *seqmap_fetch(unsigned int id, struct timeval *now);
#endif
+57
View File
@@ -0,0 +1,57 @@
/*
* fping: fast-ping, file-ping, favorite-ping, funky-ping
*
* Ping a list of target hosts in a round robin fashion.
* A better ping overall.
*
* fping website: http://www.fping.org
*
* Current maintainer of fping: David Schweikert
* Please send suggestions and patches to: david@schweikert.ch
*
*
* Original author: Roland Schemers <schemers@stanford.edu>
* IPv6 Support: Jeroen Massar <jeroen@unfix.org / jeroen@ipng.nl>
* Improved main loop: David Schweikert <david@schweikert.ch>
* Debian Merge, TOS settings: Tobi Oetiker <tobi@oetiker.ch>
* Bugfixes, byte order & senseful seq.-numbers: Stephan Fuhrmann (stephan.fuhrmann AT 1und1.de)
*
*
* Redistribution and use in source and binary forms are permitted
* provided that the above copyright notice and this paragraph are
* duplicated in all such forms and that any documentation,
* advertising materials, and other materials related to such
* distribution and use acknowledge that the software was developed
* by Stanford University. The name of the University may not be used
* to endorse or promote products derived from this software without
* specific prior written permission.
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*/
#include "fping.h"
#include "config.h"
int open_ping_socket_ipv4();
int open_ping_socket_ipv6();
void socket_set_src_addr_ipv4(int s, FPING_INADDR src_addr);
void socket_set_src_addr_ipv6(int s, FPING_INADDR src_addr);
int open_ping_socket()
{
#ifndef IPV6
return open_ping_socket_ipv4();
#else
return open_ping_socket_ipv6();
#endif
}
void socket_set_src_addr(int s, FPING_INADDR src_addr)
{
#ifndef IPV6
socket_set_src_addr_ipv4(s, src_addr);
#else
socket_set_src_addr_ipv6(s, src_addr);
#endif
}
+73
View File
@@ -0,0 +1,73 @@
/*
* fping: fast-ping, file-ping, favorite-ping, funky-ping
*
* Ping a list of target hosts in a round robin fashion.
* A better ping overall.
*
* fping website: http://www.fping.org
*
* Current maintainer of fping: David Schweikert
* Please send suggestions and patches to: david@schweikert.ch
*
*
* Original author: Roland Schemers <schemers@stanford.edu>
* IPv6 Support: Jeroen Massar <jeroen@unfix.org / jeroen@ipng.nl>
* Improved main loop: David Schweikert <david@schweikert.ch>
* Debian Merge, TOS settings: Tobi Oetiker <tobi@oetiker.ch>
* Bugfixes, byte order & senseful seq.-numbers: Stephan Fuhrmann (stephan.fuhrmann AT 1und1.de)
*
*
* Redistribution and use in source and binary forms are permitted
* provided that the above copyright notice and this paragraph are
* duplicated in all such forms and that any documentation,
* advertising materials, and other materials related to such
* distribution and use acknowledge that the software was developed
* by Stanford University. The name of the University may not be used
* to endorse or promote products derived from this software without
* specific prior written permission.
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*/
#include "fping.h"
#include "config.h"
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <stdio.h>
#include <string.h>
int open_ping_socket_ipv4()
{
struct protoent *proto;
int s;
/* confirm that ICMP is available on this machine */
if( ( proto = getprotobyname( "icmp" ) ) == NULL )
crash_and_burn( "icmp: unknown protocol" );
/* create raw socket for ICMP calls (ping) */
s = socket( AF_INET, SOCK_RAW, proto->p_proto );
if( s < 0 ) {
/* try non-privileged icmp (works on Mac OSX without privileges, for example) */
s = socket( AF_INET, SOCK_DGRAM, proto->p_proto );
if( s < 0 ) {
errno_crash_and_burn( "can't create socket (must run as root?)" );
}
}
return s;
}
void socket_set_src_addr_ipv4(int s, FPING_INADDR src_addr)
{
struct sockaddr_in sa;
memset( &sa, 0, sizeof( sa ) );
sa.sin_family = AF_INET;
sa.sin_addr = src_addr;
if ( bind( s, (struct sockaddr *)&sa, sizeof( sa ) ) < 0 )
errno_crash_and_burn( "cannot bind source address" );
}
+76
View File
@@ -0,0 +1,76 @@
/*
* fping: fast-ping, file-ping, favorite-ping, funky-ping
*
* Ping a list of target hosts in a round robin fashion.
* A better ping overall.
*
* fping website: http://www.fping.org
*
* Current maintainer of fping: David Schweikert
* Please send suggestions and patches to: david@schweikert.ch
*
*
* Original author: Roland Schemers <schemers@stanford.edu>
* IPv6 Support: Jeroen Massar <jeroen@unfix.org / jeroen@ipng.nl>
* Improved main loop: David Schweikert <david@schweikert.ch>
* Debian Merge, TOS settings: Tobi Oetiker <tobi@oetiker.ch>
* Bugfixes, byte order & senseful seq.-numbers: Stephan Fuhrmann (stephan.fuhrmann AT 1und1.de)
*
*
* Redistribution and use in source and binary forms are permitted
* provided that the above copyright notice and this paragraph are
* duplicated in all such forms and that any documentation,
* advertising materials, and other materials related to such
* distribution and use acknowledge that the software was developed
* by Stanford University. The name of the University may not be used
* to endorse or promote products derived from this software without
* specific prior written permission.
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*/
#include "fping.h"
#include "config.h"
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <stdio.h>
#include <string.h>
#include <netinet/icmp6.h>
int open_ping_socket_ipv6()
{
struct protoent *proto;
int opton = 1;
int s;
/* confirm that ICMP is available on this machine */
if( ( proto = getprotobyname( "ipv6-icmp" ) ) == NULL )
crash_and_burn( "icmp: unknown protocol" );
/* create raw socket for ICMP calls (ping) */
s = socket( AF_INET6, SOCK_RAW, proto->p_proto );
if( s < 0 ) {
/* try non-privileged icmp (works on Mac OSX without privileges, for example) */
s = socket( AF_INET6, SOCK_DGRAM, proto->p_proto );
if( s < 0 ) {
errno_crash_and_burn( "can't create raw socket (must run as root?)" );
}
}
return s;
}
void socket_set_src_addr_ipv6(int s, FPING_INADDR src_addr)
{
struct sockaddr_in6 sa;
memset( &sa, 0, sizeof( sa ) );
sa.sin6_family = AF_INET6;
sa.sin6_addr = src_addr;
if ( bind( s, (struct sockaddr *)&sa, sizeof( sa ) ) < 0 )
errno_crash_and_burn( "cannot bind source address" );
}