]> git.gsnw.org Git - fping.git/commitdiff
Fix changelog entry for the new -p lower limit v5.4
authorDavid Schweikert <david@schweikert.ch>
Tue, 19 Aug 2025 08:05:27 +0000 (10:05 +0200)
committerDavid Schweikert <david@schweikert.ch>
Tue, 19 Aug 2025 08:07:34 +0000 (10:07 +0200)
115 files changed:
CHANGELOG.md
ci/tmp.4rIIEYCP9c/fping-5.3/CHANGELOG.md [new file with mode: 0644]
ci/tmp.4rIIEYCP9c/fping-5.3/COPYING [new file with mode: 0644]
ci/tmp.4rIIEYCP9c/fping-5.3/INSTALL [new file with mode: 0644]
ci/tmp.4rIIEYCP9c/fping-5.3/Makefile.am [new file with mode: 0644]
ci/tmp.4rIIEYCP9c/fping-5.3/README.md [new file with mode: 0644]
ci/tmp.4rIIEYCP9c/fping-5.3/ci/build-1-autotools.sh [new file with mode: 0755]
ci/tmp.4rIIEYCP9c/fping-5.3/ci/build-2-test-command.sh [new file with mode: 0755]
ci/tmp.4rIIEYCP9c/fping-5.3/ci/build-3-prepare-macos.sh [new file with mode: 0755]
ci/tmp.4rIIEYCP9c/fping-5.3/ci/build-4-compile.sh [new file with mode: 0755]
ci/tmp.4rIIEYCP9c/fping-5.3/ci/deploy-bintray.sh [new file with mode: 0755]
ci/tmp.4rIIEYCP9c/fping-5.3/ci/deploy-coveralls.sh [new file with mode: 0755]
ci/tmp.4rIIEYCP9c/fping-5.3/ci/deploy-coverity.sh [new file with mode: 0755]
ci/tmp.4rIIEYCP9c/fping-5.3/ci/prepare-linux.sh [new file with mode: 0755]
ci/tmp.4rIIEYCP9c/fping-5.3/ci/run-lcov.sh [new file with mode: 0755]
ci/tmp.4rIIEYCP9c/fping-5.3/ci/run-tests.sh [new file with mode: 0755]
ci/tmp.4rIIEYCP9c/fping-5.3/ci/test-01-basics.pl [new file with mode: 0755]
ci/tmp.4rIIEYCP9c/fping-5.3/ci/test-02-help.pl [new file with mode: 0755]
ci/tmp.4rIIEYCP9c/fping-5.3/ci/test-03-forbidden.pl [new file with mode: 0755]
ci/tmp.4rIIEYCP9c/fping-5.3/ci/test-04-options-a-b.pl [new file with mode: 0755]
ci/tmp.4rIIEYCP9c/fping-5.3/ci/test-05-options-c-e.pl [new file with mode: 0755]
ci/tmp.4rIIEYCP9c/fping-5.3/ci/test-06-options-f-h.pl [new file with mode: 0755]
ci/tmp.4rIIEYCP9c/fping-5.3/ci/test-07-options-i-m.pl [new file with mode: 0755]
ci/tmp.4rIIEYCP9c/fping-5.3/ci/test-08-options-n-q.pl [new file with mode: 0755]
ci/tmp.4rIIEYCP9c/fping-5.3/ci/test-09-option-r-t.pl [new file with mode: 0755]
ci/tmp.4rIIEYCP9c/fping-5.3/ci/test-10-option-u-x.pl [new file with mode: 0755]
ci/tmp.4rIIEYCP9c/fping-5.3/ci/test-11-unpriv.pl [new file with mode: 0755]
ci/tmp.4rIIEYCP9c/fping-5.3/ci/test-12-option-type.pl [new file with mode: 0755]
ci/tmp.4rIIEYCP9c/fping-5.3/ci/test-13-unknown-host.pl [new file with mode: 0755]
ci/tmp.4rIIEYCP9c/fping-5.3/ci/test-14-ping-internet-hosts.pl [new file with mode: 0755]
ci/tmp.4rIIEYCP9c/fping-5.3/ci/test-15-netdata.pl [new file with mode: 0755]
ci/tmp.4rIIEYCP9c/fping-5.3/ci/test-issue-56.pl [new file with mode: 0755]
ci/tmp.4rIIEYCP9c/fping-5.3/ci/test-issue-58.pl [new file with mode: 0755]
ci/tmp.4rIIEYCP9c/fping-5.3/ci/test-tarball.sh [new file with mode: 0755]
ci/tmp.4rIIEYCP9c/fping-5.3/configure.ac [new file with mode: 0644]
ci/tmp.4rIIEYCP9c/fping-5.3/contrib/Dockerfile [new file with mode: 0644]
ci/tmp.4rIIEYCP9c/fping-5.3/contrib/fping.spec [new file with mode: 0644]
ci/tmp.4rIIEYCP9c/fping-5.3/doc/CHANGELOG.pre-v4 [new file with mode: 0644]
ci/tmp.4rIIEYCP9c/fping-5.3/doc/Makefile.am [new file with mode: 0644]
ci/tmp.4rIIEYCP9c/fping-5.3/doc/README.1992 [new file with mode: 0644]
ci/tmp.4rIIEYCP9c/fping-5.3/doc/fping.8 [new file with mode: 0644]
ci/tmp.4rIIEYCP9c/fping-5.3/doc/fping.pod [new file with mode: 0644]
ci/tmp.4rIIEYCP9c/fping-5.3/src/Makefile.am [new file with mode: 0644]
ci/tmp.4rIIEYCP9c/fping-5.3/src/fping [new file with mode: 0755]
ci/tmp.4rIIEYCP9c/fping-5.3/src/fping-fping.o [new file with mode: 0644]
ci/tmp.4rIIEYCP9c/fping-5.3/src/fping-optparse.o [new file with mode: 0644]
ci/tmp.4rIIEYCP9c/fping-5.3/src/fping-seqmap.o [new file with mode: 0644]
ci/tmp.4rIIEYCP9c/fping-5.3/src/fping-socket4.o [new file with mode: 0644]
ci/tmp.4rIIEYCP9c/fping-5.3/src/fping-socket6.o [new file with mode: 0644]
ci/tmp.4rIIEYCP9c/fping-5.3/src/fping.c [new file with mode: 0644]
ci/tmp.4rIIEYCP9c/fping-5.3/src/fping.h [new file with mode: 0644]
ci/tmp.4rIIEYCP9c/fping-5.3/src/options.h [new file with mode: 0644]
ci/tmp.4rIIEYCP9c/fping-5.3/src/optparse.c [new file with mode: 0644]
ci/tmp.4rIIEYCP9c/fping-5.3/src/optparse.h [new file with mode: 0644]
ci/tmp.4rIIEYCP9c/fping-5.3/src/seqmap.c [new file with mode: 0644]
ci/tmp.4rIIEYCP9c/fping-5.3/src/seqmap.h [new file with mode: 0644]
ci/tmp.4rIIEYCP9c/fping-5.3/src/socket4.c [new file with mode: 0644]
ci/tmp.4rIIEYCP9c/fping-5.3/src/socket6.c [new file with mode: 0644]
ci/tmp.VwGIuQgZdr/fping-5.4/CHANGELOG.md [new file with mode: 0644]
ci/tmp.VwGIuQgZdr/fping-5.4/COPYING [new file with mode: 0644]
ci/tmp.VwGIuQgZdr/fping-5.4/INSTALL [new file with mode: 0644]
ci/tmp.VwGIuQgZdr/fping-5.4/Makefile.am [new file with mode: 0644]
ci/tmp.VwGIuQgZdr/fping-5.4/README.md [new file with mode: 0644]
ci/tmp.VwGIuQgZdr/fping-5.4/ci/build-1-autotools.sh [new file with mode: 0755]
ci/tmp.VwGIuQgZdr/fping-5.4/ci/build-2-test-command.sh [new file with mode: 0755]
ci/tmp.VwGIuQgZdr/fping-5.4/ci/build-3-prepare-macos.sh [new file with mode: 0755]
ci/tmp.VwGIuQgZdr/fping-5.4/ci/build-4-compile.sh [new file with mode: 0755]
ci/tmp.VwGIuQgZdr/fping-5.4/ci/deploy-bintray.sh [new file with mode: 0755]
ci/tmp.VwGIuQgZdr/fping-5.4/ci/deploy-coveralls.sh [new file with mode: 0755]
ci/tmp.VwGIuQgZdr/fping-5.4/ci/deploy-coverity.sh [new file with mode: 0755]
ci/tmp.VwGIuQgZdr/fping-5.4/ci/prepare-linux.sh [new file with mode: 0755]
ci/tmp.VwGIuQgZdr/fping-5.4/ci/run-lcov.sh [new file with mode: 0755]
ci/tmp.VwGIuQgZdr/fping-5.4/ci/run-tests.sh [new file with mode: 0755]
ci/tmp.VwGIuQgZdr/fping-5.4/ci/test-01-basics.pl [new file with mode: 0755]
ci/tmp.VwGIuQgZdr/fping-5.4/ci/test-02-help.pl [new file with mode: 0755]
ci/tmp.VwGIuQgZdr/fping-5.4/ci/test-03-forbidden.pl [new file with mode: 0755]
ci/tmp.VwGIuQgZdr/fping-5.4/ci/test-04-options-a-b.pl [new file with mode: 0755]
ci/tmp.VwGIuQgZdr/fping-5.4/ci/test-05-options-c-e.pl [new file with mode: 0755]
ci/tmp.VwGIuQgZdr/fping-5.4/ci/test-06-options-f-h.pl [new file with mode: 0755]
ci/tmp.VwGIuQgZdr/fping-5.4/ci/test-07-options-i-m.pl [new file with mode: 0755]
ci/tmp.VwGIuQgZdr/fping-5.4/ci/test-08-options-n-q.pl [new file with mode: 0755]
ci/tmp.VwGIuQgZdr/fping-5.4/ci/test-09-option-r-t.pl [new file with mode: 0755]
ci/tmp.VwGIuQgZdr/fping-5.4/ci/test-10-option-u-x.pl [new file with mode: 0755]
ci/tmp.VwGIuQgZdr/fping-5.4/ci/test-11-unpriv.pl [new file with mode: 0755]
ci/tmp.VwGIuQgZdr/fping-5.4/ci/test-12-option-type.pl [new file with mode: 0755]
ci/tmp.VwGIuQgZdr/fping-5.4/ci/test-13-unknown-host.pl [new file with mode: 0755]
ci/tmp.VwGIuQgZdr/fping-5.4/ci/test-14-ping-internet-hosts.pl [new file with mode: 0755]
ci/tmp.VwGIuQgZdr/fping-5.4/ci/test-15-netdata.pl [new file with mode: 0755]
ci/tmp.VwGIuQgZdr/fping-5.4/ci/test-issue-56.pl [new file with mode: 0755]
ci/tmp.VwGIuQgZdr/fping-5.4/ci/test-issue-58.pl [new file with mode: 0755]
ci/tmp.VwGIuQgZdr/fping-5.4/ci/test-tarball.sh [new file with mode: 0755]
ci/tmp.VwGIuQgZdr/fping-5.4/configure.ac [new file with mode: 0644]
ci/tmp.VwGIuQgZdr/fping-5.4/contrib/Dockerfile [new file with mode: 0644]
ci/tmp.VwGIuQgZdr/fping-5.4/contrib/fping.spec [new file with mode: 0644]
ci/tmp.VwGIuQgZdr/fping-5.4/doc/CHANGELOG.pre-v4 [new file with mode: 0644]
ci/tmp.VwGIuQgZdr/fping-5.4/doc/Makefile.am [new file with mode: 0644]
ci/tmp.VwGIuQgZdr/fping-5.4/doc/README.1992 [new file with mode: 0644]
ci/tmp.VwGIuQgZdr/fping-5.4/doc/fping.8 [new file with mode: 0644]
ci/tmp.VwGIuQgZdr/fping-5.4/doc/fping.pod [new file with mode: 0644]
ci/tmp.VwGIuQgZdr/fping-5.4/src/Makefile.am [new file with mode: 0644]
ci/tmp.VwGIuQgZdr/fping-5.4/src/fping [new file with mode: 0755]
ci/tmp.VwGIuQgZdr/fping-5.4/src/fping-fping.o [new file with mode: 0644]
ci/tmp.VwGIuQgZdr/fping-5.4/src/fping-optparse.o [new file with mode: 0644]
ci/tmp.VwGIuQgZdr/fping-5.4/src/fping-seqmap.o [new file with mode: 0644]
ci/tmp.VwGIuQgZdr/fping-5.4/src/fping-socket4.o [new file with mode: 0644]
ci/tmp.VwGIuQgZdr/fping-5.4/src/fping-socket6.o [new file with mode: 0644]
ci/tmp.VwGIuQgZdr/fping-5.4/src/fping.c [new file with mode: 0644]
ci/tmp.VwGIuQgZdr/fping-5.4/src/fping.h [new file with mode: 0644]
ci/tmp.VwGIuQgZdr/fping-5.4/src/options.h [new file with mode: 0644]
ci/tmp.VwGIuQgZdr/fping-5.4/src/optparse.c [new file with mode: 0644]
ci/tmp.VwGIuQgZdr/fping-5.4/src/optparse.h [new file with mode: 0644]
ci/tmp.VwGIuQgZdr/fping-5.4/src/seqmap.c [new file with mode: 0644]
ci/tmp.VwGIuQgZdr/fping-5.4/src/seqmap.h [new file with mode: 0644]
ci/tmp.VwGIuQgZdr/fping-5.4/src/socket4.c [new file with mode: 0644]
ci/tmp.VwGIuQgZdr/fping-5.4/src/socket6.c [new file with mode: 0644]

index 7cd88bc478926d018c2566f60acad99b367662c9..07434d8ac5b7b386a5f5fedc163ea2c1bb7a312f 100644 (file)
@@ -5,9 +5,9 @@ fping 5.4 (2025-08-19)
 
 - Memory allocation safety checks for event storage (thanks David.A for bug report)
 - Fix off-by-one boundary check in seqmap code (thanks David.A for bug report)
-- The minimum value for the per-host interval (-i flag) is now 0.001 (milliseconds),
-  since it probably never makes sense to use a smaller value, and to avoid trying
-  to do a too large memory allocation.
+- The minimum value for the period (-p flag) is now 0.001 milliseconds,
+  since it probably never makes sense to use a smaller value, and to avoid doing
+  a very large memory allocation for event storage.
 
 fping 5.3 (2025-01-02)
 ======================
diff --git a/ci/tmp.4rIIEYCP9c/fping-5.3/CHANGELOG.md b/ci/tmp.4rIIEYCP9c/fping-5.3/CHANGELOG.md
new file mode 100644 (file)
index 0000000..7cd88bc
--- /dev/null
@@ -0,0 +1,299 @@
+fping 5.4 (2025-08-19)
+======================
+
+## Bugfixes
+
+- Memory allocation safety checks for event storage (thanks David.A for bug report)
+- Fix off-by-one boundary check in seqmap code (thanks David.A for bug report)
+- The minimum value for the per-host interval (-i flag) is now 0.001 (milliseconds),
+  since it probably never makes sense to use a smaller value, and to avoid trying
+  to do a too large memory allocation.
+
+fping 5.3 (2025-01-02)
+======================
+
+## New features
+
+- New option --icmp-timestamp to send ICMP timestamp requests (ICMP type 13)
+  instead of ICMP Echo requests (#353 #363, thanks @auerswal and @gsnw-sebast)
+- New option --print-ttl to print returned TTL value (#354, thanks @nalves599)
+- New option --print-tos to print returned TOS value (#335 #346 #347, thanks
+  @auerswal and @gsnw-sebast)
+- New option --check-source (#334, thanks @auerswal)
+- Predefined various timestamp formats (#321, thanks @auerswal and @gsnw-sebast)
+- Print cumulative stats with -Q SECS,cumulative (#315, thanks @auerswal)
+
+## Bugfixes and other changes
+
+- ci: Upgrade actions/upload-artifact to v4 (#360, thanks @gsnw-sebast)
+- ci: Azure Pipeline only trigger when changes are made in the development branch
+  (#359, thanks @gsnw-sebast)
+- ci: Upgrade actions/upload-artifact to v3 (#355, thanks @pevik)
+- ci: Azure Pipeline YAML add docker build (#354, thanks @gsnw-sebast)
+- Dockerfile: change distribution from ubuntu to debian (#350, thanks
+  @gsnw-sebast)
+- Fix warning unused parameter 'reply_timestamp' under macOS (#348, thanks
+  @gsnw-sebast)
+- Fix increase maximum -s value to 65507 (#344, thanks @pevik)
+- ci: use File::Temp to create temporary directory (#343, thanks @auerswal)
+- Fix -k, --fwmark with setuid fping executable (#342, thanks @auerswal)
+- Another batch of additional tests (take 2) (#341, thanks @auerswal)
+- Document that -a and -u are overridden by -c and -C (#338, thanks @auerswal)
+- Fix macOS build warning sets SEQMAP_TIMEOUT_IN_NSSEQMAP_TIMEOUT_IN_NS as INT64_C
+  (#336, thanks @gsnw-sebast)
+- Fix inconsistent limits for address generation via -g, --generator using either
+  range or CIDR (#331, thanks @auerswal)
+- Some additional tests (#329, thanks @auerswal)
+- ci: skip an unreliable test on macOS (#328, thanks @auerswal)
+- Fix incorrect return-value check for a scanf like function (CWE-253) (#323,
+  thanks @gsnw-sebast)
+- A few more tests to increase code coverage a little bit (#320, thanks @auerswal)
+- Github fix: Change to codeql-action-v2 (#319, thanks @gsnw-sebast)
+- Developer function: Debug with Visual Studio Code (#318, thanks @gsnw-sebast)
+
+fping 5.2 (2024-04-21)
+======================
+
+## New features
+
+- New option -X / --fast-reachable to exit immediately once N hosts have been
+  found (#260, thanks @chriscray and @gsnw)
+
+- New option -k / -fwmark to set Linux fwmark mask (#289, thanks @tomangert and
+  @deepkv)
+
+## Bugfixes and other changes
+
+- Always output fatal error messages (#303, thanks @auerswal)
+- Fallback to SO\_TIMESTAMP if SO\_TIMESTAMPNS is not available (#279, thanks
+  @gsnw)
+- Fix "not enough sequence numbers available" error on BSD-like systems (#307,
+  thanks @cagney, @gsnw)
+- Fix running in unprivileged mode (#248, thanks @sfan5)
+- Fix build issue for NetBSD/alpha (#255, thanks @0-wiz-0)
+- Fix build issue for OpenBSD/alpha (#275, thanks @gsnw)
+- Fix build warning for long int usage (#258, thanks @gsnw)
+- Fix build error with musl libc (#263, thanks @kraj)
+- Fix to guard against division by zero (#293, thanks @auerswal)
+- Decouple -a/-u effects from -c (#298, thanks @auerswal)
+- Added contrib/Dockerfile (#224, thanks @darless)
+- Remove host from Netdata chart titles (#253, thanks @ilyam8)
+- Add additional tests (#292, #297, thanks @auerswal)
+- Update github action os images (#282, thanks @gsnw)
+- Fix Azure pipeline tests (#308, thanks @gsnw)
+- Various autoconf fixes (#286, #283, thanks @gsnw)
+- Extended configure script with --enable-debug and output cpu usage (#311,
+  thanks @gsnw)
+- Documentation: Update Netdata website link (#257, thanks @ilyam8)
+- Documentation: fix description of --file option (#268, thanks @MohGeek)
+- Documentation: improve exit status description (#294, thanks @auerswal)
+- Documentation: move description of -i MSEC (#298, thanks @auerswal)
+- Documentation: improve help output for options -c and -C (#302, #auerswal)
+
+
+fping 5.1 (2022-02-06)
+======================
+
+## Bugfixes and other changes
+
+- Use setcap to specify specific files in fping.spec (#232, thanks @zdyxry)
+- Netdata: use host instead name as family label (#226, thanks @k0ste)
+- Netdata: use formatstring macro PRId64 (#229, thanks @gsnw)
+- Allow -4 option to be given multiple times (#215, thanks @normanr)
+- Documentation fix (#208, thanks @timgates42)
+- Retain privileges until after privileged setsockopt (#200, thanks @simetnicbr)
+- Set bind to source only when option is set (#198, thanks @dinoex)
+- Update Azure test pipeline (#197, thanks @gsnw)
+- Fix getnameinfo not called properly for IPv4 (#227, thanks @aafbsd)
+- Fixed wrong timestamp under Free- and OpenBSD and macOS (#217, thanks @gsnw)
+- Documentation updates (#240, thanks @auerswal)
+- Updated autotools (autoconf 2.71, automake 1.16.5, libtool 2.4.6)
+
+
+fping 5.0 (2020-08-05)
+======================
+
+## Incompatible Changes
+
+- In non-quiet loop and count mode, a line is printed for every lost packet
+  (#175, thanks @kbucheli):
+
+  ```
+  $ fping -D -c2 8.8.8.8 8.8.8.7
+  [1596092373.18423] 8.8.8.8 : [0], 64 bytes, 12.8 ms (12.8 avg, 0% loss)
+  [1596092374.18223] 8.8.8.7 : [0], timed out (NaN avg, 100% loss)
+  [1596092374.18424] 8.8.8.8 : [1], 64 bytes, 12.3 ms (12.5 avg, 0% loss)
+  [1596092375.18344] 8.8.8.7 : [1], timed out (NaN avg, 100% loss)
+
+  8.8.8.8 : xmt/rcv/%loss = 2/2/0%, min/avg/max = 12.3/12.5/12.8
+  8.8.8.7 : xmt/rcv/%loss = 2/0/100%
+  ```
+
+- The returned size in bytes now always excludes the IP header, so if before it
+  reported '84 bytes' e.g. when using 'fping -l', now it reports '64 bytes'.
+  This is to make the reported size consistent with ping(8) from iputils and
+  also with fping when pinging a IPv6 host (which never included the IPv6
+  header size).
+
+## New features
+
+- The number of sent pings is only counted when the pings are received or have
+  timed out, ensuring that the loss ratio will be always correct. This makes it
+  possible, for example, to use loop mode (-l) with interval statistics (-Q)
+  and a timeout larger than period, without having the issue that initially
+  some pings would be reported as missing (#193)
+
+- Improved precision of measurements from 10us to 1us (#136, thanks @tycho)
+
+## Bugfixes and other changes
+
+- The reported size of received packets is now always correct on Linux even for
+  packets > 4096 bytes (#180)
+
+- Travis CI automated testing now also macos testing and additional ubuntu
+  distributions (#196)
+
+fping 4.4 (2020-07-24)
+======================
+## Bugfixes and other changes
+
+- Fix wrong ident used for normal (non-unprivileged) pings (#191, thanks @tycho)
+- Fix build with --disable-ipv6 (#187, thanks Polynomial-C)
+
+fping 4.3 (2020-07-11)
+======================
+
+## New features
+
+- Linux unprivileged ping support (#173, thanks @tycho)
+- Add SIGQUIT summary support similar to ping (#185, thanks @laddp)
+
+## Bugfixes and other changes
+
+- Corrected long option name of -s to --stats (#148, thanks @wopfel)
+- Do not fail if using fping6 with -6 flag (#149, thanks @stromnet)
+- Fail if interface binding (-I) does not work (#162, thanks @kbucheli)
+- Fix using option -4 when fping is compiled IPv4-only (#154, thanks @pbhenson)
+- Add Azure pipeline test build (#153 and #170, thanks @gsnw)
+- GCC 10 compatibility fixes (#167 and #168, thanks @cranderson)
+- Macos build fix (#174, thanks @tycho)
+- Fix xmt stats in Netdata output (#172, thanks @vlvkobal)
+- Only increase num_alive if response is not a duplicate (#151, thanks @brownowski)
+- Use line buffering for stdout (#179, thanks @bg6cq)
+
+fping 4.2 (2019-02-19)
+======================
+
+## New features
+
+- New option -x / --reachable to check if the number of reachable hosts is >= a certain
+  number. Useful for example to implement connectivity-checks (#138, thanks @deepak0004)
+
+## Bugfixes and other changes
+
+- Allow decimal numbers for '-t', '-i', '-p', and '-Q'
+- Fix build with --disable-ipv6 (#134, thanks @Polynomial-C)
+- Fix hang with '-6', with ipv6 kernel module, but not loaded (#140, thanks @abelbeck)
+- Assume '-6' if the binary is named 'fping6' (this is mostly for special
+  embedded-distro use cases, and not meant to be used generally in place of
+  compiling IPv6-only binary or using '-6', see also the notes in #139, thanks
+  abelbeck)
+- Get rid of warning "timeout (-t) value larger than period (-p) produces unexpected results"
+  (#142, thanks @MrDragon1122)
+  
+
+fping 4.1 (2018-09-17)
+======================
+
+## Bugfixes and other changes
+
+- Fix problem when socket fd is 0 (#125, thanks Ramón Novoa!)
+- Fix running on servers with disabled IPv6 (#118, thanks Simon Matter)
+- Allow running "fping -h" or "--help" even when raw socket can't be opened (#131, thanks @teto)
+- Fix build issue with FreeBSD and IPv6 (#132, thanks @gsnw)
+
+fping 4.0 (2017-04-23)
+======================
+
+## Incompatible Changes
+
+##### fping and fping6 unification
+
+fping and fping6 are now unified into one binary. It means that, for example,
+doing 'fping google.com' is going to ping the IPv6 IP of google.com on
+IPv6-enabled hosts.  
+
+If you need exact compatibility with old versions, you can configure 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
+
+##### Option -n, not the same as -d anymore
+
+Option -n / --name is now doing a reverse-DNS lookups on host addresses,
+only if they are given as IP address, but not for hostnames. For example,
+if you write 'fping -n google.com', fping would previously do a
+forward-DNS lookup on google.com, and then a reverse-DNS lookup on the
+resolved IP address. Now, it is just going to keep the name 'google.com'.
+That same behavior can be achieved with the option -d / --rdns (which was
+previously an alias for -n).
+
+                     fping<4.0              fping>=4.0
+    fping -n NAME    NAME->IP->IPNAME       NAME
+    fping -d NAME    NAME->IP->IPNAME       NAME->IP->IPNAME
+
+##### Discarding of late packets
+
+fping will now discard replies, if they arrive after the defined timeout
+for reply packets, specified with -t. This change is relevant only for the
+count and loop modes, where the measured times should be now more
+consistent (see github issue [#32][i32] for details).
+
+To prevent loosing reply packets because of this change, the default
+timeout in count and loop modes is now automatically adjusted to the
+period interval (up to 2000 ms), but it can be overriden with the -t
+option. The default timeout for non-loop/count modes remains 500 ms.
+
+##### No restrictions by default
+
+fping will not enforce -i >= 1 and -p >= 10 anymore, except if you
+'./configure --enable-safe-limits'.
+
+The reasoning to removing the restrictions by default, is that users can
+clog the network with other tools anyway, and these restrictions are
+sometimes getting in the way (for example if you try to ping a lot of
+hosts).
+
+##### Default interval (-i) changed from 25ms to 10ms
+
+The default minimum interval between ping probes has been changed from
+25ms to 10ms. The reason is that 25ms is very high, considering today's
+fast networks: it generates at most 31 kbps of traffic (for IPv4 and
+default payload size).
+
+## New features
+
+- Unified 'fping' and 'fping6' into one binary ([#80][i80])
+- Long option names for all options
+- IPv6 enabled by default
+- New option -4 to force IPv4
+- New option -6 to force IPv6
+- Keep original name if a hostname is given with -n/--name
+- Option -d/--rdns now always does a rdns-lookup, even for names, as '-n' was doing until now
+- Enforce -t timeout on reply packets, by discarding late packets ([#32][i32])
+- Auto-adjust timeout for -c/-C/-l mode to value of -p
+
+## Bugfixes and other changes
+
+- -i/-p restrictions disabled by default (enable with --enable-safe-limits)
+- Default interval -i changed from 25ms to 10ms
+- Fix compatibility issue with GNU Hurd
+- A C99 compiler is now required
+- Option parsing with optparse (https://github.com/skeeto/optparse). Thanks Christopher Wellons!
+- New changelog file format
+
+[i32]: https://github.com/schweikert/fping/issues/32
+[i80]: https://github.com/schweikert/fping/issues/80
+
+(see doc/CHANGELOG.pre-v4 for older changes)
diff --git a/ci/tmp.4rIIEYCP9c/fping-5.3/COPYING b/ci/tmp.4rIIEYCP9c/fping-5.3/COPYING
new file mode 100644 (file)
index 0000000..cceb651
--- /dev/null
@@ -0,0 +1,17 @@
+ * 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.
diff --git a/ci/tmp.4rIIEYCP9c/fping-5.3/INSTALL b/ci/tmp.4rIIEYCP9c/fping-5.3/INSTALL
new file mode 100644 (file)
index 0000000..e23597f
--- /dev/null
@@ -0,0 +1,177 @@
+Basic Installation
+==================
+
+   These are generic installation instructions.
+
+   --> See the README file for fping-specific instructions. <--
+
+   The `configure' shell script attempts to guess correct values for
+various system-dependent variables used during compilation.  It uses
+those values to create a `Makefile' in each directory of the package.
+It may also create one or more `.h' files containing system-dependent
+definitions.  Finally, it creates a shell script `config.status' that
+you can run in the future to recreate the current configuration, a file
+`config.cache' that saves the results of its tests to speed up
+reconfiguring, and a file `config.log' containing compiler output
+(useful mainly for debugging `configure').
+
+   If you need to do unusual things to compile the package, please try
+to figure out how `configure' could check whether to do them, and mail
+diffs or instructions to the address given in the `README' so they can
+be considered for the next release.  If at some point `config.cache'
+contains results you don't want to keep, you may remove or edit it.
+
+   The file `configure.in' is used to create `configure' by a program
+called `autoconf'.  You only need `configure.in' if you want to change
+it or regenerate `configure' using a newer version of `autoconf'.
+
+The simplest way to compile this package is:
+
+  1. `cd' to the directory containing the package's source code and type
+     `./configure' to configure the package for your system.  If you're
+     using `csh' on an old version of System V, you might need to type
+     `sh ./configure' instead to prevent `csh' from trying to execute
+     `configure' itself.
+
+     Running `configure' takes a while.  While running, it prints some
+     messages telling which features it is checking for.
+
+  2. Type `make' to compile the package.
+
+  3. Optionally, type `make check' to run any self-tests that come with
+     the package.
+
+  4. Type `make install' to install the programs and any data files and
+     documentation.
+
+  5. You can remove the program binaries and object files from the
+     source code directory by typing `make clean'.  To also remove the
+     files that `configure' created (so you can compile the package for
+     a different kind of computer), type `make distclean'.  There is
+     also a `make maintainer-clean' target, but that is intended mainly
+     for the package's developers.  If you use it, you may have to get
+     all sorts of other programs in order to regenerate files that came
+     with the distribution.
+
+Compilers and Options
+=====================
+
+   Some systems require unusual options for compilation or linking that
+the `configure' script does not know about.  You can give `configure'
+initial values for variables by setting them in the environment.  Using
+a Bourne-compatible shell, you can do that on the command line like
+this:
+     CC=c89 CFLAGS=-O2 LIBS=-lposix ./configure
+
+Or on systems that have the `env' program, you can do it like this:
+     env CPPFLAGS=-I/usr/local/include LDFLAGS=-s ./configure
+
+Compiling For Multiple Architectures
+====================================
+
+   You can compile the package for more than one kind of computer at the
+same time, by placing the object files for each architecture in their
+own directory.  To do this, you must use a version of `make' that
+supports the `VPATH' variable, such as GNU `make'.  `cd' to the
+directory where you want the object files and executables to go and run
+the `configure' script.  `configure' automatically checks for the
+source code in the directory that `configure' is in and in `..'.
+
+   If you have to use a `make' that does not supports the `VPATH'
+variable, you have to compile the package for one architecture at a time
+in the source code directory.  After you have installed the package for
+one architecture, use `make distclean' before reconfiguring for another
+architecture.
+
+Installation Names
+==================
+
+   By default, `make install' will install the package's files in
+`/usr/local/bin', `/usr/local/man', etc.  You can specify an
+installation prefix other than `/usr/local' by giving `configure' the
+option `--prefix=PATH'.
+
+   You can specify separate installation prefixes for
+architecture-specific files and architecture-independent files.  If you
+give `configure' the option `--exec-prefix=PATH', the package will use
+PATH as the prefix for installing programs and libraries.
+Documentation and other data files will still use the regular prefix.
+
+   If the package supports it, you can cause programs to be installed
+with an extra prefix or suffix on their names by giving `configure' the
+option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'.
+
+Optional Features
+=================
+
+   Some packages pay attention to `--enable-FEATURE' options to
+`configure', where FEATURE indicates an optional part of the package.
+They may also pay attention to `--with-PACKAGE' options, where PACKAGE
+is something like `gnu-as' or `x' (for the X Window System).  The
+`README' should mention any `--enable-' and `--with-' options that the
+package recognizes.
+
+   For packages that use the X Window System, `configure' can usually
+find the X include and library files automatically, but if it doesn't,
+you can use the `configure' options `--x-includes=DIR' and
+`--x-libraries=DIR' to specify their locations.
+
+Specifying the System Type
+==========================
+
+   There may be some features `configure' can not figure out
+automatically, but needs to determine by the type of host the package
+will run on.  Usually `configure' can figure that out, but if it prints
+a message saying it can not guess the host type, give it the
+`--host=TYPE' option.  TYPE can either be a short name for the system
+type, such as `sun4', or a canonical name with three fields:
+     CPU-COMPANY-SYSTEM
+
+See the file `config.sub' for the possible values of each field.  If
+`config.sub' isn't included in this package, then this package doesn't
+need to know the host type.
+
+   If you are building compiler tools for cross-compiling, you can also
+use the `--target=TYPE' option to select the type of system they will
+produce code for and the `--build=TYPE' option to select the type of
+system on which you are compiling the package.
+
+Sharing Defaults
+================
+
+   If you want to set default values for `configure' scripts to share,
+you can create a site shell script called `config.site' that gives
+default values for variables like `CC', `cache_file', and `prefix'.
+`configure' looks for `PREFIX/share/config.site' if it exists, then
+`PREFIX/etc/config.site' if it exists.  Or, you can set the
+`CONFIG_SITE' environment variable to the location of the site script.
+A warning: not all `configure' scripts look for a site script.
+
+Operation Controls
+==================
+
+   `configure' recognizes the following options to control how it
+operates.
+
+`--cache-file=FILE'
+     Use and save the results of the tests in FILE instead of
+     `./config.cache'.  Set FILE to `/dev/null' to disable caching, for
+     debugging `configure'.
+
+`--help'
+     Print a summary of the options to `configure', and exit.
+
+`--quiet'
+`--silent'
+`-q'
+     Do not print messages saying which checks are being made.
+
+`--srcdir=DIR'
+     Look for the package's source code in directory DIR.  Usually
+     `configure' can determine that directory automatically.
+
+`--version'
+     Print the version of Autoconf used to generate the `configure'
+     script, and exit.
+
+`configure' also accepts some other, not widely useful, options.
diff --git a/ci/tmp.4rIIEYCP9c/fping-5.3/Makefile.am b/ci/tmp.4rIIEYCP9c/fping-5.3/Makefile.am
new file mode 100644 (file)
index 0000000..2ea59b9
--- /dev/null
@@ -0,0 +1,3 @@
+SUBDIRS = doc src
+
+EXTRA_DIST = CHANGELOG.md contrib README.md ci/*.sh ci/*.pl
diff --git a/ci/tmp.4rIIEYCP9c/fping-5.3/README.md b/ci/tmp.4rIIEYCP9c/fping-5.3/README.md
new file mode 100644 (file)
index 0000000..8cf4f88
--- /dev/null
@@ -0,0 +1,50 @@
+[![Build Status](https://travis-ci.org/schweikert/fping.svg?branch=develop)](https://travis-ci.org/schweikert/fping)
+[![Coverage Status](https://coveralls.io/repos/github/schweikert/fping/badge.svg?branch=develop)](https://coveralls.io/github/schweikert/fping?branch=develop)
+[![Coverity Scan Build Status](https://scan.coverity.com/projects/11559/badge.svg?flat=1")](https://scan.coverity.com/projects/schweikert-fping)
+
+# fping
+
+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 long long
+story: Roland Schemers did publish a first version of it in 1992 and it has
+established itself since then as a standard tool.
+
+_Current maintainer_:  
+  David Schweikert \<david@schweikert.ch\>
+
+_Website_:  
+  https://fping.org/
+
+_Mailing-list_:  
+  https://groups.google.com/group/fping-users
+
+## Installation
+
+If you want to install fping from source, proceed as follows:
+
+0. Run `./autogen.sh`
+   (only if you got the source from Github).
+1. Run `./configure` with the correct arguments.
+   (see: `./configure --help`)
+2. Run `make; make install`.
+3. Make fping either setuid, or, if under Linux:
+   `sudo setcap cap_net_raw,cap_net_admin+ep fping`
+
+If you can't run fping as root or can't use the cap_net_raw capability, you can
+also run fping in unprivileged mode. This works on MacOS and also on Linux,
+provided that your GID is included in the range defined in
+`/proc/sys/net/ipv4/ping_group_range`. This is particularly useful for running
+fping in rootless / unprivileged containers. The --fwmark option needs root or
+cap_net_admin.
+
+## Usage
+
+Have a look at the [fping(8)](doc/fping.pod) manual page for usage help.
+(`fping -h` will also give a minimal help output.)
+
+## Credits
+
+* Original author:  Roland Schemers (schemers@stanford.edu)
+* Previous maintainer:  RL "Bob" Morgan (morgan@stanford.edu)
+* Initial IPv6 Support: Jeroen Massar (jeroen@unfix.org / jeroen@ipng.nl)
+* Other contributors: see [CHANGELOG.md](CHANGELOG.md)
diff --git a/ci/tmp.4rIIEYCP9c/fping-5.3/ci/build-1-autotools.sh b/ci/tmp.4rIIEYCP9c/fping-5.3/ci/build-1-autotools.sh
new file mode 100755 (executable)
index 0000000..f0ea2e0
--- /dev/null
@@ -0,0 +1,61 @@
+#!/bin/bash
+
+set -e
+set -x
+
+if [[ "$OSTYPE" == "darwin"* ]]; then
+    exit 0
+fi
+
+AUTOCONF=http://ftp.gnu.org/gnu/autoconf/autoconf-2.71.tar.gz
+AUTOMAKE=http://ftp.gnu.org/gnu/automake/automake-1.16.5.tar.gz
+LIBTOOL=http://ftp.gnu.org/gnu/libtool/libtool-2.4.6.tar.gz
+PREFIX=$(pwd)/ci/build
+PATH=$(pwd)/ci/build/bin:$PATH
+
+if [ ! -d ci ]; then
+    echo "you must run this in the root fping directory" >&2
+    exit 1
+fi
+
+# remove standard versions
+sudo apt-get remove -qq autoconf automake autotools-dev libtool
+
+# prepare build environment
+cd ci
+rm -rf build
+mkdir -p build/src
+cd build/src
+
+# autoconf
+(
+AUTOCONF_FILE=$(basename $AUTOCONF)
+AUTOCONF_DIR=$(echo $AUTOCONF_FILE | sed -e 's/\.tar.*//')
+wget $AUTOCONF
+tar xf $AUTOCONF_FILE
+cd $AUTOCONF_DIR
+./configure --prefix=$PREFIX
+make install
+)
+
+# automake
+(
+AUTOMAKE_FILE=$(basename $AUTOMAKE)
+AUTOMAKE_DIR=$(echo $AUTOMAKE_FILE | sed -e 's/\.tar.*//')
+wget $AUTOMAKE
+tar xf $AUTOMAKE_FILE
+cd $AUTOMAKE_DIR
+./configure --prefix=$PREFIX
+make install
+)
+
+# libtool
+(
+LIBTOOL_FILE=$(basename $LIBTOOL)
+LIBTOOL_DIR=$(echo $LIBTOOL_FILE | sed -e 's/\.tar.*//')
+wget $LIBTOOL
+tar xf $LIBTOOL_FILE
+cd $LIBTOOL_DIR
+./configure --prefix=$PREFIX
+make install
+)
diff --git a/ci/tmp.4rIIEYCP9c/fping-5.3/ci/build-2-test-command.sh b/ci/tmp.4rIIEYCP9c/fping-5.3/ci/build-2-test-command.sh
new file mode 100755 (executable)
index 0000000..77f3905
--- /dev/null
@@ -0,0 +1,6 @@
+#!/bin/sh
+
+set -ex
+
+curl -L http://cpanmin.us | perl - -L $HOME/perl5 App::cpanminus
+$HOME/perl5/bin/cpanm --sudo Test::Command
diff --git a/ci/tmp.4rIIEYCP9c/fping-5.3/ci/build-3-prepare-macos.sh b/ci/tmp.4rIIEYCP9c/fping-5.3/ci/build-3-prepare-macos.sh
new file mode 100755 (executable)
index 0000000..09125eb
--- /dev/null
@@ -0,0 +1,13 @@
+#!/bin/bash
+
+# only do this on Mac OS X
+if [ `uname -s` != "Darwin" ]; then
+    exit 0;
+fi
+
+if [[ ! `ifconfig lo0` =~ 127\.0\.0\.2 ]]; then
+    sudo ifconfig lo0 127.0.0.2/8 alias
+    sudo ifconfig lo0 127.0.0.3/8 alias
+    sudo ifconfig lo0 127.0.0.4/8 alias
+    sudo ifconfig lo0 127.0.0.5/8 alias
+fi 
diff --git a/ci/tmp.4rIIEYCP9c/fping-5.3/ci/build-4-compile.sh b/ci/tmp.4rIIEYCP9c/fping-5.3/ci/build-4-compile.sh
new file mode 100755 (executable)
index 0000000..e2a660c
--- /dev/null
@@ -0,0 +1,28 @@
+#!/bin/bash
+set -x
+
+PATH=$(pwd)/ci/build/bin:$PATH
+
+if [ ! -d ci ]; then
+    echo "you must run this in the root fping directory" >&2
+    exit 1
+fi
+
+autoreconf -i
+./configure --enable-ipv4 --enable-ipv6 --enable-safe-limits --prefix=/opt/fping
+make CFLAGS="-g -O0 -fprofile-arcs -ftest-coverage"
+## setcap currently doesn't work anymore on travis-ci
+#sudo setcap cap_net_raw+ep src/fping
+## setcap debugging:
+#pwd
+#df -k .
+#which setcap
+#uname -a
+#mount
+#
+#sudo apt-get install strace
+#sudo strace setcap cap_net_raw+ep src/fping
+
+# use setuid, since setcap is not available
+sudo chown root src/fping
+sudo chmod u+s  src/fping
diff --git a/ci/tmp.4rIIEYCP9c/fping-5.3/ci/deploy-bintray.sh b/ci/tmp.4rIIEYCP9c/fping-5.3/ci/deploy-bintray.sh
new file mode 100755 (executable)
index 0000000..0dc8800
--- /dev/null
@@ -0,0 +1,14 @@
+#!/bin/bash
+
+# upload to bintray.com/schweikert
+
+set -e
+
+VERSION=$(ls fping-*.tar.gz | sed -e 's/^fping-//' | sed -e 's/\.tar\.gz$//')
+if [[ "$VERSION" =~ ^[0-9]+\.[0-9]+$ ]]; then
+    REPO=release
+else
+    REPO=beta
+fi
+curl -T fping-$VERSION.tar.gz -uschweikert:$BINTRAY_API_KEY https://api.bintray.com/content/schweikert/$REPO/fping/$VERSION/fping-$VERSION.tar.gz
+echo
diff --git a/ci/tmp.4rIIEYCP9c/fping-5.3/ci/deploy-coveralls.sh b/ci/tmp.4rIIEYCP9c/fping-5.3/ci/deploy-coveralls.sh
new file mode 100755 (executable)
index 0000000..9080f0b
--- /dev/null
@@ -0,0 +1,16 @@
+#!/bin/sh
+
+set -xe
+
+if [ "$TRAVIS_DIST" = "trusty" ]; then
+    echo "skip coveralls on trusty because coveralls errors out due to python issues"
+    exit 0
+elif [ "$TRAVIS_OS_NAME" = "osx" ]; then
+    pip3 install --user cpp-coveralls
+    PATH="${PATH}:$(python3 -c 'import site; print(site.USER_BASE)')/bin"
+else
+    pip install --user cpp-coveralls
+fi
+
+export COVERALLS_PARALLEL=true
+coveralls --build-root src --exclude src/optparse.c --exclude ci --exclude config.h --gcov-options '\-lp'
diff --git a/ci/tmp.4rIIEYCP9c/fping-5.3/ci/deploy-coverity.sh b/ci/tmp.4rIIEYCP9c/fping-5.3/ci/deploy-coverity.sh
new file mode 100755 (executable)
index 0000000..b009d2f
--- /dev/null
@@ -0,0 +1,25 @@
+#!/bin/sh
+
+set -e
+
+COVERITY_SCAN_PROJECT_NAME=schweikert/fping
+COVERITY_SCAN_EMAIL=david@schweikert.ch
+
+if [ -z "$COVERITY_SCAN_TOKEN" ]; then
+    echo "ERROR: COVERITY_SCAN_TOKEN not defined." >&2
+    exit 1
+fi
+
+curl -o /tmp/cov-analysis-linux64.tgz https://scan.coverity.com/download/linux64 \
+    --form project=$COVERITY_SCAN_PROJECT_NAME --form token=$COVERITY_SCAN_TOKEN
+tar xfz /tmp/cov-analysis-linux64.tgz
+./autogen.sh
+./configure --enable-ipv4 --enable-ipv6 --enable-safe-limits --prefix=/opt/fping
+cov-analysis-linux64-*/bin/cov-build --dir cov-int make -j4
+tar cfz cov-int.tar.gz cov-int
+curl https://scan.coverity.com/builds?project=$COVERITY_SCAN_PROJECT_NAME \
+    --form token=$COVERITY_SCAN_TOKEN \
+    --form email=$COVERITY_SCAN_EMAIL \
+    --form file=@cov-int.tar.gz \
+    --form version="`git rev-parse --short HEAD`" \
+    --form description="`git rev-parse --short HEAD` / $TRAVIS_BUILD_ID "
diff --git a/ci/tmp.4rIIEYCP9c/fping-5.3/ci/prepare-linux.sh b/ci/tmp.4rIIEYCP9c/fping-5.3/ci/prepare-linux.sh
new file mode 100755 (executable)
index 0000000..efe8b3b
--- /dev/null
@@ -0,0 +1,7 @@
+#!/bin/bash
+
+sudo setcap cap_net_raw,cap_net_admin+ep src/fping
+
+if [[ ! $PATH =~ fping/src ]]; then
+    PATH=/home/dws/checkouts/fping/src:$PATH
+fi
diff --git a/ci/tmp.4rIIEYCP9c/fping-5.3/ci/run-lcov.sh b/ci/tmp.4rIIEYCP9c/fping-5.3/ci/run-lcov.sh
new file mode 100755 (executable)
index 0000000..c7470b6
--- /dev/null
@@ -0,0 +1,9 @@
+#!/bin/sh
+
+lcov -c -no-external \
+    -d . \
+    -b src \
+    -o lcov-all.info
+
+lcov --remove lcov-all.info -o lcov.info \
+    '*/optparse.c'
diff --git a/ci/tmp.4rIIEYCP9c/fping-5.3/ci/run-tests.sh b/ci/tmp.4rIIEYCP9c/fping-5.3/ci/run-tests.sh
new file mode 100755 (executable)
index 0000000..9d5a308
--- /dev/null
@@ -0,0 +1,8 @@
+#!/bin/sh
+
+set -ex
+
+PATH=`pwd`/src:$PATH
+
+prove ci/test-*.pl
+ci/test-tarball.sh
diff --git a/ci/tmp.4rIIEYCP9c/fping-5.3/ci/test-01-basics.pl b/ci/tmp.4rIIEYCP9c/fping-5.3/ci/test-01-basics.pl
new file mode 100755 (executable)
index 0000000..e54bc22
--- /dev/null
@@ -0,0 +1,55 @@
+#!/usr/bin/perl -w
+
+use Test::Command tests => 15;
+use Test::More;
+
+# ping 127.0.0.1
+{
+    my $cmd = Test::Command->new(cmd => "fping 127.0.0.1");
+    $cmd->exit_is_num(0);
+    $cmd->stdout_is_eq("127.0.0.1 is alive\n");
+    $cmd->stderr_is_eq("");
+}
+
+# ping ::1
+SKIP: {
+    #system("/sbin/ifconfig >&2");
+    if($ENV{SKIP_IPV6}) {
+        skip 'Skip IPv6 tests', 3;
+    }
+    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("");
+}
+
+# ping ff02::1
+SKIP: {
+    #system("/sbin/ifconfig >&2");
+    if($ENV{SKIP_IPV6}) {
+        skip 'Skip IPv6 tests', 3;
+    }
+    my $cmd = Test::Command->new(cmd => "fping ff02::1");
+    $cmd->exit_is_num(0);
+    $cmd->stdout_is_eq("ff02::1 is alive\n");
+    $cmd->stderr_like(qr{ \[<- .*\]});
+}
+
+# ping 3 times 127.0.0.1
+{
+    my $cmd = Test::Command->new(cmd => "fping -p 100 -C3 127.0.0.1");
+    $cmd->exit_is_num(0);
+    $cmd->stdout_like(qr{127\.0\.0\.1 : \[0\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\)
+127\.0\.0\.1 : \[1\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\)
+127\.0\.0\.1 : \[2\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\)
+});
+    $cmd->stderr_like(qr{127\.0\.0\.1 : \d\.\d+ \d\.\d+ \d\.\d+\n});
+}
+
+# invalid target name
+{
+    my $cmd = Test::Command->new(cmd => "fping host.name.invalid");
+    $cmd->exit_is_num(2);
+    $cmd->stdout_is_eq("");
+    $cmd->stderr_like(qr{host\.name\.invalid: .+\n});
+}
diff --git a/ci/tmp.4rIIEYCP9c/fping-5.3/ci/test-02-help.pl b/ci/tmp.4rIIEYCP9c/fping-5.3/ci/test-02-help.pl
new file mode 100755 (executable)
index 0000000..0f66d13
--- /dev/null
@@ -0,0 +1,46 @@
+#!/usr/bin/perl -w
+
+use Test::Command tests => 15;
+
+my $I_HELP = "   -I, --iface=IFACE  bind to a particular interface\n";
+$I_HELP = '' if $^O eq 'darwin';
+
+# fping -h (special pre-parse code path)
+my $cmd1 = Test::Command->new(cmd => "fping -h");
+$cmd1->exit_is_num(0);
+$cmd1->stdout_like(qr{Usage: fping \[options\] \[targets\.\.\.\]
+
+Probing options:
+.*
+   -v, --version      show version
+}s);
+$cmd1->stderr_is_eq("");
+
+# fping -4 -h (normal option parsing code path)
+my $cmd4 = Test::Command->new(cmd => "fping -4 -h");
+$cmd4->exit_is_num(0);
+$cmd4->stdout_like(qr{Usage: fping \[options\] \[targets\.\.\.\]
+
+Probing options:
+.*
+   -v, --version      show version
+}s);
+$cmd4->stderr_is_eq("");
+
+# fping -v
+my $cmd2 = Test::Command->new(cmd => "fping -v");
+$cmd2->exit_is_num(0);
+$cmd2->stdout_like(qr{fping: Version \S+});
+$cmd2->stderr_is_eq("");
+
+# fping with unknown option
+my $cmd3 = Test::Command->new(cmd => "fping -Z");
+$cmd3->exit_is_num(1);
+$cmd3->stdout_is_eq("");
+$cmd3->stderr_like(qr{^fping: (illegal|invalid) option -- '?Z'?\nsee 'fping -h' for usage information\n$});
+
+# fping with unknown long option
+my $cmd5 = Test::Command->new(cmd => "fping --unknown-long-option");
+$cmd5->exit_is_num(1);
+$cmd5->stdout_is_eq("");
+$cmd5->stderr_like(qr{^fping: (illegal|invalid) option -- '?unknown-long-option'?\nsee 'fping -h' for usage information\n$});
diff --git a/ci/tmp.4rIIEYCP9c/fping-5.3/ci/test-03-forbidden.pl b/ci/tmp.4rIIEYCP9c/fping-5.3/ci/test-03-forbidden.pl
new file mode 100755 (executable)
index 0000000..97962c1
--- /dev/null
@@ -0,0 +1,63 @@
+#!/usr/bin/perl -w
+
+use Test::Command tests => 36;
+
+# fping -i 0
+my $cmd1 = Test::Command->new(cmd => "fping -i 0 -T10 -g 127.0.0.1/29");
+$cmd1->exit_is_num(1);
+$cmd1->stdout_is_eq("");
+$cmd1->stderr_is_eq(<<END);
+fping: -i must be >= 1
+END
+
+# fping -p 9
+my $cmd2 = Test::Command->new(cmd => "fping -c3 -p 9 127.0.0.1");
+$cmd2->exit_is_num(1);
+$cmd2->stdout_is_eq("");
+$cmd2->stderr_is_eq(<<END);
+fping: -p must be >= 10
+END
+
+# fping -H 300
+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("fping: ttl 300 out of range\n");
+
+# fping -a -u
+my $cmd6 = Test::Command->new(cmd => "fping -a -u 127.0.0.1");
+$cmd6->exit_is_num(1);
+$cmd6->stdout_is_eq("");
+$cmd6->stderr_is_eq("fping: specify only one of a, u\n");
+
+# fping -c -l
+my $cmd7 = Test::Command->new(cmd => "fping -c3 -l 127.0.0.1");
+$cmd7->exit_is_num(1);
+$cmd7->stdout_is_eq("");
+$cmd7->stderr_is_eq("fping: specify only one of c, l\n");
+
+# fping -b 65508
+my $cmd8 = Test::Command->new(cmd => "fping -b 65508 127.0.0.1");
+$cmd8->exit_is_num(1);
+$cmd8->stdout_is_eq("");
+$cmd8->stderr_is_eq("fping: data size 65508 not valid, must not be larger than 65507\n");
+
+# fping -B 0.9
+my $cmd9 = Test::Command->new(cmd => "fping -B 0.9 127.0.0.1");
+$cmd9->exit_is_num(1);
+$cmd9->stdout_is_eq("");
+$cmd9->stderr_is_eq("fping: backoff factor 0.9 not valid, must be between 1.0 and 5.0\n");
+
+# fping -B 5.1
+my $cmd10 = Test::Command->new(cmd => "fping -B 5.1 127.0.0.1");
+$cmd10->exit_is_num(1);
+$cmd10->stdout_is_eq("");
+$cmd10->stderr_is_eq("fping: backoff factor 5.1 not valid, must be between 1.0 and 5.0\n");
+
+# non-negative only
+for my $arg (qw(i p Q t)) {
+    my $cmd = Test::Command->new(cmd => "fping -$arg -1");
+    $cmd->exit_is_num(1);
+    $cmd->stdout_is_eq("");
+    $cmd->stderr_like(qr{Usage:});
+}
diff --git a/ci/tmp.4rIIEYCP9c/fping-5.3/ci/test-04-options-a-b.pl b/ci/tmp.4rIIEYCP9c/fping-5.3/ci/test-04-options-a-b.pl
new file mode 100755 (executable)
index 0000000..ea7eb89
--- /dev/null
@@ -0,0 +1,218 @@
+#!/usr/bin/perl -w
+
+use Test::Command tests => 68;
+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 -6 -4
+{
+my $cmd = Test::Command->new(cmd => "fping -6 -4 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($ENV{SKIP_IPV6}) {
+        skip 'Skip IPv6 tests', 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");
+$cmd->exit_is_num(0);
+$cmd->stdout_is_eq("127.0.0.1\n127.0.0.2\n");
+$cmd->stderr_is_eq("");
+}
+
+# fping -a --print-ttl
+{
+my $cmd = Test::Command->new(cmd => "fping -a --print-ttl 127.0.0.1 127.0.0.2");
+$cmd->exit_is_num(0);
+$cmd->stdout_like(qr{127\.0\.0\.1 \(TTL \d+\)\n127\.0\.0\.2 \(TTL \d+\)\n});
+$cmd->stderr_is_eq("");
+}
+
+# fping -a --icmp-timestamp
+SKIP: {
+if($^O eq 'darwin') {
+    skip 'On macOS, this test is unreliable', 3;
+}
+my $cmd = Test::Command->new(cmd => "fping -a --icmp-timestamp 127.0.0.1");
+$cmd->exit_is_num(0);
+$cmd->stdout_like(qr{127\.0\.0\.1 timestamps: Originate=\d+ Receive=\d+ Transmit=\d+ Localreceive=\d+});
+$cmd->stderr_is_eq("");
+}
+
+# fping --print-ttl
+{
+my $cmd = Test::Command->new(cmd => "fping --print-ttl 127.0.0.1");
+$cmd->exit_is_num(0);
+$cmd->stdout_like(qr{127\.0\.0\.1 is alive \(TTL \d+\)});
+$cmd->stderr_is_eq("");
+}
+
+# fping --icmp-timestamp
+SKIP: {
+if($^O eq 'darwin') {
+    skip 'On macOS, this test is unreliable', 3;
+}
+my $cmd = Test::Command->new(cmd => "fping --icmp-timestamp 127.0.0.1");
+$cmd->exit_is_num(0);
+$cmd->stdout_like(qr{127\.0\.0\.1 is alive, timestamps: Originate=\d+ Receive=\d+ Transmit=\d+ Localreceive=\d+});
+$cmd->stderr_is_eq("");
+}
+
+# fping --icmp-timestamp --print-tos --print-ttl -e
+SKIP: {
+if($^O eq 'darwin') {
+    skip 'On macOS, this test is unreliable', 3;
+}
+my $cmd = Test::Command->new(cmd => "fping --icmp-timestamp --print-tos --print-ttl -e 127.0.0.1");
+$cmd->exit_is_num(0);
+$cmd->stdout_like(qr{127\.0\.0\.1 is alive, timestamps: Originate=\d+ Receive=\d+ Transmit=\d+ Localreceive=\d+ \(TOS \d+\) \(TTL \d+\) \(\d+(\.\d*)? ms\)});
+$cmd->stderr_is_eq("");
+}
+
+# fping --icmp-timestamp ::1
+SKIP: {
+    if($ENV{SKIP_IPV6}) {
+        skip 'Skip IPv6 tests', 3;
+    }
+    my $cmd = Test::Command->new(cmd => "fping --icmp-timestamp ::1");
+    $cmd->exit_is_num(2);
+    $cmd->stdout_is_eq("");
+    $cmd->stderr_like(qr{^::1:.*(not supported|not known)});
+}
+
+# fping --print-ttl with IPv6
+SKIP: {
+    if($ENV{SKIP_IPV6}) {
+        skip 'Skip IPv6 tests', 3;
+    }
+    my $cmd = Test::Command->new(cmd => "fping --print-ttl ::1");
+    $cmd->exit_is_num(0);
+    $cmd->stdout_like(qr{::1 is alive \(TTL unknown\)\n});
+    $cmd->stderr_is_eq("");
+}
+
+# fping -A
+{
+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("");
+}
+
+# fping -b
+{
+my $cmd = Test::Command->new(cmd => "fping -b 1000 127.0.0.1");
+$cmd->exit_is_num(0);
+$cmd->stdout_is_eq("127.0.0.1 is alive\n");
+$cmd->stderr_is_eq("");
+}
+
+# fping --icmp-timestamp -b
+{
+my $cmd = Test::Command->new(cmd => "fping --icmp-timestamp -b 1000 127.0.0.1");
+$cmd->exit_is_num(1);
+$cmd->stdout_is_eq("");
+$cmd->stderr_like(qr{cannot change ICMP Timestamp size});
+}
+
+# fping -b --icmp-timestamp
+{
+my $cmd = Test::Command->new(cmd => "fping -b 1000 --icmp-timestamp 127.0.0.1");
+$cmd->exit_is_num(1);
+$cmd->stdout_is_eq("");
+$cmd->stderr_like(qr{cannot change ICMP Timestamp size});
+}
+
+# fping --icmp-timestamp -b 12 (ICMP Timestamp data size)
+{
+my $cmd = Test::Command->new(cmd => "fping --icmp-timestamp -b 12 127.0.0.1");
+$cmd->exit_is_num(1);
+$cmd->stdout_is_eq("");
+$cmd->stderr_like(qr{cannot change ICMP Timestamp size});
+}
+
+# fping -6 --icmp-timestamp
+SKIP: {
+    if($ENV{SKIP_IPV6}) {
+        skip 'Skip IPv6 tests', 3;
+    }
+    my $cmd = Test::Command->new(cmd => "fping -6 --icmp-timestamp ::1");
+    $cmd->exit_is_num(1);
+    $cmd->stdout_is_eq("");
+    $cmd->stderr_like(qr{ICMP Timestamp is IPv4 only});
+}
+
+# fping --icmp-timestamp -6
+SKIP: {
+    if($ENV{SKIP_IPV6}) {
+        skip 'Skip IPv6 tests', 3;
+    }
+    my $cmd = Test::Command->new(cmd => "fping --icmp-timestamp -6 ::1");
+    $cmd->exit_is_num(1);
+    $cmd->stdout_is_eq("");
+    $cmd->stderr_is_eq("fping: can't specify both -4 and -6\n");
+}
+
+# fping -B
+SKIP: {
+    if($^O eq 'darwin') {
+        skip 'timing test not reliable on macOS', 5;
+    }
+    my $t0 = [gettimeofday];
+    my $cmd = Test::Command->new(cmd => "fping  -t 100 -r 3 -B 2  8.8.8.7");
+    $cmd->exit_is_num(1);
+    $cmd->stdout_is_eq("8.8.8.7 is unreachable\n");
+    $cmd->stderr_like(qr{^(|(8.8.8.7: error while sending ping: No route to host\n)+)$});
+    my $elapsed = tv_interval($t0);
+    # 0.1 + 0.2 + 0.4 + 0.8 = 1.5
+    cmp_ok($elapsed, '>=', 1.5);
+    cmp_ok($elapsed, '<', 1.9);
+}
diff --git a/ci/tmp.4rIIEYCP9c/fping-5.3/ci/test-05-options-c-e.pl b/ci/tmp.4rIIEYCP9c/fping-5.3/ci/test-05-options-c-e.pl
new file mode 100755 (executable)
index 0000000..d1cc767
--- /dev/null
@@ -0,0 +1,365 @@
+#!/usr/bin/perl -w
+
+use Test::Command tests => 87;
+use Test::More;
+
+#  -c n           count of pings to send to each target (default 1)
+#  -C n           same as -c, report results in verbose format
+#  --check-source discard replies not from target address
+#  -d             reverse name lookup
+#  -D             print timestamp before each output line
+#  -e             show elapsed time on return packets
+
+# fping -c n
+{
+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\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\)
+127\.0\.0\.1 : \[0\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\)
+localhost : \[1\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\)
+127\.0\.0\.1 : \[1\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\)
+});
+
+$cmd->stderr_like(qr{localhost : xmt/rcv/%loss = 2/2/0%, min/avg/max = \d\.\d+/\d\.\d+/\d\.\d+
+127\.0\.0\.1 : xmt/rcv/%loss = 2/2/0%, min/avg/max = \d\.\d+/\d\.\d+/\d\.\d+
+});
+}
+
+# fping -c n --print-tos --print-ttl
+{
+my $cmd = Test::Command->new(cmd => "fping -4 -c 2 -p 100 --print-tos --print-ttl localhost 127.0.0.1");
+$cmd->exit_is_num(0);
+$cmd->stdout_like(qr{localhost : \[0\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\) \(TOS \d+\) \(TTL \d+\)
+127\.0\.0\.1 : \[0\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\) \(TOS \d+\) \(TTL \d+\)
+localhost : \[1\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\) \(TOS \d+\) \(TTL \d+\)
+127\.0\.0\.1 : \[1\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\) \(TOS \d+\) \(TTL \d+\)
+});
+
+$cmd->stderr_like(qr{localhost : xmt/rcv/%loss = 2/2/0%, min/avg/max = \d\.\d+/\d\.\d+/\d\.\d+
+127\.0\.0\.1 : xmt/rcv/%loss = 2/2/0%, min/avg/max = \d\.\d+/\d\.\d+/\d\.\d+
+});
+}
+
+# fping -c n -q
+{
+my $cmd = Test::Command->new(cmd => "fping -q -c 2 -p 100 localhost 127.0.0.1");
+$cmd->exit_is_num(0);
+$cmd->stdout_is_eq("");
+$cmd->stderr_like(qr{localhost : xmt/rcv/%loss = 2/2/0%, min/avg/max = \d\.\d+/\d\.\d+/\d\.\d+
+127\.0\.0\.1 : xmt/rcv/%loss = 2/2/0%, min/avg/max = \d\.\d+/\d\.\d+/\d\.\d+
+});
+}
+
+# fping -c n -a (-a is ignored)
+{
+my $cmd = Test::Command->new(cmd => "fping -a -c 2 -p 100 localhost 127.0.0.1");
+$cmd->exit_is_num(0);
+$cmd->stdout_like(qr{localhost : \[0\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\)
+127\.0\.0\.1 : \[0\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\)
+localhost : \[1\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\)
+127\.0\.0\.1 : \[1\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\)
+});
+
+$cmd->stderr_like(qr{localhost : xmt/rcv/%loss = 2/2/0%, min/avg/max = \d\.\d+/\d\.\d+/\d\.\d+
+127\.0\.0\.1 : xmt/rcv/%loss = 2/2/0%, min/avg/max = \d\.\d+/\d\.\d+/\d\.\d+
+});
+}
+
+# fping -c n -u (-u is ignored)
+{
+my $cmd = Test::Command->new(cmd => "fping -u -c 2 -p 100 localhost 127.0.0.1");
+$cmd->exit_is_num(0);
+$cmd->stdout_like(qr{localhost : \[0\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\)
+127\.0\.0\.1 : \[0\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\)
+localhost : \[1\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\)
+127\.0\.0\.1 : \[1\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\)
+});
+
+$cmd->stderr_like(qr{localhost : xmt/rcv/%loss = 2/2/0%, min/avg/max = \d\.\d+/\d\.\d+/\d\.\d+
+127\.0\.0\.1 : xmt/rcv/%loss = 2/2/0%, min/avg/max = \d\.\d+/\d\.\d+/\d\.\d+
+});
+}
+
+# fping -c n ff02::1
+SKIP: {
+    if($ENV{SKIP_IPV6}) {
+        skip 'Skip IPv6 tests', 3;
+    }
+    my $cmd = Test::Command->new(cmd => "fping -c 1 ff02::1");
+    $cmd->exit_is_num(0);
+    $cmd->stdout_like(qr{ff02::1 : \[0\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\)\n});
+    $cmd->stderr_like(qr{ \[<- .*\]
+ff02::1 : xmt/rcv/%loss = 1/1/0%, min/avg/max = \d\.\d+/\d\.\d+/\d\.\d+\n});
+}
+
+# fping --icmp-timestamp -c n 127.0.0.1
+SKIP: {
+if($^O eq 'darwin') {
+    skip 'On macOS, this test is unreliable', 3;
+}
+my $cmd = Test::Command->new(cmd => "fping -4 --icmp-timestamp -c 2 127.0.0.1");
+$cmd->exit_is_num(0);
+$cmd->stdout_like(qr{127\.0\.0\.1 : \[0\], 20 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\), timestamps: Originate=\d+ Receive=\d+ Transmit=\d+ Localreceive=\d+
+127\.0\.0\.1 : \[1\], 20 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\), timestamps: Originate=\d+ Receive=\d+ Transmit=\d+ Localreceive=\d+
+});
+
+$cmd->stderr_like(qr{127\.0\.0\.1 : xmt/rcv/%loss = 2/2/0%, min/avg/max = \d\.\d+/\d\.\d+/\d\.\d+
+});
+}
+
+# fping --icmp-timestamp --print-tos --print-ttl -c n 127.0.0.1
+SKIP: {
+if($^O eq 'darwin') {
+    skip 'On macOS, this test is unreliable', 3;
+}
+my $cmd = Test::Command->new(cmd => "fping -4 --icmp-timestamp --print-tos --print-ttl -p 100 -c 2 127.0.0.1");
+$cmd->exit_is_num(0);
+$cmd->stdout_like(qr{127\.0\.0\.1 : \[0\], 20 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\), timestamps: Originate=\d+ Receive=\d+ Transmit=\d+ Localreceive=\d+ \(TOS \d+\) \(TTL \d+\)
+127\.0\.0\.1 : \[1\], 20 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\), timestamps: Originate=\d+ Receive=\d+ Transmit=\d+ Localreceive=\d+ \(TOS \d+\) \(TTL \d+\)
+});
+
+$cmd->stderr_like(qr{127\.0\.0\.1 : xmt/rcv/%loss = 2/2/0%, min/avg/max = \d\.\d+/\d\.\d+/\d\.\d+
+});
+}
+
+# fping -C n
+{
+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\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\)
+127\.0\.0\.1 : \[0\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\)
+localhost : \[1\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\)
+127\.0\.0\.1 : \[1\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\)
+});
+
+$cmd->stderr_like(qr{localhost : \d\.\d+ \d\.\d+
+127\.0\.0\.1 : \d\.\d+ \d\.\d+
+});
+}
+
+# fping -C n --print-tos --print-ttl
+{
+my $cmd = Test::Command->new(cmd => "fping -4 -C 2 -p 100 --print-tos --print-ttl localhost 127.0.0.1");
+$cmd->exit_is_num(0);
+$cmd->stdout_like(qr{localhost : \[0\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\) \(TOS \d+\) \(TTL \d+\)
+127\.0\.0\.1 : \[0\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\) \(TOS \d+\) \(TTL \d+\)
+localhost : \[1\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\) \(TOS \d+\) \(TTL \d+\)
+127\.0\.0\.1 : \[1\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\) \(TOS \d+\) \(TTL \d+\)
+});
+
+$cmd->stderr_like(qr{localhost : \d\.\d+ \d\.\d+
+127\.0\.0\.1 : \d\.\d+ \d\.\d+
+});
+}
+
+# fping -C n -q
+{
+my $cmd = Test::Command->new(cmd => "fping -C 5 -q -p 100 localhost");
+$cmd->exit_is_num(0);
+$cmd->stdout_is_eq("");
+$cmd->stderr_like(qr{localhost :( \d\.\d+){5}
+});
+}
+
+# fping -C n -a (-a is ignored)
+{
+my $cmd = Test::Command->new(cmd => "fping -a -C 2 -p 100 localhost 127.0.0.1");
+$cmd->exit_is_num(0);
+$cmd->stdout_like(qr{localhost : \[0\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\)
+127\.0\.0\.1 : \[0\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\)
+localhost : \[1\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\)
+127\.0\.0\.1 : \[1\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\)
+});
+
+$cmd->stderr_like(qr{localhost : \d\.\d+ \d\.\d+
+127\.0\.0\.1 : \d\.\d+ \d\.\d+
+});
+}
+
+# fping -C n -u (-u is ignored)
+{
+my $cmd = Test::Command->new(cmd => "fping -u -C 2 -p 100 localhost 127.0.0.1");
+$cmd->exit_is_num(0);
+$cmd->stdout_like(qr{localhost : \[0\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\)
+127\.0\.0\.1 : \[0\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\)
+localhost : \[1\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\)
+127\.0\.0\.1 : \[1\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\)
+});
+
+$cmd->stderr_like(qr{localhost : \d\.\d+ \d\.\d+
+127\.0\.0\.1 : \d\.\d+ \d\.\d+
+});
+}
+
+# fping -C n -i -q
+{
+my $cmd = Test::Command->new(cmd => "fping --quiet --interval=1 --vcount=20 --period=50 127.0.0.1 127.0.0.2");
+$cmd->exit_is_num(0);
+$cmd->stdout_is_eq("");
+$cmd->stderr_like(qr{127\.0\.0\.1 :( \d\.\d+){20}
+127\.0\.0\.2 :( \d\.\d+){20}
+});
+}
+
+# fping -C n ff02::1
+SKIP: {
+    if($ENV{SKIP_IPV6}) {
+        skip 'Skip IPv6 tests', 3;
+    }
+    my $cmd = Test::Command->new(cmd => "fping -C 1 ff02::1");
+    $cmd->exit_is_num(0);
+    $cmd->stdout_like(qr{ff02::1 : \[0\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\)\n});
+    $cmd->stderr_like(qr{ \[<- .*\]\nff02::1 : \d\.\d+\n});
+}
+
+# fping --check-source
+{
+my $cmd = Test::Command->new(cmd => "fping --check-source 127.0.0.1 127.0.0.2");
+$cmd->exit_is_num(0);
+$cmd->stdout_is_eq("127.0.0.1 is alive\n127.0.0.2 is alive\n");
+$cmd->stderr_is_eq("");
+}
+
+# fping --check-source (to IPv6 multicast address -> accept no reply)
+SKIP: {
+    if($ENV{SKIP_IPV6}) {
+        skip 'Skip IPv6 tests', 3;
+    }
+    my $cmd = Test::Command->new(cmd => "fping --check-source ff02::1");
+    $cmd->exit_is_num(1);
+    $cmd->stdout_is_eq("ff02::1 is unreachable\n");
+    $cmd->stderr_is_eq("");
+}
+
+# fping -c N --check-source
+SKIP: {
+    if($ENV{SKIP_IPV6}) {
+        skip 'Skip IPv6 tests', 3;
+    }
+    my $cmd = Test::Command->new(cmd => "fping -c1 --check-source 127.0.0.1 ff02::1");
+    $cmd->exit_is_num(1);
+    $cmd->stdout_like(qr{127\.0\.0\.1 : \[0\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\)
+ff02::1   : \[0\], timed out \(NaN avg, 100% loss\)
+});
+    $cmd->stderr_like(qr{
+127\.0\.0\.1 : xmt/rcv/%loss = 1/1/0%, min/avg/max = \d\.\d+/\d\.\d+/\d\.\d+
+ff02::1   : xmt/rcv/%loss = 1/0/100%
+});
+}
+
+# fping -C N --check-source
+SKIP: {
+    if($ENV{SKIP_IPV6}) {
+        skip 'Skip IPv6 tests', 3;
+    }
+    my $cmd = Test::Command->new(cmd => "fping -C1 --check-source 127.0.0.1 ff02::1");
+    $cmd->exit_is_num(1);
+    $cmd->stdout_like(qr{127\.0\.0\.1 : \[0\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\)
+ff02::1   : \[0\], timed out \(NaN avg, 100% loss\)
+});
+    $cmd->stderr_like(qr{
+127\.0\.0\.1 : \d\.\d+
+ff02::1   : -
+});
+}
+
+# fping -d
+{
+my $cmd = Test::Command->new(cmd => "fping -d 127.0.0.1");
+$cmd->exit_is_num(0);
+$cmd->stdout_is_eq("localhost is alive\n");
+$cmd->stderr_is_eq("");
+}
+
+# fping -D
+{
+my $cmd = Test::Command->new(cmd => "fping -D -c 2 -p 100 127.0.0.1");
+$cmd->exit_is_num(0);
+$cmd->stdout_like(qr{\[\d+\.\d+\] 127\.0\.0\.1 : \[0\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\)
+\[\d+\.\d+\] 127\.0\.0\.1 : \[1\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\)
+});
+
+$cmd->stderr_like(qr{127\.0\.0\.1 : xmt/rcv/%loss = 2/2/0%, min/avg/max = \d\.\d+/\d\.\d+/\d\.\d+
+});
+}
+
+# fping -D (timestamp not before 2001-09-09)
+{
+my $cmd = Test::Command->new(cmd => "fping -D -c 2 -p 100 127.0.0.1");
+$cmd->exit_is_num(0);
+$cmd->stdout_like(qr{\[[1-9]\d{9,}\.\d+\] 127\.0\.0\.1 : \[0\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\)
+\[[1-9]\d{9,}\.\d+\] 127\.0\.0\.1 : \[1\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\)
+});
+$cmd->stderr_like(qr{127\.0\.0\.1 : xmt/rcv/%loss = 2/2/0%, min/avg/max = \d\.\d+/\d\.\d+/\d\.\d+
+});
+}
+
+# fping -D --timestamp-format=ctime
+{
+my $cmd = Test::Command->new(cmd => "fping -D --timestamp-format=ctime -c 2 -p 100 127.0.0.1");
+$cmd->exit_is_num(0);
+$cmd->stdout_like(qr{\[\w+\s\w+\s+\d+\s[\d+:]+\s\d+\] 127\.0\.0\.1 : \[0\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\)
+\[\w+\s\w+\s+\d+\s[\d+:]+\s\d+\] 127\.0\.0\.1 : \[1\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\)
+});
+
+$cmd->stderr_like(qr{127\.0\.0\.1 : xmt/rcv/%loss = 2/2/0%, min/avg/max = \d\.\d+/\d\.\d+/\d\.\d+
+});
+}
+
+# fping -D --timestamp-format=iso
+{
+my $cmd = Test::Command->new(cmd => "fping -D --timestamp-format=iso -c 2 -p 100 127.0.0.1");
+$cmd->exit_is_num(0);
+$cmd->stdout_like(qr{\[[\d+-]+T[\d+:]+\+\d+\] 127\.0\.0\.1 : \[0\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\)
+\[[\d+-]+T[\d+:]+\+\d+\] 127\.0\.0\.1 : \[1\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\)
+});
+
+$cmd->stderr_like(qr{127\.0\.0\.1 : xmt/rcv/%loss = 2/2/0%, min/avg/max = \d\.\d+/\d\.\d+/\d\.\d+
+});
+}
+
+# fping -D --timestamp-format=rfc3339
+{
+my $cmd = Test::Command->new(cmd => "fping -D --timestamp-format=rfc3339 -c 2 -p 100 127.0.0.1");
+$cmd->exit_is_num(0);
+$cmd->stdout_like(qr{\[[\d+-]+\s[\d+:]+\] 127\.0\.0\.1 : \[0\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\)
+\[[\d+-]+\s[\d+:]+\] 127\.0\.0\.1 : \[1\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\)
+});
+
+$cmd->stderr_like(qr{127\.0\.0\.1 : xmt/rcv/%loss = 2/2/0%, min/avg/max = \d\.\d+/\d\.\d+/\d\.\d+
+});
+}
+
+# fping -D --timestamp-format
+{
+my $cmd = Test::Command->new(cmd => "fping -D --timestamp-format -c 2 -p 100 127.0.0.1");
+$cmd->exit_is_num(1);
+$cmd->stdout_is_eq("");
+$cmd->stderr_like(qr{Usage:});
+}
+
+# fping -D --timestamp-format="%Y-%m-%d %H:%M:%S"
+{
+my $cmd = Test::Command->new(cmd => "fping -D --timestamp-format=\"%Y-%m-%d %H:%M:%S\" -c 2 -p 100 127.0.0.1");
+$cmd->exit_is_num(1);
+$cmd->stdout_is_eq("");
+$cmd->stderr_like(qr{Usage:});
+}
+
+# fping -e
+{
+my $cmd = Test::Command->new(cmd => "fping -e 127.0.0.1");
+$cmd->exit_is_num(0);
+$cmd->stdout_like(qr{127\.0\.0\.1 is alive \(\d\.\d+ ms\)
+});
+$cmd->stderr_is_eq("");
+}
+
+# fping -e -a
+{
+my $cmd = Test::Command->new(cmd => "fping -e -a 127.0.0.1");
+$cmd->exit_is_num(0);
+$cmd->stdout_like(qr{127\.0\.0\.1 \(\d\.\d+ ms\)
+});
+$cmd->stderr_is_eq("");
+}
diff --git a/ci/tmp.4rIIEYCP9c/fping-5.3/ci/test-06-options-f-h.pl b/ci/tmp.4rIIEYCP9c/fping-5.3/ci/test-06-options-f-h.pl
new file mode 100755 (executable)
index 0000000..c9b520a
--- /dev/null
@@ -0,0 +1,231 @@
+#!/usr/bin/perl -w
+
+use Test::Command tests => 75;
+use Test::More;
+use File::Temp;
+
+#  -f file    read list of targets from a file ( - means stdin) (only if no -g specified)
+#  -g         generate target list (only if no -f specified)
+#               (specify the start and end IP in the target list, or supply a IP netmask)
+#               (ex. ../src/fping -g 192.168.1.0 192.168.1.255 or ../src/fping -g 192.168.1.0/24)
+#  -H n       Set the IP TTL value (Time To Live hops)
+
+my $tmpfile = File::Temp->new();
+print $tmpfile "127.0.0.1\n127.0.0.2\n";
+close($tmpfile);
+
+my $tmpfile2 = File::Temp->new();
+print $tmpfile2 "# comment\n127.0.0.1\n\n127.0.0.2\n";
+close($tmpfile2);
+
+# fping without option (-> equivalent to 'fping -f -')
+{
+my $cmd = Test::Command->new(cmd => "cat ".$tmpfile->filename." | fping");
+$cmd->exit_is_num(0);
+$cmd->stdout_is_eq("127.0.0.1 is alive\n127.0.0.2 is alive\n");
+$cmd->stderr_is_eq("");
+}
+
+# fping -f -
+{
+my $cmd = Test::Command->new(cmd => "cat ".$tmpfile->filename." | fping -f -");
+$cmd->exit_is_num(0);
+$cmd->stdout_is_eq("127.0.0.1 is alive\n127.0.0.2 is alive\n");
+$cmd->stderr_is_eq("");
+}
+
+# fping -f file
+{
+my $cmd = Test::Command->new(cmd => "fping -f ".$tmpfile->filename);
+$cmd->exit_is_num(0);
+$cmd->stdout_is_eq("127.0.0.1 is alive\n127.0.0.2 is alive\n");
+$cmd->stderr_is_eq("");
+}
+
+# fping -f file (with comment and empty line)
+{
+my $cmd = Test::Command->new(cmd => "fping -f ".$tmpfile2->filename);
+$cmd->exit_is_num(0);
+$cmd->stdout_is_eq("127.0.0.1 is alive\n127.0.0.2 is alive\n");
+$cmd->stderr_is_eq("");
+}
+
+# fping -f non-existing-file (error)
+{
+my $cmd = Test::Command->new(cmd => "fping -f file-does-not-exist");
+$cmd->exit_is_num(4);
+$cmd->stdout_is_eq("");
+$cmd->stderr_like(qr{: fopen :});
+}
+
+# fping -g (error: no argument)
+{
+my $cmd = Test::Command->new(cmd => "fping -g");
+$cmd->exit_is_num(1);
+$cmd->stdout_is_eq("");
+$cmd->stderr_like(qr{^Usage: fping \[options\] \[targets\.\.\.\]});
+}
+
+# fping -g (error: single argument, but not in cidr format)
+{
+my $cmd = Test::Command->new(cmd => "fping -g 127.0.0.1");
+$cmd->exit_is_num(1);
+$cmd->stdout_is_eq("");
+$cmd->stderr_like(qr{^Usage: fping \[options\] \[targets\.\.\.\]});
+}
+
+# fping -g (error: CIDR network is not an IP address)
+{
+my $cmd = Test::Command->new(cmd => "fping -g xxx/32");
+$cmd->exit_is_num(1);
+$cmd->stdout_is_eq("");
+$cmd->stderr_like(qr{can't parse address xxx});
+}
+
+# fping -g (error: start of range is not an IP address)
+{
+my $cmd = Test::Command->new(cmd => "fping -g xxx 127.0.0.1");
+$cmd->exit_is_num(1);
+$cmd->stdout_is_eq("");
+$cmd->stderr_like(qr{can't parse address xxx});
+}
+
+# fping -g (error: end of range is not an IP address)
+{
+my $cmd = Test::Command->new(cmd => "fping -g 127.0.0.1 yyy");
+$cmd->exit_is_num(1);
+$cmd->stdout_is_eq("");
+$cmd->stderr_like(qr{can't parse address yyy});
+}
+
+# fping -g (error: too many arguments)
+{
+my $cmd = Test::Command->new(cmd => "fping -g 127.0.0.1 127.0.0.2 127.0.0.3");
+$cmd->exit_is_num(1);
+$cmd->stdout_is_eq("");
+$cmd->stderr_like(qr{^Usage: fping \[options\] \[targets\.\.\.\]});
+}
+
+# fping -g (range)
+{
+my $cmd = Test::Command->new(cmd => "fping -g 127.0.0.1 127.0.0.5");
+$cmd->exit_is_num(0);
+$cmd->stdout_is_eq("127.0.0.1 is alive\n127.0.0.2 is alive\n127.0.0.3 is alive\n127.0.0.4 is alive\n127.0.0.5 is alive\n");
+$cmd->stderr_is_eq("");
+}
+
+# fping -g (empty range)
+{
+my $cmd = Test::Command->new(cmd => "fping -g 127.0.0.2 127.0.0.1");
+$cmd->exit_is_num(1);
+$cmd->stdout_is_eq("");
+$cmd->stderr_is_eq("");
+}
+
+# fping -g (too large range)
+{
+my $cmd = Test::Command->new(cmd => "fping -g 127.0.0.1 127.255.255.254");
+$cmd->exit_is_num(1);
+$cmd->stdout_is_eq("");
+$cmd->stderr_is_eq("fping: -g parameter generates too many addresses\n");
+}
+
+# fping -g (cidr)
+{
+my $cmd = Test::Command->new(cmd => "fping -g 127.0.0.1/30");
+$cmd->exit_is_num(0);
+$cmd->stdout_is_eq("127.0.0.1 is alive\n127.0.0.2 is alive\n");
+$cmd->stderr_is_eq("");
+}
+
+# fping -g (cidr - long prefixes: point-to-point)
+{
+my $cmd = Test::Command->new(cmd => "fping -g 127.0.0.2/31");
+$cmd->exit_is_num(0);
+$cmd->stdout_is_eq("127.0.0.2 is alive\n127.0.0.3 is alive\n");
+$cmd->stderr_is_eq("");
+}
+
+# fping -g (cidr - long prefixes: host)
+{
+my $cmd = Test::Command->new(cmd => "fping -g 127.0.0.2/32");
+$cmd->exit_is_num(0);
+$cmd->stdout_is_eq("127.0.0.2 is alive\n");
+$cmd->stderr_is_eq("");
+}
+
+# fping -g (cidr - too long prefixes)
+{
+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("fping: netmask must be between 1 and 32 (is: 33)\n");
+}
+
+# fping -g (cidr - too short prefixes)
+{
+my $cmd = Test::Command->new(cmd => "fping -g 127.0.0.2/0");
+$cmd->exit_is_num(1);
+$cmd->stdout_is_eq("");
+$cmd->stderr_is_eq("fping: netmask must be between 1 and 32 (is: 0)\n");
+}
+
+# fping -g (cidr - too many addresses)
+{
+my $cmd = Test::Command->new(cmd => "fping -g 127.0.0.0/8");
+$cmd->exit_is_num(1);
+$cmd->stdout_is_eq("");
+$cmd->stderr_is_eq("fping: -g parameter generates too many addresses\n");
+}
+
+# fping -g (range - no IPv6 generator)
+SKIP: {
+    if($ENV{SKIP_IPV6}) {
+        skip 'Skip IPv6 tests', 3;
+    }
+    my $cmd = Test::Command->new(cmd => "fping -6 -g ::1 ::1");
+    $cmd->exit_is_num(1);
+    $cmd->stdout_is_eq("");
+    $cmd->stderr_is_eq("fping: -g works only with IPv4 addresses\n");
+}
+
+# fping -g (range - no IPv6 generator - start address IPv6)
+SKIP: {
+    if($ENV{SKIP_IPV6}) {
+        skip 'Skip IPv6 tests', 3;
+    }
+    my $cmd = Test::Command->new(cmd => "fping -6 -g ::1 127.0.0.1");
+    $cmd->exit_is_num(1);
+    $cmd->stdout_is_eq("");
+    $cmd->stderr_is_eq("fping: -g works only with IPv4 addresses\n");
+}
+
+# fping -g (range - no IPv6 generator - end address IPv6)
+SKIP: {
+    if($ENV{SKIP_IPV6}) {
+        skip 'Skip IPv6 tests', 3;
+    }
+    my $cmd = Test::Command->new(cmd => "fping -6 -g 127.0.0.1 ::1");
+    $cmd->exit_is_num(1);
+    $cmd->stdout_is_eq("");
+    $cmd->stderr_is_eq("fping: -g works only with IPv4 addresses\n");
+}
+
+# fping -g (CIDR - no IPv6 generator)
+SKIP: {
+    if($ENV{SKIP_IPV6}) {
+        skip 'Skip IPv6 tests', 3;
+    }
+    my $cmd = Test::Command->new(cmd => "fping -6 -g ::1/128");
+    $cmd->exit_is_num(1);
+    $cmd->stdout_is_eq("");
+    $cmd->stderr_is_eq("fping: -g works only with IPv4 addresses\n");
+}
+
+# fping -H
+{
+my $cmd = Test::Command->new(cmd => "fping -H 1 127.0.0.1");
+$cmd->exit_is_num(0);
+$cmd->stdout_is_eq("127.0.0.1 is alive\n");
+$cmd->stderr_is_eq("");
+}
diff --git a/ci/tmp.4rIIEYCP9c/fping-5.3/ci/test-07-options-i-m.pl b/ci/tmp.4rIIEYCP9c/fping-5.3/ci/test-07-options-i-m.pl
new file mode 100755 (executable)
index 0000000..426286a
--- /dev/null
@@ -0,0 +1,94 @@
+#!/usr/bin/perl -w
+
+use Test::Command tests => 16;
+use Test::More;
+
+#  -i n       interval between sending ping packets (in millisec) (default 25)
+#  -l         loop sending pings forever
+#  -k         set fwmark on ping packets
+#  -m         ping multiple interfaces on target host
+#  -M         don't fragment
+
+# fping -i n
+{
+my $cmd = Test::Command->new(cmd => "fping -i 100 127.0.0.1 127.0.0.2");
+$cmd->exit_is_num(0);
+$cmd->stdout_is_eq("127.0.0.1 is alive\n127.0.0.2 is alive\n");
+$cmd->stderr_is_eq("");
+}
+
+# fping -l
+{
+my $cmd = Test::Command->new(cmd => '(sleep 2; pkill fping)& fping -p 900 -l 127.0.0.1');
+$cmd->stdout_like(qr{127\.0\.0\.1 : \[0\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\)
+127\.0\.0\.1 : \[1\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\)
+});
+}
+
+# fping -l --print-tos --print-ttl
+{
+my $cmd = Test::Command->new(cmd => '(sleep 2; pkill fping)& fping -p 900 --print-ttl --print-tos -l 127.0.0.1');
+$cmd->stdout_like(qr{127\.0\.0\.1 : \[0\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\) \(TOS \d+\) \(TTL \d+\)
+127\.0\.0\.1 : \[1\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\) \(TOS \d+\) \(TTL \d+\)
+});
+}
+
+# fping -k
+SKIP: {
+if($^O ne 'linux') {
+    skip '-k option is only supported on Linux', 3;
+}
+my $cmd = Test::Command->new(cmd => 'fping -k 256 127.0.0.1');
+$cmd->exit_is_num(0);
+$cmd->stdout_is_eq("127.0.0.1 is alive\n");
+$cmd->stderr_is_eq("");
+}
+
+# fping -l with SIGQUIT
+{
+my $cmd = Test::Command->new(cmd => '(sleep 2; pkill -QUIT fping; sleep 2; pkill fping)& fping -p 900 -l 127.0.0.1');
+$cmd->stdout_like(qr{127\.0\.0\.1 : \[0\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\)
+127\.0\.0\.1 : \[1\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\)
+127\.0\.0\.1 : \[2\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\)
+127\.0\.0\.1 : \[3\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\)
+127\.0\.0\.1 : \[4\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\)
+});
+$cmd->stderr_like(qr{\[\d+:\d+:\d+\]
+127\.0\.0\.1 : xmt/rcv/%loss = \d+/\d+/\d+%, min/avg/max = \d+\.\d+/\d+\.\d+/\d+\.\d+
+});
+}
+
+# fping -l -Q
+SKIP: {
+if($^O eq 'darwin') {
+    skip 'On macOS, this test is unreliable', 2;
+}
+my $cmd = Test::Command->new(cmd => '(sleep 2; pkill fping)& fping -p 850 -l -Q 1 127.0.0.1');
+$cmd->stdout_is_eq("");
+$cmd->stderr_like(qr{\[\d\d:\d\d:\d\d\]
+127\.0\.0\.1 : xmt/rcv/%loss = \d/\d/\d%, min/avg/max = \d\.\d+/\d\.\d+/\d\.\d+
+\[\d\d:\d\d:\d\d\]
+127\.0\.0\.1 : xmt/rcv/%loss = \d/\d/\d%, min/avg/max = \d\.\d+/\d\.\d+/\d\.\d+
+});
+}
+
+# fping -l -t
+{
+my $cmd = Test::Command->new(cmd => '(sleep 2; pkill fping)& fping -p 900 -t 1500 -l 127.0.0.1');
+$cmd->stdout_like(qr{127\.0\.0\.1 : \[0\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\)
+127\.0\.0\.1 : \[1\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\)
+});
+}
+
+# fping -M
+SKIP: {
+    if($^O eq 'darwin') {
+        skip '-M option not supported on macOS', 3;
+    }
+    my $cmd = Test::Command->new(cmd => "fping -M 127.0.0.1");
+    $cmd->exit_is_num(0);
+    $cmd->stdout_is_eq("127.0.0.1 is alive\n");
+    $cmd->stderr_is_eq("");
+}
+
+# fping -m -> test-14-internet-hosts
diff --git a/ci/tmp.4rIIEYCP9c/fping-5.3/ci/test-08-options-n-q.pl b/ci/tmp.4rIIEYCP9c/fping-5.3/ci/test-08-options-n-q.pl
new file mode 100755 (executable)
index 0000000..d614db1
--- /dev/null
@@ -0,0 +1,187 @@
+#!/usr/bin/perl -w
+
+use Test::Command tests => 48;
+use Test::More;
+
+#  -n         show targets by name (-d is equivalent)
+#  -O n       set the type of service (tos) flag on the ICMP packets
+#  -p n       interval between ping packets to one target (in millisec)
+#               (in looping and counting modes, default 1000)
+#  -q         quiet (don't show per-target/per-ping results)
+#  -Q n       same as -q, but show summary every n seconds
+
+# fping -n -> test-14-internet-hosts
+
+# fping -d -n
+{
+my $cmd = Test::Command->new(cmd => "fping -d -n 127.0.0.1");
+$cmd->exit_is_num(1);
+$cmd->stdout_is_eq("");
+$cmd->stderr_is_eq("fping: use either one of -d or -n\n");
+}
+
+# fping -n -d
+{
+my $cmd = Test::Command->new(cmd => "fping -n -d 127.0.0.1");
+$cmd->exit_is_num(1);
+$cmd->stdout_is_eq("");
+$cmd->stderr_is_eq("fping: use either one of -d or -n\n");
+}
+
+# fping -o
+{
+my $cmd = Test::Command->new(cmd => "fping -t100 -p 100 -o -c 5 8.8.8.7");
+$cmd->exit_is_num(1);
+$cmd->stdout_is_eq("8.8.8.7 : [0], timed out (NaN avg, 100% loss)
+8.8.8.7 : [1], timed out (NaN avg, 100% loss)
+8.8.8.7 : [2], timed out (NaN avg, 100% loss)
+8.8.8.7 : [3], timed out (NaN avg, 100% loss)
+8.8.8.7 : [4], timed out (NaN avg, 100% loss)
+");
+$cmd->stderr_like(qr{^\s*8\.8\.8\.7 : xmt/rcv/%loss = 5/0/100%, outage\(ms\) = 50\d\s*$});
+}
+
+# fping -O
+{
+my $cmd = Test::Command->new(cmd => "fping -O 2 127.0.0.1");
+$cmd->exit_is_num(0);
+$cmd->stdout_is_eq("127.0.0.1 is alive\n");
+$cmd->stderr_is_eq("");
+}
+
+# fping -O --print-tos
+{
+my $cmd = Test::Command->new(cmd => "fping -O 2 --print-tos 127.0.0.1");
+$cmd->exit_is_num(0);
+$cmd->stdout_like(qr{127\.0\.0\.1 is alive \(TOS \d+\)
+});
+$cmd->stderr_is_eq("");
+}
+
+# fping -a -O --print-tos
+{
+my $cmd = Test::Command->new(cmd => "fping -a -O 32 --print-tos 127.0.0.1");
+$cmd->exit_is_num(0);
+$cmd->stdout_like(qr{127\.0\.0\.1 \(TOS \d+\)
+});
+$cmd->stderr_is_eq("");
+}
+
+# fping --print-tos
+{
+my $cmd = Test::Command->new(cmd => "fping --print-tos 127.0.0.1");
+$cmd->exit_is_num(0);
+$cmd->stdout_like(qr{127\.0\.0\.1 is alive \(TOS 0\)
+});
+$cmd->stderr_is_eq("");
+}
+
+# fping --print-tos with IPv6
+SKIP: {
+    if($ENV{SKIP_IPV6}) {
+        skip 'Skip IPv6 tests', 3;
+    }
+    my $cmd = Test::Command->new(cmd => "fping --print-tos ::1");
+    $cmd->exit_is_num(0);
+    $cmd->stdout_like(qr{::1 is alive \(TOS unknown\)\n});
+    $cmd->stderr_is_eq("");
+}
+
+# fping -q
+{
+my $cmd = Test::Command->new(cmd => "fping -q -p 100 -c 3 127.0.0.1");
+$cmd->exit_is_num(0);
+$cmd->stdout_is_eq("");
+$cmd->stderr_like(qr{127\.0\.0\.1 : xmt/rcv/%loss = 3/3/0%, min/avg/max = \d\.\d+/\d\.\d+/\d\.\d+
+});
+}
+
+# fping -Q
+{
+my $cmd = Test::Command->new(cmd => "fping -Q 1 -p 400 -c 4 127.0.0.1");
+$cmd->exit_is_num(0);
+$cmd->stdout_is_eq("");
+$cmd->stderr_like(qr{\[\d+:\d+:\d+\]
+127\.0\.0\.1 : xmt/rcv/%loss = 3/3/0%, min/avg/max = \d\.\d+/\d\.\d+/\d\.\d+
+127\.0\.0\.1 : xmt/rcv/%loss = 4/4/0%, min/avg/max = \d\.\d+/\d\.\d+/\d\.\d+
+});
+}
+
+# fping -Q (longer test to show two time stamps and reset statistics)
+{
+my $cmd = Test::Command->new(cmd => "fping -Q 1 -p 550 -c 5 127.0.0.1");
+$cmd->exit_is_num(0);
+$cmd->stdout_is_eq("");
+$cmd->stderr_like(qr{\[\d+:\d+:\d+\]
+127\.0\.0\.1 : xmt/rcv/%loss = 2/2/0%, min/avg/max = \d\.\d+/\d\.\d+/\d\.\d+
+\[\d+:\d+:\d+\]
+127\.0\.0\.1 : xmt/rcv/%loss = 2/2/0%, min/avg/max = \d\.\d+/\d\.\d+/\d\.\d+
+127\.0\.0\.1 : xmt/rcv/%loss = 5/5/0%, min/avg/max = \d\.\d+/\d\.\d+/\d\.\d+
+});
+}
+
+# fping -Q n ignores non-number characters after the number, except for keywords
+{
+my $cmd = Test::Command->new(cmd => "fping -Q 1whatever -p 550 -c 5 127.0.0.1");
+$cmd->exit_is_num(0);
+$cmd->stdout_is_eq("");
+$cmd->stderr_like(qr{\[\d+:\d+:\d+\]
+127\.0\.0\.1 : xmt/rcv/%loss = 2/2/0%, min/avg/max = \d\.\d+/\d\.\d+/\d\.\d+
+\[\d+:\d+:\d+\]
+127\.0\.0\.1 : xmt/rcv/%loss = 2/2/0%, min/avg/max = \d\.\d+/\d\.\d+/\d\.\d+
+127\.0\.0\.1 : xmt/rcv/%loss = 5/5/0%, min/avg/max = \d\.\d+/\d\.\d+/\d\.\d+
+});
+}
+
+# fping -Q n ignores unknown keywords
+{
+my $cmd = Test::Command->new(cmd => "fping -Q 1,not_a_keyword -p 550 -c 5 127.0.0.1");
+$cmd->exit_is_num(0);
+$cmd->stdout_is_eq("");
+$cmd->stderr_like(qr{\[\d+:\d+:\d+\]
+127\.0\.0\.1 : xmt/rcv/%loss = 2/2/0%, min/avg/max = \d\.\d+/\d\.\d+/\d\.\d+
+\[\d+:\d+:\d+\]
+127\.0\.0\.1 : xmt/rcv/%loss = 2/2/0%, min/avg/max = \d\.\d+/\d\.\d+/\d\.\d+
+127\.0\.0\.1 : xmt/rcv/%loss = 5/5/0%, min/avg/max = \d\.\d+/\d\.\d+/\d\.\d+
+});
+}
+
+# fping -Q n,cumulative
+{
+my $cmd = Test::Command->new(cmd => "fping -Q 1,cumulative -p 550 -c 5 127.0.0.1");
+$cmd->exit_is_num(0);
+$cmd->stdout_is_eq("");
+$cmd->stderr_like(qr{\[\d+:\d+:\d+\]
+127\.0\.0\.1 : xmt/rcv/%loss = 2/2/0%, min/avg/max = \d\.\d+/\d\.\d+/\d\.\d+
+\[\d+:\d+:\d+\]
+127\.0\.0\.1 : xmt/rcv/%loss = 4/4/0%, min/avg/max = \d\.\d+/\d\.\d+/\d\.\d+
+127\.0\.0\.1 : xmt/rcv/%loss = 5/5/0%, min/avg/max = \d\.\d+/\d\.\d+/\d\.\d+
+});
+}
+
+# fping -Q -o
+{
+my $cmd = Test::Command->new(cmd => "fping -c4 -Q1 -p550 -o 8.8.8.7");
+$cmd->exit_is_num(1);
+$cmd->stdout_is_eq("");
+$cmd->stderr_like(qr{\[\d+:\d+:\d+\]
+8\.8\.8\.7 : xmt/rcv/%loss = 1/0/100%, outage\(ms\) = 55\d
+\[\d+:\d+:\d+\]
+8\.8\.8\.7 : xmt/rcv/%loss = 2/0/100%, outage\(ms\) = 110\d
+8\.8\.8\.7 : xmt/rcv/%loss = 4/0/100%, outage\(ms\) = 220\d
+});
+}
+
+# fping -Q n,cumulative -o
+{
+my $cmd = Test::Command->new(cmd => "fping -c4 -Q1,cumulative -p550 -o 8.8.8.7");
+$cmd->exit_is_num(1);
+$cmd->stdout_is_eq("");
+$cmd->stderr_like(qr{\[\d+:\d+:\d+\]
+8\.8\.8\.7 : xmt/rcv/%loss = 1/0/100%, outage\(ms\) = 55\d
+\[\d+:\d+:\d+\]
+8\.8\.8\.7 : xmt/rcv/%loss = 3/0/100%, outage\(ms\) = 165\d
+8\.8\.8\.7 : xmt/rcv/%loss = 4/0/100%, outage\(ms\) = 220\d
+});
+}
+
diff --git a/ci/tmp.4rIIEYCP9c/fping-5.3/ci/test-09-option-r-t.pl b/ci/tmp.4rIIEYCP9c/fping-5.3/ci/test-09-option-r-t.pl
new file mode 100755 (executable)
index 0000000..2c26d24
--- /dev/null
@@ -0,0 +1,149 @@
+#!/usr/bin/perl -w
+
+use Test::Command tests => 30;
+use Test::More;
+
+#  -R         random bytes
+#  -r n       number of retries (default 3)
+#  -s         print final stats
+#  -S addr    set source address
+#  -t n       individual target initial timeout (in millisec) (default 500)
+#  -T n       ignored (for compatibility with fping 2.4)
+
+# fping -R
+{
+my $cmd = Test::Command->new(cmd => "fping -q -R -c3 -p100 127.0.0.1");
+$cmd->exit_is_num(0);
+$cmd->stdout_is_eq("");
+$cmd->stderr_like(qr{127\.0\.0\.1 : xmt/rcv/%loss = 3/3/0%.*});
+}
+
+SKIP: {
+    if($ENV{SKIP_IPV6}) {
+        skip 'Skip IPv6 tests', 3;
+    }
+    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%.*});
+}
+
+# fping -r tested in test-4-options-a-b.pl
+
+# fping -s
+{
+my $cmd = Test::Command->new(cmd => "fping -s 127.0.0.1");
+$cmd->exit_is_num(0);
+$cmd->stdout_is_eq("127.0.0.1 is alive\n");
+$cmd->stderr_like(qr{\s*
+\s*1 targets
+\s*1 alive
+\s*0 unreachable
+\s*0 unknown addresses
+\s*
+\s*0 timeouts \(waiting for response\)
+\s*1 ICMP Echos sent
+\s*1 ICMP Echo Replies received
+\s*0 other ICMP received
+
+\s*\d\.\d+ ms \(min round trip time\)
+\s*\d\.\d+ ms \(avg round trip time\)
+\s*\d\.\d+ ms \(max round trip time\)
+\s*\d\.\d+ sec \(elapsed real time\)
+});
+}
+
+# fping -s (no host reachable)
+{
+my $cmd = Test::Command->new(cmd => "fping -r0 -t100 -s 8.8.0.0");
+$cmd->exit_is_num(1);
+$cmd->stdout_is_eq("8.8.0.0 is unreachable\n");
+$cmd->stderr_like(qr{\s*
+\s*1 targets
+\s*0 alive
+\s*1 unreachable
+\s*0 unknown addresses
+\s*
+\s*1 timeouts \(waiting for response\)
+\s*1 ICMP Echos sent
+\s*0 ICMP Echo Replies received
+\s*0 other ICMP received
+
+\s*\d\.\d+ ms \(min round trip time\)
+\s*\d\.\d+ ms \(avg round trip time\)
+\s*\d\.\d+ ms \(max round trip time\)
+\s*\d\.\d+ sec \(elapsed real time\)
+});
+}
+
+# fping -s (both valid and invalid host name)
+{
+my $cmd = Test::Command->new(cmd => "fping -s 127.0.0.1 host.name.invalid");
+$cmd->exit_is_num(2);
+$cmd->stdout_is_eq("127.0.0.1 is alive\n");
+$cmd->stderr_like(qr{host\.name\.invalid: .+
+\s*
+\s*1 targets
+\s*1 alive
+\s*0 unreachable
+\s*1 unknown addresses
+\s*
+\s*0 timeouts \(waiting for response\)
+\s*1 ICMP Echos sent
+\s*1 ICMP Echo Replies received
+\s*0 other ICMP received
+
+\s*\d\.\d+ ms \(min round trip time\)
+\s*\d\.\d+ ms \(avg round trip time\)
+\s*\d\.\d+ ms \(max round trip time\)
+\s*\d\.\d+ sec \(elapsed real time\)
+});
+}
+
+# fping -S
+{
+my $cmd = Test::Command->new(cmd => "fping -S 127.0.0.1 127.0.0.1");
+$cmd->exit_is_num(0);
+$cmd->stdout_is_eq("127.0.0.1 is alive\n");
+$cmd->stderr_is_eq("");
+}
+
+# fping -S (wrong source address)
+{
+my $cmd = Test::Command->new(cmd => "fping -S 192.0.2.47 127.0.0.1");
+$cmd->exit_is_num(4);
+$cmd->stdout_is_eq("");
+$cmd->stderr_like(qr{fping: cannot bind source address : .+\n});
+}
+
+# fping -S
+SKIP: {
+    if($ENV{SKIP_IPV6}) {
+        skip 'Skip IPv6 tests', 3;
+    }
+    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("");
+}
+
+# fping -S (wrong IPv6 source address)
+SKIP: {
+    if($ENV{SKIP_IPV6}) {
+        skip 'Skip IPv6 tests', 3;
+    }
+    my $cmd = Test::Command->new(cmd => "fping -S 2001:db8::1 ::1");
+    $cmd->exit_is_num(4);
+    $cmd->stdout_is_eq("");
+    $cmd->stderr_like(qr{fping: cannot bind source address : .+\n});
+}
+
+# fping -S
+{
+my $cmd = Test::Command->new(cmd => "fping -S bla");
+$cmd->exit_is_num(1);
+$cmd->stdout_is_eq("");
+$cmd->stderr_is_eq("fping: can't parse source address: bla\n");
+}
+
+# (note: fping -t also tested in test-4-options-a-b.pl)
diff --git a/ci/tmp.4rIIEYCP9c/fping-5.3/ci/test-10-option-u-x.pl b/ci/tmp.4rIIEYCP9c/fping-5.3/ci/test-10-option-u-x.pl
new file mode 100755 (executable)
index 0000000..db45737
--- /dev/null
@@ -0,0 +1,48 @@
+#!/usr/bin/perl -w
+
+use Test::Command tests => 15;
+
+#  -u         show targets that are unreachable
+#  -v         show version
+#  -x         shows if >=N hosts are reachable or not
+#  -X         exits true immediately when N hosts are found
+
+# fping -u
+{
+my $cmd = Test::Command->new(cmd => "fping -r0 -u 8.8.0.0 127.0.0.1");
+$cmd->exit_is_num(1);
+$cmd->stdout_is_eq("8.8.0.0\n");
+$cmd->stderr_is_eq("");
+}
+
+# fping -v
+{
+my $cmd = Test::Command->new(cmd => "fping -v");
+$cmd->exit_is_num(0);
+$cmd->stdout_like(qr{ping: Version [45]\.\d+(-rc\d+)?});
+$cmd->stderr_is_eq("");
+}
+
+# fping -x
+{
+my $cmd = Test::Command->new(cmd => "fping -x 1 8.8.0.0 127.0.0.1");
+$cmd->exit_is_num(0);
+$cmd->stdout_is_eq("Enough hosts reachable (required: 1, reachable: 1)\n");
+$cmd->stderr_is_eq("");
+}
+
+# fping -x
+{
+my $cmd = Test::Command->new(cmd => "fping -x 2 8.8.0.0 127.0.0.1");
+$cmd->exit_is_num(1);
+$cmd->stdout_is_eq("Not enough hosts reachable (required: 2, reachable: 1)\n");
+$cmd->stderr_is_eq("");
+}
+
+# fping -X
+{
+my $cmd = Test::Command->new(cmd => "fping -X 1 --generate 127.0.0.0/29");
+$cmd->exit_is_num(0);
+$cmd->stdout_is_eq("Enough hosts reachable (required: 1, reachable: 1)\n");
+$cmd->stderr_is_eq("");
+}
diff --git a/ci/tmp.4rIIEYCP9c/fping-5.3/ci/test-11-unpriv.pl b/ci/tmp.4rIIEYCP9c/fping-5.3/ci/test-11-unpriv.pl
new file mode 100755 (executable)
index 0000000..debf2af
--- /dev/null
@@ -0,0 +1,95 @@
+#!/usr/bin/perl -w
+
+use English;
+use File::Copy;
+use File::Temp qw/ tempdir /;
+use Test::Command;
+use Test::More;
+
+if( $^O eq 'darwin' ) {
+    plan skip_all => 'Test irrelevant on MacOS';
+    exit 0;
+}
+
+sub get_ping_gid_range {
+    open FD, "/proc/sys/net/ipv4/ping_group_range" or return undef;
+    chomp(my $line = <FD>);
+    my @range = split(/\s+/, $line);
+    close FD;
+    return @range;
+}
+
+my @gids = split(' ', $EGID);
+my @allowed = get_ping_gid_range();
+
+# Make a copy of the binary so that we get rid of setuid bit
+my $tmpdir = tempdir(CLEANUP => 1);
+my $fping_bin = `which fping`; chomp $fping_bin;
+my $fping_copy = "$tmpdir/fping.copy";
+copy($fping_bin, $fping_copy);
+chmod 0755, $fping_copy;
+
+# Determine what test to run, based on whether unprivileged
+# pings are allowed.
+if(scalar grep { $_ >= $allowed[0] && $_ <= $allowed[1] } @gids) {
+    diag('test unprivileged mode');
+    test_unprivileged_works();
+}
+else {
+    test_privileged_fails();
+}
+
+sub test_unprivileged_works {
+    plan tests => 15;
+
+    {
+        my $cmd = Test::Command->new(cmd => "$fping_copy 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_copy --print-tos 127.0.0.1");
+        $cmd->exit_is_num(0);
+        $cmd->stdout_is_eq("127.0.0.1 is alive (TOS unknown)\n");
+        $cmd->stderr_is_eq("");
+    }
+    {
+        my $cmd = Test::Command->new(cmd => "$fping_copy --print-ttl 127.0.0.1");
+        $cmd->exit_is_num(0);
+        $cmd->stdout_is_eq("127.0.0.1 is alive (TTL unknown)\n");
+        $cmd->stderr_is_eq("");
+    }
+    SKIP: {
+        if($^O ne 'linux') {
+            skip '-k option is only supported on Linux', 3;
+        }
+        my $cmd = Test::Command->new(cmd => "$fping_copy -4 -k 256 127.0.0.1");
+        $cmd->exit_is_num(0);
+        $cmd->stdout_is_eq("127.0.0.1 is alive\n");
+        $cmd->stderr_like(qr{fwmark ipv4: .+\n});
+    }
+    SKIP: {
+        if($^O ne 'linux') {
+            skip '-k option is only supported on Linux', 3;
+        }
+        if($ENV{SKIP_IPV6}) {
+            skip 'Skip IPv6 tests', 3;
+        }
+        my $cmd = Test::Command->new(cmd => "$fping_copy -6 -k 256 ::1");
+        $cmd->exit_is_num(0);
+        $cmd->stdout_is_eq("::1 is alive\n");
+        $cmd->stderr_like(qr{fwmark ipv6: .+\n});
+    }
+}
+
+sub test_privileged_fails {
+    plan tests => 3;
+
+    {
+        my $cmd = Test::Command->new(cmd => "$fping_copy 127.0.0.1");
+        $cmd->exit_is_num(4);
+        $cmd->stdout_is_eq("");
+        $cmd->stderr_like(qr{: can't create socket \(must run as root\?\)});
+    }
+}
diff --git a/ci/tmp.4rIIEYCP9c/fping-5.3/ci/test-12-option-type.pl b/ci/tmp.4rIIEYCP9c/fping-5.3/ci/test-12-option-type.pl
new file mode 100755 (executable)
index 0000000..6514425
--- /dev/null
@@ -0,0 +1,27 @@
+#!/usr/bin/perl -w
+
+use Test::Command tests => 84;
+use Test::More;
+
+# some options require a numeric argument
+for my $arg (qw(b B c C H i O p Q r t x X)) {
+    for my $test_input (qw(xxx '')) {
+        my $cmd = Test::Command->new(cmd => "fping -$arg $test_input");
+        $cmd->exit_is_num(1);
+        $cmd->stdout_is_eq("");
+        $cmd->stderr_like(qr{Usage:});
+    }
+}
+
+# fping -k, only supported on Linux, requires a number
+SKIP: {
+    if($^O ne 'linux') {
+        skip '-k option is only supported on Linux', 6;
+    }
+    for my $test_input (qw(xxx '')) {
+        my $cmd = Test::Command->new(cmd => "fping -k $test_input 127.0.0.1");
+        $cmd->exit_is_num(1);
+        $cmd->stdout_is_eq("");
+        $cmd->stderr_like(qr{Usage:});
+    }
+}
diff --git a/ci/tmp.4rIIEYCP9c/fping-5.3/ci/test-13-unknown-host.pl b/ci/tmp.4rIIEYCP9c/fping-5.3/ci/test-13-unknown-host.pl
new file mode 100755 (executable)
index 0000000..65c8312
--- /dev/null
@@ -0,0 +1,11 @@
+#!/usr/bin/perl -w
+
+use Test::Command tests => 3;
+
+# fping
+{
+my $cmd = Test::Command->new(cmd => "fping nosuchname.example.com");
+$cmd->exit_is_num(2);
+$cmd->stdout_is_eq("");
+$cmd->stderr_like(qr{^nosuchname\.example\.com: .*not (known|found)});
+}
diff --git a/ci/tmp.4rIIEYCP9c/fping-5.3/ci/test-14-ping-internet-hosts.pl b/ci/tmp.4rIIEYCP9c/fping-5.3/ci/test-14-ping-internet-hosts.pl
new file mode 100755 (executable)
index 0000000..3c18cc4
--- /dev/null
@@ -0,0 +1,106 @@
+#!/usr/bin/perl -w
+
+use Test::Command;
+use Test::More;
+
+# evaluate if we have internet
+if(!gethostbyname("www.google.com")) {
+    plan skip_all => 'Can\'t resolve www.google.com -> no internet?';
+    exit 0;
+}
+
+plan tests => 30;
+
+my $re_num = qr{\d+(?:\.\d+)?};
+
+# fping
+{
+my $cmd = Test::Command->new(cmd => "fping -q -i 10 -p 20 -c 3 -t200  8.8.8.8 www.france-telecom.fr www.google.com");
+$cmd->exit_is_num(0);
+$cmd->stdout_is_eq("");
+$cmd->stderr_like(qr{8\.8\.8\.8\s*: xmt/rcv/%loss = [123]/[123]/\d+%, min/avg/max = $re_num/$re_num/$re_num
+www\.france-telecom\.fr\s*: xmt/rcv/%loss = [123]/[123]/\d+%, min/avg/max = $re_num/$re_num/$re_num
+www\.google\.com\s*: xmt/rcv/%loss = [123]/[123]/\d+%, min/avg/max = $re_num/$re_num/$re_num
+});
+}
+
+# fping -A -n
+{
+my $cmd = Test::Command->new(cmd => "fping -A -n 8.8.8.8");
+$cmd->exit_is_num(0);
+$cmd->stdout_is_eq("dns.google (8.8.8.8) is alive\n");
+$cmd->stderr_is_eq("");
+}
+
+# fping -4 -A -n
+{
+my $cmd = Test::Command->new(cmd => "fping -4 -A -n dns.google");
+$cmd->exit_is_num(0);
+$cmd->stdout_like(qr{^dns.google \(8\.8\.(4\.4|8\.8)\) is alive\n$});
+$cmd->stderr_is_eq("");
+}
+
+# fping -4 --addr --rdns
+{
+my $cmd = Test::Command->new(cmd => "fping -4 --addr --rdns www.apple.com");
+$cmd->exit_is_num(0);
+$cmd->stdout_like(qr{^\S+\.akamaitechnologies\.com \(\d+\.\d+\.\d+\.\d+\) is alive\n$});
+$cmd->stderr_is_eq("");
+}
+
+# fping -4 --addr --name
+{
+my $cmd = Test::Command->new(cmd => "fping -4 --addr --name www.google.com");
+$cmd->exit_is_num(0);
+$cmd->stdout_like(qr{^www\.google\.com \(\d+\.\d+\.\d+\.\d+\) is alive\n$});
+$cmd->stderr_is_eq("");
+}
+
+# fping -A -n (IPv6)
+SKIP: {
+    if($ENV{SKIP_IPV6}) {
+        skip 'Skip IPv6 tests', 3;
+    }
+    my $cmd = Test::Command->new(cmd => "fping -6 -n -A dns.google");
+    $cmd->exit_is_num(0);
+    $cmd->stdout_like(qr{^dns.google \(2001:4860:4860::88(44|88)\) is alive\n$});
+    $cmd->stderr_is_eq("");
+}
+
+# fping -m
+SKIP: {
+    if($ENV{SKIP_IPV6}) {
+        skip 'Skip IPv6 tests', 3;
+    }
+    my $cmd = Test::Command->new(cmd => "fping -A -m dns.google");
+    $cmd->exit_is_num(0);
+    $cmd->stdout_like(qr{^.* is alive\n.* is alive\n.* is alive\n.* is alive\n});
+    $cmd->stderr_is_eq("");
+}
+
+# fping -m -A
+{
+my $cmd = Test::Command->new(cmd => "fping -4 -A -m www.cloudflare.com");
+$cmd->exit_is_num(0);
+$cmd->stdout_like(qr{\d+\.\d+\.\d+\.\d+ is alive\n\d+\.\d+\.\d+\.\d+ is alive\n});
+$cmd->stderr_is_eq("");
+}
+
+# fping -n
+{
+my $cmd = Test::Command->new(cmd => "fping -n 8.8.8.8");
+$cmd->exit_is_num(0);
+$cmd->stdout_is_eq("dns.google is alive\n");
+$cmd->stderr_is_eq("");
+}
+
+# fping -M
+SKIP: {
+    if($^O eq 'darwin') {
+        skip '-M option not supported on macOS', 3;
+    }
+    my $cmd = Test::Command->new(cmd => "fping -r 0 -b 10000 -M 8.8.8.8");
+    $cmd->exit_is_num(1);
+    $cmd->stdout_is_eq("8.8.8.8 is unreachable\n");
+    $cmd->stderr_is_eq("8.8.8.8: error while sending ping: Message too long\n");
+}
diff --git a/ci/tmp.4rIIEYCP9c/fping-5.3/ci/test-15-netdata.pl b/ci/tmp.4rIIEYCP9c/fping-5.3/ci/test-15-netdata.pl
new file mode 100755 (executable)
index 0000000..83dc439
--- /dev/null
@@ -0,0 +1,35 @@
+#!/usr/bin/perl -w
+
+use Test::Command;
+use Test::More;
+
+plan tests => 3;
+
+# fping
+{
+my $cmd = Test::Command->new(cmd => "fping -c 2 -Q 1 -N 127.0.0.1");
+$cmd->exit_is_num(0);
+$cmd->stdout_like(qr{CHART fping\.127_0_0_1_packets '' 'FPing Packets' packets '127.0.0.1' fping\.packets line 110020 1
+DIMENSION xmt sent absolute 1 1
+DIMENSION rcv received absolute 1 1
+BEGIN fping\.127_0_0_1_packets
+SET xmt = 1
+SET rcv = 1
+END
+CHART fping\.127_0_0_1_quality '' 'FPing Quality' percentage '127.0.0.1' fping\.quality area 110010 1
+DIMENSION returned '' absolute 1 1
+BEGIN fping\.127_0_0_1_quality
+SET returned = 100
+END
+CHART fping\.127_0_0_1_latency '' 'FPing Latency' ms '127.0.0.1' fping\.latency area 110000 1
+DIMENSION min minimum absolute 1 1000000
+DIMENSION max maximum absolute 1 1000000
+DIMENSION avg average absolute 1 1000000
+BEGIN fping\.127_0_0_1_latency
+SET min = \d+
+SET avg = \d+
+SET max = \d+
+END}
+);
+$cmd->stderr_like(qr{127.0.0.1 : xmt/rcv/%loss = 2/2/0%, min/avg/max = \d\.\d+/\d\.\d+/\d\.\d+});
+}
diff --git a/ci/tmp.4rIIEYCP9c/fping-5.3/ci/test-issue-56.pl b/ci/tmp.4rIIEYCP9c/fping-5.3/ci/test-issue-56.pl
new file mode 100755 (executable)
index 0000000..e36cc14
--- /dev/null
@@ -0,0 +1,18 @@
+#!/usr/bin/perl -w
+
+# regression testing for github issue #56
+#
+use Test::Command;
+use Test::More;
+
+if( $^O eq 'darwin' ) {
+    plan skip_all => 'Test disabled on MacOS';
+    exit 0;
+}
+
+plan tests => 3;
+
+my $cmd1 = Test::Command->new(cmd => "fping -t100 -p100 -C3 255.255.255.255");
+$cmd1->exit_is_num(1);
+$cmd1->stdout_is_eq("");
+$cmd1->stderr_is_eq("\n255.255.255.255 : - - -\n");
diff --git a/ci/tmp.4rIIEYCP9c/fping-5.3/ci/test-issue-58.pl b/ci/tmp.4rIIEYCP9c/fping-5.3/ci/test-issue-58.pl
new file mode 100755 (executable)
index 0000000..db5161a
--- /dev/null
@@ -0,0 +1,10 @@
+#!/usr/bin/perl -w
+
+# regression testing for github issue #58
+
+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("fping: -g works only with IPv4 addresses\n");
diff --git a/ci/tmp.4rIIEYCP9c/fping-5.3/ci/test-tarball.sh b/ci/tmp.4rIIEYCP9c/fping-5.3/ci/test-tarball.sh
new file mode 100755 (executable)
index 0000000..da43a25
--- /dev/null
@@ -0,0 +1,31 @@
+#!/bin/bash
+
+# make sure that the .tar.gz file contains everything necessary
+# to build fping
+
+set -e
+set -x
+
+# skip on macos
+if [[ "$OSTYPE" == "darwin"* ]]; then
+    exit 0
+fi
+
+make dist
+VERSION=$(ls fping-*.tar.gz | sed -e 's/^fping-//' | sed -e 's/\.tar\.gz$//')
+if [ -z "$VERSION" ]; then
+    echo "tar.gz file not found." >&2
+    exit 1
+fi
+
+# unarchive
+TMPDIR=$(mktemp -d --tmpdir=ci)
+cd $TMPDIR
+tar xf ../../fping-$VERSION.tar.gz
+DIRNAME=$(ls)
+
+# build
+cd $DIRNAME
+./configure --enable-ipv4 --enable-ipv6 --prefix=/opt/fping
+make
+sudo make install 
diff --git a/ci/tmp.4rIIEYCP9c/fping-5.3/configure.ac b/ci/tmp.4rIIEYCP9c/fping-5.3/configure.ac
new file mode 100644 (file)
index 0000000..d573075
--- /dev/null
@@ -0,0 +1,129 @@
+dnl Process this file with autoconf to produce a configure script.
+
+dnl Minimum Autoconf version required.
+AC_PREREQ(2.59)
+
+AC_INIT([fping],[5.4])
+
+m4_ifdef([AC_AUTOCONF_VERSION],[AC_USE_SYSTEM_EXTENSIONS], [AC_GNU_SOURCE])
+
+# Detect Operatingsystem
+AC_CANONICAL_TARGET
+only_clock_realtime=no
+
+case "${target}" in
+  *darwin*)
+    only_clock_realtime=yes
+    ;;
+  *freebsd*)
+    only_clock_realtime=yes
+    ;;
+  *openbsd*)
+    only_clock_realtime=yes
+    ;;
+esac
+
+dnl --disable-ipv4
+AC_ARG_ENABLE([ipv4],
+  AS_HELP_STRING([--disable-ipv4], [Disable support for pinging IPv4 hosts]))
+AM_CONDITIONAL([IPV4], [test "x$enable_ipv4" != "xno"])
+AM_COND_IF([IPV4], [AC_DEFINE([IPV4], [1], [IPv4 enabled])])
+
+dnl --disable-ipv6
+AC_ARG_ENABLE([ipv6],
+  AS_HELP_STRING([--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>
+      #include <sys/types.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_TIMESTAMPNS)]))
+AS_IF([test "x$enable_timestamp" != "xno"], [
+   AC_CHECK_DECL([SO_TIMESTAMPNS], [AC_DEFINE(HAVE_SO_TIMESTAMPNS, [1], [SO_TIMESTAMPNS 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
+AS_IF([test "x$enable_timestamp" = "xyes" -a "x$have_so_timestamp" = "xno"], [
+  AC_MSG_ERROR([--enable-timestamp not supported on this platform])
+])
+AS_IF([test "x$only_clock_realtime" = "xyes"], [AC_DEFINE(ONLY_CLOCK_REALTIME, [1], [ONLY_CLOCK_REALTIME is defined])])
+
+AC_ARG_ENABLE([safe-limits],
+  AS_HELP_STRING([--enable-safe-limits], [Restrict timing parameters (-i, -p) within "safe" limits]))
+AS_IF([test "x$enable_safe_limits" = "xyes"], [
+   AC_DEFINE(FPING_SAFE_LIMITS, [1], [safe limits should be enforced])])
+
+AC_ARG_ENABLE([debug],
+  AS_HELP_STRING([--enable-debug], [enable debugging @<:@default=no@:>@]), [enable_debug=$enableval], [enable_debug=no])
+AS_IF([test "x$enable_debug" = "xyes"], [
+  AC_DEFINE([DEBUG], [1], [Define if debugging is enabled])])
+
+AM_INIT_AUTOMAKE([-Wall -Werror foreign])
+AM_MAINTAINER_MODE
+
+AC_CONFIG_HEADERS([config.h])
+
+dnl Checks for programs.
+
+AC_PROG_CC
+AM_PROG_CC_C_O
+m4_version_prereq([2.70],,[AC_PROG_CC_STDC])
+AC_PROG_CPP
+AC_PROG_INSTALL
+
+dnl Checks for libraries.
+
+AC_CHECK_FUNC(gethostbyname)
+if test $ac_cv_func_gethostbyname = no; then
+    AC_CHECK_LIB(nsl, gethostbyname)
+fi
+AC_CHECK_FUNC(connect)
+if test $ac_cv_func_connect = no; then
+    AC_CHECK_LIB(socket, connect)
+fi
+AC_CHECK_FUNC(sigaction)
+if test $ac_cv_func_sigaction = yes; then
+    AC_DEFINE([USE_SIGACTION],[1],[Define if sigaction is available.])
+fi
+
+AC_CHECK_FUNCS([strftime], [],
+  [AC_MSG_ERROR([strftime function is required but not found])])
+
+AH_TOP([
+#ifndef CONFIG_H
+#define CONFIG_H
+])
+
+AH_BOTTOM([
+/* some OSes do not define this ... lets take a wild guess */
+
+#ifndef INADDR_NONE
+#  define INADDR_NONE 0xffffffffU
+#endif
+
+#endif /* CONFIG_H */
+
+])
+
+dnl Checks for header files.
+AC_CHECK_HEADERS([unistd.h sys/file.h stdlib.h sys/select.h])
+
+AC_CONFIG_FILES([Makefile
+                 doc/Makefile
+                 src/Makefile])
+
+AC_OUTPUT
diff --git a/ci/tmp.4rIIEYCP9c/fping-5.3/contrib/Dockerfile b/ci/tmp.4rIIEYCP9c/fping-5.3/contrib/Dockerfile
new file mode 100644 (file)
index 0000000..c20a1d6
--- /dev/null
@@ -0,0 +1,17 @@
+FROM debian:stable
+
+# Base
+RUN apt-get update && apt-get install -y \
+  build-essential \
+  automake \
+  autoconf \
+  m4
+
+# Add source code
+COPY ./ /app
+
+# Compile
+WORKDIR /app
+RUN autoreconf --install
+RUN ./configure && make && make install
+ENTRYPOINT ["fping"]
\ No newline at end of file
diff --git a/ci/tmp.4rIIEYCP9c/fping-5.3/contrib/fping.spec b/ci/tmp.4rIIEYCP9c/fping-5.3/contrib/fping.spec
new file mode 100644 (file)
index 0000000..71d1ea0
--- /dev/null
@@ -0,0 +1,74 @@
+Summary: send ICMP echo probes to multiple hosts
+Name: fping
+Version: 4.2
+Release: 1
+License: Freely redistributable without restriction
+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.md COPYING CHANGELOG.md
+/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,cap_net_admin+ep /usr/sbin/fping
+    /usr/sbin/setcap cap_net_raw,cap_net_admin+ep /usr/sbin/fping6
+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:
+
diff --git a/ci/tmp.4rIIEYCP9c/fping-5.3/doc/CHANGELOG.pre-v4 b/ci/tmp.4rIIEYCP9c/fping-5.3/doc/CHANGELOG.pre-v4
new file mode 100644 (file)
index 0000000..fc9a0aa
--- /dev/null
@@ -0,0 +1,627 @@
+2017-02-09  David Schweikert  <david@schweikert.ch>
+  * Version 3.16
+  * (feature) Support kernel-timestamping of received packets (#46)
+  * (feature) Simplify restrictions: only -i >= 1 and -p >= 10 are enforced now
+  * (bugfix) Fix option -m to return all IPs of a hostname
+  * (bugfix) Fix option -H (ttl) for IPv6
+  * (bugfix) Fix option -M (don't fragment) for IPv6
+  * (bugfix) Fix option -O (ToS) for IPv6
+  * (bugfix) Fix compatibility issue with AIX (#69, @blentzgh)
+  * (bugfix) Fix option -q not suppressing some ICMP error messages (#83)
+  * (bugfix) Fix option -M expecting an argument, when it shouldn't
+  * (bugfix) Fix minor issues found by Coverity Scan
+
+2017-01-11  David Schweikert  <david@schweikert.ch>
+  * Version 3.15
+  * (bugfix) Fix compiler errors on platforms other than Linux (related
+             to the new -M option, #109)
+  * Test suite fixes for macOS
+
+2017-01-10  David Schweikert  <david@schweikert.ch>
+  * Version 3.14
+  * (feature) Ignore network and broadcast for cidrs /31 and /32 (#102, Martin Topholm)
+  * (feature) New option '-M' to set the "Don't Fragment" flag (#91, Don Bowman)
+  * (feature) New option '-N' to output statistics for netdata (see: http://my-netdata.io/, #105, Costa Tsaousis)
+  * (feature) New option '-o' to calculate total outage time (#90, @jgerbeck)
+  * (bugfix) Exit code should be 2 when the hostname can't be resolved
+            (fixes #98, reported by @green-fox)
+  * (bugfix)  Fix issue compliling on RHEL/Centos 7 (#95, @jbackman)
+  * (bugfix) Lower -i limit to 1 instead of 10
+  * (bugfix) Improve interval preciseness of -Q reporting
+  * (bugfix) Fix occasional false positive in -Q reporting (#97)
+  * (bugfix) Solaris 10 portability fix (#107, Peter Bray)
+
+2015-10-21  David Schweikert  <david@schweikert.ch>
+  * Version 3.13
+  * (bugfix) Fix ICMP errors sometimes causing crashes with fping >= 3.11
+             (fixes #85, reported by Jamie Heilman and Bill Blough)
+
+2015-10-14  David Schweikert  <david@schweikert.ch>
+  * Version 3.12
+  * (bugfix) Fix fping6 -R (fixes #84, reported by Stuart Henderson)
+
+2015-10-12  David Schweikert  <david@schweikert.ch>
+  * Version 3.11
+  * (feature)  New option -R to use random bytes instead of NULLs (#72, Anthony DeRobertis)
+  * (feature)  Small documentation and performance improvements (Ryan Underwood)
+  * (bugfix)   Fix double entries with fping -u and unreachable hosts
+  * (internal) Use sockaddr_storage and simplify code, so that we can one day support both IPv4 and IPv6 with the same binary
+
+2014-05-03  David Schweikert  <david@schweikert.ch>
+  * Version 3.10
+  * Fix confusing error message with -g and IPv6 addresses (#58, reported by Axel Beckert)
+  * Allow option '-f' also for non-root (since setuid privileges are dropped)
+  * Do not retry twice DNS lookup on DNS lookup problem
+  * Remove support for NIS groups
+  * Better document -B backoff-factor and when it can be used (#33, Oleksiy Zagorskyi)
+  * More tests added
+
+2014-03-08  David Schweikert  <david@schweikert.ch>
+  * Version 3.9
+  * Fix random output on socket error (reported by Aleksandrs Saveljevs, #56)
+  * Support ppc64le architecture by including alpha libtool version
+    (reported by Amit Kumar Gupta and Aravinda B Thunug)
+  * Fix compilation problem on FreeBSD (#57)
+  * Initial test suite and continous intergration (with travis-ci.org / coveralls.io)
+  * Don't output usage information on error
+
+2013-11-08  David Schweikert  <david@schweikert.ch>
+  * Version 3.8
+  * Fix segmentation fault introduced in version 3.7 with loop mode (reported
+    by Vlad Glagolev, #55)
+
+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)
+
+2012-04-26  David Schweikert  <david@schweikert.ch>
+  * Version 3.1
+  * -g option (generate): exclude network and broadcast address for cidr
+    ranges (idea by Eric Brander)
+  * do not explicitely check if running as root, to make it possible to
+    install fping with linux capabilities instead of making it setuid
+    (setcap cap_net_raw+ep fping)
+  * ANSI C (C89) compiler now a requirement
+  * Portability fixes
+  * Reorganized source directory
+  * Bugfix: fix timeout issue on Solaris (Sandor Geller)
+  * Man-page fixes (Axel Beckert)
+  * Added -H option to specify number of hops (Paul Duda)
+  * Output usage information to stdout when called with -h (Paul Duda)
+
+2011-12-28  David Schweikert  <david@schweikert.ch>
+  * Version 3.0
+  * rewritten main loop for improved performance
+  * -T parameter (select timeout) now obsolete
+  * Maintenance taken over from unresponsive previous maintainer
+    (anybody please step up, if you disagree)
+  * New homepage: www.fping.org
+
+2009-12-21  Tobi Oetiker  <tobi@oetiker.ch>
+  * Version v2.4b2-to3-ipv6
+  * added -On option to set the TOS octet
+  * Removed unused variables from code
+  * updated to current autoconf standards
+  * Merged Debian changes (see below)
+
+----------------------------------------------------------------------
+
+fping (2.4b2-to-ipv6-16.1) unstable; urgency=low
+
+  * NMU during Moenchengladbach BSP
+  * Fixes FTBFS on kfreebsd (Closes: #555398)
+  * Fixes typo "Paramter" in binary
+
+ -- Axel Beckert <abe@deuxchevaux.org>  Sat, 23 Jan 2010 16:22:02 +0100
+
+fping (2.4b2-to-ipv6-16) unstable; urgency=low
+
+  * Fix the following bugs
+    - Network byte order sensitivity was missing completely.
+      Added hopefully all missing calls.
+    - The sequence numbering scheme used led to packet drops.
+      Changed it to a more senseful numbering scheme.
+    - Some minor C programming mistakes ('=' instead of '==').
+    Patch by Stephan Fuhrmann; closes: #502569
+  * Add support for command line select timeout setting
+    Patch by Marton Balint; closes: #502575
+  * Remove symlinks in /usr/sbin; closes: #377732
+  * Standards-Version is 3.8.0
+
+ -- Anibal Monsalve Salazar <anibal@debian.org>  Sat, 18 Oct 2008 12:04:52 +1100
+
+fping (2.4b2-to-ipv6-15) unstable; urgency=low
+
+  * Added interface binding (-I) for fping
+    Patch by Peter Naulls <peter@mushroomnetworks.com>
+    Closes: #439014
+  * Fixed a couple of typos in fping.8. Closes: #423180
+  * Added homepage control header
+  * Bumped Standards-Version to 3.7.3
+  * Fixed the following lintian issue:
+    - debian-rules-sets-DH_COMPAT
+
+ -- Anibal Monsalve Salazar <anibal@debian.org>  Mon, 03 Mar 2008 17:46:17 +1100
+
+fping (2.4b2-to-ipv6-13) unstable; urgency=low
+
+  * Fixed stdout flush problem, closes: #340146.
+    Patch by Bart Martens <bart.martens@advalvas.be>.
+
+ -- Anibal Monsalve Salazar <anibal@debian.org>  Fri, 30 Dec 2005 08:30:09 +1100
+
+fping (2.4b2-to-ipv6-12) unstable; urgency=low
+
+  * Fixed "problem with option -r (retry limit)", closes: #318402.
+    Patch by Qingning Huo <qingningh@lanware.co.uk>.
+
+ -- Anibal Monsalve Salazar <anibal@debian.org>  Sat, 08 Oct 2005 21:26:35 +1000
+
+fping (2.4b2-to-ipv6-11) unstable; urgency=low
+
+  * Fixed "would be useful to specify 'source address' like ping for multi
+    homed machines", closes: #198486.
+    Patch by Marc Haber <mh+debian-bugs@zugschlus.de>.
+
+ -- Anibal Monsalve Salazar <anibal@debian.org>  Thu, 02 Jun 2005 08:14:54 +1000
+
+fping (2.4b2-to-ipv6-10) unstable; urgency=low
+
+  * Fixed "unnecessary delay with the -c option after the last packet"
+    (Closes: #293856). Patch by Niko Tyni <ntyni@iki.fi>
+
+ -- Anibal Monsalve Salazar <anibal@debian.org>  Sun, 06 Feb 2005 23:25:57 +1100
+
+fping (2.4b2-to-ipv6-9) unstable; urgency=low
+
+  * Fixed "fping6 always does reverse lookup" (Closes: #273647).
+    Patch by Jeroen Massar and forwarded by Bernhard Schmidt <berni@birkenwald.de>
+
+ -- Anibal Monsalve Salazar <A.Monsalve.Salazar@IEEE.org>  Mon, 10 Jan 2005 00:01:32 +1100
+
+fping (2.4b2-to-ipv6-7) unstable; urgency=low
+
+  * Build fping in build/ipv[46] instead of build and build-ipv6.
+  * Made DNS errors non-fatal for IPv6 (closes: #198056).
+
+ -- Herbert Xu <herbert@debian.org>  Fri, 20 Jun 2003 21:36:30 +1000
+
+fping (2.4b2-to-ipv6-6) unstable; urgency=low
+
+  * Do not use incorrect linux.h file (closes: #85468).
+
+ -- Herbert Xu <herbert@debian.org>  Sat, 17 May 2003 14:13:11 +1000
+
+fping (2.4b2-to-ipv6-5) unstable; urgency=low
+
+  * Fixed yet another divide by zero bug (closes: #148445).
+
+ -- Herbert Xu <herbert@debian.org>  Tue,  4 Jun 2002 12:18:03 +1000
+
+fping (2.4b2-to-ipv6-4) unstable; urgency=low
+
+  * Made fping6 setuid (closes: #136386).
+  * Moved fping back into bin.
+  * Partially applied IPv6 patch to fix IPv6 checksums (closes: #136479).
+
+ -- Herbert Xu <herbert@debian.org>  Sun,  7 Apr 2002 20:36:56 +1000
+
+fping (2.4b2-to-ipv6-3) unstable; urgency=low
+
+  * Added compatibility symlink for fping (closes: #135203).
+
+ -- Herbert Xu <herbert@debian.org>  Sat, 23 Feb 2002 08:34:11 +1100
+
+fping (2.4b2-to-ipv6-2) unstable; urgency=low
+
+  * Fixed another divide by zero error (closes: #132370).
+
+ -- Herbert Xu <herbert@debian.org>  Thu,  7 Feb 2002 20:10:48 +1100
+
+fping (2.4b2-to-ipv6-1) unstable; urgency=low
+
+  * New upstream release.
+  * Install fping into sbin as done by upstream.
+
+ -- Herbert Xu <herbert@debian.org>  Fri,  1 Feb 2002 22:11:59 +1100
+
+fping (2.2b2-3) unstable; urgency=low
+
+  * Removed INSTALL file from package (closes: #84050).
+  * Fixed alignment bug.
+
+ -- Herbert Xu <herbert@debian.org>  Sat, 10 Feb 2001 19:25:18 +1100
+
+fping (2.2b2-2) unstable; urgency=low
+
+  * Made changes for dpkg-statoverride (closes: #83838).
+
+ -- Herbert Xu <herbert@debian.org>  Sun, 28 Jan 2001 21:53:05 +1100
+
+fping (2.2b2-1) unstable; urgency=low
+
+  * New upstream release.
+  * Fixed typo that prevented -d from working (closes: #83255).
+  * Drop root privileges after opening the socket (closes: #81589).
+  * Fixed the options [tip], they were out by a factor of 10
+    (Richard Kettlewell, closes: #83742).
+
+ -- Herbert Xu <herbert@debian.org>  Sun, 28 Jan 2001 00:09:41 +1100
+
+fping (2.2b1-2) unstable; urgency=low
+
+  * Fixed typo in control file, spotted by William Ono (closes: #49909).
+
+ -- Herbert Xu <herbert@debian.org>  Mon, 15 May 2000 12:27:03 +1000
+
+fping (2.2b1-1) unstable; urgency=low
+
+  * Initial release.
+  * Fixed divide by zero error (closes: #29902).
+
+ -- Herbert Xu <herbert@debian.org>  Sat, 30 Oct 1999 16:36:19 +1000
+---------------------------------------------------------------------------------
+
+Wed Jan 16 2002
+Jeroen Massar
+- Revision v2.4b2-to-IPv6
+   - Added IPv6 support.
+   - Added -I option for selecting source IPv4/IPv6 address.
+   - Makefile.in now generates a Makefile which will build both
+     fping (IPv4) and fping6 (IPv6). Thus it makes an fping (IPv4 only)
+     and an fping6 (IPv6 only).
+   - num_unreachable was counted twice when a sendto() generated errors.
+   - See http://unfix.org/projects/ipv6/
+
+Tue Mar 14 2001
+Jason Ewasiuk <jasone@remote.net>
+- Revision v2.4b1
+        - added -g option for generating IPs from a start to an end value
+                - two available options, generate IPs from start IP to end IP
+                  or from a passed netmask, such as 192.168.1.0/24
+
+Thu Feb 15 2001
+Jason Ewasiuk <jasone@remote.net>
+- Revision v2.3b1
+        - formatting changes to code layout (fping.c)
+        NOTE:  Best viewed with a tab stop of 4
+        - merged in changes from Debian c/o Herbert Xu
+        <herbert@gondor.apana.org.au>
+                - Compilation fix on alphas with glibc
+                - Alignment issues (note from JE:  in wait_for_reply())
+                - A typo with the time specified on the command line
+                (note from JE:  bug was using 10 instead of 100)
+                - Drop privileges after obtaining socket
+                (note from JE:  might be moot, since prog exits if
+                user is not root)
+        - touched all files in package to this date
+        - couple new #ifdefs added for future WIN32 support
+        (Haven't got to adding this yet, will take a lot of rewriting.)
+
+Fri Dec  8 10:33:13 2000  Roland Schemers  <schemers@stanford.edu>
+
+        * stop using sys_errlist and start using strerror
+        fixed bug in output of -C
+
+Wed Jan  8 11:18:37 1997  Roland Schemers  <schemers@stanford.edu>
+
+        * Created ChangeLog file. What follows was from the CHANGES file.
+
+* Revision 2.0  1994/10/31 21:26:23 morgan
+
+  Substantial rewrite, including new features:
+
+    support some traditional ping features:
+      loop mode
+      specify size of data packets
+      specify how many pings to send
+      show per-response data
+      interpret ICMPs other than ICMP Echo response
+
+  also
+
+    rewrote main loop completely
+    make timings in tenths of milliseconds
+    do exponential backoff on retries
+    port to more systems
+    add some debugging stuff
+    do better checking on whether received ICMP is for us
+
+* Revision 1.24  1993/12/10  23:11:39  schemers
+
+  commented out seteuid(getuid()) since it isn't needed
+
+* Revision 1.23  1993/12/10  18:33:41  schemers
+
+  Took out the -f option for non-root users. This can be enabled by
+  defining ENABLE_F_OPTION before compiling. There is a call to
+  access before opening the file, but there is a race condition.
+  Reading from stdin is much safer.
+
+
+* Revision 1.22  1993/11/16  19:49:24  schemers
+
+  Took out setuid(getuid()) and used access() system call to
+  check for access to the file specified with "-f".
+
+* Revision 1.21  1993/07/20  18:08:19  schemers
+
+  commented out the test to make sure the ping packet came from the
+  same IP address as the one we sent to. This could cause problems on
+  multi-homed hosts.
+
+* Revision 1.20  1993/02/23  00:16:38  schemers
+
+fixed syntax error (should have compiled before checking in...)
+
+* Revision 1.19  1993/02/23  00:15:15  schemers
+
+turned off printing of "is alive" when -a is specified.
+
+* Revision 1.18  1992/07/28  15:16:44  schemers
+
+added a fflush(stdout) call before the summary is sent to stderr, so
+everything shows up in the right order.
+
+* Revision 1.17  1992/07/23  03:29:42  schemers
+* Revision 1.16  1992/07/22  19:24:37  schemers
+
+Fixed declaration of timeval_diff. Didn't notice the problem because
+I use 'cc' in stead of gcc under Ultrix. Time to switch? :-)
+
+Modified file reaing so it would skip blank lines or lines starting
+with a '#'. Now you can do something like:
+
+fping -ad < /etc/hosts
+
+* Revision 1.15  1992/07/21  17:07:18  schemers
+
+Put in sanity checks so only root can specify "dangerous" options.
+Changed usage to show switchs in alphabetical order.
+* Revision 1.14  1992/07/21  16:40:52  schemers
+* Revision 1.13  1992/07/17  21:02:17  schemers
+
+Changed the default timeout to 2500 msec, and retry to 3. This was
+due to suggestions from people with slow (WAN) networks. The default
+1 sec timeout was too fast.
+
+
+Added '-e' option for showing elapsed (round-trip) times on pakets, and
+modified the -s option to include min, max, and average round-trip times,
+and over all elapsed time.
+
+Modified action taken when a error is returned from sendto. The action
+taken now considers the host unreachable and prints the hostname
+followed by the errno message. The program will not exit and will continue
+to try other hosts.
+
+* Revision 1.12  1992/07/17  16:38:54  schemers
+* Revision 1.11  1992/07/17  16:28:38  schemers
+
+ move socket create call so I could do a setuid(getuid()) before the
+ fopen call is made. Once the socket is created root privs aren't needed
+ to send stuff out on it.
+
+ moved num_timeout counter. It really was for debug purposes and didn't
+ make sense to the general public :-) Now it is the number of timeouts
+ (pings that didn't get received with the time limit).
+
+
+* Revision 1.10 1992/07/16  16:24:38  schemers
+* Revision 1.9  1992/07/16  16:00:04  schemers
+* Revision 1.8  1992/07/16  05:44:41  schemers
+
+Added _NO_PROTO stuff for older compilers, and _POSIX_SOURCE
+for unistd.h, and _POSIX_SOURCE for stdlib.h. Also added
+check for __cplusplus.
+
+Now compiles ok under Ultrix 3.1, and Sun4 using cc. Also compiled
+ok using g++ 2.2.2.
+
+Changed '-a' and '-u' flags to be mutually exclusive (makes sense, since
+specifiying both '-a' and '-u' is the same as not specifiying anything.
+Since '-a' and '-u' are mutually exclusive, these options now only print
+the hostname, and not the 'is alive' or 'is unreachable'  messages.
+This makes it much easier to do stuff like:
+
+#!/usr/local/bin/perl
+$hosts_to_backup=`cat /etc/hosts.backup|fping -a`;
+
+Since you don't have to strip off the 'is alive' messages.
+
+Changed usage to and stats to print to stderr instead of stdout.
+
+-----------------------------------------------------------------------------
+
+RCS header info from original fping.c package (no longer required)
+
+/*
+ ***************************************************
+ *
+ * Standard RCS Header information (see co(1))
+ *
+ * $Author: schemers $
+ *
+ * $Date: 1997/01/08 20:29:33 $
+ *
+ * $Revision: 2.2 $
+ *
+ * $Locker:  $
+ *
+ * $Source: /afs/ir/group/networking/src/fping/fping-2.2/src/RCS/fping.c,v $
+ *
+ * $State: Exp $
+ *
+ * $Log: fping.c,v $
+ *
+ * Revision 2.2  1997/01/08 20:29:33  schemers
+ * changes for autoconf/automake
+ *
+ * Revision 2.1  1997/01/08 19:07:18  schemers
+ * checked in RL "Bob"'s changes before configure'ing
+ *
+ * Revision 2.0  1994/10/31  21:26:23  schemers
+ * many changes by RL "Bob" Morgan
+ *   add timing data collection, loop mode, per-packet output, etc
+ *
+ * Revision 1.24  1993/12/10  23:11:39  schemers
+ * commented out seteuid(getuid()) since it isn't needed
+ *
+ * Revision 1.23  1993/12/10  18:33:41  schemers
+ * Took out the -f option for non-root users. This can be enabled by
+ * defining ENABLE_F_OPTION before compiling. There is a call to
+ * access before opening the file, but there is a race condition.
+ * Reading from stdin is much safer.
+ *
+ * Revision 1.22  1993/11/16  19:49:24  schemers
+ * Took out setuid(getuid()) and used access() system call to
+ * check for access to the file specified with "-f".
+ *
+ * Revision 1.21  1993/07/20  18:08:19  schemers
+ * commented out the test to make sure the ping packet came from the
+ * same IP address as the one we sent to. This could cause problems on
+ * multi-homed hosts.
+ *
+ * Revision 1.20  1993/02/23  00:16:38  schemers
+ * fixed syntax error (should have compiled before checking in...)
+ *
+ * Revision 1.19  1993/02/23  00:15:15  schemers
+ * turned off printing of "is alive" when -a is specified.
+ *
+ * Revision 1.18  1992/07/28  15:16:44  schemers
+ * added a fflush(stdout) call before the summary is sent to stderr, so
+ * everything shows up in the right order.
+ *
+ * Revision 1.17  1992/07/23  03:29:42  schemers
+ * fixed declaration of timeval_diff.
+ *
+ * Revision 1.16  1992/07/22  19:24:37  schemers
+ * Modified file reading so it would skip blanks lines or lines starting
+ * with a '#'. Now you can do something like:
+ *
+ * fping -ad < /etc/hosts
+ *
+ * Revision 1.15  1992/07/21  17:07:18  schemers
+ * Put in sanity checks so only root can specify "dangerous" options.
+ * Changed usage to show switchs in alphabetical order.
+ *
+ * Revision 1.14  1992/07/21  16:40:52  schemers
+ * Now when sendto returns an error, the host is considered unreachable and
+ * and the error message (from errno) is displayed.
+ *
+ * Revision 1.13  1992/07/17  21:02:17  schemers
+ * changed default timeout to 2500 msec (for WANs), and default try
+ * to 3. This gives 10 second overall timeout.
+ *
+ * Added -e option for showing elapsed (round-trip) time on packets
+ *
+ * Modified -s option to inlude to round-trip stats
+ *
+ * Added #ifndef DEFAULT_* stuff its easier to change the defaults
+ *
+ * Reorganized main loop.
+ *
+ * cleaned up timeval stuff. removed set_timeval and timeval_expired
+ * since they aren't needed anymore. Just use timeval_diff.
+ *
+ * Revision 1.12  1992/07/17  16:38:54  schemers
+ * move socket create call so I could do a setuid(getuid()) before the
+ * fopen call is made. Once the socket is created root privs aren't needed
+ * to send stuff out on it.
+ *
+ * Revision 1.11  1992/07/17  16:28:38  schemers
+ * moved num_timeout counter. It really was for debug purposes and didn't
+ * make sense to the general public :-) Now it is the number of timeouts
+ * (pings that didn't get received with the time limit).
+ *
+ * Revision 1.10  1992/07/16  16:24:38  schemers
+ * changed usage() to use fprintf(stderr,"...");
+ *
+ * Revision 1.9  1992/07/16  16:00:04  schemers
+ * Added _NO_PROTO stuff for older compilers, and _POSIX_SOURCE
+ * for unistd.h, and _POSIX_SOURCE for stdlib.h. Also added
+ * check for __cplusplus.
+ *
+ * Revision 1.8  1992/07/16  05:44:41  schemers
+ * changed -a and -u to only show hostname in results. This is
+ * for easier parsing. Also added -v flag
+ *
+ * Revision 1.7  1992/07/14  18:45:23  schemers
+ * initialized last_time in add_host function
+ *
+ * Revision 1.6  1992/07/14  18:32:40  schemers
+ * changed select to use FD_ macros
+ *
+ * Revision 1.5  1992/07/14  17:21:22  schemers
+ * standardized exit status codes
+ *
+ * Revision 1.4  1992/06/26  15:25:35  schemers
+ * changed name from rrping to fping
+ *
+ * Revision 1.3  1992/06/24  15:39:32  schemers
+ * added -d option for unreachable systems
+ *
+ * Revision 1.2  1992/06/23  03:01:23  schemers
+ * misc fixes from R.L. "Bob" Morgan
+ *
+ * Revision 1.1  1992/06/19  18:23:52  schemers
+ * Initial revision
+ *
+ *--------------------------------------------------
+ * Copyright (c) 1992, 1994, 1997 Board of Trustees
+ *            Leland Stanford Jr. University
+ ***************************************************
+ */
+
+
diff --git a/ci/tmp.4rIIEYCP9c/fping-5.3/doc/Makefile.am b/ci/tmp.4rIIEYCP9c/fping-5.3/doc/Makefile.am
new file mode 100644 (file)
index 0000000..20adc28
--- /dev/null
@@ -0,0 +1,6 @@
+man_MANS = fping.8
+
+EXTRA_DIST = fping.8 fping.pod README.1992 CHANGELOG.pre-v4
+
+fping.8: fping.pod
+       pod2man  -c "" -s 8 -r "fping" $< >$@
diff --git a/ci/tmp.4rIIEYCP9c/fping-5.3/doc/README.1992 b/ci/tmp.4rIIEYCP9c/fping-5.3/doc/README.1992
new file mode 100644 (file)
index 0000000..a1020cd
--- /dev/null
@@ -0,0 +1,43 @@
+Original README (from 1992)
+
+        fping - A tool to quickly ping N number of hosts to determine
+        their reachability.
+
+             Roland J. Schemers III - Stanford University
+                   schemers@Stanford.EDU
+
+      fping is a ping(1) like program which uses the Internet Control
+      Message Protocol (ICMP) echo request to determine if a host is
+      up. fping is different from ping in that you can specify any
+      number of hosts on the command line, or specify a file containing
+      the lists of hosts to ping. Instead of trying one host until it
+      timeouts or replies, fping will send out a ping packet and move
+      on to the next host in a round-robin fashion. If a host replies,
+      it is noted and removed from the list of hosts to check. If a host
+      does not respond within a certain time limit and/or retry limit it 
+      will be considered unreachable. 
+
+Site
+      Stanford University has a large TCP/IP network with over 16,000 
+      assigned IP addresses and over 100 IP subnets.
+
+Problem and Issues
+
+      With a large a number of IP addresses in use, its becomes more and
+      more time consuming to check on which IP addresses are actively
+      in use, and which critical machines (routers, bridges, servers, etc)
+      are reachable. One example is we have a program which goes through
+      all of our routers arp caches looking for IP addresses that are in 
+      use. After finding a list of IP addresses that aren't in any arp
+      caches fping can then be used to see if these IP addresses really
+      aren't being used, or are just behind the routers. Checking 2500
+      hosts (99% of which are unreachable) via ping can take hours.
+       
+      fping was written to solve the problem of pinging N number of hosts
+      in an efficient manner. By sending out pings in a round-robin fashion
+      and checking on responses as they come in at random, a large number of 
+      hosts can be checked at once.
+
+      Unlike ping, fping is meant to be used in scripts and its
+      output is easy to parse.
+
diff --git a/ci/tmp.4rIIEYCP9c/fping-5.3/doc/fping.8 b/ci/tmp.4rIIEYCP9c/fping-5.3/doc/fping.8
new file mode 100644 (file)
index 0000000..bc4abeb
--- /dev/null
@@ -0,0 +1,420 @@
+.\" Automatically generated by Pod::Man 4.14 (Pod::Simple 3.43)
+.\"
+.\" Standard preamble:
+.\" ========================================================================
+.de Sp \" Vertical space (when we can't use .PP)
+.if t .sp .5v
+.if n .sp
+..
+.de Vb \" Begin verbatim text
+.ft CW
+.nf
+.ne \\$1
+..
+.de Ve \" End verbatim text
+.ft R
+.fi
+..
+.\" Set up some character translations and predefined strings.  \*(-- will
+.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left
+.\" double quote, and \*(R" will give a right double quote.  \*(C+ will
+.\" give a nicer C++.  Capital omega is used to do unbreakable dashes and
+.\" therefore won't be available.  \*(C` and \*(C' expand to `' in nroff,
+.\" nothing in troff, for use with C<>.
+.tr \(*W-
+.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p'
+.ie n \{\
+.    ds -- \(*W-
+.    ds PI pi
+.    if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch
+.    if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\"  diablo 12 pitch
+.    ds L" ""
+.    ds R" ""
+.    ds C` ""
+.    ds C' ""
+'br\}
+.el\{\
+.    ds -- \|\(em\|
+.    ds PI \(*p
+.    ds L" ``
+.    ds R" ''
+.    ds C`
+.    ds C'
+'br\}
+.\"
+.\" Escape single quotes in literal strings from groff's Unicode transform.
+.ie \n(.g .ds Aq \(aq
+.el       .ds Aq '
+.\"
+.\" If the F register is >0, we'll generate index entries on stderr for
+.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index
+.\" entries marked with X<> in POD.  Of course, you'll have to process the
+.\" output yourself in some meaningful fashion.
+.\"
+.\" Avoid warning from groff about undefined register 'F'.
+.de IX
+..
+.nr rF 0
+.if \n(.g .if rF .nr rF 1
+.if (\n(rF:(\n(.g==0)) \{\
+.    if \nF \{\
+.        de IX
+.        tm Index:\\$1\t\\n%\t"\\$2"
+..
+.        if !\nF==2 \{\
+.            nr % 0
+.            nr F 2
+.        \}
+.    \}
+.\}
+.rr rF
+.\"
+.\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2).
+.\" Fear.  Run.  Save yourself.  No user-serviceable parts.
+.    \" fudge factors for nroff and troff
+.if n \{\
+.    ds #H 0
+.    ds #V .8m
+.    ds #F .3m
+.    ds #[ \f1
+.    ds #] \fP
+.\}
+.if t \{\
+.    ds #H ((1u-(\\\\n(.fu%2u))*.13m)
+.    ds #V .6m
+.    ds #F 0
+.    ds #[ \&
+.    ds #] \&
+.\}
+.    \" simple accents for nroff and troff
+.if n \{\
+.    ds ' \&
+.    ds ` \&
+.    ds ^ \&
+.    ds , \&
+.    ds ~ ~
+.    ds /
+.\}
+.if t \{\
+.    ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u"
+.    ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u'
+.    ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u'
+.    ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u'
+.    ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u'
+.    ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u'
+.\}
+.    \" troff and (daisy-wheel) nroff accents
+.ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V'
+.ds 8 \h'\*(#H'\(*b\h'-\*(#H'
+.ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#]
+.ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H'
+.ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u'
+.ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#]
+.ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#]
+.ds ae a\h'-(\w'a'u*4/10)'e
+.ds Ae A\h'-(\w'A'u*4/10)'E
+.    \" corrections for vroff
+.if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u'
+.if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u'
+.    \" for low resolution devices (crt and lpr)
+.if \n(.H>23 .if \n(.V>19 \
+\{\
+.    ds : e
+.    ds 8 ss
+.    ds o a
+.    ds d- d\h'-1'\(ga
+.    ds D- D\h'-1'\(hy
+.    ds th \o'bp'
+.    ds Th \o'LP'
+.    ds ae ae
+.    ds Ae AE
+.\}
+.rm #[ #] #H #V #F C
+.\" ========================================================================
+.\"
+.IX Title "FPING 8"
+.TH FPING 8 "2025-08-19" "fping" ""
+.\" For nroff, turn off justification.  Always turn off hyphenation; it makes
+.\" way too many mistakes in technical documents.
+.if n .ad l
+.nh
+.SH "NAME"
+fping \- send ICMP ECHO_REQUEST packets to network hosts
+.SH "SYNOPSIS"
+.IX Header "SYNOPSIS"
+\&\fBfping\fR [ \fIoptions\fR ] [ \fIsystems...\fR ]
+.SH "DESCRIPTION"
+.IX Header "DESCRIPTION"
+\&\fBfping\fR is a program like \fBping\fR which uses the Internet Control Message
+Protocol (\s-1ICMP\s0) echo request to determine if a target host is responding.
+\&\fBfping\fR differs from \fBping\fR 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, \fBfping\fR 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. \fBfping\fR also supports
+sending a specified number of pings to a target, or looping indefinitely (as in
+\&\fBping\fR ). Unlike \fBping\fR, \fBfping\fR is meant to be used in scripts, so its
+output is designed to be easy to parse.  Current statistics can be obtained without
+termination of process with signal \s-1SIGQUIT\s0 (^\e from the keyboard on most systems).
+.SH "OPTIONS"
+.IX Header "OPTIONS"
+.IP "\fB\-4\fR, \fB\-\-ipv4\fR" 5
+.IX Item "-4, --ipv4"
+Restrict name resolution and IPs to IPv4 addresses.
+.IP "\fB\-6\fR, \fB\-\-ipv6\fR" 5
+.IX Item "-6, --ipv6"
+Restrict name resolution and IPs to IPv6 addresses.
+.IP "\fB\-a\fR, \fB\-\-alive\fR" 5
+.IX Item "-a, --alive"
+Show systems that are alive.  (Options \fB\-c\fR and \fB\-C\fR override \fB\-a\fR.)
+.IP "\fB\-A\fR, \fB\-\-addr\fR" 5
+.IX Item "-A, --addr"
+Display targets by address rather than \s-1DNS\s0 name. Combined with \-d, the output
+will be both the ip and (if available) the hostname.
+.IP "\fB\-b\fR, \fB\-\-size\fR=\fI\s-1BYTES\s0\fR" 5
+.IX Item "-b, --size=BYTES"
+Number of bytes of ping data to send.  The minimum size (normally 12) allows
+room for the data that \fBfping\fR needs to do its work (sequence number,
+timestamp).  The reported received data size includes the \s-1IP\s0 header (normally
+20 bytes) and \s-1ICMP\s0 header (8 bytes), so the minimum total size is 40 bytes.
+Default is 56, as in \fBping\fR. Maximum is the theoretical maximum \s-1IP\s0 datagram
+size (64K), though most systems limit this to a smaller, system-dependent
+number. Cannot be used together with \fB\-\-icmp\-timestamp\fR.
+.IP "\fB\-B\fR, \fB\-\-backoff\fR=\fIN\fR" 5
+.IX Item "-B, --backoff=N"
+Backoff factor. In the default mode, \fBfping\fR 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 (\fB\-t\fR) 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, \fB\-\-count\fR=\fIN\fR" 5
+.IX Item "-c, --count=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 \fB\-q\fR or \fB\-Q\fR).
+Also, statistics about responses for each target are displayed when all
+requests have been sent (or when interrupted).  This option overrides \fB\-a\fR
+or \fB\-u\fR.
+.IP "\fB\-C\fR, \fB\-\-vcount\fR=\fIN\fR" 5
+.IX Item "-C, --vcount=N"
+Similar to \fB\-c\fR, but the per-target statistics are displayed in a format
+designed for automated response-time statistics gathering. For example:
+.Sp
+.Vb 2
+\& $ fping \-C 5 \-q somehost
+\& somehost : 91.7 37.0 29.2 \- 36.8
+.Ve
+.Sp
+shows the response time in milliseconds for each of the five requests, with the
+\&\f(CW\*(C`\-\*(C'\fR indicating that no response was received to the fourth request.  This
+option overrides \fB\-a\fR or \fB\-u\fR.
+.IP "\fB\-\-check\-source\fR" 5
+.IX Item "--check-source"
+Discard Echo replies that are sourced from a different address than the target
+address. This avoids spurious reachability results on busy monitoring systems
+where two \fBfping\fR instances with the same lower 16 bits of the process \s-1ID\s0 may
+be running at the same time.
+.IP "\fB\-d\fR, \fB\-\-rdns\fR" 5
+.IX Item "-d, --rdns"
+Use \s-1DNS\s0 to lookup address of ping target. This allows you to give fping
+a list of \s-1IP\s0 addresses as input and print hostnames in the output. This is similar
+to option \fB\-n\fR/\fB\-\-name\fR, but will force a reverse-DNS lookup even if you give
+hostnames as target (\s-1NAME\-\s0>\s-1IP\-\s0>\s-1NAME\s0).
+.IP "\fB\-D\fR, \fB\-\-timestamp\fR" 5
+.IX Item "-D, --timestamp"
+Add Unix timestamps in front of output lines generated with in looping or counting
+modes (\fB\-l\fR, \fB\-c\fR, or \fB\-C\fR).
+.Sp
+Subcommand: \fB\-\-timestamp\-format\fR=\fIctime|iso|rfc3339\fR
+.Sp
+Allow to change the timestamp format of the \fB\-D\fR option to the following format types.
+.Sp
+\&\fIctime\fR = \*(L"%c\*(R" (Example: Mon Jun 10 07:50:00 2024)
+.Sp
+\&\fIiso\fR = \*(L"%Y\-%m\-%dT%T%z\*(R" (Example: 2024\-06\-10T07:50:00+0200)
+.Sp
+\&\fIrfc3339\fR = \*(L"%Y\-%m\-%d \f(CW%H:\fR%M:%S\*(R" (Example: 2024\-06\-10 07:50:00)
+.IP "\fB\-e\fR, \fB\-\-elapsed\fR" 5
+.IX Item "-e, --elapsed"
+Show elapsed (round-trip) time of packets.
+.IP "\fB\-f\fR, \fB\-\-file\fR" 5
+.IX Item "-f, --file"
+Read list of targets from a file.
+.IP "\fB\-g\fR, \fB\-\-generate\fR \fIaddr/mask\fR" 5
+.IX Item "-g, --generate addr/mask"
+Generate a target list from a supplied \s-1IP\s0 netmask, or a starting and ending \s-1IP.\s0
+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:
+.Sp
+.Vb 1
+\& $ fping \-g 192.168.1.0/24
+.Ve
+.Sp
+or
+.Sp
+.Vb 1
+\& $ fping \-g 192.168.1.1 192.168.1.254
+.Ve
+.IP "\fB\-h\fR, \fB\-\-help\fR" 5
+.IX Item "-h, --help"
+Print usage message.
+.IP "\fB\-H\fR, \fB\-\-ttl\fR=\fIN\fR" 5
+.IX Item "-H, --ttl=N"
+Set the \s-1IP TTL\s0 field (time to live hops).
+.IP "\fB\-\-print\-ttl\fR" 5
+.IX Item "--print-ttl"
+Displays the IPv4 \s-1TTL\s0 value from the \s-1IP\s0 Header in the output.
+If \fBfping\fR cannot read the \s-1TTL\s0 value, \*(L"(\s-1TTL\s0 unknown)\*(R" is returned.
+IPv4 only, requires root privileges or cap_net_raw.
+.IP "\fB\-i\fR, \fB\-\-interval\fR=\fI\s-1MSEC\s0\fR" 5
+.IX Item "-i, --interval=MSEC"
+The minimum amount of time (in milliseconds) between sending a ping packet
+to any target (default is 10, minimum is 1).
+.IP "\fB\-I\fR, \fB\-\-iface\fR=\fI\s-1IFACE\s0\fR" 5
+.IX Item "-I, --iface=IFACE"
+Set the interface (requires \s-1SO_BINDTODEVICE\s0 support).
+.IP "\fB\-\-icmp\-timestamp\fR" 5
+.IX Item "--icmp-timestamp"
+Send \s-1ICMP\s0 timestamp requests (\s-1ICMP\s0 type 13) instead of \s-1ICMP\s0 Echo requests.
+Print \s-1ICMP\s0 timestamps for originate, receive, and transmit, together with
+the local receive time in the same format, in addition to normal output.
+Cannot be used together with \fB\-b\fR because \s-1ICMP\s0 timestamp messages have a fixed size.
+IPv4 only, requires root privileges or cap_net_raw.
+.IP "\fB\-k\fR, \fB\-\-fwmark\fR=\fI\s-1FWMARK\s0\fR" 5
+.IX Item "-k, --fwmark=FWMARK"
+Set \s-1FWMARK\s0 on ping packets for policy-based routing. Requires Linux kernel
+2.6.25<=, and root privileges or cap_net_admin.
+.IP "\fB\-l\fR, \fB\-\-loop\fR" 5
+.IX Item "-l, --loop"
+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, \fB\-\-all\fR" 5
+.IX Item "-m, --all"
+Send pings to each of a target host's multiple \s-1IP\s0 addresses (use of option '\-A'
+is recommended).
+.IP "\fB\-M\fR, \fB\-\-dontfrag\fR" 5
+.IX Item "-M, --dontfrag"
+Set the \*(L"Don't Fragment\*(R" bit in the \s-1IP\s0 header (used to determine/test the \s-1MTU\s0).
+.IP "\fB\-n\fR, \fB\-\-name\fR" 5
+.IX Item "-n, --name"
+If targets are specified as \s-1IP\s0 addresses, do a reverse-DNS lookup on them
+to print hostnames in the output.
+.IP "\fB\-N\fR, \fB\-\-netdata\fR" 5
+.IX Item "-N, --netdata"
+Format output for netdata (\-l \-Q are required). See: <https://netdata.cloud/>
+.IP "\fB\-o\fR, \fB\-\-outage\fR" 5
+.IX Item "-o, --outage"
+Calculate \*(L"outage time\*(R" based on the number of lost pings and the interval used (useful for network convergence tests).
+.IP "\fB\-O\fR, \fB\-\-tos\fR=\fIN\fR" 5
+.IX Item "-O, --tos=N"
+Set the typ of service flag (\s-1TOS\s0). \fIN\fR can be either decimal or hexadecimal
+(0xh) format.
+.IP "\fB\-\-print\-tos\fR" 5
+.IX Item "--print-tos"
+Displays the \s-1TOS\s0 value in the output. If \fBfping\fR cannot read the \s-1TOS\s0 value,
+\&\*(L"(\s-1TOS\s0 unknown)\*(R" is returned.
+IPv4 only, requires root privileges or cap_net_raw.
+.IP "\fB\-p\fR, \fB\-\-period\fR=\fI\s-1MSEC\s0\fR" 5
+.IX Item "-p, --period=MSEC"
+In looping or counting modes (\fB\-l\fR, \fB\-c\fR, or \fB\-C\fR), this parameter sets
+the time in milliseconds that \fBfping\fR waits between successive packets to
+an individual target. Default is 1000 and minimum is 10.
+.IP "\fB\-q\fR, \fB\-\-quiet\fR" 5
+.IX Item "-q, --quiet"
+Quiet. Don't show per-probe results, but only the final summary. Also don't
+show \s-1ICMP\s0 error messages.
+.IP "\fB\-Q\fR, \fB\-\-squiet\fR=\fISECS[,cumulative]\fR" 5
+.IX Item "-Q, --squiet=SECS[,cumulative]"
+Like \fB\-q\fR, but additionally show interval summary results every \fI\s-1SECS\s0\fR
+seconds. With \fIcumulative\fR, show summary results since start instead of
+for the last interval, unless option \fB\-N\fR is used, too.
+.IP "\fB\-r\fR, \fB\-\-retry\fR=\fIN\fR" 5
+.IX Item "-r, --retry=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.
+.IP "\fB\-R\fR, \fB\-\-random\fR" 5
+.IX Item "-R, --random"
+Instead of using all-zeros as the packet data, generate random bytes.
+Use to defeat, e.g., link data compression.
+.IP "\fB\-s\fR, \fB\-\-stats\fR" 5
+.IX Item "-s, --stats"
+Print cumulative statistics upon exit.
+.IP "\fB\-S\fR, \fB\-\-src\fR=\fIaddr\fR" 5
+.IX Item "-S, --src=addr"
+Set source address.
+.IP "\fB\-t\fR, \fB\-\-timeout\fR=\fI\s-1MSEC\s0\fR" 5
+.IX Item "-t, --timeout=MSEC"
+Initial target timeout in milliseconds. In the default, non-loop mode, the
+default timeout is 500ms, and it represents the amount of time that \fBfping\fR
+waits for a response to its first request. Successive timeouts are multiplied
+by the backoff factor specified with \fB\-B\fR.
+.Sp
+In loop/count mode, the default timeout is automatically adjusted to match
+the \*(L"period\*(R" value (but not more than 2000ms). You can still adjust the timeout
+value with this option, if you wish to, but note that setting a value larger
+than \*(L"period\*(R" produces inconsistent results, because the timeout value can
+be respected only for the last ping.
+.Sp
+Also note that any received replies that are larger than the timeout value, will
+be discarded.
+.IP "\fB\-T\fR \fIn\fR" 5
+.IX Item "-T n"
+Ignored (for compatibility with fping 2.4).
+.IP "\fB\-u\fR, \fB\-\-unreach\fR" 5
+.IX Item "-u, --unreach"
+Show targets that are unreachable.  (Options \fB\-c\fR and \fB\-C\fR override \fB\-u\fR.)
+.IP "\fB\-v\fR, \fB\-\-version\fR" 5
+.IX Item "-v, --version"
+Print \fBfping\fR version information.
+.IP "\fB\-x\fR, \fB\-\-reachable\fR=\fIN\fR" 5
+.IX Item "-x, --reachable=N"
+Given a list of hosts, this mode checks if number of reachable hosts is >= N
+and exits true in that case.
+.IP "\fB\-X\fR, \fB\-\-fast\-reachable\fR=\fIN\fR" 5
+.IX Item "-X, --fast-reachable=N"
+Given a list of hosts, this mode immediately exits true once N alive hosts
+have been found.
+.SH "EXAMPLES"
+.IX Header "EXAMPLES"
+Generate 20 pings to two hosts in ca. 1 second (i.e. one ping every 50 ms to
+each host), and report every ping \s-1RTT\s0 at the end:
+.PP
+.Vb 1
+\& $ fping \-\-quiet \-\-interval=1 \-\-vcount=20 \-\-period=50 127.0.0.1 127.0.0.2
+.Ve
+.SH "AUTHORS"
+.IX Header "AUTHORS"
+.IP "\(bu" 4
+Roland J. Schemers \s-1III,\s0 Stanford University, concept and versions 1.x
+.IP "\(bu" 4
+\&\s-1RL\s0 \*(L"Bob\*(R" Morgan, Stanford University, versions 2.x
+.IP "\(bu" 4
+David Papp, versions 2.3x and up
+.IP "\(bu" 4
+David Schweikert, versions 3.0 and up
+.PP
+\&\fBfping website: <http://www.fping.org>\fR
+.SH "DIAGNOSTICS"
+.IX Header "DIAGNOSTICS"
+Exit status is 0 if all the hosts (or the number of hosts specified with \fB\-x\fR
+or \fB\-X\fR) are reachable, 1 if some (or too many with \fB\-x\fR or \fB\-X\fR) hosts
+were unreachable, 2 if any \s-1IP\s0 addresses were not found, 3 for invalid command
+line arguments, and 4 for a system call failure.
+.SH "RESTRICTIONS"
+.IX Header "RESTRICTIONS"
+The number of addresses that can be generated using the \f(CW\*(C`\-g\*(C'\fR, \f(CW\*(C`\-\-generate\*(C'\fR
+option is limited to 131070 (the number of host addresses in one 15\-bit IPv4
+prefix).
+.PP
+If fping was configured with \f(CW\*(C`\-\-enable\-safe\-limits\*(C'\fR, the following values are
+not allowed for non-root users:
+.IP "\(bu" 4
+\&\fB\-i\fR \fIn\fR, where \fIn\fR < 1 msec
+.IP "\(bu" 4
+\&\fB\-p\fR \fIn\fR, where \fIn\fR < 10 msec
+.SH "SEE ALSO"
+.IX Header "SEE ALSO"
+\&\f(CWping(8)\fR
diff --git a/ci/tmp.4rIIEYCP9c/fping-5.3/doc/fping.pod b/ci/tmp.4rIIEYCP9c/fping-5.3/doc/fping.pod
new file mode 100644 (file)
index 0000000..7709225
--- /dev/null
@@ -0,0 +1,345 @@
+=head1 NAME
+
+fping - send ICMP ECHO_REQUEST packets to network hosts
+
+=head1 SYNOPSIS
+
+B<fping> [ 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.  Current statistics can be obtained without
+termination of process with signal SIGQUIT (^\ from the keyboard on most systems).
+
+=head1 OPTIONS
+
+=over 5
+
+=item B<-4>, B<--ipv4>
+
+Restrict name resolution and IPs to IPv4 addresses.
+
+=item B<-6>, B<--ipv6>
+
+Restrict name resolution and IPs to IPv6 addresses.
+
+=item B<-a>, B<--alive>
+
+Show systems that are alive.  (Options B<-c> and B<-C> override B<-a>.)
+
+=item B<-A>, B<--addr>
+
+Display targets by address rather than DNS name. Combined with -d, the output
+will be both the ip and (if available) the hostname.
+
+=item B<-b>, B<--size>=I<BYTES>
+
+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. Cannot be used together with B<--icmp-timestamp>.
+
+=item B<-B>, B<--backoff>=I<N>
+
+Backoff factor. 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 (B<-t>) 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>, B<--count>=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).  This option overrides B<-a>
+or B<-u>.
+
+=item B<-C>, B<--vcount>=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.  This
+option overrides B<-a> or B<-u>.
+
+=item B<--check-source>
+
+Discard Echo replies that are sourced from a different address than the target
+address. This avoids spurious reachability results on busy monitoring systems
+where two B<fping> instances with the same lower 16 bits of the process ID may
+be running at the same time.
+
+=item B<-d>, B<--rdns>
+
+Use DNS to lookup address of ping target. This allows you to give fping
+a list of IP addresses as input and print hostnames in the output. This is similar
+to option B<-n>/B<--name>, but will force a reverse-DNS lookup even if you give
+hostnames as target (NAME->IP->NAME).
+
+=item B<-D>, B<--timestamp>
+
+Add Unix timestamps in front of output lines generated with in looping or counting
+modes (B<-l>, B<-c>, or B<-C>).
+
+Subcommand: B<--timestamp-format>=I<ctime|iso|rfc3339>
+
+Allow to change the timestamp format of the B<-D> option to the following format types.
+
+I<ctime> = "%c" (Example: Mon Jun 10 07:50:00 2024)
+
+I<iso> = "%Y-%m-%dT%T%z" (Example: 2024-06-10T07:50:00+0200)
+
+I<rfc3339> = "%Y-%m-%d %H:%M:%S" (Example: 2024-06-10 07:50:00)
+
+=item B<-e>, B<--elapsed>
+
+Show elapsed (round-trip) time of packets.
+
+=item B<-f>, B<--file>
+
+Read list of targets from a file.
+
+=item B<-g>, B<--generate> 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>, B<--help>
+
+Print usage message.
+
+=item B<-H>, B<--ttl>=I<N>
+
+Set the IP TTL field (time to live hops).
+
+=item B<--print-ttl>
+
+Displays the IPv4 TTL value from the IP Header in the output.
+If B<fping> cannot read the TTL value, "(TTL unknown)" is returned.
+IPv4 only, requires root privileges or cap_net_raw.
+
+=item B<-i>, B<--interval>=I<MSEC>
+
+The minimum amount of time (in milliseconds) between sending a ping packet
+to any target (default is 10, minimum is 1).
+
+=item B<-I>, B<--iface>=I<IFACE>
+
+Set the interface (requires SO_BINDTODEVICE support).
+
+=item B<--icmp-timestamp>
+
+Send ICMP timestamp requests (ICMP type 13) instead of ICMP Echo requests.
+Print ICMP timestamps for originate, receive, and transmit, together with
+the local receive time in the same format, in addition to normal output.
+Cannot be used together with B<-b> because ICMP timestamp messages have a fixed size.
+IPv4 only, requires root privileges or cap_net_raw.
+
+=item B<-k>, B<--fwmark>=I<FWMARK>
+
+Set FWMARK on ping packets for policy-based routing. Requires Linux kernel
+2.6.25<=, and root privileges or cap_net_admin.
+
+=item B<-l>, B<--loop>
+
+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>, B<--all>
+
+Send pings to each of a target host's multiple IP addresses (use of option '-A'
+is recommended).
+
+=item B<-M>, B<--dontfrag>
+
+Set the "Don't Fragment" bit in the IP header (used to determine/test the MTU).
+
+=item B<-n>, B<--name>
+
+If targets are specified as IP addresses, do a reverse-DNS lookup on them
+to print hostnames in the output.
+
+=item B<-N>, B<--netdata>
+
+Format output for netdata (-l -Q are required). See: L<https://netdata.cloud/>
+
+=item B<-o>, B<--outage>
+
+Calculate "outage time" based on the number of lost pings and the interval used (useful for network convergence tests).
+
+=item B<-O>, B<--tos>=I<N>
+
+Set the typ of service flag (TOS). I<N> can be either decimal or hexadecimal
+(0xh) format.
+
+=item B<--print-tos>
+
+Displays the TOS value in the output. If B<fping> cannot read the TOS value,
+"(TOS unknown)" is returned.
+IPv4 only, requires root privileges or cap_net_raw.
+
+=item B<-p>, B<--period>=I<MSEC>
+
+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 and minimum is 10.
+
+=item B<-q>, B<--quiet>
+
+Quiet. Don't show per-probe results, but only the final summary. Also don't
+show ICMP error messages.
+
+=item B<-Q>, B<--squiet>=I<SECS[,cumulative]>
+
+Like B<-q>, but additionally show interval summary results every I<SECS>
+seconds. With I<cumulative>, show summary results since start instead of
+for the last interval, unless option B<-N> is used, too.
+
+=item B<-r>, B<--retry>=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<-R>, B<--random>
+
+Instead of using all-zeros as the packet data, generate random bytes.
+Use to defeat, e.g., link data compression.
+
+=item B<-s>, B<--stats>
+
+Print cumulative statistics upon exit.
+
+=item B<-S>, B<--src>=I<addr>
+
+Set source address.
+
+=item B<-t>, B<--timeout>=I<MSEC>
+
+Initial target timeout in milliseconds. In the default, non-loop mode, the
+default timeout is 500ms, and it represents the amount of time that B<fping>
+waits for a response to its first request. Successive timeouts are multiplied
+by the backoff factor specified with B<-B>.
+
+In loop/count mode, the default timeout is automatically adjusted to match
+the "period" value (but not more than 2000ms). You can still adjust the timeout
+value with this option, if you wish to, but note that setting a value larger
+than "period" produces inconsistent results, because the timeout value can
+be respected only for the last ping.
+
+Also note that any received replies that are larger than the timeout value, will
+be discarded.
+
+=item B<-T> I<n>
+
+Ignored (for compatibility with fping 2.4).
+
+=item B<-u>, B<--unreach>
+
+Show targets that are unreachable.  (Options B<-c> and B<-C> override B<-u>.)
+
+=item B<-v>, B<--version>
+
+Print B<fping> version information.
+
+=item B<-x>, B<--reachable>=I<N>
+
+Given a list of hosts, this mode checks if number of reachable hosts is >= N
+and exits true in that case.
+
+=item B<-X>, B<--fast-reachable>=I<N>
+
+Given a list of hosts, this mode immediately exits true once N alive hosts
+have been found.
+
+=back
+
+=head1 EXAMPLES
+
+Generate 20 pings to two hosts in ca. 1 second (i.e. one ping every 50 ms to
+each host), and report every ping RTT at the end:
+
+ $ fping --quiet --interval=1 --vcount=20 --period=50 127.0.0.1 127.0.0.2
+
+=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 (or the number of hosts specified with B<-x>
+or B<-X>) are reachable, 1 if some (or too many with B<-x> or B<-X>) 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
+
+The number of addresses that can be generated using the C<-g>, C<--generate>
+option is limited to 131070 (the number of host addresses in one 15-bit IPv4
+prefix).
+
+If fping was configured with C<--enable-safe-limits>, the following values are
+not allowed for non-root users:
+
+=over 4
+
+=item *
+
+B<-i> I<n>, where I<n> < 1 msec
+
+=item *
+
+B<-p> I<n>, where I<n> < 10 msec
+
+=back
+
+=head1 SEE ALSO
+
+C<ping(8)>
diff --git a/ci/tmp.4rIIEYCP9c/fping-5.3/src/Makefile.am b/ci/tmp.4rIIEYCP9c/fping-5.3/src/Makefile.am
new file mode 100644 (file)
index 0000000..c58e474
--- /dev/null
@@ -0,0 +1,11 @@
+AM_CFLAGS = -Wall -Wextra -Wno-sign-compare
+
+sbin_PROGRAMS = fping
+
+fping_SOURCES = fping.c seqmap.c socket4.c fping.h options.h seqmap.h optparse.c optparse.h
+fping_DEPENDENCIES = ../config.h
+
+if IPV6
+fping_SOURCES += socket6.c
+fping_CFLAGS = $(AM_CFLAGS) -DIPV6
+endif
diff --git a/ci/tmp.4rIIEYCP9c/fping-5.3/src/fping b/ci/tmp.4rIIEYCP9c/fping-5.3/src/fping
new file mode 100755 (executable)
index 0000000..b2aeb58
Binary files /dev/null and b/ci/tmp.4rIIEYCP9c/fping-5.3/src/fping differ
diff --git a/ci/tmp.4rIIEYCP9c/fping-5.3/src/fping-fping.o b/ci/tmp.4rIIEYCP9c/fping-5.3/src/fping-fping.o
new file mode 100644 (file)
index 0000000..682a6a5
Binary files /dev/null and b/ci/tmp.4rIIEYCP9c/fping-5.3/src/fping-fping.o differ
diff --git a/ci/tmp.4rIIEYCP9c/fping-5.3/src/fping-optparse.o b/ci/tmp.4rIIEYCP9c/fping-5.3/src/fping-optparse.o
new file mode 100644 (file)
index 0000000..2d9e14a
Binary files /dev/null and b/ci/tmp.4rIIEYCP9c/fping-5.3/src/fping-optparse.o differ
diff --git a/ci/tmp.4rIIEYCP9c/fping-5.3/src/fping-seqmap.o b/ci/tmp.4rIIEYCP9c/fping-5.3/src/fping-seqmap.o
new file mode 100644 (file)
index 0000000..a586164
Binary files /dev/null and b/ci/tmp.4rIIEYCP9c/fping-5.3/src/fping-seqmap.o differ
diff --git a/ci/tmp.4rIIEYCP9c/fping-5.3/src/fping-socket4.o b/ci/tmp.4rIIEYCP9c/fping-5.3/src/fping-socket4.o
new file mode 100644 (file)
index 0000000..57976aa
Binary files /dev/null and b/ci/tmp.4rIIEYCP9c/fping-5.3/src/fping-socket4.o differ
diff --git a/ci/tmp.4rIIEYCP9c/fping-5.3/src/fping-socket6.o b/ci/tmp.4rIIEYCP9c/fping-5.3/src/fping-socket6.o
new file mode 100644 (file)
index 0000000..52db65d
Binary files /dev/null and b/ci/tmp.4rIIEYCP9c/fping-5.3/src/fping-socket6.o differ
diff --git a/ci/tmp.4rIIEYCP9c/fping-5.3/src/fping.c b/ci/tmp.4rIIEYCP9c/fping-5.3/src/fping.c
new file mode 100644 (file)
index 0000000..6779175
--- /dev/null
@@ -0,0 +1,3201 @@
+/*
+ * 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.
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+#include "fping.h"
+#include "config.h"
+#include "options.h"
+#include "optparse.h"
+
+#include <errno.h>
+#include <inttypes.h>
+#include <signal.h>
+#include <stdarg.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <time.h>
+
+#include "seqmap.h"
+
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif /* HAVE_UNISTD_H */
+
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif /* HAVE_STDLIB_H */
+
+#include <stddef.h>
+#include <string.h>
+
+#include <sys/socket.h>
+#include <sys/time.h>
+#include <sys/types.h>
+
+#if HAVE_SYS_FILE_H
+#include <sys/file.h>
+#endif /* HAVE_SYS_FILE_H */
+
+#ifdef IPV6
+#include <netinet/icmp6.h>
+#endif
+#include <netinet/in_systm.h>
+
+#include <netinet/ip.h>
+#include <netinet/ip_icmp.h>
+
+#include <arpa/inet.h>
+#include <ctype.h>
+#include <netdb.h>
+
+#include <sys/select.h>
+
+/*** compatibility ***/
+
+/* Mac OS X's getaddrinfo() does not fail if we use an invalid combination,
+ * e.g. AF_INET6 with "127.0.0.1". If we pass AI_UNUSABLE to flags, it behaves
+ * like other platforms. But AI_UNUSABLE isn't available on other platforms,
+ * and we can safely use 0 for flags instead.
+ */
+#ifndef AI_UNUSABLE
+#define AI_UNUSABLE 0
+#endif
+
+/* MSG_TRUNC available on Linux kernel 2.2+, makes recvmsg return the full
+ * length of the raw packet received, even if the buffer is smaller */
+#ifndef MSG_TRUNC
+#define MSG_TRUNC 0
+#define RECV_BUFSIZE 4096
+#else
+#define RECV_BUFSIZE 128
+#endif
+
+/*** externals ***/
+
+extern char *optarg;
+extern int optind, opterr;
+#ifndef h_errno
+extern int h_errno;
+#endif
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+/*** Constants ***/
+
+/* CLOCK_MONTONIC starts under macOS, OpenBSD and FreeBSD with undefined positive point and can not be use
+ * see github PR #217
+ * The configure script detect the predefined operating systems an set CLOCK_REALTIME using over ONLY_CLOCK_REALTIME variable
+ */
+#if HAVE_SO_TIMESTAMPNS || ONLY_CLOCK_REALTIME
+#define CLOCKID CLOCK_REALTIME
+#endif
+
+#if !defined(CLOCKID)
+#if defined(CLOCK_MONOTONIC)
+#define CLOCKID CLOCK_MONOTONIC
+#else
+#define CLOCKID CLOCK_REALTIME
+#endif
+#endif
+
+/*** Ping packet defines ***/
+
+#define MAX_IP_PACKET 65535 /* (theoretical) max IPv4 packet size */
+#define SIZE_IP_HDR 20 /* min IPv4 header size */
+#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 131070 /* maximum number of hosts that -g can generate */
+
+/* sized so as to be like traditional ping */
+#define DEFAULT_PING_DATA_SIZE 56
+
+/* ICMP Timestamp has a fixed payload size of 12 bytes */
+#define ICMP_TIMESTAMP_DATA_SIZE 12
+
+#ifdef FPING_SAFE_LIMITS
+#define MIN_INTERVAL_MS 1 /* in millisec */
+#define MIN_PERHOST_INTERVAL_MS 10 /* in millisec */
+#else
+#define MIN_INTERVAL_MS 0
+/* Set a very low limit for the per-host interval, even if safe limits are
+ * disabled, so that the memory allocation of the event storage is not
+ * unreasonably high. 0.001 ms would mean in theory at least 592 mbps of data
+ * sent to a single host, which probably doesn't make sense in any scenario. */
+#define MIN_PERHOST_INTERVAL_MS 0.001
+#endif
+
+/* response time array flags */
+#define RESP_WAITING -1
+#define RESP_UNUSED -2
+#define RESP_ERROR -3
+#define RESP_TIMEOUT -4
+
+/* debugging flags */
+#if defined(DEBUG) || defined(_DEBUG)
+#define DBG_TRACE 1
+#define DBG_SENT_TIMES 2
+#define DBG_RANDOM_LOSE_FEW 4
+#define DBG_RANDOM_LOSE_MANY 8
+#define DBG_PRINT_PER_SYSTEM 16
+#define DBG_REPORT_ALL_RTTS 32
+#endif /* DEBUG || _DEBUG */
+
+/* Long names for ICMP packet types */
+#define ICMP_TYPE_STR_MAX 18
+char *icmp_type_str[19] = {
+    "ICMP Echo Reply", /* 0 */
+    "",
+    "",
+    "ICMP Unreachable", /* 3 */
+    "ICMP Source Quench", /* 4 */
+    "ICMP Redirect", /* 5 */
+    "",
+    "",
+    "ICMP Echo", /* 8 */
+    "",
+    "",
+    "ICMP Time Exceeded", /* 11 */
+    "ICMP Parameter Problem", /* 12 */
+    "ICMP Timestamp Request", /* 13 */
+    "ICMP Timestamp Reply", /* 14 */
+    "ICMP Information Request", /* 15 */
+    "ICMP Information Reply", /* 16 */
+    "ICMP Mask Request", /* 17 */
+    "ICMP Mask Reply" /* 18 */
+};
+
+char *icmp_unreach_str[16] = {
+    "ICMP Network Unreachable", /* 0 */
+    "ICMP Host Unreachable", /* 1 */
+    "ICMP Protocol Unreachable", /* 2 */
+    "ICMP Port Unreachable", /* 3 */
+    "ICMP Unreachable (Fragmentation Needed)", /* 4 */
+    "ICMP Unreachable (Source Route Failed)", /* 5 */
+    "ICMP Unreachable (Destination Network Unknown)", /* 6 */
+    "ICMP Unreachable (Destination Host Unknown)", /* 7 */
+    "ICMP Unreachable (Source Host Isolated)", /* 8 */
+    "ICMP Unreachable (Communication with Network Prohibited)", /* 9 */
+    "ICMP Unreachable (Communication with Host Prohibited)", /* 10 */
+    "ICMP Unreachable (Network Unreachable For Type Of Service)", /* 11 */
+    "ICMP Unreachable (Host Unreachable For Type Of Service)", /* 12 */
+    "ICMP Unreachable (Communication Administratively Prohibited)", /* 13 */
+    "ICMP Unreachable (Host Precedence Violation)", /* 14 */
+    "ICMP Unreachable (Precedence cutoff in effect)" /* 15 */
+};
+
+#define ICMP_UNREACH_MAXTYPE 15
+
+struct event;
+typedef struct host_entry {
+    int i; /* index into array */
+    char *name; /* name as given by user */
+    char *host; /* text description of host */
+    struct sockaddr_storage saddr; /* internet address */
+    socklen_t saddr_len;
+    int64_t timeout; /* time to wait for response */
+    int64_t last_send_time; /* time of last packet sent */
+    int num_sent; /* number of ping packets sent (for statistics) */
+    int num_recv; /* number of pings received (duplicates ignored) */
+    int num_recv_total; /* number of pings received, including duplicates */
+    int64_t max_reply; /* longest response time */
+    int64_t min_reply; /* shortest response time */
+    int64_t 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 */
+    int64_t max_reply_i; /* longest response time */
+    int64_t min_reply_i; /* shortest response time */
+    int64_t total_time_i; /* sum of response times */
+    int64_t *resp_times; /* individual response times */
+
+    /* to avoid allocating two struct events each time that we send a ping, we
+     * preallocate here two struct events for each ping that we might send for
+     * this host. */
+    struct event *event_storage_ping;
+    struct event *event_storage_timeout;
+} HOST_ENTRY;
+
+int event_storage_count; /* how many events can be stored in host_entry->event_storage_xxx */
+
+/* basic algorithm to ensure that we have correct data at all times:
+ *
+ * 1. when a ping is sent:
+ *    - two events get added into event_queue:
+ *      - t+PERIOD: ping event
+ *      - t+TIMEOUT: timeout event
+ *
+ * 2. when a ping is received:
+ *    - record statistics (increase num_sent and num_received)
+ *    - remove timeout event (we store the event in seqmap, so that we can retrieve it when the response is received)
+ *
+ * 3. when a timeout happens:
+ *    - record statistics (increase num_sent only)
+ */
+
+#define EV_TYPE_PING 1
+#define EV_TYPE_TIMEOUT 2
+
+struct event {
+    struct event *ev_prev;
+    struct event *ev_next;
+    int64_t ev_time;
+    struct host_entry *host;
+    int ping_index;
+};
+
+struct event_queue {
+    struct event *first;
+    struct event *last;
+};
+
+/*** globals ***/
+
+HOST_ENTRY **table = NULL; /* array of pointers to items in the list */
+
+/* we keep two separate queues: a ping queue, for when the next ping should be
+ * sent, and a timeout queue. the reason for having two separate queues is that
+ * the ping period and the timeout value are different, so if we put them in
+ * the same event queue, we would need to scan many more entries when inserting
+ * into the sorted list.
+ */
+struct event_queue event_queue_ping;
+struct event_queue event_queue_timeout;
+
+char *prog;
+int ident4 = 0; /* our icmp identity field */
+int ident6 = 0;
+int socket4 = -1;
+int socktype4 = -1;
+int using_sock_dgram4 = 0;
+#ifndef IPV6
+int hints_ai_family = AF_INET;
+#else
+int socket6 = -1;
+int socktype6 = -1;
+int hints_ai_family = AF_UNSPEC;
+#endif
+
+volatile sig_atomic_t status_snapshot = 0;
+volatile sig_atomic_t finish_requested = 0;
+
+unsigned int debugging = 0;
+
+/* all time-related values are int64_t nanoseconds */
+unsigned int retry = DEFAULT_RETRY;
+int64_t timeout = (int64_t)DEFAULT_TIMEOUT * 1000000;
+int64_t interval = (int64_t)DEFAULT_INTERVAL * 1000000;
+int64_t perhost_interval = (int64_t)DEFAULT_PERHOST_INTERVAL * 1000000;
+float backoff = DEFAULT_BACKOFF_FACTOR;
+unsigned int ping_data_size = DEFAULT_PING_DATA_SIZE;
+unsigned int count = 1, min_reachable = 0;
+unsigned int trials;
+int64_t report_interval = 0;
+unsigned int ttl = 0;
+int src_addr_set = 0;
+struct in_addr src_addr;
+#ifdef IPV6
+int src_addr6_set = 0;
+struct in6_addr src_addr6;
+#endif
+
+/* global stats */
+int64_t max_reply = 0;
+int64_t min_reply = 0;
+int64_t total_replies = 0;
+int64_t sum_replies = 0;
+int max_hostname_len = 0;
+int num_hosts = 0; /* total number of hosts */
+int num_alive = 0, /* total number alive */
+    num_unreachable = 0, /* total number unreachable */
+    num_noaddress = 0; /* total number of addresses not found */
+int num_timeout = 0, /* number of times select timed out */
+    num_pingsent = 0, /* total pings sent */
+    num_pingreceived = 0, /* total pings received */
+    num_othericmprcvd = 0; /* total non-echo-reply ICMP received */
+
+struct timespec current_time; /* current time (pseudo) */
+int64_t current_time_ns;
+int64_t start_time;
+int64_t end_time;
+int64_t last_send_time; /* time last ping was sent */
+int64_t next_report_time; /* time next -Q report is expected */
+
+/* switches */
+int generate_flag = 0; /* flag for IP list generation */
+int verbose_flag, quiet_flag, stats_flag, unreachable_flag, alive_flag;
+int elapsed_flag, version_flag, count_flag, loop_flag, netdata_flag;
+int per_recv_flag, report_all_rtts_flag, name_flag, addr_flag, backoff_flag, rdns_flag;
+int multif_flag, timeout_flag, fast_reachable;
+int outage_flag = 0;
+int timestamp_flag = 0;
+int timestamp_format_flag = 0;
+int random_data_flag = 0;
+int cumulative_stats_flag = 0;
+int check_source_flag = 0;
+int icmp_request_typ = 0;
+int print_tos_flag = 0;
+int print_ttl_flag = 0;
+int size_flag = 0;
+#if defined(DEBUG) || defined(_DEBUG)
+int randomly_lose_flag, trace_flag, print_per_system_flag;
+int lose_factor;
+#endif /* DEBUG || _DEBUG */
+
+unsigned int fwmark = 0;
+
+char *filename = NULL; /* file containing hosts to ping */
+
+/*** forward declarations ***/
+
+void add_name(char *name);
+void add_addr(char *name, char *host, struct sockaddr *ipaddr, socklen_t ipaddr_len);
+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 send_ping(HOST_ENTRY *h, int index);
+void usage(int);
+int wait_for_reply(int64_t);
+void print_per_system_stats(void);
+void print_per_system_splits(void);
+void stats_reset_interval(HOST_ENTRY *h);
+void print_netdata(void);
+void print_global_stats(void);
+void main_loop();
+void signal_handler(int);
+void finish();
+const char *sprint_tm(int64_t t);
+void ev_enqueue(struct event_queue *queue, struct event *event);
+struct event *ev_dequeue(struct event_queue *queue);
+void ev_remove(struct event_queue *queue, struct event *event);
+void add_cidr(char *);
+void add_range(char *, char *);
+void add_addr_range_ipv4(unsigned long, unsigned long);
+void print_warning(char *fmt, ...);
+int addr_cmp(struct sockaddr *a, struct sockaddr *b);
+void host_add_ping_event(HOST_ENTRY *h, int index, int64_t ev_time);
+void host_add_timeout_event(HOST_ENTRY *h, int index, int64_t ev_time);
+struct event *host_get_timeout_event(HOST_ENTRY *h, int index);
+void stats_add(HOST_ENTRY *h, int index, int success, int64_t latency);
+void update_current_time();
+void print_timestamp_format(int64_t current_time_ns, int timestamp_format);
+static uint32_t ms_since_midnight_utc(int64_t time_val);
+
+/************************************************************
+
+  Function: p_setsockopt
+
+*************************************************************
+
+  Inputs:  p_uid: privileged uid. Others as per setsockopt(2)
+
+  Description:
+
+  Elevates privileges to p_uid when required, calls
+  setsockopt, and drops privileges back.
+
+************************************************************/
+
+int p_setsockopt(uid_t p_uid, int sockfd, int level, int optname,
+    const void *optval, socklen_t optlen)
+{
+    const uid_t saved_uid = geteuid();
+    int res;
+
+    if (p_uid != saved_uid && seteuid(p_uid)) {
+        perror("cannot elevate privileges for setsockopt");
+    }
+
+    res = setsockopt(sockfd, level, optname, optval, optlen);
+
+    if (p_uid != saved_uid && seteuid(saved_uid)) {
+        perror("fatal error: could not drop privileges after setsockopt");
+        /* continuing would be a security hole */
+        exit(4);
+    }
+
+    return res;
+}
+
+/************************************************************
+
+  Function: main
+
+*************************************************************
+
+  Inputs:  int argc, char** argv
+
+  Description:
+
+  Main program entry point
+
+************************************************************/
+
+int main(int argc, char **argv)
+{
+/* Debug: CPU Performance */
+#if defined(DEBUG) || defined(_DEBUG)
+    clock_t perf_cpu_start, perf_cpu_end;
+    double perf_cpu_time_used;
+    perf_cpu_start = clock();
+#endif /* DEBUG || _DEBUG */
+
+    int c;
+    const uid_t suid = geteuid();
+    int tos = 0;
+    struct optparse optparse_state;
+#ifdef USE_SIGACTION
+    struct sigaction act;
+#endif
+
+    /* pre-parse -h/--help, so that we also can output help information
+     * without trying to open the socket, which might fail */
+    prog = argv[0];
+    if (argc == 2 && (strcmp(argv[1], "-h") == 0 || strcmp(argv[1], "--help") == 0)) {
+        usage(0);
+    }
+
+    socket4 = open_ping_socket_ipv4(&socktype4);
+#ifdef __linux__
+    /* We only treat SOCK_DGRAM differently on Linux, where the IPv4 header
+     * structure is missing in the message.
+     */
+    using_sock_dgram4 = (socktype4 == SOCK_DGRAM);
+#endif
+
+#ifdef IPV6
+    socket6 = open_ping_socket_ipv6(&socktype6);
+    /* if called (sym-linked) via 'fping6', imply '-6'
+     * for backward compatibility */
+    if (strstr(prog, "fping6")) {
+        hints_ai_family = AF_INET6;
+    }
+#endif
+
+    memset(&src_addr, 0, sizeof(src_addr));
+#ifdef IPV6
+    memset(&src_addr6, 0, sizeof(src_addr6));
+#endif
+
+    if (!suid && suid != getuid()) {
+        /* *temporarily* drop privileges */
+        if (seteuid(getuid()) == -1)
+            perror("cannot setuid");
+    }
+
+    optparse_init(&optparse_state, argv);
+    ident4 = ident6 = htons(getpid() & 0xFFFF);
+    verbose_flag = 1;
+    backoff_flag = 1;
+    opterr = 1;
+
+    /* get command line options */
+
+    struct optparse_long longopts[] = {
+        { "ipv4", '4', OPTPARSE_NONE },
+        { "ipv6", '6', OPTPARSE_NONE },
+        { "alive", 'a', OPTPARSE_NONE },
+        { "addr", 'A', OPTPARSE_NONE },
+        { "size", 'b', OPTPARSE_REQUIRED },
+        { "backoff", 'B', OPTPARSE_REQUIRED },
+        { "count", 'c', OPTPARSE_REQUIRED },
+        { "vcount", 'C', OPTPARSE_REQUIRED },
+        { "rdns", 'd', OPTPARSE_NONE },
+        { "timestamp", 'D', OPTPARSE_NONE },
+        { "timestamp-format", '0', OPTPARSE_REQUIRED },
+        { "elapsed", 'e', OPTPARSE_NONE },
+        { "file", 'f', OPTPARSE_REQUIRED },
+        { "generate", 'g', OPTPARSE_NONE },
+        { "help", 'h', OPTPARSE_NONE },
+        { "ttl", 'H', OPTPARSE_REQUIRED },
+        { "interval", 'i', OPTPARSE_REQUIRED },
+        { "iface", 'I', OPTPARSE_REQUIRED },
+        { "icmp-timestamp", '0', OPTPARSE_NONE },
+#ifdef SO_MARK
+        { "fwmark", 'k', OPTPARSE_REQUIRED },
+#endif
+        { "loop", 'l', OPTPARSE_NONE },
+        { "all", 'm', OPTPARSE_NONE },
+        { "dontfrag", 'M', OPTPARSE_NONE },
+        { "name", 'n', OPTPARSE_NONE },
+        { "netdata", 'N', OPTPARSE_NONE },
+        { "outage", 'o', OPTPARSE_NONE },
+        { "tos", 'O', OPTPARSE_REQUIRED },
+        { "period", 'p', OPTPARSE_REQUIRED },
+        { "quiet", 'q', OPTPARSE_NONE },
+        { "squiet", 'Q', OPTPARSE_REQUIRED },
+        { "retry", 'r', OPTPARSE_REQUIRED },
+        { "random", 'R', OPTPARSE_NONE },
+        { "stats", 's', OPTPARSE_NONE },
+        { "src", 'S', OPTPARSE_REQUIRED },
+        { "timeout", 't', OPTPARSE_REQUIRED },
+        { NULL, 'T', OPTPARSE_REQUIRED },
+        { "unreach", 'u', OPTPARSE_NONE },
+        { "version", 'v', OPTPARSE_NONE },
+        { "reachable", 'x', OPTPARSE_REQUIRED },
+        { "fast-reachable", 'X', OPTPARSE_REQUIRED },
+        { "check-source", '0', OPTPARSE_NONE },
+        { "print-tos", '0', OPTPARSE_NONE },
+        { "print-ttl", '0', OPTPARSE_NONE },
+#if defined(DEBUG) || defined(_DEBUG)
+        { NULL, 'z', OPTPARSE_REQUIRED },
+#endif
+        { 0, 0, 0 }
+    };
+
+    float opt_value_float;
+    while ((c = optparse_long(&optparse_state, longopts, NULL)) != EOF) {
+        switch (c) {
+        case '0':
+            if(strstr(optparse_state.optlongname, "timestamp-format") != NULL) {
+                if(strcmp(optparse_state.optarg, "ctime") == 0) {
+                  timestamp_format_flag = 1;
+                }else if(strcmp(optparse_state.optarg, "iso") == 0) {
+                  timestamp_format_flag = 2;
+                }else if(strcmp(optparse_state.optarg, "rfc3339") == 0) {
+                  timestamp_format_flag = 3;
+                }else{
+                  usage(1);
+                }
+            } else if (strstr(optparse_state.optlongname, "check-source") != NULL) {
+                check_source_flag = 1;
+            } else if (strstr(optparse_state.optlongname, "icmp-timestamp") != NULL) {
+#ifdef IPV6
+                if (hints_ai_family != AF_UNSPEC && hints_ai_family != AF_INET) {
+                    fprintf(stderr, "%s: ICMP Timestamp is IPv4 only\n", prog);
+                    exit(1);
+                }
+                hints_ai_family = AF_INET;
+#endif
+                icmp_request_typ = 13;
+                ping_data_size = ICMP_TIMESTAMP_DATA_SIZE;
+            } else if (strstr(optparse_state.optlongname, "print-tos") != NULL) {
+                print_tos_flag = 1;
+            } else if (strstr(optparse_state.optlongname, "print-ttl") != NULL) {
+                print_ttl_flag = 1;
+            } else {
+                usage(1);
+            }
+            break;
+        case '4':
+#ifdef IPV6
+            if (hints_ai_family != AF_UNSPEC && hints_ai_family != AF_INET) {
+                fprintf(stderr, "%s: can't specify both -4 and -6\n", prog);
+                exit(1);
+            }
+            hints_ai_family = AF_INET;
+#endif
+            break;
+        case '6':
+#ifdef IPV6
+            if (hints_ai_family != AF_UNSPEC && hints_ai_family != AF_INET6) {
+                fprintf(stderr, "%s: can't specify both -4 and -6\n", prog);
+                exit(1);
+            }
+            hints_ai_family = AF_INET6;
+#else
+            fprintf(stderr, "%s: IPv6 not supported by this binary\n", prog);
+            exit(1);
+#endif
+            break;
+        case 'M':
+#ifdef IP_MTU_DISCOVER
+            if (socket4 >= 0) {
+                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 >= 0) {
+                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, "%s, -M option not supported on this platform\n", prog);
+            exit(1);
+#endif
+            break;
+
+        case 't':
+            if (sscanf(optparse_state.optarg, "%f", &opt_value_float) != 1)
+                usage(1);
+            if (opt_value_float < 0) {
+                usage(1);
+            }
+            timeout = opt_value_float * 1000000;
+            timeout_flag = 1;
+            break;
+
+        case 'r':
+            if (sscanf(optparse_state.optarg, "%u", &retry) != 1)
+                usage(1);
+            break;
+
+        case 'i':
+            if (sscanf(optparse_state.optarg, "%f", &opt_value_float) != 1)
+                usage(1);
+            if (opt_value_float < 0) {
+                usage(1);
+            }
+            interval = opt_value_float * 1000000;
+            break;
+
+        case 'p':
+            if (sscanf(optparse_state.optarg, "%f", &opt_value_float) != 1)
+                usage(1);
+            if (opt_value_float < 0) {
+                usage(1);
+            }
+            perhost_interval = opt_value_float * 1000000;
+
+            break;
+
+        case 'c':
+            if (!(count = (unsigned int)atoi(optparse_state.optarg)))
+                usage(1);
+
+            count_flag = 1;
+            break;
+
+        case 'C':
+            if (!(count = (unsigned int)atoi(optparse_state.optarg)))
+                usage(1);
+
+            count_flag = 1;
+            report_all_rtts_flag = 1;
+            break;
+
+        case 'b':
+            if (sscanf(optparse_state.optarg, "%u", &ping_data_size) != 1)
+                usage(1);
+            size_flag = 1;
+            break;
+
+        case 'h':
+            usage(0);
+            break;
+
+        case 'q':
+            verbose_flag = 0;
+            quiet_flag = 1;
+            break;
+
+        case 'Q':
+            verbose_flag = 0;
+            quiet_flag = 1;
+            if (sscanf(optparse_state.optarg, "%f", &opt_value_float) != 1)
+                usage(1);
+            if (opt_value_float < 0) {
+                usage(1);
+            }
+            report_interval = opt_value_float * 1e9;
+
+            /* recognize keyword(s) after number, ignore everything else */
+            {
+                char *comma = strchr(optparse_state.optarg, ',');
+                if ((comma != NULL) && (strcmp(++comma, "cumulative") == 0)) {
+                    cumulative_stats_flag = 1;
+                }
+            }
+
+            break;
+
+        case 'e':
+            elapsed_flag = 1;
+            break;
+
+        case 'm':
+            multif_flag = 1;
+            break;
+
+        case 'N':
+            netdata_flag = 1;
+            break;
+
+        case 'n':
+            name_flag = 1;
+            if (rdns_flag) {
+                fprintf(stderr, "%s: use either one of -d or -n\n", prog);
+                exit(1);
+            }
+            break;
+
+        case 'd':
+            rdns_flag = 1;
+            if (name_flag) {
+                fprintf(stderr, "%s: use either one of -d or -n\n", prog);
+                exit(1);
+            }
+            break;
+
+        case 'A':
+            addr_flag = 1;
+            break;
+
+        case 'B':
+            if (!(backoff = atof(optparse_state.optarg)))
+                usage(1);
+
+            break;
+
+        case 's':
+            stats_flag = 1;
+            break;
+
+        case 'D':
+            timestamp_flag = 1;
+            break;
+
+        case 'R':
+            random_data_flag = 1;
+            break;
+
+        case 'l':
+            loop_flag = 1;
+            backoff_flag = 0;
+            break;
+
+        case 'u':
+            unreachable_flag = 1;
+            break;
+
+        case 'a':
+            alive_flag = 1;
+            break;
+
+        case 'H':
+            if (!(ttl = (unsigned int)atoi(optparse_state.optarg)))
+                usage(1);
+            break;
+
+#if defined(DEBUG) || defined(_DEBUG)
+        case 'z':
+            if (sscanf(optparse_state.optarg, "0x%x", &debugging) != 1)
+                if (sscanf(optparse_state.optarg, "%u", &debugging) != 1)
+                    usage(1);
+
+            break;
+#endif /* DEBUG || _DEBUG */
+
+        case 'v':
+            printf("%s: Version %s\n", prog, VERSION);
+            exit(0);
+
+        case 'x':
+            if (!(min_reachable = (unsigned int)atoi(optparse_state.optarg)))
+                usage(1);
+            break;
+
+        case 'X':
+            if (!(min_reachable = (unsigned int)atoi(optparse_state.optarg)))
+                usage(1);
+            fast_reachable = 1;
+            break;
+
+        case 'f':
+            filename = optparse_state.optarg;
+            break;
+#ifdef SO_MARK
+        case 'k':
+            if (!(fwmark = (unsigned int)atol(optparse_state.optarg)))
+                usage(1);
+
+            if (socket4 >= 0)
+                if(-1 == p_setsockopt(suid, socket4, SOL_SOCKET, SO_MARK, &fwmark, sizeof fwmark))
+                    perror("fwmark ipv4");
+
+#ifdef IPV6
+            if (socket6 >= 0)
+                if(-1 == p_setsockopt(suid, socket6, SOL_SOCKET, SO_MARK, &fwmark, sizeof fwmark))
+                    perror("fwmark ipv6");
+#endif
+
+            break;
+#endif
+
+        case 'g':
+            /* use IP list generation */
+            /* mutually exclusive with using file input or command line targets */
+            generate_flag = 1;
+            break;
+
+        case 'S':
+            if (inet_pton(AF_INET, optparse_state.optarg, &src_addr)) {
+                src_addr_set = 1;
+                break;
+            }
+#ifdef IPV6
+            if (inet_pton(AF_INET6, optparse_state.optarg, &src_addr6)) {
+                src_addr6_set = 1;
+                break;
+            }
+#endif
+            fprintf(stderr, "%s: can't parse source address: %s\n", prog, optparse_state.optarg);
+            exit(1);
+
+        case 'I':
+#ifdef SO_BINDTODEVICE
+            if (socket4 >= 0) {
+                if (p_setsockopt(suid, socket4, SOL_SOCKET, SO_BINDTODEVICE, optparse_state.optarg, strlen(optparse_state.optarg))) {
+                    perror("binding to specific interface (SO_BINTODEVICE)");
+                    exit(1);
+                }
+            }
+#ifdef IPV6
+            if (socket6 >= 0) {
+                if (p_setsockopt(suid, socket6, SOL_SOCKET, SO_BINDTODEVICE, optparse_state.optarg, strlen(optparse_state.optarg))) {
+                    perror("binding to specific interface (SO_BINTODEVICE), IPV6");
+                    exit(1);
+                }
+            }
+#endif
+#else
+            printf("%s: cant bind to a particular net interface since SO_BINDTODEVICE is not supported on your os.\n", prog);
+            exit(3);
+            ;
+#endif
+            break;
+
+        case 'T':
+            /* This option is ignored for compatibility reasons ("select timeout" is not meaningful anymore) */
+            break;
+
+        case 'O':
+            if (sscanf(optparse_state.optarg, "%i", &tos) == 1) {
+                if (socket4 >= 0) {
+                    if (setsockopt(socket4, IPPROTO_IP, IP_TOS, &tos, sizeof(tos))) {
+                        perror("setting type of service octet IP_TOS");
+                    }
+                }
+#if defined(IPV6) && defined(IPV6_TCLASS)
+                if (socket6 >= 0) {
+                    if (setsockopt(socket6, IPPROTO_IPV6, IPV6_TCLASS, &tos, sizeof(tos))) {
+                        perror("setting type of service octet IPV6_TCLASS");
+                    }
+                }
+#endif
+            }
+            else {
+                usage(1);
+            }
+            break;
+
+        case 'o':
+            outage_flag = 1;
+            break;
+
+        case '?':
+            fprintf(stderr, "%s: %s\n", argv[0], optparse_state.errmsg);
+            fprintf(stderr, "see 'fping -h' for usage information\n");
+            exit(1);
+            break;
+        }
+    }
+
+    /* permanently drop privileges */
+    if (suid != getuid() && setuid(getuid())) {
+        perror("fatal: failed to permanently drop privileges");
+        /* continuing would be a security hole */
+        exit(4);
+    }
+
+    /* validate various option settings */
+
+#ifndef IPV6
+    if (socket4 < 0) {
+        crash_and_burn("can't create socket (must run as root?)");
+    }
+#else
+    if ((socket4 < 0 && socket6 < 0) || (hints_ai_family == AF_INET6 && socket6 < 0)) {
+        crash_and_burn("can't create socket (must run as root?)");
+    }
+#endif
+
+    if (ttl > 255) {
+        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", prog);
+        exit(1);
+    }
+
+    if (count_flag && loop_flag) {
+        fprintf(stderr, "%s: specify only one of c, l\n", prog);
+        exit(1);
+    }
+
+    if (interval < (float)MIN_INTERVAL_MS * 1000000 && getuid()) {
+        fprintf(stderr, "%s: -i must be >= %g\n", prog, (float)MIN_INTERVAL_MS);
+        exit(1);
+    }
+
+    if (perhost_interval < (float)MIN_PERHOST_INTERVAL_MS * 1000000 && getuid()) {
+        fprintf(stderr, "%s: -p must be >= %g\n", prog, (float)MIN_PERHOST_INTERVAL_MS);
+        exit(1);
+    }
+
+    if (ping_data_size > MAX_PING_DATA) {
+        fprintf(stderr, "%s: data size %u not valid, must not be larger than %u\n",
+            prog, ping_data_size, (unsigned int)MAX_PING_DATA);
+        exit(1);
+    }
+
+    if ((backoff > MAX_BACKOFF_FACTOR) || (backoff < MIN_BACKOFF_FACTOR)) {
+        fprintf(stderr, "%s: backoff factor %.1f not valid, must be between %.1f and %.1f\n",
+            prog, backoff, MIN_BACKOFF_FACTOR, MAX_BACKOFF_FACTOR);
+        exit(1);
+    }
+
+    if (icmp_request_typ == 13 && size_flag != 0) {
+        fprintf(stderr, "%s: cannot change ICMP Timestamp size\n", prog);
+        exit(1);
+    }
+
+    if (count_flag) {
+        if (verbose_flag)
+            per_recv_flag = 1;
+
+        alive_flag = unreachable_flag = verbose_flag = 0;
+    }
+
+    if (loop_flag) {
+        if (!report_interval)
+            per_recv_flag = 1;
+
+        alive_flag = unreachable_flag = verbose_flag = 0;
+    }
+
+    if (alive_flag || unreachable_flag || min_reachable)
+        verbose_flag = 0;
+
+    trials = (count > retry + 1) ? count : retry + 1;
+
+    /* auto-tune default timeout for count/loop modes
+     * see also github #32 */
+    if (loop_flag || count_flag) {
+        if (!timeout_flag) {
+            timeout = perhost_interval;
+            if (timeout > (int64_t)AUTOTUNE_TIMEOUT_MAX * 1000000) {
+                timeout = (int64_t)AUTOTUNE_TIMEOUT_MAX * 1000000;
+            }
+        }
+    }
+
+#if defined(DEBUG) || defined(_DEBUG)
+    if (debugging & DBG_TRACE)
+        trace_flag = 1;
+
+    if (debugging & DBG_RANDOM_LOSE_FEW) {
+        randomly_lose_flag = 1;
+        lose_factor = 1; /* ie, 1/4 */
+    }
+
+    if (debugging & DBG_RANDOM_LOSE_MANY) {
+        randomly_lose_flag = 1;
+        lose_factor = 5; /* ie, 3/4 */
+    }
+
+    if (debugging & DBG_PRINT_PER_SYSTEM)
+        print_per_system_flag = 1;
+
+    if ((debugging & DBG_REPORT_ALL_RTTS) && !loop_flag)
+        report_all_rtts_flag = 1;
+
+    if (trace_flag) {
+        fprintf(stderr, "%s:\n  count: %u, retry: %u, interval: %.0f ms\n",
+            prog, count, retry, interval / 1e6);
+        fprintf(stderr, "  perhost_interval: %.0f ms, timeout: %.0f\n",
+            perhost_interval / 1e6, timeout / 1e6);
+        fprintf(stderr, "  ping_data_size = %u, trials = %u\n",
+            ping_data_size, trials);
+
+        if (verbose_flag)
+            fprintf(stderr, "  verbose_flag set\n");
+        if (multif_flag)
+            fprintf(stderr, "  multif_flag set\n");
+        if (name_flag)
+            fprintf(stderr, "  name_flag set\n");
+        if (addr_flag)
+            fprintf(stderr, "  addr_flag set\n");
+        if (stats_flag)
+            fprintf(stderr, "  stats_flag set\n");
+        if (unreachable_flag)
+            fprintf(stderr, "  unreachable_flag set\n");
+        if (alive_flag)
+            fprintf(stderr, "  alive_flag set\n");
+        if (elapsed_flag)
+            fprintf(stderr, "  elapsed_flag set\n");
+        if (version_flag)
+            fprintf(stderr, "  version_flag set\n");
+        if (count_flag)
+            fprintf(stderr, "  count_flag set\n");
+        if (loop_flag)
+            fprintf(stderr, "  loop_flag set\n");
+        if (backoff_flag)
+            fprintf(stderr, "  backoff_flag set\n");
+        if (per_recv_flag)
+            fprintf(stderr, "  per_recv_flag set\n");
+        if (report_all_rtts_flag)
+            fprintf(stderr, "  report_all_rtts_flag set\n");
+        if (randomly_lose_flag)
+            fprintf(stderr, "  randomly_lose_flag set\n");
+        if (print_per_system_flag)
+            fprintf(stderr, "  print_per_system_flag set\n");
+        if (outage_flag)
+            fprintf(stderr, "  outage_flag set\n");
+        if (netdata_flag)
+            fprintf(stderr, "  netdata_flag set\n");
+    }
+#endif /* DEBUG || _DEBUG */
+
+    /* set the TTL, if the -H option was set (otherwise ttl will be = 0) */
+    if (ttl > 0) {
+        if (socket4 >= 0) {
+            if (setsockopt(socket4, IPPROTO_IP, IP_TTL, &ttl, sizeof(ttl))) {
+                perror("setting time to live");
+            }
+        }
+#ifdef IPV6
+        if (socket6 >= 0) {
+            if (setsockopt(socket6, IPPROTO_IPV6, IPV6_UNICAST_HOPS, &ttl, sizeof(ttl))) {
+                perror("setting time to live");
+            }
+        }
+#endif
+    }
+
+#if HAVE_SO_TIMESTAMPNS
+    {
+        int opt = 1;
+        if (socket4 >= 0) {
+            if (setsockopt(socket4, SOL_SOCKET, SO_TIMESTAMPNS, &opt, sizeof(opt))) {
+                if (setsockopt(socket4, SOL_SOCKET, SO_TIMESTAMP, &opt, sizeof(opt))) {
+                    perror("setting SO_TIMESTAMPNS and SO_TIMESTAMP option");
+                }
+            }
+        }
+#ifdef IPV6
+        if (socket6 >= 0) {
+            if (setsockopt(socket6, SOL_SOCKET, SO_TIMESTAMPNS, &opt, sizeof(opt))) {
+                if (setsockopt(socket6, SOL_SOCKET, SO_TIMESTAMP, &opt, sizeof(opt))) {
+                    perror("setting SO_TIMESTAMPNS and SO_TIMESTAMP option (IPv6)");
+                }
+            }
+        }
+#endif
+    }
+#endif
+
+    update_current_time();
+    start_time = current_time_ns;
+
+    /* handle host names supplied on command line or in a file */
+    /* if the generate_flag is on, then generate the IP list */
+
+    argv = &argv[optparse_state.optind];
+    argc -= optparse_state.optind;
+
+    /* calculate how many ping can be in-flight per host */
+    if (count_flag) {
+        event_storage_count = count;
+    }
+    else if (loop_flag) {
+        if (perhost_interval > timeout) {
+            event_storage_count = 1;
+        }
+        else {
+            event_storage_count = 1 + timeout / perhost_interval;
+        }
+    }
+    else {
+        event_storage_count = 1;
+    }
+
+    /* file and generate are mutually exclusive */
+    /* file and command line are mutually exclusive */
+    /* generate requires command line parameters beyond the switches */
+    if ((*argv && filename) || (filename && generate_flag) || (generate_flag && !*argv))
+        usage(1);
+
+    /* if no conditions are specified, then assume input from stdin */
+    if (!*argv && !filename && !generate_flag)
+        filename = "-";
+
+    if (*argv && !generate_flag) {
+        while (*argv) {
+            add_name(*argv);
+            ++argv;
+        }
+    }
+    else if (filename) {
+        FILE *ping_file;
+        char line[132];
+        char host[132];
+
+        if (strcmp(filename, "-") == 0)
+            ping_file = fdopen(0, "r");
+        else
+            ping_file = fopen(filename, "r");
+
+        if (!ping_file)
+            errno_crash_and_burn("fopen");
+
+        while (fgets(line, sizeof(line), ping_file)) {
+            if (sscanf(line, "%s", host) != 1)
+                continue;
+
+            if ((!*host) || (host[0] == '#')) /* magic to avoid comments */
+                continue;
+
+            add_name(host);
+        }
+
+        fclose(ping_file);
+    }
+    else if (*argv && generate_flag) {
+        if (argc == 1) {
+            /* one target: we expect a cidr range (n.n.n.n/m) */
+            add_cidr(argv[0]);
+        }
+        else if (argc == 2) {
+            add_range(argv[0], argv[1]);
+        }
+        else {
+            usage(1);
+        }
+    }
+    else {
+        usage(1);
+    }
+
+    if (!num_hosts) {
+        exit(num_noaddress ? 2 : 1);
+    }
+
+    if (socket4 >= 0 && (src_addr_set || socktype4 == SOCK_DGRAM)) {
+        socket_set_src_addr_ipv4(socket4, &src_addr, (socktype4 == SOCK_DGRAM) ? &ident4 : NULL);
+    }
+#ifdef IPV6
+    if (socket6 >= 0 && (src_addr6_set || socktype6 == SOCK_DGRAM)) {
+        socket_set_src_addr_ipv6(socket6, &src_addr6, (socktype6 == SOCK_DGRAM) ? &ident6 : NULL);
+    }
+#endif
+
+    /* allocate and initialize array to map host nr to host_entry */
+    {
+        struct event *cursor = event_queue_ping.first;
+        int i = 0;
+        table = (HOST_ENTRY **)calloc(num_hosts, sizeof(HOST_ENTRY *));
+        if (!table)
+            crash_and_burn("Can't malloc array of hosts");
+        /* initialize table of hosts. we know that we have ping events scheduled
+         * for each of them */
+        for (cursor = event_queue_ping.first; cursor; cursor = cursor->ev_next) {
+            table[i] = cursor->host;
+            cursor->host->i = i;
+            i++;
+        }
+    }
+
+    init_ping_buffer_ipv4(ping_data_size);
+#ifdef IPV6
+    init_ping_buffer_ipv6(ping_data_size);
+#endif
+
+#ifdef USE_SIGACTION
+    memset(&act, 0, sizeof(act));
+    act.sa_handler = signal_handler;
+    sigemptyset(&act.sa_mask);
+    sigaddset(&act.sa_mask, SIGINT);
+    sigaddset(&act.sa_mask, SIGQUIT);
+    act.sa_flags = SA_RESTART;
+    if (sigaction(SIGQUIT, &act, NULL) || sigaction(SIGINT, &act, NULL)) {
+        crash_and_burn("failure to set signal handler");
+    }
+#else
+    signal(SIGINT, signal_handler);
+    signal(SIGQUIT, signal_handler);
+#endif
+    setlinebuf(stdout);
+
+    if (report_interval) {
+        next_report_time = current_time_ns + report_interval;
+    }
+
+    last_send_time = 0;
+
+    seqmap_init();
+
+    /* main loop */
+    main_loop();
+
+/* Debug: CPU Performance */
+#if defined(DEBUG) || defined(_DEBUG)
+    perf_cpu_end = clock();
+    perf_cpu_time_used = ((double) (perf_cpu_end - perf_cpu_start)) / CLOCKS_PER_SEC;
+    printf("[DEBUG] CPU time used: %f sec", perf_cpu_time_used);
+#endif /* DEBUG || _DEBUG */
+
+    finish();
+
+    return 0;
+}
+
+static inline int64_t timespec_ns(struct timespec *a)
+{
+    return ((int64_t)a->tv_sec * 1000000000) + a->tv_nsec;
+}
+
+void add_cidr(char *addr)
+{
+    char *addr_end;
+    char *mask_str;
+    unsigned long mask;
+    unsigned long bitmask;
+    int ret;
+    struct addrinfo addr_hints;
+    struct addrinfo *addr_res;
+    unsigned long net_addr;
+    unsigned long net_last;
+
+    /* Split address from mask */
+    addr_end = strchr(addr, '/');
+    if (addr_end == NULL) {
+        usage(1);
+    }
+    *addr_end = '\0';
+    mask_str = addr_end + 1;
+    mask = atoi(mask_str);
+
+    /* parse address (IPv4 only) */
+    memset(&addr_hints, 0, sizeof(struct addrinfo));
+    addr_hints.ai_family = AF_UNSPEC;
+    addr_hints.ai_flags = AI_NUMERICHOST;
+    ret = getaddrinfo(addr, NULL, &addr_hints, &addr_res);
+    if (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, "%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);
+    freeaddrinfo(addr_res);
+
+    /* check mask */
+    if (mask < 1 || mask > 32) {
+        fprintf(stderr, "%s: netmask must be between 1 and 32 (is: %s)\n", prog, mask_str);
+        exit(1);
+    }
+
+    /* convert mask integer from 1 to 32 to a bitmask */
+    bitmask = ((unsigned long)0xFFFFFFFF) << (32 - mask);
+
+    /* calculate network range */
+    net_addr &= bitmask;
+    net_last = net_addr + ((unsigned long)0x1 << (32 - mask)) - 1;
+
+    /* exclude network and broadcast address for regular prefixes */
+    if (mask < 31) {
+        net_last--;
+        net_addr++;
+    }
+
+    /* add all hosts in that network (net_addr and net_last inclusive) */
+    add_addr_range_ipv4(net_addr, net_last);
+}
+
+void add_range(char *start, char *end)
+{
+    struct addrinfo addr_hints;
+    struct addrinfo *addr_res;
+    unsigned long start_long;
+    unsigned long end_long;
+    int ret;
+
+    /* parse start address (IPv4 only) */
+    memset(&addr_hints, 0, sizeof(struct addrinfo));
+    addr_hints.ai_family = AF_UNSPEC;
+    addr_hints.ai_flags = AI_NUMERICHOST;
+    ret = getaddrinfo(start, NULL, &addr_hints, &addr_res);
+    if (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, "%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);
+
+    /* parse end address (IPv4 only) */
+    memset(&addr_hints, 0, sizeof(struct addrinfo));
+    addr_hints.ai_family = AF_UNSPEC;
+    addr_hints.ai_flags = AI_NUMERICHOST;
+    ret = getaddrinfo(end, NULL, &addr_hints, &addr_res);
+    if (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, "%s: -g works only with IPv4 addresses\n", prog);
+        exit(1);
+    }
+    end_long = ntohl(((struct sockaddr_in *)addr_res->ai_addr)->sin_addr.s_addr);
+    freeaddrinfo(addr_res);
+
+    /* add IPv4 addresses from closed interval [start_long,end_long] */
+    add_addr_range_ipv4(start_long, end_long);
+}
+
+void add_addr_range_ipv4(unsigned long start_long, unsigned long end_long)
+{
+    /* check if generator limit is exceeded */
+    if (end_long >= start_long + MAX_GENERATE) {
+        fprintf(stderr, "%s: -g parameter generates too many addresses\n", prog);
+        exit(1);
+    }
+
+    /* generate */
+    for (; start_long <= end_long; start_long++) {
+        struct in_addr in_addr_tmp;
+        char buffer[20];
+        in_addr_tmp.s_addr = htonl(start_long);
+        inet_ntop(AF_INET, &in_addr_tmp, buffer, sizeof(buffer));
+        add_name(buffer);
+    }
+}
+
+void main_loop()
+{
+    int64_t lt;
+    int64_t wait_time_ns;
+    struct event *event;
+    struct host_entry *h;
+
+    while (event_queue_ping.first || event_queue_timeout.first) {
+        dbg_printf("%s", "# main_loop\n");
+
+        /* timeout event ? */
+        if (event_queue_timeout.first && event_queue_timeout.first->ev_time - current_time_ns <= 0) {
+            event = ev_dequeue(&event_queue_timeout);
+            h = event->host;
+
+            dbg_printf("%s [%d]: timeout event\n", h->host, event->ping_index);
+
+            stats_add(h, event->ping_index, 0, -1);
+
+            if (per_recv_flag) {
+                if (timestamp_flag) {
+                    print_timestamp_format(current_time_ns, timestamp_format_flag);
+                }
+                printf("%-*s : [%d], timed out",
+                    max_hostname_len, h->host, event->ping_index);
+                if (h->num_recv > 0) {
+                    printf(" (%s avg, ", sprint_tm(h->total_time / h->num_recv));
+                }
+                else {
+                    printf(" (NaN avg, ");
+                }
+                if (h->num_recv <= h->num_sent) {
+                    printf("%d%% loss)",
+                        ((h->num_sent - h->num_recv) * 100) / h->num_sent);
+                }
+                else {
+                    printf("%d%% return)",
+                        (h->num_recv_total * 100) / h->num_sent);
+                }
+                printf("\n");
+            }
+
+            /* do we need to send a retry? */
+            if (!loop_flag && !count_flag) {
+                if (h->num_sent < retry + 1) {
+                    if (backoff_flag) {
+                        h->timeout *= backoff;
+                    }
+                    send_ping(h, event->ping_index);
+                }
+            }
+
+            /* note: we process first timeout events, because we might need to
+             * wait to process ping events, while we for sure never need to
+             * wait for timeout events.
+             */
+            continue;
+        }
+
+        /* ping event ? */
+        if (event_queue_ping.first && event_queue_ping.first->ev_time - current_time_ns <= 0) {
+            /* Make sure that we don't ping more than once every "interval" */
+            lt = current_time_ns - last_send_time;
+            if (lt < interval)
+                goto wait_for_reply;
+
+            /* Dequeue the event */
+            event = ev_dequeue(&event_queue_ping);
+            h = event->host;
+
+            dbg_printf("%s [%d]: ping event\n", h->host, event->ping_index);
+
+            /* Send the ping */
+            send_ping(h, event->ping_index);
+
+            /* Loop and count mode: schedule next ping */
+            if (loop_flag || (count_flag && event->ping_index + 1 < count)) {
+                host_add_ping_event(h, event->ping_index + 1, event->ev_time + perhost_interval);
+            }
+        }
+
+    wait_for_reply:
+
+        /* When is the next ping next event? */
+        wait_time_ns = -1;
+        if (event_queue_ping.first) {
+            wait_time_ns = event_queue_ping.first->ev_time - current_time_ns;
+            if (wait_time_ns < 0)
+                wait_time_ns = 0;
+            /* make sure that we wait enough, so that the inter-ping delay is
+             * bigger than 'interval' */
+            if (wait_time_ns < interval) {
+                lt = current_time_ns - last_send_time;
+                if (lt < interval) {
+                    wait_time_ns = interval - lt;
+                }
+            }
+
+            dbg_printf("next ping event in %.0f ms (%s)\n", wait_time_ns / 1e6, event_queue_ping.first->host->host);
+        }
+
+        /* When is the next timeout event? */
+        if (event_queue_timeout.first) {
+            int64_t wait_time_timeout = event_queue_timeout.first->ev_time - current_time_ns;
+            if (wait_time_ns < 0 || wait_time_timeout < wait_time_ns) {
+                wait_time_ns = wait_time_timeout;
+                if (wait_time_ns < 0) {
+                    wait_time_ns = 0;
+                }
+            }
+
+            dbg_printf("next timeout event in %.0f ms (%s)\n", wait_time_timeout / 1e6, event_queue_timeout.first->host->host);
+        }
+
+        /* When is the next report due? */
+        if (report_interval && (loop_flag || count_flag)) {
+            int64_t wait_time_next_report = next_report_time - current_time_ns;
+            if (wait_time_next_report < wait_time_ns) {
+                wait_time_ns = wait_time_next_report;
+                if (wait_time_ns < 0) {
+                    wait_time_ns = 0;
+                }
+            }
+
+            dbg_printf("next report  event in %0.f ms\n", wait_time_next_report / 1e6);
+        }
+
+        /* if wait_time is still -1, it means that we are waiting for nothing... */
+        if (wait_time_ns == -1) {
+            break;
+        }
+
+        /* end of loop was requested by interrupt signal handler */
+        if (finish_requested) {
+            break;
+        }
+
+        /* Receive replies */
+        /* (this is what sleeps during each loop iteration) */
+        dbg_printf("waiting up to %.0f ms\n", wait_time_ns / 1e6);
+        if (wait_for_reply(wait_time_ns)) {
+            while (wait_for_reply(0))
+                ; /* process other replies in the queue */
+        }
+
+        update_current_time();
+
+        if (status_snapshot) {
+            status_snapshot = 0;
+            print_per_system_splits();
+        }
+
+        /* Print report */
+        if (report_interval && (loop_flag || count_flag) && (current_time_ns >= next_report_time)) {
+            if (netdata_flag)
+                print_netdata();
+            else
+                print_per_system_splits();
+
+            while (current_time_ns >= next_report_time) {
+                next_report_time += report_interval;
+            }
+        }
+    }
+}
+
+/************************************************************
+
+  Function: signal_handler
+
+*************************************************************
+
+  Inputs:  int signum
+
+  Description:
+
+  SIGQUIT signal handler - set flag and return
+  SIGINT signal handler - set flag and return
+
+************************************************************/
+
+void signal_handler(int signum)
+{
+    switch (signum) {
+    case SIGINT:
+        finish_requested = 1;
+        break;
+
+    case SIGQUIT:
+        status_snapshot = 1;
+        break;
+    }
+}
+
+/************************************************************
+
+  Function: update_current_time
+
+*************************************************************/
+
+void update_current_time()
+{
+    clock_gettime(CLOCKID, &current_time);
+    current_time_ns = timespec_ns(&current_time);
+}
+
+/************************************************************
+
+  Function: finish
+
+*************************************************************
+
+  Inputs:  void (none)
+
+  Description:
+
+  Main program clean up and exit point
+
+************************************************************/
+
+void finish()
+{
+    int i;
+    HOST_ENTRY *h;
+
+    update_current_time();
+    end_time = current_time_ns;
+
+    /* tot up unreachables */
+    for (i = 0; i < num_hosts; i++) {
+        h = table[i];
+
+        if (!h->num_recv) {
+            num_unreachable++;
+
+            if (verbose_flag || unreachable_flag) {
+                printf("%s", h->host);
+
+                if (verbose_flag)
+                    printf(" is unreachable");
+
+                printf("\n");
+            }
+        }
+    }
+
+    if (count_flag || loop_flag)
+        print_per_system_stats();
+#if defined(DEBUG) || defined(_DEBUG)
+    else if (print_per_system_flag)
+        print_per_system_stats();
+#endif /* DEBUG || _DEBUG */
+
+    if (stats_flag)
+        print_global_stats();
+
+    if (min_reachable) {
+        if ((num_hosts - num_unreachable) >= min_reachable) {
+            printf("Enough hosts reachable (required: %d, reachable: %d)\n", min_reachable, num_hosts - num_unreachable);
+            exit(0);
+        }
+        else {
+            printf("Not enough hosts reachable (required: %d, reachable: %d)\n", min_reachable, num_hosts - num_unreachable);
+            exit(1);
+        }
+    }
+
+    if (num_noaddress)
+        exit(2);
+    else if (num_alive != num_hosts)
+        exit(1);
+
+    exit(0);
+}
+
+/************************************************************
+
+  Function: print_per_system_stats
+
+*************************************************************
+
+  Inputs:  void (none)
+
+  Description:
+
+
+************************************************************/
+
+void print_per_system_stats(void)
+{
+    int i, j, avg, outage_ms;
+    HOST_ENTRY *h;
+    int64_t resp;
+
+    if (verbose_flag || per_recv_flag)
+        fprintf(stderr, "\n");
+
+    for (i = 0; i < num_hosts; i++) {
+        h = table[i];
+        fprintf(stderr, "%-*s :", max_hostname_len, h->host);
+
+        if (report_all_rtts_flag) {
+            for (j = 0; j < h->num_sent; j++) {
+                if ((resp = h->resp_times[j]) >= 0)
+                    fprintf(stderr, " %s", sprint_tm(resp));
+                else
+                    fprintf(stderr, " -");
+            }
+
+            fprintf(stderr, "\n");
+        }
+        else {
+            if (h->num_recv <= h->num_sent) {
+                fprintf(stderr, " xmt/rcv/%%loss = %d/%d/%d%%",
+                    h->num_sent, h->num_recv, h->num_sent > 0 ? ((h->num_sent - h->num_recv) * 100) / h->num_sent : 0);
+
+                if (outage_flag) {
+                    /* Time outage total */
+                    outage_ms = (h->num_sent - h->num_recv) * perhost_interval / 1e6;
+                    fprintf(stderr, ", outage(ms) = %d", outage_ms);
+                }
+            }
+            else {
+                fprintf(stderr, " xmt/rcv/%%return = %d/%d/%d%%",
+                    h->num_sent, h->num_recv,
+                    h->num_sent > 0 ? ((h->num_recv * 100) / h->num_sent) : 0);
+            }
+
+            if (h->num_recv) {
+                avg = h->total_time / h->num_recv;
+                fprintf(stderr, ", min/avg/max = %s", sprint_tm(h->min_reply));
+                fprintf(stderr, "/%s", sprint_tm(avg));
+                fprintf(stderr, "/%s", sprint_tm(h->max_reply));
+            }
+
+            fprintf(stderr, "\n");
+        }
+    }
+}
+
+/************************************************************
+
+  Function: print_netdata
+
+*************************************************************
+
+  Inputs:  void (none)
+
+  Description:
+
+
+************************************************************/
+
+void print_netdata(void)
+{
+    static int sent_charts = 0;
+
+    int i;
+    int64_t avg;
+    HOST_ENTRY *h;
+
+    for (i = 0; i < num_hosts; i++) {
+        h = table[i];
+
+        if (!sent_charts) {
+            printf("CHART fping.%s_packets '' 'FPing Packets' packets '%s' fping.packets line 110020 %.0f\n", h->name, h->host, report_interval / 1e9);
+            printf("DIMENSION xmt sent absolute 1 1\n");
+            printf("DIMENSION rcv received absolute 1 1\n");
+        }
+
+        printf("BEGIN fping.%s_packets\n", h->name);
+        printf("SET xmt = %d\n", h->num_sent_i);
+        printf("SET rcv = %d\n", h->num_recv_i);
+        printf("END\n");
+
+        if (!sent_charts) {
+            printf("CHART fping.%s_quality '' 'FPing Quality' percentage '%s' fping.quality area 110010 %.0f\n", h->name, h->host, report_interval / 1e9);
+            printf("DIMENSION returned '' absolute 1 1\n");
+            /* printf("DIMENSION lost '' absolute 1 1\n"); */
+        }
+
+        printf("BEGIN fping.%s_quality\n", h->name);
+        /*
+        if( h->num_recv_i <= h->num_sent_i )
+            printf("SET lost = %d\n", h->num_sent_i > 0 ? ( ( h->num_sent_i - h->num_recv_i ) * 100 ) / h->num_sent_i : 0 );
+        else
+            printf("SET lost = 0\n");
+*/
+
+        printf("SET returned = %d\n", h->num_sent_i > 0 ? ((h->num_recv_i * 100) / h->num_sent_i) : 0);
+        printf("END\n");
+
+        if (!sent_charts) {
+            printf("CHART fping.%s_latency '' 'FPing Latency' ms '%s' fping.latency area 110000 %.0f\n", h->name, h->host, report_interval / 1e9);
+            printf("DIMENSION min minimum absolute 1 1000000\n");
+            printf("DIMENSION max maximum absolute 1 1000000\n");
+            printf("DIMENSION avg average absolute 1 1000000\n");
+        }
+
+        printf("BEGIN fping.%s_latency\n", h->name);
+        if (h->num_recv_i) {
+            avg = h->total_time_i / h->num_recv_i;
+            printf("SET min = %" PRId64 "\n", h->min_reply_i);
+            printf("SET avg = %" PRId64 "\n", avg);
+            printf("SET max = %" PRId64 "\n", h->max_reply_i);
+        }
+        printf("END\n");
+
+        stats_reset_interval(h);
+    }
+
+    sent_charts = 1;
+}
+
+/************************************************************
+
+  Function: print_per_system_splits
+
+*************************************************************
+
+  Inputs:  void (none)
+
+  Description:
+
+
+************************************************************/
+
+void print_per_system_splits(void)
+{
+    int i, avg, outage_ms_i;
+    HOST_ENTRY *h;
+    struct tm *curr_tm;
+
+    if (verbose_flag || per_recv_flag)
+        fprintf(stderr, "\n");
+
+    update_current_time();
+    curr_tm = localtime((time_t *)&current_time.tv_sec);
+    fprintf(stderr, "[%2.2d:%2.2d:%2.2d]\n", curr_tm->tm_hour,
+        curr_tm->tm_min, curr_tm->tm_sec);
+
+    for (i = 0; i < num_hosts; i++) {
+        h = table[i];
+        fprintf(stderr, "%-*s :", max_hostname_len, h->host);
+
+        if (h->num_recv_i <= h->num_sent_i) {
+            fprintf(stderr, " xmt/rcv/%%loss = %d/%d/%d%%",
+                h->num_sent_i, h->num_recv_i, h->num_sent_i > 0 ? ((h->num_sent_i - h->num_recv_i) * 100) / h->num_sent_i : 0);
+
+            if (outage_flag) {
+                /* Time outage  */
+                outage_ms_i = (h->num_sent_i - h->num_recv_i) * perhost_interval / 1e6;
+                fprintf(stderr, ", outage(ms) = %d", outage_ms_i);
+            }
+        }
+        else {
+            fprintf(stderr, " xmt/rcv/%%return = %d/%d/%d%%",
+                h->num_sent_i, h->num_recv_i, h->num_sent_i > 0 ? ((h->num_recv_i * 100) / h->num_sent_i) : 0);
+        }
+
+        if (h->num_recv_i) {
+            avg = h->total_time_i / h->num_recv_i;
+            fprintf(stderr, ", min/avg/max = %s", sprint_tm(h->min_reply_i));
+            fprintf(stderr, "/%s", sprint_tm(avg));
+            fprintf(stderr, "/%s", sprint_tm(h->max_reply_i));
+        }
+
+        fprintf(stderr, "\n");
+        if (!cumulative_stats_flag) {
+            stats_reset_interval(h);
+        }
+    }
+}
+
+/************************************************************
+
+  Function: print_global_stats
+
+*************************************************************
+
+  Inputs:  void (none)
+
+  Description:
+
+
+************************************************************/
+
+void print_global_stats(void)
+{
+    fprintf(stderr, "\n");
+    fprintf(stderr, " %7d targets\n", num_hosts);
+    fprintf(stderr, " %7d alive\n", num_alive);
+    fprintf(stderr, " %7d unreachable\n", num_unreachable);
+    fprintf(stderr, " %7d unknown addresses\n", num_noaddress);
+    fprintf(stderr, "\n");
+    fprintf(stderr, " %7d timeouts (waiting for response)\n", num_timeout);
+    fprintf(stderr, " %7d ICMP Echos sent\n", num_pingsent);
+    fprintf(stderr, " %7d ICMP Echo Replies received\n", num_pingreceived);
+    fprintf(stderr, " %7d other ICMP received\n", num_othericmprcvd);
+    fprintf(stderr, "\n");
+
+    if (total_replies == 0) {
+        min_reply = 0;
+        max_reply = 0;
+        total_replies = 1;
+        sum_replies = 0;
+    }
+
+    fprintf(stderr, " %s ms (min round trip time)\n", sprint_tm(min_reply));
+    fprintf(stderr, " %s ms (avg round trip time)\n",
+        sprint_tm(sum_replies / total_replies));
+    fprintf(stderr, " %s ms (max round trip time)\n", sprint_tm(max_reply));
+    fprintf(stderr, " %12.3f sec (elapsed real time)\n",
+        (end_time - start_time) / 1e9);
+    fprintf(stderr, "\n");
+}
+
+/************************************************************
+
+  Function: send_ping
+
+*************************************************************
+
+  Inputs:  int s, HOST_ENTRY *h
+
+  Description:
+
+  Compose and transmit an ICMP_ECHO REQUEST packet.  The IP packet
+  will be added on by the kernel.  The ID field is our UNIX process ID,
+  and the sequence number is an index into an array of outstanding
+  ping requests. The sequence number will later be used to quickly
+  figure out who the ping reply came from.
+
+************************************************************/
+
+int send_ping(HOST_ENTRY *h, int index)
+{
+    int n;
+    int myseq;
+    int ret = 1;
+    uint8_t proto = ICMP_ECHO;
+
+    update_current_time();
+    h->last_send_time = current_time_ns;
+    myseq = seqmap_add(h->i, index, current_time_ns);
+
+    dbg_printf("%s [%d]: send ping\n", h->host, index);
+
+    if (h->saddr.ss_family == AF_INET && socket4 >= 0) {
+        if(icmp_request_typ == 13)
+            proto = ICMP_TSTAMP;
+        n = socket_sendto_ping_ipv4(socket4, (struct sockaddr *)&h->saddr, h->saddr_len, myseq, ident4, proto);
+    }
+#ifdef IPV6
+    else if (h->saddr.ss_family == AF_INET6 && socket6 >= 0) {
+        n = socket_sendto_ping_ipv6(socket6, (struct sockaddr *)&h->saddr, h->saddr_len, myseq, ident6);
+    }
+#endif
+    else {
+        return 0;
+    }
+
+    /* error sending? */
+    if (
+        (n < 0)
+#if defined(EHOSTDOWN)
+        && errno != EHOSTDOWN
+#endif
+    ) {
+        if (verbose_flag) {
+            print_warning("%s: error while sending ping: %s\n", h->host, strerror(errno));
+        }
+        else {
+            dbg_printf("%s: error while sending ping: %s\n", h->host, strerror(errno));
+        }
+
+        h->num_sent++;
+        h->num_sent_i++;
+        if (!loop_flag)
+            h->resp_times[index] = RESP_ERROR;
+
+        ret = 0;
+    }
+    else {
+        /* schedule timeout */
+        host_add_timeout_event(h, index, current_time_ns + h->timeout);
+
+        /* mark this trial as outstanding */
+        if (!loop_flag) {
+            h->resp_times[index] = RESP_WAITING;
+        }
+    }
+
+    num_pingsent++;
+    last_send_time = h->last_send_time;
+
+    return (ret);
+}
+
+int socket_can_read(struct timeval *timeout)
+{
+    int nfound;
+    fd_set readset;
+    int socketmax;
+
+#ifndef IPV6
+    socketmax = socket4;
+#else
+    socketmax = socket4 > socket6 ? socket4 : socket6;
+#endif
+
+select_again:
+    FD_ZERO(&readset);
+    if (socket4 >= 0)
+        FD_SET(socket4, &readset);
+#ifdef IPV6
+    if (socket6 >= 0)
+        FD_SET(socket6, &readset);
+#endif
+
+    nfound = select(socketmax + 1, &readset, NULL, NULL, timeout);
+    if (nfound < 0) {
+        if (errno == EINTR) {
+            /* interrupted system call: redo the select */
+            goto select_again;
+        }
+        else {
+            perror("select");
+        }
+    }
+
+    if (nfound > 0) {
+        if (socket4 >= 0 && FD_ISSET(socket4, &readset)) {
+            return socket4;
+        }
+#ifdef IPV6
+        if (socket6 >= 0 && FD_ISSET(socket6, &readset)) {
+            return socket6;
+        }
+#endif
+    }
+
+    return -1;
+}
+
+int receive_packet(int64_t wait_time,
+#if HAVE_SO_TIMESTAMPNS
+    int64_t *reply_timestamp,
+#else
+    int64_t *reply_timestamp __attribute__((unused)),
+#endif
+    struct sockaddr *reply_src_addr,
+    size_t reply_src_addr_len,
+    char *reply_buf,
+    size_t reply_buf_len)
+{
+    struct timeval to;
+    int s = 0;
+    int recv_len;
+    static unsigned char msg_control[40];
+    struct iovec msg_iov = {
+        reply_buf,
+        reply_buf_len
+    };
+    struct msghdr recv_msghdr = {0};
+    recv_msghdr.msg_name = reply_src_addr;
+    recv_msghdr.msg_namelen = reply_src_addr_len;
+    recv_msghdr.msg_iov = &msg_iov;
+    recv_msghdr.msg_iovlen = 1;
+    recv_msghdr.msg_control = &msg_control;
+    recv_msghdr.msg_controllen = sizeof(msg_control);
+#if HAVE_SO_TIMESTAMPNS
+    struct cmsghdr *cmsg;
+#endif
+
+    /* Wait for a socket to become ready */
+    if (wait_time) {
+        to.tv_sec = wait_time / UINT64_C(1000000000);
+        to.tv_usec = (wait_time % UINT64_C(1000000000)) / 1000 + 1;
+    }
+    else {
+        to.tv_sec = 0;
+        to.tv_usec = 0;
+    }
+    s = socket_can_read(&to);
+    if (s == -1) {
+        return 0; /* timeout */
+    }
+
+    recv_len = recvmsg(s, &recv_msghdr, MSG_TRUNC);
+    if (recv_len <= 0) {
+        return 0;
+    }
+
+#if HAVE_SO_TIMESTAMPNS
+    /* ancilliary data */
+    {
+        struct timespec reply_timestamp_ts;
+        for (cmsg = CMSG_FIRSTHDR(&recv_msghdr);
+             cmsg != NULL;
+             cmsg = CMSG_NXTHDR(&recv_msghdr, cmsg)) {
+            if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_TIMESTAMPNS) {
+                memcpy(&reply_timestamp_ts, CMSG_DATA(cmsg), sizeof(reply_timestamp_ts));
+                *reply_timestamp = timespec_ns(&reply_timestamp_ts);
+            }
+        }
+    }
+#endif
+
+#if defined(DEBUG) || defined(_DEBUG)
+    if (randomly_lose_flag) {
+        if ((random() & 0x07) <= lose_factor)
+            return 0;
+    }
+#endif
+
+    return recv_len;
+}
+
+/* stats_add: update host statistics for a single packet that was received (or timed out)
+ * h: host entry to update
+ * index: if in count mode: index number for this ping packet (-1 otherwise)
+ * success: 1 if response received, 0 otherwise
+ * latency: response time, in ns
+ */
+void stats_add(HOST_ENTRY *h, int index, int success, int64_t latency)
+{
+    /* sent count - we update only on receive/timeout, so that we don't get
+     * weird loss percentage, just because a packet was note recived yet.
+     */
+    h->num_sent++;
+    h->num_sent_i++;
+
+    if (!success) {
+        if (!loop_flag && index >= 0) {
+            h->resp_times[index] = RESP_TIMEOUT;
+        }
+        num_timeout++;
+        return;
+    }
+
+    /* received count */
+    h->num_recv++;
+    h->num_recv_i++;
+
+    /* maximum */
+    if (!h->max_reply || latency > h->max_reply) {
+        h->max_reply = latency;
+    }
+    if (!h->max_reply_i || latency > h->max_reply_i) {
+        h->max_reply_i = latency;
+    }
+
+    /* minimum */
+    if (!h->min_reply || latency < h->min_reply) {
+        h->min_reply = latency;
+    }
+    if (!h->min_reply_i || latency < h->min_reply_i) {
+        h->min_reply_i = latency;
+    }
+
+    /* total time (for average) */
+    h->total_time += latency;
+    h->total_time_i += latency;
+
+    /* response time per-packet (count mode) */
+    if (!loop_flag && index >= 0) {
+        h->resp_times[index] = latency;
+    }
+}
+
+/* stats_reset_interval: reset interval statistics
+ * h: host entry to update
+ */
+void stats_reset_interval(HOST_ENTRY *h)
+{
+    h->num_sent_i = 0;
+    h->num_recv_i = 0;
+    h->max_reply_i = 0;
+    h->min_reply_i = 0;
+    h->total_time_i = 0;
+}
+
+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,
+    int *ip_header_tos,
+    int *ip_header_ttl,
+    uint32_t *ip_header_otime_ms,
+    uint32_t *ip_header_rtime_ms,
+    uint32_t *ip_header_ttime_ms)
+{
+    struct icmp *icp;
+    int hlen = 0;
+
+    if (!using_sock_dgram4) {
+        struct ip *ip = (struct ip *)reply_buf;
+        *ip_header_tos = ip->ip_tos;
+        *ip_header_ttl = ip->ip_ttl;
+
+#if defined(__alpha__) && __STDC__ && !defined(__GLIBC__) && !defined(__NetBSD__) && !defined(__OpenBSD__)
+        /* 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(response_addr, response_addr_len, 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 -1;
+    }
+
+    icp = (struct icmp *)(reply_buf + hlen);
+
+    if ((icmp_request_typ == 0 && icp->icmp_type != ICMP_ECHOREPLY) ||
+        (icmp_request_typ == 13 && icp->icmp_type != ICMP_TSTAMPREPLY)) {
+        /* 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 -1;
+        }
+
+        sent_icmp = (struct icmp *)(reply_buf + hlen + ICMP_MINLEN + sizeof(struct ip));
+
+        if ((icmp_request_typ == 0 && sent_icmp->icmp_type != ICMP_ECHO) ||
+            (icmp_request_typ == 13 && sent_icmp->icmp_type != ICMP_TSTAMP) ||
+            sent_icmp->icmp_id != ident4) {
+            /* not caused by us */
+            return -1;
+        }
+
+        seqmap_value = seqmap_fetch(ntohs(sent_icmp->icmp_seq), current_time_ns);
+        if (seqmap_value == NULL) {
+            return -1;
+        }
+
+        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;
+        }
+
+        return -1;
+    }
+
+    *id = icp->icmp_id;
+    *seq = ntohs(icp->icmp_seq);
+    if(icp->icmp_type == ICMP_TSTAMPREPLY) {
+
+        /* Check that reply_buf_len is sufficiently big to contain the timestamps */
+        if (reply_buf_len < hlen + ICMP_MINLEN + ICMP_TIMESTAMP_DATA_SIZE) {
+            if (verbose_flag) {
+                char buf[INET6_ADDRSTRLEN];
+                getnameinfo(response_addr, response_addr_len, buf, INET6_ADDRSTRLEN, NULL, 0, NI_NUMERICHOST);
+                printf("received packet too short for ICMP Timestamp Reply (%d bytes from %s)\n", (int)reply_buf_len, buf);
+            }
+            return -1;
+        }
+
+        *ip_header_otime_ms = ntohl(icp->icmp_dun.id_ts.its_otime);
+        *ip_header_rtime_ms = ntohl(icp->icmp_dun.id_ts.its_rtime);
+        *ip_header_ttime_ms = ntohl(icp->icmp_dun.id_ts.its_ttime);
+    }
+
+    return hlen;
+}
+
+#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(response_addr, response_addr_len, 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 */
+    }
+
+    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 || sent_icmp->icmp6_id != ident6) {
+            /* not caused by us */
+            return 0;
+        }
+
+        seqmap_value = seqmap_fetch(ntohs(sent_icmp->icmp6_seq), current_time_ns);
+        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 = icp->icmp6_id;
+    *seq = ntohs(icp->icmp6_seq);
+
+    return 1;
+}
+#endif
+
+int wait_for_reply(int64_t wait_time)
+{
+    int result;
+    static char buffer[RECV_BUFSIZE];
+    struct sockaddr_storage response_addr;
+    int n, avg;
+    HOST_ENTRY *h;
+    int64_t this_reply;
+    int this_count;
+    int64_t recv_time = 0;
+    SEQMAP_VALUE *seqmap_value;
+    unsigned short id;
+    unsigned short seq;
+    int ip_header_tos = -1;
+    int ip_header_ttl = -1;
+    // ICMP Timestamp
+    uint32_t ip_header_otime_ms = 0x80000000U;
+    uint32_t ip_header_rtime_ms = 0x80000000U;
+    uint32_t ip_header_ttime_ms = 0x80000000U;
+
+    /* Receive packet */
+    result = receive_packet(wait_time, /* max. wait time, in ns */
+        &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;
+    }
+
+    update_current_time();
+    if (recv_time == 0)
+        recv_time = current_time_ns;
+
+    /* Process ICMP packet and retrieve id/seq */
+    if (response_addr.ss_family == AF_INET) {
+        int ip_hlen = decode_icmp_ipv4(
+            (struct sockaddr *)&response_addr,
+            sizeof(response_addr),
+            buffer,
+            sizeof(buffer),
+            &id,
+            &seq,
+            &ip_header_tos,
+            &ip_header_ttl,
+            &ip_header_otime_ms,
+            &ip_header_rtime_ms,
+            &ip_header_ttime_ms);
+        if (ip_hlen < 0) {
+            return 1;
+        }
+        if (id != ident4) {
+            return 1; /* packet received, but not the one we are looking for! */
+        }
+        if (!using_sock_dgram4) {
+            /* do not include IP header in returned size, to be consistent with ping(8) and also
+             * with fping with IPv6 hosts */
+            result -= ip_hlen;
+        }
+    }
+#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;
+        }
+        if (id != ident6) {
+            return 1; /* packet received, but not the one we are looking for! */
+        }
+    }
+#endif
+    else {
+        return 1;
+    }
+
+    seqmap_value = seqmap_fetch(seq, current_time_ns);
+    if (seqmap_value == NULL) {
+        return 1;
+    }
+
+    /* find corresponding host_entry */
+    n = seqmap_value->host_nr;
+    h = table[n];
+    this_count = seqmap_value->ping_count;
+    this_reply = recv_time - seqmap_value->ping_ts;
+
+    /* update stats that include invalid replies */
+    h->num_recv_total++;
+    num_pingreceived++;
+
+    dbg_printf("received [%d] from %s\n", this_count, h->host);
+
+    /* optionally require reply source equal to target address */
+    if (check_source_flag && addr_cmp((struct sockaddr *)&response_addr, (struct sockaddr *)&h->saddr)) {
+        dbg_printf("discarding reply from wrong source address\n");
+        return 1;
+    }
+
+    /* discard duplicates */
+    if (!loop_flag && h->resp_times[this_count] >= 0) {
+        if (!per_recv_flag) {
+            fprintf(stderr, "%s : duplicate for [%d], %d bytes, %s ms",
+                h->host, this_count, result, sprint_tm(this_reply));
+
+            if (addr_cmp((struct sockaddr *)&response_addr, (struct sockaddr *)&h->saddr)) {
+                char buf[INET6_ADDRSTRLEN];
+                getnameinfo((struct sockaddr *)&response_addr, sizeof(response_addr), buf, INET6_ADDRSTRLEN, NULL, 0, NI_NUMERICHOST);
+                fprintf(stderr, " [<- %s]", buf);
+            }
+            fprintf(stderr, "\n");
+        }
+        return 1;
+    }
+
+    /* discard reply if delay is larger than timeout
+     * (see also: github #32) */
+    if (this_reply > h->timeout) {
+        return 1;
+    }
+
+    /* update stats */
+    stats_add(h, this_count, 1, this_reply);
+    // TODO: move to stats_add?
+    if (!max_reply || this_reply > max_reply)
+        max_reply = this_reply;
+    if (!min_reply || this_reply < min_reply)
+        min_reply = this_reply;
+    sum_replies += this_reply;
+    total_replies++;
+
+    /* initialize timeout to initial timeout (without backoff) */
+    h->timeout = timeout;
+
+    /* remove timeout event */
+    struct event *timeout_event = host_get_timeout_event(h, this_count);
+    if (timeout_event) {
+        ev_remove(&event_queue_timeout, timeout_event);
+    }
+
+    /* print "is alive" */
+    if (h->num_recv == 1) {
+        num_alive++;
+        if (fast_reachable && num_alive >= min_reachable)
+                finish_requested = 1;
+
+        if (verbose_flag || alive_flag) {
+            printf("%s", h->host);
+
+            if (verbose_flag)
+                printf(" is alive");
+        }
+    }
+
+    /* print received ping (unless --quiet) */
+    if (per_recv_flag) {
+        if (timestamp_flag) {
+            print_timestamp_format(recv_time, timestamp_format_flag);
+        }
+        avg = h->total_time / h->num_recv;
+        printf("%-*s : [%d], %d bytes, %s ms",
+            max_hostname_len, h->host, this_count, result, sprint_tm(this_reply));
+        printf(" (%s avg, ", sprint_tm(avg));
+
+        if (h->num_recv <= h->num_sent) {
+            printf("%d%% loss)",
+                ((h->num_sent - h->num_recv) * 100) / h->num_sent);
+        }
+        else {
+            printf("%d%% return)",
+                (h->num_recv_total * 100) / h->num_sent);
+        }
+    }
+
+    if (verbose_flag || alive_flag || per_recv_flag) {
+
+        if (addr_cmp((struct sockaddr *)&response_addr, (struct sockaddr *)&h->saddr)) {
+            char buf[INET6_ADDRSTRLEN];
+            getnameinfo((struct sockaddr *)&response_addr, sizeof(response_addr), buf, INET6_ADDRSTRLEN, NULL, 0, NI_NUMERICHOST);
+            fprintf(stderr, " [<- %s]", buf);
+        }
+
+        if (icmp_request_typ == 13) {
+            printf("%s timestamps: Originate=%u Receive=%u Transmit=%u Localreceive=%u",
+                   alive_flag ? "" : ",",
+                   ip_header_otime_ms, ip_header_rtime_ms, ip_header_ttime_ms,
+                   ms_since_midnight_utc(recv_time));
+        }
+
+        if(print_tos_flag) {
+            if(ip_header_tos != -1) {
+                printf(" (TOS %d)", ip_header_tos);
+            }
+            else {
+                printf(" (TOS unknown)");
+            }
+        }
+
+        if (print_ttl_flag) {
+          if(ip_header_ttl != -1) {
+              printf(" (TTL %d)", ip_header_ttl);
+          }
+          else {
+              printf(" (TTL unknown)");
+          }
+        }
+
+        if (elapsed_flag && !per_recv_flag)
+                printf(" (%s ms)", sprint_tm(this_reply));
+
+        printf("\n");
+    }
+
+    return 1;
+}
+
+/************************************************************
+
+  Function: add_name
+
+*************************************************************
+
+  Inputs:  char* name
+
+  Description:
+
+  process input name for addition to target list
+  name can turn into multiple targets via multiple interfaces (-m)
+  or via NIS groups
+
+************************************************************/
+
+void add_name(char *name)
+{
+    struct addrinfo *res0, *res, hints;
+    int ret_ga;
+    char *printname;
+    char namebuf[256];
+    char addrbuf[256];
+
+    /* getaddrinfo */
+    memset(&hints, 0, sizeof(struct addrinfo));
+    hints.ai_flags = AI_UNUSABLE;
+    hints.ai_socktype = SOCK_RAW;
+    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_socktype = SOCK_STREAM;
+        hints.ai_protocol = 0;
+    }
+    ret_ga = getaddrinfo(name, NULL, &hints, &res0);
+    if (ret_ga) {
+        if (!quiet_flag)
+            print_warning("%s: %s\n", name, gai_strerror(ret_ga));
+        num_noaddress++;
+        return;
+    }
+
+    /* NOTE: we could/should loop with res on all addresses like this:
+     * for (res = res0; res; res = res->ai_next) {
+     * We don't do it yet, however, because is is an incompatible change
+     * (need to implement a separate option for this)
+     */
+    for (res = res0; res; res = res->ai_next) {
+        /* name_flag: addr -> name lookup requested) */
+        if (name_flag || rdns_flag) {
+            int do_rdns = rdns_flag ? 1 : 0;
+            if (name_flag) {
+                /* Was it a numerical address? Only then do a rdns-query */
+                struct addrinfo *nres;
+                hints.ai_flags = AI_NUMERICHOST;
+                if (getaddrinfo(name, NULL, &hints, &nres) == 0) {
+                    do_rdns = 1;
+                    freeaddrinfo(nres);
+                }
+            }
+
+            if (do_rdns && getnameinfo(res->ai_addr, res->ai_addrlen, namebuf, sizeof(namebuf) / sizeof(char), NULL, 0, 0) == 0) {
+                printname = namebuf;
+            }
+            else {
+                printname = name;
+            }
+        }
+        else {
+            printname = name;
+        }
+
+        /* 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: can't forward-lookup address (%s)\n", name, gai_strerror(ret));
+                }
+                continue;
+            }
+
+            if (name_flag || rdns_flag) {
+                char nameaddrbuf[512 + 3];
+                snprintf(nameaddrbuf, sizeof(nameaddrbuf) / sizeof(char), "%s (%s)", printname, addrbuf);
+                add_addr(name, nameaddrbuf, res->ai_addr, res->ai_addrlen);
+            }
+            else {
+                add_addr(name, addrbuf, res->ai_addr, res->ai_addrlen);
+            }
+        }
+        else {
+            add_addr(name, printname, res->ai_addr, res->ai_addrlen);
+        }
+
+        if (!multif_flag) {
+            break;
+        }
+    }
+
+    freeaddrinfo(res0);
+}
+
+/************************************************************
+
+  Function: add_addr
+
+*************************************************************
+
+  Description:
+
+  add single address to list of hosts to be pinged
+
+************************************************************/
+
+void add_addr(char *name, char *host, struct sockaddr *ipaddr, socklen_t ipaddr_len)
+{
+    HOST_ENTRY *p;
+    int n;
+    int64_t *i;
+
+    p = (HOST_ENTRY *)calloc(1, sizeof(HOST_ENTRY));
+    if (!p)
+        crash_and_burn("can't allocate HOST_ENTRY");
+
+    p->name = strdup(name);
+    p->host = strdup(host);
+    memcpy(&p->saddr, ipaddr, ipaddr_len);
+    p->saddr_len = ipaddr_len;
+    p->timeout = timeout;
+    p->min_reply = 0;
+
+    if (netdata_flag) {
+        char *s = p->name;
+        while (*s) {
+            if (!isalnum(*s))
+                *s = '_';
+            s++;
+        }
+    }
+
+    if (strlen(p->host) > max_hostname_len)
+        max_hostname_len = strlen(p->host);
+
+    /* array for response time results */
+    if (!loop_flag) {
+        i = (int64_t *)malloc(trials * sizeof(int64_t));
+        if (!i)
+            crash_and_burn("can't allocate resp_times array");
+
+        for (n = 1; n < trials; n++)
+            i[n] = RESP_UNUSED;
+
+        p->resp_times = i;
+    }
+
+    /* allocate event storage */
+    p->event_storage_ping = (struct event *)calloc(event_storage_count, sizeof(struct event));
+    if (!p->event_storage_ping) {
+        errno_crash_and_burn("can't allocate event_storage_ping");
+    }
+    p->event_storage_timeout = (struct event *)calloc(event_storage_count, sizeof(struct event));
+    if (!p->event_storage_timeout) {
+        errno_crash_and_burn("can't allocate event_storage_timeout");
+    }
+
+    /* schedule first ping */
+    host_add_ping_event(p, 0, current_time_ns);
+
+    num_hosts++;
+}
+
+/************************************************************
+
+  Function: crash_and_burn
+
+*************************************************************
+
+  Inputs:  char* message
+
+  Description:
+
+************************************************************/
+
+void crash_and_burn(char *message)
+{
+    fprintf(stderr, "%s: %s\n", prog, message);
+    exit(4);
+}
+
+/************************************************************
+
+  Function: errno_crash_and_burn
+
+*************************************************************
+
+  Inputs:  char* message
+
+  Description:
+
+************************************************************/
+
+void errno_crash_and_burn(char *message)
+{
+    fprintf(stderr, "%s: %s : %s\n", prog, message, strerror(errno));
+    exit(4);
+}
+
+/************************************************************
+
+  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: sprint_tm
+
+*************************************************************
+
+  render nanosecond int64_t value into milliseconds string with three digits of
+  precision.
+
+************************************************************/
+
+const char *sprint_tm(int64_t ns)
+{
+    static char buf[10];
+    double t = (double)ns / 1e6;
+
+    if (t < 0.0) {
+        /* negative (unexpected) */
+        sprintf(buf, "%.2g", t);
+    }
+    else if (t < 1.0) {
+        /* <= 0.99 ms */
+        sprintf(buf, "%.3f", t);
+    }
+    else if (t < 10.0) {
+        /* 1.00 - 9.99 ms */
+        sprintf(buf, "%.2f", t);
+    }
+    else if (t < 100.0) {
+        /* 10.0 - 99.9 ms */
+        sprintf(buf, "%.1f", t);
+    }
+    else if (t < 1000000.0) {
+        /* 100 - 1'000'000 ms */
+        sprintf(buf, "%.0f", t);
+    }
+    else {
+        sprintf(buf, "%.3e", t);
+    }
+
+    return (buf);
+}
+
+/************************************************************
+
+  Function: addr_cmp
+
+*************************************************************/
+int addr_cmp(struct sockaddr *a, struct sockaddr *b)
+{
+    if (a->sa_family != b->sa_family) {
+        return a->sa_family - b->sa_family;
+    }
+    else {
+        if (a->sa_family == AF_INET) {
+            return ((struct sockaddr_in *)a)->sin_addr.s_addr - ((struct sockaddr_in *)b)->sin_addr.s_addr;
+        }
+        else if (a->sa_family == AF_INET6) {
+            return memcmp(&((struct sockaddr_in6 *)a)->sin6_addr,
+                &((struct sockaddr_in6 *)b)->sin6_addr,
+                sizeof(((struct sockaddr_in6 *)a)->sin6_addr));
+        }
+    }
+
+    return 0;
+}
+
+void host_add_ping_event(HOST_ENTRY *h, int index, int64_t ev_time)
+{
+    struct event *event = &h->event_storage_ping[index % event_storage_count];
+    event->host = h;
+    event->ping_index = index;
+    event->ev_time = ev_time;
+    ev_enqueue(&event_queue_ping, event);
+
+    dbg_printf("%s [%d]: add ping event in %.0f ms\n",
+        event->host->host, index, (ev_time - current_time_ns) / 1e6);
+}
+
+void host_add_timeout_event(HOST_ENTRY *h, int index, int64_t ev_time)
+{
+    struct event *event = &h->event_storage_timeout[index % event_storage_count];
+    event->host = h;
+    event->ping_index = index;
+    event->ev_time = ev_time;
+    ev_enqueue(&event_queue_timeout, event);
+
+    dbg_printf("%s [%d]: add timeout event in %.0f ms\n",
+        event->host->host, index, (ev_time - current_time_ns) / 1e6);
+}
+
+struct event *host_get_timeout_event(HOST_ENTRY *h, int index)
+{
+    return &h->event_storage_timeout[index % event_storage_count];
+}
+
+/************************************************************
+
+  Function: ev_enqueue
+
+  Enqueue an event
+
+  The queue is sorted by event->ev_time, so that queue->first always points to
+  the earliest event.
+
+  We start scanning the queue from the tail, because we assume
+  that new events mostly get inserted with a event time higher
+  than the others.
+
+*************************************************************/
+void ev_enqueue(struct event_queue *queue, struct event *event)
+{
+    struct event *i;
+    struct event *i_prev;
+
+    /* Empty list */
+    if (queue->last == NULL) {
+        event->ev_next = NULL;
+        event->ev_prev = NULL;
+        queue->first = event;
+        queue->last = event;
+        return;
+    }
+
+    /* Insert on tail? */
+    if (event->ev_time - queue->last->ev_time >= 0) {
+        event->ev_next = NULL;
+        event->ev_prev = queue->last;
+        queue->last->ev_next = event;
+        queue->last = event;
+        return;
+    }
+
+    /* Find insertion point */
+    i = queue->last;
+    while (1) {
+        i_prev = i->ev_prev;
+        if (i_prev == NULL || event->ev_time - i_prev->ev_time >= 0) {
+            event->ev_prev = i_prev;
+            event->ev_next = i;
+            i->ev_prev = event;
+            if (i_prev != NULL) {
+                i_prev->ev_next = event;
+            }
+            else {
+                queue->first = event;
+            }
+            return;
+        }
+        i = i_prev;
+    }
+}
+
+/************************************************************
+
+  Function: ev_dequeue
+
+*************************************************************/
+struct event *ev_dequeue(struct event_queue *queue)
+{
+    struct event *dequeued;
+
+    if (queue->first == NULL) {
+        return NULL;
+    }
+    dequeued = queue->first;
+    ev_remove(queue, dequeued);
+
+    return dequeued;
+}
+
+/************************************************************
+
+  Function: ev_remove
+
+*************************************************************/
+void ev_remove(struct event_queue *queue, struct event *event)
+{
+    if (queue->first == event) {
+        queue->first = event->ev_next;
+    }
+    if (queue->last == event) {
+        queue->last = event->ev_prev;
+    }
+    if (event->ev_prev) {
+        event->ev_prev->ev_next = event->ev_next;
+    }
+    if (event->ev_next) {
+        event->ev_next->ev_prev = event->ev_prev;
+    }
+    event->ev_prev = NULL;
+    event->ev_next = NULL;
+}
+
+/************************************************************
+
+  Function: print_human_readable_time from current_time_ns
+
+*************************************************************/
+void print_timestamp_format(int64_t current_time_ns, int timestamp_format)
+{
+    char time_buffer[100];
+    time_t current_time_s;
+    struct tm *local_time;
+
+    current_time_s = current_time_ns / 1000000000;
+    local_time = localtime(&current_time_s);
+    switch(timestamp_format) {
+        case 1:
+            // timestamp-format ctime
+            strftime(time_buffer, sizeof(time_buffer), "%c", local_time);
+            printf("[%s] ", time_buffer);
+            break;
+        case 2:
+            // timestamp-format iso
+            strftime(time_buffer, sizeof(time_buffer), "%Y-%m-%dT%T%z", local_time);
+            printf("[%s] ", time_buffer);
+            break;
+        case 3:
+            // timestamp-format rfc3339
+            strftime(time_buffer, sizeof(time_buffer), "%Y-%m-%d %H:%M:%S", local_time);
+            printf("[%s] ", time_buffer);
+            break;
+        default:
+            printf("[%.5f] ", (double)current_time_ns / 1e9);
+    }
+}
+
+/************************************************************
+
+  Function: ms_since_midnight_utc
+
+*************************************************************
+
+  Input: int64_t: current UTC time in ns
+
+  Output: uint32_t: current time in ms since midnight UTC
+
+  Description:
+
+  Return ICMP Timestamp value corresponding to the given time value.
+  The given time value must be in UTC.
+
+*************************************************************/
+static uint32_t ms_since_midnight_utc(int64_t time_val)
+{
+    return (uint32_t)((time_val / 1000000) % (24 * 60 * 60 * 1000));
+}
+
+/************************************************************
+
+  Function: usage
+
+*************************************************************
+
+  Inputs:  int: 0 if output on request, 1 if output because of wrong argument
+
+  Description:
+
+************************************************************/
+
+void usage(int is_error)
+{
+    FILE *out = is_error ? stderr : stdout;
+    fprintf(out, "Usage: %s [options] [targets...]\n", prog);
+    fprintf(out, "\n");
+    fprintf(out, "Probing options:\n");
+    fprintf(out, "   -4, --ipv4         only ping IPv4 addresses\n");
+    fprintf(out, "   -6, --ipv6         only ping IPv6 addresses\n");
+    fprintf(out, "   -b, --size=BYTES   amount of ping data to send, in bytes (default: %d)\n", DEFAULT_PING_DATA_SIZE);
+    fprintf(out, "   -B, --backoff=N    set exponential backoff factor to N (default: 1.5)\n");
+    fprintf(out, "   -c, --count=N      count mode: send N pings to each target and report stats\n");
+    fprintf(out, "   -f, --file=FILE    read list of targets from a file ( - means stdin)\n");
+    fprintf(out, "   -g, --generate     generate target list (only if no -f specified),\n");
+    fprintf(out, "                      limited to at most %d targets\n", MAX_GENERATE);
+    fprintf(out, "                      (give start and end IP in the target list, or a CIDR address)\n");
+    fprintf(out, "                      (ex. %s -g 192.168.1.0 192.168.1.255 or %s -g 192.168.1.0/24)\n", prog, prog);
+    fprintf(out, "   -H, --ttl=N        set the IP TTL value (Time To Live hops)\n");
+    fprintf(out, "   -i, --interval=MSEC  interval between sending ping packets (default: %.0f ms)\n", interval / 1e6);
+#ifdef SO_BINDTODEVICE
+    fprintf(out, "   -I, --iface=IFACE  bind to a particular interface\n");
+#endif
+#ifdef SO_MARK
+    fprintf(out, "   -k, --fwmark=FWMARK set the routing mark\n");
+#endif
+    fprintf(out, "   -l, --loop         loop mode: send pings forever\n");
+    fprintf(out, "   -m, --all          use all IPs of provided hostnames (e.g. IPv4 and IPv6), use with -A\n");
+    fprintf(out, "   -M, --dontfrag     set the Don't Fragment flag\n");
+    fprintf(out, "   -O, --tos=N        set the type of service (tos) flag on the ICMP packets\n");
+    fprintf(out, "   -p, --period=MSEC  interval between ping packets to one target (in ms)\n");
+    fprintf(out, "                      (in loop and count modes, default: %.0f ms)\n", perhost_interval / 1e6);
+    fprintf(out, "   -r, --retry=N      number of retries (default: %d)\n", DEFAULT_RETRY);
+    fprintf(out, "   -R, --random       random packet data (to foil link data compression)\n");
+    fprintf(out, "   -S, --src=IP       set source address\n");
+    fprintf(out, "   -t, --timeout=MSEC individual target initial timeout (default: %.0f ms,\n", timeout / 1e6);
+    fprintf(out, "                      except with -l/-c/-C, where it's the -p period up to 2000 ms)\n");
+    fprintf(out, "       --check-source discard replies not from target address\n");
+    fprintf(out, "       --icmp-timestamp use ICMP Timestamp instead of ICMP Echo\n");
+    fprintf(out, "\n");
+    fprintf(out, "Output options:\n");
+    fprintf(out, "   -a, --alive        show targets that are alive\n");
+    fprintf(out, "   -A, --addr         show targets by address\n");
+    fprintf(out, "   -C, --vcount=N     same as -c, report results (not stats) in verbose format\n");
+    fprintf(out, "   -d, --rdns         show targets by name (force reverse-DNS lookup)\n");
+    fprintf(out, "   -D, --timestamp    print timestamp before each output line\n");
+    fprintf(out, "       --timestamp-format=FORMAT  show timestamp in the given format (-D required): ctime|iso|rfc3339\n");
+    fprintf(out, "   -e, --elapsed      show elapsed time on return packets\n");
+    fprintf(out, "   -n, --name         show targets by name (reverse-DNS lookup for target IPs)\n");
+    fprintf(out, "   -N, --netdata      output compatible for netdata (-l -Q are required)\n");
+    fprintf(out, "   -o, --outage       show the accumulated outage time (lost packets * packet interval)\n");
+    fprintf(out, "   -q, --quiet        quiet (don't show per-target/per-ping results)\n");
+    fprintf(out, "   -Q, --squiet=SECS[,cumulative]  same as -q, but add interval summary every SECS seconds,\n");
+    fprintf(out, "                                   with 'cumulative', print stats since beginning\n");
+    fprintf(out, "   -s, --stats        print final stats\n");
+    fprintf(out, "   -u, --unreach      show targets that are unreachable\n");
+    fprintf(out, "   -v, --version      show version\n");
+    fprintf(out, "   -x, --reachable=N  shows if >=N hosts are reachable or not\n");
+    fprintf(out, "   -X, --fast-reachable=N exits true immediately when N hosts are found\n");
+    fprintf(out, "       --print-tos    show received TOS value\n");
+    fprintf(out, "       --print-ttl    show IP TTL value\n");
+    exit(is_error);
+}
diff --git a/ci/tmp.4rIIEYCP9c/fping-5.3/src/fping.h b/ci/tmp.4rIIEYCP9c/fping-5.3/src/fping.h
new file mode 100644 (file)
index 0000000..f50710b
--- /dev/null
@@ -0,0 +1,39 @@
+#ifndef _FPING_H
+#define _FPING_H
+
+#define __APPLE_USE_RFC_3542 1
+
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <netinet/in.h>
+
+/* this requires variadic macros, part of C99 */
+#if (defined(DEBUG) || defined(_DEBUG))
+extern int64_t current_time_ns;
+extern int trace_flag;
+#define dbg_printf(fmt, ...) do { if (trace_flag) { fprintf(stderr, "[%10.5f] ", (double)(current_time_ns / 1000)/1000000); fprintf(stderr, fmt, __VA_ARGS__); } } while (0)
+            
+#else
+#define dbg_printf(fmt, ...)
+#endif
+
+
+/* fping.c */
+void crash_and_burn( char *message );
+void errno_crash_and_burn( char *message );
+int in_cksum( unsigned short *p, int n );
+extern int random_data_flag;
+
+/* socket.c */
+int  open_ping_socket_ipv4(int *socktype);
+void init_ping_buffer_ipv4(size_t ping_data_size);
+void socket_set_src_addr_ipv4(int s, struct in_addr *src_addr, int *ident);
+int  socket_sendto_ping_ipv4(int s, struct sockaddr *saddr, socklen_t saddr_len, uint16_t icmp_seq, uint16_t icmp_id, uint8_t icmp_proto);
+#ifdef IPV6
+int  open_ping_socket_ipv6(int *socktype);
+void init_ping_buffer_ipv6(size_t ping_data_size);
+void socket_set_src_addr_ipv6(int s, struct in6_addr *src_addr, int *ident);
+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/ci/tmp.4rIIEYCP9c/fping-5.3/src/options.h b/ci/tmp.4rIIEYCP9c/fping-5.3/src/options.h
new file mode 100644 (file)
index 0000000..229975c
--- /dev/null
@@ -0,0 +1,52 @@
+
+/* 
+ *  Interval is the minimum amount of time between sending a ping packet to 
+ *  any host.
+ * 
+ *  Perhost_interval is the minimum amount of time between sending a ping 
+ *  packet to a particular responding host (when count is > 1)
+ * 
+ *  Timeout  is the initial amount of time between sending a ping packet to
+ *  a particular non-responding host.
+ * 
+ *  Retry is the number of ping packets to send to a non-responding host
+ *  before giving up (in is-it-alive mode).
+ * 
+ *  Backoff factor is how much longer to wait on successive retries.
+ * 
+ * 
+ */
+
+/* constants */
+
+#ifndef DEFAULT_INTERVAL
+#define DEFAULT_INTERVAL 10        /* default time between packets (msec) */
+#endif
+
+#ifndef DEFAULT_PERHOST_INTERVAL      /* default time between packets */
+#define DEFAULT_PERHOST_INTERVAL 1000 /* to a particular destination  */
+#endif                                /* in counting/looping mode     */
+
+#ifndef DEFAULT_TIMEOUT
+#define DEFAULT_TIMEOUT 500       /* individual host timeouts */
+#define AUTOTUNE_TIMEOUT_MAX  2000
+#endif
+
+
+#ifndef DEFAULT_RETRY 
+#define DEFAULT_RETRY 3            /* number of times to retry a host */
+#endif
+
+#ifndef DEFAULT_SELECT_TIME
+#define DEFAULT_SELECT_TIME 10     /* default time to wait during select() */
+#endif
+
+#ifndef DEFAULT_BACKOFF_FACTOR
+#define DEFAULT_BACKOFF_FACTOR 1.5 /* exponential timeout factor */
+#endif
+#define MIN_BACKOFF_FACTOR     1.0 /* exponential timeout factor */
+#define MAX_BACKOFF_FACTOR     5.0 /* exponential timeout factor */
+
+#ifndef DNS_TIMEOUT
+#define DNS_TIMEOUT 1000         /* time in micro_sec for dns retry */
+#endif
diff --git a/ci/tmp.4rIIEYCP9c/fping-5.3/src/optparse.c b/ci/tmp.4rIIEYCP9c/fping-5.3/src/optparse.c
new file mode 100644 (file)
index 0000000..63a9f40
--- /dev/null
@@ -0,0 +1,266 @@
+#include "optparse.h"
+
+#define MSG_INVALID "invalid option"
+#define MSG_MISSING "option requires an argument"
+#define MSG_TOOMANY "option takes no arguments"
+
+static int
+opterror(struct optparse *options, const char *message, const char *data)
+{
+    unsigned p = 0;
+    while (*message)
+        options->errmsg[p++] = *message++;
+    const char *sep = " -- '";
+    while (*sep)
+        options->errmsg[p++] = *sep++;
+    while (p < sizeof(options->errmsg) - 2 && *data)
+        options->errmsg[p++] = *data++;
+    options->errmsg[p++] = '\'';
+    options->errmsg[p++] = '\0';
+    return '?';
+}
+
+void optparse_init(struct optparse *options, char **argv)
+{
+    options->argv = argv;
+    options->permute = 1;
+    options->optind = 1;
+    options->subopt = 0;
+    options->optarg = 0;
+    options->errmsg[0] = '\0';
+}
+
+static inline int
+is_dashdash(const char *arg)
+{
+    return arg != 0 && arg[0] == '-' && arg[1] == '-' && arg[2] == '\0';
+}
+
+static inline int
+is_shortopt(const char *arg)
+{
+    return arg != 0 && arg[0] == '-' && arg[1] != '-' && arg[1] != '\0';
+}
+
+static inline int
+is_longopt(const char *arg)
+{
+    return arg != 0 && arg[0] == '-' && arg[1] == '-' && arg[2] != '\0';
+}
+
+static void
+permute(struct optparse *options, int index)
+{
+    char *nonoption = options->argv[index];
+    for (int i = index; i < options->optind - 1; i++)
+        options->argv[i] = options->argv[i + 1];
+    options->argv[options->optind - 1] = nonoption;
+}
+
+static int
+argtype(const char *optstring, char c)
+{
+    if (c == ':')
+        return -1;
+    for (; *optstring && c != *optstring; optstring++);
+    if (!*optstring)
+        return -1;
+    int count = OPTPARSE_NONE;
+    if (optstring[1] == ':')
+        count += optstring[2] == ':' ? 2 : 1;
+    return count;
+}
+
+int optparse(struct optparse *options, const char *optstring)
+{
+    options->errmsg[0] = '\0';
+    options->optopt = 0;
+    options->optarg = 0;
+    char *option = options->argv[options->optind];
+    if (option == 0) {
+        return -1;
+    } else if (is_dashdash(option)) {
+        options->optind++; /* consume "--" */
+        return -1;
+    } else if (!is_shortopt(option)) {
+        if (options->permute) {
+            int index = options->optind;
+            options->optind++;
+            int r = optparse(options, optstring);
+            permute(options, index);
+            options->optind--;
+            return r;
+        } else {
+            return -1;
+        }
+    }
+    option += options->subopt + 1;
+    options->optopt = option[0];
+    int type = argtype(optstring, option[0]);
+    char *next = options->argv[options->optind + 1];
+    switch (type) {
+    case -1: {
+        options->optind++;
+        char str[2] = {option[0]};
+        return opterror(options, MSG_INVALID, str);
+    }
+    case OPTPARSE_NONE:
+        if (option[1]) {
+            options->subopt++;
+        } else {
+            options->subopt = 0;
+            options->optind++;
+        }
+        return option[0];
+    case OPTPARSE_REQUIRED:
+        options->subopt = 0;
+        options->optind++;
+        if (option[1]) {
+            options->optarg = option + 1;
+        } else if (next != 0) {
+            options->optarg = next;
+            options->optind++;
+        } else {
+            options->optarg = 0;
+            char str[2] = {option[0]};
+            return opterror(options, MSG_MISSING, str);
+        }
+        return option[0];
+    case OPTPARSE_OPTIONAL:
+        options->subopt = 0;
+        options->optind++;
+        if (option[1])
+            options->optarg = option + 1;
+        else
+            options->optarg = 0;
+        return option[0];
+    }
+    return 0;
+}
+
+char *optparse_arg(struct optparse *options)
+{
+    options->subopt = 0;
+    char *option = options->argv[options->optind];
+    if (option != 0)
+        options->optind++;
+    return option;
+}
+
+static inline int
+longopts_end(const struct optparse_long *longopts, int i)
+{
+    return !longopts[i].longname && !longopts[i].shortname;
+}
+
+static void
+optstring_from_long(const struct optparse_long *longopts, char *optstring)
+{
+    char *p = optstring;
+    for (int i = 0; !longopts_end(longopts, i); i++) {
+        if (longopts[i].shortname) {
+            *p++ = longopts[i].shortname;
+            for (int a = 0; a < (int)longopts[i].argtype; a++)
+                *p++ = ':';
+        }
+    }
+    *p = '\0';
+}
+
+/* Unlike strcmp(), handles options containing "=". */
+static int
+longopts_match(const char *longname, const char *option)
+{
+    if (longname == 0)
+        return 0;
+    const char *a = option, *n = longname;
+    for (; *a && *n && *a != '='; a++, n++)
+        if (*a != *n)
+            return 0;
+    return *n == '\0' && (*a == '\0' || *a == '=');
+}
+
+/* Return the part after "=", or NULL. */
+static char *
+longopts_arg(char *option)
+{
+    for (; *option && *option != '='; option++);
+    if (*option == '=')
+        return option + 1;
+    else
+        return 0;
+}
+
+static int
+long_fallback(struct optparse *options,
+              const struct optparse_long *longopts,
+              int *longindex)
+{
+    char optstring[96 * 3 + 1]; /* 96 ASCII printable characters */
+    optstring_from_long(longopts, optstring);
+    int result = optparse(options, optstring);
+    if (longindex != 0) {
+        *longindex = -1;
+        if (result != -1)
+            for (int i = 0; !longopts_end(longopts, i); i++)
+                if (longopts[i].shortname == options->optopt)
+                    *longindex = i;
+    }
+    return result;
+}
+
+int
+optparse_long(struct optparse *options,
+              const struct optparse_long *longopts,
+              int *longindex)
+{
+    char *option = options->argv[options->optind];
+    if (option == 0) {
+        return -1;
+    } else if (is_dashdash(option)) {
+        options->optind++; /* consume "--" */
+        return -1;
+    } else if (is_shortopt(option)) {
+        return long_fallback(options, longopts, longindex);
+    } else if (!is_longopt(option)) {
+        if (options->permute) {
+            int index = options->optind;
+            options->optind++;
+            int r = optparse_long(options, longopts, longindex);
+            permute(options, index);
+            options->optind--;
+            return r;
+        } else {
+            return -1;
+        }
+    }
+
+    /* Parse as long option. */
+    options->errmsg[0] = '\0';
+    options->optopt = 0;
+    options->optlongname = 0;
+    options->optarg = 0;
+    option += 2; /* skip "--" */
+    options->optind++;
+    for (int i = 0; !longopts_end(longopts, i); i++) {
+        const char *name = longopts[i].longname;
+        if (longopts_match(name, option)) {
+            options->optlongname = option;
+            if (longindex)
+                *longindex = i;
+            options->optopt = longopts[i].shortname;
+            char *arg = longopts_arg(option);
+            if (longopts[i].argtype == OPTPARSE_NONE && arg != 0) {
+                return opterror(options, MSG_TOOMANY, name);
+            } if (arg != 0) {
+                options->optarg = arg;
+            } else if (longopts[i].argtype == OPTPARSE_REQUIRED) {
+                options->optarg = options->argv[options->optind++];
+                if (options->optarg == 0)
+                    return opterror(options, MSG_MISSING, name);
+            }
+            return options->optopt;
+        }
+    }
+    return opterror(options, MSG_INVALID, option);
+}
diff --git a/ci/tmp.4rIIEYCP9c/fping-5.3/src/optparse.h b/ci/tmp.4rIIEYCP9c/fping-5.3/src/optparse.h
new file mode 100644 (file)
index 0000000..7a555ed
--- /dev/null
@@ -0,0 +1,103 @@
+#ifndef OPTPARSE_H
+#define OPTPARSE_H
+
+/**
+ * Optparse -- portable, reentrant, embeddable, getopt-like option parser
+ *
+ * The POSIX getopt() option parser has three fatal flaws. These flaws
+ * are solved by Optparse.
+ *
+ * 1) Parser state is stored entirely in global variables, some of
+ * which are static and inaccessible. This means only one thread can
+ * use getopt(). It also means it's not possible to recursively parse
+ * nested sub-arguments while in the middle of argument parsing.
+ * Optparse fixes this by storing all state on a local struct.
+ *
+ * 2) The POSIX standard provides no way to properly reset the parser.
+ * This means for portable code that getopt() is only good for one
+ * run, over one argv with one optstring. It also means subcommand
+ * options cannot be processed with getopt(). Most implementations
+ * provide a method to reset the parser, but it's not portable.
+ * Optparse provides an optparse_arg() function for stepping over
+ * subcommands and continuing parsing of options with another
+ * optstring. The Optparse struct itself can be passed around to
+ * subcommand handlers for additional subcommand option parsing. A
+ * full reset can be achieved by with an additional optparse_init().
+ *
+ * 3) Error messages are printed to stderr. This can be disabled with
+ * opterr, but the messages themselves are still inaccessible.
+ * Optparse solves this by writing an error message in its errmsg
+ * field. The downside to Optparse is that this error message will
+ * always be in English rather than the current locale.
+ *
+ * Optparse should be familiar with anyone accustomed to getopt(), and
+ * it could be a nearly drop-in replacement. The optstring is the same
+ * and the fields have the same names as the getopt() global variables
+ * (optarg, optind, optopt).
+ *
+ * Optparse also supports GNU-style long options with optparse_long().
+ * The interface is slightly different and simpler than getopt_long().
+ *
+ * By default, argv is permuted as it is parsed, moving non-option
+ * arguments to the end. This can be disabled by setting the `permute`
+ * field to 0 after initialization.
+ */
+
+struct optparse {
+    char **argv;
+    int permute;
+    int optind;
+    int optopt;
+    char *optlongname;
+    char *optarg;
+    char errmsg[64];
+    int subopt;
+};
+
+enum optparse_argtype { OPTPARSE_NONE, OPTPARSE_REQUIRED, OPTPARSE_OPTIONAL };
+
+struct optparse_long {
+    const char *longname;
+    int shortname;
+    enum optparse_argtype argtype;
+};
+
+/**
+ * Initializes the parser state.
+ */
+void optparse_init(struct optparse *options, char **argv);
+
+/**
+ * Read the next option in the argv array.
+ * @param optstring a getopt()-formatted option string.
+ * @return the next option character, -1 for done, or '?' for error
+ *
+ * Just like getopt(), a character followed by no colons means no
+ * argument. One colon means the option has a required argument. Two
+ * colons means the option takes an optional argument.
+ */
+int optparse(struct optparse *options, const char *optstring);
+
+/**
+ * Handles GNU-style long options in addition to getopt() options.
+ * This works a lot like GNU's getopt_long(). The last option in
+ * longopts must be all zeros, marking the end of the array. The
+ * longindex argument may be NULL.
+ */
+int
+optparse_long(struct optparse *options,
+              const struct optparse_long *longopts,
+              int *longindex);
+
+/**
+ * Used for stepping over non-option arguments.
+ * @return the next non-option argument, or NULL for no more arguments
+ *
+ * Argument parsing can continue with optparse() after using this
+ * function. That would be used to parse the options for the
+ * subcommand returned by optparse_arg(). This function allows you to
+ * ignore the value of optind.
+ */
+char *optparse_arg(struct optparse *options);
+
+#endif
diff --git a/ci/tmp.4rIIEYCP9c/fping-5.3/src/seqmap.c b/ci/tmp.4rIIEYCP9c/fping-5.3/src/seqmap.c
new file mode 100644 (file)
index 0000000..31bf725
--- /dev/null
@@ -0,0 +1,124 @@
+/*
+ * 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 "config.h"
+#include "seqmap.h"
+#include "limits.h"
+#include "options.h"
+#include "fping.h"
+
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdlib.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_NS)
+ * - 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;
+
+#define SEQMAP_TIMEOUT_IN_NS INT64_C(10000000000)
+#define SEQMAP_UNASSIGNED_HOST_NR UINT_MAX
+
+void seqmap_init()
+{
+    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, int64_t timestamp)
+{
+    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 != 0 && timestamp - next_value->ping_ts < SEQMAP_TIMEOUT_IN_NS) {
+        fprintf(stderr, "fping error: not enough sequence numbers available! (expire_timeout=%" PRId64 ", host_nr=%d, ping_count=%d, seqmap_next_id=%d)\n",
+            SEQMAP_TIMEOUT_IN_NS, 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 = timestamp;
+
+    /* increase next id */
+    current_id = seqmap_next_id;
+    seqmap_next_id = (seqmap_next_id + 1) % SEQMAP_MAXSEQ;
+
+    dbg_printf("seqmap_add(host: %d, index: %d) -> %d\n", host_nr, ping_count, current_id);
+
+    return current_id;
+}
+
+SEQMAP_VALUE* seqmap_fetch(unsigned int id, int64_t now)
+{
+    SEQMAP_VALUE* value;
+
+    if (id >= SEQMAP_MAXSEQ) {
+        return NULL;
+    }
+
+    value = &seqmap_map[id];
+
+    /* verify that value is not expired */
+    if (now - value->ping_ts >= SEQMAP_TIMEOUT_IN_NS) {
+        dbg_printf("seqmap_fetch(%d) -> host: %d, index: %d -> DISCARDED %ld\n", id, value->host_nr, value->ping_count,
+                now - value->ping_ts);
+        return NULL;
+    }
+
+    dbg_printf("seqmap_fetch(%d) -> host: %d, index: %d\n", id, value->host_nr, value->ping_count);
+
+    return value;
+}
diff --git a/ci/tmp.4rIIEYCP9c/fping-5.3/src/seqmap.h b/ci/tmp.4rIIEYCP9c/fping-5.3/src/seqmap.h
new file mode 100644 (file)
index 0000000..a1780b0
--- /dev/null
@@ -0,0 +1,21 @@
+#ifndef SEQMAP_H
+#define SEQMAP_H
+
+#include <sys/time.h>
+#include <stdint.h>
+
+typedef struct seqmap_value
+{
+    unsigned int    host_nr;
+    unsigned int    ping_count;
+    int64_t         ping_ts;
+
+} SEQMAP_VALUE;
+
+#define SEQMAP_MAXSEQ 65535
+
+void seqmap_init();
+unsigned int seqmap_add(unsigned int host_nr, unsigned int ping_count, int64_t now);
+SEQMAP_VALUE *seqmap_fetch(unsigned int id, int64_t now);
+
+#endif
diff --git a/ci/tmp.4rIIEYCP9c/fping-5.3/src/socket4.c b/ci/tmp.4rIIEYCP9c/fping-5.3/src/socket4.c
new file mode 100644 (file)
index 0000000..c408c6d
--- /dev/null
@@ -0,0 +1,166 @@
+/*
+ * 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"
+
+#include <fcntl.h>
+#include <netdb.h>
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+#include <netinet/ip_icmp.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/socket.h>
+#include <time.h>
+
+char* ping_buffer_ipv4 = 0;
+size_t ping_pkt_size_ipv4;
+
+int open_ping_socket_ipv4(int *socktype)
+{
+    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) */
+    *socktype = SOCK_RAW;
+    s = socket(AF_INET, *socktype, proto->p_proto);
+    if (s < 0) {
+        /* try non-privileged icmp (works on Mac OSX without privileges, for example) */
+        *socktype = SOCK_DGRAM;
+        s = socket(AF_INET, *socktype, proto->p_proto);
+        if (s < 0) {
+            return -1;
+        }
+    }
+
+    /* Make sure that we use non-blocking IO */
+    {
+        int flags;
+
+        if ((flags = fcntl(s, F_GETFL, 0)) < 0)
+            perror("fcntl");
+
+        if (fcntl(s, F_SETFL, flags | O_NONBLOCK) < 0)
+            perror("fcntl");
+    }
+
+    return s;
+}
+
+void init_ping_buffer_ipv4(size_t ping_data_size)
+{
+    /* allocate ping buffer */
+    ping_pkt_size_ipv4 = ping_data_size + ICMP_MINLEN;
+    ping_buffer_ipv4 = (char*)calloc(1, ping_pkt_size_ipv4);
+    if (!ping_buffer_ipv4)
+        crash_and_burn("can't malloc ping packet");
+}
+
+void socket_set_src_addr_ipv4(int s, struct in_addr* src_addr, int *ident)
+{
+    struct sockaddr_in sa;
+    socklen_t len = sizeof(sa);
+
+    memset(&sa, 0, len);
+    sa.sin_family = AF_INET;
+    sa.sin_addr = *src_addr;
+    if (bind(s, (struct sockaddr*)&sa, len) < 0)
+        errno_crash_and_burn("cannot bind source address");
+
+    if (ident) {
+        memset(&sa, 0, len);
+        if (getsockname(s, (struct sockaddr *)&sa, &len) < 0)
+            errno_crash_and_burn("can't get ICMP socket identity");
+
+        if (sa.sin_port)
+            *ident = sa.sin_port;
+    }
+}
+
+unsigned short calcsum(unsigned short* buffer, int length)
+{
+    unsigned long sum;
+
+    /* initialize sum to zero and loop until length (in words) is 0 */
+    for (sum = 0; length > 1; length -= 2) /* sizeof() returns number of bytes, we're interested in number of words */
+        sum += *buffer++; /* add 1 word of buffer to sum and proceed to the next */
+
+    /* we may have an extra byte */
+    if (length == 1)
+        sum += (char)*buffer;
+
+    sum = (sum >> 16) + (sum & 0xFFFF); /* add high 16 to low 16 */
+    sum += (sum >> 16); /* add carry */
+    return ~sum;
+}
+
+int socket_sendto_ping_ipv4(int s, struct sockaddr* saddr, socklen_t saddr_len, uint16_t icmp_seq_nr, uint16_t icmp_id_nr, uint8_t icmp_proto)
+{
+    struct icmp* icp;
+    struct timespec tsorig;
+    long tsorig_ms;
+    int n;
+
+    icp = (struct icmp*)ping_buffer_ipv4;
+
+    icp->icmp_type = icmp_proto;
+    if(icmp_proto == ICMP_TSTAMP) {
+        clock_gettime(CLOCK_REALTIME, &tsorig);
+        tsorig_ms = (tsorig.tv_sec % (24*60*60)) * 1000 + tsorig.tv_nsec / 1000000;
+        icp->icmp_otime = htonl(tsorig_ms);
+        icp->icmp_rtime = 0;
+        icp->icmp_ttime = 0;
+    }
+    icp->icmp_code = 0;
+    icp->icmp_cksum = 0;
+    icp->icmp_seq = htons(icmp_seq_nr);
+    icp->icmp_id = icmp_id_nr;
+
+    if (random_data_flag) {
+        for (n = ((char*)&icp->icmp_data - (char*)icp); n < ping_pkt_size_ipv4; ++n) {
+            ping_buffer_ipv4[n] = random() & 0xFF;
+        }
+    }
+
+    icp->icmp_cksum = calcsum((unsigned short*)icp, ping_pkt_size_ipv4);
+
+    n = sendto(s, icp, ping_pkt_size_ipv4, 0, saddr, saddr_len);
+
+    return n;
+}
diff --git a/ci/tmp.4rIIEYCP9c/fping-5.3/src/socket6.c b/ci/tmp.4rIIEYCP9c/fping-5.3/src/socket6.c
new file mode 100644 (file)
index 0000000..84a84ea
--- /dev/null
@@ -0,0 +1,136 @@
+/*
+ * 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"
+
+#include <fcntl.h>
+#include <netdb.h>
+#include <netinet/in.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/socket.h>
+
+#include <netinet/icmp6.h>
+
+char* ping_buffer_ipv6 = 0;
+size_t ping_pkt_size_ipv6;
+
+int open_ping_socket_ipv6(int *socktype)
+{
+    struct protoent* proto;
+    int s;
+
+    /* confirm that ICMP6 is available on this machine */
+    if ((proto = getprotobyname("ipv6-icmp")) == NULL)
+        crash_and_burn("ipv6-icmp: unknown protocol");
+
+    /* create raw socket for ICMP6 calls (ping) */
+    *socktype = SOCK_RAW;
+    s = socket(AF_INET6, *socktype, proto->p_proto);
+    if (s < 0) {
+        /* try non-privileged icmp6 (works on Mac OSX without privileges, for example) */
+        *socktype = SOCK_DGRAM;
+        s = socket(AF_INET6, *socktype, proto->p_proto);
+        if (s < 0) {
+            return -1;
+        }
+    }
+
+    /* Make sure that we use non-blocking IO */
+    {
+        int flags;
+
+        if ((flags = fcntl(s, F_GETFL, 0)) < 0)
+            perror("fcntl");
+
+        if (fcntl(s, F_SETFL, flags | O_NONBLOCK) < 0)
+            perror("fcntl");
+    }
+
+    return s;
+}
+
+void init_ping_buffer_ipv6(size_t ping_data_size)
+{
+    /* allocate ping buffer */
+    ping_pkt_size_ipv6 = ping_data_size + sizeof(struct icmp6_hdr);
+    ping_buffer_ipv6 = (char*)calloc(1, ping_pkt_size_ipv6);
+    if (!ping_buffer_ipv6)
+        crash_and_burn("can't malloc ping packet");
+}
+
+void socket_set_src_addr_ipv6(int s, struct in6_addr* src_addr, int *ident)
+{
+    struct sockaddr_in6 sa;
+    socklen_t len = sizeof(sa);
+
+    memset(&sa, 0, sizeof(sa));
+    sa.sin6_family = AF_INET6;
+    sa.sin6_addr = *src_addr;
+    if (bind(s, (struct sockaddr*)&sa, sizeof(sa)) < 0)
+        errno_crash_and_burn("cannot bind source address");
+
+    if (ident) {
+        memset(&sa, 0, len);
+        if (getsockname(s, (struct sockaddr *)&sa, &len) < 0)
+            errno_crash_and_burn("can't get ICMP6 socket identity");
+
+        if (sa.sin6_port)
+            *ident = sa.sin6_port;
+    }
+}
+
+int socket_sendto_ping_ipv6(int s, struct sockaddr* saddr, socklen_t saddr_len, uint16_t icmp_seq_nr, uint16_t icmp_id_nr)
+{
+    struct icmp6_hdr* icp;
+    int n;
+
+    icp = (struct icmp6_hdr*)ping_buffer_ipv6;
+    icp->icmp6_type = ICMP6_ECHO_REQUEST;
+    icp->icmp6_code = 0;
+    icp->icmp6_seq = htons(icmp_seq_nr);
+    icp->icmp6_id = icmp_id_nr;
+
+    if (random_data_flag) {
+        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_ipv6, 0, saddr, saddr_len);
+
+    return n;
+}
diff --git a/ci/tmp.VwGIuQgZdr/fping-5.4/CHANGELOG.md b/ci/tmp.VwGIuQgZdr/fping-5.4/CHANGELOG.md
new file mode 100644 (file)
index 0000000..7cd88bc
--- /dev/null
@@ -0,0 +1,299 @@
+fping 5.4 (2025-08-19)
+======================
+
+## Bugfixes
+
+- Memory allocation safety checks for event storage (thanks David.A for bug report)
+- Fix off-by-one boundary check in seqmap code (thanks David.A for bug report)
+- The minimum value for the per-host interval (-i flag) is now 0.001 (milliseconds),
+  since it probably never makes sense to use a smaller value, and to avoid trying
+  to do a too large memory allocation.
+
+fping 5.3 (2025-01-02)
+======================
+
+## New features
+
+- New option --icmp-timestamp to send ICMP timestamp requests (ICMP type 13)
+  instead of ICMP Echo requests (#353 #363, thanks @auerswal and @gsnw-sebast)
+- New option --print-ttl to print returned TTL value (#354, thanks @nalves599)
+- New option --print-tos to print returned TOS value (#335 #346 #347, thanks
+  @auerswal and @gsnw-sebast)
+- New option --check-source (#334, thanks @auerswal)
+- Predefined various timestamp formats (#321, thanks @auerswal and @gsnw-sebast)
+- Print cumulative stats with -Q SECS,cumulative (#315, thanks @auerswal)
+
+## Bugfixes and other changes
+
+- ci: Upgrade actions/upload-artifact to v4 (#360, thanks @gsnw-sebast)
+- ci: Azure Pipeline only trigger when changes are made in the development branch
+  (#359, thanks @gsnw-sebast)
+- ci: Upgrade actions/upload-artifact to v3 (#355, thanks @pevik)
+- ci: Azure Pipeline YAML add docker build (#354, thanks @gsnw-sebast)
+- Dockerfile: change distribution from ubuntu to debian (#350, thanks
+  @gsnw-sebast)
+- Fix warning unused parameter 'reply_timestamp' under macOS (#348, thanks
+  @gsnw-sebast)
+- Fix increase maximum -s value to 65507 (#344, thanks @pevik)
+- ci: use File::Temp to create temporary directory (#343, thanks @auerswal)
+- Fix -k, --fwmark with setuid fping executable (#342, thanks @auerswal)
+- Another batch of additional tests (take 2) (#341, thanks @auerswal)
+- Document that -a and -u are overridden by -c and -C (#338, thanks @auerswal)
+- Fix macOS build warning sets SEQMAP_TIMEOUT_IN_NSSEQMAP_TIMEOUT_IN_NS as INT64_C
+  (#336, thanks @gsnw-sebast)
+- Fix inconsistent limits for address generation via -g, --generator using either
+  range or CIDR (#331, thanks @auerswal)
+- Some additional tests (#329, thanks @auerswal)
+- ci: skip an unreliable test on macOS (#328, thanks @auerswal)
+- Fix incorrect return-value check for a scanf like function (CWE-253) (#323,
+  thanks @gsnw-sebast)
+- A few more tests to increase code coverage a little bit (#320, thanks @auerswal)
+- Github fix: Change to codeql-action-v2 (#319, thanks @gsnw-sebast)
+- Developer function: Debug with Visual Studio Code (#318, thanks @gsnw-sebast)
+
+fping 5.2 (2024-04-21)
+======================
+
+## New features
+
+- New option -X / --fast-reachable to exit immediately once N hosts have been
+  found (#260, thanks @chriscray and @gsnw)
+
+- New option -k / -fwmark to set Linux fwmark mask (#289, thanks @tomangert and
+  @deepkv)
+
+## Bugfixes and other changes
+
+- Always output fatal error messages (#303, thanks @auerswal)
+- Fallback to SO\_TIMESTAMP if SO\_TIMESTAMPNS is not available (#279, thanks
+  @gsnw)
+- Fix "not enough sequence numbers available" error on BSD-like systems (#307,
+  thanks @cagney, @gsnw)
+- Fix running in unprivileged mode (#248, thanks @sfan5)
+- Fix build issue for NetBSD/alpha (#255, thanks @0-wiz-0)
+- Fix build issue for OpenBSD/alpha (#275, thanks @gsnw)
+- Fix build warning for long int usage (#258, thanks @gsnw)
+- Fix build error with musl libc (#263, thanks @kraj)
+- Fix to guard against division by zero (#293, thanks @auerswal)
+- Decouple -a/-u effects from -c (#298, thanks @auerswal)
+- Added contrib/Dockerfile (#224, thanks @darless)
+- Remove host from Netdata chart titles (#253, thanks @ilyam8)
+- Add additional tests (#292, #297, thanks @auerswal)
+- Update github action os images (#282, thanks @gsnw)
+- Fix Azure pipeline tests (#308, thanks @gsnw)
+- Various autoconf fixes (#286, #283, thanks @gsnw)
+- Extended configure script with --enable-debug and output cpu usage (#311,
+  thanks @gsnw)
+- Documentation: Update Netdata website link (#257, thanks @ilyam8)
+- Documentation: fix description of --file option (#268, thanks @MohGeek)
+- Documentation: improve exit status description (#294, thanks @auerswal)
+- Documentation: move description of -i MSEC (#298, thanks @auerswal)
+- Documentation: improve help output for options -c and -C (#302, #auerswal)
+
+
+fping 5.1 (2022-02-06)
+======================
+
+## Bugfixes and other changes
+
+- Use setcap to specify specific files in fping.spec (#232, thanks @zdyxry)
+- Netdata: use host instead name as family label (#226, thanks @k0ste)
+- Netdata: use formatstring macro PRId64 (#229, thanks @gsnw)
+- Allow -4 option to be given multiple times (#215, thanks @normanr)
+- Documentation fix (#208, thanks @timgates42)
+- Retain privileges until after privileged setsockopt (#200, thanks @simetnicbr)
+- Set bind to source only when option is set (#198, thanks @dinoex)
+- Update Azure test pipeline (#197, thanks @gsnw)
+- Fix getnameinfo not called properly for IPv4 (#227, thanks @aafbsd)
+- Fixed wrong timestamp under Free- and OpenBSD and macOS (#217, thanks @gsnw)
+- Documentation updates (#240, thanks @auerswal)
+- Updated autotools (autoconf 2.71, automake 1.16.5, libtool 2.4.6)
+
+
+fping 5.0 (2020-08-05)
+======================
+
+## Incompatible Changes
+
+- In non-quiet loop and count mode, a line is printed for every lost packet
+  (#175, thanks @kbucheli):
+
+  ```
+  $ fping -D -c2 8.8.8.8 8.8.8.7
+  [1596092373.18423] 8.8.8.8 : [0], 64 bytes, 12.8 ms (12.8 avg, 0% loss)
+  [1596092374.18223] 8.8.8.7 : [0], timed out (NaN avg, 100% loss)
+  [1596092374.18424] 8.8.8.8 : [1], 64 bytes, 12.3 ms (12.5 avg, 0% loss)
+  [1596092375.18344] 8.8.8.7 : [1], timed out (NaN avg, 100% loss)
+
+  8.8.8.8 : xmt/rcv/%loss = 2/2/0%, min/avg/max = 12.3/12.5/12.8
+  8.8.8.7 : xmt/rcv/%loss = 2/0/100%
+  ```
+
+- The returned size in bytes now always excludes the IP header, so if before it
+  reported '84 bytes' e.g. when using 'fping -l', now it reports '64 bytes'.
+  This is to make the reported size consistent with ping(8) from iputils and
+  also with fping when pinging a IPv6 host (which never included the IPv6
+  header size).
+
+## New features
+
+- The number of sent pings is only counted when the pings are received or have
+  timed out, ensuring that the loss ratio will be always correct. This makes it
+  possible, for example, to use loop mode (-l) with interval statistics (-Q)
+  and a timeout larger than period, without having the issue that initially
+  some pings would be reported as missing (#193)
+
+- Improved precision of measurements from 10us to 1us (#136, thanks @tycho)
+
+## Bugfixes and other changes
+
+- The reported size of received packets is now always correct on Linux even for
+  packets > 4096 bytes (#180)
+
+- Travis CI automated testing now also macos testing and additional ubuntu
+  distributions (#196)
+
+fping 4.4 (2020-07-24)
+======================
+## Bugfixes and other changes
+
+- Fix wrong ident used for normal (non-unprivileged) pings (#191, thanks @tycho)
+- Fix build with --disable-ipv6 (#187, thanks Polynomial-C)
+
+fping 4.3 (2020-07-11)
+======================
+
+## New features
+
+- Linux unprivileged ping support (#173, thanks @tycho)
+- Add SIGQUIT summary support similar to ping (#185, thanks @laddp)
+
+## Bugfixes and other changes
+
+- Corrected long option name of -s to --stats (#148, thanks @wopfel)
+- Do not fail if using fping6 with -6 flag (#149, thanks @stromnet)
+- Fail if interface binding (-I) does not work (#162, thanks @kbucheli)
+- Fix using option -4 when fping is compiled IPv4-only (#154, thanks @pbhenson)
+- Add Azure pipeline test build (#153 and #170, thanks @gsnw)
+- GCC 10 compatibility fixes (#167 and #168, thanks @cranderson)
+- Macos build fix (#174, thanks @tycho)
+- Fix xmt stats in Netdata output (#172, thanks @vlvkobal)
+- Only increase num_alive if response is not a duplicate (#151, thanks @brownowski)
+- Use line buffering for stdout (#179, thanks @bg6cq)
+
+fping 4.2 (2019-02-19)
+======================
+
+## New features
+
+- New option -x / --reachable to check if the number of reachable hosts is >= a certain
+  number. Useful for example to implement connectivity-checks (#138, thanks @deepak0004)
+
+## Bugfixes and other changes
+
+- Allow decimal numbers for '-t', '-i', '-p', and '-Q'
+- Fix build with --disable-ipv6 (#134, thanks @Polynomial-C)
+- Fix hang with '-6', with ipv6 kernel module, but not loaded (#140, thanks @abelbeck)
+- Assume '-6' if the binary is named 'fping6' (this is mostly for special
+  embedded-distro use cases, and not meant to be used generally in place of
+  compiling IPv6-only binary or using '-6', see also the notes in #139, thanks
+  abelbeck)
+- Get rid of warning "timeout (-t) value larger than period (-p) produces unexpected results"
+  (#142, thanks @MrDragon1122)
+  
+
+fping 4.1 (2018-09-17)
+======================
+
+## Bugfixes and other changes
+
+- Fix problem when socket fd is 0 (#125, thanks Ramón Novoa!)
+- Fix running on servers with disabled IPv6 (#118, thanks Simon Matter)
+- Allow running "fping -h" or "--help" even when raw socket can't be opened (#131, thanks @teto)
+- Fix build issue with FreeBSD and IPv6 (#132, thanks @gsnw)
+
+fping 4.0 (2017-04-23)
+======================
+
+## Incompatible Changes
+
+##### fping and fping6 unification
+
+fping and fping6 are now unified into one binary. It means that, for example,
+doing 'fping google.com' is going to ping the IPv6 IP of google.com on
+IPv6-enabled hosts.  
+
+If you need exact compatibility with old versions, you can configure 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
+
+##### Option -n, not the same as -d anymore
+
+Option -n / --name is now doing a reverse-DNS lookups on host addresses,
+only if they are given as IP address, but not for hostnames. For example,
+if you write 'fping -n google.com', fping would previously do a
+forward-DNS lookup on google.com, and then a reverse-DNS lookup on the
+resolved IP address. Now, it is just going to keep the name 'google.com'.
+That same behavior can be achieved with the option -d / --rdns (which was
+previously an alias for -n).
+
+                     fping<4.0              fping>=4.0
+    fping -n NAME    NAME->IP->IPNAME       NAME
+    fping -d NAME    NAME->IP->IPNAME       NAME->IP->IPNAME
+
+##### Discarding of late packets
+
+fping will now discard replies, if they arrive after the defined timeout
+for reply packets, specified with -t. This change is relevant only for the
+count and loop modes, where the measured times should be now more
+consistent (see github issue [#32][i32] for details).
+
+To prevent loosing reply packets because of this change, the default
+timeout in count and loop modes is now automatically adjusted to the
+period interval (up to 2000 ms), but it can be overriden with the -t
+option. The default timeout for non-loop/count modes remains 500 ms.
+
+##### No restrictions by default
+
+fping will not enforce -i >= 1 and -p >= 10 anymore, except if you
+'./configure --enable-safe-limits'.
+
+The reasoning to removing the restrictions by default, is that users can
+clog the network with other tools anyway, and these restrictions are
+sometimes getting in the way (for example if you try to ping a lot of
+hosts).
+
+##### Default interval (-i) changed from 25ms to 10ms
+
+The default minimum interval between ping probes has been changed from
+25ms to 10ms. The reason is that 25ms is very high, considering today's
+fast networks: it generates at most 31 kbps of traffic (for IPv4 and
+default payload size).
+
+## New features
+
+- Unified 'fping' and 'fping6' into one binary ([#80][i80])
+- Long option names for all options
+- IPv6 enabled by default
+- New option -4 to force IPv4
+- New option -6 to force IPv6
+- Keep original name if a hostname is given with -n/--name
+- Option -d/--rdns now always does a rdns-lookup, even for names, as '-n' was doing until now
+- Enforce -t timeout on reply packets, by discarding late packets ([#32][i32])
+- Auto-adjust timeout for -c/-C/-l mode to value of -p
+
+## Bugfixes and other changes
+
+- -i/-p restrictions disabled by default (enable with --enable-safe-limits)
+- Default interval -i changed from 25ms to 10ms
+- Fix compatibility issue with GNU Hurd
+- A C99 compiler is now required
+- Option parsing with optparse (https://github.com/skeeto/optparse). Thanks Christopher Wellons!
+- New changelog file format
+
+[i32]: https://github.com/schweikert/fping/issues/32
+[i80]: https://github.com/schweikert/fping/issues/80
+
+(see doc/CHANGELOG.pre-v4 for older changes)
diff --git a/ci/tmp.VwGIuQgZdr/fping-5.4/COPYING b/ci/tmp.VwGIuQgZdr/fping-5.4/COPYING
new file mode 100644 (file)
index 0000000..cceb651
--- /dev/null
@@ -0,0 +1,17 @@
+ * 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.
diff --git a/ci/tmp.VwGIuQgZdr/fping-5.4/INSTALL b/ci/tmp.VwGIuQgZdr/fping-5.4/INSTALL
new file mode 100644 (file)
index 0000000..e23597f
--- /dev/null
@@ -0,0 +1,177 @@
+Basic Installation
+==================
+
+   These are generic installation instructions.
+
+   --> See the README file for fping-specific instructions. <--
+
+   The `configure' shell script attempts to guess correct values for
+various system-dependent variables used during compilation.  It uses
+those values to create a `Makefile' in each directory of the package.
+It may also create one or more `.h' files containing system-dependent
+definitions.  Finally, it creates a shell script `config.status' that
+you can run in the future to recreate the current configuration, a file
+`config.cache' that saves the results of its tests to speed up
+reconfiguring, and a file `config.log' containing compiler output
+(useful mainly for debugging `configure').
+
+   If you need to do unusual things to compile the package, please try
+to figure out how `configure' could check whether to do them, and mail
+diffs or instructions to the address given in the `README' so they can
+be considered for the next release.  If at some point `config.cache'
+contains results you don't want to keep, you may remove or edit it.
+
+   The file `configure.in' is used to create `configure' by a program
+called `autoconf'.  You only need `configure.in' if you want to change
+it or regenerate `configure' using a newer version of `autoconf'.
+
+The simplest way to compile this package is:
+
+  1. `cd' to the directory containing the package's source code and type
+     `./configure' to configure the package for your system.  If you're
+     using `csh' on an old version of System V, you might need to type
+     `sh ./configure' instead to prevent `csh' from trying to execute
+     `configure' itself.
+
+     Running `configure' takes a while.  While running, it prints some
+     messages telling which features it is checking for.
+
+  2. Type `make' to compile the package.
+
+  3. Optionally, type `make check' to run any self-tests that come with
+     the package.
+
+  4. Type `make install' to install the programs and any data files and
+     documentation.
+
+  5. You can remove the program binaries and object files from the
+     source code directory by typing `make clean'.  To also remove the
+     files that `configure' created (so you can compile the package for
+     a different kind of computer), type `make distclean'.  There is
+     also a `make maintainer-clean' target, but that is intended mainly
+     for the package's developers.  If you use it, you may have to get
+     all sorts of other programs in order to regenerate files that came
+     with the distribution.
+
+Compilers and Options
+=====================
+
+   Some systems require unusual options for compilation or linking that
+the `configure' script does not know about.  You can give `configure'
+initial values for variables by setting them in the environment.  Using
+a Bourne-compatible shell, you can do that on the command line like
+this:
+     CC=c89 CFLAGS=-O2 LIBS=-lposix ./configure
+
+Or on systems that have the `env' program, you can do it like this:
+     env CPPFLAGS=-I/usr/local/include LDFLAGS=-s ./configure
+
+Compiling For Multiple Architectures
+====================================
+
+   You can compile the package for more than one kind of computer at the
+same time, by placing the object files for each architecture in their
+own directory.  To do this, you must use a version of `make' that
+supports the `VPATH' variable, such as GNU `make'.  `cd' to the
+directory where you want the object files and executables to go and run
+the `configure' script.  `configure' automatically checks for the
+source code in the directory that `configure' is in and in `..'.
+
+   If you have to use a `make' that does not supports the `VPATH'
+variable, you have to compile the package for one architecture at a time
+in the source code directory.  After you have installed the package for
+one architecture, use `make distclean' before reconfiguring for another
+architecture.
+
+Installation Names
+==================
+
+   By default, `make install' will install the package's files in
+`/usr/local/bin', `/usr/local/man', etc.  You can specify an
+installation prefix other than `/usr/local' by giving `configure' the
+option `--prefix=PATH'.
+
+   You can specify separate installation prefixes for
+architecture-specific files and architecture-independent files.  If you
+give `configure' the option `--exec-prefix=PATH', the package will use
+PATH as the prefix for installing programs and libraries.
+Documentation and other data files will still use the regular prefix.
+
+   If the package supports it, you can cause programs to be installed
+with an extra prefix or suffix on their names by giving `configure' the
+option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'.
+
+Optional Features
+=================
+
+   Some packages pay attention to `--enable-FEATURE' options to
+`configure', where FEATURE indicates an optional part of the package.
+They may also pay attention to `--with-PACKAGE' options, where PACKAGE
+is something like `gnu-as' or `x' (for the X Window System).  The
+`README' should mention any `--enable-' and `--with-' options that the
+package recognizes.
+
+   For packages that use the X Window System, `configure' can usually
+find the X include and library files automatically, but if it doesn't,
+you can use the `configure' options `--x-includes=DIR' and
+`--x-libraries=DIR' to specify their locations.
+
+Specifying the System Type
+==========================
+
+   There may be some features `configure' can not figure out
+automatically, but needs to determine by the type of host the package
+will run on.  Usually `configure' can figure that out, but if it prints
+a message saying it can not guess the host type, give it the
+`--host=TYPE' option.  TYPE can either be a short name for the system
+type, such as `sun4', or a canonical name with three fields:
+     CPU-COMPANY-SYSTEM
+
+See the file `config.sub' for the possible values of each field.  If
+`config.sub' isn't included in this package, then this package doesn't
+need to know the host type.
+
+   If you are building compiler tools for cross-compiling, you can also
+use the `--target=TYPE' option to select the type of system they will
+produce code for and the `--build=TYPE' option to select the type of
+system on which you are compiling the package.
+
+Sharing Defaults
+================
+
+   If you want to set default values for `configure' scripts to share,
+you can create a site shell script called `config.site' that gives
+default values for variables like `CC', `cache_file', and `prefix'.
+`configure' looks for `PREFIX/share/config.site' if it exists, then
+`PREFIX/etc/config.site' if it exists.  Or, you can set the
+`CONFIG_SITE' environment variable to the location of the site script.
+A warning: not all `configure' scripts look for a site script.
+
+Operation Controls
+==================
+
+   `configure' recognizes the following options to control how it
+operates.
+
+`--cache-file=FILE'
+     Use and save the results of the tests in FILE instead of
+     `./config.cache'.  Set FILE to `/dev/null' to disable caching, for
+     debugging `configure'.
+
+`--help'
+     Print a summary of the options to `configure', and exit.
+
+`--quiet'
+`--silent'
+`-q'
+     Do not print messages saying which checks are being made.
+
+`--srcdir=DIR'
+     Look for the package's source code in directory DIR.  Usually
+     `configure' can determine that directory automatically.
+
+`--version'
+     Print the version of Autoconf used to generate the `configure'
+     script, and exit.
+
+`configure' also accepts some other, not widely useful, options.
diff --git a/ci/tmp.VwGIuQgZdr/fping-5.4/Makefile.am b/ci/tmp.VwGIuQgZdr/fping-5.4/Makefile.am
new file mode 100644 (file)
index 0000000..2ea59b9
--- /dev/null
@@ -0,0 +1,3 @@
+SUBDIRS = doc src
+
+EXTRA_DIST = CHANGELOG.md contrib README.md ci/*.sh ci/*.pl
diff --git a/ci/tmp.VwGIuQgZdr/fping-5.4/README.md b/ci/tmp.VwGIuQgZdr/fping-5.4/README.md
new file mode 100644 (file)
index 0000000..8cf4f88
--- /dev/null
@@ -0,0 +1,50 @@
+[![Build Status](https://travis-ci.org/schweikert/fping.svg?branch=develop)](https://travis-ci.org/schweikert/fping)
+[![Coverage Status](https://coveralls.io/repos/github/schweikert/fping/badge.svg?branch=develop)](https://coveralls.io/github/schweikert/fping?branch=develop)
+[![Coverity Scan Build Status](https://scan.coverity.com/projects/11559/badge.svg?flat=1")](https://scan.coverity.com/projects/schweikert-fping)
+
+# fping
+
+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 long long
+story: Roland Schemers did publish a first version of it in 1992 and it has
+established itself since then as a standard tool.
+
+_Current maintainer_:  
+  David Schweikert \<david@schweikert.ch\>
+
+_Website_:  
+  https://fping.org/
+
+_Mailing-list_:  
+  https://groups.google.com/group/fping-users
+
+## Installation
+
+If you want to install fping from source, proceed as follows:
+
+0. Run `./autogen.sh`
+   (only if you got the source from Github).
+1. Run `./configure` with the correct arguments.
+   (see: `./configure --help`)
+2. Run `make; make install`.
+3. Make fping either setuid, or, if under Linux:
+   `sudo setcap cap_net_raw,cap_net_admin+ep fping`
+
+If you can't run fping as root or can't use the cap_net_raw capability, you can
+also run fping in unprivileged mode. This works on MacOS and also on Linux,
+provided that your GID is included in the range defined in
+`/proc/sys/net/ipv4/ping_group_range`. This is particularly useful for running
+fping in rootless / unprivileged containers. The --fwmark option needs root or
+cap_net_admin.
+
+## Usage
+
+Have a look at the [fping(8)](doc/fping.pod) manual page for usage help.
+(`fping -h` will also give a minimal help output.)
+
+## Credits
+
+* Original author:  Roland Schemers (schemers@stanford.edu)
+* Previous maintainer:  RL "Bob" Morgan (morgan@stanford.edu)
+* Initial IPv6 Support: Jeroen Massar (jeroen@unfix.org / jeroen@ipng.nl)
+* Other contributors: see [CHANGELOG.md](CHANGELOG.md)
diff --git a/ci/tmp.VwGIuQgZdr/fping-5.4/ci/build-1-autotools.sh b/ci/tmp.VwGIuQgZdr/fping-5.4/ci/build-1-autotools.sh
new file mode 100755 (executable)
index 0000000..f0ea2e0
--- /dev/null
@@ -0,0 +1,61 @@
+#!/bin/bash
+
+set -e
+set -x
+
+if [[ "$OSTYPE" == "darwin"* ]]; then
+    exit 0
+fi
+
+AUTOCONF=http://ftp.gnu.org/gnu/autoconf/autoconf-2.71.tar.gz
+AUTOMAKE=http://ftp.gnu.org/gnu/automake/automake-1.16.5.tar.gz
+LIBTOOL=http://ftp.gnu.org/gnu/libtool/libtool-2.4.6.tar.gz
+PREFIX=$(pwd)/ci/build
+PATH=$(pwd)/ci/build/bin:$PATH
+
+if [ ! -d ci ]; then
+    echo "you must run this in the root fping directory" >&2
+    exit 1
+fi
+
+# remove standard versions
+sudo apt-get remove -qq autoconf automake autotools-dev libtool
+
+# prepare build environment
+cd ci
+rm -rf build
+mkdir -p build/src
+cd build/src
+
+# autoconf
+(
+AUTOCONF_FILE=$(basename $AUTOCONF)
+AUTOCONF_DIR=$(echo $AUTOCONF_FILE | sed -e 's/\.tar.*//')
+wget $AUTOCONF
+tar xf $AUTOCONF_FILE
+cd $AUTOCONF_DIR
+./configure --prefix=$PREFIX
+make install
+)
+
+# automake
+(
+AUTOMAKE_FILE=$(basename $AUTOMAKE)
+AUTOMAKE_DIR=$(echo $AUTOMAKE_FILE | sed -e 's/\.tar.*//')
+wget $AUTOMAKE
+tar xf $AUTOMAKE_FILE
+cd $AUTOMAKE_DIR
+./configure --prefix=$PREFIX
+make install
+)
+
+# libtool
+(
+LIBTOOL_FILE=$(basename $LIBTOOL)
+LIBTOOL_DIR=$(echo $LIBTOOL_FILE | sed -e 's/\.tar.*//')
+wget $LIBTOOL
+tar xf $LIBTOOL_FILE
+cd $LIBTOOL_DIR
+./configure --prefix=$PREFIX
+make install
+)
diff --git a/ci/tmp.VwGIuQgZdr/fping-5.4/ci/build-2-test-command.sh b/ci/tmp.VwGIuQgZdr/fping-5.4/ci/build-2-test-command.sh
new file mode 100755 (executable)
index 0000000..77f3905
--- /dev/null
@@ -0,0 +1,6 @@
+#!/bin/sh
+
+set -ex
+
+curl -L http://cpanmin.us | perl - -L $HOME/perl5 App::cpanminus
+$HOME/perl5/bin/cpanm --sudo Test::Command
diff --git a/ci/tmp.VwGIuQgZdr/fping-5.4/ci/build-3-prepare-macos.sh b/ci/tmp.VwGIuQgZdr/fping-5.4/ci/build-3-prepare-macos.sh
new file mode 100755 (executable)
index 0000000..09125eb
--- /dev/null
@@ -0,0 +1,13 @@
+#!/bin/bash
+
+# only do this on Mac OS X
+if [ `uname -s` != "Darwin" ]; then
+    exit 0;
+fi
+
+if [[ ! `ifconfig lo0` =~ 127\.0\.0\.2 ]]; then
+    sudo ifconfig lo0 127.0.0.2/8 alias
+    sudo ifconfig lo0 127.0.0.3/8 alias
+    sudo ifconfig lo0 127.0.0.4/8 alias
+    sudo ifconfig lo0 127.0.0.5/8 alias
+fi 
diff --git a/ci/tmp.VwGIuQgZdr/fping-5.4/ci/build-4-compile.sh b/ci/tmp.VwGIuQgZdr/fping-5.4/ci/build-4-compile.sh
new file mode 100755 (executable)
index 0000000..e2a660c
--- /dev/null
@@ -0,0 +1,28 @@
+#!/bin/bash
+set -x
+
+PATH=$(pwd)/ci/build/bin:$PATH
+
+if [ ! -d ci ]; then
+    echo "you must run this in the root fping directory" >&2
+    exit 1
+fi
+
+autoreconf -i
+./configure --enable-ipv4 --enable-ipv6 --enable-safe-limits --prefix=/opt/fping
+make CFLAGS="-g -O0 -fprofile-arcs -ftest-coverage"
+## setcap currently doesn't work anymore on travis-ci
+#sudo setcap cap_net_raw+ep src/fping
+## setcap debugging:
+#pwd
+#df -k .
+#which setcap
+#uname -a
+#mount
+#
+#sudo apt-get install strace
+#sudo strace setcap cap_net_raw+ep src/fping
+
+# use setuid, since setcap is not available
+sudo chown root src/fping
+sudo chmod u+s  src/fping
diff --git a/ci/tmp.VwGIuQgZdr/fping-5.4/ci/deploy-bintray.sh b/ci/tmp.VwGIuQgZdr/fping-5.4/ci/deploy-bintray.sh
new file mode 100755 (executable)
index 0000000..0dc8800
--- /dev/null
@@ -0,0 +1,14 @@
+#!/bin/bash
+
+# upload to bintray.com/schweikert
+
+set -e
+
+VERSION=$(ls fping-*.tar.gz | sed -e 's/^fping-//' | sed -e 's/\.tar\.gz$//')
+if [[ "$VERSION" =~ ^[0-9]+\.[0-9]+$ ]]; then
+    REPO=release
+else
+    REPO=beta
+fi
+curl -T fping-$VERSION.tar.gz -uschweikert:$BINTRAY_API_KEY https://api.bintray.com/content/schweikert/$REPO/fping/$VERSION/fping-$VERSION.tar.gz
+echo
diff --git a/ci/tmp.VwGIuQgZdr/fping-5.4/ci/deploy-coveralls.sh b/ci/tmp.VwGIuQgZdr/fping-5.4/ci/deploy-coveralls.sh
new file mode 100755 (executable)
index 0000000..9080f0b
--- /dev/null
@@ -0,0 +1,16 @@
+#!/bin/sh
+
+set -xe
+
+if [ "$TRAVIS_DIST" = "trusty" ]; then
+    echo "skip coveralls on trusty because coveralls errors out due to python issues"
+    exit 0
+elif [ "$TRAVIS_OS_NAME" = "osx" ]; then
+    pip3 install --user cpp-coveralls
+    PATH="${PATH}:$(python3 -c 'import site; print(site.USER_BASE)')/bin"
+else
+    pip install --user cpp-coveralls
+fi
+
+export COVERALLS_PARALLEL=true
+coveralls --build-root src --exclude src/optparse.c --exclude ci --exclude config.h --gcov-options '\-lp'
diff --git a/ci/tmp.VwGIuQgZdr/fping-5.4/ci/deploy-coverity.sh b/ci/tmp.VwGIuQgZdr/fping-5.4/ci/deploy-coverity.sh
new file mode 100755 (executable)
index 0000000..b009d2f
--- /dev/null
@@ -0,0 +1,25 @@
+#!/bin/sh
+
+set -e
+
+COVERITY_SCAN_PROJECT_NAME=schweikert/fping
+COVERITY_SCAN_EMAIL=david@schweikert.ch
+
+if [ -z "$COVERITY_SCAN_TOKEN" ]; then
+    echo "ERROR: COVERITY_SCAN_TOKEN not defined." >&2
+    exit 1
+fi
+
+curl -o /tmp/cov-analysis-linux64.tgz https://scan.coverity.com/download/linux64 \
+    --form project=$COVERITY_SCAN_PROJECT_NAME --form token=$COVERITY_SCAN_TOKEN
+tar xfz /tmp/cov-analysis-linux64.tgz
+./autogen.sh
+./configure --enable-ipv4 --enable-ipv6 --enable-safe-limits --prefix=/opt/fping
+cov-analysis-linux64-*/bin/cov-build --dir cov-int make -j4
+tar cfz cov-int.tar.gz cov-int
+curl https://scan.coverity.com/builds?project=$COVERITY_SCAN_PROJECT_NAME \
+    --form token=$COVERITY_SCAN_TOKEN \
+    --form email=$COVERITY_SCAN_EMAIL \
+    --form file=@cov-int.tar.gz \
+    --form version="`git rev-parse --short HEAD`" \
+    --form description="`git rev-parse --short HEAD` / $TRAVIS_BUILD_ID "
diff --git a/ci/tmp.VwGIuQgZdr/fping-5.4/ci/prepare-linux.sh b/ci/tmp.VwGIuQgZdr/fping-5.4/ci/prepare-linux.sh
new file mode 100755 (executable)
index 0000000..efe8b3b
--- /dev/null
@@ -0,0 +1,7 @@
+#!/bin/bash
+
+sudo setcap cap_net_raw,cap_net_admin+ep src/fping
+
+if [[ ! $PATH =~ fping/src ]]; then
+    PATH=/home/dws/checkouts/fping/src:$PATH
+fi
diff --git a/ci/tmp.VwGIuQgZdr/fping-5.4/ci/run-lcov.sh b/ci/tmp.VwGIuQgZdr/fping-5.4/ci/run-lcov.sh
new file mode 100755 (executable)
index 0000000..c7470b6
--- /dev/null
@@ -0,0 +1,9 @@
+#!/bin/sh
+
+lcov -c -no-external \
+    -d . \
+    -b src \
+    -o lcov-all.info
+
+lcov --remove lcov-all.info -o lcov.info \
+    '*/optparse.c'
diff --git a/ci/tmp.VwGIuQgZdr/fping-5.4/ci/run-tests.sh b/ci/tmp.VwGIuQgZdr/fping-5.4/ci/run-tests.sh
new file mode 100755 (executable)
index 0000000..9d5a308
--- /dev/null
@@ -0,0 +1,8 @@
+#!/bin/sh
+
+set -ex
+
+PATH=`pwd`/src:$PATH
+
+prove ci/test-*.pl
+ci/test-tarball.sh
diff --git a/ci/tmp.VwGIuQgZdr/fping-5.4/ci/test-01-basics.pl b/ci/tmp.VwGIuQgZdr/fping-5.4/ci/test-01-basics.pl
new file mode 100755 (executable)
index 0000000..e54bc22
--- /dev/null
@@ -0,0 +1,55 @@
+#!/usr/bin/perl -w
+
+use Test::Command tests => 15;
+use Test::More;
+
+# ping 127.0.0.1
+{
+    my $cmd = Test::Command->new(cmd => "fping 127.0.0.1");
+    $cmd->exit_is_num(0);
+    $cmd->stdout_is_eq("127.0.0.1 is alive\n");
+    $cmd->stderr_is_eq("");
+}
+
+# ping ::1
+SKIP: {
+    #system("/sbin/ifconfig >&2");
+    if($ENV{SKIP_IPV6}) {
+        skip 'Skip IPv6 tests', 3;
+    }
+    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("");
+}
+
+# ping ff02::1
+SKIP: {
+    #system("/sbin/ifconfig >&2");
+    if($ENV{SKIP_IPV6}) {
+        skip 'Skip IPv6 tests', 3;
+    }
+    my $cmd = Test::Command->new(cmd => "fping ff02::1");
+    $cmd->exit_is_num(0);
+    $cmd->stdout_is_eq("ff02::1 is alive\n");
+    $cmd->stderr_like(qr{ \[<- .*\]});
+}
+
+# ping 3 times 127.0.0.1
+{
+    my $cmd = Test::Command->new(cmd => "fping -p 100 -C3 127.0.0.1");
+    $cmd->exit_is_num(0);
+    $cmd->stdout_like(qr{127\.0\.0\.1 : \[0\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\)
+127\.0\.0\.1 : \[1\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\)
+127\.0\.0\.1 : \[2\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\)
+});
+    $cmd->stderr_like(qr{127\.0\.0\.1 : \d\.\d+ \d\.\d+ \d\.\d+\n});
+}
+
+# invalid target name
+{
+    my $cmd = Test::Command->new(cmd => "fping host.name.invalid");
+    $cmd->exit_is_num(2);
+    $cmd->stdout_is_eq("");
+    $cmd->stderr_like(qr{host\.name\.invalid: .+\n});
+}
diff --git a/ci/tmp.VwGIuQgZdr/fping-5.4/ci/test-02-help.pl b/ci/tmp.VwGIuQgZdr/fping-5.4/ci/test-02-help.pl
new file mode 100755 (executable)
index 0000000..0f66d13
--- /dev/null
@@ -0,0 +1,46 @@
+#!/usr/bin/perl -w
+
+use Test::Command tests => 15;
+
+my $I_HELP = "   -I, --iface=IFACE  bind to a particular interface\n";
+$I_HELP = '' if $^O eq 'darwin';
+
+# fping -h (special pre-parse code path)
+my $cmd1 = Test::Command->new(cmd => "fping -h");
+$cmd1->exit_is_num(0);
+$cmd1->stdout_like(qr{Usage: fping \[options\] \[targets\.\.\.\]
+
+Probing options:
+.*
+   -v, --version      show version
+}s);
+$cmd1->stderr_is_eq("");
+
+# fping -4 -h (normal option parsing code path)
+my $cmd4 = Test::Command->new(cmd => "fping -4 -h");
+$cmd4->exit_is_num(0);
+$cmd4->stdout_like(qr{Usage: fping \[options\] \[targets\.\.\.\]
+
+Probing options:
+.*
+   -v, --version      show version
+}s);
+$cmd4->stderr_is_eq("");
+
+# fping -v
+my $cmd2 = Test::Command->new(cmd => "fping -v");
+$cmd2->exit_is_num(0);
+$cmd2->stdout_like(qr{fping: Version \S+});
+$cmd2->stderr_is_eq("");
+
+# fping with unknown option
+my $cmd3 = Test::Command->new(cmd => "fping -Z");
+$cmd3->exit_is_num(1);
+$cmd3->stdout_is_eq("");
+$cmd3->stderr_like(qr{^fping: (illegal|invalid) option -- '?Z'?\nsee 'fping -h' for usage information\n$});
+
+# fping with unknown long option
+my $cmd5 = Test::Command->new(cmd => "fping --unknown-long-option");
+$cmd5->exit_is_num(1);
+$cmd5->stdout_is_eq("");
+$cmd5->stderr_like(qr{^fping: (illegal|invalid) option -- '?unknown-long-option'?\nsee 'fping -h' for usage information\n$});
diff --git a/ci/tmp.VwGIuQgZdr/fping-5.4/ci/test-03-forbidden.pl b/ci/tmp.VwGIuQgZdr/fping-5.4/ci/test-03-forbidden.pl
new file mode 100755 (executable)
index 0000000..97962c1
--- /dev/null
@@ -0,0 +1,63 @@
+#!/usr/bin/perl -w
+
+use Test::Command tests => 36;
+
+# fping -i 0
+my $cmd1 = Test::Command->new(cmd => "fping -i 0 -T10 -g 127.0.0.1/29");
+$cmd1->exit_is_num(1);
+$cmd1->stdout_is_eq("");
+$cmd1->stderr_is_eq(<<END);
+fping: -i must be >= 1
+END
+
+# fping -p 9
+my $cmd2 = Test::Command->new(cmd => "fping -c3 -p 9 127.0.0.1");
+$cmd2->exit_is_num(1);
+$cmd2->stdout_is_eq("");
+$cmd2->stderr_is_eq(<<END);
+fping: -p must be >= 10
+END
+
+# fping -H 300
+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("fping: ttl 300 out of range\n");
+
+# fping -a -u
+my $cmd6 = Test::Command->new(cmd => "fping -a -u 127.0.0.1");
+$cmd6->exit_is_num(1);
+$cmd6->stdout_is_eq("");
+$cmd6->stderr_is_eq("fping: specify only one of a, u\n");
+
+# fping -c -l
+my $cmd7 = Test::Command->new(cmd => "fping -c3 -l 127.0.0.1");
+$cmd7->exit_is_num(1);
+$cmd7->stdout_is_eq("");
+$cmd7->stderr_is_eq("fping: specify only one of c, l\n");
+
+# fping -b 65508
+my $cmd8 = Test::Command->new(cmd => "fping -b 65508 127.0.0.1");
+$cmd8->exit_is_num(1);
+$cmd8->stdout_is_eq("");
+$cmd8->stderr_is_eq("fping: data size 65508 not valid, must not be larger than 65507\n");
+
+# fping -B 0.9
+my $cmd9 = Test::Command->new(cmd => "fping -B 0.9 127.0.0.1");
+$cmd9->exit_is_num(1);
+$cmd9->stdout_is_eq("");
+$cmd9->stderr_is_eq("fping: backoff factor 0.9 not valid, must be between 1.0 and 5.0\n");
+
+# fping -B 5.1
+my $cmd10 = Test::Command->new(cmd => "fping -B 5.1 127.0.0.1");
+$cmd10->exit_is_num(1);
+$cmd10->stdout_is_eq("");
+$cmd10->stderr_is_eq("fping: backoff factor 5.1 not valid, must be between 1.0 and 5.0\n");
+
+# non-negative only
+for my $arg (qw(i p Q t)) {
+    my $cmd = Test::Command->new(cmd => "fping -$arg -1");
+    $cmd->exit_is_num(1);
+    $cmd->stdout_is_eq("");
+    $cmd->stderr_like(qr{Usage:});
+}
diff --git a/ci/tmp.VwGIuQgZdr/fping-5.4/ci/test-04-options-a-b.pl b/ci/tmp.VwGIuQgZdr/fping-5.4/ci/test-04-options-a-b.pl
new file mode 100755 (executable)
index 0000000..ea7eb89
--- /dev/null
@@ -0,0 +1,218 @@
+#!/usr/bin/perl -w
+
+use Test::Command tests => 68;
+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 -6 -4
+{
+my $cmd = Test::Command->new(cmd => "fping -6 -4 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($ENV{SKIP_IPV6}) {
+        skip 'Skip IPv6 tests', 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");
+$cmd->exit_is_num(0);
+$cmd->stdout_is_eq("127.0.0.1\n127.0.0.2\n");
+$cmd->stderr_is_eq("");
+}
+
+# fping -a --print-ttl
+{
+my $cmd = Test::Command->new(cmd => "fping -a --print-ttl 127.0.0.1 127.0.0.2");
+$cmd->exit_is_num(0);
+$cmd->stdout_like(qr{127\.0\.0\.1 \(TTL \d+\)\n127\.0\.0\.2 \(TTL \d+\)\n});
+$cmd->stderr_is_eq("");
+}
+
+# fping -a --icmp-timestamp
+SKIP: {
+if($^O eq 'darwin') {
+    skip 'On macOS, this test is unreliable', 3;
+}
+my $cmd = Test::Command->new(cmd => "fping -a --icmp-timestamp 127.0.0.1");
+$cmd->exit_is_num(0);
+$cmd->stdout_like(qr{127\.0\.0\.1 timestamps: Originate=\d+ Receive=\d+ Transmit=\d+ Localreceive=\d+});
+$cmd->stderr_is_eq("");
+}
+
+# fping --print-ttl
+{
+my $cmd = Test::Command->new(cmd => "fping --print-ttl 127.0.0.1");
+$cmd->exit_is_num(0);
+$cmd->stdout_like(qr{127\.0\.0\.1 is alive \(TTL \d+\)});
+$cmd->stderr_is_eq("");
+}
+
+# fping --icmp-timestamp
+SKIP: {
+if($^O eq 'darwin') {
+    skip 'On macOS, this test is unreliable', 3;
+}
+my $cmd = Test::Command->new(cmd => "fping --icmp-timestamp 127.0.0.1");
+$cmd->exit_is_num(0);
+$cmd->stdout_like(qr{127\.0\.0\.1 is alive, timestamps: Originate=\d+ Receive=\d+ Transmit=\d+ Localreceive=\d+});
+$cmd->stderr_is_eq("");
+}
+
+# fping --icmp-timestamp --print-tos --print-ttl -e
+SKIP: {
+if($^O eq 'darwin') {
+    skip 'On macOS, this test is unreliable', 3;
+}
+my $cmd = Test::Command->new(cmd => "fping --icmp-timestamp --print-tos --print-ttl -e 127.0.0.1");
+$cmd->exit_is_num(0);
+$cmd->stdout_like(qr{127\.0\.0\.1 is alive, timestamps: Originate=\d+ Receive=\d+ Transmit=\d+ Localreceive=\d+ \(TOS \d+\) \(TTL \d+\) \(\d+(\.\d*)? ms\)});
+$cmd->stderr_is_eq("");
+}
+
+# fping --icmp-timestamp ::1
+SKIP: {
+    if($ENV{SKIP_IPV6}) {
+        skip 'Skip IPv6 tests', 3;
+    }
+    my $cmd = Test::Command->new(cmd => "fping --icmp-timestamp ::1");
+    $cmd->exit_is_num(2);
+    $cmd->stdout_is_eq("");
+    $cmd->stderr_like(qr{^::1:.*(not supported|not known)});
+}
+
+# fping --print-ttl with IPv6
+SKIP: {
+    if($ENV{SKIP_IPV6}) {
+        skip 'Skip IPv6 tests', 3;
+    }
+    my $cmd = Test::Command->new(cmd => "fping --print-ttl ::1");
+    $cmd->exit_is_num(0);
+    $cmd->stdout_like(qr{::1 is alive \(TTL unknown\)\n});
+    $cmd->stderr_is_eq("");
+}
+
+# fping -A
+{
+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("");
+}
+
+# fping -b
+{
+my $cmd = Test::Command->new(cmd => "fping -b 1000 127.0.0.1");
+$cmd->exit_is_num(0);
+$cmd->stdout_is_eq("127.0.0.1 is alive\n");
+$cmd->stderr_is_eq("");
+}
+
+# fping --icmp-timestamp -b
+{
+my $cmd = Test::Command->new(cmd => "fping --icmp-timestamp -b 1000 127.0.0.1");
+$cmd->exit_is_num(1);
+$cmd->stdout_is_eq("");
+$cmd->stderr_like(qr{cannot change ICMP Timestamp size});
+}
+
+# fping -b --icmp-timestamp
+{
+my $cmd = Test::Command->new(cmd => "fping -b 1000 --icmp-timestamp 127.0.0.1");
+$cmd->exit_is_num(1);
+$cmd->stdout_is_eq("");
+$cmd->stderr_like(qr{cannot change ICMP Timestamp size});
+}
+
+# fping --icmp-timestamp -b 12 (ICMP Timestamp data size)
+{
+my $cmd = Test::Command->new(cmd => "fping --icmp-timestamp -b 12 127.0.0.1");
+$cmd->exit_is_num(1);
+$cmd->stdout_is_eq("");
+$cmd->stderr_like(qr{cannot change ICMP Timestamp size});
+}
+
+# fping -6 --icmp-timestamp
+SKIP: {
+    if($ENV{SKIP_IPV6}) {
+        skip 'Skip IPv6 tests', 3;
+    }
+    my $cmd = Test::Command->new(cmd => "fping -6 --icmp-timestamp ::1");
+    $cmd->exit_is_num(1);
+    $cmd->stdout_is_eq("");
+    $cmd->stderr_like(qr{ICMP Timestamp is IPv4 only});
+}
+
+# fping --icmp-timestamp -6
+SKIP: {
+    if($ENV{SKIP_IPV6}) {
+        skip 'Skip IPv6 tests', 3;
+    }
+    my $cmd = Test::Command->new(cmd => "fping --icmp-timestamp -6 ::1");
+    $cmd->exit_is_num(1);
+    $cmd->stdout_is_eq("");
+    $cmd->stderr_is_eq("fping: can't specify both -4 and -6\n");
+}
+
+# fping -B
+SKIP: {
+    if($^O eq 'darwin') {
+        skip 'timing test not reliable on macOS', 5;
+    }
+    my $t0 = [gettimeofday];
+    my $cmd = Test::Command->new(cmd => "fping  -t 100 -r 3 -B 2  8.8.8.7");
+    $cmd->exit_is_num(1);
+    $cmd->stdout_is_eq("8.8.8.7 is unreachable\n");
+    $cmd->stderr_like(qr{^(|(8.8.8.7: error while sending ping: No route to host\n)+)$});
+    my $elapsed = tv_interval($t0);
+    # 0.1 + 0.2 + 0.4 + 0.8 = 1.5
+    cmp_ok($elapsed, '>=', 1.5);
+    cmp_ok($elapsed, '<', 1.9);
+}
diff --git a/ci/tmp.VwGIuQgZdr/fping-5.4/ci/test-05-options-c-e.pl b/ci/tmp.VwGIuQgZdr/fping-5.4/ci/test-05-options-c-e.pl
new file mode 100755 (executable)
index 0000000..d1cc767
--- /dev/null
@@ -0,0 +1,365 @@
+#!/usr/bin/perl -w
+
+use Test::Command tests => 87;
+use Test::More;
+
+#  -c n           count of pings to send to each target (default 1)
+#  -C n           same as -c, report results in verbose format
+#  --check-source discard replies not from target address
+#  -d             reverse name lookup
+#  -D             print timestamp before each output line
+#  -e             show elapsed time on return packets
+
+# fping -c n
+{
+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\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\)
+127\.0\.0\.1 : \[0\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\)
+localhost : \[1\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\)
+127\.0\.0\.1 : \[1\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\)
+});
+
+$cmd->stderr_like(qr{localhost : xmt/rcv/%loss = 2/2/0%, min/avg/max = \d\.\d+/\d\.\d+/\d\.\d+
+127\.0\.0\.1 : xmt/rcv/%loss = 2/2/0%, min/avg/max = \d\.\d+/\d\.\d+/\d\.\d+
+});
+}
+
+# fping -c n --print-tos --print-ttl
+{
+my $cmd = Test::Command->new(cmd => "fping -4 -c 2 -p 100 --print-tos --print-ttl localhost 127.0.0.1");
+$cmd->exit_is_num(0);
+$cmd->stdout_like(qr{localhost : \[0\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\) \(TOS \d+\) \(TTL \d+\)
+127\.0\.0\.1 : \[0\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\) \(TOS \d+\) \(TTL \d+\)
+localhost : \[1\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\) \(TOS \d+\) \(TTL \d+\)
+127\.0\.0\.1 : \[1\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\) \(TOS \d+\) \(TTL \d+\)
+});
+
+$cmd->stderr_like(qr{localhost : xmt/rcv/%loss = 2/2/0%, min/avg/max = \d\.\d+/\d\.\d+/\d\.\d+
+127\.0\.0\.1 : xmt/rcv/%loss = 2/2/0%, min/avg/max = \d\.\d+/\d\.\d+/\d\.\d+
+});
+}
+
+# fping -c n -q
+{
+my $cmd = Test::Command->new(cmd => "fping -q -c 2 -p 100 localhost 127.0.0.1");
+$cmd->exit_is_num(0);
+$cmd->stdout_is_eq("");
+$cmd->stderr_like(qr{localhost : xmt/rcv/%loss = 2/2/0%, min/avg/max = \d\.\d+/\d\.\d+/\d\.\d+
+127\.0\.0\.1 : xmt/rcv/%loss = 2/2/0%, min/avg/max = \d\.\d+/\d\.\d+/\d\.\d+
+});
+}
+
+# fping -c n -a (-a is ignored)
+{
+my $cmd = Test::Command->new(cmd => "fping -a -c 2 -p 100 localhost 127.0.0.1");
+$cmd->exit_is_num(0);
+$cmd->stdout_like(qr{localhost : \[0\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\)
+127\.0\.0\.1 : \[0\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\)
+localhost : \[1\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\)
+127\.0\.0\.1 : \[1\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\)
+});
+
+$cmd->stderr_like(qr{localhost : xmt/rcv/%loss = 2/2/0%, min/avg/max = \d\.\d+/\d\.\d+/\d\.\d+
+127\.0\.0\.1 : xmt/rcv/%loss = 2/2/0%, min/avg/max = \d\.\d+/\d\.\d+/\d\.\d+
+});
+}
+
+# fping -c n -u (-u is ignored)
+{
+my $cmd = Test::Command->new(cmd => "fping -u -c 2 -p 100 localhost 127.0.0.1");
+$cmd->exit_is_num(0);
+$cmd->stdout_like(qr{localhost : \[0\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\)
+127\.0\.0\.1 : \[0\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\)
+localhost : \[1\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\)
+127\.0\.0\.1 : \[1\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\)
+});
+
+$cmd->stderr_like(qr{localhost : xmt/rcv/%loss = 2/2/0%, min/avg/max = \d\.\d+/\d\.\d+/\d\.\d+
+127\.0\.0\.1 : xmt/rcv/%loss = 2/2/0%, min/avg/max = \d\.\d+/\d\.\d+/\d\.\d+
+});
+}
+
+# fping -c n ff02::1
+SKIP: {
+    if($ENV{SKIP_IPV6}) {
+        skip 'Skip IPv6 tests', 3;
+    }
+    my $cmd = Test::Command->new(cmd => "fping -c 1 ff02::1");
+    $cmd->exit_is_num(0);
+    $cmd->stdout_like(qr{ff02::1 : \[0\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\)\n});
+    $cmd->stderr_like(qr{ \[<- .*\]
+ff02::1 : xmt/rcv/%loss = 1/1/0%, min/avg/max = \d\.\d+/\d\.\d+/\d\.\d+\n});
+}
+
+# fping --icmp-timestamp -c n 127.0.0.1
+SKIP: {
+if($^O eq 'darwin') {
+    skip 'On macOS, this test is unreliable', 3;
+}
+my $cmd = Test::Command->new(cmd => "fping -4 --icmp-timestamp -c 2 127.0.0.1");
+$cmd->exit_is_num(0);
+$cmd->stdout_like(qr{127\.0\.0\.1 : \[0\], 20 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\), timestamps: Originate=\d+ Receive=\d+ Transmit=\d+ Localreceive=\d+
+127\.0\.0\.1 : \[1\], 20 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\), timestamps: Originate=\d+ Receive=\d+ Transmit=\d+ Localreceive=\d+
+});
+
+$cmd->stderr_like(qr{127\.0\.0\.1 : xmt/rcv/%loss = 2/2/0%, min/avg/max = \d\.\d+/\d\.\d+/\d\.\d+
+});
+}
+
+# fping --icmp-timestamp --print-tos --print-ttl -c n 127.0.0.1
+SKIP: {
+if($^O eq 'darwin') {
+    skip 'On macOS, this test is unreliable', 3;
+}
+my $cmd = Test::Command->new(cmd => "fping -4 --icmp-timestamp --print-tos --print-ttl -p 100 -c 2 127.0.0.1");
+$cmd->exit_is_num(0);
+$cmd->stdout_like(qr{127\.0\.0\.1 : \[0\], 20 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\), timestamps: Originate=\d+ Receive=\d+ Transmit=\d+ Localreceive=\d+ \(TOS \d+\) \(TTL \d+\)
+127\.0\.0\.1 : \[1\], 20 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\), timestamps: Originate=\d+ Receive=\d+ Transmit=\d+ Localreceive=\d+ \(TOS \d+\) \(TTL \d+\)
+});
+
+$cmd->stderr_like(qr{127\.0\.0\.1 : xmt/rcv/%loss = 2/2/0%, min/avg/max = \d\.\d+/\d\.\d+/\d\.\d+
+});
+}
+
+# fping -C n
+{
+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\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\)
+127\.0\.0\.1 : \[0\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\)
+localhost : \[1\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\)
+127\.0\.0\.1 : \[1\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\)
+});
+
+$cmd->stderr_like(qr{localhost : \d\.\d+ \d\.\d+
+127\.0\.0\.1 : \d\.\d+ \d\.\d+
+});
+}
+
+# fping -C n --print-tos --print-ttl
+{
+my $cmd = Test::Command->new(cmd => "fping -4 -C 2 -p 100 --print-tos --print-ttl localhost 127.0.0.1");
+$cmd->exit_is_num(0);
+$cmd->stdout_like(qr{localhost : \[0\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\) \(TOS \d+\) \(TTL \d+\)
+127\.0\.0\.1 : \[0\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\) \(TOS \d+\) \(TTL \d+\)
+localhost : \[1\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\) \(TOS \d+\) \(TTL \d+\)
+127\.0\.0\.1 : \[1\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\) \(TOS \d+\) \(TTL \d+\)
+});
+
+$cmd->stderr_like(qr{localhost : \d\.\d+ \d\.\d+
+127\.0\.0\.1 : \d\.\d+ \d\.\d+
+});
+}
+
+# fping -C n -q
+{
+my $cmd = Test::Command->new(cmd => "fping -C 5 -q -p 100 localhost");
+$cmd->exit_is_num(0);
+$cmd->stdout_is_eq("");
+$cmd->stderr_like(qr{localhost :( \d\.\d+){5}
+});
+}
+
+# fping -C n -a (-a is ignored)
+{
+my $cmd = Test::Command->new(cmd => "fping -a -C 2 -p 100 localhost 127.0.0.1");
+$cmd->exit_is_num(0);
+$cmd->stdout_like(qr{localhost : \[0\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\)
+127\.0\.0\.1 : \[0\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\)
+localhost : \[1\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\)
+127\.0\.0\.1 : \[1\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\)
+});
+
+$cmd->stderr_like(qr{localhost : \d\.\d+ \d\.\d+
+127\.0\.0\.1 : \d\.\d+ \d\.\d+
+});
+}
+
+# fping -C n -u (-u is ignored)
+{
+my $cmd = Test::Command->new(cmd => "fping -u -C 2 -p 100 localhost 127.0.0.1");
+$cmd->exit_is_num(0);
+$cmd->stdout_like(qr{localhost : \[0\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\)
+127\.0\.0\.1 : \[0\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\)
+localhost : \[1\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\)
+127\.0\.0\.1 : \[1\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\)
+});
+
+$cmd->stderr_like(qr{localhost : \d\.\d+ \d\.\d+
+127\.0\.0\.1 : \d\.\d+ \d\.\d+
+});
+}
+
+# fping -C n -i -q
+{
+my $cmd = Test::Command->new(cmd => "fping --quiet --interval=1 --vcount=20 --period=50 127.0.0.1 127.0.0.2");
+$cmd->exit_is_num(0);
+$cmd->stdout_is_eq("");
+$cmd->stderr_like(qr{127\.0\.0\.1 :( \d\.\d+){20}
+127\.0\.0\.2 :( \d\.\d+){20}
+});
+}
+
+# fping -C n ff02::1
+SKIP: {
+    if($ENV{SKIP_IPV6}) {
+        skip 'Skip IPv6 tests', 3;
+    }
+    my $cmd = Test::Command->new(cmd => "fping -C 1 ff02::1");
+    $cmd->exit_is_num(0);
+    $cmd->stdout_like(qr{ff02::1 : \[0\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\)\n});
+    $cmd->stderr_like(qr{ \[<- .*\]\nff02::1 : \d\.\d+\n});
+}
+
+# fping --check-source
+{
+my $cmd = Test::Command->new(cmd => "fping --check-source 127.0.0.1 127.0.0.2");
+$cmd->exit_is_num(0);
+$cmd->stdout_is_eq("127.0.0.1 is alive\n127.0.0.2 is alive\n");
+$cmd->stderr_is_eq("");
+}
+
+# fping --check-source (to IPv6 multicast address -> accept no reply)
+SKIP: {
+    if($ENV{SKIP_IPV6}) {
+        skip 'Skip IPv6 tests', 3;
+    }
+    my $cmd = Test::Command->new(cmd => "fping --check-source ff02::1");
+    $cmd->exit_is_num(1);
+    $cmd->stdout_is_eq("ff02::1 is unreachable\n");
+    $cmd->stderr_is_eq("");
+}
+
+# fping -c N --check-source
+SKIP: {
+    if($ENV{SKIP_IPV6}) {
+        skip 'Skip IPv6 tests', 3;
+    }
+    my $cmd = Test::Command->new(cmd => "fping -c1 --check-source 127.0.0.1 ff02::1");
+    $cmd->exit_is_num(1);
+    $cmd->stdout_like(qr{127\.0\.0\.1 : \[0\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\)
+ff02::1   : \[0\], timed out \(NaN avg, 100% loss\)
+});
+    $cmd->stderr_like(qr{
+127\.0\.0\.1 : xmt/rcv/%loss = 1/1/0%, min/avg/max = \d\.\d+/\d\.\d+/\d\.\d+
+ff02::1   : xmt/rcv/%loss = 1/0/100%
+});
+}
+
+# fping -C N --check-source
+SKIP: {
+    if($ENV{SKIP_IPV6}) {
+        skip 'Skip IPv6 tests', 3;
+    }
+    my $cmd = Test::Command->new(cmd => "fping -C1 --check-source 127.0.0.1 ff02::1");
+    $cmd->exit_is_num(1);
+    $cmd->stdout_like(qr{127\.0\.0\.1 : \[0\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\)
+ff02::1   : \[0\], timed out \(NaN avg, 100% loss\)
+});
+    $cmd->stderr_like(qr{
+127\.0\.0\.1 : \d\.\d+
+ff02::1   : -
+});
+}
+
+# fping -d
+{
+my $cmd = Test::Command->new(cmd => "fping -d 127.0.0.1");
+$cmd->exit_is_num(0);
+$cmd->stdout_is_eq("localhost is alive\n");
+$cmd->stderr_is_eq("");
+}
+
+# fping -D
+{
+my $cmd = Test::Command->new(cmd => "fping -D -c 2 -p 100 127.0.0.1");
+$cmd->exit_is_num(0);
+$cmd->stdout_like(qr{\[\d+\.\d+\] 127\.0\.0\.1 : \[0\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\)
+\[\d+\.\d+\] 127\.0\.0\.1 : \[1\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\)
+});
+
+$cmd->stderr_like(qr{127\.0\.0\.1 : xmt/rcv/%loss = 2/2/0%, min/avg/max = \d\.\d+/\d\.\d+/\d\.\d+
+});
+}
+
+# fping -D (timestamp not before 2001-09-09)
+{
+my $cmd = Test::Command->new(cmd => "fping -D -c 2 -p 100 127.0.0.1");
+$cmd->exit_is_num(0);
+$cmd->stdout_like(qr{\[[1-9]\d{9,}\.\d+\] 127\.0\.0\.1 : \[0\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\)
+\[[1-9]\d{9,}\.\d+\] 127\.0\.0\.1 : \[1\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\)
+});
+$cmd->stderr_like(qr{127\.0\.0\.1 : xmt/rcv/%loss = 2/2/0%, min/avg/max = \d\.\d+/\d\.\d+/\d\.\d+
+});
+}
+
+# fping -D --timestamp-format=ctime
+{
+my $cmd = Test::Command->new(cmd => "fping -D --timestamp-format=ctime -c 2 -p 100 127.0.0.1");
+$cmd->exit_is_num(0);
+$cmd->stdout_like(qr{\[\w+\s\w+\s+\d+\s[\d+:]+\s\d+\] 127\.0\.0\.1 : \[0\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\)
+\[\w+\s\w+\s+\d+\s[\d+:]+\s\d+\] 127\.0\.0\.1 : \[1\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\)
+});
+
+$cmd->stderr_like(qr{127\.0\.0\.1 : xmt/rcv/%loss = 2/2/0%, min/avg/max = \d\.\d+/\d\.\d+/\d\.\d+
+});
+}
+
+# fping -D --timestamp-format=iso
+{
+my $cmd = Test::Command->new(cmd => "fping -D --timestamp-format=iso -c 2 -p 100 127.0.0.1");
+$cmd->exit_is_num(0);
+$cmd->stdout_like(qr{\[[\d+-]+T[\d+:]+\+\d+\] 127\.0\.0\.1 : \[0\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\)
+\[[\d+-]+T[\d+:]+\+\d+\] 127\.0\.0\.1 : \[1\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\)
+});
+
+$cmd->stderr_like(qr{127\.0\.0\.1 : xmt/rcv/%loss = 2/2/0%, min/avg/max = \d\.\d+/\d\.\d+/\d\.\d+
+});
+}
+
+# fping -D --timestamp-format=rfc3339
+{
+my $cmd = Test::Command->new(cmd => "fping -D --timestamp-format=rfc3339 -c 2 -p 100 127.0.0.1");
+$cmd->exit_is_num(0);
+$cmd->stdout_like(qr{\[[\d+-]+\s[\d+:]+\] 127\.0\.0\.1 : \[0\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\)
+\[[\d+-]+\s[\d+:]+\] 127\.0\.0\.1 : \[1\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\)
+});
+
+$cmd->stderr_like(qr{127\.0\.0\.1 : xmt/rcv/%loss = 2/2/0%, min/avg/max = \d\.\d+/\d\.\d+/\d\.\d+
+});
+}
+
+# fping -D --timestamp-format
+{
+my $cmd = Test::Command->new(cmd => "fping -D --timestamp-format -c 2 -p 100 127.0.0.1");
+$cmd->exit_is_num(1);
+$cmd->stdout_is_eq("");
+$cmd->stderr_like(qr{Usage:});
+}
+
+# fping -D --timestamp-format="%Y-%m-%d %H:%M:%S"
+{
+my $cmd = Test::Command->new(cmd => "fping -D --timestamp-format=\"%Y-%m-%d %H:%M:%S\" -c 2 -p 100 127.0.0.1");
+$cmd->exit_is_num(1);
+$cmd->stdout_is_eq("");
+$cmd->stderr_like(qr{Usage:});
+}
+
+# fping -e
+{
+my $cmd = Test::Command->new(cmd => "fping -e 127.0.0.1");
+$cmd->exit_is_num(0);
+$cmd->stdout_like(qr{127\.0\.0\.1 is alive \(\d\.\d+ ms\)
+});
+$cmd->stderr_is_eq("");
+}
+
+# fping -e -a
+{
+my $cmd = Test::Command->new(cmd => "fping -e -a 127.0.0.1");
+$cmd->exit_is_num(0);
+$cmd->stdout_like(qr{127\.0\.0\.1 \(\d\.\d+ ms\)
+});
+$cmd->stderr_is_eq("");
+}
diff --git a/ci/tmp.VwGIuQgZdr/fping-5.4/ci/test-06-options-f-h.pl b/ci/tmp.VwGIuQgZdr/fping-5.4/ci/test-06-options-f-h.pl
new file mode 100755 (executable)
index 0000000..c9b520a
--- /dev/null
@@ -0,0 +1,231 @@
+#!/usr/bin/perl -w
+
+use Test::Command tests => 75;
+use Test::More;
+use File::Temp;
+
+#  -f file    read list of targets from a file ( - means stdin) (only if no -g specified)
+#  -g         generate target list (only if no -f specified)
+#               (specify the start and end IP in the target list, or supply a IP netmask)
+#               (ex. ../src/fping -g 192.168.1.0 192.168.1.255 or ../src/fping -g 192.168.1.0/24)
+#  -H n       Set the IP TTL value (Time To Live hops)
+
+my $tmpfile = File::Temp->new();
+print $tmpfile "127.0.0.1\n127.0.0.2\n";
+close($tmpfile);
+
+my $tmpfile2 = File::Temp->new();
+print $tmpfile2 "# comment\n127.0.0.1\n\n127.0.0.2\n";
+close($tmpfile2);
+
+# fping without option (-> equivalent to 'fping -f -')
+{
+my $cmd = Test::Command->new(cmd => "cat ".$tmpfile->filename." | fping");
+$cmd->exit_is_num(0);
+$cmd->stdout_is_eq("127.0.0.1 is alive\n127.0.0.2 is alive\n");
+$cmd->stderr_is_eq("");
+}
+
+# fping -f -
+{
+my $cmd = Test::Command->new(cmd => "cat ".$tmpfile->filename." | fping -f -");
+$cmd->exit_is_num(0);
+$cmd->stdout_is_eq("127.0.0.1 is alive\n127.0.0.2 is alive\n");
+$cmd->stderr_is_eq("");
+}
+
+# fping -f file
+{
+my $cmd = Test::Command->new(cmd => "fping -f ".$tmpfile->filename);
+$cmd->exit_is_num(0);
+$cmd->stdout_is_eq("127.0.0.1 is alive\n127.0.0.2 is alive\n");
+$cmd->stderr_is_eq("");
+}
+
+# fping -f file (with comment and empty line)
+{
+my $cmd = Test::Command->new(cmd => "fping -f ".$tmpfile2->filename);
+$cmd->exit_is_num(0);
+$cmd->stdout_is_eq("127.0.0.1 is alive\n127.0.0.2 is alive\n");
+$cmd->stderr_is_eq("");
+}
+
+# fping -f non-existing-file (error)
+{
+my $cmd = Test::Command->new(cmd => "fping -f file-does-not-exist");
+$cmd->exit_is_num(4);
+$cmd->stdout_is_eq("");
+$cmd->stderr_like(qr{: fopen :});
+}
+
+# fping -g (error: no argument)
+{
+my $cmd = Test::Command->new(cmd => "fping -g");
+$cmd->exit_is_num(1);
+$cmd->stdout_is_eq("");
+$cmd->stderr_like(qr{^Usage: fping \[options\] \[targets\.\.\.\]});
+}
+
+# fping -g (error: single argument, but not in cidr format)
+{
+my $cmd = Test::Command->new(cmd => "fping -g 127.0.0.1");
+$cmd->exit_is_num(1);
+$cmd->stdout_is_eq("");
+$cmd->stderr_like(qr{^Usage: fping \[options\] \[targets\.\.\.\]});
+}
+
+# fping -g (error: CIDR network is not an IP address)
+{
+my $cmd = Test::Command->new(cmd => "fping -g xxx/32");
+$cmd->exit_is_num(1);
+$cmd->stdout_is_eq("");
+$cmd->stderr_like(qr{can't parse address xxx});
+}
+
+# fping -g (error: start of range is not an IP address)
+{
+my $cmd = Test::Command->new(cmd => "fping -g xxx 127.0.0.1");
+$cmd->exit_is_num(1);
+$cmd->stdout_is_eq("");
+$cmd->stderr_like(qr{can't parse address xxx});
+}
+
+# fping -g (error: end of range is not an IP address)
+{
+my $cmd = Test::Command->new(cmd => "fping -g 127.0.0.1 yyy");
+$cmd->exit_is_num(1);
+$cmd->stdout_is_eq("");
+$cmd->stderr_like(qr{can't parse address yyy});
+}
+
+# fping -g (error: too many arguments)
+{
+my $cmd = Test::Command->new(cmd => "fping -g 127.0.0.1 127.0.0.2 127.0.0.3");
+$cmd->exit_is_num(1);
+$cmd->stdout_is_eq("");
+$cmd->stderr_like(qr{^Usage: fping \[options\] \[targets\.\.\.\]});
+}
+
+# fping -g (range)
+{
+my $cmd = Test::Command->new(cmd => "fping -g 127.0.0.1 127.0.0.5");
+$cmd->exit_is_num(0);
+$cmd->stdout_is_eq("127.0.0.1 is alive\n127.0.0.2 is alive\n127.0.0.3 is alive\n127.0.0.4 is alive\n127.0.0.5 is alive\n");
+$cmd->stderr_is_eq("");
+}
+
+# fping -g (empty range)
+{
+my $cmd = Test::Command->new(cmd => "fping -g 127.0.0.2 127.0.0.1");
+$cmd->exit_is_num(1);
+$cmd->stdout_is_eq("");
+$cmd->stderr_is_eq("");
+}
+
+# fping -g (too large range)
+{
+my $cmd = Test::Command->new(cmd => "fping -g 127.0.0.1 127.255.255.254");
+$cmd->exit_is_num(1);
+$cmd->stdout_is_eq("");
+$cmd->stderr_is_eq("fping: -g parameter generates too many addresses\n");
+}
+
+# fping -g (cidr)
+{
+my $cmd = Test::Command->new(cmd => "fping -g 127.0.0.1/30");
+$cmd->exit_is_num(0);
+$cmd->stdout_is_eq("127.0.0.1 is alive\n127.0.0.2 is alive\n");
+$cmd->stderr_is_eq("");
+}
+
+# fping -g (cidr - long prefixes: point-to-point)
+{
+my $cmd = Test::Command->new(cmd => "fping -g 127.0.0.2/31");
+$cmd->exit_is_num(0);
+$cmd->stdout_is_eq("127.0.0.2 is alive\n127.0.0.3 is alive\n");
+$cmd->stderr_is_eq("");
+}
+
+# fping -g (cidr - long prefixes: host)
+{
+my $cmd = Test::Command->new(cmd => "fping -g 127.0.0.2/32");
+$cmd->exit_is_num(0);
+$cmd->stdout_is_eq("127.0.0.2 is alive\n");
+$cmd->stderr_is_eq("");
+}
+
+# fping -g (cidr - too long prefixes)
+{
+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("fping: netmask must be between 1 and 32 (is: 33)\n");
+}
+
+# fping -g (cidr - too short prefixes)
+{
+my $cmd = Test::Command->new(cmd => "fping -g 127.0.0.2/0");
+$cmd->exit_is_num(1);
+$cmd->stdout_is_eq("");
+$cmd->stderr_is_eq("fping: netmask must be between 1 and 32 (is: 0)\n");
+}
+
+# fping -g (cidr - too many addresses)
+{
+my $cmd = Test::Command->new(cmd => "fping -g 127.0.0.0/8");
+$cmd->exit_is_num(1);
+$cmd->stdout_is_eq("");
+$cmd->stderr_is_eq("fping: -g parameter generates too many addresses\n");
+}
+
+# fping -g (range - no IPv6 generator)
+SKIP: {
+    if($ENV{SKIP_IPV6}) {
+        skip 'Skip IPv6 tests', 3;
+    }
+    my $cmd = Test::Command->new(cmd => "fping -6 -g ::1 ::1");
+    $cmd->exit_is_num(1);
+    $cmd->stdout_is_eq("");
+    $cmd->stderr_is_eq("fping: -g works only with IPv4 addresses\n");
+}
+
+# fping -g (range - no IPv6 generator - start address IPv6)
+SKIP: {
+    if($ENV{SKIP_IPV6}) {
+        skip 'Skip IPv6 tests', 3;
+    }
+    my $cmd = Test::Command->new(cmd => "fping -6 -g ::1 127.0.0.1");
+    $cmd->exit_is_num(1);
+    $cmd->stdout_is_eq("");
+    $cmd->stderr_is_eq("fping: -g works only with IPv4 addresses\n");
+}
+
+# fping -g (range - no IPv6 generator - end address IPv6)
+SKIP: {
+    if($ENV{SKIP_IPV6}) {
+        skip 'Skip IPv6 tests', 3;
+    }
+    my $cmd = Test::Command->new(cmd => "fping -6 -g 127.0.0.1 ::1");
+    $cmd->exit_is_num(1);
+    $cmd->stdout_is_eq("");
+    $cmd->stderr_is_eq("fping: -g works only with IPv4 addresses\n");
+}
+
+# fping -g (CIDR - no IPv6 generator)
+SKIP: {
+    if($ENV{SKIP_IPV6}) {
+        skip 'Skip IPv6 tests', 3;
+    }
+    my $cmd = Test::Command->new(cmd => "fping -6 -g ::1/128");
+    $cmd->exit_is_num(1);
+    $cmd->stdout_is_eq("");
+    $cmd->stderr_is_eq("fping: -g works only with IPv4 addresses\n");
+}
+
+# fping -H
+{
+my $cmd = Test::Command->new(cmd => "fping -H 1 127.0.0.1");
+$cmd->exit_is_num(0);
+$cmd->stdout_is_eq("127.0.0.1 is alive\n");
+$cmd->stderr_is_eq("");
+}
diff --git a/ci/tmp.VwGIuQgZdr/fping-5.4/ci/test-07-options-i-m.pl b/ci/tmp.VwGIuQgZdr/fping-5.4/ci/test-07-options-i-m.pl
new file mode 100755 (executable)
index 0000000..426286a
--- /dev/null
@@ -0,0 +1,94 @@
+#!/usr/bin/perl -w
+
+use Test::Command tests => 16;
+use Test::More;
+
+#  -i n       interval between sending ping packets (in millisec) (default 25)
+#  -l         loop sending pings forever
+#  -k         set fwmark on ping packets
+#  -m         ping multiple interfaces on target host
+#  -M         don't fragment
+
+# fping -i n
+{
+my $cmd = Test::Command->new(cmd => "fping -i 100 127.0.0.1 127.0.0.2");
+$cmd->exit_is_num(0);
+$cmd->stdout_is_eq("127.0.0.1 is alive\n127.0.0.2 is alive\n");
+$cmd->stderr_is_eq("");
+}
+
+# fping -l
+{
+my $cmd = Test::Command->new(cmd => '(sleep 2; pkill fping)& fping -p 900 -l 127.0.0.1');
+$cmd->stdout_like(qr{127\.0\.0\.1 : \[0\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\)
+127\.0\.0\.1 : \[1\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\)
+});
+}
+
+# fping -l --print-tos --print-ttl
+{
+my $cmd = Test::Command->new(cmd => '(sleep 2; pkill fping)& fping -p 900 --print-ttl --print-tos -l 127.0.0.1');
+$cmd->stdout_like(qr{127\.0\.0\.1 : \[0\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\) \(TOS \d+\) \(TTL \d+\)
+127\.0\.0\.1 : \[1\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\) \(TOS \d+\) \(TTL \d+\)
+});
+}
+
+# fping -k
+SKIP: {
+if($^O ne 'linux') {
+    skip '-k option is only supported on Linux', 3;
+}
+my $cmd = Test::Command->new(cmd => 'fping -k 256 127.0.0.1');
+$cmd->exit_is_num(0);
+$cmd->stdout_is_eq("127.0.0.1 is alive\n");
+$cmd->stderr_is_eq("");
+}
+
+# fping -l with SIGQUIT
+{
+my $cmd = Test::Command->new(cmd => '(sleep 2; pkill -QUIT fping; sleep 2; pkill fping)& fping -p 900 -l 127.0.0.1');
+$cmd->stdout_like(qr{127\.0\.0\.1 : \[0\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\)
+127\.0\.0\.1 : \[1\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\)
+127\.0\.0\.1 : \[2\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\)
+127\.0\.0\.1 : \[3\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\)
+127\.0\.0\.1 : \[4\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\)
+});
+$cmd->stderr_like(qr{\[\d+:\d+:\d+\]
+127\.0\.0\.1 : xmt/rcv/%loss = \d+/\d+/\d+%, min/avg/max = \d+\.\d+/\d+\.\d+/\d+\.\d+
+});
+}
+
+# fping -l -Q
+SKIP: {
+if($^O eq 'darwin') {
+    skip 'On macOS, this test is unreliable', 2;
+}
+my $cmd = Test::Command->new(cmd => '(sleep 2; pkill fping)& fping -p 850 -l -Q 1 127.0.0.1');
+$cmd->stdout_is_eq("");
+$cmd->stderr_like(qr{\[\d\d:\d\d:\d\d\]
+127\.0\.0\.1 : xmt/rcv/%loss = \d/\d/\d%, min/avg/max = \d\.\d+/\d\.\d+/\d\.\d+
+\[\d\d:\d\d:\d\d\]
+127\.0\.0\.1 : xmt/rcv/%loss = \d/\d/\d%, min/avg/max = \d\.\d+/\d\.\d+/\d\.\d+
+});
+}
+
+# fping -l -t
+{
+my $cmd = Test::Command->new(cmd => '(sleep 2; pkill fping)& fping -p 900 -t 1500 -l 127.0.0.1');
+$cmd->stdout_like(qr{127\.0\.0\.1 : \[0\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\)
+127\.0\.0\.1 : \[1\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\)
+});
+}
+
+# fping -M
+SKIP: {
+    if($^O eq 'darwin') {
+        skip '-M option not supported on macOS', 3;
+    }
+    my $cmd = Test::Command->new(cmd => "fping -M 127.0.0.1");
+    $cmd->exit_is_num(0);
+    $cmd->stdout_is_eq("127.0.0.1 is alive\n");
+    $cmd->stderr_is_eq("");
+}
+
+# fping -m -> test-14-internet-hosts
diff --git a/ci/tmp.VwGIuQgZdr/fping-5.4/ci/test-08-options-n-q.pl b/ci/tmp.VwGIuQgZdr/fping-5.4/ci/test-08-options-n-q.pl
new file mode 100755 (executable)
index 0000000..d614db1
--- /dev/null
@@ -0,0 +1,187 @@
+#!/usr/bin/perl -w
+
+use Test::Command tests => 48;
+use Test::More;
+
+#  -n         show targets by name (-d is equivalent)
+#  -O n       set the type of service (tos) flag on the ICMP packets
+#  -p n       interval between ping packets to one target (in millisec)
+#               (in looping and counting modes, default 1000)
+#  -q         quiet (don't show per-target/per-ping results)
+#  -Q n       same as -q, but show summary every n seconds
+
+# fping -n -> test-14-internet-hosts
+
+# fping -d -n
+{
+my $cmd = Test::Command->new(cmd => "fping -d -n 127.0.0.1");
+$cmd->exit_is_num(1);
+$cmd->stdout_is_eq("");
+$cmd->stderr_is_eq("fping: use either one of -d or -n\n");
+}
+
+# fping -n -d
+{
+my $cmd = Test::Command->new(cmd => "fping -n -d 127.0.0.1");
+$cmd->exit_is_num(1);
+$cmd->stdout_is_eq("");
+$cmd->stderr_is_eq("fping: use either one of -d or -n\n");
+}
+
+# fping -o
+{
+my $cmd = Test::Command->new(cmd => "fping -t100 -p 100 -o -c 5 8.8.8.7");
+$cmd->exit_is_num(1);
+$cmd->stdout_is_eq("8.8.8.7 : [0], timed out (NaN avg, 100% loss)
+8.8.8.7 : [1], timed out (NaN avg, 100% loss)
+8.8.8.7 : [2], timed out (NaN avg, 100% loss)
+8.8.8.7 : [3], timed out (NaN avg, 100% loss)
+8.8.8.7 : [4], timed out (NaN avg, 100% loss)
+");
+$cmd->stderr_like(qr{^\s*8\.8\.8\.7 : xmt/rcv/%loss = 5/0/100%, outage\(ms\) = 50\d\s*$});
+}
+
+# fping -O
+{
+my $cmd = Test::Command->new(cmd => "fping -O 2 127.0.0.1");
+$cmd->exit_is_num(0);
+$cmd->stdout_is_eq("127.0.0.1 is alive\n");
+$cmd->stderr_is_eq("");
+}
+
+# fping -O --print-tos
+{
+my $cmd = Test::Command->new(cmd => "fping -O 2 --print-tos 127.0.0.1");
+$cmd->exit_is_num(0);
+$cmd->stdout_like(qr{127\.0\.0\.1 is alive \(TOS \d+\)
+});
+$cmd->stderr_is_eq("");
+}
+
+# fping -a -O --print-tos
+{
+my $cmd = Test::Command->new(cmd => "fping -a -O 32 --print-tos 127.0.0.1");
+$cmd->exit_is_num(0);
+$cmd->stdout_like(qr{127\.0\.0\.1 \(TOS \d+\)
+});
+$cmd->stderr_is_eq("");
+}
+
+# fping --print-tos
+{
+my $cmd = Test::Command->new(cmd => "fping --print-tos 127.0.0.1");
+$cmd->exit_is_num(0);
+$cmd->stdout_like(qr{127\.0\.0\.1 is alive \(TOS 0\)
+});
+$cmd->stderr_is_eq("");
+}
+
+# fping --print-tos with IPv6
+SKIP: {
+    if($ENV{SKIP_IPV6}) {
+        skip 'Skip IPv6 tests', 3;
+    }
+    my $cmd = Test::Command->new(cmd => "fping --print-tos ::1");
+    $cmd->exit_is_num(0);
+    $cmd->stdout_like(qr{::1 is alive \(TOS unknown\)\n});
+    $cmd->stderr_is_eq("");
+}
+
+# fping -q
+{
+my $cmd = Test::Command->new(cmd => "fping -q -p 100 -c 3 127.0.0.1");
+$cmd->exit_is_num(0);
+$cmd->stdout_is_eq("");
+$cmd->stderr_like(qr{127\.0\.0\.1 : xmt/rcv/%loss = 3/3/0%, min/avg/max = \d\.\d+/\d\.\d+/\d\.\d+
+});
+}
+
+# fping -Q
+{
+my $cmd = Test::Command->new(cmd => "fping -Q 1 -p 400 -c 4 127.0.0.1");
+$cmd->exit_is_num(0);
+$cmd->stdout_is_eq("");
+$cmd->stderr_like(qr{\[\d+:\d+:\d+\]
+127\.0\.0\.1 : xmt/rcv/%loss = 3/3/0%, min/avg/max = \d\.\d+/\d\.\d+/\d\.\d+
+127\.0\.0\.1 : xmt/rcv/%loss = 4/4/0%, min/avg/max = \d\.\d+/\d\.\d+/\d\.\d+
+});
+}
+
+# fping -Q (longer test to show two time stamps and reset statistics)
+{
+my $cmd = Test::Command->new(cmd => "fping -Q 1 -p 550 -c 5 127.0.0.1");
+$cmd->exit_is_num(0);
+$cmd->stdout_is_eq("");
+$cmd->stderr_like(qr{\[\d+:\d+:\d+\]
+127\.0\.0\.1 : xmt/rcv/%loss = 2/2/0%, min/avg/max = \d\.\d+/\d\.\d+/\d\.\d+
+\[\d+:\d+:\d+\]
+127\.0\.0\.1 : xmt/rcv/%loss = 2/2/0%, min/avg/max = \d\.\d+/\d\.\d+/\d\.\d+
+127\.0\.0\.1 : xmt/rcv/%loss = 5/5/0%, min/avg/max = \d\.\d+/\d\.\d+/\d\.\d+
+});
+}
+
+# fping -Q n ignores non-number characters after the number, except for keywords
+{
+my $cmd = Test::Command->new(cmd => "fping -Q 1whatever -p 550 -c 5 127.0.0.1");
+$cmd->exit_is_num(0);
+$cmd->stdout_is_eq("");
+$cmd->stderr_like(qr{\[\d+:\d+:\d+\]
+127\.0\.0\.1 : xmt/rcv/%loss = 2/2/0%, min/avg/max = \d\.\d+/\d\.\d+/\d\.\d+
+\[\d+:\d+:\d+\]
+127\.0\.0\.1 : xmt/rcv/%loss = 2/2/0%, min/avg/max = \d\.\d+/\d\.\d+/\d\.\d+
+127\.0\.0\.1 : xmt/rcv/%loss = 5/5/0%, min/avg/max = \d\.\d+/\d\.\d+/\d\.\d+
+});
+}
+
+# fping -Q n ignores unknown keywords
+{
+my $cmd = Test::Command->new(cmd => "fping -Q 1,not_a_keyword -p 550 -c 5 127.0.0.1");
+$cmd->exit_is_num(0);
+$cmd->stdout_is_eq("");
+$cmd->stderr_like(qr{\[\d+:\d+:\d+\]
+127\.0\.0\.1 : xmt/rcv/%loss = 2/2/0%, min/avg/max = \d\.\d+/\d\.\d+/\d\.\d+
+\[\d+:\d+:\d+\]
+127\.0\.0\.1 : xmt/rcv/%loss = 2/2/0%, min/avg/max = \d\.\d+/\d\.\d+/\d\.\d+
+127\.0\.0\.1 : xmt/rcv/%loss = 5/5/0%, min/avg/max = \d\.\d+/\d\.\d+/\d\.\d+
+});
+}
+
+# fping -Q n,cumulative
+{
+my $cmd = Test::Command->new(cmd => "fping -Q 1,cumulative -p 550 -c 5 127.0.0.1");
+$cmd->exit_is_num(0);
+$cmd->stdout_is_eq("");
+$cmd->stderr_like(qr{\[\d+:\d+:\d+\]
+127\.0\.0\.1 : xmt/rcv/%loss = 2/2/0%, min/avg/max = \d\.\d+/\d\.\d+/\d\.\d+
+\[\d+:\d+:\d+\]
+127\.0\.0\.1 : xmt/rcv/%loss = 4/4/0%, min/avg/max = \d\.\d+/\d\.\d+/\d\.\d+
+127\.0\.0\.1 : xmt/rcv/%loss = 5/5/0%, min/avg/max = \d\.\d+/\d\.\d+/\d\.\d+
+});
+}
+
+# fping -Q -o
+{
+my $cmd = Test::Command->new(cmd => "fping -c4 -Q1 -p550 -o 8.8.8.7");
+$cmd->exit_is_num(1);
+$cmd->stdout_is_eq("");
+$cmd->stderr_like(qr{\[\d+:\d+:\d+\]
+8\.8\.8\.7 : xmt/rcv/%loss = 1/0/100%, outage\(ms\) = 55\d
+\[\d+:\d+:\d+\]
+8\.8\.8\.7 : xmt/rcv/%loss = 2/0/100%, outage\(ms\) = 110\d
+8\.8\.8\.7 : xmt/rcv/%loss = 4/0/100%, outage\(ms\) = 220\d
+});
+}
+
+# fping -Q n,cumulative -o
+{
+my $cmd = Test::Command->new(cmd => "fping -c4 -Q1,cumulative -p550 -o 8.8.8.7");
+$cmd->exit_is_num(1);
+$cmd->stdout_is_eq("");
+$cmd->stderr_like(qr{\[\d+:\d+:\d+\]
+8\.8\.8\.7 : xmt/rcv/%loss = 1/0/100%, outage\(ms\) = 55\d
+\[\d+:\d+:\d+\]
+8\.8\.8\.7 : xmt/rcv/%loss = 3/0/100%, outage\(ms\) = 165\d
+8\.8\.8\.7 : xmt/rcv/%loss = 4/0/100%, outage\(ms\) = 220\d
+});
+}
+
diff --git a/ci/tmp.VwGIuQgZdr/fping-5.4/ci/test-09-option-r-t.pl b/ci/tmp.VwGIuQgZdr/fping-5.4/ci/test-09-option-r-t.pl
new file mode 100755 (executable)
index 0000000..2c26d24
--- /dev/null
@@ -0,0 +1,149 @@
+#!/usr/bin/perl -w
+
+use Test::Command tests => 30;
+use Test::More;
+
+#  -R         random bytes
+#  -r n       number of retries (default 3)
+#  -s         print final stats
+#  -S addr    set source address
+#  -t n       individual target initial timeout (in millisec) (default 500)
+#  -T n       ignored (for compatibility with fping 2.4)
+
+# fping -R
+{
+my $cmd = Test::Command->new(cmd => "fping -q -R -c3 -p100 127.0.0.1");
+$cmd->exit_is_num(0);
+$cmd->stdout_is_eq("");
+$cmd->stderr_like(qr{127\.0\.0\.1 : xmt/rcv/%loss = 3/3/0%.*});
+}
+
+SKIP: {
+    if($ENV{SKIP_IPV6}) {
+        skip 'Skip IPv6 tests', 3;
+    }
+    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%.*});
+}
+
+# fping -r tested in test-4-options-a-b.pl
+
+# fping -s
+{
+my $cmd = Test::Command->new(cmd => "fping -s 127.0.0.1");
+$cmd->exit_is_num(0);
+$cmd->stdout_is_eq("127.0.0.1 is alive\n");
+$cmd->stderr_like(qr{\s*
+\s*1 targets
+\s*1 alive
+\s*0 unreachable
+\s*0 unknown addresses
+\s*
+\s*0 timeouts \(waiting for response\)
+\s*1 ICMP Echos sent
+\s*1 ICMP Echo Replies received
+\s*0 other ICMP received
+
+\s*\d\.\d+ ms \(min round trip time\)
+\s*\d\.\d+ ms \(avg round trip time\)
+\s*\d\.\d+ ms \(max round trip time\)
+\s*\d\.\d+ sec \(elapsed real time\)
+});
+}
+
+# fping -s (no host reachable)
+{
+my $cmd = Test::Command->new(cmd => "fping -r0 -t100 -s 8.8.0.0");
+$cmd->exit_is_num(1);
+$cmd->stdout_is_eq("8.8.0.0 is unreachable\n");
+$cmd->stderr_like(qr{\s*
+\s*1 targets
+\s*0 alive
+\s*1 unreachable
+\s*0 unknown addresses
+\s*
+\s*1 timeouts \(waiting for response\)
+\s*1 ICMP Echos sent
+\s*0 ICMP Echo Replies received
+\s*0 other ICMP received
+
+\s*\d\.\d+ ms \(min round trip time\)
+\s*\d\.\d+ ms \(avg round trip time\)
+\s*\d\.\d+ ms \(max round trip time\)
+\s*\d\.\d+ sec \(elapsed real time\)
+});
+}
+
+# fping -s (both valid and invalid host name)
+{
+my $cmd = Test::Command->new(cmd => "fping -s 127.0.0.1 host.name.invalid");
+$cmd->exit_is_num(2);
+$cmd->stdout_is_eq("127.0.0.1 is alive\n");
+$cmd->stderr_like(qr{host\.name\.invalid: .+
+\s*
+\s*1 targets
+\s*1 alive
+\s*0 unreachable
+\s*1 unknown addresses
+\s*
+\s*0 timeouts \(waiting for response\)
+\s*1 ICMP Echos sent
+\s*1 ICMP Echo Replies received
+\s*0 other ICMP received
+
+\s*\d\.\d+ ms \(min round trip time\)
+\s*\d\.\d+ ms \(avg round trip time\)
+\s*\d\.\d+ ms \(max round trip time\)
+\s*\d\.\d+ sec \(elapsed real time\)
+});
+}
+
+# fping -S
+{
+my $cmd = Test::Command->new(cmd => "fping -S 127.0.0.1 127.0.0.1");
+$cmd->exit_is_num(0);
+$cmd->stdout_is_eq("127.0.0.1 is alive\n");
+$cmd->stderr_is_eq("");
+}
+
+# fping -S (wrong source address)
+{
+my $cmd = Test::Command->new(cmd => "fping -S 192.0.2.47 127.0.0.1");
+$cmd->exit_is_num(4);
+$cmd->stdout_is_eq("");
+$cmd->stderr_like(qr{fping: cannot bind source address : .+\n});
+}
+
+# fping -S
+SKIP: {
+    if($ENV{SKIP_IPV6}) {
+        skip 'Skip IPv6 tests', 3;
+    }
+    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("");
+}
+
+# fping -S (wrong IPv6 source address)
+SKIP: {
+    if($ENV{SKIP_IPV6}) {
+        skip 'Skip IPv6 tests', 3;
+    }
+    my $cmd = Test::Command->new(cmd => "fping -S 2001:db8::1 ::1");
+    $cmd->exit_is_num(4);
+    $cmd->stdout_is_eq("");
+    $cmd->stderr_like(qr{fping: cannot bind source address : .+\n});
+}
+
+# fping -S
+{
+my $cmd = Test::Command->new(cmd => "fping -S bla");
+$cmd->exit_is_num(1);
+$cmd->stdout_is_eq("");
+$cmd->stderr_is_eq("fping: can't parse source address: bla\n");
+}
+
+# (note: fping -t also tested in test-4-options-a-b.pl)
diff --git a/ci/tmp.VwGIuQgZdr/fping-5.4/ci/test-10-option-u-x.pl b/ci/tmp.VwGIuQgZdr/fping-5.4/ci/test-10-option-u-x.pl
new file mode 100755 (executable)
index 0000000..db45737
--- /dev/null
@@ -0,0 +1,48 @@
+#!/usr/bin/perl -w
+
+use Test::Command tests => 15;
+
+#  -u         show targets that are unreachable
+#  -v         show version
+#  -x         shows if >=N hosts are reachable or not
+#  -X         exits true immediately when N hosts are found
+
+# fping -u
+{
+my $cmd = Test::Command->new(cmd => "fping -r0 -u 8.8.0.0 127.0.0.1");
+$cmd->exit_is_num(1);
+$cmd->stdout_is_eq("8.8.0.0\n");
+$cmd->stderr_is_eq("");
+}
+
+# fping -v
+{
+my $cmd = Test::Command->new(cmd => "fping -v");
+$cmd->exit_is_num(0);
+$cmd->stdout_like(qr{ping: Version [45]\.\d+(-rc\d+)?});
+$cmd->stderr_is_eq("");
+}
+
+# fping -x
+{
+my $cmd = Test::Command->new(cmd => "fping -x 1 8.8.0.0 127.0.0.1");
+$cmd->exit_is_num(0);
+$cmd->stdout_is_eq("Enough hosts reachable (required: 1, reachable: 1)\n");
+$cmd->stderr_is_eq("");
+}
+
+# fping -x
+{
+my $cmd = Test::Command->new(cmd => "fping -x 2 8.8.0.0 127.0.0.1");
+$cmd->exit_is_num(1);
+$cmd->stdout_is_eq("Not enough hosts reachable (required: 2, reachable: 1)\n");
+$cmd->stderr_is_eq("");
+}
+
+# fping -X
+{
+my $cmd = Test::Command->new(cmd => "fping -X 1 --generate 127.0.0.0/29");
+$cmd->exit_is_num(0);
+$cmd->stdout_is_eq("Enough hosts reachable (required: 1, reachable: 1)\n");
+$cmd->stderr_is_eq("");
+}
diff --git a/ci/tmp.VwGIuQgZdr/fping-5.4/ci/test-11-unpriv.pl b/ci/tmp.VwGIuQgZdr/fping-5.4/ci/test-11-unpriv.pl
new file mode 100755 (executable)
index 0000000..debf2af
--- /dev/null
@@ -0,0 +1,95 @@
+#!/usr/bin/perl -w
+
+use English;
+use File::Copy;
+use File::Temp qw/ tempdir /;
+use Test::Command;
+use Test::More;
+
+if( $^O eq 'darwin' ) {
+    plan skip_all => 'Test irrelevant on MacOS';
+    exit 0;
+}
+
+sub get_ping_gid_range {
+    open FD, "/proc/sys/net/ipv4/ping_group_range" or return undef;
+    chomp(my $line = <FD>);
+    my @range = split(/\s+/, $line);
+    close FD;
+    return @range;
+}
+
+my @gids = split(' ', $EGID);
+my @allowed = get_ping_gid_range();
+
+# Make a copy of the binary so that we get rid of setuid bit
+my $tmpdir = tempdir(CLEANUP => 1);
+my $fping_bin = `which fping`; chomp $fping_bin;
+my $fping_copy = "$tmpdir/fping.copy";
+copy($fping_bin, $fping_copy);
+chmod 0755, $fping_copy;
+
+# Determine what test to run, based on whether unprivileged
+# pings are allowed.
+if(scalar grep { $_ >= $allowed[0] && $_ <= $allowed[1] } @gids) {
+    diag('test unprivileged mode');
+    test_unprivileged_works();
+}
+else {
+    test_privileged_fails();
+}
+
+sub test_unprivileged_works {
+    plan tests => 15;
+
+    {
+        my $cmd = Test::Command->new(cmd => "$fping_copy 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_copy --print-tos 127.0.0.1");
+        $cmd->exit_is_num(0);
+        $cmd->stdout_is_eq("127.0.0.1 is alive (TOS unknown)\n");
+        $cmd->stderr_is_eq("");
+    }
+    {
+        my $cmd = Test::Command->new(cmd => "$fping_copy --print-ttl 127.0.0.1");
+        $cmd->exit_is_num(0);
+        $cmd->stdout_is_eq("127.0.0.1 is alive (TTL unknown)\n");
+        $cmd->stderr_is_eq("");
+    }
+    SKIP: {
+        if($^O ne 'linux') {
+            skip '-k option is only supported on Linux', 3;
+        }
+        my $cmd = Test::Command->new(cmd => "$fping_copy -4 -k 256 127.0.0.1");
+        $cmd->exit_is_num(0);
+        $cmd->stdout_is_eq("127.0.0.1 is alive\n");
+        $cmd->stderr_like(qr{fwmark ipv4: .+\n});
+    }
+    SKIP: {
+        if($^O ne 'linux') {
+            skip '-k option is only supported on Linux', 3;
+        }
+        if($ENV{SKIP_IPV6}) {
+            skip 'Skip IPv6 tests', 3;
+        }
+        my $cmd = Test::Command->new(cmd => "$fping_copy -6 -k 256 ::1");
+        $cmd->exit_is_num(0);
+        $cmd->stdout_is_eq("::1 is alive\n");
+        $cmd->stderr_like(qr{fwmark ipv6: .+\n});
+    }
+}
+
+sub test_privileged_fails {
+    plan tests => 3;
+
+    {
+        my $cmd = Test::Command->new(cmd => "$fping_copy 127.0.0.1");
+        $cmd->exit_is_num(4);
+        $cmd->stdout_is_eq("");
+        $cmd->stderr_like(qr{: can't create socket \(must run as root\?\)});
+    }
+}
diff --git a/ci/tmp.VwGIuQgZdr/fping-5.4/ci/test-12-option-type.pl b/ci/tmp.VwGIuQgZdr/fping-5.4/ci/test-12-option-type.pl
new file mode 100755 (executable)
index 0000000..6514425
--- /dev/null
@@ -0,0 +1,27 @@
+#!/usr/bin/perl -w
+
+use Test::Command tests => 84;
+use Test::More;
+
+# some options require a numeric argument
+for my $arg (qw(b B c C H i O p Q r t x X)) {
+    for my $test_input (qw(xxx '')) {
+        my $cmd = Test::Command->new(cmd => "fping -$arg $test_input");
+        $cmd->exit_is_num(1);
+        $cmd->stdout_is_eq("");
+        $cmd->stderr_like(qr{Usage:});
+    }
+}
+
+# fping -k, only supported on Linux, requires a number
+SKIP: {
+    if($^O ne 'linux') {
+        skip '-k option is only supported on Linux', 6;
+    }
+    for my $test_input (qw(xxx '')) {
+        my $cmd = Test::Command->new(cmd => "fping -k $test_input 127.0.0.1");
+        $cmd->exit_is_num(1);
+        $cmd->stdout_is_eq("");
+        $cmd->stderr_like(qr{Usage:});
+    }
+}
diff --git a/ci/tmp.VwGIuQgZdr/fping-5.4/ci/test-13-unknown-host.pl b/ci/tmp.VwGIuQgZdr/fping-5.4/ci/test-13-unknown-host.pl
new file mode 100755 (executable)
index 0000000..65c8312
--- /dev/null
@@ -0,0 +1,11 @@
+#!/usr/bin/perl -w
+
+use Test::Command tests => 3;
+
+# fping
+{
+my $cmd = Test::Command->new(cmd => "fping nosuchname.example.com");
+$cmd->exit_is_num(2);
+$cmd->stdout_is_eq("");
+$cmd->stderr_like(qr{^nosuchname\.example\.com: .*not (known|found)});
+}
diff --git a/ci/tmp.VwGIuQgZdr/fping-5.4/ci/test-14-ping-internet-hosts.pl b/ci/tmp.VwGIuQgZdr/fping-5.4/ci/test-14-ping-internet-hosts.pl
new file mode 100755 (executable)
index 0000000..3c18cc4
--- /dev/null
@@ -0,0 +1,106 @@
+#!/usr/bin/perl -w
+
+use Test::Command;
+use Test::More;
+
+# evaluate if we have internet
+if(!gethostbyname("www.google.com")) {
+    plan skip_all => 'Can\'t resolve www.google.com -> no internet?';
+    exit 0;
+}
+
+plan tests => 30;
+
+my $re_num = qr{\d+(?:\.\d+)?};
+
+# fping
+{
+my $cmd = Test::Command->new(cmd => "fping -q -i 10 -p 20 -c 3 -t200  8.8.8.8 www.france-telecom.fr www.google.com");
+$cmd->exit_is_num(0);
+$cmd->stdout_is_eq("");
+$cmd->stderr_like(qr{8\.8\.8\.8\s*: xmt/rcv/%loss = [123]/[123]/\d+%, min/avg/max = $re_num/$re_num/$re_num
+www\.france-telecom\.fr\s*: xmt/rcv/%loss = [123]/[123]/\d+%, min/avg/max = $re_num/$re_num/$re_num
+www\.google\.com\s*: xmt/rcv/%loss = [123]/[123]/\d+%, min/avg/max = $re_num/$re_num/$re_num
+});
+}
+
+# fping -A -n
+{
+my $cmd = Test::Command->new(cmd => "fping -A -n 8.8.8.8");
+$cmd->exit_is_num(0);
+$cmd->stdout_is_eq("dns.google (8.8.8.8) is alive\n");
+$cmd->stderr_is_eq("");
+}
+
+# fping -4 -A -n
+{
+my $cmd = Test::Command->new(cmd => "fping -4 -A -n dns.google");
+$cmd->exit_is_num(0);
+$cmd->stdout_like(qr{^dns.google \(8\.8\.(4\.4|8\.8)\) is alive\n$});
+$cmd->stderr_is_eq("");
+}
+
+# fping -4 --addr --rdns
+{
+my $cmd = Test::Command->new(cmd => "fping -4 --addr --rdns www.apple.com");
+$cmd->exit_is_num(0);
+$cmd->stdout_like(qr{^\S+\.akamaitechnologies\.com \(\d+\.\d+\.\d+\.\d+\) is alive\n$});
+$cmd->stderr_is_eq("");
+}
+
+# fping -4 --addr --name
+{
+my $cmd = Test::Command->new(cmd => "fping -4 --addr --name www.google.com");
+$cmd->exit_is_num(0);
+$cmd->stdout_like(qr{^www\.google\.com \(\d+\.\d+\.\d+\.\d+\) is alive\n$});
+$cmd->stderr_is_eq("");
+}
+
+# fping -A -n (IPv6)
+SKIP: {
+    if($ENV{SKIP_IPV6}) {
+        skip 'Skip IPv6 tests', 3;
+    }
+    my $cmd = Test::Command->new(cmd => "fping -6 -n -A dns.google");
+    $cmd->exit_is_num(0);
+    $cmd->stdout_like(qr{^dns.google \(2001:4860:4860::88(44|88)\) is alive\n$});
+    $cmd->stderr_is_eq("");
+}
+
+# fping -m
+SKIP: {
+    if($ENV{SKIP_IPV6}) {
+        skip 'Skip IPv6 tests', 3;
+    }
+    my $cmd = Test::Command->new(cmd => "fping -A -m dns.google");
+    $cmd->exit_is_num(0);
+    $cmd->stdout_like(qr{^.* is alive\n.* is alive\n.* is alive\n.* is alive\n});
+    $cmd->stderr_is_eq("");
+}
+
+# fping -m -A
+{
+my $cmd = Test::Command->new(cmd => "fping -4 -A -m www.cloudflare.com");
+$cmd->exit_is_num(0);
+$cmd->stdout_like(qr{\d+\.\d+\.\d+\.\d+ is alive\n\d+\.\d+\.\d+\.\d+ is alive\n});
+$cmd->stderr_is_eq("");
+}
+
+# fping -n
+{
+my $cmd = Test::Command->new(cmd => "fping -n 8.8.8.8");
+$cmd->exit_is_num(0);
+$cmd->stdout_is_eq("dns.google is alive\n");
+$cmd->stderr_is_eq("");
+}
+
+# fping -M
+SKIP: {
+    if($^O eq 'darwin') {
+        skip '-M option not supported on macOS', 3;
+    }
+    my $cmd = Test::Command->new(cmd => "fping -r 0 -b 10000 -M 8.8.8.8");
+    $cmd->exit_is_num(1);
+    $cmd->stdout_is_eq("8.8.8.8 is unreachable\n");
+    $cmd->stderr_is_eq("8.8.8.8: error while sending ping: Message too long\n");
+}
diff --git a/ci/tmp.VwGIuQgZdr/fping-5.4/ci/test-15-netdata.pl b/ci/tmp.VwGIuQgZdr/fping-5.4/ci/test-15-netdata.pl
new file mode 100755 (executable)
index 0000000..83dc439
--- /dev/null
@@ -0,0 +1,35 @@
+#!/usr/bin/perl -w
+
+use Test::Command;
+use Test::More;
+
+plan tests => 3;
+
+# fping
+{
+my $cmd = Test::Command->new(cmd => "fping -c 2 -Q 1 -N 127.0.0.1");
+$cmd->exit_is_num(0);
+$cmd->stdout_like(qr{CHART fping\.127_0_0_1_packets '' 'FPing Packets' packets '127.0.0.1' fping\.packets line 110020 1
+DIMENSION xmt sent absolute 1 1
+DIMENSION rcv received absolute 1 1
+BEGIN fping\.127_0_0_1_packets
+SET xmt = 1
+SET rcv = 1
+END
+CHART fping\.127_0_0_1_quality '' 'FPing Quality' percentage '127.0.0.1' fping\.quality area 110010 1
+DIMENSION returned '' absolute 1 1
+BEGIN fping\.127_0_0_1_quality
+SET returned = 100
+END
+CHART fping\.127_0_0_1_latency '' 'FPing Latency' ms '127.0.0.1' fping\.latency area 110000 1
+DIMENSION min minimum absolute 1 1000000
+DIMENSION max maximum absolute 1 1000000
+DIMENSION avg average absolute 1 1000000
+BEGIN fping\.127_0_0_1_latency
+SET min = \d+
+SET avg = \d+
+SET max = \d+
+END}
+);
+$cmd->stderr_like(qr{127.0.0.1 : xmt/rcv/%loss = 2/2/0%, min/avg/max = \d\.\d+/\d\.\d+/\d\.\d+});
+}
diff --git a/ci/tmp.VwGIuQgZdr/fping-5.4/ci/test-issue-56.pl b/ci/tmp.VwGIuQgZdr/fping-5.4/ci/test-issue-56.pl
new file mode 100755 (executable)
index 0000000..e36cc14
--- /dev/null
@@ -0,0 +1,18 @@
+#!/usr/bin/perl -w
+
+# regression testing for github issue #56
+#
+use Test::Command;
+use Test::More;
+
+if( $^O eq 'darwin' ) {
+    plan skip_all => 'Test disabled on MacOS';
+    exit 0;
+}
+
+plan tests => 3;
+
+my $cmd1 = Test::Command->new(cmd => "fping -t100 -p100 -C3 255.255.255.255");
+$cmd1->exit_is_num(1);
+$cmd1->stdout_is_eq("");
+$cmd1->stderr_is_eq("\n255.255.255.255 : - - -\n");
diff --git a/ci/tmp.VwGIuQgZdr/fping-5.4/ci/test-issue-58.pl b/ci/tmp.VwGIuQgZdr/fping-5.4/ci/test-issue-58.pl
new file mode 100755 (executable)
index 0000000..db5161a
--- /dev/null
@@ -0,0 +1,10 @@
+#!/usr/bin/perl -w
+
+# regression testing for github issue #58
+
+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("fping: -g works only with IPv4 addresses\n");
diff --git a/ci/tmp.VwGIuQgZdr/fping-5.4/ci/test-tarball.sh b/ci/tmp.VwGIuQgZdr/fping-5.4/ci/test-tarball.sh
new file mode 100755 (executable)
index 0000000..da43a25
--- /dev/null
@@ -0,0 +1,31 @@
+#!/bin/bash
+
+# make sure that the .tar.gz file contains everything necessary
+# to build fping
+
+set -e
+set -x
+
+# skip on macos
+if [[ "$OSTYPE" == "darwin"* ]]; then
+    exit 0
+fi
+
+make dist
+VERSION=$(ls fping-*.tar.gz | sed -e 's/^fping-//' | sed -e 's/\.tar\.gz$//')
+if [ -z "$VERSION" ]; then
+    echo "tar.gz file not found." >&2
+    exit 1
+fi
+
+# unarchive
+TMPDIR=$(mktemp -d --tmpdir=ci)
+cd $TMPDIR
+tar xf ../../fping-$VERSION.tar.gz
+DIRNAME=$(ls)
+
+# build
+cd $DIRNAME
+./configure --enable-ipv4 --enable-ipv6 --prefix=/opt/fping
+make
+sudo make install 
diff --git a/ci/tmp.VwGIuQgZdr/fping-5.4/configure.ac b/ci/tmp.VwGIuQgZdr/fping-5.4/configure.ac
new file mode 100644 (file)
index 0000000..d573075
--- /dev/null
@@ -0,0 +1,129 @@
+dnl Process this file with autoconf to produce a configure script.
+
+dnl Minimum Autoconf version required.
+AC_PREREQ(2.59)
+
+AC_INIT([fping],[5.4])
+
+m4_ifdef([AC_AUTOCONF_VERSION],[AC_USE_SYSTEM_EXTENSIONS], [AC_GNU_SOURCE])
+
+# Detect Operatingsystem
+AC_CANONICAL_TARGET
+only_clock_realtime=no
+
+case "${target}" in
+  *darwin*)
+    only_clock_realtime=yes
+    ;;
+  *freebsd*)
+    only_clock_realtime=yes
+    ;;
+  *openbsd*)
+    only_clock_realtime=yes
+    ;;
+esac
+
+dnl --disable-ipv4
+AC_ARG_ENABLE([ipv4],
+  AS_HELP_STRING([--disable-ipv4], [Disable support for pinging IPv4 hosts]))
+AM_CONDITIONAL([IPV4], [test "x$enable_ipv4" != "xno"])
+AM_COND_IF([IPV4], [AC_DEFINE([IPV4], [1], [IPv4 enabled])])
+
+dnl --disable-ipv6
+AC_ARG_ENABLE([ipv6],
+  AS_HELP_STRING([--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>
+      #include <sys/types.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_TIMESTAMPNS)]))
+AS_IF([test "x$enable_timestamp" != "xno"], [
+   AC_CHECK_DECL([SO_TIMESTAMPNS], [AC_DEFINE(HAVE_SO_TIMESTAMPNS, [1], [SO_TIMESTAMPNS 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
+AS_IF([test "x$enable_timestamp" = "xyes" -a "x$have_so_timestamp" = "xno"], [
+  AC_MSG_ERROR([--enable-timestamp not supported on this platform])
+])
+AS_IF([test "x$only_clock_realtime" = "xyes"], [AC_DEFINE(ONLY_CLOCK_REALTIME, [1], [ONLY_CLOCK_REALTIME is defined])])
+
+AC_ARG_ENABLE([safe-limits],
+  AS_HELP_STRING([--enable-safe-limits], [Restrict timing parameters (-i, -p) within "safe" limits]))
+AS_IF([test "x$enable_safe_limits" = "xyes"], [
+   AC_DEFINE(FPING_SAFE_LIMITS, [1], [safe limits should be enforced])])
+
+AC_ARG_ENABLE([debug],
+  AS_HELP_STRING([--enable-debug], [enable debugging @<:@default=no@:>@]), [enable_debug=$enableval], [enable_debug=no])
+AS_IF([test "x$enable_debug" = "xyes"], [
+  AC_DEFINE([DEBUG], [1], [Define if debugging is enabled])])
+
+AM_INIT_AUTOMAKE([-Wall -Werror foreign])
+AM_MAINTAINER_MODE
+
+AC_CONFIG_HEADERS([config.h])
+
+dnl Checks for programs.
+
+AC_PROG_CC
+AM_PROG_CC_C_O
+m4_version_prereq([2.70],,[AC_PROG_CC_STDC])
+AC_PROG_CPP
+AC_PROG_INSTALL
+
+dnl Checks for libraries.
+
+AC_CHECK_FUNC(gethostbyname)
+if test $ac_cv_func_gethostbyname = no; then
+    AC_CHECK_LIB(nsl, gethostbyname)
+fi
+AC_CHECK_FUNC(connect)
+if test $ac_cv_func_connect = no; then
+    AC_CHECK_LIB(socket, connect)
+fi
+AC_CHECK_FUNC(sigaction)
+if test $ac_cv_func_sigaction = yes; then
+    AC_DEFINE([USE_SIGACTION],[1],[Define if sigaction is available.])
+fi
+
+AC_CHECK_FUNCS([strftime], [],
+  [AC_MSG_ERROR([strftime function is required but not found])])
+
+AH_TOP([
+#ifndef CONFIG_H
+#define CONFIG_H
+])
+
+AH_BOTTOM([
+/* some OSes do not define this ... lets take a wild guess */
+
+#ifndef INADDR_NONE
+#  define INADDR_NONE 0xffffffffU
+#endif
+
+#endif /* CONFIG_H */
+
+])
+
+dnl Checks for header files.
+AC_CHECK_HEADERS([unistd.h sys/file.h stdlib.h sys/select.h])
+
+AC_CONFIG_FILES([Makefile
+                 doc/Makefile
+                 src/Makefile])
+
+AC_OUTPUT
diff --git a/ci/tmp.VwGIuQgZdr/fping-5.4/contrib/Dockerfile b/ci/tmp.VwGIuQgZdr/fping-5.4/contrib/Dockerfile
new file mode 100644 (file)
index 0000000..c20a1d6
--- /dev/null
@@ -0,0 +1,17 @@
+FROM debian:stable
+
+# Base
+RUN apt-get update && apt-get install -y \
+  build-essential \
+  automake \
+  autoconf \
+  m4
+
+# Add source code
+COPY ./ /app
+
+# Compile
+WORKDIR /app
+RUN autoreconf --install
+RUN ./configure && make && make install
+ENTRYPOINT ["fping"]
\ No newline at end of file
diff --git a/ci/tmp.VwGIuQgZdr/fping-5.4/contrib/fping.spec b/ci/tmp.VwGIuQgZdr/fping-5.4/contrib/fping.spec
new file mode 100644 (file)
index 0000000..71d1ea0
--- /dev/null
@@ -0,0 +1,74 @@
+Summary: send ICMP echo probes to multiple hosts
+Name: fping
+Version: 4.2
+Release: 1
+License: Freely redistributable without restriction
+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.md COPYING CHANGELOG.md
+/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,cap_net_admin+ep /usr/sbin/fping
+    /usr/sbin/setcap cap_net_raw,cap_net_admin+ep /usr/sbin/fping6
+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:
+
diff --git a/ci/tmp.VwGIuQgZdr/fping-5.4/doc/CHANGELOG.pre-v4 b/ci/tmp.VwGIuQgZdr/fping-5.4/doc/CHANGELOG.pre-v4
new file mode 100644 (file)
index 0000000..fc9a0aa
--- /dev/null
@@ -0,0 +1,627 @@
+2017-02-09  David Schweikert  <david@schweikert.ch>
+  * Version 3.16
+  * (feature) Support kernel-timestamping of received packets (#46)
+  * (feature) Simplify restrictions: only -i >= 1 and -p >= 10 are enforced now
+  * (bugfix) Fix option -m to return all IPs of a hostname
+  * (bugfix) Fix option -H (ttl) for IPv6
+  * (bugfix) Fix option -M (don't fragment) for IPv6
+  * (bugfix) Fix option -O (ToS) for IPv6
+  * (bugfix) Fix compatibility issue with AIX (#69, @blentzgh)
+  * (bugfix) Fix option -q not suppressing some ICMP error messages (#83)
+  * (bugfix) Fix option -M expecting an argument, when it shouldn't
+  * (bugfix) Fix minor issues found by Coverity Scan
+
+2017-01-11  David Schweikert  <david@schweikert.ch>
+  * Version 3.15
+  * (bugfix) Fix compiler errors on platforms other than Linux (related
+             to the new -M option, #109)
+  * Test suite fixes for macOS
+
+2017-01-10  David Schweikert  <david@schweikert.ch>
+  * Version 3.14
+  * (feature) Ignore network and broadcast for cidrs /31 and /32 (#102, Martin Topholm)
+  * (feature) New option '-M' to set the "Don't Fragment" flag (#91, Don Bowman)
+  * (feature) New option '-N' to output statistics for netdata (see: http://my-netdata.io/, #105, Costa Tsaousis)
+  * (feature) New option '-o' to calculate total outage time (#90, @jgerbeck)
+  * (bugfix) Exit code should be 2 when the hostname can't be resolved
+            (fixes #98, reported by @green-fox)
+  * (bugfix)  Fix issue compliling on RHEL/Centos 7 (#95, @jbackman)
+  * (bugfix) Lower -i limit to 1 instead of 10
+  * (bugfix) Improve interval preciseness of -Q reporting
+  * (bugfix) Fix occasional false positive in -Q reporting (#97)
+  * (bugfix) Solaris 10 portability fix (#107, Peter Bray)
+
+2015-10-21  David Schweikert  <david@schweikert.ch>
+  * Version 3.13
+  * (bugfix) Fix ICMP errors sometimes causing crashes with fping >= 3.11
+             (fixes #85, reported by Jamie Heilman and Bill Blough)
+
+2015-10-14  David Schweikert  <david@schweikert.ch>
+  * Version 3.12
+  * (bugfix) Fix fping6 -R (fixes #84, reported by Stuart Henderson)
+
+2015-10-12  David Schweikert  <david@schweikert.ch>
+  * Version 3.11
+  * (feature)  New option -R to use random bytes instead of NULLs (#72, Anthony DeRobertis)
+  * (feature)  Small documentation and performance improvements (Ryan Underwood)
+  * (bugfix)   Fix double entries with fping -u and unreachable hosts
+  * (internal) Use sockaddr_storage and simplify code, so that we can one day support both IPv4 and IPv6 with the same binary
+
+2014-05-03  David Schweikert  <david@schweikert.ch>
+  * Version 3.10
+  * Fix confusing error message with -g and IPv6 addresses (#58, reported by Axel Beckert)
+  * Allow option '-f' also for non-root (since setuid privileges are dropped)
+  * Do not retry twice DNS lookup on DNS lookup problem
+  * Remove support for NIS groups
+  * Better document -B backoff-factor and when it can be used (#33, Oleksiy Zagorskyi)
+  * More tests added
+
+2014-03-08  David Schweikert  <david@schweikert.ch>
+  * Version 3.9
+  * Fix random output on socket error (reported by Aleksandrs Saveljevs, #56)
+  * Support ppc64le architecture by including alpha libtool version
+    (reported by Amit Kumar Gupta and Aravinda B Thunug)
+  * Fix compilation problem on FreeBSD (#57)
+  * Initial test suite and continous intergration (with travis-ci.org / coveralls.io)
+  * Don't output usage information on error
+
+2013-11-08  David Schweikert  <david@schweikert.ch>
+  * Version 3.8
+  * Fix segmentation fault introduced in version 3.7 with loop mode (reported
+    by Vlad Glagolev, #55)
+
+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)
+
+2012-04-26  David Schweikert  <david@schweikert.ch>
+  * Version 3.1
+  * -g option (generate): exclude network and broadcast address for cidr
+    ranges (idea by Eric Brander)
+  * do not explicitely check if running as root, to make it possible to
+    install fping with linux capabilities instead of making it setuid
+    (setcap cap_net_raw+ep fping)
+  * ANSI C (C89) compiler now a requirement
+  * Portability fixes
+  * Reorganized source directory
+  * Bugfix: fix timeout issue on Solaris (Sandor Geller)
+  * Man-page fixes (Axel Beckert)
+  * Added -H option to specify number of hops (Paul Duda)
+  * Output usage information to stdout when called with -h (Paul Duda)
+
+2011-12-28  David Schweikert  <david@schweikert.ch>
+  * Version 3.0
+  * rewritten main loop for improved performance
+  * -T parameter (select timeout) now obsolete
+  * Maintenance taken over from unresponsive previous maintainer
+    (anybody please step up, if you disagree)
+  * New homepage: www.fping.org
+
+2009-12-21  Tobi Oetiker  <tobi@oetiker.ch>
+  * Version v2.4b2-to3-ipv6
+  * added -On option to set the TOS octet
+  * Removed unused variables from code
+  * updated to current autoconf standards
+  * Merged Debian changes (see below)
+
+----------------------------------------------------------------------
+
+fping (2.4b2-to-ipv6-16.1) unstable; urgency=low
+
+  * NMU during Moenchengladbach BSP
+  * Fixes FTBFS on kfreebsd (Closes: #555398)
+  * Fixes typo "Paramter" in binary
+
+ -- Axel Beckert <abe@deuxchevaux.org>  Sat, 23 Jan 2010 16:22:02 +0100
+
+fping (2.4b2-to-ipv6-16) unstable; urgency=low
+
+  * Fix the following bugs
+    - Network byte order sensitivity was missing completely.
+      Added hopefully all missing calls.
+    - The sequence numbering scheme used led to packet drops.
+      Changed it to a more senseful numbering scheme.
+    - Some minor C programming mistakes ('=' instead of '==').
+    Patch by Stephan Fuhrmann; closes: #502569
+  * Add support for command line select timeout setting
+    Patch by Marton Balint; closes: #502575
+  * Remove symlinks in /usr/sbin; closes: #377732
+  * Standards-Version is 3.8.0
+
+ -- Anibal Monsalve Salazar <anibal@debian.org>  Sat, 18 Oct 2008 12:04:52 +1100
+
+fping (2.4b2-to-ipv6-15) unstable; urgency=low
+
+  * Added interface binding (-I) for fping
+    Patch by Peter Naulls <peter@mushroomnetworks.com>
+    Closes: #439014
+  * Fixed a couple of typos in fping.8. Closes: #423180
+  * Added homepage control header
+  * Bumped Standards-Version to 3.7.3
+  * Fixed the following lintian issue:
+    - debian-rules-sets-DH_COMPAT
+
+ -- Anibal Monsalve Salazar <anibal@debian.org>  Mon, 03 Mar 2008 17:46:17 +1100
+
+fping (2.4b2-to-ipv6-13) unstable; urgency=low
+
+  * Fixed stdout flush problem, closes: #340146.
+    Patch by Bart Martens <bart.martens@advalvas.be>.
+
+ -- Anibal Monsalve Salazar <anibal@debian.org>  Fri, 30 Dec 2005 08:30:09 +1100
+
+fping (2.4b2-to-ipv6-12) unstable; urgency=low
+
+  * Fixed "problem with option -r (retry limit)", closes: #318402.
+    Patch by Qingning Huo <qingningh@lanware.co.uk>.
+
+ -- Anibal Monsalve Salazar <anibal@debian.org>  Sat, 08 Oct 2005 21:26:35 +1000
+
+fping (2.4b2-to-ipv6-11) unstable; urgency=low
+
+  * Fixed "would be useful to specify 'source address' like ping for multi
+    homed machines", closes: #198486.
+    Patch by Marc Haber <mh+debian-bugs@zugschlus.de>.
+
+ -- Anibal Monsalve Salazar <anibal@debian.org>  Thu, 02 Jun 2005 08:14:54 +1000
+
+fping (2.4b2-to-ipv6-10) unstable; urgency=low
+
+  * Fixed "unnecessary delay with the -c option after the last packet"
+    (Closes: #293856). Patch by Niko Tyni <ntyni@iki.fi>
+
+ -- Anibal Monsalve Salazar <anibal@debian.org>  Sun, 06 Feb 2005 23:25:57 +1100
+
+fping (2.4b2-to-ipv6-9) unstable; urgency=low
+
+  * Fixed "fping6 always does reverse lookup" (Closes: #273647).
+    Patch by Jeroen Massar and forwarded by Bernhard Schmidt <berni@birkenwald.de>
+
+ -- Anibal Monsalve Salazar <A.Monsalve.Salazar@IEEE.org>  Mon, 10 Jan 2005 00:01:32 +1100
+
+fping (2.4b2-to-ipv6-7) unstable; urgency=low
+
+  * Build fping in build/ipv[46] instead of build and build-ipv6.
+  * Made DNS errors non-fatal for IPv6 (closes: #198056).
+
+ -- Herbert Xu <herbert@debian.org>  Fri, 20 Jun 2003 21:36:30 +1000
+
+fping (2.4b2-to-ipv6-6) unstable; urgency=low
+
+  * Do not use incorrect linux.h file (closes: #85468).
+
+ -- Herbert Xu <herbert@debian.org>  Sat, 17 May 2003 14:13:11 +1000
+
+fping (2.4b2-to-ipv6-5) unstable; urgency=low
+
+  * Fixed yet another divide by zero bug (closes: #148445).
+
+ -- Herbert Xu <herbert@debian.org>  Tue,  4 Jun 2002 12:18:03 +1000
+
+fping (2.4b2-to-ipv6-4) unstable; urgency=low
+
+  * Made fping6 setuid (closes: #136386).
+  * Moved fping back into bin.
+  * Partially applied IPv6 patch to fix IPv6 checksums (closes: #136479).
+
+ -- Herbert Xu <herbert@debian.org>  Sun,  7 Apr 2002 20:36:56 +1000
+
+fping (2.4b2-to-ipv6-3) unstable; urgency=low
+
+  * Added compatibility symlink for fping (closes: #135203).
+
+ -- Herbert Xu <herbert@debian.org>  Sat, 23 Feb 2002 08:34:11 +1100
+
+fping (2.4b2-to-ipv6-2) unstable; urgency=low
+
+  * Fixed another divide by zero error (closes: #132370).
+
+ -- Herbert Xu <herbert@debian.org>  Thu,  7 Feb 2002 20:10:48 +1100
+
+fping (2.4b2-to-ipv6-1) unstable; urgency=low
+
+  * New upstream release.
+  * Install fping into sbin as done by upstream.
+
+ -- Herbert Xu <herbert@debian.org>  Fri,  1 Feb 2002 22:11:59 +1100
+
+fping (2.2b2-3) unstable; urgency=low
+
+  * Removed INSTALL file from package (closes: #84050).
+  * Fixed alignment bug.
+
+ -- Herbert Xu <herbert@debian.org>  Sat, 10 Feb 2001 19:25:18 +1100
+
+fping (2.2b2-2) unstable; urgency=low
+
+  * Made changes for dpkg-statoverride (closes: #83838).
+
+ -- Herbert Xu <herbert@debian.org>  Sun, 28 Jan 2001 21:53:05 +1100
+
+fping (2.2b2-1) unstable; urgency=low
+
+  * New upstream release.
+  * Fixed typo that prevented -d from working (closes: #83255).
+  * Drop root privileges after opening the socket (closes: #81589).
+  * Fixed the options [tip], they were out by a factor of 10
+    (Richard Kettlewell, closes: #83742).
+
+ -- Herbert Xu <herbert@debian.org>  Sun, 28 Jan 2001 00:09:41 +1100
+
+fping (2.2b1-2) unstable; urgency=low
+
+  * Fixed typo in control file, spotted by William Ono (closes: #49909).
+
+ -- Herbert Xu <herbert@debian.org>  Mon, 15 May 2000 12:27:03 +1000
+
+fping (2.2b1-1) unstable; urgency=low
+
+  * Initial release.
+  * Fixed divide by zero error (closes: #29902).
+
+ -- Herbert Xu <herbert@debian.org>  Sat, 30 Oct 1999 16:36:19 +1000
+---------------------------------------------------------------------------------
+
+Wed Jan 16 2002
+Jeroen Massar
+- Revision v2.4b2-to-IPv6
+   - Added IPv6 support.
+   - Added -I option for selecting source IPv4/IPv6 address.
+   - Makefile.in now generates a Makefile which will build both
+     fping (IPv4) and fping6 (IPv6). Thus it makes an fping (IPv4 only)
+     and an fping6 (IPv6 only).
+   - num_unreachable was counted twice when a sendto() generated errors.
+   - See http://unfix.org/projects/ipv6/
+
+Tue Mar 14 2001
+Jason Ewasiuk <jasone@remote.net>
+- Revision v2.4b1
+        - added -g option for generating IPs from a start to an end value
+                - two available options, generate IPs from start IP to end IP
+                  or from a passed netmask, such as 192.168.1.0/24
+
+Thu Feb 15 2001
+Jason Ewasiuk <jasone@remote.net>
+- Revision v2.3b1
+        - formatting changes to code layout (fping.c)
+        NOTE:  Best viewed with a tab stop of 4
+        - merged in changes from Debian c/o Herbert Xu
+        <herbert@gondor.apana.org.au>
+                - Compilation fix on alphas with glibc
+                - Alignment issues (note from JE:  in wait_for_reply())
+                - A typo with the time specified on the command line
+                (note from JE:  bug was using 10 instead of 100)
+                - Drop privileges after obtaining socket
+                (note from JE:  might be moot, since prog exits if
+                user is not root)
+        - touched all files in package to this date
+        - couple new #ifdefs added for future WIN32 support
+        (Haven't got to adding this yet, will take a lot of rewriting.)
+
+Fri Dec  8 10:33:13 2000  Roland Schemers  <schemers@stanford.edu>
+
+        * stop using sys_errlist and start using strerror
+        fixed bug in output of -C
+
+Wed Jan  8 11:18:37 1997  Roland Schemers  <schemers@stanford.edu>
+
+        * Created ChangeLog file. What follows was from the CHANGES file.
+
+* Revision 2.0  1994/10/31 21:26:23 morgan
+
+  Substantial rewrite, including new features:
+
+    support some traditional ping features:
+      loop mode
+      specify size of data packets
+      specify how many pings to send
+      show per-response data
+      interpret ICMPs other than ICMP Echo response
+
+  also
+
+    rewrote main loop completely
+    make timings in tenths of milliseconds
+    do exponential backoff on retries
+    port to more systems
+    add some debugging stuff
+    do better checking on whether received ICMP is for us
+
+* Revision 1.24  1993/12/10  23:11:39  schemers
+
+  commented out seteuid(getuid()) since it isn't needed
+
+* Revision 1.23  1993/12/10  18:33:41  schemers
+
+  Took out the -f option for non-root users. This can be enabled by
+  defining ENABLE_F_OPTION before compiling. There is a call to
+  access before opening the file, but there is a race condition.
+  Reading from stdin is much safer.
+
+
+* Revision 1.22  1993/11/16  19:49:24  schemers
+
+  Took out setuid(getuid()) and used access() system call to
+  check for access to the file specified with "-f".
+
+* Revision 1.21  1993/07/20  18:08:19  schemers
+
+  commented out the test to make sure the ping packet came from the
+  same IP address as the one we sent to. This could cause problems on
+  multi-homed hosts.
+
+* Revision 1.20  1993/02/23  00:16:38  schemers
+
+fixed syntax error (should have compiled before checking in...)
+
+* Revision 1.19  1993/02/23  00:15:15  schemers
+
+turned off printing of "is alive" when -a is specified.
+
+* Revision 1.18  1992/07/28  15:16:44  schemers
+
+added a fflush(stdout) call before the summary is sent to stderr, so
+everything shows up in the right order.
+
+* Revision 1.17  1992/07/23  03:29:42  schemers
+* Revision 1.16  1992/07/22  19:24:37  schemers
+
+Fixed declaration of timeval_diff. Didn't notice the problem because
+I use 'cc' in stead of gcc under Ultrix. Time to switch? :-)
+
+Modified file reaing so it would skip blank lines or lines starting
+with a '#'. Now you can do something like:
+
+fping -ad < /etc/hosts
+
+* Revision 1.15  1992/07/21  17:07:18  schemers
+
+Put in sanity checks so only root can specify "dangerous" options.
+Changed usage to show switchs in alphabetical order.
+* Revision 1.14  1992/07/21  16:40:52  schemers
+* Revision 1.13  1992/07/17  21:02:17  schemers
+
+Changed the default timeout to 2500 msec, and retry to 3. This was
+due to suggestions from people with slow (WAN) networks. The default
+1 sec timeout was too fast.
+
+
+Added '-e' option for showing elapsed (round-trip) times on pakets, and
+modified the -s option to include min, max, and average round-trip times,
+and over all elapsed time.
+
+Modified action taken when a error is returned from sendto. The action
+taken now considers the host unreachable and prints the hostname
+followed by the errno message. The program will not exit and will continue
+to try other hosts.
+
+* Revision 1.12  1992/07/17  16:38:54  schemers
+* Revision 1.11  1992/07/17  16:28:38  schemers
+
+ move socket create call so I could do a setuid(getuid()) before the
+ fopen call is made. Once the socket is created root privs aren't needed
+ to send stuff out on it.
+
+ moved num_timeout counter. It really was for debug purposes and didn't
+ make sense to the general public :-) Now it is the number of timeouts
+ (pings that didn't get received with the time limit).
+
+
+* Revision 1.10 1992/07/16  16:24:38  schemers
+* Revision 1.9  1992/07/16  16:00:04  schemers
+* Revision 1.8  1992/07/16  05:44:41  schemers
+
+Added _NO_PROTO stuff for older compilers, and _POSIX_SOURCE
+for unistd.h, and _POSIX_SOURCE for stdlib.h. Also added
+check for __cplusplus.
+
+Now compiles ok under Ultrix 3.1, and Sun4 using cc. Also compiled
+ok using g++ 2.2.2.
+
+Changed '-a' and '-u' flags to be mutually exclusive (makes sense, since
+specifiying both '-a' and '-u' is the same as not specifiying anything.
+Since '-a' and '-u' are mutually exclusive, these options now only print
+the hostname, and not the 'is alive' or 'is unreachable'  messages.
+This makes it much easier to do stuff like:
+
+#!/usr/local/bin/perl
+$hosts_to_backup=`cat /etc/hosts.backup|fping -a`;
+
+Since you don't have to strip off the 'is alive' messages.
+
+Changed usage to and stats to print to stderr instead of stdout.
+
+-----------------------------------------------------------------------------
+
+RCS header info from original fping.c package (no longer required)
+
+/*
+ ***************************************************
+ *
+ * Standard RCS Header information (see co(1))
+ *
+ * $Author: schemers $
+ *
+ * $Date: 1997/01/08 20:29:33 $
+ *
+ * $Revision: 2.2 $
+ *
+ * $Locker:  $
+ *
+ * $Source: /afs/ir/group/networking/src/fping/fping-2.2/src/RCS/fping.c,v $
+ *
+ * $State: Exp $
+ *
+ * $Log: fping.c,v $
+ *
+ * Revision 2.2  1997/01/08 20:29:33  schemers
+ * changes for autoconf/automake
+ *
+ * Revision 2.1  1997/01/08 19:07:18  schemers
+ * checked in RL "Bob"'s changes before configure'ing
+ *
+ * Revision 2.0  1994/10/31  21:26:23  schemers
+ * many changes by RL "Bob" Morgan
+ *   add timing data collection, loop mode, per-packet output, etc
+ *
+ * Revision 1.24  1993/12/10  23:11:39  schemers
+ * commented out seteuid(getuid()) since it isn't needed
+ *
+ * Revision 1.23  1993/12/10  18:33:41  schemers
+ * Took out the -f option for non-root users. This can be enabled by
+ * defining ENABLE_F_OPTION before compiling. There is a call to
+ * access before opening the file, but there is a race condition.
+ * Reading from stdin is much safer.
+ *
+ * Revision 1.22  1993/11/16  19:49:24  schemers
+ * Took out setuid(getuid()) and used access() system call to
+ * check for access to the file specified with "-f".
+ *
+ * Revision 1.21  1993/07/20  18:08:19  schemers
+ * commented out the test to make sure the ping packet came from the
+ * same IP address as the one we sent to. This could cause problems on
+ * multi-homed hosts.
+ *
+ * Revision 1.20  1993/02/23  00:16:38  schemers
+ * fixed syntax error (should have compiled before checking in...)
+ *
+ * Revision 1.19  1993/02/23  00:15:15  schemers
+ * turned off printing of "is alive" when -a is specified.
+ *
+ * Revision 1.18  1992/07/28  15:16:44  schemers
+ * added a fflush(stdout) call before the summary is sent to stderr, so
+ * everything shows up in the right order.
+ *
+ * Revision 1.17  1992/07/23  03:29:42  schemers
+ * fixed declaration of timeval_diff.
+ *
+ * Revision 1.16  1992/07/22  19:24:37  schemers
+ * Modified file reading so it would skip blanks lines or lines starting
+ * with a '#'. Now you can do something like:
+ *
+ * fping -ad < /etc/hosts
+ *
+ * Revision 1.15  1992/07/21  17:07:18  schemers
+ * Put in sanity checks so only root can specify "dangerous" options.
+ * Changed usage to show switchs in alphabetical order.
+ *
+ * Revision 1.14  1992/07/21  16:40:52  schemers
+ * Now when sendto returns an error, the host is considered unreachable and
+ * and the error message (from errno) is displayed.
+ *
+ * Revision 1.13  1992/07/17  21:02:17  schemers
+ * changed default timeout to 2500 msec (for WANs), and default try
+ * to 3. This gives 10 second overall timeout.
+ *
+ * Added -e option for showing elapsed (round-trip) time on packets
+ *
+ * Modified -s option to inlude to round-trip stats
+ *
+ * Added #ifndef DEFAULT_* stuff its easier to change the defaults
+ *
+ * Reorganized main loop.
+ *
+ * cleaned up timeval stuff. removed set_timeval and timeval_expired
+ * since they aren't needed anymore. Just use timeval_diff.
+ *
+ * Revision 1.12  1992/07/17  16:38:54  schemers
+ * move socket create call so I could do a setuid(getuid()) before the
+ * fopen call is made. Once the socket is created root privs aren't needed
+ * to send stuff out on it.
+ *
+ * Revision 1.11  1992/07/17  16:28:38  schemers
+ * moved num_timeout counter. It really was for debug purposes and didn't
+ * make sense to the general public :-) Now it is the number of timeouts
+ * (pings that didn't get received with the time limit).
+ *
+ * Revision 1.10  1992/07/16  16:24:38  schemers
+ * changed usage() to use fprintf(stderr,"...");
+ *
+ * Revision 1.9  1992/07/16  16:00:04  schemers
+ * Added _NO_PROTO stuff for older compilers, and _POSIX_SOURCE
+ * for unistd.h, and _POSIX_SOURCE for stdlib.h. Also added
+ * check for __cplusplus.
+ *
+ * Revision 1.8  1992/07/16  05:44:41  schemers
+ * changed -a and -u to only show hostname in results. This is
+ * for easier parsing. Also added -v flag
+ *
+ * Revision 1.7  1992/07/14  18:45:23  schemers
+ * initialized last_time in add_host function
+ *
+ * Revision 1.6  1992/07/14  18:32:40  schemers
+ * changed select to use FD_ macros
+ *
+ * Revision 1.5  1992/07/14  17:21:22  schemers
+ * standardized exit status codes
+ *
+ * Revision 1.4  1992/06/26  15:25:35  schemers
+ * changed name from rrping to fping
+ *
+ * Revision 1.3  1992/06/24  15:39:32  schemers
+ * added -d option for unreachable systems
+ *
+ * Revision 1.2  1992/06/23  03:01:23  schemers
+ * misc fixes from R.L. "Bob" Morgan
+ *
+ * Revision 1.1  1992/06/19  18:23:52  schemers
+ * Initial revision
+ *
+ *--------------------------------------------------
+ * Copyright (c) 1992, 1994, 1997 Board of Trustees
+ *            Leland Stanford Jr. University
+ ***************************************************
+ */
+
+
diff --git a/ci/tmp.VwGIuQgZdr/fping-5.4/doc/Makefile.am b/ci/tmp.VwGIuQgZdr/fping-5.4/doc/Makefile.am
new file mode 100644 (file)
index 0000000..20adc28
--- /dev/null
@@ -0,0 +1,6 @@
+man_MANS = fping.8
+
+EXTRA_DIST = fping.8 fping.pod README.1992 CHANGELOG.pre-v4
+
+fping.8: fping.pod
+       pod2man  -c "" -s 8 -r "fping" $< >$@
diff --git a/ci/tmp.VwGIuQgZdr/fping-5.4/doc/README.1992 b/ci/tmp.VwGIuQgZdr/fping-5.4/doc/README.1992
new file mode 100644 (file)
index 0000000..a1020cd
--- /dev/null
@@ -0,0 +1,43 @@
+Original README (from 1992)
+
+        fping - A tool to quickly ping N number of hosts to determine
+        their reachability.
+
+             Roland J. Schemers III - Stanford University
+                   schemers@Stanford.EDU
+
+      fping is a ping(1) like program which uses the Internet Control
+      Message Protocol (ICMP) echo request to determine if a host is
+      up. fping is different from ping in that you can specify any
+      number of hosts on the command line, or specify a file containing
+      the lists of hosts to ping. Instead of trying one host until it
+      timeouts or replies, fping will send out a ping packet and move
+      on to the next host in a round-robin fashion. If a host replies,
+      it is noted and removed from the list of hosts to check. If a host
+      does not respond within a certain time limit and/or retry limit it 
+      will be considered unreachable. 
+
+Site
+      Stanford University has a large TCP/IP network with over 16,000 
+      assigned IP addresses and over 100 IP subnets.
+
+Problem and Issues
+
+      With a large a number of IP addresses in use, its becomes more and
+      more time consuming to check on which IP addresses are actively
+      in use, and which critical machines (routers, bridges, servers, etc)
+      are reachable. One example is we have a program which goes through
+      all of our routers arp caches looking for IP addresses that are in 
+      use. After finding a list of IP addresses that aren't in any arp
+      caches fping can then be used to see if these IP addresses really
+      aren't being used, or are just behind the routers. Checking 2500
+      hosts (99% of which are unreachable) via ping can take hours.
+       
+      fping was written to solve the problem of pinging N number of hosts
+      in an efficient manner. By sending out pings in a round-robin fashion
+      and checking on responses as they come in at random, a large number of 
+      hosts can be checked at once.
+
+      Unlike ping, fping is meant to be used in scripts and its
+      output is easy to parse.
+
diff --git a/ci/tmp.VwGIuQgZdr/fping-5.4/doc/fping.8 b/ci/tmp.VwGIuQgZdr/fping-5.4/doc/fping.8
new file mode 100644 (file)
index 0000000..bc4abeb
--- /dev/null
@@ -0,0 +1,420 @@
+.\" Automatically generated by Pod::Man 4.14 (Pod::Simple 3.43)
+.\"
+.\" Standard preamble:
+.\" ========================================================================
+.de Sp \" Vertical space (when we can't use .PP)
+.if t .sp .5v
+.if n .sp
+..
+.de Vb \" Begin verbatim text
+.ft CW
+.nf
+.ne \\$1
+..
+.de Ve \" End verbatim text
+.ft R
+.fi
+..
+.\" Set up some character translations and predefined strings.  \*(-- will
+.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left
+.\" double quote, and \*(R" will give a right double quote.  \*(C+ will
+.\" give a nicer C++.  Capital omega is used to do unbreakable dashes and
+.\" therefore won't be available.  \*(C` and \*(C' expand to `' in nroff,
+.\" nothing in troff, for use with C<>.
+.tr \(*W-
+.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p'
+.ie n \{\
+.    ds -- \(*W-
+.    ds PI pi
+.    if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch
+.    if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\"  diablo 12 pitch
+.    ds L" ""
+.    ds R" ""
+.    ds C` ""
+.    ds C' ""
+'br\}
+.el\{\
+.    ds -- \|\(em\|
+.    ds PI \(*p
+.    ds L" ``
+.    ds R" ''
+.    ds C`
+.    ds C'
+'br\}
+.\"
+.\" Escape single quotes in literal strings from groff's Unicode transform.
+.ie \n(.g .ds Aq \(aq
+.el       .ds Aq '
+.\"
+.\" If the F register is >0, we'll generate index entries on stderr for
+.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index
+.\" entries marked with X<> in POD.  Of course, you'll have to process the
+.\" output yourself in some meaningful fashion.
+.\"
+.\" Avoid warning from groff about undefined register 'F'.
+.de IX
+..
+.nr rF 0
+.if \n(.g .if rF .nr rF 1
+.if (\n(rF:(\n(.g==0)) \{\
+.    if \nF \{\
+.        de IX
+.        tm Index:\\$1\t\\n%\t"\\$2"
+..
+.        if !\nF==2 \{\
+.            nr % 0
+.            nr F 2
+.        \}
+.    \}
+.\}
+.rr rF
+.\"
+.\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2).
+.\" Fear.  Run.  Save yourself.  No user-serviceable parts.
+.    \" fudge factors for nroff and troff
+.if n \{\
+.    ds #H 0
+.    ds #V .8m
+.    ds #F .3m
+.    ds #[ \f1
+.    ds #] \fP
+.\}
+.if t \{\
+.    ds #H ((1u-(\\\\n(.fu%2u))*.13m)
+.    ds #V .6m
+.    ds #F 0
+.    ds #[ \&
+.    ds #] \&
+.\}
+.    \" simple accents for nroff and troff
+.if n \{\
+.    ds ' \&
+.    ds ` \&
+.    ds ^ \&
+.    ds , \&
+.    ds ~ ~
+.    ds /
+.\}
+.if t \{\
+.    ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u"
+.    ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u'
+.    ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u'
+.    ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u'
+.    ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u'
+.    ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u'
+.\}
+.    \" troff and (daisy-wheel) nroff accents
+.ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V'
+.ds 8 \h'\*(#H'\(*b\h'-\*(#H'
+.ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#]
+.ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H'
+.ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u'
+.ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#]
+.ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#]
+.ds ae a\h'-(\w'a'u*4/10)'e
+.ds Ae A\h'-(\w'A'u*4/10)'E
+.    \" corrections for vroff
+.if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u'
+.if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u'
+.    \" for low resolution devices (crt and lpr)
+.if \n(.H>23 .if \n(.V>19 \
+\{\
+.    ds : e
+.    ds 8 ss
+.    ds o a
+.    ds d- d\h'-1'\(ga
+.    ds D- D\h'-1'\(hy
+.    ds th \o'bp'
+.    ds Th \o'LP'
+.    ds ae ae
+.    ds Ae AE
+.\}
+.rm #[ #] #H #V #F C
+.\" ========================================================================
+.\"
+.IX Title "FPING 8"
+.TH FPING 8 "2025-08-19" "fping" ""
+.\" For nroff, turn off justification.  Always turn off hyphenation; it makes
+.\" way too many mistakes in technical documents.
+.if n .ad l
+.nh
+.SH "NAME"
+fping \- send ICMP ECHO_REQUEST packets to network hosts
+.SH "SYNOPSIS"
+.IX Header "SYNOPSIS"
+\&\fBfping\fR [ \fIoptions\fR ] [ \fIsystems...\fR ]
+.SH "DESCRIPTION"
+.IX Header "DESCRIPTION"
+\&\fBfping\fR is a program like \fBping\fR which uses the Internet Control Message
+Protocol (\s-1ICMP\s0) echo request to determine if a target host is responding.
+\&\fBfping\fR differs from \fBping\fR 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, \fBfping\fR 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. \fBfping\fR also supports
+sending a specified number of pings to a target, or looping indefinitely (as in
+\&\fBping\fR ). Unlike \fBping\fR, \fBfping\fR is meant to be used in scripts, so its
+output is designed to be easy to parse.  Current statistics can be obtained without
+termination of process with signal \s-1SIGQUIT\s0 (^\e from the keyboard on most systems).
+.SH "OPTIONS"
+.IX Header "OPTIONS"
+.IP "\fB\-4\fR, \fB\-\-ipv4\fR" 5
+.IX Item "-4, --ipv4"
+Restrict name resolution and IPs to IPv4 addresses.
+.IP "\fB\-6\fR, \fB\-\-ipv6\fR" 5
+.IX Item "-6, --ipv6"
+Restrict name resolution and IPs to IPv6 addresses.
+.IP "\fB\-a\fR, \fB\-\-alive\fR" 5
+.IX Item "-a, --alive"
+Show systems that are alive.  (Options \fB\-c\fR and \fB\-C\fR override \fB\-a\fR.)
+.IP "\fB\-A\fR, \fB\-\-addr\fR" 5
+.IX Item "-A, --addr"
+Display targets by address rather than \s-1DNS\s0 name. Combined with \-d, the output
+will be both the ip and (if available) the hostname.
+.IP "\fB\-b\fR, \fB\-\-size\fR=\fI\s-1BYTES\s0\fR" 5
+.IX Item "-b, --size=BYTES"
+Number of bytes of ping data to send.  The minimum size (normally 12) allows
+room for the data that \fBfping\fR needs to do its work (sequence number,
+timestamp).  The reported received data size includes the \s-1IP\s0 header (normally
+20 bytes) and \s-1ICMP\s0 header (8 bytes), so the minimum total size is 40 bytes.
+Default is 56, as in \fBping\fR. Maximum is the theoretical maximum \s-1IP\s0 datagram
+size (64K), though most systems limit this to a smaller, system-dependent
+number. Cannot be used together with \fB\-\-icmp\-timestamp\fR.
+.IP "\fB\-B\fR, \fB\-\-backoff\fR=\fIN\fR" 5
+.IX Item "-B, --backoff=N"
+Backoff factor. In the default mode, \fBfping\fR 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 (\fB\-t\fR) 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, \fB\-\-count\fR=\fIN\fR" 5
+.IX Item "-c, --count=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 \fB\-q\fR or \fB\-Q\fR).
+Also, statistics about responses for each target are displayed when all
+requests have been sent (or when interrupted).  This option overrides \fB\-a\fR
+or \fB\-u\fR.
+.IP "\fB\-C\fR, \fB\-\-vcount\fR=\fIN\fR" 5
+.IX Item "-C, --vcount=N"
+Similar to \fB\-c\fR, but the per-target statistics are displayed in a format
+designed for automated response-time statistics gathering. For example:
+.Sp
+.Vb 2
+\& $ fping \-C 5 \-q somehost
+\& somehost : 91.7 37.0 29.2 \- 36.8
+.Ve
+.Sp
+shows the response time in milliseconds for each of the five requests, with the
+\&\f(CW\*(C`\-\*(C'\fR indicating that no response was received to the fourth request.  This
+option overrides \fB\-a\fR or \fB\-u\fR.
+.IP "\fB\-\-check\-source\fR" 5
+.IX Item "--check-source"
+Discard Echo replies that are sourced from a different address than the target
+address. This avoids spurious reachability results on busy monitoring systems
+where two \fBfping\fR instances with the same lower 16 bits of the process \s-1ID\s0 may
+be running at the same time.
+.IP "\fB\-d\fR, \fB\-\-rdns\fR" 5
+.IX Item "-d, --rdns"
+Use \s-1DNS\s0 to lookup address of ping target. This allows you to give fping
+a list of \s-1IP\s0 addresses as input and print hostnames in the output. This is similar
+to option \fB\-n\fR/\fB\-\-name\fR, but will force a reverse-DNS lookup even if you give
+hostnames as target (\s-1NAME\-\s0>\s-1IP\-\s0>\s-1NAME\s0).
+.IP "\fB\-D\fR, \fB\-\-timestamp\fR" 5
+.IX Item "-D, --timestamp"
+Add Unix timestamps in front of output lines generated with in looping or counting
+modes (\fB\-l\fR, \fB\-c\fR, or \fB\-C\fR).
+.Sp
+Subcommand: \fB\-\-timestamp\-format\fR=\fIctime|iso|rfc3339\fR
+.Sp
+Allow to change the timestamp format of the \fB\-D\fR option to the following format types.
+.Sp
+\&\fIctime\fR = \*(L"%c\*(R" (Example: Mon Jun 10 07:50:00 2024)
+.Sp
+\&\fIiso\fR = \*(L"%Y\-%m\-%dT%T%z\*(R" (Example: 2024\-06\-10T07:50:00+0200)
+.Sp
+\&\fIrfc3339\fR = \*(L"%Y\-%m\-%d \f(CW%H:\fR%M:%S\*(R" (Example: 2024\-06\-10 07:50:00)
+.IP "\fB\-e\fR, \fB\-\-elapsed\fR" 5
+.IX Item "-e, --elapsed"
+Show elapsed (round-trip) time of packets.
+.IP "\fB\-f\fR, \fB\-\-file\fR" 5
+.IX Item "-f, --file"
+Read list of targets from a file.
+.IP "\fB\-g\fR, \fB\-\-generate\fR \fIaddr/mask\fR" 5
+.IX Item "-g, --generate addr/mask"
+Generate a target list from a supplied \s-1IP\s0 netmask, or a starting and ending \s-1IP.\s0
+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:
+.Sp
+.Vb 1
+\& $ fping \-g 192.168.1.0/24
+.Ve
+.Sp
+or
+.Sp
+.Vb 1
+\& $ fping \-g 192.168.1.1 192.168.1.254
+.Ve
+.IP "\fB\-h\fR, \fB\-\-help\fR" 5
+.IX Item "-h, --help"
+Print usage message.
+.IP "\fB\-H\fR, \fB\-\-ttl\fR=\fIN\fR" 5
+.IX Item "-H, --ttl=N"
+Set the \s-1IP TTL\s0 field (time to live hops).
+.IP "\fB\-\-print\-ttl\fR" 5
+.IX Item "--print-ttl"
+Displays the IPv4 \s-1TTL\s0 value from the \s-1IP\s0 Header in the output.
+If \fBfping\fR cannot read the \s-1TTL\s0 value, \*(L"(\s-1TTL\s0 unknown)\*(R" is returned.
+IPv4 only, requires root privileges or cap_net_raw.
+.IP "\fB\-i\fR, \fB\-\-interval\fR=\fI\s-1MSEC\s0\fR" 5
+.IX Item "-i, --interval=MSEC"
+The minimum amount of time (in milliseconds) between sending a ping packet
+to any target (default is 10, minimum is 1).
+.IP "\fB\-I\fR, \fB\-\-iface\fR=\fI\s-1IFACE\s0\fR" 5
+.IX Item "-I, --iface=IFACE"
+Set the interface (requires \s-1SO_BINDTODEVICE\s0 support).
+.IP "\fB\-\-icmp\-timestamp\fR" 5
+.IX Item "--icmp-timestamp"
+Send \s-1ICMP\s0 timestamp requests (\s-1ICMP\s0 type 13) instead of \s-1ICMP\s0 Echo requests.
+Print \s-1ICMP\s0 timestamps for originate, receive, and transmit, together with
+the local receive time in the same format, in addition to normal output.
+Cannot be used together with \fB\-b\fR because \s-1ICMP\s0 timestamp messages have a fixed size.
+IPv4 only, requires root privileges or cap_net_raw.
+.IP "\fB\-k\fR, \fB\-\-fwmark\fR=\fI\s-1FWMARK\s0\fR" 5
+.IX Item "-k, --fwmark=FWMARK"
+Set \s-1FWMARK\s0 on ping packets for policy-based routing. Requires Linux kernel
+2.6.25<=, and root privileges or cap_net_admin.
+.IP "\fB\-l\fR, \fB\-\-loop\fR" 5
+.IX Item "-l, --loop"
+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, \fB\-\-all\fR" 5
+.IX Item "-m, --all"
+Send pings to each of a target host's multiple \s-1IP\s0 addresses (use of option '\-A'
+is recommended).
+.IP "\fB\-M\fR, \fB\-\-dontfrag\fR" 5
+.IX Item "-M, --dontfrag"
+Set the \*(L"Don't Fragment\*(R" bit in the \s-1IP\s0 header (used to determine/test the \s-1MTU\s0).
+.IP "\fB\-n\fR, \fB\-\-name\fR" 5
+.IX Item "-n, --name"
+If targets are specified as \s-1IP\s0 addresses, do a reverse-DNS lookup on them
+to print hostnames in the output.
+.IP "\fB\-N\fR, \fB\-\-netdata\fR" 5
+.IX Item "-N, --netdata"
+Format output for netdata (\-l \-Q are required). See: <https://netdata.cloud/>
+.IP "\fB\-o\fR, \fB\-\-outage\fR" 5
+.IX Item "-o, --outage"
+Calculate \*(L"outage time\*(R" based on the number of lost pings and the interval used (useful for network convergence tests).
+.IP "\fB\-O\fR, \fB\-\-tos\fR=\fIN\fR" 5
+.IX Item "-O, --tos=N"
+Set the typ of service flag (\s-1TOS\s0). \fIN\fR can be either decimal or hexadecimal
+(0xh) format.
+.IP "\fB\-\-print\-tos\fR" 5
+.IX Item "--print-tos"
+Displays the \s-1TOS\s0 value in the output. If \fBfping\fR cannot read the \s-1TOS\s0 value,
+\&\*(L"(\s-1TOS\s0 unknown)\*(R" is returned.
+IPv4 only, requires root privileges or cap_net_raw.
+.IP "\fB\-p\fR, \fB\-\-period\fR=\fI\s-1MSEC\s0\fR" 5
+.IX Item "-p, --period=MSEC"
+In looping or counting modes (\fB\-l\fR, \fB\-c\fR, or \fB\-C\fR), this parameter sets
+the time in milliseconds that \fBfping\fR waits between successive packets to
+an individual target. Default is 1000 and minimum is 10.
+.IP "\fB\-q\fR, \fB\-\-quiet\fR" 5
+.IX Item "-q, --quiet"
+Quiet. Don't show per-probe results, but only the final summary. Also don't
+show \s-1ICMP\s0 error messages.
+.IP "\fB\-Q\fR, \fB\-\-squiet\fR=\fISECS[,cumulative]\fR" 5
+.IX Item "-Q, --squiet=SECS[,cumulative]"
+Like \fB\-q\fR, but additionally show interval summary results every \fI\s-1SECS\s0\fR
+seconds. With \fIcumulative\fR, show summary results since start instead of
+for the last interval, unless option \fB\-N\fR is used, too.
+.IP "\fB\-r\fR, \fB\-\-retry\fR=\fIN\fR" 5
+.IX Item "-r, --retry=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.
+.IP "\fB\-R\fR, \fB\-\-random\fR" 5
+.IX Item "-R, --random"
+Instead of using all-zeros as the packet data, generate random bytes.
+Use to defeat, e.g., link data compression.
+.IP "\fB\-s\fR, \fB\-\-stats\fR" 5
+.IX Item "-s, --stats"
+Print cumulative statistics upon exit.
+.IP "\fB\-S\fR, \fB\-\-src\fR=\fIaddr\fR" 5
+.IX Item "-S, --src=addr"
+Set source address.
+.IP "\fB\-t\fR, \fB\-\-timeout\fR=\fI\s-1MSEC\s0\fR" 5
+.IX Item "-t, --timeout=MSEC"
+Initial target timeout in milliseconds. In the default, non-loop mode, the
+default timeout is 500ms, and it represents the amount of time that \fBfping\fR
+waits for a response to its first request. Successive timeouts are multiplied
+by the backoff factor specified with \fB\-B\fR.
+.Sp
+In loop/count mode, the default timeout is automatically adjusted to match
+the \*(L"period\*(R" value (but not more than 2000ms). You can still adjust the timeout
+value with this option, if you wish to, but note that setting a value larger
+than \*(L"period\*(R" produces inconsistent results, because the timeout value can
+be respected only for the last ping.
+.Sp
+Also note that any received replies that are larger than the timeout value, will
+be discarded.
+.IP "\fB\-T\fR \fIn\fR" 5
+.IX Item "-T n"
+Ignored (for compatibility with fping 2.4).
+.IP "\fB\-u\fR, \fB\-\-unreach\fR" 5
+.IX Item "-u, --unreach"
+Show targets that are unreachable.  (Options \fB\-c\fR and \fB\-C\fR override \fB\-u\fR.)
+.IP "\fB\-v\fR, \fB\-\-version\fR" 5
+.IX Item "-v, --version"
+Print \fBfping\fR version information.
+.IP "\fB\-x\fR, \fB\-\-reachable\fR=\fIN\fR" 5
+.IX Item "-x, --reachable=N"
+Given a list of hosts, this mode checks if number of reachable hosts is >= N
+and exits true in that case.
+.IP "\fB\-X\fR, \fB\-\-fast\-reachable\fR=\fIN\fR" 5
+.IX Item "-X, --fast-reachable=N"
+Given a list of hosts, this mode immediately exits true once N alive hosts
+have been found.
+.SH "EXAMPLES"
+.IX Header "EXAMPLES"
+Generate 20 pings to two hosts in ca. 1 second (i.e. one ping every 50 ms to
+each host), and report every ping \s-1RTT\s0 at the end:
+.PP
+.Vb 1
+\& $ fping \-\-quiet \-\-interval=1 \-\-vcount=20 \-\-period=50 127.0.0.1 127.0.0.2
+.Ve
+.SH "AUTHORS"
+.IX Header "AUTHORS"
+.IP "\(bu" 4
+Roland J. Schemers \s-1III,\s0 Stanford University, concept and versions 1.x
+.IP "\(bu" 4
+\&\s-1RL\s0 \*(L"Bob\*(R" Morgan, Stanford University, versions 2.x
+.IP "\(bu" 4
+David Papp, versions 2.3x and up
+.IP "\(bu" 4
+David Schweikert, versions 3.0 and up
+.PP
+\&\fBfping website: <http://www.fping.org>\fR
+.SH "DIAGNOSTICS"
+.IX Header "DIAGNOSTICS"
+Exit status is 0 if all the hosts (or the number of hosts specified with \fB\-x\fR
+or \fB\-X\fR) are reachable, 1 if some (or too many with \fB\-x\fR or \fB\-X\fR) hosts
+were unreachable, 2 if any \s-1IP\s0 addresses were not found, 3 for invalid command
+line arguments, and 4 for a system call failure.
+.SH "RESTRICTIONS"
+.IX Header "RESTRICTIONS"
+The number of addresses that can be generated using the \f(CW\*(C`\-g\*(C'\fR, \f(CW\*(C`\-\-generate\*(C'\fR
+option is limited to 131070 (the number of host addresses in one 15\-bit IPv4
+prefix).
+.PP
+If fping was configured with \f(CW\*(C`\-\-enable\-safe\-limits\*(C'\fR, the following values are
+not allowed for non-root users:
+.IP "\(bu" 4
+\&\fB\-i\fR \fIn\fR, where \fIn\fR < 1 msec
+.IP "\(bu" 4
+\&\fB\-p\fR \fIn\fR, where \fIn\fR < 10 msec
+.SH "SEE ALSO"
+.IX Header "SEE ALSO"
+\&\f(CWping(8)\fR
diff --git a/ci/tmp.VwGIuQgZdr/fping-5.4/doc/fping.pod b/ci/tmp.VwGIuQgZdr/fping-5.4/doc/fping.pod
new file mode 100644 (file)
index 0000000..7709225
--- /dev/null
@@ -0,0 +1,345 @@
+=head1 NAME
+
+fping - send ICMP ECHO_REQUEST packets to network hosts
+
+=head1 SYNOPSIS
+
+B<fping> [ 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.  Current statistics can be obtained without
+termination of process with signal SIGQUIT (^\ from the keyboard on most systems).
+
+=head1 OPTIONS
+
+=over 5
+
+=item B<-4>, B<--ipv4>
+
+Restrict name resolution and IPs to IPv4 addresses.
+
+=item B<-6>, B<--ipv6>
+
+Restrict name resolution and IPs to IPv6 addresses.
+
+=item B<-a>, B<--alive>
+
+Show systems that are alive.  (Options B<-c> and B<-C> override B<-a>.)
+
+=item B<-A>, B<--addr>
+
+Display targets by address rather than DNS name. Combined with -d, the output
+will be both the ip and (if available) the hostname.
+
+=item B<-b>, B<--size>=I<BYTES>
+
+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. Cannot be used together with B<--icmp-timestamp>.
+
+=item B<-B>, B<--backoff>=I<N>
+
+Backoff factor. 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 (B<-t>) 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>, B<--count>=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).  This option overrides B<-a>
+or B<-u>.
+
+=item B<-C>, B<--vcount>=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.  This
+option overrides B<-a> or B<-u>.
+
+=item B<--check-source>
+
+Discard Echo replies that are sourced from a different address than the target
+address. This avoids spurious reachability results on busy monitoring systems
+where two B<fping> instances with the same lower 16 bits of the process ID may
+be running at the same time.
+
+=item B<-d>, B<--rdns>
+
+Use DNS to lookup address of ping target. This allows you to give fping
+a list of IP addresses as input and print hostnames in the output. This is similar
+to option B<-n>/B<--name>, but will force a reverse-DNS lookup even if you give
+hostnames as target (NAME->IP->NAME).
+
+=item B<-D>, B<--timestamp>
+
+Add Unix timestamps in front of output lines generated with in looping or counting
+modes (B<-l>, B<-c>, or B<-C>).
+
+Subcommand: B<--timestamp-format>=I<ctime|iso|rfc3339>
+
+Allow to change the timestamp format of the B<-D> option to the following format types.
+
+I<ctime> = "%c" (Example: Mon Jun 10 07:50:00 2024)
+
+I<iso> = "%Y-%m-%dT%T%z" (Example: 2024-06-10T07:50:00+0200)
+
+I<rfc3339> = "%Y-%m-%d %H:%M:%S" (Example: 2024-06-10 07:50:00)
+
+=item B<-e>, B<--elapsed>
+
+Show elapsed (round-trip) time of packets.
+
+=item B<-f>, B<--file>
+
+Read list of targets from a file.
+
+=item B<-g>, B<--generate> 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>, B<--help>
+
+Print usage message.
+
+=item B<-H>, B<--ttl>=I<N>
+
+Set the IP TTL field (time to live hops).
+
+=item B<--print-ttl>
+
+Displays the IPv4 TTL value from the IP Header in the output.
+If B<fping> cannot read the TTL value, "(TTL unknown)" is returned.
+IPv4 only, requires root privileges or cap_net_raw.
+
+=item B<-i>, B<--interval>=I<MSEC>
+
+The minimum amount of time (in milliseconds) between sending a ping packet
+to any target (default is 10, minimum is 1).
+
+=item B<-I>, B<--iface>=I<IFACE>
+
+Set the interface (requires SO_BINDTODEVICE support).
+
+=item B<--icmp-timestamp>
+
+Send ICMP timestamp requests (ICMP type 13) instead of ICMP Echo requests.
+Print ICMP timestamps for originate, receive, and transmit, together with
+the local receive time in the same format, in addition to normal output.
+Cannot be used together with B<-b> because ICMP timestamp messages have a fixed size.
+IPv4 only, requires root privileges or cap_net_raw.
+
+=item B<-k>, B<--fwmark>=I<FWMARK>
+
+Set FWMARK on ping packets for policy-based routing. Requires Linux kernel
+2.6.25<=, and root privileges or cap_net_admin.
+
+=item B<-l>, B<--loop>
+
+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>, B<--all>
+
+Send pings to each of a target host's multiple IP addresses (use of option '-A'
+is recommended).
+
+=item B<-M>, B<--dontfrag>
+
+Set the "Don't Fragment" bit in the IP header (used to determine/test the MTU).
+
+=item B<-n>, B<--name>
+
+If targets are specified as IP addresses, do a reverse-DNS lookup on them
+to print hostnames in the output.
+
+=item B<-N>, B<--netdata>
+
+Format output for netdata (-l -Q are required). See: L<https://netdata.cloud/>
+
+=item B<-o>, B<--outage>
+
+Calculate "outage time" based on the number of lost pings and the interval used (useful for network convergence tests).
+
+=item B<-O>, B<--tos>=I<N>
+
+Set the typ of service flag (TOS). I<N> can be either decimal or hexadecimal
+(0xh) format.
+
+=item B<--print-tos>
+
+Displays the TOS value in the output. If B<fping> cannot read the TOS value,
+"(TOS unknown)" is returned.
+IPv4 only, requires root privileges or cap_net_raw.
+
+=item B<-p>, B<--period>=I<MSEC>
+
+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 and minimum is 10.
+
+=item B<-q>, B<--quiet>
+
+Quiet. Don't show per-probe results, but only the final summary. Also don't
+show ICMP error messages.
+
+=item B<-Q>, B<--squiet>=I<SECS[,cumulative]>
+
+Like B<-q>, but additionally show interval summary results every I<SECS>
+seconds. With I<cumulative>, show summary results since start instead of
+for the last interval, unless option B<-N> is used, too.
+
+=item B<-r>, B<--retry>=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<-R>, B<--random>
+
+Instead of using all-zeros as the packet data, generate random bytes.
+Use to defeat, e.g., link data compression.
+
+=item B<-s>, B<--stats>
+
+Print cumulative statistics upon exit.
+
+=item B<-S>, B<--src>=I<addr>
+
+Set source address.
+
+=item B<-t>, B<--timeout>=I<MSEC>
+
+Initial target timeout in milliseconds. In the default, non-loop mode, the
+default timeout is 500ms, and it represents the amount of time that B<fping>
+waits for a response to its first request. Successive timeouts are multiplied
+by the backoff factor specified with B<-B>.
+
+In loop/count mode, the default timeout is automatically adjusted to match
+the "period" value (but not more than 2000ms). You can still adjust the timeout
+value with this option, if you wish to, but note that setting a value larger
+than "period" produces inconsistent results, because the timeout value can
+be respected only for the last ping.
+
+Also note that any received replies that are larger than the timeout value, will
+be discarded.
+
+=item B<-T> I<n>
+
+Ignored (for compatibility with fping 2.4).
+
+=item B<-u>, B<--unreach>
+
+Show targets that are unreachable.  (Options B<-c> and B<-C> override B<-u>.)
+
+=item B<-v>, B<--version>
+
+Print B<fping> version information.
+
+=item B<-x>, B<--reachable>=I<N>
+
+Given a list of hosts, this mode checks if number of reachable hosts is >= N
+and exits true in that case.
+
+=item B<-X>, B<--fast-reachable>=I<N>
+
+Given a list of hosts, this mode immediately exits true once N alive hosts
+have been found.
+
+=back
+
+=head1 EXAMPLES
+
+Generate 20 pings to two hosts in ca. 1 second (i.e. one ping every 50 ms to
+each host), and report every ping RTT at the end:
+
+ $ fping --quiet --interval=1 --vcount=20 --period=50 127.0.0.1 127.0.0.2
+
+=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 (or the number of hosts specified with B<-x>
+or B<-X>) are reachable, 1 if some (or too many with B<-x> or B<-X>) 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
+
+The number of addresses that can be generated using the C<-g>, C<--generate>
+option is limited to 131070 (the number of host addresses in one 15-bit IPv4
+prefix).
+
+If fping was configured with C<--enable-safe-limits>, the following values are
+not allowed for non-root users:
+
+=over 4
+
+=item *
+
+B<-i> I<n>, where I<n> < 1 msec
+
+=item *
+
+B<-p> I<n>, where I<n> < 10 msec
+
+=back
+
+=head1 SEE ALSO
+
+C<ping(8)>
diff --git a/ci/tmp.VwGIuQgZdr/fping-5.4/src/Makefile.am b/ci/tmp.VwGIuQgZdr/fping-5.4/src/Makefile.am
new file mode 100644 (file)
index 0000000..c58e474
--- /dev/null
@@ -0,0 +1,11 @@
+AM_CFLAGS = -Wall -Wextra -Wno-sign-compare
+
+sbin_PROGRAMS = fping
+
+fping_SOURCES = fping.c seqmap.c socket4.c fping.h options.h seqmap.h optparse.c optparse.h
+fping_DEPENDENCIES = ../config.h
+
+if IPV6
+fping_SOURCES += socket6.c
+fping_CFLAGS = $(AM_CFLAGS) -DIPV6
+endif
diff --git a/ci/tmp.VwGIuQgZdr/fping-5.4/src/fping b/ci/tmp.VwGIuQgZdr/fping-5.4/src/fping
new file mode 100755 (executable)
index 0000000..dc0098d
Binary files /dev/null and b/ci/tmp.VwGIuQgZdr/fping-5.4/src/fping differ
diff --git a/ci/tmp.VwGIuQgZdr/fping-5.4/src/fping-fping.o b/ci/tmp.VwGIuQgZdr/fping-5.4/src/fping-fping.o
new file mode 100644 (file)
index 0000000..564be54
Binary files /dev/null and b/ci/tmp.VwGIuQgZdr/fping-5.4/src/fping-fping.o differ
diff --git a/ci/tmp.VwGIuQgZdr/fping-5.4/src/fping-optparse.o b/ci/tmp.VwGIuQgZdr/fping-5.4/src/fping-optparse.o
new file mode 100644 (file)
index 0000000..75fbf33
Binary files /dev/null and b/ci/tmp.VwGIuQgZdr/fping-5.4/src/fping-optparse.o differ
diff --git a/ci/tmp.VwGIuQgZdr/fping-5.4/src/fping-seqmap.o b/ci/tmp.VwGIuQgZdr/fping-5.4/src/fping-seqmap.o
new file mode 100644 (file)
index 0000000..72bd0f3
Binary files /dev/null and b/ci/tmp.VwGIuQgZdr/fping-5.4/src/fping-seqmap.o differ
diff --git a/ci/tmp.VwGIuQgZdr/fping-5.4/src/fping-socket4.o b/ci/tmp.VwGIuQgZdr/fping-5.4/src/fping-socket4.o
new file mode 100644 (file)
index 0000000..c770f1e
Binary files /dev/null and b/ci/tmp.VwGIuQgZdr/fping-5.4/src/fping-socket4.o differ
diff --git a/ci/tmp.VwGIuQgZdr/fping-5.4/src/fping-socket6.o b/ci/tmp.VwGIuQgZdr/fping-5.4/src/fping-socket6.o
new file mode 100644 (file)
index 0000000..4760776
Binary files /dev/null and b/ci/tmp.VwGIuQgZdr/fping-5.4/src/fping-socket6.o differ
diff --git a/ci/tmp.VwGIuQgZdr/fping-5.4/src/fping.c b/ci/tmp.VwGIuQgZdr/fping-5.4/src/fping.c
new file mode 100644 (file)
index 0000000..6779175
--- /dev/null
@@ -0,0 +1,3201 @@
+/*
+ * 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.
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+#include "fping.h"
+#include "config.h"
+#include "options.h"
+#include "optparse.h"
+
+#include <errno.h>
+#include <inttypes.h>
+#include <signal.h>
+#include <stdarg.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <time.h>
+
+#include "seqmap.h"
+
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif /* HAVE_UNISTD_H */
+
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif /* HAVE_STDLIB_H */
+
+#include <stddef.h>
+#include <string.h>
+
+#include <sys/socket.h>
+#include <sys/time.h>
+#include <sys/types.h>
+
+#if HAVE_SYS_FILE_H
+#include <sys/file.h>
+#endif /* HAVE_SYS_FILE_H */
+
+#ifdef IPV6
+#include <netinet/icmp6.h>
+#endif
+#include <netinet/in_systm.h>
+
+#include <netinet/ip.h>
+#include <netinet/ip_icmp.h>
+
+#include <arpa/inet.h>
+#include <ctype.h>
+#include <netdb.h>
+
+#include <sys/select.h>
+
+/*** compatibility ***/
+
+/* Mac OS X's getaddrinfo() does not fail if we use an invalid combination,
+ * e.g. AF_INET6 with "127.0.0.1". If we pass AI_UNUSABLE to flags, it behaves
+ * like other platforms. But AI_UNUSABLE isn't available on other platforms,
+ * and we can safely use 0 for flags instead.
+ */
+#ifndef AI_UNUSABLE
+#define AI_UNUSABLE 0
+#endif
+
+/* MSG_TRUNC available on Linux kernel 2.2+, makes recvmsg return the full
+ * length of the raw packet received, even if the buffer is smaller */
+#ifndef MSG_TRUNC
+#define MSG_TRUNC 0
+#define RECV_BUFSIZE 4096
+#else
+#define RECV_BUFSIZE 128
+#endif
+
+/*** externals ***/
+
+extern char *optarg;
+extern int optind, opterr;
+#ifndef h_errno
+extern int h_errno;
+#endif
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+/*** Constants ***/
+
+/* CLOCK_MONTONIC starts under macOS, OpenBSD and FreeBSD with undefined positive point and can not be use
+ * see github PR #217
+ * The configure script detect the predefined operating systems an set CLOCK_REALTIME using over ONLY_CLOCK_REALTIME variable
+ */
+#if HAVE_SO_TIMESTAMPNS || ONLY_CLOCK_REALTIME
+#define CLOCKID CLOCK_REALTIME
+#endif
+
+#if !defined(CLOCKID)
+#if defined(CLOCK_MONOTONIC)
+#define CLOCKID CLOCK_MONOTONIC
+#else
+#define CLOCKID CLOCK_REALTIME
+#endif
+#endif
+
+/*** Ping packet defines ***/
+
+#define MAX_IP_PACKET 65535 /* (theoretical) max IPv4 packet size */
+#define SIZE_IP_HDR 20 /* min IPv4 header size */
+#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 131070 /* maximum number of hosts that -g can generate */
+
+/* sized so as to be like traditional ping */
+#define DEFAULT_PING_DATA_SIZE 56
+
+/* ICMP Timestamp has a fixed payload size of 12 bytes */
+#define ICMP_TIMESTAMP_DATA_SIZE 12
+
+#ifdef FPING_SAFE_LIMITS
+#define MIN_INTERVAL_MS 1 /* in millisec */
+#define MIN_PERHOST_INTERVAL_MS 10 /* in millisec */
+#else
+#define MIN_INTERVAL_MS 0
+/* Set a very low limit for the per-host interval, even if safe limits are
+ * disabled, so that the memory allocation of the event storage is not
+ * unreasonably high. 0.001 ms would mean in theory at least 592 mbps of data
+ * sent to a single host, which probably doesn't make sense in any scenario. */
+#define MIN_PERHOST_INTERVAL_MS 0.001
+#endif
+
+/* response time array flags */
+#define RESP_WAITING -1
+#define RESP_UNUSED -2
+#define RESP_ERROR -3
+#define RESP_TIMEOUT -4
+
+/* debugging flags */
+#if defined(DEBUG) || defined(_DEBUG)
+#define DBG_TRACE 1
+#define DBG_SENT_TIMES 2
+#define DBG_RANDOM_LOSE_FEW 4
+#define DBG_RANDOM_LOSE_MANY 8
+#define DBG_PRINT_PER_SYSTEM 16
+#define DBG_REPORT_ALL_RTTS 32
+#endif /* DEBUG || _DEBUG */
+
+/* Long names for ICMP packet types */
+#define ICMP_TYPE_STR_MAX 18
+char *icmp_type_str[19] = {
+    "ICMP Echo Reply", /* 0 */
+    "",
+    "",
+    "ICMP Unreachable", /* 3 */
+    "ICMP Source Quench", /* 4 */
+    "ICMP Redirect", /* 5 */
+    "",
+    "",
+    "ICMP Echo", /* 8 */
+    "",
+    "",
+    "ICMP Time Exceeded", /* 11 */
+    "ICMP Parameter Problem", /* 12 */
+    "ICMP Timestamp Request", /* 13 */
+    "ICMP Timestamp Reply", /* 14 */
+    "ICMP Information Request", /* 15 */
+    "ICMP Information Reply", /* 16 */
+    "ICMP Mask Request", /* 17 */
+    "ICMP Mask Reply" /* 18 */
+};
+
+char *icmp_unreach_str[16] = {
+    "ICMP Network Unreachable", /* 0 */
+    "ICMP Host Unreachable", /* 1 */
+    "ICMP Protocol Unreachable", /* 2 */
+    "ICMP Port Unreachable", /* 3 */
+    "ICMP Unreachable (Fragmentation Needed)", /* 4 */
+    "ICMP Unreachable (Source Route Failed)", /* 5 */
+    "ICMP Unreachable (Destination Network Unknown)", /* 6 */
+    "ICMP Unreachable (Destination Host Unknown)", /* 7 */
+    "ICMP Unreachable (Source Host Isolated)", /* 8 */
+    "ICMP Unreachable (Communication with Network Prohibited)", /* 9 */
+    "ICMP Unreachable (Communication with Host Prohibited)", /* 10 */
+    "ICMP Unreachable (Network Unreachable For Type Of Service)", /* 11 */
+    "ICMP Unreachable (Host Unreachable For Type Of Service)", /* 12 */
+    "ICMP Unreachable (Communication Administratively Prohibited)", /* 13 */
+    "ICMP Unreachable (Host Precedence Violation)", /* 14 */
+    "ICMP Unreachable (Precedence cutoff in effect)" /* 15 */
+};
+
+#define ICMP_UNREACH_MAXTYPE 15
+
+struct event;
+typedef struct host_entry {
+    int i; /* index into array */
+    char *name; /* name as given by user */
+    char *host; /* text description of host */
+    struct sockaddr_storage saddr; /* internet address */
+    socklen_t saddr_len;
+    int64_t timeout; /* time to wait for response */
+    int64_t last_send_time; /* time of last packet sent */
+    int num_sent; /* number of ping packets sent (for statistics) */
+    int num_recv; /* number of pings received (duplicates ignored) */
+    int num_recv_total; /* number of pings received, including duplicates */
+    int64_t max_reply; /* longest response time */
+    int64_t min_reply; /* shortest response time */
+    int64_t 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 */
+    int64_t max_reply_i; /* longest response time */
+    int64_t min_reply_i; /* shortest response time */
+    int64_t total_time_i; /* sum of response times */
+    int64_t *resp_times; /* individual response times */
+
+    /* to avoid allocating two struct events each time that we send a ping, we
+     * preallocate here two struct events for each ping that we might send for
+     * this host. */
+    struct event *event_storage_ping;
+    struct event *event_storage_timeout;
+} HOST_ENTRY;
+
+int event_storage_count; /* how many events can be stored in host_entry->event_storage_xxx */
+
+/* basic algorithm to ensure that we have correct data at all times:
+ *
+ * 1. when a ping is sent:
+ *    - two events get added into event_queue:
+ *      - t+PERIOD: ping event
+ *      - t+TIMEOUT: timeout event
+ *
+ * 2. when a ping is received:
+ *    - record statistics (increase num_sent and num_received)
+ *    - remove timeout event (we store the event in seqmap, so that we can retrieve it when the response is received)
+ *
+ * 3. when a timeout happens:
+ *    - record statistics (increase num_sent only)
+ */
+
+#define EV_TYPE_PING 1
+#define EV_TYPE_TIMEOUT 2
+
+struct event {
+    struct event *ev_prev;
+    struct event *ev_next;
+    int64_t ev_time;
+    struct host_entry *host;
+    int ping_index;
+};
+
+struct event_queue {
+    struct event *first;
+    struct event *last;
+};
+
+/*** globals ***/
+
+HOST_ENTRY **table = NULL; /* array of pointers to items in the list */
+
+/* we keep two separate queues: a ping queue, for when the next ping should be
+ * sent, and a timeout queue. the reason for having two separate queues is that
+ * the ping period and the timeout value are different, so if we put them in
+ * the same event queue, we would need to scan many more entries when inserting
+ * into the sorted list.
+ */
+struct event_queue event_queue_ping;
+struct event_queue event_queue_timeout;
+
+char *prog;
+int ident4 = 0; /* our icmp identity field */
+int ident6 = 0;
+int socket4 = -1;
+int socktype4 = -1;
+int using_sock_dgram4 = 0;
+#ifndef IPV6
+int hints_ai_family = AF_INET;
+#else
+int socket6 = -1;
+int socktype6 = -1;
+int hints_ai_family = AF_UNSPEC;
+#endif
+
+volatile sig_atomic_t status_snapshot = 0;
+volatile sig_atomic_t finish_requested = 0;
+
+unsigned int debugging = 0;
+
+/* all time-related values are int64_t nanoseconds */
+unsigned int retry = DEFAULT_RETRY;
+int64_t timeout = (int64_t)DEFAULT_TIMEOUT * 1000000;
+int64_t interval = (int64_t)DEFAULT_INTERVAL * 1000000;
+int64_t perhost_interval = (int64_t)DEFAULT_PERHOST_INTERVAL * 1000000;
+float backoff = DEFAULT_BACKOFF_FACTOR;
+unsigned int ping_data_size = DEFAULT_PING_DATA_SIZE;
+unsigned int count = 1, min_reachable = 0;
+unsigned int trials;
+int64_t report_interval = 0;
+unsigned int ttl = 0;
+int src_addr_set = 0;
+struct in_addr src_addr;
+#ifdef IPV6
+int src_addr6_set = 0;
+struct in6_addr src_addr6;
+#endif
+
+/* global stats */
+int64_t max_reply = 0;
+int64_t min_reply = 0;
+int64_t total_replies = 0;
+int64_t sum_replies = 0;
+int max_hostname_len = 0;
+int num_hosts = 0; /* total number of hosts */
+int num_alive = 0, /* total number alive */
+    num_unreachable = 0, /* total number unreachable */
+    num_noaddress = 0; /* total number of addresses not found */
+int num_timeout = 0, /* number of times select timed out */
+    num_pingsent = 0, /* total pings sent */
+    num_pingreceived = 0, /* total pings received */
+    num_othericmprcvd = 0; /* total non-echo-reply ICMP received */
+
+struct timespec current_time; /* current time (pseudo) */
+int64_t current_time_ns;
+int64_t start_time;
+int64_t end_time;
+int64_t last_send_time; /* time last ping was sent */
+int64_t next_report_time; /* time next -Q report is expected */
+
+/* switches */
+int generate_flag = 0; /* flag for IP list generation */
+int verbose_flag, quiet_flag, stats_flag, unreachable_flag, alive_flag;
+int elapsed_flag, version_flag, count_flag, loop_flag, netdata_flag;
+int per_recv_flag, report_all_rtts_flag, name_flag, addr_flag, backoff_flag, rdns_flag;
+int multif_flag, timeout_flag, fast_reachable;
+int outage_flag = 0;
+int timestamp_flag = 0;
+int timestamp_format_flag = 0;
+int random_data_flag = 0;
+int cumulative_stats_flag = 0;
+int check_source_flag = 0;
+int icmp_request_typ = 0;
+int print_tos_flag = 0;
+int print_ttl_flag = 0;
+int size_flag = 0;
+#if defined(DEBUG) || defined(_DEBUG)
+int randomly_lose_flag, trace_flag, print_per_system_flag;
+int lose_factor;
+#endif /* DEBUG || _DEBUG */
+
+unsigned int fwmark = 0;
+
+char *filename = NULL; /* file containing hosts to ping */
+
+/*** forward declarations ***/
+
+void add_name(char *name);
+void add_addr(char *name, char *host, struct sockaddr *ipaddr, socklen_t ipaddr_len);
+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 send_ping(HOST_ENTRY *h, int index);
+void usage(int);
+int wait_for_reply(int64_t);
+void print_per_system_stats(void);
+void print_per_system_splits(void);
+void stats_reset_interval(HOST_ENTRY *h);
+void print_netdata(void);
+void print_global_stats(void);
+void main_loop();
+void signal_handler(int);
+void finish();
+const char *sprint_tm(int64_t t);
+void ev_enqueue(struct event_queue *queue, struct event *event);
+struct event *ev_dequeue(struct event_queue *queue);
+void ev_remove(struct event_queue *queue, struct event *event);
+void add_cidr(char *);
+void add_range(char *, char *);
+void add_addr_range_ipv4(unsigned long, unsigned long);
+void print_warning(char *fmt, ...);
+int addr_cmp(struct sockaddr *a, struct sockaddr *b);
+void host_add_ping_event(HOST_ENTRY *h, int index, int64_t ev_time);
+void host_add_timeout_event(HOST_ENTRY *h, int index, int64_t ev_time);
+struct event *host_get_timeout_event(HOST_ENTRY *h, int index);
+void stats_add(HOST_ENTRY *h, int index, int success, int64_t latency);
+void update_current_time();
+void print_timestamp_format(int64_t current_time_ns, int timestamp_format);
+static uint32_t ms_since_midnight_utc(int64_t time_val);
+
+/************************************************************
+
+  Function: p_setsockopt
+
+*************************************************************
+
+  Inputs:  p_uid: privileged uid. Others as per setsockopt(2)
+
+  Description:
+
+  Elevates privileges to p_uid when required, calls
+  setsockopt, and drops privileges back.
+
+************************************************************/
+
+int p_setsockopt(uid_t p_uid, int sockfd, int level, int optname,
+    const void *optval, socklen_t optlen)
+{
+    const uid_t saved_uid = geteuid();
+    int res;
+
+    if (p_uid != saved_uid && seteuid(p_uid)) {
+        perror("cannot elevate privileges for setsockopt");
+    }
+
+    res = setsockopt(sockfd, level, optname, optval, optlen);
+
+    if (p_uid != saved_uid && seteuid(saved_uid)) {
+        perror("fatal error: could not drop privileges after setsockopt");
+        /* continuing would be a security hole */
+        exit(4);
+    }
+
+    return res;
+}
+
+/************************************************************
+
+  Function: main
+
+*************************************************************
+
+  Inputs:  int argc, char** argv
+
+  Description:
+
+  Main program entry point
+
+************************************************************/
+
+int main(int argc, char **argv)
+{
+/* Debug: CPU Performance */
+#if defined(DEBUG) || defined(_DEBUG)
+    clock_t perf_cpu_start, perf_cpu_end;
+    double perf_cpu_time_used;
+    perf_cpu_start = clock();
+#endif /* DEBUG || _DEBUG */
+
+    int c;
+    const uid_t suid = geteuid();
+    int tos = 0;
+    struct optparse optparse_state;
+#ifdef USE_SIGACTION
+    struct sigaction act;
+#endif
+
+    /* pre-parse -h/--help, so that we also can output help information
+     * without trying to open the socket, which might fail */
+    prog = argv[0];
+    if (argc == 2 && (strcmp(argv[1], "-h") == 0 || strcmp(argv[1], "--help") == 0)) {
+        usage(0);
+    }
+
+    socket4 = open_ping_socket_ipv4(&socktype4);
+#ifdef __linux__
+    /* We only treat SOCK_DGRAM differently on Linux, where the IPv4 header
+     * structure is missing in the message.
+     */
+    using_sock_dgram4 = (socktype4 == SOCK_DGRAM);
+#endif
+
+#ifdef IPV6
+    socket6 = open_ping_socket_ipv6(&socktype6);
+    /* if called (sym-linked) via 'fping6', imply '-6'
+     * for backward compatibility */
+    if (strstr(prog, "fping6")) {
+        hints_ai_family = AF_INET6;
+    }
+#endif
+
+    memset(&src_addr, 0, sizeof(src_addr));
+#ifdef IPV6
+    memset(&src_addr6, 0, sizeof(src_addr6));
+#endif
+
+    if (!suid && suid != getuid()) {
+        /* *temporarily* drop privileges */
+        if (seteuid(getuid()) == -1)
+            perror("cannot setuid");
+    }
+
+    optparse_init(&optparse_state, argv);
+    ident4 = ident6 = htons(getpid() & 0xFFFF);
+    verbose_flag = 1;
+    backoff_flag = 1;
+    opterr = 1;
+
+    /* get command line options */
+
+    struct optparse_long longopts[] = {
+        { "ipv4", '4', OPTPARSE_NONE },
+        { "ipv6", '6', OPTPARSE_NONE },
+        { "alive", 'a', OPTPARSE_NONE },
+        { "addr", 'A', OPTPARSE_NONE },
+        { "size", 'b', OPTPARSE_REQUIRED },
+        { "backoff", 'B', OPTPARSE_REQUIRED },
+        { "count", 'c', OPTPARSE_REQUIRED },
+        { "vcount", 'C', OPTPARSE_REQUIRED },
+        { "rdns", 'd', OPTPARSE_NONE },
+        { "timestamp", 'D', OPTPARSE_NONE },
+        { "timestamp-format", '0', OPTPARSE_REQUIRED },
+        { "elapsed", 'e', OPTPARSE_NONE },
+        { "file", 'f', OPTPARSE_REQUIRED },
+        { "generate", 'g', OPTPARSE_NONE },
+        { "help", 'h', OPTPARSE_NONE },
+        { "ttl", 'H', OPTPARSE_REQUIRED },
+        { "interval", 'i', OPTPARSE_REQUIRED },
+        { "iface", 'I', OPTPARSE_REQUIRED },
+        { "icmp-timestamp", '0', OPTPARSE_NONE },
+#ifdef SO_MARK
+        { "fwmark", 'k', OPTPARSE_REQUIRED },
+#endif
+        { "loop", 'l', OPTPARSE_NONE },
+        { "all", 'm', OPTPARSE_NONE },
+        { "dontfrag", 'M', OPTPARSE_NONE },
+        { "name", 'n', OPTPARSE_NONE },
+        { "netdata", 'N', OPTPARSE_NONE },
+        { "outage", 'o', OPTPARSE_NONE },
+        { "tos", 'O', OPTPARSE_REQUIRED },
+        { "period", 'p', OPTPARSE_REQUIRED },
+        { "quiet", 'q', OPTPARSE_NONE },
+        { "squiet", 'Q', OPTPARSE_REQUIRED },
+        { "retry", 'r', OPTPARSE_REQUIRED },
+        { "random", 'R', OPTPARSE_NONE },
+        { "stats", 's', OPTPARSE_NONE },
+        { "src", 'S', OPTPARSE_REQUIRED },
+        { "timeout", 't', OPTPARSE_REQUIRED },
+        { NULL, 'T', OPTPARSE_REQUIRED },
+        { "unreach", 'u', OPTPARSE_NONE },
+        { "version", 'v', OPTPARSE_NONE },
+        { "reachable", 'x', OPTPARSE_REQUIRED },
+        { "fast-reachable", 'X', OPTPARSE_REQUIRED },
+        { "check-source", '0', OPTPARSE_NONE },
+        { "print-tos", '0', OPTPARSE_NONE },
+        { "print-ttl", '0', OPTPARSE_NONE },
+#if defined(DEBUG) || defined(_DEBUG)
+        { NULL, 'z', OPTPARSE_REQUIRED },
+#endif
+        { 0, 0, 0 }
+    };
+
+    float opt_value_float;
+    while ((c = optparse_long(&optparse_state, longopts, NULL)) != EOF) {
+        switch (c) {
+        case '0':
+            if(strstr(optparse_state.optlongname, "timestamp-format") != NULL) {
+                if(strcmp(optparse_state.optarg, "ctime") == 0) {
+                  timestamp_format_flag = 1;
+                }else if(strcmp(optparse_state.optarg, "iso") == 0) {
+                  timestamp_format_flag = 2;
+                }else if(strcmp(optparse_state.optarg, "rfc3339") == 0) {
+                  timestamp_format_flag = 3;
+                }else{
+                  usage(1);
+                }
+            } else if (strstr(optparse_state.optlongname, "check-source") != NULL) {
+                check_source_flag = 1;
+            } else if (strstr(optparse_state.optlongname, "icmp-timestamp") != NULL) {
+#ifdef IPV6
+                if (hints_ai_family != AF_UNSPEC && hints_ai_family != AF_INET) {
+                    fprintf(stderr, "%s: ICMP Timestamp is IPv4 only\n", prog);
+                    exit(1);
+                }
+                hints_ai_family = AF_INET;
+#endif
+                icmp_request_typ = 13;
+                ping_data_size = ICMP_TIMESTAMP_DATA_SIZE;
+            } else if (strstr(optparse_state.optlongname, "print-tos") != NULL) {
+                print_tos_flag = 1;
+            } else if (strstr(optparse_state.optlongname, "print-ttl") != NULL) {
+                print_ttl_flag = 1;
+            } else {
+                usage(1);
+            }
+            break;
+        case '4':
+#ifdef IPV6
+            if (hints_ai_family != AF_UNSPEC && hints_ai_family != AF_INET) {
+                fprintf(stderr, "%s: can't specify both -4 and -6\n", prog);
+                exit(1);
+            }
+            hints_ai_family = AF_INET;
+#endif
+            break;
+        case '6':
+#ifdef IPV6
+            if (hints_ai_family != AF_UNSPEC && hints_ai_family != AF_INET6) {
+                fprintf(stderr, "%s: can't specify both -4 and -6\n", prog);
+                exit(1);
+            }
+            hints_ai_family = AF_INET6;
+#else
+            fprintf(stderr, "%s: IPv6 not supported by this binary\n", prog);
+            exit(1);
+#endif
+            break;
+        case 'M':
+#ifdef IP_MTU_DISCOVER
+            if (socket4 >= 0) {
+                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 >= 0) {
+                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, "%s, -M option not supported on this platform\n", prog);
+            exit(1);
+#endif
+            break;
+
+        case 't':
+            if (sscanf(optparse_state.optarg, "%f", &opt_value_float) != 1)
+                usage(1);
+            if (opt_value_float < 0) {
+                usage(1);
+            }
+            timeout = opt_value_float * 1000000;
+            timeout_flag = 1;
+            break;
+
+        case 'r':
+            if (sscanf(optparse_state.optarg, "%u", &retry) != 1)
+                usage(1);
+            break;
+
+        case 'i':
+            if (sscanf(optparse_state.optarg, "%f", &opt_value_float) != 1)
+                usage(1);
+            if (opt_value_float < 0) {
+                usage(1);
+            }
+            interval = opt_value_float * 1000000;
+            break;
+
+        case 'p':
+            if (sscanf(optparse_state.optarg, "%f", &opt_value_float) != 1)
+                usage(1);
+            if (opt_value_float < 0) {
+                usage(1);
+            }
+            perhost_interval = opt_value_float * 1000000;
+
+            break;
+
+        case 'c':
+            if (!(count = (unsigned int)atoi(optparse_state.optarg)))
+                usage(1);
+
+            count_flag = 1;
+            break;
+
+        case 'C':
+            if (!(count = (unsigned int)atoi(optparse_state.optarg)))
+                usage(1);
+
+            count_flag = 1;
+            report_all_rtts_flag = 1;
+            break;
+
+        case 'b':
+            if (sscanf(optparse_state.optarg, "%u", &ping_data_size) != 1)
+                usage(1);
+            size_flag = 1;
+            break;
+
+        case 'h':
+            usage(0);
+            break;
+
+        case 'q':
+            verbose_flag = 0;
+            quiet_flag = 1;
+            break;
+
+        case 'Q':
+            verbose_flag = 0;
+            quiet_flag = 1;
+            if (sscanf(optparse_state.optarg, "%f", &opt_value_float) != 1)
+                usage(1);
+            if (opt_value_float < 0) {
+                usage(1);
+            }
+            report_interval = opt_value_float * 1e9;
+
+            /* recognize keyword(s) after number, ignore everything else */
+            {
+                char *comma = strchr(optparse_state.optarg, ',');
+                if ((comma != NULL) && (strcmp(++comma, "cumulative") == 0)) {
+                    cumulative_stats_flag = 1;
+                }
+            }
+
+            break;
+
+        case 'e':
+            elapsed_flag = 1;
+            break;
+
+        case 'm':
+            multif_flag = 1;
+            break;
+
+        case 'N':
+            netdata_flag = 1;
+            break;
+
+        case 'n':
+            name_flag = 1;
+            if (rdns_flag) {
+                fprintf(stderr, "%s: use either one of -d or -n\n", prog);
+                exit(1);
+            }
+            break;
+
+        case 'd':
+            rdns_flag = 1;
+            if (name_flag) {
+                fprintf(stderr, "%s: use either one of -d or -n\n", prog);
+                exit(1);
+            }
+            break;
+
+        case 'A':
+            addr_flag = 1;
+            break;
+
+        case 'B':
+            if (!(backoff = atof(optparse_state.optarg)))
+                usage(1);
+
+            break;
+
+        case 's':
+            stats_flag = 1;
+            break;
+
+        case 'D':
+            timestamp_flag = 1;
+            break;
+
+        case 'R':
+            random_data_flag = 1;
+            break;
+
+        case 'l':
+            loop_flag = 1;
+            backoff_flag = 0;
+            break;
+
+        case 'u':
+            unreachable_flag = 1;
+            break;
+
+        case 'a':
+            alive_flag = 1;
+            break;
+
+        case 'H':
+            if (!(ttl = (unsigned int)atoi(optparse_state.optarg)))
+                usage(1);
+            break;
+
+#if defined(DEBUG) || defined(_DEBUG)
+        case 'z':
+            if (sscanf(optparse_state.optarg, "0x%x", &debugging) != 1)
+                if (sscanf(optparse_state.optarg, "%u", &debugging) != 1)
+                    usage(1);
+
+            break;
+#endif /* DEBUG || _DEBUG */
+
+        case 'v':
+            printf("%s: Version %s\n", prog, VERSION);
+            exit(0);
+
+        case 'x':
+            if (!(min_reachable = (unsigned int)atoi(optparse_state.optarg)))
+                usage(1);
+            break;
+
+        case 'X':
+            if (!(min_reachable = (unsigned int)atoi(optparse_state.optarg)))
+                usage(1);
+            fast_reachable = 1;
+            break;
+
+        case 'f':
+            filename = optparse_state.optarg;
+            break;
+#ifdef SO_MARK
+        case 'k':
+            if (!(fwmark = (unsigned int)atol(optparse_state.optarg)))
+                usage(1);
+
+            if (socket4 >= 0)
+                if(-1 == p_setsockopt(suid, socket4, SOL_SOCKET, SO_MARK, &fwmark, sizeof fwmark))
+                    perror("fwmark ipv4");
+
+#ifdef IPV6
+            if (socket6 >= 0)
+                if(-1 == p_setsockopt(suid, socket6, SOL_SOCKET, SO_MARK, &fwmark, sizeof fwmark))
+                    perror("fwmark ipv6");
+#endif
+
+            break;
+#endif
+
+        case 'g':
+            /* use IP list generation */
+            /* mutually exclusive with using file input or command line targets */
+            generate_flag = 1;
+            break;
+
+        case 'S':
+            if (inet_pton(AF_INET, optparse_state.optarg, &src_addr)) {
+                src_addr_set = 1;
+                break;
+            }
+#ifdef IPV6
+            if (inet_pton(AF_INET6, optparse_state.optarg, &src_addr6)) {
+                src_addr6_set = 1;
+                break;
+            }
+#endif
+            fprintf(stderr, "%s: can't parse source address: %s\n", prog, optparse_state.optarg);
+            exit(1);
+
+        case 'I':
+#ifdef SO_BINDTODEVICE
+            if (socket4 >= 0) {
+                if (p_setsockopt(suid, socket4, SOL_SOCKET, SO_BINDTODEVICE, optparse_state.optarg, strlen(optparse_state.optarg))) {
+                    perror("binding to specific interface (SO_BINTODEVICE)");
+                    exit(1);
+                }
+            }
+#ifdef IPV6
+            if (socket6 >= 0) {
+                if (p_setsockopt(suid, socket6, SOL_SOCKET, SO_BINDTODEVICE, optparse_state.optarg, strlen(optparse_state.optarg))) {
+                    perror("binding to specific interface (SO_BINTODEVICE), IPV6");
+                    exit(1);
+                }
+            }
+#endif
+#else
+            printf("%s: cant bind to a particular net interface since SO_BINDTODEVICE is not supported on your os.\n", prog);
+            exit(3);
+            ;
+#endif
+            break;
+
+        case 'T':
+            /* This option is ignored for compatibility reasons ("select timeout" is not meaningful anymore) */
+            break;
+
+        case 'O':
+            if (sscanf(optparse_state.optarg, "%i", &tos) == 1) {
+                if (socket4 >= 0) {
+                    if (setsockopt(socket4, IPPROTO_IP, IP_TOS, &tos, sizeof(tos))) {
+                        perror("setting type of service octet IP_TOS");
+                    }
+                }
+#if defined(IPV6) && defined(IPV6_TCLASS)
+                if (socket6 >= 0) {
+                    if (setsockopt(socket6, IPPROTO_IPV6, IPV6_TCLASS, &tos, sizeof(tos))) {
+                        perror("setting type of service octet IPV6_TCLASS");
+                    }
+                }
+#endif
+            }
+            else {
+                usage(1);
+            }
+            break;
+
+        case 'o':
+            outage_flag = 1;
+            break;
+
+        case '?':
+            fprintf(stderr, "%s: %s\n", argv[0], optparse_state.errmsg);
+            fprintf(stderr, "see 'fping -h' for usage information\n");
+            exit(1);
+            break;
+        }
+    }
+
+    /* permanently drop privileges */
+    if (suid != getuid() && setuid(getuid())) {
+        perror("fatal: failed to permanently drop privileges");
+        /* continuing would be a security hole */
+        exit(4);
+    }
+
+    /* validate various option settings */
+
+#ifndef IPV6
+    if (socket4 < 0) {
+        crash_and_burn("can't create socket (must run as root?)");
+    }
+#else
+    if ((socket4 < 0 && socket6 < 0) || (hints_ai_family == AF_INET6 && socket6 < 0)) {
+        crash_and_burn("can't create socket (must run as root?)");
+    }
+#endif
+
+    if (ttl > 255) {
+        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", prog);
+        exit(1);
+    }
+
+    if (count_flag && loop_flag) {
+        fprintf(stderr, "%s: specify only one of c, l\n", prog);
+        exit(1);
+    }
+
+    if (interval < (float)MIN_INTERVAL_MS * 1000000 && getuid()) {
+        fprintf(stderr, "%s: -i must be >= %g\n", prog, (float)MIN_INTERVAL_MS);
+        exit(1);
+    }
+
+    if (perhost_interval < (float)MIN_PERHOST_INTERVAL_MS * 1000000 && getuid()) {
+        fprintf(stderr, "%s: -p must be >= %g\n", prog, (float)MIN_PERHOST_INTERVAL_MS);
+        exit(1);
+    }
+
+    if (ping_data_size > MAX_PING_DATA) {
+        fprintf(stderr, "%s: data size %u not valid, must not be larger than %u\n",
+            prog, ping_data_size, (unsigned int)MAX_PING_DATA);
+        exit(1);
+    }
+
+    if ((backoff > MAX_BACKOFF_FACTOR) || (backoff < MIN_BACKOFF_FACTOR)) {
+        fprintf(stderr, "%s: backoff factor %.1f not valid, must be between %.1f and %.1f\n",
+            prog, backoff, MIN_BACKOFF_FACTOR, MAX_BACKOFF_FACTOR);
+        exit(1);
+    }
+
+    if (icmp_request_typ == 13 && size_flag != 0) {
+        fprintf(stderr, "%s: cannot change ICMP Timestamp size\n", prog);
+        exit(1);
+    }
+
+    if (count_flag) {
+        if (verbose_flag)
+            per_recv_flag = 1;
+
+        alive_flag = unreachable_flag = verbose_flag = 0;
+    }
+
+    if (loop_flag) {
+        if (!report_interval)
+            per_recv_flag = 1;
+
+        alive_flag = unreachable_flag = verbose_flag = 0;
+    }
+
+    if (alive_flag || unreachable_flag || min_reachable)
+        verbose_flag = 0;
+
+    trials = (count > retry + 1) ? count : retry + 1;
+
+    /* auto-tune default timeout for count/loop modes
+     * see also github #32 */
+    if (loop_flag || count_flag) {
+        if (!timeout_flag) {
+            timeout = perhost_interval;
+            if (timeout > (int64_t)AUTOTUNE_TIMEOUT_MAX * 1000000) {
+                timeout = (int64_t)AUTOTUNE_TIMEOUT_MAX * 1000000;
+            }
+        }
+    }
+
+#if defined(DEBUG) || defined(_DEBUG)
+    if (debugging & DBG_TRACE)
+        trace_flag = 1;
+
+    if (debugging & DBG_RANDOM_LOSE_FEW) {
+        randomly_lose_flag = 1;
+        lose_factor = 1; /* ie, 1/4 */
+    }
+
+    if (debugging & DBG_RANDOM_LOSE_MANY) {
+        randomly_lose_flag = 1;
+        lose_factor = 5; /* ie, 3/4 */
+    }
+
+    if (debugging & DBG_PRINT_PER_SYSTEM)
+        print_per_system_flag = 1;
+
+    if ((debugging & DBG_REPORT_ALL_RTTS) && !loop_flag)
+        report_all_rtts_flag = 1;
+
+    if (trace_flag) {
+        fprintf(stderr, "%s:\n  count: %u, retry: %u, interval: %.0f ms\n",
+            prog, count, retry, interval / 1e6);
+        fprintf(stderr, "  perhost_interval: %.0f ms, timeout: %.0f\n",
+            perhost_interval / 1e6, timeout / 1e6);
+        fprintf(stderr, "  ping_data_size = %u, trials = %u\n",
+            ping_data_size, trials);
+
+        if (verbose_flag)
+            fprintf(stderr, "  verbose_flag set\n");
+        if (multif_flag)
+            fprintf(stderr, "  multif_flag set\n");
+        if (name_flag)
+            fprintf(stderr, "  name_flag set\n");
+        if (addr_flag)
+            fprintf(stderr, "  addr_flag set\n");
+        if (stats_flag)
+            fprintf(stderr, "  stats_flag set\n");
+        if (unreachable_flag)
+            fprintf(stderr, "  unreachable_flag set\n");
+        if (alive_flag)
+            fprintf(stderr, "  alive_flag set\n");
+        if (elapsed_flag)
+            fprintf(stderr, "  elapsed_flag set\n");
+        if (version_flag)
+            fprintf(stderr, "  version_flag set\n");
+        if (count_flag)
+            fprintf(stderr, "  count_flag set\n");
+        if (loop_flag)
+            fprintf(stderr, "  loop_flag set\n");
+        if (backoff_flag)
+            fprintf(stderr, "  backoff_flag set\n");
+        if (per_recv_flag)
+            fprintf(stderr, "  per_recv_flag set\n");
+        if (report_all_rtts_flag)
+            fprintf(stderr, "  report_all_rtts_flag set\n");
+        if (randomly_lose_flag)
+            fprintf(stderr, "  randomly_lose_flag set\n");
+        if (print_per_system_flag)
+            fprintf(stderr, "  print_per_system_flag set\n");
+        if (outage_flag)
+            fprintf(stderr, "  outage_flag set\n");
+        if (netdata_flag)
+            fprintf(stderr, "  netdata_flag set\n");
+    }
+#endif /* DEBUG || _DEBUG */
+
+    /* set the TTL, if the -H option was set (otherwise ttl will be = 0) */
+    if (ttl > 0) {
+        if (socket4 >= 0) {
+            if (setsockopt(socket4, IPPROTO_IP, IP_TTL, &ttl, sizeof(ttl))) {
+                perror("setting time to live");
+            }
+        }
+#ifdef IPV6
+        if (socket6 >= 0) {
+            if (setsockopt(socket6, IPPROTO_IPV6, IPV6_UNICAST_HOPS, &ttl, sizeof(ttl))) {
+                perror("setting time to live");
+            }
+        }
+#endif
+    }
+
+#if HAVE_SO_TIMESTAMPNS
+    {
+        int opt = 1;
+        if (socket4 >= 0) {
+            if (setsockopt(socket4, SOL_SOCKET, SO_TIMESTAMPNS, &opt, sizeof(opt))) {
+                if (setsockopt(socket4, SOL_SOCKET, SO_TIMESTAMP, &opt, sizeof(opt))) {
+                    perror("setting SO_TIMESTAMPNS and SO_TIMESTAMP option");
+                }
+            }
+        }
+#ifdef IPV6
+        if (socket6 >= 0) {
+            if (setsockopt(socket6, SOL_SOCKET, SO_TIMESTAMPNS, &opt, sizeof(opt))) {
+                if (setsockopt(socket6, SOL_SOCKET, SO_TIMESTAMP, &opt, sizeof(opt))) {
+                    perror("setting SO_TIMESTAMPNS and SO_TIMESTAMP option (IPv6)");
+                }
+            }
+        }
+#endif
+    }
+#endif
+
+    update_current_time();
+    start_time = current_time_ns;
+
+    /* handle host names supplied on command line or in a file */
+    /* if the generate_flag is on, then generate the IP list */
+
+    argv = &argv[optparse_state.optind];
+    argc -= optparse_state.optind;
+
+    /* calculate how many ping can be in-flight per host */
+    if (count_flag) {
+        event_storage_count = count;
+    }
+    else if (loop_flag) {
+        if (perhost_interval > timeout) {
+            event_storage_count = 1;
+        }
+        else {
+            event_storage_count = 1 + timeout / perhost_interval;
+        }
+    }
+    else {
+        event_storage_count = 1;
+    }
+
+    /* file and generate are mutually exclusive */
+    /* file and command line are mutually exclusive */
+    /* generate requires command line parameters beyond the switches */
+    if ((*argv && filename) || (filename && generate_flag) || (generate_flag && !*argv))
+        usage(1);
+
+    /* if no conditions are specified, then assume input from stdin */
+    if (!*argv && !filename && !generate_flag)
+        filename = "-";
+
+    if (*argv && !generate_flag) {
+        while (*argv) {
+            add_name(*argv);
+            ++argv;
+        }
+    }
+    else if (filename) {
+        FILE *ping_file;
+        char line[132];
+        char host[132];
+
+        if (strcmp(filename, "-") == 0)
+            ping_file = fdopen(0, "r");
+        else
+            ping_file = fopen(filename, "r");
+
+        if (!ping_file)
+            errno_crash_and_burn("fopen");
+
+        while (fgets(line, sizeof(line), ping_file)) {
+            if (sscanf(line, "%s", host) != 1)
+                continue;
+
+            if ((!*host) || (host[0] == '#')) /* magic to avoid comments */
+                continue;
+
+            add_name(host);
+        }
+
+        fclose(ping_file);
+    }
+    else if (*argv && generate_flag) {
+        if (argc == 1) {
+            /* one target: we expect a cidr range (n.n.n.n/m) */
+            add_cidr(argv[0]);
+        }
+        else if (argc == 2) {
+            add_range(argv[0], argv[1]);
+        }
+        else {
+            usage(1);
+        }
+    }
+    else {
+        usage(1);
+    }
+
+    if (!num_hosts) {
+        exit(num_noaddress ? 2 : 1);
+    }
+
+    if (socket4 >= 0 && (src_addr_set || socktype4 == SOCK_DGRAM)) {
+        socket_set_src_addr_ipv4(socket4, &src_addr, (socktype4 == SOCK_DGRAM) ? &ident4 : NULL);
+    }
+#ifdef IPV6
+    if (socket6 >= 0 && (src_addr6_set || socktype6 == SOCK_DGRAM)) {
+        socket_set_src_addr_ipv6(socket6, &src_addr6, (socktype6 == SOCK_DGRAM) ? &ident6 : NULL);
+    }
+#endif
+
+    /* allocate and initialize array to map host nr to host_entry */
+    {
+        struct event *cursor = event_queue_ping.first;
+        int i = 0;
+        table = (HOST_ENTRY **)calloc(num_hosts, sizeof(HOST_ENTRY *));
+        if (!table)
+            crash_and_burn("Can't malloc array of hosts");
+        /* initialize table of hosts. we know that we have ping events scheduled
+         * for each of them */
+        for (cursor = event_queue_ping.first; cursor; cursor = cursor->ev_next) {
+            table[i] = cursor->host;
+            cursor->host->i = i;
+            i++;
+        }
+    }
+
+    init_ping_buffer_ipv4(ping_data_size);
+#ifdef IPV6
+    init_ping_buffer_ipv6(ping_data_size);
+#endif
+
+#ifdef USE_SIGACTION
+    memset(&act, 0, sizeof(act));
+    act.sa_handler = signal_handler;
+    sigemptyset(&act.sa_mask);
+    sigaddset(&act.sa_mask, SIGINT);
+    sigaddset(&act.sa_mask, SIGQUIT);
+    act.sa_flags = SA_RESTART;
+    if (sigaction(SIGQUIT, &act, NULL) || sigaction(SIGINT, &act, NULL)) {
+        crash_and_burn("failure to set signal handler");
+    }
+#else
+    signal(SIGINT, signal_handler);
+    signal(SIGQUIT, signal_handler);
+#endif
+    setlinebuf(stdout);
+
+    if (report_interval) {
+        next_report_time = current_time_ns + report_interval;
+    }
+
+    last_send_time = 0;
+
+    seqmap_init();
+
+    /* main loop */
+    main_loop();
+
+/* Debug: CPU Performance */
+#if defined(DEBUG) || defined(_DEBUG)
+    perf_cpu_end = clock();
+    perf_cpu_time_used = ((double) (perf_cpu_end - perf_cpu_start)) / CLOCKS_PER_SEC;
+    printf("[DEBUG] CPU time used: %f sec", perf_cpu_time_used);
+#endif /* DEBUG || _DEBUG */
+
+    finish();
+
+    return 0;
+}
+
+static inline int64_t timespec_ns(struct timespec *a)
+{
+    return ((int64_t)a->tv_sec * 1000000000) + a->tv_nsec;
+}
+
+void add_cidr(char *addr)
+{
+    char *addr_end;
+    char *mask_str;
+    unsigned long mask;
+    unsigned long bitmask;
+    int ret;
+    struct addrinfo addr_hints;
+    struct addrinfo *addr_res;
+    unsigned long net_addr;
+    unsigned long net_last;
+
+    /* Split address from mask */
+    addr_end = strchr(addr, '/');
+    if (addr_end == NULL) {
+        usage(1);
+    }
+    *addr_end = '\0';
+    mask_str = addr_end + 1;
+    mask = atoi(mask_str);
+
+    /* parse address (IPv4 only) */
+    memset(&addr_hints, 0, sizeof(struct addrinfo));
+    addr_hints.ai_family = AF_UNSPEC;
+    addr_hints.ai_flags = AI_NUMERICHOST;
+    ret = getaddrinfo(addr, NULL, &addr_hints, &addr_res);
+    if (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, "%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);
+    freeaddrinfo(addr_res);
+
+    /* check mask */
+    if (mask < 1 || mask > 32) {
+        fprintf(stderr, "%s: netmask must be between 1 and 32 (is: %s)\n", prog, mask_str);
+        exit(1);
+    }
+
+    /* convert mask integer from 1 to 32 to a bitmask */
+    bitmask = ((unsigned long)0xFFFFFFFF) << (32 - mask);
+
+    /* calculate network range */
+    net_addr &= bitmask;
+    net_last = net_addr + ((unsigned long)0x1 << (32 - mask)) - 1;
+
+    /* exclude network and broadcast address for regular prefixes */
+    if (mask < 31) {
+        net_last--;
+        net_addr++;
+    }
+
+    /* add all hosts in that network (net_addr and net_last inclusive) */
+    add_addr_range_ipv4(net_addr, net_last);
+}
+
+void add_range(char *start, char *end)
+{
+    struct addrinfo addr_hints;
+    struct addrinfo *addr_res;
+    unsigned long start_long;
+    unsigned long end_long;
+    int ret;
+
+    /* parse start address (IPv4 only) */
+    memset(&addr_hints, 0, sizeof(struct addrinfo));
+    addr_hints.ai_family = AF_UNSPEC;
+    addr_hints.ai_flags = AI_NUMERICHOST;
+    ret = getaddrinfo(start, NULL, &addr_hints, &addr_res);
+    if (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, "%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);
+
+    /* parse end address (IPv4 only) */
+    memset(&addr_hints, 0, sizeof(struct addrinfo));
+    addr_hints.ai_family = AF_UNSPEC;
+    addr_hints.ai_flags = AI_NUMERICHOST;
+    ret = getaddrinfo(end, NULL, &addr_hints, &addr_res);
+    if (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, "%s: -g works only with IPv4 addresses\n", prog);
+        exit(1);
+    }
+    end_long = ntohl(((struct sockaddr_in *)addr_res->ai_addr)->sin_addr.s_addr);
+    freeaddrinfo(addr_res);
+
+    /* add IPv4 addresses from closed interval [start_long,end_long] */
+    add_addr_range_ipv4(start_long, end_long);
+}
+
+void add_addr_range_ipv4(unsigned long start_long, unsigned long end_long)
+{
+    /* check if generator limit is exceeded */
+    if (end_long >= start_long + MAX_GENERATE) {
+        fprintf(stderr, "%s: -g parameter generates too many addresses\n", prog);
+        exit(1);
+    }
+
+    /* generate */
+    for (; start_long <= end_long; start_long++) {
+        struct in_addr in_addr_tmp;
+        char buffer[20];
+        in_addr_tmp.s_addr = htonl(start_long);
+        inet_ntop(AF_INET, &in_addr_tmp, buffer, sizeof(buffer));
+        add_name(buffer);
+    }
+}
+
+void main_loop()
+{
+    int64_t lt;
+    int64_t wait_time_ns;
+    struct event *event;
+    struct host_entry *h;
+
+    while (event_queue_ping.first || event_queue_timeout.first) {
+        dbg_printf("%s", "# main_loop\n");
+
+        /* timeout event ? */
+        if (event_queue_timeout.first && event_queue_timeout.first->ev_time - current_time_ns <= 0) {
+            event = ev_dequeue(&event_queue_timeout);
+            h = event->host;
+
+            dbg_printf("%s [%d]: timeout event\n", h->host, event->ping_index);
+
+            stats_add(h, event->ping_index, 0, -1);
+
+            if (per_recv_flag) {
+                if (timestamp_flag) {
+                    print_timestamp_format(current_time_ns, timestamp_format_flag);
+                }
+                printf("%-*s : [%d], timed out",
+                    max_hostname_len, h->host, event->ping_index);
+                if (h->num_recv > 0) {
+                    printf(" (%s avg, ", sprint_tm(h->total_time / h->num_recv));
+                }
+                else {
+                    printf(" (NaN avg, ");
+                }
+                if (h->num_recv <= h->num_sent) {
+                    printf("%d%% loss)",
+                        ((h->num_sent - h->num_recv) * 100) / h->num_sent);
+                }
+                else {
+                    printf("%d%% return)",
+                        (h->num_recv_total * 100) / h->num_sent);
+                }
+                printf("\n");
+            }
+
+            /* do we need to send a retry? */
+            if (!loop_flag && !count_flag) {
+                if (h->num_sent < retry + 1) {
+                    if (backoff_flag) {
+                        h->timeout *= backoff;
+                    }
+                    send_ping(h, event->ping_index);
+                }
+            }
+
+            /* note: we process first timeout events, because we might need to
+             * wait to process ping events, while we for sure never need to
+             * wait for timeout events.
+             */
+            continue;
+        }
+
+        /* ping event ? */
+        if (event_queue_ping.first && event_queue_ping.first->ev_time - current_time_ns <= 0) {
+            /* Make sure that we don't ping more than once every "interval" */
+            lt = current_time_ns - last_send_time;
+            if (lt < interval)
+                goto wait_for_reply;
+
+            /* Dequeue the event */
+            event = ev_dequeue(&event_queue_ping);
+            h = event->host;
+
+            dbg_printf("%s [%d]: ping event\n", h->host, event->ping_index);
+
+            /* Send the ping */
+            send_ping(h, event->ping_index);
+
+            /* Loop and count mode: schedule next ping */
+            if (loop_flag || (count_flag && event->ping_index + 1 < count)) {
+                host_add_ping_event(h, event->ping_index + 1, event->ev_time + perhost_interval);
+            }
+        }
+
+    wait_for_reply:
+
+        /* When is the next ping next event? */
+        wait_time_ns = -1;
+        if (event_queue_ping.first) {
+            wait_time_ns = event_queue_ping.first->ev_time - current_time_ns;
+            if (wait_time_ns < 0)
+                wait_time_ns = 0;
+            /* make sure that we wait enough, so that the inter-ping delay is
+             * bigger than 'interval' */
+            if (wait_time_ns < interval) {
+                lt = current_time_ns - last_send_time;
+                if (lt < interval) {
+                    wait_time_ns = interval - lt;
+                }
+            }
+
+            dbg_printf("next ping event in %.0f ms (%s)\n", wait_time_ns / 1e6, event_queue_ping.first->host->host);
+        }
+
+        /* When is the next timeout event? */
+        if (event_queue_timeout.first) {
+            int64_t wait_time_timeout = event_queue_timeout.first->ev_time - current_time_ns;
+            if (wait_time_ns < 0 || wait_time_timeout < wait_time_ns) {
+                wait_time_ns = wait_time_timeout;
+                if (wait_time_ns < 0) {
+                    wait_time_ns = 0;
+                }
+            }
+
+            dbg_printf("next timeout event in %.0f ms (%s)\n", wait_time_timeout / 1e6, event_queue_timeout.first->host->host);
+        }
+
+        /* When is the next report due? */
+        if (report_interval && (loop_flag || count_flag)) {
+            int64_t wait_time_next_report = next_report_time - current_time_ns;
+            if (wait_time_next_report < wait_time_ns) {
+                wait_time_ns = wait_time_next_report;
+                if (wait_time_ns < 0) {
+                    wait_time_ns = 0;
+                }
+            }
+
+            dbg_printf("next report  event in %0.f ms\n", wait_time_next_report / 1e6);
+        }
+
+        /* if wait_time is still -1, it means that we are waiting for nothing... */
+        if (wait_time_ns == -1) {
+            break;
+        }
+
+        /* end of loop was requested by interrupt signal handler */
+        if (finish_requested) {
+            break;
+        }
+
+        /* Receive replies */
+        /* (this is what sleeps during each loop iteration) */
+        dbg_printf("waiting up to %.0f ms\n", wait_time_ns / 1e6);
+        if (wait_for_reply(wait_time_ns)) {
+            while (wait_for_reply(0))
+                ; /* process other replies in the queue */
+        }
+
+        update_current_time();
+
+        if (status_snapshot) {
+            status_snapshot = 0;
+            print_per_system_splits();
+        }
+
+        /* Print report */
+        if (report_interval && (loop_flag || count_flag) && (current_time_ns >= next_report_time)) {
+            if (netdata_flag)
+                print_netdata();
+            else
+                print_per_system_splits();
+
+            while (current_time_ns >= next_report_time) {
+                next_report_time += report_interval;
+            }
+        }
+    }
+}
+
+/************************************************************
+
+  Function: signal_handler
+
+*************************************************************
+
+  Inputs:  int signum
+
+  Description:
+
+  SIGQUIT signal handler - set flag and return
+  SIGINT signal handler - set flag and return
+
+************************************************************/
+
+void signal_handler(int signum)
+{
+    switch (signum) {
+    case SIGINT:
+        finish_requested = 1;
+        break;
+
+    case SIGQUIT:
+        status_snapshot = 1;
+        break;
+    }
+}
+
+/************************************************************
+
+  Function: update_current_time
+
+*************************************************************/
+
+void update_current_time()
+{
+    clock_gettime(CLOCKID, &current_time);
+    current_time_ns = timespec_ns(&current_time);
+}
+
+/************************************************************
+
+  Function: finish
+
+*************************************************************
+
+  Inputs:  void (none)
+
+  Description:
+
+  Main program clean up and exit point
+
+************************************************************/
+
+void finish()
+{
+    int i;
+    HOST_ENTRY *h;
+
+    update_current_time();
+    end_time = current_time_ns;
+
+    /* tot up unreachables */
+    for (i = 0; i < num_hosts; i++) {
+        h = table[i];
+
+        if (!h->num_recv) {
+            num_unreachable++;
+
+            if (verbose_flag || unreachable_flag) {
+                printf("%s", h->host);
+
+                if (verbose_flag)
+                    printf(" is unreachable");
+
+                printf("\n");
+            }
+        }
+    }
+
+    if (count_flag || loop_flag)
+        print_per_system_stats();
+#if defined(DEBUG) || defined(_DEBUG)
+    else if (print_per_system_flag)
+        print_per_system_stats();
+#endif /* DEBUG || _DEBUG */
+
+    if (stats_flag)
+        print_global_stats();
+
+    if (min_reachable) {
+        if ((num_hosts - num_unreachable) >= min_reachable) {
+            printf("Enough hosts reachable (required: %d, reachable: %d)\n", min_reachable, num_hosts - num_unreachable);
+            exit(0);
+        }
+        else {
+            printf("Not enough hosts reachable (required: %d, reachable: %d)\n", min_reachable, num_hosts - num_unreachable);
+            exit(1);
+        }
+    }
+
+    if (num_noaddress)
+        exit(2);
+    else if (num_alive != num_hosts)
+        exit(1);
+
+    exit(0);
+}
+
+/************************************************************
+
+  Function: print_per_system_stats
+
+*************************************************************
+
+  Inputs:  void (none)
+
+  Description:
+
+
+************************************************************/
+
+void print_per_system_stats(void)
+{
+    int i, j, avg, outage_ms;
+    HOST_ENTRY *h;
+    int64_t resp;
+
+    if (verbose_flag || per_recv_flag)
+        fprintf(stderr, "\n");
+
+    for (i = 0; i < num_hosts; i++) {
+        h = table[i];
+        fprintf(stderr, "%-*s :", max_hostname_len, h->host);
+
+        if (report_all_rtts_flag) {
+            for (j = 0; j < h->num_sent; j++) {
+                if ((resp = h->resp_times[j]) >= 0)
+                    fprintf(stderr, " %s", sprint_tm(resp));
+                else
+                    fprintf(stderr, " -");
+            }
+
+            fprintf(stderr, "\n");
+        }
+        else {
+            if (h->num_recv <= h->num_sent) {
+                fprintf(stderr, " xmt/rcv/%%loss = %d/%d/%d%%",
+                    h->num_sent, h->num_recv, h->num_sent > 0 ? ((h->num_sent - h->num_recv) * 100) / h->num_sent : 0);
+
+                if (outage_flag) {
+                    /* Time outage total */
+                    outage_ms = (h->num_sent - h->num_recv) * perhost_interval / 1e6;
+                    fprintf(stderr, ", outage(ms) = %d", outage_ms);
+                }
+            }
+            else {
+                fprintf(stderr, " xmt/rcv/%%return = %d/%d/%d%%",
+                    h->num_sent, h->num_recv,
+                    h->num_sent > 0 ? ((h->num_recv * 100) / h->num_sent) : 0);
+            }
+
+            if (h->num_recv) {
+                avg = h->total_time / h->num_recv;
+                fprintf(stderr, ", min/avg/max = %s", sprint_tm(h->min_reply));
+                fprintf(stderr, "/%s", sprint_tm(avg));
+                fprintf(stderr, "/%s", sprint_tm(h->max_reply));
+            }
+
+            fprintf(stderr, "\n");
+        }
+    }
+}
+
+/************************************************************
+
+  Function: print_netdata
+
+*************************************************************
+
+  Inputs:  void (none)
+
+  Description:
+
+
+************************************************************/
+
+void print_netdata(void)
+{
+    static int sent_charts = 0;
+
+    int i;
+    int64_t avg;
+    HOST_ENTRY *h;
+
+    for (i = 0; i < num_hosts; i++) {
+        h = table[i];
+
+        if (!sent_charts) {
+            printf("CHART fping.%s_packets '' 'FPing Packets' packets '%s' fping.packets line 110020 %.0f\n", h->name, h->host, report_interval / 1e9);
+            printf("DIMENSION xmt sent absolute 1 1\n");
+            printf("DIMENSION rcv received absolute 1 1\n");
+        }
+
+        printf("BEGIN fping.%s_packets\n", h->name);
+        printf("SET xmt = %d\n", h->num_sent_i);
+        printf("SET rcv = %d\n", h->num_recv_i);
+        printf("END\n");
+
+        if (!sent_charts) {
+            printf("CHART fping.%s_quality '' 'FPing Quality' percentage '%s' fping.quality area 110010 %.0f\n", h->name, h->host, report_interval / 1e9);
+            printf("DIMENSION returned '' absolute 1 1\n");
+            /* printf("DIMENSION lost '' absolute 1 1\n"); */
+        }
+
+        printf("BEGIN fping.%s_quality\n", h->name);
+        /*
+        if( h->num_recv_i <= h->num_sent_i )
+            printf("SET lost = %d\n", h->num_sent_i > 0 ? ( ( h->num_sent_i - h->num_recv_i ) * 100 ) / h->num_sent_i : 0 );
+        else
+            printf("SET lost = 0\n");
+*/
+
+        printf("SET returned = %d\n", h->num_sent_i > 0 ? ((h->num_recv_i * 100) / h->num_sent_i) : 0);
+        printf("END\n");
+
+        if (!sent_charts) {
+            printf("CHART fping.%s_latency '' 'FPing Latency' ms '%s' fping.latency area 110000 %.0f\n", h->name, h->host, report_interval / 1e9);
+            printf("DIMENSION min minimum absolute 1 1000000\n");
+            printf("DIMENSION max maximum absolute 1 1000000\n");
+            printf("DIMENSION avg average absolute 1 1000000\n");
+        }
+
+        printf("BEGIN fping.%s_latency\n", h->name);
+        if (h->num_recv_i) {
+            avg = h->total_time_i / h->num_recv_i;
+            printf("SET min = %" PRId64 "\n", h->min_reply_i);
+            printf("SET avg = %" PRId64 "\n", avg);
+            printf("SET max = %" PRId64 "\n", h->max_reply_i);
+        }
+        printf("END\n");
+
+        stats_reset_interval(h);
+    }
+
+    sent_charts = 1;
+}
+
+/************************************************************
+
+  Function: print_per_system_splits
+
+*************************************************************
+
+  Inputs:  void (none)
+
+  Description:
+
+
+************************************************************/
+
+void print_per_system_splits(void)
+{
+    int i, avg, outage_ms_i;
+    HOST_ENTRY *h;
+    struct tm *curr_tm;
+
+    if (verbose_flag || per_recv_flag)
+        fprintf(stderr, "\n");
+
+    update_current_time();
+    curr_tm = localtime((time_t *)&current_time.tv_sec);
+    fprintf(stderr, "[%2.2d:%2.2d:%2.2d]\n", curr_tm->tm_hour,
+        curr_tm->tm_min, curr_tm->tm_sec);
+
+    for (i = 0; i < num_hosts; i++) {
+        h = table[i];
+        fprintf(stderr, "%-*s :", max_hostname_len, h->host);
+
+        if (h->num_recv_i <= h->num_sent_i) {
+            fprintf(stderr, " xmt/rcv/%%loss = %d/%d/%d%%",
+                h->num_sent_i, h->num_recv_i, h->num_sent_i > 0 ? ((h->num_sent_i - h->num_recv_i) * 100) / h->num_sent_i : 0);
+
+            if (outage_flag) {
+                /* Time outage  */
+                outage_ms_i = (h->num_sent_i - h->num_recv_i) * perhost_interval / 1e6;
+                fprintf(stderr, ", outage(ms) = %d", outage_ms_i);
+            }
+        }
+        else {
+            fprintf(stderr, " xmt/rcv/%%return = %d/%d/%d%%",
+                h->num_sent_i, h->num_recv_i, h->num_sent_i > 0 ? ((h->num_recv_i * 100) / h->num_sent_i) : 0);
+        }
+
+        if (h->num_recv_i) {
+            avg = h->total_time_i / h->num_recv_i;
+            fprintf(stderr, ", min/avg/max = %s", sprint_tm(h->min_reply_i));
+            fprintf(stderr, "/%s", sprint_tm(avg));
+            fprintf(stderr, "/%s", sprint_tm(h->max_reply_i));
+        }
+
+        fprintf(stderr, "\n");
+        if (!cumulative_stats_flag) {
+            stats_reset_interval(h);
+        }
+    }
+}
+
+/************************************************************
+
+  Function: print_global_stats
+
+*************************************************************
+
+  Inputs:  void (none)
+
+  Description:
+
+
+************************************************************/
+
+void print_global_stats(void)
+{
+    fprintf(stderr, "\n");
+    fprintf(stderr, " %7d targets\n", num_hosts);
+    fprintf(stderr, " %7d alive\n", num_alive);
+    fprintf(stderr, " %7d unreachable\n", num_unreachable);
+    fprintf(stderr, " %7d unknown addresses\n", num_noaddress);
+    fprintf(stderr, "\n");
+    fprintf(stderr, " %7d timeouts (waiting for response)\n", num_timeout);
+    fprintf(stderr, " %7d ICMP Echos sent\n", num_pingsent);
+    fprintf(stderr, " %7d ICMP Echo Replies received\n", num_pingreceived);
+    fprintf(stderr, " %7d other ICMP received\n", num_othericmprcvd);
+    fprintf(stderr, "\n");
+
+    if (total_replies == 0) {
+        min_reply = 0;
+        max_reply = 0;
+        total_replies = 1;
+        sum_replies = 0;
+    }
+
+    fprintf(stderr, " %s ms (min round trip time)\n", sprint_tm(min_reply));
+    fprintf(stderr, " %s ms (avg round trip time)\n",
+        sprint_tm(sum_replies / total_replies));
+    fprintf(stderr, " %s ms (max round trip time)\n", sprint_tm(max_reply));
+    fprintf(stderr, " %12.3f sec (elapsed real time)\n",
+        (end_time - start_time) / 1e9);
+    fprintf(stderr, "\n");
+}
+
+/************************************************************
+
+  Function: send_ping
+
+*************************************************************
+
+  Inputs:  int s, HOST_ENTRY *h
+
+  Description:
+
+  Compose and transmit an ICMP_ECHO REQUEST packet.  The IP packet
+  will be added on by the kernel.  The ID field is our UNIX process ID,
+  and the sequence number is an index into an array of outstanding
+  ping requests. The sequence number will later be used to quickly
+  figure out who the ping reply came from.
+
+************************************************************/
+
+int send_ping(HOST_ENTRY *h, int index)
+{
+    int n;
+    int myseq;
+    int ret = 1;
+    uint8_t proto = ICMP_ECHO;
+
+    update_current_time();
+    h->last_send_time = current_time_ns;
+    myseq = seqmap_add(h->i, index, current_time_ns);
+
+    dbg_printf("%s [%d]: send ping\n", h->host, index);
+
+    if (h->saddr.ss_family == AF_INET && socket4 >= 0) {
+        if(icmp_request_typ == 13)
+            proto = ICMP_TSTAMP;
+        n = socket_sendto_ping_ipv4(socket4, (struct sockaddr *)&h->saddr, h->saddr_len, myseq, ident4, proto);
+    }
+#ifdef IPV6
+    else if (h->saddr.ss_family == AF_INET6 && socket6 >= 0) {
+        n = socket_sendto_ping_ipv6(socket6, (struct sockaddr *)&h->saddr, h->saddr_len, myseq, ident6);
+    }
+#endif
+    else {
+        return 0;
+    }
+
+    /* error sending? */
+    if (
+        (n < 0)
+#if defined(EHOSTDOWN)
+        && errno != EHOSTDOWN
+#endif
+    ) {
+        if (verbose_flag) {
+            print_warning("%s: error while sending ping: %s\n", h->host, strerror(errno));
+        }
+        else {
+            dbg_printf("%s: error while sending ping: %s\n", h->host, strerror(errno));
+        }
+
+        h->num_sent++;
+        h->num_sent_i++;
+        if (!loop_flag)
+            h->resp_times[index] = RESP_ERROR;
+
+        ret = 0;
+    }
+    else {
+        /* schedule timeout */
+        host_add_timeout_event(h, index, current_time_ns + h->timeout);
+
+        /* mark this trial as outstanding */
+        if (!loop_flag) {
+            h->resp_times[index] = RESP_WAITING;
+        }
+    }
+
+    num_pingsent++;
+    last_send_time = h->last_send_time;
+
+    return (ret);
+}
+
+int socket_can_read(struct timeval *timeout)
+{
+    int nfound;
+    fd_set readset;
+    int socketmax;
+
+#ifndef IPV6
+    socketmax = socket4;
+#else
+    socketmax = socket4 > socket6 ? socket4 : socket6;
+#endif
+
+select_again:
+    FD_ZERO(&readset);
+    if (socket4 >= 0)
+        FD_SET(socket4, &readset);
+#ifdef IPV6
+    if (socket6 >= 0)
+        FD_SET(socket6, &readset);
+#endif
+
+    nfound = select(socketmax + 1, &readset, NULL, NULL, timeout);
+    if (nfound < 0) {
+        if (errno == EINTR) {
+            /* interrupted system call: redo the select */
+            goto select_again;
+        }
+        else {
+            perror("select");
+        }
+    }
+
+    if (nfound > 0) {
+        if (socket4 >= 0 && FD_ISSET(socket4, &readset)) {
+            return socket4;
+        }
+#ifdef IPV6
+        if (socket6 >= 0 && FD_ISSET(socket6, &readset)) {
+            return socket6;
+        }
+#endif
+    }
+
+    return -1;
+}
+
+int receive_packet(int64_t wait_time,
+#if HAVE_SO_TIMESTAMPNS
+    int64_t *reply_timestamp,
+#else
+    int64_t *reply_timestamp __attribute__((unused)),
+#endif
+    struct sockaddr *reply_src_addr,
+    size_t reply_src_addr_len,
+    char *reply_buf,
+    size_t reply_buf_len)
+{
+    struct timeval to;
+    int s = 0;
+    int recv_len;
+    static unsigned char msg_control[40];
+    struct iovec msg_iov = {
+        reply_buf,
+        reply_buf_len
+    };
+    struct msghdr recv_msghdr = {0};
+    recv_msghdr.msg_name = reply_src_addr;
+    recv_msghdr.msg_namelen = reply_src_addr_len;
+    recv_msghdr.msg_iov = &msg_iov;
+    recv_msghdr.msg_iovlen = 1;
+    recv_msghdr.msg_control = &msg_control;
+    recv_msghdr.msg_controllen = sizeof(msg_control);
+#if HAVE_SO_TIMESTAMPNS
+    struct cmsghdr *cmsg;
+#endif
+
+    /* Wait for a socket to become ready */
+    if (wait_time) {
+        to.tv_sec = wait_time / UINT64_C(1000000000);
+        to.tv_usec = (wait_time % UINT64_C(1000000000)) / 1000 + 1;
+    }
+    else {
+        to.tv_sec = 0;
+        to.tv_usec = 0;
+    }
+    s = socket_can_read(&to);
+    if (s == -1) {
+        return 0; /* timeout */
+    }
+
+    recv_len = recvmsg(s, &recv_msghdr, MSG_TRUNC);
+    if (recv_len <= 0) {
+        return 0;
+    }
+
+#if HAVE_SO_TIMESTAMPNS
+    /* ancilliary data */
+    {
+        struct timespec reply_timestamp_ts;
+        for (cmsg = CMSG_FIRSTHDR(&recv_msghdr);
+             cmsg != NULL;
+             cmsg = CMSG_NXTHDR(&recv_msghdr, cmsg)) {
+            if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_TIMESTAMPNS) {
+                memcpy(&reply_timestamp_ts, CMSG_DATA(cmsg), sizeof(reply_timestamp_ts));
+                *reply_timestamp = timespec_ns(&reply_timestamp_ts);
+            }
+        }
+    }
+#endif
+
+#if defined(DEBUG) || defined(_DEBUG)
+    if (randomly_lose_flag) {
+        if ((random() & 0x07) <= lose_factor)
+            return 0;
+    }
+#endif
+
+    return recv_len;
+}
+
+/* stats_add: update host statistics for a single packet that was received (or timed out)
+ * h: host entry to update
+ * index: if in count mode: index number for this ping packet (-1 otherwise)
+ * success: 1 if response received, 0 otherwise
+ * latency: response time, in ns
+ */
+void stats_add(HOST_ENTRY *h, int index, int success, int64_t latency)
+{
+    /* sent count - we update only on receive/timeout, so that we don't get
+     * weird loss percentage, just because a packet was note recived yet.
+     */
+    h->num_sent++;
+    h->num_sent_i++;
+
+    if (!success) {
+        if (!loop_flag && index >= 0) {
+            h->resp_times[index] = RESP_TIMEOUT;
+        }
+        num_timeout++;
+        return;
+    }
+
+    /* received count */
+    h->num_recv++;
+    h->num_recv_i++;
+
+    /* maximum */
+    if (!h->max_reply || latency > h->max_reply) {
+        h->max_reply = latency;
+    }
+    if (!h->max_reply_i || latency > h->max_reply_i) {
+        h->max_reply_i = latency;
+    }
+
+    /* minimum */
+    if (!h->min_reply || latency < h->min_reply) {
+        h->min_reply = latency;
+    }
+    if (!h->min_reply_i || latency < h->min_reply_i) {
+        h->min_reply_i = latency;
+    }
+
+    /* total time (for average) */
+    h->total_time += latency;
+    h->total_time_i += latency;
+
+    /* response time per-packet (count mode) */
+    if (!loop_flag && index >= 0) {
+        h->resp_times[index] = latency;
+    }
+}
+
+/* stats_reset_interval: reset interval statistics
+ * h: host entry to update
+ */
+void stats_reset_interval(HOST_ENTRY *h)
+{
+    h->num_sent_i = 0;
+    h->num_recv_i = 0;
+    h->max_reply_i = 0;
+    h->min_reply_i = 0;
+    h->total_time_i = 0;
+}
+
+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,
+    int *ip_header_tos,
+    int *ip_header_ttl,
+    uint32_t *ip_header_otime_ms,
+    uint32_t *ip_header_rtime_ms,
+    uint32_t *ip_header_ttime_ms)
+{
+    struct icmp *icp;
+    int hlen = 0;
+
+    if (!using_sock_dgram4) {
+        struct ip *ip = (struct ip *)reply_buf;
+        *ip_header_tos = ip->ip_tos;
+        *ip_header_ttl = ip->ip_ttl;
+
+#if defined(__alpha__) && __STDC__ && !defined(__GLIBC__) && !defined(__NetBSD__) && !defined(__OpenBSD__)
+        /* 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(response_addr, response_addr_len, 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 -1;
+    }
+
+    icp = (struct icmp *)(reply_buf + hlen);
+
+    if ((icmp_request_typ == 0 && icp->icmp_type != ICMP_ECHOREPLY) ||
+        (icmp_request_typ == 13 && icp->icmp_type != ICMP_TSTAMPREPLY)) {
+        /* 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 -1;
+        }
+
+        sent_icmp = (struct icmp *)(reply_buf + hlen + ICMP_MINLEN + sizeof(struct ip));
+
+        if ((icmp_request_typ == 0 && sent_icmp->icmp_type != ICMP_ECHO) ||
+            (icmp_request_typ == 13 && sent_icmp->icmp_type != ICMP_TSTAMP) ||
+            sent_icmp->icmp_id != ident4) {
+            /* not caused by us */
+            return -1;
+        }
+
+        seqmap_value = seqmap_fetch(ntohs(sent_icmp->icmp_seq), current_time_ns);
+        if (seqmap_value == NULL) {
+            return -1;
+        }
+
+        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;
+        }
+
+        return -1;
+    }
+
+    *id = icp->icmp_id;
+    *seq = ntohs(icp->icmp_seq);
+    if(icp->icmp_type == ICMP_TSTAMPREPLY) {
+
+        /* Check that reply_buf_len is sufficiently big to contain the timestamps */
+        if (reply_buf_len < hlen + ICMP_MINLEN + ICMP_TIMESTAMP_DATA_SIZE) {
+            if (verbose_flag) {
+                char buf[INET6_ADDRSTRLEN];
+                getnameinfo(response_addr, response_addr_len, buf, INET6_ADDRSTRLEN, NULL, 0, NI_NUMERICHOST);
+                printf("received packet too short for ICMP Timestamp Reply (%d bytes from %s)\n", (int)reply_buf_len, buf);
+            }
+            return -1;
+        }
+
+        *ip_header_otime_ms = ntohl(icp->icmp_dun.id_ts.its_otime);
+        *ip_header_rtime_ms = ntohl(icp->icmp_dun.id_ts.its_rtime);
+        *ip_header_ttime_ms = ntohl(icp->icmp_dun.id_ts.its_ttime);
+    }
+
+    return hlen;
+}
+
+#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(response_addr, response_addr_len, 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 */
+    }
+
+    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 || sent_icmp->icmp6_id != ident6) {
+            /* not caused by us */
+            return 0;
+        }
+
+        seqmap_value = seqmap_fetch(ntohs(sent_icmp->icmp6_seq), current_time_ns);
+        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 = icp->icmp6_id;
+    *seq = ntohs(icp->icmp6_seq);
+
+    return 1;
+}
+#endif
+
+int wait_for_reply(int64_t wait_time)
+{
+    int result;
+    static char buffer[RECV_BUFSIZE];
+    struct sockaddr_storage response_addr;
+    int n, avg;
+    HOST_ENTRY *h;
+    int64_t this_reply;
+    int this_count;
+    int64_t recv_time = 0;
+    SEQMAP_VALUE *seqmap_value;
+    unsigned short id;
+    unsigned short seq;
+    int ip_header_tos = -1;
+    int ip_header_ttl = -1;
+    // ICMP Timestamp
+    uint32_t ip_header_otime_ms = 0x80000000U;
+    uint32_t ip_header_rtime_ms = 0x80000000U;
+    uint32_t ip_header_ttime_ms = 0x80000000U;
+
+    /* Receive packet */
+    result = receive_packet(wait_time, /* max. wait time, in ns */
+        &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;
+    }
+
+    update_current_time();
+    if (recv_time == 0)
+        recv_time = current_time_ns;
+
+    /* Process ICMP packet and retrieve id/seq */
+    if (response_addr.ss_family == AF_INET) {
+        int ip_hlen = decode_icmp_ipv4(
+            (struct sockaddr *)&response_addr,
+            sizeof(response_addr),
+            buffer,
+            sizeof(buffer),
+            &id,
+            &seq,
+            &ip_header_tos,
+            &ip_header_ttl,
+            &ip_header_otime_ms,
+            &ip_header_rtime_ms,
+            &ip_header_ttime_ms);
+        if (ip_hlen < 0) {
+            return 1;
+        }
+        if (id != ident4) {
+            return 1; /* packet received, but not the one we are looking for! */
+        }
+        if (!using_sock_dgram4) {
+            /* do not include IP header in returned size, to be consistent with ping(8) and also
+             * with fping with IPv6 hosts */
+            result -= ip_hlen;
+        }
+    }
+#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;
+        }
+        if (id != ident6) {
+            return 1; /* packet received, but not the one we are looking for! */
+        }
+    }
+#endif
+    else {
+        return 1;
+    }
+
+    seqmap_value = seqmap_fetch(seq, current_time_ns);
+    if (seqmap_value == NULL) {
+        return 1;
+    }
+
+    /* find corresponding host_entry */
+    n = seqmap_value->host_nr;
+    h = table[n];
+    this_count = seqmap_value->ping_count;
+    this_reply = recv_time - seqmap_value->ping_ts;
+
+    /* update stats that include invalid replies */
+    h->num_recv_total++;
+    num_pingreceived++;
+
+    dbg_printf("received [%d] from %s\n", this_count, h->host);
+
+    /* optionally require reply source equal to target address */
+    if (check_source_flag && addr_cmp((struct sockaddr *)&response_addr, (struct sockaddr *)&h->saddr)) {
+        dbg_printf("discarding reply from wrong source address\n");
+        return 1;
+    }
+
+    /* discard duplicates */
+    if (!loop_flag && h->resp_times[this_count] >= 0) {
+        if (!per_recv_flag) {
+            fprintf(stderr, "%s : duplicate for [%d], %d bytes, %s ms",
+                h->host, this_count, result, sprint_tm(this_reply));
+
+            if (addr_cmp((struct sockaddr *)&response_addr, (struct sockaddr *)&h->saddr)) {
+                char buf[INET6_ADDRSTRLEN];
+                getnameinfo((struct sockaddr *)&response_addr, sizeof(response_addr), buf, INET6_ADDRSTRLEN, NULL, 0, NI_NUMERICHOST);
+                fprintf(stderr, " [<- %s]", buf);
+            }
+            fprintf(stderr, "\n");
+        }
+        return 1;
+    }
+
+    /* discard reply if delay is larger than timeout
+     * (see also: github #32) */
+    if (this_reply > h->timeout) {
+        return 1;
+    }
+
+    /* update stats */
+    stats_add(h, this_count, 1, this_reply);
+    // TODO: move to stats_add?
+    if (!max_reply || this_reply > max_reply)
+        max_reply = this_reply;
+    if (!min_reply || this_reply < min_reply)
+        min_reply = this_reply;
+    sum_replies += this_reply;
+    total_replies++;
+
+    /* initialize timeout to initial timeout (without backoff) */
+    h->timeout = timeout;
+
+    /* remove timeout event */
+    struct event *timeout_event = host_get_timeout_event(h, this_count);
+    if (timeout_event) {
+        ev_remove(&event_queue_timeout, timeout_event);
+    }
+
+    /* print "is alive" */
+    if (h->num_recv == 1) {
+        num_alive++;
+        if (fast_reachable && num_alive >= min_reachable)
+                finish_requested = 1;
+
+        if (verbose_flag || alive_flag) {
+            printf("%s", h->host);
+
+            if (verbose_flag)
+                printf(" is alive");
+        }
+    }
+
+    /* print received ping (unless --quiet) */
+    if (per_recv_flag) {
+        if (timestamp_flag) {
+            print_timestamp_format(recv_time, timestamp_format_flag);
+        }
+        avg = h->total_time / h->num_recv;
+        printf("%-*s : [%d], %d bytes, %s ms",
+            max_hostname_len, h->host, this_count, result, sprint_tm(this_reply));
+        printf(" (%s avg, ", sprint_tm(avg));
+
+        if (h->num_recv <= h->num_sent) {
+            printf("%d%% loss)",
+                ((h->num_sent - h->num_recv) * 100) / h->num_sent);
+        }
+        else {
+            printf("%d%% return)",
+                (h->num_recv_total * 100) / h->num_sent);
+        }
+    }
+
+    if (verbose_flag || alive_flag || per_recv_flag) {
+
+        if (addr_cmp((struct sockaddr *)&response_addr, (struct sockaddr *)&h->saddr)) {
+            char buf[INET6_ADDRSTRLEN];
+            getnameinfo((struct sockaddr *)&response_addr, sizeof(response_addr), buf, INET6_ADDRSTRLEN, NULL, 0, NI_NUMERICHOST);
+            fprintf(stderr, " [<- %s]", buf);
+        }
+
+        if (icmp_request_typ == 13) {
+            printf("%s timestamps: Originate=%u Receive=%u Transmit=%u Localreceive=%u",
+                   alive_flag ? "" : ",",
+                   ip_header_otime_ms, ip_header_rtime_ms, ip_header_ttime_ms,
+                   ms_since_midnight_utc(recv_time));
+        }
+
+        if(print_tos_flag) {
+            if(ip_header_tos != -1) {
+                printf(" (TOS %d)", ip_header_tos);
+            }
+            else {
+                printf(" (TOS unknown)");
+            }
+        }
+
+        if (print_ttl_flag) {
+          if(ip_header_ttl != -1) {
+              printf(" (TTL %d)", ip_header_ttl);
+          }
+          else {
+              printf(" (TTL unknown)");
+          }
+        }
+
+        if (elapsed_flag && !per_recv_flag)
+                printf(" (%s ms)", sprint_tm(this_reply));
+
+        printf("\n");
+    }
+
+    return 1;
+}
+
+/************************************************************
+
+  Function: add_name
+
+*************************************************************
+
+  Inputs:  char* name
+
+  Description:
+
+  process input name for addition to target list
+  name can turn into multiple targets via multiple interfaces (-m)
+  or via NIS groups
+
+************************************************************/
+
+void add_name(char *name)
+{
+    struct addrinfo *res0, *res, hints;
+    int ret_ga;
+    char *printname;
+    char namebuf[256];
+    char addrbuf[256];
+
+    /* getaddrinfo */
+    memset(&hints, 0, sizeof(struct addrinfo));
+    hints.ai_flags = AI_UNUSABLE;
+    hints.ai_socktype = SOCK_RAW;
+    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_socktype = SOCK_STREAM;
+        hints.ai_protocol = 0;
+    }
+    ret_ga = getaddrinfo(name, NULL, &hints, &res0);
+    if (ret_ga) {
+        if (!quiet_flag)
+            print_warning("%s: %s\n", name, gai_strerror(ret_ga));
+        num_noaddress++;
+        return;
+    }
+
+    /* NOTE: we could/should loop with res on all addresses like this:
+     * for (res = res0; res; res = res->ai_next) {
+     * We don't do it yet, however, because is is an incompatible change
+     * (need to implement a separate option for this)
+     */
+    for (res = res0; res; res = res->ai_next) {
+        /* name_flag: addr -> name lookup requested) */
+        if (name_flag || rdns_flag) {
+            int do_rdns = rdns_flag ? 1 : 0;
+            if (name_flag) {
+                /* Was it a numerical address? Only then do a rdns-query */
+                struct addrinfo *nres;
+                hints.ai_flags = AI_NUMERICHOST;
+                if (getaddrinfo(name, NULL, &hints, &nres) == 0) {
+                    do_rdns = 1;
+                    freeaddrinfo(nres);
+                }
+            }
+
+            if (do_rdns && getnameinfo(res->ai_addr, res->ai_addrlen, namebuf, sizeof(namebuf) / sizeof(char), NULL, 0, 0) == 0) {
+                printname = namebuf;
+            }
+            else {
+                printname = name;
+            }
+        }
+        else {
+            printname = name;
+        }
+
+        /* 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: can't forward-lookup address (%s)\n", name, gai_strerror(ret));
+                }
+                continue;
+            }
+
+            if (name_flag || rdns_flag) {
+                char nameaddrbuf[512 + 3];
+                snprintf(nameaddrbuf, sizeof(nameaddrbuf) / sizeof(char), "%s (%s)", printname, addrbuf);
+                add_addr(name, nameaddrbuf, res->ai_addr, res->ai_addrlen);
+            }
+            else {
+                add_addr(name, addrbuf, res->ai_addr, res->ai_addrlen);
+            }
+        }
+        else {
+            add_addr(name, printname, res->ai_addr, res->ai_addrlen);
+        }
+
+        if (!multif_flag) {
+            break;
+        }
+    }
+
+    freeaddrinfo(res0);
+}
+
+/************************************************************
+
+  Function: add_addr
+
+*************************************************************
+
+  Description:
+
+  add single address to list of hosts to be pinged
+
+************************************************************/
+
+void add_addr(char *name, char *host, struct sockaddr *ipaddr, socklen_t ipaddr_len)
+{
+    HOST_ENTRY *p;
+    int n;
+    int64_t *i;
+
+    p = (HOST_ENTRY *)calloc(1, sizeof(HOST_ENTRY));
+    if (!p)
+        crash_and_burn("can't allocate HOST_ENTRY");
+
+    p->name = strdup(name);
+    p->host = strdup(host);
+    memcpy(&p->saddr, ipaddr, ipaddr_len);
+    p->saddr_len = ipaddr_len;
+    p->timeout = timeout;
+    p->min_reply = 0;
+
+    if (netdata_flag) {
+        char *s = p->name;
+        while (*s) {
+            if (!isalnum(*s))
+                *s = '_';
+            s++;
+        }
+    }
+
+    if (strlen(p->host) > max_hostname_len)
+        max_hostname_len = strlen(p->host);
+
+    /* array for response time results */
+    if (!loop_flag) {
+        i = (int64_t *)malloc(trials * sizeof(int64_t));
+        if (!i)
+            crash_and_burn("can't allocate resp_times array");
+
+        for (n = 1; n < trials; n++)
+            i[n] = RESP_UNUSED;
+
+        p->resp_times = i;
+    }
+
+    /* allocate event storage */
+    p->event_storage_ping = (struct event *)calloc(event_storage_count, sizeof(struct event));
+    if (!p->event_storage_ping) {
+        errno_crash_and_burn("can't allocate event_storage_ping");
+    }
+    p->event_storage_timeout = (struct event *)calloc(event_storage_count, sizeof(struct event));
+    if (!p->event_storage_timeout) {
+        errno_crash_and_burn("can't allocate event_storage_timeout");
+    }
+
+    /* schedule first ping */
+    host_add_ping_event(p, 0, current_time_ns);
+
+    num_hosts++;
+}
+
+/************************************************************
+
+  Function: crash_and_burn
+
+*************************************************************
+
+  Inputs:  char* message
+
+  Description:
+
+************************************************************/
+
+void crash_and_burn(char *message)
+{
+    fprintf(stderr, "%s: %s\n", prog, message);
+    exit(4);
+}
+
+/************************************************************
+
+  Function: errno_crash_and_burn
+
+*************************************************************
+
+  Inputs:  char* message
+
+  Description:
+
+************************************************************/
+
+void errno_crash_and_burn(char *message)
+{
+    fprintf(stderr, "%s: %s : %s\n", prog, message, strerror(errno));
+    exit(4);
+}
+
+/************************************************************
+
+  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: sprint_tm
+
+*************************************************************
+
+  render nanosecond int64_t value into milliseconds string with three digits of
+  precision.
+
+************************************************************/
+
+const char *sprint_tm(int64_t ns)
+{
+    static char buf[10];
+    double t = (double)ns / 1e6;
+
+    if (t < 0.0) {
+        /* negative (unexpected) */
+        sprintf(buf, "%.2g", t);
+    }
+    else if (t < 1.0) {
+        /* <= 0.99 ms */
+        sprintf(buf, "%.3f", t);
+    }
+    else if (t < 10.0) {
+        /* 1.00 - 9.99 ms */
+        sprintf(buf, "%.2f", t);
+    }
+    else if (t < 100.0) {
+        /* 10.0 - 99.9 ms */
+        sprintf(buf, "%.1f", t);
+    }
+    else if (t < 1000000.0) {
+        /* 100 - 1'000'000 ms */
+        sprintf(buf, "%.0f", t);
+    }
+    else {
+        sprintf(buf, "%.3e", t);
+    }
+
+    return (buf);
+}
+
+/************************************************************
+
+  Function: addr_cmp
+
+*************************************************************/
+int addr_cmp(struct sockaddr *a, struct sockaddr *b)
+{
+    if (a->sa_family != b->sa_family) {
+        return a->sa_family - b->sa_family;
+    }
+    else {
+        if (a->sa_family == AF_INET) {
+            return ((struct sockaddr_in *)a)->sin_addr.s_addr - ((struct sockaddr_in *)b)->sin_addr.s_addr;
+        }
+        else if (a->sa_family == AF_INET6) {
+            return memcmp(&((struct sockaddr_in6 *)a)->sin6_addr,
+                &((struct sockaddr_in6 *)b)->sin6_addr,
+                sizeof(((struct sockaddr_in6 *)a)->sin6_addr));
+        }
+    }
+
+    return 0;
+}
+
+void host_add_ping_event(HOST_ENTRY *h, int index, int64_t ev_time)
+{
+    struct event *event = &h->event_storage_ping[index % event_storage_count];
+    event->host = h;
+    event->ping_index = index;
+    event->ev_time = ev_time;
+    ev_enqueue(&event_queue_ping, event);
+
+    dbg_printf("%s [%d]: add ping event in %.0f ms\n",
+        event->host->host, index, (ev_time - current_time_ns) / 1e6);
+}
+
+void host_add_timeout_event(HOST_ENTRY *h, int index, int64_t ev_time)
+{
+    struct event *event = &h->event_storage_timeout[index % event_storage_count];
+    event->host = h;
+    event->ping_index = index;
+    event->ev_time = ev_time;
+    ev_enqueue(&event_queue_timeout, event);
+
+    dbg_printf("%s [%d]: add timeout event in %.0f ms\n",
+        event->host->host, index, (ev_time - current_time_ns) / 1e6);
+}
+
+struct event *host_get_timeout_event(HOST_ENTRY *h, int index)
+{
+    return &h->event_storage_timeout[index % event_storage_count];
+}
+
+/************************************************************
+
+  Function: ev_enqueue
+
+  Enqueue an event
+
+  The queue is sorted by event->ev_time, so that queue->first always points to
+  the earliest event.
+
+  We start scanning the queue from the tail, because we assume
+  that new events mostly get inserted with a event time higher
+  than the others.
+
+*************************************************************/
+void ev_enqueue(struct event_queue *queue, struct event *event)
+{
+    struct event *i;
+    struct event *i_prev;
+
+    /* Empty list */
+    if (queue->last == NULL) {
+        event->ev_next = NULL;
+        event->ev_prev = NULL;
+        queue->first = event;
+        queue->last = event;
+        return;
+    }
+
+    /* Insert on tail? */
+    if (event->ev_time - queue->last->ev_time >= 0) {
+        event->ev_next = NULL;
+        event->ev_prev = queue->last;
+        queue->last->ev_next = event;
+        queue->last = event;
+        return;
+    }
+
+    /* Find insertion point */
+    i = queue->last;
+    while (1) {
+        i_prev = i->ev_prev;
+        if (i_prev == NULL || event->ev_time - i_prev->ev_time >= 0) {
+            event->ev_prev = i_prev;
+            event->ev_next = i;
+            i->ev_prev = event;
+            if (i_prev != NULL) {
+                i_prev->ev_next = event;
+            }
+            else {
+                queue->first = event;
+            }
+            return;
+        }
+        i = i_prev;
+    }
+}
+
+/************************************************************
+
+  Function: ev_dequeue
+
+*************************************************************/
+struct event *ev_dequeue(struct event_queue *queue)
+{
+    struct event *dequeued;
+
+    if (queue->first == NULL) {
+        return NULL;
+    }
+    dequeued = queue->first;
+    ev_remove(queue, dequeued);
+
+    return dequeued;
+}
+
+/************************************************************
+
+  Function: ev_remove
+
+*************************************************************/
+void ev_remove(struct event_queue *queue, struct event *event)
+{
+    if (queue->first == event) {
+        queue->first = event->ev_next;
+    }
+    if (queue->last == event) {
+        queue->last = event->ev_prev;
+    }
+    if (event->ev_prev) {
+        event->ev_prev->ev_next = event->ev_next;
+    }
+    if (event->ev_next) {
+        event->ev_next->ev_prev = event->ev_prev;
+    }
+    event->ev_prev = NULL;
+    event->ev_next = NULL;
+}
+
+/************************************************************
+
+  Function: print_human_readable_time from current_time_ns
+
+*************************************************************/
+void print_timestamp_format(int64_t current_time_ns, int timestamp_format)
+{
+    char time_buffer[100];
+    time_t current_time_s;
+    struct tm *local_time;
+
+    current_time_s = current_time_ns / 1000000000;
+    local_time = localtime(&current_time_s);
+    switch(timestamp_format) {
+        case 1:
+            // timestamp-format ctime
+            strftime(time_buffer, sizeof(time_buffer), "%c", local_time);
+            printf("[%s] ", time_buffer);
+            break;
+        case 2:
+            // timestamp-format iso
+            strftime(time_buffer, sizeof(time_buffer), "%Y-%m-%dT%T%z", local_time);
+            printf("[%s] ", time_buffer);
+            break;
+        case 3:
+            // timestamp-format rfc3339
+            strftime(time_buffer, sizeof(time_buffer), "%Y-%m-%d %H:%M:%S", local_time);
+            printf("[%s] ", time_buffer);
+            break;
+        default:
+            printf("[%.5f] ", (double)current_time_ns / 1e9);
+    }
+}
+
+/************************************************************
+
+  Function: ms_since_midnight_utc
+
+*************************************************************
+
+  Input: int64_t: current UTC time in ns
+
+  Output: uint32_t: current time in ms since midnight UTC
+
+  Description:
+
+  Return ICMP Timestamp value corresponding to the given time value.
+  The given time value must be in UTC.
+
+*************************************************************/
+static uint32_t ms_since_midnight_utc(int64_t time_val)
+{
+    return (uint32_t)((time_val / 1000000) % (24 * 60 * 60 * 1000));
+}
+
+/************************************************************
+
+  Function: usage
+
+*************************************************************
+
+  Inputs:  int: 0 if output on request, 1 if output because of wrong argument
+
+  Description:
+
+************************************************************/
+
+void usage(int is_error)
+{
+    FILE *out = is_error ? stderr : stdout;
+    fprintf(out, "Usage: %s [options] [targets...]\n", prog);
+    fprintf(out, "\n");
+    fprintf(out, "Probing options:\n");
+    fprintf(out, "   -4, --ipv4         only ping IPv4 addresses\n");
+    fprintf(out, "   -6, --ipv6         only ping IPv6 addresses\n");
+    fprintf(out, "   -b, --size=BYTES   amount of ping data to send, in bytes (default: %d)\n", DEFAULT_PING_DATA_SIZE);
+    fprintf(out, "   -B, --backoff=N    set exponential backoff factor to N (default: 1.5)\n");
+    fprintf(out, "   -c, --count=N      count mode: send N pings to each target and report stats\n");
+    fprintf(out, "   -f, --file=FILE    read list of targets from a file ( - means stdin)\n");
+    fprintf(out, "   -g, --generate     generate target list (only if no -f specified),\n");
+    fprintf(out, "                      limited to at most %d targets\n", MAX_GENERATE);
+    fprintf(out, "                      (give start and end IP in the target list, or a CIDR address)\n");
+    fprintf(out, "                      (ex. %s -g 192.168.1.0 192.168.1.255 or %s -g 192.168.1.0/24)\n", prog, prog);
+    fprintf(out, "   -H, --ttl=N        set the IP TTL value (Time To Live hops)\n");
+    fprintf(out, "   -i, --interval=MSEC  interval between sending ping packets (default: %.0f ms)\n", interval / 1e6);
+#ifdef SO_BINDTODEVICE
+    fprintf(out, "   -I, --iface=IFACE  bind to a particular interface\n");
+#endif
+#ifdef SO_MARK
+    fprintf(out, "   -k, --fwmark=FWMARK set the routing mark\n");
+#endif
+    fprintf(out, "   -l, --loop         loop mode: send pings forever\n");
+    fprintf(out, "   -m, --all          use all IPs of provided hostnames (e.g. IPv4 and IPv6), use with -A\n");
+    fprintf(out, "   -M, --dontfrag     set the Don't Fragment flag\n");
+    fprintf(out, "   -O, --tos=N        set the type of service (tos) flag on the ICMP packets\n");
+    fprintf(out, "   -p, --period=MSEC  interval between ping packets to one target (in ms)\n");
+    fprintf(out, "                      (in loop and count modes, default: %.0f ms)\n", perhost_interval / 1e6);
+    fprintf(out, "   -r, --retry=N      number of retries (default: %d)\n", DEFAULT_RETRY);
+    fprintf(out, "   -R, --random       random packet data (to foil link data compression)\n");
+    fprintf(out, "   -S, --src=IP       set source address\n");
+    fprintf(out, "   -t, --timeout=MSEC individual target initial timeout (default: %.0f ms,\n", timeout / 1e6);
+    fprintf(out, "                      except with -l/-c/-C, where it's the -p period up to 2000 ms)\n");
+    fprintf(out, "       --check-source discard replies not from target address\n");
+    fprintf(out, "       --icmp-timestamp use ICMP Timestamp instead of ICMP Echo\n");
+    fprintf(out, "\n");
+    fprintf(out, "Output options:\n");
+    fprintf(out, "   -a, --alive        show targets that are alive\n");
+    fprintf(out, "   -A, --addr         show targets by address\n");
+    fprintf(out, "   -C, --vcount=N     same as -c, report results (not stats) in verbose format\n");
+    fprintf(out, "   -d, --rdns         show targets by name (force reverse-DNS lookup)\n");
+    fprintf(out, "   -D, --timestamp    print timestamp before each output line\n");
+    fprintf(out, "       --timestamp-format=FORMAT  show timestamp in the given format (-D required): ctime|iso|rfc3339\n");
+    fprintf(out, "   -e, --elapsed      show elapsed time on return packets\n");
+    fprintf(out, "   -n, --name         show targets by name (reverse-DNS lookup for target IPs)\n");
+    fprintf(out, "   -N, --netdata      output compatible for netdata (-l -Q are required)\n");
+    fprintf(out, "   -o, --outage       show the accumulated outage time (lost packets * packet interval)\n");
+    fprintf(out, "   -q, --quiet        quiet (don't show per-target/per-ping results)\n");
+    fprintf(out, "   -Q, --squiet=SECS[,cumulative]  same as -q, but add interval summary every SECS seconds,\n");
+    fprintf(out, "                                   with 'cumulative', print stats since beginning\n");
+    fprintf(out, "   -s, --stats        print final stats\n");
+    fprintf(out, "   -u, --unreach      show targets that are unreachable\n");
+    fprintf(out, "   -v, --version      show version\n");
+    fprintf(out, "   -x, --reachable=N  shows if >=N hosts are reachable or not\n");
+    fprintf(out, "   -X, --fast-reachable=N exits true immediately when N hosts are found\n");
+    fprintf(out, "       --print-tos    show received TOS value\n");
+    fprintf(out, "       --print-ttl    show IP TTL value\n");
+    exit(is_error);
+}
diff --git a/ci/tmp.VwGIuQgZdr/fping-5.4/src/fping.h b/ci/tmp.VwGIuQgZdr/fping-5.4/src/fping.h
new file mode 100644 (file)
index 0000000..f50710b
--- /dev/null
@@ -0,0 +1,39 @@
+#ifndef _FPING_H
+#define _FPING_H
+
+#define __APPLE_USE_RFC_3542 1
+
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <netinet/in.h>
+
+/* this requires variadic macros, part of C99 */
+#if (defined(DEBUG) || defined(_DEBUG))
+extern int64_t current_time_ns;
+extern int trace_flag;
+#define dbg_printf(fmt, ...) do { if (trace_flag) { fprintf(stderr, "[%10.5f] ", (double)(current_time_ns / 1000)/1000000); fprintf(stderr, fmt, __VA_ARGS__); } } while (0)
+            
+#else
+#define dbg_printf(fmt, ...)
+#endif
+
+
+/* fping.c */
+void crash_and_burn( char *message );
+void errno_crash_and_burn( char *message );
+int in_cksum( unsigned short *p, int n );
+extern int random_data_flag;
+
+/* socket.c */
+int  open_ping_socket_ipv4(int *socktype);
+void init_ping_buffer_ipv4(size_t ping_data_size);
+void socket_set_src_addr_ipv4(int s, struct in_addr *src_addr, int *ident);
+int  socket_sendto_ping_ipv4(int s, struct sockaddr *saddr, socklen_t saddr_len, uint16_t icmp_seq, uint16_t icmp_id, uint8_t icmp_proto);
+#ifdef IPV6
+int  open_ping_socket_ipv6(int *socktype);
+void init_ping_buffer_ipv6(size_t ping_data_size);
+void socket_set_src_addr_ipv6(int s, struct in6_addr *src_addr, int *ident);
+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/ci/tmp.VwGIuQgZdr/fping-5.4/src/options.h b/ci/tmp.VwGIuQgZdr/fping-5.4/src/options.h
new file mode 100644 (file)
index 0000000..229975c
--- /dev/null
@@ -0,0 +1,52 @@
+
+/* 
+ *  Interval is the minimum amount of time between sending a ping packet to 
+ *  any host.
+ * 
+ *  Perhost_interval is the minimum amount of time between sending a ping 
+ *  packet to a particular responding host (when count is > 1)
+ * 
+ *  Timeout  is the initial amount of time between sending a ping packet to
+ *  a particular non-responding host.
+ * 
+ *  Retry is the number of ping packets to send to a non-responding host
+ *  before giving up (in is-it-alive mode).
+ * 
+ *  Backoff factor is how much longer to wait on successive retries.
+ * 
+ * 
+ */
+
+/* constants */
+
+#ifndef DEFAULT_INTERVAL
+#define DEFAULT_INTERVAL 10        /* default time between packets (msec) */
+#endif
+
+#ifndef DEFAULT_PERHOST_INTERVAL      /* default time between packets */
+#define DEFAULT_PERHOST_INTERVAL 1000 /* to a particular destination  */
+#endif                                /* in counting/looping mode     */
+
+#ifndef DEFAULT_TIMEOUT
+#define DEFAULT_TIMEOUT 500       /* individual host timeouts */
+#define AUTOTUNE_TIMEOUT_MAX  2000
+#endif
+
+
+#ifndef DEFAULT_RETRY 
+#define DEFAULT_RETRY 3            /* number of times to retry a host */
+#endif
+
+#ifndef DEFAULT_SELECT_TIME
+#define DEFAULT_SELECT_TIME 10     /* default time to wait during select() */
+#endif
+
+#ifndef DEFAULT_BACKOFF_FACTOR
+#define DEFAULT_BACKOFF_FACTOR 1.5 /* exponential timeout factor */
+#endif
+#define MIN_BACKOFF_FACTOR     1.0 /* exponential timeout factor */
+#define MAX_BACKOFF_FACTOR     5.0 /* exponential timeout factor */
+
+#ifndef DNS_TIMEOUT
+#define DNS_TIMEOUT 1000         /* time in micro_sec for dns retry */
+#endif
diff --git a/ci/tmp.VwGIuQgZdr/fping-5.4/src/optparse.c b/ci/tmp.VwGIuQgZdr/fping-5.4/src/optparse.c
new file mode 100644 (file)
index 0000000..63a9f40
--- /dev/null
@@ -0,0 +1,266 @@
+#include "optparse.h"
+
+#define MSG_INVALID "invalid option"
+#define MSG_MISSING "option requires an argument"
+#define MSG_TOOMANY "option takes no arguments"
+
+static int
+opterror(struct optparse *options, const char *message, const char *data)
+{
+    unsigned p = 0;
+    while (*message)
+        options->errmsg[p++] = *message++;
+    const char *sep = " -- '";
+    while (*sep)
+        options->errmsg[p++] = *sep++;
+    while (p < sizeof(options->errmsg) - 2 && *data)
+        options->errmsg[p++] = *data++;
+    options->errmsg[p++] = '\'';
+    options->errmsg[p++] = '\0';
+    return '?';
+}
+
+void optparse_init(struct optparse *options, char **argv)
+{
+    options->argv = argv;
+    options->permute = 1;
+    options->optind = 1;
+    options->subopt = 0;
+    options->optarg = 0;
+    options->errmsg[0] = '\0';
+}
+
+static inline int
+is_dashdash(const char *arg)
+{
+    return arg != 0 && arg[0] == '-' && arg[1] == '-' && arg[2] == '\0';
+}
+
+static inline int
+is_shortopt(const char *arg)
+{
+    return arg != 0 && arg[0] == '-' && arg[1] != '-' && arg[1] != '\0';
+}
+
+static inline int
+is_longopt(const char *arg)
+{
+    return arg != 0 && arg[0] == '-' && arg[1] == '-' && arg[2] != '\0';
+}
+
+static void
+permute(struct optparse *options, int index)
+{
+    char *nonoption = options->argv[index];
+    for (int i = index; i < options->optind - 1; i++)
+        options->argv[i] = options->argv[i + 1];
+    options->argv[options->optind - 1] = nonoption;
+}
+
+static int
+argtype(const char *optstring, char c)
+{
+    if (c == ':')
+        return -1;
+    for (; *optstring && c != *optstring; optstring++);
+    if (!*optstring)
+        return -1;
+    int count = OPTPARSE_NONE;
+    if (optstring[1] == ':')
+        count += optstring[2] == ':' ? 2 : 1;
+    return count;
+}
+
+int optparse(struct optparse *options, const char *optstring)
+{
+    options->errmsg[0] = '\0';
+    options->optopt = 0;
+    options->optarg = 0;
+    char *option = options->argv[options->optind];
+    if (option == 0) {
+        return -1;
+    } else if (is_dashdash(option)) {
+        options->optind++; /* consume "--" */
+        return -1;
+    } else if (!is_shortopt(option)) {
+        if (options->permute) {
+            int index = options->optind;
+            options->optind++;
+            int r = optparse(options, optstring);
+            permute(options, index);
+            options->optind--;
+            return r;
+        } else {
+            return -1;
+        }
+    }
+    option += options->subopt + 1;
+    options->optopt = option[0];
+    int type = argtype(optstring, option[0]);
+    char *next = options->argv[options->optind + 1];
+    switch (type) {
+    case -1: {
+        options->optind++;
+        char str[2] = {option[0]};
+        return opterror(options, MSG_INVALID, str);
+    }
+    case OPTPARSE_NONE:
+        if (option[1]) {
+            options->subopt++;
+        } else {
+            options->subopt = 0;
+            options->optind++;
+        }
+        return option[0];
+    case OPTPARSE_REQUIRED:
+        options->subopt = 0;
+        options->optind++;
+        if (option[1]) {
+            options->optarg = option + 1;
+        } else if (next != 0) {
+            options->optarg = next;
+            options->optind++;
+        } else {
+            options->optarg = 0;
+            char str[2] = {option[0]};
+            return opterror(options, MSG_MISSING, str);
+        }
+        return option[0];
+    case OPTPARSE_OPTIONAL:
+        options->subopt = 0;
+        options->optind++;
+        if (option[1])
+            options->optarg = option + 1;
+        else
+            options->optarg = 0;
+        return option[0];
+    }
+    return 0;
+}
+
+char *optparse_arg(struct optparse *options)
+{
+    options->subopt = 0;
+    char *option = options->argv[options->optind];
+    if (option != 0)
+        options->optind++;
+    return option;
+}
+
+static inline int
+longopts_end(const struct optparse_long *longopts, int i)
+{
+    return !longopts[i].longname && !longopts[i].shortname;
+}
+
+static void
+optstring_from_long(const struct optparse_long *longopts, char *optstring)
+{
+    char *p = optstring;
+    for (int i = 0; !longopts_end(longopts, i); i++) {
+        if (longopts[i].shortname) {
+            *p++ = longopts[i].shortname;
+            for (int a = 0; a < (int)longopts[i].argtype; a++)
+                *p++ = ':';
+        }
+    }
+    *p = '\0';
+}
+
+/* Unlike strcmp(), handles options containing "=". */
+static int
+longopts_match(const char *longname, const char *option)
+{
+    if (longname == 0)
+        return 0;
+    const char *a = option, *n = longname;
+    for (; *a && *n && *a != '='; a++, n++)
+        if (*a != *n)
+            return 0;
+    return *n == '\0' && (*a == '\0' || *a == '=');
+}
+
+/* Return the part after "=", or NULL. */
+static char *
+longopts_arg(char *option)
+{
+    for (; *option && *option != '='; option++);
+    if (*option == '=')
+        return option + 1;
+    else
+        return 0;
+}
+
+static int
+long_fallback(struct optparse *options,
+              const struct optparse_long *longopts,
+              int *longindex)
+{
+    char optstring[96 * 3 + 1]; /* 96 ASCII printable characters */
+    optstring_from_long(longopts, optstring);
+    int result = optparse(options, optstring);
+    if (longindex != 0) {
+        *longindex = -1;
+        if (result != -1)
+            for (int i = 0; !longopts_end(longopts, i); i++)
+                if (longopts[i].shortname == options->optopt)
+                    *longindex = i;
+    }
+    return result;
+}
+
+int
+optparse_long(struct optparse *options,
+              const struct optparse_long *longopts,
+              int *longindex)
+{
+    char *option = options->argv[options->optind];
+    if (option == 0) {
+        return -1;
+    } else if (is_dashdash(option)) {
+        options->optind++; /* consume "--" */
+        return -1;
+    } else if (is_shortopt(option)) {
+        return long_fallback(options, longopts, longindex);
+    } else if (!is_longopt(option)) {
+        if (options->permute) {
+            int index = options->optind;
+            options->optind++;
+            int r = optparse_long(options, longopts, longindex);
+            permute(options, index);
+            options->optind--;
+            return r;
+        } else {
+            return -1;
+        }
+    }
+
+    /* Parse as long option. */
+    options->errmsg[0] = '\0';
+    options->optopt = 0;
+    options->optlongname = 0;
+    options->optarg = 0;
+    option += 2; /* skip "--" */
+    options->optind++;
+    for (int i = 0; !longopts_end(longopts, i); i++) {
+        const char *name = longopts[i].longname;
+        if (longopts_match(name, option)) {
+            options->optlongname = option;
+            if (longindex)
+                *longindex = i;
+            options->optopt = longopts[i].shortname;
+            char *arg = longopts_arg(option);
+            if (longopts[i].argtype == OPTPARSE_NONE && arg != 0) {
+                return opterror(options, MSG_TOOMANY, name);
+            } if (arg != 0) {
+                options->optarg = arg;
+            } else if (longopts[i].argtype == OPTPARSE_REQUIRED) {
+                options->optarg = options->argv[options->optind++];
+                if (options->optarg == 0)
+                    return opterror(options, MSG_MISSING, name);
+            }
+            return options->optopt;
+        }
+    }
+    return opterror(options, MSG_INVALID, option);
+}
diff --git a/ci/tmp.VwGIuQgZdr/fping-5.4/src/optparse.h b/ci/tmp.VwGIuQgZdr/fping-5.4/src/optparse.h
new file mode 100644 (file)
index 0000000..7a555ed
--- /dev/null
@@ -0,0 +1,103 @@
+#ifndef OPTPARSE_H
+#define OPTPARSE_H
+
+/**
+ * Optparse -- portable, reentrant, embeddable, getopt-like option parser
+ *
+ * The POSIX getopt() option parser has three fatal flaws. These flaws
+ * are solved by Optparse.
+ *
+ * 1) Parser state is stored entirely in global variables, some of
+ * which are static and inaccessible. This means only one thread can
+ * use getopt(). It also means it's not possible to recursively parse
+ * nested sub-arguments while in the middle of argument parsing.
+ * Optparse fixes this by storing all state on a local struct.
+ *
+ * 2) The POSIX standard provides no way to properly reset the parser.
+ * This means for portable code that getopt() is only good for one
+ * run, over one argv with one optstring. It also means subcommand
+ * options cannot be processed with getopt(). Most implementations
+ * provide a method to reset the parser, but it's not portable.
+ * Optparse provides an optparse_arg() function for stepping over
+ * subcommands and continuing parsing of options with another
+ * optstring. The Optparse struct itself can be passed around to
+ * subcommand handlers for additional subcommand option parsing. A
+ * full reset can be achieved by with an additional optparse_init().
+ *
+ * 3) Error messages are printed to stderr. This can be disabled with
+ * opterr, but the messages themselves are still inaccessible.
+ * Optparse solves this by writing an error message in its errmsg
+ * field. The downside to Optparse is that this error message will
+ * always be in English rather than the current locale.
+ *
+ * Optparse should be familiar with anyone accustomed to getopt(), and
+ * it could be a nearly drop-in replacement. The optstring is the same
+ * and the fields have the same names as the getopt() global variables
+ * (optarg, optind, optopt).
+ *
+ * Optparse also supports GNU-style long options with optparse_long().
+ * The interface is slightly different and simpler than getopt_long().
+ *
+ * By default, argv is permuted as it is parsed, moving non-option
+ * arguments to the end. This can be disabled by setting the `permute`
+ * field to 0 after initialization.
+ */
+
+struct optparse {
+    char **argv;
+    int permute;
+    int optind;
+    int optopt;
+    char *optlongname;
+    char *optarg;
+    char errmsg[64];
+    int subopt;
+};
+
+enum optparse_argtype { OPTPARSE_NONE, OPTPARSE_REQUIRED, OPTPARSE_OPTIONAL };
+
+struct optparse_long {
+    const char *longname;
+    int shortname;
+    enum optparse_argtype argtype;
+};
+
+/**
+ * Initializes the parser state.
+ */
+void optparse_init(struct optparse *options, char **argv);
+
+/**
+ * Read the next option in the argv array.
+ * @param optstring a getopt()-formatted option string.
+ * @return the next option character, -1 for done, or '?' for error
+ *
+ * Just like getopt(), a character followed by no colons means no
+ * argument. One colon means the option has a required argument. Two
+ * colons means the option takes an optional argument.
+ */
+int optparse(struct optparse *options, const char *optstring);
+
+/**
+ * Handles GNU-style long options in addition to getopt() options.
+ * This works a lot like GNU's getopt_long(). The last option in
+ * longopts must be all zeros, marking the end of the array. The
+ * longindex argument may be NULL.
+ */
+int
+optparse_long(struct optparse *options,
+              const struct optparse_long *longopts,
+              int *longindex);
+
+/**
+ * Used for stepping over non-option arguments.
+ * @return the next non-option argument, or NULL for no more arguments
+ *
+ * Argument parsing can continue with optparse() after using this
+ * function. That would be used to parse the options for the
+ * subcommand returned by optparse_arg(). This function allows you to
+ * ignore the value of optind.
+ */
+char *optparse_arg(struct optparse *options);
+
+#endif
diff --git a/ci/tmp.VwGIuQgZdr/fping-5.4/src/seqmap.c b/ci/tmp.VwGIuQgZdr/fping-5.4/src/seqmap.c
new file mode 100644 (file)
index 0000000..31bf725
--- /dev/null
@@ -0,0 +1,124 @@
+/*
+ * 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 "config.h"
+#include "seqmap.h"
+#include "limits.h"
+#include "options.h"
+#include "fping.h"
+
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdlib.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_NS)
+ * - 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;
+
+#define SEQMAP_TIMEOUT_IN_NS INT64_C(10000000000)
+#define SEQMAP_UNASSIGNED_HOST_NR UINT_MAX
+
+void seqmap_init()
+{
+    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, int64_t timestamp)
+{
+    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 != 0 && timestamp - next_value->ping_ts < SEQMAP_TIMEOUT_IN_NS) {
+        fprintf(stderr, "fping error: not enough sequence numbers available! (expire_timeout=%" PRId64 ", host_nr=%d, ping_count=%d, seqmap_next_id=%d)\n",
+            SEQMAP_TIMEOUT_IN_NS, 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 = timestamp;
+
+    /* increase next id */
+    current_id = seqmap_next_id;
+    seqmap_next_id = (seqmap_next_id + 1) % SEQMAP_MAXSEQ;
+
+    dbg_printf("seqmap_add(host: %d, index: %d) -> %d\n", host_nr, ping_count, current_id);
+
+    return current_id;
+}
+
+SEQMAP_VALUE* seqmap_fetch(unsigned int id, int64_t now)
+{
+    SEQMAP_VALUE* value;
+
+    if (id >= SEQMAP_MAXSEQ) {
+        return NULL;
+    }
+
+    value = &seqmap_map[id];
+
+    /* verify that value is not expired */
+    if (now - value->ping_ts >= SEQMAP_TIMEOUT_IN_NS) {
+        dbg_printf("seqmap_fetch(%d) -> host: %d, index: %d -> DISCARDED %ld\n", id, value->host_nr, value->ping_count,
+                now - value->ping_ts);
+        return NULL;
+    }
+
+    dbg_printf("seqmap_fetch(%d) -> host: %d, index: %d\n", id, value->host_nr, value->ping_count);
+
+    return value;
+}
diff --git a/ci/tmp.VwGIuQgZdr/fping-5.4/src/seqmap.h b/ci/tmp.VwGIuQgZdr/fping-5.4/src/seqmap.h
new file mode 100644 (file)
index 0000000..a1780b0
--- /dev/null
@@ -0,0 +1,21 @@
+#ifndef SEQMAP_H
+#define SEQMAP_H
+
+#include <sys/time.h>
+#include <stdint.h>
+
+typedef struct seqmap_value
+{
+    unsigned int    host_nr;
+    unsigned int    ping_count;
+    int64_t         ping_ts;
+
+} SEQMAP_VALUE;
+
+#define SEQMAP_MAXSEQ 65535
+
+void seqmap_init();
+unsigned int seqmap_add(unsigned int host_nr, unsigned int ping_count, int64_t now);
+SEQMAP_VALUE *seqmap_fetch(unsigned int id, int64_t now);
+
+#endif
diff --git a/ci/tmp.VwGIuQgZdr/fping-5.4/src/socket4.c b/ci/tmp.VwGIuQgZdr/fping-5.4/src/socket4.c
new file mode 100644 (file)
index 0000000..c408c6d
--- /dev/null
@@ -0,0 +1,166 @@
+/*
+ * 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"
+
+#include <fcntl.h>
+#include <netdb.h>
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+#include <netinet/ip_icmp.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/socket.h>
+#include <time.h>
+
+char* ping_buffer_ipv4 = 0;
+size_t ping_pkt_size_ipv4;
+
+int open_ping_socket_ipv4(int *socktype)
+{
+    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) */
+    *socktype = SOCK_RAW;
+    s = socket(AF_INET, *socktype, proto->p_proto);
+    if (s < 0) {
+        /* try non-privileged icmp (works on Mac OSX without privileges, for example) */
+        *socktype = SOCK_DGRAM;
+        s = socket(AF_INET, *socktype, proto->p_proto);
+        if (s < 0) {
+            return -1;
+        }
+    }
+
+    /* Make sure that we use non-blocking IO */
+    {
+        int flags;
+
+        if ((flags = fcntl(s, F_GETFL, 0)) < 0)
+            perror("fcntl");
+
+        if (fcntl(s, F_SETFL, flags | O_NONBLOCK) < 0)
+            perror("fcntl");
+    }
+
+    return s;
+}
+
+void init_ping_buffer_ipv4(size_t ping_data_size)
+{
+    /* allocate ping buffer */
+    ping_pkt_size_ipv4 = ping_data_size + ICMP_MINLEN;
+    ping_buffer_ipv4 = (char*)calloc(1, ping_pkt_size_ipv4);
+    if (!ping_buffer_ipv4)
+        crash_and_burn("can't malloc ping packet");
+}
+
+void socket_set_src_addr_ipv4(int s, struct in_addr* src_addr, int *ident)
+{
+    struct sockaddr_in sa;
+    socklen_t len = sizeof(sa);
+
+    memset(&sa, 0, len);
+    sa.sin_family = AF_INET;
+    sa.sin_addr = *src_addr;
+    if (bind(s, (struct sockaddr*)&sa, len) < 0)
+        errno_crash_and_burn("cannot bind source address");
+
+    if (ident) {
+        memset(&sa, 0, len);
+        if (getsockname(s, (struct sockaddr *)&sa, &len) < 0)
+            errno_crash_and_burn("can't get ICMP socket identity");
+
+        if (sa.sin_port)
+            *ident = sa.sin_port;
+    }
+}
+
+unsigned short calcsum(unsigned short* buffer, int length)
+{
+    unsigned long sum;
+
+    /* initialize sum to zero and loop until length (in words) is 0 */
+    for (sum = 0; length > 1; length -= 2) /* sizeof() returns number of bytes, we're interested in number of words */
+        sum += *buffer++; /* add 1 word of buffer to sum and proceed to the next */
+
+    /* we may have an extra byte */
+    if (length == 1)
+        sum += (char)*buffer;
+
+    sum = (sum >> 16) + (sum & 0xFFFF); /* add high 16 to low 16 */
+    sum += (sum >> 16); /* add carry */
+    return ~sum;
+}
+
+int socket_sendto_ping_ipv4(int s, struct sockaddr* saddr, socklen_t saddr_len, uint16_t icmp_seq_nr, uint16_t icmp_id_nr, uint8_t icmp_proto)
+{
+    struct icmp* icp;
+    struct timespec tsorig;
+    long tsorig_ms;
+    int n;
+
+    icp = (struct icmp*)ping_buffer_ipv4;
+
+    icp->icmp_type = icmp_proto;
+    if(icmp_proto == ICMP_TSTAMP) {
+        clock_gettime(CLOCK_REALTIME, &tsorig);
+        tsorig_ms = (tsorig.tv_sec % (24*60*60)) * 1000 + tsorig.tv_nsec / 1000000;
+        icp->icmp_otime = htonl(tsorig_ms);
+        icp->icmp_rtime = 0;
+        icp->icmp_ttime = 0;
+    }
+    icp->icmp_code = 0;
+    icp->icmp_cksum = 0;
+    icp->icmp_seq = htons(icmp_seq_nr);
+    icp->icmp_id = icmp_id_nr;
+
+    if (random_data_flag) {
+        for (n = ((char*)&icp->icmp_data - (char*)icp); n < ping_pkt_size_ipv4; ++n) {
+            ping_buffer_ipv4[n] = random() & 0xFF;
+        }
+    }
+
+    icp->icmp_cksum = calcsum((unsigned short*)icp, ping_pkt_size_ipv4);
+
+    n = sendto(s, icp, ping_pkt_size_ipv4, 0, saddr, saddr_len);
+
+    return n;
+}
diff --git a/ci/tmp.VwGIuQgZdr/fping-5.4/src/socket6.c b/ci/tmp.VwGIuQgZdr/fping-5.4/src/socket6.c
new file mode 100644 (file)
index 0000000..84a84ea
--- /dev/null
@@ -0,0 +1,136 @@
+/*
+ * 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"
+
+#include <fcntl.h>
+#include <netdb.h>
+#include <netinet/in.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/socket.h>
+
+#include <netinet/icmp6.h>
+
+char* ping_buffer_ipv6 = 0;
+size_t ping_pkt_size_ipv6;
+
+int open_ping_socket_ipv6(int *socktype)
+{
+    struct protoent* proto;
+    int s;
+
+    /* confirm that ICMP6 is available on this machine */
+    if ((proto = getprotobyname("ipv6-icmp")) == NULL)
+        crash_and_burn("ipv6-icmp: unknown protocol");
+
+    /* create raw socket for ICMP6 calls (ping) */
+    *socktype = SOCK_RAW;
+    s = socket(AF_INET6, *socktype, proto->p_proto);
+    if (s < 0) {
+        /* try non-privileged icmp6 (works on Mac OSX without privileges, for example) */
+        *socktype = SOCK_DGRAM;
+        s = socket(AF_INET6, *socktype, proto->p_proto);
+        if (s < 0) {
+            return -1;
+        }
+    }
+
+    /* Make sure that we use non-blocking IO */
+    {
+        int flags;
+
+        if ((flags = fcntl(s, F_GETFL, 0)) < 0)
+            perror("fcntl");
+
+        if (fcntl(s, F_SETFL, flags | O_NONBLOCK) < 0)
+            perror("fcntl");
+    }
+
+    return s;
+}
+
+void init_ping_buffer_ipv6(size_t ping_data_size)
+{
+    /* allocate ping buffer */
+    ping_pkt_size_ipv6 = ping_data_size + sizeof(struct icmp6_hdr);
+    ping_buffer_ipv6 = (char*)calloc(1, ping_pkt_size_ipv6);
+    if (!ping_buffer_ipv6)
+        crash_and_burn("can't malloc ping packet");
+}
+
+void socket_set_src_addr_ipv6(int s, struct in6_addr* src_addr, int *ident)
+{
+    struct sockaddr_in6 sa;
+    socklen_t len = sizeof(sa);
+
+    memset(&sa, 0, sizeof(sa));
+    sa.sin6_family = AF_INET6;
+    sa.sin6_addr = *src_addr;
+    if (bind(s, (struct sockaddr*)&sa, sizeof(sa)) < 0)
+        errno_crash_and_burn("cannot bind source address");
+
+    if (ident) {
+        memset(&sa, 0, len);
+        if (getsockname(s, (struct sockaddr *)&sa, &len) < 0)
+            errno_crash_and_burn("can't get ICMP6 socket identity");
+
+        if (sa.sin6_port)
+            *ident = sa.sin6_port;
+    }
+}
+
+int socket_sendto_ping_ipv6(int s, struct sockaddr* saddr, socklen_t saddr_len, uint16_t icmp_seq_nr, uint16_t icmp_id_nr)
+{
+    struct icmp6_hdr* icp;
+    int n;
+
+    icp = (struct icmp6_hdr*)ping_buffer_ipv6;
+    icp->icmp6_type = ICMP6_ECHO_REQUEST;
+    icp->icmp6_code = 0;
+    icp->icmp6_seq = htons(icmp_seq_nr);
+    icp->icmp6_id = icmp_id_nr;
+
+    if (random_data_flag) {
+        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_ipv6, 0, saddr, saddr_len);
+
+    return n;
+}